summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-16 23:04:23 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-16 23:04:23 +0000
commitd7f4595986302dcf131b943152a843d067e53c1e (patch)
tree7165e6c839aaae33587dab4dbc28df862d1c8428 /chrome
parentefb07436b9ba4737247cdf0e8ba0529e27942468 (diff)
downloadchromium_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')
-rw-r--r--chrome/browser/plugin_process_host.cc94
-rw-r--r--chrome/browser/plugin_process_host.h3
-rw-r--r--chrome/browser/render_widget_host.cc8
-rw-r--r--chrome/common/plugin_messages_internal.h13
-rw-r--r--chrome/plugin/webplugin_delegate_stub.cc5
-rw-r--r--chrome/plugin/webplugin_delegate_stub.h2
-rw-r--r--chrome/plugin/webplugin_proxy.cc39
-rw-r--r--chrome/plugin/webplugin_proxy.h3
-rw-r--r--chrome/renderer/webplugin_delegate_proxy.cc11
-rw-r--r--chrome/renderer/webplugin_delegate_proxy.h6
10 files changed, 150 insertions, 34 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_;