diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-16 23:04:23 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-16 23:04:23 +0000 |
commit | d7f4595986302dcf131b943152a843d067e53c1e (patch) | |
tree | 7165e6c839aaae33587dab4dbc28df862d1c8428 /chrome/browser | |
parent | efb07436b9ba4737247cdf0e8ba0529e27942468 (diff) | |
download | chromium_src-d7f4595986302dcf131b943152a843d067e53c1e.zip chromium_src-d7f4595986302dcf131b943152a843d067e53c1e.tar.gz chromium_src-d7f4595986302dcf131b943152a843d067e53c1e.tar.bz2 |
Improve scrolling performance when there are many windowed plugins in a page.
This works by parenting windowed plugins with an HWND that's hosted in the browser process, so that no synchronous cross process messages are used when scrolling.
BUG=5428
Review URL: http://codereview.chromium.org/18082
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8239 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-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 |
3 files changed, 103 insertions, 2 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) |