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"
8 #include "ash/test/ash_test_base.h"
9 #include "base/compiler_specific.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/time.h"
12 #include "third_party/skia/include/core/SkColor.h"
13 #include "ui/aura/client/window_types.h"
14 #include "ui/aura/root_window.h"
15 #include "ui/aura/test/test_windows.h"
16 #include "ui/aura/window.h"
17 #include "ui/gfx/rect.h"
22 // Implementation that just counts the number of times we've been told that a
24 class TestVideoDetectorObserver
: public VideoDetectorObserver
{
26 TestVideoDetectorObserver() : num_invocations_(0) {}
28 int num_invocations() const { return num_invocations_
; }
29 void reset_stats() { num_invocations_
= 0; }
31 // VideoDetectorObserver implementation.
32 virtual void OnVideoDetected() OVERRIDE
{ num_invocations_
++; }
35 // Number of times that OnVideoDetected() has been called.
38 DISALLOW_COPY_AND_ASSIGN(TestVideoDetectorObserver
);
41 class VideoDetectorTest
: public AshTestBase
{
43 VideoDetectorTest() {}
44 virtual ~VideoDetectorTest() {}
46 void SetUp() OVERRIDE
{
48 observer_
.reset(new TestVideoDetectorObserver
);
49 detector_
= Shell::GetInstance()->video_detector();
50 detector_
->AddObserver(observer_
.get());
52 now_
= base::TimeTicks::Now();
53 detector_
->set_now_for_test(now_
);
57 // Move |detector_|'s idea of the current time forward by |delta|.
58 void AdvanceTime(base::TimeDelta delta
) {
60 detector_
->set_now_for_test(now_
);
63 VideoDetector
* detector_
; // not owned
65 scoped_ptr
<TestVideoDetectorObserver
> observer_
;
70 DISALLOW_COPY_AND_ASSIGN(VideoDetectorTest
);
73 TEST_F(VideoDetectorTest
, Basic
) {
74 gfx::Rect
window_bounds(gfx::Point(), gfx::Size(1024, 768));
75 scoped_ptr
<aura::Window
> window(
76 aura::test::CreateTestWindow(SK_ColorRED
, 12345, window_bounds
, NULL
));
78 // Send enough updates, but make them be too small to trigger detection.
79 gfx::Rect
update_region(
81 gfx::Size(VideoDetector::kMinUpdateWidth
- 1,
82 VideoDetector::kMinUpdateHeight
));
83 for (int i
= 0; i
< VideoDetector::kMinFramesPerSecond
; ++i
)
84 detector_
->OnWindowPaintScheduled(window
.get(), update_region
);
85 EXPECT_EQ(0, observer_
->num_invocations());
87 // Send not-quite-enough adaquately-sized updates.
88 observer_
->reset_stats();
89 AdvanceTime(base::TimeDelta::FromSeconds(2));
90 update_region
.set_size(
91 gfx::Size(VideoDetector::kMinUpdateWidth
,
92 VideoDetector::kMinUpdateHeight
));
93 for (int i
= 0; i
< VideoDetector::kMinFramesPerSecond
- 1; ++i
)
94 detector_
->OnWindowPaintScheduled(window
.get(), update_region
);
95 EXPECT_EQ(0, observer_
->num_invocations());
97 // We should get notified after the next update, but not in response to
98 // additional updates.
99 detector_
->OnWindowPaintScheduled(window
.get(), update_region
);
100 EXPECT_EQ(1, observer_
->num_invocations());
101 detector_
->OnWindowPaintScheduled(window
.get(), update_region
);
102 EXPECT_EQ(1, observer_
->num_invocations());
104 // Spread out the frames over two seconds; we shouldn't detect video.
105 observer_
->reset_stats();
106 AdvanceTime(base::TimeDelta::FromSeconds(2));
107 for (int i
= 0; i
< VideoDetector::kMinFramesPerSecond
- 1; ++i
)
108 detector_
->OnWindowPaintScheduled(window
.get(), update_region
);
109 AdvanceTime(base::TimeDelta::FromSeconds(1));
110 for (int i
= 0; i
< VideoDetector::kMinFramesPerSecond
- 1; ++i
)
111 detector_
->OnWindowPaintScheduled(window
.get(), update_region
);
112 EXPECT_EQ(0, observer_
->num_invocations());
115 TEST_F(VideoDetectorTest
, WindowNotVisible
) {
116 gfx::Rect
window_bounds(gfx::Point(), gfx::Size(1024, 768));
117 scoped_ptr
<aura::Window
> window(
118 aura::test::CreateTestWindow(SK_ColorRED
, 12345, window_bounds
, NULL
));
120 // Reparent the window to the root to make sure that visibility changes aren't
122 Shell::GetRootWindow()->AddChild(window
.get());
124 // We shouldn't report video that's played in a hidden window.
126 gfx::Rect
update_region(
128 gfx::Size(VideoDetector::kMinUpdateWidth
,
129 VideoDetector::kMinUpdateHeight
));
130 for (int i
= 0; i
< VideoDetector::kMinFramesPerSecond
; ++i
)
131 detector_
->OnWindowPaintScheduled(window
.get(), update_region
);
132 EXPECT_EQ(0, observer_
->num_invocations());
134 // Make the window visible and send more updates.
135 observer_
->reset_stats();
136 AdvanceTime(base::TimeDelta::FromSeconds(2));
138 for (int i
= 0; i
< VideoDetector::kMinFramesPerSecond
; ++i
)
139 detector_
->OnWindowPaintScheduled(window
.get(), update_region
);
140 EXPECT_EQ(1, observer_
->num_invocations());
142 // We also shouldn't report video in a window that's fully offscreen.
143 observer_
->reset_stats();
144 AdvanceTime(base::TimeDelta::FromSeconds(2));
145 gfx::Rect
offscreen_bounds(
146 gfx::Point(Shell::GetRootWindow()->bounds().width(), 0),
147 window_bounds
.size());
148 window
->SetBounds(offscreen_bounds
);
149 ASSERT_EQ(offscreen_bounds
, window
->bounds());
150 for (int i
= 0; i
< VideoDetector::kMinFramesPerSecond
; ++i
)
151 detector_
->OnWindowPaintScheduled(window
.get(), update_region
);
152 EXPECT_EQ(0, observer_
->num_invocations());
155 TEST_F(VideoDetectorTest
, MultipleWindows
) {
156 // Create two windows.
157 gfx::Rect
window_bounds(gfx::Point(), gfx::Size(1024, 768));
158 scoped_ptr
<aura::Window
> window1(
159 aura::test::CreateTestWindow(SK_ColorRED
, 12345, window_bounds
, NULL
));
160 scoped_ptr
<aura::Window
> window2(
161 aura::test::CreateTestWindow(SK_ColorBLUE
, 23456, window_bounds
, NULL
));
163 // Even if there's video playing in both, the observer should only receive a
164 // single notification.
165 gfx::Rect
update_region(
167 gfx::Size(VideoDetector::kMinUpdateWidth
,
168 VideoDetector::kMinUpdateHeight
));
169 for (int i
= 0; i
< VideoDetector::kMinFramesPerSecond
; ++i
)
170 detector_
->OnWindowPaintScheduled(window1
.get(), update_region
);
171 for (int i
= 0; i
< VideoDetector::kMinFramesPerSecond
; ++i
)
172 detector_
->OnWindowPaintScheduled(window2
.get(), update_region
);
173 EXPECT_EQ(1, observer_
->num_invocations());
176 // Test that the observer receives repeated notifications.
177 TEST_F(VideoDetectorTest
, RepeatedNotifications
) {
178 gfx::Rect
window_bounds(gfx::Point(), gfx::Size(1024, 768));
179 scoped_ptr
<aura::Window
> window(
180 aura::test::CreateTestWindow(SK_ColorRED
, 12345, window_bounds
, NULL
));
182 gfx::Rect
update_region(
184 gfx::Size(VideoDetector::kMinUpdateWidth
,
185 VideoDetector::kMinUpdateHeight
));
186 for (int i
= 0; i
< VideoDetector::kMinFramesPerSecond
; ++i
)
187 detector_
->OnWindowPaintScheduled(window
.get(), update_region
);
188 EXPECT_EQ(1, observer_
->num_invocations());
190 // Let enough time pass that a second notification should be sent.
191 observer_
->reset_stats();
192 AdvanceTime(base::TimeDelta::FromSeconds(
193 static_cast<int64
>(VideoDetector::kNotifyIntervalSec
+ 1)));
194 for (int i
= 0; i
< VideoDetector::kMinFramesPerSecond
; ++i
)
195 detector_
->OnWindowPaintScheduled(window
.get(), update_region
);
196 EXPECT_EQ(1, observer_
->num_invocations());