michael@0: // Copyright (c) 2009 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #ifndef CHROME_COMMON_CHILD_PROCESS_HOST_H_ michael@0: #define CHROME_COMMON_CHILD_PROCESS_HOST_H_ michael@0: michael@0: #include "build/build_config.h" michael@0: michael@0: #include michael@0: michael@0: #include "base/basictypes.h" michael@0: #include "base/scoped_ptr.h" michael@0: #include "base/waitable_event_watcher.h" michael@0: #include "chrome/common/child_process_info.h" michael@0: #include "chrome/common/ipc_channel.h" michael@0: michael@0: namespace mozilla { michael@0: namespace ipc { michael@0: class FileDescriptor; michael@0: } michael@0: } michael@0: michael@0: class NotificationType; michael@0: michael@0: // Plugins/workers and other child processes that live on the IO thread should michael@0: // derive from this class. michael@0: class ChildProcessHost : michael@0: public IPC::Message::Sender, michael@0: public ChildProcessInfo, michael@0: public base::WaitableEventWatcher::Delegate, michael@0: public IPC::Channel::Listener { michael@0: public: michael@0: virtual ~ChildProcessHost(); michael@0: michael@0: // ResourceDispatcherHost::Receiver implementation: michael@0: virtual bool Send(IPC::Message* msg); michael@0: michael@0: // The Iterator class allows iteration through either all child processes, or michael@0: // ones of a specific type, depending on which constructor is used. Note that michael@0: // this should be done from the IO thread and that the iterator should not be michael@0: // kept around as it may be invalidated on subsequent event processing in the michael@0: // event loop. michael@0: class Iterator { michael@0: public: michael@0: Iterator(); michael@0: Iterator(ProcessType type); michael@0: ChildProcessHost* operator->() { return *iterator_; } michael@0: ChildProcessHost* operator*() { return *iterator_; } michael@0: ChildProcessHost* operator++(); michael@0: bool Done(); michael@0: michael@0: private: michael@0: bool all_; michael@0: ProcessType type_; michael@0: std::list::iterator iterator_; michael@0: }; michael@0: michael@0: protected: michael@0: explicit ChildProcessHost(ProcessType type); michael@0: michael@0: // Derived classes return true if it's ok to shut down the child process. michael@0: virtual bool CanShutdown() = 0; michael@0: michael@0: // Creates the IPC channel. Returns true iff it succeeded. michael@0: bool CreateChannel(); michael@0: michael@0: bool CreateChannel(mozilla::ipc::FileDescriptor& aFileDescriptor); michael@0: michael@0: // Once the subclass gets a handle to the process, it needs to tell michael@0: // ChildProcessHost using this function. michael@0: void SetHandle(base::ProcessHandle handle); michael@0: michael@0: // Notifies us that an instance has been created on this child process. michael@0: void InstanceCreated(); michael@0: michael@0: // IPC::Channel::Listener implementation: michael@0: virtual void OnMessageReceived(const IPC::Message& msg) { } michael@0: virtual void OnChannelConnected(int32_t peer_pid) { } michael@0: virtual void OnChannelError() { } michael@0: michael@0: bool opening_channel() { return opening_channel_; } michael@0: const std::wstring& channel_id() { return channel_id_; } michael@0: michael@0: base::WaitableEvent* GetProcessEvent() { return process_event_.get(); } michael@0: michael@0: const IPC::Channel& channel() const { return *channel_; } michael@0: IPC::Channel* channelp() const { return channel_.get(); } michael@0: michael@0: private: michael@0: // Sends the given notification to the notification service on the UI thread. michael@0: void Notify(NotificationType type); michael@0: michael@0: protected: michael@0: // WaitableEventWatcher::Delegate implementation: michael@0: virtual void OnWaitableEventSignaled(base::WaitableEvent *event); michael@0: michael@0: private: michael@0: // By using an internal class as the IPC::Channel::Listener, we can intercept michael@0: // OnMessageReceived/OnChannelConnected and do our own processing before michael@0: // calling the subclass' implementation. michael@0: class ListenerHook : public IPC::Channel::Listener { michael@0: public: michael@0: ListenerHook(ChildProcessHost* host); michael@0: virtual void OnMessageReceived(const IPC::Message& msg); michael@0: virtual void OnChannelConnected(int32_t peer_pid); michael@0: virtual void OnChannelError(); michael@0: virtual void GetQueuedMessages(std::queue& queue); michael@0: private: michael@0: ChildProcessHost* host_; michael@0: }; michael@0: michael@0: ListenerHook listener_; michael@0: michael@0: // True while we're waiting the channel to be opened. michael@0: bool opening_channel_; michael@0: michael@0: // The IPC::Channel. michael@0: scoped_ptr channel_; michael@0: michael@0: // IPC Channel's id. michael@0: std::wstring channel_id_; michael@0: michael@0: // Used to watch the child process handle. michael@0: base::WaitableEventWatcher watcher_; michael@0: michael@0: scoped_ptr process_event_; michael@0: }; michael@0: michael@0: #endif // CHROME_COMMON_CHILD_PROCESS_HOST_H_