broker_host.cc 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. // Copyright 2016 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 "mojo/core/broker_host.h"
  5. #include <utility>
  6. #include "base/logging.h"
  7. #include "base/memory/platform_shared_memory_region.h"
  8. #include "base/memory/ref_counted.h"
  9. #include "base/threading/thread_task_runner_handle.h"
  10. #include "build/build_config.h"
  11. #include "mojo/core/broker_messages.h"
  12. #include "mojo/core/platform_handle_utils.h"
  13. #if BUILDFLAG(IS_WIN)
  14. #include <windows.h>
  15. #endif
  16. namespace mojo {
  17. namespace core {
  18. BrokerHost::BrokerHost(base::Process client_process,
  19. ConnectionParams connection_params,
  20. const ProcessErrorCallback& process_error_callback)
  21. : process_error_callback_(process_error_callback)
  22. #if BUILDFLAG(IS_WIN)
  23. ,
  24. client_process_(std::move(client_process))
  25. #endif
  26. {
  27. CHECK(connection_params.endpoint().is_valid() ||
  28. connection_params.server_endpoint().is_valid());
  29. base::CurrentThread::Get()->AddDestructionObserver(this);
  30. channel_ = Channel::Create(this, std::move(connection_params),
  31. #if BUILDFLAG(IS_WIN)
  32. client_process_
  33. #else
  34. client_process
  35. #endif
  36. .IsValid()
  37. ? Channel::HandlePolicy::kAcceptHandles
  38. : Channel::HandlePolicy::kRejectHandles,
  39. base::ThreadTaskRunnerHandle::Get());
  40. channel_->Start();
  41. }
  42. BrokerHost::~BrokerHost() {
  43. // We're always destroyed on the creation thread, which is the IO thread.
  44. base::CurrentThread::Get()->RemoveDestructionObserver(this);
  45. if (channel_)
  46. channel_->ShutDown();
  47. }
  48. bool BrokerHost::PrepareHandlesForClient(
  49. std::vector<PlatformHandleInTransit>* handles) {
  50. #if BUILDFLAG(IS_WIN)
  51. if (!client_process_.IsValid())
  52. return false;
  53. bool handles_ok = true;
  54. for (auto& handle : *handles) {
  55. if (!handle.TransferToProcess(client_process_.Duplicate()))
  56. handles_ok = false;
  57. }
  58. return handles_ok;
  59. #else
  60. return true;
  61. #endif
  62. }
  63. bool BrokerHost::SendChannel(PlatformHandle handle) {
  64. CHECK(handle.is_valid());
  65. CHECK(channel_);
  66. #if BUILDFLAG(IS_WIN)
  67. InitData* data;
  68. Channel::MessagePtr message =
  69. CreateBrokerMessage(BrokerMessageType::INIT, 1, 0, &data);
  70. data->pipe_name_length = 0;
  71. #else
  72. Channel::MessagePtr message =
  73. CreateBrokerMessage(BrokerMessageType::INIT, 1, nullptr);
  74. #endif
  75. std::vector<PlatformHandleInTransit> handles(1);
  76. handles[0] = PlatformHandleInTransit(std::move(handle));
  77. // This may legitimately fail on Windows if the client process is in another
  78. // session, e.g., is an elevated process.
  79. if (!PrepareHandlesForClient(&handles))
  80. return false;
  81. message->SetHandles(std::move(handles));
  82. channel_->Write(std::move(message));
  83. return true;
  84. }
  85. #if BUILDFLAG(IS_WIN)
  86. void BrokerHost::SendNamedChannel(base::WStringPiece pipe_name) {
  87. InitData* data;
  88. wchar_t* name_data;
  89. Channel::MessagePtr message = CreateBrokerMessage(
  90. BrokerMessageType::INIT, 0, sizeof(*name_data) * pipe_name.length(),
  91. &data, reinterpret_cast<void**>(&name_data));
  92. data->pipe_name_length = static_cast<uint32_t>(pipe_name.length());
  93. std::copy(pipe_name.begin(), pipe_name.end(), name_data);
  94. channel_->Write(std::move(message));
  95. }
  96. #endif // BUILDFLAG(IS_WIN)
  97. void BrokerHost::OnBufferRequest(uint32_t num_bytes) {
  98. base::subtle::PlatformSharedMemoryRegion region =
  99. base::subtle::PlatformSharedMemoryRegion::CreateWritable(num_bytes);
  100. std::vector<PlatformHandleInTransit> handles;
  101. handles.reserve(2);
  102. if (region.IsValid()) {
  103. PlatformHandle h[2];
  104. ExtractPlatformHandlesFromSharedMemoryRegionHandle(
  105. region.PassPlatformHandle(), &h[0], &h[1]);
  106. handles.emplace_back(std::move(h[0]));
  107. #if !BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC)
  108. // Non-POSIX systems, as well as Android and Mac, only use a single handle
  109. // to represent a writable region.
  110. DCHECK(!h[1].is_valid());
  111. #else
  112. DCHECK(h[1].is_valid());
  113. handles.emplace_back(std::move(h[1]));
  114. #endif
  115. }
  116. BufferResponseData* response;
  117. Channel::MessagePtr message = CreateBrokerMessage(
  118. BrokerMessageType::BUFFER_RESPONSE, handles.size(), 0, &response);
  119. if (handles.empty()) {
  120. response->guid_high = 0;
  121. response->guid_low = 0;
  122. } else {
  123. const base::UnguessableToken& guid = region.GetGUID();
  124. response->guid_high = guid.GetHighForSerialization();
  125. response->guid_low = guid.GetLowForSerialization();
  126. PrepareHandlesForClient(&handles);
  127. message->SetHandles(std::move(handles));
  128. }
  129. channel_->Write(std::move(message));
  130. }
  131. void BrokerHost::OnChannelMessage(const void* payload,
  132. size_t payload_size,
  133. std::vector<PlatformHandle> handles) {
  134. if (payload_size < sizeof(BrokerMessageHeader))
  135. return;
  136. const BrokerMessageHeader* header =
  137. static_cast<const BrokerMessageHeader*>(payload);
  138. switch (header->type) {
  139. case BrokerMessageType::BUFFER_REQUEST:
  140. if (payload_size ==
  141. sizeof(BrokerMessageHeader) + sizeof(BufferRequestData)) {
  142. const BufferRequestData* request =
  143. reinterpret_cast<const BufferRequestData*>(header + 1);
  144. OnBufferRequest(request->size);
  145. }
  146. break;
  147. default:
  148. DLOG(ERROR) << "Unexpected broker message type: " << header->type;
  149. break;
  150. }
  151. }
  152. void BrokerHost::OnChannelError(Channel::Error error) {
  153. if (process_error_callback_ &&
  154. error == Channel::Error::kReceivedMalformedData) {
  155. process_error_callback_.Run("Broker host received malformed message");
  156. }
  157. delete this;
  158. }
  159. void BrokerHost::WillDestroyCurrentMessageLoop() {
  160. delete this;
  161. }
  162. } // namespace core
  163. } // namespace mojo