[go: nahoru, domu]

blob: 0632537ba7168c7e8e2f46a4af4525c6b032c35d [file] [log] [blame]
// Copyright 2012 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/me2me_desktop_environment.h"
#include <memory>
#include <utility>
#include "base/environment.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/task/single_thread_task_runner.h"
#include "build/build_config.h"
#include "remoting/base/logging.h"
#include "remoting/host/action_executor.h"
#include "remoting/host/base/screen_controls.h"
#include "remoting/host/client_session_control.h"
#include "remoting/host/curtain_mode.h"
#include "remoting/host/desktop_resizer.h"
#include "remoting/host/host_window.h"
#include "remoting/host/host_window_proxy.h"
#include "remoting/host/input_injector.h"
#include "remoting/host/input_monitor/local_input_monitor.h"
#include "remoting/host/remote_open_url/remote_open_url_util.h"
#include "remoting/host/resizing_host_observer.h"
#include "remoting/protocol/capability_names.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
#if BUILDFLAG(IS_POSIX)
#include <sys/types.h>
#include <unistd.h>
#endif // BUILDFLAG(IS_POSIX)
#if BUILDFLAG(IS_WIN)
#include "base/win/windows_version.h"
#endif // BUILDFLAG(IS_WIN)
#if defined(REMOTING_USE_X11)
#include "remoting/host/linux/wayland_utils.h"
#include "remoting/host/linux/x11_util.h"
#include "ui/gfx/x/connection.h"
#endif // defined(REMOTING_USE_X11)
namespace remoting {
namespace {
#if defined(REMOTING_USE_X11)
// Helper function that caches the result of IsUsingVideoDummyDriver().
bool UsingVideoDummyDriver() {
static bool is_using_dummy_driver =
IsUsingVideoDummyDriver(x11::Connection::Get());
return is_using_dummy_driver;
}
#endif // defined(REMOTING_USE_X11)
} // namespace
Me2MeDesktopEnvironment::~Me2MeDesktopEnvironment() {
DCHECK(caller_task_runner()->BelongsToCurrentThread());
}
std::unique_ptr<ActionExecutor>
Me2MeDesktopEnvironment::CreateActionExecutor() {
DCHECK(caller_task_runner()->BelongsToCurrentThread());
return ActionExecutor::Create();
}
std::unique_ptr<ScreenControls>
Me2MeDesktopEnvironment::CreateScreenControls() {
DCHECK(caller_task_runner()->BelongsToCurrentThread());
// We only want to restore the host resolution on disconnect if we are not
// curtained so we don't mess up the user's window layout unnecessarily if
// they disconnect and reconnect. Both OS X and Windows will restore the
// resolution automatically when the user logs back in on the console, and on
// Linux the curtain-mode uses a separate session.
auto resizer = std::make_unique<ResizingHostObserver>(
DesktopResizer::Create(), curtain_ == nullptr);
resizer->RegisterForDisplayChanges(*GetDisplayInfoMonitor());
return resizer;
}
std::string Me2MeDesktopEnvironment::GetCapabilities() const {
std::string capabilities = BasicDesktopEnvironment::GetCapabilities();
if (!capabilities.empty()) {
capabilities += " ";
}
capabilities += protocol::kRateLimitResizeRequests;
if (InputInjector::SupportsTouchEvents()) {
capabilities += " ";
capabilities += protocol::kTouchEventsCapability;
}
if (desktop_environment_options().enable_file_transfer()) {
capabilities += " ";
capabilities += protocol::kFileTransferCapability;
}
#if BUILDFLAG(IS_WIN)
capabilities += " ";
capabilities += protocol::kSendAttentionSequenceAction;
if (base::win::OSInfo::GetInstance()->version_type() !=
base::win::VersionType::SUITE_HOME) {
capabilities += " ";
capabilities += protocol::kLockWorkstationAction;
}
#endif // BUILDFLAG(IS_WIN)
if (desktop_environment_options().enable_remote_open_url() &&
IsRemoteOpenUrlSupported()) {
capabilities += " ";
capabilities += protocol::kRemoteOpenUrlCapability;
}
if (desktop_environment_options().enable_remote_webauthn()) {
capabilities += " ";
capabilities += protocol::kRemoteWebAuthnCapability;
}
#if BUILDFLAG(IS_LINUX) && defined(REMOTING_USE_X11)
if (!IsRunningWayland()) {
capabilities += " ";
capabilities += protocol::kMultiStreamCapability;
// Client-controlled layout is only supported with Xorg+video-dummy.
if (UsingVideoDummyDriver()) {
capabilities += " ";
capabilities += protocol::kClientControlledLayoutCapability;
}
}
#endif // BUILDFLAG(IS_LINUX) && defined(REMOTING_USE_X11)
return capabilities;
}
Me2MeDesktopEnvironment::Me2MeDesktopEnvironment(
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
base::WeakPtr<ClientSessionControl> client_session_control,
const DesktopEnvironmentOptions& options)
: BasicDesktopEnvironment(caller_task_runner,
video_capture_task_runner,
input_task_runner,
ui_task_runner,
client_session_control,
options) {
DCHECK(caller_task_runner->BelongsToCurrentThread());
// TODO(zijiehe): This logic should belong to RemotingMe2MeHost, instead of
// Me2MeDesktopEnvironment, which does not take response to create a new
// session.
// X DAMAGE is not enabled by default, since it is broken on many systems -
// see http://crbug.com/73423. It's safe to enable it here because it works
// properly under Xvfb.
mutable_desktop_capture_options()->set_use_update_notifications(true);
#if BUILDFLAG(IS_LINUX)
// Setting this option to false means that the capture differ wrapper will not
// be used when the X11 capturer is selected. This reduces the X11 capture
// time by a few milliseconds per frame and is safe because we can rely on
// XDAMAGE to identify the changed regions rather than checking each pixel
// ourselves.
mutable_desktop_capture_options()->set_detect_updated_region(false);
#endif
#if BUILDFLAG(IS_LINUX)
if (IsRunningWayland()) {
mutable_desktop_capture_options()->set_prefer_cursor_embedded(false);
}
#endif
}
bool Me2MeDesktopEnvironment::InitializeSecurity(
base::WeakPtr<ClientSessionControl> client_session_control) {
DCHECK(caller_task_runner()->BelongsToCurrentThread());
// Detach the session from the local console if the caller requested.
if (desktop_environment_options().enable_curtaining()) {
curtain_ = CurtainMode::Create(caller_task_runner(), ui_task_runner(),
client_session_control);
if (!curtain_->Activate()) {
LOG(ERROR) << "Failed to activate the curtain mode.";
curtain_ = nullptr;
return false;
}
return true;
}
// Otherwise, if the session is shared with the local user start monitoring
// the local input and create the in-session UI.
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
bool want_user_interface = false;
#elif BUILDFLAG(IS_APPLE)
// Don't try to display any UI on top of the system's login screen as this
// is rejected by the Window Server on OS X 10.7.4, and prevents the
// capturer from working (http://crbug.com/140984).
// TODO(lambroslambrou): Use a better technique of detecting whether we're
// running in the LoginWindow context, and refactor this into a separate
// function to be used here and in CurtainMode::ActivateCurtain().
bool want_user_interface = getuid() != 0;
#else
bool want_user_interface =
desktop_environment_options().enable_user_interface();
#endif
if (want_user_interface) {
// Create the local input monitor.
local_input_monitor_ = LocalInputMonitor::Create(
caller_task_runner(), input_task_runner(), ui_task_runner());
local_input_monitor_->StartMonitoringForClientSession(
client_session_control);
// Create the disconnect window.
#if BUILDFLAG(IS_WIN)
disconnect_window_ =
HostWindow::CreateAutoHidingDisconnectWindow(LocalInputMonitor::Create(
caller_task_runner(), input_task_runner(), ui_task_runner()));
#else
disconnect_window_ = HostWindow::CreateDisconnectWindow();
#endif
disconnect_window_ = std::make_unique<HostWindowProxy>(
caller_task_runner(), ui_task_runner(), std::move(disconnect_window_));
disconnect_window_->Start(client_session_control);
}
return true;
}
Me2MeDesktopEnvironmentFactory::Me2MeDesktopEnvironmentFactory(
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
: BasicDesktopEnvironmentFactory(caller_task_runner,
video_capture_task_runner,
input_task_runner,
ui_task_runner) {}
Me2MeDesktopEnvironmentFactory::~Me2MeDesktopEnvironmentFactory() = default;
std::unique_ptr<DesktopEnvironment> Me2MeDesktopEnvironmentFactory::Create(
base::WeakPtr<ClientSessionControl> client_session_control,
base::WeakPtr<ClientSessionEvents> client_session_events,
const DesktopEnvironmentOptions& options) {
DCHECK(caller_task_runner()->BelongsToCurrentThread());
std::unique_ptr<Me2MeDesktopEnvironment> desktop_environment(
new Me2MeDesktopEnvironment(caller_task_runner(),
video_capture_task_runner(),
input_task_runner(), ui_task_runner(),
client_session_control, options));
if (!desktop_environment->InitializeSecurity(client_session_control)) {
return nullptr;
}
return desktop_environment;
}
} // namespace remoting