video_detector_unittest.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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.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 21namespace ash { 22namespace test { 23 24// Implementation that just counts the number of times we've been told that a 25// video is playing. 26class 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 63class 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 100TEST_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 two seconds; we shouldn't detect video. 136 observer_->reset_stats(); 137 AdvanceTime(base::TimeDelta::FromSeconds(2)); 138 for (int i = 0; i < VideoDetector::kMinFramesPerSecond - 1; ++i) 139 detector_->OnWindowPaintScheduled(window.get(), update_region); 140 AdvanceTime(base::TimeDelta::FromSeconds(1)); 141 for (int i = 0; i < VideoDetector::kMinFramesPerSecond - 1; ++i) 142 detector_->OnWindowPaintScheduled(window.get(), update_region); 143 EXPECT_EQ(0, observer_->num_invocations()); 144} 145 146TEST_F(VideoDetectorTest, WindowNotVisible) { 147 gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); 148 scoped_ptr<aura::Window> window( 149 CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); 150 151 // Reparent the window to the root to make sure that visibility changes aren't 152 // animated. 153 Shell::GetPrimaryRootWindow()->AddChild(window.get()); 154 155 // We shouldn't report video that's played in a hidden window. 156 window->Hide(); 157 gfx::Rect update_region( 158 gfx::Point(), 159 gfx::Size(VideoDetector::kMinUpdateWidth, 160 VideoDetector::kMinUpdateHeight)); 161 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 162 detector_->OnWindowPaintScheduled(window.get(), update_region); 163 EXPECT_EQ(0, observer_->num_invocations()); 164 165 // Make the window visible and send more updates. 166 observer_->reset_stats(); 167 AdvanceTime(base::TimeDelta::FromSeconds(2)); 168 window->Show(); 169 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 170 detector_->OnWindowPaintScheduled(window.get(), update_region); 171 EXPECT_EQ(1, observer_->num_invocations()); 172 EXPECT_EQ(0, observer_->num_fullscreens()); 173 EXPECT_EQ(1, observer_->num_not_fullscreens()); 174 175 // We also shouldn't report video in a window that's fully offscreen. 176 observer_->reset_stats(); 177 AdvanceTime(base::TimeDelta::FromSeconds(2)); 178 gfx::Rect offscreen_bounds( 179 gfx::Point(Shell::GetPrimaryRootWindow()->bounds().width(), 0), 180 window_bounds.size()); 181 window->SetBounds(offscreen_bounds); 182 ASSERT_EQ(offscreen_bounds, window->bounds()); 183 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 184 detector_->OnWindowPaintScheduled(window.get(), update_region); 185 EXPECT_EQ(0, observer_->num_invocations()); 186} 187 188TEST_F(VideoDetectorTest, MultipleWindows) { 189 // Create two windows. 190 gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); 191 scoped_ptr<aura::Window> window1( 192 CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); 193 scoped_ptr<aura::Window> window2( 194 CreateTestWindowInShell(SK_ColorBLUE, 23456, window_bounds)); 195 196 // Even if there's video playing in both, the observer should only receive a 197 // single notification. 198 gfx::Rect update_region( 199 gfx::Point(), 200 gfx::Size(VideoDetector::kMinUpdateWidth, 201 VideoDetector::kMinUpdateHeight)); 202 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 203 detector_->OnWindowPaintScheduled(window1.get(), update_region); 204 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 205 detector_->OnWindowPaintScheduled(window2.get(), update_region); 206 EXPECT_EQ(1, observer_->num_invocations()); 207 EXPECT_EQ(0, observer_->num_fullscreens()); 208 EXPECT_EQ(1, observer_->num_not_fullscreens()); 209} 210 211// Test that the observer receives repeated notifications. 212TEST_F(VideoDetectorTest, RepeatedNotifications) { 213 gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); 214 scoped_ptr<aura::Window> window( 215 CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); 216 217 gfx::Rect update_region( 218 gfx::Point(), 219 gfx::Size(VideoDetector::kMinUpdateWidth, 220 VideoDetector::kMinUpdateHeight)); 221 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 222 detector_->OnWindowPaintScheduled(window.get(), update_region); 223 EXPECT_EQ(1, observer_->num_invocations()); 224 EXPECT_EQ(0, observer_->num_fullscreens()); 225 EXPECT_EQ(1, observer_->num_not_fullscreens()); 226 // Let enough time pass that a second notification should be sent. 227 observer_->reset_stats(); 228 AdvanceTime(base::TimeDelta::FromSeconds( 229 static_cast<int64>(VideoDetector::kNotifyIntervalSec + 1))); 230 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 231 detector_->OnWindowPaintScheduled(window.get(), update_region); 232 EXPECT_EQ(1, observer_->num_invocations()); 233 EXPECT_EQ(0, observer_->num_fullscreens()); 234 EXPECT_EQ(1, observer_->num_not_fullscreens()); 235} 236 237// Test that the observer receives a true value when the window is fullscreen. 238TEST_F(VideoDetectorTest, FullscreenWindow) { 239 gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); 240 scoped_ptr<aura::Window> window( 241 CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); 242 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); 243 window->Focus(); 244 gfx::Rect update_region( 245 gfx::Point(), 246 gfx::Size(VideoDetector::kMinUpdateWidth, 247 VideoDetector::kMinUpdateHeight)); 248 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 249 detector_->OnWindowPaintScheduled(window.get(), update_region); 250 EXPECT_EQ(1, observer_->num_invocations()); 251 EXPECT_EQ(1, observer_->num_fullscreens()); 252 EXPECT_EQ(0, observer_->num_not_fullscreens()); 253} 254 255} // namespace test 256} // namespace ash 257