• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
5 #include "mojo/edk/system/broker_host.h"
6 
7 #include <fcntl.h>
8 #include <unistd.h>
9 
10 #include <utility>
11 
12 #include "base/logging.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/threading/thread_task_runner_handle.h"
16 #include "mojo/edk/embedder/embedder_internal.h"
17 #include "mojo/edk/embedder/platform_channel_utils_posix.h"
18 #include "mojo/edk/embedder/platform_handle_vector.h"
19 #include "mojo/edk/embedder/platform_shared_buffer.h"
20 #include "mojo/edk/system/broker_messages.h"
21 
22 namespace mojo {
23 namespace edk {
24 
25 namespace {
26 // To prevent abuse, limit the maximum size of shared memory buffers.
27 // TODO(amistry): Re-consider this limit, or do something smarter.
28 const size_t kMaxSharedBufferSize = 16 * 1024 * 1024;
29 }
30 
BrokerHost(ScopedPlatformHandle platform_handle)31 BrokerHost::BrokerHost(ScopedPlatformHandle platform_handle) {
32   CHECK(platform_handle.is_valid());
33 
34   base::MessageLoop::current()->AddDestructionObserver(this);
35 
36   channel_ = Channel::Create(this, std::move(platform_handle),
37                              base::ThreadTaskRunnerHandle::Get());
38   channel_->Start();
39 }
40 
~BrokerHost()41 BrokerHost::~BrokerHost() {
42   // We're always destroyed on the creation thread, which is the IO thread.
43   base::MessageLoop::current()->RemoveDestructionObserver(this);
44 
45   if (channel_)
46     channel_->ShutDown();
47 }
48 
SendChannel(ScopedPlatformHandle handle)49 void BrokerHost::SendChannel(ScopedPlatformHandle handle) {
50   CHECK(handle.is_valid());
51   CHECK(channel_);
52 
53   Channel::MessagePtr message =
54       CreateBrokerMessage(BrokerMessageType::INIT, 1, nullptr);
55   ScopedPlatformHandleVectorPtr handles;
56   handles.reset(new PlatformHandleVector(1));
57   handles->at(0) = handle.release();
58   message->SetHandles(std::move(handles));
59 
60   channel_->Write(std::move(message));
61 }
62 
OnBufferRequest(size_t num_bytes)63 void BrokerHost::OnBufferRequest(size_t num_bytes) {
64   scoped_refptr<PlatformSharedBuffer> buffer;
65   scoped_refptr<PlatformSharedBuffer> read_only_buffer;
66   if (num_bytes <= kMaxSharedBufferSize) {
67     buffer = PlatformSharedBuffer::Create(num_bytes);
68     if (buffer)
69       read_only_buffer = buffer->CreateReadOnlyDuplicate();
70     if (!read_only_buffer)
71       buffer = nullptr;
72   } else {
73     LOG(ERROR) << "Shared buffer request too large: " << num_bytes;
74   }
75 
76   Channel::MessagePtr message = CreateBrokerMessage(
77       BrokerMessageType::BUFFER_RESPONSE, buffer ? 2 : 0, nullptr);
78   if (buffer) {
79     ScopedPlatformHandleVectorPtr handles;
80     handles.reset(new PlatformHandleVector(2));
81     handles->at(0) = buffer->PassPlatformHandle().release();
82     handles->at(1) = read_only_buffer->PassPlatformHandle().release();
83     message->SetHandles(std::move(handles));
84   }
85 
86   channel_->Write(std::move(message));
87 }
88 
OnChannelMessage(const void * payload,size_t payload_size,ScopedPlatformHandleVectorPtr handles)89 void BrokerHost::OnChannelMessage(const void* payload,
90                                   size_t payload_size,
91                                   ScopedPlatformHandleVectorPtr handles) {
92   if (payload_size < sizeof(BrokerMessageHeader))
93     return;
94 
95   const BrokerMessageHeader* header =
96       static_cast<const BrokerMessageHeader*>(payload);
97   switch (header->type) {
98     case BrokerMessageType::BUFFER_REQUEST:
99       if (payload_size ==
100             sizeof(BrokerMessageHeader) + sizeof(BufferRequestData)) {
101         const BufferRequestData* request =
102             reinterpret_cast<const BufferRequestData*>(header + 1);
103         OnBufferRequest(request->size);
104         return;
105       }
106       break;
107 
108     default:
109       break;
110   }
111 
112   LOG(ERROR) << "Unexpected broker message type: " << header->type;
113 }
114 
OnChannelError()115 void BrokerHost::OnChannelError() {
116   if (channel_) {
117     channel_->ShutDown();
118     channel_ = nullptr;
119   }
120 
121   delete this;
122 }
123 
WillDestroyCurrentMessageLoop()124 void BrokerHost::WillDestroyCurrentMessageLoop() {
125   delete this;
126 }
127 
128 }  // namespace edk
129 }  // namespace mojo
130