Add explicit |forceOnlineSignin| to user pod status
[chromium-blink-merge.git] / remoting / host / setup / host_starter.cc
blob298be8ed7d45ddc1bfb4dd903f32d9c4d259802c
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/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"
14 namespace {
15 const int kMaxGetTokensRetries = 3;
16 } // namespace
18 namespace remoting {
20 HostStarter::HostStarter(
21 scoped_ptr<gaia::GaiaOAuthClient> oauth_client,
22 scoped_ptr<remoting::ServiceClient> service_client,
23 scoped_refptr<remoting::DaemonController> daemon_controller)
24 : oauth_client_(oauth_client.Pass()),
25 service_client_(service_client.Pass()),
26 daemon_controller_(daemon_controller),
27 consent_to_data_collection_(false),
28 unregistering_host_(false),
29 weak_ptr_factory_(this) {
30 weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
31 main_task_runner_ = base::ThreadTaskRunnerHandle::Get();
34 HostStarter::~HostStarter() {
37 scoped_ptr<HostStarter> HostStarter::Create(
38 const std::string& chromoting_hosts_url,
39 net::URLRequestContextGetter* url_request_context_getter) {
40 scoped_ptr<gaia::GaiaOAuthClient> oauth_client(
41 new gaia::GaiaOAuthClient(url_request_context_getter));
42 scoped_ptr<remoting::ServiceClient> service_client(
43 new remoting::ServiceClient(
44 chromoting_hosts_url, url_request_context_getter));
45 scoped_refptr<remoting::DaemonController> daemon_controller(
46 remoting::DaemonController::Create());
47 return scoped_ptr<HostStarter>(
48 new HostStarter(oauth_client.Pass(), service_client.Pass(),
49 daemon_controller));
52 void HostStarter::StartHost(
53 const std::string& host_name,
54 const std::string& host_pin,
55 bool consent_to_data_collection,
56 const std::string& auth_code,
57 const std::string& redirect_url,
58 CompletionCallback on_done) {
59 DCHECK(main_task_runner_->BelongsToCurrentThread());
60 DCHECK(on_done_.is_null());
62 host_name_ = host_name;
63 host_pin_ = host_pin;
64 consent_to_data_collection_ = consent_to_data_collection;
65 on_done_ = on_done;
66 oauth_client_info_.client_id =
67 google_apis::GetOAuth2ClientID(google_apis::CLIENT_REMOTING);
68 oauth_client_info_.client_secret =
69 google_apis::GetOAuth2ClientSecret(google_apis::CLIENT_REMOTING);
70 oauth_client_info_.redirect_uri = redirect_url;
71 // Map the authorization code to refresh and access tokens.
72 oauth_client_->GetTokensFromAuthCode(oauth_client_info_, auth_code,
73 kMaxGetTokensRetries, this);
76 void HostStarter::OnGetTokensResponse(
77 const std::string& refresh_token,
78 const std::string& access_token,
79 int expires_in_seconds) {
80 if (!main_task_runner_->BelongsToCurrentThread()) {
81 main_task_runner_->PostTask(FROM_HERE, base::Bind(
82 &HostStarter::OnGetTokensResponse, weak_ptr_,
83 refresh_token, access_token, expires_in_seconds));
84 return;
86 refresh_token_ = refresh_token;
87 access_token_ = access_token;
88 // Get the email corresponding to the access token.
89 oauth_client_->GetUserEmail(access_token_, 1, this);
92 void HostStarter::OnRefreshTokenResponse(
93 const std::string& access_token,
94 int expires_in_seconds) {
95 // We never request a refresh token, so this call is not expected.
96 NOTREACHED();
99 // This function is called twice: once with the host owner credentials, and once
100 // with the service account credentials.
101 void HostStarter::OnGetUserEmailResponse(const std::string& user_email) {
102 if (!main_task_runner_->BelongsToCurrentThread()) {
103 main_task_runner_->PostTask(FROM_HERE, base::Bind(
104 &HostStarter::OnGetUserEmailResponse, weak_ptr_, user_email));
105 return;
108 if (host_owner_.empty()) {
109 // This is the first callback, with the host owner credentials. Store the
110 // owner's email, and register the host.
111 host_owner_ = user_email;
112 host_id_ = base::GenerateGUID();
113 key_pair_ = RsaKeyPair::Generate();
115 std::string host_client_id;
116 host_client_id = google_apis::GetOAuth2ClientID(
117 google_apis::CLIENT_REMOTING_HOST);
119 service_client_->RegisterHost(
120 host_id_, host_name_, key_pair_->GetPublicKey(), host_client_id,
121 access_token_, this);
122 } else {
123 // This is the second callback, with the service account credentials.
124 // This email is the service account's email, used to login to XMPP.
125 xmpp_login_ = user_email;
126 StartHostProcess();
130 void HostStarter::OnHostRegistered(const std::string& authorization_code) {
131 if (!main_task_runner_->BelongsToCurrentThread()) {
132 main_task_runner_->PostTask(FROM_HERE, base::Bind(
133 &HostStarter::OnHostRegistered, weak_ptr_, authorization_code));
134 return;
137 if (authorization_code.empty()) {
138 // No service account code, start the host with the owner's credentials.
139 xmpp_login_ = host_owner_;
140 StartHostProcess();
141 return;
144 // Received a service account authorization code, update oauth_client_info_
145 // to use the service account client keys, and get service account tokens.
146 oauth_client_info_.client_id =
147 google_apis::GetOAuth2ClientID(
148 google_apis::CLIENT_REMOTING_HOST);
149 oauth_client_info_.client_secret =
150 google_apis::GetOAuth2ClientSecret(
151 google_apis::CLIENT_REMOTING_HOST);
152 oauth_client_info_.redirect_uri = "oob";
153 oauth_client_->GetTokensFromAuthCode(
154 oauth_client_info_, authorization_code, kMaxGetTokensRetries, this);
157 void HostStarter::StartHostProcess() {
158 // Start the host.
159 std::string host_secret_hash = remoting::MakeHostPinHash(host_id_, host_pin_);
160 scoped_ptr<base::DictionaryValue> config(new base::DictionaryValue());
161 if (host_owner_ != xmpp_login_) {
162 config->SetString("host_owner", host_owner_);
164 config->SetString("xmpp_login", xmpp_login_);
165 config->SetString("oauth_refresh_token", refresh_token_);
166 config->SetString("host_id", host_id_);
167 config->SetString("host_name", host_name_);
168 config->SetString("private_key", key_pair_->ToString());
169 config->SetString("host_secret_hash", host_secret_hash);
170 daemon_controller_->SetConfigAndStart(
171 config.Pass(), consent_to_data_collection_,
172 base::Bind(&HostStarter::OnHostStarted, base::Unretained(this)));
175 void HostStarter::OnHostStarted(DaemonController::AsyncResult result) {
176 if (!main_task_runner_->BelongsToCurrentThread()) {
177 main_task_runner_->PostTask(FROM_HERE, base::Bind(
178 &HostStarter::OnHostStarted, weak_ptr_, result));
179 return;
181 if (result != DaemonController::RESULT_OK) {
182 unregistering_host_ = true;
183 service_client_->UnregisterHost(host_id_, access_token_, this);
184 return;
186 CompletionCallback cb = on_done_;
187 on_done_.Reset();
188 cb.Run(START_COMPLETE);
191 void HostStarter::OnOAuthError() {
192 if (!main_task_runner_->BelongsToCurrentThread()) {
193 main_task_runner_->PostTask(FROM_HERE, base::Bind(
194 &HostStarter::OnOAuthError, weak_ptr_));
195 return;
197 CompletionCallback cb = on_done_;
198 on_done_.Reset();
199 if (unregistering_host_) {
200 LOG(ERROR) << "OAuth error occurred when unregistering host.";
201 cb.Run(START_ERROR);
202 } else {
203 cb.Run(OAUTH_ERROR);
207 void HostStarter::OnNetworkError(int response_code) {
208 if (!main_task_runner_->BelongsToCurrentThread()) {
209 main_task_runner_->PostTask(FROM_HERE, base::Bind(
210 &HostStarter::OnNetworkError, weak_ptr_, response_code));
211 return;
213 CompletionCallback cb = on_done_;
214 on_done_.Reset();
215 if (unregistering_host_) {
216 LOG(ERROR) << "Network error occurred when unregistering host.";
217 cb.Run(START_ERROR);
218 } else {
219 cb.Run(NETWORK_ERROR);
223 void HostStarter::OnHostUnregistered() {
224 if (!main_task_runner_->BelongsToCurrentThread()) {
225 main_task_runner_->PostTask(FROM_HERE, base::Bind(
226 &HostStarter::OnHostUnregistered, weak_ptr_));
227 return;
229 CompletionCallback cb = on_done_;
230 on_done_.Reset();
231 cb.Run(START_ERROR);
234 } // namespace remoting