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