core.cc 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538
  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. #include "mojo/core/core.h"
  5. #include <string.h>
  6. #include <algorithm>
  7. #include <memory>
  8. #include <utility>
  9. #include "base/bind.h"
  10. #include "base/containers/stack_container.h"
  11. #include "base/location.h"
  12. #include "base/logging.h"
  13. #include "base/memory/ptr_util.h"
  14. #include "base/memory/writable_shared_memory_region.h"
  15. #include "base/rand_util.h"
  16. #include "base/strings/string_number_conversions.h"
  17. #include "base/strings/string_piece.h"
  18. #include "base/threading/thread_task_runner_handle.h"
  19. #include "base/time/time.h"
  20. #include "base/trace_event/memory_dump_manager.h"
  21. #include "base/trace_event/trace_id_helper.h"
  22. #include "build/build_config.h"
  23. #include "mojo/core/channel.h"
  24. #include "mojo/core/configuration.h"
  25. #include "mojo/core/data_pipe_consumer_dispatcher.h"
  26. #include "mojo/core/data_pipe_producer_dispatcher.h"
  27. #include "mojo/core/embedder/process_error_callback.h"
  28. #include "mojo/core/handle_signals_state.h"
  29. #include "mojo/core/invitation_dispatcher.h"
  30. #include "mojo/core/message_pipe_dispatcher.h"
  31. #include "mojo/core/platform_handle_dispatcher.h"
  32. #include "mojo/core/platform_handle_utils.h"
  33. #include "mojo/core/platform_shared_memory_mapping.h"
  34. #include "mojo/core/ports/event.h"
  35. #include "mojo/core/ports/name.h"
  36. #include "mojo/core/ports/node.h"
  37. #include "mojo/core/request_context.h"
  38. #include "mojo/core/shared_buffer_dispatcher.h"
  39. #include "mojo/core/user_message_impl.h"
  40. #include "mojo/core/watcher_dispatcher.h"
  41. #include "mojo/public/cpp/bindings/mojo_buildflags.h"
  42. #include "mojo/public/cpp/platform/platform_handle_internal.h"
  43. namespace mojo {
  44. namespace core {
  45. namespace {
  46. // This is an unnecessarily large limit that is relatively easy to enforce.
  47. const uint32_t kMaxHandlesPerMessage = 1024 * 1024;
  48. // TODO(rockot): Maybe we could negotiate a debugging pipe ID for cross-process
  49. // pipes too; for now we just use a constant. This only affects bootstrap pipes.
  50. const uint64_t kUnknownPipeIdForDebug = 0x7f7f7f7f7f7f7f7fUL;
  51. // The pipe name which must be used for the sole pipe attachment on any isolated
  52. // invitation.
  53. constexpr base::StringPiece kIsolatedInvitationPipeName = {"\0\0\0\0", 4};
  54. // Set according to the field trial "MojoAvoidRandomPipeId".
  55. bool g_avoid_random_pipe_id;
  56. void InvokeProcessErrorCallback(MojoProcessErrorHandler handler,
  57. uintptr_t context,
  58. const std::string& error,
  59. MojoProcessErrorFlags flags) {
  60. MojoProcessErrorDetails details;
  61. details.struct_size = sizeof(details);
  62. DCHECK(base::IsValueInRangeForNumericType<uint32_t>(error.size()));
  63. details.error_message_length = static_cast<uint32_t>(error.size());
  64. if (!error.empty())
  65. details.error_message = error.data();
  66. else
  67. details.error_message = nullptr;
  68. details.flags = flags;
  69. handler(context, &details);
  70. }
  71. // Helper class which is bound to the lifetime of a
  72. // ProcessErrorCallback generated by the |MojoSendInvitation()|
  73. // API. When the last reference to the error callback is lost within the EDK,
  74. // which will happen shortly after a connection to the process is lost, that
  75. // obviously guarantees that no more invocations of the callback will occur. At
  76. // that point, the corresponding instance of this object (owned by the callback
  77. // -- see Core::SendInvitation) will be destroyed.
  78. class ProcessDisconnectHandler {
  79. public:
  80. ProcessDisconnectHandler(MojoProcessErrorHandler handler, uintptr_t context)
  81. : handler_(handler), context_(context) {}
  82. ProcessDisconnectHandler(const ProcessDisconnectHandler&) = delete;
  83. ProcessDisconnectHandler& operator=(const ProcessDisconnectHandler&) = delete;
  84. ~ProcessDisconnectHandler() {
  85. InvokeProcessErrorCallback(handler_, context_, std::string(),
  86. MOJO_PROCESS_ERROR_FLAG_DISCONNECTED);
  87. }
  88. private:
  89. const MojoProcessErrorHandler handler_;
  90. const uintptr_t context_;
  91. };
  92. void RunMojoProcessErrorHandler(
  93. ProcessDisconnectHandler* disconnect_handler,
  94. MojoProcessErrorHandler handler,
  95. uintptr_t context,
  96. const std::string& error) {
  97. InvokeProcessErrorCallback(handler, context, error,
  98. MOJO_PROCESS_ERROR_FLAG_NONE);
  99. }
  100. uint64_t MakePipeId() {
  101. #if BUILDFLAG(MOJO_TRACE_ENABLED)
  102. return base::trace_event::GetNextGlobalTraceId();
  103. #else
  104. if (g_avoid_random_pipe_id)
  105. return 0;
  106. return base::RandUint64();
  107. #endif
  108. }
  109. } // namespace
  110. Core::Core() {
  111. handles_ = std::make_unique<HandleTable>();
  112. base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
  113. handles_.get(), "MojoHandleTable", nullptr);
  114. }
  115. Core::~Core() {
  116. if (node_controller_ && node_controller_->io_task_runner()) {
  117. // If this races with IO thread shutdown the callback will be dropped and
  118. // the NodeController will be shutdown on this thread anyway, which is also
  119. // just fine.
  120. auto io_task_runner = node_controller_->io_task_runner();
  121. io_task_runner->PostTask(FROM_HERE,
  122. base::BindOnce(&Core::PassNodeControllerToIOThread,
  123. std::move(node_controller_)));
  124. }
  125. base::trace_event::MemoryDumpManager::GetInstance()
  126. ->UnregisterAndDeleteDumpProviderSoon(std::move(handles_));
  127. }
  128. void Core::SetIOTaskRunner(
  129. scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) {
  130. GetNodeController()->SetIOTaskRunner(std::move(io_task_runner));
  131. }
  132. NodeController* Core::GetNodeController() {
  133. base::AutoLock lock(node_controller_lock_);
  134. if (!node_controller_)
  135. node_controller_ = std::make_unique<NodeController>();
  136. return node_controller_.get();
  137. }
  138. scoped_refptr<Dispatcher> Core::GetDispatcher(MojoHandle handle) {
  139. base::AutoLock lock(handles_->GetLock());
  140. return handles_->GetDispatcher(handle);
  141. }
  142. scoped_refptr<Dispatcher> Core::GetAndRemoveDispatcher(MojoHandle handle) {
  143. scoped_refptr<Dispatcher> dispatcher;
  144. base::AutoLock lock(handles_->GetLock());
  145. handles_->GetAndRemoveDispatcher(handle, &dispatcher);
  146. return dispatcher;
  147. }
  148. MojoHandle Core::CreatePartialMessagePipe(ports::PortRef* peer) {
  149. RequestContext request_context;
  150. ports::PortRef local_port;
  151. GetNodeController()->node()->CreatePortPair(&local_port, peer);
  152. return AddDispatcher(new MessagePipeDispatcher(
  153. GetNodeController(), local_port, kUnknownPipeIdForDebug, 0));
  154. }
  155. MojoHandle Core::CreatePartialMessagePipe(const ports::PortRef& port) {
  156. RequestContext request_context;
  157. return AddDispatcher(new MessagePipeDispatcher(GetNodeController(), port,
  158. kUnknownPipeIdForDebug, 1));
  159. }
  160. void Core::SendBrokerClientInvitation(
  161. base::Process target_process,
  162. ConnectionParams connection_params,
  163. const std::vector<std::pair<std::string, ports::PortRef>>& attached_ports,
  164. const ProcessErrorCallback& process_error_callback) {
  165. RequestContext request_context;
  166. GetNodeController()->SendBrokerClientInvitation(
  167. std::move(target_process), std::move(connection_params), attached_ports,
  168. process_error_callback);
  169. }
  170. void Core::ConnectIsolated(ConnectionParams connection_params,
  171. const ports::PortRef& port,
  172. base::StringPiece connection_name) {
  173. RequestContext request_context;
  174. GetNodeController()->ConnectIsolated(std::move(connection_params), port,
  175. connection_name);
  176. }
  177. MojoHandle Core::AddDispatcher(scoped_refptr<Dispatcher> dispatcher) {
  178. base::AutoLock lock(handles_->GetLock());
  179. return handles_->AddDispatcher(dispatcher);
  180. }
  181. bool Core::AddDispatchersFromTransit(
  182. const std::vector<Dispatcher::DispatcherInTransit>& dispatchers,
  183. MojoHandle* handles) {
  184. bool failed = false;
  185. {
  186. base::AutoLock lock(handles_->GetLock());
  187. if (!handles_->AddDispatchersFromTransit(dispatchers, handles))
  188. failed = true;
  189. }
  190. if (failed) {
  191. for (auto d : dispatchers) {
  192. if (d.dispatcher)
  193. d.dispatcher->Close();
  194. }
  195. return false;
  196. }
  197. return true;
  198. }
  199. MojoResult Core::AcquireDispatchersForTransit(
  200. const MojoHandle* handles,
  201. size_t num_handles,
  202. std::vector<Dispatcher::DispatcherInTransit>* dispatchers) {
  203. base::AutoLock lock(handles_->GetLock());
  204. MojoResult rv = handles_->BeginTransit(handles, num_handles, dispatchers);
  205. if (rv != MOJO_RESULT_OK)
  206. handles_->CancelTransit(*dispatchers);
  207. return rv;
  208. }
  209. void Core::ReleaseDispatchersForTransit(
  210. const std::vector<Dispatcher::DispatcherInTransit>& dispatchers,
  211. bool in_transit) {
  212. base::AutoLock lock(handles_->GetLock());
  213. if (in_transit)
  214. handles_->CompleteTransitAndClose(dispatchers);
  215. else
  216. handles_->CancelTransit(dispatchers);
  217. }
  218. void Core::RequestShutdown(base::OnceClosure callback) {
  219. GetNodeController()->RequestShutdown(std::move(callback));
  220. }
  221. MojoHandle Core::ExtractMessagePipeFromInvitation(const std::string& name) {
  222. RequestContext request_context;
  223. ports::PortRef port0, port1;
  224. GetNodeController()->node()->CreatePortPair(&port0, &port1);
  225. MojoHandle handle = AddDispatcher(new MessagePipeDispatcher(
  226. GetNodeController(), port0, kUnknownPipeIdForDebug, 1));
  227. GetNodeController()->MergePortIntoInviter(name, port1);
  228. return handle;
  229. }
  230. MojoTimeTicks Core::GetTimeTicksNow() {
  231. return base::TimeTicks::Now().ToInternalValue();
  232. }
  233. MojoResult Core::Close(MojoHandle handle) {
  234. RequestContext request_context;
  235. scoped_refptr<Dispatcher> dispatcher;
  236. {
  237. base::AutoLock lock(handles_->GetLock());
  238. MojoResult rv = handles_->GetAndRemoveDispatcher(handle, &dispatcher);
  239. if (rv != MOJO_RESULT_OK)
  240. return rv;
  241. }
  242. dispatcher->Close();
  243. return MOJO_RESULT_OK;
  244. }
  245. MojoResult Core::QueryHandleSignalsState(
  246. MojoHandle handle,
  247. MojoHandleSignalsState* signals_state) {
  248. RequestContext request_context;
  249. scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle);
  250. if (!dispatcher || !signals_state)
  251. return MOJO_RESULT_INVALID_ARGUMENT;
  252. *signals_state = dispatcher->GetHandleSignalsState();
  253. return MOJO_RESULT_OK;
  254. }
  255. MojoResult Core::CreateTrap(MojoTrapEventHandler handler,
  256. const MojoCreateTrapOptions* options,
  257. MojoHandle* trap_handle) {
  258. if (options && options->struct_size < sizeof(*options))
  259. return MOJO_RESULT_INVALID_ARGUMENT;
  260. RequestContext request_context;
  261. if (!trap_handle)
  262. return MOJO_RESULT_INVALID_ARGUMENT;
  263. *trap_handle = AddDispatcher(new WatcherDispatcher(handler));
  264. if (*trap_handle == MOJO_HANDLE_INVALID)
  265. return MOJO_RESULT_RESOURCE_EXHAUSTED;
  266. return MOJO_RESULT_OK;
  267. }
  268. MojoResult Core::AddTrigger(MojoHandle trap_handle,
  269. MojoHandle handle,
  270. MojoHandleSignals signals,
  271. MojoTriggerCondition condition,
  272. uintptr_t context,
  273. const MojoAddTriggerOptions* options) {
  274. if (options && options->struct_size < sizeof(*options))
  275. return MOJO_RESULT_INVALID_ARGUMENT;
  276. RequestContext request_context;
  277. scoped_refptr<Dispatcher> watcher = GetDispatcher(trap_handle);
  278. if (!watcher || watcher->GetType() != Dispatcher::Type::WATCHER)
  279. return MOJO_RESULT_INVALID_ARGUMENT;
  280. scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle);
  281. if (!dispatcher)
  282. return MOJO_RESULT_INVALID_ARGUMENT;
  283. return watcher->WatchDispatcher(std::move(dispatcher), signals, condition,
  284. context);
  285. }
  286. MojoResult Core::RemoveTrigger(MojoHandle trap_handle,
  287. uintptr_t context,
  288. const MojoRemoveTriggerOptions* options) {
  289. if (options && options->struct_size < sizeof(*options))
  290. return MOJO_RESULT_INVALID_ARGUMENT;
  291. RequestContext request_context;
  292. scoped_refptr<Dispatcher> watcher = GetDispatcher(trap_handle);
  293. if (!watcher || watcher->GetType() != Dispatcher::Type::WATCHER)
  294. return MOJO_RESULT_INVALID_ARGUMENT;
  295. return watcher->CancelWatch(context);
  296. }
  297. MojoResult Core::ArmTrap(MojoHandle trap_handle,
  298. const MojoArmTrapOptions* options,
  299. uint32_t* num_blocking_events,
  300. MojoTrapEvent* blocking_events) {
  301. if (options && options->struct_size < sizeof(*options))
  302. return MOJO_RESULT_INVALID_ARGUMENT;
  303. RequestContext request_context;
  304. scoped_refptr<Dispatcher> watcher = GetDispatcher(trap_handle);
  305. if (!watcher || watcher->GetType() != Dispatcher::Type::WATCHER)
  306. return MOJO_RESULT_INVALID_ARGUMENT;
  307. return watcher->Arm(num_blocking_events, blocking_events);
  308. }
  309. MojoResult Core::CreateMessage(const MojoCreateMessageOptions* options,
  310. MojoMessageHandle* message_handle) {
  311. if (!message_handle)
  312. return MOJO_RESULT_INVALID_ARGUMENT;
  313. if (options && options->struct_size < sizeof(*options))
  314. return MOJO_RESULT_INVALID_ARGUMENT;
  315. const MojoCreateMessageFlags flags =
  316. options ? options->flags : MOJO_CREATE_MESSAGE_FLAG_NONE;
  317. *message_handle = reinterpret_cast<MojoMessageHandle>(
  318. UserMessageImpl::CreateEventForNewMessage(flags).release());
  319. return MOJO_RESULT_OK;
  320. }
  321. MojoResult Core::DestroyMessage(MojoMessageHandle message_handle) {
  322. if (!message_handle)
  323. return MOJO_RESULT_INVALID_ARGUMENT;
  324. RequestContext request_context;
  325. delete reinterpret_cast<ports::UserMessageEvent*>(message_handle);
  326. return MOJO_RESULT_OK;
  327. }
  328. MojoResult Core::SerializeMessage(MojoMessageHandle message_handle,
  329. const MojoSerializeMessageOptions* options) {
  330. if (!message_handle)
  331. return MOJO_RESULT_INVALID_ARGUMENT;
  332. if (options && options->struct_size < sizeof(*options))
  333. return MOJO_RESULT_INVALID_ARGUMENT;
  334. RequestContext request_context;
  335. return reinterpret_cast<ports::UserMessageEvent*>(message_handle)
  336. ->GetMessage<UserMessageImpl>()
  337. ->SerializeIfNecessary();
  338. }
  339. MojoResult Core::AppendMessageData(MojoMessageHandle message_handle,
  340. uint32_t additional_payload_size,
  341. const MojoHandle* handles,
  342. uint32_t num_handles,
  343. const MojoAppendMessageDataOptions* options,
  344. void** buffer,
  345. uint32_t* buffer_size) {
  346. if (!message_handle || (num_handles && !handles))
  347. return MOJO_RESULT_INVALID_ARGUMENT;
  348. if (options && options->struct_size < sizeof(*options))
  349. return MOJO_RESULT_INVALID_ARGUMENT;
  350. RequestContext request_context;
  351. auto* message = reinterpret_cast<ports::UserMessageEvent*>(message_handle)
  352. ->GetMessage<UserMessageImpl>();
  353. MojoResult rv =
  354. message->AppendData(additional_payload_size, handles, num_handles);
  355. if (rv != MOJO_RESULT_OK)
  356. return rv;
  357. if (options && (options->flags & MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE))
  358. message->CommitSize();
  359. if (buffer)
  360. *buffer = message->user_payload();
  361. if (buffer_size) {
  362. *buffer_size =
  363. base::checked_cast<uint32_t>(message->user_payload_capacity());
  364. }
  365. return MOJO_RESULT_OK;
  366. }
  367. MojoResult Core::GetMessageData(MojoMessageHandle message_handle,
  368. const MojoGetMessageDataOptions* options,
  369. void** buffer,
  370. uint32_t* num_bytes,
  371. MojoHandle* handles,
  372. uint32_t* num_handles) {
  373. if (!message_handle || (num_handles && *num_handles && !handles))
  374. return MOJO_RESULT_INVALID_ARGUMENT;
  375. if (options && options->struct_size < sizeof(*options))
  376. return MOJO_RESULT_INVALID_ARGUMENT;
  377. auto* message = reinterpret_cast<ports::UserMessageEvent*>(message_handle)
  378. ->GetMessage<UserMessageImpl>();
  379. if (!message->IsSerialized() || !message->IsTransmittable())
  380. return MOJO_RESULT_FAILED_PRECONDITION;
  381. if (num_bytes) {
  382. base::CheckedNumeric<uint32_t> payload_size = message->user_payload_size();
  383. *num_bytes = payload_size.ValueOrDie();
  384. }
  385. if (message->user_payload_size() > 0) {
  386. if (!num_bytes || !buffer)
  387. return MOJO_RESULT_RESOURCE_EXHAUSTED;
  388. *buffer = message->user_payload();
  389. } else if (buffer) {
  390. *buffer = nullptr;
  391. }
  392. if (options && (options->flags & MOJO_GET_MESSAGE_DATA_FLAG_IGNORE_HANDLES))
  393. return MOJO_RESULT_OK;
  394. uint32_t max_num_handles = 0;
  395. if (num_handles) {
  396. max_num_handles = *num_handles;
  397. *num_handles = static_cast<uint32_t>(message->num_handles());
  398. }
  399. if (message->num_handles() > max_num_handles ||
  400. message->num_handles() > kMaxHandlesPerMessage) {
  401. return MOJO_RESULT_RESOURCE_EXHAUSTED;
  402. }
  403. RequestContext request_context;
  404. Dispatcher::SetExtractingHandlesFromMessage(true);
  405. MojoResult result = message->ExtractSerializedHandles(
  406. UserMessageImpl::ExtractBadHandlePolicy::kAbort, handles);
  407. Dispatcher::SetExtractingHandlesFromMessage(false);
  408. return result;
  409. }
  410. MojoResult Core::SetMessageContext(
  411. MojoMessageHandle message_handle,
  412. uintptr_t context,
  413. MojoMessageContextSerializer serializer,
  414. MojoMessageContextDestructor destructor,
  415. const MojoSetMessageContextOptions* options) {
  416. if (!message_handle)
  417. return MOJO_RESULT_INVALID_ARGUMENT;
  418. if (options && options->struct_size < sizeof(*options))
  419. return MOJO_RESULT_INVALID_ARGUMENT;
  420. auto* message = reinterpret_cast<ports::UserMessageEvent*>(message_handle)
  421. ->GetMessage<UserMessageImpl>();
  422. return message->SetContext(context, serializer, destructor);
  423. }
  424. MojoResult Core::GetMessageContext(MojoMessageHandle message_handle,
  425. const MojoGetMessageContextOptions* options,
  426. uintptr_t* context) {
  427. if (!message_handle)
  428. return MOJO_RESULT_INVALID_ARGUMENT;
  429. if (options && options->struct_size < sizeof(*options))
  430. return MOJO_RESULT_INVALID_ARGUMENT;
  431. auto* message = reinterpret_cast<ports::UserMessageEvent*>(message_handle)
  432. ->GetMessage<UserMessageImpl>();
  433. if (!message->HasContext())
  434. return MOJO_RESULT_NOT_FOUND;
  435. *context = message->context();
  436. return MOJO_RESULT_OK;
  437. }
  438. MojoResult Core::CreateMessagePipe(const MojoCreateMessagePipeOptions* options,
  439. MojoHandle* message_pipe_handle0,
  440. MojoHandle* message_pipe_handle1) {
  441. RequestContext request_context;
  442. ports::PortRef port0, port1;
  443. GetNodeController()->node()->CreatePortPair(&port0, &port1);
  444. DCHECK(message_pipe_handle0);
  445. DCHECK(message_pipe_handle1);
  446. uint64_t pipe_id = MakePipeId();
  447. *message_pipe_handle0 = AddDispatcher(new MessagePipeDispatcher(
  448. GetNodeController(), port0, pipe_id, /*endpoint=*/0));
  449. if (*message_pipe_handle0 == MOJO_HANDLE_INVALID)
  450. return MOJO_RESULT_RESOURCE_EXHAUSTED;
  451. *message_pipe_handle1 = AddDispatcher(new MessagePipeDispatcher(
  452. GetNodeController(), port1, pipe_id, /*endpoint=*/1));
  453. if (*message_pipe_handle1 == MOJO_HANDLE_INVALID) {
  454. scoped_refptr<Dispatcher> dispatcher0;
  455. {
  456. base::AutoLock lock(handles_->GetLock());
  457. handles_->GetAndRemoveDispatcher(*message_pipe_handle0, &dispatcher0);
  458. }
  459. dispatcher0->Close();
  460. return MOJO_RESULT_RESOURCE_EXHAUSTED;
  461. }
  462. return MOJO_RESULT_OK;
  463. }
  464. MojoResult Core::WriteMessage(MojoHandle message_pipe_handle,
  465. MojoMessageHandle message_handle,
  466. const MojoWriteMessageOptions* options) {
  467. RequestContext request_context;
  468. if (!message_handle)
  469. return MOJO_RESULT_INVALID_ARGUMENT;
  470. auto message_event = base::WrapUnique(
  471. reinterpret_cast<ports::UserMessageEvent*>(message_handle));
  472. auto* message = message_event->GetMessage<UserMessageImpl>();
  473. if (!message || !message->IsTransmittable())
  474. return MOJO_RESULT_INVALID_ARGUMENT;
  475. auto dispatcher = GetDispatcher(message_pipe_handle);
  476. if (!dispatcher)
  477. return MOJO_RESULT_INVALID_ARGUMENT;
  478. return dispatcher->WriteMessage(std::move(message_event));
  479. }
  480. MojoResult Core::ReadMessage(MojoHandle message_pipe_handle,
  481. const MojoReadMessageOptions* options,
  482. MojoMessageHandle* message_handle) {
  483. RequestContext request_context;
  484. auto dispatcher = GetDispatcher(message_pipe_handle);
  485. if (!dispatcher || !message_handle)
  486. return MOJO_RESULT_INVALID_ARGUMENT;
  487. std::unique_ptr<ports::UserMessageEvent> message_event;
  488. MojoResult rv = dispatcher->ReadMessage(&message_event);
  489. if (rv != MOJO_RESULT_OK)
  490. return rv;
  491. *message_handle =
  492. reinterpret_cast<MojoMessageHandle>(message_event.release());
  493. return MOJO_RESULT_OK;
  494. }
  495. MojoResult Core::FuseMessagePipes(MojoHandle handle0,
  496. MojoHandle handle1,
  497. const MojoFuseMessagePipesOptions* options) {
  498. RequestContext request_context;
  499. scoped_refptr<Dispatcher> dispatcher0;
  500. scoped_refptr<Dispatcher> dispatcher1;
  501. bool valid_handles = true;
  502. {
  503. base::AutoLock lock(handles_->GetLock());
  504. MojoResult result0 =
  505. handles_->GetAndRemoveDispatcher(handle0, &dispatcher0);
  506. MojoResult result1 =
  507. handles_->GetAndRemoveDispatcher(handle1, &dispatcher1);
  508. if (result0 != MOJO_RESULT_OK || result1 != MOJO_RESULT_OK ||
  509. dispatcher0->GetType() != Dispatcher::Type::MESSAGE_PIPE ||
  510. dispatcher1->GetType() != Dispatcher::Type::MESSAGE_PIPE)
  511. valid_handles = false;
  512. }
  513. if (!valid_handles) {
  514. if (dispatcher0)
  515. dispatcher0->Close();
  516. if (dispatcher1)
  517. dispatcher1->Close();
  518. return MOJO_RESULT_INVALID_ARGUMENT;
  519. }
  520. MessagePipeDispatcher* mpd0 =
  521. static_cast<MessagePipeDispatcher*>(dispatcher0.get());
  522. MessagePipeDispatcher* mpd1 =
  523. static_cast<MessagePipeDispatcher*>(dispatcher1.get());
  524. if (!mpd0->Fuse(mpd1))
  525. return MOJO_RESULT_FAILED_PRECONDITION;
  526. return MOJO_RESULT_OK;
  527. }
  528. MojoResult Core::NotifyBadMessage(MojoMessageHandle message_handle,
  529. const char* error,
  530. size_t error_num_bytes,
  531. const MojoNotifyBadMessageOptions* options) {
  532. if (!message_handle)
  533. return MOJO_RESULT_INVALID_ARGUMENT;
  534. auto* message_event =
  535. reinterpret_cast<ports::UserMessageEvent*>(message_handle);
  536. auto* message = message_event->GetMessage<UserMessageImpl>();
  537. NodeController* node_controller = GetNodeController();
  538. if (!node_controller->HasBadMessageHandler(message->source_node())) {
  539. if (message->source_node() == ports::kInvalidNodeName)
  540. DVLOG(1) << "Received invalid message from unknown node.";
  541. if (!default_process_error_callback_.is_null())
  542. default_process_error_callback_.Run(std::string(error, error_num_bytes));
  543. return MOJO_RESULT_OK;
  544. }
  545. node_controller->NotifyBadMessageFrom(message->source_node(),
  546. std::string(error, error_num_bytes));
  547. return MOJO_RESULT_OK;
  548. }
  549. MojoResult Core::CreateDataPipe(const MojoCreateDataPipeOptions* options,
  550. MojoHandle* data_pipe_producer_handle,
  551. MojoHandle* data_pipe_consumer_handle) {
  552. RequestContext request_context;
  553. if (options && options->struct_size < sizeof(MojoCreateDataPipeOptions))
  554. return MOJO_RESULT_INVALID_ARGUMENT;
  555. MojoCreateDataPipeOptions create_options;
  556. create_options.struct_size = sizeof(MojoCreateDataPipeOptions);
  557. create_options.flags = options ? options->flags : 0;
  558. create_options.element_num_bytes = options ? options->element_num_bytes : 1;
  559. // TODO(rockot): Use Configuration to get default data pipe capacity.
  560. create_options.capacity_num_bytes = options && options->capacity_num_bytes
  561. ? options->capacity_num_bytes
  562. : 64 * 1024;
  563. if (!create_options.element_num_bytes || !create_options.capacity_num_bytes ||
  564. create_options.capacity_num_bytes < create_options.element_num_bytes) {
  565. return MOJO_RESULT_INVALID_ARGUMENT;
  566. }
  567. base::subtle::PlatformSharedMemoryRegion ring_buffer_region =
  568. base::WritableSharedMemoryRegion::TakeHandleForSerialization(
  569. GetNodeController()->CreateSharedBuffer(
  570. create_options.capacity_num_bytes));
  571. // NOTE: We demote the writable region to an unsafe region so that the
  572. // producer handle can be transferred freely. There is no compelling reason
  573. // to restrict access rights of consumers since they are the exclusive
  574. // consumer of this pipe, and it would be impossible to support such access
  575. // control on Android anyway.
  576. auto writable_region_handle = ring_buffer_region.PassPlatformHandle();
  577. #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_APPLE)
  578. // This isn't strictly necessary, but it does make the handle configuration
  579. // consistent with regular UnsafeSharedMemoryRegions.
  580. writable_region_handle.readonly_fd.reset();
  581. #endif
  582. base::UnsafeSharedMemoryRegion producer_region =
  583. base::UnsafeSharedMemoryRegion::Deserialize(
  584. base::subtle::PlatformSharedMemoryRegion::Take(
  585. std::move(writable_region_handle),
  586. base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe,
  587. create_options.capacity_num_bytes, ring_buffer_region.GetGUID()));
  588. if (!producer_region.IsValid())
  589. return MOJO_RESULT_RESOURCE_EXHAUSTED;
  590. ports::PortRef port0, port1;
  591. GetNodeController()->node()->CreatePortPair(&port0, &port1);
  592. DCHECK(data_pipe_producer_handle);
  593. DCHECK(data_pipe_consumer_handle);
  594. base::UnsafeSharedMemoryRegion consumer_region = producer_region.Duplicate();
  595. uint64_t pipe_id = MakePipeId();
  596. scoped_refptr<Dispatcher> producer = DataPipeProducerDispatcher::Create(
  597. GetNodeController(), port0, std::move(producer_region), create_options,
  598. pipe_id);
  599. if (!producer)
  600. return MOJO_RESULT_RESOURCE_EXHAUSTED;
  601. scoped_refptr<Dispatcher> consumer = DataPipeConsumerDispatcher::Create(
  602. GetNodeController(), port1, std::move(consumer_region), create_options,
  603. pipe_id);
  604. if (!consumer) {
  605. producer->Close();
  606. return MOJO_RESULT_RESOURCE_EXHAUSTED;
  607. }
  608. *data_pipe_producer_handle = AddDispatcher(producer);
  609. *data_pipe_consumer_handle = AddDispatcher(consumer);
  610. if (*data_pipe_producer_handle == MOJO_HANDLE_INVALID ||
  611. *data_pipe_consumer_handle == MOJO_HANDLE_INVALID) {
  612. if (*data_pipe_producer_handle != MOJO_HANDLE_INVALID) {
  613. scoped_refptr<Dispatcher> unused;
  614. base::AutoLock lock(handles_->GetLock());
  615. handles_->GetAndRemoveDispatcher(*data_pipe_producer_handle, &unused);
  616. }
  617. producer->Close();
  618. consumer->Close();
  619. return MOJO_RESULT_RESOURCE_EXHAUSTED;
  620. }
  621. return MOJO_RESULT_OK;
  622. }
  623. MojoResult Core::WriteData(MojoHandle data_pipe_producer_handle,
  624. const void* elements,
  625. uint32_t* num_bytes,
  626. const MojoWriteDataOptions* options) {
  627. RequestContext request_context;
  628. scoped_refptr<Dispatcher> dispatcher(
  629. GetDispatcher(data_pipe_producer_handle));
  630. if (!dispatcher)
  631. return MOJO_RESULT_INVALID_ARGUMENT;
  632. MojoWriteDataOptions validated_options;
  633. if (options) {
  634. if (options->struct_size < sizeof(*options))
  635. return MOJO_RESULT_INVALID_ARGUMENT;
  636. constexpr MojoWriteDataFlags kSupportedFlags =
  637. MOJO_WRITE_DATA_FLAG_NONE | MOJO_WRITE_DATA_FLAG_ALL_OR_NONE;
  638. if (options->flags & ~kSupportedFlags)
  639. return MOJO_RESULT_UNIMPLEMENTED;
  640. validated_options.flags = options->flags;
  641. } else {
  642. validated_options.flags = MOJO_WRITE_DATA_FLAG_NONE;
  643. }
  644. return dispatcher->WriteData(elements, num_bytes, validated_options);
  645. }
  646. MojoResult Core::BeginWriteData(MojoHandle data_pipe_producer_handle,
  647. const MojoBeginWriteDataOptions* options,
  648. void** buffer,
  649. uint32_t* buffer_num_bytes) {
  650. RequestContext request_context;
  651. scoped_refptr<Dispatcher> dispatcher(
  652. GetDispatcher(data_pipe_producer_handle));
  653. if (!dispatcher)
  654. return MOJO_RESULT_INVALID_ARGUMENT;
  655. if (options) {
  656. if (options->struct_size < sizeof(*options))
  657. return MOJO_RESULT_INVALID_ARGUMENT;
  658. if (options->flags != MOJO_BEGIN_WRITE_DATA_FLAG_NONE)
  659. return MOJO_RESULT_UNIMPLEMENTED;
  660. }
  661. return dispatcher->BeginWriteData(buffer, buffer_num_bytes);
  662. }
  663. MojoResult Core::EndWriteData(MojoHandle data_pipe_producer_handle,
  664. uint32_t num_bytes_written,
  665. const MojoEndWriteDataOptions* options) {
  666. RequestContext request_context;
  667. scoped_refptr<Dispatcher> dispatcher(
  668. GetDispatcher(data_pipe_producer_handle));
  669. if (!dispatcher)
  670. return MOJO_RESULT_INVALID_ARGUMENT;
  671. if (options) {
  672. if (options->struct_size < sizeof(*options))
  673. return MOJO_RESULT_INVALID_ARGUMENT;
  674. if (options->flags != MOJO_END_WRITE_DATA_FLAG_NONE)
  675. return MOJO_RESULT_UNIMPLEMENTED;
  676. }
  677. return dispatcher->EndWriteData(num_bytes_written);
  678. }
  679. MojoResult Core::ReadData(MojoHandle data_pipe_consumer_handle,
  680. const MojoReadDataOptions* options,
  681. void* elements,
  682. uint32_t* num_bytes) {
  683. RequestContext request_context;
  684. scoped_refptr<Dispatcher> dispatcher(
  685. GetDispatcher(data_pipe_consumer_handle));
  686. if (!dispatcher)
  687. return MOJO_RESULT_INVALID_ARGUMENT;
  688. MojoReadDataOptions validated_options;
  689. if (options) {
  690. if (options->struct_size < sizeof(*options))
  691. return MOJO_RESULT_INVALID_ARGUMENT;
  692. constexpr MojoReadDataFlags kSupportedFlags =
  693. MOJO_READ_DATA_FLAG_NONE | MOJO_READ_DATA_FLAG_ALL_OR_NONE |
  694. MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_QUERY |
  695. MOJO_READ_DATA_FLAG_PEEK;
  696. if (options->flags & ~kSupportedFlags)
  697. return MOJO_RESULT_UNIMPLEMENTED;
  698. validated_options.flags = options->flags;
  699. } else {
  700. validated_options.flags = MOJO_WRITE_DATA_FLAG_NONE;
  701. }
  702. return dispatcher->ReadData(validated_options, elements, num_bytes);
  703. }
  704. MojoResult Core::BeginReadData(MojoHandle data_pipe_consumer_handle,
  705. const MojoBeginReadDataOptions* options,
  706. const void** buffer,
  707. uint32_t* buffer_num_bytes) {
  708. RequestContext request_context;
  709. scoped_refptr<Dispatcher> dispatcher(
  710. GetDispatcher(data_pipe_consumer_handle));
  711. if (!dispatcher)
  712. return MOJO_RESULT_INVALID_ARGUMENT;
  713. if (options) {
  714. if (options->struct_size < sizeof(*options))
  715. return MOJO_RESULT_INVALID_ARGUMENT;
  716. if (options->flags != MOJO_BEGIN_READ_DATA_FLAG_NONE)
  717. return MOJO_RESULT_UNIMPLEMENTED;
  718. }
  719. return dispatcher->BeginReadData(buffer, buffer_num_bytes);
  720. }
  721. MojoResult Core::EndReadData(MojoHandle data_pipe_consumer_handle,
  722. uint32_t num_bytes_read,
  723. const MojoEndReadDataOptions* options) {
  724. RequestContext request_context;
  725. scoped_refptr<Dispatcher> dispatcher(
  726. GetDispatcher(data_pipe_consumer_handle));
  727. if (!dispatcher)
  728. return MOJO_RESULT_INVALID_ARGUMENT;
  729. if (options) {
  730. if (options->struct_size < sizeof(*options))
  731. return MOJO_RESULT_INVALID_ARGUMENT;
  732. if (options->flags != MOJO_END_READ_DATA_FLAG_NONE)
  733. return MOJO_RESULT_UNIMPLEMENTED;
  734. }
  735. return dispatcher->EndReadData(num_bytes_read);
  736. }
  737. MojoResult Core::CreateSharedBuffer(
  738. uint64_t num_bytes,
  739. const MojoCreateSharedBufferOptions* options,
  740. MojoHandle* shared_buffer_handle) {
  741. RequestContext request_context;
  742. MojoCreateSharedBufferOptions validated_options = {};
  743. MojoResult result = SharedBufferDispatcher::ValidateCreateOptions(
  744. options, &validated_options);
  745. if (result != MOJO_RESULT_OK)
  746. return result;
  747. scoped_refptr<SharedBufferDispatcher> dispatcher;
  748. result = SharedBufferDispatcher::Create(
  749. validated_options, GetNodeController(), num_bytes, &dispatcher);
  750. if (result != MOJO_RESULT_OK) {
  751. DCHECK(!dispatcher);
  752. return result;
  753. }
  754. *shared_buffer_handle = AddDispatcher(dispatcher);
  755. if (*shared_buffer_handle == MOJO_HANDLE_INVALID) {
  756. LOG(ERROR) << "Handle table full";
  757. dispatcher->Close();
  758. return MOJO_RESULT_RESOURCE_EXHAUSTED;
  759. }
  760. return MOJO_RESULT_OK;
  761. }
  762. MojoResult Core::DuplicateBufferHandle(
  763. MojoHandle buffer_handle,
  764. const MojoDuplicateBufferHandleOptions* options,
  765. MojoHandle* new_buffer_handle) {
  766. RequestContext request_context;
  767. scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle));
  768. if (!dispatcher)
  769. return MOJO_RESULT_INVALID_ARGUMENT;
  770. // Don't verify |options| here; that's the dispatcher's job.
  771. scoped_refptr<Dispatcher> new_dispatcher;
  772. MojoResult result =
  773. dispatcher->DuplicateBufferHandle(options, &new_dispatcher);
  774. if (result != MOJO_RESULT_OK)
  775. return result;
  776. *new_buffer_handle = AddDispatcher(new_dispatcher);
  777. if (*new_buffer_handle == MOJO_HANDLE_INVALID) {
  778. LOG(ERROR) << "Handle table full";
  779. new_dispatcher->Close();
  780. return MOJO_RESULT_RESOURCE_EXHAUSTED;
  781. }
  782. return MOJO_RESULT_OK;
  783. }
  784. MojoResult Core::MapBuffer(MojoHandle buffer_handle,
  785. uint64_t offset,
  786. uint64_t num_bytes,
  787. const MojoMapBufferOptions* options,
  788. void** buffer) {
  789. scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle));
  790. if (!dispatcher)
  791. return MOJO_RESULT_INVALID_ARGUMENT;
  792. if (options) {
  793. if (options->struct_size < sizeof(*options))
  794. return MOJO_RESULT_INVALID_ARGUMENT;
  795. if (options->flags != MOJO_MAP_BUFFER_FLAG_NONE)
  796. return MOJO_RESULT_UNIMPLEMENTED;
  797. }
  798. std::unique_ptr<PlatformSharedMemoryMapping> mapping;
  799. MojoResult result = dispatcher->MapBuffer(offset, num_bytes, &mapping);
  800. if (result != MOJO_RESULT_OK)
  801. return result;
  802. DCHECK(mapping);
  803. void* address = mapping->GetBase();
  804. {
  805. base::AutoLock locker(mapping_table_lock_);
  806. if (mapping_table_.size() >= GetConfiguration().max_mapping_table_size)
  807. return MOJO_RESULT_RESOURCE_EXHAUSTED;
  808. auto emplace_result = mapping_table_.emplace(address, std::move(mapping));
  809. DCHECK(emplace_result.second);
  810. }
  811. *buffer = address;
  812. return MOJO_RESULT_OK;
  813. }
  814. MojoResult Core::UnmapBuffer(void* buffer) {
  815. std::unique_ptr<PlatformSharedMemoryMapping> mapping;
  816. // Destroy |mapping| while not holding the lock.
  817. {
  818. base::AutoLock lock(mapping_table_lock_);
  819. auto iter = mapping_table_.find(buffer);
  820. if (iter == mapping_table_.end())
  821. return MOJO_RESULT_INVALID_ARGUMENT;
  822. // Grab a reference so that it gets unmapped outside of this lock.
  823. mapping = std::move(iter->second);
  824. mapping_table_.erase(iter);
  825. }
  826. return MOJO_RESULT_OK;
  827. }
  828. MojoResult Core::GetBufferInfo(MojoHandle buffer_handle,
  829. const MojoGetBufferInfoOptions* options,
  830. MojoSharedBufferInfo* info) {
  831. if (options) {
  832. if (options->struct_size < sizeof(*options))
  833. return MOJO_RESULT_INVALID_ARGUMENT;
  834. if (options->flags != MOJO_GET_BUFFER_INFO_FLAG_NONE)
  835. return MOJO_RESULT_UNIMPLEMENTED;
  836. }
  837. if (!info || info->struct_size < sizeof(MojoSharedBufferInfo))
  838. return MOJO_RESULT_INVALID_ARGUMENT;
  839. scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle));
  840. if (!dispatcher)
  841. return MOJO_RESULT_INVALID_ARGUMENT;
  842. return dispatcher->GetBufferInfo(info);
  843. }
  844. MojoResult Core::WrapPlatformHandle(
  845. const MojoPlatformHandle* platform_handle,
  846. const MojoWrapPlatformHandleOptions* options,
  847. MojoHandle* mojo_handle) {
  848. if (!platform_handle ||
  849. platform_handle->struct_size < sizeof(*platform_handle)) {
  850. return MOJO_RESULT_INVALID_ARGUMENT;
  851. }
  852. auto handle = PlatformHandle::FromMojoPlatformHandle(platform_handle);
  853. MojoHandle h =
  854. AddDispatcher(PlatformHandleDispatcher::Create(std::move(handle)));
  855. if (h == MOJO_HANDLE_INVALID)
  856. return MOJO_RESULT_RESOURCE_EXHAUSTED;
  857. *mojo_handle = h;
  858. return MOJO_RESULT_OK;
  859. }
  860. MojoResult Core::UnwrapPlatformHandle(
  861. MojoHandle mojo_handle,
  862. const MojoUnwrapPlatformHandleOptions* options,
  863. MojoPlatformHandle* platform_handle) {
  864. if (!platform_handle ||
  865. platform_handle->struct_size < sizeof(*platform_handle)) {
  866. return MOJO_RESULT_INVALID_ARGUMENT;
  867. }
  868. scoped_refptr<Dispatcher> dispatcher;
  869. {
  870. base::AutoLock lock(handles_->GetLock());
  871. dispatcher = handles_->GetDispatcher(mojo_handle);
  872. if (!dispatcher ||
  873. dispatcher->GetType() != Dispatcher::Type::PLATFORM_HANDLE)
  874. return MOJO_RESULT_INVALID_ARGUMENT;
  875. MojoResult result =
  876. handles_->GetAndRemoveDispatcher(mojo_handle, &dispatcher);
  877. if (result != MOJO_RESULT_OK)
  878. return result;
  879. }
  880. PlatformHandleDispatcher* phd =
  881. static_cast<PlatformHandleDispatcher*>(dispatcher.get());
  882. PlatformHandle handle = phd->TakePlatformHandle();
  883. phd->Close();
  884. PlatformHandle::ToMojoPlatformHandle(std::move(handle), platform_handle);
  885. return MOJO_RESULT_OK;
  886. }
  887. MojoResult Core::WrapPlatformSharedMemoryRegion(
  888. const MojoPlatformHandle* platform_handles,
  889. uint32_t num_platform_handles,
  890. uint64_t size,
  891. const MojoSharedBufferGuid* guid,
  892. MojoPlatformSharedMemoryRegionAccessMode access_mode,
  893. const MojoWrapPlatformSharedMemoryRegionOptions* options,
  894. MojoHandle* mojo_handle) {
  895. DCHECK(size);
  896. #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_MAC)
  897. if (access_mode == MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_WRITABLE) {
  898. if (num_platform_handles != 2)
  899. return MOJO_RESULT_INVALID_ARGUMENT;
  900. }
  901. #else
  902. if (num_platform_handles != 1)
  903. return MOJO_RESULT_INVALID_ARGUMENT;
  904. #endif
  905. PlatformHandle handles[2];
  906. bool handles_ok = true;
  907. for (size_t i = 0; i < num_platform_handles; ++i) {
  908. handles[i] = PlatformHandle::FromMojoPlatformHandle(&platform_handles[i]);
  909. if (!handles[i].is_valid())
  910. handles_ok = false;
  911. }
  912. if (!handles_ok)
  913. return MOJO_RESULT_INVALID_ARGUMENT;
  914. base::UnguessableToken token =
  915. mojo::internal::PlatformHandleInternal::UnmarshalUnguessableToken(guid);
  916. base::subtle::PlatformSharedMemoryRegion::Mode mode;
  917. switch (access_mode) {
  918. case MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_READ_ONLY:
  919. mode = base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly;
  920. break;
  921. case MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_WRITABLE:
  922. mode = base::subtle::PlatformSharedMemoryRegion::Mode::kWritable;
  923. break;
  924. case MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_UNSAFE:
  925. mode = base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe;
  926. break;
  927. default:
  928. return MOJO_RESULT_INVALID_ARGUMENT;
  929. }
  930. base::subtle::PlatformSharedMemoryRegion region =
  931. base::subtle::PlatformSharedMemoryRegion::Take(
  932. CreateSharedMemoryRegionHandleFromPlatformHandles(
  933. std::move(handles[0]), std::move(handles[1])),
  934. mode, size, token);
  935. if (!region.IsValid())
  936. return MOJO_RESULT_UNKNOWN;
  937. scoped_refptr<SharedBufferDispatcher> dispatcher;
  938. MojoResult result =
  939. SharedBufferDispatcher::CreateFromPlatformSharedMemoryRegion(
  940. std::move(region), &dispatcher);
  941. if (result != MOJO_RESULT_OK)
  942. return result;
  943. MojoHandle h = AddDispatcher(dispatcher);
  944. if (h == MOJO_HANDLE_INVALID) {
  945. dispatcher->Close();
  946. return MOJO_RESULT_RESOURCE_EXHAUSTED;
  947. }
  948. *mojo_handle = h;
  949. return MOJO_RESULT_OK;
  950. }
  951. MojoResult Core::UnwrapPlatformSharedMemoryRegion(
  952. MojoHandle mojo_handle,
  953. const MojoUnwrapPlatformSharedMemoryRegionOptions* options,
  954. MojoPlatformHandle* platform_handles,
  955. uint32_t* num_platform_handles,
  956. uint64_t* size,
  957. MojoSharedBufferGuid* guid,
  958. MojoPlatformSharedMemoryRegionAccessMode* access_mode) {
  959. scoped_refptr<Dispatcher> dispatcher;
  960. MojoResult result = MOJO_RESULT_OK;
  961. {
  962. base::AutoLock lock(handles_->GetLock());
  963. result = handles_->GetAndRemoveDispatcher(mojo_handle, &dispatcher);
  964. if (result != MOJO_RESULT_OK)
  965. return result;
  966. }
  967. if (dispatcher->GetType() != Dispatcher::Type::SHARED_BUFFER) {
  968. dispatcher->Close();
  969. return MOJO_RESULT_INVALID_ARGUMENT;
  970. }
  971. SharedBufferDispatcher* shm_dispatcher =
  972. static_cast<SharedBufferDispatcher*>(dispatcher.get());
  973. base::subtle::PlatformSharedMemoryRegion region =
  974. shm_dispatcher->PassPlatformSharedMemoryRegion();
  975. DCHECK(region.IsValid());
  976. DCHECK(size);
  977. *size = region.GetSize();
  978. *guid = mojo::internal::PlatformHandleInternal::MarshalUnguessableToken(
  979. region.GetGUID());
  980. DCHECK(access_mode);
  981. switch (region.GetMode()) {
  982. case base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly:
  983. *access_mode = MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_READ_ONLY;
  984. break;
  985. case base::subtle::PlatformSharedMemoryRegion::Mode::kWritable:
  986. *access_mode = MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_WRITABLE;
  987. break;
  988. case base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe:
  989. *access_mode = MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_UNSAFE;
  990. break;
  991. default:
  992. return MOJO_RESULT_INVALID_ARGUMENT;
  993. }
  994. PlatformHandle handle;
  995. PlatformHandle read_only_handle;
  996. ExtractPlatformHandlesFromSharedMemoryRegionHandle(
  997. region.PassPlatformHandle(), &handle, &read_only_handle);
  998. const uint32_t available_handle_storage_slots = *num_platform_handles;
  999. if (available_handle_storage_slots < 1)
  1000. return MOJO_RESULT_RESOURCE_EXHAUSTED;
  1001. *num_platform_handles = 1;
  1002. #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_MAC)
  1003. if (region.GetMode() ==
  1004. base::subtle::PlatformSharedMemoryRegion::Mode::kWritable) {
  1005. if (available_handle_storage_slots < 2)
  1006. return MOJO_RESULT_INVALID_ARGUMENT;
  1007. PlatformHandle::ToMojoPlatformHandle(std::move(read_only_handle),
  1008. &platform_handles[1]);
  1009. if (platform_handles[1].type == MOJO_PLATFORM_HANDLE_TYPE_INVALID)
  1010. return MOJO_RESULT_INVALID_ARGUMENT;
  1011. *num_platform_handles = 2;
  1012. }
  1013. #endif
  1014. PlatformHandle::ToMojoPlatformHandle(std::move(handle), &platform_handles[0]);
  1015. if (platform_handles[0].type == MOJO_PLATFORM_HANDLE_TYPE_INVALID)
  1016. return MOJO_RESULT_INVALID_ARGUMENT;
  1017. return MOJO_RESULT_OK;
  1018. }
  1019. MojoResult Core::CreateInvitation(const MojoCreateInvitationOptions* options,
  1020. MojoHandle* invitation_handle) {
  1021. if (options && options->struct_size < sizeof(*options))
  1022. return MOJO_RESULT_INVALID_ARGUMENT;
  1023. if (!invitation_handle)
  1024. return MOJO_RESULT_INVALID_ARGUMENT;
  1025. *invitation_handle = AddDispatcher(new InvitationDispatcher);
  1026. if (*invitation_handle == MOJO_HANDLE_INVALID)
  1027. return MOJO_RESULT_RESOURCE_EXHAUSTED;
  1028. return MOJO_RESULT_OK;
  1029. }
  1030. MojoResult Core::AttachMessagePipeToInvitation(
  1031. MojoHandle invitation_handle,
  1032. const void* name,
  1033. uint32_t name_num_bytes,
  1034. const MojoAttachMessagePipeToInvitationOptions* options,
  1035. MojoHandle* message_pipe_handle) {
  1036. if (options && options->struct_size < sizeof(*options))
  1037. return MOJO_RESULT_INVALID_ARGUMENT;
  1038. if (!message_pipe_handle)
  1039. return MOJO_RESULT_INVALID_ARGUMENT;
  1040. if (name_num_bytes == 0)
  1041. return MOJO_RESULT_INVALID_ARGUMENT;
  1042. scoped_refptr<Dispatcher> dispatcher = GetDispatcher(invitation_handle);
  1043. if (!dispatcher || dispatcher->GetType() != Dispatcher::Type::INVITATION)
  1044. return MOJO_RESULT_INVALID_ARGUMENT;
  1045. auto* invitation_dispatcher =
  1046. static_cast<InvitationDispatcher*>(dispatcher.get());
  1047. RequestContext request_context;
  1048. ports::PortRef remote_peer_port;
  1049. MojoHandle local_handle = CreatePartialMessagePipe(&remote_peer_port);
  1050. if (local_handle == MOJO_HANDLE_INVALID)
  1051. return MOJO_RESULT_RESOURCE_EXHAUSTED;
  1052. MojoResult result = invitation_dispatcher->AttachMessagePipe(
  1053. base::StringPiece(static_cast<const char*>(name), name_num_bytes),
  1054. std::move(remote_peer_port));
  1055. if (result != MOJO_RESULT_OK) {
  1056. Close(local_handle);
  1057. return result;
  1058. }
  1059. *message_pipe_handle = local_handle;
  1060. return MOJO_RESULT_OK;
  1061. }
  1062. MojoResult Core::ExtractMessagePipeFromInvitation(
  1063. MojoHandle invitation_handle,
  1064. const void* name,
  1065. uint32_t name_num_bytes,
  1066. const MojoExtractMessagePipeFromInvitationOptions* options,
  1067. MojoHandle* message_pipe_handle) {
  1068. if (options && options->struct_size < sizeof(*options))
  1069. return MOJO_RESULT_INVALID_ARGUMENT;
  1070. if (!message_pipe_handle)
  1071. return MOJO_RESULT_INVALID_ARGUMENT;
  1072. if (name_num_bytes == 0)
  1073. return MOJO_RESULT_INVALID_ARGUMENT;
  1074. RequestContext request_context;
  1075. base::StringPiece name_string(static_cast<const char*>(name), name_num_bytes);
  1076. scoped_refptr<Dispatcher> dispatcher = GetDispatcher(invitation_handle);
  1077. if (!dispatcher || dispatcher->GetType() != Dispatcher::Type::INVITATION)
  1078. return MOJO_RESULT_INVALID_ARGUMENT;
  1079. auto* invitation_dispatcher =
  1080. static_cast<InvitationDispatcher*>(dispatcher.get());
  1081. // First attempt to extract from the invitation object itself. This is for
  1082. // cases where this invitation was created in-process or is an accepted
  1083. // isolated invitation.
  1084. MojoResult extract_result = invitation_dispatcher->ExtractMessagePipe(
  1085. name_string, message_pipe_handle);
  1086. if (extract_result == MOJO_RESULT_OK ||
  1087. extract_result == MOJO_RESULT_RESOURCE_EXHAUSTED) {
  1088. return extract_result;
  1089. }
  1090. *message_pipe_handle =
  1091. ExtractMessagePipeFromInvitation(std::string(name_string));
  1092. if (*message_pipe_handle == MOJO_HANDLE_INVALID)
  1093. return MOJO_RESULT_RESOURCE_EXHAUSTED;
  1094. return MOJO_RESULT_OK;
  1095. }
  1096. MojoResult Core::SendInvitation(
  1097. MojoHandle invitation_handle,
  1098. const MojoPlatformProcessHandle* process_handle,
  1099. const MojoInvitationTransportEndpoint* transport_endpoint,
  1100. MojoProcessErrorHandler error_handler,
  1101. uintptr_t error_handler_context,
  1102. const MojoSendInvitationOptions* options) {
  1103. if (options && options->struct_size < sizeof(*options))
  1104. return MOJO_RESULT_INVALID_ARGUMENT;
  1105. base::Process target_process;
  1106. if (process_handle) {
  1107. MojoResult result =
  1108. UnwrapAndClonePlatformProcessHandle(process_handle, target_process);
  1109. if (result != MOJO_RESULT_OK)
  1110. return result;
  1111. }
  1112. ProcessErrorCallback process_error_callback;
  1113. if (error_handler) {
  1114. process_error_callback =
  1115. base::BindRepeating(&RunMojoProcessErrorHandler,
  1116. base::Owned(new ProcessDisconnectHandler(
  1117. error_handler, error_handler_context)),
  1118. error_handler, error_handler_context);
  1119. } else if (default_process_error_callback_) {
  1120. process_error_callback = default_process_error_callback_;
  1121. }
  1122. if (!transport_endpoint)
  1123. return MOJO_RESULT_INVALID_ARGUMENT;
  1124. if (transport_endpoint->struct_size < sizeof(*transport_endpoint))
  1125. return MOJO_RESULT_INVALID_ARGUMENT;
  1126. if (transport_endpoint->num_platform_handles == 0)
  1127. return MOJO_RESULT_INVALID_ARGUMENT;
  1128. if (!transport_endpoint->platform_handles)
  1129. return MOJO_RESULT_INVALID_ARGUMENT;
  1130. if (transport_endpoint->type != MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL &&
  1131. transport_endpoint->type !=
  1132. MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER &&
  1133. transport_endpoint->type !=
  1134. MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_ASYNC) {
  1135. return MOJO_RESULT_UNIMPLEMENTED;
  1136. }
  1137. scoped_refptr<Dispatcher> dispatcher = GetDispatcher(invitation_handle);
  1138. if (!dispatcher || dispatcher->GetType() != Dispatcher::Type::INVITATION)
  1139. return MOJO_RESULT_INVALID_ARGUMENT;
  1140. auto* invitation_dispatcher =
  1141. static_cast<InvitationDispatcher*>(dispatcher.get());
  1142. auto endpoint = PlatformHandle::FromMojoPlatformHandle(
  1143. &transport_endpoint->platform_handles[0]);
  1144. if (!endpoint.is_valid())
  1145. return MOJO_RESULT_INVALID_ARGUMENT;
  1146. ConnectionParams connection_params;
  1147. #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_POSIX)
  1148. if (transport_endpoint->type ==
  1149. MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER) {
  1150. connection_params =
  1151. ConnectionParams(PlatformChannelServerEndpoint(std::move(endpoint)));
  1152. }
  1153. #endif
  1154. if (!connection_params.server_endpoint().is_valid()) {
  1155. connection_params =
  1156. ConnectionParams(PlatformChannelEndpoint(std::move(endpoint)));
  1157. }
  1158. // At this point everything else has been validated, so we can take ownership
  1159. // of the dispatcher.
  1160. {
  1161. base::AutoLock lock(handles_->GetLock());
  1162. scoped_refptr<Dispatcher> removed_dispatcher;
  1163. MojoResult result = handles_->GetAndRemoveDispatcher(invitation_handle,
  1164. &removed_dispatcher);
  1165. if (result != MOJO_RESULT_OK) {
  1166. // Release ownership of the endpoint platform handle, per the API
  1167. // contract. The caller retains ownership on failure.
  1168. connection_params.TakeEndpoint().TakePlatformHandle().release();
  1169. connection_params.TakeServerEndpoint().TakePlatformHandle().release();
  1170. return result;
  1171. }
  1172. DCHECK_EQ(removed_dispatcher.get(), invitation_dispatcher);
  1173. }
  1174. std::vector<std::pair<std::string, ports::PortRef>> attached_ports;
  1175. InvitationDispatcher::PortMapping attached_port_map =
  1176. invitation_dispatcher->TakeAttachedPorts();
  1177. invitation_dispatcher->Close();
  1178. for (auto& entry : attached_port_map)
  1179. attached_ports.emplace_back(entry.first, std::move(entry.second));
  1180. connection_params.set_is_untrusted_process(
  1181. options &&
  1182. (options->flags & MOJO_SEND_INVITATION_FLAG_UNTRUSTED_PROCESS));
  1183. bool is_isolated =
  1184. options && (options->flags & MOJO_SEND_INVITATION_FLAG_ISOLATED);
  1185. RequestContext request_context;
  1186. if (is_isolated) {
  1187. DCHECK_EQ(attached_ports.size(), 1u);
  1188. DCHECK_EQ(attached_ports[0].first, kIsolatedInvitationPipeName);
  1189. base::StringPiece connection_name(options->isolated_connection_name,
  1190. options->isolated_connection_name_length);
  1191. GetNodeController()->ConnectIsolated(std::move(connection_params),
  1192. attached_ports[0].second,
  1193. connection_name);
  1194. } else {
  1195. if (transport_endpoint->type ==
  1196. MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_ASYNC) {
  1197. connection_params.set_is_async(true);
  1198. }
  1199. GetNodeController()->SendBrokerClientInvitation(
  1200. std::move(target_process), std::move(connection_params), attached_ports,
  1201. process_error_callback);
  1202. }
  1203. return MOJO_RESULT_OK;
  1204. }
  1205. MojoResult Core::AcceptInvitation(
  1206. const MojoInvitationTransportEndpoint* transport_endpoint,
  1207. const MojoAcceptInvitationOptions* options,
  1208. MojoHandle* invitation_handle) {
  1209. if (options && options->struct_size < sizeof(*options))
  1210. return MOJO_RESULT_INVALID_ARGUMENT;
  1211. if (!transport_endpoint)
  1212. return MOJO_RESULT_INVALID_ARGUMENT;
  1213. if (transport_endpoint->struct_size < sizeof(*transport_endpoint))
  1214. return MOJO_RESULT_INVALID_ARGUMENT;
  1215. if (transport_endpoint->num_platform_handles == 0)
  1216. return MOJO_RESULT_INVALID_ARGUMENT;
  1217. if (!transport_endpoint->platform_handles)
  1218. return MOJO_RESULT_INVALID_ARGUMENT;
  1219. if (transport_endpoint->type != MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL &&
  1220. transport_endpoint->type !=
  1221. MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER &&
  1222. transport_endpoint->type !=
  1223. MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_ASYNC) {
  1224. return MOJO_RESULT_UNIMPLEMENTED;
  1225. }
  1226. if (!invitation_handle)
  1227. return MOJO_RESULT_INVALID_ARGUMENT;
  1228. auto dispatcher = base::MakeRefCounted<InvitationDispatcher>();
  1229. *invitation_handle = AddDispatcher(dispatcher);
  1230. if (*invitation_handle == MOJO_HANDLE_INVALID)
  1231. return MOJO_RESULT_RESOURCE_EXHAUSTED;
  1232. auto endpoint = PlatformHandle::FromMojoPlatformHandle(
  1233. &transport_endpoint->platform_handles[0]);
  1234. if (!endpoint.is_valid()) {
  1235. Close(*invitation_handle);
  1236. *invitation_handle = MOJO_HANDLE_INVALID;
  1237. return MOJO_RESULT_INVALID_ARGUMENT;
  1238. }
  1239. ConnectionParams connection_params;
  1240. #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_POSIX)
  1241. if (transport_endpoint->type ==
  1242. MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER) {
  1243. connection_params =
  1244. ConnectionParams(PlatformChannelServerEndpoint(std::move(endpoint)));
  1245. }
  1246. #endif
  1247. if (!connection_params.server_endpoint().is_valid()) {
  1248. connection_params =
  1249. ConnectionParams(PlatformChannelEndpoint(std::move(endpoint)));
  1250. }
  1251. if (options &&
  1252. options->flags & MOJO_ACCEPT_INVITATION_FLAG_LEAK_TRANSPORT_ENDPOINT) {
  1253. connection_params.set_leak_endpoint(true);
  1254. }
  1255. bool is_isolated =
  1256. options && (options->flags & MOJO_ACCEPT_INVITATION_FLAG_ISOLATED);
  1257. NodeController* const node_controller = GetNodeController();
  1258. RequestContext request_context;
  1259. if (is_isolated) {
  1260. // For an isolated invitation, we simply mint a new port pair here and send
  1261. // one name to the remote endpoint while stashing the other in the accepted
  1262. // invitation object for later extraction.
  1263. ports::PortRef local_port;
  1264. ports::PortRef remote_port;
  1265. node_controller->node()->CreatePortPair(&local_port, &remote_port);
  1266. node_controller->ConnectIsolated(std::move(connection_params), remote_port,
  1267. base::StringPiece());
  1268. MojoResult result =
  1269. dispatcher->AttachMessagePipe(kIsolatedInvitationPipeName, local_port);
  1270. DCHECK_EQ(MOJO_RESULT_OK, result);
  1271. } else {
  1272. if (transport_endpoint->type ==
  1273. MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_ASYNC) {
  1274. connection_params.set_is_async(true);
  1275. }
  1276. node_controller->AcceptBrokerClientInvitation(std::move(connection_params));
  1277. }
  1278. return MOJO_RESULT_OK;
  1279. }
  1280. MojoResult Core::SetQuota(MojoHandle handle,
  1281. MojoQuotaType type,
  1282. uint64_t limit,
  1283. const MojoSetQuotaOptions* options) {
  1284. RequestContext request_context;
  1285. if (options && options->struct_size < sizeof(*options))
  1286. return MOJO_RESULT_INVALID_ARGUMENT;
  1287. auto dispatcher = GetDispatcher(handle);
  1288. if (!dispatcher)
  1289. return MOJO_RESULT_INVALID_ARGUMENT;
  1290. return dispatcher->SetQuota(type, limit);
  1291. }
  1292. MojoResult Core::QueryQuota(MojoHandle handle,
  1293. MojoQuotaType type,
  1294. const MojoQueryQuotaOptions* options,
  1295. uint64_t* limit,
  1296. uint64_t* usage) {
  1297. RequestContext request_context;
  1298. if (options && options->struct_size < sizeof(*options))
  1299. return MOJO_RESULT_INVALID_ARGUMENT;
  1300. auto dispatcher = GetDispatcher(handle);
  1301. if (!dispatcher)
  1302. return MOJO_RESULT_INVALID_ARGUMENT;
  1303. return dispatcher->QueryQuota(type, limit, usage);
  1304. }
  1305. MojoResult Core::SetDefaultProcessErrorHandler(
  1306. MojoDefaultProcessErrorHandler handler,
  1307. const MojoSetDefaultProcessErrorHandlerOptions* options) {
  1308. if (default_process_error_callback_ && handler)
  1309. return MOJO_RESULT_ALREADY_EXISTS;
  1310. if (!handler) {
  1311. default_process_error_callback_.Reset();
  1312. return MOJO_RESULT_OK;
  1313. }
  1314. default_process_error_callback_ = base::BindRepeating(
  1315. [](MojoDefaultProcessErrorHandler handler, const std::string& error) {
  1316. MojoProcessErrorDetails details = {0};
  1317. details.struct_size = sizeof(details);
  1318. details.error_message_length = static_cast<uint32_t>(error.size());
  1319. details.error_message = error.c_str();
  1320. handler(&details);
  1321. },
  1322. handler);
  1323. return MOJO_RESULT_OK;
  1324. }
  1325. void Core::GetActiveHandlesForTest(std::vector<MojoHandle>* handles) {
  1326. base::AutoLock lock(handles_->GetLock());
  1327. handles_->GetActiveHandlesForTest(handles);
  1328. }
  1329. // static
  1330. void Core::set_avoid_random_pipe_id(bool avoid_random_pipe_id) {
  1331. g_avoid_random_pipe_id = avoid_random_pipe_id;
  1332. }
  1333. // static
  1334. void Core::PassNodeControllerToIOThread(
  1335. std::unique_ptr<NodeController> node_controller) {
  1336. // It's OK to leak this reference. At this point we know the IO loop is still
  1337. // running, and we know the NodeController will observe its eventual
  1338. // destruction. This tells the NodeController to delete itself when that
  1339. // happens.
  1340. node_controller.release()->DestroyOnIOThreadShutdown();
  1341. }
  1342. } // namespace core
  1343. } // namespace mojo