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