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/public/c/system/thunks.h"
6
7 #include <cstddef>
8 #include <cstdint>
9 #include <cstring>
10
11 #include "base/logging.h"
12 #include "base/macros.h"
13 #include "base/memory/protected_memory.h"
14 #include "base/memory/protected_memory_cfi.h"
15 #include "base/no_destructor.h"
16 #include "build/build_config.h"
17 #include "mojo/public/c/system/core.h"
18
19 #if defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_WIN)
20 #include "base/environment.h"
21 #include "base/files/file_path.h"
22 #include "base/optional.h"
23 #include "base/scoped_native_library.h"
24 #include "base/threading/thread_restrictions.h"
25 #endif
26
27 namespace {
28
29 typedef void (*MojoGetSystemThunksFunction)(MojoSystemThunks* thunks);
30
31 #if defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_WIN)
32 PROTECTED_MEMORY_SECTION
33 base::ProtectedMemory<MojoGetSystemThunksFunction> g_get_thunks;
34 #endif
35
36 PROTECTED_MEMORY_SECTION base::ProtectedMemory<MojoSystemThunks> g_thunks;
37
NotImplemented(const char * name)38 MojoResult NotImplemented(const char* name) {
39 DLOG(ERROR) << "Function 'Mojo" << name
40 << "()' not supported in this version of Mojo Core.";
41 return MOJO_RESULT_UNIMPLEMENTED;
42 }
43
44 } // namespace
45
46 // Macro to verify that the thunk symbol |name| is actually present in the
47 // runtime version of Mojo Core that is currently in use.
48 #define FUNCTION_IS_IMPLEMENTED(name) \
49 (reinterpret_cast<uintptr_t>(static_cast<const void*>(&g_thunks->name)) - \
50 reinterpret_cast<uintptr_t>(static_cast<const void*>(&g_thunks)) < \
51 g_thunks->size)
52
53 #define INVOKE_THUNK(name, ...) \
54 FUNCTION_IS_IMPLEMENTED(name) \
55 ? base::UnsanitizedCfiCall(g_thunks, &MojoSystemThunks::name)(__VA_ARGS__) \
56 : NotImplemented(#name)
57
58 namespace mojo {
59
60 // NOTE: This is defined within the global mojo namespace so that it can be
61 // referenced as a friend to base::ScopedAllowBlocking when library support is
62 // enabled.
63 class CoreLibraryInitializer {
64 public:
CoreLibraryInitializer(const MojoInitializeOptions * options)65 CoreLibraryInitializer(const MojoInitializeOptions* options) {
66 #if defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_WIN)
67 bool application_provided_path = false;
68 base::Optional<base::FilePath> library_path;
69 if (options && options->struct_size >= sizeof(*options) &&
70 options->mojo_core_path) {
71 base::StringPiece utf8_path(options->mojo_core_path,
72 options->mojo_core_path_length);
73 library_path.emplace(base::FilePath::FromUTF8Unsafe(utf8_path));
74 application_provided_path = true;
75 } else {
76 auto environment = base::Environment::Create();
77 std::string library_path_value;
78 const char kLibraryPathEnvironmentVar[] = "MOJO_CORE_LIBRARY_PATH";
79 if (environment->GetVar(kLibraryPathEnvironmentVar, &library_path_value))
80 library_path = base::FilePath::FromUTF8Unsafe(library_path_value);
81 }
82
83 if (!library_path) {
84 // Default to looking for the library in the current working directory.
85 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
86 const base::FilePath::CharType kDefaultLibraryPathValue[] =
87 FILE_PATH_LITERAL("./libmojo_core.so");
88 #elif defined(OS_WIN)
89 const base::FilePath::CharType kDefaultLibraryPathValue[] =
90 FILE_PATH_LITERAL("mojo_core.dll");
91 #endif
92 library_path.emplace(kDefaultLibraryPathValue);
93 }
94
95 base::ScopedAllowBlocking allow_blocking;
96 library_.emplace(*library_path);
97 if (!application_provided_path) {
98 CHECK(library_->is_valid())
99 << "Unable to load the mojo_core library. Make sure the library is "
100 << "in the working directory or is correctly pointed to by the "
101 << "MOJO_CORE_LIBRARY_PATH environment variable.";
102 } else {
103 CHECK(library_->is_valid())
104 << "Unable to locate mojo_core library. This application expects to "
105 << "find it at " << library_path->value();
106 }
107
108 const char kGetThunksFunctionName[] = "MojoGetSystemThunks";
109 {
110 auto writer = base::AutoWritableMemory::Create(g_get_thunks);
111 *g_get_thunks = reinterpret_cast<MojoGetSystemThunksFunction>(
112 library_->GetFunctionPointer(kGetThunksFunctionName));
113 }
114 CHECK(*g_get_thunks) << "Invalid mojo_core library: "
115 << library_path->value();
116
117 DCHECK_EQ(g_thunks->size, 0u);
118 {
119 auto writer = base::AutoWritableMemory::Create(g_thunks);
120 g_thunks->size = sizeof(*g_thunks);
121 base::UnsanitizedCfiCall(g_get_thunks)(&*g_thunks);
122 }
123
124 CHECK_GT(g_thunks->size, 0u)
125 << "Invalid mojo_core library: " << library_path->value();
126 #else // defined(OS_CHROMEOS) || defined(OS_LINUX)
127 NOTREACHED()
128 << "Dynamic mojo_core loading is not supported on this platform.";
129 #endif // defined(OS_CHROMEOS) || defined(OS_LINUX)
130 }
131
132 ~CoreLibraryInitializer() = default;
133
134 private:
135 #if defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_WIN)
136 base::Optional<base::ScopedNativeLibrary> library_;
137 #endif
138
139 DISALLOW_COPY_AND_ASSIGN(CoreLibraryInitializer);
140 };
141
142 } // namespace mojo
143
144 extern "C" {
145
MojoInitialize(const struct MojoInitializeOptions * options)146 MojoResult MojoInitialize(const struct MojoInitializeOptions* options) {
147 static base::NoDestructor<mojo::CoreLibraryInitializer> initializer(options);
148 ALLOW_UNUSED_LOCAL(initializer);
149 DCHECK(g_thunks->Initialize);
150
151 return INVOKE_THUNK(Initialize, options);
152 }
153
MojoGetTimeTicksNow()154 MojoTimeTicks MojoGetTimeTicksNow() {
155 return INVOKE_THUNK(GetTimeTicksNow);
156 }
157
MojoClose(MojoHandle handle)158 MojoResult MojoClose(MojoHandle handle) {
159 return INVOKE_THUNK(Close, handle);
160 }
161
MojoQueryHandleSignalsState(MojoHandle handle,struct MojoHandleSignalsState * signals_state)162 MojoResult MojoQueryHandleSignalsState(
163 MojoHandle handle,
164 struct MojoHandleSignalsState* signals_state) {
165 return INVOKE_THUNK(QueryHandleSignalsState, handle, signals_state);
166 }
167
MojoCreateMessagePipe(const MojoCreateMessagePipeOptions * options,MojoHandle * message_pipe_handle0,MojoHandle * message_pipe_handle1)168 MojoResult MojoCreateMessagePipe(const MojoCreateMessagePipeOptions* options,
169 MojoHandle* message_pipe_handle0,
170 MojoHandle* message_pipe_handle1) {
171 return INVOKE_THUNK(CreateMessagePipe, options, message_pipe_handle0,
172 message_pipe_handle1);
173 }
174
MojoWriteMessage(MojoHandle message_pipe_handle,MojoMessageHandle message_handle,const MojoWriteMessageOptions * options)175 MojoResult MojoWriteMessage(MojoHandle message_pipe_handle,
176 MojoMessageHandle message_handle,
177 const MojoWriteMessageOptions* options) {
178 return INVOKE_THUNK(WriteMessage, message_pipe_handle, message_handle,
179 options);
180 }
181
MojoReadMessage(MojoHandle message_pipe_handle,const MojoReadMessageOptions * options,MojoMessageHandle * message_handle)182 MojoResult MojoReadMessage(MojoHandle message_pipe_handle,
183 const MojoReadMessageOptions* options,
184 MojoMessageHandle* message_handle) {
185 return INVOKE_THUNK(ReadMessage, message_pipe_handle, options,
186 message_handle);
187 }
188
MojoFuseMessagePipes(MojoHandle handle0,MojoHandle handle1,const MojoFuseMessagePipesOptions * options)189 MojoResult MojoFuseMessagePipes(MojoHandle handle0,
190 MojoHandle handle1,
191 const MojoFuseMessagePipesOptions* options) {
192 return INVOKE_THUNK(FuseMessagePipes, handle0, handle1, options);
193 }
194
MojoCreateDataPipe(const MojoCreateDataPipeOptions * options,MojoHandle * data_pipe_producer_handle,MojoHandle * data_pipe_consumer_handle)195 MojoResult MojoCreateDataPipe(const MojoCreateDataPipeOptions* options,
196 MojoHandle* data_pipe_producer_handle,
197 MojoHandle* data_pipe_consumer_handle) {
198 return INVOKE_THUNK(CreateDataPipe, options, data_pipe_producer_handle,
199 data_pipe_consumer_handle);
200 }
201
MojoWriteData(MojoHandle data_pipe_producer_handle,const void * elements,uint32_t * num_elements,const MojoWriteDataOptions * options)202 MojoResult MojoWriteData(MojoHandle data_pipe_producer_handle,
203 const void* elements,
204 uint32_t* num_elements,
205 const MojoWriteDataOptions* options) {
206 return INVOKE_THUNK(WriteData, data_pipe_producer_handle, elements,
207 num_elements, options);
208 }
209
MojoBeginWriteData(MojoHandle data_pipe_producer_handle,const MojoBeginWriteDataOptions * options,void ** buffer,uint32_t * buffer_num_elements)210 MojoResult MojoBeginWriteData(MojoHandle data_pipe_producer_handle,
211 const MojoBeginWriteDataOptions* options,
212 void** buffer,
213 uint32_t* buffer_num_elements) {
214 return INVOKE_THUNK(BeginWriteData, data_pipe_producer_handle, options,
215 buffer, buffer_num_elements);
216 }
217
MojoEndWriteData(MojoHandle data_pipe_producer_handle,uint32_t num_elements_written,const MojoEndWriteDataOptions * options)218 MojoResult MojoEndWriteData(MojoHandle data_pipe_producer_handle,
219 uint32_t num_elements_written,
220 const MojoEndWriteDataOptions* options) {
221 return INVOKE_THUNK(EndWriteData, data_pipe_producer_handle,
222 num_elements_written, options);
223 }
224
MojoReadData(MojoHandle data_pipe_consumer_handle,const MojoReadDataOptions * options,void * elements,uint32_t * num_elements)225 MojoResult MojoReadData(MojoHandle data_pipe_consumer_handle,
226 const MojoReadDataOptions* options,
227 void* elements,
228 uint32_t* num_elements) {
229 return INVOKE_THUNK(ReadData, data_pipe_consumer_handle, options, elements,
230 num_elements);
231 }
232
MojoBeginReadData(MojoHandle data_pipe_consumer_handle,const MojoBeginReadDataOptions * options,const void ** buffer,uint32_t * buffer_num_elements)233 MojoResult MojoBeginReadData(MojoHandle data_pipe_consumer_handle,
234 const MojoBeginReadDataOptions* options,
235 const void** buffer,
236 uint32_t* buffer_num_elements) {
237 return INVOKE_THUNK(BeginReadData, data_pipe_consumer_handle, options, buffer,
238 buffer_num_elements);
239 }
240
MojoEndReadData(MojoHandle data_pipe_consumer_handle,uint32_t num_elements_read,const MojoEndReadDataOptions * options)241 MojoResult MojoEndReadData(MojoHandle data_pipe_consumer_handle,
242 uint32_t num_elements_read,
243 const MojoEndReadDataOptions* options) {
244 return INVOKE_THUNK(EndReadData, data_pipe_consumer_handle, num_elements_read,
245 options);
246 }
247
MojoCreateSharedBuffer(uint64_t num_bytes,const MojoCreateSharedBufferOptions * options,MojoHandle * shared_buffer_handle)248 MojoResult MojoCreateSharedBuffer(uint64_t num_bytes,
249 const MojoCreateSharedBufferOptions* options,
250 MojoHandle* shared_buffer_handle) {
251 return INVOKE_THUNK(CreateSharedBuffer, num_bytes, options,
252 shared_buffer_handle);
253 }
254
MojoDuplicateBufferHandle(MojoHandle buffer_handle,const MojoDuplicateBufferHandleOptions * options,MojoHandle * new_buffer_handle)255 MojoResult MojoDuplicateBufferHandle(
256 MojoHandle buffer_handle,
257 const MojoDuplicateBufferHandleOptions* options,
258 MojoHandle* new_buffer_handle) {
259 return INVOKE_THUNK(DuplicateBufferHandle, buffer_handle, options,
260 new_buffer_handle);
261 }
262
MojoMapBuffer(MojoHandle buffer_handle,uint64_t offset,uint64_t num_bytes,const MojoMapBufferOptions * options,void ** buffer)263 MojoResult MojoMapBuffer(MojoHandle buffer_handle,
264 uint64_t offset,
265 uint64_t num_bytes,
266 const MojoMapBufferOptions* options,
267 void** buffer) {
268 return INVOKE_THUNK(MapBuffer, buffer_handle, offset, num_bytes, options,
269 buffer);
270 }
271
MojoUnmapBuffer(void * buffer)272 MojoResult MojoUnmapBuffer(void* buffer) {
273 return INVOKE_THUNK(UnmapBuffer, buffer);
274 }
275
MojoGetBufferInfo(MojoHandle buffer_handle,const MojoGetBufferInfoOptions * options,MojoSharedBufferInfo * info)276 MojoResult MojoGetBufferInfo(MojoHandle buffer_handle,
277 const MojoGetBufferInfoOptions* options,
278 MojoSharedBufferInfo* info) {
279 return INVOKE_THUNK(GetBufferInfo, buffer_handle, options, info);
280 }
281
MojoCreateTrap(MojoTrapEventHandler handler,const MojoCreateTrapOptions * options,MojoHandle * trap_handle)282 MojoResult MojoCreateTrap(MojoTrapEventHandler handler,
283 const MojoCreateTrapOptions* options,
284 MojoHandle* trap_handle) {
285 return INVOKE_THUNK(CreateTrap, handler, options, trap_handle);
286 }
287
MojoAddTrigger(MojoHandle trap_handle,MojoHandle handle,MojoHandleSignals signals,MojoTriggerCondition condition,uintptr_t context,const MojoAddTriggerOptions * options)288 MojoResult MojoAddTrigger(MojoHandle trap_handle,
289 MojoHandle handle,
290 MojoHandleSignals signals,
291 MojoTriggerCondition condition,
292 uintptr_t context,
293 const MojoAddTriggerOptions* options) {
294 return INVOKE_THUNK(AddTrigger, trap_handle, handle, signals, condition,
295 context, options);
296 }
297
MojoRemoveTrigger(MojoHandle trap_handle,uintptr_t context,const MojoRemoveTriggerOptions * options)298 MojoResult MojoRemoveTrigger(MojoHandle trap_handle,
299 uintptr_t context,
300 const MojoRemoveTriggerOptions* options) {
301 return INVOKE_THUNK(RemoveTrigger, trap_handle, context, options);
302 }
303
MojoArmTrap(MojoHandle trap_handle,const MojoArmTrapOptions * options,uint32_t * num_blocking_events,MojoTrapEvent * blocking_events)304 MojoResult MojoArmTrap(MojoHandle trap_handle,
305 const MojoArmTrapOptions* options,
306 uint32_t* num_blocking_events,
307 MojoTrapEvent* blocking_events) {
308 return INVOKE_THUNK(ArmTrap, trap_handle, options, num_blocking_events,
309 blocking_events);
310 }
311
MojoCreateMessage(const MojoCreateMessageOptions * options,MojoMessageHandle * message)312 MojoResult MojoCreateMessage(const MojoCreateMessageOptions* options,
313 MojoMessageHandle* message) {
314 return INVOKE_THUNK(CreateMessage, options, message);
315 }
316
MojoDestroyMessage(MojoMessageHandle message)317 MojoResult MojoDestroyMessage(MojoMessageHandle message) {
318 return INVOKE_THUNK(DestroyMessage, message);
319 }
320
MojoSerializeMessage(MojoMessageHandle message,const MojoSerializeMessageOptions * options)321 MojoResult MojoSerializeMessage(MojoMessageHandle message,
322 const MojoSerializeMessageOptions* options) {
323 return INVOKE_THUNK(SerializeMessage, message, options);
324 }
325
MojoAppendMessageData(MojoMessageHandle message,uint32_t payload_size,const MojoHandle * handles,uint32_t num_handles,const MojoAppendMessageDataOptions * options,void ** buffer,uint32_t * buffer_size)326 MojoResult MojoAppendMessageData(MojoMessageHandle message,
327 uint32_t payload_size,
328 const MojoHandle* handles,
329 uint32_t num_handles,
330 const MojoAppendMessageDataOptions* options,
331 void** buffer,
332 uint32_t* buffer_size) {
333 return INVOKE_THUNK(AppendMessageData, message, payload_size, handles,
334 num_handles, options, buffer, buffer_size);
335 }
336
MojoGetMessageData(MojoMessageHandle message,const MojoGetMessageDataOptions * options,void ** buffer,uint32_t * num_bytes,MojoHandle * handles,uint32_t * num_handles)337 MojoResult MojoGetMessageData(MojoMessageHandle message,
338 const MojoGetMessageDataOptions* options,
339 void** buffer,
340 uint32_t* num_bytes,
341 MojoHandle* handles,
342 uint32_t* num_handles) {
343 return INVOKE_THUNK(GetMessageData, message, options, buffer, num_bytes,
344 handles, num_handles);
345 }
346
MojoSetMessageContext(MojoMessageHandle message,uintptr_t context,MojoMessageContextSerializer serializer,MojoMessageContextDestructor destructor,const MojoSetMessageContextOptions * options)347 MojoResult MojoSetMessageContext(MojoMessageHandle message,
348 uintptr_t context,
349 MojoMessageContextSerializer serializer,
350 MojoMessageContextDestructor destructor,
351 const MojoSetMessageContextOptions* options) {
352 return INVOKE_THUNK(SetMessageContext, message, context, serializer,
353 destructor, options);
354 }
355
MojoGetMessageContext(MojoMessageHandle message,const MojoGetMessageContextOptions * options,uintptr_t * context)356 MojoResult MojoGetMessageContext(MojoMessageHandle message,
357 const MojoGetMessageContextOptions* options,
358 uintptr_t* context) {
359 return INVOKE_THUNK(GetMessageContext, message, options, context);
360 }
361
MojoNotifyBadMessage(MojoMessageHandle message,const char * error,uint32_t error_num_bytes,const MojoNotifyBadMessageOptions * options)362 MojoResult MojoNotifyBadMessage(MojoMessageHandle message,
363 const char* error,
364 uint32_t error_num_bytes,
365 const MojoNotifyBadMessageOptions* options) {
366 return INVOKE_THUNK(NotifyBadMessage, message, error, error_num_bytes,
367 options);
368 }
369
MojoWrapPlatformHandle(const MojoPlatformHandle * platform_handle,const MojoWrapPlatformHandleOptions * options,MojoHandle * mojo_handle)370 MojoResult MojoWrapPlatformHandle(const MojoPlatformHandle* platform_handle,
371 const MojoWrapPlatformHandleOptions* options,
372 MojoHandle* mojo_handle) {
373 return INVOKE_THUNK(WrapPlatformHandle, platform_handle, options,
374 mojo_handle);
375 }
376
MojoUnwrapPlatformHandle(MojoHandle mojo_handle,const MojoUnwrapPlatformHandleOptions * options,MojoPlatformHandle * platform_handle)377 MojoResult MojoUnwrapPlatformHandle(
378 MojoHandle mojo_handle,
379 const MojoUnwrapPlatformHandleOptions* options,
380 MojoPlatformHandle* platform_handle) {
381 return INVOKE_THUNK(UnwrapPlatformHandle, mojo_handle, options,
382 platform_handle);
383 }
384
MojoWrapPlatformSharedMemoryRegion(const struct MojoPlatformHandle * platform_handles,uint32_t num_platform_handles,uint64_t num_bytes,const MojoSharedBufferGuid * guid,MojoPlatformSharedMemoryRegionAccessMode access_mode,const MojoWrapPlatformSharedMemoryRegionOptions * options,MojoHandle * mojo_handle)385 MojoResult MojoWrapPlatformSharedMemoryRegion(
386 const struct MojoPlatformHandle* platform_handles,
387 uint32_t num_platform_handles,
388 uint64_t num_bytes,
389 const MojoSharedBufferGuid* guid,
390 MojoPlatformSharedMemoryRegionAccessMode access_mode,
391 const MojoWrapPlatformSharedMemoryRegionOptions* options,
392 MojoHandle* mojo_handle) {
393 return INVOKE_THUNK(WrapPlatformSharedMemoryRegion, platform_handles,
394 num_platform_handles, num_bytes, guid, access_mode,
395 options, mojo_handle);
396 }
397
MojoUnwrapPlatformSharedMemoryRegion(MojoHandle mojo_handle,const MojoUnwrapPlatformSharedMemoryRegionOptions * options,struct MojoPlatformHandle * platform_handles,uint32_t * num_platform_handles,uint64_t * num_bytes,struct MojoSharedBufferGuid * guid,MojoPlatformSharedMemoryRegionAccessMode * access_mode)398 MojoResult MojoUnwrapPlatformSharedMemoryRegion(
399 MojoHandle mojo_handle,
400 const MojoUnwrapPlatformSharedMemoryRegionOptions* options,
401 struct MojoPlatformHandle* platform_handles,
402 uint32_t* num_platform_handles,
403 uint64_t* num_bytes,
404 struct MojoSharedBufferGuid* guid,
405 MojoPlatformSharedMemoryRegionAccessMode* access_mode) {
406 return INVOKE_THUNK(UnwrapPlatformSharedMemoryRegion, mojo_handle, options,
407 platform_handles, num_platform_handles, num_bytes, guid,
408 access_mode);
409 }
410
MojoCreateInvitation(const MojoCreateInvitationOptions * options,MojoHandle * invitation_handle)411 MojoResult MojoCreateInvitation(const MojoCreateInvitationOptions* options,
412 MojoHandle* invitation_handle) {
413 return INVOKE_THUNK(CreateInvitation, options, invitation_handle);
414 }
415
MojoAttachMessagePipeToInvitation(MojoHandle invitation_handle,const void * name,uint32_t name_num_bytes,const MojoAttachMessagePipeToInvitationOptions * options,MojoHandle * message_pipe_handle)416 MojoResult MojoAttachMessagePipeToInvitation(
417 MojoHandle invitation_handle,
418 const void* name,
419 uint32_t name_num_bytes,
420 const MojoAttachMessagePipeToInvitationOptions* options,
421 MojoHandle* message_pipe_handle) {
422 return INVOKE_THUNK(AttachMessagePipeToInvitation, invitation_handle, name,
423 name_num_bytes, options, message_pipe_handle);
424 }
425
MojoExtractMessagePipeFromInvitation(MojoHandle invitation_handle,const void * name,uint32_t name_num_bytes,const MojoExtractMessagePipeFromInvitationOptions * options,MojoHandle * message_pipe_handle)426 MojoResult MojoExtractMessagePipeFromInvitation(
427 MojoHandle invitation_handle,
428 const void* name,
429 uint32_t name_num_bytes,
430 const MojoExtractMessagePipeFromInvitationOptions* options,
431 MojoHandle* message_pipe_handle) {
432 return INVOKE_THUNK(ExtractMessagePipeFromInvitation, invitation_handle, name,
433 name_num_bytes, options, message_pipe_handle);
434 }
435
MojoSendInvitation(MojoHandle invitation_handle,const MojoPlatformProcessHandle * process_handle,const MojoInvitationTransportEndpoint * transport_endpoint,MojoProcessErrorHandler error_handler,uintptr_t error_handler_context,const MojoSendInvitationOptions * options)436 MojoResult MojoSendInvitation(
437 MojoHandle invitation_handle,
438 const MojoPlatformProcessHandle* process_handle,
439 const MojoInvitationTransportEndpoint* transport_endpoint,
440 MojoProcessErrorHandler error_handler,
441 uintptr_t error_handler_context,
442 const MojoSendInvitationOptions* options) {
443 return INVOKE_THUNK(SendInvitation, invitation_handle, process_handle,
444 transport_endpoint, error_handler, error_handler_context,
445 options);
446 }
447
MojoAcceptInvitation(const MojoInvitationTransportEndpoint * transport_endpoint,const MojoAcceptInvitationOptions * options,MojoHandle * invitation_handle)448 MojoResult MojoAcceptInvitation(
449 const MojoInvitationTransportEndpoint* transport_endpoint,
450 const MojoAcceptInvitationOptions* options,
451 MojoHandle* invitation_handle) {
452 return INVOKE_THUNK(AcceptInvitation, transport_endpoint, options,
453 invitation_handle);
454 }
455
MojoSetQuota(MojoHandle handle,MojoQuotaType type,uint64_t limit,const MojoSetQuotaOptions * options)456 MojoResult MojoSetQuota(MojoHandle handle,
457 MojoQuotaType type,
458 uint64_t limit,
459 const MojoSetQuotaOptions* options) {
460 return INVOKE_THUNK(SetQuota, handle, type, limit, options);
461 }
462
MojoQueryQuota(MojoHandle handle,MojoQuotaType type,const MojoQueryQuotaOptions * options,uint64_t * limit,uint64_t * usage)463 MojoResult MojoQueryQuota(MojoHandle handle,
464 MojoQuotaType type,
465 const MojoQueryQuotaOptions* options,
466 uint64_t* limit,
467 uint64_t* usage) {
468 return INVOKE_THUNK(QueryQuota, handle, type, options, limit, usage);
469 }
470
471 } // extern "C"
472
MojoEmbedderSetSystemThunks(const MojoSystemThunks * thunks)473 void MojoEmbedderSetSystemThunks(const MojoSystemThunks* thunks) {
474 // Assume embedders will always use matching versions of the Mojo Core and
475 // public APIs.
476 DCHECK_EQ(thunks->size, sizeof(*g_thunks));
477
478 // This should only have to check that the |g_thunks->size| is zero, but we
479 // have multiple Mojo Core initializations in some test suites still. For now
480 // we allow double calls as long as they're the same thunks as before.
481 DCHECK(g_thunks->size == 0 || !memcmp(&*g_thunks, thunks, sizeof(*g_thunks)))
482 << "Cannot set embedder thunks after Mojo API calls have been made.";
483
484 auto writer = base::AutoWritableMemory::Create(g_thunks);
485 *g_thunks = *thunks;
486 }
487