1 // Copyright (c) 2012 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_PROCESS_SERVICE_PROCESS_CONTROL_H_ 6 #define CHROME_BROWSER_SERVICE_PROCESS_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/cancelable_callback.h" 16 #include "base/id_map.h" 17 #include "base/memory/scoped_ptr.h" 18 #include "base/memory/singleton.h" 19 #include "base/process/process.h" 20 #include "content/public/browser/notification_observer.h" 21 #include "content/public/browser/notification_registrar.h" 22 #include "ipc/ipc_channel_proxy.h" 23 #include "ipc/ipc_listener.h" 24 #include "ipc/ipc_sender.h" 25 26 namespace base { 27 class CommandLine; 28 } 29 30 namespace cloud_print { 31 struct CloudPrintProxyInfo; 32 } // namespace cloud_print 33 34 // A ServiceProcessControl works as a portal between the service process and 35 // the browser process. 36 // 37 // It is used to start and terminate the service process. It is also used 38 // to send and receive IPC messages from the service process. 39 // 40 // THREADING 41 // 42 // This class is accessed on the UI thread through some UI actions. It then 43 // talks to the IPC channel on the IO thread. 44 class ServiceProcessControl : public IPC::Sender, 45 public IPC::Listener, 46 public content::NotificationObserver { 47 public: 48 enum ServiceProcessEvent { 49 SERVICE_EVENT_INITIALIZE, 50 SERVICE_EVENT_ENABLED_ON_LAUNCH, 51 SERVICE_EVENT_ENABLE, 52 SERVICE_EVENT_DISABLE, 53 SERVICE_EVENT_DISABLE_BY_POLICY, 54 SERVICE_EVENT_LAUNCH, 55 SERVICE_EVENT_LAUNCHED, 56 SERVICE_EVENT_LAUNCH_FAILED, 57 SERVICE_EVENT_CHANNEL_CONNECTED, 58 SERVICE_EVENT_CHANNEL_ERROR, 59 SERVICE_EVENT_INFO_REQUEST, 60 SERVICE_EVENT_INFO_REPLY, 61 SERVICE_EVENT_HISTOGRAMS_REQUEST, 62 SERVICE_EVENT_HISTOGRAMS_REPLY, 63 SERVICE_PRINTERS_REQUEST, 64 SERVICE_PRINTERS_REPLY, 65 SERVICE_EVENT_MAX, 66 }; 67 68 typedef IDMap<ServiceProcessControl>::iterator iterator; 69 typedef std::queue<IPC::Message> MessageQueue; 70 typedef base::Callback<void(const cloud_print::CloudPrintProxyInfo&)> 71 CloudPrintProxyInfoCallback; 72 typedef base::Callback<void(const std::vector<std::string>&)> 73 PrintersCallback; 74 75 // Returns the singleton instance of this class. 76 static ServiceProcessControl* GetInstance(); 77 78 // Return true if this object is connected to the service. 79 // Virtual for testing. 80 virtual bool IsConnected() const; 81 82 // If no service process is currently running, creates a new service process 83 // and connects to it. If a service process is already running this method 84 // will try to connect to it. 85 // |success_task| is called when we have successfully launched the process 86 // and connected to it. 87 // |failure_task| is called when we failed to connect to the service process. 88 // It is OK to pass the same value for |success_task| and |failure_task|. In 89 // this case, the task is invoked on success or failure. 90 // Note that if we are already connected to service process then 91 // |success_task| can be invoked in the context of the Launch call. 92 // Virtual for testing. 93 virtual void Launch(const base::Closure& success_task, 94 const base::Closure& failure_task); 95 96 // Disconnect the IPC channel from the service process. 97 // Virtual for testing. 98 virtual void Disconnect(); 99 100 // IPC::Listener implementation. 101 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; 102 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE; 103 virtual void OnChannelError() OVERRIDE; 104 105 // IPC::Sender implementation 106 virtual bool Send(IPC::Message* message) OVERRIDE; 107 108 // content::NotificationObserver implementation. 109 virtual void Observe(int type, 110 const content::NotificationSource& source, 111 const content::NotificationDetails& details) OVERRIDE; 112 113 // Send a shutdown message to the service process. IPC channel will be 114 // destroyed after calling this method. 115 // Return true if the message was sent. 116 // Virtual for testing. 117 virtual bool Shutdown(); 118 119 // Send request for cloud print proxy info (enabled state, email, proxy id). 120 // The callback gets the information when received. 121 // Returns true if request was sent. Callback will be called only in case of 122 // reply from service. The method resets any previous callback. 123 // This call starts service if needed. 124 bool GetCloudPrintProxyInfo( 125 const CloudPrintProxyInfoCallback& cloud_print_status_callback); 126 127 // Send request for histograms collected in service process. 128 // Returns true if request was sent, and callback will be called in case of 129 // success or timeout. The method resets any previous callback. 130 // Returns false if service is not running or other failure, callback will not 131 // be called in this case. 132 bool GetHistograms(const base::Closure& cloud_print_status_callback, 133 const base::TimeDelta& timeout); 134 135 // Send request for printers available for cloud print proxy. 136 // The callback gets the information when received. 137 // Returns true if request was sent. Callback will be called only in case of 138 // reply from service. The method resets any previous callback. 139 // This call starts service if needed. 140 bool GetPrinters(const PrintersCallback& enumerate_printers_callback); 141 142 private: 143 // This class is responsible for launching the service process on the 144 // PROCESS_LAUNCHER thread. 145 class Launcher 146 : public base::RefCountedThreadSafe<ServiceProcessControl::Launcher> { 147 public: 148 Launcher(ServiceProcessControl* process, 149 scoped_ptr<base::CommandLine> cmd_line); 150 // Execute the command line to start the process asynchronously. After the 151 // command is executed |task| is called with the process handle on the UI 152 // thread. 153 void Run(const base::Closure& task); 154 155 bool launched() const { return launched_; } 156 157 private: 158 friend class base::RefCountedThreadSafe<ServiceProcessControl::Launcher>; 159 virtual ~Launcher(); 160 161 #if !defined(OS_MACOSX) 162 void DoDetectLaunched(); 163 #endif // !OS_MACOSX 164 165 void DoRun(); 166 void Notify(); 167 void CloseProcessHandle(); 168 ServiceProcessControl* process_; 169 scoped_ptr<base::CommandLine> cmd_line_; 170 base::Closure notify_task_; 171 bool launched_; 172 uint32 retry_count_; 173 base::ProcessHandle process_handle_; 174 }; 175 176 friend class MockServiceProcessControl; 177 friend class CloudPrintProxyPolicyStartupTest; 178 179 ServiceProcessControl(); 180 virtual ~ServiceProcessControl(); 181 182 friend struct DefaultSingletonTraits<ServiceProcessControl>; 183 184 typedef std::vector<base::Closure> TaskList; 185 186 // Message handlers 187 void OnCloudPrintProxyInfo( 188 const cloud_print::CloudPrintProxyInfo& proxy_info); 189 void OnHistograms(const std::vector<std::string>& pickled_histograms); 190 void OnPrinters(const std::vector<std::string>& printers); 191 192 // Runs callback provided in |GetHistograms()|. 193 void RunHistogramsCallback(); 194 195 // Helper method to invoke all the callbacks based on success or failure. 196 void RunConnectDoneTasks(); 197 198 // Method called by Launcher when the service process is launched. 199 void OnProcessLaunched(); 200 201 // Used internally to connect to the service process. 202 void ConnectInternal(); 203 204 // Takes ownership of the pointer. Split out for testing. 205 void SetChannel(scoped_ptr<IPC::ChannelProxy> channel); 206 207 static void RunAllTasksHelper(TaskList* task_list); 208 209 // IPC channel to the service process. 210 scoped_ptr<IPC::ChannelProxy> channel_; 211 212 // Service process launcher. 213 scoped_refptr<Launcher> launcher_; 214 215 // Callbacks that get invoked when the channel is successfully connected. 216 TaskList connect_success_tasks_; 217 // Callbacks that get invoked when there was a connection failure. 218 TaskList connect_failure_tasks_; 219 220 // Callback that gets invoked when a printers is received from 221 // the cloud print proxy. 222 PrintersCallback printers_callback_; 223 224 // Callback that gets invoked when a status message is received from 225 // the cloud print proxy. 226 CloudPrintProxyInfoCallback cloud_print_info_callback_; 227 228 // Callback that gets invoked when a message with histograms is received from 229 // the service process. 230 base::Closure histograms_callback_; 231 232 content::NotificationRegistrar registrar_; 233 234 // Callback that gets invoked if service didn't reply in time. 235 base::CancelableClosure histograms_timeout_callback_; 236 }; 237 238 #endif // CHROME_BROWSER_SERVICE_PROCESS_SERVICE_PROCESS_CONTROL_H_ 239