Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / remoting / host / setup / host_starter.cc
blob5eda05c52a6f1b285d2f06faaf22be1156227d1d
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/callback_helpers.h"
9 #include "base/guid.h"
10 #include "base/location.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "base/values.h"
13 #include "google_apis/google_api_keys.h"
14 #include "remoting/host/pin_hash.h"
15 #include "remoting/host/setup/oauth_helper.h"
17 namespace {
18 const int kMaxGetTokensRetries = 3;
19 } // namespace
21 namespace remoting {
23 HostStarter::HostStarter(
24 scoped_ptr<gaia::GaiaOAuthClient> oauth_client,
25 scoped_ptr<remoting::ServiceClient> service_client,
26 scoped_refptr<remoting::DaemonController> daemon_controller)
27 : oauth_client_(oauth_client.Pass()),
28 service_client_(service_client.Pass()),
29 daemon_controller_(daemon_controller),
30 consent_to_data_collection_(false),
31 unregistering_host_(false),
32 weak_ptr_factory_(this) {
33 weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
34 main_task_runner_ = base::ThreadTaskRunnerHandle::Get();
37 HostStarter::~HostStarter() {
40 scoped_ptr<HostStarter> HostStarter::Create(
41 const std::string& chromoting_hosts_url,
42 net::URLRequestContextGetter* url_request_context_getter) {
43 scoped_ptr<gaia::GaiaOAuthClient> oauth_client(
44 new gaia::GaiaOAuthClient(url_request_context_getter));
45 scoped_ptr<remoting::ServiceClient> service_client(
46 new remoting::ServiceClient(
47 chromoting_hosts_url, url_request_context_getter));
48 scoped_refptr<remoting::DaemonController> daemon_controller(
49 remoting::DaemonController::Create());
50 return make_scoped_ptr(new HostStarter(
51 oauth_client.Pass(), service_client.Pass(), daemon_controller));
54 void HostStarter::StartHost(
55 const std::string& host_name,
56 const std::string& host_pin,
57 bool consent_to_data_collection,
58 const std::string& auth_code,
59 const std::string& redirect_url,
60 CompletionCallback on_done) {
61 DCHECK(main_task_runner_->BelongsToCurrentThread());
62 DCHECK(on_done_.is_null());
64 host_name_ = host_name;
65 host_pin_ = host_pin;
66 consent_to_data_collection_ = consent_to_data_collection;
67 on_done_ = on_done;
68 oauth_client_info_.client_id =
69 google_apis::GetOAuth2ClientID(google_apis::CLIENT_REMOTING);
70 oauth_client_info_.client_secret =
71 google_apis::GetOAuth2ClientSecret(google_apis::CLIENT_REMOTING);
72 oauth_client_info_.redirect_uri = redirect_url;
73 // Map the authorization code to refresh and access tokens.
74 oauth_client_->GetTokensFromAuthCode(oauth_client_info_, auth_code,
75 kMaxGetTokensRetries, this);
78 void HostStarter::OnGetTokensResponse(
79 const std::string& refresh_token,
80 const std::string& access_token,
81 int expires_in_seconds) {
82 if (!main_task_runner_->BelongsToCurrentThread()) {
83 main_task_runner_->PostTask(FROM_HERE, base::Bind(
84 &HostStarter::OnGetTokensResponse, weak_ptr_,
85 refresh_token, access_token, expires_in_seconds));
86 return;
88 refresh_token_ = refresh_token;
89 access_token_ = access_token;
90 // Get the email corresponding to the access token.
91 oauth_client_->GetUserEmail(access_token_, 1, this);
94 void HostStarter::OnRefreshTokenResponse(
95 const std::string& access_token,
96 int expires_in_seconds) {
97 // We never request a refresh token, so this call is not expected.
98 NOTREACHED();
101 // This function is called twice: once with the host owner credentials, and once
102 // with the service account credentials.
103 void HostStarter::OnGetUserEmailResponse(const std::string& user_email) {
104 if (!main_task_runner_->BelongsToCurrentThread()) {
105 main_task_runner_->PostTask(FROM_HERE, base::Bind(
106 &HostStarter::OnGetUserEmailResponse, weak_ptr_, user_email));
107 return;
110 if (host_owner_.empty()) {
111 // This is the first callback, with the host owner credentials. Store the
112 // owner's email, and register the host.
113 host_owner_ = user_email;
114 host_id_ = base::GenerateGUID();
115 key_pair_ = RsaKeyPair::Generate();
117 std::string host_client_id;
118 host_client_id = google_apis::GetOAuth2ClientID(
119 google_apis::CLIENT_REMOTING_HOST);
121 service_client_->RegisterHost(
122 host_id_, host_name_, key_pair_->GetPublicKey(), host_client_id,
123 access_token_, this);
124 } else {
125 // This is the second callback, with the service account credentials.
126 // This email is the service account's email, used to login to XMPP.
127 xmpp_login_ = user_email;
128 StartHostProcess();
132 void HostStarter::OnHostRegistered(const std::string& authorization_code) {
133 if (!main_task_runner_->BelongsToCurrentThread()) {
134 main_task_runner_->PostTask(FROM_HERE, base::Bind(
135 &HostStarter::OnHostRegistered, weak_ptr_, authorization_code));
136 return;
139 if (authorization_code.empty()) {
140 // No service account code, start the host with the owner's credentials.
141 xmpp_login_ = host_owner_;
142 StartHostProcess();
143 return;
146 // Received a service account authorization code, update oauth_client_info_
147 // to use the service account client keys, and get service account tokens.
148 oauth_client_info_.client_id =
149 google_apis::GetOAuth2ClientID(
150 google_apis::CLIENT_REMOTING_HOST);
151 oauth_client_info_.client_secret =
152 google_apis::GetOAuth2ClientSecret(
153 google_apis::CLIENT_REMOTING_HOST);
154 oauth_client_info_.redirect_uri = "oob";
155 oauth_client_->GetTokensFromAuthCode(
156 oauth_client_info_, authorization_code, kMaxGetTokensRetries, this);
159 void HostStarter::StartHostProcess() {
160 // Start the host.
161 std::string host_secret_hash = remoting::MakeHostPinHash(host_id_, host_pin_);
162 scoped_ptr<base::DictionaryValue> config(new base::DictionaryValue());
163 if (host_owner_ != xmpp_login_) {
164 config->SetString("host_owner", host_owner_);
166 config->SetString("xmpp_login", xmpp_login_);
167 config->SetString("oauth_refresh_token", refresh_token_);
168 config->SetString("host_id", host_id_);
169 config->SetString("host_name", host_name_);
170 config->SetString("private_key", key_pair_->ToString());
171 config->SetString("host_secret_hash", host_secret_hash);
172 daemon_controller_->SetConfigAndStart(
173 config.Pass(), consent_to_data_collection_,
174 base::Bind(&HostStarter::OnHostStarted, base::Unretained(this)));
177 void HostStarter::OnHostStarted(DaemonController::AsyncResult result) {
178 if (!main_task_runner_->BelongsToCurrentThread()) {
179 main_task_runner_->PostTask(FROM_HERE, base::Bind(
180 &HostStarter::OnHostStarted, weak_ptr_, result));
181 return;
183 if (result != DaemonController::RESULT_OK) {
184 unregistering_host_ = true;
185 service_client_->UnregisterHost(host_id_, access_token_, this);
186 return;
188 base::ResetAndReturn(&on_done_).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 if (unregistering_host_) {
198 LOG(ERROR) << "OAuth error occurred when unregistering host.";
201 base::ResetAndReturn(&on_done_)
202 .Run(unregistering_host_ ? START_ERROR : OAUTH_ERROR);
205 void HostStarter::OnNetworkError(int response_code) {
206 if (!main_task_runner_->BelongsToCurrentThread()) {
207 main_task_runner_->PostTask(FROM_HERE, base::Bind(
208 &HostStarter::OnNetworkError, weak_ptr_, response_code));
209 return;
211 if (unregistering_host_) {
212 LOG(ERROR) << "Network error occurred when unregistering host.";
215 base::ResetAndReturn(&on_done_)
216 .Run(unregistering_host_ ? START_ERROR : NETWORK_ERROR);
219 void HostStarter::OnHostUnregistered() {
220 if (!main_task_runner_->BelongsToCurrentThread()) {
221 main_task_runner_->PostTask(FROM_HERE, base::Bind(
222 &HostStarter::OnHostUnregistered, weak_ptr_));
223 return;
225 base::ResetAndReturn(&on_done_).Run(START_ERROR);
228 } // namespace remoting