summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/plugin_carbon_interpose_mac.cc25
-rw-r--r--chrome/browser/plugin_process_host.cc20
-rw-r--r--chrome/browser/plugin_process_host.h11
-rw-r--r--chrome/browser/plugin_process_host_mac.cc43
-rwxr-xr-xchrome/chrome.gyp1
-rw-r--r--chrome/common/plugin_messages_internal.h28
-rw-r--r--chrome/plugin/plugin_main.cc10
-rw-r--r--chrome/plugin/plugin_thread.cc42
-rw-r--r--webkit/glue/plugins/fake_plugin_window_tracker_mac.h2
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl_mac.mm15
10 files changed, 196 insertions, 1 deletions
diff --git a/chrome/browser/plugin_carbon_interpose_mac.cc b/chrome/browser/plugin_carbon_interpose_mac.cc
index 315cdfa..0443476 100644
--- a/chrome/browser/plugin_carbon_interpose_mac.cc
+++ b/chrome/browser/plugin_carbon_interpose_mac.cc
@@ -4,8 +4,18 @@
#include <Carbon/Carbon.h>
+#include "base/gfx/rect.h"
#include "webkit/glue/plugins/fake_plugin_window_tracker_mac.h"
+namespace webkit_glue {
+
+void NotifyBrowserOfPluginSelectWindow(uint32 window_id, CGRect bounds);
+void NotifyBrowserOfPluginShowWindow(uint32 window_id, CGRect bounds);
+void NotifyBrowserOfPluginHideWindow(uint32 window_id, CGRect bounds);
+void NotifyBrowserOfPluginDisposeWindow(uint32 window_id, CGRect bounds);
+
+}
+
// 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 };
@@ -64,23 +74,38 @@ static Boolean ChromePluginIsWindowHilited(WindowRef window) {
return isHilited;
}
+static CGRect CGRectForWindow(WindowRef window) {
+ CGRect bounds = { { 0, 0 }, { 0, 0 } };
+ HIWindowGetBounds(window, kWindowContentRgn, kHICoordSpace72DPIGlobal,
+ &bounds);
+ return bounds;
+}
+
static void ChromePluginSelectWindow(WindowRef window) {
SwitchToPluginProcess();
SelectWindow(window);
+ webkit_glue::NotifyBrowserOfPluginSelectWindow(HIWindowGetCGWindowID(window),
+ CGRectForWindow(window));
}
static void ChromePluginShowWindow(WindowRef window) {
SwitchToPluginProcess();
ShowWindow(window);
+ webkit_glue::NotifyBrowserOfPluginShowWindow(HIWindowGetCGWindowID(window),
+ CGRectForWindow(window));
}
static void ChromePluginDisposeWindow(WindowRef window) {
SwitchToSavedProcess();
+ webkit_glue::NotifyBrowserOfPluginDisposeWindow(HIWindowGetCGWindowID(window),
+ CGRectForWindow(window));
DisposeWindow(window);
}
static void ChromePluginHideWindow(WindowRef window) {
SwitchToSavedProcess();
+ webkit_glue::NotifyBrowserOfPluginHideWindow(HIWindowGetCGWindowID(window),
+ CGRectForWindow(window));
HideWindow(window);
}
diff --git a/chrome/browser/plugin_process_host.cc b/chrome/browser/plugin_process_host.cc
index 4c1d949..142315d 100644
--- a/chrome/browser/plugin_process_host.cc
+++ b/chrome/browser/plugin_process_host.cc
@@ -27,7 +27,10 @@
#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "base/thread.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser_window.h"
#include "chrome/browser/child_process_security_policy.h"
#include "chrome/browser/chrome_plugin_browsing_context.h"
#include "chrome/browser/chrome_thread.h"
@@ -325,6 +328,13 @@ PluginProcessHost::~PluginProcessHost() {
window_index++) {
PostMessage(*window_index, WM_CLOSE, 0, 0);
}
+#elif defined(OS_MACOSX)
+ // If the plugin process crashed but had windows open at the time, make
+ // sure that the menu bar is visible if the browser window is not also in
+ // fullscreen mode.
+ if (!plugin_visible_windows_set_.empty()) {
+ SetSystemUIMode(kUIModeNormal, 0);
+ }
#endif
}
@@ -477,6 +487,16 @@ void PluginProcessHost::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(PluginProcessHostMsg_MapNativeViewId,
OnMapNativeViewId)
#endif
+#if defined(OS_MACOSX)
+ IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginSelectWindow,
+ OnPluginSelectWindow)
+ IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginShowWindow,
+ OnPluginShowWindow)
+ IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginHideWindow,
+ OnPluginHideWindow)
+ IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginDisposeWindow,
+ OnPluginDisposeWindow)
+#endif
IPC_MESSAGE_UNHANDLED_ERROR()
IPC_END_MESSAGE_MAP()
}
diff --git a/chrome/browser/plugin_process_host.h b/chrome/browser/plugin_process_host.h
index 36f8d1e..6c5e17f 100644
--- a/chrome/browser/plugin_process_host.h
+++ b/chrome/browser/plugin_process_host.h
@@ -112,6 +112,13 @@ class PluginProcessHost : public ChildProcessHost,
void OnMapNativeViewId(gfx::NativeViewId id, gfx::PluginWindowHandle* output);
#endif
+#if defined(OS_MACOSX)
+ void OnPluginSelectWindow(uint32 window_id, gfx::Rect window_rect);
+ void OnPluginShowWindow(uint32 window_id, gfx::Rect window_rect);
+ void OnPluginHideWindow(uint32 window_id, gfx::Rect window_rect);
+ void OnPluginDisposeWindow(uint32 window_id, gfx::Rect window_rect);
+#endif
+
virtual bool CanShutdown() { return sent_requests_.empty(); }
struct ChannelRequest {
@@ -143,6 +150,10 @@ class PluginProcessHost : public ChildProcessHost,
// Tracks plugin parent windows created on the UI thread.
std::set<HWND> plugin_parent_windows_set_;
#endif
+#if defined(OS_MACOSX)
+ // Tracks plugin windows currently visible
+ std::set<uint32> plugin_visible_windows_set_;
+#endif
DISALLOW_COPY_AND_ASSIGN(PluginProcessHost);
};
diff --git a/chrome/browser/plugin_process_host_mac.cc b/chrome/browser/plugin_process_host_mac.cc
new file mode 100644
index 0000000..d222880
--- /dev/null
+++ b/chrome/browser/plugin_process_host_mac.cc
@@ -0,0 +1,43 @@
+// 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 <Carbon/Carbon.h>
+
+#include "build/build_config.h"
+
+#include <vector>
+
+#include "base/logging.h"
+#include "chrome/browser/plugin_process_host.h"
+
+void PluginProcessHost::OnPluginSelectWindow(uint32 window_id,
+ gfx::Rect window_rect) {
+ plugin_visible_windows_set_.insert(window_id);
+}
+
+void PluginProcessHost::OnPluginShowWindow(uint32 window_id,
+ gfx::Rect window_rect) {
+ plugin_visible_windows_set_.insert(window_id);
+ CGRect window_bounds = {
+ { window_rect.x(), window_rect.y() },
+ { window_rect.width(), window_rect.height() }
+ };
+ CGRect main_display_bounds = CGDisplayBounds(CGMainDisplayID());
+ if (CGRectEqualToRect(window_bounds, main_display_bounds)) {
+ // If the plugin has just shown a window that's the same dimensions as
+ // the main display, hide the menubar so that it has the whole screen.
+ SetSystemUIMode(kUIModeAllSuppressed, kUIOptionAutoShowMenuBar);
+ }
+}
+
+void PluginProcessHost::OnPluginHideWindow(uint32 window_id,
+ gfx::Rect window_rect) {
+ plugin_visible_windows_set_.erase(window_id);
+ SetSystemUIMode(kUIModeNormal, 0);
+}
+
+void PluginProcessHost::OnPluginDisposeWindow(uint32 window_id,
+ gfx::Rect window_rect) {
+ plugin_visible_windows_set_.erase(window_id);
+}
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 84fa030..2af7789 100755
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -1739,6 +1739,7 @@
'browser/plugin_installer.h',
'browser/plugin_process_host.cc',
'browser/plugin_process_host.h',
+ 'browser/plugin_process_host_mac.cc',
'browser/plugin_service.cc',
'browser/plugin_service.h',
'browser/possible_url_model.cc',
diff --git a/chrome/common/plugin_messages_internal.h b/chrome/common/plugin_messages_internal.h
index f03cf97..6301e68 100644
--- a/chrome/common/plugin_messages_internal.h
+++ b/chrome/common/plugin_messages_internal.h
@@ -123,6 +123,34 @@ IPC_BEGIN_MESSAGES(PluginProcessHost)
gfx::PluginWindowHandle /* output: X window id */)
#endif
+#if defined(OS_MACOSX)
+ // On Mac OS X, we need the browser to keep track of plugin windows so
+ // that it can add and remove them from stacking groups, hide and show the
+ // menu bar, etc. We pass the window rect for convenience so that the
+ // browser can easily tell if the window is fullscreen.
+
+ // Notifies the browser that the plugin has selected a window (i.e., brought
+ // it to the front and wants it to have keyboard focus).
+ IPC_MESSAGE_CONTROL2(PluginProcessHostMsg_PluginSelectWindow,
+ uint32 /* window ID */,
+ gfx::Rect /* window rect */)
+
+ // Notifies the browser that the plugin has shown a window.
+ IPC_MESSAGE_CONTROL2(PluginProcessHostMsg_PluginShowWindow,
+ uint32 /* window ID */,
+ gfx::Rect /* window rect */)
+
+ // Notifies the browser that the plugin has hidden a window.
+ IPC_MESSAGE_CONTROL2(PluginProcessHostMsg_PluginHideWindow,
+ 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 */)
+#endif
+
IPC_END_MESSAGES(PluginProcessHost)
diff --git a/chrome/plugin/plugin_main.cc b/chrome/plugin/plugin_main.cc
index afc83a5..835b6ca 100644
--- a/chrome/plugin/plugin_main.cc
+++ b/chrome/plugin/plugin_main.cc
@@ -67,7 +67,17 @@ static void TrimInterposeEnvironment() {
// main() routine for running as the plugin process.
int PluginMain(const MainFunctionParams& parameters) {
// The main thread of the plugin services UI.
+#if defined(OS_MACOSX)
+ // For Mac NPAPI plugins, we don't want a MessageLoop::TYPE_UI because
+ // that will cause events to be dispatched via the Cocoa responder chain.
+ // If the plugin creates its own windows with Carbon APIs (for example,
+ // full screen mode in Flash), those windows would not receive events.
+ // Instead, WebPluginDelegateImpl::OnNullEvent will dispatch any pending
+ // system events directly to the plugin.
+ MessageLoop main_message_loop(MessageLoop::TYPE_DEFAULT);
+#else
MessageLoop main_message_loop(MessageLoop::TYPE_UI);
+#endif
std::wstring app_name = chrome::kBrowserAppName;
PlatformThread::SetName(WideToASCII(app_name + L"_PluginMain").c_str());
diff --git a/chrome/plugin/plugin_thread.cc b/chrome/plugin/plugin_thread.cc
index c2a21bd..5969089 100644
--- a/chrome/plugin/plugin_thread.cc
+++ b/chrome/plugin/plugin_thread.cc
@@ -164,6 +164,48 @@ bool GetPluginFinderURL(std::string* plugin_finder_url) {
return true;
}
+#if defined(OS_MACOSX)
+__attribute__((visibility("default")))
+void NotifyBrowserOfPluginSelectWindow(uint32 window_id, CGRect bounds) {
+ PluginThread* plugin_thread = PluginThread::current();
+ if (plugin_thread) {
+ gfx::Rect window_bounds(bounds);
+ plugin_thread->Send(
+ new PluginProcessHostMsg_PluginSelectWindow(window_id, window_bounds));
+ }
+}
+
+__attribute__((visibility("default")))
+void NotifyBrowserOfPluginShowWindow(uint32 window_id, CGRect bounds) {
+ PluginThread* plugin_thread = PluginThread::current();
+ if (plugin_thread) {
+ gfx::Rect window_bounds(bounds);
+ plugin_thread->Send(
+ new PluginProcessHostMsg_PluginShowWindow(window_id, window_bounds));
+ }
+}
+
+__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;
diff --git a/webkit/glue/plugins/fake_plugin_window_tracker_mac.h b/webkit/glue/plugins/fake_plugin_window_tracker_mac.h
index d2e7bee..e06bf01 100644
--- a/webkit/glue/plugins/fake_plugin_window_tracker_mac.h
+++ b/webkit/glue/plugins/fake_plugin_window_tracker_mac.h
@@ -12,7 +12,7 @@
class WebPluginDelegateImpl;
-// Serves as a bridge between password delegate instances and the Carbon
+// Serves as a bridge between plugin delegate instances and the Carbon
// interposing library. The Carbon functions we interpose work in terms of
// WindowRefs, and we need to be able to map from those back to the plugin
// delegates that know what we should claim about the state of the world.
diff --git a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm
index 6542381..c64b562b 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm
+++ b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm
@@ -563,6 +563,21 @@ WebPluginResourceClient* WebPluginDelegateImpl::CreateResourceClient(
}
void WebPluginDelegateImpl::OnNullEvent() {
+ if (!webkit_glue::IsPluginRunningInRendererProcess()) {
+ // If the plugin is running in a subprocess, drain any pending system
+ // events so that the plugin's event handlers will get called on any
+ // windows it has created. Filter out activate/deactivate events on
+ // the fake browser window, but pass everything else through.
+ EventRecord event;
+ while (GetNextEvent(everyEvent, &event)) {
+ if (event.what == activateEvt && cg_context_.window &&
+ reinterpret_cast<void *>(event.message) != cg_context_.window)
+ continue;
+ instance()->NPP_HandleEvent(&event);
+ }
+ }
+
+ // Send an idle event so that the plugin can do background work
NPEvent np_event = {0};
np_event.what = nullEvent;
np_event.when = TickCount();