summaryrefslogtreecommitdiffstats
path: root/chrome/browser
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/browser
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/browser')
-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
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() {