Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1117)

Side by Side Diff: content/renderer/pepper/plugin_instance_throttler_impl.cc

Issue 904913003: Plugin Power Saver: Fix implicitly sized and below the fold plugins. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix windows compile Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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_instance_throttler_impl.h" 5 #include "content/renderer/pepper/plugin_instance_throttler_impl.h"
6 6
7 #include "base/metrics/histogram.h" 7 #include "base/metrics/histogram.h"
8 #include "base/time/time.h" 8 #include "base/time/time.h"
9 #include "content/public/common/content_constants.h" 9 #include "content/public/common/content_constants.h"
10 #include "content/public/renderer/render_frame.h"
11 #include "content/public/renderer/render_thread.h" 10 #include "content/public/renderer/render_thread.h"
11 #include "content/renderer/render_frame_impl.h"
12 #include "third_party/WebKit/public/platform/WebRect.h"
12 #include "third_party/WebKit/public/web/WebInputEvent.h" 13 #include "third_party/WebKit/public/web/WebInputEvent.h"
14 #include "third_party/WebKit/public/web/WebPluginParams.h"
13 #include "ui/gfx/color_utils.h" 15 #include "ui/gfx/color_utils.h"
14 #include "url/gurl.h" 16 #include "url/gurl.h"
15 17
16 namespace content { 18 namespace content {
17 19
18 namespace { 20 namespace {
19 21
20 // When we give up waiting for a suitable preview frame, and simply suspend
21 // the plugin where it's at. In milliseconds.
22 const int kThrottleTimeout = 5000;
23
24 // Threshold for 'boring' score to accept a frame as good enough to be a 22 // Threshold for 'boring' score to accept a frame as good enough to be a
25 // representative keyframe. Units are the ratio of all pixels that are within 23 // representative keyframe. Units are the ratio of all pixels that are within
26 // the most common luma bin. The same threshold is used for history thumbnails. 24 // the most common luma bin. The same threshold is used for history thumbnails.
27 const double kAcceptableFrameMaximumBoringness = 0.94; 25 const double kAcceptableFrameMaximumBoringness = 0.94;
28 26
29 const int kMinimumConsecutiveInterestingFrames = 4; 27 const int kMinimumConsecutiveInterestingFrames = 4;
30 28
29 const char kPosterParamName[] = "poster";
piman 2015/02/06 22:13:12 We're exposing this to the web, I think this shoul
tommycli 2015/02/06 22:57:10 Okay I will follow through on this. I will email b
30
31 } // namespace 31 } // namespace
32 32
33 // static 33 // static
34 scoped_ptr<PluginInstanceThrottler> PluginInstanceThrottler::Get( 34 const int PluginInstanceThrottlerImpl::kMaximumFramesToExamine = 150;
35 RenderFrame* frame,
36 const GURL& plugin_url,
37 PluginPowerSaverMode power_saver_mode) {
38 if (power_saver_mode == PluginPowerSaverMode::POWER_SAVER_MODE_ESSENTIAL)
39 return nullptr;
40 35
41 bool power_saver_enabled = 36 // static
42 power_saver_mode == 37 scoped_ptr<PluginInstanceThrottler> PluginInstanceThrottler::Create(
43 PluginPowerSaverMode::POWER_SAVER_MODE_PERIPHERAL_THROTTLED; 38 bool power_saver_enabled) {
44 return make_scoped_ptr( 39 return make_scoped_ptr(new PluginInstanceThrottlerImpl(power_saver_enabled));
45 new PluginInstanceThrottlerImpl(frame, plugin_url, power_saver_enabled));
46 } 40 }
47 41
48 // static 42 // static
43 GURL PluginInstanceThrottler::GetPluginInstancePosterImage(
44 const blink::WebPluginParams& params,
45 const GURL& page_base_url) {
46 DCHECK_EQ(params.attributeNames.size(), params.attributeValues.size());
47
48 for (size_t i = 0; i < params.attributeNames.size(); ++i) {
49 if (params.attributeNames[i] == kPosterParamName) {
50 std::string poster_value(params.attributeValues[i].utf8());
51 if (!poster_value.empty())
52 return page_base_url.Resolve(poster_value);
53 }
54 }
55 return GURL();
56 }
57
58 // static
49 void PluginInstanceThrottler::RecordUnthrottleMethodMetric( 59 void PluginInstanceThrottler::RecordUnthrottleMethodMetric(
50 PluginInstanceThrottlerImpl::PowerSaverUnthrottleMethod method) { 60 PluginInstanceThrottlerImpl::PowerSaverUnthrottleMethod method) {
51 UMA_HISTOGRAM_ENUMERATION( 61 UMA_HISTOGRAM_ENUMERATION(
52 "Plugin.PowerSaver.Unthrottle", method, 62 "Plugin.PowerSaver.Unthrottle", method,
53 PluginInstanceThrottler::UNTHROTTLE_METHOD_NUM_ITEMS); 63 PluginInstanceThrottler::UNTHROTTLE_METHOD_NUM_ITEMS);
54 } 64 }
55 65
56 PluginInstanceThrottlerImpl::PluginInstanceThrottlerImpl( 66 PluginInstanceThrottlerImpl::PluginInstanceThrottlerImpl(
57 RenderFrame* frame,
58 const GURL& plugin_url,
59 bool power_saver_enabled) 67 bool power_saver_enabled)
60 : state_(power_saver_enabled ? POWER_SAVER_ENABLED_AWAITING_KEYFRAME 68 : state_(power_saver_enabled ? THROTTLER_STATE_AWAITING_KEYFRAME
61 : POWER_SAVER_DISABLED), 69 : THROTTLER_STATE_POWER_SAVER_DISABLED),
62 is_hidden_for_placeholder_(false), 70 is_hidden_for_placeholder_(false),
63 consecutive_interesting_frames_(0), 71 consecutive_interesting_frames_(0),
64 keyframe_extraction_timed_out_(false), 72 frames_examined_(0),
65 weak_factory_(this) { 73 weak_factory_(this) {
66 // To collect UMAs, register peripheral content even if power saver disabled.
67 if (frame) {
68 frame->RegisterPeripheralPlugin(
69 plugin_url.GetOrigin(),
70 base::Bind(&PluginInstanceThrottlerImpl::MarkPluginEssential,
71 weak_factory_.GetWeakPtr(), UNTHROTTLE_METHOD_BY_WHITELIST));
72 }
73
74 if (power_saver_enabled) {
75 base::MessageLoop::current()->PostDelayedTask(
76 FROM_HERE,
77 base::Bind(&PluginInstanceThrottlerImpl::TimeoutKeyframeExtraction,
78 weak_factory_.GetWeakPtr()),
79 base::TimeDelta::FromMilliseconds(kThrottleTimeout));
80 }
81 } 74 }
82 75
83 PluginInstanceThrottlerImpl::~PluginInstanceThrottlerImpl() { 76 PluginInstanceThrottlerImpl::~PluginInstanceThrottlerImpl() {
84 FOR_EACH_OBSERVER(Observer, observer_list_, OnThrottlerDestroyed()); 77 FOR_EACH_OBSERVER(Observer, observer_list_, OnThrottlerDestroyed());
85 if (state_ != PLUGIN_INSTANCE_MARKED_ESSENTIAL) 78 if (state_ != THROTTLER_STATE_MARKED_ESSENTIAL)
86 RecordUnthrottleMethodMetric(UNTHROTTLE_METHOD_NEVER); 79 RecordUnthrottleMethodMetric(UNTHROTTLE_METHOD_NEVER);
87 } 80 }
88 81
89 void PluginInstanceThrottlerImpl::AddObserver(Observer* observer) { 82 void PluginInstanceThrottlerImpl::AddObserver(Observer* observer) {
90 observer_list_.AddObserver(observer); 83 observer_list_.AddObserver(observer);
91 } 84 }
92 85
93 void PluginInstanceThrottlerImpl::RemoveObserver(Observer* observer) { 86 void PluginInstanceThrottlerImpl::RemoveObserver(Observer* observer) {
94 observer_list_.RemoveObserver(observer); 87 observer_list_.RemoveObserver(observer);
95 } 88 }
96 89
97 bool PluginInstanceThrottlerImpl::IsThrottled() const { 90 bool PluginInstanceThrottlerImpl::IsThrottled() const {
98 return state_ == POWER_SAVER_ENABLED_PLUGIN_THROTTLED; 91 return state_ == THROTTLER_STATE_PLUGIN_THROTTLED;
99 } 92 }
100 93
101 bool PluginInstanceThrottlerImpl::IsHiddenForPlaceholder() const { 94 bool PluginInstanceThrottlerImpl::IsHiddenForPlaceholder() const {
102 return is_hidden_for_placeholder_; 95 return is_hidden_for_placeholder_;
103 } 96 }
104 97
105 void PluginInstanceThrottlerImpl::MarkPluginEssential( 98 void PluginInstanceThrottlerImpl::MarkPluginEssential(
106 PowerSaverUnthrottleMethod method) { 99 PowerSaverUnthrottleMethod method) {
107 if (state_ == PLUGIN_INSTANCE_MARKED_ESSENTIAL) 100 if (state_ == THROTTLER_STATE_MARKED_ESSENTIAL)
108 return; 101 return;
109 102
110 bool was_throttled = IsThrottled(); 103 bool was_throttled = IsThrottled();
111 state_ = PLUGIN_INSTANCE_MARKED_ESSENTIAL; 104 state_ = THROTTLER_STATE_MARKED_ESSENTIAL;
112 RecordUnthrottleMethodMetric(method); 105 RecordUnthrottleMethodMetric(method);
113 106
114 if (was_throttled) 107 if (was_throttled)
115 FOR_EACH_OBSERVER(Observer, observer_list_, OnThrottleStateChange()); 108 FOR_EACH_OBSERVER(Observer, observer_list_, OnThrottleStateChange());
116 } 109 }
117 110
118 void PluginInstanceThrottlerImpl::SetHiddenForPlaceholder(bool hidden) { 111 void PluginInstanceThrottlerImpl::SetHiddenForPlaceholder(bool hidden) {
119 is_hidden_for_placeholder_ = hidden; 112 is_hidden_for_placeholder_ = hidden;
120 FOR_EACH_OBSERVER(Observer, observer_list_, OnHiddenForPlaceholder(hidden)); 113 FOR_EACH_OBSERVER(Observer, observer_list_, OnHiddenForPlaceholder(hidden));
121 } 114 }
122 115
116 void PluginInstanceThrottlerImpl::Initialize(
117 RenderFrameImpl* frame,
118 const GURL& content_origin,
119 const std::string& plugin_module_name,
120 const blink::WebRect& bounds) {
121 // |frame| may be nullptr in tests.
122 if (frame) {
123 PluginPowerSaverHelper* helper = frame->plugin_power_saver_helper();
124 bool cross_origin_main_content = false;
125 if (!helper->ShouldThrottleContent(content_origin, plugin_module_name,
126 bounds.width, bounds.height,
127 &cross_origin_main_content)) {
128 state_ = THROTTLER_STATE_MARKED_ESSENTIAL;
129
130 if (cross_origin_main_content)
131 helper->WhitelistContentOrigin(content_origin);
132
133 return;
134 }
135
136 // To collect UMAs, register peripheral content even if power saver mode
137 // is disabled.
138 helper->RegisterPeripheralPlugin(
139 content_origin,
140 base::Bind(&PluginInstanceThrottlerImpl::MarkPluginEssential,
141 weak_factory_.GetWeakPtr(), UNTHROTTLE_METHOD_BY_WHITELIST));
142 }
143 }
144
123 void PluginInstanceThrottlerImpl::OnImageFlush(const SkBitmap* bitmap) { 145 void PluginInstanceThrottlerImpl::OnImageFlush(const SkBitmap* bitmap) {
124 DCHECK(needs_representative_keyframe()); 146 DCHECK(needs_representative_keyframe());
125 if (!bitmap) 147 if (!bitmap)
126 return; 148 return;
127 149
150 ++frames_examined_;
151
128 double boring_score = color_utils::CalculateBoringScore(*bitmap); 152 double boring_score = color_utils::CalculateBoringScore(*bitmap);
129 if (boring_score <= kAcceptableFrameMaximumBoringness) 153 if (boring_score <= kAcceptableFrameMaximumBoringness)
130 ++consecutive_interesting_frames_; 154 ++consecutive_interesting_frames_;
131 else 155 else
132 consecutive_interesting_frames_ = 0; 156 consecutive_interesting_frames_ = 0;
133 157
134 if (keyframe_extraction_timed_out_ || 158 if (frames_examined_ >= kMaximumFramesToExamine ||
135 consecutive_interesting_frames_ >= kMinimumConsecutiveInterestingFrames) { 159 consecutive_interesting_frames_ >= kMinimumConsecutiveInterestingFrames) {
136 FOR_EACH_OBSERVER(Observer, observer_list_, OnKeyframeExtracted(bitmap)); 160 FOR_EACH_OBSERVER(Observer, observer_list_, OnKeyframeExtracted(bitmap));
137 EngageThrottle(); 161 EngageThrottle();
138 } 162 }
139 } 163 }
140 164
141 bool PluginInstanceThrottlerImpl::ConsumeInputEvent( 165 bool PluginInstanceThrottlerImpl::ConsumeInputEvent(
142 const blink::WebInputEvent& event) { 166 const blink::WebInputEvent& event) {
143 // Always allow right-clicks through so users may verify it's a plug-in. 167 // Always allow right-clicks through so users may verify it's a plug-in.
144 // TODO(tommycli): We should instead show a custom context menu (probably 168 // TODO(tommycli): We should instead show a custom context menu (probably
145 // using PluginPlaceholder) so users aren't confused and try to click the 169 // using PluginPlaceholder) so users aren't confused and try to click the
146 // Flash-internal 'Play' menu item. This is a stopgap solution. 170 // Flash-internal 'Play' menu item. This is a stopgap solution.
147 if (event.modifiers & blink::WebInputEvent::Modifiers::RightButtonDown) 171 if (event.modifiers & blink::WebInputEvent::Modifiers::RightButtonDown)
148 return false; 172 return false;
149 173
150 if (state_ != PLUGIN_INSTANCE_MARKED_ESSENTIAL && 174 if (state_ != THROTTLER_STATE_MARKED_ESSENTIAL &&
151 event.type == blink::WebInputEvent::MouseUp && 175 event.type == blink::WebInputEvent::MouseUp &&
152 (event.modifiers & blink::WebInputEvent::LeftButtonDown)) { 176 (event.modifiers & blink::WebInputEvent::LeftButtonDown)) {
153 bool was_throttled = IsThrottled(); 177 bool was_throttled = IsThrottled();
154 MarkPluginEssential(UNTHROTTLE_METHOD_BY_CLICK); 178 MarkPluginEssential(UNTHROTTLE_METHOD_BY_CLICK);
155 return was_throttled; 179 return was_throttled;
156 } 180 }
157 181
158 return IsThrottled(); 182 return IsThrottled();
159 } 183 }
160 184
161 void PluginInstanceThrottlerImpl::EngageThrottle() { 185 void PluginInstanceThrottlerImpl::EngageThrottle() {
162 if (state_ != POWER_SAVER_ENABLED_AWAITING_KEYFRAME) 186 if (state_ != THROTTLER_STATE_AWAITING_KEYFRAME)
163 return; 187 return;
164 188
165 state_ = POWER_SAVER_ENABLED_PLUGIN_THROTTLED; 189 state_ = THROTTLER_STATE_PLUGIN_THROTTLED;
166 FOR_EACH_OBSERVER(Observer, observer_list_, OnThrottleStateChange()); 190 FOR_EACH_OBSERVER(Observer, observer_list_, OnThrottleStateChange());
167 } 191 }
168 192
169 void PluginInstanceThrottlerImpl::TimeoutKeyframeExtraction() {
170 keyframe_extraction_timed_out_ = true;
171 }
172
173 } // namespace content 193 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698