| // Copyright 2015 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_IPC_SUPPORT_H_ |
| #define MOJO_EDK_SYSTEM_IPC_SUPPORT_H_ |
| |
| #include "base/callback_forward.h" |
| #include "base/gtest_prod_util.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/task_runner.h" |
| #include "mojo/edk/embedder/process_type.h" |
| #include "mojo/edk/embedder/scoped_platform_handle.h" |
| #include "mojo/edk/embedder/slave_info.h" |
| #include "mojo/edk/system/channel_id.h" |
| #include "mojo/edk/system/connection_identifier.h" |
| #include "mojo/edk/system/process_identifier.h" |
| #include "mojo/edk/system/system_impl_export.h" |
| #include "mojo/public/cpp/system/macros.h" |
| |
| namespace mojo { |
| |
| namespace embedder { |
| class PlatformSupport; |
| class ProcessDelegate; |
| } |
| |
| namespace system { |
| |
| class ChannelManager; |
| class ConnectionManager; |
| class MessagePipeDispatcher; |
| |
| // This test (and its helper function) need to be friended. |
| FORWARD_DECLARE_TEST(IPCSupportTest, MasterSlaveInternal); |
| FORWARD_DECLARE_TEST(IPCSupportTest, MultiprocessMasterSlaveInternal); |
| void MultiprocessMasterSlaveInternalTestChildTest(); |
| |
| // |IPCSupport| encapsulates all the objects that are needed to support IPC for |
| // a single "process" (whether that be a master or a slave). |
| // |
| // ("Process" typically means a real process, but for testing purposes, multiple |
| // instances can coexist within a single real process.) |
| // |
| // Each "process" must have an |embedder::PlatformSupport| and a suitable |
| // |embedder::ProcessDelegate|, together with an I/O thread and a thread on |
| // which to call delegate methods (which may be the same as the I/O thread). |
| // |
| // For testing purposes within a single real process, except for the I/O thread, |
| // these may be shared between "processes" (i.e., instances of |IPCSupport|) -- |
| // there must be a separate I/O thread for each |IPCSupport|. |
| // |
| // Except for |ShutdownOnIOThread()|, this class is thread-safe. (No methods may |
| // be called during/after |ShutdownOnIOThread()|.) |
| class MOJO_SYSTEM_IMPL_EXPORT IPCSupport { |
| public: |
| // Constructor: initializes for the given |process_type|; |process_delegate| |
| // must match the process type. |platform_handle| is only used for slave |
| // processes. |
| // |
| // All the (pointer) arguments must remain alive (and, in the case of task |
| // runners, continue to process tasks) until |ShutdownOnIOThread()| has been |
| // called. |
| IPCSupport(embedder::PlatformSupport* platform_support, |
| embedder::ProcessType process_type, |
| scoped_refptr<base::TaskRunner> delegate_thread_task_runner, |
| embedder::ProcessDelegate* process_delegate, |
| scoped_refptr<base::TaskRunner> io_thread_task_runner, |
| embedder::ScopedPlatformHandle platform_handle); |
| // Note: This object must be shut down before destruction (see |
| // |ShutdownOnIOThread()|). |
| ~IPCSupport(); |
| |
| // This must be called (exactly once) on the I/O thread before this object is |
| // destroyed (which may happen on any thread). Note: This does *not* call the |
| // process delegate's |OnShutdownComplete()|. |
| void ShutdownOnIOThread(); |
| |
| // Generates a new (unique) connection identifier, for use with |
| // |ConnectToSlave()| and |ConnectToMaster()|, below. |
| ConnectionIdentifier GenerateConnectionIdentifier(); |
| |
| // Called in the master process to connect a slave process to the IPC system. |
| // |
| // |connection_id| should be a unique connection identifier, which will also |
| // be given to the slave (in |ConnectToMaster()|, below). |slave_info| is |
| // context for the caller (it is treated as an opaque value by this class). |
| // |platform_handle| should be the master's handle to an OS "pipe" between |
| // master and slave. This will then bootstrap a |Channel| between master and |
| // slave together with an initial message pipe (returning a dispatcher for the |
| // master's side). |
| // |
| // |callback| will be run after the |Channel| is created, either using |
| // |callback_thread_task_runner| (if it is non-null) or on the I/O thread. |
| // |*channel_id| will be set to the ID for the channel (immediately); the |
| // channel may be destroyed using this ID, but only after the callback has |
| // been run. |
| // |
| // TODO(vtl): Add some more channel management functionality to this class. |
| // Maybe make this callback interface more sane. |
| scoped_refptr<system::MessagePipeDispatcher> ConnectToSlave( |
| const ConnectionIdentifier& connection_id, |
| embedder::SlaveInfo slave_info, |
| embedder::ScopedPlatformHandle platform_handle, |
| const base::Closure& callback, |
| scoped_refptr<base::TaskRunner> callback_thread_task_runner, |
| ChannelId* channel_id); |
| |
| // Called in a slave process to connect it to the master process and thus the |
| // IPC system, creating a |Channel| and an initial message pipe (return a |
| // dispatcher for the slave's side). See |ConnectToSlave()|, above. |
| // |
| // |callback|, |callback_thread_task_runner|, and |channel_id| are as in |
| // |ConnectToSlave()|. |
| // |
| // TODO(vtl): |ConnectToSlave()|'s channel management TODO also applies here. |
| scoped_refptr<system::MessagePipeDispatcher> ConnectToMaster( |
| const ConnectionIdentifier& connection_id, |
| const base::Closure& callback, |
| scoped_refptr<base::TaskRunner> callback_thread_task_runner, |
| ChannelId* channel_id); |
| |
| embedder::ProcessType process_type() const { return process_type_; } |
| embedder::ProcessDelegate* process_delegate() const { |
| return process_delegate_; |
| } |
| base::TaskRunner* delegate_thread_task_runner() const { |
| return delegate_thread_task_runner_.get(); |
| } |
| base::TaskRunner* io_thread_task_runner() const { |
| return io_thread_task_runner_.get(); |
| } |
| // TODO(vtl): The things that use the following should probably be moved into |
| // this class. |
| ChannelManager* channel_manager() const { return channel_manager_.get(); } |
| |
| private: |
| // These test |ConnectToSlaveInternal()| and |ConnectToMasterInternal()|. |
| FRIEND_TEST_ALL_PREFIXES(IPCSupportTest, MasterSlaveInternal); |
| FRIEND_TEST_ALL_PREFIXES(IPCSupportTest, MultiprocessMasterSlaveInternal); |
| friend void MultiprocessMasterSlaveInternalTestChildTest(); |
| |
| // Helper for |ConnectToSlave()|. Connects (using the connection manager) to |
| // the slave using |platform_handle| (a handle to an OS "pipe" between master |
| // and slave) and creates a second OS "pipe" between the master and slave |
| // (returning the master's handle). |*slave_process_identifier| will be set to |
| // the process identifier assigned to the slave. |
| embedder::ScopedPlatformHandle ConnectToSlaveInternal( |
| const ConnectionIdentifier& connection_id, |
| embedder::SlaveInfo slave_info, |
| embedder::ScopedPlatformHandle platform_handle, |
| ProcessIdentifier* slave_process_identifier); |
| |
| // Helper for |ConnectToMaster()|. Connects (using the connection manager) to |
| // the master (using the handle to the OS "pipe" that was given to |
| // |SlaveConnectionManager::Init()|) and creates a second OS "pipe" between |
| // the master and slave (returning the slave's handle). |
| embedder::ScopedPlatformHandle ConnectToMasterInternal( |
| const ConnectionIdentifier& connection_id); |
| |
| ConnectionManager* connection_manager() const { |
| return connection_manager_.get(); |
| } |
| |
| // These are all set on construction and reset by |ShutdownOnIOThread()|. |
| embedder::ProcessType process_type_; |
| scoped_refptr<base::TaskRunner> delegate_thread_task_runner_; |
| embedder::ProcessDelegate* process_delegate_; |
| scoped_refptr<base::TaskRunner> io_thread_task_runner_; |
| |
| scoped_ptr<ConnectionManager> connection_manager_; |
| scoped_ptr<ChannelManager> channel_manager_; |
| |
| MOJO_DISALLOW_COPY_AND_ASSIGN(IPCSupport); |
| }; |
| |
| } // namespace system |
| } // namespace mojo |
| |
| #endif // MOJO_EDK_SYSTEM_IPC_SUPPORT_H_ |