| Index: components/signin/core/browser/gaia_cookie_manager_service.cc
|
| diff --git a/components/signin/core/browser/gaia_cookie_manager_service.cc b/components/signin/core/browser/gaia_cookie_manager_service.cc
|
| index 28f4c88c06ffa34f0cf3b72dfb0891e890d44e2a..36ba75a96fa725b20ce0d281a7c88f1872f328e0 100644
|
| --- a/components/signin/core/browser/gaia_cookie_manager_service.cc
|
| +++ b/components/signin/core/browser/gaia_cookie_manager_service.cc
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "components/signin/core/browser/gaia_cookie_manager_service.h"
|
|
|
| +#include <queue>
|
| #include <vector>
|
|
|
| #include "base/json/json_reader.h"
|
| @@ -22,7 +23,6 @@
|
| #include "net/url_request/url_fetcher.h"
|
| #include "net/url_request/url_fetcher_delegate.h"
|
|
|
| -
|
| namespace {
|
|
|
| // In case of an error while fetching using the GaiaAuthFetcher, retry with
|
| @@ -61,8 +61,56 @@ bool IsTransientError(const GoogleServiceAuthError& error) {
|
| error.state() == GoogleServiceAuthError::REQUEST_CANCELED;
|
| }
|
|
|
| +enum GaiaCookieRequestType {
|
| + ADD_ACCOUNT,
|
| + LOG_OUT_ALL_ACCOUNTS,
|
| + LOG_OUT_ONE_ACCOUNT,
|
| + LIST_ACCOUNTS
|
| +};
|
| +
|
| } // namespace
|
|
|
| +GaiaCookieManagerService::GaiaCookieRequest::GaiaCookieRequest(
|
| + GaiaCookieRequestType request_type,
|
| + const std::string& account_id,
|
| + const GaiaCookieManagerService::ListAccountsCallback&
|
| + list_accounts_callback)
|
| + : request_type_(request_type),
|
| + account_id_(account_id),
|
| + list_accounts_callback_(list_accounts_callback) {}
|
| +
|
| +GaiaCookieManagerService::GaiaCookieRequest::~GaiaCookieRequest() {
|
| +}
|
| +
|
| +// static
|
| +GaiaCookieManagerService::GaiaCookieRequest
|
| +GaiaCookieManagerService::GaiaCookieRequest::CreateAddAccountRequest(
|
| + const std::string& account_id) {
|
| + return GaiaCookieManagerService::GaiaCookieRequest(
|
| + GaiaCookieManagerService::GaiaCookieRequestType::ADD_ACCOUNT,
|
| + account_id,
|
| + GaiaCookieManagerService::ListAccountsCallback());
|
| +}
|
| +
|
| +// static
|
| +GaiaCookieManagerService::GaiaCookieRequest
|
| +GaiaCookieManagerService::GaiaCookieRequest::CreateLogOutRequest() {
|
| + return GaiaCookieManagerService::GaiaCookieRequest(
|
| + GaiaCookieManagerService::GaiaCookieRequestType::LOG_OUT,
|
| + std::string(),
|
| + GaiaCookieManagerService::ListAccountsCallback());
|
| +}
|
| +
|
| +GaiaCookieManagerService::GaiaCookieRequest
|
| +GaiaCookieManagerService::GaiaCookieRequest::CreateListAccountsRequest(
|
| + const GaiaCookieManagerService::ListAccountsCallback&
|
| + list_accounts_callback) {
|
| + return GaiaCookieManagerService::GaiaCookieRequest(
|
| + GaiaCookieManagerService::GaiaCookieRequestType::LIST_ACCOUNTS,
|
| + std::string(),
|
| + list_accounts_callback);
|
| +}
|
| +
|
| GaiaCookieManagerService::ExternalCcResultFetcher::ExternalCcResultFetcher(
|
| GaiaCookieManagerService* helper)
|
| : helper_(helper) {
|
| @@ -235,85 +283,98 @@ GaiaCookieManagerService::GaiaCookieManagerService(
|
|
|
| GaiaCookieManagerService::~GaiaCookieManagerService() {
|
| CancelAll();
|
| - DCHECK(accounts_.empty());
|
| + DCHECK(requests_.empty());
|
| }
|
|
|
| void GaiaCookieManagerService::AddAccountToCookie(
|
| const std::string& account_id) {
|
| DCHECK(!account_id.empty());
|
| VLOG(1) << "GaiaCookieManagerService::AddAccountToCookie: " << account_id;
|
| - accounts_.push_back(account_id);
|
| - if (accounts_.size() == 1)
|
| - StartFetching();
|
| + requests_.push_back(GaiaCookieRequest::CreateAddAccountRequest(account_id));
|
| + if (requests_.size() == 1)
|
| + StartFetchingUbertoken();
|
| }
|
|
|
| -void GaiaCookieManagerService::AddObserver(Observer* observer) {
|
| - observer_list_.AddObserver(observer);
|
| -}
|
| +void GaiaCookieManagerService::ListAccounts(
|
| + const ListAccountsCallback& callback) {
|
| + // Not implemented yet.
|
| + NOTREACHED();
|
|
|
| -void GaiaCookieManagerService::RemoveObserver(Observer* observer) {
|
| - observer_list_.RemoveObserver(observer);
|
| -}
|
| + // TODO(mlerman): Once this service listens to all GAIA cookie changes, cache
|
| + // the results of ListAccounts, and return them here if the GAIA cookie
|
| + // hasn't changed since the last call.
|
|
|
| -void GaiaCookieManagerService::CancelAll() {
|
| - VLOG(1) << "GaiaCookieManagerService::CancelAll";
|
| - gaia_auth_fetcher_.reset();
|
| - uber_token_fetcher_.reset();
|
| - accounts_.clear();
|
| - gaia_auth_fetcher_timer_.Stop();
|
| -}
|
| + // If there's a GAIA call being executed, wait for it to complete. If it was
|
| + // another /ListAccounts then we'll use the results it caches.
|
| + if (gaia_auth_fetcher_)
|
| + return;
|
|
|
| -void GaiaCookieManagerService::LogOut(
|
| - const std::string& account_id,
|
| - const std::vector<std::string>& accounts) {
|
| - DCHECK(!account_id.empty());
|
| - VLOG(1) << "GaiaCookieManagerService::LogOut: " << account_id
|
| - << " accounts=" << accounts.size();
|
| - LogOutInternal(account_id, accounts);
|
| + VLOG(1) << "GaiaCookieManagerService::ListAccounts";
|
| + gaia_auth_fetcher_.reset(
|
| + new GaiaAuthFetcher(this, source_,
|
| + signin_client_->GetURLRequestContext()));
|
| + gaia_auth_fetcher_->StartListAccounts();
|
| }
|
|
|
| -void GaiaCookieManagerService::LogOutInternal(
|
| - const std::string& account_id,
|
| - const std::vector<std::string>& accounts) {
|
| - bool pending = !accounts_.empty();
|
| -
|
| - if (pending) {
|
| - for (std::deque<std::string>::const_iterator it = accounts_.begin() + 1;
|
| - it != accounts_.end(); it++) {
|
| - if (!it->empty() &&
|
| - (std::find(accounts.begin(), accounts.end(), *it) == accounts.end() ||
|
| - *it == account_id)) {
|
| +void GaiaCookieManagerService::LogOutAllAccounts() {
|
| + VLOG(1) << "GaiaCookieManagerService::LogOutAllAccounts";
|
| +
|
| + bool log_out_queued = false;
|
| + if (!requests_.empty()) {
|
| + // Track requests to keep; all other unstarted requests will be removed.
|
| + std::vector<GaiaCookieRequest> requests_to_keep;
|
| +
|
| + // Check all pending, non-executing requests.
|
| + for (auto it = requests_.begin() + 1; it != requests_.end(); ++it) {
|
| + if (it->request_type() == GaiaCookieRequestType::ADD_ACCOUNT) {
|
| // We have a pending log in request for an account followed by
|
| // a signout.
|
| GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED);
|
| - SignalComplete(*it, error);
|
| + SignalComplete(it->account_id(), error);
|
| }
|
| - }
|
|
|
| - // Remove every thing in the work list besides the one that is running.
|
| - accounts_.resize(1);
|
| - }
|
| + // Keep all requests except for ADD_ACCOUNTS.
|
| + if (it->request_type() != GaiaCookieRequestType::ADD_ACCOUNT)
|
| + requests_to_keep.push_back(*it);
|
|
|
| - // Signal a logout to be the next thing to do unless the pending
|
| - // action is already a logout.
|
| - if (!pending || !accounts_.front().empty())
|
| - accounts_.push_back("");
|
| + // Verify a LOG_OUT isn't already queued.
|
| + if (it->request_type() == GaiaCookieRequestType::LOG_OUT)
|
| + log_out_queued = true;
|
| + }
|
| +
|
| + // Verify a LOG_OUT isn't currently being processed.
|
| + if (requests_.front().request_type() == GaiaCookieRequestType::LOG_OUT)
|
| + log_out_queued = true;
|
|
|
| - for (std::vector<std::string>::const_iterator it = accounts.begin();
|
| - it != accounts.end(); it++) {
|
| - if (*it != account_id) {
|
| - DCHECK(!it->empty());
|
| - accounts_.push_back(*it);
|
| + // Remove all but the executing request. Re-add all requests being kept.
|
| + if (requests_.size() > 1) {
|
| + requests_.erase(requests_.begin() + 1, requests_.end());
|
| + requests_.insert(
|
| + requests_.end(), requests_to_keep.begin(), requests_to_keep.end());
|
| }
|
| }
|
|
|
| - if (!pending)
|
| - StartLogOutUrlFetch();
|
| + if (!log_out_queued) {
|
| + requests_.push_back(GaiaCookieRequest::CreateLogOutRequest());
|
| + if (requests_.size() == 1)
|
| + StartLogOutUrlFetch();
|
| + }
|
| }
|
|
|
| -void GaiaCookieManagerService::LogOutAllAccounts() {
|
| - VLOG(1) << "GaiaCookieManagerService::LogOutAllAccounts";
|
| - LogOutInternal("", std::vector<std::string>());
|
| +void GaiaCookieManagerService::AddObserver(Observer* observer) {
|
| + observer_list_.AddObserver(observer);
|
| +}
|
| +
|
| +void GaiaCookieManagerService::RemoveObserver(Observer* observer) {
|
| + observer_list_.RemoveObserver(observer);
|
| +}
|
| +
|
| +void GaiaCookieManagerService::CancelAll() {
|
| + VLOG(1) << "GaiaCookieManagerService::CancelAll";
|
| + gaia_auth_fetcher_.reset();
|
| + uber_token_fetcher_.reset();
|
| + requests_.clear();
|
| + gaia_auth_fetcher_timer_.Stop();
|
| }
|
|
|
| void GaiaCookieManagerService::SignalComplete(
|
| @@ -332,7 +393,7 @@ void GaiaCookieManagerService::StartFetchingExternalCcResult() {
|
| }
|
|
|
| void GaiaCookieManagerService::StartLogOutUrlFetch() {
|
| - DCHECK(accounts_.front().empty());
|
| + DCHECK(requests_.front().request_type() == GaiaCookieRequestType::LOG_OUT);
|
| VLOG(1) << "GaiaCookieManagerService::StartLogOutUrlFetch";
|
| GURL logout_url(GaiaUrls::GetInstance()->service_logout_url().Resolve(
|
| base::StringPrintf("?source=%s", source_.c_str())));
|
| @@ -345,7 +406,7 @@ void GaiaCookieManagerService::StartLogOutUrlFetch() {
|
| void GaiaCookieManagerService::OnUbertokenSuccess(
|
| const std::string& uber_token) {
|
| VLOG(1) << "GaiaCookieManagerService::OnUbertokenSuccess"
|
| - << " account=" << accounts_.front();
|
| + << " account=" << requests_.front().account_id();
|
| gaia_auth_fetcher_retries_ = 0;
|
| uber_token_ = uber_token;
|
| StartFetchingMergeSession();
|
| @@ -354,16 +415,18 @@ void GaiaCookieManagerService::OnUbertokenSuccess(
|
| void GaiaCookieManagerService::OnUbertokenFailure(
|
| const GoogleServiceAuthError& error) {
|
| VLOG(1) << "Failed to retrieve ubertoken"
|
| - << " account=" << accounts_.front() << " error=" << error.ToString();
|
| - const std::string account_id = accounts_.front();
|
| - HandleNextAccount();
|
| + << " account=" << requests_.front().account_id()
|
| + << " error=" << error.ToString();
|
| + const std::string account_id = requests_.front().account_id();
|
| + HandleNextRequest();
|
| SignalComplete(account_id, error);
|
| }
|
|
|
| void GaiaCookieManagerService::OnMergeSessionSuccess(const std::string& data) {
|
| - VLOG(1) << "MergeSession successful account=" << accounts_.front();
|
| - const std::string account_id = accounts_.front();
|
| - HandleNextAccount();
|
| + VLOG(1) << "MergeSession successful account="
|
| + << requests_.front().account_id();
|
| + const std::string account_id = requests_.front().account_id();
|
| + HandleNextRequest();
|
| SignalComplete(account_id, GoogleServiceAuthError::AuthErrorNone());
|
|
|
| gaia_auth_fetcher_backoff_.InformOfRequest(true);
|
| @@ -373,8 +436,8 @@ void GaiaCookieManagerService::OnMergeSessionSuccess(const std::string& data) {
|
| void GaiaCookieManagerService::OnMergeSessionFailure(
|
| const GoogleServiceAuthError& error) {
|
| VLOG(1) << "Failed MergeSession"
|
| - << " account=" << accounts_.front() << " error=" << error.ToString()
|
| - << " on retry=" << gaia_auth_fetcher_retries_;
|
| + << " account=" << requests_.front().account_id()
|
| + << " error=" << error.ToString();
|
|
|
| if (++gaia_auth_fetcher_retries_ < kMaxGaiaAuthFetcherRetries &&
|
| IsTransientError(error)) {
|
| @@ -386,18 +449,18 @@ void GaiaCookieManagerService::OnMergeSessionFailure(
|
| }
|
|
|
| uber_token_ = std::string();
|
| - const std::string account_id = accounts_.front();
|
| - HandleNextAccount();
|
| + const std::string account_id = requests_.front().account_id();
|
| + HandleNextRequest();
|
| SignalComplete(account_id, error);
|
| }
|
|
|
| -void GaiaCookieManagerService::StartFetching() {
|
| +void GaiaCookieManagerService::StartFetchingUbertoken() {
|
| VLOG(1) << "GaiaCookieManagerService::StartFetching account_id="
|
| - << accounts_.front();
|
| + << requests_.front().account_id();
|
| uber_token_fetcher_.reset(
|
| new UbertokenFetcher(token_service_, this, source_,
|
| signin_client_->GetURLRequestContext()));
|
| - uber_token_fetcher_->StartFetchingToken(accounts_.front());
|
| + uber_token_fetcher_->StartFetchingToken(requests_.front().account_id());
|
| }
|
|
|
| void GaiaCookieManagerService::StartFetchingMergeSession() {
|
| @@ -414,23 +477,28 @@ void GaiaCookieManagerService::StartFetchingMergeSession() {
|
|
|
| void GaiaCookieManagerService::OnURLFetchComplete(
|
| const net::URLFetcher* source) {
|
| - DCHECK(accounts_.front().empty());
|
| + DCHECK(requests_.front().request_type() == GaiaCookieRequestType::LOG_OUT);
|
| VLOG(1) << "GaiaCookieManagerService::OnURLFetchComplete";
|
| - HandleNextAccount();
|
| + HandleNextRequest();
|
| }
|
|
|
| -void GaiaCookieManagerService::HandleNextAccount() {
|
| - VLOG(1) << "GaiaCookieManagerService::HandleNextAccount";
|
| - accounts_.pop_front();
|
| +void GaiaCookieManagerService::HandleNextRequest() {
|
| + VLOG(1) << "GaiaCookieManagerService::HandleNextRequest";
|
| + requests_.pop_front();
|
| gaia_auth_fetcher_.reset();
|
| - if (accounts_.empty()) {
|
| - VLOG(1) << "GaiaCookieManagerService::HandleNextAccount: no more";
|
| + if (requests_.empty()) {
|
| + VLOG(1) << "GaiaCookieManagerService::HandleNextRequest: no more";
|
| uber_token_fetcher_.reset();
|
| } else {
|
| - if (accounts_.front().empty()) {
|
| - StartLogOutUrlFetch();
|
| - } else {
|
| - StartFetching();
|
| - }
|
| + switch (requests_.front().request_type()) {
|
| + case GaiaCookieRequestType::ADD_ACCOUNT:
|
| + StartFetchingUbertoken();
|
| + break;
|
| + case GaiaCookieRequestType::LOG_OUT:
|
| + StartLogOutUrlFetch();
|
| + break;
|
| + case GaiaCookieRequestType::LIST_ACCOUNTS:
|
| + break;
|
| + };
|
| }
|
| }
|
|
|