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/browser | |
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/browser')
-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 |
5 files changed, 92 insertions, 104 deletions
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() { |