910e62b5创建于 1月15日历史提交
// 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