Refactor WebsiteSettings to operate on a SecurityInfo
[chromium-blink-merge.git] / content / renderer / pepper / plugin_power_saver_helper.cc
blobfc45a6985094150dbf5c756eef4cc53366789728
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/pepper/plugin_power_saver_helper.h"
7 #include <string>
9 #include "base/command_line.h"
10 #include "base/metrics/histogram.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "content/common/frame_messages.h"
13 #include "content/public/common/content_constants.h"
14 #include "content/public/common/content_switches.h"
15 #include "content/public/renderer/plugin_instance_throttler.h"
16 #include "content/public/renderer/render_frame.h"
17 #include "ppapi/shared_impl/ppapi_constants.h"
18 #include "third_party/WebKit/public/web/WebLocalFrame.h"
20 namespace content {
22 namespace {
24 // Initial decision of the peripheral content decision.
25 // These numeric values are used in UMA logs; do not change them.
26 enum PeripheralHeuristicDecision {
27 HEURISTIC_DECISION_PERIPHERAL = 0,
28 HEURISTIC_DECISION_ESSENTIAL_SAME_ORIGIN = 1,
29 HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_BIG = 2,
30 HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_WHITELISTED = 3,
31 HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_TINY = 4,
32 HEURISTIC_DECISION_ESSENTIAL_UNKNOWN_SIZE = 5,
33 HEURISTIC_DECISION_NUM_ITEMS
36 const char kPeripheralHeuristicHistogram[] =
37 "Plugin.PowerSaver.PeripheralHeuristic";
39 // Plugin content below this size in height and width is considered "tiny".
40 // Tiny content is never peripheral, as tiny plugins often serve a critical
41 // purpose, and the user often cannot find and click to unthrottle it.
42 const int kPeripheralContentTinySize = 5;
44 void RecordDecisionMetric(PeripheralHeuristicDecision decision) {
45 UMA_HISTOGRAM_ENUMERATION(kPeripheralHeuristicHistogram, decision,
46 HEURISTIC_DECISION_NUM_ITEMS);
49 } // namespace
51 PluginPowerSaverHelper::PeripheralPlugin::PeripheralPlugin(
52 const url::Origin& content_origin,
53 const base::Closure& unthrottle_callback)
54 : content_origin(content_origin),
55 unthrottle_callback(unthrottle_callback) {}
57 PluginPowerSaverHelper::PeripheralPlugin::~PeripheralPlugin() {
60 PluginPowerSaverHelper::PluginPowerSaverHelper(RenderFrame* render_frame)
61 : RenderFrameObserver(render_frame)
62 , override_for_testing_(Normal) {
63 base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess();
64 std::string override_for_testing = command_line.GetSwitchValueASCII(
65 switches::kOverridePluginPowerSaverForTesting);
66 if (override_for_testing == "never")
67 override_for_testing_ = Never;
68 else if (override_for_testing == "ignore-list")
69 override_for_testing_ = IgnoreList;
70 else if (override_for_testing == "always")
71 override_for_testing_ = Always;
74 PluginPowerSaverHelper::~PluginPowerSaverHelper() {
77 void PluginPowerSaverHelper::DidCommitProvisionalLoad(
78 bool is_new_navigation,
79 bool is_same_page_navigation) {
80 blink::WebFrame* frame = render_frame()->GetWebFrame();
81 // Only apply to top-level and new page navigation.
82 if (frame->parent() || is_same_page_navigation)
83 return; // Not a top-level navigation.
85 origin_whitelist_.clear();
88 bool PluginPowerSaverHelper::OnMessageReceived(const IPC::Message& message) {
89 bool handled = true;
90 IPC_BEGIN_MESSAGE_MAP(PluginPowerSaverHelper, message)
91 IPC_MESSAGE_HANDLER(FrameMsg_UpdatePluginContentOriginWhitelist,
92 OnUpdatePluginContentOriginWhitelist)
93 IPC_MESSAGE_UNHANDLED(handled = false)
94 IPC_END_MESSAGE_MAP()
95 return handled;
98 void PluginPowerSaverHelper::OnUpdatePluginContentOriginWhitelist(
99 const std::set<url::Origin>& origin_whitelist) {
100 origin_whitelist_ = origin_whitelist;
102 // Check throttled plugin instances to see if any can be unthrottled.
103 auto it = peripheral_plugins_.begin();
104 while (it != peripheral_plugins_.end()) {
105 if (origin_whitelist.count(it->content_origin)) {
106 it->unthrottle_callback.Run();
107 it = peripheral_plugins_.erase(it);
108 } else {
109 ++it;
114 void PluginPowerSaverHelper::RegisterPeripheralPlugin(
115 const url::Origin& content_origin,
116 const base::Closure& unthrottle_callback) {
117 peripheral_plugins_.push_back(
118 PeripheralPlugin(content_origin, unthrottle_callback));
121 bool PluginPowerSaverHelper::ShouldThrottleContent(
122 const url::Origin& main_frame_origin,
123 const url::Origin& content_origin,
124 const std::string& plugin_module_name,
125 int width,
126 int height,
127 bool* cross_origin_main_content) const {
128 if (cross_origin_main_content)
129 *cross_origin_main_content = false;
131 // This feature has only been tested throughly with Flash thus far.
132 // It is also enabled for the Power Saver test plugin for browser tests.
133 if (override_for_testing_ == Always) {
134 return true;
135 } else if (override_for_testing_ == Never) {
136 return false;
137 } else if (override_for_testing_ == Normal &&
138 plugin_module_name != content::kFlashPluginName) {
139 return false;
142 if (main_frame_origin.IsSameOriginWith(content_origin)) {
143 RecordDecisionMetric(HEURISTIC_DECISION_ESSENTIAL_SAME_ORIGIN);
144 return false;
147 if (width <= 0 || height <= 0) {
148 RecordDecisionMetric(HEURISTIC_DECISION_ESSENTIAL_UNKNOWN_SIZE);
149 return false;
152 // Whitelisted plugin origins are also essential.
153 if (origin_whitelist_.count(content_origin)) {
154 RecordDecisionMetric(HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_WHITELISTED);
155 return false;
158 // Never mark tiny content as peripheral.
159 if (width <= kPeripheralContentTinySize &&
160 height <= kPeripheralContentTinySize) {
161 RecordDecisionMetric(HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_TINY);
162 return false;
165 // Plugin content large in both dimensions are the "main attraction".
166 if (PluginInstanceThrottler::IsLargeContent(width, height)) {
167 RecordDecisionMetric(HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_BIG);
168 if (cross_origin_main_content)
169 *cross_origin_main_content = true;
170 return false;
173 RecordDecisionMetric(HEURISTIC_DECISION_PERIPHERAL);
174 return true;
177 void PluginPowerSaverHelper::WhitelistContentOrigin(
178 const url::Origin& content_origin) {
179 if (origin_whitelist_.insert(content_origin).second) {
180 Send(new FrameHostMsg_PluginContentOriginAllowed(
181 render_frame()->GetRoutingID(), content_origin));
185 } // namespace content