summaryrefslogtreecommitdiffstats
path: root/chrome/browser/plugin_carbon_interpose_mac.cc
diff options
context:
space:
mode:
authorstuartmorgan@google.com <stuartmorgan@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-07 22:03:17 +0000
committerstuartmorgan@google.com <stuartmorgan@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-07 22:03:17 +0000
commitf3ef7b1c17b3f9a1db703a7b099e697e401d21a9 (patch)
treec6252141eeb6637bb2a4630d1735bbf965933a56 /chrome/browser/plugin_carbon_interpose_mac.cc
parent1ef7ccfa171759ab86cdf6b98cf5145b9db688b0 (diff)
downloadchromium_src-f3ef7b1c17b3f9a1db703a7b099e697e401d21a9.zip
chromium_src-f3ef7b1c17b3f9a1db703a7b099e697e401d21a9.tar.gz
chromium_src-f3ef7b1c17b3f9a1db703a7b099e697e401d21a9.tar.bz2
Set up a interposing library for Carbon calls made by plugins.
This gives us a library that's inserted into plugin process via DYLD_INSERT_LIBRARIES to intercept Carbon calls, and moves the window/process activation handling into that library (based on Carbon window activation/deactivation calls, rather than polling the front window). Over time we'll interpose more, but this gives us the foundation. This fixes both the "window loses focus when loading a page with plugins" and "can't click on YouTube controls" bugs. BUG=18203,18553 TEST=Clicking on Flash plugins should work much more reliably, opening a page with a plugin shouldn't cause the window to lose focus. Review URL: http://codereview.chromium.org/164100 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@22799 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/plugin_carbon_interpose_mac.cc')
-rw-r--r--chrome/browser/plugin_carbon_interpose_mac.cc105
1 files changed, 105 insertions, 0 deletions
diff --git a/chrome/browser/plugin_carbon_interpose_mac.cc b/chrome/browser/plugin_carbon_interpose_mac.cc
new file mode 100644
index 0000000..315cdfa
--- /dev/null
+++ b/chrome/browser/plugin_carbon_interpose_mac.cc
@@ -0,0 +1,105 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <Carbon/Carbon.h>
+
+#include "webkit/glue/plugins/fake_plugin_window_tracker_mac.h"
+
+// The process that was frontmost when a plugin created a new window; generally
+// we expect this to be the browser UI process.
+static ProcessSerialNumber g_saved_front_process = { 0, 0 };
+
+// Bring the plugin process to the front so that the user can see it.
+// TODO: Make this an IPC to order the plugin process above the browser
+// process but not necessarily the frontmost.
+static void SwitchToPluginProcess() {
+ ProcessSerialNumber this_process, front_process;
+ if (GetCurrentProcess(&this_process) != noErr)
+ return;
+ if (GetFrontProcess(&front_process) != noErr)
+ return;
+ Boolean matched = false;
+ if (SameProcess(&this_process, &front_process, &matched) != noErr)
+ return;
+ if (!matched) {
+ // TODO: We may need to keep a stack, or at least check the total window
+ // count, since this won't work if a plugin opens more than one window at
+ // a time.
+ g_saved_front_process = front_process;
+ SetFrontProcess(&this_process);
+ }
+}
+
+// If the plugin process is still the front process, bring the prior
+// front process (normally this will be the browser process) back to
+// the front.
+// TODO: Make this an IPC message so that the browser can properly
+// reactivate the window.
+static void SwitchToSavedProcess() {
+ ProcessSerialNumber this_process, front_process;
+ if (GetCurrentProcess(&this_process) != noErr)
+ return;
+ if (GetFrontProcess(&front_process) != noErr)
+ return;
+ Boolean matched = false;
+ if (SameProcess(&this_process, &front_process, &matched) != noErr)
+ return;
+ if (matched) {
+ SetFrontProcess(&g_saved_front_process);
+ }
+}
+
+#pragma mark -
+
+static Boolean ChromePluginIsWindowHilited(WindowRef window) {
+ // TODO(stuartmorgan): Always returning true (instead of the real answer,
+ // which would be false) means that clicking works, but it's not correct
+ // either. Ideally we need a way to find out if the delegate corresponds
+ // to a browser window that is active.
+ const WebPluginDelegateImpl* delegate =
+ FakePluginWindowTracker::SharedInstance()->GetDelegateForFakeWindow(
+ window);
+ Boolean isHilited = delegate ? true : IsWindowHilited(window);
+ return isHilited;
+}
+
+static void ChromePluginSelectWindow(WindowRef window) {
+ SwitchToPluginProcess();
+ SelectWindow(window);
+}
+
+static void ChromePluginShowWindow(WindowRef window) {
+ SwitchToPluginProcess();
+ ShowWindow(window);
+}
+
+static void ChromePluginDisposeWindow(WindowRef window) {
+ SwitchToSavedProcess();
+ DisposeWindow(window);
+}
+
+static void ChromePluginHideWindow(WindowRef window) {
+ SwitchToSavedProcess();
+ HideWindow(window);
+}
+
+#pragma mark -
+
+struct interpose_substitution {
+ const void* replacement;
+ const void* original;
+};
+
+#define INTERPOSE_FUNCTION(function) \
+ { reinterpret_cast<const void*>(ChromePlugin##function), \
+ reinterpret_cast<const void*>(function) }
+
+__attribute__((used)) static const interpose_substitution substitutions[]
+ __attribute__((section("__DATA, __interpose"))) = {
+ INTERPOSE_FUNCTION(IsWindowHilited),
+ INTERPOSE_FUNCTION(SelectWindow),
+ INTERPOSE_FUNCTION(ShowWindow),
+ INTERPOSE_FUNCTION(DisposeWindow),
+ INTERPOSE_FUNCTION(HideWindow),
+};