Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / remoting / host / setup / host_starter.cc
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/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"
15
16 namespace {
17 const int kMaxGetTokensRetries = 3;
18 }  // namespace
19
20 namespace remoting {
21
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();
34 }
35
36 HostStarter::~HostStarter() {
37 }
38
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 scoped_ptr<HostStarter>(
50       new HostStarter(oauth_client.Pass(), service_client.Pass(),
51                       daemon_controller));
52 }
53
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());
63
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);
76 }
77
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;
87   }
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);
92 }
93
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();
99 }
100
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;
108   }
109
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();
116
117     std::string host_client_id;
118     host_client_id = google_apis::GetOAuth2ClientID(
119         google_apis::CLIENT_REMOTING_HOST);
120
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();
129   }
130 }
131
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;
137   }
138
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;
144   }
145
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);
157 }
158
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_);
165   }
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)));
175 }
176
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;
182   }
183   if (result != DaemonController::RESULT_OK) {
184     unregistering_host_ = true;
185     service_client_->UnregisterHost(host_id_, access_token_, this);
186     return;
187   }
188   CompletionCallback cb = on_done_;
189   on_done_.Reset();
190   cb.Run(START_COMPLETE);
191 }
192
193 void HostStarter::OnOAuthError() {
194   if (!main_task_runner_->BelongsToCurrentThread()) {
195     main_task_runner_->PostTask(FROM_HERE, base::Bind(
196         &HostStarter::OnOAuthError, weak_ptr_));
197     return;
198   }
199   CompletionCallback cb = on_done_;
200   on_done_.Reset();
201   if (unregistering_host_) {
202     LOG(ERROR) << "OAuth error occurred when unregistering host.";
203     cb.Run(START_ERROR);
204   } else {
205     cb.Run(OAUTH_ERROR);
206   }
207 }
208
209 void HostStarter::OnNetworkError(int response_code) {
210   if (!main_task_runner_->BelongsToCurrentThread()) {
211     main_task_runner_->PostTask(FROM_HERE, base::Bind(
212         &HostStarter::OnNetworkError, weak_ptr_, response_code));
213     return;
214   }
215   CompletionCallback cb = on_done_;
216   on_done_.Reset();
217   if (unregistering_host_) {
218     LOG(ERROR) << "Network error occurred when unregistering host.";
219     cb.Run(START_ERROR);
220   } else {
221     cb.Run(NETWORK_ERROR);
222   }
223 }
224
225 void HostStarter::OnHostUnregistered() {
226   if (!main_task_runner_->BelongsToCurrentThread()) {
227     main_task_runner_->PostTask(FROM_HERE, base::Bind(
228         &HostStarter::OnHostUnregistered, weak_ptr_));
229     return;
230   }
231   CompletionCallback cb = on_done_;
232   on_done_.Reset();
233   cb.Run(START_ERROR);
234 }
235
236 }  // namespace remoting