Home | History | Annotate | Download | only in setup
      1 // Copyright 2013 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 #include "remoting/host/setup/daemon_controller.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/location.h"
      9 #include "base/single_thread_task_runner.h"
     10 #include "base/thread_task_runner_handle.h"
     11 #include "base/values.h"
     12 #include "remoting/base/auto_thread.h"
     13 #include "remoting/base/auto_thread_task_runner.h"
     14 
     15 namespace remoting {
     16 
     17 // Name of the Daemon Controller's worker thread.
     18 const char kDaemonControllerThreadName[] = "Daemon Controller thread";
     19 
     20 DaemonController::DaemonController(scoped_ptr<Delegate> delegate)
     21     : caller_task_runner_(base::ThreadTaskRunnerHandle::Get()),
     22       delegate_(delegate.Pass()) {
     23   // Launch the delegate thread.
     24   delegate_thread_.reset(new AutoThread(kDaemonControllerThreadName));
     25 #if defined(OS_WIN)
     26   delegate_thread_->SetComInitType(AutoThread::COM_INIT_STA);
     27   delegate_task_runner_ =
     28       delegate_thread_->StartWithType(base::MessageLoop::TYPE_UI);
     29 #else
     30   delegate_task_runner_ =
     31       delegate_thread_->StartWithType(base::MessageLoop::TYPE_DEFAULT);
     32 #endif
     33 }
     34 
     35 DaemonController::State DaemonController::GetState() {
     36   DCHECK(caller_task_runner_->BelongsToCurrentThread());
     37   return delegate_->GetState();
     38 }
     39 
     40 void DaemonController::GetConfig(const GetConfigCallback& done) {
     41   DCHECK(caller_task_runner_->BelongsToCurrentThread());
     42 
     43   DaemonController::GetConfigCallback wrapped_done = base::Bind(
     44       &DaemonController::InvokeConfigCallbackAndScheduleNext, this, done);
     45   base::Closure request = base::Bind(
     46       &DaemonController::DoGetConfig, this, wrapped_done);
     47   ServiceOrQueueRequest(request);
     48 }
     49 
     50 void DaemonController::SetConfigAndStart(
     51     scoped_ptr<base::DictionaryValue> config,
     52     bool consent,
     53     const CompletionCallback& done) {
     54   DCHECK(caller_task_runner_->BelongsToCurrentThread());
     55 
     56   DaemonController::CompletionCallback wrapped_done = base::Bind(
     57       &DaemonController::InvokeCompletionCallbackAndScheduleNext, this, done);
     58   base::Closure request = base::Bind(
     59       &DaemonController::DoSetConfigAndStart, this, base::Passed(&config),
     60       consent, wrapped_done);
     61   ServiceOrQueueRequest(request);
     62 }
     63 
     64 void DaemonController::UpdateConfig(scoped_ptr<base::DictionaryValue> config,
     65                                     const CompletionCallback& done) {
     66   DCHECK(caller_task_runner_->BelongsToCurrentThread());
     67 
     68   DaemonController::CompletionCallback wrapped_done = base::Bind(
     69       &DaemonController::InvokeCompletionCallbackAndScheduleNext, this, done);
     70   base::Closure request = base::Bind(
     71       &DaemonController::DoUpdateConfig, this, base::Passed(&config),
     72       wrapped_done);
     73   ServiceOrQueueRequest(request);
     74 }
     75 
     76 void DaemonController::Stop(const CompletionCallback& done) {
     77   DCHECK(caller_task_runner_->BelongsToCurrentThread());
     78 
     79   DaemonController::CompletionCallback wrapped_done = base::Bind(
     80       &DaemonController::InvokeCompletionCallbackAndScheduleNext, this, done);
     81   base::Closure request = base::Bind(
     82       &DaemonController::DoStop, this, wrapped_done);
     83   ServiceOrQueueRequest(request);
     84 }
     85 
     86 void DaemonController::SetWindow(void* window_handle) {
     87   DCHECK(caller_task_runner_->BelongsToCurrentThread());
     88 
     89   base::Closure done = base::Bind(&DaemonController::ScheduleNext, this);
     90   base::Closure request = base::Bind(
     91       &DaemonController::DoSetWindow, this, window_handle, done);
     92   ServiceOrQueueRequest(request);
     93 }
     94 
     95 void DaemonController::GetVersion(const GetVersionCallback& done) {
     96   DCHECK(caller_task_runner_->BelongsToCurrentThread());
     97 
     98   DaemonController::GetVersionCallback wrapped_done = base::Bind(
     99       &DaemonController::InvokeVersionCallbackAndScheduleNext, this, done);
    100   base::Closure request = base::Bind(
    101       &DaemonController::DoGetVersion, this, wrapped_done);
    102   ServiceOrQueueRequest(request);
    103 }
    104 
    105 void DaemonController::GetUsageStatsConsent(
    106     const GetUsageStatsConsentCallback& done) {
    107   DCHECK(caller_task_runner_->BelongsToCurrentThread());
    108 
    109   DaemonController::GetUsageStatsConsentCallback wrapped_done = base::Bind(
    110       &DaemonController::InvokeConsentCallbackAndScheduleNext, this, done);
    111   base::Closure request = base::Bind(
    112       &DaemonController::DoGetUsageStatsConsent, this, wrapped_done);
    113   ServiceOrQueueRequest(request);
    114 }
    115 
    116 DaemonController::~DaemonController() {
    117   // Make sure |delegate_| is deleted on the background thread.
    118   delegate_task_runner_->DeleteSoon(FROM_HERE, delegate_.release());
    119 
    120   // Stop the thread.
    121   delegate_task_runner_ = NULL;
    122   caller_task_runner_->DeleteSoon(FROM_HERE, delegate_thread_.release());
    123 }
    124 
    125 void DaemonController::DoGetConfig(const GetConfigCallback& done) {
    126   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
    127 
    128   scoped_ptr<base::DictionaryValue> config = delegate_->GetConfig();
    129   caller_task_runner_->PostTask(FROM_HERE,
    130                                 base::Bind(done, base::Passed(&config)));
    131 }
    132 
    133 void DaemonController::DoSetConfigAndStart(
    134     scoped_ptr<base::DictionaryValue> config,
    135     bool consent,
    136     const CompletionCallback& done) {
    137   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
    138 
    139   delegate_->SetConfigAndStart(config.Pass(), consent, done);
    140 }
    141 
    142 void DaemonController::DoUpdateConfig(
    143     scoped_ptr<base::DictionaryValue> config,
    144     const CompletionCallback& done) {
    145   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
    146 
    147   delegate_->UpdateConfig(config.Pass(), done);
    148 }
    149 
    150 void DaemonController::DoStop(const CompletionCallback& done) {
    151   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
    152 
    153   delegate_->Stop(done);
    154 }
    155 
    156 void DaemonController::DoSetWindow(void* window_handle,
    157                                    const base::Closure& done) {
    158   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
    159 
    160   delegate_->SetWindow(window_handle);
    161   caller_task_runner_->PostTask(FROM_HERE, done);
    162 }
    163 
    164 void DaemonController::DoGetVersion(const GetVersionCallback& done) {
    165   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
    166 
    167   std::string version = delegate_->GetVersion();
    168   caller_task_runner_->PostTask(FROM_HERE, base::Bind(done, version));
    169 }
    170 
    171 void DaemonController::DoGetUsageStatsConsent(
    172     const GetUsageStatsConsentCallback& done) {
    173   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
    174 
    175   DaemonController::UsageStatsConsent consent =
    176       delegate_->GetUsageStatsConsent();
    177   caller_task_runner_->PostTask(FROM_HERE, base::Bind(done, consent));
    178 }
    179 
    180 void DaemonController::InvokeCompletionCallbackAndScheduleNext(
    181     const CompletionCallback& done,
    182     AsyncResult result) {
    183   if (!caller_task_runner_->BelongsToCurrentThread()) {
    184     caller_task_runner_->PostTask(
    185         FROM_HERE,
    186         base::Bind(&DaemonController::InvokeCompletionCallbackAndScheduleNext,
    187                    this, done, result));
    188     return;
    189   }
    190 
    191   done.Run(result);
    192   ScheduleNext();
    193 }
    194 
    195 void DaemonController::InvokeConfigCallbackAndScheduleNext(
    196     const GetConfigCallback& done,
    197     scoped_ptr<base::DictionaryValue> config) {
    198   DCHECK(caller_task_runner_->BelongsToCurrentThread());
    199 
    200   done.Run(config.Pass());
    201   ScheduleNext();
    202 }
    203 
    204 void DaemonController::InvokeConsentCallbackAndScheduleNext(
    205     const GetUsageStatsConsentCallback& done,
    206     const UsageStatsConsent& consent) {
    207   DCHECK(caller_task_runner_->BelongsToCurrentThread());
    208 
    209   done.Run(consent);
    210   ScheduleNext();
    211 }
    212 
    213 void DaemonController::InvokeVersionCallbackAndScheduleNext(
    214     const GetVersionCallback& done,
    215     const std::string& version) {
    216   DCHECK(caller_task_runner_->BelongsToCurrentThread());
    217 
    218   done.Run(version);
    219   ScheduleNext();
    220 }
    221 
    222 void DaemonController::ScheduleNext() {
    223   DCHECK(caller_task_runner_->BelongsToCurrentThread());
    224 
    225   pending_requests_.pop();
    226   ServiceNextRequest();
    227 }
    228 
    229 void DaemonController::ServiceOrQueueRequest(const base::Closure& request) {
    230   bool servicing_request = !pending_requests_.empty();
    231   pending_requests_.push(request);
    232   if (!servicing_request)
    233     ServiceNextRequest();
    234 }
    235 
    236 void DaemonController::ServiceNextRequest() {
    237   if (!pending_requests_.empty())
    238     delegate_task_runner_->PostTask(FROM_HERE, pending_requests_.front());
    239 }
    240 
    241 }  // namespace remoting
    242