summaryrefslogtreecommitdiff
path: root/chromium/components/signin
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-07-31 15:50:41 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-08-30 12:35:23 +0000
commit7b2ffa587235a47d4094787d72f38102089f402a (patch)
tree30e82af9cbab08a7fa028bb18f4f2987a3f74dfa /chromium/components/signin
parentd94af01c90575348c4e81a418257f254b6f8d225 (diff)
downloadqtwebengine-chromium-7b2ffa587235a47d4094787d72f38102089f402a.tar.gz
BASELINE: Update Chromium to 76.0.3809.94
Change-Id: I321c3f5f929c105aec0f98c5091ef6108822e647 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/components/signin')
-rw-r--r--chromium/components/signin/OWNERS1
-rw-r--r--chromium/components/signin/core/browser/BUILD.gn23
-rw-r--r--chromium/components/signin/core/browser/DEPS4
-rw-r--r--chromium/components/signin/core/browser/about_signin_internals.cc52
-rw-r--r--chromium/components/signin/core/browser/about_signin_internals.h17
-rw-r--r--chromium/components/signin/core/browser/account_fetcher_service.cc1
-rw-r--r--chromium/components/signin/core/browser/account_info.cc16
-rw-r--r--chromium/components/signin/core/browser/account_info.h7
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor.cc22
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor.h3
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor_unittest.cc74
-rw-r--r--chromium/components/signin/core/browser/account_tracker_service.cc162
-rw-r--r--chromium/components/signin/core/browser/account_tracker_service.h59
-rw-r--r--chromium/components/signin/core/browser/account_tracker_service_unittest.cc205
-rw-r--r--chromium/components/signin/core/browser/android/OWNERS3
-rw-r--r--chromium/components/signin/core/browser/android/java/src/org/chromium/components/signin/OAuth2TokenService.java53
-rw-r--r--chromium/components/signin/core/browser/avatar_icon_util.cc106
-rw-r--r--chromium/components/signin/core/browser/avatar_icon_util_unittest.cc37
-rw-r--r--chromium/components/signin/core/browser/gaia_cookie_manager_service.cc350
-rw-r--r--chromium/components/signin/core/browser/gaia_cookie_manager_service.h104
-rw-r--r--chromium/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc575
-rw-r--r--chromium/components/signin/core/browser/identity_manager_wrapper.cc10
-rw-r--r--chromium/components/signin/core/browser/identity_manager_wrapper.h5
-rw-r--r--chromium/components/signin/core/browser/mutable_profile_oauth2_token_service_delegate_unittest.cc48
-rw-r--r--chromium/components/signin/core/browser/oauth2_token_service_delegate_android.cc107
-rw-r--r--chromium/components/signin/core/browser/oauth2_token_service_delegate_android.h31
-rw-r--r--chromium/components/signin/core/browser/oauth2_token_service_delegate_android_unittest.cc294
-rw-r--r--chromium/components/signin/core/browser/oauth_multilogin_helper.cc202
-rw-r--r--chromium/components/signin/core/browser/oauth_multilogin_helper.h98
-rw-r--r--chromium/components/signin/core/browser/oauth_multilogin_helper_unittest.cc495
-rw-r--r--chromium/components/signin/core/browser/oauth_multilogin_token_fetcher.cc136
-rw-r--r--chromium/components/signin/core/browser/oauth_multilogin_token_fetcher.h74
-rw-r--r--chromium/components/signin/core/browser/oauth_multilogin_token_fetcher_unittest.cc226
-rw-r--r--chromium/components/signin/core/browser/profile_oauth2_token_service_delegate_chromeos_unittest.cc2
-rw-r--r--chromium/components/signin/core/browser/resources/signin_index.html2
-rw-r--r--chromium/components/signin/core/browser/set_accounts_in_cookie_result.h22
-rw-r--r--chromium/components/signin/core/browser/signin_client.h6
-rw-r--r--chromium/components/signin/core/browser/signin_error_controller.cc2
-rw-r--r--chromium/components/signin/core/browser/signin_header_helper_unittest.cc3
-rw-r--r--chromium/components/signin/core/browser/signin_manager.cc118
-rw-r--r--chromium/components/signin/core/browser/signin_manager.h58
-rw-r--r--chromium/components/signin/core/browser/signin_manager_base.cc119
-rw-r--r--chromium/components/signin/core/browser/signin_manager_base.h75
-rw-r--r--chromium/components/signin/core/browser/test_signin_client.cc37
-rw-r--r--chromium/components/signin/core/browser/test_signin_client.h22
-rw-r--r--chromium/components/signin/ios/browser/account_consistency_service_unittest.mm8
46 files changed, 2474 insertions, 1600 deletions
diff --git a/chromium/components/signin/OWNERS b/chromium/components/signin/OWNERS
index ef731172939..184a152c6fd 100644
--- a/chromium/components/signin/OWNERS
+++ b/chromium/components/signin/OWNERS
@@ -1,3 +1,4 @@
+bsazonov@chromium.org
droger@chromium.org
msarda@chromium.org
diff --git a/chromium/components/signin/core/browser/BUILD.gn b/chromium/components/signin/core/browser/BUILD.gn
index 462981bb0f9..d2700ec7b52 100644
--- a/chromium/components/signin/core/browser/BUILD.gn
+++ b/chromium/components/signin/core/browser/BUILD.gn
@@ -32,6 +32,7 @@ static_library("shared") {
"avatar_icon_util.h",
"identity_utils.cc",
"identity_utils.h",
+ "set_accounts_in_cookie_result.h",
"signin_metrics.cc",
"signin_metrics.h",
"signin_pref_names.cc",
@@ -80,6 +81,10 @@ static_library("internals") {
"gaia_cookie_manager_service.h",
"oauth2_token_service_delegate_android.cc",
"oauth2_token_service_delegate_android.h",
+ "oauth_multilogin_helper.cc",
+ "oauth_multilogin_helper.h",
+ "oauth_multilogin_token_fetcher.cc",
+ "oauth_multilogin_token_fetcher.h",
"profile_oauth2_token_service.cc",
"profile_oauth2_token_service.h",
"profile_oauth2_token_service_delegate_chromeos.cc",
@@ -102,7 +107,6 @@ static_library("internals") {
":shared",
":signin_buildflags",
"//base",
- "//components/data_use_measurement/core",
"//components/image_fetcher/core",
"//components/keyed_service/core",
"//components/prefs",
@@ -118,7 +122,13 @@ static_library("internals") {
}
if (is_chromeos) {
- deps += [ "//chromeos/components/account_manager" ]
+ deps += [
+ "//chromeos/components/account_manager",
+
+ # TODO(crbug.com/816954): Remove this line when Account Manager is
+ # launched.
+ "//chromeos/constants",
+ ]
}
}
@@ -190,7 +200,6 @@ static_library("browser") {
]
deps = [
"//base:i18n",
- "//components/data_use_measurement/core",
"//components/google/core/browser",
"//components/metrics",
"//components/os_crypt",
@@ -274,9 +283,10 @@ source_set("unit_tests") {
"device_id_helper_unittest.cc",
"dice_account_reconcilor_delegate_unittest.cc",
"gaia_cookie_manager_service_unittest.cc",
- "identity_utils_unittest.cc",
"mice_account_reconcilor_delegate_unittest.cc",
"mutable_profile_oauth2_token_service_delegate_unittest.cc",
+ "oauth_multilogin_helper_unittest.cc",
+ "oauth_multilogin_token_fetcher_unittest.cc",
"profile_oauth2_token_service_delegate_chromeos_unittest.cc",
"signin_error_controller_unittest.cc",
"signin_header_helper_unittest.cc",
@@ -321,7 +331,10 @@ source_set("unit_tests") {
}
if (is_android) {
- sources += [ "consistency_cookie_manager_unittest.cc" ]
+ sources += [
+ "consistency_cookie_manager_unittest.cc",
+ "oauth2_token_service_delegate_android_unittest.cc",
+ ]
}
if (!enable_dice_support) {
diff --git a/chromium/components/signin/core/browser/DEPS b/chromium/components/signin/core/browser/DEPS
index 8ad0b6d3de8..6aa48343a03 100644
--- a/chromium/components/signin/core/browser/DEPS
+++ b/chromium/components/signin/core/browser/DEPS
@@ -1,7 +1,9 @@
include_rules = [
"+chromeos/components/account_manager",
+ # TODO(crbug.com/816954): Remove this line when Account Manager is
+ # launched.
+ "+chromeos/constants",
"+components/account_id",
- "+components/data_use_measurement/core",
"+components/image_fetcher/core",
"+components/metrics",
"+jni",
diff --git a/chromium/components/signin/core/browser/about_signin_internals.cc b/chromium/components/signin/core/browser/about_signin_internals.cc
index bdb28ddc86d..b3e4d988d4c 100644
--- a/chromium/components/signin/core/browser/about_signin_internals.cc
+++ b/chromium/components/signin/core/browser/about_signin_internals.cc
@@ -33,6 +33,35 @@ namespace {
// |kMaxRefreshTokenListSize| events are kept in memory.
const size_t kMaxRefreshTokenListSize = 50;
+enum class GaiaCookiesState {
+ kAllowed,
+ kClearOnExit,
+ kBlocked,
+};
+
+GaiaCookiesState GetGaiaCookiesState(SigninClient* signin_client) {
+ bool signin_cookies_allowed = signin_client->AreSigninCookiesAllowed();
+ if (!signin_cookies_allowed)
+ return GaiaCookiesState::kBlocked;
+
+ bool clear_cookies_on_exit = signin_client->AreSigninCookiesDeletedOnExit();
+ if (clear_cookies_on_exit)
+ return GaiaCookiesState::kClearOnExit;
+
+ return GaiaCookiesState::kAllowed;
+}
+
+std::string GetGaiaCookiesStateAsString(const GaiaCookiesState state) {
+ switch (state) {
+ case GaiaCookiesState::kBlocked:
+ return "Not allowed";
+ case GaiaCookiesState::kClearOnExit:
+ return "Cleared on exit";
+ case GaiaCookiesState::kAllowed:
+ return "Allowed";
+ }
+}
+
std::string GetTimeStr(base::Time time) {
return base::UTF16ToUTF8(base::TimeFormatShortDateAndTime(time));
}
@@ -290,17 +319,31 @@ void AboutSigninInternals::Initialize(SigninClient* client) {
RefreshSigninPrefs();
+ client_->AddContentSettingsObserver(this);
signin_error_controller_->AddObserver(this);
identity_manager_->AddObserver(this);
identity_manager_->AddDiagnosticsObserver(this);
}
void AboutSigninInternals::Shutdown() {
+ client_->RemoveContentSettingsObserver(this);
signin_error_controller_->RemoveObserver(this);
identity_manager_->RemoveObserver(this);
identity_manager_->RemoveDiagnosticsObserver(this);
}
+void AboutSigninInternals::OnContentSettingChanged(
+ const ContentSettingsPattern& primary_pattern,
+ const ContentSettingsPattern& secondary_pattern,
+ ContentSettingsType content_type,
+ const std::string& resource_identifier) {
+ // If this is not a change to cookie settings, just ignore.
+ if (content_type != CONTENT_SETTINGS_TYPE_COOKIES)
+ return;
+
+ NotifyObservers();
+}
+
void AboutSigninInternals::NotifyObservers() {
if (!signin_observers_.might_have_observers())
return;
@@ -578,6 +621,9 @@ AboutSigninInternals::SigninStatus::ToValue(
->GetDetailedStateOfLoadingOfRefreshTokens();
AddSectionEntry(basic_info, "TokenService Load Status",
TokenServiceLoadCredentialsStateToLabel(load_tokens_state));
+ AddSectionEntry(
+ basic_info, "Gaia cookies state",
+ GetGaiaCookiesStateAsString(GetGaiaCookiesState(signin_client)));
if (identity_manager->HasPrimaryAccount()) {
CoreAccountInfo account_info = identity_manager->GetPrimaryAccountInfo();
@@ -681,16 +727,16 @@ AboutSigninInternals::SigninStatus::ToValue(
// Account info section
auto account_info_section = std::make_unique<base::ListValue>();
- const std::vector<AccountInfo>& accounts_with_refresh_tokens =
+ const std::vector<CoreAccountInfo>& accounts_with_refresh_tokens =
identity_manager->GetAccountsWithRefreshTokens();
if (accounts_with_refresh_tokens.size() == 0) {
auto no_token_entry = std::make_unique<base::DictionaryValue>();
no_token_entry->SetString("accountId", "No token in Token Service.");
account_info_section->Append(std::move(no_token_entry));
} else {
- for (const AccountInfo account_info : accounts_with_refresh_tokens) {
+ for (const CoreAccountInfo& account_info : accounts_with_refresh_tokens) {
auto entry = std::make_unique<base::DictionaryValue>();
- entry->SetString("accountId", account_info.account_id);
+ entry->SetString("accountId", account_info.account_id.id);
// TODO(https://crbug.com/919793): Remove this field once the token
// service is internally consistent on all platforms.
entry->SetBoolean("hasRefreshToken",
diff --git a/chromium/components/signin/core/browser/about_signin_internals.h b/chromium/components/signin/core/browser/about_signin_internals.h
index 370e47f21b9..ccfd208c6f8 100644
--- a/chromium/components/signin/core/browser/about_signin_internals.h
+++ b/chromium/components/signin/core/browser/about_signin_internals.h
@@ -15,6 +15,7 @@
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/values.h"
+#include "components/content_settings/core/browser/content_settings_observer.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/signin/core/browser/signin_client.h"
#include "components/signin/core/browser/signin_error_controller.h"
@@ -35,11 +36,11 @@ using TimedSigninStatusValue = std::pair<std::string, std::string>;
// This class collects authentication, signin and token information
// to propagate to about:signin-internals via SigninInternalsUI.
-class AboutSigninInternals
- : public KeyedService,
- SigninErrorController::Observer,
- identity::IdentityManager::Observer,
- identity::IdentityManager::DiagnosticsObserver {
+class AboutSigninInternals : public KeyedService,
+ public content_settings::Observer,
+ SigninErrorController::Observer,
+ identity::IdentityManager::Observer,
+ identity::IdentityManager::DiagnosticsObserver {
public:
class Observer {
public:
@@ -217,6 +218,12 @@ class AboutSigninInternals
// SigninErrorController::Observer implementation
void OnErrorChanged() override;
+ // content_settings::Observer implementation.
+ void OnContentSettingChanged(const ContentSettingsPattern& primary_pattern,
+ const ContentSettingsPattern& secondary_pattern,
+ ContentSettingsType content_type,
+ const std::string& resource_identifier) override;
+
// Weak pointer to the identity manager.
identity::IdentityManager* identity_manager_;
diff --git a/chromium/components/signin/core/browser/account_fetcher_service.cc b/chromium/components/signin/core/browser/account_fetcher_service.cc
index 059f0e34131..6ff6a0421b4 100644
--- a/chromium/components/signin/core/browser/account_fetcher_service.cc
+++ b/chromium/components/signin/core/browser/account_fetcher_service.cc
@@ -331,7 +331,6 @@ void AccountFetcherService::FetchAccountImage(const std::string& account_id) {
void AccountFetcherService::OnUserInfoFetchFailure(
const std::string& account_id) {
LOG(WARNING) << "Failed to get UserInfo for " << account_id;
- account_tracker_service_->NotifyAccountUpdateFailed(account_id);
user_info_requests_.erase(account_id);
}
diff --git a/chromium/components/signin/core/browser/account_info.cc b/chromium/components/signin/core/browser/account_info.cc
index c089abf4033..3c164ea34ab 100644
--- a/chromium/components/signin/core/browser/account_info.cc
+++ b/chromium/components/signin/core/browser/account_info.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "components/signin/core/browser/account_info.h"
+#include "google_apis/gaia/gaia_auth_util.h"
namespace {
@@ -103,6 +104,21 @@ bool AccountInfo::UpdateWith(const AccountInfo& other) {
return modified;
}
+bool operator==(const CoreAccountInfo& l, const CoreAccountInfo& r) {
+ return l.account_id == r.account_id && l.gaia == r.gaia &&
+ gaia::AreEmailsSame(l.email, r.email) &&
+ l.is_under_advanced_protection == r.is_under_advanced_protection;
+}
+bool operator!=(const CoreAccountInfo& l, const CoreAccountInfo& r) {
+ return !(l == r);
+}
+
+std::ostream& operator<<(std::ostream& os, const CoreAccountInfo& account) {
+ os << "account_id: " << account.account_id << ", gaia: " << account.gaia
+ << ", email: " << account.email << ", adv_prot: " << std::boolalpha
+ << account.is_under_advanced_protection;
+ return os;
+}
AccountId AccountIdFromAccountInfo(const CoreAccountInfo& account_info) {
if (account_info.email.empty() || account_info.gaia.empty())
diff --git a/chromium/components/signin/core/browser/account_info.h b/chromium/components/signin/core/browser/account_info.h
index fa581f0ca88..ca47ac7fd82 100644
--- a/chromium/components/signin/core/browser/account_info.h
+++ b/chromium/components/signin/core/browser/account_info.h
@@ -8,6 +8,7 @@
#include <string>
#include "components/account_id/account_id.h"
+#include "google_apis/gaia/core_account_id.h"
#include "ui/gfx/image/image.h"
// Value representing no hosted domain associated with an account.
@@ -29,7 +30,7 @@ struct CoreAccountInfo {
CoreAccountInfo& operator=(const CoreAccountInfo& other);
CoreAccountInfo& operator=(CoreAccountInfo&& other) noexcept;
- std::string account_id;
+ CoreAccountId account_id;
std::string gaia;
std::string email;
@@ -70,6 +71,10 @@ struct AccountInfo : public CoreAccountInfo {
bool UpdateWith(const AccountInfo& other);
};
+bool operator==(const CoreAccountInfo& l, const CoreAccountInfo& r);
+bool operator!=(const CoreAccountInfo& l, const CoreAccountInfo& r);
+std::ostream& operator<<(std::ostream& os, const CoreAccountInfo& account);
+
// Returns AccountID populated from |account_info|.
AccountId AccountIdFromAccountInfo(const CoreAccountInfo& account_info);
diff --git a/chromium/components/signin/core/browser/account_reconcilor.cc b/chromium/components/signin/core/browser/account_reconcilor.cc
index 4075ad6bb46..a2f98a11ed4 100644
--- a/chromium/components/signin/core/browser/account_reconcilor.cc
+++ b/chromium/components/signin/core/browser/account_reconcilor.cc
@@ -23,6 +23,7 @@
#include "components/signin/core/browser/account_consistency_method.h"
#include "components/signin/core/browser/account_reconcilor_delegate.h"
#include "components/signin/core/browser/consistency_cookie_manager_base.h"
+#include "components/signin/core/browser/set_accounts_in_cookie_result.h"
#include "components/signin/core/browser/signin_buildflags.h"
#include "components/signin/core/browser/signin_client.h"
#include "components/signin/core/browser/signin_metrics.h"
@@ -89,7 +90,7 @@ bool RevokeAllSecondaryTokens(
if (revoke_option ==
AccountReconcilorDelegate::RevokeTokenOption::kDoNotRevoke)
return false;
- for (const AccountInfo& account_info :
+ for (const CoreAccountInfo& account_info :
identity_manager->GetAccountsWithRefreshTokens()) {
std::string account(account_info.account_id);
if (account == primary_account)
@@ -395,7 +396,7 @@ void AccountReconcilor::PerformSetCookiesAction(
const signin::MultiloginParameters& parameters) {
reconcile_is_noop_ = false;
if (!delegate_->IsAccountConsistencyEnforced()) {
- OnSetAccountsInCookieCompleted(GoogleServiceAuthError::AuthErrorNone());
+ OnSetAccountsInCookieCompleted(signin::SetAccountsInCookieResult::kSuccess);
return;
}
VLOG(1) << "AccountReconcilor::PerformSetCookiesAction: "
@@ -509,7 +510,8 @@ void AccountReconcilor::FinishReconcileWithMultiloginEndpoint(
// instead.
PerformLogoutAllAccountsAction();
gaia_accounts.clear();
- OnSetAccountsInCookieCompleted(GoogleServiceAuthError::AuthErrorNone());
+ OnSetAccountsInCookieCompleted(
+ signin::SetAccountsInCookieResult::kSuccess);
DCHECK(!is_reconcile_started_);
} else {
// Reconcilor has to do some calls to gaia. is_reconcile_started_ is true
@@ -521,7 +523,7 @@ void AccountReconcilor::FinishReconcileWithMultiloginEndpoint(
}
} else {
// Nothing to do, accounts already match.
- OnSetAccountsInCookieCompleted(GoogleServiceAuthError::AuthErrorNone());
+ OnSetAccountsInCookieCompleted(signin::SetAccountsInCookieResult::kSuccess);
DCHECK(!is_reconcile_started_);
}
@@ -865,13 +867,17 @@ bool AccountReconcilor::IsIdentityManagerReady() {
}
void AccountReconcilor::OnSetAccountsInCookieCompleted(
- const GoogleServiceAuthError& error) {
+ signin::SetAccountsInCookieResult result) {
VLOG(1) << "AccountReconcilor::OnSetAccountsInCookieCompleted: "
- << "Error was " << error.ToString();
+ << "Error was " << static_cast<int>(result);
if (is_reconcile_started_) {
- if (error.state() != GoogleServiceAuthError::State::NONE &&
+ if (result != signin::SetAccountsInCookieResult::kSuccess &&
!error_during_last_reconcile_.IsPersistentError()) {
- error_during_last_reconcile_ = error;
+ error_during_last_reconcile_ =
+ result == signin::SetAccountsInCookieResult::kTransientError
+ ? GoogleServiceAuthError(
+ GoogleServiceAuthError::CONNECTION_FAILED)
+ : GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_ERROR);
delegate_->OnReconcileError(error_during_last_reconcile_);
}
diff --git a/chromium/components/signin/core/browser/account_reconcilor.h b/chromium/components/signin/core/browser/account_reconcilor.h
index adaad558514..9801137824e 100644
--- a/chromium/components/signin/core/browser/account_reconcilor.h
+++ b/chromium/components/signin/core/browser/account_reconcilor.h
@@ -35,6 +35,7 @@ extern const base::Feature kUseMultiloginEndpoint;
namespace signin {
class AccountReconcilorDelegate;
class ConsistencyCookieManagerBase;
+enum class SetAccountsInCookieResult;
}
class SigninClient;
@@ -302,7 +303,7 @@ class AccountReconcilor : public KeyedService,
void OnAddAccountToCookieCompleted(const std::string& account_id,
const GoogleServiceAuthError& error);
- void OnSetAccountsInCookieCompleted(const GoogleServiceAuthError& error);
+ void OnSetAccountsInCookieCompleted(signin::SetAccountsInCookieResult result);
// Lock related methods.
void IncrementLockCount();
diff --git a/chromium/components/signin/core/browser/account_reconcilor_unittest.cc b/chromium/components/signin/core/browser/account_reconcilor_unittest.cc
index a7f1b917e46..a1d22a5f74e 100644
--- a/chromium/components/signin/core/browser/account_reconcilor_unittest.cc
+++ b/chromium/components/signin/core/browser/account_reconcilor_unittest.cc
@@ -26,6 +26,7 @@
#include "components/signin/core/browser/list_accounts_test_utils.h"
#include "components/signin/core/browser/mice_account_reconcilor_delegate.h"
#include "components/signin/core/browser/mirror_account_reconcilor_delegate.h"
+#include "components/signin/core/browser/set_accounts_in_cookie_result.h"
#include "components/signin/core/browser/signin_buildflags.h"
#include "components/signin/core/browser/signin_metrics.h"
#include "components/signin/core/browser/signin_pref_names.h"
@@ -251,7 +252,7 @@ class AccountReconcilorTest : public ::testing::Test {
void SimulateSetAccountsInCookieCompleted(
AccountReconcilor* reconcilor,
- const GoogleServiceAuthError& error);
+ signin::SetAccountsInCookieResult result);
void SetAccountConsistency(signin::AccountConsistencyMethod method);
@@ -327,8 +328,8 @@ INSTANTIATE_TEST_SUITE_P(Dice_Mirror,
AccountReconcilorTest::AccountReconcilorTest()
: account_consistency_(signin::AccountConsistencyMethod::kDisabled),
- test_signin_client_(&pref_service_),
- identity_test_env_(&test_url_loader_factory_,
+ test_signin_client_(&pref_service_, &test_url_loader_factory_),
+ identity_test_env_(/*test_url_loader_factory=*/nullptr,
&pref_service_,
account_consistency_,
&test_signin_client_) {
@@ -390,8 +391,8 @@ void AccountReconcilorTest::SimulateAddAccountToCookieCompleted(
void AccountReconcilorTest::SimulateSetAccountsInCookieCompleted(
AccountReconcilor* reconcilor,
- const GoogleServiceAuthError& error) {
- reconcilor->OnSetAccountsInCookieCompleted(error);
+ signin::SetAccountsInCookieResult result) {
+ reconcilor->OnSetAccountsInCookieCompleted(result);
}
void AccountReconcilorTest::SimulateCookieContentSettingsChanged(
@@ -1040,8 +1041,8 @@ TEST_P(AccountReconcilorTestDiceMultilogin, TableRowTest) {
GetParam().is_first_reconcile == IsFirstReconcile::kFirst ? true : false;
reconcilor->StartReconcile();
- SimulateSetAccountsInCookieCompleted(reconcilor,
- GoogleServiceAuthError::AuthErrorNone());
+ SimulateSetAccountsInCookieCompleted(
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
ASSERT_FALSE(reconcilor->is_reconcile_started_);
if (GetParam().tokens == GetParam().tokens_after_reconcile_multilogin) {
@@ -1138,7 +1139,7 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, DiceReconcileWithoutSignin) {
reconcilor, account_id, GoogleServiceAuthError::AuthErrorNone());
} else {
SimulateSetAccountsInCookieCompleted(
- reconcilor, GoogleServiceAuthError::AuthErrorNone());
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
}
ASSERT_FALSE(reconcilor->is_reconcile_started_);
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
@@ -1174,7 +1175,7 @@ TEST_P(AccountReconcilorDiceEndpointParamTest,
const std::string account_id_2 = account_info_2.account_id;
auto* identity_manager = identity_test_env()->identity_manager();
- std::vector<AccountInfo> accounts =
+ std::vector<CoreAccountInfo> accounts =
identity_manager->GetAccountsWithRefreshTokens();
ASSERT_EQ(2u, accounts.size());
ASSERT_TRUE(identity_manager->HasAccountWithRefreshToken(account_id_1));
@@ -1212,7 +1213,7 @@ TEST_P(AccountReconcilorDiceEndpointParamTest,
reconcilor, account_id_2, GoogleServiceAuthError::AuthErrorNone());
} else {
SimulateSetAccountsInCookieCompleted(
- reconcilor, GoogleServiceAuthError::AuthErrorNone());
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
}
ASSERT_FALSE(reconcilor->is_reconcile_started_);
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
@@ -1233,7 +1234,7 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, DiceLastKnownFirstAccount) {
account_info_1.gaia, &test_url_loader_factory_);
auto* identity_manager = identity_test_env()->identity_manager();
- std::vector<AccountInfo> accounts =
+ std::vector<CoreAccountInfo> accounts =
identity_manager->GetAccountsWithRefreshTokens();
ASSERT_EQ(2u, accounts.size());
ASSERT_TRUE(identity_manager->HasAccountWithRefreshToken(account_id_1));
@@ -1291,7 +1292,7 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, DiceLastKnownFirstAccount) {
reconcilor, account_id_1, GoogleServiceAuthError::AuthErrorNone());
} else {
SimulateSetAccountsInCookieCompleted(
- reconcilor, GoogleServiceAuthError::AuthErrorNone());
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
}
ASSERT_FALSE(reconcilor->is_reconcile_started_);
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
@@ -1358,7 +1359,7 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, UnverifiedAccountMerge) {
reconcilor, chrome_account_id, GoogleServiceAuthError::AuthErrorNone());
} else {
SimulateSetAccountsInCookieCompleted(
- reconcilor, GoogleServiceAuthError::AuthErrorNone());
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
}
ASSERT_FALSE(reconcilor->is_reconcile_started_);
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
@@ -1454,7 +1455,7 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, DiceNoMigrationAfterReconcile) {
reconcilor, account_id, GoogleServiceAuthError::AuthErrorNone());
} else {
SimulateSetAccountsInCookieCompleted(
- reconcilor, GoogleServiceAuthError::AuthErrorNone());
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
}
ASSERT_FALSE(reconcilor->is_reconcile_started_);
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
@@ -1501,7 +1502,7 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, MigrationClearSecondaryTokens) {
reconcilor, account_id_1, GoogleServiceAuthError::AuthErrorNone());
} else {
SimulateSetAccountsInCookieCompleted(
- reconcilor, GoogleServiceAuthError::AuthErrorNone());
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
}
ASSERT_FALSE(reconcilor->is_reconcile_started_);
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_SCHEDULED,
@@ -1734,8 +1735,8 @@ TEST_P(AccountReconcilorTestMirrorMultilogin, TableRowTest) {
GetParam().is_first_reconcile == IsFirstReconcile::kFirst ? true : false;
reconcilor->StartReconcile();
- SimulateSetAccountsInCookieCompleted(reconcilor,
- GoogleServiceAuthError::AuthErrorNone());
+ SimulateSetAccountsInCookieCompleted(
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
ASSERT_FALSE(reconcilor->is_reconcile_started_);
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
@@ -1851,8 +1852,8 @@ TEST_P(AccountReconcilorTestMiceMultilogin, TableRowTest) {
GetParam().is_first_reconcile == IsFirstReconcile::kFirst ? true : false;
reconcilor->StartReconcile();
- SimulateSetAccountsInCookieCompleted(reconcilor,
- GoogleServiceAuthError::AuthErrorNone());
+ SimulateSetAccountsInCookieCompleted(
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
ASSERT_FALSE(reconcilor->is_reconcile_started_);
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
@@ -1933,8 +1934,8 @@ TEST_F(AccountReconcilorMiceTest, AccountReconcilorStateScheduled) {
account_info.account_id);
// Unblock the first reconcile.
- SimulateSetAccountsInCookieCompleted(reconcilor,
- GoogleServiceAuthError::AuthErrorNone());
+ SimulateSetAccountsInCookieCompleted(
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
// Wait until the first reconcile finishes, and a second reconcile is done.
// The second reconcile will be a no-op.
base::RunLoop().RunUntilIdle();
@@ -1980,7 +1981,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, TokensNotLoaded) {
reconcilor, account_id, GoogleServiceAuthError::AuthErrorNone());
} else {
SimulateSetAccountsInCookieCompleted(
- reconcilor, GoogleServiceAuthError::AuthErrorNone());
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
}
ASSERT_FALSE(reconcilor->is_reconcile_started_);
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
@@ -2088,7 +2089,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest,
reconcilor, account_id, GoogleServiceAuthError::AuthErrorNone());
} else {
SimulateSetAccountsInCookieCompleted(
- reconcilor, GoogleServiceAuthError::AuthErrorNone());
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
}
ASSERT_FALSE(reconcilor->is_reconcile_started_);
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
@@ -2293,7 +2294,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, StartReconcileAddToCookie) {
reconcilor, account_id2, GoogleServiceAuthError::AuthErrorNone());
} else {
SimulateSetAccountsInCookieCompleted(
- reconcilor, GoogleServiceAuthError::AuthErrorNone());
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
}
ASSERT_FALSE(reconcilor->is_reconcile_started_);
@@ -2398,12 +2399,14 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest,
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(reconcilor->is_reconcile_started_);
- GoogleServiceAuthError error(
- GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
if (!IsMultiloginEnabled()) {
- SimulateAddAccountToCookieCompleted(reconcilor, account_id2, error);
+ SimulateAddAccountToCookieCompleted(
+ reconcilor, account_id2,
+ GoogleServiceAuthError(
+ GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
} else {
- SimulateSetAccountsInCookieCompleted(reconcilor, error);
+ SimulateSetAccountsInCookieCompleted(
+ reconcilor, signin::SetAccountsInCookieResult::kPersistentError);
}
ASSERT_FALSE(reconcilor->is_reconcile_started_);
@@ -2452,7 +2455,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest,
reconcilor, account_id, GoogleServiceAuthError::AuthErrorNone());
} else {
SimulateSetAccountsInCookieCompleted(
- reconcilor, GoogleServiceAuthError::AuthErrorNone());
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
}
ASSERT_FALSE(reconcilor->is_reconcile_started_);
@@ -2521,7 +2524,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest,
reconcilor, account_id2, GoogleServiceAuthError::AuthErrorNone());
} else {
SimulateSetAccountsInCookieCompleted(
- reconcilor, GoogleServiceAuthError::AuthErrorNone());
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
}
ASSERT_FALSE(reconcilor->is_reconcile_started_);
@@ -2559,7 +2562,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest,
reconcilor, account_id3, GoogleServiceAuthError::AuthErrorNone());
} else {
SimulateSetAccountsInCookieCompleted(
- reconcilor, GoogleServiceAuthError::AuthErrorNone());
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
}
ASSERT_FALSE(reconcilor->is_reconcile_started_);
@@ -2617,7 +2620,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, StartReconcileBadPrimary) {
reconcilor, account_id, GoogleServiceAuthError::AuthErrorNone());
} else {
SimulateSetAccountsInCookieCompleted(
- reconcilor, GoogleServiceAuthError::AuthErrorNone());
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
}
ASSERT_FALSE(reconcilor->is_reconcile_started_);
@@ -2866,7 +2869,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest,
reconcilor, account_id, GoogleServiceAuthError::AuthErrorNone());
} else {
SimulateSetAccountsInCookieCompleted(
- reconcilor, GoogleServiceAuthError::AuthErrorNone());
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
}
ASSERT_FALSE(reconcilor->is_reconcile_started_);
}
@@ -2912,7 +2915,8 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, NoLoopWithBadPrimary) {
SimulateAddAccountToCookieCompleted(
reconcilor, account_id2, GoogleServiceAuthError::AuthErrorNone());
} else {
- SimulateSetAccountsInCookieCompleted(reconcilor, error);
+ SimulateSetAccountsInCookieCompleted(
+ reconcilor, signin::SetAccountsInCookieResult::kPersistentError);
}
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(reconcilor->is_reconcile_started_);
@@ -2972,7 +2976,7 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, WontMergeAccountsWithError) {
reconcilor, account_id1, GoogleServiceAuthError::AuthErrorNone());
} else {
SimulateSetAccountsInCookieCompleted(
- reconcilor, GoogleServiceAuthError::AuthErrorNone());
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
}
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(reconcilor->is_reconcile_started_);
diff --git a/chromium/components/signin/core/browser/account_tracker_service.cc b/chromium/components/signin/core/browser/account_tracker_service.cc
index 05be0c6698f..c30ba074019 100644
--- a/chromium/components/signin/core/browser/account_tracker_service.cc
+++ b/chromium/components/signin/core/browser/account_tracker_service.cc
@@ -46,28 +46,12 @@ const char kAccountChildAccountStatusPath[] = "is_child_account";
const char kAdvancedProtectionAccountStatusPath[] =
"is_under_advanced_protection";
-// TODO(knn): Remove once deprecated service flags have been migrated from
-// preferences.
-const char kChildAccountServiceFlag[] = "uca";
-
// Account folders used for storing account related data at disk.
const base::FilePath::CharType kAccountsFolder[] =
FILE_PATH_LITERAL("Accounts");
const base::FilePath::CharType kAvatarImagesFolder[] =
FILE_PATH_LITERAL("Avatar Images");
-// TODO(M48): Remove deprecated preference migration.
-const char kAccountServiceFlagsPath[] = "service_flags";
-
-void RemoveDeprecatedServiceFlags(PrefService* pref_service) {
- ListPrefUpdate update(pref_service, prefs::kAccountInfo);
- for (size_t i = 0; i < update->GetSize(); ++i) {
- base::DictionaryValue* dict = nullptr;
- if (update->GetDictionary(i, &dict))
- dict->RemoveWithoutPathExpansion(kAccountServiceFlagsPath, nullptr);
- }
-}
-
// Reads a PNG image from disk and decodes it. If the reading/decoding attempt
// was unsuccessful, an empty image is returned.
gfx::Image ReadImage(const base::FilePath& image_path) {
@@ -169,7 +153,7 @@ std::vector<AccountInfo> AccountTrackerService::GetAccounts() const {
}
AccountInfo AccountTrackerService::GetAccountInfo(
- const std::string& account_id) const {
+ const CoreAccountId& account_id) const {
const auto iterator = accounts_.find(account_id);
if (iterator != accounts_.end())
return iterator->second;
@@ -229,12 +213,6 @@ void AccountTrackerService::NotifyAccountUpdated(
observer.OnAccountUpdated(account_info);
}
-void AccountTrackerService::NotifyAccountUpdateFailed(
- const std::string& account_id) {
- for (auto& observer : observer_list_)
- observer.OnAccountUpdateFailed(account_id);
-}
-
void AccountTrackerService::NotifyAccountRemoved(
const AccountInfo& account_info) {
DCHECK(!account_info.gaia.empty());
@@ -243,17 +221,18 @@ void AccountTrackerService::NotifyAccountRemoved(
}
void AccountTrackerService::StartTrackingAccount(
- const std::string& account_id) {
+ const CoreAccountId& account_id) {
if (!base::ContainsKey(accounts_, account_id)) {
DVLOG(1) << "StartTracking " << account_id;
AccountInfo account_info;
account_info.account_id = account_id;
account_info.is_child_account = false;
- accounts_.insert(make_pair(account_id, account_info));
+ accounts_.insert(std::make_pair(account_id, account_info));
}
}
-void AccountTrackerService::StopTrackingAccount(const std::string& account_id) {
+void AccountTrackerService::StopTrackingAccount(
+ const CoreAccountId& account_id) {
DVLOG(1) << "StopTracking " << account_id;
if (base::ContainsKey(accounts_, account_id)) {
AccountInfo account_info = std::move(accounts_[account_id]);
@@ -267,7 +246,7 @@ void AccountTrackerService::StopTrackingAccount(const std::string& account_id) {
}
void AccountTrackerService::SetAccountInfoFromUserInfo(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const base::DictionaryValue* user_info) {
DCHECK(base::ContainsKey(accounts_, account_id));
AccountInfo& account_info = accounts_[account_id];
@@ -290,7 +269,7 @@ void AccountTrackerService::SetAccountInfoFromUserInfo(
SaveToPrefs(account_info);
}
-void AccountTrackerService::SetAccountImage(const std::string& account_id,
+void AccountTrackerService::SetAccountImage(const CoreAccountId& account_id,
const gfx::Image& image) {
if (!base::ContainsKey(accounts_, account_id))
return;
@@ -300,7 +279,7 @@ void AccountTrackerService::SetAccountImage(const std::string& account_id,
NotifyAccountUpdated(account_info);
}
-void AccountTrackerService::SetIsChildAccount(const std::string& account_id,
+void AccountTrackerService::SetIsChildAccount(const CoreAccountId& account_id,
bool is_child_account) {
DCHECK(base::ContainsKey(accounts_, account_id));
AccountInfo& account_info = accounts_[account_id];
@@ -313,7 +292,7 @@ void AccountTrackerService::SetIsChildAccount(const std::string& account_id,
}
void AccountTrackerService::SetIsAdvancedProtectionAccount(
- const std::string& account_id,
+ const CoreAccountId& account_id,
bool is_under_advanced_protection) {
DCHECK(base::ContainsKey(accounts_, account_id));
AccountInfo& account_info = accounts_[account_id];
@@ -328,10 +307,10 @@ void AccountTrackerService::SetIsAdvancedProtectionAccount(
void AccountTrackerService::MigrateToGaiaId() {
DCHECK_EQ(GetMigrationState(), MIGRATION_IN_PROGRESS);
- std::vector<std::string> to_remove;
+ std::vector<CoreAccountId> to_remove;
std::vector<AccountInfo> migrated_accounts;
for (const auto& pair : accounts_) {
- const std::string& new_account_id = pair.second.gaia;
+ const CoreAccountId new_account_id(pair.second.gaia);
if (pair.first == new_account_id)
continue;
@@ -353,7 +332,7 @@ void AccountTrackerService::MigrateToGaiaId() {
for (AccountInfo& new_account_info : migrated_accounts) {
// Copy the AccountInfo |gaia| member field so that it is not left in
// an undeterminate state in the structure after std::map::emplace call.
- std::string account_id = new_account_info.gaia;
+ CoreAccountId account_id = new_account_info.account_id;
SaveToPrefs(new_account_info);
accounts_.emplace(std::move(account_id), std::move(new_account_info));
@@ -414,14 +393,15 @@ AccountTrackerService::GetMigrationState(const PrefService* pref_service) {
}
base::FilePath AccountTrackerService::GetImagePathFor(
- const std::string& account_id) {
+ const CoreAccountId& account_id) {
return user_data_dir_.Append(kAccountsFolder)
.Append(kAvatarImagesFolder)
- .AppendASCII(account_id);
+ .AppendASCII(account_id.id);
}
-void AccountTrackerService::OnAccountImageLoaded(const std::string& account_id,
- gfx::Image image) {
+void AccountTrackerService::OnAccountImageLoaded(
+ const CoreAccountId& account_id,
+ gfx::Image image) {
if (base::ContainsKey(accounts_, account_id) &&
accounts_[account_id].account_image.IsEmpty()) {
AccountInfo& account_info = accounts_[account_id];
@@ -434,7 +414,7 @@ void AccountTrackerService::LoadAccountImagesFromDisk() {
if (!image_storage_task_runner_)
return;
for (const auto& pair : accounts_) {
- const std::string& account_id = pair.second.account_id;
+ const CoreAccountId& account_id = pair.second.account_id;
PostTaskAndReplyWithResult(
image_storage_task_runner_.get(), FROM_HERE,
base::BindOnce(&ReadImage, GetImagePathFor(account_id)),
@@ -444,7 +424,7 @@ void AccountTrackerService::LoadAccountImagesFromDisk() {
}
void AccountTrackerService::SaveAccountImageToDisk(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const gfx::Image& image) {
if (!image_storage_task_runner_)
return;
@@ -454,7 +434,7 @@ void AccountTrackerService::SaveAccountImageToDisk(
}
void AccountTrackerService::RemoveAccountImageFromDisk(
- const std::string& account_id) {
+ const CoreAccountId& account_id) {
if (!image_storage_task_runner_)
return;
image_storage_task_runner_->PostTask(
@@ -463,55 +443,39 @@ void AccountTrackerService::RemoveAccountImageFromDisk(
void AccountTrackerService::LoadFromPrefs() {
const base::ListValue* list = pref_service_->GetList(prefs::kAccountInfo);
- std::set<std::string> to_remove;
- bool contains_deprecated_service_flags = false;
+ std::set<CoreAccountId> to_remove;
for (size_t i = 0; i < list->GetSize(); ++i) {
const base::DictionaryValue* dict;
if (list->GetDictionary(i, &dict)) {
- base::string16 value;
+ std::string value;
if (dict->GetString(kAccountKeyPath, &value)) {
- std::string account_id = base::UTF16ToUTF8(value);
-
// Ignore incorrectly persisted non-canonical account ids.
- if (account_id.find('@') != std::string::npos &&
- account_id != gaia::CanonicalizeEmail(account_id)) {
- to_remove.insert(account_id);
+ if (value.find('@') != std::string::npos &&
+ value != gaia::CanonicalizeEmail(value)) {
+ to_remove.insert(CoreAccountId(value));
continue;
}
+ CoreAccountId account_id(value);
StartTrackingAccount(account_id);
AccountInfo& account_info = accounts_[account_id];
if (dict->GetString(kAccountGaiaPath, &value))
- account_info.gaia = base::UTF16ToUTF8(value);
+ account_info.gaia = value;
if (dict->GetString(kAccountEmailPath, &value))
- account_info.email = base::UTF16ToUTF8(value);
+ account_info.email = value;
if (dict->GetString(kAccountHostedDomainPath, &value))
- account_info.hosted_domain = base::UTF16ToUTF8(value);
+ account_info.hosted_domain = value;
if (dict->GetString(kAccountFullNamePath, &value))
- account_info.full_name = base::UTF16ToUTF8(value);
+ account_info.full_name = value;
if (dict->GetString(kAccountGivenNamePath, &value))
- account_info.given_name = base::UTF16ToUTF8(value);
+ account_info.given_name = value;
if (dict->GetString(kAccountLocalePath, &value))
- account_info.locale = base::UTF16ToUTF8(value);
+ account_info.locale = value;
if (dict->GetString(kAccountPictureURLPath, &value))
- account_info.picture_url = base::UTF16ToUTF8(value);
+ account_info.picture_url = value;
bool is_child_account = false;
- // Migrate deprecated service flag preference.
- const base::ListValue* service_flags_list;
- if (dict->GetList(kAccountServiceFlagsPath, &service_flags_list)) {
- contains_deprecated_service_flags = true;
- std::string flag_string;
- for (const auto& flag : *service_flags_list) {
- if (flag.GetAsString(&flag_string) &&
- flag_string == kChildAccountServiceFlag) {
- is_child_account = true;
- break;
- }
- }
- account_info.is_child_account = is_child_account;
- }
if (dict->GetBoolean(kAccountChildAccountStatusPath, &is_child_account))
account_info.is_child_account = is_child_account;
@@ -528,12 +492,6 @@ void AccountTrackerService::LoadFromPrefs() {
}
}
- UMA_HISTOGRAM_BOOLEAN("Signin.AccountTracker.DeprecatedServiceFlagDeleted",
- contains_deprecated_service_flags);
-
- if (contains_deprecated_service_flags)
- RemoveDeprecatedServiceFlags(pref_service_);
-
// Remove any obsolete prefs.
for (auto account_id : to_remove) {
AccountInfo account_info;
@@ -572,12 +530,12 @@ void AccountTrackerService::SaveToPrefs(const AccountInfo& account_info) {
return;
base::DictionaryValue* dict = nullptr;
- base::string16 account_id_16 = base::UTF8ToUTF16(account_info.account_id);
ListPrefUpdate update(pref_service_, prefs::kAccountInfo);
for (size_t i = 0; i < update->GetSize(); ++i, dict = nullptr) {
if (update->GetDictionary(i, &dict)) {
- base::string16 value;
- if (dict->GetString(kAccountKeyPath, &value) && value == account_id_16)
+ std::string value;
+ if (dict->GetString(kAccountKeyPath, &value) &&
+ value == account_info.account_id.id)
break;
}
}
@@ -587,7 +545,7 @@ void AccountTrackerService::SaveToPrefs(const AccountInfo& account_info) {
update->Append(base::WrapUnique(dict));
// |dict| is invalidated at this point, so it needs to be reset.
update->GetDictionary(update->GetSize() - 1, &dict);
- dict->SetString(kAccountKeyPath, account_id_16);
+ dict->SetString(kAccountKeyPath, account_info.account_id.id);
}
dict->SetString(kAccountEmailPath, account_info.email);
@@ -607,13 +565,13 @@ void AccountTrackerService::RemoveFromPrefs(const AccountInfo& account_info) {
if (!pref_service_)
return;
- base::string16 account_id_16 = base::UTF8ToUTF16(account_info.account_id);
ListPrefUpdate update(pref_service_, prefs::kAccountInfo);
for (size_t i = 0; i < update->GetSize(); ++i) {
base::DictionaryValue* dict = nullptr;
if (update->GetDictionary(i, &dict)) {
- base::string16 value;
- if (dict->GetString(kAccountKeyPath, &value) && value == account_id_16) {
+ std::string value;
+ if (dict->GetString(kAccountKeyPath, &value) &&
+ value == account_info.account_id.id) {
update->Remove(i, nullptr);
break;
}
@@ -621,14 +579,14 @@ void AccountTrackerService::RemoveFromPrefs(const AccountInfo& account_info) {
}
}
-std::string AccountTrackerService::PickAccountIdForAccount(
+CoreAccountId AccountTrackerService::PickAccountIdForAccount(
const std::string& gaia,
const std::string& email) const {
return PickAccountIdForAccount(pref_service_, gaia, email);
}
// static
-std::string AccountTrackerService::PickAccountIdForAccount(
+CoreAccountId AccountTrackerService::PickAccountIdForAccount(
const PrefService* pref_service,
const std::string& gaia,
const std::string& email) {
@@ -639,29 +597,24 @@ std::string AccountTrackerService::PickAccountIdForAccount(
case MIGRATION_NOT_STARTED:
// Some tests don't use a real email address. To support these cases,
// don't try to canonicalize these strings.
- return (email.find('@') == std::string::npos)
- ? email
- : gaia::CanonicalizeEmail(email);
+ return CoreAccountId(email.find('@') == std::string::npos
+ ? email
+ : gaia::CanonicalizeEmail(email));
case MIGRATION_IN_PROGRESS:
case MIGRATION_DONE:
- return gaia;
+ return CoreAccountId(gaia);
default:
NOTREACHED();
- return email;
+ return CoreAccountId(email);
}
}
-std::string AccountTrackerService::SeedAccountInfo(const std::string& gaia,
- const std::string& email) {
- const std::string account_id = PickAccountIdForAccount(gaia, email);
- const bool already_exists = base::ContainsKey(accounts_, account_id);
- StartTrackingAccount(account_id);
- AccountInfo& account_info = accounts_[account_id];
- DCHECK(!already_exists || account_info.gaia.empty() ||
- account_info.gaia == gaia);
+CoreAccountId AccountTrackerService::SeedAccountInfo(const std::string& gaia,
+ const std::string& email) {
+ AccountInfo account_info;
account_info.gaia = gaia;
account_info.email = email;
- SaveToPrefs(account_info);
+ CoreAccountId account_id = SeedAccountInfo(account_info);
DVLOG(1) << "AccountTrackerService::SeedAccountInfo"
<< " account_id=" << account_id << " gaia_id=" << gaia
@@ -670,14 +623,15 @@ std::string AccountTrackerService::SeedAccountInfo(const std::string& gaia,
return account_id;
}
-std::string AccountTrackerService::SeedAccountInfo(AccountInfo info) {
+CoreAccountId AccountTrackerService::SeedAccountInfo(AccountInfo info) {
info.account_id = PickAccountIdForAccount(info.gaia, info.email);
- if (!base::ContainsKey(accounts_, info.account_id)) {
- StartTrackingAccount(info.account_id);
- }
-
+ const bool already_exists = base::ContainsKey(accounts_, info.account_id);
+ StartTrackingAccount(info.account_id);
AccountInfo& account_info = accounts_[info.account_id];
+ DCHECK(!already_exists || account_info.gaia.empty() ||
+ account_info.gaia == info.gaia);
+
// Update the missing fields in |account_info| with |info|.
if (account_info.UpdateWith(info)) {
if (!account_info.gaia.empty())
@@ -688,7 +642,7 @@ std::string AccountTrackerService::SeedAccountInfo(AccountInfo info) {
return info.account_id;
}
-void AccountTrackerService::RemoveAccount(const std::string& account_id) {
+void AccountTrackerService::RemoveAccount(const CoreAccountId& account_id) {
StopTrackingAccount(account_id);
}
diff --git a/chromium/components/signin/core/browser/account_tracker_service.h b/chromium/components/signin/core/browser/account_tracker_service.h
index 5bf928b49e5..e0511f891da 100644
--- a/chromium/components/signin/core/browser/account_tracker_service.h
+++ b/chromium/components/signin/core/browser/account_tracker_service.h
@@ -19,6 +19,7 @@
#include "build/build_config.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/signin/core/browser/account_info.h"
+#include "google_apis/gaia/core_account_id.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "ui/gfx/image/image.h"
@@ -46,9 +47,8 @@ void SimulateSuccessfulFetchOfAccountInfo(IdentityManager*,
const std::string&);
}
-// AccountTrackerService is a KeyedService that retrieves and caches GAIA
-// information about Google Accounts.
-class AccountTrackerService : public KeyedService {
+// Retrieves and caches GAIA information about Google Accounts.
+class AccountTrackerService {
public:
// Clients of AccountTrackerService can implement this interface and register
// with AddObserver() to learn about account information changes.
@@ -56,7 +56,6 @@ class AccountTrackerService : public KeyedService {
public:
virtual ~Observer() {}
virtual void OnAccountUpdated(const AccountInfo& info) {}
- virtual void OnAccountUpdateFailed(const std::string& account_id) {}
virtual void OnAccountRemoved(const AccountInfo& info) {}
};
@@ -72,13 +71,12 @@ class AccountTrackerService : public KeyedService {
};
AccountTrackerService();
- ~AccountTrackerService() override;
+ ~AccountTrackerService();
// Registers the preferences used by AccountTrackerService.
static void RegisterPrefs(PrefRegistrySimple* registry);
- // KeyedService implementation.
- void Shutdown() override;
+ void Shutdown();
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
@@ -91,37 +89,38 @@ class AccountTrackerService : public KeyedService {
// Returns the list of known accounts and for which gaia IDs
// have been fetched.
std::vector<AccountInfo> GetAccounts() const;
- AccountInfo GetAccountInfo(const std::string& account_id) const;
+ AccountInfo GetAccountInfo(const CoreAccountId& account_id) const;
AccountInfo FindAccountInfoByGaiaId(const std::string& gaia_id) const;
AccountInfo FindAccountInfoByEmail(const std::string& email) const;
// Picks the correct account_id for the specified account depending on the
// migration state.
- std::string PickAccountIdForAccount(const std::string& gaia,
- const std::string& email) const;
- static std::string PickAccountIdForAccount(const PrefService* pref_service,
- const std::string& gaia,
- const std::string& email);
+ CoreAccountId PickAccountIdForAccount(const std::string& gaia,
+ const std::string& email) const;
+ static CoreAccountId PickAccountIdForAccount(const PrefService* pref_service,
+ const std::string& gaia,
+ const std::string& email);
// Seeds the account whose account_id is given by PickAccountIdForAccount()
// with its corresponding gaia id and email address. Returns the same
// value PickAccountIdForAccount() when given the same arguments.
- std::string SeedAccountInfo(const std::string& gaia,
- const std::string& email);
+ CoreAccountId SeedAccountInfo(const std::string& gaia,
+ const std::string& email);
// Seeds the account represented by |info|. If the account is already tracked
// and compatible, the empty fields will be updated with values from |info|.
// If after the update IsValid() is true, OnAccountUpdated will be fired.
- std::string SeedAccountInfo(AccountInfo info);
+ CoreAccountId SeedAccountInfo(AccountInfo info);
// Sets whether the account is a Unicorn account.
- void SetIsChildAccount(const std::string& account_id, bool is_child_account);
+ void SetIsChildAccount(const CoreAccountId& account_id,
+ bool is_child_account);
// Sets whether the account is under advanced protection.
- void SetIsAdvancedProtectionAccount(const std::string& account_id,
+ void SetIsAdvancedProtectionAccount(const CoreAccountId& account_id,
bool is_under_advanced_protection);
- void RemoveAccount(const std::string& account_id);
+ void RemoveAccount(const CoreAccountId& account_id);
// Is migration of the account id from normalized email to gaia id supported
// on the current platform?
@@ -137,12 +136,13 @@ class AccountTrackerService : public KeyedService {
protected:
// Available to be called in tests.
- void SetAccountInfoFromUserInfo(const std::string& account_id,
+ void SetAccountInfoFromUserInfo(const CoreAccountId& account_id,
const base::DictionaryValue* user_info);
// Updates the account image. Does nothing if |account_id| does not exist in
// |accounts_|.
- void SetAccountImage(const std::string& account_id, const gfx::Image& image);
+ void SetAccountImage(const CoreAccountId& account_id,
+ const gfx::Image& image);
private:
friend class AccountFetcherService;
@@ -158,11 +158,10 @@ class AccountTrackerService : public KeyedService {
const std::string&);
void NotifyAccountUpdated(const AccountInfo& account_info);
- void NotifyAccountUpdateFailed(const std::string& account_id);
- void NotifyAccountRemoved(const AccountInfo& accoint_info);
+ void NotifyAccountRemoved(const AccountInfo& account_info);
- void StartTrackingAccount(const std::string& account_id);
- void StopTrackingAccount(const std::string& account_id);
+ void StartTrackingAccount(const CoreAccountId& account_id);
+ void StopTrackingAccount(const CoreAccountId& account_id);
// Load the current state of the account info from the preferences file.
void LoadFromPrefs();
@@ -170,12 +169,12 @@ class AccountTrackerService : public KeyedService {
void RemoveFromPrefs(const AccountInfo& account);
// Used to load/save account images from/to disc.
- base::FilePath GetImagePathFor(const std::string& account_id);
- void OnAccountImageLoaded(const std::string& account_id, gfx::Image image);
+ base::FilePath GetImagePathFor(const CoreAccountId& account_id);
+ void OnAccountImageLoaded(const CoreAccountId& account_id, gfx::Image image);
void LoadAccountImagesFromDisk();
- void SaveAccountImageToDisk(const std::string& account_id,
+ void SaveAccountImageToDisk(const CoreAccountId& account_id,
const gfx::Image& image);
- void RemoveAccountImageFromDisk(const std::string& account_id);
+ void RemoveAccountImageFromDisk(const CoreAccountId& account_id);
// Migrate accounts to be keyed by gaia id instead of normalized email.
// Requires that the migration state is set to MIGRATION_IN_PROGRESS.
@@ -198,7 +197,7 @@ class AccountTrackerService : public KeyedService {
const PrefService* pref_service);
PrefService* pref_service_ = nullptr; // Not owned.
- std::map<std::string, AccountInfo> accounts_;
+ std::map<CoreAccountId, AccountInfo> accounts_;
base::ObserverList<Observer>::Unchecked observer_list_;
base::FilePath user_data_dir_;
diff --git a/chromium/components/signin/core/browser/account_tracker_service_unittest.cc b/chromium/components/signin/core/browser/account_tracker_service_unittest.cc
index 7b0aae13a82..46eac21d21b 100644
--- a/chromium/components/signin/core/browser/account_tracker_service_unittest.cc
+++ b/chromium/components/signin/core/browser/account_tracker_service_unittest.cc
@@ -120,12 +120,16 @@ class TrackingEvent {
public:
TrackingEvent(TrackingEventType type,
const std::string& account_id,
- const std::string& gaia_id)
- : type_(type), account_id_(account_id), gaia_id_(gaia_id) {}
+ const std::string& gaia_id,
+ const std::string& email)
+ : type_(type),
+ account_id_(account_id),
+ gaia_id_(gaia_id),
+ email_(email) {}
bool operator==(const TrackingEvent& event) const {
return type_ == event.type_ && account_id_ == event.account_id_ &&
- (gaia_id_.empty() || gaia_id_ == event.gaia_id_);
+ gaia_id_ == event.gaia_id_ && email_ == event.email_;
}
std::string ToString() const {
@@ -138,8 +142,9 @@ class TrackingEvent {
typestr = "REM";
break;
}
- return base::StringPrintf("{ type: %s, account_id: %s, gaia: %s }", typestr,
- account_id_.c_str(), gaia_id_.c_str());
+ return base::StringPrintf(
+ "{ type: %s, account_id: %s, gaia: %s, email: %s }", typestr,
+ account_id_.c_str(), gaia_id_.c_str(), email_.c_str());
}
private:
@@ -148,6 +153,7 @@ class TrackingEvent {
TrackingEventType type_;
std::string account_id_;
std::string gaia_id_;
+ std::string email_;
};
bool CompareByUser(TrackingEvent a, TrackingEvent b) {
@@ -187,11 +193,13 @@ class AccountTrackerObserver : public AccountTrackerService::Observer {
};
void AccountTrackerObserver::OnAccountUpdated(const AccountInfo& ids) {
- events_.push_back(TrackingEvent(UPDATED, ids.account_id, ids.gaia));
+ events_.push_back(
+ TrackingEvent(UPDATED, ids.account_id, ids.gaia, ids.email));
}
void AccountTrackerObserver::OnAccountRemoved(const AccountInfo& ids) {
- events_.push_back(TrackingEvent(REMOVED, ids.account_id, ids.gaia));
+ events_.push_back(
+ TrackingEvent(REMOVED, ids.account_id, ids.gaia, ids.email));
}
void AccountTrackerObserver::Clear() {
@@ -331,8 +339,8 @@ class AccountTrackerServiceTest : public testing::Test {
PrefService* prefs() { return &pref_service_; }
AccountTrackerObserver* observer() { return &observer_; }
- network::TestURLLoaderFactory* test_url_loader_factory() {
- return signin_client_.test_url_loader_factory();
+ network::TestURLLoaderFactory* GetTestURLLoaderFactory() {
+ return signin_client_.GetTestURLLoaderFactory();
}
bool* force_account_id_to_email_for_legacy_tests_pointer() {
@@ -398,11 +406,11 @@ void AccountTrackerServiceTest::ReturnFetchResults(
net::HttpStatusCode response_code,
const std::string& response_string) {
GURL url = GaiaUrls::GetInstance()->oauth_user_info_url();
- EXPECT_TRUE(test_url_loader_factory()->IsPending(url.spec()));
+ EXPECT_TRUE(GetTestURLLoaderFactory()->IsPending(url.spec()));
// It's possible for multiple requests to be pending. Respond to all of them.
- while (test_url_loader_factory()->IsPending(url.spec())) {
- test_url_loader_factory()->SimulateResponseForPendingRequest(
+ while (GetTestURLLoaderFactory()->IsPending(url.spec())) {
+ GetTestURLLoaderFactory()->SimulateResponseForPendingRequest(
url, network::URLLoaderCompletionStatus(net::OK),
network::CreateResourceResponseHead(response_code), response_string,
network::TestURLLoaderFactory::kMostRecentMatch);
@@ -430,14 +438,14 @@ void AccountTrackerServiceTest::ReturnAccountInfoFetchFailure(
void AccountTrackerServiceTest::ReturnAccountImageFetchSuccess(
AccountKey account_key) {
- test_url_loader_factory()->AddResponse(
+ GetTestURLLoaderFactory()->AddResponse(
AccountKeyToPictureURLWithSize(account_key), "image data");
scoped_task_environment_.RunUntilIdle();
}
void AccountTrackerServiceTest::ReturnAccountImageFetchFailure(
AccountKey account_key) {
- test_url_loader_factory()->AddResponse(
+ GetTestURLLoaderFactory()->AddResponse(
AccountKeyToPictureURLWithSize(account_key), std::string(),
net::HTTP_BAD_REQUEST);
scoped_task_environment_.RunUntilIdle();
@@ -464,7 +472,8 @@ TEST_F(AccountTrackerServiceTest, TokenAvailable_UserInfo_ImageSuccess) {
EXPECT_TRUE(account_fetcher()->IsAllUserInfoFetched());
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyAlpha),
- AccountKeyToGaiaId(kAccountKeyAlpha)),
+ AccountKeyToGaiaId(kAccountKeyAlpha),
+ AccountKeyToEmail(kAccountKeyAlpha)),
}));
EXPECT_TRUE(account_tracker()
@@ -473,7 +482,8 @@ TEST_F(AccountTrackerServiceTest, TokenAvailable_UserInfo_ImageSuccess) {
ReturnAccountImageFetchSuccess(kAccountKeyAlpha);
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyAlpha),
- AccountKeyToGaiaId(kAccountKeyAlpha)),
+ AccountKeyToGaiaId(kAccountKeyAlpha),
+ AccountKeyToEmail(kAccountKeyAlpha)),
}));
EXPECT_FALSE(account_tracker()
->GetAccountInfo(AccountKeyToAccountId(kAccountKeyAlpha))
@@ -486,7 +496,8 @@ TEST_F(AccountTrackerServiceTest, TokenAvailable_UserInfo_ImageFailure) {
EXPECT_TRUE(account_fetcher()->IsAllUserInfoFetched());
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyAlpha),
- AccountKeyToGaiaId(kAccountKeyAlpha)),
+ AccountKeyToGaiaId(kAccountKeyAlpha),
+ AccountKeyToEmail(kAccountKeyAlpha)),
}));
EXPECT_TRUE(account_tracker()
@@ -504,12 +515,14 @@ TEST_F(AccountTrackerServiceTest, TokenAvailable_UserInfo_Revoked) {
EXPECT_TRUE(account_fetcher()->IsAllUserInfoFetched());
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyAlpha),
- AccountKeyToGaiaId(kAccountKeyAlpha)),
+ AccountKeyToGaiaId(kAccountKeyAlpha),
+ AccountKeyToEmail(kAccountKeyAlpha)),
}));
SimulateTokenRevoked(kAccountKeyAlpha);
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(REMOVED, AccountKeyToAccountId(kAccountKeyAlpha),
- AccountKeyToGaiaId(kAccountKeyAlpha)),
+ AccountKeyToGaiaId(kAccountKeyAlpha),
+ AccountKeyToEmail(kAccountKeyAlpha)),
}));
}
@@ -526,7 +539,8 @@ TEST_F(AccountTrackerServiceTest, TokenAvailableTwice_UserInfoOnce) {
EXPECT_TRUE(account_fetcher()->IsAllUserInfoFetched());
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyAlpha),
- AccountKeyToGaiaId(kAccountKeyAlpha)),
+ AccountKeyToGaiaId(kAccountKeyAlpha),
+ AccountKeyToEmail(kAccountKeyAlpha)),
}));
SimulateTokenAvailable(kAccountKeyAlpha);
@@ -549,9 +563,11 @@ TEST_F(AccountTrackerServiceTest, TwoTokenAvailable_TwoUserInfo) {
EXPECT_TRUE(account_fetcher()->IsAllUserInfoFetched());
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyAlpha),
- AccountKeyToGaiaId(kAccountKeyAlpha)),
+ AccountKeyToGaiaId(kAccountKeyAlpha),
+ AccountKeyToEmail(kAccountKeyAlpha)),
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyBeta),
- AccountKeyToGaiaId(kAccountKeyBeta)),
+ AccountKeyToGaiaId(kAccountKeyBeta),
+ AccountKeyToEmail(kAccountKeyBeta)),
}));
}
@@ -562,13 +578,15 @@ TEST_F(AccountTrackerServiceTest, TwoTokenAvailable_OneUserInfo) {
EXPECT_FALSE(account_fetcher()->IsAllUserInfoFetched());
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyBeta),
- AccountKeyToGaiaId(kAccountKeyBeta)),
+ AccountKeyToGaiaId(kAccountKeyBeta),
+ AccountKeyToEmail(kAccountKeyBeta)),
}));
ReturnAccountInfoFetchSuccess(kAccountKeyAlpha);
EXPECT_TRUE(account_fetcher()->IsAllUserInfoFetched());
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyAlpha),
- AccountKeyToGaiaId(kAccountKeyAlpha)),
+ AccountKeyToGaiaId(kAccountKeyAlpha),
+ AccountKeyToEmail(kAccountKeyAlpha)),
}));
}
@@ -619,7 +637,7 @@ TEST_F(AccountTrackerServiceTest, GetAccountInfo_TokenAvailable_EnableNetwork) {
SimulateTokenAvailable(kAccountKeyAlpha);
IssueAccessToken(kAccountKeyAlpha);
// No fetcher has been created yet.
- EXPECT_EQ(0, test_url_loader_factory()->NumPending());
+ EXPECT_EQ(0, GetTestURLLoaderFactory()->NumPending());
// Enable the network to create the fetcher then issue the access token.
account_fetcher()->EnableNetworkFetchesForTest();
@@ -689,17 +707,21 @@ TEST_F(AccountTrackerServiceTest, Persistence) {
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyAlpha),
- AccountKeyToGaiaId(kAccountKeyAlpha)),
+ AccountKeyToGaiaId(kAccountKeyAlpha),
+ AccountKeyToEmail(kAccountKeyAlpha)),
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyBeta),
- AccountKeyToGaiaId(kAccountKeyBeta)),
+ AccountKeyToGaiaId(kAccountKeyBeta),
+ AccountKeyToEmail(kAccountKeyBeta)),
}));
// Wait until all account images are loaded.
scoped_task_environment_.RunUntilIdle();
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyAlpha),
- AccountKeyToGaiaId(kAccountKeyAlpha)),
+ AccountKeyToGaiaId(kAccountKeyAlpha),
+ AccountKeyToEmail(kAccountKeyAlpha)),
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyBeta),
- AccountKeyToGaiaId(kAccountKeyBeta)),
+ AccountKeyToGaiaId(kAccountKeyBeta),
+ AccountKeyToEmail(kAccountKeyBeta)),
}));
std::vector<AccountInfo> infos = account_tracker()->GetAccounts();
@@ -740,20 +762,36 @@ TEST_F(AccountTrackerServiceTest, Persistence) {
}
TEST_F(AccountTrackerServiceTest, SeedAccountInfo) {
- std::vector<AccountInfo> infos = account_tracker()->GetAccounts();
- EXPECT_EQ(0u, infos.size());
+ EXPECT_TRUE(account_tracker()->GetAccounts().empty());
- const std::string gaia_id = AccountKeyToGaiaId(kAccountKeyAlpha);
- const std::string email = AccountKeyToEmail(kAccountKeyAlpha);
+ const std::string gaia_id = AccountKeyToGaiaId(kAccountKeyFooBar);
+ const std::string email = AccountKeyToEmail(kAccountKeyFooBar);
+ const std::string email_dotted = AccountKeyToEmail(kAccountKeyFooDotBar);
const std::string account_id =
account_tracker()->PickAccountIdForAccount(gaia_id, email);
- account_tracker()->SeedAccountInfo(gaia_id, email);
- infos = account_tracker()->GetAccounts();
+ account_tracker()->SeedAccountInfo(gaia_id, email);
+ auto infos = account_tracker()->GetAccounts();
ASSERT_EQ(1u, infos.size());
EXPECT_EQ(account_id, infos[0].account_id);
EXPECT_EQ(gaia_id, infos[0].gaia);
EXPECT_EQ(email, infos[0].email);
+ EXPECT_TRUE(observer()->CheckEvents({
+ TrackingEvent(UPDATED, account_id, gaia_id, email),
+ }));
+
+ account_tracker()->SeedAccountInfo(gaia_id, email_dotted);
+ infos = account_tracker()->GetAccounts();
+ ASSERT_EQ(1u, infos.size()) << "Seeding information to an existing account "
+ "should not add a new account";
+ EXPECT_EQ(account_id, infos[0].account_id)
+ << "Account id is either the canonicalized email or gaia, it should "
+ "remain the same";
+ EXPECT_EQ(gaia_id, infos[0].gaia);
+ EXPECT_EQ(email_dotted, infos[0].email) << "Email should be changed";
+ EXPECT_TRUE(observer()->CheckEvents({
+ TrackingEvent(UPDATED, account_id, gaia_id, email_dotted),
+ }));
}
TEST_F(AccountTrackerServiceTest, SeedAccountInfoFull) {
@@ -770,7 +808,7 @@ TEST_F(AccountTrackerServiceTest, SeedAccountInfoFull) {
EXPECT_EQ(info.email, stored_info.email);
EXPECT_EQ(info.full_name, stored_info.full_name);
EXPECT_TRUE(observer()->CheckEvents({
- TrackingEvent(UPDATED, info.account_id, info.gaia),
+ TrackingEvent(UPDATED, info.account_id, info.gaia, info.email),
}));
// Validate that seeding new full informations to an existing account works
@@ -785,7 +823,7 @@ TEST_F(AccountTrackerServiceTest, SeedAccountInfoFull) {
EXPECT_EQ(info.email, stored_info.email);
EXPECT_EQ(info.given_name, stored_info.given_name);
EXPECT_TRUE(observer()->CheckEvents({
- TrackingEvent(UPDATED, info.account_id, info.gaia),
+ TrackingEvent(UPDATED, info.account_id, info.gaia, info.email),
}));
// Validate that seeding invalid information to an existing account doesn't
@@ -827,7 +865,8 @@ TEST_F(AccountTrackerServiceTest, UpgradeToFullAccountInfo) {
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyIncomplete),
- AccountKeyToGaiaId(kAccountKeyIncomplete)),
+ AccountKeyToGaiaId(kAccountKeyIncomplete),
+ AccountKeyToEmail(kAccountKeyIncomplete)),
}));
// Enabling network fetches shouldn't cause any actual fetch since the
@@ -923,48 +962,6 @@ TEST_F(AccountTrackerServiceTest, LegacyDottedAccountIds) {
EXPECT_EQ(AccountKeyToEmail(kAccountKeyFooBar), infos[0].email);
}
-TEST_F(AccountTrackerServiceTest, NoDeprecatedServiceFlags) {
- const std::string email_alpha = AccountKeyToEmail(kAccountKeyAlpha);
- const std::string gaia_alpha = AccountKeyToGaiaId(kAccountKeyAlpha);
-
- ListPrefUpdate update(prefs(), prefs::kAccountInfo);
-
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
- dict->SetString("account_id", email_alpha);
- dict->SetString("email", email_alpha);
- dict->SetString("gaia", gaia_alpha);
- update->Append(std::move(dict));
-
- base::HistogramTester tester;
-
- ResetAccountTracker();
- tester.ExpectBucketCount("Signin.AccountTracker.DeprecatedServiceFlagDeleted",
- false, 1);
-}
-
-TEST_F(AccountTrackerServiceTest, MigrateDeprecatedServiceFlags) {
- const std::string email_alpha = AccountKeyToEmail(kAccountKeyAlpha);
- const std::string gaia_alpha = AccountKeyToGaiaId(kAccountKeyAlpha);
-
- ListPrefUpdate update(prefs(), prefs::kAccountInfo);
-
- std::unique_ptr<base::ListValue> service_flags(new base::ListValue());
- service_flags->Append(std::make_unique<base::Value>("uca"));
-
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
- dict->SetString("account_id", email_alpha);
- dict->SetString("email", email_alpha);
- dict->SetString("gaia", gaia_alpha);
- dict->SetList("service_flags", std::move(service_flags));
- update->Append(std::move(dict));
-
- base::HistogramTester tester;
-
- ResetAccountTracker();
- tester.ExpectBucketCount("Signin.AccountTracker.DeprecatedServiceFlagDeleted",
- true, 1);
-}
-
TEST_F(AccountTrackerServiceTest, MigrateAccountIdToGaiaId) {
if (!AccountTrackerService::IsMigrationSupported())
return;
@@ -1158,7 +1155,8 @@ TEST_F(AccountTrackerServiceTest, ChildAccountUpdatedAndRevoked) {
GenerateValidTokenInfoResponse(kAccountKeyChild));
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyChild),
- AccountKeyToGaiaId(kAccountKeyChild)),
+ AccountKeyToGaiaId(kAccountKeyChild),
+ AccountKeyToEmail(kAccountKeyChild)),
}));
AccountInfo info = account_tracker()->GetAccountInfo(
AccountKeyToAccountId(kAccountKeyChild));
@@ -1166,7 +1164,8 @@ TEST_F(AccountTrackerServiceTest, ChildAccountUpdatedAndRevoked) {
SimulateTokenRevoked(kAccountKeyChild);
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(REMOVED, AccountKeyToAccountId(kAccountKeyChild),
- AccountKeyToGaiaId(kAccountKeyChild)),
+ AccountKeyToGaiaId(kAccountKeyChild),
+ AccountKeyToEmail(kAccountKeyChild)),
}));
}
@@ -1184,7 +1183,8 @@ TEST_F(AccountTrackerServiceTest, ChildAccountUpdatedAndRevokedWithUpdate) {
GenerateValidTokenInfoResponse(kAccountKeyChild));
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyChild),
- AccountKeyToGaiaId(kAccountKeyChild)),
+ AccountKeyToGaiaId(kAccountKeyChild),
+ AccountKeyToEmail(kAccountKeyChild)),
}));
AccountInfo info = account_tracker()->GetAccountInfo(
AccountKeyToAccountId(kAccountKeyChild));
@@ -1194,14 +1194,17 @@ TEST_F(AccountTrackerServiceTest, ChildAccountUpdatedAndRevokedWithUpdate) {
// On Android, is_child_account is set to false before removing it.
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyChild),
- AccountKeyToGaiaId(kAccountKeyChild)),
+ AccountKeyToGaiaId(kAccountKeyChild),
+ AccountKeyToEmail(kAccountKeyChild)),
TrackingEvent(REMOVED, AccountKeyToAccountId(kAccountKeyChild),
- AccountKeyToGaiaId(kAccountKeyChild)),
+ AccountKeyToGaiaId(kAccountKeyChild),
+ AccountKeyToEmail(kAccountKeyChild)),
}));
#else
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(REMOVED, AccountKeyToAccountId(kAccountKeyChild),
- AccountKeyToGaiaId(kAccountKeyChild)),
+ AccountKeyToGaiaId(kAccountKeyChild),
+ AccountKeyToEmail(kAccountKeyChild)),
}));
#endif
}
@@ -1221,23 +1224,28 @@ TEST_F(AccountTrackerServiceTest, ChildAccountUpdatedTwiceThenRevoked) {
#endif
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyChild),
- AccountKeyToGaiaId(kAccountKeyChild)),
+ AccountKeyToGaiaId(kAccountKeyChild),
+ AccountKeyToEmail(kAccountKeyChild)),
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyChild),
- AccountKeyToGaiaId(kAccountKeyChild)),
+ AccountKeyToGaiaId(kAccountKeyChild),
+ AccountKeyToEmail(kAccountKeyChild)),
}));
SimulateTokenRevoked(kAccountKeyChild);
#if defined(OS_ANDROID)
// On Android, is_child_account is set to false before removing it.
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyChild),
- AccountKeyToGaiaId(kAccountKeyChild)),
+ AccountKeyToGaiaId(kAccountKeyChild),
+ AccountKeyToEmail(kAccountKeyChild)),
TrackingEvent(REMOVED, AccountKeyToAccountId(kAccountKeyChild),
- AccountKeyToGaiaId(kAccountKeyChild)),
+ AccountKeyToGaiaId(kAccountKeyChild),
+ AccountKeyToEmail(kAccountKeyChild)),
}));
#else
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(REMOVED, AccountKeyToAccountId(kAccountKeyChild),
- AccountKeyToGaiaId(kAccountKeyChild)),
+ AccountKeyToGaiaId(kAccountKeyChild),
+ AccountKeyToEmail(kAccountKeyChild)),
}));
#endif
}
@@ -1261,7 +1269,8 @@ TEST_F(AccountTrackerServiceTest, ChildAccountGraduation) {
GenerateValidTokenInfoResponse(kAccountKeyChild));
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyChild),
- AccountKeyToGaiaId(kAccountKeyChild)),
+ AccountKeyToGaiaId(kAccountKeyChild),
+ AccountKeyToEmail(kAccountKeyChild)),
}));
// Now simulate child account graduation.
@@ -1277,13 +1286,15 @@ TEST_F(AccountTrackerServiceTest, ChildAccountGraduation) {
EXPECT_FALSE(info.is_child_account);
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyChild),
- AccountKeyToGaiaId(kAccountKeyChild)),
+ AccountKeyToGaiaId(kAccountKeyChild),
+ AccountKeyToEmail(kAccountKeyChild)),
}));
SimulateTokenRevoked(kAccountKeyChild);
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(REMOVED, AccountKeyToAccountId(kAccountKeyChild),
- AccountKeyToGaiaId(kAccountKeyChild)),
+ AccountKeyToGaiaId(kAccountKeyChild),
+ AccountKeyToEmail(kAccountKeyChild)),
}));
}
@@ -1293,14 +1304,16 @@ TEST_F(AccountTrackerServiceTest, RemoveAccountBeforeImageFetchDone) {
ReturnAccountInfoFetchSuccess(kAccountKeyAlpha);
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyAlpha),
- AccountKeyToGaiaId(kAccountKeyAlpha)),
+ AccountKeyToGaiaId(kAccountKeyAlpha),
+ AccountKeyToEmail(kAccountKeyAlpha)),
}));
SimulateTokenRevoked(kAccountKeyAlpha);
ReturnAccountImageFetchFailure(kAccountKeyAlpha);
EXPECT_TRUE(observer()->CheckEvents({
TrackingEvent(REMOVED, AccountKeyToAccountId(kAccountKeyAlpha),
- AccountKeyToGaiaId(kAccountKeyAlpha)),
+ AccountKeyToGaiaId(kAccountKeyAlpha),
+ AccountKeyToEmail(kAccountKeyAlpha)),
}));
}
diff --git a/chromium/components/signin/core/browser/android/OWNERS b/chromium/components/signin/core/browser/android/OWNERS
deleted file mode 100644
index e50e23c175d..00000000000
--- a/chromium/components/signin/core/browser/android/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-bsazonov@chromium.org
-
-# COMPONENT: Services>SignIn
diff --git a/chromium/components/signin/core/browser/android/java/src/org/chromium/components/signin/OAuth2TokenService.java b/chromium/components/signin/core/browser/android/java/src/org/chromium/components/signin/OAuth2TokenService.java
index 2158328dbbb..c05c650293f 100644
--- a/chromium/components/signin/core/browser/android/java/src/org/chromium/components/signin/OAuth2TokenService.java
+++ b/chromium/components/signin/core/browser/android/java/src/org/chromium/components/signin/OAuth2TokenService.java
@@ -23,11 +23,8 @@ import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
/**
* Java instance for the native OAuth2TokenService.
@@ -257,49 +254,6 @@ public final class OAuth2TokenService
}
/**
- * Call this method to retrieve an OAuth2 access token for the given account and scope. This
- * method times out after the specified timeout, and will return null if that happens.
- *
- * Given that this is a blocking method call, this should never be called from the UI thread.
- *
- * @param account the account to get the access token for.
- * @param scope The scope to get an auth token for (without Android-style 'oauth2:' prefix).
- * @param timeout the timeout.
- * @param unit the unit for |timeout|.
- */
- @VisibleForTesting
- public static String getAccessTokenWithTimeout(
- Account account, String scope, long timeout, TimeUnit unit) {
- assert !ThreadUtils.runningOnUiThread();
- final AtomicReference<String> result = new AtomicReference<>();
- final Semaphore semaphore = new Semaphore(0);
- getAccessToken(account, scope, new GetAccessTokenCallback() {
- @Override
- public void onGetTokenSuccess(String token) {
- result.set(token);
- semaphore.release();
- }
-
- @Override
- public void onGetTokenFailure(boolean isTransientError) {
- result.set(null);
- semaphore.release();
- }
- });
- try {
- if (semaphore.tryAcquire(timeout, unit)) {
- return result.get();
- } else {
- Log.d(TAG, "Failed to retrieve auth token within timeout (%s %s)", timeout, unit);
- return null;
- }
- } catch (InterruptedException e) {
- Log.w(TAG, "Got interrupted while waiting for auth token");
- return null;
- }
- }
-
- /**
* Called by native to check whether the account has an OAuth2 refresh token.
*/
@CalledByNative
@@ -394,7 +348,12 @@ public final class OAuth2TokenService
}
@CalledByNative
- private static void saveStoredAccounts(String[] accounts) {
+ /**
+ * Called by native to save the account IDs that have associated OAuth2 refresh tokens.
+ * This is called during updateAccountList to sync with getSystemAccountNames.
+ * @param accounts IDs to save.
+ */
+ private static void setAccounts(String[] accounts) {
Set<String> set = new HashSet<>(Arrays.asList(accounts));
ContextUtils.getAppSharedPreferences()
.edit()
diff --git a/chromium/components/signin/core/browser/avatar_icon_util.cc b/chromium/components/signin/core/browser/avatar_icon_util.cc
index 5e613d24b9c..2a74566b464 100644
--- a/chromium/components/signin/core/browser/avatar_icon_util.cc
+++ b/chromium/components/signin/core/browser/avatar_icon_util.cc
@@ -5,6 +5,7 @@
#include "components/signin/core/browser/avatar_icon_util.h"
#include <string>
+#include <vector>
#include "base/stl_util.h"
#include "base/strings/string_split.h"
@@ -16,20 +17,25 @@
namespace {
// Separator of URL path components.
-const char kURLPathSeparator[] = "/";
+constexpr char kURLPathSeparator[] = "/";
-// Constants describing image URL format.
+// Constants describing legacy image URL format.
// See https://crbug.com/733306#c3 for details.
-const size_t kImageURLPathComponentsCount = 6;
-const size_t kImageURLPathComponentsCountWithOptions = 7;
-const size_t kImageURLPathOptionsComponentPosition = 5;
+constexpr size_t kLegacyURLPathComponentsCount = 6;
+constexpr size_t kLegacyURLPathComponentsCountWithOptions = 7;
+constexpr size_t kLegacyURLPathOptionsComponentPosition = 5;
+// Constants describing content image URL format.
+// See https://crbug.com/911332#c15 for details.
+constexpr size_t kContentURLPathMinComponentsCount = 2;
+constexpr size_t kContentURLPathMaxComponentsCount = 3;
+constexpr char kContentURLOptionsStartChar = '=';
// Various options that can be embedded in image URL.
-const char kImageURLOptionSeparator[] = "-";
-const char kImageURLOptionSizePattern[] = R"(s\d+)";
-const char kImageURLOptionSizeFormat[] = "s%d";
-const char kImageURLOptionSquareCrop[] = "c";
+constexpr char kImageURLOptionSeparator[] = "-";
+constexpr char kImageURLOptionSizePattern[] = R"(s\d+)";
+constexpr char kImageURLOptionSizeFormat[] = "s%d";
+constexpr char kImageURLOptionSquareCrop[] = "c";
// Option to disable default avatar if user doesn't have a custom one.
-const char kImageURLOptionNoSilhouette[] = "ns";
+constexpr char kImageURLOptionNoSilhouette[] = "ns";
std::string BuildImageURLOptionsString(int image_size,
bool no_silhouette,
@@ -53,6 +59,62 @@ std::string BuildImageURLOptionsString(int image_size,
return base::JoinString(url_options, kImageURLOptionSeparator);
}
+// Returns an empty vector if |url_components| couldn't be processed as a legacy
+// image URL.
+std::vector<std::string> TryProcessAsLegacyImageURL(
+ std::vector<std::string> url_components,
+ int image_size,
+ bool no_silhouette) {
+ if (url_components.back().empty())
+ return {};
+
+ if (url_components.size() == kLegacyURLPathComponentsCount) {
+ url_components.insert(
+ url_components.begin() + kLegacyURLPathOptionsComponentPosition,
+ BuildImageURLOptionsString(image_size, no_silhouette, std::string()));
+ return url_components;
+ }
+
+ if (url_components.size() == kLegacyURLPathComponentsCountWithOptions) {
+ std::string options =
+ url_components.at(kLegacyURLPathOptionsComponentPosition);
+ url_components[kLegacyURLPathOptionsComponentPosition] =
+ BuildImageURLOptionsString(image_size, no_silhouette, options);
+ return url_components;
+ }
+
+ return {};
+}
+
+// Returns an empty vector if |url_components| couldn't be processed as a
+// content image URL.
+std::vector<std::string> TryProcessAsContentImageURL(
+ std::vector<std::string> url_components,
+ int image_size,
+ bool no_silhouette) {
+ if (url_components.size() < kContentURLPathMinComponentsCount ||
+ url_components.size() > kContentURLPathMaxComponentsCount ||
+ url_components.back().empty()) {
+ return {};
+ }
+
+ std::string* options_component = &url_components.back();
+ // Extract existing options from |options_component|.
+ const size_t options_pos =
+ options_component->find(kContentURLOptionsStartChar);
+ std::string component_without_options =
+ options_component->substr(0, options_pos);
+ std::string existing_options =
+ options_pos == std::string::npos
+ ? ""
+ : options_component->substr(options_pos + 1);
+ // Update options in |options_component|.
+ *options_component =
+ component_without_options + kContentURLOptionsStartChar +
+ BuildImageURLOptionsString(image_size, no_silhouette, existing_options);
+ return url_components;
+}
+
} // namespace
namespace signin {
@@ -66,24 +128,20 @@ GURL GetAvatarImageURLWithOptions(const GURL& old_url,
base::SplitString(old_url.path(), kURLPathSeparator,
base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
- if (components.size() < kImageURLPathComponentsCount ||
- components.size() > kImageURLPathComponentsCountWithOptions ||
- components.back().empty()) {
- return old_url;
+ auto new_components =
+ TryProcessAsContentImageURL(components, image_size, no_silhouette);
+
+ if (new_components.empty()) {
+ new_components =
+ TryProcessAsLegacyImageURL(components, image_size, no_silhouette);
}
- if (components.size() == kImageURLPathComponentsCount) {
- components.insert(
- components.begin() + kImageURLPathOptionsComponentPosition,
- BuildImageURLOptionsString(image_size, no_silhouette, std::string()));
- } else {
- DCHECK_EQ(kImageURLPathComponentsCountWithOptions, components.size());
- std::string options = components.at(kImageURLPathOptionsComponentPosition);
- components[kImageURLPathOptionsComponentPosition] =
- BuildImageURLOptionsString(image_size, no_silhouette, options);
+ if (new_components.empty()) {
+ // URL doesn't match any known patterns, so return unchanged.
+ return old_url;
}
- std::string new_path = base::JoinString(components, kURLPathSeparator);
+ std::string new_path = base::JoinString(new_components, kURLPathSeparator);
GURL::Replacements replacement;
replacement.SetPathStr(new_path);
return old_url.ReplaceComponents(replacement);
diff --git a/chromium/components/signin/core/browser/avatar_icon_util_unittest.cc b/chromium/components/signin/core/browser/avatar_icon_util_unittest.cc
index 7f592916406..f3686240080 100644
--- a/chromium/components/signin/core/browser/avatar_icon_util_unittest.cc
+++ b/chromium/components/signin/core/browser/avatar_icon_util_unittest.cc
@@ -9,7 +9,7 @@
namespace {
-TEST(AvatarIconUtilTest, GetAvatarImageURLWithOptionsNoInitialSize) {
+TEST(AvatarIconUtilTest, GetAvatarImageURLWithOptionsNoInitialSize_LegacyURL) {
GURL in("http://example.com/-A/AAAAAAAAAAI/AAAAAAAAACQ/B/photo.jpg");
GURL result =
signin::GetAvatarImageURLWithOptions(in, 128, false /* no_silhouette */);
@@ -18,7 +18,8 @@ TEST(AvatarIconUtilTest, GetAvatarImageURLWithOptionsNoInitialSize) {
EXPECT_EQ(result, expected);
}
-TEST(AvatarIconUtilTest, GetAvatarImageURLWithOptionsSizeAlreadySpecified) {
+TEST(AvatarIconUtilTest,
+ GetAvatarImageURLWithOptionsSizeAlreadySpecified_LegacyURL) {
// If there's already a size specified in the URL, it should be changed to the
// specified size in the resulting URL.
GURL in("http://example.com/-A/AAAAAAAAAAI/AAAAAAAAACQ/B/s64-c/photo.jpg");
@@ -29,7 +30,8 @@ TEST(AvatarIconUtilTest, GetAvatarImageURLWithOptionsSizeAlreadySpecified) {
EXPECT_EQ(result, expected);
}
-TEST(AvatarIconUtilTest, GetAvatarImageURLWithOptionsOtherSizeSpecified) {
+TEST(AvatarIconUtilTest,
+ GetAvatarImageURLWithOptionsOtherSizeSpecified_LegacyURL) {
// If there's already a size specified in the URL, it should be changed to the
// specified size in the resulting URL.
GURL in("http://example.com/-A/AAAAAAAAAAI/AAAAAAAAACQ/B/s128-c/photo.jpg");
@@ -40,7 +42,7 @@ TEST(AvatarIconUtilTest, GetAvatarImageURLWithOptionsOtherSizeSpecified) {
EXPECT_EQ(result, expected);
}
-TEST(AvatarIconUtilTest, GetAvatarImageURLWithOptionsSameSize) {
+TEST(AvatarIconUtilTest, GetAvatarImageURLWithOptionsSameSize_LegacyURL) {
// If there's already a size specified in the URL, and it's already the
// requested size, true should be returned and the URL should remain
// unchanged.
@@ -52,7 +54,8 @@ TEST(AvatarIconUtilTest, GetAvatarImageURLWithOptionsSameSize) {
EXPECT_EQ(result, expected);
}
-TEST(AvatarIconUtilTest, GetAvatarImageURLWithOptionsNoFileNameInPath) {
+TEST(AvatarIconUtilTest,
+ GetAvatarImageURLWithOptionsNoFileNameInPath_LegacyURL) {
// If there is no file path component in the URL path, we should return
// the input URL.
GURL in("http://example.com/-A/AAAAAAAAAAI/AAAAAAAAACQ/B/");
@@ -61,7 +64,7 @@ TEST(AvatarIconUtilTest, GetAvatarImageURLWithOptionsNoFileNameInPath) {
EXPECT_EQ(result, in);
}
-TEST(AvatarIconUtilTest, GetAvatarImageURLWithOptionsNoSilhouette) {
+TEST(AvatarIconUtilTest, GetAvatarImageURLWithOptionsNoSilhouette_LegacyURL) {
// If there's already a size specified in the URL, it should be changed to the
// specified size in the resulting URL.
GURL in("http://example.com/-A/AAAAAAAAAAI/AAAAAAAAACQ/B/photo.jpg");
@@ -72,7 +75,8 @@ TEST(AvatarIconUtilTest, GetAvatarImageURLWithOptionsNoSilhouette) {
EXPECT_EQ(result, expected);
}
-TEST(AvatarIconUtilTest, GetAvatarImageURLWithOptionsSizeReplaceNoSilhouette) {
+TEST(AvatarIconUtilTest,
+ GetAvatarImageURLWithOptionsSizeReplaceNoSilhouette_LegacyURL) {
// If there's already a no_silhouette option specified in the URL, it should
// be removed if necessary.
GURL in("http://example.com/-A/AAAAAAAAAAI/AAAAAAAAACQ/B/s64-c-ns/photo.jpg");
@@ -83,7 +87,8 @@ TEST(AvatarIconUtilTest, GetAvatarImageURLWithOptionsSizeReplaceNoSilhouette) {
EXPECT_EQ(result, expected);
}
-TEST(AvatarIconUtilTest, GetAvatarImageURLWithOptionsUnknownShouldBePreserved) {
+TEST(AvatarIconUtilTest,
+ GetAvatarImageURLWithOptionsUnknownShouldBePreserved_LegacyURL) {
// If there are any unknown options encoded in URL,
// GetAvatarImageURLWithOptions should preserve them.
GURL in("http://example.com/-A/AAAAAAAAAAI/AAAAAAAAACQ/B/s64-mo-k/photo.jpg");
@@ -94,4 +99,20 @@ TEST(AvatarIconUtilTest, GetAvatarImageURLWithOptionsUnknownShouldBePreserved) {
EXPECT_EQ(result, expected);
}
+TEST(AvatarIconUtilTest, GetAvatarImageURLWithExistingOptions_ContentURL) {
+ GURL in("http://example.com/-A/ABcdefghijk1l2mN3=s256");
+ GURL result =
+ signin::GetAvatarImageURLWithOptions(in, 128, false /* no_silhouette */);
+ GURL expected("http://example.com/-A/ABcdefghijk1l2mN3=s128-c");
+ EXPECT_EQ(result, expected);
+}
+
+TEST(AvatarIconUtilTest, GetAvatarImageURLNoExistingOptions_ContentURL) {
+ GURL in("http://example.com/-A/ABcdefghijk1l2mN3");
+ GURL result =
+ signin::GetAvatarImageURLWithOptions(in, 128, true /* no_silhouette */);
+ GURL expected("http://example.com/-A/ABcdefghijk1l2mN3=s128-c-ns");
+ EXPECT_EQ(result, expected);
+}
+
} // namespace
diff --git a/chromium/components/signin/core/browser/gaia_cookie_manager_service.cc b/chromium/components/signin/core/browser/gaia_cookie_manager_service.cc
index 7a576c1c6cb..7f95e128b2f 100644
--- a/chromium/components/signin/core/browser/gaia_cookie_manager_service.cc
+++ b/chromium/components/signin/core/browser/gaia_cookie_manager_service.cc
@@ -10,6 +10,8 @@
#include <set>
#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
#include "base/json/json_reader.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
@@ -20,14 +22,13 @@
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
-#include "components/data_use_measurement/core/data_use_user_data.h"
#include "components/signin/core/browser/account_tracker_service.h"
+#include "components/signin/core/browser/set_accounts_in_cookie_result.h"
#include "components/signin/core/browser/signin_metrics.h"
#include "components/signin/core/browser/ubertoken_fetcher_impl.h"
#include "google_apis/gaia/gaia_constants.h"
#include "google_apis/gaia/gaia_urls.h"
#include "google_apis/gaia/oauth2_token_service.h"
-#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/cookies/cookie_change_dispatcher.h"
@@ -37,6 +38,10 @@
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
+#if defined(OS_CHROMEOS)
+#include "chromeos/constants/chromeos_switches.h"
+#endif
+
namespace signin {
MultiloginParameters::MultiloginParameters(
const gaia::MultiloginMode mode,
@@ -108,20 +113,10 @@ void RecordListAccountsFailure(GoogleServiceAuthError::State error_state) {
GoogleServiceAuthError::NUM_STATES);
}
-void RecordGetAccessTokenFinished(GoogleServiceAuthError error) {
- UMA_HISTOGRAM_ENUMERATION("Signin.GetAccessTokenFinished", error.state(),
- GoogleServiceAuthError::NUM_STATES);
-}
-
void RecordLogoutRequestState(LogoutRequestState logout_state) {
UMA_HISTOGRAM_ENUMERATION("Signin.GaiaCookieManager.Logout", logout_state);
}
-void RecordMultiloginFinished(GoogleServiceAuthError error) {
- UMA_HISTOGRAM_ENUMERATION("Signin.MultiloginFinished", error.state(),
- GoogleServiceAuthError::NUM_STATES);
-}
-
// Record ListAccounts errors for individual retries.
void RecordListAccountsRetryResult(GoogleServiceAuthError error,
int retry_attempt_number) {
@@ -191,9 +186,9 @@ const std::string GaiaCookieManagerService::GaiaCookieRequest::GetAccountID() {
void GaiaCookieManagerService::GaiaCookieRequest::
RunSetAccountsInCookieCompletedCallback(
- const GoogleServiceAuthError& error) {
+ signin::SetAccountsInCookieResult result) {
if (set_accounts_in_cookie_completed_callback_)
- std::move(set_accounts_in_cookie_completed_callback_).Run(error);
+ std::move(set_accounts_in_cookie_completed_callback_).Run(result);
}
void GaiaCookieManagerService::GaiaCookieRequest::
@@ -270,7 +265,7 @@ void GaiaCookieManagerService::ExternalCcResultFetcher::Start(
CleanupTransientState();
results_.clear();
helper_->gaia_auth_fetcher_ = helper_->signin_client_->CreateGaiaAuthFetcher(
- this, gaia::GaiaSource::kChrome, helper_->GetURLLoaderFactory());
+ this, gaia::GaiaSource::kChrome);
helper_->gaia_auth_fetcher_->StartGetCheckConnectionInfo();
// Some fetches may timeout. Start a timer to decide when the result fetcher
@@ -373,10 +368,7 @@ GaiaCookieManagerService::ExternalCcResultFetcher::CreateAndStartLoader(
auto request = std::make_unique<network::ResourceRequest>();
request->url = url;
- request->load_flags =
- net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES;
- // TODO(https://crbug.com/808498) re-add data use measurement once
- // SimpleURLLoader supports it: data_use_measurement::DataUseUserData::SIGNIN
+ request->allow_credentials = false;
std::unique_ptr<network::SimpleURLLoader> loader =
network::SimpleURLLoader::Create(std::move(request), traffic_annotation);
@@ -461,21 +453,8 @@ void GaiaCookieManagerService::ExternalCcResultFetcher::
GaiaCookieManagerService::GaiaCookieManagerService(
OAuth2TokenService* token_service,
SigninClient* signin_client)
- : GaiaCookieManagerService(
- token_service,
- signin_client,
- base::BindRepeating(&SigninClient::GetURLLoaderFactory,
- base::Unretained(signin_client))) {}
-
-GaiaCookieManagerService::GaiaCookieManagerService(
- OAuth2TokenService* token_service,
- SigninClient* signin_client,
- base::RepeatingCallback<scoped_refptr<network::SharedURLLoaderFactory>()>
- shared_url_loader_factory_getter)
- : OAuth2TokenService::Consumer("gaia_cookie_manager"),
- token_service_(token_service),
+ : token_service_(token_service),
signin_client_(signin_client),
- shared_url_loader_factory_getter_(shared_url_loader_factory_getter),
external_cc_result_fetcher_(this),
fetcher_backoff_(&kBackoffPolicy),
fetcher_retries_(0),
@@ -524,39 +503,15 @@ void GaiaCookieManagerService::SetAccountsInCookie(
account_ids, source,
std::move(set_accounts_in_cookies_completed_callback)));
if (!signin_client_->AreSigninCookiesAllowed()) {
- OnSetAccountsFinished(
- GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
+ OnSetAccountsFinished(signin::SetAccountsInCookieResult::kPersistentError);
return;
}
if (requests_.size() == 1) {
fetcher_retries_ = 0;
- signin_client_->DelayNetworkCall(base::BindOnce(
- &GaiaCookieManagerService::StartFetchingAccessTokensForMultilogin,
- base::Unretained(this)));
+ StartSetAccounts();
}
}
-void GaiaCookieManagerService::SetAccountsInCookieWithTokens() {
-#ifndef NDEBUG
- // Check that there is no duplicate accounts.
- std::set<std::string> accounts_no_duplicates(
- requests_.front().account_ids().begin(),
- requests_.front().account_ids().end());
- DCHECK_EQ(requests_.front().account_ids().size(),
- accounts_no_duplicates.size());
-#endif
-
- std::vector<GaiaAuthFetcher::MultiloginTokenIDPair> accounts =
- std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>();
- accounts.reserve(requests_.front().account_ids().size());
- int i = 0;
- for (const std::string& account_id : requests_.front().account_ids()) {
- accounts.emplace_back(account_id, access_tokens_[account_id]);
- ++i;
- }
- StartFetchingMultiLogin(accounts);
-}
-
void GaiaCookieManagerService::AddAccountToCookieInternal(
const std::string& account_id,
gaia::GaiaSource source,
@@ -575,7 +530,7 @@ void GaiaCookieManagerService::AddAccountToCookieInternal(
if (requests_.size() == 1) {
signin_client_->DelayNetworkCall(
base::BindOnce(&GaiaCookieManagerService::StartFetchingUbertoken,
- base::Unretained(this)));
+ weak_ptr_factory_.GetWeakPtr()));
}
}
@@ -627,7 +582,7 @@ void GaiaCookieManagerService::TriggerListAccounts() {
requests_.push_back(GaiaCookieRequest::CreateListAccountsRequest());
signin_client_->DelayNetworkCall(
base::BindOnce(&GaiaCookieManagerService::StartFetchingListAccounts,
- base::Unretained(this)));
+ weak_ptr_factory_.GetWeakPtr()));
} else if (std::find_if(requests_.begin(), requests_.end(),
[](const GaiaCookieRequest& request) {
return request.request_type() == LIST_ACCOUNTS;
@@ -689,8 +644,9 @@ void GaiaCookieManagerService::LogOutAllAccounts(gaia::GaiaSource source) {
requests_.push_back(GaiaCookieRequest::CreateLogOutRequest(source));
if (requests_.size() == 1) {
fetcher_retries_ = 0;
- signin_client_->DelayNetworkCall(base::BindOnce(
- &GaiaCookieManagerService::StartGaiaLogOut, base::Unretained(this)));
+ signin_client_->DelayNetworkCall(
+ base::BindOnce(&GaiaCookieManagerService::StartGaiaLogOut,
+ weak_ptr_factory_.GetWeakPtr()));
}
}
}
@@ -707,13 +663,14 @@ void GaiaCookieManagerService::CancelAll() {
VLOG(1) << "GaiaCookieManagerService::CancelAll";
gaia_auth_fetcher_.reset();
uber_token_fetcher_.reset();
+ oauth_multilogin_helper_.reset();
requests_.clear();
fetcher_timer_.Stop();
}
scoped_refptr<network::SharedURLLoaderFactory>
GaiaCookieManagerService::GetURLLoaderFactory() {
- return shared_url_loader_factory_getter_.Run();
+ return signin_client_->GetURLLoaderFactory();
}
void GaiaCookieManagerService::MarkListAccountsStale() {
@@ -750,7 +707,7 @@ void GaiaCookieManagerService::OnCookieChange(
fetcher_retries_ = 0;
signin_client_->DelayNetworkCall(
base::BindOnce(&GaiaCookieManagerService::StartFetchingListAccounts,
- base::Unretained(this)));
+ weak_ptr_factory_.GetWeakPtr()));
}
}
@@ -778,10 +735,10 @@ void GaiaCookieManagerService::SignalAddToCookieComplete(
}
void GaiaCookieManagerService::SignalSetAccountsComplete(
- const GoogleServiceAuthError& error) {
+ signin::SetAccountsInCookieResult result) {
DCHECK(requests_.front().request_type() ==
GaiaCookieRequestType::SET_ACCOUNTS);
- requests_.front().RunSetAccountsInCookieCompletedCallback(error);
+ requests_.front().RunSetAccountsInCookieCompletedCallback(result);
}
void GaiaCookieManagerService::OnUbertokenFetchComplete(
@@ -814,54 +771,7 @@ void GaiaCookieManagerService::OnUbertokenFetchComplete(
signin_client_->DelayNetworkCall(
base::BindOnce(&GaiaCookieManagerService::StartFetchingMergeSession,
- base::Unretained(this)));
-}
-
-void GaiaCookieManagerService::OnTokenFetched(const std::string& account_id,
- const std::string& token) {
- access_tokens_.insert(std::make_pair(account_id, token));
- if (access_tokens_.size() == requests_.front().account_ids().size()) {
- fetcher_retries_ = 0;
- token_requests_.clear();
- signin_client_->DelayNetworkCall(
- base::BindOnce(&GaiaCookieManagerService::SetAccountsInCookieWithTokens,
- base::Unretained(this)));
- }
-}
-
-void GaiaCookieManagerService::OnGetTokenSuccess(
- const OAuth2TokenService::Request* request,
- const OAuth2AccessTokenConsumer::TokenResponse& token_response) {
- DCHECK(requests_.front().request_type() ==
- GaiaCookieRequestType::SET_ACCOUNTS);
- fetcher_backoff_.InformOfRequest(true);
- OnTokenFetched(request->GetAccountId(), token_response.access_token);
-}
-
-void GaiaCookieManagerService::OnGetTokenFailure(
- const OAuth2TokenService::Request* request,
- const GoogleServiceAuthError& error) {
- VLOG(1) << "Failed to retrieve accesstoken"
- << " account=" << request->GetAccountId()
- << " error=" << error.ToString();
- if (++fetcher_retries_ < signin::kMaxFetcherRetries &&
- error.IsTransientError()) {
- fetcher_backoff_.InformOfRequest(false);
- UMA_HISTOGRAM_ENUMERATION("Signin.GetAccessTokenRetry", error.state(),
- GoogleServiceAuthError::NUM_STATES);
- OAuth2TokenService::ScopeSet scopes;
- scopes.insert(GaiaConstants::kOAuth1LoginScope);
- fetcher_timer_.Start(
- FROM_HERE, fetcher_backoff_.GetTimeUntilRelease(),
- base::BindOnce(
- &SigninClient::DelayNetworkCall, base::Unretained(signin_client_),
- base::BindOnce(&GaiaCookieManagerService::
- StartFetchingAccessTokenForMultilogin,
- base::Unretained(this), request->GetAccountId())));
- return;
- }
- RecordGetAccessTokenFinished(error);
- OnSetAccountsFinished(error);
+ weak_ptr_factory_.GetWeakPtr()));
}
void GaiaCookieManagerService::OnMergeSessionSuccess(const std::string& data) {
@@ -896,7 +806,7 @@ void GaiaCookieManagerService::OnMergeSessionFailure(
base::BindOnce(
&SigninClient::DelayNetworkCall, base::Unretained(signin_client_),
base::BindOnce(&GaiaCookieManagerService::StartFetchingMergeSession,
- base::Unretained(this))));
+ weak_ptr_factory_.GetWeakPtr())));
return;
}
@@ -908,53 +818,6 @@ void GaiaCookieManagerService::OnMergeSessionFailure(
HandleNextRequest();
}
-void GaiaCookieManagerService::OnOAuthMultiloginFinished(
- const OAuthMultiloginResult& result) {
- DCHECK(requests_.front().request_type() ==
- GaiaCookieRequestType::SET_ACCOUNTS);
- RecordMultiloginFinished(result.error());
- if (result.error().state() == GoogleServiceAuthError::NONE) {
- VLOG(1) << "Multilogin successful accounts="
- << base::JoinString(requests_.front().account_ids(), " ");
- std::vector<std::string> account_ids = requests_.front().account_ids();
- access_tokens_.clear();
- fetcher_backoff_.InformOfRequest(true);
- StartSettingCookies(result);
- return;
- }
- if (++fetcher_retries_ < signin::kMaxFetcherRetries &&
- result.error().IsTransientError()) {
- UMA_HISTOGRAM_ENUMERATION("Signin.MultiloginRetry", result.error().state(),
- GoogleServiceAuthError::NUM_STATES);
- fetcher_backoff_.InformOfRequest(false);
- fetcher_timer_.Start(
- FROM_HERE, fetcher_backoff_.GetTimeUntilRelease(),
- base::BindOnce(
- &SigninClient::DelayNetworkCall, base::Unretained(signin_client_),
- base::BindOnce(
- &GaiaCookieManagerService::SetAccountsInCookieWithTokens,
- base::Unretained(this))));
- return;
- }
- // If Gaia responded with status: "INVALID_TOKENS", we have to mark tokens as
- // invalid.
- if (result.error().state() ==
- GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS) {
- for (const std::string& account_id : result.failed_accounts()) {
- DCHECK(base::ContainsKey(access_tokens_, account_id));
- token_service_->InvalidateTokenForMultilogin(account_id,
- access_tokens_[account_id]);
- access_tokens_.erase(account_id);
- }
- for (const std::string& account_id : result.failed_accounts()) {
- // Maybe the access token was expired, try to get a new one.
- StartFetchingAccessTokenForMultilogin(account_id);
- }
- return;
- }
- OnSetAccountsFinished(result.error());
-}
-
void GaiaCookieManagerService::OnListAccountsSuccess(const std::string& data) {
VLOG(1) << "ListAccounts successful";
DCHECK(requests_.front().request_type() ==
@@ -1012,7 +875,7 @@ void GaiaCookieManagerService::OnListAccountsFailure(
base::BindOnce(
&SigninClient::DelayNetworkCall, base::Unretained(signin_client_),
base::BindOnce(&GaiaCookieManagerService::StartFetchingListAccounts,
- base::Unretained(this))));
+ weak_ptr_factory_.GetWeakPtr())));
return;
}
@@ -1044,42 +907,16 @@ void GaiaCookieManagerService::OnLogOutFailure(
fetcher_backoff_.InformOfRequest(false);
fetcher_timer_.Start(
FROM_HERE, fetcher_backoff_.GetTimeUntilRelease(),
- base::BindOnce(&SigninClient::DelayNetworkCall,
- base::Unretained(signin_client_),
- base::Bind(&GaiaCookieManagerService::StartGaiaLogOut,
- base::Unretained(this))));
+ base::BindOnce(
+ &SigninClient::DelayNetworkCall, base::Unretained(signin_client_),
+ base::BindOnce(&GaiaCookieManagerService::StartGaiaLogOut,
+ weak_ptr_factory_.GetWeakPtr())));
return;
}
HandleNextRequest();
}
-void GaiaCookieManagerService::StartFetchingAccessTokenForMultilogin(
- const std::string& account_id) {
- token_requests_.push_back(
- token_service_->StartRequestForMultilogin(account_id, this));
-}
-
-void GaiaCookieManagerService::StartFetchingAccessTokensForMultilogin() {
- DCHECK_EQ(SET_ACCOUNTS, requests_.front().request_type());
- VLOG(1) << "GaiaCookieManagerService::StartFetchingAccessToken account_id ="
- << base::JoinString(requests_.front().account_ids(), " ");
-
- if (!external_cc_result_fetched_ &&
- !external_cc_result_fetcher_.IsRunning()) {
- external_cc_result_fetcher_.Start(base::BindOnce(
- &GaiaCookieManagerService::StartFetchingAccessTokensForMultilogin,
- weak_ptr_factory_.GetWeakPtr()));
- return;
- }
-
- token_requests_.clear();
- access_tokens_.clear();
- for (const std::string& account_id : requests_.front().account_ids()) {
- StartFetchingAccessTokenForMultilogin(account_id);
- }
-}
-
void GaiaCookieManagerService::StartFetchingUbertoken() {
const std::string account_id = requests_.front().GetAccountID();
VLOG(1) << "GaiaCookieManagerService::StartFetchingUbertoken account_id="
@@ -1090,28 +927,17 @@ void GaiaCookieManagerService::StartFetchingUbertoken() {
base::Unretained(this)),
base::BindRepeating(
[](SigninClient* client,
- scoped_refptr<network::SharedURLLoaderFactory> url_loader,
GaiaAuthConsumer* consumer) -> std::unique_ptr<GaiaAuthFetcher> {
- return client->CreateGaiaAuthFetcher(
- consumer, gaia::GaiaSource::kChrome, url_loader);
+ return client->CreateGaiaAuthFetcher(consumer,
+ gaia::GaiaSource::kChrome);
},
- base::Unretained(signin_client_), GetURLLoaderFactory()));
-}
-
-void GaiaCookieManagerService::StartFetchingMultiLogin(
- const std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>& accounts) {
- DCHECK(external_cc_result_fetched_);
- gaia_auth_fetcher_ = signin_client_->CreateGaiaAuthFetcher(
- this, requests_.front().source(), GetURLLoaderFactory());
-
- gaia_auth_fetcher_->StartOAuthMultilogin(
- accounts, external_cc_result_fetcher_.GetExternalCcResult());
+ base::Unretained(signin_client_)));
}
void GaiaCookieManagerService::StartFetchingMergeSession() {
DCHECK(!uber_token_.empty());
- gaia_auth_fetcher_ = signin_client_->CreateGaiaAuthFetcher(
- this, requests_.front().source(), GetURLLoaderFactory());
+ gaia_auth_fetcher_ =
+ signin_client_->CreateGaiaAuthFetcher(this, requests_.front().source());
gaia_auth_fetcher_->StartMergeSession(
uber_token_, external_cc_result_fetcher_.GetExternalCcResult());
@@ -1121,17 +947,20 @@ void GaiaCookieManagerService::StartGaiaLogOut() {
DCHECK(requests_.front().request_type() == GaiaCookieRequestType::LOG_OUT);
VLOG(1) << "GaiaCookieManagerService::StartGaiaLogOut";
- signin_client_->PreGaiaLogout(base::BindOnce(
- &GaiaCookieManagerService::StartFetchingLogOut, base::Unretained(this)));
+ signin_client_->PreGaiaLogout(
+ base::BindOnce(&GaiaCookieManagerService::StartFetchingLogOut,
+ weak_ptr_factory_.GetWeakPtr()));
}
void GaiaCookieManagerService::StartFetchingLogOut() {
RecordLogoutRequestState(LogoutRequestState::kStarted);
- gaia_auth_fetcher_ = signin_client_->CreateGaiaAuthFetcher(
- this, requests_.front().source(), GetURLLoaderFactory());
+ gaia_auth_fetcher_ =
+ signin_client_->CreateGaiaAuthFetcher(this, requests_.front().source());
bool use_continue_url = false;
#if defined(OS_ANDROID)
use_continue_url = base::FeatureList::IsEnabled(signin::kMiceFeature);
+#elif defined(OS_CHROMEOS)
+ use_continue_url = chromeos::switches::IsAccountManagerEnabled();
#endif
if (use_continue_url) {
gaia_auth_fetcher_->StartLogOutWithBlankContinueURL();
@@ -1142,71 +971,37 @@ void GaiaCookieManagerService::StartFetchingLogOut() {
void GaiaCookieManagerService::StartFetchingListAccounts() {
VLOG(1) << "GaiaCookieManagerService::ListAccounts";
- gaia_auth_fetcher_ = signin_client_->CreateGaiaAuthFetcher(
- this, requests_.front().source(), GetURLLoaderFactory());
+ gaia_auth_fetcher_ =
+ signin_client_->CreateGaiaAuthFetcher(this, requests_.front().source());
gaia_auth_fetcher_->StartListAccounts();
}
-void GaiaCookieManagerService::OnSetAccountsFinished(
- const GoogleServiceAuthError& error) {
- MarkListAccountsStale();
- access_tokens_.clear();
- token_requests_.clear();
- cookies_to_set_.clear();
- SignalSetAccountsComplete(error);
- HandleNextRequest();
-}
+void GaiaCookieManagerService::StartSetAccounts() {
+ DCHECK(!requests_.empty());
+ DCHECK_EQ(GaiaCookieRequestType::SET_ACCOUNTS,
+ requests_.front().request_type());
+ DCHECK(!requests_.front().account_ids().empty());
-void GaiaCookieManagerService::OnCookieSet(
- const std::string& cookie_name,
- const std::string& cookie_domain,
- net::CanonicalCookie::CookieInclusionStatus status) {
- cookies_to_set_.erase(std::make_pair(cookie_name, cookie_domain));
- bool success =
- (status == net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
- if (!success) {
- VLOG(1) << "Failed to set cookie " << cookie_name
- << " for domain=" << cookie_domain << ".";
+ if (!external_cc_result_fetched_ &&
+ !external_cc_result_fetcher_.IsRunning()) {
+ external_cc_result_fetcher_.Start(
+ base::BindOnce(&GaiaCookieManagerService::StartSetAccounts,
+ weak_ptr_factory_.GetWeakPtr()));
+ return;
}
- UMA_HISTOGRAM_BOOLEAN("Signin.SetCookieSuccess", success);
- if (cookies_to_set_.empty())
- OnSetAccountsFinished(GoogleServiceAuthError::AuthErrorNone());
-}
-
-void GaiaCookieManagerService::StartSettingCookies(
- const OAuthMultiloginResult& result) {
- network::mojom::CookieManager* cookie_manager =
- signin_client_->GetCookieManager();
- DCHECK(cookies_to_set_.empty());
-
- const std::vector<net::CanonicalCookie>& cookies = result.cookies();
+ oauth_multilogin_helper_ = std::make_unique<signin::OAuthMultiloginHelper>(
+ signin_client_, token_service_, requests_.front().account_ids(),
+ external_cc_result_fetcher_.GetExternalCcResult(),
+ base::BindOnce(&GaiaCookieManagerService::OnSetAccountsFinished,
+ weak_ptr_factory_.GetWeakPtr()));
+}
- for (const net::CanonicalCookie& cookie : cookies) {
- cookies_to_set_.insert(std::make_pair(cookie.Name(), cookie.Domain()));
- }
- for (const net::CanonicalCookie& cookie : cookies) {
- if (cookies_to_set_.find(std::make_pair(cookie.Name(), cookie.Domain())) !=
- cookies_to_set_.end()) {
- base::OnceCallback<void(net::CanonicalCookie::CookieInclusionStatus)>
- callback = base::BindOnce(&GaiaCookieManagerService::OnCookieSet,
- weak_ptr_factory_.GetWeakPtr(),
- cookie.Name(), cookie.Domain());
- net::CookieOptions options;
- options.set_include_httponly();
- // Permit it to set a SameSite cookie if it wants to.
- options.set_same_site_cookie_context(
- net::CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT);
- cookie_manager->SetCanonicalCookie(
- cookie, "https", options,
- mojo::WrapCallbackWithDefaultInvokeIfNotRun(
- std::move(callback), net::CanonicalCookie::CookieInclusionStatus::
- EXCLUDE_UNKNOWN_ERROR));
- } else {
- LOG(ERROR) << "Duplicate cookie found: " << cookie.Name() << " "
- << cookie.Domain();
- }
- }
+void GaiaCookieManagerService::OnSetAccountsFinished(
+ signin::SetAccountsInCookieResult result) {
+ MarkListAccountsStale();
+ SignalSetAccountsComplete(result);
+ HandleNextRequest();
}
void GaiaCookieManagerService::HandleNextRequest() {
@@ -1235,26 +1030,23 @@ void GaiaCookieManagerService::HandleNextRequest() {
DCHECK_EQ(1u, requests_.front().account_ids().size());
signin_client_->DelayNetworkCall(
base::BindOnce(&GaiaCookieManagerService::StartFetchingUbertoken,
- base::Unretained(this)));
+ weak_ptr_factory_.GetWeakPtr()));
break;
case GaiaCookieRequestType::SET_ACCOUNTS:
- DCHECK(!requests_.front().account_ids().empty());
- signin_client_->DelayNetworkCall(base::BindOnce(
- &GaiaCookieManagerService::StartFetchingAccessTokensForMultilogin,
- base::Unretained(this)));
+ StartSetAccounts();
break;
case GaiaCookieRequestType::LOG_OUT:
DCHECK(requests_.front().account_ids().empty());
signin_client_->DelayNetworkCall(
base::BindOnce(&GaiaCookieManagerService::StartGaiaLogOut,
- base::Unretained(this)));
+ weak_ptr_factory_.GetWeakPtr()));
break;
case GaiaCookieRequestType::LIST_ACCOUNTS:
DCHECK(requests_.front().account_ids().empty());
uber_token_fetcher_.reset();
signin_client_->DelayNetworkCall(
base::BindOnce(&GaiaCookieManagerService::StartFetchingListAccounts,
- base::Unretained(this)));
+ weak_ptr_factory_.GetWeakPtr()));
break;
}
}
diff --git a/chromium/components/signin/core/browser/gaia_cookie_manager_service.h b/chromium/components/signin/core/browser/gaia_cookie_manager_service.h
index 8073b55d947..94901f4e0a5 100644
--- a/chromium/components/signin/core/browser/gaia_cookie_manager_service.h
+++ b/chromium/components/signin/core/browser/gaia_cookie_manager_service.h
@@ -12,18 +12,18 @@
#include <utility>
#include <vector>
-#include "base/callback.h"
+#include "base/callback_forward.h"
#include "base/containers/circular_deque.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/timer/timer.h"
+#include "components/signin/core/browser/oauth_multilogin_helper.h"
#include "components/signin/core/browser/signin_client.h"
#include "google_apis/gaia/gaia_auth_consumer.h"
#include "google_apis/gaia/gaia_auth_fetcher.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/oauth2_token_service.h"
-#include "google_apis/gaia/oauth_multilogin_result.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "net/base/backoff_entry.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
@@ -40,6 +40,7 @@ class SimpleURLLoader;
namespace signin {
class UbertokenFetcherImpl;
+enum class SetAccountsInCookieResult;
// The maximum number of retries for a fetcher used in this class.
constexpr int kMaxFetcherRetries = 8;
@@ -70,8 +71,7 @@ struct MultiloginParameters {
// GAIA cookie are blocked (such as youtube). This is executed once for the
// lifetime of this object, when the first call is made to AddAccountToCookie.
class GaiaCookieManagerService : public GaiaAuthConsumer,
- public network::mojom::CookieChangeListener,
- public OAuth2TokenService::Consumer {
+ public network::mojom::CookieChangeListener {
public:
enum GaiaCookieRequestType {
ADD_ACCOUNT,
@@ -80,10 +80,10 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
SET_ACCOUNTS
};
- typedef base::OnceCallback<void(const GoogleServiceAuthError& error)>
+ typedef base::OnceCallback<void(signin::SetAccountsInCookieResult)>
SetAccountsInCookieCompletedCallback;
- typedef base::OnceCallback<void(const std::string& account_id,
- const GoogleServiceAuthError& error)>
+ typedef base::OnceCallback<void(const std::string&,
+ const GoogleServiceAuthError&)>
AddAccountToCookieCompletedCallback;
// Contains the information and parameters for any request.
@@ -102,7 +102,7 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
gaia::GaiaSource source() const { return source_; }
void RunSetAccountsInCookieCompletedCallback(
- const GoogleServiceAuthError& error);
+ signin::SetAccountsInCookieResult result);
void RunAddAccountToCookieCompletedCallback(
const std::string& account_id,
const GoogleServiceAuthError& error);
@@ -229,19 +229,6 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
GaiaCookieManagerService(OAuth2TokenService* token_service,
SigninClient* signin_client);
- // Creates a GaiaCookieManagerService that uses the provided
- // |shared_url_loader_factory_getter| to determine the SharedUrlLoaderFactory
- // used for cookie-related requests.
- // Note: SharedUrlLoaderFactory is passed via callback, so that if the
- // callback has side-effects (e.g. network initialization), they do not occur
- // until the first time GaiaCookieManagerService::GetSharedUrlLoaderFactory is
- // called.
- GaiaCookieManagerService(
- OAuth2TokenService* token_service,
- SigninClient* signin_client,
- base::RepeatingCallback<scoped_refptr<network::SharedURLLoaderFactory>()>
- shared_url_loader_factory_getter);
-
~GaiaCookieManagerService() override;
void InitCookieListener();
@@ -265,11 +252,6 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
SetAccountsInCookieCompletedCallback
set_accounts_in_cookies_completed_callback);
- // Takes list of account_ids from the front request, matches them with a
- // corresponding stored access_token and calls StartMultilogin.
- // Virtual for testing purposes.
- virtual void SetAccountsInCookieWithTokens();
-
// Returns if the listed accounts are up to date or not. The out parameter
// will be assigned the current cached accounts (whether they are not up to
// date or not). If the accounts are not up to date, a ListAccounts fetch is
@@ -299,7 +281,7 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
void LogOutAllAccounts(gaia::GaiaSource source);
// Call observers when setting accounts in cookie completes.
- void SignalSetAccountsComplete(const GoogleServiceAuthError& error);
+ void SignalSetAccountsComplete(signin::SetAccountsInCookieResult result);
// Returns true of there are pending log ins or outs.
bool is_running() const { return requests_.size() > 0; }
@@ -320,20 +302,10 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
void OnUbertokenFetchComplete(GoogleServiceAuthError error,
const std::string& uber_token);
- private:
- FRIEND_TEST_ALL_PREFIXES(GaiaCookieManagerServiceTest,
- MultiloginSuccessAndCookiesSet);
- FRIEND_TEST_ALL_PREFIXES(GaiaCookieManagerServiceTest,
- MultiloginFailurePersistentError);
- FRIEND_TEST_ALL_PREFIXES(GaiaCookieManagerServiceTest,
- MultiloginFailureMaxRetriesReached);
- FRIEND_TEST_ALL_PREFIXES(GaiaCookieManagerServiceTest,
- FetcherRetriesZeroedBetweenCalls);
- FRIEND_TEST_ALL_PREFIXES(GaiaCookieManagerServiceTest,
- MultiloginFailureInvalidGaiaCredentialsMobile);
- FRIEND_TEST_ALL_PREFIXES(GaiaCookieManagerServiceTest,
- MultiloginFailureInvalidGaiaCredentialsDesktop);
+ // Final call in the Setting accounts in cookie procedure. Public for testing.
+ void OnSetAccountsFinished(signin::SetAccountsInCookieResult result);
+ private:
scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory();
// Calls the AddAccountToCookie completion callback.
@@ -352,57 +324,24 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
network::mojom::CookieChangeCause cause) override;
void OnCookieListenerConnectionError();
- // Overridden from OAuth2TokenService::Consumer.
- void OnGetTokenSuccess(
- const OAuth2TokenService::Request* request,
- const OAuth2AccessTokenConsumer::TokenResponse& token_response) override;
- void OnGetTokenFailure(const OAuth2TokenService::Request* request,
- const GoogleServiceAuthError& error) override;
- // Called when either refresh or access token becomes available.
- void OnTokenFetched(const std::string& account_id, const std::string& token);
-
// Overridden from GaiaAuthConsumer.
void OnMergeSessionSuccess(const std::string& data) override;
void OnMergeSessionFailure(const GoogleServiceAuthError& error) override;
- void OnOAuthMultiloginFinished(const OAuthMultiloginResult& result) override;
void OnListAccountsSuccess(const std::string& data) override;
void OnListAccountsFailure(const GoogleServiceAuthError& error) override;
void OnLogOutSuccess() override;
void OnLogOutFailure(const GoogleServiceAuthError& error) override;
- // Callback for CookieManager::SetCanonicalCookie.
- void OnCookieSet(const std::string& cookie_name,
- const std::string& cookie_domain,
- net::CanonicalCookie::CookieInclusionStatus status);
-
- // Final call in the Setting accounts in cookie procedure. Virtual for testing
- // purposes.
- virtual void OnSetAccountsFinished(const GoogleServiceAuthError& error);
-
// Helper method for AddAccountToCookie* methods.
void AddAccountToCookieInternal(
const std::string& account_id,
gaia::GaiaSource source,
AddAccountToCookieCompletedCallback completion_callback);
- // Helper function to trigger fetching retry in case of failure for only
- // failed account id. Virtual for testing purposes.
- virtual void StartFetchingAccessTokenForMultilogin(
- const std::string& account_id);
-
- // Starts the process of fetching the access token with OauthLogin scope and
- // performing SetAccountsInCookie on success. Virtual so that it can be
- // overridden in tests.
- virtual void StartFetchingAccessTokensForMultilogin();
-
// Starts the proess of fetching the uber token and performing a merge session
// for the next account. Virtual so that it can be overriden in tests.
virtual void StartFetchingUbertoken();
- // Starts the process of setting accounts in cookie.
- void StartFetchingMultiLogin(
- const std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>& accounts);
-
// Virtual for testing purposes.
virtual void StartFetchingMergeSession();
@@ -416,8 +355,8 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
// Virtual for testing purpose.
virtual void StartFetchingLogOut();
- // Starts setting parsed cookies in browser.
- void StartSettingCookies(const OAuthMultiloginResult& result);
+ // Starts setting account using multilogin endpoint.
+ void StartSetAccounts();
// Start the next request, if needed.
void HandleNextRequest();
@@ -425,11 +364,10 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
OAuth2TokenService* token_service_;
SigninClient* signin_client_;
- base::RepeatingCallback<scoped_refptr<network::SharedURLLoaderFactory>()>
- shared_url_loader_factory_getter_;
std::unique_ptr<GaiaAuthFetcher> gaia_auth_fetcher_;
std::unique_ptr<signin::UbertokenFetcherImpl> uber_token_fetcher_;
ExternalCcResultFetcher external_cc_result_fetcher_;
+ std::unique_ptr<signin::OAuthMultiloginHelper> oauth_multilogin_helper_;
// If the GaiaAuthFetcher or SimpleURLLoader fails, retry with exponential
// backoff and network delay.
@@ -440,21 +378,9 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
// The last fetched ubertoken, for use in MergeSession retries.
std::string uber_token_;
- // Access tokens for use inside SetAccountsToCookie.
- // TODO (valeriyas): make FetchUberToken use those instead of a separate
- // access_token.
- std::unordered_map<std::string, std::string> access_tokens_;
-
- // Current list of processed token requests;
- std::vector<std::unique_ptr<OAuth2TokenService::Request>> token_requests_;
-
// The access token that can be used to prime the UberToken fetch.
std::string access_token_;
- // List of pairs (cookie name and cookie domain) that have to be set in
- // cookie jar.
- std::set<std::pair<std::string, std::string>> cookies_to_set_;
-
// Connection to the CookieManager that signals when the GAIA cookies change.
mojo::Binding<network::mojom::CookieChangeListener> cookie_listener_binding_;
diff --git a/chromium/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc b/chromium/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc
index 2b71d6111db..85a5c442b00 100644
--- a/chromium/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc
+++ b/chromium/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc
@@ -96,11 +96,7 @@ class InstrumentedGaiaCookieManagerService : public GaiaCookieManagerService {
public:
InstrumentedGaiaCookieManagerService(OAuth2TokenService* token_service,
SigninClient* signin_client)
- : GaiaCookieManagerService(
- token_service,
- signin_client,
- base::BindRepeating(&SigninClient::GetURLLoaderFactory,
- base::Unretained(signin_client))) {
+ : GaiaCookieManagerService(token_service, signin_client) {
total++;
}
@@ -110,11 +106,6 @@ class InstrumentedGaiaCookieManagerService : public GaiaCookieManagerService {
MOCK_METHOD0(StartFetchingListAccounts, void());
MOCK_METHOD0(StartFetchingLogOut, void());
MOCK_METHOD0(StartFetchingMergeSession, void());
- MOCK_METHOD1(StartFetchingAccessTokenForMultilogin,
- void(const std::string& account_id));
- MOCK_METHOD0(SetAccountsInCookieWithTokens, void());
- MOCK_METHOD1(OnSetAccountsFinished,
- void(const GoogleServiceAuthError& error));
private:
DISALLOW_COPY_AND_ASSIGN(InstrumentedGaiaCookieManagerService);
@@ -125,18 +116,7 @@ class GaiaCookieManagerServiceTest : public testing::Test {
GaiaCookieManagerServiceTest()
: no_error_(GoogleServiceAuthError::NONE),
error_(GoogleServiceAuthError::SERVICE_ERROR),
- canceled_(GoogleServiceAuthError::REQUEST_CANCELED) {}
-
- class RequestMockImpl : public OAuth2TokenService::Request {
- public:
- RequestMockImpl(std::string account_id) { account_id_ = account_id; }
- std::string GetAccountId() const override { return account_id_; }
-
- private:
- std::string account_id_;
- };
-
- void SetUp() override {
+ canceled_(GoogleServiceAuthError::REQUEST_CANCELED) {
AccountTrackerService::RegisterPrefs(pref_service_.registry());
signin_client_.reset(new TestSigninClient(&pref_service_));
}
@@ -199,7 +179,7 @@ class GaiaCookieManagerServiceTest : public testing::Test {
}
void SimulateGetCheckConnectionInfoSuccess(const std::string& data) {
- signin_client_->test_url_loader_factory()->AddResponse(
+ signin_client_->GetTestURLLoaderFactory()->AddResponse(
GaiaUrls::GetInstance()
->GetCheckConnectionInfoURLWithSource(GaiaConstants::kChromeSource)
.spec(),
@@ -209,7 +189,7 @@ class GaiaCookieManagerServiceTest : public testing::Test {
void SimulateGetCheckConnectionInfoResult(const std::string& url,
const std::string& result) {
- signin_client_->test_url_loader_factory()->AddResponse(url, result);
+ signin_client_->GetTestURLLoaderFactory()->AddResponse(url, result);
base::RunLoop().RunUntilIdle();
}
@@ -221,12 +201,12 @@ class GaiaCookieManagerServiceTest : public testing::Test {
}
bool IsLoadPending(const std::string& url) {
- return signin_client_->test_url_loader_factory()->IsPending(
+ return signin_client_->GetTestURLLoaderFactory()->IsPending(
GURL(url).spec());
}
bool IsLoadPending() {
- return signin_client_->test_url_loader_factory()->NumPending() > 0;
+ return signin_client_->GetTestURLLoaderFactory()->NumPending() > 0;
}
const GoogleServiceAuthError& no_error() { return no_error_; }
@@ -366,549 +346,6 @@ TEST_F(GaiaCookieManagerServiceTest, FailedUbertoken) {
SimulateUbertokenFailure(&helper, error());
}
-TEST_F(GaiaCookieManagerServiceTest, AccessTokenSuccess) {
- InstrumentedGaiaCookieManagerService helper(token_service(), signin_client());
- MockObserver observer(&helper);
-
- auto test_task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>();
- base::ScopedClosureRunner task_runner_ =
- base::ThreadTaskRunnerHandle::OverrideForTesting(test_task_runner);
-
- const std::string account_id1 = "12345";
- const std::string account_id2 = "23456";
-
- testing::InSequence mock_sequence;
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id1))
- .Times(1);
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id2))
- .Times(1);
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id1))
- .Times(1);
- EXPECT_CALL(helper, SetAccountsInCookieWithTokens());
-
- const std::vector<std::string> account_ids = {account_id1, account_id2};
-
- helper.SetAccountsInCookie(
- account_ids, gaia::GaiaSource::kChrome,
- GaiaCookieManagerService::SetAccountsInCookieCompletedCallback());
-
- RequestMockImpl request1(account_id1);
- RequestMockImpl request2(account_id2);
-
- SimulateAccessTokenSuccess(&helper, &request2);
-
- GoogleServiceAuthError error(GoogleServiceAuthError::SERVICE_UNAVAILABLE);
-
- // Transient error, retry.
- SimulateAccessTokenFailure(&helper, &request1, error);
-
- DCHECK(helper.is_running());
- Advance(test_task_runner, helper.GetBackoffEntry()->GetTimeUntilRelease());
-
- SimulateAccessTokenSuccess(&helper, &request1);
-}
-
-TEST_F(GaiaCookieManagerServiceTest,
- AccessTokenFailureTransientErrorMaxRetriesReached) {
- InstrumentedGaiaCookieManagerService helper(token_service(), signin_client());
- MockObserver observer(&helper);
-
- auto test_task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>();
- base::ScopedClosureRunner task_runner_ =
- base::ThreadTaskRunnerHandle::OverrideForTesting(test_task_runner);
-
- const std::string account_id1 = "12345";
- const std::string account_id2 = "23456";
-
- GoogleServiceAuthError error(GoogleServiceAuthError::SERVICE_UNAVAILABLE);
-
- testing::InSequence mock_sequence;
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id1))
- .Times(1);
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id2))
- .Times(1);
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id1))
- .Times(signin::kMaxFetcherRetries - 1);
- EXPECT_CALL(helper, OnSetAccountsFinished(error)).Times(1);
- EXPECT_CALL(helper, SetAccountsInCookieWithTokens()).Times(0);
-
- const std::vector<std::string> account_ids = {account_id1, account_id2};
-
- helper.SetAccountsInCookie(
- account_ids, gaia::GaiaSource::kChrome,
- GaiaCookieManagerService::SetAccountsInCookieCompletedCallback());
-
- RequestMockImpl request1(account_id1);
- RequestMockImpl request2(account_id2);
-
- EXPECT_LT(helper.GetBackoffEntry()->GetTimeUntilRelease(),
- base::TimeDelta::FromMilliseconds(1100));
-
- // Transient error, retry, fail when maximum number of retries is reached.
- for (int i = 0; i < signin::kMaxFetcherRetries - 1; ++i) {
- SimulateAccessTokenFailure(&helper, &request1, error);
- Advance(test_task_runner, helper.GetBackoffEntry()->GetTimeUntilRelease());
- }
- SimulateAccessTokenFailure(&helper, &request1, error);
- // Check that no Multilogin is triggered.
- SimulateAccessTokenSuccess(&helper, &request2);
-}
-
-TEST_F(GaiaCookieManagerServiceTest, AccessTokenFailurePersistentError) {
- InstrumentedGaiaCookieManagerService helper(token_service(), signin_client());
- MockObserver observer(&helper);
-
- const std::string account_id1 = "12345";
- const std::string account_id2 = "23456";
-
- GoogleServiceAuthError error(
- GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
-
- testing::InSequence mock_sequence;
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id1))
- .Times(1);
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id2))
- .Times(1);
- EXPECT_CALL(helper, OnSetAccountsFinished(error)).Times(1);
- EXPECT_CALL(helper, SetAccountsInCookieWithTokens()).Times(0);
-
- const std::vector<std::string> account_ids = {account_id1, account_id2};
-
- helper.SetAccountsInCookie(
- account_ids, gaia::GaiaSource::kChrome,
- GaiaCookieManagerService::SetAccountsInCookieCompletedCallback());
-
- RequestMockImpl request1(account_id1);
- RequestMockImpl request2(account_id2);
-
- SimulateAccessTokenFailure(&helper, &request1, error);
-
- // Check that no Multilogin is triggered.
- SimulateAccessTokenSuccess(&helper, &request2);
-}
-
-TEST_F(GaiaCookieManagerServiceTest, FetcherRetriesZeroedBetweenCalls) {
- InstrumentedGaiaCookieManagerService helper(token_service(), signin_client());
- MockObserver observer(&helper);
-
- auto test_task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>();
- base::ScopedClosureRunner task_runner_ =
- base::ThreadTaskRunnerHandle::OverrideForTesting(test_task_runner);
-
- const std::string account_id1 = "12345";
- const std::string account_id2 = "23456";
-
- GoogleServiceAuthError error(GoogleServiceAuthError::SERVICE_UNAVAILABLE);
-
- std::string data =
- R"()]}'
- {
- "status": "OK",
- "cookies":[
- {
- "name":"SID",
- "value":"vAlUe1",
- "domain":".google.ru",
- "path":"/",
- "isSecure":true,
- "isHttpOnly":false,
- "priority":"HIGH",
- "maxAge":63070000
- }
- ]
- }
- )";
- OAuthMultiloginResult result(data);
- ASSERT_EQ(result.error().state(), GoogleServiceAuthError::State::NONE);
-
- testing::InSequence mock_sequence;
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id1))
- .Times(1);
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id2))
- .Times(1);
- // retry call
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id1))
- .Times(signin::kMaxFetcherRetries - 1);
- // retry call
- EXPECT_CALL(helper, SetAccountsInCookieWithTokens()).Times(1);
- EXPECT_CALL(helper,
- OnSetAccountsFinished(GoogleServiceAuthError::AuthErrorNone()))
- .Times(1);
-
- const std::vector<std::string> account_ids = {account_id1, account_id2};
-
- helper.SetAccountsInCookie(
- account_ids, gaia::GaiaSource::kChrome,
- GaiaCookieManagerService::SetAccountsInCookieCompletedCallback());
-
- RequestMockImpl request1(account_id1);
- RequestMockImpl request2(account_id2);
- // Transient error, retry.
- // Succeed when only one retry is left. Simulate Multilogin failure. Check
- // that it retries.
- for (int i = 0; i < signin::kMaxFetcherRetries - 1; ++i) {
- SimulateAccessTokenFailure(&helper, &request1, error);
- Advance(test_task_runner, helper.GetBackoffEntry()->GetTimeUntilRelease());
- }
- SimulateAccessTokenSuccess(&helper, &request1);
- SimulateAccessTokenSuccess(&helper, &request2);
-
- std::vector<GaiaAuthFetcher::MultiloginTokenIDPair> accounts =
- std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>();
- accounts.emplace_back(account_id1, "AccessToken");
- accounts.emplace_back(account_id2, "AccessToken");
-
- helper.StartFetchingMultiLogin(accounts);
- SimulateMultiloginFinished(&helper, OAuthMultiloginResult(error));
- SimulateMultiloginFinished(&helper, result);
-}
-
-TEST_F(GaiaCookieManagerServiceTest, MultiloginSuccessAndCookiesSet) {
- InstrumentedGaiaCookieManagerService helper(token_service(), signin_client());
- MockObserver observer(&helper);
-
- auto test_task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>();
- base::ScopedClosureRunner task_runner_ =
- base::ThreadTaskRunnerHandle::OverrideForTesting(test_task_runner);
-
- const std::string account_id1 = "12345";
- const std::string account_id2 = "23456";
- const std::vector<std::string> account_ids = {account_id1, account_id2};
-
- std::vector<GaiaAuthFetcher::MultiloginTokenIDPair> accounts =
- std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>();
- accounts.emplace_back(account_id1, "AccessToken");
- accounts.emplace_back(account_id2, "AccessToken");
-
- GoogleServiceAuthError error(GoogleServiceAuthError::SERVICE_UNAVAILABLE);
-
- std::string data =
- R"()]}'
- {
- "status": "OK",
- "cookies":[
- {
- "name":"SID",
- "value":"vAlUe1",
- "domain":".google.ru",
- "path":"/",
- "isSecure":true,
- "isHttpOnly":false,
- "priority":"HIGH",
- "maxAge":63070000
- },
- {
- "name":"SID",
- "value":"vAlUe1",
- "domain":".google.ru",
- "path":"/",
- "isSecure":true,
- "isHttpOnly":false,
- "priority":"HIGH",
- "maxAge":63070000
- },
- {
- "name":"HSID",
- "value":"vAlUe4",
- "host":"google.fr",
- "path":"/",
- "isSecure":true,
- "isHttpOnly":false,
- "priority":"HIGH",
- "maxAge":0
- }
- ]
- }
- )";
- OAuthMultiloginResult result(data);
- ASSERT_EQ(result.error().state(), GoogleServiceAuthError::State::NONE);
-
- testing::InSequence mock_sequence;
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id1))
- .Times(1);
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id2))
- .Times(1);
- EXPECT_CALL(helper, SetAccountsInCookieWithTokens()).Times(1);
- EXPECT_CALL(helper,
- OnSetAccountsFinished(GoogleServiceAuthError::AuthErrorNone()))
- .Times(1);
-
- // Needed to insert request in the queue.
- helper.SetAccountsInCookie(
- account_ids, gaia::GaiaSource::kChrome,
- GaiaCookieManagerService::SetAccountsInCookieCompletedCallback());
-
- helper.StartFetchingMultiLogin(accounts);
-
- SimulateMultiloginFinished(&helper, OAuthMultiloginResult(error));
-
- DCHECK(helper.is_running());
- Advance(test_task_runner, helper.GetBackoffEntry()->GetTimeUntilRelease());
-
- SimulateMultiloginFinished(&helper, result);
-}
-
-TEST_F(GaiaCookieManagerServiceTest, MultiloginFailurePersistentError) {
- InstrumentedGaiaCookieManagerService helper(token_service(), signin_client());
- MockObserver observer(&helper);
-
- const std::string account_id1 = "12345";
- const std::string account_id2 = "23456";
- const std::vector<std::string> account_ids = {account_id1, account_id2};
-
- std::vector<GaiaAuthFetcher::MultiloginTokenIDPair> accounts =
- std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>();
- accounts.emplace_back(account_id1, "AccessToken");
- accounts.emplace_back(account_id2, "AccessToken");
-
- GoogleServiceAuthError error(GoogleServiceAuthError::SERVICE_ERROR);
-
- testing::InSequence mock_sequence;
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id1))
- .Times(1);
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id2))
- .Times(1);
- EXPECT_CALL(helper, OnSetAccountsFinished(error)).Times(1);
-
- // Needed to insert request in the queue.
- helper.SetAccountsInCookie(
- account_ids, gaia::GaiaSource::kChrome,
- GaiaCookieManagerService::SetAccountsInCookieCompletedCallback());
-
- helper.StartFetchingMultiLogin(accounts);
-
- SimulateMultiloginFinished(&helper, OAuthMultiloginResult(error));
-}
-
-TEST_F(GaiaCookieManagerServiceTest, MultiloginFailureMaxRetriesReached) {
- InstrumentedGaiaCookieManagerService helper(token_service(), signin_client());
- MockObserver observer(&helper);
-
- auto test_task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>();
- base::ScopedClosureRunner task_runner_ =
- base::ThreadTaskRunnerHandle::OverrideForTesting(test_task_runner);
-
- const std::string account_id1 = "12345";
- const std::string account_id2 = "23456";
- const std::vector<std::string> account_ids = {account_id1, account_id2};
-
- std::vector<GaiaAuthFetcher::MultiloginTokenIDPair> accounts =
- std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>();
- accounts.emplace_back(account_id1, "AccessToken");
- accounts.emplace_back(account_id2, "AccessToken");
-
- GoogleServiceAuthError error(GoogleServiceAuthError::SERVICE_UNAVAILABLE);
-
- testing::InSequence mock_sequence;
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id1))
- .Times(1);
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id2))
- .Times(1);
- // This is the retry call, the first call is skipped as we call
- // StartFetchingMultiLogim explicitly instead.
- EXPECT_CALL(helper, SetAccountsInCookieWithTokens())
- .Times(signin::kMaxFetcherRetries - 1);
- EXPECT_CALL(helper, OnSetAccountsFinished(error)).Times(1);
-
- // Needed to insert request in the queue.
- helper.SetAccountsInCookie(
- account_ids, gaia::GaiaSource::kChrome,
- GaiaCookieManagerService::SetAccountsInCookieCompletedCallback());
-
- helper.StartFetchingMultiLogin(accounts);
-
- // Transient error, retry, fail when maximum number of retries is reached.
- for (int i = 0; i < signin::kMaxFetcherRetries - 1; ++i) {
- SimulateMultiloginFinished(&helper, OAuthMultiloginResult(error));
- Advance(test_task_runner, helper.GetBackoffEntry()->GetTimeUntilRelease());
- }
- SimulateMultiloginFinished(&helper, OAuthMultiloginResult(error));
-}
-
-TEST_F(GaiaCookieManagerServiceTest,
- MultiloginFailureInvalidGaiaCredentialsMobile) {
- InstrumentedGaiaCookieManagerService helper(token_service(), signin_client());
- MockObserver observer(&helper);
-
- const std::string account_id1 = "12345";
- const std::string account_id2 = "23456";
- const std::vector<std::string> account_ids = {account_id1, account_id2};
-
- std::vector<GaiaAuthFetcher::MultiloginTokenIDPair> accounts =
- std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>();
- accounts.emplace_back(account_id1, "AccessToken");
- accounts.emplace_back(account_id2, "AccessToken");
-
- RequestMockImpl request1(account_id1);
- RequestMockImpl request2(account_id2);
-
- GoogleServiceAuthError error(
- GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
-
- std::string data_ok =
- R"()]}'
- {
- "status": "OK",
- "cookies":[
- {
- "name":"SID",
- "value":"vAlUe1",
- "domain":".google.ru",
- "path":"/",
- "isSecure":true,
- "isHttpOnly":false,
- "priority":"HIGH",
- "maxAge":63070000
- }
- ]
- }
- )";
- OAuthMultiloginResult result_ok(data_ok);
- ASSERT_EQ(result_ok.error().state(), GoogleServiceAuthError::State::NONE);
-
- std::string data_failed =
- R"()]}'
- {
- "status": "INVALID_TOKENS",
- "failed_accounts": [
- {
- "obfuscated_id": "12345", "status": "RECOVERABLE"
- },
- {
- "obfuscated_id": "23456", "status": "OK"
- }
- ]
- }
- )";
- OAuthMultiloginResult result_failed(data_failed);
- ASSERT_EQ(result_failed.error().state(),
- GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS);
-
- testing::InSequence mock_sequence;
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id1))
- .Times(1);
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id2))
- .Times(1);
- EXPECT_CALL(helper, SetAccountsInCookieWithTokens()).Times(1);
-
- // On mobile token_service is expected to retry getting access tokens first.
- EXPECT_CALL(helper, OnSetAccountsFinished(error)).Times(0);
-
- // Expect to try to refetch failed account one more time.
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id1))
- .Times(1);
-
- // This time access tokens are supposed to be correct.
- EXPECT_CALL(helper, SetAccountsInCookieWithTokens()).Times(1);
- EXPECT_CALL(helper,
- OnSetAccountsFinished(GoogleServiceAuthError::AuthErrorNone()))
- .Times(1);
-
- // Needed to insert request in the queue.
- helper.SetAccountsInCookie(
- account_ids, gaia::GaiaSource::kChrome,
- GaiaCookieManagerService::SetAccountsInCookieCompletedCallback());
-
- // Both requests for access tokens are successful but they could be returned
- // from cache and be stale.
- SimulateAccessTokenSuccess(&helper, &request1);
- SimulateAccessTokenSuccess(&helper, &request2);
- // Both tokens are inserted in the map.
- EXPECT_EQ(2u, helper.access_tokens_.size());
-
- helper.StartFetchingMultiLogin(accounts);
- // Access tokens were stale, Multilogin failed.
- SimulateMultiloginFinished(&helper, result_failed);
-
- // GaiaCookieManagerService should retry fetching access token again,
- // it should be removed from the token map.
- EXPECT_EQ(1u, helper.access_tokens_.size());
- EXPECT_EQ(helper.access_tokens_.begin()->first, account_id2);
-
- // This time access token is fresh.
- SimulateAccessTokenSuccess(&helper, &request1);
-
- EXPECT_EQ(2u, helper.access_tokens_.size());
-
- // And Multilogin is successful.
- SimulateMultiloginFinished(&helper, result_ok);
-
- // The end.
-}
-
-TEST_F(GaiaCookieManagerServiceTest,
- MultiloginFailureInvalidGaiaCredentialsDesktop) {
- InstrumentedGaiaCookieManagerService helper(token_service(), signin_client());
- MockObserver observer(&helper);
-
- const std::string account_id1 = "12345";
- const std::string account_id2 = "23456";
- const std::vector<std::string> account_ids = {account_id1, account_id2};
-
- std::vector<GaiaAuthFetcher::MultiloginTokenIDPair> accounts =
- std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>();
- accounts.emplace_back(account_id1, "AccessToken");
- accounts.emplace_back(account_id2, "AccessToken");
-
- RequestMockImpl request1(account_id1);
- RequestMockImpl request2(account_id2);
-
- GoogleServiceAuthError error(
- GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
-
- std::string data_failed =
- R"()]}'
- {
- "status": "INVALID_TOKENS",
- "failed_accounts": [
- {
- "obfuscated_id": "12345", "status": "RECOVERABLE"
- },
- {
- "obfuscated_id": "23456", "status": "OK"
- }
- ]
- }
- )";
- OAuthMultiloginResult result_failed(data_failed);
- ASSERT_EQ(result_failed.error().state(),
- GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS);
-
- testing::InSequence mock_sequence;
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id1))
- .Times(1);
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id2))
- .Times(1);
- EXPECT_CALL(helper, SetAccountsInCookieWithTokens()).Times(1);
- // Expect to try to refetch failed account one more time.
- EXPECT_CALL(helper, StartFetchingAccessTokenForMultilogin(account_id1))
- .Times(1);
- // And fail right away.
- EXPECT_CALL(helper, SetAccountsInCookieWithTokens()).Times(0);
- EXPECT_CALL(helper, OnSetAccountsFinished(error)).Times(1);
-
- // Needed to insert request in the queue.
- helper.SetAccountsInCookie(
- account_ids, gaia::GaiaSource::kChrome,
- GaiaCookieManagerService::SetAccountsInCookieCompletedCallback());
-
- // Both requests for access tokens are successful but they could be returned
- // from cache and be stale.
- SimulateAccessTokenSuccess(&helper, &request1);
- SimulateAccessTokenSuccess(&helper, &request2);
- // Both tokens are inserted in the map.
- EXPECT_EQ(2u, helper.access_tokens_.size());
-
- helper.StartFetchingMultiLogin(accounts);
-
- // On desktop refresh tokens were used and failed. Token service will retry
- // fetching access token but refresh token is supposed to be set in error and
- // request will return with immediate error.
- SimulateMultiloginFinished(&helper, result_failed);
-
- SimulateAccessTokenFailure(&helper, &request1, error);
-}
-
TEST_F(GaiaCookieManagerServiceTest, ContinueAfterSuccess) {
InstrumentedGaiaCookieManagerService helper(token_service(), signin_client());
MockObserver observer(&helper);
diff --git a/chromium/components/signin/core/browser/identity_manager_wrapper.cc b/chromium/components/signin/core/browser/identity_manager_wrapper.cc
index 9281edbb567..2025ebcd649 100644
--- a/chromium/components/signin/core/browser/identity_manager_wrapper.cc
+++ b/chromium/components/signin/core/browser/identity_manager_wrapper.cc
@@ -11,7 +11,7 @@
#include "services/identity/public/cpp/primary_account_mutator.h"
IdentityManagerWrapper::IdentityManagerWrapper(
- AccountTrackerService* account_tracker_service,
+ std::unique_ptr<AccountTrackerService> account_tracker_service,
std::unique_ptr<ProfileOAuth2TokenService> token_service,
std::unique_ptr<GaiaCookieManagerService> gaia_cookie_manager_service,
std::unique_ptr<SigninManagerBase> signin_manager,
@@ -20,16 +20,12 @@ IdentityManagerWrapper::IdentityManagerWrapper(
std::unique_ptr<identity::AccountsMutator> accounts_mutator,
std::unique_ptr<identity::AccountsCookieMutator> accounts_cookie_mutator,
std::unique_ptr<identity::DiagnosticsProvider> diagnostics_provider)
- : identity::IdentityManager(std::move(token_service),
+ : identity::IdentityManager(std::move(account_tracker_service),
+ std::move(token_service),
std::move(gaia_cookie_manager_service),
std::move(signin_manager),
std::move(account_fetcher_service),
- account_tracker_service,
std::move(primary_account_mutator),
std::move(accounts_mutator),
std::move(accounts_cookie_mutator),
std::move(diagnostics_provider)) {}
-
-void IdentityManagerWrapper::Shutdown() {
- IdentityManager::Shutdown();
-}
diff --git a/chromium/components/signin/core/browser/identity_manager_wrapper.h b/chromium/components/signin/core/browser/identity_manager_wrapper.h
index 916d1961d4d..b1c03249a61 100644
--- a/chromium/components/signin/core/browser/identity_manager_wrapper.h
+++ b/chromium/components/signin/core/browser/identity_manager_wrapper.h
@@ -28,7 +28,7 @@ class IdentityManagerWrapper : public KeyedService,
public identity::IdentityManager {
public:
IdentityManagerWrapper(
- AccountTrackerService* account_tracker_service,
+ std::unique_ptr<AccountTrackerService> account_tracker_service,
std::unique_ptr<ProfileOAuth2TokenService> token_service,
std::unique_ptr<GaiaCookieManagerService> gaia_cookie_manager_service,
std::unique_ptr<SigninManagerBase> signin_manager,
@@ -37,9 +37,6 @@ class IdentityManagerWrapper : public KeyedService,
std::unique_ptr<identity::AccountsMutator> accounts_mutator,
std::unique_ptr<identity::AccountsCookieMutator> accounts_cookie_mutator,
std::unique_ptr<identity::DiagnosticsProvider> diagnostics_provider);
-
- // KeyedService overrides.
- void Shutdown() override;
};
#endif // COMPONENTS_SIGNIN_CORE_BROWSER_IDENTITY_MANAGER_WRAPPER_H_
diff --git a/chromium/components/signin/core/browser/mutable_profile_oauth2_token_service_delegate_unittest.cc b/chromium/components/signin/core/browser/mutable_profile_oauth2_token_service_delegate_unittest.cc
index df7b61bc268..7a42f2e4c1d 100644
--- a/chromium/components/signin/core/browser/mutable_profile_oauth2_token_service_delegate_unittest.cc
+++ b/chromium/components/signin/core/browser/mutable_profile_oauth2_token_service_delegate_unittest.cc
@@ -88,7 +88,7 @@ class MutableProfileOAuth2TokenServiceDelegateTest
MutableProfileOAuth2TokenServiceDelegateTest()
: scoped_task_environment_(
base::test::ScopedTaskEnvironment::MainThreadType::UI,
- base::test::ScopedTaskEnvironment::ExecutionMode::ASYNC),
+ base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::ASYNC),
access_token_success_count_(0),
access_token_failure_count_(0),
access_token_failure_(GoogleServiceAuthError::NONE),
@@ -107,7 +107,7 @@ class MutableProfileOAuth2TokenServiceDelegateTest
AccountTrackerService::RegisterPrefs(pref_service_.registry());
SigninManagerBase::RegisterProfilePrefs(pref_service_.registry());
client_.reset(new TestSigninClient(&pref_service_));
- client_->test_url_loader_factory()->AddResponse(
+ client_->GetTestURLLoaderFactory()->AddResponse(
GaiaUrls::GetInstance()->oauth2_revoke_url().spec(), "");
LoadTokenDatabase();
account_tracker_service_.Initialize(&pref_service_, base::FilePath());
@@ -138,7 +138,7 @@ class MutableProfileOAuth2TokenServiceDelegateTest
}
void AddSuccessfulOAuhTokenResponse() {
- client_->test_url_loader_factory()->AddResponse(
+ client_->GetTestURLLoaderFactory()->AddResponse(
GaiaUrls::GetInstance()->oauth2_token_url().spec(),
GetValidTokenResponse("token", 3600));
}
@@ -204,12 +204,12 @@ class MutableProfileOAuth2TokenServiceDelegateTest
}
// OAuth2TokenService::DiagnosticsObserver implementation
- void OnRefreshTokenAvailableFromSource(const std::string& account_id,
+ void OnRefreshTokenAvailableFromSource(const CoreAccountId& account_id,
bool is_refresh_token_valid,
const std::string& source) override {
source_for_refresh_token_available_ = source;
}
- void OnRefreshTokenRevokedFromSource(const std::string& account_id,
+ void OnRefreshTokenRevokedFromSource(const CoreAccountId& account_id,
const std::string& source) override {
source_for_refresh_token_revoked_ = source;
}
@@ -541,9 +541,9 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
account_tracker_service_.SeedAccountInfo(secondary_account);
ResetObserverCounts();
- AddAuthTokenManually("AccountId-" + primary_account.account_id,
+ AddAuthTokenManually("AccountId-" + primary_account.account_id.id,
"refresh_token");
- AddAuthTokenManually("AccountId-" + secondary_account.account_id,
+ AddAuthTokenManually("AccountId-" + secondary_account.account_id.id,
"refresh_token");
oauth2_service_delegate_->LoadCredentials(primary_account.account_id);
base::RunLoop().RunUntilIdle();
@@ -582,9 +582,9 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
account_tracker_service_.SeedAccountInfo(secondary_account);
ResetObserverCounts();
- AddAuthTokenManually("AccountId-" + primary_account.account_id,
+ AddAuthTokenManually("AccountId-" + primary_account.account_id.id,
"refresh_token");
- AddAuthTokenManually("AccountId-" + secondary_account.account_id,
+ AddAuthTokenManually("AccountId-" + secondary_account.account_id.id,
"refresh_token");
oauth2_service_delegate_->LoadCredentials(primary_account.account_id);
base::RunLoop().RunUntilIdle();
@@ -623,9 +623,9 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
account_tracker_service_.SeedAccountInfo(secondary_account);
ResetObserverCounts();
- AddAuthTokenManually("AccountId-" + primary_account.account_id,
+ AddAuthTokenManually("AccountId-" + primary_account.account_id.id,
"refresh_token");
- AddAuthTokenManually("AccountId-" + secondary_account.account_id,
+ AddAuthTokenManually("AccountId-" + secondary_account.account_id.id,
"refresh_token");
oauth2_service_delegate_->LoadCredentials(primary_account.account_id);
base::RunLoop().RunUntilIdle();
@@ -659,7 +659,7 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
account_tracker_service_.SeedAccountInfo(primary_account);
ResetObserverCounts();
- AddAuthTokenManually("AccountId-" + primary_account.account_id,
+ AddAuthTokenManually("AccountId-" + primary_account.account_id.id,
"refresh_token");
oauth2_service_delegate_->LoadCredentials(primary_account.account_id);
base::RunLoop().RunUntilIdle();
@@ -792,39 +792,39 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, RevokeRetries) {
InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kDisabled);
const std::string url = GaiaUrls::GetInstance()->oauth2_revoke_url().spec();
// Revokes will remain in "pending" state.
- client_->test_url_loader_factory()->ClearResponses();
+ client_->GetTestURLLoaderFactory()->ClearResponses();
oauth2_service_delegate_->UpdateCredentials("account_id", "refresh_token");
EXPECT_TRUE(oauth2_service_delegate_->server_revokes_.empty());
- EXPECT_FALSE(client_->test_url_loader_factory()->IsPending(url));
+ EXPECT_FALSE(client_->GetTestURLLoaderFactory()->IsPending(url));
oauth2_service_delegate_->RevokeCredentials("account_id");
EXPECT_EQ(1u, oauth2_service_delegate_->server_revokes_.size());
- EXPECT_TRUE(client_->test_url_loader_factory()->IsPending(url));
+ EXPECT_TRUE(client_->GetTestURLLoaderFactory()->IsPending(url));
// Fail and retry.
- client_->test_url_loader_factory()->SimulateResponseForPendingRequest(
+ client_->GetTestURLLoaderFactory()->SimulateResponseForPendingRequest(
url, std::string(), net::HTTP_INTERNAL_SERVER_ERROR);
- EXPECT_TRUE(client_->test_url_loader_factory()->IsPending(url));
+ EXPECT_TRUE(client_->GetTestURLLoaderFactory()->IsPending(url));
EXPECT_EQ(1u, oauth2_service_delegate_->server_revokes_.size());
// Fail and retry.
- client_->test_url_loader_factory()->SimulateResponseForPendingRequest(
+ client_->GetTestURLLoaderFactory()->SimulateResponseForPendingRequest(
url, std::string(), net::HTTP_INTERNAL_SERVER_ERROR);
- EXPECT_TRUE(client_->test_url_loader_factory()->IsPending(url));
+ EXPECT_TRUE(client_->GetTestURLLoaderFactory()->IsPending(url));
EXPECT_EQ(1u, oauth2_service_delegate_->server_revokes_.size());
// Do not retry after third attempt.
- client_->test_url_loader_factory()->SimulateResponseForPendingRequest(
+ client_->GetTestURLLoaderFactory()->SimulateResponseForPendingRequest(
url, std::string(), net::HTTP_INTERNAL_SERVER_ERROR);
- EXPECT_FALSE(client_->test_url_loader_factory()->IsPending(url));
+ EXPECT_FALSE(client_->GetTestURLLoaderFactory()->IsPending(url));
EXPECT_TRUE(oauth2_service_delegate_->server_revokes_.empty());
// No retry after success.
oauth2_service_delegate_->UpdateCredentials("account_id", "refresh_token");
oauth2_service_delegate_->RevokeCredentials("account_id");
EXPECT_EQ(1u, oauth2_service_delegate_->server_revokes_.size());
- EXPECT_TRUE(client_->test_url_loader_factory()->IsPending(url));
- client_->test_url_loader_factory()->SimulateResponseForPendingRequest(
+ EXPECT_TRUE(client_->GetTestURLLoaderFactory()->IsPending(url));
+ client_->GetTestURLLoaderFactory()->SimulateResponseForPendingRequest(
url, std::string(), net::HTTP_OK);
- EXPECT_FALSE(client_->test_url_loader_factory()->IsPending(url));
+ EXPECT_FALSE(client_->GetTestURLLoaderFactory()->IsPending(url));
EXPECT_TRUE(oauth2_service_delegate_->server_revokes_.empty());
}
diff --git a/chromium/components/signin/core/browser/oauth2_token_service_delegate_android.cc b/chromium/components/signin/core/browser/oauth2_token_service_delegate_android.cc
index 575b6123c44..386c6dc93e7 100644
--- a/chromium/components/signin/core/browser/oauth2_token_service_delegate_android.cc
+++ b/chromium/components/signin/core/browser/oauth2_token_service_delegate_android.cc
@@ -150,16 +150,14 @@ OAuth2TokenServiceDelegateAndroid::OAuth2TokenServiceDelegateAndroid(
if (account_tracker_service_->GetMigrationState() ==
AccountTrackerService::MIGRATION_IN_PROGRESS) {
std::vector<std::string> accounts = GetAccounts();
- std::vector<std::string> accounts_id;
+ std::vector<CoreAccountId> accounts_id;
for (auto account_name : accounts) {
AccountInfo account_info =
account_tracker_service_->FindAccountInfoByEmail(account_name);
DCHECK(!account_info.gaia.empty());
accounts_id.push_back(account_info.gaia);
}
- ScopedJavaLocalRef<jobjectArray> java_accounts(
- base::android::ToJavaArrayOfStrings(env, accounts_id));
- Java_OAuth2TokenService_saveStoredAccounts(env, java_accounts);
+ SetAccounts(accounts_id);
}
if (!disable_interaction_with_system_accounts_) {
@@ -244,6 +242,36 @@ OAuth2TokenServiceDelegateAndroid::GetSystemAccountNames() {
return account_names;
}
+std::vector<CoreAccountId>
+OAuth2TokenServiceDelegateAndroid::GetSystemAccounts() {
+ std::vector<CoreAccountId> ids;
+ for (const std::string& name : GetSystemAccountNames()) {
+ CoreAccountId id(MapAccountNameToAccountId(name));
+ if (!id.empty())
+ ids.push_back(std::move(id));
+ }
+ return ids;
+}
+
+std::vector<CoreAccountId>
+OAuth2TokenServiceDelegateAndroid::GetValidAccounts() {
+ std::vector<CoreAccountId> ids;
+ for (const std::string& id : GetAccounts()) {
+ if (ValidateAccountId(id))
+ ids.emplace_back(id);
+ }
+ return ids;
+}
+
+void OAuth2TokenServiceDelegateAndroid::SetAccounts(
+ const std::vector<CoreAccountId>& accounts) {
+ JNIEnv* env = AttachCurrentThread();
+ std::vector<std::string> str_ids(accounts.begin(), accounts.end());
+ ScopedJavaLocalRef<jobjectArray> java_accounts(
+ base::android::ToJavaArrayOfStrings(env, str_ids));
+ Java_OAuth2TokenService_setAccounts(env, java_accounts);
+}
+
OAuth2AccessTokenFetcher*
OAuth2TokenServiceDelegateAndroid::CreateAccessTokenFetcher(
const std::string& account_id,
@@ -284,52 +312,33 @@ void OAuth2TokenServiceDelegateAndroid::UpdateAccountList(
// Clear any auth errors so that client can retry to get access tokens.
errors_.clear();
- UpdateAccountList(MapAccountNameToAccountId(signed_in_account_name));
+ UpdateAccountList(MapAccountNameToAccountId(signed_in_account_name),
+ GetValidAccounts(), GetSystemAccounts());
}
void OAuth2TokenServiceDelegateAndroid::UpdateAccountList(
- const std::string& signed_in_account_id) {
- std::vector<std::string> curr_ids;
- for (const std::string& curr_name : GetSystemAccountNames()) {
- std::string curr_id(MapAccountNameToAccountId(curr_name));
- if (!curr_id.empty())
- curr_ids.push_back(curr_id);
- }
-
- std::vector<std::string> prev_ids;
- for (const std::string& prev_id : GetAccounts()) {
- if (ValidateAccountId(prev_id))
- prev_ids.push_back(prev_id);
- }
-
+ const CoreAccountId& signed_in_account_id,
+ const std::vector<CoreAccountId>& prev_ids,
+ const std::vector<CoreAccountId>& curr_ids) {
DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::UpdateAccountList:"
<< " sigined_in_account_id=" << signed_in_account_id
<< " prev_ids=" << prev_ids.size()
<< " curr_ids=" << curr_ids.size();
- std::vector<std::string> refreshed_ids;
- std::vector<std::string> revoked_ids;
+ std::vector<CoreAccountId> refreshed_ids;
+ std::vector<CoreAccountId> revoked_ids;
bool keep_accounts = UpdateAccountList(
signed_in_account_id, prev_ids, curr_ids, &refreshed_ids, &revoked_ids);
ScopedBatchChange batch(this);
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobjectArray> java_accounts;
- if (keep_accounts) {
- java_accounts = base::android::ToJavaArrayOfStrings(env, curr_ids);
- } else {
- DCHECK(!base::FeatureList::IsEnabled(signin::kMiceFeature));
- java_accounts =
- base::android::ToJavaArrayOfStrings(env, std::vector<std::string>());
- }
// Save the current accounts in the token service before calling
// FireRefreshToken* methods.
- Java_OAuth2TokenService_saveStoredAccounts(env, java_accounts);
+ SetAccounts(keep_accounts ? curr_ids : std::vector<CoreAccountId>());
- for (const std::string& refreshed_id : refreshed_ids)
+ for (const CoreAccountId& refreshed_id : refreshed_ids)
FireRefreshTokenAvailable(refreshed_id);
- for (const std::string& revoked_id : revoked_ids)
+ for (const CoreAccountId& revoked_id : revoked_ids)
FireRefreshTokenRevoked(revoked_id);
if (fire_refresh_token_loaded_ == RT_WAIT_FOR_VALIDATION) {
fire_refresh_token_loaded_ = RT_LOADED;
@@ -338,7 +347,7 @@ void OAuth2TokenServiceDelegateAndroid::UpdateAccountList(
fire_refresh_token_loaded_ = RT_HAS_BEEN_VALIDATED;
}
- // Clear accounts no longer exist on device from AccountTrackerService.
+ // Clear accounts that no longer exist on device from AccountTrackerService.
std::vector<AccountInfo> accounts_info =
account_tracker_service_->GetAccounts();
for (const AccountInfo& info : accounts_info) {
@@ -361,16 +370,16 @@ void OAuth2TokenServiceDelegateAndroid::UpdateAccountList(
}
bool OAuth2TokenServiceDelegateAndroid::UpdateAccountList(
- const std::string& signed_in_id,
- const std::vector<std::string>& prev_ids,
- const std::vector<std::string>& curr_ids,
- std::vector<std::string>* refreshed_ids,
- std::vector<std::string>* revoked_ids) {
+ const CoreAccountId& signed_in_id,
+ const std::vector<CoreAccountId>& prev_ids,
+ const std::vector<CoreAccountId>& curr_ids,
+ std::vector<CoreAccountId>* refreshed_ids,
+ std::vector<CoreAccountId>* revoked_ids) {
bool keep_accounts = base::FeatureList::IsEnabled(signin::kMiceFeature) ||
base::ContainsValue(curr_ids, signed_in_id);
if (keep_accounts) {
// Revoke token for ids that have been removed from the device.
- for (const std::string& prev_id : prev_ids) {
+ for (const CoreAccountId& prev_id : prev_ids) {
if (prev_id == signed_in_id)
continue;
if (!base::ContainsValue(curr_ids, prev_id)) {
@@ -386,7 +395,7 @@ bool OAuth2TokenServiceDelegateAndroid::UpdateAccountList(
<< "refreshed=" << signed_in_id;
refreshed_ids->push_back(signed_in_id);
}
- for (const std::string& curr_id : curr_ids) {
+ for (const CoreAccountId& curr_id : curr_ids) {
if (curr_id == signed_in_id)
continue;
DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::UpdateAccountList:"
@@ -400,7 +409,7 @@ bool OAuth2TokenServiceDelegateAndroid::UpdateAccountList(
<< "revoked=" << signed_in_id;
revoked_ids->push_back(signed_in_id);
}
- for (const std::string& prev_id : prev_ids) {
+ for (const CoreAccountId& prev_id : prev_ids) {
if (prev_id == signed_in_id)
continue;
DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::UpdateAccountList:"
@@ -469,10 +478,7 @@ void OAuth2TokenServiceDelegateAndroid::RevokeAllCredentials() {
// Clear accounts in the token service before calling
// |FireRefreshTokenRevoked|.
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobjectArray> java_accounts(
- base::android::ToJavaArrayOfStrings(env, std::vector<std::string>()));
- Java_OAuth2TokenService_saveStoredAccounts(env, java_accounts);
+ SetAccounts(std::vector<CoreAccountId>());
for (const std::string& account : accounts_to_revoke)
FireRefreshTokenRevoked(account);
@@ -499,17 +505,18 @@ void OAuth2TokenServiceDelegateAndroid::ReloadAccountsFromSystem(
const std::string& primary_account_id) {
// UpdateAccountList() effectively synchronizes the accounts in the Token
// Service with those present at the system level.
- UpdateAccountList(primary_account_id);
+ UpdateAccountList(primary_account_id, GetValidAccounts(),
+ GetSystemAccounts());
}
std::string OAuth2TokenServiceDelegateAndroid::MapAccountIdToAccountName(
- const std::string& account_id) const {
+ const CoreAccountId& account_id) const {
return account_tracker_service_->GetAccountInfo(account_id).email;
}
-std::string OAuth2TokenServiceDelegateAndroid::MapAccountNameToAccountId(
+CoreAccountId OAuth2TokenServiceDelegateAndroid::MapAccountNameToAccountId(
const std::string& account_name) const {
- std::string account_id =
+ CoreAccountId account_id =
account_tracker_service_->FindAccountInfoByEmail(account_name).account_id;
DCHECK(!account_id.empty() || account_name.empty())
<< "Can't find account id, account_name=" << account_name;
diff --git a/chromium/components/signin/core/browser/oauth2_token_service_delegate_android.h b/chromium/components/signin/core/browser/oauth2_token_service_delegate_android.h
index 8808eeac0e5..d3603245d49 100644
--- a/chromium/components/signin/core/browser/oauth2_token_service_delegate_android.h
+++ b/chromium/components/signin/core/browser/oauth2_token_service_delegate_android.h
@@ -55,9 +55,6 @@ class OAuth2TokenServiceDelegateAndroid : public OAuth2TokenServiceDelegate {
const GoogleServiceAuthError& error) override;
std::vector<std::string> GetAccounts() override;
- // Lists account names at the OS level.
- std::vector<std::string> GetSystemAccountNames();
-
void UpdateAccountList(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
@@ -67,7 +64,9 @@ class OAuth2TokenServiceDelegateAndroid : public OAuth2TokenServiceDelegate {
// android account ids and check the token status of each.
// NOTE: TokenAvailable notifications will be sent for all accounts, even if
// they were already known. See https://crbug.com/939470 for details.
- void UpdateAccountList(const std::string& signed_in_account_id);
+ void UpdateAccountList(const CoreAccountId& signed_in_account_id,
+ const std::vector<CoreAccountId>& prev_ids,
+ const std::vector<CoreAccountId>& curr_ids);
// Overridden from OAuth2TokenService to complete signout of all
// OA2TService aware accounts.
@@ -98,8 +97,9 @@ class OAuth2TokenServiceDelegateAndroid : public OAuth2TokenServiceDelegate {
void FireRefreshTokensLoaded() override;
private:
- std::string MapAccountIdToAccountName(const std::string& account_id) const;
- std::string MapAccountNameToAccountId(const std::string& account_name) const;
+ std::string MapAccountIdToAccountName(const CoreAccountId& account_id) const;
+ CoreAccountId MapAccountNameToAccountId(
+ const std::string& account_name) const;
enum RefreshTokenLoadStatus {
RT_LOAD_NOT_START,
@@ -110,11 +110,20 @@ class OAuth2TokenServiceDelegateAndroid : public OAuth2TokenServiceDelegate {
// Return whether accounts are valid and we have access to all the tokens in
// |curr_ids|.
- bool UpdateAccountList(const std::string& signed_in_id,
- const std::vector<std::string>& prev_ids,
- const std::vector<std::string>& curr_ids,
- std::vector<std::string>* refreshed_ids,
- std::vector<std::string>* revoked_ids);
+ bool UpdateAccountList(const CoreAccountId& signed_in_id,
+ const std::vector<CoreAccountId>& prev_ids,
+ const std::vector<CoreAccountId>& curr_ids,
+ std::vector<CoreAccountId>* refreshed_ids,
+ std::vector<CoreAccountId>* revoked_ids);
+
+ // Lists account names at the OS level.
+ std::vector<std::string> GetSystemAccountNames();
+ // As |GetSystemAccountNames| but returning account IDs.
+ std::vector<CoreAccountId> GetSystemAccounts();
+ // As |GetAccounts| but with only validated account IDs.
+ std::vector<CoreAccountId> GetValidAccounts();
+ // Set accounts using Java's Oauth2TokenService.setAccounts.
+ virtual void SetAccounts(const std::vector<CoreAccountId>& accounts);
base::android::ScopedJavaGlobalRef<jobject> java_ref_;
diff --git a/chromium/components/signin/core/browser/oauth2_token_service_delegate_android_unittest.cc b/chromium/components/signin/core/browser/oauth2_token_service_delegate_android_unittest.cc
new file mode 100644
index 00000000000..6fe207ad174
--- /dev/null
+++ b/chromium/components/signin/core/browser/oauth2_token_service_delegate_android_unittest.cc
@@ -0,0 +1,294 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/core/browser/oauth2_token_service_delegate_android.h"
+
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::InSequence;
+using ::testing::Return;
+using ::testing::Sequence;
+using ::testing::StrictMock;
+
+namespace signin {
+
+namespace {
+const std::vector<CoreAccountId> kEmptyVector;
+class OAuth2TokenServiceDelegateAndroidForTest
+ : public OAuth2TokenServiceDelegateAndroid {
+ public:
+ OAuth2TokenServiceDelegateAndroidForTest(
+ AccountTrackerService* account_tracker_service)
+ : OAuth2TokenServiceDelegateAndroid(account_tracker_service) {}
+ MOCK_METHOD1(SetAccounts, void(const std::vector<CoreAccountId>&));
+};
+
+class TestObserver : public OAuth2TokenService::Observer {
+ public:
+ MOCK_METHOD1(OnRefreshTokenAvailable, void(const std::string&));
+ MOCK_METHOD1(OnRefreshTokenRevoked, void(const std::string&));
+ MOCK_METHOD0(OnRefreshTokensLoaded, void());
+};
+} // namespace
+
+class OAuth2TokenServiceDelegateAndroidTest : public testing::Test {
+ public:
+ OAuth2TokenServiceDelegateAndroidTest() {}
+ ~OAuth2TokenServiceDelegateAndroidTest() override = default;
+
+ protected:
+ void SetUp() override {
+ testing::Test::SetUp();
+ AccountTrackerService::RegisterPrefs(pref_service_.registry());
+ account_tracker_service_.Initialize(&pref_service_, base::FilePath());
+ OAuth2TokenServiceDelegateAndroid::
+ set_disable_interaction_with_system_accounts();
+ delegate_ = std::make_unique<OAuth2TokenServiceDelegateAndroidForTest>(
+ &account_tracker_service_);
+ delegate_->AddObserver(&observer_);
+ CreateAndSeedAccounts();
+ }
+
+ void TearDown() override {
+ delegate_->RemoveObserver(&observer_);
+ testing::Test::TearDown();
+ }
+
+ AccountInfo CreateAccountInfo(const std::string& gaia_id,
+ const std::string& email) {
+ AccountInfo account_info;
+
+ account_info.gaia = gaia_id;
+ account_info.email = email;
+ account_info.full_name = "fullname";
+ account_info.given_name = "givenname";
+ account_info.hosted_domain = "example.com";
+ account_info.locale = "en";
+ account_info.picture_url = "https://example.com";
+ account_info.is_child_account = false;
+ account_info.account_id = account_tracker_service_.PickAccountIdForAccount(
+ account_info.gaia, account_info.email);
+
+ DCHECK(account_info.IsValid());
+
+ return account_info;
+ }
+
+ void CreateAndSeedAccounts() {
+ account1_ = CreateAccountInfo("gaia-id-user-1", "user-1@example.com");
+ account2_ = CreateAccountInfo("gaia-id-user-2", "user-2@example.com");
+ // SeedAccountInfo is required for
+ // OAuth2TokenServiceDelegateAndrod::MapAccountNameToAccountId
+ account_tracker_service_.SeedAccountInfo(account1_);
+ account_tracker_service_.SeedAccountInfo(account2_);
+ }
+
+ AccountTrackerService account_tracker_service_;
+ sync_preferences::TestingPrefServiceSyncable pref_service_;
+ std::unique_ptr<OAuth2TokenServiceDelegateAndroidForTest> delegate_;
+ StrictMock<TestObserver> observer_;
+
+ AccountInfo account1_;
+ AccountInfo account2_;
+};
+
+TEST_F(OAuth2TokenServiceDelegateAndroidTest,
+ UpdateAccountListWith0SystemAccount0AccountAndNotSignedIn) {
+ EXPECT_CALL(*delegate_, SetAccounts(kEmptyVector)).WillOnce(Return());
+ // No observer call expected
+ delegate_->UpdateAccountList(std::string(), {}, {});
+ EXPECT_TRUE(account_tracker_service_.GetAccounts().empty());
+}
+
+TEST_F(OAuth2TokenServiceDelegateAndroidTest,
+ UpdateAccountListWith1SystemAccount0AccountAndNotSignedIn) {
+ EXPECT_CALL(*delegate_, SetAccounts(kEmptyVector)).WillOnce(Return());
+ // No observer call expected
+ delegate_->UpdateAccountList(std::string(), {}, {account1_.account_id});
+ EXPECT_EQ(std::vector<AccountInfo>{account1_},
+ account_tracker_service_.GetAccounts());
+}
+
+TEST_F(OAuth2TokenServiceDelegateAndroidTest,
+ UpdateAccountListWith1SystemAccount1AccountAndNotSignedIn) {
+ Sequence seq;
+ EXPECT_CALL(*delegate_, SetAccounts(kEmptyVector))
+ .InSequence(seq)
+ .WillOnce(Return());
+ // Stored account from |GetAccounts| must fire a revoked event
+ EXPECT_CALL(observer_, OnRefreshTokenRevoked(account1_.account_id.id))
+ .InSequence(seq)
+ .WillOnce(Return());
+
+ delegate_->UpdateAccountList(std::string(), {account1_.account_id},
+ {account1_.account_id});
+ EXPECT_EQ(std::vector<AccountInfo>{account1_},
+ account_tracker_service_.GetAccounts());
+}
+
+TEST_F(OAuth2TokenServiceDelegateAndroidTest,
+ UpdateAccountListWith1SystemAccount0AccountAndSignedIn) {
+ Sequence seq;
+ EXPECT_CALL(*delegate_,
+ SetAccounts(std::vector<CoreAccountId>({account1_.account_id})))
+ .InSequence(seq)
+ .WillOnce(Return());
+ EXPECT_CALL(observer_, OnRefreshTokenAvailable(account1_.account_id.id))
+ .InSequence(seq)
+ .WillOnce(Return());
+
+ delegate_->UpdateAccountList(account1_.account_id, {},
+ {account1_.account_id});
+ EXPECT_EQ(std::vector<AccountInfo>{account1_},
+ account_tracker_service_.GetAccounts());
+}
+
+TEST_F(OAuth2TokenServiceDelegateAndroidTest,
+ UpdateAccountListWith1SystemAccount1AccountAndSignedIn) {
+ Sequence seq;
+ EXPECT_CALL(*delegate_,
+ SetAccounts(std::vector<CoreAccountId>({account1_.account_id})))
+ .InSequence(seq)
+ .WillOnce(Return());
+ EXPECT_CALL(observer_, OnRefreshTokenAvailable(account1_.account_id.id))
+ .InSequence(seq)
+ .WillOnce(Return());
+
+ delegate_->UpdateAccountList(account1_.account_id, {account1_.account_id},
+ {account1_.account_id});
+ EXPECT_EQ(std::vector<AccountInfo>{account1_},
+ account_tracker_service_.GetAccounts());
+}
+
+TEST_F(OAuth2TokenServiceDelegateAndroidTest,
+ UpdateAccountListWith1SystemAccount1AccountDifferentAndSignedIn) {
+ Sequence seq;
+ EXPECT_CALL(*delegate_,
+ SetAccounts(std::vector<CoreAccountId>({account1_.account_id})))
+ .InSequence(seq)
+ .WillOnce(Return());
+ // Previously stored account is removed, new account is available
+ EXPECT_CALL(observer_, OnRefreshTokenAvailable(account1_.account_id.id))
+ .InSequence(seq)
+ .WillOnce(Return());
+ EXPECT_CALL(observer_, OnRefreshTokenRevoked(account2_.account_id.id))
+ .InSequence(seq)
+ .WillOnce(Return());
+
+ delegate_->UpdateAccountList(account1_.account_id, {account2_.account_id},
+ {account1_.account_id});
+ EXPECT_EQ(std::vector<AccountInfo>{account1_},
+ account_tracker_service_.GetAccounts());
+}
+
+TEST_F(OAuth2TokenServiceDelegateAndroidTest,
+ UpdateAccountListWith0SystemAccount1AccountSignedIn) {
+ Sequence seq;
+ EXPECT_CALL(*delegate_, SetAccounts(kEmptyVector))
+ .InSequence(seq)
+ .WillOnce(Return());
+ EXPECT_CALL(observer_, OnRefreshTokenRevoked(account1_.account_id.id))
+ .InSequence(seq)
+ .WillOnce(Return());
+
+ delegate_->UpdateAccountList(account1_.account_id, {account1_.account_id},
+ {});
+ EXPECT_TRUE(account_tracker_service_.GetAccounts().empty());
+}
+
+TEST_F(OAuth2TokenServiceDelegateAndroidTest,
+ UpdateAccountListWith1SystemAccount0AccountAndSignedInDifferent) {
+ EXPECT_CALL(*delegate_, SetAccounts(kEmptyVector)).WillOnce(Return());
+
+ delegate_->UpdateAccountList(account2_.account_id, {},
+ {account1_.account_id});
+ EXPECT_EQ(std::vector<AccountInfo>{account1_},
+ account_tracker_service_.GetAccounts());
+}
+
+// Test Getsysaccounts return a user != from signed user while GetAccounts not
+// empty
+TEST_F(OAuth2TokenServiceDelegateAndroidTest,
+ UpdateAccountListWith1SystemAccount1AccountAndSignedInDifferent) {
+ Sequence seq;
+ EXPECT_CALL(*delegate_, SetAccounts(kEmptyVector))
+ .InSequence(seq)
+ .WillOnce(Return());
+ EXPECT_CALL(observer_, OnRefreshTokenRevoked(account1_.account_id.id))
+ .InSequence(seq)
+ .WillOnce(Return());
+
+ delegate_->UpdateAccountList(account2_.account_id, {account1_.account_id},
+ {account1_.account_id});
+ EXPECT_EQ(std::vector<AccountInfo>{account1_},
+ account_tracker_service_.GetAccounts());
+}
+
+TEST_F(OAuth2TokenServiceDelegateAndroidTest,
+ UpdateAccountListWith2SystemAccount0AccountAndSignedIn) {
+ Sequence seq;
+ EXPECT_CALL(*delegate_, SetAccounts(std::vector<CoreAccountId>(
+ {account1_.account_id, account2_.account_id})))
+ .InSequence(seq)
+ .WillOnce(Return());
+ // OnRefreshTokenAvailable fired, signed in account should go first.
+ EXPECT_CALL(observer_, OnRefreshTokenAvailable(account2_.account_id.id))
+ .InSequence(seq)
+ .WillOnce(Return());
+ EXPECT_CALL(observer_, OnRefreshTokenAvailable(account1_.account_id.id))
+ .InSequence(seq)
+ .WillOnce(Return());
+
+ delegate_->UpdateAccountList(account2_.account_id, {},
+ {account1_.account_id, account2_.account_id});
+ EXPECT_EQ(std::vector<AccountInfo>({account1_, account2_}),
+ account_tracker_service_.GetAccounts());
+}
+
+TEST_F(OAuth2TokenServiceDelegateAndroidTest,
+ UpdateAccountListWith2SystemAccount1AccountAndSignedIn) {
+ Sequence seq;
+ EXPECT_CALL(*delegate_, SetAccounts(std::vector<CoreAccountId>(
+ {account1_.account_id, account2_.account_id})))
+ .InSequence(seq)
+ .WillOnce(Return());
+ // OnRefreshTokenAvailable fired, signed in account should go first.
+ EXPECT_CALL(observer_, OnRefreshTokenAvailable(account1_.account_id.id))
+ .InSequence(seq)
+ .WillOnce(Return());
+ EXPECT_CALL(observer_, OnRefreshTokenAvailable(account2_.account_id.id))
+ .InSequence(seq)
+ .WillOnce(Return());
+ delegate_->UpdateAccountList(account1_.account_id, {account2_.account_id},
+ {account1_.account_id, account2_.account_id});
+ EXPECT_EQ(std::vector<AccountInfo>({account1_, account2_}),
+ account_tracker_service_.GetAccounts());
+}
+
+TEST_F(OAuth2TokenServiceDelegateAndroidTest,
+ UpdateAccountListWith1SystemAccount2AccountAndSignedIn) {
+ Sequence seq;
+ EXPECT_CALL(*delegate_,
+ SetAccounts(std::vector<CoreAccountId>({account1_.account_id})))
+ .InSequence(seq)
+ .WillOnce(Return());
+ // OnRefreshTokenAvailable fired, signed in account should go first.
+ EXPECT_CALL(observer_, OnRefreshTokenAvailable(account1_.account_id.id))
+ .InSequence(seq)
+ .WillOnce(Return());
+ EXPECT_CALL(observer_, OnRefreshTokenRevoked(account2_.account_id.id))
+ .InSequence(seq)
+ .WillOnce(Return());
+
+ delegate_->UpdateAccountList(account1_.account_id,
+ {account1_.account_id, account2_.account_id},
+ {account1_.account_id});
+ EXPECT_EQ(std::vector<AccountInfo>({account1_}),
+ account_tracker_service_.GetAccounts());
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/core/browser/oauth_multilogin_helper.cc b/chromium/components/signin/core/browser/oauth_multilogin_helper.cc
new file mode 100644
index 00000000000..ab38dc09254
--- /dev/null
+++ b/chromium/components/signin/core/browser/oauth_multilogin_helper.cc
@@ -0,0 +1,202 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/core/browser/oauth_multilogin_helper.h"
+
+#include <algorithm>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
+#include "components/signin/core/browser/oauth_multilogin_token_fetcher.h"
+#include "components/signin/core/browser/set_accounts_in_cookie_result.h"
+#include "components/signin/core/browser/signin_client.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "google_apis/gaia/oauth_multilogin_result.h"
+#include "mojo/public/cpp/bindings/callback_helpers.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+
+namespace {
+
+constexpr int kMaxFetcherRetries = 3;
+
+std::string FindTokenForAccount(
+ const std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>& token_id_pairs,
+ const std::string& account_id) {
+ for (auto it = token_id_pairs.cbegin(); it != token_id_pairs.cend(); ++it) {
+ if (account_id == it->gaia_id_)
+ return it->token_;
+ }
+ return std::string();
+}
+
+} // namespace
+
+namespace signin {
+
+OAuthMultiloginHelper::OAuthMultiloginHelper(
+ SigninClient* signin_client,
+ OAuth2TokenService* token_service,
+ const std::vector<std::string>& account_ids,
+ const std::string& external_cc_result,
+ base::OnceCallback<void(signin::SetAccountsInCookieResult)> callback)
+ : signin_client_(signin_client),
+ token_service_(token_service),
+ account_ids_(account_ids),
+ external_cc_result_(external_cc_result),
+ callback_(std::move(callback)),
+ weak_ptr_factory_(this) {
+ DCHECK(signin_client_);
+ DCHECK(token_service_);
+ DCHECK(!account_ids_.empty());
+ DCHECK(callback_);
+
+#ifndef NDEBUG
+ // Check that there is no duplicate accounts.
+ std::set<std::string> accounts_no_duplicates(account_ids_.begin(),
+ account_ids_.end());
+ DCHECK_EQ(account_ids_.size(), accounts_no_duplicates.size());
+#endif
+
+ StartFetchingTokens();
+}
+
+OAuthMultiloginHelper::~OAuthMultiloginHelper() = default;
+
+void OAuthMultiloginHelper::StartFetchingTokens() {
+ DCHECK(!token_fetcher_);
+ DCHECK(token_id_pairs_.empty());
+ token_fetcher_ = std::make_unique<signin::OAuthMultiloginTokenFetcher>(
+ signin_client_, token_service_, account_ids_,
+ base::BindOnce(&OAuthMultiloginHelper::OnAccessTokensSuccess,
+ base::Unretained(this)),
+ base::BindOnce(&OAuthMultiloginHelper::OnAccessTokensFailure,
+ base::Unretained(this)));
+}
+
+void OAuthMultiloginHelper::OnAccessTokensSuccess(
+ const std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>& token_id_pairs) {
+ DCHECK(token_id_pairs_.empty());
+ token_id_pairs_ = token_id_pairs;
+ DCHECK_EQ(token_id_pairs_.size(), account_ids_.size());
+ token_fetcher_.reset();
+
+ signin_client_->DelayNetworkCall(
+ base::BindOnce(&OAuthMultiloginHelper::StartFetchingMultiLogin,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void OAuthMultiloginHelper::OnAccessTokensFailure(
+ const GoogleServiceAuthError& error) {
+ token_fetcher_.reset();
+ std::move(callback_).Run(
+ error.IsTransientError()
+ ? signin::SetAccountsInCookieResult::kTransientError
+ : signin::SetAccountsInCookieResult::kPersistentError);
+ // Do not add anything below this line, because this may be deleted.
+}
+
+void OAuthMultiloginHelper::StartFetchingMultiLogin() {
+ DCHECK_EQ(token_id_pairs_.size(), account_ids_.size());
+ gaia_auth_fetcher_ =
+ signin_client_->CreateGaiaAuthFetcher(this, gaia::GaiaSource::kChrome);
+ gaia_auth_fetcher_->StartOAuthMultilogin(token_id_pairs_,
+ external_cc_result_);
+}
+
+void OAuthMultiloginHelper::OnOAuthMultiloginFinished(
+ const OAuthMultiloginResult& result) {
+ if (result.status() == OAuthMultiloginResponseStatus::kOk) {
+ VLOG(1) << "Multilogin successful accounts="
+ << base::JoinString(account_ids_, " ");
+ StartSettingCookies(result);
+ return;
+ }
+
+ // If Gaia responded with kInvalidTokens, we have to mark tokens as invalid.
+ if (result.status() == OAuthMultiloginResponseStatus::kInvalidTokens) {
+ for (const std::string& failed_account_id : result.failed_accounts()) {
+ std::string failed_token =
+ FindTokenForAccount(token_id_pairs_, failed_account_id);
+ if (failed_token.empty()) {
+ LOG(ERROR)
+ << "Unexpected failed token for account not present in request: "
+ << failed_account_id;
+ continue;
+ }
+ token_service_->InvalidateTokenForMultilogin(failed_account_id,
+ failed_token);
+ }
+ }
+
+ bool is_transient_error =
+ result.status() == OAuthMultiloginResponseStatus::kInvalidTokens ||
+ result.status() == OAuthMultiloginResponseStatus::kRetry;
+
+ if (is_transient_error && ++fetcher_retries_ < kMaxFetcherRetries) {
+ token_id_pairs_.clear();
+ StartFetchingTokens();
+ return;
+ }
+ std::move(callback_).Run(
+ is_transient_error ? signin::SetAccountsInCookieResult::kTransientError
+ : signin::SetAccountsInCookieResult::kPersistentError);
+ // Do not add anything below this line, because this may be deleted.
+}
+
+void OAuthMultiloginHelper::StartSettingCookies(
+ const OAuthMultiloginResult& result) {
+ DCHECK(cookies_to_set_.empty());
+ network::mojom::CookieManager* cookie_manager =
+ signin_client_->GetCookieManager();
+ const std::vector<net::CanonicalCookie>& cookies = result.cookies();
+
+ for (const net::CanonicalCookie& cookie : cookies) {
+ cookies_to_set_.insert(std::make_pair(cookie.Name(), cookie.Domain()));
+ }
+ for (const net::CanonicalCookie& cookie : cookies) {
+ if (cookies_to_set_.find(std::make_pair(cookie.Name(), cookie.Domain())) !=
+ cookies_to_set_.end()) {
+ base::OnceCallback<void(net::CanonicalCookie::CookieInclusionStatus)>
+ callback = base::BindOnce(&OAuthMultiloginHelper::OnCookieSet,
+ weak_ptr_factory_.GetWeakPtr(),
+ cookie.Name(), cookie.Domain());
+ net::CookieOptions options;
+ options.set_include_httponly();
+ // Permit it to set a SameSite cookie if it wants to.
+ options.set_same_site_cookie_context(
+ net::CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT);
+ cookie_manager->SetCanonicalCookie(
+ cookie, "https", options,
+ mojo::WrapCallbackWithDefaultInvokeIfNotRun(
+ std::move(callback), net::CanonicalCookie::CookieInclusionStatus::
+ EXCLUDE_UNKNOWN_ERROR));
+ } else {
+ LOG(ERROR) << "Duplicate cookie found: " << cookie.Name() << " "
+ << cookie.Domain();
+ }
+ }
+}
+
+void OAuthMultiloginHelper::OnCookieSet(
+ const std::string& cookie_name,
+ const std::string& cookie_domain,
+ net::CanonicalCookie::CookieInclusionStatus status) {
+ cookies_to_set_.erase(std::make_pair(cookie_name, cookie_domain));
+ bool success =
+ (status == net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+ if (!success) {
+ LOG(ERROR) << "Failed to set cookie " << cookie_name
+ << " for domain=" << cookie_domain << ".";
+ }
+ UMA_HISTOGRAM_BOOLEAN("Signin.SetCookieSuccess", success);
+ if (cookies_to_set_.empty())
+ std::move(callback_).Run(signin::SetAccountsInCookieResult::kSuccess);
+ // Do not add anything below this line, because this may be deleted.
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/core/browser/oauth_multilogin_helper.h b/chromium/components/signin/core/browser/oauth_multilogin_helper.h
new file mode 100644
index 00000000000..69064a9f0b0
--- /dev/null
+++ b/chromium/components/signin/core/browser/oauth_multilogin_helper.h
@@ -0,0 +1,98 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_OAUTH_MULTILOGIN_HELPER_H_
+#define COMPONENTS_SIGNIN_CORE_BROWSER_OAUTH_MULTILOGIN_HELPER_H_
+
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "google_apis/gaia/gaia_auth_consumer.h"
+#include "google_apis/gaia/gaia_auth_fetcher.h"
+#include "services/network/public/mojom/cookie_manager.mojom.h"
+
+class GaiaAuthFetcher;
+class GoogleServiceAuthError;
+class OAuth2TokenService;
+class SigninClient;
+
+namespace signin {
+
+class OAuthMultiloginTokenFetcher;
+enum class SetAccountsInCookieResult;
+
+// This is a helper class that drives the OAuth multilogin process.
+// The main steps are:
+// - fetch access tokens with login scope,
+// - call the oauth multilogin endpoint,
+// - get the cookies from the response body, and set them in the cookie manager.
+// It is safe to delete this object from within the callbacks.
+class OAuthMultiloginHelper : public GaiaAuthConsumer {
+ public:
+ OAuthMultiloginHelper(
+ SigninClient* signin_client,
+ OAuth2TokenService* token_service,
+ const std::vector<std::string>& account_ids,
+ const std::string& external_cc_result,
+ base::OnceCallback<void(signin::SetAccountsInCookieResult)> callback);
+
+ ~OAuthMultiloginHelper() override;
+
+ private:
+ // Starts fetching tokens with OAuthMultiloginTokenFetcher.
+ void StartFetchingTokens();
+
+ // Callbacks for OAuthMultiloginTokenFetcher.
+ void OnAccessTokensSuccess(
+ const std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>&
+ token_id_pairs);
+ void OnAccessTokensFailure(const GoogleServiceAuthError& error);
+
+ // Actual call to the multilogin endpoint.
+ void StartFetchingMultiLogin();
+
+ // Overridden from GaiaAuthConsumer.
+ void OnOAuthMultiloginFinished(const OAuthMultiloginResult& result) override;
+
+ // Starts setting parsed cookies in browser.
+ void StartSettingCookies(const OAuthMultiloginResult& result);
+
+ // Callback for CookieManager::SetCanonicalCookie.
+ void OnCookieSet(const std::string& cookie_name,
+ const std::string& cookie_domain,
+ net::CanonicalCookie::CookieInclusionStatus status);
+
+ SigninClient* signin_client_;
+ OAuth2TokenService* token_service_;
+
+ int fetcher_retries_ = 0;
+
+ // Account ids to set in the cookie.
+ const std::vector<std::string> account_ids_;
+ // See GaiaCookieManagerService::ExternalCcResultFetcher for details.
+ const std::string external_cc_result_;
+ // Access tokens, in the same order as the account ids.
+ std::vector<GaiaAuthFetcher::MultiloginTokenIDPair> token_id_pairs_;
+
+ base::OnceCallback<void(signin::SetAccountsInCookieResult)> callback_;
+ std::unique_ptr<GaiaAuthFetcher> gaia_auth_fetcher_;
+ std::unique_ptr<OAuthMultiloginTokenFetcher> token_fetcher_;
+
+ // List of pairs (cookie name and cookie domain) that have to be set in
+ // cookie jar.
+ std::set<std::pair<std::string, std::string>> cookies_to_set_;
+
+ base::WeakPtrFactory<OAuthMultiloginHelper> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(OAuthMultiloginHelper);
+};
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_CORE_BROWSER_OAUTH_MULTILOGIN_HELPER_H_
diff --git a/chromium/components/signin/core/browser/oauth_multilogin_helper_unittest.cc b/chromium/components/signin/core/browser/oauth_multilogin_helper_unittest.cc
new file mode 100644
index 00000000000..8c19a4b7009
--- /dev/null
+++ b/chromium/components/signin/core/browser/oauth_multilogin_helper_unittest.cc
@@ -0,0 +1,495 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/core/browser/oauth_multilogin_helper.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/test/scoped_task_environment.h"
+#include "components/signin/core/browser/set_accounts_in_cookie_result.h"
+#include "components/signin/core/browser/test_signin_client.h"
+#include "google_apis/gaia/fake_oauth2_token_service.h"
+#include "google_apis/gaia/gaia_urls.h"
+#include "services/network/test/test_cookie_manager.h"
+#include "services/network/test/test_url_loader_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace signin {
+
+namespace {
+
+const char kAccountId[] = "account_id_1";
+const char kAccountId2[] = "account_id_2";
+const char kAccessToken[] = "access_token_1";
+const char kAccessToken2[] = "access_token_2";
+
+const char kExternalCcResult[] = "youtube:OK";
+
+constexpr int kMaxFetcherRetries = 3;
+
+const char kMultiloginSuccessResponse[] =
+ R"()]}'
+ {
+ "status": "OK",
+ "cookies":[
+ {
+ "name":"SID",
+ "value":"SID_value",
+ "domain":".google.fr",
+ "path":"/",
+ "isSecure":true,
+ "isHttpOnly":false,
+ "priority":"HIGH",
+ "maxAge":63070000
+ }
+ ]
+ }
+ )";
+
+const char kMultiloginSuccessResponseTwoCookies[] =
+ R"()]}'
+ {
+ "status": "OK",
+ "cookies":[
+ {
+ "name":"SID",
+ "value":"SID_value",
+ "domain":".google.fr",
+ "path":"/",
+ "isSecure":true,
+ "isHttpOnly":false,
+ "priority":"HIGH",
+ "maxAge":63070000
+ },
+ {
+ "name":"FOO",
+ "value":"FOO_value",
+ "domain":".google.com",
+ "path":"/",
+ "isSecure":true,
+ "isHttpOnly":false,
+ "priority":"HIGH",
+ "maxAge":63070000
+ }
+ ]
+ }
+ )";
+
+const char kMultiloginSuccessResponseWithSecondaryDomain[] =
+ R"()]}'
+ {
+ "status": "OK",
+ "cookies":[
+ {
+ "name":"SID",
+ "value":"SID_value",
+ "domain":".youtube.com",
+ "path":"/",
+ "isSecure":true,
+ "isHttpOnly":false,
+ "priority":"HIGH",
+ "maxAge":63070000
+ },
+ {
+ "name":"FOO",
+ "value":"FOO_value",
+ "domain":".google.com",
+ "path":"/",
+ "isSecure":true,
+ "isHttpOnly":false,
+ "priority":"HIGH",
+ "maxAge":63070000
+ }
+ ]
+ }
+ )";
+
+const char kMultiloginRetryResponse[] =
+ R"()]}'
+ {
+ "status": "RETRY"
+ }
+ )";
+
+const char kMultiloginInvalidTokenResponse[] =
+ R"()]}'
+ {
+ "status": "INVALID_TOKENS",
+ "failed_accounts": [
+ { "obfuscated_id": "account_id_1", "status": "RECOVERABLE" },
+ { "obfuscated_id": "account_id_2", "status": "OK" }
+ ]
+ }
+ )";
+
+// GMock matcher that checks that the cookie has the expected parameters.
+MATCHER_P3(CookieMatcher, name, value, domain, "") {
+ return arg.Name() == name && arg.Value() == value && arg.Domain() == domain &&
+ arg.Path() == "/" && arg.IsSecure() && !arg.IsHttpOnly();
+}
+
+void RunSetCookieCallbackWithSuccess(
+ const net::CanonicalCookie&,
+ const std::string&,
+ const net::CookieOptions&,
+ network::mojom::CookieManager::SetCanonicalCookieCallback callback) {
+ std::move(callback).Run(net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+}
+
+class MockCookieManager
+ : public ::testing::StrictMock<network::TestCookieManager> {
+ public:
+ MOCK_METHOD4(SetCanonicalCookie,
+ void(const net::CanonicalCookie& cookie,
+ const std::string& source_scheme,
+ const net::CookieOptions& cookie_options,
+ SetCanonicalCookieCallback callback));
+};
+
+class MockTokenService : public FakeOAuth2TokenService {
+ public:
+ MOCK_METHOD2(InvalidateTokenForMultilogin,
+ void(const std::string& account_id, const std::string& token));
+};
+
+} // namespace
+
+class OAuthMultiloginHelperTest : public testing::Test {
+ public:
+ OAuthMultiloginHelperTest() : test_signin_client_(/*prefs=*/nullptr) {
+ std::unique_ptr<MockCookieManager> cookie_manager =
+ std::make_unique<MockCookieManager>();
+ mock_cookie_manager_ = cookie_manager.get();
+ test_signin_client_.set_cookie_manager(std::move(cookie_manager));
+ }
+
+ ~OAuthMultiloginHelperTest() override = default;
+
+ std::unique_ptr<OAuthMultiloginHelper> CreateHelper(
+ const std::vector<std::string> account_ids) {
+ return std::make_unique<OAuthMultiloginHelper>(
+ &test_signin_client_, token_service(), account_ids, std::string(),
+ base::BindOnce(&OAuthMultiloginHelperTest::OnOAuthMultiloginFinished,
+ base::Unretained(this)));
+ }
+
+ std::unique_ptr<OAuthMultiloginHelper> CreateHelperWithExternalCcResult(
+ const std::vector<std::string> account_ids) {
+ return std::make_unique<OAuthMultiloginHelper>(
+ &test_signin_client_, token_service(), account_ids, kExternalCcResult,
+ base::BindOnce(&OAuthMultiloginHelperTest::OnOAuthMultiloginFinished,
+ base::Unretained(this)));
+ }
+
+ network::TestURLLoaderFactory* url_loader() {
+ return test_signin_client_.GetTestURLLoaderFactory();
+ }
+
+ std::string multilogin_url() const {
+ return GaiaUrls::GetInstance()->oauth_multilogin_url().spec() +
+ "?source=ChromiumBrowser";
+ }
+
+ std::string multilogin_url_with_external_cc_result() const {
+ return GaiaUrls::GetInstance()->oauth_multilogin_url().spec() +
+ "?source=ChromiumBrowser&externalCcResult=" + kExternalCcResult;
+ }
+
+ MockCookieManager* cookie_manager() { return mock_cookie_manager_; }
+ MockTokenService* token_service() { return &mock_token_service_; }
+
+ protected:
+ void OnOAuthMultiloginFinished(signin::SetAccountsInCookieResult result) {
+ DCHECK(!callback_called_);
+ callback_called_ = true;
+ result_ = result;
+ }
+
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+
+ bool callback_called_ = false;
+ signin::SetAccountsInCookieResult result_;
+
+ MockCookieManager* mock_cookie_manager_; // Owned by test_signin_client_
+ TestSigninClient test_signin_client_;
+ MockTokenService mock_token_service_;
+};
+
+// Everything succeeds.
+TEST_F(OAuthMultiloginHelperTest, Success) {
+ token_service()->AddAccount(kAccountId);
+ std::unique_ptr<OAuthMultiloginHelper> helper = CreateHelper({kAccountId});
+
+ // Configure mock cookie manager:
+ // - check that the cookie is the expected one
+ // - immediately invoke the callback
+ EXPECT_CALL(
+ *cookie_manager(),
+ SetCanonicalCookie(CookieMatcher("SID", "SID_value", ".google.fr"),
+ "https", testing::_, testing::_))
+ .WillOnce(::testing::Invoke(RunSetCookieCallbackWithSuccess));
+
+ // Issue access token.
+ OAuth2AccessTokenConsumer::TokenResponse success_response;
+ success_response.access_token = kAccessToken;
+ token_service()->IssueAllTokensForAccount(kAccountId, success_response);
+
+ // Multilogin call.
+ EXPECT_FALSE(callback_called_);
+ EXPECT_TRUE(url_loader()->IsPending(multilogin_url()));
+ url_loader()->AddResponse(multilogin_url(), kMultiloginSuccessResponse);
+ EXPECT_FALSE(url_loader()->IsPending(multilogin_url()));
+ EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(signin::SetAccountsInCookieResult::kSuccess, result_);
+}
+
+// Multiple cookies in the multilogin response.
+TEST_F(OAuthMultiloginHelperTest, MultipleCookies) {
+ token_service()->AddAccount(kAccountId);
+ std::unique_ptr<OAuthMultiloginHelper> helper = CreateHelper({kAccountId});
+
+ // Configure mock cookie manager:
+ // - check that the cookie is the expected one
+ // - immediately invoke the callback
+ EXPECT_CALL(
+ *cookie_manager(),
+ SetCanonicalCookie(CookieMatcher("SID", "SID_value", ".google.fr"),
+ "https", testing::_, testing::_))
+ .WillOnce(::testing::Invoke(RunSetCookieCallbackWithSuccess));
+ EXPECT_CALL(
+ *cookie_manager(),
+ SetCanonicalCookie(CookieMatcher("FOO", "FOO_value", ".google.com"),
+ "https", testing::_, testing::_))
+ .WillOnce(::testing::Invoke(RunSetCookieCallbackWithSuccess));
+
+ // Issue access token.
+ OAuth2AccessTokenConsumer::TokenResponse success_response;
+ success_response.access_token = kAccessToken;
+ token_service()->IssueAllTokensForAccount(kAccountId, success_response);
+
+ // Multilogin call.
+ EXPECT_FALSE(callback_called_);
+ EXPECT_TRUE(url_loader()->IsPending(multilogin_url()));
+ url_loader()->AddResponse(multilogin_url(),
+ kMultiloginSuccessResponseTwoCookies);
+ EXPECT_FALSE(url_loader()->IsPending(multilogin_url()));
+ EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(signin::SetAccountsInCookieResult::kSuccess, result_);
+}
+
+// Multiple cookies in the multilogin response.
+TEST_F(OAuthMultiloginHelperTest, SuccessWithExternalCcResult) {
+ token_service()->AddAccount(kAccountId);
+ std::unique_ptr<OAuthMultiloginHelper> helper =
+ CreateHelperWithExternalCcResult({kAccountId});
+
+ // Configure mock cookie manager:
+ // - check that the cookie is the expected one
+ // - immediately invoke the callback
+ EXPECT_CALL(
+ *cookie_manager(),
+ SetCanonicalCookie(CookieMatcher("SID", "SID_value", ".youtube.com"),
+ "https", testing::_, testing::_))
+ .WillOnce(::testing::Invoke(RunSetCookieCallbackWithSuccess));
+ EXPECT_CALL(
+ *cookie_manager(),
+ SetCanonicalCookie(CookieMatcher("FOO", "FOO_value", ".google.com"),
+ "https", testing::_, testing::_))
+ .WillOnce(::testing::Invoke(RunSetCookieCallbackWithSuccess));
+
+ // Issue access token.
+ OAuth2AccessTokenConsumer::TokenResponse success_response;
+ success_response.access_token = kAccessToken;
+ token_service()->IssueAllTokensForAccount(kAccountId, success_response);
+
+ // Multilogin call.
+ EXPECT_FALSE(callback_called_);
+ EXPECT_TRUE(
+ url_loader()->IsPending(multilogin_url_with_external_cc_result()));
+ url_loader()->AddResponse(multilogin_url_with_external_cc_result(),
+ kMultiloginSuccessResponseWithSecondaryDomain);
+ EXPECT_FALSE(
+ url_loader()->IsPending(multilogin_url_with_external_cc_result()));
+ EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(signin::SetAccountsInCookieResult::kSuccess, result_);
+}
+
+// Failure to get the access token.
+TEST_F(OAuthMultiloginHelperTest, OneAccountAccessTokenFailure) {
+ token_service()->AddAccount(kAccountId);
+ std::unique_ptr<OAuthMultiloginHelper> helper = CreateHelper({kAccountId});
+
+ token_service()->IssueErrorForAllPendingRequestsForAccount(
+ kAccountId,
+ GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
+ EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(signin::SetAccountsInCookieResult::kPersistentError, result_);
+}
+
+// Retry on transient errors in the multilogin call.
+TEST_F(OAuthMultiloginHelperTest, OneAccountTransientMultiloginError) {
+ token_service()->AddAccount(kAccountId);
+ std::unique_ptr<OAuthMultiloginHelper> helper = CreateHelper({kAccountId});
+
+ // Configure mock cookie manager:
+ // - check that the cookie is the expected one
+ // - immediately invoke the callback
+ EXPECT_CALL(
+ *cookie_manager(),
+ SetCanonicalCookie(CookieMatcher("SID", "SID_value", ".google.fr"),
+ "https", testing::_, testing::_))
+ .WillOnce(::testing::Invoke(RunSetCookieCallbackWithSuccess));
+
+ // Issue access token.
+ OAuth2AccessTokenConsumer::TokenResponse success_response;
+ success_response.access_token = kAccessToken;
+ token_service()->IssueAllTokensForAccount(kAccountId, success_response);
+
+ // Multilogin call fails with transient error.
+ EXPECT_TRUE(url_loader()->IsPending(multilogin_url()));
+ url_loader()->SimulateResponseForPendingRequest(multilogin_url(),
+ kMultiloginRetryResponse);
+
+ // Call is retried and succeeds.
+ EXPECT_FALSE(url_loader()->IsPending(multilogin_url()));
+ token_service()->IssueAllTokensForAccount(kAccountId, success_response);
+ EXPECT_FALSE(callback_called_);
+ EXPECT_TRUE(url_loader()->IsPending(multilogin_url()));
+ url_loader()->AddResponse(multilogin_url(), kMultiloginSuccessResponse);
+ EXPECT_FALSE(url_loader()->IsPending(multilogin_url()));
+ EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(signin::SetAccountsInCookieResult::kSuccess, result_);
+}
+
+// Stop retrying after too many transient errors in the multilogin call.
+TEST_F(OAuthMultiloginHelperTest,
+ OneAccountTransientMultiloginErrorMaxRetries) {
+ token_service()->AddAccount(kAccountId);
+ std::unique_ptr<OAuthMultiloginHelper> helper = CreateHelper({kAccountId});
+
+ // Issue access token.
+ OAuth2AccessTokenConsumer::TokenResponse success_response;
+ success_response.access_token = kAccessToken;
+
+ // Multilogin call fails with transient error, retry many times.
+ for (int i = 0; i < kMaxFetcherRetries; ++i) {
+ token_service()->IssueAllTokensForAccount(kAccountId, success_response);
+ EXPECT_TRUE(url_loader()->IsPending(multilogin_url()));
+ EXPECT_FALSE(callback_called_);
+ url_loader()->SimulateResponseForPendingRequest(multilogin_url(),
+ kMultiloginRetryResponse);
+ }
+
+ // Failure after exceeding the maximum number of retries.
+ EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(signin::SetAccountsInCookieResult::kTransientError, result_);
+}
+
+// Persistent error in the multilogin call.
+TEST_F(OAuthMultiloginHelperTest, OneAccountPersistentMultiloginError) {
+ token_service()->AddAccount(kAccountId);
+ std::unique_ptr<OAuthMultiloginHelper> helper = CreateHelper({kAccountId});
+
+ // Issue access token.
+ OAuth2AccessTokenConsumer::TokenResponse success_response;
+ success_response.access_token = kAccessToken;
+ token_service()->IssueAllTokensForAccount(kAccountId, success_response);
+
+ // Multilogin call fails with persistent error.
+ EXPECT_FALSE(callback_called_);
+ EXPECT_TRUE(url_loader()->IsPending(multilogin_url()));
+ url_loader()->AddResponse(multilogin_url(), "blah"); // Unexpected response.
+ EXPECT_FALSE(url_loader()->IsPending(multilogin_url()));
+ EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(signin::SetAccountsInCookieResult::kPersistentError, result_);
+}
+
+// Retry on "invalid token" in the multilogin response.
+TEST_F(OAuthMultiloginHelperTest, InvalidTokenError) {
+ token_service()->AddAccount(kAccountId);
+ token_service()->AddAccount(kAccountId2);
+ std::unique_ptr<OAuthMultiloginHelper> helper =
+ CreateHelper({kAccountId, kAccountId2});
+
+ // Configure mock cookie manager:
+ // - check that the cookie is the expected one
+ // - immediately invoke the callback
+ EXPECT_CALL(
+ *cookie_manager(),
+ SetCanonicalCookie(CookieMatcher("SID", "SID_value", ".google.fr"),
+ "https", testing::_, testing::_))
+ .WillOnce(::testing::Invoke(RunSetCookieCallbackWithSuccess));
+
+ // The failed access token should be invalidated.
+ EXPECT_CALL(*token_service(),
+ InvalidateTokenForMultilogin(kAccountId, kAccessToken));
+
+ // Issue access tokens.
+ OAuth2AccessTokenConsumer::TokenResponse success_response;
+ success_response.access_token = kAccessToken;
+ token_service()->IssueAllTokensForAccount(kAccountId, success_response);
+ OAuth2AccessTokenConsumer::TokenResponse success_response_2;
+ success_response_2.access_token = kAccessToken2;
+ token_service()->IssueAllTokensForAccount(kAccountId2, success_response_2);
+
+ // Multilogin call fails with invalid token for kAccountId.
+ EXPECT_TRUE(url_loader()->IsPending(multilogin_url()));
+ url_loader()->SimulateResponseForPendingRequest(
+ multilogin_url(), kMultiloginInvalidTokenResponse);
+
+ // Both tokens are retried.
+ token_service()->IssueAllTokensForAccount(kAccountId, success_response);
+ EXPECT_FALSE(callback_called_);
+ EXPECT_FALSE(url_loader()->IsPending(multilogin_url()));
+ token_service()->IssueAllTokensForAccount(kAccountId2, success_response);
+
+ // Multilogin succeeds the second time.
+ EXPECT_FALSE(callback_called_);
+ EXPECT_TRUE(url_loader()->IsPending(multilogin_url()));
+ url_loader()->AddResponse(multilogin_url(), kMultiloginSuccessResponse);
+ EXPECT_FALSE(url_loader()->IsPending(multilogin_url()));
+ EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(signin::SetAccountsInCookieResult::kSuccess, result_);
+}
+
+// Retry on "invalid token" in the multilogin response.
+TEST_F(OAuthMultiloginHelperTest, InvalidTokenErrorMaxRetries) {
+ token_service()->AddAccount(kAccountId);
+ token_service()->AddAccount(kAccountId2);
+ std::unique_ptr<OAuthMultiloginHelper> helper =
+ CreateHelper({kAccountId, kAccountId2});
+
+ // The failed access token should be invalidated.
+ EXPECT_CALL(*token_service(),
+ InvalidateTokenForMultilogin(kAccountId, kAccessToken))
+ .Times(kMaxFetcherRetries);
+
+ // Issue access tokens.
+ OAuth2AccessTokenConsumer::TokenResponse success_response;
+ success_response.access_token = kAccessToken;
+ OAuth2AccessTokenConsumer::TokenResponse success_response_2;
+ success_response_2.access_token = kAccessToken2;
+
+ // Multilogin call fails with invalid token for kAccountId. Retry many times.
+ for (int i = 0; i < kMaxFetcherRetries; ++i) {
+ token_service()->IssueAllTokensForAccount(kAccountId, success_response);
+ EXPECT_FALSE(url_loader()->IsPending(multilogin_url()));
+ token_service()->IssueAllTokensForAccount(kAccountId2, success_response_2);
+
+ EXPECT_FALSE(callback_called_);
+ EXPECT_TRUE(url_loader()->IsPending(multilogin_url()));
+
+ url_loader()->SimulateResponseForPendingRequest(
+ multilogin_url(), kMultiloginInvalidTokenResponse);
+ }
+
+ // The maximum number of retries is reached, fail.
+ EXPECT_FALSE(url_loader()->IsPending(multilogin_url()));
+ EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(signin::SetAccountsInCookieResult::kTransientError, result_);
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/core/browser/oauth_multilogin_token_fetcher.cc b/chromium/components/signin/core/browser/oauth_multilogin_token_fetcher.cc
new file mode 100644
index 00000000000..d01a50aa468
--- /dev/null
+++ b/chromium/components/signin/core/browser/oauth_multilogin_token_fetcher.cc
@@ -0,0 +1,136 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/core/browser/oauth_multilogin_token_fetcher.h"
+
+#include <algorithm>
+#include <set>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
+#include "components/signin/core/browser/signin_client.h"
+
+namespace {
+
+void RecordGetAccessTokenFinished(GoogleServiceAuthError error) {
+ UMA_HISTOGRAM_ENUMERATION("Signin.GetAccessTokenFinished", error.state(),
+ GoogleServiceAuthError::NUM_STATES);
+}
+
+} // namespace
+
+namespace signin {
+
+OAuthMultiloginTokenFetcher::OAuthMultiloginTokenFetcher(
+ SigninClient* signin_client,
+ OAuth2TokenService* token_service,
+ const std::vector<std::string>& account_ids,
+ SuccessCallback success_callback,
+ FailureCallback failure_callback)
+ : OAuth2TokenService::Consumer("oauth_multilogin_token_fetcher"),
+ signin_client_(signin_client),
+ token_service_(token_service),
+ account_ids_(account_ids),
+ success_callback_(std::move(success_callback)),
+ failure_callback_(std::move(failure_callback)),
+ weak_ptr_factory_(this) {
+ DCHECK(signin_client_);
+ DCHECK(token_service_);
+ DCHECK(!account_ids_.empty());
+ DCHECK(success_callback_);
+ DCHECK(failure_callback_);
+
+#ifndef NDEBUG
+ // Check that there is no duplicate accounts.
+ std::set<std::string> accounts_no_duplicates(account_ids_.begin(),
+ account_ids_.end());
+ DCHECK_EQ(account_ids_.size(), accounts_no_duplicates.size());
+#endif
+
+ for (const std::string& account_id : account_ids_)
+ StartFetchingToken(account_id);
+}
+
+OAuthMultiloginTokenFetcher::~OAuthMultiloginTokenFetcher() = default;
+
+void OAuthMultiloginTokenFetcher::StartFetchingToken(
+ const std::string& account_id) {
+ DCHECK(!account_id.empty());
+ token_requests_.push_back(
+ token_service_->StartRequestForMultilogin(account_id, this));
+}
+
+void OAuthMultiloginTokenFetcher::OnGetTokenSuccess(
+ const OAuth2TokenService::Request* request,
+ const OAuth2AccessTokenConsumer::TokenResponse& token_response) {
+ std::string account_id = request->GetAccountId();
+ DCHECK(account_ids_.cend() !=
+ std::find(account_ids_.cbegin(), account_ids_.cend(), account_id));
+
+ const std::string token = token_response.access_token;
+ DCHECK(!token.empty());
+ // Do not use |request| and |token_response| below this line, as they are
+ // deleted.
+ EraseRequest(request);
+
+ const auto& inserted =
+ access_tokens_.insert(std::make_pair(account_id, token));
+ DCHECK(inserted.second); // If this fires, we have a duplicate account.
+
+ if (access_tokens_.size() == account_ids_.size()) {
+ std::vector<GaiaAuthFetcher::MultiloginTokenIDPair> token_id_pairs;
+ for (const auto& id : account_ids_) {
+ const auto& it = access_tokens_.find(id);
+ DCHECK(!it->second.empty());
+ // TODO(https://crbug.com/956503): Don't assume that the account ID is the
+ // Gaia ID.
+ token_id_pairs.emplace_back(id, it->second);
+ }
+ RecordGetAccessTokenFinished(GoogleServiceAuthError::AuthErrorNone());
+ std::move(success_callback_).Run(token_id_pairs);
+ // Do not add anything below this line, as this may be deleted.
+ }
+}
+
+void OAuthMultiloginTokenFetcher::OnGetTokenFailure(
+ const OAuth2TokenService::Request* request,
+ const GoogleServiceAuthError& error) {
+ std::string account_id = request->GetAccountId();
+ VLOG(1) << "Failed to retrieve accesstoken account=" << account_id
+ << " error=" << error.ToString();
+ if (error.IsTransientError() &&
+ retried_requests_.find(account_id) == retried_requests_.end()) {
+ retried_requests_.insert(account_id);
+ UMA_HISTOGRAM_ENUMERATION("Signin.GetAccessTokenRetry", error.state(),
+ GoogleServiceAuthError::NUM_STATES);
+ EraseRequest(request);
+ // Fetching fresh access tokens requires network.
+ signin_client_->DelayNetworkCall(
+ base::BindOnce(&OAuthMultiloginTokenFetcher::StartFetchingToken,
+ weak_ptr_factory_.GetWeakPtr(), account_id));
+ return;
+ }
+ RecordGetAccessTokenFinished(error);
+ // Copy the error because it is a reference owned by token_requests_.
+ GoogleServiceAuthError error_copy = error;
+ token_requests_.clear(); // Cancel pending requests.
+ std::move(failure_callback_).Run(error_copy);
+ // Do not add anything below this line, as this may be deleted.
+}
+
+void OAuthMultiloginTokenFetcher::EraseRequest(
+ const OAuth2TokenService::Request* request) {
+ for (auto it = token_requests_.begin(); it != token_requests_.end(); ++it) {
+ if (it->get() == request) {
+ token_requests_.erase(it);
+ return;
+ }
+ }
+ NOTREACHED() << "Request not found";
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/core/browser/oauth_multilogin_token_fetcher.h b/chromium/components/signin/core/browser/oauth_multilogin_token_fetcher.h
new file mode 100644
index 00000000000..168ba881513
--- /dev/null
+++ b/chromium/components/signin/core/browser/oauth_multilogin_token_fetcher.h
@@ -0,0 +1,74 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_OAUTH_MULTILOGIN_TOKEN_FETCHER_H_
+#define COMPONENTS_SIGNIN_CORE_BROWSER_OAUTH_MULTILOGIN_TOKEN_FETCHER_H_
+
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/bind_helpers.h"
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "google_apis/gaia/gaia_auth_fetcher.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "google_apis/gaia/oauth2_token_service.h"
+
+class SigninClient;
+
+namespace signin {
+
+// Fetches multilogin access tokens in parallel for multiple accounts.
+// It is safe to delete this object from within the callbacks.
+class OAuthMultiloginTokenFetcher : public OAuth2TokenService::Consumer {
+ public:
+ using SuccessCallback = base::OnceCallback<void(
+ const std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>&)>;
+ using FailureCallback =
+ base::OnceCallback<void(const GoogleServiceAuthError&)>;
+
+ OAuthMultiloginTokenFetcher(SigninClient* signin_client,
+ OAuth2TokenService* token_service,
+ const std::vector<std::string>& account_ids,
+ SuccessCallback success_callback,
+ FailureCallback failure_callback);
+
+ ~OAuthMultiloginTokenFetcher() override;
+
+ private:
+ void StartFetchingToken(const std::string& account_id);
+
+ // Overridden from OAuth2TokenService::Consumer.
+ void OnGetTokenSuccess(
+ const OAuth2TokenService::Request* request,
+ const OAuth2AccessTokenConsumer::TokenResponse& token_response) override;
+ void OnGetTokenFailure(const OAuth2TokenService::Request* request,
+ const GoogleServiceAuthError& error) override;
+
+ // Helper function to remove a request from token_requests_.
+ void EraseRequest(const OAuth2TokenService::Request* request);
+
+ SigninClient* signin_client_;
+ OAuth2TokenService* token_service_;
+ const std::vector<std::string> account_ids_;
+
+ SuccessCallback success_callback_;
+ FailureCallback failure_callback_;
+
+ std::vector<std::unique_ptr<OAuth2TokenService::Request>> token_requests_;
+ std::map<std::string, std::string> access_tokens_;
+ std::set<std::string> retried_requests_; // Requests are retried once.
+
+ base::WeakPtrFactory<OAuthMultiloginTokenFetcher> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(OAuthMultiloginTokenFetcher);
+};
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_CORE_BROWSER_OAUTH_MULTILOGIN_TOKEN_FETCHER_H_
diff --git a/chromium/components/signin/core/browser/oauth_multilogin_token_fetcher_unittest.cc b/chromium/components/signin/core/browser/oauth_multilogin_token_fetcher_unittest.cc
new file mode 100644
index 00000000000..a40df52a3d6
--- /dev/null
+++ b/chromium/components/signin/core/browser/oauth_multilogin_token_fetcher_unittest.cc
@@ -0,0 +1,226 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/core/browser/oauth_multilogin_token_fetcher.h"
+
+#include <map>
+#include <memory>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/test/scoped_task_environment.h"
+#include "components/signin/core/browser/test_signin_client.h"
+#include "google_apis/gaia/fake_oauth2_token_service.h"
+#include "google_apis/gaia/gaia_constants.h"
+#include "google_apis/gaia/gaia_urls.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace signin {
+
+namespace {
+
+const char kAccountId[] = "account_id";
+const char kAccessToken[] = "access_token";
+
+// Status of the token fetch.
+enum class FetchStatus { kSuccess, kFailure, kPending };
+
+} // namespace
+
+class OAuthMultiloginTokenFetcherTest : public testing::Test {
+ public:
+ OAuthMultiloginTokenFetcherTest() : test_signin_client_(/*prefs=*/nullptr) {}
+
+ ~OAuthMultiloginTokenFetcherTest() override = default;
+
+ std::unique_ptr<OAuthMultiloginTokenFetcher> CreateFetcher(
+ const std::vector<std::string> account_ids) {
+ return std::make_unique<OAuthMultiloginTokenFetcher>(
+ &test_signin_client_, &token_service_, account_ids,
+ base::BindOnce(&OAuthMultiloginTokenFetcherTest::OnSuccess,
+ base::Unretained(this)),
+ base::BindOnce(&OAuthMultiloginTokenFetcherTest::OnFailure,
+ base::Unretained(this)));
+ }
+
+ // Returns the status of the token fetch.
+ FetchStatus GetFetchStatus() const {
+ if (success_callback_called_)
+ return FetchStatus::kSuccess;
+ return failure_callback_called_ ? FetchStatus::kFailure
+ : FetchStatus::kPending;
+ }
+
+ protected:
+ // Success callback for OAuthMultiloginTokenFetcher.
+ void OnSuccess(const std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>&
+ token_id_pairs) {
+ DCHECK(!success_callback_called_);
+ DCHECK(token_id_pairs_.empty());
+ success_callback_called_ = true;
+ token_id_pairs_ = token_id_pairs;
+ }
+
+ // Failure callback for OAuthMultiloginTokenFetcher.
+ void OnFailure(const GoogleServiceAuthError& error) {
+ DCHECK(!failure_callback_called_);
+ failure_callback_called_ = true;
+ error_ = error;
+ }
+
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+
+ bool success_callback_called_ = false;
+ bool failure_callback_called_ = false;
+ GoogleServiceAuthError error_;
+ std::vector<GaiaAuthFetcher::MultiloginTokenIDPair> token_id_pairs_;
+
+ TestSigninClient test_signin_client_;
+ FakeOAuth2TokenService token_service_;
+};
+
+TEST_F(OAuthMultiloginTokenFetcherTest, OneAccountSuccess) {
+ token_service_.AddAccount(kAccountId);
+ std::unique_ptr<OAuthMultiloginTokenFetcher> fetcher =
+ CreateFetcher({kAccountId});
+ EXPECT_EQ(FetchStatus::kPending, GetFetchStatus());
+ OAuth2AccessTokenConsumer::TokenResponse success_response;
+ success_response.access_token = kAccessToken;
+ token_service_.IssueAllTokensForAccount(kAccountId, success_response);
+ EXPECT_EQ(FetchStatus::kSuccess, GetFetchStatus());
+ // Check result.
+ EXPECT_EQ(1u, token_id_pairs_.size());
+ EXPECT_EQ(kAccountId, token_id_pairs_[0].gaia_id_);
+ EXPECT_EQ(kAccessToken, token_id_pairs_[0].token_);
+}
+
+TEST_F(OAuthMultiloginTokenFetcherTest, OneAccountPersistentError) {
+ token_service_.AddAccount(kAccountId);
+ std::unique_ptr<OAuthMultiloginTokenFetcher> fetcher =
+ CreateFetcher({kAccountId});
+ EXPECT_EQ(FetchStatus::kPending, GetFetchStatus());
+ token_service_.IssueErrorForAllPendingRequestsForAccount(
+ kAccountId,
+ GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
+ EXPECT_EQ(FetchStatus::kFailure, GetFetchStatus());
+ EXPECT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, error_.state());
+}
+
+TEST_F(OAuthMultiloginTokenFetcherTest, OneAccountTransientError) {
+ token_service_.AddAccount(kAccountId);
+ std::unique_ptr<OAuthMultiloginTokenFetcher> fetcher =
+ CreateFetcher({kAccountId});
+ // Connection failure will be retried.
+ token_service_.IssueErrorForAllPendingRequestsForAccount(
+ kAccountId,
+ GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED));
+ EXPECT_EQ(FetchStatus::kPending, GetFetchStatus());
+ // Success on retry.
+ OAuth2AccessTokenConsumer::TokenResponse success_response;
+ success_response.access_token = kAccessToken;
+ token_service_.IssueAllTokensForAccount(kAccountId, success_response);
+ EXPECT_EQ(FetchStatus::kSuccess, GetFetchStatus());
+ // Check result.
+ EXPECT_EQ(1u, token_id_pairs_.size());
+ EXPECT_EQ(kAccountId, token_id_pairs_[0].gaia_id_);
+ EXPECT_EQ(kAccessToken, token_id_pairs_[0].token_);
+}
+
+TEST_F(OAuthMultiloginTokenFetcherTest, OneAccountTransientErrorMaxRetries) {
+ token_service_.AddAccount(kAccountId);
+ std::unique_ptr<OAuthMultiloginTokenFetcher> fetcher =
+ CreateFetcher({kAccountId});
+ // Repeated connection failures.
+ token_service_.IssueErrorForAllPendingRequestsForAccount(
+ kAccountId,
+ GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED));
+ EXPECT_EQ(FetchStatus::kPending, GetFetchStatus());
+ token_service_.IssueErrorForAllPendingRequestsForAccount(
+ kAccountId,
+ GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED));
+ // Stop retrying, and fail.
+ EXPECT_EQ(FetchStatus::kFailure, GetFetchStatus());
+ EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED, error_.state());
+}
+
+// The flow succeeds even if requests are received out of order.
+TEST_F(OAuthMultiloginTokenFetcherTest, MultipleAccountsSuccess) {
+ token_service_.AddAccount("account_1");
+ token_service_.AddAccount("account_2");
+ token_service_.AddAccount("account_3");
+ std::unique_ptr<OAuthMultiloginTokenFetcher> fetcher =
+ CreateFetcher({"account_1", "account_2", "account_3"});
+ OAuth2AccessTokenConsumer::TokenResponse success_response;
+ success_response.access_token = "token_3";
+ token_service_.IssueAllTokensForAccount("account_3", success_response);
+ success_response.access_token = "token_1";
+ token_service_.IssueAllTokensForAccount("account_1", success_response);
+ EXPECT_EQ(FetchStatus::kPending, GetFetchStatus());
+ success_response.access_token = "token_2";
+ token_service_.IssueAllTokensForAccount("account_2", success_response);
+ EXPECT_EQ(FetchStatus::kSuccess, GetFetchStatus());
+ // Check result.
+ EXPECT_EQ(3u, token_id_pairs_.size());
+ EXPECT_EQ("account_1", token_id_pairs_[0].gaia_id_);
+ EXPECT_EQ("account_2", token_id_pairs_[1].gaia_id_);
+ EXPECT_EQ("account_3", token_id_pairs_[2].gaia_id_);
+ EXPECT_EQ("token_1", token_id_pairs_[0].token_);
+ EXPECT_EQ("token_2", token_id_pairs_[1].token_);
+ EXPECT_EQ("token_3", token_id_pairs_[2].token_);
+}
+
+TEST_F(OAuthMultiloginTokenFetcherTest, MultipleAccountsTransientError) {
+ token_service_.AddAccount("account_1");
+ token_service_.AddAccount("account_2");
+ token_service_.AddAccount("account_3");
+ std::unique_ptr<OAuthMultiloginTokenFetcher> fetcher =
+ CreateFetcher({"account_1", "account_2", "account_3"});
+ // Connection failures will be retried.
+ token_service_.IssueErrorForAllPendingRequestsForAccount(
+ "account_1",
+ GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED));
+ token_service_.IssueErrorForAllPendingRequestsForAccount(
+ "account_2",
+ GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED));
+ token_service_.IssueErrorForAllPendingRequestsForAccount(
+ "account_3",
+ GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED));
+ // Success on retry.
+ OAuth2AccessTokenConsumer::TokenResponse success_response;
+ success_response.access_token = kAccessToken;
+ success_response.access_token = "token_1";
+ token_service_.IssueAllTokensForAccount("account_1", success_response);
+ success_response.access_token = "token_2";
+ token_service_.IssueAllTokensForAccount("account_2", success_response);
+ EXPECT_EQ(FetchStatus::kPending, GetFetchStatus());
+ success_response.access_token = "token_3";
+ token_service_.IssueAllTokensForAccount("account_3", success_response);
+ EXPECT_EQ(FetchStatus::kSuccess, GetFetchStatus());
+ // Check result.
+ EXPECT_EQ(3u, token_id_pairs_.size());
+ EXPECT_EQ("account_1", token_id_pairs_[0].gaia_id_);
+ EXPECT_EQ("account_2", token_id_pairs_[1].gaia_id_);
+ EXPECT_EQ("account_3", token_id_pairs_[2].gaia_id_);
+ EXPECT_EQ("token_1", token_id_pairs_[0].token_);
+ EXPECT_EQ("token_2", token_id_pairs_[1].token_);
+ EXPECT_EQ("token_3", token_id_pairs_[2].token_);
+}
+
+TEST_F(OAuthMultiloginTokenFetcherTest, MultipleAccountsPersistentError) {
+ token_service_.AddAccount("account_1");
+ token_service_.AddAccount("account_2");
+ token_service_.AddAccount("account_3");
+ std::unique_ptr<OAuthMultiloginTokenFetcher> fetcher =
+ CreateFetcher({"account_1", "account_2", "account_3"});
+ EXPECT_EQ(FetchStatus::kPending, GetFetchStatus());
+ token_service_.IssueErrorForAllPendingRequestsForAccount(
+ "account_2",
+ GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
+ // Fail as soon as one of the accounts is in error.
+ EXPECT_EQ(FetchStatus::kFailure, GetFetchStatus());
+ EXPECT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, error_.state());
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/core/browser/profile_oauth2_token_service_delegate_chromeos_unittest.cc b/chromium/components/signin/core/browser/profile_oauth2_token_service_delegate_chromeos_unittest.cc
index a32eeff5a5f..088a552ca34 100644
--- a/chromium/components/signin/core/browser/profile_oauth2_token_service_delegate_chromeos_unittest.cc
+++ b/chromium/components/signin/core/browser/profile_oauth2_token_service_delegate_chromeos_unittest.cc
@@ -193,7 +193,7 @@ class CrOSOAuthDelegateTest : public testing::Test {
}
void AddSuccessfulOAuthTokenResponse() {
- client_->test_url_loader_factory()->AddResponse(
+ client_->GetTestURLLoaderFactory()->AddResponse(
GaiaUrls::GetInstance()->oauth2_token_url().spec(),
GetValidTokenResponse("token", 3600));
}
diff --git a/chromium/components/signin/core/browser/resources/signin_index.html b/chromium/components/signin/core/browser/resources/signin_index.html
index 835d2d2c565..64d66020dcb 100644
--- a/chromium/components/signin/core/browser/resources/signin_index.html
+++ b/chromium/components/signin/core/browser/resources/signin_index.html
@@ -77,7 +77,7 @@
<div class="account-section">
<table class="signin-details">
<tr class="header">
- <td>Accound Id</td>
+ <td>Account Id</td>
<td>Has refresh token</td>
<td>Has persistent auth error</td>
</tr>
diff --git a/chromium/components/signin/core/browser/set_accounts_in_cookie_result.h b/chromium/components/signin/core/browser/set_accounts_in_cookie_result.h
new file mode 100644
index 00000000000..6adba69ab8f
--- /dev/null
+++ b/chromium/components/signin/core/browser/set_accounts_in_cookie_result.h
@@ -0,0 +1,22 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_SET_ACCOUNTS_IN_COOKIE_RESULT_H_
+#define COMPONENTS_SIGNIN_CORE_BROWSER_SET_ACCOUNTS_IN_COOKIE_RESULT_H_
+
+namespace signin {
+
+// Result of a "Set Accounts" cookie operation.
+enum class SetAccountsInCookieResult {
+ // The request succeeded.
+ kSuccess,
+ // The request failed, and can be retried.
+ kTransientError,
+ // The request failed and should not be retried.
+ kPersistentError,
+};
+
+} // namespace signin
+
+#endif // COMPONENTS_SIGNIN_CORE_BROWSER_SET_ACCOUNTS_IN_COOKIE_RESULT_H_
diff --git a/chromium/components/signin/core/browser/signin_client.h b/chromium/components/signin/core/browser/signin_client.h
index 0b288a6213c..8587e23de6c 100644
--- a/chromium/components/signin/core/browser/signin_client.h
+++ b/chromium/components/signin/core/browser/signin_client.h
@@ -79,6 +79,9 @@ class SigninClient : public KeyedService {
// Returns true if GAIA cookies are allowed in the content area.
virtual bool AreSigninCookiesAllowed() = 0;
+ // Returns true if signin cookies are cleared on exit.
+ virtual bool AreSigninCookiesDeletedOnExit() = 0;
+
// Adds an observer to listen for changes to the state of sign in cookie
// settings.
virtual void AddContentSettingsObserver(
@@ -92,8 +95,7 @@ class SigninClient : public KeyedService {
// Creates a new platform-specific GaiaAuthFetcher.
virtual std::unique_ptr<GaiaAuthFetcher> CreateGaiaAuthFetcher(
GaiaAuthConsumer* consumer,
- gaia::GaiaSource source,
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) = 0;
+ gaia::GaiaSource source) = 0;
// Schedules migration to happen at next startup.
virtual void SetReadyForDiceMigration(bool is_ready) {}
diff --git a/chromium/components/signin/core/browser/signin_error_controller.cc b/chromium/components/signin/core/browser/signin_error_controller.cc
index 9b2e0b98035..e3e4668f03e 100644
--- a/chromium/components/signin/core/browser/signin_error_controller.cc
+++ b/chromium/components/signin/core/browser/signin_error_controller.cc
@@ -82,7 +82,7 @@ bool SigninErrorController::UpdateSecondaryAccountErrors(
// account id, use that error. Otherwise, just take the first actionable
// error we find.
bool error_changed = false;
- for (const AccountInfo& account_info :
+ for (const CoreAccountInfo& account_info :
identity_manager_->GetAccountsWithRefreshTokens()) {
std::string account_id = account_info.account_id;
diff --git a/chromium/components/signin/core/browser/signin_header_helper_unittest.cc b/chromium/components/signin/core/browser/signin_header_helper_unittest.cc
index a8935aac517..61487c836db 100644
--- a/chromium/components/signin/core/browser/signin_header_helper_unittest.cc
+++ b/chromium/components/signin/core/browser/signin_header_helper_unittest.cc
@@ -41,8 +41,7 @@ class SigninHeaderHelperTest : public testing::Test {
HostContentSettingsMap::RegisterProfilePrefs(prefs_.registry());
settings_map_ = new HostContentSettingsMap(
- &prefs_, false /* incognito_profile */, false /* guest_profile */,
- false /* store_last_modified */,
+ &prefs_, false /* is_off_the_record */, false /* store_last_modified */,
false /* migrate_requesting_and_top_level_origin_settings */);
cookie_settings_ =
new content_settings::CookieSettings(settings_map_.get(), &prefs_, "");
diff --git a/chromium/components/signin/core/browser/signin_manager.cc b/chromium/components/signin/core/browser/signin_manager.cc
index 09759330bcf..d97a3e1c54a 100644
--- a/chromium/components/signin/core/browser/signin_manager.cc
+++ b/chromium/components/signin/core/browser/signin_manager.cc
@@ -8,14 +8,12 @@
#include <vector>
#include "base/bind.h"
-#include "base/metrics/histogram_macros.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "components/prefs/pref_service.h"
#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/gaia_cookie_manager_service.h"
#include "components/signin/core/browser/identity_utils.h"
#include "components/signin/core/browser/signin_metrics.h"
#include "components/signin/core/browser/signin_pref_names.h"
@@ -31,9 +29,11 @@ SigninManager::SigninManager(
AccountTrackerService* account_tracker_service,
GaiaCookieManagerService* cookie_manager_service,
signin::AccountConsistencyMethod account_consistency)
- : SigninManagerBase(client, token_service, account_tracker_service),
- cookie_manager_service_(cookie_manager_service),
- account_consistency_(account_consistency),
+ : SigninManagerBase(client,
+ token_service,
+ account_tracker_service,
+ cookie_manager_service,
+ account_consistency),
weak_pointer_factory_(this) {}
SigninManager::~SigninManager() {
@@ -41,104 +41,6 @@ SigninManager::~SigninManager() {
local_state_pref_registrar_.RemoveAll();
}
-void SigninManager::SignOut(
- signin_metrics::ProfileSignout signout_source_metric,
- signin_metrics::SignoutDelete signout_delete_metric) {
- RemoveAccountsOption remove_option =
- (account_consistency_ == signin::AccountConsistencyMethod::kDice)
- ? RemoveAccountsOption::kRemoveAuthenticatedAccountIfInError
- : RemoveAccountsOption::kRemoveAllAccounts;
- StartSignOut(signout_source_metric, signout_delete_metric, remove_option);
-}
-
-void SigninManager::SignOutAndRemoveAllAccounts(
- signin_metrics::ProfileSignout signout_source_metric,
- signin_metrics::SignoutDelete signout_delete_metric) {
- StartSignOut(signout_source_metric, signout_delete_metric,
- RemoveAccountsOption::kRemoveAllAccounts);
-}
-
-void SigninManager::SignOutAndKeepAllAccounts(
- signin_metrics::ProfileSignout signout_source_metric,
- signin_metrics::SignoutDelete signout_delete_metric) {
- StartSignOut(signout_source_metric, signout_delete_metric,
- RemoveAccountsOption::kKeepAllAccounts);
-}
-
-void SigninManager::StartSignOut(
- signin_metrics::ProfileSignout signout_source_metric,
- signin_metrics::SignoutDelete signout_delete_metric,
- RemoveAccountsOption remove_option) {
- signin_client()->PreSignOut(
- base::BindOnce(&SigninManager::OnSignoutDecisionReached,
- base::Unretained(this), signout_source_metric,
- signout_delete_metric, remove_option),
- signout_source_metric);
-}
-
-void SigninManager::OnSignoutDecisionReached(
- signin_metrics::ProfileSignout signout_source_metric,
- signin_metrics::SignoutDelete signout_delete_metric,
- RemoveAccountsOption remove_option,
- SigninClient::SignoutDecision signout_decision) {
- DCHECK(IsInitialized());
-
- signin_metrics::LogSignout(signout_source_metric, signout_delete_metric);
- if (!IsAuthenticated()) {
- return;
- }
-
- // TODO(crbug.com/887756): Consider moving this higher up, or document why
- // the above blocks are exempt from the |signout_decision| early return.
- if (signout_decision == SigninClient::SignoutDecision::DISALLOW_SIGNOUT) {
- DVLOG(1) << "Ignoring attempt to sign out while signout disallowed";
- return;
- }
-
- AccountInfo account_info = GetAuthenticatedAccountInfo();
- const std::string account_id = GetAuthenticatedAccountId();
- const std::string username = account_info.email;
- const base::Time signin_time =
- base::Time::FromDeltaSinceWindowsEpoch(base::TimeDelta::FromMicroseconds(
- signin_client()->GetPrefs()->GetInt64(prefs::kSignedInTime)));
- ClearAuthenticatedAccountId();
- signin_client()->GetPrefs()->ClearPref(prefs::kGoogleServicesHostedDomain);
- signin_client()->GetPrefs()->ClearPref(prefs::kGoogleServicesAccountId);
- signin_client()->GetPrefs()->ClearPref(prefs::kGoogleServicesUserAccountId);
- signin_client()->GetPrefs()->ClearPref(prefs::kSignedInTime);
-
- // Determine the duration the user was logged in and log that to UMA.
- if (!signin_time.is_null()) {
- base::TimeDelta signed_in_duration = base::Time::Now() - signin_time;
- UMA_HISTOGRAM_COUNTS_1M("Signin.SignedInDurationBeforeSignout",
- signed_in_duration.InMinutes());
- }
-
- // Revoke all tokens before sending signed_out notification, because there
- // may be components that don't listen for token service events when the
- // profile is not connected to an account.
- switch (remove_option) {
- case RemoveAccountsOption::kRemoveAllAccounts:
- VLOG(0) << "Revoking all refresh tokens on server. Reason: sign out, "
- << "IsSigninAllowed: " << IsSigninAllowed();
- token_service()->RevokeAllCredentials(
- signin_metrics::SourceForRefreshTokenOperation::
- kSigninManager_ClearPrimaryAccount);
- break;
- case RemoveAccountsOption::kRemoveAuthenticatedAccountIfInError:
- if (token_service()->RefreshTokenHasError(account_id))
- token_service()->RevokeCredentials(
- account_id, signin_metrics::SourceForRefreshTokenOperation::
- kSigninManager_ClearPrimaryAccount);
- break;
- case RemoveAccountsOption::kKeepAllAccounts:
- // Do nothing.
- break;
- }
-
- FireGoogleSignedOut(account_info);
-}
-
void SigninManager::FinalizeInitBeforeLoadingRefreshTokens(
PrefService* local_state) {
// local_state can be null during unit tests.
@@ -201,9 +103,11 @@ void SigninManager::SetSigninAllowed(bool allowed) {
}
void SigninManager::OnSigninAllowedPrefChanged() {
- if (!IsSigninAllowed() && IsAuthenticated())
+ if (!IsSigninAllowed() && IsAuthenticated()) {
+ VLOG(0) << "IsSigninAllowed() set to false, signing out the user";
SignOut(signin_metrics::SIGNOUT_PREF_CHANGED,
signin_metrics::SignoutDelete::IGNORE_METRIC);
+ }
}
// static
@@ -250,12 +154,6 @@ void SigninManager::FireGoogleSigninSucceeded() {
}
}
-void SigninManager::FireGoogleSignedOut(const AccountInfo& account_info) {
- if (observer_ != nullptr) {
- observer_->GoogleSignedOut(account_info);
- }
-}
-
void SigninManager::OnRefreshTokensLoaded() {
token_service()->RemoveObserver(this);
diff --git a/chromium/components/signin/core/browser/signin_manager.h b/chromium/components/signin/core/browser/signin_manager.h
index 5efd7f4bfc2..c70c9d93b6b 100644
--- a/chromium/components/signin/core/browser/signin_manager.h
+++ b/chromium/components/signin/core/browser/signin_manager.h
@@ -30,16 +30,13 @@
#include "components/keyed_service/core/keyed_service.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_member.h"
-#include "components/signin/core/browser/account_consistency_method.h"
#include "components/signin/core/browser/account_info.h"
#include "components/signin/core/browser/account_tracker_service.h"
#include "components/signin/core/browser/profile_oauth2_token_service.h"
-#include "components/signin/core/browser/signin_client.h"
#include "components/signin/core/browser/signin_manager_base.h"
#include "components/signin/core/browser/signin_metrics.h"
#include "net/cookies/canonical_cookie.h"
-class GaiaCookieManagerService;
class PrefService;
namespace identity {
@@ -49,16 +46,6 @@ class IdentityManager;
class SigninManager : public SigninManagerBase,
public OAuth2TokenService::Observer {
public:
- // Used to remove accounts from the token service and the account tracker.
- enum class RemoveAccountsOption {
- // Do not remove accounts.
- kKeepAllAccounts,
- // Remove all the accounts.
- kRemoveAllAccounts,
- // Removes the authenticated account if it is in authentication error.
- kRemoveAuthenticatedAccountIfInError
- };
-
// This is used to distinguish URLs belonging to the special web signin flow
// running in the special signin process from other URLs on the same domain.
// We do not grant WebUI privilieges / bindings to this process or to URLs of
@@ -78,30 +65,6 @@ class SigninManager : public SigninManagerBase,
// are actually SigninManager instances.
static SigninManager* FromSigninManagerBase(SigninManagerBase* manager);
- // Signs a user out, removing the preference, erasing all keys
- // associated with the authenticated user, and canceling all auth in progress.
- // On mobile and on desktop pre-DICE, this also removes all accounts from
- // Chrome by revoking all refresh tokens.
- // On desktop with DICE enabled, this will remove the authenticated account
- // from Chrome only if it is in authentication error. No other accounts are
- // removed.
- void SignOut(signin_metrics::ProfileSignout signout_source_metric,
- signin_metrics::SignoutDelete signout_delete_metric);
-
- // Signs a user out, removing the preference, erasing all keys
- // associated with the authenticated user, and canceling all auth in progress.
- // It removes all accounts from Chrome by revoking all refresh tokens.
- void SignOutAndRemoveAllAccounts(
- signin_metrics::ProfileSignout signout_source_metric,
- signin_metrics::SignoutDelete signout_delete_metric);
-
- // Signs a user out, removing the preference, erasing all keys
- // associated with the authenticated user, and canceling all auth in progress.
- // Does not remove the accounts from the token service.
- void SignOutAndKeepAllAccounts(
- signin_metrics::ProfileSignout signout_source_metric,
- signin_metrics::SignoutDelete signout_delete_metric);
-
// On platforms where SigninManager is responsible for dealing with
// invalid username policy updates, we need to check this during
// initialization and sign the user out.
@@ -121,14 +84,6 @@ class SigninManager : public SigninManagerBase,
// Sets whether sign-in is allowed or not.
void SetSigninAllowed(bool allowed);
- protected:
- // The sign out process which is started by SigninClient::PreSignOut()
- virtual void OnSignoutDecisionReached(
- signin_metrics::ProfileSignout signout_source_metric,
- signin_metrics::SignoutDelete signout_delete_metric,
- RemoveAccountsOption remove_option,
- SigninClient::SignoutDecision signout_decision);
-
private:
friend class identity::IdentityManager;
FRIEND_TEST_ALL_PREFIXES(SigninManagerTest, Prohibited);
@@ -137,26 +92,15 @@ class SigninManager : public SigninManagerBase,
// Send all observers |GoogleSigninSucceeded| notifications.
void FireGoogleSigninSucceeded();
- // Send all observers |GoogleSignedOut| notifications.
- void FireGoogleSignedOut(const AccountInfo& account_info);
-
// OAuth2TokenService::Observer:
void OnRefreshTokensLoaded() override;
- // Starts the sign out process.
- void StartSignOut(signin_metrics::ProfileSignout signout_source_metric,
- signin_metrics::SignoutDelete signout_delete_metric,
- RemoveAccountsOption remove_option);
-
void OnSigninAllowedPrefChanged();
void OnGoogleServicesUsernamePatternChanged();
// Returns true if the passed username is allowed by policy.
bool IsAllowedUsername(const std::string& username) const;
- // Object used to use the token to push a GAIA cookie into the cookie jar.
- GaiaCookieManagerService* cookie_manager_service_;
-
// Helper object to listen for changes to signin preferences stored in non-
// profile-specific local prefs (like kGoogleServicesUsernamePattern).
PrefChangeRegistrar local_state_pref_registrar_;
@@ -164,8 +108,6 @@ class SigninManager : public SigninManagerBase,
// Helper object to listen for changes to the signin allowed preference.
BooleanPrefMember signin_allowed_;
- signin::AccountConsistencyMethod account_consistency_;
-
base::WeakPtrFactory<SigninManager> weak_pointer_factory_;
DISALLOW_COPY_AND_ASSIGN(SigninManager);
diff --git a/chromium/components/signin/core/browser/signin_manager_base.cc b/chromium/components/signin/core/browser/signin_manager_base.cc
index e4af9362091..37ee80721d5 100644
--- a/chromium/components/signin/core/browser/signin_manager_base.cc
+++ b/chromium/components/signin/core/browser/signin_manager_base.cc
@@ -9,6 +9,7 @@
#include "base/command_line.h"
#include "base/memory/ref_counted.h"
+#include "base/metrics/histogram_macros.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -16,6 +17,7 @@
#include "components/prefs/pref_service.h"
#include "components/signin/core/browser/account_info.h"
#include "components/signin/core/browser/account_tracker_service.h"
+#include "components/signin/core/browser/gaia_cookie_manager_service.h"
#include "components/signin/core/browser/profile_oauth2_token_service.h"
#include "components/signin/core/browser/signin_client.h"
#include "components/signin/core/browser/signin_pref_names.h"
@@ -27,11 +29,14 @@
SigninManagerBase::SigninManagerBase(
SigninClient* client,
ProfileOAuth2TokenService* token_service,
- AccountTrackerService* account_tracker_service)
+ AccountTrackerService* account_tracker_service,
+ GaiaCookieManagerService* cookie_manager_service,
+ signin::AccountConsistencyMethod account_consistency)
: client_(client),
token_service_(token_service),
account_tracker_service_(account_tracker_service),
initialized_(false),
+ account_consistency_(account_consistency),
weak_pointer_factory_(this) {
DCHECK(client_);
DCHECK(account_tracker_service_);
@@ -218,10 +223,17 @@ void SigninManagerBase::SetAuthenticatedAccountId(
// Commit authenticated account info immediately so that it does not get lost
// if Chrome crashes before the next commit interval.
client_->GetPrefs()->CommitPendingWrite();
+
+ if (observer_) {
+ observer_->AuthenticatedAccountSet(info);
+ }
}
void SigninManagerBase::ClearAuthenticatedAccountId() {
authenticated_account_id_.clear();
+ if (observer_) {
+ observer_->AuthenticatedAccountCleared();
+ }
}
bool SigninManagerBase::IsAuthenticated() const {
@@ -237,3 +249,108 @@ void SigninManagerBase::ClearObserver() {
DCHECK(observer_);
observer_ = nullptr;
}
+
+#if !defined(OS_CHROMEOS)
+void SigninManagerBase::SignOut(
+ signin_metrics::ProfileSignout signout_source_metric,
+ signin_metrics::SignoutDelete signout_delete_metric) {
+ RemoveAccountsOption remove_option =
+ (account_consistency_ == signin::AccountConsistencyMethod::kDice)
+ ? RemoveAccountsOption::kRemoveAuthenticatedAccountIfInError
+ : RemoveAccountsOption::kRemoveAllAccounts;
+ StartSignOut(signout_source_metric, signout_delete_metric, remove_option);
+}
+
+void SigninManagerBase::SignOutAndRemoveAllAccounts(
+ signin_metrics::ProfileSignout signout_source_metric,
+ signin_metrics::SignoutDelete signout_delete_metric) {
+ StartSignOut(signout_source_metric, signout_delete_metric,
+ RemoveAccountsOption::kRemoveAllAccounts);
+}
+
+void SigninManagerBase::SignOutAndKeepAllAccounts(
+ signin_metrics::ProfileSignout signout_source_metric,
+ signin_metrics::SignoutDelete signout_delete_metric) {
+ StartSignOut(signout_source_metric, signout_delete_metric,
+ RemoveAccountsOption::kKeepAllAccounts);
+}
+
+void SigninManagerBase::StartSignOut(
+ signin_metrics::ProfileSignout signout_source_metric,
+ signin_metrics::SignoutDelete signout_delete_metric,
+ RemoveAccountsOption remove_option) {
+ signin_client()->PreSignOut(
+ base::BindOnce(&SigninManagerBase::OnSignoutDecisionReached,
+ base::Unretained(this), signout_source_metric,
+ signout_delete_metric, remove_option),
+ signout_source_metric);
+}
+
+void SigninManagerBase::OnSignoutDecisionReached(
+ signin_metrics::ProfileSignout signout_source_metric,
+ signin_metrics::SignoutDelete signout_delete_metric,
+ RemoveAccountsOption remove_option,
+ SigninClient::SignoutDecision signout_decision) {
+ DCHECK(IsInitialized());
+
+ signin_metrics::LogSignout(signout_source_metric, signout_delete_metric);
+ if (!IsAuthenticated()) {
+ return;
+ }
+
+ // TODO(crbug.com/887756): Consider moving this higher up, or document why
+ // the above blocks are exempt from the |signout_decision| early return.
+ if (signout_decision == SigninClient::SignoutDecision::DISALLOW_SIGNOUT) {
+ DVLOG(1) << "Ignoring attempt to sign out while signout disallowed";
+ return;
+ }
+
+ AccountInfo account_info = GetAuthenticatedAccountInfo();
+ const std::string account_id = GetAuthenticatedAccountId();
+ const std::string username = account_info.email;
+ const base::Time signin_time =
+ base::Time::FromDeltaSinceWindowsEpoch(base::TimeDelta::FromMicroseconds(
+ signin_client()->GetPrefs()->GetInt64(prefs::kSignedInTime)));
+ ClearAuthenticatedAccountId();
+ signin_client()->GetPrefs()->ClearPref(prefs::kGoogleServicesHostedDomain);
+ signin_client()->GetPrefs()->ClearPref(prefs::kGoogleServicesAccountId);
+ signin_client()->GetPrefs()->ClearPref(prefs::kGoogleServicesUserAccountId);
+ signin_client()->GetPrefs()->ClearPref(prefs::kSignedInTime);
+
+ // Determine the duration the user was logged in and log that to UMA.
+ if (!signin_time.is_null()) {
+ base::TimeDelta signed_in_duration = base::Time::Now() - signin_time;
+ UMA_HISTOGRAM_COUNTS_1M("Signin.SignedInDurationBeforeSignout",
+ signed_in_duration.InMinutes());
+ }
+
+ // Revoke all tokens before sending signed_out notification, because there
+ // may be components that don't listen for token service events when the
+ // profile is not connected to an account.
+ switch (remove_option) {
+ case RemoveAccountsOption::kRemoveAllAccounts:
+ VLOG(0) << "Revoking all refresh tokens on server. Reason: sign out";
+ token_service()->RevokeAllCredentials(
+ signin_metrics::SourceForRefreshTokenOperation::
+ kSigninManager_ClearPrimaryAccount);
+ break;
+ case RemoveAccountsOption::kRemoveAuthenticatedAccountIfInError:
+ if (token_service()->RefreshTokenHasError(account_id))
+ token_service()->RevokeCredentials(
+ account_id, signin_metrics::SourceForRefreshTokenOperation::
+ kSigninManager_ClearPrimaryAccount);
+ break;
+ case RemoveAccountsOption::kKeepAllAccounts:
+ // Do nothing.
+ break;
+ }
+
+ FireGoogleSignedOut(account_info);
+}
+
+void SigninManagerBase::FireGoogleSignedOut(const AccountInfo& account_info) {
+ if (observer_ != nullptr) {
+ observer_->GoogleSignedOut(account_info);
+ }
+}
+#endif // !defined(OS_CHROMEOS)
diff --git a/chromium/components/signin/core/browser/signin_manager_base.h b/chromium/components/signin/core/browser/signin_manager_base.h
index 6d04878c264..9297ca097fe 100644
--- a/chromium/components/signin/core/browser/signin_manager_base.h
+++ b/chromium/components/signin/core/browser/signin_manager_base.h
@@ -33,10 +33,13 @@
#include "base/observer_list.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_member.h"
+#include "components/signin/core/browser/account_consistency_method.h"
#include "components/signin/core/browser/account_info.h"
+#include "components/signin/core/browser/signin_client.h"
#include "google_apis/gaia/google_service_auth_error.h"
class AccountTrackerService;
+class GaiaCookieManagerService;
class PrefRegistrySimple;
class PrefService;
class ProfileOAuth2TokenService;
@@ -53,6 +56,14 @@ class SigninManagerBase {
// Called when the currently signed-in user for a user has been signed out.
virtual void GoogleSignedOut(const AccountInfo& account_info) {}
+ // Called during the signin as soon as
+ // SigninManagerBase::authenticated_account_id_ is set.
+ virtual void AuthenticatedAccountSet(const AccountInfo& account_info) {}
+
+ // Called during the signout as soon as
+ // SigninManagerBase::authenticated_account_id_ is cleared.
+ virtual void AuthenticatedAccountCleared() {}
+
protected:
virtual ~Observer() {}
@@ -73,11 +84,25 @@ class SigninManagerBase {
#endif
SigninManagerBase(SigninClient* client,
ProfileOAuth2TokenService* token_service,
- AccountTrackerService* account_tracker_service);
+ AccountTrackerService* account_tracker_service,
+ GaiaCookieManagerService* cookie_manager_service,
+ signin::AccountConsistencyMethod account_consistency);
#if !defined(OS_CHROMEOS)
public:
#endif
+#if !defined(OS_CHROMEOS)
+ // Used to remove accounts from the token service and the account tracker.
+ enum class RemoveAccountsOption {
+ // Do not remove accounts.
+ kKeepAllAccounts,
+ // Remove all the accounts.
+ kRemoveAllAccounts,
+ // Removes the authenticated account if it is in authentication error.
+ kRemoveAuthenticatedAccountIfInError
+ };
+#endif
+
virtual ~SigninManagerBase();
// Registers per-profile prefs.
@@ -122,6 +147,34 @@ class SigninManagerBase {
void SetObserver(Observer* observer);
void ClearObserver();
+ // Signout API surfaces (not supported on ChromeOS, where signout is not
+ // permitted).
+#if !defined(OS_CHROMEOS)
+ // Signs a user out, removing the preference, erasing all keys
+ // associated with the authenticated user, and canceling all auth in progress.
+ // On mobile and on desktop pre-DICE, this also removes all accounts from
+ // Chrome by revoking all refresh tokens.
+ // On desktop with DICE enabled, this will remove the authenticated account
+ // from Chrome only if it is in authentication error. No other accounts are
+ // removed.
+ void SignOut(signin_metrics::ProfileSignout signout_source_metric,
+ signin_metrics::SignoutDelete signout_delete_metric);
+
+ // Signs a user out, removing the preference, erasing all keys
+ // associated with the authenticated user, and canceling all auth in progress.
+ // It removes all accounts from Chrome by revoking all refresh tokens.
+ void SignOutAndRemoveAllAccounts(
+ signin_metrics::ProfileSignout signout_source_metric,
+ signin_metrics::SignoutDelete signout_delete_metric);
+
+ // Signs a user out, removing the preference, erasing all keys
+ // associated with the authenticated user, and canceling all auth in progress.
+ // Does not remove the accounts from the token service.
+ void SignOutAndKeepAllAccounts(
+ signin_metrics::ProfileSignout signout_source_metric,
+ signin_metrics::SignoutDelete signout_delete_metric);
+#endif
+
protected:
SigninClient* signin_client() const { return client_; }
@@ -160,6 +213,23 @@ class SigninManagerBase {
// SigninManagerBase.
friend class SigninManager;
+#if !defined(OS_CHROMEOS)
+ // Starts the sign out process.
+ void StartSignOut(signin_metrics::ProfileSignout signout_source_metric,
+ signin_metrics::SignoutDelete signout_delete_metric,
+ RemoveAccountsOption remove_option);
+
+ // The sign out process which is started by SigninClient::PreSignOut()
+ void OnSignoutDecisionReached(
+ signin_metrics::ProfileSignout signout_source_metric,
+ signin_metrics::SignoutDelete signout_delete_metric,
+ RemoveAccountsOption remove_option,
+ SigninClient::SignoutDecision signout_decision);
+
+ // Send all observers |GoogleSignedOut| notifications.
+ void FireGoogleSignedOut(const AccountInfo& account_info);
+#endif
+
SigninClient* client_;
// The ProfileOAuth2TokenService instance associated with this object. Must
@@ -167,6 +237,7 @@ class SigninManagerBase {
ProfileOAuth2TokenService* token_service_;
AccountTrackerService* account_tracker_service_;
+
bool initialized_;
// Account id after successful authentication.
@@ -175,6 +246,8 @@ class SigninManagerBase {
// The list of callbacks notified on shutdown.
base::CallbackList<void()> on_shutdown_callback_list_;
+ signin::AccountConsistencyMethod account_consistency_;
+
base::WeakPtrFactory<SigninManagerBase> weak_pointer_factory_;
DISALLOW_COPY_AND_ASSIGN(SigninManagerBase);
diff --git a/chromium/components/signin/core/browser/test_signin_client.cc b/chromium/components/signin/core/browser/test_signin_client.cc
index 237beae6d9b..3a74d1ada5c 100644
--- a/chromium/components/signin/core/browser/test_signin_client.cc
+++ b/chromium/components/signin/core/browser/test_signin_client.cc
@@ -12,8 +12,11 @@
#include "services/network/test/test_cookie_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
-TestSigninClient::TestSigninClient(PrefService* pref_service)
- : pref_service_(pref_service),
+TestSigninClient::TestSigninClient(
+ PrefService* pref_service,
+ network::TestURLLoaderFactory* test_url_loader_factory)
+ : test_url_loader_factory_(test_url_loader_factory),
+ pref_service_(pref_service),
are_signin_cookies_allowed_(true),
network_calls_delayed_(false),
is_signout_allowed_(true),
@@ -37,7 +40,7 @@ void TestSigninClient::PreSignOut(
scoped_refptr<network::SharedURLLoaderFactory>
TestSigninClient::GetURLLoaderFactory() {
- return test_url_loader_factory_.GetSafeWeakWrapper();
+ return GetTestURLLoaderFactory()->GetSafeWeakWrapper();
}
network::mojom::CookieManager* TestSigninClient::GetCookieManager() {
@@ -46,6 +49,25 @@ network::mojom::CookieManager* TestSigninClient::GetCookieManager() {
return cookie_manager_.get();
}
+network::TestURLLoaderFactory* TestSigninClient::GetTestURLLoaderFactory() {
+ if (test_url_loader_factory_)
+ return test_url_loader_factory_;
+
+ if (!default_test_url_loader_factory_) {
+ default_test_url_loader_factory_ =
+ std::make_unique<network::TestURLLoaderFactory>();
+ }
+
+ return default_test_url_loader_factory_.get();
+}
+
+void TestSigninClient::OverrideTestUrlLoaderFactory(
+ network::TestURLLoaderFactory* factory) {
+ DCHECK(!default_test_url_loader_factory_);
+ DCHECK(!test_url_loader_factory_);
+ test_url_loader_factory_ = factory;
+}
+
std::string TestSigninClient::GetProductVersion() { return ""; }
void TestSigninClient::SetNetworkCallsDelayed(bool value) {
@@ -70,6 +92,10 @@ bool TestSigninClient::AreSigninCookiesAllowed() {
return are_signin_cookies_allowed_;
}
+bool TestSigninClient::AreSigninCookiesDeletedOnExit() {
+ return false;
+}
+
void TestSigninClient::AddContentSettingsObserver(
content_settings::Observer* observer) {
}
@@ -88,10 +114,9 @@ void TestSigninClient::DelayNetworkCall(base::OnceClosure callback) {
std::unique_ptr<GaiaAuthFetcher> TestSigninClient::CreateGaiaAuthFetcher(
GaiaAuthConsumer* consumer,
- gaia::GaiaSource source,
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
+ gaia::GaiaSource source) {
return std::make_unique<GaiaAuthFetcher>(consumer, source,
- url_loader_factory);
+ GetURLLoaderFactory());
}
void TestSigninClient::PreGaiaLogout(base::OnceClosure callback) {
diff --git a/chromium/components/signin/core/browser/test_signin_client.h b/chromium/components/signin/core/browser/test_signin_client.h
index 103cf5999e4..2347b86a978 100644
--- a/chromium/components/signin/core/browser/test_signin_client.h
+++ b/chromium/components/signin/core/browser/test_signin_client.h
@@ -27,7 +27,9 @@ class PrefService;
// part of its interface.
class TestSigninClient : public SigninClient {
public:
- TestSigninClient(PrefService* pref_service);
+ TestSigninClient(
+ PrefService* pref_service,
+ network::TestURLLoaderFactory* test_url_loader_factory = nullptr);
~TestSigninClient() override;
// SigninClient implementation that is specialized for unit tests.
@@ -57,9 +59,12 @@ class TestSigninClient : public SigninClient {
cookie_manager_ = std::move(cookie_manager);
}
- network::TestURLLoaderFactory* test_url_loader_factory() {
- return &test_url_loader_factory_;
- }
+ // Returns |test_url_loader_factory_| if it is specified. Otherwise, lazily
+ // creates a default factory and returns it.
+ network::TestURLLoaderFactory* GetTestURLLoaderFactory();
+
+ // Pass a TestURLLoader factory to use instead of the default one.
+ void OverrideTestUrlLoaderFactory(network::TestURLLoaderFactory* factory);
void set_are_signin_cookies_allowed(bool value) {
are_signin_cookies_allowed_ = value;
@@ -79,6 +84,7 @@ class TestSigninClient : public SigninClient {
bool IsFirstRun() const override;
base::Time GetInstallDate() override;
bool AreSigninCookiesAllowed() override;
+ bool AreSigninCookiesDeletedOnExit() override;
void AddContentSettingsObserver(
content_settings::Observer* observer) override;
void RemoveContentSettingsObserver(
@@ -86,14 +92,14 @@ class TestSigninClient : public SigninClient {
void DelayNetworkCall(base::OnceClosure callback) override;
std::unique_ptr<GaiaAuthFetcher> CreateGaiaAuthFetcher(
GaiaAuthConsumer* consumer,
- gaia::GaiaSource source,
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
- override;
+ gaia::GaiaSource source) override;
void PreGaiaLogout(base::OnceClosure callback) override;
void SetReadyForDiceMigration(bool ready) override;
private:
- network::TestURLLoaderFactory test_url_loader_factory_;
+ std::unique_ptr<network::TestURLLoaderFactory>
+ default_test_url_loader_factory_;
+ network::TestURLLoaderFactory* test_url_loader_factory_;
PrefService* pref_service_;
std::unique_ptr<network::mojom::CookieManager> cookie_manager_;
diff --git a/chromium/components/signin/ios/browser/account_consistency_service_unittest.mm b/chromium/components/signin/ios/browser/account_consistency_service_unittest.mm
index 45d33c881e4..0a2e3d0648f 100644
--- a/chromium/components/signin/ios/browser/account_consistency_service_unittest.mm
+++ b/chromium/components/signin/ios/browser/account_consistency_service_unittest.mm
@@ -130,13 +130,13 @@ class AccountConsistencyServiceTest : public PlatformTest {
HostContentSettingsMap::RegisterProfilePrefs(prefs_.registry());
web_view_load_expection_count_ = 0;
- signin_client_.reset(new TestSigninClient(&prefs_));
+ signin_client_.reset(
+ new TestSigninClient(&prefs_, &test_url_loader_factory_));
identity_test_env_.reset(new identity::IdentityTestEnvironment(
- &test_url_loader_factory_, &prefs_,
+ /*test_url_loader_factory=*/nullptr, &prefs_,
signin::AccountConsistencyMethod::kDisabled, signin_client_.get()));
settings_map_ = new HostContentSettingsMap(
- &prefs_, false /* incognito_profile */, false /* guest_profile */,
- false /* store_last_modified */,
+ &prefs_, false /* is_off_the_record */, false /* store_last_modified */,
false /* migrate_requesting_and_top_level_origin_settings */);
cookie_settings_ =
new content_settings::CookieSettings(settings_map_.get(), &prefs_, "");