|  | // 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 |