// 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_EDK_SYSTEM_CORE_H_ #define MOJO_EDK_SYSTEM_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 "mojo/edk/embedder/scoped_platform_handle.h" #include "mojo/edk/system/dispatcher.h" #include "mojo/edk/system/handle_signals_state.h" #include "mojo/edk/system/handle_table.h" #include "mojo/edk/system/mapping_table.h" #include "mojo/edk/system/node_controller.h" #include "mojo/edk/system/system_impl_export.h" #include "mojo/public/c/system/buffer.h" #include "mojo/public/c/system/data_pipe.h" #include "mojo/public/c/system/message_pipe.h" #include "mojo/public/c/system/platform_handle.h" #include "mojo/public/c/system/types.h" #include "mojo/public/cpp/system/message_pipe.h" namespace base { class PortProvider; } namespace mojo { namespace edk { // |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(); // 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); void SetDefaultProcessErrorCallback(const ProcessErrorCallback& callback); // Called in the parent process any time a new child is launched. void AddChild(base::ProcessHandle process_handle, ConnectionParams connection_params, const std::string& child_token, const ProcessErrorCallback& process_error_callback); // Called in the parent process when a child process fails to launch. void ChildLaunchFailed(const std::string& child_token); // 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. This returns one end of a message pipe to each process. ScopedMessagePipeHandle ConnectToPeerProcess(ScopedPlatformHandle pipe_handle, const std::string& peer_token); void ClosePeerConnection(const std::string& peer_token); // Called in a child process exactly once during early initialization. void InitChild(ConnectionParams connection_params); // Creates a message pipe endpoint associated with |token|, which a child // holding the token can later locate and connect to. ScopedMessagePipeHandle CreateParentMessagePipe( const std::string& token, const std::string& child_token); // Creates a message pipe endpoint and connects it to a pipe the parent has // associated with |token|. ScopedMessagePipeHandle CreateChildMessagePipe(const std::string& token); // Sets the mach port provider for this process. void SetMachPortProvider(base::PortProvider* port_provider); 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); // See "mojo/edk/embedder/embedder.h" for more information on these functions. MojoResult CreatePlatformHandleWrapper(ScopedPlatformHandle platform_handle, MojoHandle* wrapper_handle); MojoResult PassWrappedPlatformHandle(MojoHandle wrapper_handle, ScopedPlatformHandle* platform_handle); MojoResult CreateSharedBufferWrapper( base::SharedMemoryHandle shared_memory_handle, size_t num_bytes, bool read_only, MojoHandle* mojo_wrapper_handle); MojoResult PassSharedMemoryHandle( MojoHandle mojo_handle, base::SharedMemoryHandle* shared_memory_handle, size_t* num_bytes, bool* read_only); // 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); MojoResult SetProperty(MojoPropertyType type, const void* value); // --------------------------------------------------------------------------- // The following methods are essentially implementations of the Mojo Core // functions of the Mojo API, with the C interface translated to C++ by // "mojo/edk/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 Wait(MojoHandle handle, MojoHandleSignals signals, MojoDeadline deadline, MojoHandleSignalsState* signals_state); MojoResult WaitMany(const MojoHandle* handles, const MojoHandleSignals* signals, uint32_t num_handles, MojoDeadline deadline, uint32_t* result_index, MojoHandleSignalsState* signals_states); MojoResult Watch(MojoHandle handle, MojoHandleSignals signals, MojoWatchCallback callback, uintptr_t context); MojoResult CancelWatch(MojoHandle handle, uintptr_t context); MojoResult AllocMessage(uint32_t num_bytes, const MojoHandle* handles, uint32_t num_handles, MojoAllocMessageFlags flags, MojoMessageHandle* message); MojoResult FreeMessage(MojoMessageHandle message); MojoResult GetMessageBuffer(MojoMessageHandle message, void** buffer); MojoResult GetProperty(MojoPropertyType type, void* value); // These methods correspond to the API functions defined in // "mojo/public/c/system/wait_set.h": MojoResult CreateWaitSet(MojoHandle* wait_set_handle); MojoResult AddHandle(MojoHandle wait_set_handle, MojoHandle handle, MojoHandleSignals signals); MojoResult RemoveHandle(MojoHandle wait_set_handle, MojoHandle handle); MojoResult GetReadyHandles(MojoHandle wait_set_handle, uint32_t* count, MojoHandle* handles, MojoResult* results, MojoHandleSignalsState* signals_states); // 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, const void* bytes, uint32_t num_bytes, const MojoHandle* handles, uint32_t num_handles, MojoWriteMessageFlags flags); MojoResult WriteMessageNew(MojoHandle message_pipe_handle, MojoMessageHandle message, MojoWriteMessageFlags flags); MojoResult ReadMessage(MojoHandle message_pipe_handle, void* bytes, uint32_t* num_bytes, MojoHandle* handles, uint32_t* num_handles, MojoReadMessageFlags flags); MojoResult ReadMessageNew(MojoHandle message_pipe_handle, MojoMessageHandle* message, uint32_t* num_bytes, MojoHandle* handles, uint32_t* num_handles, MojoReadMessageFlags flags); MojoResult FuseMessagePipes(MojoHandle handle0, MojoHandle handle1); MojoResult NotifyBadMessage(MojoMessageHandle message, const char* error, size_t error_num_bytes); // 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, MojoWriteDataFlags flags); MojoResult BeginWriteData(MojoHandle data_pipe_producer_handle, void** buffer, uint32_t* buffer_num_bytes, MojoWriteDataFlags flags); MojoResult EndWriteData(MojoHandle data_pipe_producer_handle, uint32_t num_bytes_written); MojoResult ReadData(MojoHandle data_pipe_consumer_handle, void* elements, uint32_t* num_bytes, MojoReadDataFlags flags); MojoResult BeginReadData(MojoHandle data_pipe_consumer_handle, const void** buffer, uint32_t* buffer_num_bytes, MojoReadDataFlags flags); MojoResult EndReadData(MojoHandle data_pipe_consumer_handle, uint32_t num_bytes_read); // These methods correspond to the API functions defined in // "mojo/public/c/system/buffer.h": MojoResult CreateSharedBuffer( const MojoCreateSharedBufferOptions* options, uint64_t num_bytes, 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, void** buffer, MojoMapBufferFlags flags); MojoResult UnmapBuffer(void* buffer); // These methods correspond to the API functions defined in // "mojo/public/c/system/platform_handle.h". MojoResult WrapPlatformHandle(const MojoPlatformHandle* platform_handle, MojoHandle* mojo_handle); MojoResult UnwrapPlatformHandle(MojoHandle mojo_handle, MojoPlatformHandle* platform_handle); MojoResult WrapPlatformSharedBufferHandle( const MojoPlatformHandle* platform_handle, size_t size, MojoPlatformSharedBufferHandleFlags flags, MojoHandle* mojo_handle); MojoResult UnwrapPlatformSharedBufferHandle( MojoHandle mojo_handle, MojoPlatformHandle* platform_handle, size_t* size, MojoPlatformSharedBufferHandleFlags* flags); void GetActiveHandlesForTest(std::vector<MojoHandle>* handles); private: MojoResult WaitManyInternal(const MojoHandle* handles, const MojoHandleSignals* signals, uint32_t num_handles, MojoDeadline deadline, uint32_t* result_index, HandleSignalsState* signals_states); // 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_; base::Lock handles_lock_; HandleTable handles_; base::Lock mapping_table_lock_; // Protects |mapping_table_|. MappingTable mapping_table_; base::Lock property_lock_; // Properties that can be read using the MojoGetProperty() API. bool property_sync_call_allowed_ = true; DISALLOW_COPY_AND_ASSIGN(Core); }; } // namespace edk } // namespace mojo #endif // MOJO_EDK_SYSTEM_CORE_H_