chromium/components/exo/server/wayland_server_controller.cc

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/exo/server/wayland_server_controller.h"

#include <memory>

#include "base/atomic_sequence_num.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/ptr_util.h"
#include "base/task/current_thread.h"
#include "components/exo/data_exchange_delegate.h"
#include "components/exo/display.h"
#include "components/exo/input_method_surface_manager.h"
#include "components/exo/notification_surface_manager.h"
#include "components/exo/security_delegate.h"
#include "components/exo/server/wayland_server_handle.h"
#include "components/exo/toast_surface_manager.h"
#include "components/exo/wayland/server.h"
#include "components/exo/wm_helper.h"

namespace exo {

namespace {
WaylandServerController* g_instance = nullptr;
}  // namespace

// static
std::unique_ptr<WaylandServerController>
WaylandServerController::CreateIfNecessary(
    std::unique_ptr<DataExchangeDelegate> data_exchange_delegate,
    std::unique_ptr<SecurityDelegate> security_delegate,
    std::unique_ptr<NotificationSurfaceManager> notification_surface_manager,
    std::unique_ptr<InputMethodSurfaceManager> input_method_surface_manager,
    std::unique_ptr<ToastSurfaceManager> toast_surface_manager) {
  return std::make_unique<WaylandServerController>(
      std::move(data_exchange_delegate), std::move(security_delegate),
      std::move(notification_surface_manager),
      std::move(input_method_surface_manager),
      std::move(toast_surface_manager));
}

// static
WaylandServerController* WaylandServerController::Get() {
  DCHECK(g_instance);
  return g_instance;
}

WaylandServerController::~WaylandServerController() {
  // TODO(crbug.com/40717074): Investigate if we can eliminate Shutdown
  // methods.
  display_->Shutdown();
  wayland::Server::SetServerGetter(base::NullCallback());
  DCHECK_EQ(g_instance, this);
  g_instance = nullptr;
}

wayland::Server* WaylandServerController::GetServerForDisplay(
    wl_display* display) {
  if (default_server_ && default_server_->GetWaylandDisplay() == display) {
    return default_server_.get();
  }

  for (const auto& pair : on_demand_servers_) {
    if (pair.second->GetWaylandDisplay() == display) {
      return pair.second.get();
    }
  }

  return nullptr;
}

WaylandServerController::WaylandServerController(
    std::unique_ptr<DataExchangeDelegate> data_exchange_delegate,
    std::unique_ptr<SecurityDelegate> security_delegate,
    std::unique_ptr<NotificationSurfaceManager> notification_surface_manager,
    std::unique_ptr<InputMethodSurfaceManager> input_method_surface_manager,
    std::unique_ptr<ToastSurfaceManager> toast_surface_manager)
    : wm_helper_(std::make_unique<WMHelper>()),
      display_(
          std::make_unique<Display>(std::move(notification_surface_manager),
                                    std::move(input_method_surface_manager),
                                    std::move(toast_surface_manager),
                                    std::move(data_exchange_delegate))) {
  DCHECK(!g_instance);
  g_instance = this;
  default_server_ =
      wayland::Server::Create(display_.get(), std::move(security_delegate));
  default_server_->StartWithDefaultPath(base::BindOnce([](bool success) {
    DCHECK(success) << "Failed to start the default wayland server.";
  }));
  wayland::Server::SetServerGetter(base::BindRepeating(
      &WaylandServerController::GetServerForDisplay, base::Unretained(this)));
}

void WaylandServerController::ListenOnSocket(
    std::unique_ptr<SecurityDelegate> security_delegate,
    base::ScopedFD socket,
    base::OnceCallback<void(std::unique_ptr<WaylandServerHandle>)> callback) {
  std::unique_ptr<wayland::Server> server =
      wayland::Server::Create(display_.get(), std::move(security_delegate));
  auto* server_ptr = server.get();
  auto start_callback = base::BindOnce(&WaylandServerController::OnSocketAdded,
                                       weak_factory_.GetWeakPtr(),
                                       std::move(server), std::move(callback));
  server_ptr->StartWithFdAsync(std::move(socket), std::move(start_callback));
}

void WaylandServerController::OnSocketAdded(
    std::unique_ptr<wayland::Server> server,
    base::OnceCallback<void(std::unique_ptr<WaylandServerHandle>)> callback,
    bool success) {
  if (!success) {
    std::move(callback).Run(nullptr);
    return;
  }

  // WrapUnique() is needed since the constructor is private.
  auto handle = base::WrapUnique(new WaylandServerHandle());
  on_demand_servers_.emplace(handle.get(), std::move(server));
  std::move(callback).Run(std::move(handle));
}

void WaylandServerController::CloseSocket(WaylandServerHandle* server) {
  on_demand_servers_.erase(server);
}

}  // namespace exo