| 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 1aef48f0c9d3e9394c4a54103dff45e590155616..ccea52aace662a6229f5ace8e6dae48e608c76cc 100644
|
| --- a/components/signin/core/browser/gaia_cookie_manager_service.cc
|
| +++ b/components/signin/core/browser/gaia_cookie_manager_service.cc
|
| @@ -15,6 +15,7 @@
|
| #include "base/values.h"
|
| #include "components/signin/core/browser/signin_metrics.h"
|
| #include "google_apis/gaia/gaia_auth_fetcher.h"
|
| +#include "google_apis/gaia/gaia_auth_util.h"
|
| #include "google_apis/gaia/gaia_constants.h"
|
| #include "google_apis/gaia/gaia_urls.h"
|
| #include "google_apis/gaia/oauth2_token_service.h"
|
| @@ -72,12 +73,9 @@ enum GaiaCookieRequestType {
|
|
|
| GaiaCookieManagerService::GaiaCookieRequest::GaiaCookieRequest(
|
| GaiaCookieRequestType request_type,
|
| - const std::string& account_id,
|
| - const GaiaCookieManagerService::ListAccountsCallback&
|
| - list_accounts_callback)
|
| + const std::string& account_id)
|
| : request_type_(request_type),
|
| - account_id_(account_id),
|
| - list_accounts_callback_(list_accounts_callback) {}
|
| + account_id_(account_id) {}
|
|
|
| GaiaCookieManagerService::GaiaCookieRequest::~GaiaCookieRequest() {
|
| }
|
| @@ -87,28 +85,21 @@ GaiaCookieManagerService::GaiaCookieRequest
|
| GaiaCookieManagerService::GaiaCookieRequest::CreateAddAccountRequest(
|
| const std::string& account_id) {
|
| return GaiaCookieManagerService::GaiaCookieRequest(
|
| - GaiaCookieManagerService::GaiaCookieRequestType::ADD_ACCOUNT,
|
| - account_id,
|
| - GaiaCookieManagerService::ListAccountsCallback());
|
| + GaiaCookieManagerService::GaiaCookieRequestType::ADD_ACCOUNT, account_id);
|
| }
|
|
|
| // static
|
| GaiaCookieManagerService::GaiaCookieRequest
|
| GaiaCookieManagerService::GaiaCookieRequest::CreateLogOutRequest() {
|
| return GaiaCookieManagerService::GaiaCookieRequest(
|
| - GaiaCookieManagerService::GaiaCookieRequestType::LOG_OUT,
|
| - std::string(),
|
| - GaiaCookieManagerService::ListAccountsCallback());
|
| + GaiaCookieManagerService::GaiaCookieRequestType::LOG_OUT, std::string());
|
| }
|
|
|
| GaiaCookieManagerService::GaiaCookieRequest
|
| -GaiaCookieManagerService::GaiaCookieRequest::CreateListAccountsRequest(
|
| - const GaiaCookieManagerService::ListAccountsCallback&
|
| - list_accounts_callback) {
|
| +GaiaCookieManagerService::GaiaCookieRequest::CreateListAccountsRequest() {
|
| return GaiaCookieManagerService::GaiaCookieRequest(
|
| GaiaCookieManagerService::GaiaCookieRequestType::LIST_ACCOUNTS,
|
| - std::string(),
|
| - list_accounts_callback);
|
| + std::string());
|
| }
|
|
|
| GaiaCookieManagerService::ExternalCcResultFetcher::ExternalCcResultFetcher(
|
| @@ -295,7 +286,8 @@ GaiaCookieManagerService::GaiaCookieManagerService(
|
| gaia_auth_fetcher_backoff_(&kBackoffPolicy),
|
| gaia_auth_fetcher_retries_(0),
|
| source_(source),
|
| - external_cc_result_fetched_(false) {
|
| + external_cc_result_fetched_(false),
|
| + list_accounts_fetched_once_(false) {
|
| }
|
|
|
| GaiaCookieManagerService::~GaiaCookieManagerService() {
|
| @@ -303,8 +295,26 @@ GaiaCookieManagerService::~GaiaCookieManagerService() {
|
| DCHECK(requests_.empty());
|
| }
|
|
|
| +void GaiaCookieManagerService::Init() {
|
| + cookie_changed_subscription_ = signin_client_->AddCookieChangedCallback(
|
| + GaiaUrls::GetInstance()->google_url(),
|
| + "APISID",
|
| + base::Bind(&GaiaCookieManagerService::OnCookieChanged,
|
| + base::Unretained(this)));
|
| +}
|
| +
|
| +void GaiaCookieManagerService::Shutdown() {
|
| + cookie_changed_subscription_.reset();
|
| +}
|
| +
|
| void GaiaCookieManagerService::AddAccountToCookie(
|
| const std::string& account_id) {
|
| + if (!signin_client_->AreSigninCookiesAllowed()) {
|
| + SignalComplete(account_id,
|
| + GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
|
| + return;
|
| + }
|
| +
|
| DCHECK(!account_id.empty());
|
| VLOG(1) << "GaiaCookieManagerService::AddAccountToCookie: " << account_id;
|
| requests_.push_back(GaiaCookieRequest::CreateAddAccountRequest(account_id));
|
| @@ -312,25 +322,26 @@ void GaiaCookieManagerService::AddAccountToCookie(
|
| StartFetchingUbertoken();
|
| }
|
|
|
| -void GaiaCookieManagerService::ListAccounts(
|
| - const ListAccountsCallback& callback) {
|
| - // Not implemented yet.
|
| - NOTREACHED();
|
| +bool GaiaCookieManagerService::ListAccounts(
|
| + std::vector<std::pair<std::string,bool> >* accounts) {
|
| + DCHECK(accounts);
|
| + accounts->clear();
|
|
|
| - // 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.
|
| + // There is a fetch currently executing (the results being provided in the
|
| + // parameter don't align with the fetches that have been started), or the list
|
| + // of accounts haven't been fetched even once.
|
| + if (!requests_.empty())
|
| + return false;
|
|
|
| - // 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;
|
| + if (!list_accounts_fetched_once_) {
|
| + gaia_auth_fetcher_retries_ = 0;
|
| + requests_.push_back(GaiaCookieRequest::CreateListAccountsRequest());
|
| + StartFetchingListAccounts();
|
| + return false;
|
| + }
|
|
|
| - VLOG(1) << "GaiaCookieManagerService::ListAccounts";
|
| - gaia_auth_fetcher_.reset(
|
| - new GaiaAuthFetcher(this, source_,
|
| - signin_client_->GetURLRequestContext()));
|
| - gaia_auth_fetcher_->StartListAccounts();
|
| + accounts->assign(listed_accounts_.begin(), listed_accounts_.end());
|
| + return true;
|
| }
|
|
|
| void GaiaCookieManagerService::LogOutAllAccounts() {
|
| @@ -394,6 +405,41 @@ void GaiaCookieManagerService::CancelAll() {
|
| gaia_auth_fetcher_timer_.Stop();
|
| }
|
|
|
| +// It is unknown if the cookie was changed because of processing initiated by
|
| +// this class or other (such as the user clearing all cookies or a cookie being
|
| +// evicted).
|
| +void GaiaCookieManagerService::OnCookieChanged(
|
| + const net::CanonicalCookie& cookie,
|
| + bool removed) {
|
| + DCHECK_EQ("APISID", cookie.Name());
|
| + DCHECK_EQ(GaiaUrls::GetInstance()->google_url().host(), cookie.Domain());
|
| + gaia_auth_fetcher_retries_ = 0;
|
| + if (requests_.empty()) {
|
| + requests_.push_back(GaiaCookieRequest::CreateListAccountsRequest());
|
| + StartFetchingListAccounts();
|
| + } else {
|
| + // Remove all pending ListAccount calls; for efficiency, only call
|
| + // after all pending requests are processed.
|
| + // 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) {
|
| + // Keep all requests except for LIST_ACCOUNTS.
|
| + if (it->request_type() != GaiaCookieRequestType::LIST_ACCOUNTS)
|
| + requests_to_keep.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());
|
| + }
|
| + requests_.push_back(GaiaCookieRequest::CreateListAccountsRequest());
|
| + }
|
| +}
|
| +
|
| void GaiaCookieManagerService::SignalComplete(
|
| const std::string& account_id,
|
| const GoogleServiceAuthError& error) {
|
| @@ -446,6 +492,8 @@ void GaiaCookieManagerService::OnUbertokenFailure(
|
| void GaiaCookieManagerService::OnMergeSessionSuccess(const std::string& data) {
|
| VLOG(1) << "MergeSession successful account="
|
| << requests_.front().account_id();
|
| + DCHECK(requests_.front().request_type() ==
|
| + GaiaCookieRequestType::ADD_ACCOUNT);
|
| const std::string account_id = requests_.front().account_id();
|
| HandleNextRequest();
|
| SignalComplete(account_id, GoogleServiceAuthError::AuthErrorNone());
|
| @@ -456,10 +504,11 @@ void GaiaCookieManagerService::OnMergeSessionSuccess(const std::string& data) {
|
|
|
| void GaiaCookieManagerService::OnMergeSessionFailure(
|
| const GoogleServiceAuthError& error) {
|
| + DCHECK(requests_.front().request_type() ==
|
| + GaiaCookieRequestType::ADD_ACCOUNT);
|
| VLOG(1) << "Failed MergeSession"
|
| << " account=" << requests_.front().account_id()
|
| << " error=" << error.ToString();
|
| -
|
| if (++gaia_auth_fetcher_retries_ < kMaxGaiaAuthFetcherRetries &&
|
| IsTransientError(error)) {
|
| gaia_auth_fetcher_backoff_.InformOfRequest(false);
|
| @@ -475,6 +524,46 @@ void GaiaCookieManagerService::OnMergeSessionFailure(
|
| SignalComplete(account_id, error);
|
| }
|
|
|
| +void GaiaCookieManagerService::OnListAccountsSuccess(const std::string& data) {
|
| + VLOG(1) << "ListAccounts successful";
|
| + DCHECK(requests_.front().request_type() ==
|
| + GaiaCookieRequestType::LIST_ACCOUNTS);
|
| + gaia_auth_fetcher_backoff_.InformOfRequest(true);
|
| +
|
| + if (!gaia::ParseListAccountsData(data, &listed_accounts_)) {
|
| + listed_accounts_.clear();
|
| + OnListAccountsFailure(GoogleServiceAuthError(
|
| + GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE));
|
| + return;
|
| + }
|
| +
|
| + list_accounts_fetched_once_ = true;
|
| + FOR_EACH_OBSERVER(Observer, observer_list_,
|
| + OnGaiaAccountsInCookieUpdated(
|
| + listed_accounts_,
|
| + GoogleServiceAuthError(GoogleServiceAuthError::NONE)));
|
| + HandleNextRequest();
|
| +}
|
| +
|
| +void GaiaCookieManagerService::OnListAccountsFailure(
|
| + const GoogleServiceAuthError& error) {
|
| + VLOG(1) << "ListAccounts failed";
|
| + DCHECK(requests_.front().request_type() ==
|
| + GaiaCookieRequestType::LIST_ACCOUNTS);
|
| + if (++gaia_auth_fetcher_retries_ < kMaxGaiaAuthFetcherRetries &&
|
| + IsTransientError(error)) {
|
| + gaia_auth_fetcher_backoff_.InformOfRequest(false);
|
| + gaia_auth_fetcher_timer_.Start(
|
| + FROM_HERE, gaia_auth_fetcher_backoff_.GetTimeUntilRelease(), this,
|
| + &GaiaCookieManagerService::StartFetchingListAccounts);
|
| + return;
|
| + }
|
| +
|
| + FOR_EACH_OBSERVER(Observer, observer_list_,
|
| + OnGaiaAccountsInCookieUpdated(listed_accounts_, error));
|
| + HandleNextRequest();
|
| +}
|
| +
|
| void GaiaCookieManagerService::StartFetchingUbertoken() {
|
| VLOG(1) << "GaiaCookieManagerService::StartFetching account_id="
|
| << requests_.front().account_id();
|
| @@ -494,6 +583,14 @@ void GaiaCookieManagerService::StartFetchingMergeSession() {
|
| external_cc_result_fetcher_.GetExternalCcResult());
|
| }
|
|
|
| +void GaiaCookieManagerService::StartFetchingListAccounts() {
|
| + VLOG(1) << "GaiaCookieManagerService::ListAccounts";
|
| + gaia_auth_fetcher_.reset(
|
| + new GaiaAuthFetcher(this, source_,
|
| + signin_client_->GetURLRequestContext()));
|
| + gaia_auth_fetcher_->StartListAccounts();
|
| +}
|
| +
|
| void GaiaCookieManagerService::OnURLFetchComplete(
|
| const net::URLFetcher* source) {
|
| DCHECK(requests_.front().request_type() == GaiaCookieRequestType::LOG_OUT);
|
| @@ -503,8 +600,20 @@ void GaiaCookieManagerService::OnURLFetchComplete(
|
|
|
| void GaiaCookieManagerService::HandleNextRequest() {
|
| VLOG(1) << "GaiaCookieManagerService::HandleNextRequest";
|
| - requests_.pop_front();
|
| + if (requests_.front().request_type() ==
|
| + GaiaCookieRequestType::LIST_ACCOUNTS) {
|
| + // This and any directly subsequent list accounts would return the same.
|
| + while (!requests_.empty() && requests_.front().request_type() ==
|
| + GaiaCookieRequestType::LIST_ACCOUNTS) {
|
| + requests_.pop_front();
|
| + }
|
| + } else {
|
| + // Pop the completed request.
|
| + requests_.pop_front();
|
| + }
|
| +
|
| gaia_auth_fetcher_.reset();
|
| + gaia_auth_fetcher_retries_ = 0;
|
| if (requests_.empty()) {
|
| VLOG(1) << "GaiaCookieManagerService::HandleNextRequest: no more";
|
| uber_token_fetcher_.reset();
|
| @@ -517,6 +626,8 @@ void GaiaCookieManagerService::HandleNextRequest() {
|
| StartLogOutUrlFetch();
|
| break;
|
| case GaiaCookieRequestType::LIST_ACCOUNTS:
|
| + uber_token_fetcher_.reset();
|
| + StartFetchingListAccounts();
|
| break;
|
| };
|
| }
|
|
|