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.
6 #include "base/command_line.h"
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "content/public/common/content_switches.h"
11 #include "content/public/renderer/render_frame.h"
12 #include "content/renderer/pepper/plugin_instance_throttler_impl.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "third_party/WebKit/public/web/WebInputEvent.h"
16 #include "third_party/WebKit/public/web/WebPluginParams.h"
17 #include "ui/gfx/canvas.h"
20 using testing::Return
;
26 class PluginInstanceThrottlerImplTest
27 : public testing::Test
,
28 public PluginInstanceThrottler::Observer
{
30 const int kMaximumFramesToExamine
=
31 PluginInstanceThrottlerImpl::kMaximumFramesToExamine
;
33 PluginInstanceThrottlerImplTest() : change_callback_calls_(0) {}
34 ~PluginInstanceThrottlerImplTest() override
{
35 throttler_
->RemoveObserver(this);
38 void SetUp() override
{
39 throttler_
.reset(new PluginInstanceThrottlerImpl
);
40 throttler_
->Initialize(nullptr, GURL("http://example.com"),
41 "Shockwave Flash", gfx::Size(100, 100));
42 throttler_
->AddObserver(this);
45 PluginInstanceThrottlerImpl
* throttler() {
46 DCHECK(throttler_
.get());
47 return throttler_
.get();
50 void DisablePowerSaverByRetroactiveWhitelist() {
51 throttler()->MarkPluginEssential(
52 PluginInstanceThrottlerImpl::UNTHROTTLE_METHOD_BY_WHITELIST
);
55 int change_callback_calls() { return change_callback_calls_
; }
57 void EngageThrottle() { throttler_
->EngageThrottle(); }
59 void SendEventAndTest(blink::WebInputEvent::Type event_type
,
61 bool expect_throttled
,
62 int expect_change_callback_count
) {
63 blink::WebMouseEvent event
;
64 event
.type
= event_type
;
65 event
.modifiers
= blink::WebInputEvent::Modifiers::LeftButtonDown
;
66 EXPECT_EQ(expect_consumed
, throttler()->ConsumeInputEvent(event
));
67 EXPECT_EQ(expect_throttled
, throttler()->IsThrottled());
68 EXPECT_EQ(expect_change_callback_count
, change_callback_calls());
72 // PluginInstanceThrottlerImpl::Observer
73 void OnThrottleStateChange() override
{ ++change_callback_calls_
; }
75 scoped_ptr
<PluginInstanceThrottlerImpl
> throttler_
;
77 int change_callback_calls_
;
79 base::MessageLoop loop_
;
82 TEST_F(PluginInstanceThrottlerImplTest
, ThrottleAndUnthrottleByClick
) {
83 EXPECT_FALSE(throttler()->IsThrottled());
84 EXPECT_EQ(0, change_callback_calls());
87 EXPECT_TRUE(throttler()->IsThrottled());
88 EXPECT_EQ(1, change_callback_calls());
90 // MouseUp while throttled should be consumed and disengage throttling.
91 SendEventAndTest(blink::WebInputEvent::Type::MouseUp
, true, false, 2);
94 TEST_F(PluginInstanceThrottlerImplTest
, ThrottleByKeyframe
) {
95 EXPECT_FALSE(throttler()->IsThrottled());
96 EXPECT_EQ(0, change_callback_calls());
98 SkBitmap boring_bitmap
;
99 gfx::Canvas
canvas(gfx::Size(20, 10), 1.0f
, true);
100 canvas
.FillRect(gfx::Rect(20, 10), SK_ColorBLACK
);
101 canvas
.FillRect(gfx::Rect(10, 10), SK_ColorWHITE
);
102 SkBitmap interesting_bitmap
=
103 skia::GetTopDevice(*canvas
.sk_canvas())->accessBitmap(false);
105 // Don't throttle for a boring frame.
106 throttler()->OnImageFlush(&boring_bitmap
);
107 EXPECT_FALSE(throttler()->IsThrottled());
108 EXPECT_EQ(0, change_callback_calls());
110 // Don't throttle for non-consecutive interesting frames.
111 throttler()->OnImageFlush(&interesting_bitmap
);
112 throttler()->OnImageFlush(&boring_bitmap
);
113 throttler()->OnImageFlush(&interesting_bitmap
);
114 throttler()->OnImageFlush(&boring_bitmap
);
115 throttler()->OnImageFlush(&interesting_bitmap
);
116 throttler()->OnImageFlush(&boring_bitmap
);
117 EXPECT_FALSE(throttler()->IsThrottled());
118 EXPECT_EQ(0, change_callback_calls());
120 // Throttle after consecutive interesting frames.
121 throttler()->OnImageFlush(&interesting_bitmap
);
122 throttler()->OnImageFlush(&interesting_bitmap
);
123 throttler()->OnImageFlush(&interesting_bitmap
);
124 throttler()->OnImageFlush(&interesting_bitmap
);
125 EXPECT_TRUE(throttler()->IsThrottled());
126 EXPECT_EQ(1, change_callback_calls());
129 TEST_F(PluginInstanceThrottlerImplTest
, MaximumKeyframesAnalyzed
) {
130 EXPECT_FALSE(throttler()->IsThrottled());
131 EXPECT_EQ(0, change_callback_calls());
133 SkBitmap boring_bitmap
;
135 // Throttle after tons of boring bitmaps.
136 for (int i
= 0; i
< kMaximumFramesToExamine
; ++i
) {
137 throttler()->OnImageFlush(&boring_bitmap
);
139 EXPECT_TRUE(throttler()->IsThrottled());
140 EXPECT_EQ(1, change_callback_calls());
142 TEST_F(PluginInstanceThrottlerImplTest
, IgnoreThrottlingAfterMouseUp
) {
143 EXPECT_FALSE(throttler()->IsThrottled());
144 EXPECT_EQ(0, change_callback_calls());
146 // MouseUp before throttling engaged should not be consumed, but should
147 // prevent subsequent throttling from engaging.
148 SendEventAndTest(blink::WebInputEvent::Type::MouseUp
, false, false, 0);
151 EXPECT_FALSE(throttler()->IsThrottled());
152 EXPECT_EQ(0, change_callback_calls());
155 TEST_F(PluginInstanceThrottlerImplTest
, FastWhitelisting
) {
156 EXPECT_FALSE(throttler()->IsThrottled());
157 EXPECT_EQ(0, change_callback_calls());
159 DisablePowerSaverByRetroactiveWhitelist();
162 EXPECT_FALSE(throttler()->IsThrottled());
163 EXPECT_EQ(0, change_callback_calls());
166 TEST_F(PluginInstanceThrottlerImplTest
, SlowWhitelisting
) {
167 EXPECT_FALSE(throttler()->IsThrottled());
168 EXPECT_EQ(0, change_callback_calls());
171 EXPECT_TRUE(throttler()->IsThrottled());
172 EXPECT_EQ(1, change_callback_calls());
174 DisablePowerSaverByRetroactiveWhitelist();
175 EXPECT_FALSE(throttler()->IsThrottled());
176 EXPECT_EQ(2, change_callback_calls());
179 TEST_F(PluginInstanceThrottlerImplTest
, EventConsumption
) {
180 EXPECT_FALSE(throttler()->IsThrottled());
181 EXPECT_EQ(0, change_callback_calls());
184 EXPECT_TRUE(throttler()->IsThrottled());
185 EXPECT_EQ(1, change_callback_calls());
187 // Consume but don't unthrottle on a variety of other events.
188 SendEventAndTest(blink::WebInputEvent::Type::MouseDown
, true, true, 1);
189 SendEventAndTest(blink::WebInputEvent::Type::MouseWheel
, true, true, 1);
190 SendEventAndTest(blink::WebInputEvent::Type::MouseMove
, true, true, 1);
191 SendEventAndTest(blink::WebInputEvent::Type::KeyDown
, true, true, 1);
192 SendEventAndTest(blink::WebInputEvent::Type::KeyUp
, true, true, 1);
194 // Consume and unthrottle on MouseUp
195 SendEventAndTest(blink::WebInputEvent::Type::MouseUp
, true, false, 2);
197 // Don't consume events after unthrottle.
198 SendEventAndTest(blink::WebInputEvent::Type::MouseDown
, false, false, 2);
199 SendEventAndTest(blink::WebInputEvent::Type::MouseWheel
, false, false, 2);
200 SendEventAndTest(blink::WebInputEvent::Type::MouseMove
, false, false, 2);
201 SendEventAndTest(blink::WebInputEvent::Type::KeyDown
, false, false, 2);
202 SendEventAndTest(blink::WebInputEvent::Type::KeyUp
, false, false, 2);
204 // Subsequent MouseUps should also not be consumed.
205 SendEventAndTest(blink::WebInputEvent::Type::MouseUp
, false, false, 2);
208 TEST_F(PluginInstanceThrottlerImplTest
, ThrottleOnLeftClickOnly
) {
209 EXPECT_FALSE(throttler()->IsThrottled());
210 EXPECT_EQ(0, change_callback_calls());
213 EXPECT_TRUE(throttler()->IsThrottled());
214 EXPECT_EQ(1, change_callback_calls());
216 blink::WebMouseEvent event
;
217 event
.type
= blink::WebInputEvent::Type::MouseUp
;
219 event
.modifiers
= blink::WebInputEvent::Modifiers::RightButtonDown
;
220 EXPECT_FALSE(throttler()->ConsumeInputEvent(event
));
221 EXPECT_TRUE(throttler()->IsThrottled());
223 event
.modifiers
= blink::WebInputEvent::Modifiers::MiddleButtonDown
;
224 EXPECT_TRUE(throttler()->ConsumeInputEvent(event
));
225 EXPECT_TRUE(throttler()->IsThrottled());
227 event
.modifiers
= blink::WebInputEvent::Modifiers::LeftButtonDown
;
228 EXPECT_TRUE(throttler()->ConsumeInputEvent(event
));
229 EXPECT_FALSE(throttler()->IsThrottled());
232 } // namespace content