diff options
author | stuartmorgan@chromium.org <stuartmorgan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-08 19:41:08 +0000 |
---|---|---|
committer | stuartmorgan@chromium.org <stuartmorgan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-08 19:41:08 +0000 |
commit | 1289b98a04a44eb64e74aeefa7c8affcde6ae89c (patch) | |
tree | fc2c2ff2d46c8d4e600007a900bc98a5b14c2372 /chrome | |
parent | 8156e34de05c0eb074595ff7a3d850a22269bee8 (diff) | |
download | chromium_src-1289b98a04a44eb64e74aeefa7c8affcde6ae89c.zip chromium_src-1289b98a04a44eb64e74aeefa7c8affcde6ae89c.tar.gz chromium_src-1289b98a04a44eb64e74aeefa7c8affcde6ae89c.tar.bz2 |
Add Cocoa window interposing for plugin process
Adds support for noticing window show/hide done via Cocoa APIs. Also adds interposing on a couple more Carbon calls that I came across while debugging. Refactors to make things a bit less messy:
- Moves responsibility for re-activating the browser when the last plugin window closes into the browser, to simplify that logic.
- Moves utility method for activating the plugin process into the plugin, rather than the interpose library, so the Cocoa code can use it too.
- Add a data-holder and a couple of wrapper methods to reduce code duplication in the window show/hide handling.
BUG=28009, 29321
TEST=Plugin-opened windows (Gmail attachments, full-screen Flash, etc.) should work as expected again.
Review URL: http://codereview.chromium.org/465111
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@34074 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/app/framework.order | 8 | ||||
-rw-r--r-- | chrome/browser/DEPS | 1 | ||||
-rw-r--r-- | chrome/browser/plugin_carbon_interpose_mac.cc | 161 | ||||
-rw-r--r-- | chrome/browser/plugin_process_host.cc | 2 | ||||
-rw-r--r-- | chrome/browser/plugin_process_host.h | 1 | ||||
-rw-r--r-- | chrome/browser/plugin_process_host_mac.cc | 31 | ||||
-rwxr-xr-x | chrome/chrome.gyp | 2 | ||||
-rw-r--r-- | chrome/common/plugin_messages_internal.h | 5 | ||||
-rw-r--r-- | chrome/plugin/plugin_interpose_util_mac.h | 38 | ||||
-rw-r--r-- | chrome/plugin/plugin_interpose_util_mac.mm | 187 | ||||
-rw-r--r-- | chrome/plugin/plugin_main_mac.mm | 3 | ||||
-rw-r--r-- | chrome/plugin/plugin_thread.cc | 46 |
12 files changed, 326 insertions, 159 deletions
diff --git a/chrome/app/framework.order b/chrome/app/framework.order index dea2dde..508ca0f 100644 --- a/chrome/app/framework.order +++ b/chrome/app/framework.order @@ -22,10 +22,10 @@ _NP_GetMIMEDescription _NP_GetValue _NP_Initialize _NP_Shutdown -__ZN11webkit_glue31NotifyBrowserOfPluginHideWindowEj6CGRect -__ZN11webkit_glue31NotifyBrowserOfPluginShowWindowEj6CGRectb -__ZN11webkit_glue33NotifyBrowserOfPluginSelectWindowEj6CGRectb -__ZN11webkit_glue34NotifyBrowserOfPluginDisposeWindowEj6CGRect +__ZN22mac_plugin_interposing21SwitchToPluginProcessEv +__ZN22mac_plugin_interposing31NotifyBrowserOfPluginHideWindowEj6CGRect +__ZN22mac_plugin_interposing31NotifyBrowserOfPluginShowWindowEj6CGRectb +__ZN22mac_plugin_interposing33NotifyBrowserOfPluginSelectWindowEj6CGRectb __ZN23FakePluginWindowTracker14SharedInstanceEv __ZN23FakePluginWindowTracker27RemoveFakeWindowForDelegateEP21WebPluginDelegateImplP15OpaqueWindowPtr __ZN23FakePluginWindowTracker29GenerateFakeWindowForDelegateEP21WebPluginDelegateImpl diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index e550294..855116c 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS @@ -3,6 +3,7 @@ include_rules = [ "+chrome/app/locales", "+chrome/installer", "+chrome/personalization", + "+chrome/plugin", # For Mac plugin interpose library. "+chrome/tools/profiles", # For history unit tests. "+chrome/views", "+grit", # For generated headers diff --git a/chrome/browser/plugin_carbon_interpose_mac.cc b/chrome/browser/plugin_carbon_interpose_mac.cc index 94d6c38..96de137 100644 --- a/chrome/browser/plugin_carbon_interpose_mac.cc +++ b/chrome/browser/plugin_carbon_interpose_mac.cc @@ -5,77 +5,10 @@ #include <Carbon/Carbon.h> #include "base/gfx/rect.h" +#include "chrome/plugin/plugin_interpose_util_mac.h" #include "webkit/glue/plugins/fake_plugin_window_tracker_mac.h" -namespace webkit_glue { - -void NotifyBrowserOfPluginSelectWindow(uint32 window_id, CGRect bounds, - bool modal); -void NotifyBrowserOfPluginShowWindow(uint32 window_id, CGRect bounds, - bool modal); -void NotifyBrowserOfPluginHideWindow(uint32 window_id, CGRect bounds); -void NotifyBrowserOfPluginDisposeWindow(uint32 window_id, CGRect bounds); - -} // namespace webkit_glue - -// 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) { - 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); - } -} - -// Checks to see if there are any plugin-opened windows still showing, and if -// not reactivates the saved process. -// Should be called after any window has been closed. -static void MaybeReactivateSavedProcess() { - bool window_is_visible = false; - WindowRef window = GetWindowList(); - while (window != NULL) { - if (IsWindowVisible(window)) { - window_is_visible = true; - break; - } - window = GetNextWindow(window); - } - - if (!window_is_visible) - SwitchToSavedProcess(); -} +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" // Returns true if the given window is modal. static bool IsModalWindow(WindowRef window) { @@ -92,6 +25,39 @@ static bool IsContainingWindowActive(const WebPluginDelegateImpl* delegate) { return true; } +static CGRect CGRectForWindow(WindowRef window) { + CGRect bounds = { { 0, 0 }, { 0, 0 } }; + HIWindowGetBounds(window, kWindowContentRgn, kHICoordSpace72DPIGlobal, + &bounds); + return bounds; +} + +struct WindowInfo { + uint32 window_id; + CGRect bounds; + WindowInfo(WindowRef window) { + window_id = HIWindowGetCGWindowID(window); + bounds = CGRectForWindow(window); + } +}; + +static void OnPluginWindowClosed(const WindowInfo& window_info) { + mac_plugin_interposing::NotifyBrowserOfPluginHideWindow(window_info.window_id, + window_info.bounds); +} + +static void OnPluginWindowShown(WindowRef window) { + mac_plugin_interposing::NotifyBrowserOfPluginShowWindow( + HIWindowGetCGWindowID(window), CGRectForWindow(window), + IsModalWindow(window)); +} + +static void OnPluginWindowSelected(WindowRef window) { + mac_plugin_interposing::NotifyBrowserOfPluginSelectWindow( + HIWindowGetCGWindowID(window), CGRectForWindow(window), + IsModalWindow(window)); +} + #pragma mark - static Boolean ChromePluginIsWindowActive(WindowRef window) { @@ -110,52 +76,53 @@ static Boolean ChromePluginIsWindowHilited(WindowRef window) { : IsWindowHilited(window); } -static CGRect CGRectForWindow(WindowRef window) { - CGRect bounds = { { 0, 0 }, { 0, 0 } }; - HIWindowGetBounds(window, kWindowContentRgn, kHICoordSpace72DPIGlobal, - &bounds); - return bounds; -} - static void ChromePluginSelectWindow(WindowRef window) { - SwitchToPluginProcess(); + mac_plugin_interposing::SwitchToPluginProcess(); SelectWindow(window); - webkit_glue::NotifyBrowserOfPluginSelectWindow(HIWindowGetCGWindowID(window), - CGRectForWindow(window), - IsModalWindow(window)); + OnPluginWindowSelected(window); } static void ChromePluginShowWindow(WindowRef window) { - SwitchToPluginProcess(); + mac_plugin_interposing::SwitchToPluginProcess(); ShowWindow(window); - webkit_glue::NotifyBrowserOfPluginShowWindow(HIWindowGetCGWindowID(window), - CGRectForWindow(window), - IsModalWindow(window)); + OnPluginWindowShown(window); } static void ChromePluginDisposeWindow(WindowRef window) { - CGWindowID window_id = HIWindowGetCGWindowID(window); - CGRect window_rect = CGRectForWindow(window); + WindowInfo window_info(window); DisposeWindow(window); - webkit_glue::NotifyBrowserOfPluginDisposeWindow(window_id, window_rect); - MaybeReactivateSavedProcess(); + OnPluginWindowClosed(window_info); } static void ChromePluginHideWindow(WindowRef window) { - CGWindowID window_id = HIWindowGetCGWindowID(window); - CGRect window_rect = CGRectForWindow(window); + WindowInfo window_info(window); HideWindow(window); - webkit_glue::NotifyBrowserOfPluginHideWindow(window_id, window_rect); - MaybeReactivateSavedProcess(); + OnPluginWindowClosed(window_info); +} + +static void ChromePluginShowHide(WindowRef window, Boolean show) { + if (show) { + mac_plugin_interposing::SwitchToPluginProcess(); + ShowHide(window, show); + OnPluginWindowShown(window); + } else { + WindowInfo window_info(window); + ShowHide(window, show); + OnPluginWindowClosed(window_info); + } +} + +static void ChromePluginReleaseWindow(WindowRef window) { + WindowInfo window_info(window); + ReleaseWindow(window); + OnPluginWindowClosed(window_info); } static void ChromePluginDisposeDialog(DialogRef dialog) { WindowRef window = GetDialogWindow(dialog); - CGWindowID window_id = HIWindowGetCGWindowID(window); - CGRect window_rect = CGRectForWindow(window); + WindowInfo window_info(window); DisposeDialog(dialog); - webkit_glue::NotifyBrowserOfPluginDisposeWindow(window_id, window_rect); - MaybeReactivateSavedProcess(); + OnPluginWindowClosed(window_info); } #pragma mark - @@ -175,7 +142,9 @@ __attribute__((used)) static const interpose_substitution substitutions[] INTERPOSE_FUNCTION(IsWindowHilited), INTERPOSE_FUNCTION(SelectWindow), INTERPOSE_FUNCTION(ShowWindow), + INTERPOSE_FUNCTION(ShowHide), INTERPOSE_FUNCTION(DisposeWindow), INTERPOSE_FUNCTION(HideWindow), + INTERPOSE_FUNCTION(ReleaseWindow), INTERPOSE_FUNCTION(DisposeDialog), }; diff --git a/chrome/browser/plugin_process_host.cc b/chrome/browser/plugin_process_host.cc index ab17bb0..f187b8c 100644 --- a/chrome/browser/plugin_process_host.cc +++ b/chrome/browser/plugin_process_host.cc @@ -479,8 +479,6 @@ void PluginProcessHost::OnMessageReceived(const IPC::Message& msg) { OnPluginShowWindow) IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginHideWindow, OnPluginHideWindow) - IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginDisposeWindow, - OnPluginDisposeWindow) IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginReceivedFocus, OnPluginReceivedFocus) #endif diff --git a/chrome/browser/plugin_process_host.h b/chrome/browser/plugin_process_host.h index bc9feec..aee437a 100644 --- a/chrome/browser/plugin_process_host.h +++ b/chrome/browser/plugin_process_host.h @@ -128,7 +128,6 @@ class PluginProcessHost : public ChildProcessHost, void OnPluginShowWindow(uint32 window_id, gfx::Rect window_rect, bool modal); void OnPluginHideWindow(uint32 window_id, gfx::Rect window_rect); - void OnPluginDisposeWindow(uint32 window_id, gfx::Rect window_rect); void OnPluginReceivedFocus(int process_id, int instance_id); #endif diff --git a/chrome/browser/plugin_process_host_mac.cc b/chrome/browser/plugin_process_host_mac.cc index f1f0ff8..2df0eae 100644 --- a/chrome/browser/plugin_process_host_mac.cc +++ b/chrome/browser/plugin_process_host_mac.cc @@ -48,22 +48,43 @@ void PluginProcessHost::OnPluginShowWindow(uint32 window_id, } } +// Must be called on the UI thread. +// If plugin_pid is -1, the browser will be the active process on return, +// otherwise that process will be given focus back before this function returns. +static void ReleasePluginFullScreen(pid_t plugin_pid) { + // Releasing full screen only works if we are the frontmost process; grab + // focus, but give it back to the plugin process if requested. + mac_util::ActivateProcess(base::GetCurrentProcId()); + mac_util::ReleaseFullScreen(); + if (plugin_pid != -1) { + mac_util::ActivateProcess(plugin_pid); + } +} + void PluginProcessHost::OnPluginHideWindow(uint32 window_id, gfx::Rect window_rect) { + bool had_windows = !plugin_visible_windows_set_.empty(); plugin_visible_windows_set_.erase(window_id); + bool browser_needs_activation = had_windows && + plugin_visible_windows_set_.empty(); + plugin_modal_windows_set_.erase(window_id); if (plugin_fullscreen_windows_set_.find(window_id) != plugin_fullscreen_windows_set_.end()) { plugin_fullscreen_windows_set_.erase(window_id); + pid_t plugin_pid = browser_needs_activation ? -1 : handle(); + browser_needs_activation = false; ChromeThread::PostTask( ChromeThread::UI, FROM_HERE, - NewRunnableFunction(mac_util::ReleaseFullScreen)); + NewRunnableFunction(ReleasePluginFullScreen, plugin_pid)); } -} -void PluginProcessHost::OnPluginDisposeWindow(uint32 window_id, - gfx::Rect window_rect) { - OnPluginHideWindow(window_id, window_rect); + if (browser_needs_activation) { + ChromeThread::PostTask( + ChromeThread::UI, FROM_HERE, + NewRunnableFunction(mac_util::ActivateProcess, + base::GetCurrentProcId())); + } } void PluginProcessHost::OnAppActivation() { diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index acb52e3..730ff1a 100755 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -747,6 +747,8 @@ 'plugin/plugin_channel.h', 'plugin/plugin_channel_base.cc', 'plugin/plugin_channel_base.h', + 'plugin/plugin_interpose_util_mac.mm', + 'plugin/plugin_interpose_util_mac.h', 'plugin/plugin_main.cc', 'plugin/plugin_main_mac.mm', 'plugin/plugin_thread.cc', diff --git a/chrome/common/plugin_messages_internal.h b/chrome/common/plugin_messages_internal.h index 923a750..fb5dd77 100644 --- a/chrome/common/plugin_messages_internal.h +++ b/chrome/common/plugin_messages_internal.h @@ -156,11 +156,6 @@ IPC_BEGIN_MESSAGES(PluginProcessHost) uint32 /* window ID */, gfx::Rect /* window rect */) - // Notifies the browser that the plugin has disposed of a window. - IPC_MESSAGE_CONTROL2(PluginProcessHostMsg_PluginDisposeWindow, - uint32 /* window ID */, - gfx::Rect /* window rect */) - // Notifies the browser that a plugin instance has received keyboard focus IPC_MESSAGE_CONTROL2(PluginProcessHostMsg_PluginReceivedFocus, uint32 /* process ID */, diff --git a/chrome/plugin/plugin_interpose_util_mac.h b/chrome/plugin/plugin_interpose_util_mac.h new file mode 100644 index 0000000..c68d1f2 --- /dev/null +++ b/chrome/plugin/plugin_interpose_util_mac.h @@ -0,0 +1,38 @@ +// 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. + +#ifndef CHROME_PLUGIN_PLUGIN_INTERPOSE_UTIL_MAC_H_ +#define CHROME_PLUGIN_PLUGIN_INTERPOSE_UTIL_MAC_H_ + +#include <Carbon/Carbon.h> + +#import "base/basictypes.h" + +namespace mac_plugin_interposing { + +// Swizzles methods we need to watch in order to manage process and window +// focus correctly. +void SetUpCocoaInterposing(); + +// Brings the plugin process to the front so that the user can see its windows. +void SwitchToPluginProcess(); + +// Sends a message to the browser process to inform it that the given window +// has been brought forward. +void NotifyBrowserOfPluginSelectWindow(uint32 window_id, CGRect bounds, + bool modal); + +// Sends a message to the browser process to inform it that the given window +// has been shown. +void NotifyBrowserOfPluginShowWindow(uint32 window_id, CGRect bounds, + bool modal); + +// Sends a message to the browser process to inform it that the given window +// has been hidden, and switches focus back to the browser process if there are +// no remaining plugin windows. +void NotifyBrowserOfPluginHideWindow(uint32 window_id, CGRect bounds); + +} // namespace MacPluginInterpose + +#endif // CHROME_PLUGIN_PLUGIN_INTERPOSE_UTIL_MAC_H_ diff --git a/chrome/plugin/plugin_interpose_util_mac.mm b/chrome/plugin/plugin_interpose_util_mac.mm new file mode 100644 index 0000000..58165e2 --- /dev/null +++ b/chrome/plugin/plugin_interpose_util_mac.mm @@ -0,0 +1,187 @@ +// Copyright (c) 2006-2008 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 "chrome/plugin/plugin_interpose_util_mac.h" + +#import <AppKit/AppKit.h> +#import <objc/runtime.h> + +#include "chrome/common/plugin_messages.h" +#include "chrome/plugin/plugin_thread.h" + +namespace mac_plugin_interposing { + +// TODO(stuartmorgan): Make this an IPC to order the plugin process above the +// browser process only if the browser is current frontmost. +__attribute__((visibility("default"))) +void SwitchToPluginProcess() { + ProcessSerialNumber this_process, front_process; + if ((GetCurrentProcess(&this_process) != noErr) || + (GetFrontProcess(&front_process) != noErr)) { + return; + } + + Boolean matched = false; + if ((SameProcess(&this_process, &front_process, &matched) == noErr) && + !matched) { + SetFrontProcess(&this_process); + } +} + +__attribute__((visibility("default"))) +void NotifyBrowserOfPluginSelectWindow(uint32 window_id, CGRect bounds, + bool modal) { + PluginThread* plugin_thread = PluginThread::current(); + if (plugin_thread) { + gfx::Rect window_bounds(bounds); + plugin_thread->Send( + new PluginProcessHostMsg_PluginSelectWindow(window_id, window_bounds, + modal)); + } +} + +__attribute__((visibility("default"))) +void NotifyBrowserOfPluginShowWindow(uint32 window_id, CGRect bounds, + bool modal) { + PluginThread* plugin_thread = PluginThread::current(); + if (plugin_thread) { + gfx::Rect window_bounds(bounds); + plugin_thread->Send( + new PluginProcessHostMsg_PluginShowWindow(window_id, window_bounds, + modal)); + } +} + +__attribute__((visibility("default"))) +void NotifyBrowserOfPluginHideWindow(uint32 window_id, CGRect bounds) { + PluginThread* plugin_thread = PluginThread::current(); + if (plugin_thread) { + gfx::Rect window_bounds(bounds); + plugin_thread->Send( + new PluginProcessHostMsg_PluginHideWindow(window_id, window_bounds)); + } +} + +} // namespace mac_plugin_interposing + +#pragma mark - + +struct WindowInfo { + uint32 window_id; + CGRect bounds; + WindowInfo(NSWindow* window) { + NSInteger window_num = [window windowNumber]; + window_id = window_num > 0 ? window_num : 0; + bounds = NSRectToCGRect([window frame]); + } +}; + +static void OnPluginWindowClosed(const WindowInfo& window_info) { + if (window_info.window_id == 0) + return; + mac_plugin_interposing::NotifyBrowserOfPluginHideWindow(window_info.window_id, + window_info.bounds); +} + +static void OnPluginWindowShown(const WindowInfo& window_info, BOOL is_modal) { + // The window id is 0 if it has never been shown (including while it is the + // process of being shown for the first time); when that happens, we'll catch + // it in _setWindowNumber instead. + static BOOL s_pending_display_is_modal = NO; + if (window_info.window_id == 0) { + if (is_modal) + s_pending_display_is_modal = YES; + return; + } + if (s_pending_display_is_modal) { + is_modal = YES; + s_pending_display_is_modal = NO; + } + mac_plugin_interposing::NotifyBrowserOfPluginShowWindow( + window_info.window_id, window_info.bounds, is_modal); +} + +@interface NSWindow (ChromePluginInterposing) +- (void)chromePlugin_orderOut:(id)sender; +- (void)chromePlugin_orderFront:(id)sender; +- (void)chromePlugin_makeKeyAndOrderFront:(id)sender; +- (void)chromePlugin_setWindowNumber:(NSInteger)num; +@end + +@implementation NSWindow (ChromePluginInterposing) + +- (void)chromePlugin_orderOut:(id)sender { + WindowInfo window_info(self); + [self chromePlugin_orderOut:sender]; + OnPluginWindowClosed(window_info); +} + +- (void)chromePlugin_orderFront:(id)sender { + mac_plugin_interposing::SwitchToPluginProcess(); + [self chromePlugin_orderFront:sender]; + OnPluginWindowShown(WindowInfo(self), NO); +} + +- (void)chromePlugin_makeKeyAndOrderFront:(id)sender { + mac_plugin_interposing::SwitchToPluginProcess(); + [self chromePlugin_makeKeyAndOrderFront:sender]; + OnPluginWindowShown(WindowInfo(self), NO); +} + +- (void)chromePlugin_setWindowNumber:(NSInteger)num { + if (num > 0) + mac_plugin_interposing::SwitchToPluginProcess(); + [self chromePlugin_setWindowNumber:num]; + if (num > 0) + OnPluginWindowShown(WindowInfo(self), NO); +} + +@end + +@interface NSApplication (ChromePluginInterposing) +- (NSInteger)chromePlugin_runModalForWindow:(NSWindow*)window; +@end + +@implementation NSApplication (ChromePluginInterposing) + +- (NSInteger)chromePlugin_runModalForWindow:(NSWindow*)window { + mac_plugin_interposing::SwitchToPluginProcess(); + // This is out-of-order relative to the other calls, but runModalForWindow: + // won't return until the window closes, and the order only matters for + // full-screen windows. + OnPluginWindowShown(WindowInfo(window), YES); + return [self chromePlugin_runModalForWindow:window]; +} + +@end + +#pragma mark - + +static void ExchangeMethods(Class target_class, SEL original, SEL replacement) { + Method m1 = class_getInstanceMethod(target_class, original); + Method m2 = class_getInstanceMethod(target_class, replacement); + if (m1 && m2) + method_exchangeImplementations(m1, m2); + else + NOTREACHED() << "Cocoa swizzling failed"; +} + +namespace mac_plugin_interposing { + +void SetUpCocoaInterposing() { + Class nswindow_class = [NSWindow class]; + ExchangeMethods(nswindow_class, @selector(orderOut:), + @selector(chromePlugin_orderOut:)); + ExchangeMethods(nswindow_class, @selector(orderFront:), + @selector(chromePlugin_orderFront:)); + ExchangeMethods(nswindow_class, @selector(makeKeyAndOrderFront:), + @selector(chromePlugin_makeKeyAndOrderFront:)); + ExchangeMethods(nswindow_class, @selector(_setWindowNumber:), + @selector(chromePlugin_setWindowNumber:)); + + ExchangeMethods([NSApplication class], @selector(runModalForWindow:), + @selector(chromePlugin_runModalForWindow:)); +} + +} // namespace mac_plugin_interposing diff --git a/chrome/plugin/plugin_main_mac.mm b/chrome/plugin/plugin_main_mac.mm index af428e6..1f729a4 100644 --- a/chrome/plugin/plugin_main_mac.mm +++ b/chrome/plugin/plugin_main_mac.mm @@ -5,6 +5,7 @@ #include "base/chrome_application_mac.h" #include "base/string_util.h" #include "chrome/common/plugin_carbon_interpose_constants_mac.h" +#include "chrome/plugin/plugin_interpose_util_mac.h" void TrimInterposeEnvironment() { const char* interpose_list = @@ -39,4 +40,6 @@ void TrimInterposeEnvironment() { void InitializeChromeApplication() { [CrApplication sharedApplication]; + + mac_plugin_interposing::SetUpCocoaInterposing(); } diff --git a/chrome/plugin/plugin_thread.cc b/chrome/plugin/plugin_thread.cc index 91c763b..fb02ac5 100644 --- a/chrome/plugin/plugin_thread.cc +++ b/chrome/plugin/plugin_thread.cc @@ -194,52 +194,6 @@ bool GetPluginFinderURL(std::string* plugin_finder_url) { return true; } -#if defined(OS_MACOSX) -__attribute__((visibility("default"))) -void NotifyBrowserOfPluginSelectWindow(uint32 window_id, CGRect bounds, - bool modal) { - PluginThread* plugin_thread = PluginThread::current(); - if (plugin_thread) { - gfx::Rect window_bounds(bounds); - plugin_thread->Send( - new PluginProcessHostMsg_PluginSelectWindow(window_id, window_bounds, - modal)); - } -} - -__attribute__((visibility("default"))) -void NotifyBrowserOfPluginShowWindow(uint32 window_id, CGRect bounds, - bool modal) { - PluginThread* plugin_thread = PluginThread::current(); - if (plugin_thread) { - gfx::Rect window_bounds(bounds); - plugin_thread->Send( - new PluginProcessHostMsg_PluginShowWindow(window_id, window_bounds, - modal)); - } -} - -__attribute__((visibility("default"))) -void NotifyBrowserOfPluginHideWindow(uint32 window_id, CGRect bounds) { - PluginThread* plugin_thread = PluginThread::current(); - if (plugin_thread) { - gfx::Rect window_bounds(bounds); - plugin_thread->Send( - new PluginProcessHostMsg_PluginHideWindow(window_id, window_bounds)); - } -} - -__attribute__((visibility("default"))) -void NotifyBrowserOfPluginDisposeWindow(uint32 window_id, CGRect bounds) { - PluginThread* plugin_thread = PluginThread::current(); - if (plugin_thread) { - gfx::Rect window_bounds(bounds); - plugin_thread->Send( - new PluginProcessHostMsg_PluginDisposeWindow(window_id, window_bounds)); - } -} -#endif - bool IsDefaultPluginEnabled() { #if defined(OS_WIN) return true; |