// 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 #include #include #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 io_task_runner); // Retrieves the NodeController for the current process. NodeController* GetNodeController(); scoped_refptr GetDispatcher(MojoHandle handle); scoped_refptr 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>& 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); // 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& 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* 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& 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* 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 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 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 handles_; base::Lock mapping_table_lock_; // Protects |mapping_table_|. using MappingTable = std::unordered_map>; MappingTable mapping_table_; DISALLOW_COPY_AND_ASSIGN(Core); }; } // namespace core } // namespace mojo #endif // MOJO_CORE_CORE_H_