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 REMOTING_HOST_SETUP_DAEMON_CONTROLLER_H_
6 #define REMOTING_HOST_SETUP_DAEMON_CONTROLLER_H_
7 
8 #include <memory>
9 #include <string>
10 
11 #include "base/callback.h"
12 #include "base/containers/queue.h"
13 #include "base/macros.h"
14 #include "base/memory/ref_counted.h"
15 
16 namespace base {
17 class DictionaryValue;
18 class SingleThreadTaskRunner;
19 }  // namespace base
20 
21 namespace remoting {
22 
23 class AutoThread;
24 class AutoThreadTaskRunner;
25 
26 class DaemonController : public base::RefCountedThreadSafe<DaemonController> {
27  public:
28   // These enumeration values are duplicated in host_controller.js except that
29   // NOT_INSTALLED is missing here. DaemonController runs in either the remoting
30   // host or the native messaging host which are only installed as part of the
31   // host package so the host must have already been installed.
32   enum State {
33     // Placeholder state for platforms on which the daemon process is not
34     // implemented. The web-app will not show the corresponding UI. This value
35     // will eventually be deprecated or removed.
36     STATE_NOT_IMPLEMENTED = 0,
37     // The daemon is installed but not running. Call Start to start it.
38     STATE_STOPPED = 2,
39     // The daemon process is starting.
40     STATE_STARTING = 3,
41     // The daemon process is running. Call Start again to change the PIN or
42     // Stop to stop it.
43     STATE_STARTED = 4,
44     // The daemon process is stopping.
45     STATE_STOPPING = 5,
46     // The state cannot be determined.
47     STATE_UNKNOWN = 6
48   };
49 
50   // Enum used for completion callback.
51   enum AsyncResult {
52     RESULT_OK = 0,
53 
54     // The operation has FAILED.
55     RESULT_FAILED = 1,
56 
57     // User has cancelled the action (e.g. rejected UAC prompt).
58     // TODO(sergeyu): Current implementations don't return this value.
59     RESULT_CANCELLED = 2,
60 
61     // TODO(sergeyu): Add more error codes when we know how to handle
62     // them in the webapp.
63   };
64 
65   // Callback type for GetConfig(). If the host is configured then a dictionary
66   // is returned containing host_id and xmpp_login, with security-sensitive
67   // fields filtered out. An empty dictionary is returned if the host is not
68   // configured, and nullptr if the configuration is corrupt or cannot be read.
69   typedef base::OnceCallback<void(
70       std::unique_ptr<base::DictionaryValue> config)>
71       GetConfigCallback;
72 
73   // Callback used for asynchronous operations, e.g. when
74   // starting/stopping the service.
75   typedef base::OnceCallback<void(AsyncResult result)> CompletionCallback;
76 
77   // Callback used to notify a Boolean result.
78   typedef base::OnceCallback<void(bool)> BoolCallback;
79 
80   struct UsageStatsConsent {
81     // Indicates whether crash dump reporting is supported by the host.
82     bool supported;
83 
84     // Indicates if crash dump reporting is allowed by the user.
85     bool allowed;
86 
87     // Carries information whether the crash dump reporting is controlled by
88     // policy.
89     bool set_by_policy;
90   };
91 
92   // Callback type for GetUsageStatsConsent().
93   typedef base::OnceCallback<void(const UsageStatsConsent&)>
94       GetUsageStatsConsentCallback;
95 
96   // Interface representing the platform-spacific back-end. Most of its methods
97   // are blocking and should be called on a background thread. There are two
98   // exceptions:
99   //   - GetState() is synchronous and called on the UI thread. It should avoid
100   //         accessing any data members of the implementation.
101   //   - SetConfigAndStart(), UpdateConfig() and Stop() indicate completion via
102   //         a callback. There methods can be long running and should be caled
103   //         on a background thread.
104   class Delegate {
105    public:
~Delegate()106     virtual ~Delegate() {}
107 
108     // Return the "installed/running" state of the daemon process. This method
109     // should avoid accessing any data members of the implementation.
110     virtual State GetState() = 0;
111 
112     // Queries current host configuration. Any values that might be security
113     // sensitive have been filtered out.
114     virtual std::unique_ptr<base::DictionaryValue> GetConfig() = 0;
115 
116     // Checks to verify that the required OS permissions have been granted to
117     // the host process, querying the user if necessary. Notifies the callback
118     // when permission status is established, passing true iff all required
119     // permissions have been granted.
120     virtual void CheckPermission(bool it2me, BoolCallback callback) = 0;
121 
122     // Starts the daemon process. This may require that the daemon be
123     // downloaded and installed. |done| is invoked on the calling thread when
124     // the operation is completed.
125     virtual void SetConfigAndStart(
126         std::unique_ptr<base::DictionaryValue> config,
127         bool consent,
128         CompletionCallback done) = 0;
129 
130     // Updates current host configuration with the values specified in
131     // |config|. Any value in the existing configuration that isn't specified in
132     // |config| is preserved. |config| must not contain host_id or xmpp_login
133     // values, because implementations of this method cannot change them. |done|
134     // is invoked on the calling thread when the operation is completed.
135     virtual void UpdateConfig(std::unique_ptr<base::DictionaryValue> config,
136                               CompletionCallback done) = 0;
137 
138     // Stops the daemon process. |done| is invoked on the calling thread when
139     // the operation is completed.
140     virtual void Stop(CompletionCallback done) = 0;
141 
142     // Get the user's consent to crash reporting.
143     virtual UsageStatsConsent GetUsageStatsConsent() = 0;
144   };
145 
146   static scoped_refptr<DaemonController> Create();
147 
148   explicit DaemonController(std::unique_ptr<Delegate> delegate);
149 
150   // Return the "installed/running" state of the daemon process.
151   //
152   // TODO(sergeyu): This method is called synchronously from the
153   // webapp. In most cases it requires IO operations, so it may block
154   // the user interface. Replace it with asynchronous notifications,
155   // e.g. with StartStateNotifications()/StopStateNotifications() methods.
156   State GetState();
157 
158   // Queries current host configuration. The |done| is called
159   // after the configuration is read, and any values that might be security
160   // sensitive have been filtered out.
161   void GetConfig(GetConfigCallback done);
162 
163   // Checks to see if the required OS permissions have been granted. This may
164   // show a dialog to the user requesting the permissions.
165   // Notifies the callback when permission status is established, passing true
166   // iff all required permissions have been granted.
167   void CheckPermission(bool it2me, BoolCallback callback);
168 
169   // Start the daemon process. This may require that the daemon be
170   // downloaded and installed. |done| is called when the
171   // operation is finished or fails.
172   //
173   // TODO(sergeyu): This method writes config and starts the host -
174   // these two steps are merged for simplicity. Consider splitting it
175   // into SetConfig() and Start() once we have basic host setup flow
176   // working.
177   void SetConfigAndStart(std::unique_ptr<base::DictionaryValue> config,
178                          bool consent,
179                          CompletionCallback done);
180 
181   // Updates current host configuration with the values specified in
182   // |config|. Changes must take effect before the call completes.
183   // Any value in the existing configuration that isn't specified in |config|
184   // is preserved. |config| must not contain host_id or xmpp_login values,
185   // because implementations of this method cannot change them.
186   void UpdateConfig(std::unique_ptr<base::DictionaryValue> config,
187                     CompletionCallback done);
188 
189   // Stop the daemon process. It is permitted to call Stop while the daemon
190   // process is being installed, in which case the installation should be
191   // aborted if possible; if not then it is sufficient to ensure that the
192   // daemon process is not started automatically upon successful installation.
193   // As with Start, Stop may return before the operation is complete--poll
194   // GetState until the state is STATE_STOPPED.
195   void Stop(CompletionCallback done);
196 
197   // Get the user's consent to crash reporting.
198   void GetUsageStatsConsent(GetUsageStatsConsentCallback done);
199 
200  private:
201   friend class base::RefCountedThreadSafe<DaemonController>;
202   virtual ~DaemonController();
203 
204   // Blocking helper methods used to call the delegate.
205   void DoGetConfig(GetConfigCallback done);
206   void DoSetConfigAndStart(std::unique_ptr<base::DictionaryValue> config,
207                            bool consent,
208                            CompletionCallback done);
209   void DoUpdateConfig(std::unique_ptr<base::DictionaryValue> config,
210                       CompletionCallback done);
211   void DoStop(CompletionCallback done);
212   void DoGetUsageStatsConsent(GetUsageStatsConsentCallback done);
213 
214   // "Trampoline" callbacks that schedule the next pending request and then
215   // invoke the original caller-supplied callback.
216   void InvokeCompletionCallbackAndScheduleNext(CompletionCallback done,
217                                                AsyncResult result);
218   void InvokeConfigCallbackAndScheduleNext(
219       GetConfigCallback done,
220       std::unique_ptr<base::DictionaryValue> config);
221   void InvokeConsentCallbackAndScheduleNext(GetUsageStatsConsentCallback done,
222                                             const UsageStatsConsent& consent);
223 
224   // Queue management methods.
225   void OnServicingDone();
226   void ServiceOrQueueRequest(base::OnceClosure request);
227   void ServiceNextRequest();
228 
229   // Task runner on which all public methods of this class should be called.
230   scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
231 
232   // Task runner used to run blocking calls to the delegate. A single thread
233   // task runner is used to guarantee that one method of the delegate is
234   // called at a time.
235   scoped_refptr<AutoThreadTaskRunner> delegate_task_runner_;
236 
237   std::unique_ptr<AutoThread> delegate_thread_;
238 
239   std::unique_ptr<Delegate> delegate_;
240 
241   bool servicing_request_ = false;
242   base::queue<base::OnceClosure> pending_requests_;
243 
244   DISALLOW_COPY_AND_ASSIGN(DaemonController);
245 };
246 
247 }  // namespace remoting
248 
249 #endif  // REMOTING_HOST_SETUP_DAEMON_CONTROLLER_H_
250