blob: 53eb7b460957c45bce876f96447f8c015a5291df [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/host/chromeos/ash_proxy.h"
#include "ash/constants/ash_pref_names.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "base/feature_list.h"
#include "base/no_destructor.h"
#include "components/prefs/pref_service.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "remoting/base/constants.h"
#include "remoting/host/chromeos/features.h"
#include "ui/aura/env.h"
#include "ui/aura/scoped_window_capture_request.h"
#include "ui/compositor/compositor.h"
#include "ui/display/manager/display_manager.h"
#include "ui/display/screen.h"
#include "ui/display/types/display_constants.h"
namespace remoting {
namespace {
class DefaultAshProxy : public AshProxy {
public:
DefaultAshProxy() = default;
DefaultAshProxy(const DefaultAshProxy&) = delete;
DefaultAshProxy& operator=(const DefaultAshProxy&) = delete;
~DefaultAshProxy() override = default;
// AshProxy implementation:
DisplayId GetPrimaryDisplayId() const override {
if (!screen()) {
return display::kDefaultDisplayId;
}
return screen()->GetPrimaryDisplay().id();
}
const std::vector<display::Display>& GetActiveDisplays() const override {
return display_manager().active_display_list();
}
const display::Display* GetDisplayForId(DisplayId display_id) const override {
if (!display_manager().IsActiveDisplayId(display_id)) {
return nullptr;
}
return &display_manager().GetDisplayForId(display_id);
}
aura::Window* GetSelectFileContainer() override {
return shell().GetPrimaryRootWindow()->GetChildById(
ash::kShellWindowId_AlwaysOnTopContainer);
}
void CreateVideoCapturer(
mojo::PendingReceiver<viz::mojom::FrameSinkVideoCapturer> video_capturer)
override {
aura::Env::GetInstance()
->context_factory()
->GetHostFrameSinkManager()
->CreateVideoCapturer(std::move(video_capturer));
}
aura::ScopedWindowCaptureRequest MakeDisplayCapturable(
DisplayId source_display_id) override {
aura::Window* window = GetWindowToCaptureForId(source_display_id);
DCHECK(window) << "No window exists for the source_display_id: "
<< source_display_id;
if (window->IsRootWindow()) {
// Root window is always capturable so nothing to do here.
return aura::ScopedWindowCaptureRequest();
} else {
return window->MakeWindowCapturable();
}
}
viz::FrameSinkId GetFrameSinkId(DisplayId source_display_id) override {
aura::Window* window =
ash::Shell::GetRootWindowForDisplayId(source_display_id);
DCHECK(window) << "No window exists for the source_display_id: "
<< source_display_id;
return window->GetFrameSinkId();
}
ash::curtain::SecurityCurtainController& GetSecurityCurtainController()
override {
return shell().security_curtain_controller();
}
void RequestSignOut() override {
shell().session_controller()->RequestSignOut();
}
bool IsScreenReaderEnabled() const override {
return shell().session_controller()->GetActivePrefService()->GetBoolean(
ash::prefs::kAccessibilitySpokenFeedbackEnabled);
}
private:
const display::Screen* screen() const { return display::Screen::Get(); }
// We can not return a const reference, as the ash shell has no const getter
// for the display manager :/
ash::Shell& shell() const {
auto* shell = ash::Shell::Get();
DCHECK(shell);
return *shell;
}
const display::DisplayManager& display_manager() const {
const auto* result = shell().display_manager();
DCHECK(result);
return *result;
}
aura::Window* GetRootWindowForId(DisplayId id) {
return shell().GetRootWindowForDisplayId(id);
}
aura::Window* GetWindowToCaptureForId(DisplayId id) {
// Capture the uncurtained window.
return ash::Shell::GetContainer(
GetRootWindowForId(id), ash::kShellWindowId_ScreenAnimationContainer);
}
};
AshProxy* g_instance_for_testing_ = nullptr;
} // namespace
// static
AshProxy& AshProxy::Get() {
static base::NoDestructor<DefaultAshProxy> instance_;
if (g_instance_for_testing_) {
return *g_instance_for_testing_;
}
return *instance_;
}
// static
void AshProxy::SetInstanceForTesting(AshProxy* instance) {
if (instance) {
DCHECK(!g_instance_for_testing_);
}
g_instance_for_testing_ = instance;
}
// static
int AshProxy::ScaleFactorToDpi(float scale_factor) {
return static_cast<int>(scale_factor * kDefaultDpi);
}
AshProxy::~AshProxy() = default;
} // namespace remoting