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