Home | History | Annotate | Download | only in setup
      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