Index: content/renderer/pepper/plugin_power_saver_helper.cc |
diff --git a/content/renderer/pepper/plugin_power_saver_helper.cc b/content/renderer/pepper/plugin_power_saver_helper.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..40f5b545df1342601f88b738e490eda86ebe76ca |
--- /dev/null |
+++ b/content/renderer/pepper/plugin_power_saver_helper.cc |
@@ -0,0 +1,129 @@ |
+// Copyright 2014 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. |
+ |
+#include "base/callback.h" |
+#include "content/common/frame_messages.h" |
+#include "content/public/renderer/document_state.h" |
+#include "content/public/renderer/navigation_state.h" |
+#include "content/public/renderer/render_frame.h" |
+#include "content/renderer/pepper/plugin_power_saver_helper.h" |
+#include "third_party/WebKit/public/web/WebDocument.h" |
+#include "third_party/WebKit/public/web/WebLocalFrame.h" |
+#include "third_party/WebKit/public/web/WebView.h" |
+ |
+namespace content { |
+ |
+namespace { |
+ |
+// Maximum dimensions plug-in content may have while still being considered |
+// peripheral content. These match the sizes used by Safari. |
+const int kPeripheralContentMaxWidth = 400; |
+const int kPeripheralContentMaxHeight = 300; |
+ |
+} // namespace |
+ |
+PluginPowerSaverHelper::PeripheralPlugin::PeripheralPlugin( |
+ const GURL& content_origin, |
+ const base::Closure& unthrottle_callback) |
+ : content_origin(content_origin), unthrottle_callback(unthrottle_callback) { |
+} |
+ |
+PluginPowerSaverHelper::PeripheralPlugin::~PeripheralPlugin() { |
+} |
+ |
+PluginPowerSaverHelper::PluginPowerSaverHelper(RenderFrame* render_frame) |
+ : RenderFrameObserver(render_frame) { |
+} |
+ |
+PluginPowerSaverHelper::~PluginPowerSaverHelper() { |
+} |
+ |
+void PluginPowerSaverHelper::DidCommitProvisionalLoad(bool is_new_navigation) { |
+ blink::WebFrame* frame = render_frame()->GetWebFrame(); |
+ if (frame->parent()) |
+ return; // Not a top-level navigation. |
+ |
+ DocumentState* document_state = DocumentState::FromDataSource( |
+ frame->dataSource()); |
+ NavigationState* navigation_state = document_state->navigation_state(); |
+ if (!navigation_state->was_within_same_page()) |
+ origin_whitelist_.clear(); |
+} |
+ |
+bool PluginPowerSaverHelper::OnMessageReceived(const IPC::Message& message) { |
+ bool handled = true; |
+ IPC_BEGIN_MESSAGE_MAP(PluginPowerSaverHelper, message) |
+ IPC_MESSAGE_HANDLER(FrameMsg_UpdatePluginContentOriginWhitelist, |
+ OnUpdatePluginContentOriginWhitelist) |
+ IPC_MESSAGE_UNHANDLED(handled = false) |
+ IPC_END_MESSAGE_MAP() |
+ return handled; |
+} |
+ |
+void PluginPowerSaverHelper::OnUpdatePluginContentOriginWhitelist( |
+ const std::set<GURL>& origin_whitelist) { |
+ origin_whitelist_ = origin_whitelist; |
+ |
+ // Check throttled plugin instances to see if any can be unthrottled. |
+ auto it = peripheral_plugins_.begin(); |
+ while (it != peripheral_plugins_.end()) { |
+ if (origin_whitelist.count(it->content_origin)) { |
+ it->unthrottle_callback.Run(); |
+ it = peripheral_plugins_.erase(it); |
+ } else { |
+ ++it; |
+ } |
+ } |
+} |
+ |
+bool PluginPowerSaverHelper::ShouldThrottleContent(const GURL& content_origin, |
+ int width, |
+ int height, |
+ bool* cross_origin) const { |
+ DCHECK(cross_origin); |
+ *cross_origin = true; |
+ |
+ // TODO(alexmos): Update this to use the origin of the RemoteFrame when 426512 |
+ // is fixed. For now, case 3 in the comment above doesn't work in |
+ // --site-per-process mode. |
+ blink::WebFrame* main_frame = |
+ render_frame()->GetWebFrame()->view()->mainFrame(); |
+ if (main_frame->isWebRemoteFrame()) |
+ return true; |
+ |
+ // All same-origin plugin content is essential. |
+ GURL main_frame_origin = GURL(main_frame->document().url()).GetOrigin(); |
+ if (content_origin == main_frame_origin) { |
+ *cross_origin = false; |
+ return false; |
+ } |
+ |
+ // Whitelisted plugin origins are also essential. |
+ if (origin_whitelist_.count(content_origin)) |
+ return false; |
+ |
+ // Cross-origin plugin content is peripheral if smaller than a maximum size. |
+ bool content_is_small = width < kPeripheralContentMaxWidth || |
+ height < kPeripheralContentMaxHeight; |
+ |
+ return content_is_small; |
+} |
+ |
+void PluginPowerSaverHelper::RegisterPeripheralPlugin( |
+ const GURL& content_origin, |
+ const base::Closure& unthrottle_callback) { |
+ peripheral_plugins_.push_back( |
+ PeripheralPlugin(content_origin, unthrottle_callback)); |
+} |
+ |
+void PluginPowerSaverHelper::WhitelistContentOrigin( |
+ const GURL& content_origin) { |
+ if (origin_whitelist_.count(content_origin) == 0) { |
+ origin_whitelist_.insert(content_origin); |
Lei Zhang
2014/10/29 22:31:23
nit: you can just always insert, and check the ret
tommycli
2014/10/29 22:53:23
Done.
|
+ Send(new FrameHostMsg_PluginContentOriginAllowed( |
+ render_frame()->GetRoutingID(), content_origin)); |
+ } |
+} |
+ |
+} // namespace content |