mesa gn build: suppress -Wstring-conversion warnings
[chromium-blink-merge.git] / content / renderer / pepper / pepper_plugin_instance_throttler.cc
blob9300c89099f4a03b68f2eb693cc6775c10c3fc33
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/pepper_plugin_instance_throttler.h"
7 #include "base/command_line.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/metrics/histogram.h"
10 #include "base/metrics/sparse_histogram.h"
11 #include "base/time/time.h"
12 #include "content/public/common/content_constants.h"
13 #include "content/public/common/content_switches.h"
14 #include "content/renderer/pepper/plugin_power_saver_helper_impl.h"
15 #include "content/renderer/render_thread_impl.h"
16 #include "third_party/WebKit/public/web/WebInputEvent.h"
17 #include "ui/gfx/color_utils.h"
19 namespace content {
21 namespace {
23 static const int kInfiniteRatio = 99999;
25 #define UMA_HISTOGRAM_ASPECT_RATIO(name, width, height) \
26 UMA_HISTOGRAM_SPARSE_SLOWLY( \
27 name, (height) ? ((width)*100) / (height) : kInfiniteRatio);
29 // Histogram tracking prevalence of tiny Flash instances. Units in pixels.
30 enum PluginFlashTinyContentSize {
31 TINY_CONTENT_SIZE_1_1 = 0,
32 TINY_CONTENT_SIZE_5_5 = 1,
33 TINY_CONTENT_SIZE_10_10 = 2,
34 TINY_CONTENT_SIZE_LARGE = 3,
35 TINY_CONTENT_SIZE_NUM_ITEMS
38 // How the throttled power saver is unthrottled, if ever.
39 // These numeric values are used in UMA logs; do not change them.
40 enum PowerSaverUnthrottleMethod {
41 UNTHROTTLE_METHOD_NEVER = 0,
42 UNTHROTTLE_METHOD_BY_CLICK = 1,
43 UNTHROTTLE_METHOD_BY_WHITELIST = 2,
44 UNTHROTTLE_METHOD_NUM_ITEMS
47 const char kFlashClickSizeAspectRatioHistogram[] =
48 "Plugin.Flash.ClickSize.AspectRatio";
49 const char kFlashClickSizeHeightHistogram[] = "Plugin.Flash.ClickSize.Height";
50 const char kFlashClickSizeWidthHistogram[] = "Plugin.Flash.ClickSize.Width";
51 const char kFlashTinyContentSizeHistogram[] = "Plugin.Flash.TinyContentSize";
52 const char kPowerSaverUnthrottleHistogram[] = "Plugin.PowerSaver.Unthrottle";
54 // Record size metrics for all Flash instances.
55 void RecordFlashSizeMetric(int width, int height) {
56 PluginFlashTinyContentSize size = TINY_CONTENT_SIZE_LARGE;
58 if (width <= 1 && height <= 1)
59 size = TINY_CONTENT_SIZE_1_1;
60 else if (width <= 5 && height <= 5)
61 size = TINY_CONTENT_SIZE_5_5;
62 else if (width <= 10 && height <= 10)
63 size = TINY_CONTENT_SIZE_10_10;
65 UMA_HISTOGRAM_ENUMERATION(kFlashTinyContentSizeHistogram, size,
66 TINY_CONTENT_SIZE_NUM_ITEMS);
69 void RecordUnthrottleMethodMetric(PowerSaverUnthrottleMethod method) {
70 UMA_HISTOGRAM_ENUMERATION(kPowerSaverUnthrottleHistogram, method,
71 UNTHROTTLE_METHOD_NUM_ITEMS);
74 // Records size metrics for Flash instances that are clicked.
75 void RecordFlashClickSizeMetric(int width, int height) {
76 base::HistogramBase* width_histogram = base::LinearHistogram::FactoryGet(
77 kFlashClickSizeWidthHistogram,
78 0, // minimum width
79 500, // maximum width
80 100, // number of buckets.
81 base::HistogramBase::kUmaTargetedHistogramFlag);
82 width_histogram->Add(width);
84 base::HistogramBase* height_histogram = base::LinearHistogram::FactoryGet(
85 kFlashClickSizeHeightHistogram,
86 0, // minimum height
87 400, // maximum height
88 100, // number of buckets.
89 base::HistogramBase::kUmaTargetedHistogramFlag);
90 height_histogram->Add(height);
92 UMA_HISTOGRAM_ASPECT_RATIO(kFlashClickSizeAspectRatioHistogram, width,
93 height);
96 // When we give up waiting for a suitable preview frame, and simply suspend
97 // the plugin where it's at. In milliseconds.
98 const int kThrottleTimeout = 5000;
100 // Threshold for 'boring' score to accept a frame as good enough to be a
101 // representative keyframe. Units are the ratio of all pixels that are within
102 // the most common luma bin. The same threshold is used for history thumbnails.
103 const double kAcceptableFrameMaximumBoringness = 0.94;
105 const int kMinimumConsecutiveInterestingFrames = 4;
107 } // namespace
109 PepperPluginInstanceThrottler::PepperPluginInstanceThrottler(
110 PluginPowerSaverHelperImpl* power_saver_helper,
111 const blink::WebRect& bounds,
112 const std::string& module_name,
113 const GURL& plugin_url,
114 const base::Closure& throttle_change_callback)
115 : bounds_(bounds),
116 throttle_change_callback_(throttle_change_callback),
117 is_flash_plugin_(module_name == kFlashPluginName),
118 needs_representative_keyframe_(false),
119 consecutive_interesting_frames_(0),
120 has_been_clicked_(false),
121 power_saver_enabled_(false),
122 is_peripheral_content_(false),
123 plugin_throttled_(false),
124 weak_factory_(this) {
125 GURL content_origin = plugin_url.GetOrigin();
127 if (is_flash_plugin_ && RenderThread::Get()) {
128 RenderThread::Get()->RecordAction(
129 base::UserMetricsAction("Flash.PluginInstanceCreated"));
130 RecordFlashSizeMetric(bounds.width, bounds.height);
133 bool is_main_attraction = false;
134 is_peripheral_content_ =
135 is_flash_plugin_ &&
136 power_saver_helper->ShouldThrottleContent(
137 content_origin, bounds.width, bounds.height, &is_main_attraction);
139 power_saver_enabled_ = is_peripheral_content_ &&
140 base::CommandLine::ForCurrentProcess()->HasSwitch(
141 switches::kEnablePluginPowerSaver);
143 if (is_peripheral_content_) {
144 // To collect UMAs, register peripheral content even if we don't throttle.
145 power_saver_helper->RegisterPeripheralPlugin(
146 content_origin, base::Bind(&PepperPluginInstanceThrottler::
147 DisablePowerSaverByRetroactiveWhitelist,
148 weak_factory_.GetWeakPtr()));
150 if (power_saver_enabled_) {
151 needs_representative_keyframe_ = true;
152 base::MessageLoop::current()->PostDelayedTask(
153 FROM_HERE,
154 base::Bind(&PepperPluginInstanceThrottler::SetPluginThrottled,
155 weak_factory_.GetWeakPtr(), true /* throttled */),
156 base::TimeDelta::FromMilliseconds(kThrottleTimeout));
158 } else if (is_main_attraction) {
159 power_saver_helper->WhitelistContentOrigin(content_origin);
163 PepperPluginInstanceThrottler::~PepperPluginInstanceThrottler() {
166 void PepperPluginInstanceThrottler::OnImageFlush(const SkBitmap* bitmap) {
167 if (!needs_representative_keyframe_ || !bitmap)
168 return;
170 double boring_score = color_utils::CalculateBoringScore(*bitmap);
171 if (boring_score <= kAcceptableFrameMaximumBoringness)
172 ++consecutive_interesting_frames_;
173 else
174 consecutive_interesting_frames_ = 0;
176 if (consecutive_interesting_frames_ >= kMinimumConsecutiveInterestingFrames)
177 SetPluginThrottled(true);
180 bool PepperPluginInstanceThrottler::ConsumeInputEvent(
181 const blink::WebInputEvent& event) {
182 if (!has_been_clicked_ && is_flash_plugin_ &&
183 event.type == blink::WebInputEvent::MouseDown) {
184 has_been_clicked_ = true;
185 RecordFlashClickSizeMetric(bounds_.width, bounds_.height);
188 if (event.type == blink::WebInputEvent::MouseUp && is_peripheral_content_) {
189 is_peripheral_content_ = false;
190 power_saver_enabled_ = false;
192 RecordUnthrottleMethodMetric(UNTHROTTLE_METHOD_BY_CLICK);
194 if (plugin_throttled_) {
195 SetPluginThrottled(false /* throttled */);
196 return true;
200 return plugin_throttled_;
203 void PepperPluginInstanceThrottler::SetPluginThrottled(bool throttled) {
204 // Do not throttle if we've already disabled power saver.
205 if (!power_saver_enabled_ && throttled)
206 return;
208 // Once we change the throttle state, we will never need the snapshot again.
209 needs_representative_keyframe_ = false;
211 plugin_throttled_ = throttled;
212 throttle_change_callback_.Run();
215 void PepperPluginInstanceThrottler::DisablePowerSaverByRetroactiveWhitelist() {
216 if (!is_peripheral_content_)
217 return;
219 is_peripheral_content_ = false;
220 power_saver_enabled_ = false;
221 SetPluginThrottled(false);
223 RecordUnthrottleMethodMetric(UNTHROTTLE_METHOD_BY_WHITELIST);
226 } // namespace content