video_detector_unittest.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/video_detector.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/test/ash_test_base.h" 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/wm/window_state.h" 10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ash/wm/wm_event.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkColor.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/client/aura_constants.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/test/test_windows.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window.h" 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/wm/public/window_types.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace test { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implementation that just counts the number of times we've been told that a 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// video is playing. 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestVideoDetectorObserver : public VideoDetectorObserver { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestVideoDetectorObserver() : num_invocations_(0), 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_fullscreens_(0), 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_not_fullscreens_(0) {} 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_invocations() const { return num_invocations_; } 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_fullscreens() const { return num_fullscreens_; } 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_not_fullscreens() const { return num_not_fullscreens_; } 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void reset_stats() { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_invocations_ = 0; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_fullscreens_ = 0; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_not_fullscreens_ = 0; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // VideoDetectorObserver implementation. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnVideoDetected(bool is_fullscreen) OVERRIDE { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_invocations_++; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_fullscreen) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_fullscreens_++; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_not_fullscreens_++; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Number of times that OnVideoDetected() has been called. 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_invocations_; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Number of times that OnVideoDetected() has been called with is_fullscreen 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // == true. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_fullscreens_; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Number of times that OnVideoDetected() has been called with is_fullscreen 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // == false. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_not_fullscreens_; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(TestVideoDetectorObserver); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VideoDetectorTest : public AshTestBase { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoDetectorTest() {} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~VideoDetectorTest() {} 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetUp() OVERRIDE { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AshTestBase::SetUp(); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_.reset(new TestVideoDetectorObserver); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) detector_ = Shell::GetInstance()->video_detector(); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) detector_->AddObserver(observer_.get()); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) now_ = base::TimeTicks::Now(); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) detector_->set_now_for_test(now_); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void TearDown() OVERRIDE { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) detector_->RemoveObserver(observer_.get()); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AshTestBase::TearDown(); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Move |detector_|'s idea of the current time forward by |delta|. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AdvanceTime(base::TimeDelta delta) { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) now_ += delta; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) detector_->set_now_for_test(now_); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoDetector* detector_; // not owned 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<TestVideoDetectorObserver> observer_; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks now_; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(VideoDetectorTest); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VideoDetectorTest, Basic) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<aura::Window> window( 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send enough updates, but make them be too small to trigger detection. 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect update_region( 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point(), 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size(VideoDetector::kMinUpdateWidth - 1, 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoDetector::kMinUpdateHeight)); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) detector_->OnWindowPaintScheduled(window.get(), update_region); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, observer_->num_invocations()); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send not-quite-enough adaquately-sized updates. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_->reset_stats(); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AdvanceTime(base::TimeDelta::FromSeconds(2)); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) update_region.set_size( 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size(VideoDetector::kMinUpdateWidth, 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoDetector::kMinUpdateHeight)); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < VideoDetector::kMinFramesPerSecond - 1; ++i) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) detector_->OnWindowPaintScheduled(window.get(), update_region); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, observer_->num_invocations()); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should get notified after the next update, but not in response to 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // additional updates. 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) detector_->OnWindowPaintScheduled(window.get(), update_region); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, observer_->num_invocations()); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, observer_->num_fullscreens()); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, observer_->num_not_fullscreens()); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) detector_->OnWindowPaintScheduled(window.get(), update_region); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, observer_->num_invocations()); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, observer_->num_fullscreens()); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, observer_->num_not_fullscreens()); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 136a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Spread out the frames over a longer period of time, but send enough 137a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // over a one-second window that the observer should be notified. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_->reset_stats(); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AdvanceTime(base::TimeDelta::FromSeconds(2)); 140a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) detector_->OnWindowPaintScheduled(window.get(), update_region); 141a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(0, observer_->num_invocations()); 142a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 143a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) AdvanceTime(base::TimeDelta::FromMilliseconds(500)); 144a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const int kNumFrames = VideoDetector::kMinFramesPerSecond + 1; 145a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::TimeDelta kInterval = 146a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::TimeDelta::FromMilliseconds(1000 / kNumFrames); 147a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) for (int i = 0; i < kNumFrames; ++i) { 148a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) AdvanceTime(kInterval); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) detector_->OnWindowPaintScheduled(window.get(), update_region); 150a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 151a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(1, observer_->num_invocations()); 152a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 153a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Keep going and check that the observer is notified again. 154a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) for (int i = 0; i < kNumFrames; ++i) { 155a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) AdvanceTime(kInterval); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) detector_->OnWindowPaintScheduled(window.get(), update_region); 157a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 158a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(2, observer_->num_invocations()); 159a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 160a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Send updates at a slower rate and check that the observer isn't notified. 161a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::TimeDelta kSlowInterval = base::TimeDelta::FromMilliseconds( 162a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1000 / (VideoDetector::kMinFramesPerSecond - 2)); 163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) for (int i = 0; i < kNumFrames; ++i) { 164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) AdvanceTime(kSlowInterval); 165a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) detector_->OnWindowPaintScheduled(window.get(), update_region); 166a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 167a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(2, observer_->num_invocations()); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(VideoDetectorTest, Shutdown) { 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<aura::Window> window( 173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gfx::Rect update_region( 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gfx::Point(), 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gfx::Size(VideoDetector::kMinUpdateWidth, 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) VideoDetector::kMinUpdateHeight)); 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // It should not detect video during the shutdown. 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Shell::GetInstance()->OnAppTerminating(); 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) detector_->OnWindowPaintScheduled(window.get(), update_region); 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(0, observer_->num_invocations()); 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VideoDetectorTest, WindowNotVisible) { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<aura::Window> window( 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reparent the window to the root to make sure that visibility changes aren't 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // animated. 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Shell::GetPrimaryRootWindow()->AddChild(window.get()); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We shouldn't report video that's played in a hidden window. 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window->Hide(); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect update_region( 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point(), 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size(VideoDetector::kMinUpdateWidth, 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoDetector::kMinUpdateHeight)); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) detector_->OnWindowPaintScheduled(window.get(), update_region); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, observer_->num_invocations()); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make the window visible and send more updates. 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_->reset_stats(); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AdvanceTime(base::TimeDelta::FromSeconds(2)); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window->Show(); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) detector_->OnWindowPaintScheduled(window.get(), update_region); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, observer_->num_invocations()); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, observer_->num_fullscreens()); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, observer_->num_not_fullscreens()); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We also shouldn't report video in a window that's fully offscreen. 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_->reset_stats(); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AdvanceTime(base::TimeDelta::FromSeconds(2)); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect offscreen_bounds( 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point(Shell::GetPrimaryRootWindow()->bounds().width(), 0), 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_bounds.size()); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window->SetBounds(offscreen_bounds); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(offscreen_bounds, window->bounds()); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) detector_->OnWindowPaintScheduled(window.get(), update_region); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, observer_->num_invocations()); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VideoDetectorTest, MultipleWindows) { 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create two windows. 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<aura::Window> window1( 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<aura::Window> window2( 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateTestWindowInShell(SK_ColorBLUE, 23456, window_bounds)); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Even if there's video playing in both, the observer should only receive a 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // single notification. 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect update_region( 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point(), 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size(VideoDetector::kMinUpdateWidth, 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoDetector::kMinUpdateHeight)); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) detector_->OnWindowPaintScheduled(window1.get(), update_region); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) detector_->OnWindowPaintScheduled(window2.get(), update_region); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, observer_->num_invocations()); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, observer_->num_fullscreens()); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, observer_->num_not_fullscreens()); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that the observer receives repeated notifications. 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VideoDetectorTest, RepeatedNotifications) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<aura::Window> window( 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect update_region( 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point(), 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size(VideoDetector::kMinUpdateWidth, 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoDetector::kMinUpdateHeight)); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) detector_->OnWindowPaintScheduled(window.get(), update_region); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, observer_->num_invocations()); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, observer_->num_fullscreens()); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, observer_->num_not_fullscreens()); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Let enough time pass that a second notification should be sent. 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_->reset_stats(); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AdvanceTime(base::TimeDelta::FromSeconds( 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int64>(VideoDetector::kNotifyIntervalSec + 1))); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) detector_->OnWindowPaintScheduled(window.get(), update_region); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, observer_->num_invocations()); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, observer_->num_fullscreens()); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, observer_->num_not_fullscreens()); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that the observer receives a true value when the window is fullscreen. 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VideoDetectorTest, FullscreenWindow) { 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!SupportsMultipleDisplays()) 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UpdateDisplay("1024x768,1024x768"); 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const gfx::Rect kLeftBounds(gfx::Point(), gfx::Size(1024, 768)); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<aura::Window> window( 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateTestWindowInShell(SK_ColorRED, 12345, kLeftBounds)); 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) wm::WindowState window_state(window.get()); 288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const wm::WMEvent toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN); 289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) window_state.OnWMEvent(&toggle_fullscreen_event); 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(window_state.IsFullscreen()); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window->Focus(); 2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const gfx::Rect kUpdateRegion( 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point(), 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size(VideoDetector::kMinUpdateWidth, 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoDetector::kMinUpdateHeight)); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) detector_->OnWindowPaintScheduled(window.get(), kUpdateRegion); 2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(1, observer_->num_invocations()); 2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(1, observer_->num_fullscreens()); 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(0, observer_->num_not_fullscreens()); 3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Make the first window non-fullscreen and open a second fullscreen window on 3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // a different desktop. 304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) window_state.OnWMEvent(&toggle_fullscreen_event); 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_FALSE(window_state.IsFullscreen()); 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const gfx::Rect kRightBounds(gfx::Point(1024, 0), gfx::Size(1024, 768)); 3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<aura::Window> other_window( 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateTestWindowInShell(SK_ColorBLUE, 6789, kRightBounds)); 3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) wm::WindowState other_window_state(other_window.get()); 310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) other_window_state.OnWMEvent(&toggle_fullscreen_event); 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(other_window_state.IsFullscreen()); 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // When video is detected in the first (now non-fullscreen) window, fullscreen 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // video should still be reported due to the second window being fullscreen. 3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // This avoids situations where non-fullscreen video could be reported when 3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // multiple videos are playing in fullscreen and non-fullscreen windows. 3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) observer_->reset_stats(); 3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AdvanceTime(base::TimeDelta::FromSeconds(2)); 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) detector_->OnWindowPaintScheduled(window.get(), kUpdateRegion); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, observer_->num_invocations()); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, observer_->num_fullscreens()); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, observer_->num_not_fullscreens()); 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Make the second window non-fullscreen and check that the next video report 3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // is non-fullscreen. 327a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) other_window_state.OnWMEvent(&toggle_fullscreen_event); 3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_FALSE(other_window_state.IsFullscreen()); 3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) observer_->reset_stats(); 3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AdvanceTime(base::TimeDelta::FromSeconds(2)); 3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) detector_->OnWindowPaintScheduled(window.get(), kUpdateRegion); 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(1, observer_->num_invocations()); 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(0, observer_->num_fullscreens()); 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(1, observer_->num_not_fullscreens()); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace test 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace ash 340