summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorstuartmorgan@chromium.org <stuartmorgan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-08 19:41:08 +0000
committerstuartmorgan@chromium.org <stuartmorgan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-08 19:41:08 +0000
commit1289b98a04a44eb64e74aeefa7c8affcde6ae89c (patch)
treefc2c2ff2d46c8d4e600007a900bc98a5b14c2372 /chrome
parent8156e34de05c0eb074595ff7a3d850a22269bee8 (diff)
downloadchromium_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.order8
-rw-r--r--chrome/browser/DEPS1
-rw-r--r--chrome/browser/plugin_carbon_interpose_mac.cc161
-rw-r--r--chrome/browser/plugin_process_host.cc2
-rw-r--r--chrome/browser/plugin_process_host.h1
-rw-r--r--chrome/browser/plugin_process_host_mac.cc31
-rwxr-xr-xchrome/chrome.gyp2
-rw-r--r--chrome/common/plugin_messages_internal.h5
-rw-r--r--chrome/plugin/plugin_interpose_util_mac.h38
-rw-r--r--chrome/plugin/plugin_interpose_util_mac.mm187
-rw-r--r--chrome/plugin/plugin_main_mac.mm3
-rw-r--r--chrome/plugin/plugin_thread.cc46
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;