diff options
-rw-r--r-- | chrome/browser/plugin_process_host.cc | 94 | ||||
-rw-r--r-- | chrome/browser/plugin_process_host.h | 3 | ||||
-rw-r--r-- | chrome/browser/render_widget_host.cc | 8 | ||||
-rw-r--r-- | chrome/common/plugin_messages_internal.h | 13 | ||||
-rw-r--r-- | chrome/plugin/webplugin_delegate_stub.cc | 5 | ||||
-rw-r--r-- | chrome/plugin/webplugin_delegate_stub.h | 2 | ||||
-rw-r--r-- | chrome/plugin/webplugin_proxy.cc | 39 | ||||
-rw-r--r-- | chrome/plugin/webplugin_proxy.h | 3 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_proxy.cc | 11 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_proxy.h | 6 | ||||
-rw-r--r-- | webkit/glue/plugins/test/plugin_npobject_lifetime_test.cc | 3 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl.cc | 89 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl.h | 23 | ||||
-rw-r--r-- | webkit/glue/webplugin_delegate.h | 8 | ||||
-rw-r--r-- | webkit/glue/webplugin_impl.cc | 87 | ||||
-rw-r--r-- | webkit/glue/webplugin_impl.h | 6 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_webview_delegate.cc | 30 |
17 files changed, 237 insertions, 193 deletions
diff --git a/chrome/browser/plugin_process_host.cc b/chrome/browser/plugin_process_host.cc index 4607b2a..50ca1b9 100644 --- a/chrome/browser/plugin_process_host.cc +++ b/chrome/browser/plugin_process_host.cc @@ -347,6 +347,86 @@ class PluginResolveProxyHelper : RevocableStore::Revocable { }; +// Sends the reply to the create window message on the IO thread. +class SendReplyTask : public Task { + public: + SendReplyTask(FilePath plugin_path, IPC::Message* reply_msg) + : plugin_path_(plugin_path), reply_msg_(reply_msg) { } + + virtual void Run() { + PluginProcessHost* plugin = + PluginService::GetInstance()->FindPluginProcess(plugin_path_); + if (!plugin) + return; + + plugin->Send(reply_msg_); + } + + private: + FilePath plugin_path_; + IPC::Message* reply_msg_; +}; + + +// Creates a child window of the given HWND on the UI thread. +class CreateWindowTask : public Task { + public: + CreateWindowTask( + FilePath plugin_path, HWND parent, IPC::Message* reply_msg) + : plugin_path_(plugin_path), parent_(parent), reply_msg_(reply_msg) { } + + virtual void Run() { + static ATOM window_class = 0; + if (!window_class) { + WNDCLASSEX wcex; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_DBLCLKS; + wcex.lpfnWndProc = DefWindowProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = GetModuleHandle(NULL); + wcex.hIcon = 0; + wcex.hCursor = 0; + wcex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW+1); + wcex.lpszMenuName = 0; + wcex.lpszClassName = L"NativeWindowClassWrapper"; + wcex.hIconSm = 0; + window_class = RegisterClassEx(&wcex); + } + + HWND window = CreateWindowEx( + WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR, + MAKEINTATOM(window_class), 0, + WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, + 0, 0, 0, 0, parent_, 0, GetModuleHandle(NULL), 0); + + PluginProcessHostMsg_CreateWindow::WriteReplyParams( + reply_msg_, window); + + g_browser_process->io_thread()->message_loop()->PostTask( + FROM_HERE, new SendReplyTask(plugin_path_, reply_msg_)); + } + + private: + FilePath plugin_path_; + HWND parent_; + IPC::Message* reply_msg_; +}; + +// Destroys the given window on the UI thread. +class DestroyWindowTask : public Task { + public: + DestroyWindowTask(HWND window) : window_(window) { } + + virtual void Run() { + DestroyWindow(window_); + } + + private: + HWND window_; +}; + + PluginProcessHost::PluginProcessHost(PluginService* plugin_service) : process_(NULL), opening_channel_(false), @@ -580,6 +660,9 @@ void PluginProcessHost::OnMessageReceived(const IPC::Message& msg) { IPC_MESSAGE_HANDLER(PluginProcessHostMsg_GetCookies, OnGetCookies) IPC_MESSAGE_HANDLER_DELAY_REPLY(PluginProcessHostMsg_ResolveProxy, OnResolveProxy) + IPC_MESSAGE_HANDLER_DELAY_REPLY(PluginProcessHostMsg_CreateWindow, + OnCreateWindow) + IPC_MESSAGE_HANDLER(PluginProcessHostMsg_DestroyWindow, OnDestroyWindow) IPC_MESSAGE_UNHANDLED_ERROR() IPC_END_MESSAGE_MAP() @@ -839,6 +922,17 @@ void PluginProcessHost::OnGetPluginDataDir(std::wstring* retval) { *retval = plugin_service_->GetChromePluginDataDir(); } +void PluginProcessHost::OnCreateWindow(HWND parent, IPC::Message* reply_msg) { + // Need to create this window on the UI thread. + plugin_service_->main_message_loop()->PostTask(FROM_HERE, + new CreateWindowTask(plugin_path_, parent, reply_msg)); +} + +void PluginProcessHost::OnDestroyWindow(HWND window) { + plugin_service_->main_message_loop()->PostTask(FROM_HERE, + new DestroyWindowTask(window)); +} + void PluginProcessHost::Shutdown() { Send(new PluginProcessMsg_BrowserShutdown); diff --git a/chrome/browser/plugin_process_host.h b/chrome/browser/plugin_process_host.h index 713c2d4..24737fc 100644 --- a/chrome/browser/plugin_process_host.h +++ b/chrome/browser/plugin_process_host.h @@ -111,10 +111,11 @@ class PluginProcessHost : public IPC::Channel::Listener, void OnGetCookies(uint32 request_context, const GURL& url, std::string* cookies); void OnResolveProxy(const GURL& url, IPC::Message* reply_msg); - void OnPluginShutdownRequest(); void OnPluginMessage(const std::vector<uint8>& data); void OnGetPluginDataDir(std::wstring* retval); + void OnCreateWindow(HWND parent, IPC::Message* reply_msg); + void OnDestroyWindow(HWND window); struct ChannelRequest { ChannelRequest(ResourceMessageFilter* renderer_message_filter, diff --git a/chrome/browser/render_widget_host.cc b/chrome/browser/render_widget_host.cc index 2823cba..9ce5f0a 100644 --- a/chrome/browser/render_widget_host.cc +++ b/chrome/browser/render_widget_host.cc @@ -436,6 +436,9 @@ void RenderWidgetHost::OnMsgScrollRect( void RenderWidgetHost::MovePluginWindows( const std::vector<WebPluginGeometry>& plugin_window_moves) { + if (plugin_window_moves.empty()) + return; + HDWP defer_window_pos_info = ::BeginDeferWindowPos(static_cast<int>(plugin_window_moves.size())); @@ -445,7 +448,10 @@ void RenderWidgetHost::MovePluginWindows( } for (size_t i = 0; i < plugin_window_moves.size(); ++i) { - unsigned long flags = 0; + // Don't invalidate now because that would result in cross process calls + // that make scrolling slow. Instead the window is invalidated + // asynchronously by the plugin code. + unsigned long flags = SWP_NOREDRAW; const WebPluginGeometry& move = plugin_window_moves[i]; if (move.visible) diff --git a/chrome/common/plugin_messages_internal.h b/chrome/common/plugin_messages_internal.h index d78bb5e..1d9380c 100644 --- a/chrome/common/plugin_messages_internal.h +++ b/chrome/common/plugin_messages_internal.h @@ -81,6 +81,15 @@ IPC_BEGIN_MESSAGES(PluginProcessHost, 4) int /* network error */, std::string /* proxy list */) + // Creates a child window of the given parent window on the UI thread. + IPC_SYNC_MESSAGE_CONTROL1_1(PluginProcessHostMsg_CreateWindow, + HWND /* parent */, + HWND /* child */) + + // Destroys the given window on the UI thread. + IPC_MESSAGE_CONTROL1(PluginProcessHostMsg_DestroyWindow, + HWND /* window */) + IPC_END_MESSAGES(PluginProcessHost) @@ -131,11 +140,9 @@ IPC_BEGIN_MESSAGES(Plugin, 5) // contains a buffer that the plugin draws into. background_buffer is used // for transparent windowless plugins, and holds the background of the plugin // rectangle. - IPC_MESSAGE_ROUTED6(PluginMsg_UpdateGeometry, + IPC_MESSAGE_ROUTED4(PluginMsg_UpdateGeometry, gfx::Rect /* window_rect */, gfx::Rect /* clip_rect */, - std::vector<gfx::Rect> /* cutout_rects */, - bool /* visible */, base::SharedMemoryHandle /* windowless_buffer */, base::SharedMemoryHandle /* background_buffer */) diff --git a/chrome/plugin/webplugin_delegate_stub.cc b/chrome/plugin/webplugin_delegate_stub.cc index 6d9cfe6..28c0e63 100644 --- a/chrome/plugin/webplugin_delegate_stub.cc +++ b/chrome/plugin/webplugin_delegate_stub.cc @@ -239,13 +239,10 @@ void WebPluginDelegateStub::OnPrint(PluginMsg_PrintResponse_Params* params) { void WebPluginDelegateStub::OnUpdateGeometry( const gfx::Rect& window_rect, const gfx::Rect& clip_rect, - const std::vector<gfx::Rect>& cutout_rects, - bool visible, const base::SharedMemoryHandle& windowless_buffer, const base::SharedMemoryHandle& background_buffer) { webplugin_->UpdateGeometry( - window_rect, clip_rect, cutout_rects, visible, windowless_buffer, - background_buffer); + window_rect, clip_rect, windowless_buffer, background_buffer); } void WebPluginDelegateStub::OnGetPluginScriptableObject(int* route_id, diff --git a/chrome/plugin/webplugin_delegate_stub.h b/chrome/plugin/webplugin_delegate_stub.h index 8b49991..1cc21631 100644 --- a/chrome/plugin/webplugin_delegate_stub.h +++ b/chrome/plugin/webplugin_delegate_stub.h @@ -65,8 +65,6 @@ class WebPluginDelegateStub : public IPC::Channel::Listener, void OnUpdateGeometry(const gfx::Rect& window_rect, const gfx::Rect& clip_rect, - const std::vector<gfx::Rect>& cutout_rects, - bool visible, const base::SharedMemoryHandle& windowless_buffer, const base::SharedMemoryHandle& background_buffer); void OnGetPluginScriptableObject(int* route_id, void** npobject_ptr); diff --git a/chrome/plugin/webplugin_proxy.cc b/chrome/plugin/webplugin_proxy.cc index 02bd802..7302cbe 100644 --- a/chrome/plugin/webplugin_proxy.cc +++ b/chrome/plugin/webplugin_proxy.cc @@ -12,10 +12,11 @@ #include "chrome/common/gfx/chrome_canvas.h" #include "chrome/common/plugin_messages.h" #include "chrome/common/win_util.h" -#include "chrome/plugin/plugin_channel.h" -#include "chrome/plugin/webplugin_delegate_stub.h" #include "chrome/plugin/npobject_proxy.h" #include "chrome/plugin/npobject_util.h" +#include "chrome/plugin/plugin_channel.h" +#include "chrome/plugin/plugin_thread.h" +#include "chrome/plugin/webplugin_delegate_stub.h" #include "skia/ext/platform_device.h" #include "webkit/glue/plugins/webplugin_delegate_impl.h" @@ -37,7 +38,8 @@ WebPluginProxy::WebPluginProxy( delegate_(delegate), waiting_for_paint_(false), #pragma warning(suppress: 4355) // can use this - runnable_method_factory_(this) { + runnable_method_factory_(this), + parent_window_(NULL) { HANDLE event; BOOL result = DuplicateHandle(channel->renderer_handle(), @@ -54,6 +56,11 @@ WebPluginProxy::WebPluginProxy( WebPluginProxy::~WebPluginProxy() { if (cp_browsing_context_) GetContextMap().erase(cp_browsing_context_); + + if (parent_window_) { + PluginThread::GetPluginThread()->Send( + new PluginProcessHostMsg_DestroyWindow(parent_window_)); + } } bool WebPluginProxy::Send(IPC::Message* msg) { @@ -70,6 +77,26 @@ void WebPluginProxy::SetWindow(HWND window, HANDLE pump_messages_event) { &pump_messages_event_for_renderer, 0, FALSE, DUPLICATE_SAME_ACCESS); DCHECK(pump_messages_event_for_renderer != NULL); + } else { + DCHECK (window); + // To make scrolling windowed plugins fast, we create the page's direct + // child windows in the browser process. This way no cross process messages + // are sent. + HWND old_parent = GetParent(window); + IPC::SyncMessage* msg = new PluginProcessHostMsg_CreateWindow( + old_parent, &parent_window_); + + // Need to process window messages in the meantime to avoid a deadlock if + // the browser paints or sends any other (synchronous) WM_ message to the + // plugin window. + msg->EnableMessagePumping(); + PluginThread::GetPluginThread()->Send(msg); + + SetParent(window, parent_window_); + + // We want the browser process to move this window which has a message loop + // in its process. + window = parent_window_; } Send(new PluginHostMsg_SetWindow(route_id_, window, @@ -295,8 +322,6 @@ void WebPluginProxy::Paint(const gfx::Rect& rect) { void WebPluginProxy::UpdateGeometry( const gfx::Rect& window_rect, const gfx::Rect& clip_rect, - const std::vector<gfx::Rect>& cutout_rects, - bool visible, const base::SharedMemoryHandle& windowless_buffer, const base::SharedMemoryHandle& background_buffer) { gfx::Rect old = delegate_->rect(); @@ -304,7 +329,7 @@ void WebPluginProxy::UpdateGeometry( bool moved = delegate_->rect().x() != window_rect.x() || delegate_->rect().y() != window_rect.y(); - delegate_->UpdateGeometry(window_rect, clip_rect, cutout_rects, visible); + delegate_->UpdateGeometry(window_rect, clip_rect); if (windowless_buffer) { // The plugin's rect changed, so now we have a new buffer to draw into. SetWindowlessBuffer(windowless_buffer, background_buffer); @@ -314,7 +339,7 @@ void WebPluginProxy::UpdateGeometry( } // Send over any pending invalidates which occured when the plugin was // off screen. - if (visible && delegate_->windowless() && !clip_rect.IsEmpty() && + if (delegate_->windowless() && !clip_rect.IsEmpty() && old_clip_rect.IsEmpty() && !damaged_rect_.IsEmpty()) { InvalidateRect(damaged_rect_); } diff --git a/chrome/plugin/webplugin_proxy.h b/chrome/plugin/webplugin_proxy.h index 7828abf..9f6177b 100644 --- a/chrome/plugin/webplugin_proxy.h +++ b/chrome/plugin/webplugin_proxy.h @@ -86,8 +86,6 @@ class WebPluginProxy : public WebPlugin { void UpdateGeometry(const gfx::Rect& window_rect, const gfx::Rect& clip_rect, - const std::vector<gfx::Rect>& cutout_rects, - bool visible, const base::SharedMemoryHandle& windowless_buffer, const base::SharedMemoryHandle& background_buffer); @@ -132,6 +130,7 @@ class WebPluginProxy : public WebPlugin { bool waiting_for_paint_; uint32 cp_browsing_context_; scoped_ptr<base::WaitableEvent> modal_dialog_event_; + HWND parent_window_; // Variables used for desynchronized windowless plugin painting. See note in // webplugin_delegate_proxy.h for how this works. diff --git a/chrome/renderer/webplugin_delegate_proxy.cc b/chrome/renderer/webplugin_delegate_proxy.cc index f4c61a2..a13053b 100644 --- a/chrome/renderer/webplugin_delegate_proxy.cc +++ b/chrome/renderer/webplugin_delegate_proxy.cc @@ -152,7 +152,6 @@ WebPluginDelegateProxy::WebPluginDelegateProxy(const std::string& mime_type, windowless_(false), npobject_(NULL), send_deferred_update_geometry_(false), - visible_(false), sad_plugin_(NULL), window_script_object_(NULL), transparent_(false), @@ -196,8 +195,6 @@ void WebPluginDelegateProxy::FlushGeometryUpdates() { Send(new PluginMsg_UpdateGeometry(instance_id_, plugin_rect_, deferred_clip_rect_, - deferred_cutout_rects_, - visible_, NULL, NULL)); } @@ -350,14 +347,10 @@ void WebPluginDelegateProxy::OnChannelError() { void WebPluginDelegateProxy::UpdateGeometry( const gfx::Rect& window_rect, - const gfx::Rect& clip_rect, - const std::vector<gfx::Rect>& cutout_rects, - bool visible) { + const gfx::Rect& clip_rect) { plugin_rect_ = window_rect; if (!windowless_) { deferred_clip_rect_ = clip_rect; - deferred_cutout_rects_ = cutout_rects; - visible_ = visible; send_deferred_update_geometry_ = true; return; } @@ -387,7 +380,7 @@ void WebPluginDelegateProxy::UpdateGeometry( } IPC::Message* msg = new PluginMsg_UpdateGeometry( - instance_id_, window_rect, clip_rect, cutout_rects, visible, + instance_id_, window_rect, clip_rect, transport_store_handle, background_store_handle); msg->set_unblock(true); Send(msg); diff --git a/chrome/renderer/webplugin_delegate_proxy.h b/chrome/renderer/webplugin_delegate_proxy.h index 521b763..65b1edb 100644 --- a/chrome/renderer/webplugin_delegate_proxy.h +++ b/chrome/renderer/webplugin_delegate_proxy.h @@ -56,9 +56,7 @@ class WebPluginDelegateProxy : public WebPluginDelegate, virtual bool Initialize(const GURL& url, char** argn, char** argv, int argc, WebPlugin* plugin, bool load_manually); virtual void UpdateGeometry(const gfx::Rect& window_rect, - const gfx::Rect& clip_rect, - const std::vector<gfx::Rect>& cutout_rects, - bool visible); + const gfx::Rect& clip_rect); virtual void Paint(HDC hdc, const gfx::Rect& rect); virtual void Print(HDC hdc); virtual NPObject* GetPluginScriptableObject(); @@ -162,9 +160,7 @@ class WebPluginDelegateProxy : public WebPluginDelegate, gfx::Rect plugin_rect_; gfx::Rect deferred_clip_rect_; - std::vector<gfx::Rect> deferred_cutout_rects_; bool send_deferred_update_geometry_; - bool visible_; NPObject* npobject_; NPObjectStub* window_script_object_; diff --git a/webkit/glue/plugins/test/plugin_npobject_lifetime_test.cc b/webkit/glue/plugins/test/plugin_npobject_lifetime_test.cc index 8f3a89f..2907a5e 100644 --- a/webkit/glue/plugins/test/plugin_npobject_lifetime_test.cc +++ b/webkit/glue/plugins/test/plugin_npobject_lifetime_test.cc @@ -113,9 +113,6 @@ NPObjectDeletePluginInNPN_Evaluate::~NPObjectDeletePluginInNPN_Evaluate() { } NPError NPObjectDeletePluginInNPN_Evaluate::SetWindow(NPWindow* np_window) { - if (!::IsWindowVisible(reinterpret_cast<HWND>(np_window->window))) - return NPERR_NO_ERROR; - HWND window_handle = reinterpret_cast<HWND>(np_window->window); // We setup a timerproc to invoke NPN_Evaluate to destroy this plugin // instance. This is to ensure that we don't destroy the plugin instance diff --git a/webkit/glue/plugins/webplugin_delegate_impl.cc b/webkit/glue/plugins/webplugin_delegate_impl.cc index 0f713d7..a0de8da 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl.cc +++ b/webkit/glue/plugins/webplugin_delegate_impl.cc @@ -9,8 +9,6 @@ #include "base/file_util.h" #include "base/message_loop.h" -#include "base/gfx/gdi_util.h" -#include "base/gfx/point.h" #include "base/stats_counters.h" #include "base/string_util.h" #include "webkit/default_plugin/plugin_impl.h" @@ -133,7 +131,6 @@ WebPluginDelegateImpl::WebPluginDelegateImpl( plugin_wnd_proc_(NULL), last_message_(0), is_calling_wndproc(false), - initial_plugin_resize_done_(false), dummy_window_for_activation_(NULL), handle_event_message_filter_hook_(NULL), handle_event_pump_messages_event_(NULL), @@ -322,13 +319,11 @@ void WebPluginDelegateImpl::DestroyInstance() { void WebPluginDelegateImpl::UpdateGeometry( const gfx::Rect& window_rect, - const gfx::Rect& clip_rect, - const std::vector<gfx::Rect>& cutout_rects, - bool visible) { + const gfx::Rect& clip_rect) { if (windowless_) { WindowlessUpdateGeometry(window_rect, clip_rect); } else { - WindowedUpdateGeometry(window_rect, clip_rect, cutout_rects, visible); + WindowedUpdateGeometry(window_rect, clip_rect); } } @@ -377,6 +372,12 @@ void WebPluginDelegateImpl::SendJavaScriptStream(const std::string& url, void WebPluginDelegateImpl::DidReceiveManualResponse( const std::string& url, const std::string& mime_type, const std::string& headers, uint32 expected_length, uint32 last_modified) { + if (!windowless_) { + // Calling NPP_WriteReady before NPP_SetWindow causes movies to not load in + // Flash. See http://b/issue?id=892174. + DCHECK(windowed_did_set_window_); + } + instance()->DidReceiveManualResponse(url, mime_type, headers, expected_length, last_modified); } @@ -408,10 +409,8 @@ void WebPluginDelegateImpl::InstallMissingPlugin() { void WebPluginDelegateImpl::WindowedUpdateGeometry( const gfx::Rect& window_rect, - const gfx::Rect& clip_rect, - const std::vector<gfx::Rect>& cutout_rects, - bool visible) { - if (WindowedReposition(window_rect, clip_rect, cutout_rects, visible) || + const gfx::Rect& clip_rect) { + if (WindowedReposition(window_rect, clip_rect) || !windowed_did_set_window_) { // Let the plugin know that it has been moved WindowedSetWindow(); @@ -663,69 +662,33 @@ bool WebPluginDelegateImpl::CreateDummyWindowForActivation() { return true; } -void WebPluginDelegateImpl::MoveWindow( - HWND window, - const gfx::Rect& window_rect, - const gfx::Rect& clip_rect, - const std::vector<gfx::Rect>& cutout_rects, - bool visible) { - HRGN hrgn = ::CreateRectRgn(clip_rect.x(), - clip_rect.y(), - clip_rect.right(), - clip_rect.bottom()); - gfx::SubtractRectanglesFromRegion(hrgn, cutout_rects); - - // Note: System will own the hrgn after we call SetWindowRgn, - // so we don't need to call DeleteObject(hrgn) - ::SetWindowRgn(window, hrgn, FALSE); - - unsigned long flags = 0; - if (visible) - flags |= SWP_SHOWWINDOW; - else - flags |= SWP_HIDEWINDOW; - - ::SetWindowPos(window, - NULL, - window_rect.x(), - window_rect.y(), - window_rect.width(), - window_rect.height(), - flags); -} - bool WebPluginDelegateImpl::WindowedReposition( const gfx::Rect& window_rect, - const gfx::Rect& clip_rect, - const std::vector<gfx::Rect>& cutout_rects, - bool visible) { + const gfx::Rect& clip_rect) { if (!windowed_handle_) { NOTREACHED(); return false; } - if (window_rect_ == window_rect && clip_rect_ == clip_rect && - cutout_rects == cutout_rects_ && - initial_plugin_resize_done_) + if (window_rect_ == window_rect && clip_rect_ == clip_rect) return false; + // Clipping is handled by WebPlugin. + if (window_rect.size() != window_rect_.size()) { + ::SetWindowPos(windowed_handle_, + NULL, + 0, + 0, + window_rect.width(), + window_rect.height(), + SWP_SHOWWINDOW); + } + window_rect_ = window_rect; clip_rect_ = clip_rect; - cutout_rects_ = cutout_rects; - - if (!initial_plugin_resize_done_) { - // We need to ensure that the plugin process continues to reposition - // the plugin window until we receive an indication that it is now visible. - // Subsequent repositions will be done by the browser. - if (visible) - initial_plugin_resize_done_ = true; - // We created the window with 0 width and height since we didn't know it - // at the time. Now that we know the geometry, we we can update its size - // since the browser only calls SetWindowPos when scrolling occurs. - MoveWindow(windowed_handle_, window_rect, clip_rect, cutout_rects, visible); - // Ensure that the entire window gets repainted. - ::InvalidateRect(windowed_handle_, NULL, FALSE); - } + + // Ensure that the entire window gets repainted. + ::InvalidateRect(windowed_handle_, NULL, FALSE); return true; } diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h index 468d3c7..d01046c 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl.h +++ b/webkit/glue/plugins/webplugin_delegate_impl.h @@ -44,9 +44,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate { WebPlugin* plugin, bool load_manually); virtual void UpdateGeometry(const gfx::Rect& window_rect, - const gfx::Rect& clip_rect, - const std::vector<gfx::Rect>& cutout_rects, - bool visible); + const gfx::Rect& clip_rect); virtual void Paint(HDC hdc, const gfx::Rect& rect); virtual void Print(HDC hdc); virtual void SetFocus(); // only called when windowless @@ -99,12 +97,6 @@ class WebPluginDelegateImpl : public WebPluginDelegate { int quirks() { return quirks_; } - static void MoveWindow(HWND window, - const gfx::Rect& window_rect, - const gfx::Rect& clip_rect, - const std::vector<gfx::Rect>& cutout_rects, - bool visible); - private: WebPluginDelegateImpl(gfx::NativeView containing_view, NPAPI::PluginInstance *instance); @@ -113,9 +105,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate { //-------------------------- // used for windowed plugins void WindowedUpdateGeometry(const gfx::Rect& window_rect, - const gfx::Rect& clip_rect, - const std::vector<gfx::Rect>& cutout_rects, - bool visible); + const gfx::Rect& clip_rect); // Create the native window. // Returns true if the window is created (or already exists). // Returns false if unable to create the window. @@ -127,9 +117,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate { // Reposition the native window to be in sync with the given geometry. // Returns true if the native window has moved or been clipped differently. bool WindowedReposition(const gfx::Rect& window_rect, - const gfx::Rect& clip_rect, - const std::vector<gfx::Rect>& cutout_rects, - bool visible); + const gfx::Rect& clip_rect); // Tells the plugin about the current state of the window. // See NPAPI NPP_SetWindow for more information. @@ -202,11 +190,6 @@ class WebPluginDelegateImpl : public WebPluginDelegate { std::vector<gfx::Rect> cutout_rects_; int quirks_; - // We only move/size the plugin window once after its creation. The - // rest of the moves are controlled by the browser. This flag controls - // this behaviour. - bool initial_plugin_resize_done_; - // Windowless plugins don't have keyboard focus causing issues with the // plugin not receiving keyboard events if the plugin enters a modal // loop like TrackPopupMenuEx or MessageBox, etc. diff --git a/webkit/glue/webplugin_delegate.h b/webkit/glue/webplugin_delegate.h index bfa462a..7ffd952 100644 --- a/webkit/glue/webplugin_delegate.h +++ b/webkit/glue/webplugin_delegate.h @@ -48,13 +48,9 @@ class WebPluginDelegate { // plugin, relative to its containing window, to the coords given by // window_rect. Its contents should be clipped to the coords given // by clip_rect, which are relative to the origin of the plugin - // window. It's contents should also not overlap the given cutout - // rects. The clip_rect and cutout_rects are in plugin-relative - // coordinates. + // window. The clip_rect is in plugin-relative coordinates. virtual void UpdateGeometry(const gfx::Rect& window_rect, - const gfx::Rect& clip_rect, - const std::vector<gfx::Rect>& cutout_rects, - bool visible) = 0; + const gfx::Rect& clip_rect) = 0; // Tells the plugin to paint the damaged rect. The HDC is only used for // windowless plugins. diff --git a/webkit/glue/webplugin_impl.cc b/webkit/glue/webplugin_impl.cc index 003ece7..72234ad 100644 --- a/webkit/glue/webplugin_impl.cc +++ b/webkit/glue/webplugin_impl.cc @@ -134,6 +134,11 @@ bool WebPluginContainer::isPluginView() const { void WebPluginContainer::setFrameRect(const WebCore::IntRect& rect) { + // WebKit calls move every time it paints (see RenderWidget::paint). No need + // to do expensive operations if we didn't actually move. + if (rect == frameRect()) + return; + WebCore::Widget::setFrameRect(rect); impl_->setFrameRect(rect); } @@ -166,12 +171,8 @@ void WebPluginContainer::setFocus() { void WebPluginContainer::show() { // We don't want to force a geometry update when the plugin widget is // already visible as this involves a geometry update which may lead - // to unnecessary window moves in the plugin process. The only case - // where this does not apply is if the force_geometry_update_ flag - // is set, which occurs when a plugin is created and does not have - // a parent. We can send out geometry updates only when the plugin - // widget has a parent. - if (!impl_->visible_ || impl_->force_geometry_update_) { + // to unnecessary window moves in the plugin process. + if (!impl_->visible_) { impl_->show(); WebCore::Widget::show(); // This is to force an updategeometry call to the plugin process @@ -181,9 +182,7 @@ void WebPluginContainer::show() { } void WebPluginContainer::hide() { - // Please refer to WebPluginContainer::show for the reasoning behind - // the if check below. - if (impl_->visible_ || impl_->force_geometry_update_) { + if (impl_->visible_) { impl_->hide(); WebCore::Widget::hide(); // This is to force an updategeometry call to the plugin process @@ -216,6 +215,18 @@ void WebPluginContainer::setParentVisible(bool visible) { hide(); } +// We override this function so that if the plugin is windowed, we can call +// NPP_SetWindow at the first possible moment. This ensures that NPP_SetWindow +// is called before the manual load data is sent to a plugin. If this order is +// reversed, Flash won't load videos. +void WebPluginContainer::setParent(WebCore::ScrollView* view) { + WebCore::Widget::setParent(view); + if (view) { + impl_->setFrameRect(frameRect()); + impl_->delegate_->FlushGeometryUpdates(); + } +} + void WebPluginContainer::windowCutoutRects(const WebCore::IntRect& bounds, WTF::Vector<WebCore::IntRect>* cutouts) const { @@ -224,7 +235,6 @@ void WebPluginContainer::windowCutoutRects(const WebCore::IntRect& bounds, void WebPluginContainer::didReceiveResponse( const WebCore::ResourceResponse& response) { - set_ignore_response_error(false); HttpResponseInfo http_response_info; @@ -315,9 +325,7 @@ WebPluginImpl::WebPluginImpl(WebCore::Element* element, element_(element), webframe_(webframe), delegate_(delegate), - force_geometry_update_(false), visible_(false), - received_first_paint_notification_(false), widget_(NULL), plugin_url_(plugin_url), load_manually_(load_manually), @@ -634,18 +642,11 @@ void WebPluginImpl::windowCutoutRects( } void WebPluginImpl::setFrameRect(const WebCore::IntRect& rect) { - // Compute a new position and clip rect for ourselves relative to the - // containing window. We ask our delegate to reposition us accordingly. - - // When the plugin is loaded we don't have a parent frame yet. We need - // to force the plugin window to get created in the plugin process, - // when the plugin widget position is updated. This occurs just after - // the plugin is loaded (See http://b/issue?id=892174). - if (!parent()) { - force_geometry_update_ = true; + if (!parent()) return; - } + // Compute a new position and clip rect for ourselves relative to the + // containing window. We ask our delegate to reposition us accordingly. WebCore::Frame* frame = element_->document()->frame(); WebFrameImpl* webframe = WebFrameImpl::FromFrame(frame); WebViewImpl* webview = webframe->webview_impl(); @@ -660,7 +661,11 @@ void WebPluginImpl::setFrameRect(const WebCore::IntRect& rect) { std::vector<gfx::Rect> cutout_rects; CalculateBounds(rect, &window_rect, &clip_rect, &cutout_rects); - if (window_ && received_first_paint_notification_) { + delegate_->UpdateGeometry( + webkit_glue::FromIntRect(window_rect), + webkit_glue::FromIntRect(clip_rect)); + + if (window_) { // Let the WebViewDelegate know that the plugin window needs to be moved, // so that all the HWNDs are moved together. WebPluginGeometry move; @@ -673,17 +678,6 @@ void WebPluginImpl::setFrameRect(const WebCore::IntRect& rect) { webview->delegate()->DidMove(webview, move); } - delegate_->UpdateGeometry( - webkit_glue::FromIntRect(window_rect), - webkit_glue::FromIntRect(clip_rect), cutout_rects, - windowless_ || received_first_paint_notification_ ? visible_ : false); - - // delegate_ can go away as a result of above call, so check it first. - if (force_geometry_update_ && delegate_) { - force_geometry_update_ = false; - delegate_->FlushGeometryUpdates(); - } - // Initiate a download on the plugin url. This should be done for the // first update geometry sequence. if (first_geometry_update_) { @@ -709,31 +703,6 @@ void WebPluginImpl::paint(WebCore::GraphicsContext* gc, if (!widget_->frameRect().intersects(damage_rect)) return; - // A windowed plugin starts out by being invisible regardless of the style - // which webkit tells us. The paint notification from webkit indicates that - // the plugin widget is being shown and we need to make sure that - // it becomes visible. - // Please refer to https://bugs.webkit.org/show_bug.cgi?id=18901 for more - // details on this issue. - // TODO(iyengar): Remove this hack when this issue is fixed in webkit. - if (!received_first_paint_notification_) { - received_first_paint_notification_ = true; - - if (!windowless_) { - WebCore::IntRect window_rect; - WebCore::IntRect clip_rect; - std::vector<gfx::Rect> cutout_rects; - - CalculateBounds(widget_->frameRect(), &window_rect, &clip_rect, - &cutout_rects); - - delegate_->UpdateGeometry(webkit_glue::FromIntRect(window_rect), - webkit_glue::FromIntRect(clip_rect), - cutout_rects, visible_); - delegate_->FlushGeometryUpdates(); - } - } - gc->save(); DCHECK(parent()->isFrameView()); diff --git a/webkit/glue/webplugin_impl.h b/webkit/glue/webplugin_impl.h index 1d11d71..3654d3a 100644 --- a/webkit/glue/webplugin_impl.h +++ b/webkit/glue/webplugin_impl.h @@ -41,6 +41,7 @@ namespace WebCore { class ResourceHandle; class ResourceError; class ResourceResponse; + class ScrollView; class String; class Widget; } @@ -66,6 +67,7 @@ class WebPluginContainer : public WebCore::Widget { virtual void handleEvent(WebCore::Event* event); virtual void frameRectsChanged(); virtual void setParentVisible(bool visible); + virtual void setParent(WebCore::ScrollView* view); #if USE(JSC) virtual bool isPluginView() const; @@ -325,11 +327,7 @@ class WebPluginImpl : public WebPlugin, WebFrameImpl* webframe_; WebPluginDelegate* delegate_; - bool force_geometry_update_; bool visible_; - // Set when we receive the first paint notification for a windowed - // plugin widget. - bool received_first_paint_notification_; WebPluginContainer* widget_; diff --git a/webkit/tools/test_shell/test_webview_delegate.cc b/webkit/tools/test_shell/test_webview_delegate.cc index fc28aa1..631d48e 100644 --- a/webkit/tools/test_shell/test_webview_delegate.cc +++ b/webkit/tools/test_shell/test_webview_delegate.cc @@ -29,6 +29,7 @@ #if defined(OS_WIN) // TODO(port): make these files work everywhere. +#include "base/gfx/gdi_util.h" #include "webkit/glue/plugins/webplugin_delegate_impl.h" #include "webkit/tools/test_shell/drag_delegate.h" #include "webkit/tools/test_shell/drop_delegate.h" @@ -696,11 +697,32 @@ void TestWebViewDelegate::Blur(WebWidget* webwidget) { void TestWebViewDelegate::DidMove(WebWidget* webwidget, const WebPluginGeometry& move) { #if defined(OS_WIN) - // TODO(port): add me once plugins work. - WebPluginDelegateImpl::MoveWindow( - move.window, move.window_rect, move.clip_rect, move.cutout_rects, - move.visible); + HRGN hrgn = ::CreateRectRgn(move.clip_rect.x(), + move.clip_rect.y(), + move.clip_rect.right(), + move.clip_rect.bottom()); + gfx::SubtractRectanglesFromRegion(hrgn, move.cutout_rects); + + // Note: System will own the hrgn after we call SetWindowRgn, + // so we don't need to call DeleteObject(hrgn) + ::SetWindowRgn(move.window, hrgn, FALSE); + + unsigned long flags = 0; + if (move.visible) + flags |= SWP_SHOWWINDOW; + else + flags |= SWP_HIDEWINDOW; + + ::SetWindowPos(move.window, + NULL, + move.window_rect.x(), + move.window_rect.y(), + move.window_rect.width(), + move.window_rect.height(), + flags); + #endif + // TODO(port): add me once plugins work. } bool TestWebViewDelegate::IsHidden() { |