desktop_process.cc 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. //
  5. // This file implements the Windows service controlling Me2Me host processes
  6. // running within user sessions.
  7. #include "remoting/host/desktop_process.h"
  8. #include <utility>
  9. #include "base/bind.h"
  10. #include "base/callback_helpers.h"
  11. #include "base/logging.h"
  12. #include "base/memory/ref_counted.h"
  13. #include "base/message_loop/message_pump_type.h"
  14. #include "base/notreached.h"
  15. #include "base/task/current_thread.h"
  16. #include "build/build_config.h"
  17. #include "ipc/ipc_channel_proxy.h"
  18. #include "remoting/base/auto_thread.h"
  19. #include "remoting/base/auto_thread_task_runner.h"
  20. #include "remoting/host/crash_process.h"
  21. #include "remoting/host/desktop_environment.h"
  22. #include "remoting/host/desktop_session_agent.h"
  23. #if BUILDFLAG(IS_WIN)
  24. #include "base/win/windows_version.h"
  25. #endif // BUILDFLAG(IS_WIN)
  26. namespace remoting {
  27. DesktopProcess::DesktopProcess(
  28. scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
  29. scoped_refptr<AutoThreadTaskRunner> input_task_runner,
  30. scoped_refptr<AutoThreadTaskRunner> io_task_runner,
  31. mojo::ScopedMessagePipeHandle daemon_channel_handle)
  32. : caller_task_runner_(caller_task_runner),
  33. input_task_runner_(input_task_runner),
  34. io_task_runner_(io_task_runner),
  35. daemon_channel_handle_(std::move(daemon_channel_handle)) {
  36. DCHECK(caller_task_runner_->BelongsToCurrentThread());
  37. DCHECK(base::CurrentUIThread::IsSet());
  38. }
  39. DesktopProcess::~DesktopProcess() {
  40. DCHECK(!daemon_channel_);
  41. DCHECK(!desktop_agent_.get());
  42. }
  43. DesktopEnvironmentFactory& DesktopProcess::desktop_environment_factory() {
  44. DCHECK(caller_task_runner_->BelongsToCurrentThread());
  45. return *desktop_environment_factory_;
  46. }
  47. void DesktopProcess::OnNetworkProcessDisconnected() {
  48. DCHECK(caller_task_runner_->BelongsToCurrentThread());
  49. OnChannelError();
  50. }
  51. void DesktopProcess::CrashNetworkProcess(const base::Location& location) {
  52. DCHECK(caller_task_runner_->BelongsToCurrentThread());
  53. LOG(ERROR) << "Asking the daemon process to crash the network process. "
  54. << "Request originated from: " << location.ToString();
  55. desktop_session_request_handler_->CrashNetworkProcess();
  56. }
  57. void DesktopProcess::InjectSas() {
  58. DCHECK(caller_task_runner_->BelongsToCurrentThread());
  59. desktop_session_request_handler_->InjectSecureAttentionSequence();
  60. }
  61. void DesktopProcess::LockWorkstation() {
  62. DCHECK(caller_task_runner_->BelongsToCurrentThread());
  63. #if BUILDFLAG(IS_WIN)
  64. if (base::win::OSInfo::GetInstance()->version_type() ==
  65. base::win::VersionType::SUITE_HOME) {
  66. return;
  67. }
  68. if (!::LockWorkStation()) {
  69. LOG(ERROR) << "LockWorkStation() failed: " << ::GetLastError();
  70. }
  71. #else
  72. NOTREACHED();
  73. #endif // BUILDFLAG(IS_WIN)
  74. }
  75. bool DesktopProcess::OnMessageReceived(const IPC::Message& message) {
  76. DCHECK(caller_task_runner_->BelongsToCurrentThread());
  77. NOTREACHED() << "Received unexpected IPC type: " << message.type();
  78. return false;
  79. }
  80. void DesktopProcess::OnChannelConnected(int32_t peer_pid) {
  81. DCHECK(caller_task_runner_->BelongsToCurrentThread());
  82. VLOG(1) << "IPC: desktop <- daemon (" << peer_pid << ")";
  83. }
  84. void DesktopProcess::OnChannelError() {
  85. // Shutdown the desktop process.
  86. daemon_channel_.reset();
  87. if (desktop_agent_) {
  88. desktop_agent_->Stop();
  89. desktop_agent_ = nullptr;
  90. }
  91. desktop_session_request_handler_.reset();
  92. worker_process_control_.reset();
  93. caller_task_runner_ = nullptr;
  94. input_task_runner_ = nullptr;
  95. io_task_runner_ = nullptr;
  96. desktop_environment_factory_.reset();
  97. }
  98. void DesktopProcess::OnAssociatedInterfaceRequest(
  99. const std::string& interface_name,
  100. mojo::ScopedInterfaceEndpointHandle handle) {
  101. DCHECK(caller_task_runner_->BelongsToCurrentThread());
  102. if (interface_name == mojom::WorkerProcessControl::Name_) {
  103. if (worker_process_control_.is_bound()) {
  104. LOG(ERROR) << "Receiver already bound for associated interface: "
  105. << mojom::WorkerProcessControl::Name_;
  106. CrashProcess(__func__, __FILE__, __LINE__);
  107. }
  108. mojo::PendingAssociatedReceiver<mojom::WorkerProcessControl>
  109. pending_receiver(std::move(handle));
  110. worker_process_control_.Bind(std::move(pending_receiver));
  111. } else {
  112. LOG(ERROR) << "Received unexpected associated interface request: "
  113. << interface_name;
  114. CrashProcess(__func__, __FILE__, __LINE__);
  115. }
  116. }
  117. bool DesktopProcess::Start(
  118. std::unique_ptr<DesktopEnvironmentFactory> desktop_environment_factory) {
  119. DCHECK(caller_task_runner_->BelongsToCurrentThread());
  120. DCHECK(!desktop_environment_factory_);
  121. DCHECK(desktop_environment_factory);
  122. desktop_environment_factory_ = std::move(desktop_environment_factory);
  123. // Launch the audio capturing thread.
  124. scoped_refptr<AutoThreadTaskRunner> audio_task_runner;
  125. #if BUILDFLAG(IS_WIN)
  126. // On Windows the AudioCapturer requires COM, so we run a single-threaded
  127. // apartment, which requires a UI thread.
  128. audio_task_runner = AutoThread::CreateWithLoopAndComInitTypes(
  129. "ChromotingAudioThread", caller_task_runner_, base::MessagePumpType::UI,
  130. AutoThread::COM_INIT_STA);
  131. #else // !BUILDFLAG(IS_WIN)
  132. audio_task_runner = AutoThread::CreateWithType(
  133. "ChromotingAudioThread", caller_task_runner_, base::MessagePumpType::IO);
  134. #endif // !BUILDFLAG(IS_WIN)
  135. // Create a desktop agent.
  136. desktop_agent_ =
  137. new DesktopSessionAgent(audio_task_runner, caller_task_runner_,
  138. input_task_runner_, io_task_runner_);
  139. // Initialize the agent and create an IPC channel to talk to it.
  140. mojo::ScopedMessagePipeHandle desktop_pipe =
  141. desktop_agent_->Initialize(weak_factory_.GetWeakPtr());
  142. // Connect to the daemon.
  143. daemon_channel_ = IPC::ChannelProxy::Create(
  144. daemon_channel_handle_.release(), IPC::Channel::MODE_CLIENT, this,
  145. io_task_runner_, base::ThreadTaskRunnerHandle::Get());
  146. daemon_channel_->GetRemoteAssociatedInterface(
  147. &desktop_session_request_handler_);
  148. // Pass |desktop_pipe| to the daemon.
  149. desktop_session_request_handler_->ConnectDesktopChannel(
  150. std::move(desktop_pipe));
  151. return true;
  152. }
  153. void DesktopProcess::CrashProcess(const std::string& function_name,
  154. const std::string& file_name,
  155. int line_number) {
  156. // The daemon requested us to crash the process.
  157. ::remoting::CrashProcess(function_name, file_name, line_number);
  158. }
  159. } // namespace remoting