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_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/memory/singleton.h" 18 #include "base/process/process.h" 19 #include "content/public/browser/notification_observer.h" 20 #include "content/public/browser/notification_registrar.h" 21 #include "ipc/ipc_channel_proxy.h" 22 #include "ipc/ipc_listener.h" 23 #include "ipc/ipc_sender.h" 24 25 class CommandLine; 26 27 namespace cloud_print { 28 struct CloudPrintProxyInfo; 29 } // namespace cloud_print 30 31 // A ServiceProcessControl works as a portal between the service process and 32 // the browser process. 33 // 34 // It is used to start and terminate the service process. It is also used 35 // to send and receive IPC messages from the service process. 36 // 37 // THREADING 38 // 39 // This class is accessed on the UI thread through some UI actions. It then 40 // talks to the IPC channel on the IO thread. 41 class ServiceProcessControl : public IPC::Sender, 42 public IPC::Listener, 43 public content::NotificationObserver { 44 public: 45 typedef IDMap<ServiceProcessControl>::iterator iterator; 46 typedef std::queue<IPC::Message> MessageQueue; 47 typedef base::Callback<void(const cloud_print::CloudPrintProxyInfo&)> 48 CloudPrintProxyInfoHandler; 49 50 // Returns the singleton instance of this class. 51 static ServiceProcessControl* GetInstance(); 52 53 // Return true if this object is connected to the service. 54 // Virtual for testing. 55 virtual bool IsConnected() const; 56 57 // If no service process is currently running, creates a new service process 58 // and connects to it. If a service process is already running this method 59 // will try to connect to it. 60 // |success_task| is called when we have successfully launched the process 61 // and connected to it. 62 // |failure_task| is called when we failed to connect to the service process. 63 // It is OK to pass the same value for |success_task| and |failure_task|. In 64 // this case, the task is invoked on success or failure. 65 // Note that if we are already connected to service process then 66 // |success_task| can be invoked in the context of the Launch call. 67 // Virtual for testing. 68 virtual void Launch(const base::Closure& success_task, 69 const base::Closure& failure_task); 70 71 // Disconnect the IPC channel from the service process. 72 // Virtual for testing. 73 virtual void Disconnect(); 74 75 // IPC::Listener implementation. 76 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; 77 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE; 78 virtual void OnChannelError() OVERRIDE; 79 80 // IPC::Sender implementation 81 virtual bool Send(IPC::Message* message) OVERRIDE; 82 83 // content::NotificationObserver implementation. 84 virtual void Observe(int type, 85 const content::NotificationSource& source, 86 const content::NotificationDetails& details) OVERRIDE; 87 88 // Message handlers 89 void OnCloudPrintProxyInfo( 90 const cloud_print::CloudPrintProxyInfo& proxy_info); 91 92 // Send a shutdown message to the service process. IPC channel will be 93 // destroyed after calling this method. 94 // Return true if the message was sent. 95 // Virtual for testing. 96 virtual bool Shutdown(); 97 98 // Send request for cloud print proxy info (enabled state, email, proxy id). 99 // The callback gets the information when received. 100 bool GetCloudPrintProxyInfo( 101 const CloudPrintProxyInfoHandler& cloud_print_status_callback); 102 103 private: 104 // This class is responsible for launching the service process on the 105 // PROCESS_LAUNCHER thread. 106 class Launcher 107 : public base::RefCountedThreadSafe<ServiceProcessControl::Launcher> { 108 public: 109 Launcher(ServiceProcessControl* process, CommandLine* cmd_line); 110 // Execute the command line to start the process asynchronously. After the 111 // command is executed |task| is called with the process handle on the UI 112 // thread. 113 void Run(const base::Closure& task); 114 115 bool launched() const { return launched_; } 116 117 private: 118 friend class base::RefCountedThreadSafe<ServiceProcessControl::Launcher>; 119 virtual ~Launcher(); 120 121 #if !defined(OS_MACOSX) 122 void DoDetectLaunched(); 123 #endif // !OS_MACOSX 124 125 void DoRun(); 126 void Notify(); 127 ServiceProcessControl* process_; 128 scoped_ptr<CommandLine> cmd_line_; 129 base::Closure notify_task_; 130 bool launched_; 131 uint32 retry_count_; 132 }; 133 134 friend class MockServiceProcessControl; 135 friend class CloudPrintProxyPolicyStartupTest; 136 137 ServiceProcessControl(); 138 virtual ~ServiceProcessControl(); 139 140 friend struct DefaultSingletonTraits<ServiceProcessControl>; 141 142 typedef std::vector<base::Closure> TaskList; 143 144 // Helper method to invoke all the callbacks based on success or failure. 145 void RunConnectDoneTasks(); 146 147 // Method called by Launcher when the service process is launched. 148 void OnProcessLaunched(); 149 150 // Used internally to connect to the service process. 151 void ConnectInternal(); 152 153 // Takes ownership of the pointer. Split out for testing. 154 void SetChannel(IPC::ChannelProxy* channel); 155 156 static void RunAllTasksHelper(TaskList* task_list); 157 158 // IPC channel to the service process. 159 scoped_ptr<IPC::ChannelProxy> channel_; 160 161 // Service process launcher. 162 scoped_refptr<Launcher> launcher_; 163 164 // Callbacks that get invoked when the channel is successfully connected. 165 TaskList connect_success_tasks_; 166 // Callbacks that get invoked when there was a connection failure. 167 TaskList connect_failure_tasks_; 168 169 // Callback that gets invoked when a status message is received from 170 // the cloud print proxy. 171 CloudPrintProxyInfoHandler cloud_print_info_callback_; 172 173 content::NotificationRegistrar registrar_; 174 }; 175 176 #endif // CHROME_BROWSER_SERVICE_SERVICE_PROCESS_CONTROL_H_ 177