// Copyright (c) 2011 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 CHROME_BROWSER_SERVICE_SERVICE_PROCESS_CONTROL_H_ #define CHROME_BROWSER_SERVICE_SERVICE_PROCESS_CONTROL_H_ #include <queue> #include <set> #include <string> #include <vector> #include "base/basictypes.h" #include "base/callback.h" #include "base/id_map.h" #include "base/memory/scoped_ptr.h" #include "base/process.h" #include "base/task.h" #include "content/common/notification_observer.h" #include "content/common/notification_registrar.h" #include "ipc/ipc_sync_channel.h" class Profile; class CommandLine; namespace remoting { struct ChromotingHostInfo; } // namespace remoting // A ServiceProcessControl works as a portal between the service process and // the browser process. // // It is used to start and terminate the service process. It is also used // to send and receive IPC messages from the service process. // // THREADING // // This class is accessed on the UI thread through some UI actions. It then // talks to the IPC channel on the IO thread. class ServiceProcessControl : public IPC::Channel::Sender, public IPC::Channel::Listener, public NotificationObserver { public: typedef IDMap<ServiceProcessControl>::iterator iterator; typedef std::queue<IPC::Message> MessageQueue; typedef Callback1<const remoting::ChromotingHostInfo&>::Type RemotingHostStatusHandler; // An interface for handling messages received from the service process. class MessageHandler { public: virtual ~MessageHandler() {} // Called when we receive reply to remoting host status request. virtual void OnRemotingHostInfo( const remoting::ChromotingHostInfo& host_info) = 0; }; // Construct a ServiceProcessControl with |profile|.. explicit ServiceProcessControl(Profile* profile); virtual ~ServiceProcessControl(); // Return the user profile associated with this service process. Profile* profile() const { return profile_; } // Return true if this object is connected to the service. bool is_connected() const { return channel_.get() != NULL; } // If no service process is currently running, creates a new service process // and connects to it. // If a service process is already running this method will try to connect // to it. // |success_task| is called when we have successfully launched the process // and connected to it. // |failure_task| is called when we failed to connect to the service process. // It is OK to pass the same value for |success_task| and |failure_task|. In // this case, the task is invoked on success or failure. // Note that if we are already connected to service process then // |success_task| can be invoked in the context of the Launch call. // Takes ownership of |success_task| and |failure_task|. void Launch(Task* success_task, Task* failure_task); // IPC::Channel::Listener implementation. virtual bool OnMessageReceived(const IPC::Message& message); virtual void OnChannelConnected(int32 peer_pid); virtual void OnChannelError(); // IPC::Channel::Sender implementation virtual bool Send(IPC::Message* message); // NotificationObserver implementation. virtual void Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details); // Message handlers void OnCloudPrintProxyIsEnabled(bool enabled, std::string email); void OnRemotingHostInfo(const remoting::ChromotingHostInfo& host_info); // Send a shutdown message to the service process. IPC channel will be // destroyed after calling this method. // Return true if the message was sent. bool Shutdown(); // Send request for cloud print proxy status and the registered // email address. The callback gets the information when received. bool GetCloudPrintProxyStatus( Callback2<bool, std::string>::Type* cloud_print_status_callback); // Send a message to enable the remoting service in the service process. // Return true if the message was sent. bool SetRemotingHostCredentials(const std::string& user, const std::string& auth_token); bool EnableRemotingHost(); bool DisableRemotingHost(); // Send request for current status of the remoting service. // MessageHandler::OnRemotingHostInfo() will be called when remoting host // status is available. bool RequestRemotingHostStatus(); // Add a message handler for receiving messages from the service // process. void AddMessageHandler(MessageHandler* message_handler); // Remove a message handler from the list of message handlers. Must // not be called from a message handler (i.e. while a message is // being processed). void RemoveMessageHandler(MessageHandler* message_handler); private: // This class is responsible for launching the service process on the // PROCESS_LAUNCHER thread. class Launcher : public base::RefCountedThreadSafe<ServiceProcessControl::Launcher> { public: Launcher(ServiceProcessControl* process, CommandLine* cmd_line); // Execute the command line to start the process asynchronously. // After the comamnd is executed |task| is called with the process handle on // the UI thread. void Run(Task* task); bool launched() const { return launched_; } private: friend class base::RefCountedThreadSafe<ServiceProcessControl::Launcher>; virtual ~Launcher(); #if !defined(OS_MACOSX) void DoDetectLaunched(); #endif // !OS_MACOSX void DoRun(); void Notify(); ServiceProcessControl* process_; scoped_ptr<CommandLine> cmd_line_; scoped_ptr<Task> notify_task_; bool launched_; uint32 retry_count_; }; typedef std::vector<Task*> TaskList; // Helper method to invoke all the callbacks based on success on failure. void RunConnectDoneTasks(); // Method called by Launcher when the service process is launched. void OnProcessLaunched(); // Used internally to connect to the service process. void ConnectInternal(); static void RunAllTasksHelper(TaskList* task_list); Profile* profile_; // IPC channel to the service process. scoped_ptr<IPC::SyncChannel> channel_; // Service process launcher. scoped_refptr<Launcher> launcher_; // Callbacks that get invoked when the channel is successfully connected or // if there was a failure in connecting. TaskList connect_done_tasks_; // Callbacks that get invoked ONLY when the channel is successfully connected. TaskList connect_success_tasks_; // Callbacks that get invoked ONLY when there was a connection failure. TaskList connect_failure_tasks_; // Callback that gets invoked when a status message is received from // the cloud print proxy. scoped_ptr<Callback2<bool, std::string>::Type> cloud_print_status_callback_; // Handler for messages from service process. std::set<MessageHandler*> message_handlers_; NotificationRegistrar registrar_; }; #endif // CHROME_BROWSER_SERVICE_SERVICE_PROCESS_CONTROL_H_