summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortommycli <tommycli@chromium.org>2015-05-05 12:40:49 -0700
committerCommit bot <commit-bot@chromium.org>2015-05-05 19:41:15 +0000
commitee0a49b6fa5c285ec3069f858ee9ba839570eddb (patch)
tree9fc3ae8130d2fc6890f651f7cbde6603c43ef133
parent6ec419de92d2a868d26de12b9795e5985b850113 (diff)
downloadchromium_src-ee0a49b6fa5c285ec3069f858ee9ba839570eddb.zip
chromium_src-ee0a49b6fa5c285ec3069f858ee9ba839570eddb.tar.gz
chromium_src-ee0a49b6fa5c285ec3069f858ee9ba839570eddb.tar.bz2
Plugin Power Saver: Make PPS work well with prerendered pages.
This patch does two things: 1. Fixes PPS interaction with prerender. This is done by having ChromePluginPlaceholder create a PluginPreroller along with the throttler. 2. Adds a browsertest for the above process. a. This required adding a IsThrottled method to PPB_Testing_Private. b. This required modifying the PPS Test Plugin to paint some dummy 'interesting' frames. BUG=471427 Review URL: https://codereview.chromium.org/1114623002 Cr-Commit-Position: refs/heads/master@{#328381}
-rw-r--r--chrome/browser/plugins/plugin_power_saver_browsertest.cc20
-rw-r--r--chrome/browser/prerender/prerender_browsertest.cc24
-rw-r--r--chrome/renderer/chrome_content_renderer_client.cc6
-rw-r--r--chrome/renderer/plugins/chrome_plugin_placeholder.cc19
-rw-r--r--chrome/renderer/plugins/chrome_plugin_placeholder.h3
-rw-r--r--chrome/test/data/prerender/prerender_iframe_plugin_delay_load.html2
-rw-r--r--chrome/test/data/prerender/prerender_plugin_delay_load.html (renamed from chrome/test/data/prerender/plugin_delay_load.html)0
-rw-r--r--chrome/test/data/prerender/prerender_plugin_never_load.html (renamed from chrome/test/data/prerender/plugin_never_load.html)0
-rw-r--r--chrome/test/data/prerender/prerender_plugin_power_saver.html54
-rw-r--r--components/plugins/renderer/loadable_plugin_placeholder.cc19
-rw-r--r--components/plugins/renderer/loadable_plugin_placeholder.h6
-rw-r--r--content/public/renderer/plugin_instance_throttler.h2
-rw-r--r--content/renderer/pepper/plugin_instance_throttler_impl.cc19
-rw-r--r--content/renderer/pepper/plugin_instance_throttler_impl.h6
-rw-r--r--content/renderer/pepper/plugin_module.cc75
-rw-r--r--ppapi/api/private/ppb_testing_private.idl15
-rw-r--r--ppapi/c/private/ppb_testing_private.h14
-rw-r--r--ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c12
-rw-r--r--ppapi/proxy/ppapi_messages.h8
-rw-r--r--ppapi/proxy/ppb_testing_proxy.cc40
-rw-r--r--ppapi/proxy/ppb_testing_proxy.h3
-rw-r--r--ppapi/tests/power_saver_test_plugin.cc64
22 files changed, 305 insertions, 106 deletions
diff --git a/chrome/browser/plugins/plugin_power_saver_browsertest.cc b/chrome/browser/plugins/plugin_power_saver_browsertest.cc
index 21336ad..c1314b6 100644
--- a/chrome/browser/plugins/plugin_power_saver_browsertest.cc
+++ b/chrome/browser/plugins/plugin_power_saver_browsertest.cc
@@ -40,22 +40,22 @@ class PluginPowerSaverBrowserTest : virtual public InProcessBrowserTest {
bool IsPluginPeripheral(const char* element_id) {
std::string script = base::StringPrintf(
"var plugin = window.document.getElementById('%s');"
- "function handleEvent() {"
+ "function handleEvent(event) {"
" if (event.data.isPeripheral != undefined &&"
- " event.data.source == 'getPeripheralStatusResponse') {"
+ " event.data.source === 'getPowerSaverStatusResponse') {"
" window.domAutomationController.send("
" event.data.isPeripheral ? 'peripheral' : 'essential');"
" plugin.removeEventListener('message', handleEvent);"
" }"
"}"
- "if (plugin == undefined ||"
+ "if (plugin === undefined ||"
" (plugin.nodeName != 'OBJECT' && plugin.nodeName != 'EMBED')) {"
" window.domAutomationController.send('error');"
- "} else if (plugin.postMessage == undefined) {"
+ "} else if (plugin.postMessage === undefined) {"
" window.domAutomationController.send('peripheral');"
"} else {"
" plugin.addEventListener('message', handleEvent);"
- " plugin.postMessage('getPeripheralStatus');"
+ " plugin.postMessage('getPowerSaverStatus');"
"}",
element_id);
@@ -71,7 +71,7 @@ class PluginPowerSaverBrowserTest : virtual public InProcessBrowserTest {
// status message during:
// - Plugin creation, to handle a plugin freshly created from a poster.
// - Peripheral status change.
- // - In response to the explicit 'getPeripheralStatus' request, in case the
+ // - In response to the explicit 'getPowerSaverStatus' request, in case the
// test has missed the above two events.
void SimulateClickAndAwaitMarkedEssential(const char* element_id,
const gfx::Point& point) {
@@ -80,19 +80,19 @@ class PluginPowerSaverBrowserTest : virtual public InProcessBrowserTest {
std::string script = base::StringPrintf(
"var plugin = window.document.getElementById('%s');"
- "function handleEvent() {"
- " if (event.data.isPeripheral == false) {"
+ "function handleEvent(event) {"
+ " if (event.data.isPeripheral === false) {"
" window.domAutomationController.send('essential');"
" plugin.removeEventListener('message', handleEvent);"
" }"
"}"
- "if (plugin == undefined ||"
+ "if (plugin === undefined ||"
" (plugin.nodeName != 'OBJECT' && plugin.nodeName != 'EMBED')) {"
" window.domAutomationController.send('error');"
"} else {"
" plugin.addEventListener('message', handleEvent);"
" if (plugin.postMessage != undefined) {"
- " plugin.postMessage('getPeripheralStatus');"
+ " plugin.postMessage('getPowerSaverStatus');"
" }"
"}",
element_id);
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc
index 9aca6168..3f98385 100644
--- a/chrome/browser/prerender/prerender_browsertest.cc
+++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -103,6 +103,7 @@
#include "net/url_request/url_request_filter.h"
#include "net/url_request/url_request_interceptor.h"
#include "net/url_request/url_request_job.h"
+#include "ppapi/shared_impl/ppapi_switches.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"
@@ -1108,7 +1109,9 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest {
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitchASCII(switches::kPrerenderMode,
switches::kPrerenderModeSwitchValueEnabled);
- ASSERT_TRUE(ppapi::RegisterTestPlugin(command_line));
+ command_line->AppendSwitch(switches::kEnablePepperTesting);
+
+ ASSERT_TRUE(ppapi::RegisterPowerSaverTestPlugin(command_line));
}
void SetUpOnMainThread() override {
@@ -1968,8 +1971,8 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderAlertAfterOnload) {
// Checks that plugins are not loaded while a page is being preloaded, but
// are loaded when the page is displayed.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDelayLoadPlugin) {
- PrerenderTestURL("files/prerender/plugin_delay_load.html", FINAL_STATUS_USED,
- 1);
+ PrerenderTestURL("files/prerender/prerender_plugin_delay_load.html",
+ FINAL_STATUS_USED, 1);
NavigateToDestURL();
}
@@ -1981,9 +1984,16 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderContentSettingDetect) {
content_settings_map->SetDefaultContentSetting(
CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_DETECT_IMPORTANT_CONTENT);
- PrerenderTestURL("files/prerender/plugin_delay_load.html", FINAL_STATUS_USED,
- 1);
+ PrerenderTestURL("files/prerender/prerender_plugin_power_saver.html",
+ FINAL_STATUS_USED, 1);
+
+ DisableJavascriptCalls();
NavigateToDestURL();
+ bool second_placeholder_present = false;
+ ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+ GetActiveWebContents(), "AwaitPluginPrerollAndPlaceholder();",
+ &second_placeholder_present));
+ EXPECT_TRUE(second_placeholder_present);
}
// For Content Setting BLOCK, checks that plugins are never loaded.
@@ -1993,8 +2003,8 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderContentSettingBlock) {
content_settings_map->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS,
CONTENT_SETTING_BLOCK);
- PrerenderTestURL("files/prerender/plugin_never_load.html", FINAL_STATUS_USED,
- 1);
+ PrerenderTestURL("files/prerender/prerender_plugin_never_load.html",
+ FINAL_STATUS_USED, 1);
NavigateToDestURL();
}
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 22e914e..03f520d 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -858,16 +858,12 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin(
bool is_prerendering =
prerender::PrerenderHelper::IsPrerendering(render_frame);
- // TODO(tommycli): Plugin Power Saver is disabled on prerendered pages.
+ // TODO(tommycli): Background tab plugin deferral is disabled.
// This is because the placeholder does not feed back into
// ChromeContentRendererClient::CreatePlugin. Because of this, it does
// not handle the preroll to UI overlay placeholder flow correctly.
- //
- // Background tab plugin deferral is disabled for the same reason.
- //
// https://crbug.com/471427
bool power_saver_enabled =
- !is_prerendering &&
status ==
ChromeViewHostMsg_GetPluginInfo_Status::kPlayImportantContent;
diff --git a/chrome/renderer/plugins/chrome_plugin_placeholder.cc b/chrome/renderer/plugins/chrome_plugin_placeholder.cc
index c532fdd..402bfb6 100644
--- a/chrome/renderer/plugins/chrome_plugin_placeholder.cc
+++ b/chrome/renderer/plugins/chrome_plugin_placeholder.cc
@@ -13,6 +13,7 @@
#include "chrome/grit/renderer_resources.h"
#include "chrome/renderer/chrome_content_renderer_client.h"
#include "chrome/renderer/custom_menu_commands.h"
+#include "chrome/renderer/plugins/plugin_preroller.h"
#include "chrome/renderer/plugins/plugin_uma.h"
#include "components/content_settings/content/common/content_settings_messages.h"
#include "content/app/strings/grit/content_strings.h"
@@ -366,6 +367,24 @@ void ChromePluginPlaceholder::ShowContextMenu(const WebMouseEvent& event) {
#endif // OS_ANDROID
}
+blink::WebPlugin* ChromePluginPlaceholder::CreatePlugin() {
+ scoped_ptr<content::PluginInstanceThrottler> throttler;
+#if defined(ENABLE_PLUGINS)
+ // If the plugin has already been marked essential in its placeholder form,
+ // we shouldn't create a new throttler and start the process all over again.
+ if (power_saver_enabled()) {
+ throttler = content::PluginInstanceThrottler::Create();
+ // PluginPreroller manages its own lifetime.
+ new PluginPreroller(render_frame(), GetFrame(), GetPluginParams(),
+ GetPluginInfo(), GetIdentifier(), title_,
+ l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED, title_),
+ throttler.get());
+ }
+#endif
+ return render_frame()->CreatePlugin(GetFrame(), GetPluginInfo(),
+ GetPluginParams(), throttler.Pass());
+}
+
gin::ObjectTemplateBuilder ChromePluginPlaceholder::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
return LoadablePluginPlaceholder::GetObjectTemplateBuilder(isolate).SetMethod(
diff --git a/chrome/renderer/plugins/chrome_plugin_placeholder.h b/chrome/renderer/plugins/chrome_plugin_placeholder.h
index bdcf02c..d5fb2f9 100644
--- a/chrome/renderer/plugins/chrome_plugin_placeholder.h
+++ b/chrome/renderer/plugins/chrome_plugin_placeholder.h
@@ -69,6 +69,9 @@ class ChromePluginPlaceholder : public plugins::LoadablePluginPlaceholder,
const base::string16& title);
~ChromePluginPlaceholder() override;
+ // content::LoadablePluginPlaceholder method
+ blink::WebPlugin* CreatePlugin() override;
+
// gin::Wrappable (via PluginPlaceholder) method
gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override;
diff --git a/chrome/test/data/prerender/prerender_iframe_plugin_delay_load.html b/chrome/test/data/prerender/prerender_iframe_plugin_delay_load.html
index a13af56..dfa0254 100644
--- a/chrome/test/data/prerender/prerender_iframe_plugin_delay_load.html
+++ b/chrome/test/data/prerender/prerender_iframe_plugin_delay_load.html
@@ -20,6 +20,6 @@ function DidDisplayPass() {
}
</script>
<body>
-<iframe src="plugin_delay_load.html" id="plugin_iframe"></iframe>
+<iframe src="prerender_plugin_delay_load.html" id="plugin_iframe"></iframe>
</body>
</html>
diff --git a/chrome/test/data/prerender/plugin_delay_load.html b/chrome/test/data/prerender/prerender_plugin_delay_load.html
index 4a84c73..4a84c73 100644
--- a/chrome/test/data/prerender/plugin_delay_load.html
+++ b/chrome/test/data/prerender/prerender_plugin_delay_load.html
diff --git a/chrome/test/data/prerender/plugin_never_load.html b/chrome/test/data/prerender/prerender_plugin_never_load.html
index 84dc722..84dc722 100644
--- a/chrome/test/data/prerender/plugin_never_load.html
+++ b/chrome/test/data/prerender/prerender_plugin_never_load.html
diff --git a/chrome/test/data/prerender/prerender_plugin_power_saver.html b/chrome/test/data/prerender/prerender_plugin_power_saver.html
new file mode 100644
index 0000000..18cb87e
--- /dev/null
+++ b/chrome/test/data/prerender/prerender_plugin_power_saver.html
@@ -0,0 +1,54 @@
+<html>
+<!--
+This test checks the interaction between prerendering and the Plugin Power Saver
+feature. It expects:
+ - The plugin is not loaded during prerender.
+ - It is loaded (briefly) during the preroll of the plugin.
+ - It is replaced by the power saver placeholder after the preroll is over.
+
+This test relies on the Pepper plugin (but not the placeholder) implementing
+the postMessage() function on the plugin object.
+-->
+<head>
+<title>Prerender Plugin Delay Loading</title>
+
+<script>
+// Make sure plugin was not loaded while prerendering.
+function DidPrerenderPass() {
+ // |plugin| should be the blocked plugin placeholder, rather than the
+ // test plugin.
+ var plugin = window.document.getElementById('plugin');
+ return plugin.postMessage === undefined;
+}
+
+// Make sure the plugin briefly exists, then is replaced with a placeholder.
+function AwaitPluginPrerollAndPlaceholder() {
+ var plugin = window.document.getElementById('plugin');
+ function handleEvent(event) {
+ // We should eventually get a message indicating that the plugin has been
+ // throttled and replaced with a static placeholder.
+ if (event.data.isThrottled && event.data.isHiddenForPlaceholder) {
+ plugin.removeEventListener('message', handleEvent);
+ window.domAutomationController.send(true);
+ }
+ }
+
+ plugin.addEventListener('message', handleEvent);
+
+ // If postMessage is not defined, the plugin is still the initial placeholder.
+ // When the real plugin loads, we will still get the initial power saver
+ // status notifications.
+ if (plugin.postMessage !== undefined) {
+ plugin.postMessage('getPowerSaverStatus');
+ }
+}
+</script>
+
+</head>
+<body>
+
+<object id="plugin" type="application/x-ppapi-tests" height='100' width='100'>
+</object>
+
+</body>
+</html>
diff --git a/components/plugins/renderer/loadable_plugin_placeholder.cc b/components/plugins/renderer/loadable_plugin_placeholder.cc
index d3af1fc..b1567c8 100644
--- a/components/plugins/renderer/loadable_plugin_placeholder.cc
+++ b/components/plugins/renderer/loadable_plugin_placeholder.cc
@@ -292,20 +292,7 @@ void LoadablePluginPlaceholder::LoadPlugin() {
ReplacePlugin(premade_throttler_->GetWebPlugin());
premade_throttler_ = nullptr;
} else {
- // TODO(mmenke): In the case of prerendering, feed into
- // ChromeContentRendererClient::CreatePlugin instead, to
- // reduce the chance of future regressions.
- scoped_ptr<PluginInstanceThrottler> throttler;
-#if defined(ENABLE_PLUGINS)
- // If the plugin has already been marked essential in its placeholder form,
- // we shouldn't create a new throttler and start the process all over again.
- if (power_saver_enabled_)
- throttler = PluginInstanceThrottler::Create();
-#endif
- WebPlugin* plugin = render_frame()->CreatePlugin(
- GetFrame(), plugin_info_, GetPluginParams(), throttler.Pass());
-
- ReplacePlugin(plugin);
+ ReplacePlugin(CreatePlugin());
}
}
@@ -348,6 +335,10 @@ void LoadablePluginPlaceholder::SetIdentifier(const std::string& identifier) {
identifier_ = identifier;
}
+const std::string& LoadablePluginPlaceholder::GetIdentifier() const {
+ return identifier_;
+}
+
bool LoadablePluginPlaceholder::LoadingBlocked() const {
DCHECK(allow_loading_);
return is_blocked_for_background_tab_ || is_blocked_for_power_saver_poster_ ||
diff --git a/components/plugins/renderer/loadable_plugin_placeholder.h b/components/plugins/renderer/loadable_plugin_placeholder.h
index 841115b..4ddbaac 100644
--- a/components/plugins/renderer/loadable_plugin_placeholder.h
+++ b/components/plugins/renderer/loadable_plugin_placeholder.h
@@ -24,6 +24,8 @@ class LoadablePluginPlaceholder : public PluginPlaceholder {
}
#if defined(ENABLE_PLUGINS)
+ bool power_saver_enabled() const { return power_saver_enabled_; }
+
void set_power_saver_enabled(bool power_saver_enabled) {
power_saver_enabled_ = power_saver_enabled;
}
@@ -58,6 +60,7 @@ class LoadablePluginPlaceholder : public PluginPlaceholder {
void SetPluginInfo(const content::WebPluginInfo& plugin_info);
const content::WebPluginInfo& GetPluginInfo() const;
void SetIdentifier(const std::string& identifier);
+ const std::string& GetIdentifier() const;
bool LoadingAllowed() const { return allow_loading_; }
// Replace this placeholder with a different plugin (which could be
@@ -93,6 +96,9 @@ class LoadablePluginPlaceholder : public PluginPlaceholder {
bool LoadingBlocked() const;
+ // Plugin creation is embedder-specific.
+ virtual blink::WebPlugin* CreatePlugin() = 0;
+
content::WebPluginInfo plugin_info_;
base::string16 message_;
diff --git a/content/public/renderer/plugin_instance_throttler.h b/content/public/renderer/plugin_instance_throttler.h
index 0b33cc4..025ccbd 100644
--- a/content/public/renderer/plugin_instance_throttler.h
+++ b/content/public/renderer/plugin_instance_throttler.h
@@ -62,6 +62,8 @@ class CONTENT_EXPORT PluginInstanceThrottler {
virtual void OnThrottleStateChange() {}
+ virtual void OnPeripheralStateChange() {}
+
// Called when the plugin should be hidden due to a placeholder.
virtual void OnHiddenForPlaceholder(bool hidden) {}
diff --git a/content/renderer/pepper/plugin_instance_throttler_impl.cc b/content/renderer/pepper/plugin_instance_throttler_impl.cc
index 6936a1a..a73a224 100644
--- a/content/renderer/pepper/plugin_instance_throttler_impl.cc
+++ b/content/renderer/pepper/plugin_instance_throttler_impl.cc
@@ -9,11 +9,8 @@
#include "content/public/common/content_constants.h"
#include "content/public/renderer/render_thread.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
-#include "content/renderer/pepper/pepper_webplugin_impl.h"
#include "content/renderer/render_frame_impl.h"
#include "ppapi/shared_impl/ppapi_constants.h"
-#include "ppapi/shared_impl/scoped_pp_var.h"
-#include "ppapi/shared_impl/var.h"
#include "third_party/WebKit/public/platform/WebRect.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "third_party/WebKit/public/web/WebPluginParams.h"
@@ -98,16 +95,10 @@ void PluginInstanceThrottlerImpl::MarkPluginEssential(
state_ = THROTTLER_STATE_MARKED_ESSENTIAL;
RecordUnthrottleMethodMetric(method);
+ FOR_EACH_OBSERVER(Observer, observer_list_, OnPeripheralStateChange());
+
if (was_throttled)
FOR_EACH_OBSERVER(Observer, observer_list_, OnThrottleStateChange());
-
- // Notify the Power Saver test plugin of a peripheral status change.
- if (web_plugin_ && web_plugin_->instance() &&
- plugin_module_name_ == ppapi::kPowerSaverTestPluginName) {
- web_plugin_->instance()->HandleMessage(ppapi::ScopedPPVar(
- ppapi::ScopedPPVar::PassRef(),
- ppapi::StringVar::StringToPPVar("peripheralStatusChange")));
- }
}
void PluginInstanceThrottlerImpl::SetHiddenForPlaceholder(bool hidden) {
@@ -115,7 +106,7 @@ void PluginInstanceThrottlerImpl::SetHiddenForPlaceholder(bool hidden) {
FOR_EACH_OBSERVER(Observer, observer_list_, OnHiddenForPlaceholder(hidden));
}
-blink::WebPlugin* PluginInstanceThrottlerImpl::GetWebPlugin() const {
+PepperWebPluginImpl* PluginInstanceThrottlerImpl::GetWebPlugin() const {
DCHECK(web_plugin_);
return web_plugin_;
}
@@ -140,7 +131,7 @@ void PluginInstanceThrottlerImpl::Initialize(
const GURL& content_origin,
const std::string& plugin_module_name,
const gfx::Size& unobscured_size) {
- plugin_module_name_ = plugin_module_name;
+ DCHECK(unobscured_size_.IsEmpty());
unobscured_size_ = unobscured_size;
// |frame| may be nullptr in tests.
@@ -151,7 +142,9 @@ void PluginInstanceThrottlerImpl::Initialize(
unobscured_size.width(),
unobscured_size.height(),
&cross_origin_main_content)) {
+ DCHECK_NE(THROTTLER_STATE_MARKED_ESSENTIAL, state_);
state_ = THROTTLER_STATE_MARKED_ESSENTIAL;
+ FOR_EACH_OBSERVER(Observer, observer_list_, OnPeripheralStateChange());
if (cross_origin_main_content)
helper->WhitelistContentOrigin(content_origin);
diff --git a/content/renderer/pepper/plugin_instance_throttler_impl.h b/content/renderer/pepper/plugin_instance_throttler_impl.h
index 9bd9357..ec3eed68 100644
--- a/content/renderer/pepper/plugin_instance_throttler_impl.h
+++ b/content/renderer/pepper/plugin_instance_throttler_impl.h
@@ -11,6 +11,7 @@
#include "base/timer/timer.h"
#include "content/common/content_export.h"
#include "content/public/renderer/plugin_instance_throttler.h"
+#include "content/renderer/pepper/pepper_webplugin_impl.h"
#include "ppapi/shared_impl/ppb_view_shared.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/geometry/size.h"
@@ -39,7 +40,7 @@ class CONTENT_EXPORT PluginInstanceThrottlerImpl
bool IsHiddenForPlaceholder() const override;
void MarkPluginEssential(PowerSaverUnthrottleMethod method) override;
void SetHiddenForPlaceholder(bool hidden) override;
- blink::WebPlugin* GetWebPlugin() const override;
+ PepperWebPluginImpl* GetWebPlugin() const override;
const gfx::Size& GetSize() const override;
void NotifyAudioThrottled() override;
@@ -98,9 +99,6 @@ class CONTENT_EXPORT PluginInstanceThrottlerImpl
// Number of frames we've examined to find a keyframe.
int frames_examined_;
- // Plugin module name as of initialization.
- std::string plugin_module_name_;
-
// Plugin's unobscured dimensions as of initialization.
gfx::Size unobscured_size_;
diff --git a/content/renderer/pepper/plugin_module.cc b/content/renderer/pepper/plugin_module.cc
index 1cbdcaf..bb7b5e8 100644
--- a/content/renderer/pepper/plugin_module.cc
+++ b/content/renderer/pepper/plugin_module.cc
@@ -135,6 +135,7 @@
#include "ppapi/c/trusted/ppb_file_chooser_trusted.h"
#include "ppapi/c/trusted/ppb_url_loader_trusted.h"
#include "ppapi/shared_impl/callback_tracker.h"
+#include "ppapi/shared_impl/dictionary_var.h"
#include "ppapi/shared_impl/ppapi_preferences.h"
#include "ppapi/shared_impl/ppapi_switches.h"
#include "ppapi/shared_impl/ppb_input_event_shared.h"
@@ -181,6 +182,59 @@ PluginModuleSet* GetLivePluginSet() {
return &live_plugin_libs;
}
+class PowerSaverTestPluginDelegate : public PluginInstanceThrottler::Observer {
+ public:
+ explicit PowerSaverTestPluginDelegate(PluginInstanceThrottlerImpl* throttler)
+ : throttler_(throttler) {
+ throttler_->AddObserver(this);
+ PostPowerSaverStatusToJavaScript(throttler_, "initial");
+ }
+
+ virtual ~PowerSaverTestPluginDelegate() { throttler_->RemoveObserver(this); }
+
+ static void PostPowerSaverStatusToJavaScript(
+ PluginInstanceThrottlerImpl* throttler,
+ const std::string& source) {
+ if (!throttler->GetWebPlugin() || !throttler->GetWebPlugin()->instance())
+ return;
+
+ PepperPluginInstanceImpl* instance = throttler->GetWebPlugin()->instance();
+
+ // Refcounted by the returned PP_Var.
+ ppapi::DictionaryVar* dictionary = new ppapi::DictionaryVar;
+ dictionary->Set(ppapi::StringVar::StringToPPVar("source"),
+ ppapi::StringVar::StringToPPVar(source));
+ dictionary->Set(
+ ppapi::StringVar::StringToPPVar("isHiddenForPlaceholder"),
+ PP_MakeBool(PP_FromBool(throttler->IsHiddenForPlaceholder())));
+ dictionary->Set(ppapi::StringVar::StringToPPVar("isPeripheral"),
+ PP_MakeBool(PP_FromBool(throttler->power_saver_enabled())));
+ dictionary->Set(ppapi::StringVar::StringToPPVar("isThrottled"),
+ PP_MakeBool(PP_FromBool(throttler->IsThrottled())));
+
+ instance->PostMessageToJavaScript(dictionary->GetPPVar());
+ }
+
+ private:
+ void OnThrottleStateChange() override {
+ PostPowerSaverStatusToJavaScript(throttler_, "throttleStatusChange");
+ }
+
+ void OnPeripheralStateChange() override {
+ PostPowerSaverStatusToJavaScript(throttler_, "peripheralStatusChange");
+ }
+
+ void OnHiddenForPlaceholder(bool hidden) override {
+ PostPowerSaverStatusToJavaScript(throttler_,
+ "hiddenForPlaceholderStatusChange");
+ }
+
+ void OnThrottlerDestroyed() override { delete this; }
+
+ // Non-owning pointer.
+ PluginInstanceThrottlerImpl* const throttler_;
+};
+
// PPB_Core --------------------------------------------------------------------
void AddRefResource(PP_Resource resource) {
@@ -246,12 +300,24 @@ uint32_t GetLiveObjectsForInstance(PP_Instance instance_id) {
PP_Bool IsOutOfProcess() { return PP_FALSE; }
-PP_Bool IsPeripheral(PP_Instance instance_id) {
+void PostPowerSaverStatus(PP_Instance instance_id) {
PepperPluginInstanceImpl* plugin_instance =
host_globals->GetInstance(instance_id);
if (!plugin_instance || !plugin_instance->throttler())
- return PP_FALSE;
- return PP_FromBool(plugin_instance->throttler()->power_saver_enabled());
+ return;
+
+ PowerSaverTestPluginDelegate::PostPowerSaverStatusToJavaScript(
+ plugin_instance->throttler(), "getPowerSaverStatusResponse");
+}
+
+void SubscribeToPowerSaverNotifications(PP_Instance instance_id) {
+ PepperPluginInstanceImpl* plugin_instance =
+ host_globals->GetInstance(instance_id);
+ if (!plugin_instance || !plugin_instance->throttler())
+ return;
+
+ // Manages its own lifetime.
+ new PowerSaverTestPluginDelegate(plugin_instance->throttler());
}
void SimulateInputEvent(PP_Instance instance, PP_Resource input_event) {
@@ -302,7 +368,8 @@ const PPB_Testing_Private testing_interface = {
&QuitMessageLoop,
&GetLiveObjectsForInstance,
&IsOutOfProcess,
- &IsPeripheral,
+ &PostPowerSaverStatus,
+ &SubscribeToPowerSaverNotifications,
&SimulateInputEvent,
&GetDocumentURL,
&GetLiveVars,
diff --git a/ppapi/api/private/ppb_testing_private.idl b/ppapi/api/private/ppb_testing_private.idl
index 8de73f7..c2aed41 100644
--- a/ppapi/api/private/ppb_testing_private.idl
+++ b/ppapi/api/private/ppb_testing_private.idl
@@ -77,11 +77,20 @@ interface PPB_Testing_Private {
* otherwise.
*/
PP_Bool IsOutOfProcess();
-
+
+ /**
+ * Posts the plugin's current Power Saver status to JavaScript. The plugin
+ * itself does not recieve anything. This is not idiomatic for Pepper,
+ * but convenient for testing.
+ */
+ void PostPowerSaverStatus([in] PP_Instance instance);
+
/**
- * Returns PP_TRUE if the plugin is peripheral, PP_FALSE otherwise.
+ * Subscribes to changes to the plugin's Power Saver status. The status
+ * changes are not forwarded to the plugin itself, but posted to JavaScript.
+ * This is not idiomatic for Pepper, but conveienent for testing.
*/
- PP_Bool IsPeripheral([in] PP_Instance instance);
+ void SubscribeToPowerSaverNotifications([in] PP_Instance instance);
/**
* Passes the input event to the browser, which sends it back to the
diff --git a/ppapi/c/private/ppb_testing_private.h b/ppapi/c/private/ppb_testing_private.h
index 5003d75..efe456a 100644
--- a/ppapi/c/private/ppb_testing_private.h
+++ b/ppapi/c/private/ppb_testing_private.h
@@ -3,7 +3,7 @@
* found in the LICENSE file.
*/
-/* From private/ppb_testing_private.idl modified Mon Jul 28 15:12:12 2014. */
+/* From private/ppb_testing_private.idl modified Fri May 1 13:14:52 2015. */
#ifndef PPAPI_C_PRIVATE_PPB_TESTING_PRIVATE_H_
#define PPAPI_C_PRIVATE_PPB_TESTING_PRIVATE_H_
@@ -93,9 +93,17 @@ struct PPB_Testing_Private_1_0 {
*/
PP_Bool (*IsOutOfProcess)(void);
/**
- * Returns PP_TRUE if the plugin is peripheral, PP_FALSE otherwise.
+ * Posts the plugin's current Power Saver status to JavaScript. The plugin
+ * itself does not recieve anything. This is not idiomatic for Pepper,
+ * but convenient for testing.
*/
- PP_Bool (*IsPeripheral)(PP_Instance instance);
+ void (*PostPowerSaverStatus)(PP_Instance instance);
+ /**
+ * Subscribes to changes to the plugin's Power Saver status. The status
+ * changes are not forwarded to the plugin itself, but posted to JavaScript.
+ * This is not idiomatic for Pepper, but conveienent for testing.
+ */
+ void (*SubscribeToPowerSaverNotifications)(PP_Instance instance);
/**
* Passes the input event to the browser, which sends it back to the
* plugin. The plugin should implement PPP_InputEvent and register for
diff --git a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c
index 022430a..b217310 100644
--- a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c
+++ b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c
@@ -4133,9 +4133,14 @@ static PP_Bool Pnacl_M33_PPB_Testing_Private_IsOutOfProcess(void) {
return iface->IsOutOfProcess();
}
-static PP_Bool Pnacl_M33_PPB_Testing_Private_IsPeripheral(PP_Instance instance) {
+static void Pnacl_M33_PPB_Testing_Private_PostPowerSaverStatus(PP_Instance instance) {
const struct PPB_Testing_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_Testing_Private_1_0.real_iface;
- return iface->IsPeripheral(instance);
+ iface->PostPowerSaverStatus(instance);
+}
+
+static void Pnacl_M33_PPB_Testing_Private_SubscribeToPowerSaverNotifications(PP_Instance instance) {
+ const struct PPB_Testing_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_Testing_Private_1_0.real_iface;
+ iface->SubscribeToPowerSaverNotifications(instance);
}
static void Pnacl_M33_PPB_Testing_Private_SimulateInputEvent(PP_Instance instance, PP_Resource input_event) {
@@ -5633,7 +5638,8 @@ static const struct PPB_Testing_Private_1_0 Pnacl_Wrappers_PPB_Testing_Private_1
.QuitMessageLoop = (void (*)(PP_Instance instance))&Pnacl_M33_PPB_Testing_Private_QuitMessageLoop,
.GetLiveObjectsForInstance = (uint32_t (*)(PP_Instance instance))&Pnacl_M33_PPB_Testing_Private_GetLiveObjectsForInstance,
.IsOutOfProcess = (PP_Bool (*)(void))&Pnacl_M33_PPB_Testing_Private_IsOutOfProcess,
- .IsPeripheral = (PP_Bool (*)(PP_Instance instance))&Pnacl_M33_PPB_Testing_Private_IsPeripheral,
+ .PostPowerSaverStatus = (void (*)(PP_Instance instance))&Pnacl_M33_PPB_Testing_Private_PostPowerSaverStatus,
+ .SubscribeToPowerSaverNotifications = (void (*)(PP_Instance instance))&Pnacl_M33_PPB_Testing_Private_SubscribeToPowerSaverNotifications,
.SimulateInputEvent = (void (*)(PP_Instance instance, PP_Resource input_event))&Pnacl_M33_PPB_Testing_Private_SimulateInputEvent,
.GetDocumentURL = (struct PP_Var (*)(PP_Instance instance, struct PP_URLComponents_Dev* components))&Pnacl_M33_PPB_Testing_Private_GetDocumentURL,
.GetLiveVars = (uint32_t (*)(struct PP_Var live_vars[], uint32_t array_size))&Pnacl_M33_PPB_Testing_Private_GetLiveVars,
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h
index 1c978843..9f692e2 100644
--- a/ppapi/proxy/ppapi_messages.h
+++ b/ppapi/proxy/ppapi_messages.h
@@ -1204,9 +1204,11 @@ IPC_SYNC_MESSAGE_ROUTED3_1(
IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBTesting_GetLiveObjectsForInstance,
PP_Instance /* instance */,
uint32 /* result */)
-IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBTesting_IsPeripheral,
- PP_Instance /* instance */,
- PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_0(PpapiHostMsg_PPBTesting_PostPowerSaverStatus,
+ PP_Instance /* instance */)
+IPC_SYNC_MESSAGE_ROUTED1_0(
+ PpapiHostMsg_PPBTesting_SubscribeToPowerSaverNotifications,
+ PP_Instance /* instance */)
IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBTesting_SimulateInputEvent,
PP_Instance /* instance */,
ppapi::InputEventData /* input_event */)
diff --git a/ppapi/proxy/ppb_testing_proxy.cc b/ppapi/proxy/ppb_testing_proxy.cc
index 914eb44..4381798 100644
--- a/ppapi/proxy/ppb_testing_proxy.cc
+++ b/ppapi/proxy/ppb_testing_proxy.cc
@@ -80,16 +80,25 @@ PP_Bool IsOutOfProcess() {
return PP_TRUE;
}
-PP_Bool IsPeripheral(PP_Instance instance_id) {
+void PostPowerSaverStatus(PP_Instance instance_id) {
ProxyAutoLock lock;
PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance_id);
if (!dispatcher)
- return PP_FALSE;
+ return;
- PP_Bool result = PP_FALSE;
- dispatcher->Send(new PpapiHostMsg_PPBTesting_IsPeripheral(
- API_ID_PPB_TESTING, instance_id, &result));
- return result;
+ dispatcher->Send(new PpapiHostMsg_PPBTesting_PostPowerSaverStatus(
+ API_ID_PPB_TESTING, instance_id));
+}
+
+void SubscribeToPowerSaverNotifications(PP_Instance instance_id) {
+ ProxyAutoLock lock;
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance_id);
+ if (!dispatcher)
+ return;
+
+ dispatcher->Send(
+ new PpapiHostMsg_PPBTesting_SubscribeToPowerSaverNotifications(
+ API_ID_PPB_TESTING, instance_id));
}
void SimulateInputEvent(PP_Instance instance_id, PP_Resource input_event) {
@@ -150,7 +159,8 @@ const PPB_Testing_Private testing_interface = {
&QuitMessageLoop,
&GetLiveObjectsForInstance,
&IsOutOfProcess,
- &IsPeripheral,
+ &PostPowerSaverStatus,
+ &SubscribeToPowerSaverNotifications,
&SimulateInputEvent,
&GetDocumentURL,
&GetLiveVars,
@@ -186,7 +196,11 @@ bool PPB_Testing_Proxy::OnMessageReceived(const IPC::Message& msg) {
OnMsgReadImageData)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTesting_GetLiveObjectsForInstance,
OnMsgGetLiveObjectsForInstance)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTesting_IsPeripheral, OnMsgIsPeripheral)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTesting_PostPowerSaverStatus,
+ OnMsgPostPowerSaverStatus)
+ IPC_MESSAGE_HANDLER(
+ PpapiHostMsg_PPBTesting_SubscribeToPowerSaverNotifications,
+ OnMsgSubscribeToPowerSaverNotifications)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTesting_SimulateInputEvent,
OnMsgSimulateInputEvent)
IPC_MESSAGE_HANDLER(
@@ -219,9 +233,13 @@ void PPB_Testing_Proxy::OnMsgGetLiveObjectsForInstance(PP_Instance instance,
*result = ppb_testing_impl_->GetLiveObjectsForInstance(instance);
}
-void PPB_Testing_Proxy::OnMsgIsPeripheral(PP_Instance instance,
- PP_Bool* result) {
- *result = ppb_testing_impl_->IsPeripheral(instance);
+void PPB_Testing_Proxy::OnMsgPostPowerSaverStatus(PP_Instance instance) {
+ ppb_testing_impl_->PostPowerSaverStatus(instance);
+}
+
+void PPB_Testing_Proxy::OnMsgSubscribeToPowerSaverNotifications(
+ PP_Instance instance) {
+ ppb_testing_impl_->SubscribeToPowerSaverNotifications(instance);
}
void PPB_Testing_Proxy::OnMsgSimulateInputEvent(
diff --git a/ppapi/proxy/ppb_testing_proxy.h b/ppapi/proxy/ppb_testing_proxy.h
index dd8a6e8..7640291 100644
--- a/ppapi/proxy/ppb_testing_proxy.h
+++ b/ppapi/proxy/ppb_testing_proxy.h
@@ -39,7 +39,8 @@ class PPB_Testing_Proxy : public InterfaceProxy {
void OnMsgRunMessageLoop(PP_Instance instance);
void OnMsgQuitMessageLoop(PP_Instance instance);
void OnMsgGetLiveObjectsForInstance(PP_Instance instance, uint32_t* result);
- void OnMsgIsPeripheral(PP_Instance instance, PP_Bool* result);
+ void OnMsgPostPowerSaverStatus(PP_Instance instance);
+ void OnMsgSubscribeToPowerSaverNotifications(PP_Instance instance);
void OnMsgSimulateInputEvent(PP_Instance instance,
const ppapi::InputEventData& input_event);
void OnMsgSetMinimumArrayBufferSizeForShmem(uint32_t threshold);
diff --git a/ppapi/tests/power_saver_test_plugin.cc b/ppapi/tests/power_saver_test_plugin.cc
index f14c5fe..44aef4d 100644
--- a/ppapi/tests/power_saver_test_plugin.cc
+++ b/ppapi/tests/power_saver_test_plugin.cc
@@ -4,10 +4,10 @@
#include <algorithm>
+#include "ppapi/cpp/graphics_2d.h"
+#include "ppapi/cpp/image_data.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h"
-#include "ppapi/cpp/var.h"
-#include "ppapi/cpp/var_dictionary.h"
#include "ppapi/tests/test_utils.h"
// Windows defines 'PostMessage', so we have to undef it.
@@ -19,42 +19,58 @@
class PowerSaverTestInstance : public pp::Instance {
public:
explicit PowerSaverTestInstance(PP_Instance instance)
- : pp::Instance(instance), received_first_did_change_view_(false) {}
+ : pp::Instance(instance), callback_factory_(this) {}
~PowerSaverTestInstance() override {}
- // For browser tests, responds to:
- // - When postMessage("isPeripheral") is called on the plugin DOM element.
- // - When the plugin throttler posts a message notifying us that our
- // peripheral status has changed.
+ bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
+ GetTestingInterface()->SubscribeToPowerSaverNotifications(pp_instance());
+ return true;
+ }
+
void HandleMessage(const pp::Var& message_data) override {
- if (message_data.is_string()) {
- if (message_data.AsString() == "getPeripheralStatus")
- BroadcastIsPeripheralStatus("getPeripheralStatusResponse");
- else if (message_data.AsString() == "peripheralStatusChange")
- BroadcastIsPeripheralStatus("peripheralStatusChange");
+ if (message_data.is_string() &&
+ message_data.AsString() == "getPowerSaverStatus") {
+ GetTestingInterface()->PostPowerSaverStatus(pp_instance());
}
}
// Broadcast our peripheral status after the initial view data. This is for
// tests that await initial plugin creation.
void DidChangeView(const pp::View& view) override {
- if (!received_first_did_change_view_) {
- BroadcastIsPeripheralStatus("initial");
- received_first_did_change_view_ = true;
- }
+ view_ = view;
+ device_context_ = pp::Graphics2D(this, view_.GetRect().size(), true);
+ if (!BindGraphics(device_context_))
+ return;
+
+ Paint();
}
+ void OnFlush(int32_t) { Paint(); }
+
private:
- void BroadcastIsPeripheralStatus(const std::string& source) {
- pp::VarDictionary message;
- message.Set(
- "isPeripheral",
- pp::Var(PP_ToBool(GetTestingInterface()->IsPeripheral(pp_instance()))));
- message.Set("source", pp::Var(source));
- PostMessage(message);
+ void Paint() {
+ pp::ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
+ view_.GetRect().size(), true);
+ if (image.is_null())
+ return;
+
+ // Draw black and white stripes to present an "interesting" keyframe.
+ for (int y = 0; y < view_.GetRect().size().height(); ++y) {
+ for (int x = 0; x < view_.GetRect().size().width(); ++x) {
+ uint32_t color = x % 2 ? 0xFF0000FF : 0xFFFFFFFF;
+ *image.GetAddr32(pp::Point(x, y)) = color;
+ }
+ }
+
+ device_context_.ReplaceContents(&image);
+ device_context_.Flush(
+ callback_factory_.NewCallback(&PowerSaverTestInstance::OnFlush));
}
- bool received_first_did_change_view_;
+ pp::View view_;
+ pp::Graphics2D device_context_;
+
+ pp::CompletionCallbackFactory<PowerSaverTestInstance> callback_factory_;
};
class PowerSaverTestModule : public pp::Module {