| 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 |