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"
28 namespace cloud_print
{
29 struct CloudPrintProxyInfo
;
30 } // namespace cloud_print
32 // A ServiceProcessControl works as a portal between the service process and
33 // the browser process.
35 // It is used to start and terminate the service process. It is also used
36 // to send and receive IPC messages from the service process.
40 // This class is accessed on the UI thread through some UI actions. It then
41 // talks to the IPC channel on the IO thread.
42 class ServiceProcessControl
: public IPC::Sender
,
44 public content::NotificationObserver
{
46 enum ServiceProcessEvent
{
47 SERVICE_EVENT_INITIALIZE
,
48 SERVICE_EVENT_ENABLED_ON_LAUNCH
,
50 SERVICE_EVENT_DISABLE
,
51 SERVICE_EVENT_DISABLE_BY_POLICY
,
53 SERVICE_EVENT_LAUNCHED
,
54 SERVICE_EVENT_LAUNCH_FAILED
,
55 SERVICE_EVENT_CHANNEL_CONNECTED
,
56 SERVICE_EVENT_CHANNEL_ERROR
,
57 SERVICE_EVENT_INFO_REQUEST
,
58 SERVICE_EVENT_INFO_REPLY
,
59 SERVICE_EVENT_HISTOGRAMS_REQUEST
,
60 SERVICE_EVENT_HISTOGRAMS_REPLY
,
64 typedef IDMap
<ServiceProcessControl
>::iterator iterator
;
65 typedef std::queue
<IPC::Message
> MessageQueue
;
66 typedef base::Callback
<void(const cloud_print::CloudPrintProxyInfo
&)>
67 CloudPrintProxyInfoHandler
;
69 // Returns the singleton instance of this class.
70 static ServiceProcessControl
* GetInstance();
72 // Return true if this object is connected to the service.
73 // Virtual for testing.
74 virtual bool IsConnected() const;
76 // If no service process is currently running, creates a new service process
77 // and connects to it. If a service process is already running this method
78 // will try to connect to it.
79 // |success_task| is called when we have successfully launched the process
80 // and connected to it.
81 // |failure_task| is called when we failed to connect to the service process.
82 // It is OK to pass the same value for |success_task| and |failure_task|. In
83 // this case, the task is invoked on success or failure.
84 // Note that if we are already connected to service process then
85 // |success_task| can be invoked in the context of the Launch call.
86 // Virtual for testing.
87 virtual void Launch(const base::Closure
& success_task
,
88 const base::Closure
& failure_task
);
90 // Disconnect the IPC channel from the service process.
91 // Virtual for testing.
92 virtual void Disconnect();
94 // IPC::Listener implementation.
95 virtual bool OnMessageReceived(const IPC::Message
& message
) OVERRIDE
;
96 virtual void OnChannelConnected(int32 peer_pid
) OVERRIDE
;
97 virtual void OnChannelError() OVERRIDE
;
99 // IPC::Sender implementation
100 virtual bool Send(IPC::Message
* message
) OVERRIDE
;
102 // content::NotificationObserver implementation.
103 virtual void Observe(int type
,
104 const content::NotificationSource
& source
,
105 const content::NotificationDetails
& details
) OVERRIDE
;
107 // Send a shutdown message to the service process. IPC channel will be
108 // destroyed after calling this method.
109 // Return true if the message was sent.
110 // Virtual for testing.
111 virtual bool Shutdown();
113 // Send request for cloud print proxy info (enabled state, email, proxy id).
114 // The callback gets the information when received.
115 // Returns true if request was sent. Callback will be called only in case of
116 // reply from service. The method resets any previous callback.
117 // This call starts service if needed.
118 bool GetCloudPrintProxyInfo(
119 const CloudPrintProxyInfoHandler
& cloud_print_status_callback
);
121 // Send request for histograms collected in service process.
122 // Returns true if request was sent, and callback will be called in case of
123 // success or timeout. The method resets any previous callback.
124 // Returns false if service is not running or other failure, callback will not
125 // be called in this case.
126 bool GetHistograms(const base::Closure
& cloud_print_status_callback
,
127 const base::TimeDelta
& timeout
);
130 // This class is responsible for launching the service process on the
131 // PROCESS_LAUNCHER thread.
133 : public base::RefCountedThreadSafe
<ServiceProcessControl::Launcher
> {
135 Launcher(ServiceProcessControl
* process
, CommandLine
* cmd_line
);
136 // Execute the command line to start the process asynchronously. After the
137 // command is executed |task| is called with the process handle on the UI
139 void Run(const base::Closure
& task
);
141 bool launched() const { return launched_
; }
144 friend class base::RefCountedThreadSafe
<ServiceProcessControl::Launcher
>;
147 #if !defined(OS_MACOSX)
148 void DoDetectLaunched();
153 void CloseProcessHandle();
154 ServiceProcessControl
* process_
;
155 scoped_ptr
<CommandLine
> cmd_line_
;
156 base::Closure notify_task_
;
159 base::ProcessHandle process_handle_
;
162 friend class MockServiceProcessControl
;
163 friend class CloudPrintProxyPolicyStartupTest
;
165 ServiceProcessControl();
166 virtual ~ServiceProcessControl();
168 friend struct DefaultSingletonTraits
<ServiceProcessControl
>;
170 typedef std::vector
<base::Closure
> TaskList
;
173 void OnCloudPrintProxyInfo(
174 const cloud_print::CloudPrintProxyInfo
& proxy_info
);
175 void OnHistograms(const std::vector
<std::string
>& pickled_histograms
);
177 // Runs callback provided in |GetHistograms()|.
178 void RunHistogramsCallback();
180 // Helper method to invoke all the callbacks based on success or failure.
181 void RunConnectDoneTasks();
183 // Method called by Launcher when the service process is launched.
184 void OnProcessLaunched();
186 // Used internally to connect to the service process.
187 void ConnectInternal();
189 // Takes ownership of the pointer. Split out for testing.
190 void SetChannel(IPC::ChannelProxy
* channel
);
192 static void RunAllTasksHelper(TaskList
* task_list
);
194 // IPC channel to the service process.
195 scoped_ptr
<IPC::ChannelProxy
> channel_
;
197 // Service process launcher.
198 scoped_refptr
<Launcher
> launcher_
;
200 // Callbacks that get invoked when the channel is successfully connected.
201 TaskList connect_success_tasks_
;
202 // Callbacks that get invoked when there was a connection failure.
203 TaskList connect_failure_tasks_
;
205 // Callback that gets invoked when a status message is received from
206 // the cloud print proxy.
207 CloudPrintProxyInfoHandler cloud_print_info_callback_
;
209 // Callback that gets invoked when a message with histograms is received from
210 // the service process.
211 base::Closure histograms_callback_
;
213 content::NotificationRegistrar registrar_
;
215 // Callback that gets invoked if service didn't reply in time.
216 base::CancelableClosure histograms_timeout_callback_
;
219 #endif // CHROME_BROWSER_SERVICE_PROCESS_SERVICE_PROCESS_CONTROL_H_