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.
5 #ifndef CHROME_BROWSER_SERVICE_PROCESS_SERVICE_PROCESS_CONTROL_H_
6 #define CHROME_BROWSER_SERVICE_PROCESS_SERVICE_PROCESS_CONTROL_H_
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"
30 namespace cloud_print
{
31 struct CloudPrintProxyInfo
;
32 } // namespace cloud_print
34 // A ServiceProcessControl works as a portal between the service process and
35 // the browser process.
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.
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
,
46 public content::NotificationObserver
{
48 enum ServiceProcessEvent
{
49 SERVICE_EVENT_INITIALIZE
,
50 SERVICE_EVENT_ENABLED_ON_LAUNCH
,
52 SERVICE_EVENT_DISABLE
,
53 SERVICE_EVENT_DISABLE_BY_POLICY
,
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
,
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
>&)>
75 // Returns the singleton instance of this class.
76 static ServiceProcessControl
* GetInstance();
78 // Return true if this object is connected to the service.
79 // Virtual for testing.
80 virtual bool IsConnected() const;
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
);
96 // Disconnect the IPC channel from the service process.
97 // Virtual for testing.
98 virtual void Disconnect();
100 // IPC::Listener implementation.
101 bool OnMessageReceived(const IPC::Message
& message
) override
;
102 void OnChannelConnected(int32 peer_pid
) override
;
103 void OnChannelError() override
;
105 // IPC::Sender implementation
106 bool Send(IPC::Message
* message
) override
;
108 // content::NotificationObserver implementation.
109 void Observe(int type
,
110 const content::NotificationSource
& source
,
111 const content::NotificationDetails
& details
) override
;
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();
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
);
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
);
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
);
143 // This class is responsible for launching the service process on the
144 // PROCESS_LAUNCHER thread.
146 : public base::RefCountedThreadSafe
<ServiceProcessControl::Launcher
> {
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
153 void Run(const base::Closure
& task
);
155 bool launched() const { return launched_
; }
158 friend class base::RefCountedThreadSafe
<ServiceProcessControl::Launcher
>;
161 #if !defined(OS_MACOSX)
162 void DoDetectLaunched();
167 ServiceProcessControl
* process_control_
;
168 scoped_ptr
<base::CommandLine
> cmd_line_
;
169 base::Closure notify_task_
;
172 base::Process process_
;
175 friend class MockServiceProcessControl
;
176 friend class CloudPrintProxyPolicyStartupTest
;
178 ServiceProcessControl();
179 ~ServiceProcessControl() override
;
181 friend struct DefaultSingletonTraits
<ServiceProcessControl
>;
183 typedef std::vector
<base::Closure
> TaskList
;
186 void OnCloudPrintProxyInfo(
187 const cloud_print::CloudPrintProxyInfo
& proxy_info
);
188 void OnHistograms(const std::vector
<std::string
>& pickled_histograms
);
189 void OnPrinters(const std::vector
<std::string
>& printers
);
191 // Runs callback provided in |GetHistograms()|.
192 void RunHistogramsCallback();
194 // Helper method to invoke all the callbacks based on success or failure.
195 void RunConnectDoneTasks();
197 // Method called by Launcher when the service process is launched.
198 void OnProcessLaunched();
200 // Used internally to connect to the service process.
201 void ConnectInternal();
203 // Takes ownership of the pointer. Split out for testing.
204 void SetChannel(scoped_ptr
<IPC::ChannelProxy
> channel
);
206 static void RunAllTasksHelper(TaskList
* task_list
);
208 // IPC channel to the service process.
209 scoped_ptr
<IPC::ChannelProxy
> channel_
;
211 // Service process launcher.
212 scoped_refptr
<Launcher
> launcher_
;
214 // Callbacks that get invoked when the channel is successfully connected.
215 TaskList connect_success_tasks_
;
216 // Callbacks that get invoked when there was a connection failure.
217 TaskList connect_failure_tasks_
;
219 // Callback that gets invoked when a printers is received from
220 // the cloud print proxy.
221 PrintersCallback printers_callback_
;
223 // Callback that gets invoked when a status message is received from
224 // the cloud print proxy.
225 CloudPrintProxyInfoCallback cloud_print_info_callback_
;
227 // Callback that gets invoked when a message with histograms is received from
228 // the service process.
229 base::Closure histograms_callback_
;
231 content::NotificationRegistrar registrar_
;
233 // Callback that gets invoked if service didn't reply in time.
234 base::CancelableClosure histograms_timeout_callback_
;
237 #endif // CHROME_BROWSER_SERVICE_PROCESS_SERVICE_PROCESS_CONTROL_H_