386 lines
17 KiB
C++
386 lines
17 KiB
C++
// Copyright 2013 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef MOJO_CORE_CORE_H_
|
|
#define MOJO_CORE_CORE_H_
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "base/callback.h"
|
|
#include "base/macros.h"
|
|
#include "base/memory/ref_counted.h"
|
|
#include "base/memory/shared_memory_handle.h"
|
|
#include "base/synchronization/lock.h"
|
|
#include "base/task_runner.h"
|
|
#include "build/build_config.h"
|
|
#include "mojo/core/dispatcher.h"
|
|
#include "mojo/core/handle_signals_state.h"
|
|
#include "mojo/core/handle_table.h"
|
|
#include "mojo/core/node_controller.h"
|
|
#include "mojo/core/system_impl_export.h"
|
|
#include "mojo/public/c/system/buffer.h"
|
|
#include "mojo/public/c/system/data_pipe.h"
|
|
#include "mojo/public/c/system/invitation.h"
|
|
#include "mojo/public/c/system/message_pipe.h"
|
|
#include "mojo/public/c/system/platform_handle.h"
|
|
#include "mojo/public/c/system/quota.h"
|
|
#include "mojo/public/c/system/trap.h"
|
|
#include "mojo/public/c/system/types.h"
|
|
|
|
namespace base {
|
|
class PortProvider;
|
|
}
|
|
|
|
namespace mojo {
|
|
namespace core {
|
|
|
|
class MachPortRelay;
|
|
class PlatformSharedMemoryMapping;
|
|
|
|
// |Core| is an object that implements the Mojo system calls. All public methods
|
|
// are thread-safe.
|
|
class MOJO_SYSTEM_IMPL_EXPORT Core {
|
|
public:
|
|
Core();
|
|
virtual ~Core();
|
|
|
|
static Core* Get();
|
|
|
|
// Called exactly once, shortly after construction, and before any other
|
|
// methods are called on this object.
|
|
void SetIOTaskRunner(scoped_refptr<base::TaskRunner> io_task_runner);
|
|
|
|
// Retrieves the NodeController for the current process.
|
|
NodeController* GetNodeController();
|
|
|
|
scoped_refptr<Dispatcher> GetDispatcher(MojoHandle handle);
|
|
scoped_refptr<Dispatcher> GetAndRemoveDispatcher(MojoHandle handle);
|
|
|
|
void SetDefaultProcessErrorCallback(const ProcessErrorCallback& callback);
|
|
|
|
// Creates a message pipe endpoint with an unbound peer port returned in
|
|
// |*peer|. Useful for setting up cross-process bootstrap message pipes. The
|
|
// returned message pipe handle is usable immediately by the caller.
|
|
//
|
|
// The value returned in |*peer| may be passed along with a broker client
|
|
// invitation. See SendBrokerClientInvitation() below.
|
|
MojoHandle CreatePartialMessagePipe(ports::PortRef* peer);
|
|
|
|
// Like above but exchanges an existing ports::PortRef for a message pipe
|
|
// handle which wraps it.
|
|
MojoHandle CreatePartialMessagePipe(const ports::PortRef& port);
|
|
|
|
// Sends a broker client invitation to |target_process| over the connection
|
|
// medium in |connection_params|. The other end of the connection medium in
|
|
// |connection_params| can be used within the target process to call
|
|
// AcceptBrokerClientInvitation() and complete the process's admission into
|
|
// this process graph.
|
|
//
|
|
// |attached_ports| is a list of named port references to be attached to the
|
|
// invitation. An attached port can be claimed (as a message pipe handle) by
|
|
// the invitee.
|
|
void SendBrokerClientInvitation(
|
|
base::ProcessHandle target_process,
|
|
ConnectionParams connection_params,
|
|
const std::vector<std::pair<std::string, ports::PortRef>>& attached_ports,
|
|
const ProcessErrorCallback& process_error_callback);
|
|
|
|
// Accepts an invitation via |connection_params|. The other end of the
|
|
// connection medium in |connection_params| must have been used by some other
|
|
// process to send an invitation.
|
|
void AcceptBrokerClientInvitation(ConnectionParams connection_params);
|
|
|
|
// Extracts a named message pipe endpoint from the broker client invitation
|
|
// accepted by this process. Must only be called after
|
|
// AcceptBrokerClientInvitation.
|
|
MojoHandle ExtractMessagePipeFromInvitation(const std::string& name);
|
|
|
|
// Called to connect to a peer process. This should be called only if there
|
|
// is no common ancestor for the processes involved within this mojo system.
|
|
// Both processes must call this function, each passing one end of a platform
|
|
// channel. |port| is a port to be merged with the remote peer's port, which
|
|
// it will provide via the same API.
|
|
//
|
|
// |connection_name| if non-empty guarantees that no other isolated
|
|
// connections exist in the calling process using the same name. This is
|
|
// useful for invitation endpoints that use a named server accepting multiple
|
|
// connections.
|
|
void ConnectIsolated(ConnectionParams connection_params,
|
|
const ports::PortRef& port,
|
|
base::StringPiece connection_name);
|
|
|
|
// Sets the mach port provider for this process.
|
|
void SetMachPortProvider(base::PortProvider* port_provider);
|
|
|
|
#if defined(OS_MACOSX) && !defined(OS_IOS)
|
|
MachPortRelay* GetMachPortRelay();
|
|
#endif
|
|
|
|
MojoHandle AddDispatcher(scoped_refptr<Dispatcher> dispatcher);
|
|
|
|
// Adds new dispatchers for non-message-pipe handles received in a message.
|
|
// |dispatchers| and |handles| should be the same size.
|
|
bool AddDispatchersFromTransit(
|
|
const std::vector<Dispatcher::DispatcherInTransit>& dispatchers,
|
|
MojoHandle* handles);
|
|
|
|
// Marks a set of handles as busy and acquires references to each of their
|
|
// dispatchers. The caller MUST eventually call ReleaseDispatchersForTransit()
|
|
// on the resulting |*dispatchers|. Note that |*dispatchers| contents are
|
|
// extended, not replaced, by this call.
|
|
MojoResult AcquireDispatchersForTransit(
|
|
const MojoHandle* handles,
|
|
size_t num_handles,
|
|
std::vector<Dispatcher::DispatcherInTransit>* dispatchers);
|
|
|
|
// Releases dispatchers previously acquired by
|
|
// |AcquireDispatchersForTransit()|. |in_transit| should be |true| if the
|
|
// caller has fully serialized every dispatcher in |dispatchers|, in which
|
|
// case this will close and remove their handles from the handle table.
|
|
//
|
|
// If |in_transit| is false, this simply unmarks the dispatchers as busy,
|
|
// making them available for general use once again.
|
|
void ReleaseDispatchersForTransit(
|
|
const std::vector<Dispatcher::DispatcherInTransit>& dispatchers,
|
|
bool in_transit);
|
|
|
|
// Requests that the EDK tear itself down. |callback| will be called once
|
|
// the shutdown process is complete. Note that |callback| is always called
|
|
// asynchronously on the calling thread if said thread is running a message
|
|
// loop, and the calling thread must continue running a MessageLoop at least
|
|
// until the callback is called. If there is no running loop, the |callback|
|
|
// may be called from any thread. Beware!
|
|
void RequestShutdown(const base::Closure& callback);
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// The following methods are essentially implementations of the Mojo Core
|
|
// functions of the Mojo API, with the C interface translated to C++ by
|
|
// "mojo/core/embedder/entrypoints.cc". The best way to understand the
|
|
// contract of these methods is to look at the header files defining the
|
|
// corresponding API functions, referenced below.
|
|
|
|
// These methods correspond to the API functions defined in
|
|
// "mojo/public/c/system/functions.h":
|
|
MojoTimeTicks GetTimeTicksNow();
|
|
MojoResult Close(MojoHandle handle);
|
|
MojoResult QueryHandleSignalsState(MojoHandle handle,
|
|
MojoHandleSignalsState* signals_state);
|
|
MojoResult CreateTrap(MojoTrapEventHandler handler,
|
|
const MojoCreateTrapOptions* options,
|
|
MojoHandle* trap_handle);
|
|
MojoResult AddTrigger(MojoHandle trap_handle,
|
|
MojoHandle handle,
|
|
MojoHandleSignals signals,
|
|
MojoTriggerCondition condition,
|
|
uintptr_t context,
|
|
const MojoAddTriggerOptions* options);
|
|
MojoResult RemoveTrigger(MojoHandle trap_handle,
|
|
uintptr_t context,
|
|
const MojoRemoveTriggerOptions* options);
|
|
MojoResult ArmTrap(MojoHandle trap_handle,
|
|
const MojoArmTrapOptions* options,
|
|
uint32_t* num_blocking_events,
|
|
MojoTrapEvent* blocking_events);
|
|
MojoResult CreateMessage(const MojoCreateMessageOptions* options,
|
|
MojoMessageHandle* message_handle);
|
|
MojoResult DestroyMessage(MojoMessageHandle message_handle);
|
|
MojoResult SerializeMessage(MojoMessageHandle message_handle,
|
|
const MojoSerializeMessageOptions* options);
|
|
MojoResult AppendMessageData(MojoMessageHandle message_handle,
|
|
uint32_t additional_payload_size,
|
|
const MojoHandle* handles,
|
|
uint32_t num_handles,
|
|
const MojoAppendMessageDataOptions* options,
|
|
void** buffer,
|
|
uint32_t* buffer_size);
|
|
MojoResult GetMessageData(MojoMessageHandle message_handle,
|
|
const MojoGetMessageDataOptions* options,
|
|
void** buffer,
|
|
uint32_t* num_bytes,
|
|
MojoHandle* handles,
|
|
uint32_t* num_handles);
|
|
MojoResult SetMessageContext(MojoMessageHandle message_handle,
|
|
uintptr_t context,
|
|
MojoMessageContextSerializer serializer,
|
|
MojoMessageContextDestructor destructor,
|
|
const MojoSetMessageContextOptions* options);
|
|
MojoResult GetMessageContext(MojoMessageHandle message_handle,
|
|
const MojoGetMessageContextOptions* options,
|
|
uintptr_t* context);
|
|
|
|
// These methods correspond to the API functions defined in
|
|
// "mojo/public/c/system/message_pipe.h":
|
|
MojoResult CreateMessagePipe(const MojoCreateMessagePipeOptions* options,
|
|
MojoHandle* message_pipe_handle0,
|
|
MojoHandle* message_pipe_handle1);
|
|
MojoResult WriteMessage(MojoHandle message_pipe_handle,
|
|
MojoMessageHandle message_handle,
|
|
const MojoWriteMessageOptions* options);
|
|
MojoResult ReadMessage(MojoHandle message_pipe_handle,
|
|
const MojoReadMessageOptions* options,
|
|
MojoMessageHandle* message_handle);
|
|
MojoResult FuseMessagePipes(MojoHandle handle0,
|
|
MojoHandle handle1,
|
|
const MojoFuseMessagePipesOptions* options);
|
|
MojoResult NotifyBadMessage(MojoMessageHandle message_handle,
|
|
const char* error,
|
|
size_t error_num_bytes,
|
|
const MojoNotifyBadMessageOptions* options);
|
|
|
|
// These methods correspond to the API functions defined in
|
|
// "mojo/public/c/system/data_pipe.h":
|
|
MojoResult CreateDataPipe(const MojoCreateDataPipeOptions* options,
|
|
MojoHandle* data_pipe_producer_handle,
|
|
MojoHandle* data_pipe_consumer_handle);
|
|
MojoResult WriteData(MojoHandle data_pipe_producer_handle,
|
|
const void* elements,
|
|
uint32_t* num_bytes,
|
|
const MojoWriteDataOptions* options);
|
|
MojoResult BeginWriteData(MojoHandle data_pipe_producer_handle,
|
|
const MojoBeginWriteDataOptions* options,
|
|
void** buffer,
|
|
uint32_t* buffer_num_bytes);
|
|
MojoResult EndWriteData(MojoHandle data_pipe_producer_handle,
|
|
uint32_t num_bytes_written,
|
|
const MojoEndWriteDataOptions* options);
|
|
MojoResult ReadData(MojoHandle data_pipe_consumer_handle,
|
|
const MojoReadDataOptions* options,
|
|
void* elements,
|
|
uint32_t* num_bytes);
|
|
MojoResult BeginReadData(MojoHandle data_pipe_consumer_handle,
|
|
const MojoBeginReadDataOptions* options,
|
|
const void** buffer,
|
|
uint32_t* buffer_num_bytes);
|
|
MojoResult EndReadData(MojoHandle data_pipe_consumer_handle,
|
|
uint32_t num_bytes_read,
|
|
const MojoEndReadDataOptions* options);
|
|
|
|
// These methods correspond to the API functions defined in
|
|
// "mojo/public/c/system/buffer.h":
|
|
MojoResult CreateSharedBuffer(uint64_t num_bytes,
|
|
const MojoCreateSharedBufferOptions* options,
|
|
MojoHandle* shared_buffer_handle);
|
|
MojoResult DuplicateBufferHandle(
|
|
MojoHandle buffer_handle,
|
|
const MojoDuplicateBufferHandleOptions* options,
|
|
MojoHandle* new_buffer_handle);
|
|
MojoResult MapBuffer(MojoHandle buffer_handle,
|
|
uint64_t offset,
|
|
uint64_t num_bytes,
|
|
const MojoMapBufferOptions* options,
|
|
void** buffer);
|
|
MojoResult UnmapBuffer(void* buffer);
|
|
MojoResult GetBufferInfo(MojoHandle buffer_handle,
|
|
const MojoGetBufferInfoOptions* options,
|
|
MojoSharedBufferInfo* info);
|
|
|
|
// These methods correspond to the API functions defined in
|
|
// "mojo/public/c/system/platform_handle.h".
|
|
MojoResult WrapPlatformHandle(const MojoPlatformHandle* platform_handle,
|
|
const MojoWrapPlatformHandleOptions* options,
|
|
MojoHandle* mojo_handle);
|
|
MojoResult UnwrapPlatformHandle(
|
|
MojoHandle mojo_handle,
|
|
const MojoUnwrapPlatformHandleOptions* options,
|
|
MojoPlatformHandle* platform_handle);
|
|
MojoResult WrapPlatformSharedMemoryRegion(
|
|
const MojoPlatformHandle* platform_handles,
|
|
uint32_t num_platform_handles,
|
|
uint64_t size,
|
|
const MojoSharedBufferGuid* guid,
|
|
MojoPlatformSharedMemoryRegionAccessMode access_mode,
|
|
const MojoWrapPlatformSharedMemoryRegionOptions* options,
|
|
MojoHandle* mojo_handle);
|
|
MojoResult UnwrapPlatformSharedMemoryRegion(
|
|
MojoHandle mojo_handle,
|
|
const MojoUnwrapPlatformSharedMemoryRegionOptions* options,
|
|
MojoPlatformHandle* platform_handles,
|
|
uint32_t* num_platform_handles,
|
|
uint64_t* size,
|
|
MojoSharedBufferGuid* guid,
|
|
MojoPlatformSharedMemoryRegionAccessMode* access_mode);
|
|
|
|
// Invitation API.
|
|
MojoResult CreateInvitation(const MojoCreateInvitationOptions* options,
|
|
MojoHandle* invitation_handle);
|
|
MojoResult AttachMessagePipeToInvitation(
|
|
MojoHandle invitation_handle,
|
|
const void* name,
|
|
uint32_t name_num_bytes,
|
|
const MojoAttachMessagePipeToInvitationOptions* options,
|
|
MojoHandle* message_pipe_handle);
|
|
MojoResult ExtractMessagePipeFromInvitation(
|
|
MojoHandle invitation_handle,
|
|
const void* name,
|
|
uint32_t name_num_bytes,
|
|
const MojoExtractMessagePipeFromInvitationOptions* options,
|
|
MojoHandle* message_pipe_handle);
|
|
MojoResult SendInvitation(
|
|
MojoHandle invitation_handle,
|
|
const MojoPlatformProcessHandle* process_handle,
|
|
const MojoInvitationTransportEndpoint* transport_endpoint,
|
|
MojoProcessErrorHandler error_handler,
|
|
uintptr_t error_handler_context,
|
|
const MojoSendInvitationOptions* options);
|
|
MojoResult AcceptInvitation(
|
|
const MojoInvitationTransportEndpoint* transport_endpoint,
|
|
const MojoAcceptInvitationOptions* options,
|
|
MojoHandle* invitation_handle);
|
|
|
|
// Quota API.
|
|
MojoResult SetQuota(MojoHandle handle,
|
|
MojoQuotaType type,
|
|
uint64_t limit,
|
|
const MojoSetQuotaOptions* options);
|
|
MojoResult QueryQuota(MojoHandle handle,
|
|
MojoQuotaType type,
|
|
const MojoQueryQuotaOptions* options,
|
|
uint64_t* limit,
|
|
uint64_t* usage);
|
|
|
|
void GetActiveHandlesForTest(std::vector<MojoHandle>* handles);
|
|
|
|
private:
|
|
// Used to pass ownership of our NodeController over to the IO thread in the
|
|
// event that we're torn down before said thread.
|
|
static void PassNodeControllerToIOThread(
|
|
std::unique_ptr<NodeController> node_controller);
|
|
|
|
// Guards node_controller_.
|
|
//
|
|
// TODO(rockot): Consider removing this. It's only needed because we
|
|
// initialize node_controller_ lazily and that may happen on any thread.
|
|
// Otherwise it's effectively const and shouldn't need to be guarded.
|
|
//
|
|
// We can get rid of lazy initialization if we defer Mojo initialization far
|
|
// enough that zygotes don't do it. The zygote can't create a NodeController.
|
|
base::Lock node_controller_lock_;
|
|
|
|
// This is lazily initialized on first access. Always use GetNodeController()
|
|
// to access it.
|
|
std::unique_ptr<NodeController> node_controller_;
|
|
|
|
// The default callback to invoke, if any, when a process error is reported
|
|
// but cannot be associated with a specific process.
|
|
ProcessErrorCallback default_process_error_callback_;
|
|
|
|
std::unique_ptr<HandleTable> handles_;
|
|
|
|
base::Lock mapping_table_lock_; // Protects |mapping_table_|.
|
|
|
|
using MappingTable =
|
|
std::unordered_map<void*, std::unique_ptr<PlatformSharedMemoryMapping>>;
|
|
MappingTable mapping_table_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(Core);
|
|
};
|
|
|
|
} // namespace core
|
|
} // namespace mojo
|
|
|
|
#endif // MOJO_CORE_CORE_H_
|