Chromium Code Reviews| 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 <vector> | 8 #include <vector> |
| 8 | 9 |
| 9 #include "base/json/json_reader.h" | 10 #include "base/json/json_reader.h" |
| 10 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
| 11 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
| 12 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
| 13 #include "base/time/time.h" | 14 #include "base/time/time.h" |
| 14 #include "base/values.h" | 15 #include "base/values.h" |
| 15 #include "components/signin/core/browser/signin_metrics.h" | 16 #include "components/signin/core/browser/signin_metrics.h" |
| 16 #include "google_apis/gaia/gaia_auth_fetcher.h" | 17 #include "google_apis/gaia/gaia_auth_fetcher.h" |
| 17 #include "google_apis/gaia/gaia_constants.h" | 18 #include "google_apis/gaia/gaia_constants.h" |
| 18 #include "google_apis/gaia/gaia_urls.h" | 19 #include "google_apis/gaia/gaia_urls.h" |
| 19 #include "google_apis/gaia/oauth2_token_service.h" | 20 #include "google_apis/gaia/oauth2_token_service.h" |
| 20 #include "net/base/load_flags.h" | 21 #include "net/base/load_flags.h" |
| 21 #include "net/http/http_status_code.h" | 22 #include "net/http/http_status_code.h" |
| 22 #include "net/url_request/url_fetcher.h" | 23 #include "net/url_request/url_fetcher.h" |
| 23 #include "net/url_request/url_fetcher_delegate.h" | 24 #include "net/url_request/url_fetcher_delegate.h" |
| 24 | 25 |
| 26 GaiaCookieManagerService::GaiaCookieRequest::GaiaCookieRequest( | |
| 27 GaiaCookieRequestType request_type, | |
| 28 const std::string& account_id, | |
| 29 const GaiaCookieManagerService::ListAccountsCallback& | |
| 30 list_accounts_callback) | |
| 31 : request_type_(request_type), | |
| 32 account_id_(account_id), | |
| 33 list_accounts_callback_(list_accounts_callback) {} | |
| 34 | |
| 35 GaiaCookieManagerService::GaiaCookieRequest::~GaiaCookieRequest() { | |
| 36 } | |
| 37 | |
| 38 // static | |
| 39 GaiaCookieManagerService::GaiaCookieRequest | |
| 40 GaiaCookieManagerService::GaiaCookieRequest::CreateAddAccountRequest( | |
| 41 const std::string& account_id) { | |
| 42 return GaiaCookieManagerService::GaiaCookieRequest( | |
| 43 GaiaCookieManagerService::GaiaCookieRequestType::ADD_ACCOUNT, | |
| 44 account_id, | |
| 45 GaiaCookieManagerService::ListAccountsCallback()); | |
| 46 } | |
| 47 | |
| 48 // static | |
| 49 GaiaCookieManagerService::GaiaCookieRequest | |
| 50 GaiaCookieManagerService::GaiaCookieRequest::CreateLogOutRequest() { | |
| 51 return GaiaCookieManagerService::GaiaCookieRequest( | |
| 52 GaiaCookieManagerService::GaiaCookieRequestType::LOG_OUT, | |
| 53 std::string(), | |
| 54 GaiaCookieManagerService::ListAccountsCallback()); | |
| 55 } | |
| 56 | |
| 57 GaiaCookieManagerService::GaiaCookieRequest | |
| 58 GaiaCookieManagerService::GaiaCookieRequest::CreateListAccountsRequest( | |
| 59 const GaiaCookieManagerService::ListAccountsCallback& | |
| 60 list_accounts_callback) { | |
| 61 return GaiaCookieManagerService::GaiaCookieRequest( | |
| 62 GaiaCookieManagerService::GaiaCookieRequestType::LIST_ACCOUNTS, | |
| 63 std::string(), | |
| 64 list_accounts_callback); | |
| 65 } | |
| 66 | |
| 25 GaiaCookieManagerService::ExternalCcResultFetcher::ExternalCcResultFetcher( | 67 GaiaCookieManagerService::ExternalCcResultFetcher::ExternalCcResultFetcher( |
| 26 GaiaCookieManagerService* helper) | 68 GaiaCookieManagerService* helper) |
| 27 : helper_(helper) { | 69 : helper_(helper) { |
| 28 DCHECK(helper_); | 70 DCHECK(helper_); |
| 29 } | 71 } |
| 30 | 72 |
| 31 GaiaCookieManagerService::ExternalCcResultFetcher::~ExternalCcResultFetcher() { | 73 GaiaCookieManagerService::ExternalCcResultFetcher::~ExternalCcResultFetcher() { |
| 32 CleanupTransientState(); | 74 CleanupTransientState(); |
| 33 } | 75 } |
| 34 | 76 |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 185 const std::string& source, | 227 const std::string& source, |
| 186 SigninClient* signin_client) | 228 SigninClient* signin_client) |
| 187 : token_service_(token_service), | 229 : token_service_(token_service), |
| 188 signin_client_(signin_client), | 230 signin_client_(signin_client), |
| 189 external_cc_result_fetcher_(this), | 231 external_cc_result_fetcher_(this), |
| 190 source_(source) { | 232 source_(source) { |
| 191 } | 233 } |
| 192 | 234 |
| 193 GaiaCookieManagerService::~GaiaCookieManagerService() { | 235 GaiaCookieManagerService::~GaiaCookieManagerService() { |
| 194 CancelAll(); | 236 CancelAll(); |
| 195 DCHECK(accounts_.empty()); | 237 DCHECK(requests_.empty()); |
| 196 } | 238 } |
| 197 | 239 |
| 198 void GaiaCookieManagerService::AddAccountToCookie( | 240 void GaiaCookieManagerService::AddAccountToCookie( |
| 199 const std::string& account_id) { | 241 const std::string& account_id) { |
| 200 DCHECK(!account_id.empty()); | 242 DCHECK(!account_id.empty()); |
| 201 VLOG(1) << "GaiaCookieManagerService::AddAccountToCookie: " << account_id; | 243 VLOG(1) << "GaiaCookieManagerService::AddAccountToCookie: " << account_id; |
| 202 accounts_.push_back(account_id); | 244 requests_.push_back(GaiaCookieRequest::CreateAddAccountRequest(account_id)); |
| 203 if (accounts_.size() == 1) | 245 if (requests_.size() == 1) |
| 204 StartFetching(); | 246 StartFetchingUbertoken(); |
| 247 } | |
| 248 | |
| 249 void GaiaCookieManagerService::ListAccounts( | |
| 250 const ListAccountsCallback& callback) { | |
| 251 // Not implemented yet. | |
| 252 NOTREACHED(); | |
| 253 | |
| 254 // TODO(mlerman): Once this service listens to all GAIA cookie changes, cache | |
| 255 // the results of ListAccounts, and return them here if the GAIA cookie | |
| 256 // hasn't changed since the last call. | |
| 257 | |
| 258 // If there's a GAIA call being executed, wait for it to complete. If it was | |
| 259 // another /ListAccounts then we'll use the results it caches. | |
| 260 if (gaia_auth_fetcher_) | |
| 261 return; | |
| 262 | |
| 263 VLOG(1) << "GaiaCookieManagerService::ListAccounts"; | |
| 264 gaia_auth_fetcher_.reset( | |
| 265 new GaiaAuthFetcher(this, source_, | |
| 266 signin_client_->GetURLRequestContext())); | |
| 267 gaia_auth_fetcher_->StartListAccounts(); | |
| 268 } | |
| 269 | |
| 270 void GaiaCookieManagerService::LogOutAllAccounts() { | |
| 271 VLOG(1) << "GaiaCookieManagerService::LogOutAllAccounts"; | |
| 272 | |
| 273 bool log_out_queued = false; | |
| 274 if (!requests_.empty()) { | |
| 275 // Track requests to keep; all other unstarted requests will be removed. | |
| 276 std::vector<GaiaCookieRequest> requests_to_keep; | |
| 277 | |
| 278 // Check all pending, non-executing requests. | |
| 279 for (auto it = requests_.begin() + 1; it != requests_.end(); ++it) { | |
| 280 if (it->request_type() == GaiaCookieRequestType::ADD_ACCOUNT) { | |
| 281 // We have a pending log in request for an account followed by | |
| 282 // a signout. | |
| 283 GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED); | |
| 284 SignalComplete(it->account_id(), error); | |
| 285 } | |
| 286 | |
| 287 // Keep all requests except for ADD_ACCOUNTS. | |
| 288 if (it->request_type() != GaiaCookieRequestType::ADD_ACCOUNT) | |
| 289 requests_to_keep.push_back(*it); | |
| 290 | |
| 291 // Verify a LOG_OUT isn't already queued. | |
| 292 if (it->request_type() == GaiaCookieRequestType::LOG_OUT) | |
| 293 log_out_queued = true; | |
| 294 } | |
| 295 | |
| 296 // Verify a LOG_OUT isn't currently being processed. | |
| 297 if (requests_.front().request_type() == GaiaCookieRequestType::LOG_OUT) | |
| 298 log_out_queued = true; | |
| 299 | |
| 300 // Remove all put the executing request. Re-add all requests being kept. | |
|
Roger Tawa OOO till Jul 10th
2015/04/01 16:50:38
put --> but
Mike Lerman
2015/04/02 12:43:14
Done.
| |
| 301 if (requests_.size() > 1) { | |
| 302 requests_.erase(requests_.begin() + 1, requests_.end()); | |
| 303 requests_.insert( | |
| 304 requests_.end(), requests_to_keep.begin(), requests_to_keep.end()); | |
| 305 } | |
| 306 } | |
| 307 | |
| 308 if (!log_out_queued) { | |
| 309 requests_.push_back(GaiaCookieRequest::CreateLogOutRequest()); | |
| 310 if (requests_.size() == 1) | |
| 311 StartLogOutUrlFetch(); | |
| 312 } | |
| 205 } | 313 } |
| 206 | 314 |
| 207 void GaiaCookieManagerService::AddObserver(Observer* observer) { | 315 void GaiaCookieManagerService::AddObserver(Observer* observer) { |
| 208 observer_list_.AddObserver(observer); | 316 observer_list_.AddObserver(observer); |
| 209 } | 317 } |
| 210 | 318 |
| 211 void GaiaCookieManagerService::RemoveObserver(Observer* observer) { | 319 void GaiaCookieManagerService::RemoveObserver(Observer* observer) { |
| 212 observer_list_.RemoveObserver(observer); | 320 observer_list_.RemoveObserver(observer); |
| 213 } | 321 } |
| 214 | 322 |
| 215 void GaiaCookieManagerService::CancelAll() { | 323 void GaiaCookieManagerService::CancelAll() { |
| 216 VLOG(1) << "GaiaCookieManagerService::CancelAll"; | 324 VLOG(1) << "GaiaCookieManagerService::CancelAll"; |
| 217 gaia_auth_fetcher_.reset(); | 325 gaia_auth_fetcher_.reset(); |
| 218 uber_token_fetcher_.reset(); | 326 uber_token_fetcher_.reset(); |
| 219 accounts_.clear(); | 327 requests_.clear(); |
| 220 } | |
| 221 | |
| 222 void GaiaCookieManagerService::LogOut( | |
| 223 const std::string& account_id, | |
| 224 const std::vector<std::string>& accounts) { | |
| 225 DCHECK(!account_id.empty()); | |
| 226 VLOG(1) << "GaiaCookieManagerService::LogOut: " << account_id | |
| 227 << " accounts=" << accounts.size(); | |
| 228 LogOutInternal(account_id, accounts); | |
| 229 } | |
| 230 | |
| 231 void GaiaCookieManagerService::LogOutInternal( | |
| 232 const std::string& account_id, | |
| 233 const std::vector<std::string>& accounts) { | |
| 234 bool pending = !accounts_.empty(); | |
| 235 | |
| 236 if (pending) { | |
| 237 for (std::deque<std::string>::const_iterator it = accounts_.begin() + 1; | |
| 238 it != accounts_.end(); it++) { | |
| 239 if (!it->empty() && | |
| 240 (std::find(accounts.begin(), accounts.end(), *it) == accounts.end() || | |
| 241 *it == account_id)) { | |
| 242 // We have a pending log in request for an account followed by | |
| 243 // a signout. | |
| 244 GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED); | |
| 245 SignalComplete(*it, error); | |
| 246 } | |
| 247 } | |
| 248 | |
| 249 // Remove every thing in the work list besides the one that is running. | |
| 250 accounts_.resize(1); | |
| 251 } | |
| 252 | |
| 253 // Signal a logout to be the next thing to do unless the pending | |
| 254 // action is already a logout. | |
| 255 if (!pending || !accounts_.front().empty()) | |
| 256 accounts_.push_back(""); | |
| 257 | |
| 258 for (std::vector<std::string>::const_iterator it = accounts.begin(); | |
| 259 it != accounts.end(); it++) { | |
| 260 if (*it != account_id) { | |
| 261 DCHECK(!it->empty()); | |
| 262 accounts_.push_back(*it); | |
| 263 } | |
| 264 } | |
| 265 | |
| 266 if (!pending) | |
| 267 StartLogOutUrlFetch(); | |
| 268 } | |
| 269 | |
| 270 void GaiaCookieManagerService::LogOutAllAccounts() { | |
| 271 VLOG(1) << "GaiaCookieManagerService::LogOutAllAccounts"; | |
| 272 LogOutInternal("", std::vector<std::string>()); | |
| 273 } | 328 } |
| 274 | 329 |
| 275 void GaiaCookieManagerService::SignalComplete( | 330 void GaiaCookieManagerService::SignalComplete( |
| 276 const std::string& account_id, | 331 const std::string& account_id, |
| 277 const GoogleServiceAuthError& error) { | 332 const GoogleServiceAuthError& error) { |
| 278 // Its possible for the observer to delete |this| object. Don't access | 333 // Its possible for the observer to delete |this| object. Don't access |
| 279 // access any members after this calling the observer. This method should | 334 // access any members after this calling the observer. This method should |
| 280 // be the last call in any other method. | 335 // be the last call in any other method. |
| 281 FOR_EACH_OBSERVER(Observer, observer_list_, | 336 FOR_EACH_OBSERVER(Observer, observer_list_, |
| 282 OnAddAccountToCookieCompleted(account_id, error)); | 337 OnAddAccountToCookieCompleted(account_id, error)); |
| 283 } | 338 } |
| 284 | 339 |
| 285 void GaiaCookieManagerService::StartFetchingExternalCcResult() { | 340 void GaiaCookieManagerService::StartFetchingExternalCcResult() { |
| 286 if (!external_cc_result_fetcher_.IsRunning()) | 341 if (!external_cc_result_fetcher_.IsRunning()) |
| 287 external_cc_result_fetcher_.Start(); | 342 external_cc_result_fetcher_.Start(); |
| 288 } | 343 } |
| 289 | 344 |
| 290 void GaiaCookieManagerService::StartLogOutUrlFetch() { | 345 void GaiaCookieManagerService::StartLogOutUrlFetch() { |
| 291 DCHECK(accounts_.front().empty()); | 346 DCHECK(requests_.front().request_type() == GaiaCookieRequestType::LOG_OUT); |
| 292 VLOG(1) << "GaiaCookieManagerService::StartLogOutUrlFetch"; | 347 VLOG(1) << "GaiaCookieManagerService::StartLogOutUrlFetch"; |
| 293 GURL logout_url(GaiaUrls::GetInstance()->service_logout_url().Resolve( | 348 GURL logout_url(GaiaUrls::GetInstance()->service_logout_url().Resolve( |
| 294 base::StringPrintf("?source=%s", source_.c_str()))); | 349 base::StringPrintf("?source=%s", source_.c_str()))); |
| 295 net::URLFetcher* fetcher = | 350 net::URLFetcher* fetcher = |
| 296 net::URLFetcher::Create(logout_url, net::URLFetcher::GET, this); | 351 net::URLFetcher::Create(logout_url, net::URLFetcher::GET, this); |
| 297 fetcher->SetRequestContext(signin_client_->GetURLRequestContext()); | 352 fetcher->SetRequestContext(signin_client_->GetURLRequestContext()); |
| 298 fetcher->Start(); | 353 fetcher->Start(); |
| 299 } | 354 } |
| 300 | 355 |
| 301 void GaiaCookieManagerService::OnUbertokenSuccess( | 356 void GaiaCookieManagerService::OnUbertokenSuccess( |
| 302 const std::string& uber_token) { | 357 const std::string& uber_token) { |
| 303 VLOG(1) << "GaiaCookieManagerService::OnUbertokenSuccess" | 358 VLOG(1) << "GaiaCookieManagerService::OnUbertokenSuccess" |
| 304 << " account=" << accounts_.front(); | 359 << " account=" << requests_.front().account_id(); |
| 305 gaia_auth_fetcher_.reset( | 360 gaia_auth_fetcher_.reset( |
| 306 new GaiaAuthFetcher(this, source_, | 361 new GaiaAuthFetcher(this, source_, |
| 307 signin_client_->GetURLRequestContext())); | 362 signin_client_->GetURLRequestContext())); |
| 308 | 363 |
| 309 // It's possible that not all external checks have completed. | 364 // It's possible that not all external checks have completed. |
| 310 // GetExternalCcResult() returns results for those that have. | 365 // GetExternalCcResult() returns results for those that have. |
| 311 gaia_auth_fetcher_->StartMergeSession(uber_token, | 366 gaia_auth_fetcher_->StartMergeSession(uber_token, |
| 312 external_cc_result_fetcher_.GetExternalCcResult()); | 367 external_cc_result_fetcher_.GetExternalCcResult()); |
| 313 } | 368 } |
| 314 | 369 |
| 315 void GaiaCookieManagerService::OnUbertokenFailure( | 370 void GaiaCookieManagerService::OnUbertokenFailure( |
| 316 const GoogleServiceAuthError& error) { | 371 const GoogleServiceAuthError& error) { |
| 317 VLOG(1) << "Failed to retrieve ubertoken" | 372 VLOG(1) << "Failed to retrieve ubertoken" |
| 318 << " account=" << accounts_.front() << " error=" << error.ToString(); | 373 << " account=" << requests_.front().account_id() |
| 319 const std::string account_id = accounts_.front(); | 374 << " error=" << error.ToString(); |
| 320 HandleNextAccount(); | 375 const std::string account_id = requests_.front().account_id(); |
| 376 HandleNextRequest(); | |
| 321 SignalComplete(account_id, error); | 377 SignalComplete(account_id, error); |
| 322 } | 378 } |
| 323 | 379 |
| 324 void GaiaCookieManagerService::OnMergeSessionSuccess(const std::string& data) { | 380 void GaiaCookieManagerService::OnMergeSessionSuccess(const std::string& data) { |
| 325 VLOG(1) << "MergeSession successful account=" << accounts_.front(); | 381 VLOG(1) << "MergeSession successful account=" |
| 326 const std::string account_id = accounts_.front(); | 382 << requests_.front().account_id(); |
| 327 HandleNextAccount(); | 383 const std::string account_id = requests_.front().account_id(); |
| 384 HandleNextRequest(); | |
| 328 SignalComplete(account_id, GoogleServiceAuthError::AuthErrorNone()); | 385 SignalComplete(account_id, GoogleServiceAuthError::AuthErrorNone()); |
| 329 } | 386 } |
| 330 | 387 |
| 331 void GaiaCookieManagerService::OnMergeSessionFailure( | 388 void GaiaCookieManagerService::OnMergeSessionFailure( |
| 332 const GoogleServiceAuthError& error) { | 389 const GoogleServiceAuthError& error) { |
| 333 VLOG(1) << "Failed MergeSession" | 390 VLOG(1) << "Failed MergeSession" |
| 334 << " account=" << accounts_.front() << " error=" << error.ToString(); | 391 << " account=" << requests_.front().account_id() |
| 335 const std::string account_id = accounts_.front(); | 392 << " error=" << error.ToString(); |
| 336 HandleNextAccount(); | 393 const std::string account_id = requests_.front().account_id(); |
| 394 HandleNextRequest(); | |
| 337 SignalComplete(account_id, error); | 395 SignalComplete(account_id, error); |
| 338 } | 396 } |
| 339 | 397 |
| 340 void GaiaCookieManagerService::StartFetching() { | 398 void GaiaCookieManagerService::StartFetchingUbertoken() { |
| 341 VLOG(1) << "GaiaCookieManagerService::StartFetching account_id=" | 399 VLOG(1) << "GaiaCookieManagerService::StartFetching account_id=" |
| 342 << accounts_.front(); | 400 << requests_.front().account_id(); |
| 343 uber_token_fetcher_.reset( | 401 uber_token_fetcher_.reset( |
| 344 new UbertokenFetcher(token_service_, this, source_, | 402 new UbertokenFetcher(token_service_, this, source_, |
| 345 signin_client_->GetURLRequestContext())); | 403 signin_client_->GetURLRequestContext())); |
| 346 uber_token_fetcher_->StartFetchingToken(accounts_.front()); | 404 uber_token_fetcher_->StartFetchingToken(requests_.front().account_id()); |
| 347 } | 405 } |
| 348 | 406 |
| 349 void GaiaCookieManagerService::OnURLFetchComplete( | 407 void GaiaCookieManagerService::OnURLFetchComplete( |
| 350 const net::URLFetcher* source) { | 408 const net::URLFetcher* source) { |
| 351 DCHECK(accounts_.front().empty()); | 409 DCHECK(requests_.front().request_type() == GaiaCookieRequestType::LOG_OUT); |
| 352 VLOG(1) << "GaiaCookieManagerService::OnURLFetchComplete"; | 410 VLOG(1) << "GaiaCookieManagerService::OnURLFetchComplete"; |
| 353 HandleNextAccount(); | 411 HandleNextRequest(); |
| 354 } | 412 } |
| 355 | 413 |
| 356 void GaiaCookieManagerService::HandleNextAccount() { | 414 void GaiaCookieManagerService::HandleNextRequest() { |
| 357 VLOG(1) << "GaiaCookieManagerService::HandleNextAccount"; | 415 VLOG(1) << "GaiaCookieManagerService::HandleNextRequest"; |
| 358 accounts_.pop_front(); | 416 requests_.pop_front(); |
| 359 gaia_auth_fetcher_.reset(); | 417 gaia_auth_fetcher_.reset(); |
| 360 if (accounts_.empty()) { | 418 if (requests_.empty()) { |
| 361 VLOG(1) << "GaiaCookieManagerService::HandleNextAccount: no more"; | 419 VLOG(1) << "GaiaCookieManagerService::HandleNextRequest: no more"; |
| 362 uber_token_fetcher_.reset(); | 420 uber_token_fetcher_.reset(); |
| 363 } else { | 421 } else { |
| 364 if (accounts_.front().empty()) { | 422 switch (requests_.front().request_type()) { |
| 365 StartLogOutUrlFetch(); | 423 case GaiaCookieRequestType::ADD_ACCOUNT: |
| 366 } else { | 424 StartFetchingUbertoken(); |
| 367 StartFetching(); | 425 break; |
| 368 } | 426 case GaiaCookieRequestType::LOG_OUT: |
| 427 StartLogOutUrlFetch(); | |
| 428 break; | |
| 429 case GaiaCookieRequestType::LIST_ACCOUNTS: | |
| 430 break; | |
| 431 }; | |
| 369 } | 432 } |
| 370 } | 433 } |
| OLD | NEW |