• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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/core.h"
6 
7 #include <string.h>
8 
9 #include <utility>
10 
11 #include "base/bind.h"
12 #include "base/containers/stack_container.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/macros.h"
16 #include "base/memory/ptr_util.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/rand_util.h"
19 #include "base/threading/thread_task_runner_handle.h"
20 #include "base/time/time.h"
21 #include "mojo/edk/embedder/embedder.h"
22 #include "mojo/edk/embedder/embedder_internal.h"
23 #include "mojo/edk/embedder/platform_shared_buffer.h"
24 #include "mojo/edk/system/channel.h"
25 #include "mojo/edk/system/configuration.h"
26 #include "mojo/edk/system/data_pipe_consumer_dispatcher.h"
27 #include "mojo/edk/system/data_pipe_producer_dispatcher.h"
28 #include "mojo/edk/system/handle_signals_state.h"
29 #include "mojo/edk/system/message_for_transit.h"
30 #include "mojo/edk/system/message_pipe_dispatcher.h"
31 #include "mojo/edk/system/platform_handle_dispatcher.h"
32 #include "mojo/edk/system/ports/name.h"
33 #include "mojo/edk/system/ports/node.h"
34 #include "mojo/edk/system/request_context.h"
35 #include "mojo/edk/system/shared_buffer_dispatcher.h"
36 #include "mojo/edk/system/wait_set_dispatcher.h"
37 #include "mojo/edk/system/waiter.h"
38 
39 namespace mojo {
40 namespace edk {
41 
42 namespace {
43 
44 // This is an unnecessarily large limit that is relatively easy to enforce.
45 const uint32_t kMaxHandlesPerMessage = 1024 * 1024;
46 
47 // TODO(rockot): Maybe we could negotiate a debugging pipe ID for cross-process
48 // pipes too; for now we just use a constant. This only affects bootstrap pipes.
49 const uint64_t kUnknownPipeIdForDebug = 0x7f7f7f7f7f7f7f7fUL;
50 
CallWatchCallback(MojoWatchCallback callback,uintptr_t context,MojoResult result,const HandleSignalsState & signals_state,MojoWatchNotificationFlags flags)51 void CallWatchCallback(MojoWatchCallback callback,
52                        uintptr_t context,
53                        MojoResult result,
54                        const HandleSignalsState& signals_state,
55                        MojoWatchNotificationFlags flags) {
56   callback(context, result, static_cast<MojoHandleSignalsState>(signals_state),
57       flags);
58 }
59 
MojoPlatformHandleToScopedPlatformHandle(const MojoPlatformHandle * platform_handle,ScopedPlatformHandle * out_handle)60 MojoResult MojoPlatformHandleToScopedPlatformHandle(
61     const MojoPlatformHandle* platform_handle,
62     ScopedPlatformHandle* out_handle) {
63   if (platform_handle->struct_size != sizeof(MojoPlatformHandle))
64     return MOJO_RESULT_INVALID_ARGUMENT;
65 
66   if (platform_handle->type == MOJO_PLATFORM_HANDLE_TYPE_INVALID) {
67     out_handle->reset();
68     return MOJO_RESULT_OK;
69   }
70 
71   PlatformHandle handle;
72   switch (platform_handle->type) {
73 #if defined(OS_POSIX)
74     case MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR:
75       handle.handle = static_cast<int>(platform_handle->value);
76       break;
77 #endif
78 
79 #if defined(OS_MACOSX) && !defined(OS_IOS)
80     case MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT:
81       handle.type = PlatformHandle::Type::MACH;
82       handle.port = static_cast<mach_port_t>(platform_handle->value);
83       break;
84 #endif
85 
86 #if defined(OS_WIN)
87     case MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE:
88       handle.handle = reinterpret_cast<HANDLE>(platform_handle->value);
89       break;
90 #endif
91 
92     default:
93       return MOJO_RESULT_INVALID_ARGUMENT;
94   }
95 
96   out_handle->reset(handle);
97   return MOJO_RESULT_OK;
98 }
99 
ScopedPlatformHandleToMojoPlatformHandle(ScopedPlatformHandle handle,MojoPlatformHandle * platform_handle)100 MojoResult ScopedPlatformHandleToMojoPlatformHandle(
101     ScopedPlatformHandle handle,
102     MojoPlatformHandle* platform_handle) {
103   if (platform_handle->struct_size != sizeof(MojoPlatformHandle))
104     return MOJO_RESULT_INVALID_ARGUMENT;
105 
106   if (!handle.is_valid()) {
107     platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_INVALID;
108     return MOJO_RESULT_OK;
109   }
110 
111 #if defined(OS_POSIX)
112   switch (handle.get().type) {
113     case PlatformHandle::Type::POSIX:
114       platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR;
115       platform_handle->value = static_cast<uint64_t>(handle.release().handle);
116       break;
117 
118 #if defined(OS_MACOSX) && !defined(OS_IOS)
119     case PlatformHandle::Type::MACH:
120       platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT;
121       platform_handle->value = static_cast<uint64_t>(handle.release().port);
122       break;
123 #endif  // defined(OS_MACOSX) && !defined(OS_IOS)
124 
125     default:
126       return MOJO_RESULT_INVALID_ARGUMENT;
127   }
128 #elif defined(OS_WIN)
129   platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE;
130   platform_handle->value = reinterpret_cast<uint64_t>(handle.release().handle);
131 #endif  // defined(OS_WIN)
132 
133   return MOJO_RESULT_OK;
134 }
135 
136 }  // namespace
137 
Core()138 Core::Core() {}
139 
~Core()140 Core::~Core() {
141   if (node_controller_ && node_controller_->io_task_runner()) {
142     // If this races with IO thread shutdown the callback will be dropped and
143     // the NodeController will be shutdown on this thread anyway, which is also
144     // just fine.
145     scoped_refptr<base::TaskRunner> io_task_runner =
146         node_controller_->io_task_runner();
147     io_task_runner->PostTask(FROM_HERE,
148                              base::Bind(&Core::PassNodeControllerToIOThread,
149                                         base::Passed(&node_controller_)));
150   }
151 }
152 
SetIOTaskRunner(scoped_refptr<base::TaskRunner> io_task_runner)153 void Core::SetIOTaskRunner(scoped_refptr<base::TaskRunner> io_task_runner) {
154   GetNodeController()->SetIOTaskRunner(io_task_runner);
155 }
156 
GetNodeController()157 NodeController* Core::GetNodeController() {
158   base::AutoLock lock(node_controller_lock_);
159   if (!node_controller_)
160     node_controller_.reset(new NodeController(this));
161   return node_controller_.get();
162 }
163 
GetDispatcher(MojoHandle handle)164 scoped_refptr<Dispatcher> Core::GetDispatcher(MojoHandle handle) {
165   base::AutoLock lock(handles_lock_);
166   return handles_.GetDispatcher(handle);
167 }
168 
SetDefaultProcessErrorCallback(const ProcessErrorCallback & callback)169 void Core::SetDefaultProcessErrorCallback(
170     const ProcessErrorCallback& callback) {
171   default_process_error_callback_ = callback;
172 }
173 
AddChild(base::ProcessHandle process_handle,ConnectionParams connection_params,const std::string & child_token,const ProcessErrorCallback & process_error_callback)174 void Core::AddChild(base::ProcessHandle process_handle,
175                     ConnectionParams connection_params,
176                     const std::string& child_token,
177                     const ProcessErrorCallback& process_error_callback) {
178   GetNodeController()->ConnectToChild(process_handle,
179                                       std::move(connection_params), child_token,
180                                       process_error_callback);
181 }
182 
ChildLaunchFailed(const std::string & child_token)183 void Core::ChildLaunchFailed(const std::string& child_token) {
184   RequestContext request_context;
185   GetNodeController()->CloseChildPorts(child_token);
186 }
187 
ConnectToPeerProcess(ScopedPlatformHandle pipe_handle,const std::string & peer_token)188 ScopedMessagePipeHandle Core::ConnectToPeerProcess(
189     ScopedPlatformHandle pipe_handle,
190     const std::string& peer_token) {
191   RequestContext request_context;
192   ports::PortRef port0, port1;
193   GetNodeController()->node()->CreatePortPair(&port0, &port1);
194   MojoHandle handle = AddDispatcher(new MessagePipeDispatcher(
195       GetNodeController(), port0, kUnknownPipeIdForDebug, 0));
196   ConnectionParams connection_params(std::move(pipe_handle));
197   GetNodeController()->ConnectToPeer(std::move(connection_params), port1,
198                                      peer_token);
199   return ScopedMessagePipeHandle(MessagePipeHandle(handle));
200 }
201 
ClosePeerConnection(const std::string & peer_token)202 void Core::ClosePeerConnection(const std::string& peer_token) {
203   GetNodeController()->ClosePeerConnection(peer_token);
204 }
205 
InitChild(ConnectionParams connection_params)206 void Core::InitChild(ConnectionParams connection_params) {
207   GetNodeController()->ConnectToParent(std::move(connection_params));
208 }
209 
SetMachPortProvider(base::PortProvider * port_provider)210 void Core::SetMachPortProvider(base::PortProvider* port_provider) {
211 #if defined(OS_MACOSX) && !defined(OS_IOS)
212   GetNodeController()->CreateMachPortRelay(port_provider);
213 #endif
214 }
215 
AddDispatcher(scoped_refptr<Dispatcher> dispatcher)216 MojoHandle Core::AddDispatcher(scoped_refptr<Dispatcher> dispatcher) {
217   base::AutoLock lock(handles_lock_);
218   return handles_.AddDispatcher(dispatcher);
219 }
220 
AddDispatchersFromTransit(const std::vector<Dispatcher::DispatcherInTransit> & dispatchers,MojoHandle * handles)221 bool Core::AddDispatchersFromTransit(
222     const std::vector<Dispatcher::DispatcherInTransit>& dispatchers,
223     MojoHandle* handles) {
224   bool failed = false;
225   {
226     base::AutoLock lock(handles_lock_);
227     if (!handles_.AddDispatchersFromTransit(dispatchers, handles))
228       failed = true;
229   }
230   if (failed) {
231     for (auto d : dispatchers)
232       d.dispatcher->Close();
233     return false;
234   }
235   return true;
236 }
237 
CreatePlatformHandleWrapper(ScopedPlatformHandle platform_handle,MojoHandle * wrapper_handle)238 MojoResult Core::CreatePlatformHandleWrapper(
239     ScopedPlatformHandle platform_handle,
240     MojoHandle* wrapper_handle) {
241   MojoHandle h = AddDispatcher(
242       PlatformHandleDispatcher::Create(std::move(platform_handle)));
243   if (h == MOJO_HANDLE_INVALID)
244     return MOJO_RESULT_RESOURCE_EXHAUSTED;
245   *wrapper_handle = h;
246   return MOJO_RESULT_OK;
247 }
248 
PassWrappedPlatformHandle(MojoHandle wrapper_handle,ScopedPlatformHandle * platform_handle)249 MojoResult Core::PassWrappedPlatformHandle(
250     MojoHandle wrapper_handle,
251     ScopedPlatformHandle* platform_handle) {
252   base::AutoLock lock(handles_lock_);
253   scoped_refptr<Dispatcher> d;
254   MojoResult result = handles_.GetAndRemoveDispatcher(wrapper_handle, &d);
255   if (result != MOJO_RESULT_OK)
256     return result;
257   if (d->GetType() == Dispatcher::Type::PLATFORM_HANDLE) {
258     PlatformHandleDispatcher* phd =
259         static_cast<PlatformHandleDispatcher*>(d.get());
260     *platform_handle = phd->PassPlatformHandle();
261   } else {
262     result = MOJO_RESULT_INVALID_ARGUMENT;
263   }
264   d->Close();
265   return result;
266 }
267 
CreateSharedBufferWrapper(base::SharedMemoryHandle shared_memory_handle,size_t num_bytes,bool read_only,MojoHandle * mojo_wrapper_handle)268 MojoResult Core::CreateSharedBufferWrapper(
269     base::SharedMemoryHandle shared_memory_handle,
270     size_t num_bytes,
271     bool read_only,
272     MojoHandle* mojo_wrapper_handle) {
273   DCHECK(num_bytes);
274   scoped_refptr<PlatformSharedBuffer> platform_buffer =
275       PlatformSharedBuffer::CreateFromSharedMemoryHandle(num_bytes, read_only,
276                                                          shared_memory_handle);
277   if (!platform_buffer)
278     return MOJO_RESULT_UNKNOWN;
279 
280   scoped_refptr<SharedBufferDispatcher> dispatcher;
281   MojoResult result = SharedBufferDispatcher::CreateFromPlatformSharedBuffer(
282       platform_buffer, &dispatcher);
283   if (result != MOJO_RESULT_OK)
284     return result;
285   MojoHandle h = AddDispatcher(dispatcher);
286   if (h == MOJO_HANDLE_INVALID)
287     return MOJO_RESULT_RESOURCE_EXHAUSTED;
288   *mojo_wrapper_handle = h;
289   return MOJO_RESULT_OK;
290 }
291 
PassSharedMemoryHandle(MojoHandle mojo_handle,base::SharedMemoryHandle * shared_memory_handle,size_t * num_bytes,bool * read_only)292 MojoResult Core::PassSharedMemoryHandle(
293     MojoHandle mojo_handle,
294     base::SharedMemoryHandle* shared_memory_handle,
295     size_t* num_bytes,
296     bool* read_only) {
297   if (!shared_memory_handle)
298     return MOJO_RESULT_INVALID_ARGUMENT;
299 
300   scoped_refptr<Dispatcher> dispatcher;
301   MojoResult result = MOJO_RESULT_OK;
302   {
303     base::AutoLock lock(handles_lock_);
304     // Get the dispatcher and check it before removing it from the handle table
305     // to ensure that the dispatcher is of the correct type. This ensures we
306     // don't close and remove the wrong type of dispatcher.
307     dispatcher = handles_.GetDispatcher(mojo_handle);
308     if (!dispatcher || dispatcher->GetType() != Dispatcher::Type::SHARED_BUFFER)
309       return MOJO_RESULT_INVALID_ARGUMENT;
310 
311     result = handles_.GetAndRemoveDispatcher(mojo_handle, &dispatcher);
312     if (result != MOJO_RESULT_OK)
313       return result;
314   }
315 
316   SharedBufferDispatcher* shm_dispatcher =
317       static_cast<SharedBufferDispatcher*>(dispatcher.get());
318   scoped_refptr<PlatformSharedBuffer> platform_shared_buffer =
319       shm_dispatcher->PassPlatformSharedBuffer();
320 
321   if (!platform_shared_buffer)
322     return MOJO_RESULT_INVALID_ARGUMENT;
323 
324   if (num_bytes)
325     *num_bytes = platform_shared_buffer->GetNumBytes();
326   if (read_only)
327     *read_only = platform_shared_buffer->IsReadOnly();
328   *shared_memory_handle = platform_shared_buffer->DuplicateSharedMemoryHandle();
329 
330   shm_dispatcher->Close();
331   return result;
332 }
333 
RequestShutdown(const base::Closure & callback)334 void Core::RequestShutdown(const base::Closure& callback) {
335   GetNodeController()->RequestShutdown(callback);
336 }
337 
CreateParentMessagePipe(const std::string & token,const std::string & child_token)338 ScopedMessagePipeHandle Core::CreateParentMessagePipe(
339     const std::string& token, const std::string& child_token) {
340   RequestContext request_context;
341   ports::PortRef port0, port1;
342   GetNodeController()->node()->CreatePortPair(&port0, &port1);
343   MojoHandle handle = AddDispatcher(
344       new MessagePipeDispatcher(GetNodeController(), port0,
345                                 kUnknownPipeIdForDebug, 0));
346   GetNodeController()->ReservePort(token, port1, child_token);
347   return ScopedMessagePipeHandle(MessagePipeHandle(handle));
348 }
349 
CreateChildMessagePipe(const std::string & token)350 ScopedMessagePipeHandle Core::CreateChildMessagePipe(const std::string& token) {
351   RequestContext request_context;
352   ports::PortRef port0, port1;
353   GetNodeController()->node()->CreatePortPair(&port0, &port1);
354   MojoHandle handle = AddDispatcher(
355       new MessagePipeDispatcher(GetNodeController(), port0,
356                                 kUnknownPipeIdForDebug, 1));
357   GetNodeController()->MergePortIntoParent(token, port1);
358   return ScopedMessagePipeHandle(MessagePipeHandle(handle));
359 }
360 
SetProperty(MojoPropertyType type,const void * value)361 MojoResult Core::SetProperty(MojoPropertyType type, const void* value) {
362   base::AutoLock locker(property_lock_);
363   switch (type) {
364     case MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED:
365       property_sync_call_allowed_ = *static_cast<const bool*>(value);
366       return MOJO_RESULT_OK;
367     default:
368       return MOJO_RESULT_INVALID_ARGUMENT;
369   }
370 }
371 
GetTimeTicksNow()372 MojoTimeTicks Core::GetTimeTicksNow() {
373   return base::TimeTicks::Now().ToInternalValue();
374 }
375 
Close(MojoHandle handle)376 MojoResult Core::Close(MojoHandle handle) {
377   RequestContext request_context;
378   scoped_refptr<Dispatcher> dispatcher;
379   {
380     base::AutoLock lock(handles_lock_);
381     MojoResult rv = handles_.GetAndRemoveDispatcher(handle, &dispatcher);
382     if (rv != MOJO_RESULT_OK)
383       return rv;
384   }
385   dispatcher->Close();
386   return MOJO_RESULT_OK;
387 }
388 
Wait(MojoHandle handle,MojoHandleSignals signals,MojoDeadline deadline,MojoHandleSignalsState * signals_state)389 MojoResult Core::Wait(MojoHandle handle,
390                       MojoHandleSignals signals,
391                       MojoDeadline deadline,
392                       MojoHandleSignalsState* signals_state) {
393   RequestContext request_context;
394   uint32_t unused = static_cast<uint32_t>(-1);
395   HandleSignalsState hss;
396   MojoResult rv = WaitManyInternal(&handle, &signals, 1, deadline, &unused,
397                                    signals_state ? &hss : nullptr);
398   if (rv != MOJO_RESULT_INVALID_ARGUMENT && signals_state)
399     *signals_state = hss;
400   return rv;
401 }
402 
WaitMany(const MojoHandle * handles,const MojoHandleSignals * signals,uint32_t num_handles,MojoDeadline deadline,uint32_t * result_index,MojoHandleSignalsState * signals_state)403 MojoResult Core::WaitMany(const MojoHandle* handles,
404                           const MojoHandleSignals* signals,
405                           uint32_t num_handles,
406                           MojoDeadline deadline,
407                           uint32_t* result_index,
408                           MojoHandleSignalsState* signals_state) {
409   RequestContext request_context;
410   if (num_handles < 1)
411     return MOJO_RESULT_INVALID_ARGUMENT;
412   if (num_handles > GetConfiguration().max_wait_many_num_handles)
413     return MOJO_RESULT_RESOURCE_EXHAUSTED;
414 
415   uint32_t index = static_cast<uint32_t>(-1);
416   MojoResult rv;
417   if (!signals_state) {
418     rv = WaitManyInternal(handles, signals, num_handles, deadline, &index,
419                           nullptr);
420   } else {
421     // Note: The |reinterpret_cast| is safe, since |HandleSignalsState| is a
422     // subclass of |MojoHandleSignalsState| that doesn't add any data members.
423     rv = WaitManyInternal(handles, signals, num_handles, deadline, &index,
424                           reinterpret_cast<HandleSignalsState*>(signals_state));
425   }
426   if (index != static_cast<uint32_t>(-1) && result_index)
427     *result_index = index;
428   return rv;
429 }
430 
Watch(MojoHandle handle,MojoHandleSignals signals,MojoWatchCallback callback,uintptr_t context)431 MojoResult Core::Watch(MojoHandle handle,
432                        MojoHandleSignals signals,
433                        MojoWatchCallback callback,
434                        uintptr_t context) {
435   RequestContext request_context;
436   scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle);
437   if (!dispatcher)
438     return MOJO_RESULT_INVALID_ARGUMENT;
439   return dispatcher->Watch(
440       signals, base::Bind(&CallWatchCallback, callback, context), context);
441 }
442 
CancelWatch(MojoHandle handle,uintptr_t context)443 MojoResult Core::CancelWatch(MojoHandle handle, uintptr_t context) {
444   RequestContext request_context;
445   scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle);
446   if (!dispatcher)
447     return MOJO_RESULT_INVALID_ARGUMENT;
448   return dispatcher->CancelWatch(context);
449 }
450 
AllocMessage(uint32_t num_bytes,const MojoHandle * handles,uint32_t num_handles,MojoAllocMessageFlags flags,MojoMessageHandle * message)451 MojoResult Core::AllocMessage(uint32_t num_bytes,
452                               const MojoHandle* handles,
453                               uint32_t num_handles,
454                               MojoAllocMessageFlags flags,
455                               MojoMessageHandle* message) {
456   if (!message)
457     return MOJO_RESULT_INVALID_ARGUMENT;
458 
459   if (num_handles == 0) {  // Fast path: no handles.
460     std::unique_ptr<MessageForTransit> msg;
461     MojoResult rv = MessageForTransit::Create(&msg, num_bytes, nullptr, 0);
462     if (rv != MOJO_RESULT_OK)
463       return rv;
464 
465     *message = reinterpret_cast<MojoMessageHandle>(msg.release());
466     return MOJO_RESULT_OK;
467   }
468 
469   if (!handles)
470     return MOJO_RESULT_INVALID_ARGUMENT;
471 
472   if (num_handles > kMaxHandlesPerMessage)
473     return MOJO_RESULT_RESOURCE_EXHAUSTED;
474 
475   std::vector<Dispatcher::DispatcherInTransit> dispatchers;
476   {
477     base::AutoLock lock(handles_lock_);
478     MojoResult rv = handles_.BeginTransit(handles, num_handles, &dispatchers);
479     if (rv != MOJO_RESULT_OK) {
480       handles_.CancelTransit(dispatchers);
481       return rv;
482     }
483   }
484   DCHECK_EQ(num_handles, dispatchers.size());
485 
486   std::unique_ptr<MessageForTransit> msg;
487   MojoResult rv = MessageForTransit::Create(
488       &msg, num_bytes, dispatchers.data(), num_handles);
489 
490   {
491     base::AutoLock lock(handles_lock_);
492     if (rv == MOJO_RESULT_OK) {
493       handles_.CompleteTransitAndClose(dispatchers);
494       *message = reinterpret_cast<MojoMessageHandle>(msg.release());
495     } else {
496       handles_.CancelTransit(dispatchers);
497     }
498   }
499 
500   return rv;
501 }
502 
FreeMessage(MojoMessageHandle message)503 MojoResult Core::FreeMessage(MojoMessageHandle message) {
504   if (!message)
505     return MOJO_RESULT_INVALID_ARGUMENT;
506 
507   delete reinterpret_cast<MessageForTransit*>(message);
508 
509   return MOJO_RESULT_OK;
510 }
511 
GetMessageBuffer(MojoMessageHandle message,void ** buffer)512 MojoResult Core::GetMessageBuffer(MojoMessageHandle message, void** buffer) {
513   if (!message)
514     return MOJO_RESULT_INVALID_ARGUMENT;
515 
516   *buffer = reinterpret_cast<MessageForTransit*>(message)->mutable_bytes();
517 
518   return MOJO_RESULT_OK;
519 }
520 
GetProperty(MojoPropertyType type,void * value)521 MojoResult Core::GetProperty(MojoPropertyType type, void* value) {
522   base::AutoLock locker(property_lock_);
523   switch (type) {
524     case MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED:
525       *static_cast<bool*>(value) = property_sync_call_allowed_;
526       return MOJO_RESULT_OK;
527     default:
528       return MOJO_RESULT_INVALID_ARGUMENT;
529   }
530 }
531 
CreateWaitSet(MojoHandle * wait_set_handle)532 MojoResult Core::CreateWaitSet(MojoHandle* wait_set_handle) {
533   RequestContext request_context;
534   if (!wait_set_handle)
535     return MOJO_RESULT_INVALID_ARGUMENT;
536 
537   scoped_refptr<WaitSetDispatcher> dispatcher = new WaitSetDispatcher();
538   MojoHandle h = AddDispatcher(dispatcher);
539   if (h == MOJO_HANDLE_INVALID) {
540     LOG(ERROR) << "Handle table full";
541     dispatcher->Close();
542     return MOJO_RESULT_RESOURCE_EXHAUSTED;
543   }
544 
545   *wait_set_handle = h;
546   return MOJO_RESULT_OK;
547 }
548 
AddHandle(MojoHandle wait_set_handle,MojoHandle handle,MojoHandleSignals signals)549 MojoResult Core::AddHandle(MojoHandle wait_set_handle,
550                            MojoHandle handle,
551                            MojoHandleSignals signals) {
552   RequestContext request_context;
553   scoped_refptr<Dispatcher> wait_set_dispatcher(GetDispatcher(wait_set_handle));
554   if (!wait_set_dispatcher)
555     return MOJO_RESULT_INVALID_ARGUMENT;
556 
557   scoped_refptr<Dispatcher> dispatcher(GetDispatcher(handle));
558   if (!dispatcher)
559     return MOJO_RESULT_INVALID_ARGUMENT;
560 
561   return wait_set_dispatcher->AddWaitingDispatcher(dispatcher, signals, handle);
562 }
563 
RemoveHandle(MojoHandle wait_set_handle,MojoHandle handle)564 MojoResult Core::RemoveHandle(MojoHandle wait_set_handle,
565                               MojoHandle handle) {
566   RequestContext request_context;
567   scoped_refptr<Dispatcher> wait_set_dispatcher(GetDispatcher(wait_set_handle));
568   if (!wait_set_dispatcher)
569     return MOJO_RESULT_INVALID_ARGUMENT;
570 
571   scoped_refptr<Dispatcher> dispatcher(GetDispatcher(handle));
572   if (!dispatcher)
573     return MOJO_RESULT_INVALID_ARGUMENT;
574 
575   return wait_set_dispatcher->RemoveWaitingDispatcher(dispatcher);
576 }
577 
GetReadyHandles(MojoHandle wait_set_handle,uint32_t * count,MojoHandle * handles,MojoResult * results,MojoHandleSignalsState * signals_states)578 MojoResult Core::GetReadyHandles(MojoHandle wait_set_handle,
579                                  uint32_t* count,
580                                  MojoHandle* handles,
581                                  MojoResult* results,
582                                  MojoHandleSignalsState* signals_states) {
583   RequestContext request_context;
584   if (!handles || !count || !(*count) || !results)
585     return MOJO_RESULT_INVALID_ARGUMENT;
586 
587   scoped_refptr<Dispatcher> wait_set_dispatcher(GetDispatcher(wait_set_handle));
588   if (!wait_set_dispatcher)
589     return MOJO_RESULT_INVALID_ARGUMENT;
590 
591   DispatcherVector awoken_dispatchers;
592   base::StackVector<uintptr_t, 16> contexts;
593   contexts->assign(*count, MOJO_HANDLE_INVALID);
594 
595   MojoResult result = wait_set_dispatcher->GetReadyDispatchers(
596       count, &awoken_dispatchers, results, contexts->data());
597 
598   if (result == MOJO_RESULT_OK) {
599     for (size_t i = 0; i < *count; i++) {
600       handles[i] = static_cast<MojoHandle>(contexts[i]);
601       if (signals_states)
602         signals_states[i] = awoken_dispatchers[i]->GetHandleSignalsState();
603     }
604   }
605 
606   return result;
607 }
608 
CreateMessagePipe(const MojoCreateMessagePipeOptions * options,MojoHandle * message_pipe_handle0,MojoHandle * message_pipe_handle1)609 MojoResult Core::CreateMessagePipe(
610     const MojoCreateMessagePipeOptions* options,
611     MojoHandle* message_pipe_handle0,
612     MojoHandle* message_pipe_handle1) {
613   RequestContext request_context;
614   ports::PortRef port0, port1;
615   GetNodeController()->node()->CreatePortPair(&port0, &port1);
616 
617   CHECK(message_pipe_handle0);
618   CHECK(message_pipe_handle1);
619 
620   uint64_t pipe_id = base::RandUint64();
621 
622   *message_pipe_handle0 = AddDispatcher(
623       new MessagePipeDispatcher(GetNodeController(), port0, pipe_id, 0));
624   if (*message_pipe_handle0 == MOJO_HANDLE_INVALID)
625     return MOJO_RESULT_RESOURCE_EXHAUSTED;
626 
627   *message_pipe_handle1 = AddDispatcher(
628       new MessagePipeDispatcher(GetNodeController(), port1, pipe_id, 1));
629   if (*message_pipe_handle1 == MOJO_HANDLE_INVALID) {
630     scoped_refptr<Dispatcher> unused;
631     unused->Close();
632 
633     base::AutoLock lock(handles_lock_);
634     handles_.GetAndRemoveDispatcher(*message_pipe_handle0, &unused);
635     return MOJO_RESULT_RESOURCE_EXHAUSTED;
636   }
637 
638   return MOJO_RESULT_OK;
639 }
640 
WriteMessage(MojoHandle message_pipe_handle,const void * bytes,uint32_t num_bytes,const MojoHandle * handles,uint32_t num_handles,MojoWriteMessageFlags flags)641 MojoResult Core::WriteMessage(MojoHandle message_pipe_handle,
642                               const void* bytes,
643                               uint32_t num_bytes,
644                               const MojoHandle* handles,
645                               uint32_t num_handles,
646                               MojoWriteMessageFlags flags) {
647   if (num_bytes && !bytes)
648     return MOJO_RESULT_INVALID_ARGUMENT;
649 
650   MojoMessageHandle message;
651   MojoResult rv = AllocMessage(num_bytes, handles, num_handles,
652                                MOJO_ALLOC_MESSAGE_FLAG_NONE, &message);
653   if (rv != MOJO_RESULT_OK)
654     return rv;
655 
656   if (num_bytes) {
657     void* buffer = nullptr;
658     rv = GetMessageBuffer(message, &buffer);
659     DCHECK_EQ(rv, MOJO_RESULT_OK);
660     memcpy(buffer, bytes, num_bytes);
661   }
662 
663   return WriteMessageNew(message_pipe_handle, message, flags);
664 }
665 
WriteMessageNew(MojoHandle message_pipe_handle,MojoMessageHandle message,MojoWriteMessageFlags flags)666 MojoResult Core::WriteMessageNew(MojoHandle message_pipe_handle,
667                                  MojoMessageHandle message,
668                                  MojoWriteMessageFlags flags) {
669   RequestContext request_context;
670   std::unique_ptr<MessageForTransit> message_for_transit(
671       reinterpret_cast<MessageForTransit*>(message));
672   auto dispatcher = GetDispatcher(message_pipe_handle);
673   if (!dispatcher)
674     return MOJO_RESULT_INVALID_ARGUMENT;
675 
676   return dispatcher->WriteMessage(std::move(message_for_transit), flags);
677 }
678 
ReadMessage(MojoHandle message_pipe_handle,void * bytes,uint32_t * num_bytes,MojoHandle * handles,uint32_t * num_handles,MojoReadMessageFlags flags)679 MojoResult Core::ReadMessage(MojoHandle message_pipe_handle,
680                              void* bytes,
681                              uint32_t* num_bytes,
682                              MojoHandle* handles,
683                              uint32_t* num_handles,
684                              MojoReadMessageFlags flags) {
685   CHECK((!num_handles || !*num_handles || handles) &&
686         (!num_bytes || !*num_bytes || bytes));
687   RequestContext request_context;
688   auto dispatcher = GetDispatcher(message_pipe_handle);
689   if (!dispatcher)
690     return MOJO_RESULT_INVALID_ARGUMENT;
691   std::unique_ptr<MessageForTransit> message;
692   MojoResult rv =
693       dispatcher->ReadMessage(&message, num_bytes, handles, num_handles, flags,
694                               false /* ignore_num_bytes */);
695   if (rv != MOJO_RESULT_OK)
696     return rv;
697 
698   if (message && message->num_bytes())
699     memcpy(bytes, message->bytes(), message->num_bytes());
700 
701   return MOJO_RESULT_OK;
702 }
703 
ReadMessageNew(MojoHandle message_pipe_handle,MojoMessageHandle * message,uint32_t * num_bytes,MojoHandle * handles,uint32_t * num_handles,MojoReadMessageFlags flags)704 MojoResult Core::ReadMessageNew(MojoHandle message_pipe_handle,
705                                 MojoMessageHandle* message,
706                                 uint32_t* num_bytes,
707                                 MojoHandle* handles,
708                                 uint32_t* num_handles,
709                                 MojoReadMessageFlags flags) {
710   CHECK(message);
711   CHECK(!num_handles || !*num_handles || handles);
712   RequestContext request_context;
713   auto dispatcher = GetDispatcher(message_pipe_handle);
714   if (!dispatcher)
715     return MOJO_RESULT_INVALID_ARGUMENT;
716   std::unique_ptr<MessageForTransit> msg;
717   MojoResult rv =
718       dispatcher->ReadMessage(&msg, num_bytes, handles, num_handles, flags,
719                               true /* ignore_num_bytes */);
720   if (rv != MOJO_RESULT_OK)
721     return rv;
722   *message = reinterpret_cast<MojoMessageHandle>(msg.release());
723   return MOJO_RESULT_OK;
724 }
725 
FuseMessagePipes(MojoHandle handle0,MojoHandle handle1)726 MojoResult Core::FuseMessagePipes(MojoHandle handle0, MojoHandle handle1) {
727   RequestContext request_context;
728   scoped_refptr<Dispatcher> dispatcher0;
729   scoped_refptr<Dispatcher> dispatcher1;
730 
731   bool valid_handles = true;
732   {
733     base::AutoLock lock(handles_lock_);
734     MojoResult result0 = handles_.GetAndRemoveDispatcher(handle0, &dispatcher0);
735     MojoResult result1 = handles_.GetAndRemoveDispatcher(handle1, &dispatcher1);
736     if (result0 != MOJO_RESULT_OK || result1 != MOJO_RESULT_OK ||
737         dispatcher0->GetType() != Dispatcher::Type::MESSAGE_PIPE ||
738         dispatcher1->GetType() != Dispatcher::Type::MESSAGE_PIPE)
739       valid_handles = false;
740   }
741 
742   if (!valid_handles) {
743     if (dispatcher0)
744       dispatcher0->Close();
745     if (dispatcher1)
746       dispatcher1->Close();
747     return MOJO_RESULT_INVALID_ARGUMENT;
748   }
749 
750   MessagePipeDispatcher* mpd0 =
751       static_cast<MessagePipeDispatcher*>(dispatcher0.get());
752   MessagePipeDispatcher* mpd1 =
753       static_cast<MessagePipeDispatcher*>(dispatcher1.get());
754 
755   if (!mpd0->Fuse(mpd1))
756     return MOJO_RESULT_FAILED_PRECONDITION;
757 
758   return MOJO_RESULT_OK;
759 }
760 
NotifyBadMessage(MojoMessageHandle message,const char * error,size_t error_num_bytes)761 MojoResult Core::NotifyBadMessage(MojoMessageHandle message,
762                                   const char* error,
763                                   size_t error_num_bytes) {
764   if (!message)
765     return MOJO_RESULT_INVALID_ARGUMENT;
766 
767   const PortsMessage& ports_message =
768       reinterpret_cast<MessageForTransit*>(message)->ports_message();
769   if (ports_message.source_node() == ports::kInvalidNodeName) {
770     DVLOG(1) << "Received invalid message from unknown node.";
771     if (!default_process_error_callback_.is_null())
772       default_process_error_callback_.Run(std::string(error, error_num_bytes));
773     return MOJO_RESULT_OK;
774   }
775 
776   GetNodeController()->NotifyBadMessageFrom(
777       ports_message.source_node(), std::string(error, error_num_bytes));
778   return MOJO_RESULT_OK;
779 }
780 
CreateDataPipe(const MojoCreateDataPipeOptions * options,MojoHandle * data_pipe_producer_handle,MojoHandle * data_pipe_consumer_handle)781 MojoResult Core::CreateDataPipe(
782     const MojoCreateDataPipeOptions* options,
783     MojoHandle* data_pipe_producer_handle,
784     MojoHandle* data_pipe_consumer_handle) {
785   RequestContext request_context;
786   if (options && options->struct_size != sizeof(MojoCreateDataPipeOptions))
787     return MOJO_RESULT_INVALID_ARGUMENT;
788 
789   MojoCreateDataPipeOptions create_options;
790   create_options.struct_size = sizeof(MojoCreateDataPipeOptions);
791   create_options.flags = options ? options->flags : 0;
792   create_options.element_num_bytes = options ? options->element_num_bytes : 1;
793   // TODO(rockot): Use Configuration to get default data pipe capacity.
794   create_options.capacity_num_bytes =
795       options && options->capacity_num_bytes ? options->capacity_num_bytes
796                                              : 64 * 1024;
797 
798   // TODO(rockot): Broker through the parent when necessary.
799   scoped_refptr<PlatformSharedBuffer> ring_buffer =
800       GetNodeController()->CreateSharedBuffer(
801           create_options.capacity_num_bytes);
802   if (!ring_buffer)
803     return MOJO_RESULT_RESOURCE_EXHAUSTED;
804 
805   ports::PortRef port0, port1;
806   GetNodeController()->node()->CreatePortPair(&port0, &port1);
807 
808   CHECK(data_pipe_producer_handle);
809   CHECK(data_pipe_consumer_handle);
810 
811   uint64_t pipe_id = base::RandUint64();
812 
813   scoped_refptr<Dispatcher> producer = new DataPipeProducerDispatcher(
814       GetNodeController(), port0, ring_buffer, create_options,
815       true /* initialized */, pipe_id);
816   scoped_refptr<Dispatcher> consumer = new DataPipeConsumerDispatcher(
817       GetNodeController(), port1, ring_buffer, create_options,
818       true /* initialized */, pipe_id);
819 
820   *data_pipe_producer_handle = AddDispatcher(producer);
821   *data_pipe_consumer_handle = AddDispatcher(consumer);
822   if (*data_pipe_producer_handle == MOJO_HANDLE_INVALID ||
823       *data_pipe_consumer_handle == MOJO_HANDLE_INVALID) {
824     if (*data_pipe_producer_handle != MOJO_HANDLE_INVALID) {
825       scoped_refptr<Dispatcher> unused;
826       base::AutoLock lock(handles_lock_);
827       handles_.GetAndRemoveDispatcher(*data_pipe_producer_handle, &unused);
828     }
829     producer->Close();
830     consumer->Close();
831     return MOJO_RESULT_RESOURCE_EXHAUSTED;
832   }
833 
834   return MOJO_RESULT_OK;
835 }
836 
WriteData(MojoHandle data_pipe_producer_handle,const void * elements,uint32_t * num_bytes,MojoWriteDataFlags flags)837 MojoResult Core::WriteData(MojoHandle data_pipe_producer_handle,
838                            const void* elements,
839                            uint32_t* num_bytes,
840                            MojoWriteDataFlags flags) {
841   RequestContext request_context;
842   scoped_refptr<Dispatcher> dispatcher(
843       GetDispatcher(data_pipe_producer_handle));
844   if (!dispatcher)
845     return MOJO_RESULT_INVALID_ARGUMENT;
846 
847   return dispatcher->WriteData(elements, num_bytes, flags);
848 }
849 
BeginWriteData(MojoHandle data_pipe_producer_handle,void ** buffer,uint32_t * buffer_num_bytes,MojoWriteDataFlags flags)850 MojoResult Core::BeginWriteData(MojoHandle data_pipe_producer_handle,
851                                 void** buffer,
852                                 uint32_t* buffer_num_bytes,
853                                 MojoWriteDataFlags flags) {
854   RequestContext request_context;
855   scoped_refptr<Dispatcher> dispatcher(
856       GetDispatcher(data_pipe_producer_handle));
857   if (!dispatcher)
858     return MOJO_RESULT_INVALID_ARGUMENT;
859 
860   return dispatcher->BeginWriteData(buffer, buffer_num_bytes, flags);
861 }
862 
EndWriteData(MojoHandle data_pipe_producer_handle,uint32_t num_bytes_written)863 MojoResult Core::EndWriteData(MojoHandle data_pipe_producer_handle,
864                               uint32_t num_bytes_written) {
865   RequestContext request_context;
866   scoped_refptr<Dispatcher> dispatcher(
867       GetDispatcher(data_pipe_producer_handle));
868   if (!dispatcher)
869     return MOJO_RESULT_INVALID_ARGUMENT;
870 
871   return dispatcher->EndWriteData(num_bytes_written);
872 }
873 
ReadData(MojoHandle data_pipe_consumer_handle,void * elements,uint32_t * num_bytes,MojoReadDataFlags flags)874 MojoResult Core::ReadData(MojoHandle data_pipe_consumer_handle,
875                           void* elements,
876                           uint32_t* num_bytes,
877                           MojoReadDataFlags flags) {
878   RequestContext request_context;
879   scoped_refptr<Dispatcher> dispatcher(
880       GetDispatcher(data_pipe_consumer_handle));
881   if (!dispatcher)
882     return MOJO_RESULT_INVALID_ARGUMENT;
883 
884   return dispatcher->ReadData(elements, num_bytes, flags);
885 }
886 
BeginReadData(MojoHandle data_pipe_consumer_handle,const void ** buffer,uint32_t * buffer_num_bytes,MojoReadDataFlags flags)887 MojoResult Core::BeginReadData(MojoHandle data_pipe_consumer_handle,
888                                const void** buffer,
889                                uint32_t* buffer_num_bytes,
890                                MojoReadDataFlags flags) {
891   RequestContext request_context;
892   scoped_refptr<Dispatcher> dispatcher(
893       GetDispatcher(data_pipe_consumer_handle));
894   if (!dispatcher)
895     return MOJO_RESULT_INVALID_ARGUMENT;
896 
897   return dispatcher->BeginReadData(buffer, buffer_num_bytes, flags);
898 }
899 
EndReadData(MojoHandle data_pipe_consumer_handle,uint32_t num_bytes_read)900 MojoResult Core::EndReadData(MojoHandle data_pipe_consumer_handle,
901                              uint32_t num_bytes_read) {
902   RequestContext request_context;
903   scoped_refptr<Dispatcher> dispatcher(
904       GetDispatcher(data_pipe_consumer_handle));
905   if (!dispatcher)
906     return MOJO_RESULT_INVALID_ARGUMENT;
907 
908   return dispatcher->EndReadData(num_bytes_read);
909 }
910 
CreateSharedBuffer(const MojoCreateSharedBufferOptions * options,uint64_t num_bytes,MojoHandle * shared_buffer_handle)911 MojoResult Core::CreateSharedBuffer(
912     const MojoCreateSharedBufferOptions* options,
913     uint64_t num_bytes,
914     MojoHandle* shared_buffer_handle) {
915   RequestContext request_context;
916   MojoCreateSharedBufferOptions validated_options = {};
917   MojoResult result = SharedBufferDispatcher::ValidateCreateOptions(
918       options, &validated_options);
919   if (result != MOJO_RESULT_OK)
920     return result;
921 
922   scoped_refptr<SharedBufferDispatcher> dispatcher;
923   result = SharedBufferDispatcher::Create(
924       validated_options, GetNodeController(), num_bytes, &dispatcher);
925   if (result != MOJO_RESULT_OK) {
926     DCHECK(!dispatcher);
927     return result;
928   }
929 
930   *shared_buffer_handle = AddDispatcher(dispatcher);
931   if (*shared_buffer_handle == MOJO_HANDLE_INVALID) {
932     LOG(ERROR) << "Handle table full";
933     dispatcher->Close();
934     return MOJO_RESULT_RESOURCE_EXHAUSTED;
935   }
936 
937   return MOJO_RESULT_OK;
938 }
939 
DuplicateBufferHandle(MojoHandle buffer_handle,const MojoDuplicateBufferHandleOptions * options,MojoHandle * new_buffer_handle)940 MojoResult Core::DuplicateBufferHandle(
941     MojoHandle buffer_handle,
942     const MojoDuplicateBufferHandleOptions* options,
943     MojoHandle* new_buffer_handle) {
944   RequestContext request_context;
945   scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle));
946   if (!dispatcher)
947     return MOJO_RESULT_INVALID_ARGUMENT;
948 
949   // Don't verify |options| here; that's the dispatcher's job.
950   scoped_refptr<Dispatcher> new_dispatcher;
951   MojoResult result =
952       dispatcher->DuplicateBufferHandle(options, &new_dispatcher);
953   if (result != MOJO_RESULT_OK)
954     return result;
955 
956   *new_buffer_handle = AddDispatcher(new_dispatcher);
957   if (*new_buffer_handle == MOJO_HANDLE_INVALID) {
958     LOG(ERROR) << "Handle table full";
959     dispatcher->Close();
960     return MOJO_RESULT_RESOURCE_EXHAUSTED;
961   }
962 
963   return MOJO_RESULT_OK;
964 }
965 
MapBuffer(MojoHandle buffer_handle,uint64_t offset,uint64_t num_bytes,void ** buffer,MojoMapBufferFlags flags)966 MojoResult Core::MapBuffer(MojoHandle buffer_handle,
967                            uint64_t offset,
968                            uint64_t num_bytes,
969                            void** buffer,
970                            MojoMapBufferFlags flags) {
971   RequestContext request_context;
972   scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle));
973   if (!dispatcher)
974     return MOJO_RESULT_INVALID_ARGUMENT;
975 
976   std::unique_ptr<PlatformSharedBufferMapping> mapping;
977   MojoResult result = dispatcher->MapBuffer(offset, num_bytes, flags, &mapping);
978   if (result != MOJO_RESULT_OK)
979     return result;
980 
981   DCHECK(mapping);
982   void* address = mapping->GetBase();
983   {
984     base::AutoLock locker(mapping_table_lock_);
985     result = mapping_table_.AddMapping(std::move(mapping));
986   }
987   if (result != MOJO_RESULT_OK)
988     return result;
989 
990   *buffer = address;
991   return MOJO_RESULT_OK;
992 }
993 
UnmapBuffer(void * buffer)994 MojoResult Core::UnmapBuffer(void* buffer) {
995   RequestContext request_context;
996   base::AutoLock lock(mapping_table_lock_);
997   return mapping_table_.RemoveMapping(buffer);
998 }
999 
WrapPlatformHandle(const MojoPlatformHandle * platform_handle,MojoHandle * mojo_handle)1000 MojoResult Core::WrapPlatformHandle(const MojoPlatformHandle* platform_handle,
1001                                     MojoHandle* mojo_handle) {
1002   ScopedPlatformHandle handle;
1003   MojoResult result = MojoPlatformHandleToScopedPlatformHandle(platform_handle,
1004                                                                &handle);
1005   if (result != MOJO_RESULT_OK)
1006     return result;
1007 
1008   return CreatePlatformHandleWrapper(std::move(handle), mojo_handle);
1009 }
1010 
UnwrapPlatformHandle(MojoHandle mojo_handle,MojoPlatformHandle * platform_handle)1011 MojoResult Core::UnwrapPlatformHandle(MojoHandle mojo_handle,
1012                                       MojoPlatformHandle* platform_handle) {
1013   ScopedPlatformHandle handle;
1014   MojoResult result = PassWrappedPlatformHandle(mojo_handle, &handle);
1015   if (result != MOJO_RESULT_OK)
1016     return result;
1017 
1018   return ScopedPlatformHandleToMojoPlatformHandle(std::move(handle),
1019                                                   platform_handle);
1020 }
1021 
WrapPlatformSharedBufferHandle(const MojoPlatformHandle * platform_handle,size_t size,MojoPlatformSharedBufferHandleFlags flags,MojoHandle * mojo_handle)1022 MojoResult Core::WrapPlatformSharedBufferHandle(
1023     const MojoPlatformHandle* platform_handle,
1024     size_t size,
1025     MojoPlatformSharedBufferHandleFlags flags,
1026     MojoHandle* mojo_handle) {
1027   DCHECK(size);
1028   ScopedPlatformHandle handle;
1029   MojoResult result = MojoPlatformHandleToScopedPlatformHandle(platform_handle,
1030                                                                &handle);
1031   if (result != MOJO_RESULT_OK)
1032     return result;
1033 
1034   bool read_only = flags & MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_READ_ONLY;
1035   scoped_refptr<PlatformSharedBuffer> platform_buffer =
1036       PlatformSharedBuffer::CreateFromPlatformHandle(size, read_only,
1037                                                      std::move(handle));
1038   if (!platform_buffer)
1039     return MOJO_RESULT_UNKNOWN;
1040 
1041   scoped_refptr<SharedBufferDispatcher> dispatcher;
1042   result = SharedBufferDispatcher::CreateFromPlatformSharedBuffer(
1043       platform_buffer, &dispatcher);
1044   if (result != MOJO_RESULT_OK)
1045     return result;
1046 
1047   MojoHandle h = AddDispatcher(dispatcher);
1048   if (h == MOJO_HANDLE_INVALID) {
1049     dispatcher->Close();
1050     return MOJO_RESULT_RESOURCE_EXHAUSTED;
1051   }
1052 
1053   *mojo_handle = h;
1054   return MOJO_RESULT_OK;
1055 }
1056 
UnwrapPlatformSharedBufferHandle(MojoHandle mojo_handle,MojoPlatformHandle * platform_handle,size_t * size,MojoPlatformSharedBufferHandleFlags * flags)1057 MojoResult Core::UnwrapPlatformSharedBufferHandle(
1058     MojoHandle mojo_handle,
1059     MojoPlatformHandle* platform_handle,
1060     size_t* size,
1061     MojoPlatformSharedBufferHandleFlags* flags) {
1062   scoped_refptr<Dispatcher> dispatcher;
1063   MojoResult result = MOJO_RESULT_OK;
1064   {
1065     base::AutoLock lock(handles_lock_);
1066     result = handles_.GetAndRemoveDispatcher(mojo_handle, &dispatcher);
1067     if (result != MOJO_RESULT_OK)
1068       return result;
1069   }
1070 
1071   if (dispatcher->GetType() != Dispatcher::Type::SHARED_BUFFER) {
1072     dispatcher->Close();
1073     return MOJO_RESULT_INVALID_ARGUMENT;
1074   }
1075 
1076   SharedBufferDispatcher* shm_dispatcher =
1077       static_cast<SharedBufferDispatcher*>(dispatcher.get());
1078   scoped_refptr<PlatformSharedBuffer> platform_shared_buffer =
1079       shm_dispatcher->PassPlatformSharedBuffer();
1080   CHECK(platform_shared_buffer);
1081 
1082   CHECK(size);
1083   *size = platform_shared_buffer->GetNumBytes();
1084 
1085   CHECK(flags);
1086   *flags = MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_NONE;
1087   if (platform_shared_buffer->IsReadOnly())
1088     *flags |= MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_READ_ONLY;
1089 
1090   ScopedPlatformHandle handle = platform_shared_buffer->PassPlatformHandle();
1091   return ScopedPlatformHandleToMojoPlatformHandle(std::move(handle),
1092                                                   platform_handle);
1093 }
1094 
GetActiveHandlesForTest(std::vector<MojoHandle> * handles)1095 void Core::GetActiveHandlesForTest(std::vector<MojoHandle>* handles) {
1096   base::AutoLock lock(handles_lock_);
1097   handles_.GetActiveHandlesForTest(handles);
1098 }
1099 
WaitManyInternal(const MojoHandle * handles,const MojoHandleSignals * signals,uint32_t num_handles,MojoDeadline deadline,uint32_t * result_index,HandleSignalsState * signals_states)1100 MojoResult Core::WaitManyInternal(const MojoHandle* handles,
1101                                   const MojoHandleSignals* signals,
1102                                   uint32_t num_handles,
1103                                   MojoDeadline deadline,
1104                                   uint32_t* result_index,
1105                                   HandleSignalsState* signals_states) {
1106   CHECK(handles);
1107   CHECK(signals);
1108   DCHECK_GT(num_handles, 0u);
1109   if (result_index) {
1110     DCHECK_EQ(*result_index, static_cast<uint32_t>(-1));
1111   }
1112 
1113   // The primary caller of |WaitManyInternal()| is |Wait()|, which only waits on
1114   // a single handle. In the common case of a single handle, this avoid a heap
1115   // allocation.
1116   base::StackVector<scoped_refptr<Dispatcher>, 1> dispatchers;
1117   dispatchers->reserve(num_handles);
1118   for (uint32_t i = 0; i < num_handles; i++) {
1119     scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handles[i]);
1120     if (!dispatcher) {
1121       if (result_index)
1122         *result_index = i;
1123       return MOJO_RESULT_INVALID_ARGUMENT;
1124     }
1125     dispatchers->push_back(dispatcher);
1126   }
1127 
1128   // TODO(vtl): Should make the waiter live (permanently) in TLS.
1129   Waiter waiter;
1130   waiter.Init();
1131 
1132   uint32_t i;
1133   MojoResult rv = MOJO_RESULT_OK;
1134   for (i = 0; i < num_handles; i++) {
1135     rv = dispatchers[i]->AddAwakable(
1136         &waiter, signals[i], i, signals_states ? &signals_states[i] : nullptr);
1137     if (rv != MOJO_RESULT_OK) {
1138       if (result_index)
1139         *result_index = i;
1140       break;
1141     }
1142   }
1143   uint32_t num_added = i;
1144 
1145   if (rv == MOJO_RESULT_ALREADY_EXISTS) {
1146     rv = MOJO_RESULT_OK;  // The i-th one is already "triggered".
1147   } else if (rv == MOJO_RESULT_OK) {
1148     uintptr_t uintptr_result = *result_index;
1149     rv = waiter.Wait(deadline, &uintptr_result);
1150     *result_index = static_cast<uint32_t>(uintptr_result);
1151   }
1152 
1153   // Make sure no other dispatchers try to wake |waiter| for the current
1154   // |Wait()|/|WaitMany()| call. (Only after doing this can |waiter| be
1155   // destroyed, but this would still be required if the waiter were in TLS.)
1156   for (i = 0; i < num_added; i++) {
1157     dispatchers[i]->RemoveAwakable(
1158         &waiter, signals_states ? &signals_states[i] : nullptr);
1159   }
1160   if (signals_states) {
1161     for (; i < num_handles; i++)
1162       signals_states[i] = dispatchers[i]->GetHandleSignalsState();
1163   }
1164 
1165   return rv;
1166 }
1167 
1168 // static
PassNodeControllerToIOThread(std::unique_ptr<NodeController> node_controller)1169 void Core::PassNodeControllerToIOThread(
1170     std::unique_ptr<NodeController> node_controller) {
1171   // It's OK to leak this reference. At this point we know the IO loop is still
1172   // running, and we know the NodeController will observe its eventual
1173   // destruction. This tells the NodeController to delete itself when that
1174   // happens.
1175   node_controller.release()->DestroyOnIOThreadShutdown();
1176 }
1177 
1178 }  // namespace edk
1179 }  // namespace mojo
1180