Explicitly add python-numpy dependency to install-build-deps.
[chromium-blink-merge.git] / remoting / host / setup / host_starter.cc
blob127c4a98706fe1c42b0ccc1a621adb3be2383b9a
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.
5 #include "remoting/host/setup/host_starter.h"
7 #include "base/bind.h"
8 #include "base/guid.h"
9 #include "base/location.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "base/values.h"
12 #include "google_apis/google_api_keys.h"
13 #include "remoting/host/pin_hash.h"
14 #include "remoting/host/setup/oauth_helper.h"
16 namespace {
17 const int kMaxGetTokensRetries = 3;
18 } // namespace
20 namespace remoting {
22 HostStarter::HostStarter(
23 scoped_ptr<gaia::GaiaOAuthClient> oauth_client,
24 scoped_ptr<remoting::ServiceClient> service_client,
25 scoped_refptr<remoting::DaemonController> daemon_controller)
26 : oauth_client_(oauth_client.Pass()),
27 service_client_(service_client.Pass()),
28 daemon_controller_(daemon_controller),
29 consent_to_data_collection_(false),
30 unregistering_host_(false),
31 weak_ptr_factory_(this) {
32 weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
33 main_task_runner_ = base::ThreadTaskRunnerHandle::Get();
36 HostStarter::~HostStarter() {
39 scoped_ptr<HostStarter> HostStarter::Create(
40 const std::string& chromoting_hosts_url,
41 net::URLRequestContextGetter* url_request_context_getter) {
42 scoped_ptr<gaia::GaiaOAuthClient> oauth_client(
43 new gaia::GaiaOAuthClient(url_request_context_getter));
44 scoped_ptr<remoting::ServiceClient> service_client(
45 new remoting::ServiceClient(
46 chromoting_hosts_url, url_request_context_getter));
47 scoped_refptr<remoting::DaemonController> daemon_controller(
48 remoting::DaemonController::Create());
49 return make_scoped_ptr(new HostStarter(
50 oauth_client.Pass(), service_client.Pass(), daemon_controller));
53 void HostStarter::StartHost(
54 const std::string& host_name,
55 const std::string& host_pin,
56 bool consent_to_data_collection,
57 const std::string& auth_code,
58 const std::string& redirect_url,
59 CompletionCallback on_done) {
60 DCHECK(main_task_runner_->BelongsToCurrentThread());
61 DCHECK(on_done_.is_null());
63 host_name_ = host_name;
64 host_pin_ = host_pin;
65 consent_to_data_collection_ = consent_to_data_collection;
66 on_done_ = on_done;
67 oauth_client_info_.client_id =
68 google_apis::GetOAuth2ClientID(google_apis::CLIENT_REMOTING);
69 oauth_client_info_.client_secret =
70 google_apis::GetOAuth2ClientSecret(google_apis::CLIENT_REMOTING);
71 oauth_client_info_.redirect_uri = redirect_url;
72 // Map the authorization code to refresh and access tokens.
73 oauth_client_->GetTokensFromAuthCode(oauth_client_info_, auth_code,
74 kMaxGetTokensRetries, this);
77 void HostStarter::OnGetTokensResponse(
78 const std::string& refresh_token,
79 const std::string& access_token,
80 int expires_in_seconds) {
81 if (!main_task_runner_->BelongsToCurrentThread()) {
82 main_task_runner_->PostTask(FROM_HERE, base::Bind(
83 &HostStarter::OnGetTokensResponse, weak_ptr_,
84 refresh_token, access_token, expires_in_seconds));
85 return;
87 refresh_token_ = refresh_token;
88 access_token_ = access_token;
89 // Get the email corresponding to the access token.
90 oauth_client_->GetUserEmail(access_token_, 1, this);
93 void HostStarter::OnRefreshTokenResponse(
94 const std::string& access_token,
95 int expires_in_seconds) {
96 // We never request a refresh token, so this call is not expected.
97 NOTREACHED();
100 // This function is called twice: once with the host owner credentials, and once
101 // with the service account credentials.
102 void HostStarter::OnGetUserEmailResponse(const std::string& user_email) {
103 if (!main_task_runner_->BelongsToCurrentThread()) {
104 main_task_runner_->PostTask(FROM_HERE, base::Bind(
105 &HostStarter::OnGetUserEmailResponse, weak_ptr_, user_email));
106 return;
109 if (host_owner_.empty()) {
110 // This is the first callback, with the host owner credentials. Store the
111 // owner's email, and register the host.
112 host_owner_ = user_email;
113 host_id_ = base::GenerateGUID();
114 key_pair_ = RsaKeyPair::Generate();
116 std::string host_client_id;
117 host_client_id = google_apis::GetOAuth2ClientID(
118 google_apis::CLIENT_REMOTING_HOST);
120 service_client_->RegisterHost(
121 host_id_, host_name_, key_pair_->GetPublicKey(), host_client_id,
122 access_token_, this);
123 } else {
124 // This is the second callback, with the service account credentials.
125 // This email is the service account's email, used to login to XMPP.
126 xmpp_login_ = user_email;
127 StartHostProcess();
131 void HostStarter::OnHostRegistered(const std::string& authorization_code) {
132 if (!main_task_runner_->BelongsToCurrentThread()) {
133 main_task_runner_->PostTask(FROM_HERE, base::Bind(
134 &HostStarter::OnHostRegistered, weak_ptr_, authorization_code));
135 return;
138 if (authorization_code.empty()) {
139 // No service account code, start the host with the owner's credentials.
140 xmpp_login_ = host_owner_;
141 StartHostProcess();
142 return;
145 // Received a service account authorization code, update oauth_client_info_
146 // to use the service account client keys, and get service account tokens.
147 oauth_client_info_.client_id =
148 google_apis::GetOAuth2ClientID(
149 google_apis::CLIENT_REMOTING_HOST);
150 oauth_client_info_.client_secret =
151 google_apis::GetOAuth2ClientSecret(
152 google_apis::CLIENT_REMOTING_HOST);
153 oauth_client_info_.redirect_uri = "oob";
154 oauth_client_->GetTokensFromAuthCode(
155 oauth_client_info_, authorization_code, kMaxGetTokensRetries, this);
158 void HostStarter::StartHostProcess() {
159 // Start the host.
160 std::string host_secret_hash = remoting::MakeHostPinHash(host_id_, host_pin_);
161 scoped_ptr<base::DictionaryValue> config(new base::DictionaryValue());
162 if (host_owner_ != xmpp_login_) {
163 config->SetString("host_owner", host_owner_);
165 config->SetString("xmpp_login", xmpp_login_);
166 config->SetString("oauth_refresh_token", refresh_token_);
167 config->SetString("host_id", host_id_);
168 config->SetString("host_name", host_name_);
169 config->SetString("private_key", key_pair_->ToString());
170 config->SetString("host_secret_hash", host_secret_hash);
171 daemon_controller_->SetConfigAndStart(
172 config.Pass(), consent_to_data_collection_,
173 base::Bind(&HostStarter::OnHostStarted, base::Unretained(this)));
176 void HostStarter::OnHostStarted(DaemonController::AsyncResult result) {
177 if (!main_task_runner_->BelongsToCurrentThread()) {
178 main_task_runner_->PostTask(FROM_HERE, base::Bind(
179 &HostStarter::OnHostStarted, weak_ptr_, result));
180 return;
182 if (result != DaemonController::RESULT_OK) {
183 unregistering_host_ = true;
184 service_client_->UnregisterHost(host_id_, access_token_, this);
185 return;
187 CompletionCallback cb = on_done_;
188 on_done_.Reset();
189 cb.Run(START_COMPLETE);
192 void HostStarter::OnOAuthError() {
193 if (!main_task_runner_->BelongsToCurrentThread()) {
194 main_task_runner_->PostTask(FROM_HERE, base::Bind(
195 &HostStarter::OnOAuthError, weak_ptr_));
196 return;
198 CompletionCallback cb = on_done_;
199 on_done_.Reset();
200 if (unregistering_host_) {
201 LOG(ERROR) << "OAuth error occurred when unregistering host.";
202 cb.Run(START_ERROR);
203 } else {
204 cb.Run(OAUTH_ERROR);
208 void HostStarter::OnNetworkError(int response_code) {
209 if (!main_task_runner_->BelongsToCurrentThread()) {
210 main_task_runner_->PostTask(FROM_HERE, base::Bind(
211 &HostStarter::OnNetworkError, weak_ptr_, response_code));
212 return;
214 CompletionCallback cb = on_done_;
215 on_done_.Reset();
216 if (unregistering_host_) {
217 LOG(ERROR) << "Network error occurred when unregistering host.";
218 cb.Run(START_ERROR);
219 } else {
220 cb.Run(NETWORK_ERROR);
224 void HostStarter::OnHostUnregistered() {
225 if (!main_task_runner_->BelongsToCurrentThread()) {
226 main_task_runner_->PostTask(FROM_HERE, base::Bind(
227 &HostStarter::OnHostUnregistered, weak_ptr_));
228 return;
230 CompletionCallback cb = on_done_;
231 on_done_.Reset();
232 cb.Run(START_ERROR);
235 } // namespace remoting