From 24e863243cc6e12da33425f8401f0920170d7062 Mon Sep 17 00:00:00 2001 From: "ananta@chromium.org" Date: Fri, 27 Mar 2009 16:21:25 +0000 Subject: We need to set the clipping region of the HDC passed in to a windowless flash plugin instance in NPP_HandleEvent for WM_PAINT. The windowless flash plugin instance queries the clipping region of the DC and on not finding it proceeds to paint the plugin window rect, which causes unnecessary CPU spikes. This fixes bug http://code.google.com/p/chromium/issues/detail?id=8835, where the plugin process would consume CPU even when we scrolled down to the static video images. With this fix the CPU usage for windowless flash plugins is on par with Firefox. Added a uitest which validates whether the hdc passed in to HandleEvent for WM_PAINT has a valid clipping region. Bug=8835 Review URL: http://codereview.chromium.org/53106 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@12651 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/plugin/webplugin_proxy.cc | 7 ++ webkit/glue/plugins/test/npapi_test_plugin.vcproj | 16 ++--- webkit/glue/plugins/test/plugin_client.cc | 15 ++--- .../test/plugin_execute_script_delete_test.cc | 58 ----------------- .../test/plugin_execute_script_delete_test.h | 28 -------- webkit/glue/plugins/test/plugin_windowless_test.cc | 75 ++++++++++++++++++++++ webkit/glue/plugins/test/plugin_windowless_test.h | 28 ++++++++ 7 files changed, 124 insertions(+), 103 deletions(-) delete mode 100644 webkit/glue/plugins/test/plugin_execute_script_delete_test.cc delete mode 100644 webkit/glue/plugins/test/plugin_execute_script_delete_test.h create mode 100644 webkit/glue/plugins/test/plugin_windowless_test.cc create mode 100644 webkit/glue/plugins/test/plugin_windowless_test.h diff --git a/chrome/plugin/webplugin_proxy.cc b/chrome/plugin/webplugin_proxy.cc index 38310fb..34bdb92 100644 --- a/chrome/plugin/webplugin_proxy.cc +++ b/chrome/plugin/webplugin_proxy.cc @@ -322,9 +322,16 @@ void WebPluginProxy::Paint(const gfx::Rect& rect) { rect.x(), rect.y(), SRCCOPY); } + RECT clip_rect = rect.ToRECT(); + HRGN clip_region = CreateRectRgnIndirect(&clip_rect); + SelectClipRgn(windowless_hdc_, clip_region); + // Before we send the invalidate, paint so that renderer uses the updated // bitmap. delegate_->Paint(windowless_hdc_, offset_rect); + + SelectClipRgn(windowless_hdc_, NULL); + DeleteObject(clip_region); } void WebPluginProxy::UpdateGeometry( diff --git a/webkit/glue/plugins/test/npapi_test_plugin.vcproj b/webkit/glue/plugins/test/npapi_test_plugin.vcproj index 426885d..5c5d95a 100644 --- a/webkit/glue/plugins/test/npapi_test_plugin.vcproj +++ b/webkit/glue/plugins/test/npapi_test_plugin.vcproj @@ -183,14 +183,6 @@ > - - - - @@ -263,6 +255,14 @@ > + + + + diff --git a/webkit/glue/plugins/test/plugin_client.cc b/webkit/glue/plugins/test/plugin_client.cc index 7b00e7c..b515779 100644 --- a/webkit/glue/plugins/test/plugin_client.cc +++ b/webkit/glue/plugins/test/plugin_client.cc @@ -6,7 +6,6 @@ #include "webkit/glue/plugins/test/plugin_client.h" #include "webkit/glue/plugins/test/plugin_arguments_test.h" #include "webkit/glue/plugins/test/plugin_delete_plugin_in_stream_test.h" -#include "webkit/glue/plugins/test/plugin_execute_script_delete_test.h" #include "webkit/glue/plugins/test/plugin_get_javascript_url_test.h" #include "webkit/glue/plugins/test/plugin_geturl_test.h" #include "webkit/glue/plugins/test/plugin_javascript_open_popup.h" @@ -15,6 +14,7 @@ #include "webkit/glue/plugins/test/plugin_npobject_lifetime_test.h" #include "webkit/glue/plugins/test/plugin_npobject_proxy_test.h" #include "webkit/glue/plugins/test/plugin_window_size_test.h" +#include "webkit/glue/plugins/test/plugin_windowless_test.h" #include "third_party/npapi/bindings/npapi.h" #include "third_party/npapi/bindings/npruntime.h" @@ -100,9 +100,11 @@ NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, } else if (base::strcasecmp(argv[name_index], "npobject_proxy") == 0) { new_test = new NPAPIClient::NPObjectProxyTest(instance, NPAPIClient::PluginClient::HostFunctions()); - } else if (base::strcasecmp(argv[name_index], - "execute_script_delete_in_paint") == 0) { - new_test = new NPAPIClient::ExecuteScriptDeleteTest(instance, + } else if ((base::strcasecmp(argv[name_index], + "execute_script_delete_in_paint") == 0) || + (base::strcasecmp(argv[name_index], + "execute_script_delete_in_mouse_move") == 0)) { + new_test = new NPAPIClient::WindowlessPluginTest(instance, NPAPIClient::PluginClient::HostFunctions(), argv[name_index]); windowless_plugin = true; } else if (base::strcasecmp(argv[name_index], "getjavascripturl") == 0) { @@ -138,11 +140,6 @@ NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, "plugin_popup_with_plugin_target") == 0) { new_test = new NPAPIClient::ExecuteJavascriptPopupWindowTargetPluginTest( instance, NPAPIClient::PluginClient::HostFunctions()); - } else if (base::strcasecmp(argv[name_index], - "execute_script_delete_in_mouse_move") == 0) { - new_test = new NPAPIClient::ExecuteScriptDeleteTest(instance, - NPAPIClient::PluginClient::HostFunctions(), argv[name_index]); - windowless_plugin = true; } else if (base::strcasecmp(argv[name_index], "private") == 0) { new_test = new NPAPIClient::PrivateTest(instance, NPAPIClient::PluginClient::HostFunctions()); diff --git a/webkit/glue/plugins/test/plugin_execute_script_delete_test.cc b/webkit/glue/plugins/test/plugin_execute_script_delete_test.cc deleted file mode 100644 index 1087fc3..0000000 --- a/webkit/glue/plugins/test/plugin_execute_script_delete_test.cc +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2006-2008 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. - -#define STRSAFE_NO_DEPRECATE -#include "webkit/glue/plugins/test/plugin_execute_script_delete_test.h" -#include "webkit/glue/plugins/test/plugin_client.h" - -namespace NPAPIClient { - -ExecuteScriptDeleteTest::ExecuteScriptDeleteTest( - NPP id, NPNetscapeFuncs *host_functions, const std::string& test_name) - : PluginTest(id, host_functions), - test_name_(test_name) { -} - -int16 ExecuteScriptDeleteTest::HandleEvent(void* event) { - - NPNetscapeFuncs* browser = NPAPIClient::PluginClient::HostFunctions(); - - NPBool supports_windowless = 0; - NPError result = browser->getvalue(id(), NPNVSupportsWindowless, - &supports_windowless); - if ((result != NPERR_NO_ERROR) || (supports_windowless != TRUE)) { - SetError("Failed to read NPNVSupportsWindowless value"); - SignalTestCompleted(); - return PluginTest::HandleEvent(event); - } - - NPEvent* np_event = reinterpret_cast(event); - if (WM_PAINT == np_event->event && - base::strcasecmp(test_name_.c_str(), - "execute_script_delete_in_paint") == 0) { - NPUTF8* urlString = "javascript:DeletePluginWithinScript()"; - NPUTF8* targetString = NULL; - browser->geturl(id(), urlString, targetString); - SignalTestCompleted(); - } else if (WM_MOUSEMOVE == np_event->event && - base::strcasecmp(test_name_.c_str(), - "execute_script_delete_in_mouse_move") == 0) { - std::string script = "javascript:DeletePluginWithinScript()"; - NPString script_string; - script_string.UTF8Characters = script.c_str(); - script_string.UTF8Length = - static_cast(script.length()); - - NPObject *window_obj = NULL; - browser->getvalue(id(), NPNVWindowNPObject, &window_obj); - NPVariant result_var; - NPError result = browser->evaluate(id(), window_obj, - &script_string, &result_var); - SignalTestCompleted(); - } - // If this test failed, then we'd have crashed by now. - return PluginTest::HandleEvent(event); -} - -} // namespace NPAPIClient diff --git a/webkit/glue/plugins/test/plugin_execute_script_delete_test.h b/webkit/glue/plugins/test/plugin_execute_script_delete_test.h deleted file mode 100644 index 2830fa1..0000000 --- a/webkit/glue/plugins/test/plugin_execute_script_delete_test.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2006-2008 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. - -#ifndef WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_EXECUTE_SCRIPT_DELETE_TEST_H -#define WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_EXECUTE_SCRIPT_DELETE_TEST_H - -#include "webkit/glue/plugins/test/plugin_test.h" - -namespace NPAPIClient { - -// This class tests the case where a plugin instance is deleted by invoking -// a javascript function in the context of a paint event. -class ExecuteScriptDeleteTest : public PluginTest { - public: - // Constructor. - ExecuteScriptDeleteTest(NPP id, NPNetscapeFuncs *host_functions, - const std::string& test_name); - // NPAPI HandleEvent handler - virtual int16 HandleEvent(void* event); - - private: - std::string test_name_; -}; - -} // namespace NPAPIClient - -#endif // WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_EXECUTE_SCRIPT_DELETE_TEST_H diff --git a/webkit/glue/plugins/test/plugin_windowless_test.cc b/webkit/glue/plugins/test/plugin_windowless_test.cc new file mode 100644 index 0000000..131102c --- /dev/null +++ b/webkit/glue/plugins/test/plugin_windowless_test.cc @@ -0,0 +1,75 @@ +// Copyright (c) 2006-2008 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. + +#define STRSAFE_NO_DEPRECATE +#include "webkit/glue/plugins/test/plugin_windowless_test.h" +#include "webkit/glue/plugins/test/plugin_client.h" + +namespace NPAPIClient { + +WindowlessPluginTest::WindowlessPluginTest( + NPP id, NPNetscapeFuncs *host_functions, const std::string& test_name) + : PluginTest(id, host_functions), + test_name_(test_name) { +} + +int16 WindowlessPluginTest::HandleEvent(void* event) { + + NPNetscapeFuncs* browser = NPAPIClient::PluginClient::HostFunctions(); + + NPBool supports_windowless = 0; + NPError result = browser->getvalue(id(), NPNVSupportsWindowless, + &supports_windowless); + if ((result != NPERR_NO_ERROR) || (supports_windowless != TRUE)) { + SetError("Failed to read NPNVSupportsWindowless value"); + SignalTestCompleted(); + return PluginTest::HandleEvent(event); + } + + NPEvent* np_event = reinterpret_cast(event); + if (WM_PAINT == np_event->event && + base::strcasecmp(test_name_.c_str(), + "execute_script_delete_in_paint") == 0) { + HDC paint_dc = reinterpret_cast(np_event->wParam); + if (paint_dc == NULL) { + SetError("Invalid Window DC passed to HandleEvent for WM_PAINT"); + SignalTestCompleted(); + return NPERR_GENERIC_ERROR; + } + + HRGN clipping_region = CreateRectRgn(0, 0, 0, 0); + if (!GetClipRgn(paint_dc, clipping_region)) { + SetError("No clipping region set in window DC"); + DeleteObject(clipping_region); + SignalTestCompleted(); + return NPERR_GENERIC_ERROR; + } + + DeleteObject(clipping_region); + + NPUTF8* urlString = "javascript:DeletePluginWithinScript()"; + NPUTF8* targetString = NULL; + browser->geturl(id(), urlString, targetString); + SignalTestCompleted(); + } else if (WM_MOUSEMOVE == np_event->event && + base::strcasecmp(test_name_.c_str(), + "execute_script_delete_in_mouse_move") == 0) { + std::string script = "javascript:DeletePluginWithinScript()"; + NPString script_string; + script_string.UTF8Characters = script.c_str(); + script_string.UTF8Length = + static_cast(script.length()); + + NPObject *window_obj = NULL; + browser->getvalue(id(), NPNVWindowNPObject, &window_obj); + NPVariant result_var; + NPError result = browser->evaluate(id(), window_obj, + &script_string, &result_var); + SignalTestCompleted(); + } + // If this test failed, then we'd have crashed by now. + return PluginTest::HandleEvent(event); +} + +} // namespace NPAPIClient diff --git a/webkit/glue/plugins/test/plugin_windowless_test.h b/webkit/glue/plugins/test/plugin_windowless_test.h new file mode 100644 index 0000000..93f7cfc --- /dev/null +++ b/webkit/glue/plugins/test/plugin_windowless_test.h @@ -0,0 +1,28 @@ +// Copyright (c) 2006-2008 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. + +#ifndef WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_EXECUTE_SCRIPT_DELETE_TEST_H +#define WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_EXECUTE_SCRIPT_DELETE_TEST_H + +#include "webkit/glue/plugins/test/plugin_test.h" + +namespace NPAPIClient { + +// This class contains a list of windowless plugin tests. Please add additional +// tests to this class. +class WindowlessPluginTest : public PluginTest { + public: + // Constructor. + WindowlessPluginTest(NPP id, NPNetscapeFuncs *host_functions, + const std::string& test_name); + // NPAPI HandleEvent handler + virtual int16 HandleEvent(void* event); + + private: + std::string test_name_; +}; + +} // namespace NPAPIClient + +#endif // WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_EXECUTE_SCRIPT_DELETE_TEST_H -- cgit v1.1