blob: 8e9c1728abccc1de9b25acb34723c91901bc2d21 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/wm/video_detector.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/shell.h"
#include "ash/wm/window_state.h"
#include "base/bind.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/wm/core/window_util.h"
namespace ash {
namespace {
// How long to wait before attempting to re-establish a lost connection.
constexpr base::TimeDelta kReEstablishConnectionDelay =
base::TimeDelta::FromMilliseconds(100);
} // namespace
VideoDetector::VideoDetector()
: state_(State::NOT_PLAYING),
video_is_playing_(false),
window_observer_manager_(this),
scoped_session_observer_(this),
is_shutting_down_(false),
binding_(this),
weak_factory_(this) {
Shell::Get()->aura_env()->AddObserver(this);
Shell::Get()->AddShellObserver(this);
EstablishConnectionToViz();
}
VideoDetector::~VideoDetector() {
Shell::Get()->RemoveShellObserver(this);
Shell::Get()->aura_env()->RemoveObserver(this);
}
void VideoDetector::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}
void VideoDetector::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
void VideoDetector::OnWindowInitialized(aura::Window* window) {
window_observer_manager_.Add(window);
}
void VideoDetector::OnWindowDestroying(aura::Window* window) {
if (fullscreen_root_windows_.count(window)) {
window_observer_manager_.Remove(window);
fullscreen_root_windows_.erase(window);
UpdateState();
}
}
void VideoDetector::OnWindowDestroyed(aura::Window* window) {
window_observer_manager_.Remove(window);
}
void VideoDetector::OnChromeTerminating() {
// Stop checking video activity once the shutdown
// process starts. crbug.com/231696.
is_shutting_down_ = true;
}
void VideoDetector::OnFullscreenStateChanged(bool is_fullscreen,
aura::Window* root_window) {
if (is_fullscreen && !fullscreen_root_windows_.count(root_window)) {
fullscreen_root_windows_.insert(root_window);
if (!window_observer_manager_.IsObserving(root_window))
window_observer_manager_.Add(root_window);
UpdateState();
} else if (!is_fullscreen && fullscreen_root_windows_.count(root_window)) {
fullscreen_root_windows_.erase(root_window);
window_observer_manager_.Remove(root_window);
UpdateState();
}
}
void VideoDetector::UpdateState() {
State new_state = State::NOT_PLAYING;
if (video_is_playing_) {
new_state = fullscreen_root_windows_.empty() ? State::PLAYING_WINDOWED
: State::PLAYING_FULLSCREEN;
}
if (state_ != new_state) {
state_ = new_state;
for (auto& observer : observers_)
observer.OnVideoStateChanged(state_);
}
}
void VideoDetector::OnVideoActivityStarted() {
if (is_shutting_down_)
return;
video_is_playing_ = true;
UpdateState();
}
void VideoDetector::OnVideoActivityEnded() {
video_is_playing_ = false;
UpdateState();
}
void VideoDetector::EstablishConnectionToViz() {
viz::mojom::VideoDetectorObserverPtr observer;
if (binding_.is_bound())
binding_.Close();
binding_.Bind(mojo::MakeRequest(&observer));
binding_.set_connection_error_handler(base::BindOnce(
&VideoDetector::OnConnectionError, base::Unretained(this)));
Shell::Get()
->aura_env()
->context_factory_private()
->GetHostFrameSinkManager()
->AddVideoDetectorObserver(std::move(observer));
}
void VideoDetector::OnConnectionError() {
if (video_is_playing_)
OnVideoActivityEnded();
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&VideoDetector::EstablishConnectionToViz,
weak_factory_.GetWeakPtr()),
kReEstablishConnectionDelay);
}
} // namespace ash