diff options
-rw-r--r-- | chrome/browser/plugin_carbon_interpose_mac.cc | 25 | ||||
-rw-r--r-- | chrome/browser/plugin_process_host.cc | 20 | ||||
-rw-r--r-- | chrome/browser/plugin_process_host.h | 11 | ||||
-rw-r--r-- | chrome/browser/plugin_process_host_mac.cc | 43 | ||||
-rwxr-xr-x | chrome/chrome.gyp | 1 | ||||
-rw-r--r-- | chrome/common/plugin_messages_internal.h | 28 | ||||
-rw-r--r-- | chrome/plugin/plugin_main.cc | 10 | ||||
-rw-r--r-- | chrome/plugin/plugin_thread.cc | 42 | ||||
-rw-r--r-- | webkit/glue/plugins/fake_plugin_window_tracker_mac.h | 2 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl_mac.mm | 15 |
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(); |