[Ozone-Gbm] Explicitly crash if trying software rendering on GBM
[chromium-blink-merge.git] / content / renderer / pepper / plugin_instance_throttler_impl.cc
blob1ff6248f3b349d75a7aa60f9b6b82bace08566e8
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_instance_throttler_impl.h"
7 #include "base/metrics/histogram.h"
8 #include "base/time/time.h"
9 #include "content/public/common/content_constants.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"
13 #include "third_party/WebKit/public/web/WebInputEvent.h"
14 #include "third_party/WebKit/public/web/WebPluginParams.h"
15 #include "ui/gfx/color_utils.h"
16 #include "url/gurl.h"
18 namespace content {
20 namespace {
22 // Threshold for 'boring' score to accept a frame as good enough to be a
23 // representative keyframe. Units are the ratio of all pixels that are within
24 // the most common luma bin. The same threshold is used for history thumbnails.
25 const double kAcceptableFrameMaximumBoringness = 0.94;
27 const int kMinimumConsecutiveInterestingFrames = 4;
29 } // namespace
31 // static
32 const int PluginInstanceThrottlerImpl::kMaximumFramesToExamine = 150;
34 // static
35 scoped_ptr<PluginInstanceThrottler> PluginInstanceThrottler::Create(
36 bool power_saver_enabled) {
37 return make_scoped_ptr(new PluginInstanceThrottlerImpl(power_saver_enabled));
40 // static
41 void PluginInstanceThrottler::RecordUnthrottleMethodMetric(
42 PluginInstanceThrottlerImpl::PowerSaverUnthrottleMethod method) {
43 UMA_HISTOGRAM_ENUMERATION(
44 "Plugin.PowerSaver.Unthrottle", method,
45 PluginInstanceThrottler::UNTHROTTLE_METHOD_NUM_ITEMS);
48 PluginInstanceThrottlerImpl::PluginInstanceThrottlerImpl(
49 bool power_saver_enabled)
50 : state_(power_saver_enabled ? THROTTLER_STATE_AWAITING_KEYFRAME
51 : THROTTLER_STATE_POWER_SAVER_DISABLED),
52 is_hidden_for_placeholder_(false),
53 web_plugin_(nullptr),
54 consecutive_interesting_frames_(0),
55 frames_examined_(0),
56 weak_factory_(this) {
59 PluginInstanceThrottlerImpl::~PluginInstanceThrottlerImpl() {
60 FOR_EACH_OBSERVER(Observer, observer_list_, OnThrottlerDestroyed());
61 if (state_ != THROTTLER_STATE_MARKED_ESSENTIAL)
62 RecordUnthrottleMethodMetric(UNTHROTTLE_METHOD_NEVER);
65 void PluginInstanceThrottlerImpl::AddObserver(Observer* observer) {
66 observer_list_.AddObserver(observer);
69 void PluginInstanceThrottlerImpl::RemoveObserver(Observer* observer) {
70 observer_list_.RemoveObserver(observer);
73 bool PluginInstanceThrottlerImpl::IsThrottled() const {
74 return state_ == THROTTLER_STATE_PLUGIN_THROTTLED;
77 bool PluginInstanceThrottlerImpl::IsHiddenForPlaceholder() const {
78 return is_hidden_for_placeholder_;
81 void PluginInstanceThrottlerImpl::MarkPluginEssential(
82 PowerSaverUnthrottleMethod method) {
83 if (state_ == THROTTLER_STATE_MARKED_ESSENTIAL)
84 return;
86 bool was_throttled = IsThrottled();
87 state_ = THROTTLER_STATE_MARKED_ESSENTIAL;
88 RecordUnthrottleMethodMetric(method);
90 if (was_throttled)
91 FOR_EACH_OBSERVER(Observer, observer_list_, OnThrottleStateChange());
94 void PluginInstanceThrottlerImpl::SetHiddenForPlaceholder(bool hidden) {
95 is_hidden_for_placeholder_ = hidden;
96 FOR_EACH_OBSERVER(Observer, observer_list_, OnHiddenForPlaceholder(hidden));
99 blink::WebPlugin* PluginInstanceThrottlerImpl::GetWebPlugin() const {
100 DCHECK(web_plugin_);
101 return web_plugin_;
104 void PluginInstanceThrottlerImpl::SetWebPlugin(blink::WebPlugin* web_plugin) {
105 DCHECK(!web_plugin_);
106 web_plugin_ = web_plugin;
109 void PluginInstanceThrottlerImpl::Initialize(
110 RenderFrameImpl* frame,
111 const GURL& content_origin,
112 const std::string& plugin_module_name,
113 const blink::WebRect& bounds) {
114 // |frame| may be nullptr in tests.
115 if (frame) {
116 PluginPowerSaverHelper* helper = frame->plugin_power_saver_helper();
117 bool cross_origin_main_content = false;
118 if (!helper->ShouldThrottleContent(content_origin, plugin_module_name,
119 bounds.width, bounds.height,
120 &cross_origin_main_content)) {
121 state_ = THROTTLER_STATE_MARKED_ESSENTIAL;
123 if (cross_origin_main_content)
124 helper->WhitelistContentOrigin(content_origin);
126 return;
129 // To collect UMAs, register peripheral content even if power saver mode
130 // is disabled.
131 helper->RegisterPeripheralPlugin(
132 content_origin,
133 base::Bind(&PluginInstanceThrottlerImpl::MarkPluginEssential,
134 weak_factory_.GetWeakPtr(), UNTHROTTLE_METHOD_BY_WHITELIST));
138 void PluginInstanceThrottlerImpl::OnImageFlush(const SkBitmap* bitmap) {
139 DCHECK(needs_representative_keyframe());
140 if (!bitmap)
141 return;
143 ++frames_examined_;
145 double boring_score = color_utils::CalculateBoringScore(*bitmap);
146 if (boring_score <= kAcceptableFrameMaximumBoringness)
147 ++consecutive_interesting_frames_;
148 else
149 consecutive_interesting_frames_ = 0;
151 if (frames_examined_ >= kMaximumFramesToExamine ||
152 consecutive_interesting_frames_ >= kMinimumConsecutiveInterestingFrames) {
153 FOR_EACH_OBSERVER(Observer, observer_list_, OnKeyframeExtracted(bitmap));
154 EngageThrottle();
158 bool PluginInstanceThrottlerImpl::ConsumeInputEvent(
159 const blink::WebInputEvent& event) {
160 // Always allow right-clicks through so users may verify it's a plug-in.
161 // TODO(tommycli): We should instead show a custom context menu (probably
162 // using PluginPlaceholder) so users aren't confused and try to click the
163 // Flash-internal 'Play' menu item. This is a stopgap solution.
164 if (event.modifiers & blink::WebInputEvent::Modifiers::RightButtonDown)
165 return false;
167 if (state_ != THROTTLER_STATE_MARKED_ESSENTIAL &&
168 event.type == blink::WebInputEvent::MouseUp &&
169 (event.modifiers & blink::WebInputEvent::LeftButtonDown)) {
170 bool was_throttled = IsThrottled();
171 MarkPluginEssential(UNTHROTTLE_METHOD_BY_CLICK);
172 return was_throttled;
175 return IsThrottled();
178 void PluginInstanceThrottlerImpl::EngageThrottle() {
179 if (state_ != THROTTLER_STATE_AWAITING_KEYFRAME)
180 return;
182 state_ = THROTTLER_STATE_PLUGIN_THROTTLED;
183 FOR_EACH_OBSERVER(Observer, observer_list_, OnThrottleStateChange());
186 } // namespace content