OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "components/signin/core/browser/gaia_cookie_manager_service.h" | 5 #include "components/signin/core/browser/gaia_cookie_manager_service.h" |
6 | 6 |
7 #include <queue> | 7 #include <queue> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/json/json_reader.h" | 10 #include "base/json/json_reader.h" |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 results.push_back(it->first + ":" + it->second); | 129 results.push_back(it->first + ":" + it->second); |
130 } | 130 } |
131 return JoinString(results, ","); | 131 return JoinString(results, ","); |
132 } | 132 } |
133 | 133 |
134 void GaiaCookieManagerService::ExternalCcResultFetcher::Start() { | 134 void GaiaCookieManagerService::ExternalCcResultFetcher::Start() { |
135 m_external_cc_result_start_time_ = base::Time::Now(); | 135 m_external_cc_result_start_time_ = base::Time::Now(); |
136 | 136 |
137 CleanupTransientState(); | 137 CleanupTransientState(); |
138 results_.clear(); | 138 results_.clear(); |
139 gaia_auth_fetcher_.reset( | 139 helper_->gaia_auth_fetcher_.reset( |
140 new GaiaAuthFetcher(this, helper_->source_, helper_->request_context())); | 140 new GaiaAuthFetcher(this, helper_->source_, helper_->request_context())); |
141 gaia_auth_fetcher_->StartGetCheckConnectionInfo(); | 141 helper_->gaia_auth_fetcher_->StartGetCheckConnectionInfo(); |
142 | 142 |
143 // Some fetches may timeout. Start a timer to decide when the result fetcher | 143 // Some fetches may timeout. Start a timer to decide when the result fetcher |
144 // has waited long enough. | 144 // has waited long enough. |
145 // TODO(rogerta): I have no idea how long to wait before timing out. | 145 // TODO(rogerta): I have no idea how long to wait before timing out. |
146 // Gaia folks say this should take no more than 2 second even in mobile. | 146 // Gaia folks say this should take no more than 2 second even in mobile. |
147 // This will need to be tweaked. | 147 // This will need to be tweaked. |
148 timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(5), this, | 148 timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(5), this, |
149 &GaiaCookieManagerService::ExternalCcResultFetcher::Timeout); | 149 &GaiaCookieManagerService::ExternalCcResultFetcher::Timeout); |
150 } | 150 } |
151 | 151 |
152 bool GaiaCookieManagerService::ExternalCcResultFetcher::IsRunning() { | 152 bool GaiaCookieManagerService::ExternalCcResultFetcher::IsRunning() { |
153 return gaia_auth_fetcher_ || fetchers_.size() > 0u; | 153 return helper_->gaia_auth_fetcher_ || fetchers_.size() > 0u; |
154 } | 154 } |
155 | 155 |
156 void GaiaCookieManagerService::ExternalCcResultFetcher::TimeoutForTests() { | 156 void GaiaCookieManagerService::ExternalCcResultFetcher::TimeoutForTests() { |
157 Timeout(); | 157 Timeout(); |
158 } | 158 } |
159 | 159 |
160 void GaiaCookieManagerService::ExternalCcResultFetcher:: | 160 void GaiaCookieManagerService::ExternalCcResultFetcher:: |
161 OnGetCheckConnectionInfoSuccess(const std::string& data) { | 161 OnGetCheckConnectionInfoSuccess(const std::string& data) { |
| 162 helper_->gaia_auth_fetcher_backoff_.InformOfRequest(true); |
| 163 gaia_auth_fetcher_timer_.Stop(); |
162 scoped_ptr<base::Value> value(base::JSONReader::Read(data)); | 164 scoped_ptr<base::Value> value(base::JSONReader::Read(data)); |
163 const base::ListValue* list; | 165 const base::ListValue* list; |
164 if (!value || !value->GetAsList(&list)) { | 166 if (!value || !value->GetAsList(&list)) { |
165 CleanupTransientState(); | 167 CleanupTransientState(); |
166 FireGetCheckConnectionInfoCompleted(false); | 168 GetCheckConnectionInfoCompleted(false); |
167 return; | 169 return; |
168 } | 170 } |
169 | 171 |
170 // If there is nothing to check, terminate immediately. | 172 // If there is nothing to check, terminate immediately. |
171 if (list->GetSize() == 0) { | 173 if (list->GetSize() == 0) { |
172 CleanupTransientState(); | 174 CleanupTransientState(); |
173 FireGetCheckConnectionInfoCompleted(true); | 175 GetCheckConnectionInfoCompleted(true); |
174 return; | 176 return; |
175 } | 177 } |
176 | 178 |
177 // Start a fetcher for each connection URL that needs to be checked. | 179 // Start a fetcher for each connection URL that needs to be checked. |
178 for (size_t i = 0; i < list->GetSize(); ++i) { | 180 for (size_t i = 0; i < list->GetSize(); ++i) { |
179 const base::DictionaryValue* dict; | 181 const base::DictionaryValue* dict; |
180 if (list->GetDictionary(i, &dict)) { | 182 if (list->GetDictionary(i, &dict)) { |
181 std::string token; | 183 std::string token; |
182 std::string url; | 184 std::string url; |
183 if (dict->GetString("carryBackToken", &token) && | 185 if (dict->GetString("carryBackToken", &token) && |
184 dict->GetString("url", &url)) { | 186 dict->GetString("url", &url)) { |
185 results_[token] = "null"; | 187 results_[token] = "null"; |
186 net::URLFetcher* fetcher = CreateFetcher(GURL(url)); | 188 net::URLFetcher* fetcher = CreateFetcher(GURL(url)); |
187 fetchers_[fetcher->GetOriginalURL()] = std::make_pair(token, fetcher); | 189 fetchers_[fetcher->GetOriginalURL()] = std::make_pair(token, fetcher); |
188 fetcher->Start(); | 190 fetcher->Start(); |
189 } | 191 } |
190 } | 192 } |
191 } | 193 } |
192 } | 194 } |
193 | 195 |
194 void GaiaCookieManagerService::ExternalCcResultFetcher:: | 196 void GaiaCookieManagerService::ExternalCcResultFetcher:: |
195 OnGetCheckConnectionInfoError(const GoogleServiceAuthError& error) { | 197 OnGetCheckConnectionInfoError(const GoogleServiceAuthError& error) { |
| 198 if (++helper_->gaia_auth_fetcher_retries_ < kMaxGaiaAuthFetcherRetries && |
| 199 IsTransientError(error)) { |
| 200 helper_->gaia_auth_fetcher_backoff_.InformOfRequest(false); |
| 201 gaia_auth_fetcher_timer_.Start( |
| 202 FROM_HERE, helper_->gaia_auth_fetcher_backoff_.GetTimeUntilRelease(), |
| 203 this, &GaiaCookieManagerService::ExternalCcResultFetcher::Start); |
| 204 return; |
| 205 } |
| 206 |
196 CleanupTransientState(); | 207 CleanupTransientState(); |
197 FireGetCheckConnectionInfoCompleted(false); | 208 GetCheckConnectionInfoCompleted(false); |
198 } | 209 } |
199 | 210 |
200 net::URLFetcher* | 211 net::URLFetcher* |
201 GaiaCookieManagerService::ExternalCcResultFetcher::CreateFetcher( | 212 GaiaCookieManagerService::ExternalCcResultFetcher::CreateFetcher( |
202 const GURL& url) { | 213 const GURL& url) { |
203 net::URLFetcher* fetcher = | 214 net::URLFetcher* fetcher = |
204 net::URLFetcher::Create(0, url, net::URLFetcher::GET, this); | 215 net::URLFetcher::Create(0, url, net::URLFetcher::GET, this); |
205 fetcher->SetRequestContext(helper_->request_context()); | 216 fetcher->SetRequestContext(helper_->request_context()); |
206 fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | 217 fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | |
207 net::LOAD_DO_NOT_SAVE_COOKIES); | 218 net::LOAD_DO_NOT_SAVE_COOKIES); |
(...skipping 22 matching lines...) Expand all Loading... |
230 // Clean up tracking of this fetcher. The rest will be cleaned up after | 241 // Clean up tracking of this fetcher. The rest will be cleaned up after |
231 // the timer expires in CleanupTransientState(). | 242 // the timer expires in CleanupTransientState(). |
232 DCHECK_EQ(source, fetchers_[url].second); | 243 DCHECK_EQ(source, fetchers_[url].second); |
233 fetchers_.erase(url); | 244 fetchers_.erase(url); |
234 delete source; | 245 delete source; |
235 | 246 |
236 // If all expected responses have been received, cancel the timer and | 247 // If all expected responses have been received, cancel the timer and |
237 // report the result. | 248 // report the result. |
238 if (fetchers_.empty()) { | 249 if (fetchers_.empty()) { |
239 CleanupTransientState(); | 250 CleanupTransientState(); |
240 FireGetCheckConnectionInfoCompleted(true); | 251 GetCheckConnectionInfoCompleted(true); |
241 } | 252 } |
242 } | 253 } |
243 } | 254 } |
244 | 255 |
245 void GaiaCookieManagerService::ExternalCcResultFetcher::Timeout() { | 256 void GaiaCookieManagerService::ExternalCcResultFetcher::Timeout() { |
246 CleanupTransientState(); | 257 CleanupTransientState(); |
247 FireGetCheckConnectionInfoCompleted(false); | 258 GetCheckConnectionInfoCompleted(false); |
248 } | 259 } |
249 | 260 |
250 void GaiaCookieManagerService::ExternalCcResultFetcher:: | 261 void GaiaCookieManagerService::ExternalCcResultFetcher:: |
251 CleanupTransientState() { | 262 CleanupTransientState() { |
252 timer_.Stop(); | 263 timer_.Stop(); |
253 gaia_auth_fetcher_.reset(); | 264 helper_->gaia_auth_fetcher_.reset(); |
254 | 265 |
255 for (URLToTokenAndFetcher::const_iterator it = fetchers_.begin(); | 266 for (URLToTokenAndFetcher::const_iterator it = fetchers_.begin(); |
256 it != fetchers_.end(); ++it) { | 267 it != fetchers_.end(); ++it) { |
257 delete it->second.second; | 268 delete it->second.second; |
258 } | 269 } |
259 fetchers_.clear(); | 270 fetchers_.clear(); |
260 } | 271 } |
261 | 272 |
262 void GaiaCookieManagerService::ExternalCcResultFetcher:: | 273 void GaiaCookieManagerService::ExternalCcResultFetcher:: |
263 FireGetCheckConnectionInfoCompleted(bool succeeded) { | 274 GetCheckConnectionInfoCompleted(bool succeeded) { |
264 base::TimeDelta time_to_check_connections = | 275 base::TimeDelta time_to_check_connections = |
265 base::Time::Now() - m_external_cc_result_start_time_; | 276 base::Time::Now() - m_external_cc_result_start_time_; |
266 signin_metrics::LogExternalCcResultFetches(succeeded, | 277 signin_metrics::LogExternalCcResultFetches(succeeded, |
267 time_to_check_connections); | 278 time_to_check_connections); |
268 FOR_EACH_OBSERVER(Observer, helper_->observer_list_, | 279 |
269 GetCheckConnectionInfoCompleted(succeeded)); | 280 helper_->external_cc_result_fetched_ = true; |
| 281 // Since the ExternalCCResultFetcher is only Started in place of calling |
| 282 // StartFetchingMergeSession, we can assume we need to call |
| 283 // StartFetchingMergeSession. If this assumption becomes invalid, a Callback |
| 284 // will need to be passed to Start() and Run() here. |
| 285 helper_->StartFetchingMergeSession(); |
270 } | 286 } |
271 | 287 |
272 GaiaCookieManagerService::GaiaCookieManagerService( | 288 GaiaCookieManagerService::GaiaCookieManagerService( |
273 OAuth2TokenService* token_service, | 289 OAuth2TokenService* token_service, |
274 const std::string& source, | 290 const std::string& source, |
275 SigninClient* signin_client) | 291 SigninClient* signin_client) |
276 : token_service_(token_service), | 292 : token_service_(token_service), |
277 signin_client_(signin_client), | 293 signin_client_(signin_client), |
278 external_cc_result_fetcher_(this), | 294 external_cc_result_fetcher_(this), |
279 gaia_auth_fetcher_backoff_(&kBackoffPolicy), | 295 gaia_auth_fetcher_backoff_(&kBackoffPolicy), |
280 gaia_auth_fetcher_retries_(0), | 296 gaia_auth_fetcher_retries_(0), |
281 source_(source) { | 297 source_(source), |
| 298 external_cc_result_fetched_(false) { |
282 } | 299 } |
283 | 300 |
284 GaiaCookieManagerService::~GaiaCookieManagerService() { | 301 GaiaCookieManagerService::~GaiaCookieManagerService() { |
285 CancelAll(); | 302 CancelAll(); |
286 DCHECK(requests_.empty()); | 303 DCHECK(requests_.empty()); |
287 } | 304 } |
288 | 305 |
289 void GaiaCookieManagerService::AddAccountToCookie( | 306 void GaiaCookieManagerService::AddAccountToCookie( |
290 const std::string& account_id) { | 307 const std::string& account_id) { |
291 DCHECK(!account_id.empty()); | 308 DCHECK(!account_id.empty()); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 void GaiaCookieManagerService::SignalComplete( | 397 void GaiaCookieManagerService::SignalComplete( |
381 const std::string& account_id, | 398 const std::string& account_id, |
382 const GoogleServiceAuthError& error) { | 399 const GoogleServiceAuthError& error) { |
383 // Its possible for the observer to delete |this| object. Don't access | 400 // Its possible for the observer to delete |this| object. Don't access |
384 // access any members after this calling the observer. This method should | 401 // access any members after this calling the observer. This method should |
385 // be the last call in any other method. | 402 // be the last call in any other method. |
386 FOR_EACH_OBSERVER(Observer, observer_list_, | 403 FOR_EACH_OBSERVER(Observer, observer_list_, |
387 OnAddAccountToCookieCompleted(account_id, error)); | 404 OnAddAccountToCookieCompleted(account_id, error)); |
388 } | 405 } |
389 | 406 |
390 void GaiaCookieManagerService::StartFetchingExternalCcResult() { | |
391 if (!external_cc_result_fetcher_.IsRunning()) | |
392 external_cc_result_fetcher_.Start(); | |
393 } | |
394 | |
395 void GaiaCookieManagerService::StartLogOutUrlFetch() { | 407 void GaiaCookieManagerService::StartLogOutUrlFetch() { |
396 DCHECK(requests_.front().request_type() == GaiaCookieRequestType::LOG_OUT); | 408 DCHECK(requests_.front().request_type() == GaiaCookieRequestType::LOG_OUT); |
397 VLOG(1) << "GaiaCookieManagerService::StartLogOutUrlFetch"; | 409 VLOG(1) << "GaiaCookieManagerService::StartLogOutUrlFetch"; |
398 GURL logout_url(GaiaUrls::GetInstance()->service_logout_url().Resolve( | 410 GURL logout_url(GaiaUrls::GetInstance()->service_logout_url().Resolve( |
399 base::StringPrintf("?source=%s", source_.c_str()))); | 411 base::StringPrintf("?source=%s", source_.c_str()))); |
400 net::URLFetcher* fetcher = | 412 net::URLFetcher* fetcher = |
401 net::URLFetcher::Create(logout_url, net::URLFetcher::GET, this); | 413 net::URLFetcher::Create(logout_url, net::URLFetcher::GET, this); |
402 fetcher->SetRequestContext(signin_client_->GetURLRequestContext()); | 414 fetcher->SetRequestContext(signin_client_->GetURLRequestContext()); |
403 fetcher->Start(); | 415 fetcher->Start(); |
404 } | 416 } |
405 | 417 |
406 void GaiaCookieManagerService::OnUbertokenSuccess( | 418 void GaiaCookieManagerService::OnUbertokenSuccess( |
407 const std::string& uber_token) { | 419 const std::string& uber_token) { |
| 420 DCHECK(requests_.front().request_type() == |
| 421 GaiaCookieRequestType::ADD_ACCOUNT); |
408 VLOG(1) << "GaiaCookieManagerService::OnUbertokenSuccess" | 422 VLOG(1) << "GaiaCookieManagerService::OnUbertokenSuccess" |
409 << " account=" << requests_.front().account_id(); | 423 << " account=" << requests_.front().account_id(); |
410 gaia_auth_fetcher_retries_ = 0; | 424 gaia_auth_fetcher_retries_ = 0; |
411 uber_token_ = uber_token; | 425 uber_token_ = uber_token; |
| 426 |
| 427 if (!external_cc_result_fetched_ && |
| 428 !external_cc_result_fetcher_.IsRunning()) { |
| 429 external_cc_result_fetcher_.Start(); |
| 430 return; |
| 431 } |
| 432 |
412 StartFetchingMergeSession(); | 433 StartFetchingMergeSession(); |
413 } | 434 } |
414 | 435 |
415 void GaiaCookieManagerService::OnUbertokenFailure( | 436 void GaiaCookieManagerService::OnUbertokenFailure( |
416 const GoogleServiceAuthError& error) { | 437 const GoogleServiceAuthError& error) { |
417 VLOG(1) << "Failed to retrieve ubertoken" | 438 VLOG(1) << "Failed to retrieve ubertoken" |
418 << " account=" << requests_.front().account_id() | 439 << " account=" << requests_.front().account_id() |
419 << " error=" << error.ToString(); | 440 << " error=" << error.ToString(); |
420 const std::string account_id = requests_.front().account_id(); | 441 const std::string account_id = requests_.front().account_id(); |
421 HandleNextRequest(); | 442 HandleNextRequest(); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
462 signin_client_->GetURLRequestContext())); | 483 signin_client_->GetURLRequestContext())); |
463 uber_token_fetcher_->StartFetchingToken(requests_.front().account_id()); | 484 uber_token_fetcher_->StartFetchingToken(requests_.front().account_id()); |
464 } | 485 } |
465 | 486 |
466 void GaiaCookieManagerService::StartFetchingMergeSession() { | 487 void GaiaCookieManagerService::StartFetchingMergeSession() { |
467 DCHECK(!uber_token_.empty()); | 488 DCHECK(!uber_token_.empty()); |
468 gaia_auth_fetcher_.reset( | 489 gaia_auth_fetcher_.reset( |
469 new GaiaAuthFetcher(this, source_, | 490 new GaiaAuthFetcher(this, source_, |
470 signin_client_->GetURLRequestContext())); | 491 signin_client_->GetURLRequestContext())); |
471 | 492 |
472 // It's possible that not all external checks have completed. | |
473 // GetExternalCcResult() returns results for those that have. | |
474 gaia_auth_fetcher_->StartMergeSession(uber_token_, | 493 gaia_auth_fetcher_->StartMergeSession(uber_token_, |
475 external_cc_result_fetcher_.GetExternalCcResult()); | 494 external_cc_result_fetcher_.GetExternalCcResult()); |
476 } | 495 } |
477 | 496 |
478 void GaiaCookieManagerService::OnURLFetchComplete( | 497 void GaiaCookieManagerService::OnURLFetchComplete( |
479 const net::URLFetcher* source) { | 498 const net::URLFetcher* source) { |
480 DCHECK(requests_.front().request_type() == GaiaCookieRequestType::LOG_OUT); | 499 DCHECK(requests_.front().request_type() == GaiaCookieRequestType::LOG_OUT); |
481 VLOG(1) << "GaiaCookieManagerService::OnURLFetchComplete"; | 500 VLOG(1) << "GaiaCookieManagerService::OnURLFetchComplete"; |
482 HandleNextRequest(); | 501 HandleNextRequest(); |
483 } | 502 } |
(...skipping 11 matching lines...) Expand all Loading... |
495 StartFetchingUbertoken(); | 514 StartFetchingUbertoken(); |
496 break; | 515 break; |
497 case GaiaCookieRequestType::LOG_OUT: | 516 case GaiaCookieRequestType::LOG_OUT: |
498 StartLogOutUrlFetch(); | 517 StartLogOutUrlFetch(); |
499 break; | 518 break; |
500 case GaiaCookieRequestType::LIST_ACCOUNTS: | 519 case GaiaCookieRequestType::LIST_ACCOUNTS: |
501 break; | 520 break; |
502 }; | 521 }; |
503 } | 522 } |
504 } | 523 } |
OLD | NEW |