Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(396)

Side by Side Diff: remoting/host/signaling_connector.cc

Issue 141063009: Separate access token caching logic from signaling connector. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Change C++11 swap() to plain old copy-and-clear. Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « remoting/host/signaling_connector.h ('k') | remoting/remoting_host.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/host/signaling_connector.h" 5 #include "remoting/host/signaling_connector.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/strings/string_util.h" 9 #include "base/strings/string_util.h"
10 #include "google_apis/google_api_keys.h" 10 #include "google_apis/google_api_keys.h"
11 #include "net/url_request/url_fetcher.h" 11 #include "net/url_request/url_fetcher.h"
12 #include "net/url_request/url_request_context_getter.h" 12 #include "net/url_request/url_request_context_getter.h"
13 #include "remoting/base/logging.h" 13 #include "remoting/base/logging.h"
14 #include "remoting/host/dns_blackhole_checker.h" 14 #include "remoting/host/dns_blackhole_checker.h"
15 15
16 namespace remoting { 16 namespace remoting {
17 17
18 namespace { 18 namespace {
19 19
20 // The delay between reconnect attempts will increase exponentially up 20 // The delay between reconnect attempts will increase exponentially up
21 // to the maximum specified here. 21 // to the maximum specified here.
22 const int kMaxReconnectDelaySeconds = 10 * 60; 22 const int kMaxReconnectDelaySeconds = 10 * 60;
23 23
24 // Time when we we try to update OAuth token before its expiration.
25 const int kTokenUpdateTimeBeforeExpirySeconds = 60;
26
27 } // namespace 24 } // namespace
28 25
29 SignalingConnector::OAuthCredentials::OAuthCredentials(
30 const std::string& login_value,
31 const std::string& refresh_token_value,
32 bool is_service_account)
33 : login(login_value),
34 refresh_token(refresh_token_value),
35 is_service_account(is_service_account) {
36 }
37
38 SignalingConnector::SignalingConnector( 26 SignalingConnector::SignalingConnector(
39 XmppSignalStrategy* signal_strategy, 27 XmppSignalStrategy* signal_strategy,
40 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
41 scoped_ptr<DnsBlackholeChecker> dns_blackhole_checker, 28 scoped_ptr<DnsBlackholeChecker> dns_blackhole_checker,
42 const base::Closure& auth_failed_callback) 29 const base::Closure& auth_failed_callback)
43 : signal_strategy_(signal_strategy), 30 : signal_strategy_(signal_strategy),
44 url_request_context_getter_(url_request_context_getter),
45 auth_failed_callback_(auth_failed_callback), 31 auth_failed_callback_(auth_failed_callback),
46 dns_blackhole_checker_(dns_blackhole_checker.Pass()), 32 dns_blackhole_checker_(dns_blackhole_checker.Pass()),
47 reconnect_attempts_(0), 33 reconnect_attempts_(0) {
48 refreshing_oauth_token_(false) {
49 DCHECK(!auth_failed_callback_.is_null()); 34 DCHECK(!auth_failed_callback_.is_null());
50 DCHECK(dns_blackhole_checker_.get()); 35 DCHECK(dns_blackhole_checker_.get());
51 net::NetworkChangeNotifier::AddConnectionTypeObserver(this); 36 net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
52 net::NetworkChangeNotifier::AddIPAddressObserver(this); 37 net::NetworkChangeNotifier::AddIPAddressObserver(this);
53 signal_strategy_->AddListener(this); 38 signal_strategy_->AddListener(this);
54 ScheduleTryReconnect(); 39 ScheduleTryReconnect();
55 } 40 }
56 41
57 SignalingConnector::~SignalingConnector() { 42 SignalingConnector::~SignalingConnector() {
58 signal_strategy_->RemoveListener(this); 43 signal_strategy_->RemoveListener(this);
59 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this); 44 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
60 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); 45 net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
61 } 46 }
62 47
63 void SignalingConnector::EnableOAuth( 48 void SignalingConnector::EnableOAuth(OAuthTokenGetter* oauth_token_getter) {
64 scoped_ptr<OAuthCredentials> oauth_credentials) { 49 oauth_token_getter_ = oauth_token_getter;
65 oauth_credentials_ = oauth_credentials.Pass();
66 gaia_oauth_client_.reset(
67 new gaia::GaiaOAuthClient(url_request_context_getter_.get()));
68 } 50 }
69 51
70 void SignalingConnector::OnSignalStrategyStateChange( 52 void SignalingConnector::OnSignalStrategyStateChange(
71 SignalStrategy::State state) { 53 SignalStrategy::State state) {
72 DCHECK(CalledOnValidThread()); 54 DCHECK(CalledOnValidThread());
73 55
74 if (state == SignalStrategy::CONNECTED) { 56 if (state == SignalStrategy::CONNECTED) {
75 HOST_LOG << "Signaling connected."; 57 HOST_LOG << "Signaling connected.";
76 reconnect_attempts_ = 0; 58 reconnect_attempts_ = 0;
77 } else if (state == SignalStrategy::DISCONNECTED) { 59 } else if (state == SignalStrategy::DISCONNECTED) {
(...skipping 26 matching lines...) Expand all
104 } 86 }
105 87
106 void SignalingConnector::OnIPAddressChanged() { 88 void SignalingConnector::OnIPAddressChanged() {
107 DCHECK(CalledOnValidThread()); 89 DCHECK(CalledOnValidThread());
108 if (signal_strategy_->GetState() == SignalStrategy::DISCONNECTED) { 90 if (signal_strategy_->GetState() == SignalStrategy::DISCONNECTED) {
109 HOST_LOG << "IP address has changed."; 91 HOST_LOG << "IP address has changed.";
110 ResetAndTryReconnect(); 92 ResetAndTryReconnect();
111 } 93 }
112 } 94 }
113 95
114 void SignalingConnector::OnGetTokensResponse(const std::string& user_email, 96 void SignalingConnector::OnAccessToken(OAuthTokenGetter::Status status,
115 const std::string& access_token, 97 const std::string& user_email,
116 int expires_seconds) { 98 const std::string& access_token) {
117 NOTREACHED(); 99 DCHECK(CalledOnValidThread());
118 }
119 100
120 void SignalingConnector::OnRefreshTokenResponse( 101 if (status == OAuthTokenGetter::AUTH_ERROR) {
121 const std::string& access_token,
122 int expires_seconds) {
123 DCHECK(CalledOnValidThread());
124 DCHECK(oauth_credentials_.get());
125 HOST_LOG << "Received OAuth token.";
126
127 oauth_access_token_ = access_token;
128 auth_token_expiry_time_ = base::Time::Now() +
129 base::TimeDelta::FromSeconds(expires_seconds) -
130 base::TimeDelta::FromSeconds(kTokenUpdateTimeBeforeExpirySeconds);
131
132 gaia_oauth_client_->GetUserEmail(access_token, 1, this);
133 }
134
135 void SignalingConnector::OnGetUserEmailResponse(const std::string& user_email) {
136 DCHECK(CalledOnValidThread());
137 DCHECK(oauth_credentials_.get());
138 HOST_LOG << "Received user info.";
139
140 if (user_email != oauth_credentials_->login) {
141 LOG(ERROR) << "OAuth token and email address do not refer to "
142 "the same account.";
143 auth_failed_callback_.Run(); 102 auth_failed_callback_.Run();
144 return; 103 return;
104 } else if (status == OAuthTokenGetter::NETWORK_ERROR) {
105 OnNetworkError();
106 return;
145 } 107 }
146 108
147 signal_strategy_->SetAuthInfo(oauth_credentials_->login, 109 DCHECK_EQ(status, OAuthTokenGetter::SUCCESS);
148 oauth_access_token_, "oauth2"); 110 HOST_LOG << "Received user info.";
149 refreshing_oauth_token_ = false; 111
112 signal_strategy_->SetAuthInfo(user_email, access_token, "oauth2");
150 113
151 // Now that we've refreshed the token and verified that it's for the correct 114 // Now that we've refreshed the token and verified that it's for the correct
152 // user account, try to connect using the new token. 115 // user account, try to connect using the new token.
153 DCHECK_EQ(signal_strategy_->GetState(), SignalStrategy::DISCONNECTED); 116 DCHECK_EQ(signal_strategy_->GetState(), SignalStrategy::DISCONNECTED);
154 signal_strategy_->Connect(); 117 signal_strategy_->Connect();
155 } 118 }
156 119
157 void SignalingConnector::OnOAuthError() { 120 void SignalingConnector::OnNetworkError() {
158 DCHECK(CalledOnValidThread()); 121 DCHECK(CalledOnValidThread());
159 LOG(ERROR) << "OAuth: invalid credentials.";
160 refreshing_oauth_token_ = false;
161 reconnect_attempts_++;
162 auth_failed_callback_.Run();
163 }
164
165 void SignalingConnector::OnNetworkError(int response_code) {
166 DCHECK(CalledOnValidThread());
167 LOG(ERROR) << "Network error when trying to update OAuth token: "
168 << response_code;
169 refreshing_oauth_token_ = false;
170 reconnect_attempts_++; 122 reconnect_attempts_++;
171 ScheduleTryReconnect(); 123 ScheduleTryReconnect();
172 } 124 }
173 125
174 void SignalingConnector::ScheduleTryReconnect() { 126 void SignalingConnector::ScheduleTryReconnect() {
175 DCHECK(CalledOnValidThread()); 127 DCHECK(CalledOnValidThread());
176 if (timer_.IsRunning() || net::NetworkChangeNotifier::IsOffline()) 128 if (timer_.IsRunning() || net::NetworkChangeNotifier::IsOffline())
177 return; 129 return;
178 int delay_s = std::min(1 << reconnect_attempts_, 130 int delay_s = std::min(1 << reconnect_attempts_,
179 kMaxReconnectDelaySeconds); 131 kMaxReconnectDelaySeconds);
(...skipping 28 matching lines...) Expand all
208 // an outright block. 160 // an outright block.
209 if (!allow) { 161 if (!allow) {
210 reconnect_attempts_++; 162 reconnect_attempts_++;
211 HOST_LOG << "Talkgadget check failed. Scheduling reconnect. Attempt " 163 HOST_LOG << "Talkgadget check failed. Scheduling reconnect. Attempt "
212 << reconnect_attempts_; 164 << reconnect_attempts_;
213 ScheduleTryReconnect(); 165 ScheduleTryReconnect();
214 return; 166 return;
215 } 167 }
216 168
217 if (signal_strategy_->GetState() == SignalStrategy::DISCONNECTED) { 169 if (signal_strategy_->GetState() == SignalStrategy::DISCONNECTED) {
218 bool need_new_auth_token = oauth_credentials_.get() && 170 HOST_LOG << "Attempting to connect signaling.";
219 (auth_token_expiry_time_.is_null() || 171 oauth_token_getter_->CallWithToken(
220 base::Time::Now() >= auth_token_expiry_time_); 172 base::Bind(&SignalingConnector::OnAccessToken, AsWeakPtr()));
221 if (need_new_auth_token) {
222 RefreshOAuthToken();
223 } else {
224 HOST_LOG << "Attempting to connect signaling.";
225 signal_strategy_->Connect();
226 }
227 } 173 }
228 } 174 }
229 175
230 void SignalingConnector::RefreshOAuthToken() {
231 DCHECK(CalledOnValidThread());
232 HOST_LOG << "Refreshing OAuth token.";
233 DCHECK(!refreshing_oauth_token_);
234
235 // Service accounts use different API keys, as they use the client app flow.
236 google_apis::OAuth2Client oauth2_client;
237 if (oauth_credentials_->is_service_account) {
238 oauth2_client = google_apis::CLIENT_REMOTING_HOST;
239 } else {
240 oauth2_client = google_apis::CLIENT_REMOTING;
241 }
242
243 gaia::OAuthClientInfo client_info = {
244 google_apis::GetOAuth2ClientID(oauth2_client),
245 google_apis::GetOAuth2ClientSecret(oauth2_client),
246 // Redirect URL is only used when getting tokens from auth code. It
247 // is not required when getting access tokens.
248 ""
249 };
250
251 refreshing_oauth_token_ = true;
252 std::vector<std::string> empty_scope_list; // (Use scope from refresh token.)
253 gaia_oauth_client_->RefreshToken(
254 client_info, oauth_credentials_->refresh_token, empty_scope_list,
255 1, this);
256 }
257
258 } // namespace remoting 176 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/signaling_connector.h ('k') | remoting/remoting_host.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698