- add sources.
[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_util.h"
10 #include "base/compiler_specific.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/time/time.h"
13 #include "third_party/skia/include/core/SkColor.h"
14 #include "ui/aura/client/aura_constants.h"
15 #include "ui/aura/client/window_types.h"
16 #include "ui/aura/root_window.h"
17 #include "ui/aura/test/test_windows.h"
18 #include "ui/aura/window.h"
19 #include "ui/gfx/rect.h"
20
21 namespace ash {
22 namespace test {
23
24 // Implementation that just counts the number of times we've been told that a
25 // video is playing.
26 class TestVideoDetectorObserver : public VideoDetectorObserver {
27  public:
28   TestVideoDetectorObserver() : num_invocations_(0),
29                                 num_fullscreens_(0),
30                                 num_not_fullscreens_(0) {}
31
32   int num_invocations() const { return num_invocations_; }
33   int num_fullscreens() const { return num_fullscreens_; }
34   int num_not_fullscreens() const { return num_not_fullscreens_; }
35   void reset_stats() {
36     num_invocations_ = 0;
37     num_fullscreens_ = 0;
38     num_not_fullscreens_ = 0;
39   }
40
41   // VideoDetectorObserver implementation.
42   virtual void OnVideoDetected(bool is_fullscreen) OVERRIDE {
43     num_invocations_++;
44     if (is_fullscreen)
45       num_fullscreens_++;
46     else
47       num_not_fullscreens_++;
48   }
49
50  private:
51   // Number of times that OnVideoDetected() has been called.
52   int num_invocations_;
53   // Number of times that OnVideoDetected() has been called with is_fullscreen
54   // == true.
55   int num_fullscreens_;
56   // Number of times that OnVideoDetected() has been called with is_fullscreen
57   // == false.
58   int num_not_fullscreens_;
59
60   DISALLOW_COPY_AND_ASSIGN(TestVideoDetectorObserver);
61 };
62
63 class VideoDetectorTest : public AshTestBase {
64  public:
65   VideoDetectorTest() {}
66   virtual ~VideoDetectorTest() {}
67
68   virtual void SetUp() OVERRIDE {
69     AshTestBase::SetUp();
70     observer_.reset(new TestVideoDetectorObserver);
71     detector_ = Shell::GetInstance()->video_detector();
72     detector_->AddObserver(observer_.get());
73
74     now_ = base::TimeTicks::Now();
75     detector_->set_now_for_test(now_);
76   }
77
78   virtual void TearDown() OVERRIDE {
79     detector_->RemoveObserver(observer_.get());
80     AshTestBase::TearDown();
81   }
82
83  protected:
84   // Move |detector_|'s idea of the current time forward by |delta|.
85   void AdvanceTime(base::TimeDelta delta) {
86     now_ += delta;
87     detector_->set_now_for_test(now_);
88   }
89
90   VideoDetector* detector_;  // not owned
91
92   scoped_ptr<TestVideoDetectorObserver> observer_;
93
94   base::TimeTicks now_;
95
96  private:
97   DISALLOW_COPY_AND_ASSIGN(VideoDetectorTest);
98 };
99
100 TEST_F(VideoDetectorTest, Basic) {
101   gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768));
102   scoped_ptr<aura::Window> window(
103       CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds));
104
105   // Send enough updates, but make them be too small to trigger detection.
106   gfx::Rect update_region(
107       gfx::Point(),
108       gfx::Size(VideoDetector::kMinUpdateWidth - 1,
109                 VideoDetector::kMinUpdateHeight));
110   for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
111     detector_->OnWindowPaintScheduled(window.get(), update_region);
112   EXPECT_EQ(0, observer_->num_invocations());
113
114   // Send not-quite-enough adaquately-sized updates.
115   observer_->reset_stats();
116   AdvanceTime(base::TimeDelta::FromSeconds(2));
117   update_region.set_size(
118       gfx::Size(VideoDetector::kMinUpdateWidth,
119                 VideoDetector::kMinUpdateHeight));
120   for (int i = 0; i < VideoDetector::kMinFramesPerSecond - 1; ++i)
121     detector_->OnWindowPaintScheduled(window.get(), update_region);
122   EXPECT_EQ(0, observer_->num_invocations());
123
124   // We should get notified after the next update, but not in response to
125   // additional updates.
126   detector_->OnWindowPaintScheduled(window.get(), update_region);
127   EXPECT_EQ(1, observer_->num_invocations());
128   EXPECT_EQ(0, observer_->num_fullscreens());
129   EXPECT_EQ(1, observer_->num_not_fullscreens());
130   detector_->OnWindowPaintScheduled(window.get(), update_region);
131   EXPECT_EQ(1, observer_->num_invocations());
132   EXPECT_EQ(0, observer_->num_fullscreens());
133   EXPECT_EQ(1, observer_->num_not_fullscreens());
134
135   // Spread out the frames over a longer period of time, but send enough
136   // over a one-second window that the observer should be notified.
137   observer_->reset_stats();
138   AdvanceTime(base::TimeDelta::FromSeconds(2));
139   detector_->OnWindowPaintScheduled(window.get(), update_region);
140   EXPECT_EQ(0, observer_->num_invocations());
141
142   AdvanceTime(base::TimeDelta::FromMilliseconds(500));
143   const int kNumFrames = VideoDetector::kMinFramesPerSecond + 1;
144   base::TimeDelta kInterval =
145       base::TimeDelta::FromMilliseconds(1000 / kNumFrames);
146   for (int i = 0; i < kNumFrames; ++i) {
147     AdvanceTime(kInterval);
148     detector_->OnWindowPaintScheduled(window.get(), update_region);
149   }
150   EXPECT_EQ(1, observer_->num_invocations());
151
152   // Keep going and check that the observer is notified again.
153   for (int i = 0; i < kNumFrames; ++i) {
154     AdvanceTime(kInterval);
155     detector_->OnWindowPaintScheduled(window.get(), update_region);
156   }
157   EXPECT_EQ(2, observer_->num_invocations());
158
159   // Send updates at a slower rate and check that the observer isn't notified.
160   base::TimeDelta kSlowInterval = base::TimeDelta::FromMilliseconds(
161       1000 / (VideoDetector::kMinFramesPerSecond - 2));
162   for (int i = 0; i < kNumFrames; ++i) {
163     AdvanceTime(kSlowInterval);
164     detector_->OnWindowPaintScheduled(window.get(), update_region);
165   }
166   EXPECT_EQ(2, observer_->num_invocations());
167 }
168
169 TEST_F(VideoDetectorTest, Shutdown) {
170   gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768));
171   scoped_ptr<aura::Window> window(
172       CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds));
173   gfx::Rect update_region(
174       gfx::Point(),
175       gfx::Size(VideoDetector::kMinUpdateWidth,
176                 VideoDetector::kMinUpdateHeight));
177
178   // It should not detect video during the shutdown.
179   Shell::GetInstance()->OnAppTerminating();
180   for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
181     detector_->OnWindowPaintScheduled(window.get(), update_region);
182   EXPECT_EQ(0, observer_->num_invocations());
183 }
184
185 TEST_F(VideoDetectorTest, WindowNotVisible) {
186   gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768));
187   scoped_ptr<aura::Window> window(
188       CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds));
189
190   // Reparent the window to the root to make sure that visibility changes aren't
191   // animated.
192   Shell::GetPrimaryRootWindow()->AddChild(window.get());
193
194   // We shouldn't report video that's played in a hidden window.
195   window->Hide();
196   gfx::Rect update_region(
197       gfx::Point(),
198       gfx::Size(VideoDetector::kMinUpdateWidth,
199                 VideoDetector::kMinUpdateHeight));
200   for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
201     detector_->OnWindowPaintScheduled(window.get(), update_region);
202   EXPECT_EQ(0, observer_->num_invocations());
203
204   // Make the window visible and send more updates.
205   observer_->reset_stats();
206   AdvanceTime(base::TimeDelta::FromSeconds(2));
207   window->Show();
208   for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
209     detector_->OnWindowPaintScheduled(window.get(), update_region);
210   EXPECT_EQ(1, observer_->num_invocations());
211   EXPECT_EQ(0, observer_->num_fullscreens());
212   EXPECT_EQ(1, observer_->num_not_fullscreens());
213
214   // We also shouldn't report video in a window that's fully offscreen.
215   observer_->reset_stats();
216   AdvanceTime(base::TimeDelta::FromSeconds(2));
217   gfx::Rect offscreen_bounds(
218       gfx::Point(Shell::GetPrimaryRootWindow()->bounds().width(), 0),
219       window_bounds.size());
220   window->SetBounds(offscreen_bounds);
221   ASSERT_EQ(offscreen_bounds, window->bounds());
222   for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
223     detector_->OnWindowPaintScheduled(window.get(), update_region);
224   EXPECT_EQ(0, observer_->num_invocations());
225 }
226
227 TEST_F(VideoDetectorTest, MultipleWindows) {
228   // Create two windows.
229   gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768));
230   scoped_ptr<aura::Window> window1(
231       CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds));
232   scoped_ptr<aura::Window> window2(
233       CreateTestWindowInShell(SK_ColorBLUE, 23456, window_bounds));
234
235   // Even if there's video playing in both, the observer should only receive a
236   // single notification.
237   gfx::Rect update_region(
238       gfx::Point(),
239       gfx::Size(VideoDetector::kMinUpdateWidth,
240                 VideoDetector::kMinUpdateHeight));
241   for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
242     detector_->OnWindowPaintScheduled(window1.get(), update_region);
243   for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
244     detector_->OnWindowPaintScheduled(window2.get(), update_region);
245   EXPECT_EQ(1, observer_->num_invocations());
246   EXPECT_EQ(0, observer_->num_fullscreens());
247   EXPECT_EQ(1, observer_->num_not_fullscreens());
248 }
249
250 // Test that the observer receives repeated notifications.
251 TEST_F(VideoDetectorTest, RepeatedNotifications) {
252   gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768));
253   scoped_ptr<aura::Window> window(
254       CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds));
255
256   gfx::Rect update_region(
257       gfx::Point(),
258       gfx::Size(VideoDetector::kMinUpdateWidth,
259                 VideoDetector::kMinUpdateHeight));
260   for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
261     detector_->OnWindowPaintScheduled(window.get(), update_region);
262   EXPECT_EQ(1, observer_->num_invocations());
263   EXPECT_EQ(0, observer_->num_fullscreens());
264   EXPECT_EQ(1, observer_->num_not_fullscreens());
265   // Let enough time pass that a second notification should be sent.
266   observer_->reset_stats();
267   AdvanceTime(base::TimeDelta::FromSeconds(
268       static_cast<int64>(VideoDetector::kNotifyIntervalSec + 1)));
269   for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
270     detector_->OnWindowPaintScheduled(window.get(), update_region);
271   EXPECT_EQ(1, observer_->num_invocations());
272   EXPECT_EQ(0, observer_->num_fullscreens());
273   EXPECT_EQ(1, observer_->num_not_fullscreens());
274 }
275
276 // Test that the observer receives a true value when the window is fullscreen.
277 TEST_F(VideoDetectorTest, FullscreenWindow) {
278   gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768));
279   scoped_ptr<aura::Window> window(
280       CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds));
281   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
282   window->Focus();
283   gfx::Rect update_region(
284       gfx::Point(),
285       gfx::Size(VideoDetector::kMinUpdateWidth,
286                 VideoDetector::kMinUpdateHeight));
287   for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i)
288     detector_->OnWindowPaintScheduled(window.get(), update_region);
289   EXPECT_EQ(1, observer_->num_invocations());
290   EXPECT_EQ(1, observer_->num_fullscreens());
291   EXPECT_EQ(0, observer_->num_not_fullscreens());
292 }
293
294 }  // namespace test
295 }  // namespace ash