| 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..13c079ee1c876503c7f49eeb5416aaa4958b3265
|
| --- /dev/null
|
| +++ b/content/renderer/pepper/plugin_power_saver_helper.cc
|
| @@ -0,0 +1,128 @@
|
| +// 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 class level comment 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_.insert(content_origin).second) {
|
| + Send(new FrameHostMsg_PluginContentOriginAllowed(
|
| + render_frame()->GetRoutingID(), content_origin));
|
| + }
|
| +}
|
| +
|
| +} // namespace content
|
|
|