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 #include "remoting/host/setup/host_starter.h"
      6 
      7 #include "base/guid.h"
      8 #include "base/thread_task_runner_handle.h"
      9 #include "base/values.h"
     10 #include "google_apis/google_api_keys.h"
     11 #include "remoting/host/pin_hash.h"
     12 #include "remoting/host/setup/oauth_helper.h"
     13 
     14 namespace {
     15 const int kMaxGetTokensRetries = 3;
     16 }  // namespace
     17 
     18 namespace remoting {
     19 
     20 HostStarter::HostStarter(
     21     scoped_ptr<gaia::GaiaOAuthClient> oauth_client,
     22     scoped_ptr<remoting::ServiceClient> service_client,
     23     scoped_ptr<remoting::DaemonController> daemon_controller)
     24     : oauth_client_(oauth_client.Pass()),
     25       service_client_(service_client.Pass()),
     26       daemon_controller_(daemon_controller.Pass()),
     27       consent_to_data_collection_(false),
     28       weak_ptr_factory_(this),
     29       weak_ptr_(weak_ptr_factory_.GetWeakPtr()) {
     30   main_task_runner_ = base::ThreadTaskRunnerHandle::Get();
     31 }
     32 
     33 HostStarter::~HostStarter() {
     34 }
     35 
     36 scoped_ptr<HostStarter> HostStarter::Create(
     37     const std::string& chromoting_hosts_url,
     38     net::URLRequestContextGetter* url_request_context_getter) {
     39   scoped_ptr<gaia::GaiaOAuthClient> oauth_client(
     40       new gaia::GaiaOAuthClient(url_request_context_getter));
     41   scoped_ptr<remoting::ServiceClient> service_client(
     42       new remoting::ServiceClient(
     43           chromoting_hosts_url, url_request_context_getter));
     44   scoped_ptr<remoting::DaemonController> daemon_controller(
     45       remoting::DaemonController::Create());
     46   return scoped_ptr<HostStarter>(
     47       new HostStarter(oauth_client.Pass(), service_client.Pass(),
     48                       daemon_controller.Pass()));
     49 }
     50 
     51 void HostStarter::StartHost(
     52     const std::string& host_name,
     53     const std::string& host_pin,
     54     bool consent_to_data_collection,
     55     const std::string& auth_code,
     56     const std::string& redirect_url,
     57     CompletionCallback on_done) {
     58   DCHECK(main_task_runner_->BelongsToCurrentThread());
     59   DCHECK(on_done_.is_null());
     60 
     61   host_name_ = host_name;
     62   host_pin_ = host_pin;
     63   consent_to_data_collection_ = consent_to_data_collection;
     64   on_done_ = on_done;
     65   oauth_client_info_.client_id =
     66       google_apis::GetOAuth2ClientID(google_apis::CLIENT_REMOTING);
     67   oauth_client_info_.client_secret =
     68       google_apis::GetOAuth2ClientSecret(google_apis::CLIENT_REMOTING);
     69   oauth_client_info_.redirect_uri = redirect_url;
     70   // Map the authorization code to refresh and access tokens.
     71   oauth_client_->GetTokensFromAuthCode(oauth_client_info_, auth_code,
     72                                        kMaxGetTokensRetries, this);
     73 }
     74 
     75 void HostStarter::OnGetTokensResponse(
     76     const std::string& refresh_token,
     77     const std::string& access_token,
     78     int expires_in_seconds) {
     79   if (!main_task_runner_->BelongsToCurrentThread()) {
     80     main_task_runner_->PostTask(FROM_HERE, base::Bind(
     81         &HostStarter::OnGetTokensResponse, weak_ptr_,
     82         refresh_token, access_token, expires_in_seconds));
     83     return;
     84   }
     85   refresh_token_ = refresh_token;
     86   access_token_ = access_token;
     87   // Get the email corresponding to the access token.
     88   oauth_client_->GetUserEmail(access_token_, 1, this);
     89 }
     90 
     91 void HostStarter::OnRefreshTokenResponse(
     92     const std::string& access_token,
     93     int expires_in_seconds) {
     94   // We never request a refresh token, so this call is not expected.
     95   NOTREACHED();
     96 }
     97 
     98 void HostStarter::OnGetUserEmailResponse(const std::string& user_email) {
     99   if (!main_task_runner_->BelongsToCurrentThread()) {
    100     main_task_runner_->PostTask(FROM_HERE, base::Bind(
    101         &HostStarter::OnGetUserEmailResponse, weak_ptr_, user_email));
    102     return;
    103   }
    104   user_email_ = user_email;
    105   // Register the host.
    106   host_id_ = base::GenerateGUID();
    107   key_pair_ = RsaKeyPair::Generate();
    108   service_client_->RegisterHost(
    109       host_id_, host_name_, key_pair_->GetPublicKey(), access_token_, this);
    110 }
    111 
    112 void HostStarter::OnHostRegistered() {
    113   if (!main_task_runner_->BelongsToCurrentThread()) {
    114     main_task_runner_->PostTask(FROM_HERE, base::Bind(
    115         &HostStarter::OnHostRegistered, weak_ptr_));
    116     return;
    117   }
    118   // Start the host.
    119   std::string host_secret_hash = remoting::MakeHostPinHash(host_id_, host_pin_);
    120   scoped_ptr<base::DictionaryValue> config(new base::DictionaryValue());
    121   config->SetString("xmpp_login", user_email_);
    122   config->SetString("oauth_refresh_token", refresh_token_);
    123   config->SetString("host_id", host_id_);
    124   config->SetString("host_name", host_name_);
    125   config->SetString("private_key", key_pair_->ToString());
    126   config->SetString("host_secret_hash", host_secret_hash);
    127   daemon_controller_->SetConfigAndStart(
    128       config.Pass(), consent_to_data_collection_,
    129       base::Bind(&HostStarter::OnHostStarted, base::Unretained(this)));
    130 }
    131 
    132 void HostStarter::OnHostStarted(DaemonController::AsyncResult result) {
    133   if (!main_task_runner_->BelongsToCurrentThread()) {
    134     main_task_runner_->PostTask(FROM_HERE, base::Bind(
    135         &HostStarter::OnHostStarted, weak_ptr_, result));
    136     return;
    137   }
    138   if (result != DaemonController::RESULT_OK) {
    139     service_client_->UnregisterHost(host_id_, access_token_, this);
    140     return;
    141   }
    142   Result done_result = (result == DaemonController::RESULT_OK) ?
    143       START_COMPLETE : START_ERROR;
    144   CompletionCallback cb = on_done_;
    145   on_done_.Reset();
    146   cb.Run(done_result);
    147 }
    148 
    149 void HostStarter::OnOAuthError() {
    150   if (!main_task_runner_->BelongsToCurrentThread()) {
    151     main_task_runner_->PostTask(FROM_HERE, base::Bind(
    152         &HostStarter::OnOAuthError, weak_ptr_));
    153     return;
    154   }
    155   CompletionCallback cb = on_done_;
    156   on_done_.Reset();
    157   cb.Run(OAUTH_ERROR);
    158 }
    159 
    160 void HostStarter::OnNetworkError(int response_code) {
    161   if (!main_task_runner_->BelongsToCurrentThread()) {
    162     main_task_runner_->PostTask(FROM_HERE, base::Bind(
    163         &HostStarter::OnNetworkError, weak_ptr_, response_code));
    164     return;
    165   }
    166   CompletionCallback cb = on_done_;
    167   on_done_.Reset();
    168   cb.Run(NETWORK_ERROR);
    169 }
    170 
    171 void HostStarter::OnHostUnregistered() {
    172   if (!main_task_runner_->BelongsToCurrentThread()) {
    173     main_task_runner_->PostTask(FROM_HERE, base::Bind(
    174         &HostStarter::OnHostUnregistered, weak_ptr_));
    175     return;
    176   }
    177   CompletionCallback cb = on_done_;
    178   on_done_.Reset();
    179   cb.Run(START_ERROR);
    180 }
    181 
    182 }  // namespace remoting
    183