Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ash / wm / video_detector_unittest.cc
blobf5682e688db12efcc71bdb17eada7d8c094d551f
1 // Copyright (c) 2012 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 "ash/wm/video_detector.h"
7 #include "ash/shell.h"
8 #include "ash/test/ash_test_base.h"
9 #include "ash/wm/window_state.h"
10 #include "ash/wm/wm_event.h"
11 #include "base/compiler_specific.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/time/time.h"
14 #include "third_party/skia/include/core/SkColor.h"
15 #include "ui/aura/client/aura_constants.h"
16 #include "ui/aura/test/test_windows.h"
17 #include "ui/aura/window.h"
18 #include "ui/aura/window_event_dispatcher.h"
19 #include "ui/gfx/rect.h"
20 #include "ui/wm/public/window_types.h"
22 namespace ash {
23 namespace test {
25 // Implementation that just counts the number of times we've been told that a
26 // video is playing.
27 class TestVideoDetectorObserver : public VideoDetectorObserver {
28 public:
29 TestVideoDetectorObserver() : num_invocations_(0),
30 num_fullscreens_(0),
31 num_not_fullscreens_(0) {}
33 int num_invocations() const { return num_invocations_; }
34 int num_fullscreens() const { return num_fullscreens_; }
35 int num_not_fullscreens() const { return num_not_fullscreens_; }
36 void reset_stats() {
37 num_invocations_ = 0;
38 num_fullscreens_ = 0;
39 num_not_fullscreens_ = 0;
42 // VideoDetectorObserver implementation.
43 virtual void OnVideoDetected(bool is_fullscreen) OVERRIDE {
44 num_invocations_++;
45 if (is_fullscreen)
46 num_fullscreens_++;
47 else
48 num_not_fullscreens_++;
51 private:
52 // Number of times that OnVideoDetected() has been called.
53 int num_invocations_;
54 // Number of times that OnVideoDetected() has been called with is_fullscreen
55 // == true.
56 int num_fullscreens_;
57 // Number of times that OnVideoDetected() has been called with is_fullscreen
58 // == false.
59 int num_not_fullscreens_;
61 DISALLOW_COPY_AND_ASSIGN(TestVideoDetectorObserver);
64 class VideoDetectorTest : public AshTestBase {
65 public:
66 VideoDetectorTest() {}
67 virtual ~VideoDetectorTest() {}
69 virtual void SetUp() OVERRIDE {
70 AshTestBase::SetUp();
71 observer_.reset(new TestVideoDetectorObserver);
72 detector_ = Shell::GetInstance()->video_detector();
73 detector_->AddObserver(observer_.get());
75 now_ = base::TimeTicks::Now();
76 detector_->set_now_for_test(now_);
79 virtual void TearDown() OVERRIDE {
80 detector_->RemoveObserver(observer_.get());
81 AshTestBase::TearDown();
84 protected:
85 // Move |detector_|'s idea of the current time forward by |delta|.
86 void AdvanceTime(base::TimeDelta delta) {
87 now_ += delta;
88 detector_->set_now_for_test(now_);
91 VideoDetector* detector_; // not owned
93 scoped_ptr<TestVideoDetectorObserver> observer_;
95 base::TimeTicks now_;
97 private:
98 DISALLOW_COPY_AND_ASSIGN(VideoDetectorTest);
101 TEST_F(VideoDetectorTest, Basic) {
102 gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768));
103 scoped_ptr<aura::Window> window(
104 CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds));
106 // Send enough updates, but make them be too small to trigger detection.
107 gfx::Rect update_region(
108 gfx::Point(),
109 gfx::Size(VideoDetector::kMinUpdateWidth - 1,
110 VideoDetector::kMinUpdateHeight));
111 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
112 detector_->OnDelegatedFrameDamage(window.get(), update_region);
113 EXPECT_EQ(0, observer_->num_invocations());
115 // Send not-quite-enough adaquately-sized updates.
116 observer_->reset_stats();
117 AdvanceTime(base::TimeDelta::FromSeconds(2));
118 update_region.set_size(
119 gfx::Size(VideoDetector::kMinUpdateWidth,
120 VideoDetector::kMinUpdateHeight));
121 for (int i = 0; i < VideoDetector::kMinFramesPerSecond - 1; ++i)
122 detector_->OnDelegatedFrameDamage(window.get(), update_region);
123 EXPECT_EQ(0, observer_->num_invocations());
125 // We should get notified after the next update, but not in response to
126 // additional updates.
127 detector_->OnDelegatedFrameDamage(window.get(), update_region);
128 EXPECT_EQ(1, observer_->num_invocations());
129 EXPECT_EQ(0, observer_->num_fullscreens());
130 EXPECT_EQ(1, observer_->num_not_fullscreens());
131 detector_->OnDelegatedFrameDamage(window.get(), update_region);
132 EXPECT_EQ(1, observer_->num_invocations());
133 EXPECT_EQ(0, observer_->num_fullscreens());
134 EXPECT_EQ(1, observer_->num_not_fullscreens());
136 // Spread out the frames over a longer period of time, but send enough
137 // over a one-second window that the observer should be notified.
138 observer_->reset_stats();
139 AdvanceTime(base::TimeDelta::FromSeconds(2));
140 detector_->OnDelegatedFrameDamage(window.get(), update_region);
141 EXPECT_EQ(0, observer_->num_invocations());
143 AdvanceTime(base::TimeDelta::FromMilliseconds(500));
144 const int kNumFrames = VideoDetector::kMinFramesPerSecond + 1;
145 base::TimeDelta kInterval =
146 base::TimeDelta::FromMilliseconds(1000 / kNumFrames);
147 for (int i = 0; i < kNumFrames; ++i) {
148 AdvanceTime(kInterval);
149 detector_->OnDelegatedFrameDamage(window.get(), update_region);
151 EXPECT_EQ(1, observer_->num_invocations());
153 // Keep going and check that the observer is notified again.
154 for (int i = 0; i < kNumFrames; ++i) {
155 AdvanceTime(kInterval);
156 detector_->OnDelegatedFrameDamage(window.get(), update_region);
158 EXPECT_EQ(2, observer_->num_invocations());
160 // Send updates at a slower rate and check that the observer isn't notified.
161 base::TimeDelta kSlowInterval = base::TimeDelta::FromMilliseconds(
162 1000 / (VideoDetector::kMinFramesPerSecond - 2));
163 for (int i = 0; i < kNumFrames; ++i) {
164 AdvanceTime(kSlowInterval);
165 detector_->OnDelegatedFrameDamage(window.get(), update_region);
167 EXPECT_EQ(2, observer_->num_invocations());
170 TEST_F(VideoDetectorTest, Shutdown) {
171 gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768));
172 scoped_ptr<aura::Window> window(
173 CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds));
174 gfx::Rect update_region(
175 gfx::Point(),
176 gfx::Size(VideoDetector::kMinUpdateWidth,
177 VideoDetector::kMinUpdateHeight));
179 // It should not detect video during the shutdown.
180 Shell::GetInstance()->OnAppTerminating();
181 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
182 detector_->OnDelegatedFrameDamage(window.get(), update_region);
183 EXPECT_EQ(0, observer_->num_invocations());
186 TEST_F(VideoDetectorTest, WindowNotVisible) {
187 gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768));
188 scoped_ptr<aura::Window> window(
189 CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds));
191 // Reparent the window to the root to make sure that visibility changes aren't
192 // animated.
193 Shell::GetPrimaryRootWindow()->AddChild(window.get());
195 // We shouldn't report video that's played in a hidden window.
196 window->Hide();
197 gfx::Rect update_region(
198 gfx::Point(),
199 gfx::Size(VideoDetector::kMinUpdateWidth,
200 VideoDetector::kMinUpdateHeight));
201 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
202 detector_->OnDelegatedFrameDamage(window.get(), update_region);
203 EXPECT_EQ(0, observer_->num_invocations());
205 // Make the window visible and send more updates.
206 observer_->reset_stats();
207 AdvanceTime(base::TimeDelta::FromSeconds(2));
208 window->Show();
209 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
210 detector_->OnDelegatedFrameDamage(window.get(), update_region);
211 EXPECT_EQ(1, observer_->num_invocations());
212 EXPECT_EQ(0, observer_->num_fullscreens());
213 EXPECT_EQ(1, observer_->num_not_fullscreens());
215 // We also shouldn't report video in a window that's fully offscreen.
216 observer_->reset_stats();
217 AdvanceTime(base::TimeDelta::FromSeconds(2));
218 gfx::Rect offscreen_bounds(
219 gfx::Point(Shell::GetPrimaryRootWindow()->bounds().width(), 0),
220 window_bounds.size());
221 window->SetBounds(offscreen_bounds);
222 ASSERT_EQ(offscreen_bounds, window->bounds());
223 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
224 detector_->OnDelegatedFrameDamage(window.get(), update_region);
225 EXPECT_EQ(0, observer_->num_invocations());
228 TEST_F(VideoDetectorTest, MultipleWindows) {
229 // Create two windows.
230 gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768));
231 scoped_ptr<aura::Window> window1(
232 CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds));
233 scoped_ptr<aura::Window> window2(
234 CreateTestWindowInShell(SK_ColorBLUE, 23456, window_bounds));
236 // Even if there's video playing in both, the observer should only receive a
237 // single notification.
238 gfx::Rect update_region(
239 gfx::Point(),
240 gfx::Size(VideoDetector::kMinUpdateWidth,
241 VideoDetector::kMinUpdateHeight));
242 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
243 detector_->OnDelegatedFrameDamage(window1.get(), update_region);
244 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
245 detector_->OnDelegatedFrameDamage(window2.get(), update_region);
246 EXPECT_EQ(1, observer_->num_invocations());
247 EXPECT_EQ(0, observer_->num_fullscreens());
248 EXPECT_EQ(1, observer_->num_not_fullscreens());
251 // Test that the observer receives repeated notifications.
252 TEST_F(VideoDetectorTest, RepeatedNotifications) {
253 gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768));
254 scoped_ptr<aura::Window> window(
255 CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds));
257 gfx::Rect update_region(
258 gfx::Point(),
259 gfx::Size(VideoDetector::kMinUpdateWidth,
260 VideoDetector::kMinUpdateHeight));
261 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
262 detector_->OnDelegatedFrameDamage(window.get(), update_region);
263 EXPECT_EQ(1, observer_->num_invocations());
264 EXPECT_EQ(0, observer_->num_fullscreens());
265 EXPECT_EQ(1, observer_->num_not_fullscreens());
266 // Let enough time pass that a second notification should be sent.
267 observer_->reset_stats();
268 AdvanceTime(base::TimeDelta::FromSeconds(
269 static_cast<int64>(VideoDetector::kNotifyIntervalSec + 1)));
270 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
271 detector_->OnDelegatedFrameDamage(window.get(), update_region);
272 EXPECT_EQ(1, observer_->num_invocations());
273 EXPECT_EQ(0, observer_->num_fullscreens());
274 EXPECT_EQ(1, observer_->num_not_fullscreens());
277 // Test that the observer receives a true value when the window is fullscreen.
278 TEST_F(VideoDetectorTest, FullscreenWindow) {
279 if (!SupportsMultipleDisplays())
280 return;
282 UpdateDisplay("1024x768,1024x768");
284 const gfx::Rect kLeftBounds(gfx::Point(), gfx::Size(1024, 768));
285 scoped_ptr<aura::Window> window(
286 CreateTestWindowInShell(SK_ColorRED, 12345, kLeftBounds));
287 wm::WindowState* window_state = wm::GetWindowState(window.get());
288 const wm::WMEvent toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN);
289 window_state->OnWMEvent(&toggle_fullscreen_event);
290 ASSERT_TRUE(window_state->IsFullscreen());
291 window->Focus();
292 const gfx::Rect kUpdateRegion(
293 gfx::Point(),
294 gfx::Size(VideoDetector::kMinUpdateWidth,
295 VideoDetector::kMinUpdateHeight));
296 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
297 detector_->OnDelegatedFrameDamage(window.get(), kUpdateRegion);
298 EXPECT_EQ(1, observer_->num_invocations());
299 EXPECT_EQ(1, observer_->num_fullscreens());
300 EXPECT_EQ(0, observer_->num_not_fullscreens());
302 // Make the first window non-fullscreen and open a second fullscreen window on
303 // a different desktop.
304 window_state->OnWMEvent(&toggle_fullscreen_event);
305 ASSERT_FALSE(window_state->IsFullscreen());
306 const gfx::Rect kRightBounds(gfx::Point(1024, 0), gfx::Size(1024, 768));
307 scoped_ptr<aura::Window> other_window(
308 CreateTestWindowInShell(SK_ColorBLUE, 6789, kRightBounds));
309 wm::WindowState* other_window_state = wm::GetWindowState(other_window.get());
310 other_window_state->OnWMEvent(&toggle_fullscreen_event);
311 ASSERT_TRUE(other_window_state->IsFullscreen());
313 // When video is detected in the first (now non-fullscreen) window, fullscreen
314 // video should still be reported due to the second window being fullscreen.
315 // This avoids situations where non-fullscreen video could be reported when
316 // multiple videos are playing in fullscreen and non-fullscreen windows.
317 observer_->reset_stats();
318 AdvanceTime(base::TimeDelta::FromSeconds(2));
319 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
320 detector_->OnDelegatedFrameDamage(window.get(), kUpdateRegion);
321 EXPECT_EQ(1, observer_->num_invocations());
322 EXPECT_EQ(1, observer_->num_fullscreens());
323 EXPECT_EQ(0, observer_->num_not_fullscreens());
325 // Make the second window non-fullscreen and check that the next video report
326 // is non-fullscreen.
327 other_window_state->OnWMEvent(&toggle_fullscreen_event);
328 ASSERT_FALSE(other_window_state->IsFullscreen());
329 observer_->reset_stats();
330 AdvanceTime(base::TimeDelta::FromSeconds(2));
331 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
332 detector_->OnDelegatedFrameDamage(window.get(), kUpdateRegion);
333 EXPECT_EQ(1, observer_->num_invocations());
334 EXPECT_EQ(0, observer_->num_fullscreens());
335 EXPECT_EQ(1, observer_->num_not_fullscreens());
338 } // namespace test
339 } // namespace ash