1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_SERVICE_SERVICE_PROCESS_CONTROL_H_ 6 #define CHROME_BROWSER_SERVICE_SERVICE_PROCESS_CONTROL_H_ 7 8 #include <queue> 9 #include <set> 10 #include <string> 11 #include <vector> 12 13 #include "base/basictypes.h" 14 #include "base/callback.h" 15 #include "base/id_map.h" 16 #include "base/memory/scoped_ptr.h" 17 #include "base/process.h" 18 #include "base/task.h" 19 #include "content/common/notification_observer.h" 20 #include "content/common/notification_registrar.h" 21 #include "ipc/ipc_sync_channel.h" 22 23 class Profile; 24 class CommandLine; 25 26 namespace remoting { 27 struct ChromotingHostInfo; 28 } // namespace remoting 29 30 // A ServiceProcessControl works as a portal between the service process and 31 // the browser process. 32 // 33 // It is used to start and terminate the service process. It is also used 34 // to send and receive IPC messages from the service process. 35 // 36 // THREADING 37 // 38 // This class is accessed on the UI thread through some UI actions. It then 39 // talks to the IPC channel on the IO thread. 40 class ServiceProcessControl : public IPC::Channel::Sender, 41 public IPC::Channel::Listener, 42 public NotificationObserver { 43 public: 44 typedef IDMap<ServiceProcessControl>::iterator iterator; 45 typedef std::queue<IPC::Message> MessageQueue; 46 typedef Callback1<const remoting::ChromotingHostInfo&>::Type 47 RemotingHostStatusHandler; 48 49 // An interface for handling messages received from the service process. 50 class MessageHandler { 51 public: ~MessageHandler()52 virtual ~MessageHandler() {} 53 54 // Called when we receive reply to remoting host status request. 55 virtual void OnRemotingHostInfo( 56 const remoting::ChromotingHostInfo& host_info) = 0; 57 }; 58 59 // Construct a ServiceProcessControl with |profile|.. 60 explicit ServiceProcessControl(Profile* profile); 61 virtual ~ServiceProcessControl(); 62 63 // Return the user profile associated with this service process. profile()64 Profile* profile() const { return profile_; } 65 66 // Return true if this object is connected to the service. is_connected()67 bool is_connected() const { return channel_.get() != NULL; } 68 69 // If no service process is currently running, creates a new service process 70 // and connects to it. 71 // If a service process is already running this method will try to connect 72 // to it. 73 // |success_task| is called when we have successfully launched the process 74 // and connected to it. 75 // |failure_task| is called when we failed to connect to the service process. 76 // It is OK to pass the same value for |success_task| and |failure_task|. In 77 // this case, the task is invoked on success or failure. 78 // Note that if we are already connected to service process then 79 // |success_task| can be invoked in the context of the Launch call. 80 // Takes ownership of |success_task| and |failure_task|. 81 void Launch(Task* success_task, Task* failure_task); 82 83 // IPC::Channel::Listener implementation. 84 virtual bool OnMessageReceived(const IPC::Message& message); 85 virtual void OnChannelConnected(int32 peer_pid); 86 virtual void OnChannelError(); 87 88 // IPC::Channel::Sender implementation 89 virtual bool Send(IPC::Message* message); 90 91 // NotificationObserver implementation. 92 virtual void Observe(NotificationType type, 93 const NotificationSource& source, 94 const NotificationDetails& details); 95 96 // Message handlers 97 void OnCloudPrintProxyIsEnabled(bool enabled, std::string email); 98 void OnRemotingHostInfo(const remoting::ChromotingHostInfo& host_info); 99 100 // Send a shutdown message to the service process. IPC channel will be 101 // destroyed after calling this method. 102 // Return true if the message was sent. 103 bool Shutdown(); 104 105 // Send request for cloud print proxy status and the registered 106 // email address. The callback gets the information when received. 107 bool GetCloudPrintProxyStatus( 108 Callback2<bool, std::string>::Type* cloud_print_status_callback); 109 110 // Send a message to enable the remoting service in the service process. 111 // Return true if the message was sent. 112 bool SetRemotingHostCredentials(const std::string& user, 113 const std::string& auth_token); 114 115 bool EnableRemotingHost(); 116 bool DisableRemotingHost(); 117 118 // Send request for current status of the remoting service. 119 // MessageHandler::OnRemotingHostInfo() will be called when remoting host 120 // status is available. 121 bool RequestRemotingHostStatus(); 122 123 // Add a message handler for receiving messages from the service 124 // process. 125 void AddMessageHandler(MessageHandler* message_handler); 126 127 // Remove a message handler from the list of message handlers. Must 128 // not be called from a message handler (i.e. while a message is 129 // being processed). 130 void RemoveMessageHandler(MessageHandler* message_handler); 131 132 private: 133 // This class is responsible for launching the service process on the 134 // PROCESS_LAUNCHER thread. 135 class Launcher 136 : public base::RefCountedThreadSafe<ServiceProcessControl::Launcher> { 137 public: 138 Launcher(ServiceProcessControl* process, CommandLine* cmd_line); 139 // Execute the command line to start the process asynchronously. 140 // After the comamnd is executed |task| is called with the process handle on 141 // the UI thread. 142 void Run(Task* task); 143 launched()144 bool launched() const { return launched_; } 145 146 private: 147 friend class base::RefCountedThreadSafe<ServiceProcessControl::Launcher>; 148 virtual ~Launcher(); 149 150 #if !defined(OS_MACOSX) 151 void DoDetectLaunched(); 152 #endif // !OS_MACOSX 153 154 void DoRun(); 155 void Notify(); 156 ServiceProcessControl* process_; 157 scoped_ptr<CommandLine> cmd_line_; 158 scoped_ptr<Task> notify_task_; 159 bool launched_; 160 uint32 retry_count_; 161 }; 162 163 typedef std::vector<Task*> TaskList; 164 165 // Helper method to invoke all the callbacks based on success on failure. 166 void RunConnectDoneTasks(); 167 168 // Method called by Launcher when the service process is launched. 169 void OnProcessLaunched(); 170 171 // Used internally to connect to the service process. 172 void ConnectInternal(); 173 174 static void RunAllTasksHelper(TaskList* task_list); 175 176 Profile* profile_; 177 178 // IPC channel to the service process. 179 scoped_ptr<IPC::SyncChannel> channel_; 180 181 // Service process launcher. 182 scoped_refptr<Launcher> launcher_; 183 184 // Callbacks that get invoked when the channel is successfully connected or 185 // if there was a failure in connecting. 186 TaskList connect_done_tasks_; 187 // Callbacks that get invoked ONLY when the channel is successfully connected. 188 TaskList connect_success_tasks_; 189 // Callbacks that get invoked ONLY when there was a connection failure. 190 TaskList connect_failure_tasks_; 191 192 // Callback that gets invoked when a status message is received from 193 // the cloud print proxy. 194 scoped_ptr<Callback2<bool, std::string>::Type> cloud_print_status_callback_; 195 196 // Handler for messages from service process. 197 std::set<MessageHandler*> message_handlers_; 198 199 NotificationRegistrar registrar_; 200 }; 201 202 #endif // CHROME_BROWSER_SERVICE_SERVICE_PROCESS_CONTROL_H_ 203