Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / ash / wm / video_detector_unittest.cc
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.
4
5 #include "ash/wm/video_detector.h"
6
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"
21
22 namespace ash {
23 namespace test {
24
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) {}
32
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;
40   }
41
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_++;
49   }
50
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_;
60
61   DISALLOW_COPY_AND_ASSIGN(TestVideoDetectorObserver);
62 };
63
64 class VideoDetectorTest : public AshTestBase {
65  public:
66   VideoDetectorTest() {}
67   virtual ~VideoDetectorTest() {}
68
69   virtual void SetUp() OVERRIDE {
70     AshTestBase::SetUp();
71     observer_.reset(new TestVideoDetectorObserver);
72     detector_ = Shell::GetInstance()->video_detector();
73     detector_->AddObserver(observer_.get());
74
75     now_ = base::TimeTicks::Now();
76     detector_->set_now_for_test(now_);
77   }
78
79   virtual void TearDown() OVERRIDE {
80     detector_->RemoveObserver(observer_.get());
81     AshTestBase::TearDown();
82   }
83
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_);
89   }
90
91   VideoDetector* detector_;  // not owned
92
93   scoped_ptr<TestVideoDetectorObserver> observer_;
94
95   base::TimeTicks now_;
96
97  private:
98   DISALLOW_COPY_AND_ASSIGN(VideoDetectorTest);
99 };
100
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));
105
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());
114
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());
124
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());
135
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());
142
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);
150   }
151   EXPECT_EQ(1, observer_->num_invocations());
152
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);
157   }
158   EXPECT_EQ(2, observer_->num_invocations());
159
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);
166   }
167   EXPECT_EQ(2, observer_->num_invocations());
168 }
169
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));
178
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());
184 }
185
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));
190
191   // Reparent the window to the root to make sure that visibility changes aren't
192   // animated.
193   Shell::GetPrimaryRootWindow()->AddChild(window.get());
194
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());
204
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());
214
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());
226 }
227
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));
235
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());
249 }
250
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));
256
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());
275 }
276
277 // Test that the observer receives a true value when the window is fullscreen.
278 TEST_F(VideoDetectorTest, FullscreenWindow) {
279   if (!SupportsMultipleDisplays())
280     return;
281
282   UpdateDisplay("1024x768,1024x768");
283
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());
301
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());
312
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());
324
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());
336 }
337
338 }  // namespace test
339 }  // namespace ash