From f3ef7b1c17b3f9a1db703a7b099e697e401d21a9 Mon Sep 17 00:00:00 2001 From: "stuartmorgan@google.com" Date: Fri, 7 Aug 2009 22:03:17 +0000 Subject: 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 --- chrome/browser/plugin_carbon_interpose_mac.cc | 105 ++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 chrome/browser/plugin_carbon_interpose_mac.cc (limited to 'chrome/browser/plugin_carbon_interpose_mac.cc') 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 + +#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(ChromePlugin##function), \ + reinterpret_cast(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), +}; -- cgit v1.1