| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/renderer/pepper/plugin_power_saver_helper_impl.h" | 5 #include "content/renderer/pepper/plugin_power_saver_helper_impl.h" |
| 6 | 6 |
| 7 #include "base/metrics/histogram.h" | 7 #include "base/metrics/histogram.h" |
| 8 #include "base/strings/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" |
| 9 #include "content/common/frame_messages.h" | 9 #include "content/common/frame_messages.h" |
| 10 #include "content/public/renderer/document_state.h" | 10 #include "content/public/renderer/document_state.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 | 21 |
| 22 const char kPosterParamName[] = "poster"; | 22 const char kPosterParamName[] = "poster"; |
| 23 | 23 |
| 24 // Initial decision of the peripheral content decision. | 24 // Initial decision of the peripheral content decision. |
| 25 // These numeric values are used in UMA logs; do not change them. | 25 // These numeric values are used in UMA logs; do not change them. |
| 26 enum PeripheralHeuristicDecision { | 26 enum PeripheralHeuristicDecision { |
| 27 HEURISTIC_DECISION_PERIPHERAL = 0, | 27 HEURISTIC_DECISION_PERIPHERAL = 0, |
| 28 HEURISTIC_DECISION_ESSENTIAL_SAME_ORIGIN = 1, | 28 HEURISTIC_DECISION_ESSENTIAL_SAME_ORIGIN = 1, |
| 29 HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_BIG = 2, | 29 HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_BIG = 2, |
| 30 HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_WHITELISTED = 3, | 30 HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_WHITELISTED = 3, |
| 31 HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_TINY = 4, |
| 31 HEURISTIC_DECISION_NUM_ITEMS | 32 HEURISTIC_DECISION_NUM_ITEMS |
| 32 }; | 33 }; |
| 33 | 34 |
| 34 const char kPeripheralHeuristicHistogram[] = | 35 const char kPeripheralHeuristicHistogram[] = |
| 35 "Plugin.PowerSaver.PeripheralHeuristic"; | 36 "Plugin.PowerSaver.PeripheralHeuristic"; |
| 36 | 37 |
| 37 // Maximum dimensions plug-in content may have while still being considered | 38 // Maximum dimensions plug-in content may have while still being considered |
| 38 // peripheral content. These match the sizes used by Safari. | 39 // peripheral content. These match the sizes used by Safari. |
| 39 const int kPeripheralContentMaxWidth = 400; | 40 const int kPeripheralContentMaxWidth = 400; |
| 40 const int kPeripheralContentMaxHeight = 300; | 41 const int kPeripheralContentMaxHeight = 300; |
| 41 | 42 |
| 43 // Plug-in content below this size in height and width is considered "tiny". |
| 44 // Tiny content is never peripheral, as tiny plug-ins often serve a critical |
| 45 // purpose, and the user often cannot find and click to unthrottle it. |
| 46 const int kPeripheralContentTinySize = 5; |
| 47 |
| 42 void RecordDecisionMetric(PeripheralHeuristicDecision decision) { | 48 void RecordDecisionMetric(PeripheralHeuristicDecision decision) { |
| 43 UMA_HISTOGRAM_ENUMERATION(kPeripheralHeuristicHistogram, decision, | 49 UMA_HISTOGRAM_ENUMERATION(kPeripheralHeuristicHistogram, decision, |
| 44 HEURISTIC_DECISION_NUM_ITEMS); | 50 HEURISTIC_DECISION_NUM_ITEMS); |
| 45 } | 51 } |
| 46 | 52 |
| 47 const char kWebPluginParamHeight[] = "height"; | 53 const char kWebPluginParamHeight[] = "height"; |
| 48 const char kWebPluginParamWidth[] = "width"; | 54 const char kWebPluginParamWidth[] = "width"; |
| 49 | 55 |
| 50 // Returns true if valid non-negative height and width extracted. | 56 // Returns true if valid non-negative height and width extracted. |
| 51 // When this returns false, |width| and |height| are set to undefined values. | 57 // When this returns false, |width| and |height| are set to undefined values. |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 130 | 136 |
| 131 GURL PluginPowerSaverHelperImpl::GetPluginInstancePosterImage( | 137 GURL PluginPowerSaverHelperImpl::GetPluginInstancePosterImage( |
| 132 const blink::WebPluginParams& params, | 138 const blink::WebPluginParams& params, |
| 133 const GURL& base_url) const { | 139 const GURL& base_url) const { |
| 134 DCHECK_EQ(params.attributeNames.size(), params.attributeValues.size()); | 140 DCHECK_EQ(params.attributeNames.size(), params.attributeValues.size()); |
| 135 | 141 |
| 136 GURL content_origin = GURL(params.url).GetOrigin(); | 142 GURL content_origin = GURL(params.url).GetOrigin(); |
| 137 int width = 0; | 143 int width = 0; |
| 138 int height = 0; | 144 int height = 0; |
| 139 | 145 |
| 140 bool cross_origin = false; | |
| 141 if (!ExtractDimensions(params, &width, &height)) | 146 if (!ExtractDimensions(params, &width, &height)) |
| 142 return GURL(); | 147 return GURL(); |
| 143 | 148 |
| 144 if (!ShouldThrottleContent(content_origin, width, height, &cross_origin)) | 149 if (!ShouldThrottleContent(content_origin, width, height, nullptr)) |
| 145 return GURL(); | 150 return GURL(); |
| 146 | 151 |
| 147 for (size_t i = 0; i < params.attributeNames.size(); ++i) { | 152 for (size_t i = 0; i < params.attributeNames.size(); ++i) { |
| 148 if (params.attributeNames[i] == kPosterParamName) { | 153 if (params.attributeNames[i] == kPosterParamName) { |
| 149 std::string poster_value(params.attributeValues[i].utf8()); | 154 std::string poster_value(params.attributeValues[i].utf8()); |
| 150 if (!poster_value.empty()) | 155 if (!poster_value.empty()) |
| 151 return base_url.Resolve(poster_value); | 156 return base_url.Resolve(poster_value); |
| 152 } | 157 } |
| 153 } | 158 } |
| 154 return GURL(); | 159 return GURL(); |
| 155 } | 160 } |
| 156 | 161 |
| 157 void PluginPowerSaverHelperImpl::RegisterPeripheralPlugin( | 162 void PluginPowerSaverHelperImpl::RegisterPeripheralPlugin( |
| 158 const GURL& content_origin, | 163 const GURL& content_origin, |
| 159 const base::Closure& unthrottle_callback) { | 164 const base::Closure& unthrottle_callback) { |
| 160 peripheral_plugins_.push_back( | 165 peripheral_plugins_.push_back( |
| 161 PeripheralPlugin(content_origin, unthrottle_callback)); | 166 PeripheralPlugin(content_origin, unthrottle_callback)); |
| 162 } | 167 } |
| 163 | 168 |
| 164 bool PluginPowerSaverHelperImpl::ShouldThrottleContent( | 169 bool PluginPowerSaverHelperImpl::ShouldThrottleContent( |
| 165 const GURL& content_origin, | 170 const GURL& content_origin, |
| 166 int width, | 171 int width, |
| 167 int height, | 172 int height, |
| 168 bool* cross_origin) const { | 173 bool* is_main_attraction) const { |
| 169 DCHECK(cross_origin); | 174 DCHECK_EQ(content_origin.GetOrigin(), content_origin); |
| 170 *cross_origin = true; | 175 if (is_main_attraction) |
| 176 *is_main_attraction = false; |
| 171 | 177 |
| 172 // TODO(alexmos): Update this to use the origin of the RemoteFrame when 426512 | 178 // TODO(alexmos): Update this to use the origin of the RemoteFrame when 426512 |
| 173 // is fixed. For now, case 3 in the class level comment doesn't work in | 179 // is fixed. For now, case 3 in the class level comment doesn't work in |
| 174 // --site-per-process mode. | 180 // --site-per-process mode. |
| 175 blink::WebFrame* main_frame = | 181 blink::WebFrame* main_frame = |
| 176 render_frame()->GetWebFrame()->view()->mainFrame(); | 182 render_frame()->GetWebFrame()->view()->mainFrame(); |
| 177 if (main_frame->isWebRemoteFrame()) { | 183 if (main_frame->isWebRemoteFrame()) { |
| 178 RecordDecisionMetric(HEURISTIC_DECISION_PERIPHERAL); | 184 RecordDecisionMetric(HEURISTIC_DECISION_PERIPHERAL); |
| 179 return true; | 185 return true; |
| 180 } | 186 } |
| 181 | 187 |
| 182 // All same-origin plugin content is essential. | 188 // All same-origin plugin content is essential. |
| 183 GURL main_frame_origin = GURL(main_frame->document().url()).GetOrigin(); | 189 GURL main_frame_origin = GURL(main_frame->document().url()).GetOrigin(); |
| 184 if (content_origin == main_frame_origin) { | 190 if (content_origin == main_frame_origin) { |
| 185 RecordDecisionMetric(HEURISTIC_DECISION_ESSENTIAL_SAME_ORIGIN); | 191 RecordDecisionMetric(HEURISTIC_DECISION_ESSENTIAL_SAME_ORIGIN); |
| 186 *cross_origin = false; | |
| 187 return false; | 192 return false; |
| 188 } | 193 } |
| 189 | 194 |
| 190 // Whitelisted plugin origins are also essential. | 195 // Whitelisted plugin origins are also essential. |
| 191 if (origin_whitelist_.count(content_origin)) { | 196 if (origin_whitelist_.count(content_origin)) { |
| 192 RecordDecisionMetric(HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_WHITELISTED); | 197 RecordDecisionMetric(HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_WHITELISTED); |
| 193 return false; | 198 return false; |
| 194 } | 199 } |
| 195 | 200 |
| 196 // Cross-origin plugin content is peripheral if smaller than a maximum size. | 201 // Never mark tiny content as peripheral. |
| 197 bool content_is_small = width < kPeripheralContentMaxWidth || | 202 if (width <= kPeripheralContentTinySize && |
| 198 height < kPeripheralContentMaxHeight; | 203 height <= kPeripheralContentTinySize) { |
| 204 RecordDecisionMetric(HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_TINY); |
| 205 return false; |
| 206 } |
| 199 | 207 |
| 200 if (content_is_small) | 208 // Plugin content large in both dimensions are the "main attraction". |
| 201 RecordDecisionMetric(HEURISTIC_DECISION_PERIPHERAL); | 209 if (width >= kPeripheralContentMaxWidth && |
| 202 else | 210 height >= kPeripheralContentMaxHeight) { |
| 203 RecordDecisionMetric(HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_BIG); | 211 RecordDecisionMetric(HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_BIG); |
| 212 if (is_main_attraction) |
| 213 *is_main_attraction = true; |
| 214 return false; |
| 215 } |
| 204 | 216 |
| 205 return content_is_small; | 217 RecordDecisionMetric(HEURISTIC_DECISION_PERIPHERAL); |
| 218 return true; |
| 206 } | 219 } |
| 207 | 220 |
| 208 void PluginPowerSaverHelperImpl::WhitelistContentOrigin( | 221 void PluginPowerSaverHelperImpl::WhitelistContentOrigin( |
| 209 const GURL& content_origin) { | 222 const GURL& content_origin) { |
| 210 DCHECK_EQ(content_origin.GetOrigin(), content_origin); | 223 DCHECK_EQ(content_origin.GetOrigin(), content_origin); |
| 211 if (origin_whitelist_.insert(content_origin).second) { | 224 if (origin_whitelist_.insert(content_origin).second) { |
| 212 Send(new FrameHostMsg_PluginContentOriginAllowed( | 225 Send(new FrameHostMsg_PluginContentOriginAllowed( |
| 213 render_frame()->GetRoutingID(), content_origin)); | 226 render_frame()->GetRoutingID(), content_origin)); |
| 214 } | 227 } |
| 215 } | 228 } |
| 216 | 229 |
| 217 } // namespace content | 230 } // namespace content |
| OLD | NEW |