chromoting_host_services_client.cc 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. // Copyright 2021 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. #include "remoting/host/chromoting_host_services_client.h"
  5. #include "base/bind.h"
  6. #include "base/environment.h"
  7. #include "base/notreached.h"
  8. #include "base/sequence_checker.h"
  9. #include "build/build_config.h"
  10. #include "mojo/public/cpp/bindings/pending_remote.h"
  11. #include "mojo/public/cpp/system/isolated_connection.h"
  12. #include "remoting/host/ipc_constants.h"
  13. #include "remoting/host/mojom/chromoting_host_services.mojom.h"
  14. #if BUILDFLAG(IS_WIN)
  15. #include <windows.h>
  16. #include "remoting/host/win/acl_util.h"
  17. #endif
  18. namespace remoting {
  19. namespace {
  20. bool g_initialized = false;
  21. } // namespace
  22. #if BUILDFLAG(IS_LINUX)
  23. // static
  24. constexpr char
  25. ChromotingHostServicesClient::kChromeRemoteDesktopSessionEnvVar[];
  26. #endif
  27. ChromotingHostServicesClient::ChromotingHostServicesClient()
  28. : ChromotingHostServicesClient(base::Environment::Create(),
  29. GetChromotingHostServicesServerName()) {
  30. DCHECK(g_initialized)
  31. << "ChromotingHostServicesClient::Initialize() has not been called.";
  32. }
  33. ChromotingHostServicesClient::ChromotingHostServicesClient(
  34. std::unique_ptr<base::Environment> environment,
  35. const mojo::NamedPlatformChannel::ServerName& server_name)
  36. : environment_(std::move(environment)), server_name_(server_name) {}
  37. ChromotingHostServicesClient::~ChromotingHostServicesClient() {
  38. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  39. }
  40. // static
  41. bool ChromotingHostServicesClient::Initialize() {
  42. DCHECK(!g_initialized);
  43. #if BUILDFLAG(IS_WIN)
  44. // The ChromotingHostServices server runs under the LocalService account,
  45. // which normally isn't allowed to query process info like session ID of a
  46. // process running under a different account, so we add an ACL to allow it.
  47. g_initialized = AddProcessAccessRightForWellKnownSid(
  48. WinLocalServiceSid, PROCESS_QUERY_LIMITED_INFORMATION);
  49. #else
  50. // Other platforms don't need initialization.
  51. g_initialized = true;
  52. #endif
  53. return g_initialized;
  54. }
  55. mojom::ChromotingSessionServices*
  56. ChromotingHostServicesClient::GetSessionServices() const {
  57. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  58. if (!const_cast<ChromotingHostServicesClient*>(this)
  59. ->EnsureSessionServicesBinding()) {
  60. return nullptr;
  61. }
  62. return session_services_remote_.get();
  63. }
  64. bool ChromotingHostServicesClient::EnsureConnection() {
  65. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  66. if (remote_.is_bound()) {
  67. return true;
  68. }
  69. auto endpoint = mojo::NamedPlatformChannel::ConnectToServer(server_name_);
  70. if (!endpoint.is_valid()) {
  71. LOG(WARNING) << "Cannot connect to IPC through server name " << server_name_
  72. << ". Endpoint is invalid.";
  73. return false;
  74. }
  75. connection_ = std::make_unique<mojo::IsolatedConnection>();
  76. mojo::PendingRemote<mojom::ChromotingHostServices> pending_remote(
  77. connection_->Connect(std::move(endpoint)), /* version= */ 0);
  78. if (!pending_remote.is_valid()) {
  79. LOG(WARNING) << "Invalid message pipe.";
  80. connection_.reset();
  81. return false;
  82. }
  83. remote_.Bind(std::move(pending_remote));
  84. remote_.set_disconnect_handler(base::BindOnce(
  85. &ChromotingHostServicesClient::OnDisconnected, base::Unretained(this)));
  86. return true;
  87. }
  88. bool ChromotingHostServicesClient::EnsureSessionServicesBinding() {
  89. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  90. if (session_services_remote_.is_bound()) {
  91. return true;
  92. }
  93. #if BUILDFLAG(IS_LINUX)
  94. if (!environment_->HasVar(kChromeRemoteDesktopSessionEnvVar)) {
  95. LOG(WARNING) << "Current desktop environment is not remotable.";
  96. return false;
  97. }
  98. #endif
  99. if (!EnsureConnection()) {
  100. return false;
  101. }
  102. remote_->BindSessionServices(
  103. session_services_remote_.BindNewPipeAndPassReceiver());
  104. session_services_remote_.set_disconnect_handler(
  105. base::BindOnce(&ChromotingHostServicesClient::OnSessionDisconnected,
  106. base::Unretained(this)));
  107. return true;
  108. }
  109. void ChromotingHostServicesClient::OnDisconnected() {
  110. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  111. remote_.reset();
  112. connection_.reset();
  113. }
  114. void ChromotingHostServicesClient::OnSessionDisconnected() {
  115. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  116. session_services_remote_.reset();
  117. if (on_session_disconnected_callback_for_testing_) {
  118. std::move(on_session_disconnected_callback_for_testing_).Run();
  119. }
  120. }
  121. } // namespace remoting