blob: e7b863f546e6ea248ca5d7d36912e78173a44bc9 [file] [log] [blame]
// Copyright 2017 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 "services/identity/public/cpp/identity_manager.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "build/build_config.h"
#include "components/signin/core/browser/account_tracker_service.h"
#include "components/signin/core/browser/fake_gaia_cookie_manager_service.h"
#include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
#include "components/signin/core/browser/fake_signin_manager.h"
#include "components/signin/core/browser/profile_management_switches.h"
#include "components/signin/core/browser/test_signin_client.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "services/identity/public/cpp/identity_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace identity {
namespace {
#if defined(OS_CHROMEOS)
using SigninManagerForTest = FakeSigninManagerBase;
#else
using SigninManagerForTest = FakeSigninManager;
#endif // OS_CHROMEOS
const char kTestGaiaId[] = "dummyId";
const char kTestGaiaId2[] = "dummyId2";
const char kTestGaiaId3[] = "dummyId3";
const char kTestEmail[] = "me@gmail.com";
const char kTestEmail2[] = "me2@gmail.com";
const char kTestEmail3[] = "me3@gmail.com";
#if defined(OS_CHROMEOS)
const char kTestEmailWithPeriod[] = "m.e@gmail.com";
#endif
// Subclass of FakeProfileOAuth2TokenService with bespoke behavior.
class CustomFakeProfileOAuth2TokenService
: public FakeProfileOAuth2TokenService {
public:
void set_on_access_token_invalidated_info(
std::string expected_account_id_to_invalidate,
std::set<std::string> expected_scopes_to_invalidate,
std::string expected_access_token_to_invalidate,
base::OnceClosure callback) {
expected_account_id_to_invalidate_ = expected_account_id_to_invalidate;
expected_scopes_to_invalidate_ = expected_scopes_to_invalidate;
expected_access_token_to_invalidate_ = expected_access_token_to_invalidate;
on_access_token_invalidated_callback_ = std::move(callback);
}
private:
// OAuth2TokenService:
void InvalidateAccessTokenImpl(const std::string& account_id,
const std::string& client_id,
const ScopeSet& scopes,
const std::string& access_token) override {
if (on_access_token_invalidated_callback_) {
EXPECT_EQ(expected_account_id_to_invalidate_, account_id);
EXPECT_EQ(expected_scopes_to_invalidate_, scopes);
EXPECT_EQ(expected_access_token_to_invalidate_, access_token);
std::move(on_access_token_invalidated_callback_).Run();
}
}
std::string expected_account_id_to_invalidate_;
std::set<std::string> expected_scopes_to_invalidate_;
std::string expected_access_token_to_invalidate_;
base::OnceClosure on_access_token_invalidated_callback_;
};
class AccountTrackerServiceForTest : public AccountTrackerService {
public:
void SetAccountStateFromUserInfo(const std::string& account_id,
const base::DictionaryValue* user_info) {
AccountTrackerService::SetAccountStateFromUserInfo(account_id, user_info);
}
};
class TestSigninManagerObserver : public SigninManagerBase::Observer {
public:
explicit TestSigninManagerObserver(SigninManagerBase* signin_manager)
: signin_manager_(signin_manager) {
signin_manager_->AddObserver(this);
}
~TestSigninManagerObserver() override {
signin_manager_->RemoveObserver(this);
}
void set_identity_manager(IdentityManager* identity_manager) {
identity_manager_ = identity_manager;
}
void set_on_google_signin_succeeded_callback(base::OnceClosure callback) {
on_google_signin_succeeded_callback_ = std::move(callback);
}
void set_on_google_signed_out_callback(base::OnceClosure callback) {
on_google_signed_out_callback_ = std::move(callback);
}
const AccountInfo& primary_account_from_signin_callback() {
return primary_account_from_signin_callback_;
}
const AccountInfo& primary_account_from_signout_callback() {
return primary_account_from_signout_callback_;
}
private:
// SigninManager::Observer:
void GoogleSigninSucceeded(const AccountInfo& account_info) override {
ASSERT_TRUE(identity_manager_);
primary_account_from_signin_callback_ =
identity_manager_->GetPrimaryAccountInfo();
if (on_google_signin_succeeded_callback_)
std::move(on_google_signin_succeeded_callback_).Run();
}
void GoogleSignedOut(const AccountInfo& account_info) override {
ASSERT_TRUE(identity_manager_);
primary_account_from_signout_callback_ =
identity_manager_->GetPrimaryAccountInfo();
if (on_google_signed_out_callback_)
std::move(on_google_signed_out_callback_).Run();
}
SigninManagerBase* signin_manager_;
IdentityManager* identity_manager_;
base::OnceClosure on_google_signin_succeeded_callback_;
base::OnceClosure on_google_signed_out_callback_;
AccountInfo primary_account_from_signin_callback_;
AccountInfo primary_account_from_signout_callback_;
};
// Class that observes updates from both ProfileOAuth2TokenService and
// IdentityManager and verifies thereby that IdentityManager receives updates
// before direct observers of ProfileOAuth2TokenService.
class TestTokenServiceObserver : public OAuth2TokenService::Observer,
public identity::IdentityManager::Observer {
public:
explicit TestTokenServiceObserver(OAuth2TokenService* token_service)
: token_service_(token_service) {
token_service_->AddObserver(this);
}
~TestTokenServiceObserver() override {
token_service_->RemoveObserver(this);
identity_manager_->RemoveObserver(this);
}
void set_identity_manager(IdentityManager* identity_manager) {
identity_manager_ = identity_manager;
identity_manager_->AddObserver(this);
}
void set_on_refresh_token_available_callback(base::OnceClosure callback) {
on_refresh_token_available_callback_ = std::move(callback);
}
void set_on_refresh_token_revoked_callback(base::OnceClosure callback) {
on_refresh_token_revoked_callback_ = std::move(callback);
}
private:
// IdentityManager::Observer:
void OnRefreshTokenUpdatedForAccount(const AccountInfo& account_info,
bool is_valid) override {
EXPECT_TRUE(
account_id_from_identity_manager_token_updated_callback_.empty());
account_id_from_identity_manager_token_updated_callback_ =
account_info.account_id;
}
void OnRefreshTokenRemovedForAccount(
const AccountInfo& account_info) override {
EXPECT_TRUE(
account_id_from_identity_manager_token_removed_callback_.empty());
account_id_from_identity_manager_token_removed_callback_ =
account_info.account_id;
}
// OAuth2TokenService::Observer:
void OnRefreshTokenAvailable(const std::string& account_id) override {
// This object should have received the corresponding IdentityManager
// callback before receiving this callback.
EXPECT_EQ(account_id_from_identity_manager_token_updated_callback_,
account_id);
account_id_from_identity_manager_token_updated_callback_.clear();
if (on_refresh_token_available_callback_)
std::move(on_refresh_token_available_callback_).Run();
}
void OnRefreshTokenRevoked(const std::string& account_id) override {
// This object should have received the corresponding IdentityManager
// callback before receiving this callback.
EXPECT_EQ(account_id_from_identity_manager_token_removed_callback_,
account_id);
account_id_from_identity_manager_token_removed_callback_.clear();
if (on_refresh_token_revoked_callback_)
std::move(on_refresh_token_revoked_callback_).Run();
}
OAuth2TokenService* token_service_;
IdentityManager* identity_manager_;
std::string account_id_from_identity_manager_token_updated_callback_;
std::string account_id_from_identity_manager_token_removed_callback_;
base::OnceClosure on_refresh_token_available_callback_;
base::OnceClosure on_refresh_token_revoked_callback_;
};
class TestIdentityManagerObserver : IdentityManager::Observer {
public:
explicit TestIdentityManagerObserver(IdentityManager* identity_manager)
: identity_manager_(identity_manager) {
identity_manager_->AddObserver(this);
}
~TestIdentityManagerObserver() override {
identity_manager_->RemoveObserver(this);
}
void set_on_primary_account_set_callback(base::OnceClosure callback) {
on_primary_account_set_callback_ = std::move(callback);
}
void set_on_primary_account_cleared_callback(base::OnceClosure callback) {
on_primary_account_cleared_callback_ = std::move(callback);
}
const AccountInfo& primary_account_from_set_callback() {
return primary_account_from_set_callback_;
}
const AccountInfo& primary_account_from_cleared_callback() {
return primary_account_from_cleared_callback_;
}
void set_on_refresh_token_updated_callback(base::OnceClosure callback) {
on_refresh_token_updated_callback_ = std::move(callback);
}
void set_on_refresh_token_removed_callback(base::OnceClosure callback) {
on_refresh_token_removed_callback_ = std::move(callback);
}
const AccountInfo& account_from_refresh_token_updated_callback() {
return account_from_refresh_token_updated_callback_;
}
bool validity_from_refresh_token_updated_callback() {
return validity_from_refresh_token_updated_callback_;
}
const AccountInfo& account_from_refresh_token_removed_callback() {
return account_from_refresh_token_removed_callback_;
}
void set_on_accounts_in_cookie_updated_callback(base::OnceClosure callback) {
on_accounts_in_cookie_updated_callback_ = std::move(callback);
}
const std::vector<AccountInfo>& accounts_from_cookie_change_callback() {
return accounts_from_cookie_change_callback_;
}
private:
// IdentityManager::Observer:
void OnPrimaryAccountSet(const AccountInfo& primary_account_info) override {
primary_account_from_set_callback_ = primary_account_info;
if (on_primary_account_set_callback_)
std::move(on_primary_account_set_callback_).Run();
}
void OnPrimaryAccountCleared(
const AccountInfo& previous_primary_account_info) override {
primary_account_from_cleared_callback_ = previous_primary_account_info;
if (on_primary_account_cleared_callback_)
std::move(on_primary_account_cleared_callback_).Run();
}
void OnRefreshTokenUpdatedForAccount(const AccountInfo& account_info,
bool is_valid) override {
account_from_refresh_token_updated_callback_ = account_info;
validity_from_refresh_token_updated_callback_ = is_valid;
if (on_refresh_token_updated_callback_)
std::move(on_refresh_token_updated_callback_).Run();
}
void OnRefreshTokenRemovedForAccount(
const AccountInfo& account_info) override {
account_from_refresh_token_removed_callback_ = account_info;
if (on_refresh_token_removed_callback_)
std::move(on_refresh_token_removed_callback_).Run();
}
void OnAccountsInCookieUpdated(
const std::vector<AccountInfo>& accounts) override {
accounts_from_cookie_change_callback_ = accounts;
if (on_accounts_in_cookie_updated_callback_)
std::move(on_accounts_in_cookie_updated_callback_).Run();
}
IdentityManager* identity_manager_;
base::OnceClosure on_primary_account_set_callback_;
base::OnceClosure on_primary_account_cleared_callback_;
base::OnceClosure on_refresh_token_updated_callback_;
base::OnceClosure on_refresh_token_removed_callback_;
base::OnceClosure on_accounts_in_cookie_updated_callback_;
AccountInfo primary_account_from_set_callback_;
AccountInfo primary_account_from_cleared_callback_;
AccountInfo account_from_refresh_token_updated_callback_;
bool validity_from_refresh_token_updated_callback_;
AccountInfo account_from_refresh_token_removed_callback_;
std::vector<AccountInfo> accounts_from_cookie_change_callback_;
};
class TestIdentityManagerDiagnosticsObserver
: IdentityManager::DiagnosticsObserver {
public:
explicit TestIdentityManagerDiagnosticsObserver(
IdentityManager* identity_manager)
: identity_manager_(identity_manager) {
identity_manager_->AddDiagnosticsObserver(this);
}
~TestIdentityManagerDiagnosticsObserver() override {
identity_manager_->RemoveDiagnosticsObserver(this);
}
void set_on_access_token_requested_callback(base::OnceClosure callback) {
on_access_token_requested_callback_ = std::move(callback);
}
const std::string& token_requestor_account_id() {
return token_requestor_account_id_;
}
const std::string& token_requestor_consumer_id() {
return token_requestor_consumer_id_;
}
const OAuth2TokenService::ScopeSet& token_requestor_scopes() {
return token_requestor_scopes_;
}
private:
// IdentityManager::DiagnosticsObserver:
void OnAccessTokenRequested(
const std::string& account_id,
const std::string& consumer_id,
const OAuth2TokenService::ScopeSet& scopes) override {
token_requestor_account_id_ = account_id;
token_requestor_consumer_id_ = consumer_id;
token_requestor_scopes_ = scopes;
if (on_access_token_requested_callback_)
std::move(on_access_token_requested_callback_).Run();
}
IdentityManager* identity_manager_;
base::OnceClosure on_access_token_requested_callback_;
std::string token_requestor_account_id_;
std::string token_requestor_consumer_id_;
OAuth2TokenService::ScopeSet token_requestor_scopes_;
};
} // namespace
class IdentityManagerTest : public testing::Test {
public:
IdentityManagerTest()
: signin_client_(&pref_service_),
#if defined(OS_CHROMEOS)
signin_manager_(&signin_client_, &account_tracker_),
#else
signin_manager_(&signin_client_,
&token_service_,
&account_tracker_,
nullptr),
#endif
gaia_cookie_manager_service_(&token_service_,
"identity_manager_unittest",
&signin_client_) {
AccountTrackerService::RegisterPrefs(pref_service_.registry());
SigninManagerBase::RegisterProfilePrefs(pref_service_.registry());
SigninManagerBase::RegisterPrefs(pref_service_.registry());
account_tracker_.Initialize(&signin_client_);
signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
RecreateIdentityManager();
}
IdentityManager* identity_manager() { return identity_manager_.get(); }
TestIdentityManagerObserver* identity_manager_observer() {
return identity_manager_observer_.get();
}
TestIdentityManagerDiagnosticsObserver*
identity_manager_diagnostics_observer() {
return identity_manager_diagnostics_observer_.get();
}
AccountTrackerServiceForTest* account_tracker() { return &account_tracker_; }
SigninManagerForTest* signin_manager() { return &signin_manager_; }
CustomFakeProfileOAuth2TokenService* token_service() {
return &token_service_;
}
FakeGaiaCookieManagerService* gaia_cookie_manager_service() {
return &gaia_cookie_manager_service_;
}
// Used by some tests that need to re-instantiate IdentityManager after
// performing some other setup.
void RecreateIdentityManager() {
// Reset them all to null first to ensure that they're destroyed, as
// otherwise SigninManager ends up getting a new DiagnosticsObserver added
// before the old one is removed.
identity_manager_observer_.reset();
identity_manager_diagnostics_observer_.reset();
identity_manager_.reset();
identity_manager_.reset(
new IdentityManager(&signin_manager_, &token_service_,
&account_tracker_, &gaia_cookie_manager_service_));
identity_manager_observer_.reset(
new TestIdentityManagerObserver(identity_manager_.get()));
identity_manager_diagnostics_observer_.reset(
new TestIdentityManagerDiagnosticsObserver(identity_manager_.get()));
}
private:
base::MessageLoop message_loop_;
sync_preferences::TestingPrefServiceSyncable pref_service_;
AccountTrackerServiceForTest account_tracker_;
TestSigninClient signin_client_;
SigninManagerForTest signin_manager_;
CustomFakeProfileOAuth2TokenService token_service_;
FakeGaiaCookieManagerService gaia_cookie_manager_service_;
std::unique_ptr<IdentityManager> identity_manager_;
std::unique_ptr<TestIdentityManagerObserver> identity_manager_observer_;
std::unique_ptr<TestIdentityManagerDiagnosticsObserver>
identity_manager_diagnostics_observer_;
DISALLOW_COPY_AND_ASSIGN(IdentityManagerTest);
};
// Test that IdentityManager starts off with the information in SigninManager.
TEST_F(IdentityManagerTest, PrimaryAccountInfoAtStartup) {
AccountInfo primary_account_info =
identity_manager()->GetPrimaryAccountInfo();
EXPECT_EQ(kTestGaiaId, primary_account_info.gaia);
EXPECT_EQ(kTestEmail, primary_account_info.email);
}
// Signin/signout tests aren't relevant and cannot build on ChromeOS, which
// doesn't support signin/signout.
#if !defined(OS_CHROMEOS)
// Test that the user signing in results in firing of the IdentityManager
// observer callback and the IdentityManager's state being updated.
TEST_F(IdentityManagerTest, PrimaryAccountInfoAfterSignin) {
base::RunLoop run_loop;
identity_manager_observer()->set_on_primary_account_set_callback(
run_loop.QuitClosure());
signin_manager()->SignIn(kTestGaiaId, kTestEmail, "password");
run_loop.Run();
AccountInfo primary_account_from_set_callback =
identity_manager_observer()->primary_account_from_set_callback();
EXPECT_EQ(kTestGaiaId, primary_account_from_set_callback.gaia);
EXPECT_EQ(kTestEmail, primary_account_from_set_callback.email);
AccountInfo primary_account_info =
identity_manager()->GetPrimaryAccountInfo();
EXPECT_EQ(kTestGaiaId, primary_account_info.gaia);
EXPECT_EQ(kTestEmail, primary_account_info.email);
}
// Test that the user signing out results in firing of the IdentityManager
// observer callback and the IdentityManager's state being updated.
TEST_F(IdentityManagerTest, PrimaryAccountInfoAfterSigninAndSignout) {
// First ensure that the user is signed in from the POV of the
// IdentityManager.
base::RunLoop run_loop;
identity_manager_observer()->set_on_primary_account_set_callback(
run_loop.QuitClosure());
signin_manager()->SignIn(kTestGaiaId, kTestEmail, "password");
run_loop.Run();
// Sign the user out and check that the IdentityManager responds
// appropriately.
base::RunLoop run_loop2;
identity_manager_observer()->set_on_primary_account_cleared_callback(
run_loop2.QuitClosure());
signin_manager()->ForceSignOut();
run_loop2.Run();
AccountInfo primary_account_from_cleared_callback =
identity_manager_observer()->primary_account_from_cleared_callback();
EXPECT_EQ(kTestGaiaId, primary_account_from_cleared_callback.gaia);
EXPECT_EQ(kTestEmail, primary_account_from_cleared_callback.email);
AccountInfo primary_account_info =
identity_manager()->GetPrimaryAccountInfo();
EXPECT_EQ("", primary_account_info.gaia);
EXPECT_EQ("", primary_account_info.email);
}
#endif // !defined(OS_CHROMEOS)
TEST_F(IdentityManagerTest, HasPrimaryAccount) {
EXPECT_TRUE(identity_manager()->HasPrimaryAccount());
#if !defined(OS_CHROMEOS)
base::RunLoop run_loop;
identity_manager_observer()->set_on_primary_account_cleared_callback(
run_loop.QuitClosure());
signin_manager()->ForceSignOut();
run_loop.Run();
EXPECT_FALSE(identity_manager()->HasPrimaryAccount());
#endif
}
TEST_F(IdentityManagerTest, GetAccountsInteractionWithPrimaryAccount) {
// Should not have any refresh tokens at initialization.
EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
std::string account_id = signin_manager()->GetAuthenticatedAccountId();
// Add a refresh token for the primary account and check that it shows up in
// GetAccountsWithRefreshTokens().
SetRefreshTokenForPrimaryAccount(token_service(), identity_manager());
std::vector<AccountInfo> accounts_after_update =
identity_manager()->GetAccountsWithRefreshTokens();
EXPECT_EQ(1u, accounts_after_update.size());
EXPECT_EQ(accounts_after_update[0].account_id, account_id);
EXPECT_EQ(accounts_after_update[0].gaia, kTestGaiaId);
EXPECT_EQ(accounts_after_update[0].email, kTestEmail);
// Update the token and check that it doesn't change the state (or blow up).
SetRefreshTokenForPrimaryAccount(token_service(), identity_manager());
std::vector<AccountInfo> accounts_after_second_update =
identity_manager()->GetAccountsWithRefreshTokens();
EXPECT_EQ(1u, accounts_after_second_update.size());
EXPECT_EQ(accounts_after_second_update[0].account_id, account_id);
EXPECT_EQ(accounts_after_second_update[0].gaia, kTestGaiaId);
EXPECT_EQ(accounts_after_second_update[0].email, kTestEmail);
// Remove the token for the primary account and check that this is likewise
// reflected.
RemoveRefreshTokenForPrimaryAccount(token_service(), identity_manager());
EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
}
TEST_F(IdentityManagerTest,
QueryingOfRefreshTokensInteractionWithPrimaryAccount) {
AccountInfo account_info = identity_manager()->GetPrimaryAccountInfo();
std::string account_id = account_info.account_id;
// Should not have a refresh token for the primary account at initialization.
EXPECT_FALSE(
identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
// Add a refresh token for the primary account and check that it affects this
// state.
SetRefreshTokenForPrimaryAccount(token_service(), identity_manager());
EXPECT_TRUE(
identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken());
// Update the token and check that it doesn't change the state (or blow up).
SetRefreshTokenForPrimaryAccount(token_service(), identity_manager());
EXPECT_TRUE(
identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken());
// Remove the token for the primary account and check that this is likewise
// reflected.
RemoveRefreshTokenForPrimaryAccount(token_service(), identity_manager());
EXPECT_FALSE(
identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
}
TEST_F(IdentityManagerTest, GetAccountsReflectsNonemptyInitialState) {
EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
std::string account_id = signin_manager()->GetAuthenticatedAccountId();
// Add a refresh token for the primary account and sanity-check that it shows
// up in GetAccountsWithRefreshTokens().
SetRefreshTokenForPrimaryAccount(token_service(), identity_manager());
std::vector<AccountInfo> accounts_after_update =
identity_manager()->GetAccountsWithRefreshTokens();
EXPECT_EQ(1u, accounts_after_update.size());
EXPECT_EQ(accounts_after_update[0].account_id, account_id);
EXPECT_EQ(accounts_after_update[0].gaia, kTestGaiaId);
EXPECT_EQ(accounts_after_update[0].email, kTestEmail);
// Recreate the IdentityManager and check that the newly-created instance
// reflects the current state.
RecreateIdentityManager();
std::vector<AccountInfo> accounts_after_recreation =
identity_manager()->GetAccountsWithRefreshTokens();
EXPECT_EQ(1u, accounts_after_recreation.size());
EXPECT_EQ(accounts_after_recreation[0].account_id, account_id);
EXPECT_EQ(accounts_after_recreation[0].gaia, kTestGaiaId);
EXPECT_EQ(accounts_after_recreation[0].email, kTestEmail);
}
TEST_F(IdentityManagerTest,
QueryingOfRefreshTokensReflectsNonemptyInitialState) {
AccountInfo account_info = identity_manager()->GetPrimaryAccountInfo();
std::string account_id = account_info.account_id;
EXPECT_FALSE(
identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
SetRefreshTokenForPrimaryAccount(token_service(), identity_manager());
EXPECT_TRUE(
identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken());
// Recreate the IdentityManager and check that the newly-created instance
// reflects the current state.
RecreateIdentityManager();
EXPECT_TRUE(
identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken());
}
TEST_F(IdentityManagerTest, GetAccountsInteractionWithSecondaryAccounts) {
// Should not have any refresh tokens at initialization.
EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
// Add a refresh token for a secondary account and check that it shows up in
// GetAccountsWithRefreshTokens().
account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2);
std::string account_id2 =
account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2).account_id;
SetRefreshTokenForAccount(token_service(), identity_manager(), account_id2);
std::vector<AccountInfo> accounts_after_update =
identity_manager()->GetAccountsWithRefreshTokens();
EXPECT_EQ(1u, accounts_after_update.size());
EXPECT_EQ(accounts_after_update[0].account_id, account_id2);
EXPECT_EQ(accounts_after_update[0].gaia, kTestGaiaId2);
EXPECT_EQ(accounts_after_update[0].email, kTestEmail2);
// Add a refresh token for a different secondary account and check that it
// also shows up in GetAccountsWithRefreshTokens().
account_tracker()->SeedAccountInfo(kTestGaiaId3, kTestEmail3);
std::string account_id3 =
account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId3).account_id;
SetRefreshTokenForAccount(token_service(), identity_manager(), account_id3);
std::vector<AccountInfo> accounts_after_second_update =
identity_manager()->GetAccountsWithRefreshTokens();
EXPECT_EQ(2u, accounts_after_second_update.size());
for (AccountInfo account_info : accounts_after_second_update) {
if (account_info.account_id == account_id2) {
EXPECT_EQ(account_info.gaia, kTestGaiaId2);
EXPECT_EQ(account_info.email, kTestEmail2);
} else {
EXPECT_EQ(account_info.gaia, kTestGaiaId3);
EXPECT_EQ(account_info.email, kTestEmail3);
}
}
// Remove the token for account2 and check that account3 is still present.
RemoveRefreshTokenForAccount(token_service(), identity_manager(),
account_id2);
std::vector<AccountInfo> accounts_after_third_update =
identity_manager()->GetAccountsWithRefreshTokens();
EXPECT_EQ(1u, accounts_after_third_update.size());
EXPECT_EQ(accounts_after_third_update[0].account_id, account_id3);
EXPECT_EQ(accounts_after_third_update[0].gaia, kTestGaiaId3);
EXPECT_EQ(accounts_after_third_update[0].email, kTestEmail3);
}
TEST_F(IdentityManagerTest,
HasPrimaryAccountWithRefreshTokenInteractionWithSecondaryAccounts) {
EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
// Adding a refresh token for a secondary account shouldn't change anything
// about the primary account
account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2);
std::string account_id2 =
account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2).account_id;
SetRefreshTokenForAccount(token_service(), identity_manager(), account_id2);
EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
// Adding a refresh token for a different secondary account should not do so
// either.
account_tracker()->SeedAccountInfo(kTestGaiaId3, kTestEmail3);
std::string account_id3 =
account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId3).account_id;
SetRefreshTokenForAccount(token_service(), identity_manager(), account_id3);
EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
// Removing the token for account2 should have no effect.
RemoveRefreshTokenForAccount(token_service(), identity_manager(),
account_id2);
EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
}
TEST_F(IdentityManagerTest,
HasAccountWithRefreshTokenInteractionWithSecondaryAccounts) {
account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2);
AccountInfo account_info2 =
account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2);
std::string account_id2 = account_info2.account_id;
EXPECT_FALSE(
identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
// Add a refresh token for account_info2 and check that this is reflected by
// HasAccountWithRefreshToken(.account_id).
SetRefreshTokenForAccount(token_service(), identity_manager(), account_id2);
EXPECT_TRUE(
identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
// Go through the same process for a different secondary account.
account_tracker()->SeedAccountInfo(kTestGaiaId3, kTestEmail3);
AccountInfo account_info3 =
account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId3);
std::string account_id3 = account_info3.account_id;
EXPECT_TRUE(
identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
EXPECT_FALSE(
identity_manager()->HasAccountWithRefreshToken(account_info3.account_id));
SetRefreshTokenForAccount(token_service(), identity_manager(), account_id3);
EXPECT_TRUE(
identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
EXPECT_TRUE(
identity_manager()->HasAccountWithRefreshToken(account_info3.account_id));
// Remove the token for account2.
RemoveRefreshTokenForAccount(token_service(), identity_manager(),
account_id2);
EXPECT_FALSE(
identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
EXPECT_TRUE(
identity_manager()->HasAccountWithRefreshToken(account_info3.account_id));
}
TEST_F(IdentityManagerTest,
GetAccountsInteractionBetweenPrimaryAndSecondaryAccounts) {
// Should not have any refresh tokens at initialization.
EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
// Add a refresh token for a secondary account and check that it shows up in
// GetAccountsWithRefreshTokens().
account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2);
std::string account_id2 =
account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2).account_id;
SetRefreshTokenForAccount(token_service(), identity_manager(), account_id2);
std::vector<AccountInfo> accounts_after_update =
identity_manager()->GetAccountsWithRefreshTokens();
EXPECT_EQ(1u, accounts_after_update.size());
EXPECT_EQ(accounts_after_update[0].account_id, account_id2);
EXPECT_EQ(accounts_after_update[0].gaia, kTestGaiaId2);
EXPECT_EQ(accounts_after_update[0].email, kTestEmail2);
EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
// Add a refresh token for the primary account and check that it
// also shows up in GetAccountsWithRefreshTokens().
std::string primary_account_id =
signin_manager()->GetAuthenticatedAccountId();
SetRefreshTokenForPrimaryAccount(token_service(), identity_manager());
std::vector<AccountInfo> accounts_after_second_update =
identity_manager()->GetAccountsWithRefreshTokens();
EXPECT_EQ(2u, accounts_after_second_update.size());
for (AccountInfo account_info : accounts_after_second_update) {
if (account_info.account_id == account_id2) {
EXPECT_EQ(account_info.gaia, kTestGaiaId2);
EXPECT_EQ(account_info.email, kTestEmail2);
} else {
EXPECT_EQ(account_info.gaia, kTestGaiaId);
EXPECT_EQ(account_info.email, kTestEmail);
}
}
EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken());
// Remove the token for the primary account and check that account2 is still
// present.
RemoveRefreshTokenForPrimaryAccount(token_service(), identity_manager());
std::vector<AccountInfo> accounts_after_third_update =
identity_manager()->GetAccountsWithRefreshTokens();
EXPECT_EQ(1u, accounts_after_third_update.size());
EXPECT_EQ(accounts_after_update[0].account_id, account_id2);
EXPECT_EQ(accounts_after_update[0].gaia, kTestGaiaId2);
EXPECT_EQ(accounts_after_update[0].email, kTestEmail2);
EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
}
TEST_F(
IdentityManagerTest,
HasPrimaryAccountWithRefreshTokenInteractionBetweenPrimaryAndSecondaryAccounts) {
EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
// Add a refresh token for a secondary account and check that it doesn't
// impact the above state.
account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2);
std::string account_id2 =
account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2).account_id;
SetRefreshTokenForAccount(token_service(), identity_manager(), account_id2);
EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
// Add a refresh token for the primary account and check that it
// *does* impact the stsate of HasPrimaryAccountWithRefreshToken().
std::string primary_account_id =
signin_manager()->GetAuthenticatedAccountId();
SetRefreshTokenForPrimaryAccount(token_service(), identity_manager());
EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken());
// Remove the token for the secondary account and check that this doesn't flip
// the state.
RemoveRefreshTokenForAccount(token_service(), identity_manager(),
account_id2);
EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken());
// Remove the token for the primary account and check that this flips the
// state.
RemoveRefreshTokenForPrimaryAccount(token_service(), identity_manager());
EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
}
TEST_F(
IdentityManagerTest,
HasAccountWithRefreshTokenInteractionBetweenPrimaryAndSecondaryAccounts) {
AccountInfo primary_account_info =
identity_manager()->GetPrimaryAccountInfo();
std::string primary_account_id = primary_account_info.account_id;
account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2);
AccountInfo account_info2 =
account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2);
std::string account_id2 = account_info2.account_id;
EXPECT_FALSE(identity_manager()->HasAccountWithRefreshToken(
primary_account_info.account_id));
EXPECT_FALSE(
identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
// Add a refresh token for account_info2 and check that this is reflected by
// HasAccountWithRefreshToken(.account_id).
SetRefreshTokenForAccount(token_service(), identity_manager(), account_id2);
EXPECT_FALSE(identity_manager()->HasAccountWithRefreshToken(
primary_account_info.account_id));
EXPECT_TRUE(
identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
// Go through the same process for the primary account.
SetRefreshTokenForPrimaryAccount(token_service(), identity_manager());
EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(
primary_account_info.account_id));
EXPECT_TRUE(
identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
// Remove the token for account2.
RemoveRefreshTokenForAccount(token_service(), identity_manager(),
account_id2);
EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(
primary_account_info.account_id));
EXPECT_FALSE(
identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
}
TEST_F(IdentityManagerTest, RemoveAccessTokenFromCache) {
std::set<std::string> scopes{"scope"};
std::string access_token = "access_token";
signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
std::string account_id = signin_manager()->GetAuthenticatedAccountId();
token_service()->UpdateCredentials(account_id, "refresh_token");
base::RunLoop run_loop;
token_service()->set_on_access_token_invalidated_info(
account_id, scopes, access_token, run_loop.QuitClosure());
identity_manager()->RemoveAccessTokenFromCache(account_id, scopes,
access_token);
run_loop.Run();
}
TEST_F(IdentityManagerTest, CreateAccessTokenFetcher) {
std::set<std::string> scopes{"scope"};
AccessTokenFetcher::TokenCallback callback = base::BindOnce(
[](GoogleServiceAuthError error, AccessTokenInfo access_token_info) {});
std::unique_ptr<AccessTokenFetcher> token_fetcher =
identity_manager()->CreateAccessTokenFetcherForAccount(
identity_manager()->GetPrimaryAccountInfo().account_id,
"dummy_consumer", scopes, std::move(callback));
EXPECT_TRUE(token_fetcher);
}
TEST_F(IdentityManagerTest, ObserveAccessTokenFetch) {
base::RunLoop run_loop;
identity_manager_diagnostics_observer()
->set_on_access_token_requested_callback(run_loop.QuitClosure());
signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
std::string account_id = signin_manager()->GetAuthenticatedAccountId();
token_service()->UpdateCredentials(account_id, "refresh_token");
std::set<std::string> scopes{"scope"};
AccessTokenFetcher::TokenCallback callback = base::BindOnce(
[](GoogleServiceAuthError error, AccessTokenInfo access_token_info) {});
std::unique_ptr<AccessTokenFetcher> token_fetcher =
identity_manager()->CreateAccessTokenFetcherForAccount(
identity_manager()->GetPrimaryAccountInfo().account_id,
"dummy_consumer", scopes, std::move(callback));
run_loop.Run();
EXPECT_EQ(
account_id,
identity_manager_diagnostics_observer()->token_requestor_account_id());
EXPECT_EQ(
"dummy_consumer",
identity_manager_diagnostics_observer()->token_requestor_consumer_id());
EXPECT_EQ(scopes,
identity_manager_diagnostics_observer()->token_requestor_scopes());
}
#if !defined(OS_CHROMEOS)
TEST_F(IdentityManagerTest,
IdentityManagerGetsSignInEventBeforeSigninManagerObserver) {
signin_manager()->ForceSignOut();
base::RunLoop run_loop;
TestSigninManagerObserver signin_manager_observer(signin_manager());
signin_manager_observer.set_on_google_signin_succeeded_callback(
run_loop.QuitClosure());
// NOTE: For this test to be meaningful, TestSigninManagerObserver
// needs to be created before the IdentityManager instance that it's
// interacting with. Otherwise, even an implementation where they're
// both SigninManager::Observers would work as IdentityManager would
// get notified first during the observer callbacks.
RecreateIdentityManager();
signin_manager_observer.set_identity_manager(identity_manager());
signin_manager()->SignIn(kTestGaiaId, kTestEmail, "password");
run_loop.Run();
AccountInfo primary_account_from_signin_callback =
signin_manager_observer.primary_account_from_signin_callback();
EXPECT_EQ(kTestGaiaId, primary_account_from_signin_callback.gaia);
EXPECT_EQ(kTestEmail, primary_account_from_signin_callback.email);
}
TEST_F(IdentityManagerTest,
IdentityManagerGetsSignOutEventBeforeSigninManagerObserver) {
base::RunLoop run_loop;
TestSigninManagerObserver signin_manager_observer(signin_manager());
signin_manager_observer.set_on_google_signed_out_callback(
run_loop.QuitClosure());
// NOTE: For this test to be meaningful, TestSigninManagerObserver
// needs to be created before the IdentityManager instance that it's
// interacting with. Otherwise, even an implementation where they're
// both SigninManager::Observers would work as IdentityManager would
// get notified first during the observer callbacks.
RecreateIdentityManager();
signin_manager_observer.set_identity_manager(identity_manager());
signin_manager()->ForceSignOut();
run_loop.Run();
AccountInfo primary_account_from_signout_callback =
signin_manager_observer.primary_account_from_signout_callback();
EXPECT_EQ(std::string(), primary_account_from_signout_callback.gaia);
EXPECT_EQ(std::string(), primary_account_from_signout_callback.email);
}
#endif
#if defined(OS_CHROMEOS)
// On ChromeOS, AccountTrackerService first receives the normalized email
// address from GAIA and then later has it updated with the user's
// originally-specified version of their email address (at the time of that
// address' creation). This latter will differ if the user's originally-
// specified address was not in normalized form (e.g., if it contained
// periods). This test simulates such a flow in order to verify that
// IdentityManager correctly reflects the updated version. See crbug.com/842041
// and crbug.com/842670 for further details.
TEST_F(IdentityManagerTest, IdentityManagerReflectsUpdatedEmailAddress) {
AccountInfo primary_account_info =
identity_manager()->GetPrimaryAccountInfo();
EXPECT_EQ(kTestGaiaId, primary_account_info.gaia);
EXPECT_EQ(kTestEmail, primary_account_info.email);
// Simulate the flow wherein the user's email address was updated
// to the originally-created non-normalized version.
base::DictionaryValue user_info;
user_info.SetString("id", kTestGaiaId);
user_info.SetString("email", kTestEmailWithPeriod);
account_tracker()->SetAccountStateFromUserInfo(
primary_account_info.account_id, &user_info);
// Verify that IdentityManager reflects the update.
primary_account_info = identity_manager()->GetPrimaryAccountInfo();
EXPECT_EQ(kTestGaiaId, primary_account_info.gaia);
EXPECT_EQ(kTestEmailWithPeriod, primary_account_info.email);
}
#endif
TEST_F(IdentityManagerTest,
CallbackSentOnPrimaryAccountRefreshTokenUpdateWithValidToken) {
std::string account_id = signin_manager()->GetAuthenticatedAccountId();
SetRefreshTokenForPrimaryAccount(token_service(), identity_manager());
AccountInfo account_info =
identity_manager_observer()
->account_from_refresh_token_updated_callback();
EXPECT_EQ(kTestGaiaId, account_info.gaia);
EXPECT_EQ(kTestEmail, account_info.email);
EXPECT_TRUE(identity_manager_observer()
->validity_from_refresh_token_updated_callback());
}
TEST_F(IdentityManagerTest,
CallbackSentOnPrimaryAccountRefreshTokenUpdateWithInvalidToken) {
std::string account_id = signin_manager()->GetAuthenticatedAccountId();
SetInvalidRefreshTokenForPrimaryAccount(token_service(), identity_manager());
AccountInfo account_info =
identity_manager_observer()
->account_from_refresh_token_updated_callback();
EXPECT_EQ(kTestGaiaId, account_info.gaia);
EXPECT_EQ(kTestEmail, account_info.email);
EXPECT_FALSE(identity_manager_observer()
->validity_from_refresh_token_updated_callback());
}
TEST_F(IdentityManagerTest, CallbackSentOnPrimaryAccountRefreshTokenRemoval) {
std::string account_id = signin_manager()->GetAuthenticatedAccountId();
SetRefreshTokenForPrimaryAccount(token_service(), identity_manager());
RemoveRefreshTokenForPrimaryAccount(token_service(), identity_manager());
AccountInfo account_info =
identity_manager_observer()
->account_from_refresh_token_removed_callback();
EXPECT_EQ(kTestGaiaId, account_info.gaia);
EXPECT_EQ(kTestEmail, account_info.email);
}
TEST_F(IdentityManagerTest,
CallbackSentOnSecondaryAccountRefreshTokenUpdateWithValidToken) {
AccountInfo expected_account_info = MakeAccountAvailable(
account_tracker(), token_service(), identity_manager(), kTestEmail2);
EXPECT_EQ(kTestEmail2, expected_account_info.email);
AccountInfo account_info =
identity_manager_observer()
->account_from_refresh_token_updated_callback();
EXPECT_EQ(expected_account_info.account_id, account_info.account_id);
EXPECT_EQ(expected_account_info.gaia, account_info.gaia);
EXPECT_EQ(expected_account_info.email, account_info.email);
EXPECT_TRUE(identity_manager_observer()
->validity_from_refresh_token_updated_callback());
}
TEST_F(IdentityManagerTest,
CallbackSentOnSecondaryAccountRefreshTokenUpdateWithInvalidToken) {
AccountInfo expected_account_info = MakeAccountAvailable(
account_tracker(), token_service(), identity_manager(), kTestEmail2);
EXPECT_EQ(kTestEmail2, expected_account_info.email);
SetInvalidRefreshTokenForAccount(token_service(), identity_manager(),
expected_account_info.account_id);
AccountInfo account_info =
identity_manager_observer()
->account_from_refresh_token_updated_callback();
EXPECT_EQ(expected_account_info.account_id, account_info.account_id);
EXPECT_EQ(expected_account_info.gaia, account_info.gaia);
EXPECT_EQ(expected_account_info.email, account_info.email);
EXPECT_FALSE(identity_manager_observer()
->validity_from_refresh_token_updated_callback());
}
TEST_F(IdentityManagerTest, CallbackSentOnSecondaryAccountRefreshTokenRemoval) {
AccountInfo expected_account_info = MakeAccountAvailable(
account_tracker(), token_service(), identity_manager(), kTestEmail2);
EXPECT_EQ(kTestEmail2, expected_account_info.email);
RemoveRefreshTokenForAccount(token_service(), identity_manager(),
expected_account_info.account_id);
AccountInfo account_info =
identity_manager_observer()
->account_from_refresh_token_removed_callback();
EXPECT_EQ(expected_account_info.account_id, account_info.account_id);
EXPECT_EQ(expected_account_info.gaia, account_info.gaia);
EXPECT_EQ(expected_account_info.email, account_info.email);
}
#if !defined(OS_CHROMEOS)
TEST_F(
IdentityManagerTest,
CallbackSentOnSecondaryAccountRefreshTokenUpdateWithValidTokenWhenNoPrimaryAccount) {
base::RunLoop run_loop;
identity_manager_observer()->set_on_primary_account_cleared_callback(
run_loop.QuitClosure());
signin_manager()->ForceSignOut();
run_loop.Run();
AccountInfo expected_account_info = MakeAccountAvailable(
account_tracker(), token_service(), identity_manager(), kTestEmail2);
EXPECT_EQ(kTestEmail2, expected_account_info.email);
AccountInfo account_info =
identity_manager_observer()
->account_from_refresh_token_updated_callback();
EXPECT_EQ(expected_account_info.account_id, account_info.account_id);
EXPECT_EQ(expected_account_info.gaia, account_info.gaia);
EXPECT_EQ(expected_account_info.email, account_info.email);
EXPECT_TRUE(identity_manager_observer()
->validity_from_refresh_token_updated_callback());
}
TEST_F(
IdentityManagerTest,
CallbackSentOnSecondaryAccountRefreshTokenUpdateWithInvalidTokenWhenNoPrimaryAccount) {
base::RunLoop run_loop;
identity_manager_observer()->set_on_primary_account_cleared_callback(
run_loop.QuitClosure());
signin_manager()->ForceSignOut();
run_loop.Run();
AccountInfo expected_account_info = MakeAccountAvailable(
account_tracker(), token_service(), identity_manager(), kTestEmail2);
EXPECT_EQ(kTestEmail2, expected_account_info.email);
SetInvalidRefreshTokenForAccount(token_service(), identity_manager(),
expected_account_info.account_id);
AccountInfo account_info =
identity_manager_observer()
->account_from_refresh_token_updated_callback();
EXPECT_EQ(expected_account_info.account_id, account_info.account_id);
EXPECT_EQ(expected_account_info.gaia, account_info.gaia);
EXPECT_EQ(expected_account_info.email, account_info.email);
EXPECT_FALSE(identity_manager_observer()
->validity_from_refresh_token_updated_callback());
}
TEST_F(IdentityManagerTest,
CallbackSentOnSecondaryAccountRefreshTokenRemovalWhenNoPrimaryAccount) {
base::RunLoop run_loop;
identity_manager_observer()->set_on_primary_account_cleared_callback(
run_loop.QuitClosure());
signin_manager()->ForceSignOut();
run_loop.Run();
AccountInfo expected_account_info = MakeAccountAvailable(
account_tracker(), token_service(), identity_manager(), kTestEmail2);
EXPECT_EQ(kTestEmail2, expected_account_info.email);
RemoveRefreshTokenForAccount(token_service(), identity_manager(),
expected_account_info.account_id);
AccountInfo account_info =
identity_manager_observer()
->account_from_refresh_token_removed_callback();
EXPECT_EQ(expected_account_info.account_id, account_info.account_id);
EXPECT_EQ(expected_account_info.gaia, account_info.gaia);
EXPECT_EQ(expected_account_info.email, account_info.email);
}
#endif
TEST_F(IdentityManagerTest,
CallbackNotSentOnRefreshTokenRemovalOfUnknownAccount) {
base::RunLoop run_loop;
identity_manager_observer()->set_on_refresh_token_removed_callback(
base::BindOnce([] { EXPECT_TRUE(false); }));
token_service()->RevokeCredentials("dummy_account");
run_loop.RunUntilIdle();
}
TEST_F(IdentityManagerTest,
IdentityManagerGetsTokenUpdateEventBeforeTokenServiceObserver) {
std::string account_id = signin_manager()->GetAuthenticatedAccountId();
base::RunLoop run_loop;
TestTokenServiceObserver token_service_observer(token_service());
token_service_observer.set_on_refresh_token_available_callback(
run_loop.QuitClosure());
// NOTE: For this test to be meaningful, TestTokenServiceObserver
// needs to be created before the IdentityManager instance that it's
// interacting with. Otherwise, even an implementation where they're
// both TokenService::Observers would work as IdentityManager would
// get notified first during the observer callbacks.
RecreateIdentityManager();
token_service_observer.set_identity_manager(identity_manager());
// When the observer receives the callback directly from the token service,
// IdentityManager should have already received the event and forwarded it on
// to its own observers. This is checked internally by
// TestTokenServiceObserver.
token_service()->UpdateCredentials(account_id, "refresh_token");
run_loop.Run();
}
TEST_F(IdentityManagerTest,
IdentityManagerGetsTokenRemovalEventBeforeTokenServiceObserver) {
std::string account_id = signin_manager()->GetAuthenticatedAccountId();
base::RunLoop run_loop;
TestTokenServiceObserver token_service_observer(token_service());
token_service_observer.set_on_refresh_token_available_callback(
run_loop.QuitClosure());
// NOTE: For this test to be meaningful, TestTokenServiceObserver
// needs to be created before the IdentityManager instance that it's
// interacting with. Otherwise, even an implementation where they're
// both TokenService::Observers would work as IdentityManager would
// get notified first during the observer callbacks.
RecreateIdentityManager();
token_service_observer.set_identity_manager(identity_manager());
token_service()->UpdateCredentials(account_id, "refresh_token");
run_loop.Run();
// When the observer receives the callback directly from the token service,
// IdentityManager should have already received the event and forwarded it on
// to its own observers. This is checked internally by
// TestTokenServiceObserver.
base::RunLoop run_loop2;
token_service_observer.set_on_refresh_token_revoked_callback(
run_loop2.QuitClosure());
token_service()->RevokeCredentials(account_id);
run_loop2.Run();
}
TEST_F(IdentityManagerTest,
CallbackSentOnUpdateToAccountsInCookieWithNoAccounts) {
base::RunLoop run_loop;
identity_manager_observer()->set_on_accounts_in_cookie_updated_callback(
run_loop.QuitClosure());
gaia_cookie_manager_service()->SetListAccountsResponseNoAccounts();
gaia_cookie_manager_service()->TriggerListAccounts(
"identity_manager_unittest");
run_loop.Run();
EXPECT_TRUE(identity_manager_observer()
->accounts_from_cookie_change_callback()
.empty());
}
TEST_F(IdentityManagerTest,
CallbackSentOnUpdateToAccountsInCookieWithOneAccount) {
base::RunLoop run_loop;
identity_manager_observer()->set_on_accounts_in_cookie_updated_callback(
run_loop.QuitClosure());
gaia_cookie_manager_service()->SetListAccountsResponseOneAccount(kTestEmail,
kTestGaiaId);
gaia_cookie_manager_service()->TriggerListAccounts(
"identity_manager_unittest");
run_loop.Run();
EXPECT_EQ(1u, identity_manager_observer()
->accounts_from_cookie_change_callback()
.size());
AccountInfo account_info =
identity_manager_observer()->accounts_from_cookie_change_callback()[0];
EXPECT_EQ(account_tracker()->PickAccountIdForAccount(kTestGaiaId, kTestEmail),
account_info.account_id);
EXPECT_EQ(kTestGaiaId, account_info.gaia);
EXPECT_EQ(kTestEmail, account_info.email);
}
TEST_F(IdentityManagerTest,
CallbackSentOnUpdateToAccountsInCookieWithTwoAccounts) {
base::RunLoop run_loop;
identity_manager_observer()->set_on_accounts_in_cookie_updated_callback(
run_loop.QuitClosure());
gaia_cookie_manager_service()->SetListAccountsResponseTwoAccounts(
kTestEmail, kTestGaiaId, kTestEmail2, kTestGaiaId2);
gaia_cookie_manager_service()->TriggerListAccounts(
"identity_manager_unittest");
run_loop.Run();
EXPECT_EQ(2u, identity_manager_observer()
->accounts_from_cookie_change_callback()
.size());
// Verify not only that both accounts are present but that they are listed in
// the expected order as well.
AccountInfo account_info1 =
identity_manager_observer()->accounts_from_cookie_change_callback()[0];
EXPECT_EQ(account_tracker()->PickAccountIdForAccount(kTestGaiaId, kTestEmail),
account_info1.account_id);
EXPECT_EQ(kTestGaiaId, account_info1.gaia);
EXPECT_EQ(kTestEmail, account_info1.email);
AccountInfo account_info2 =
identity_manager_observer()->accounts_from_cookie_change_callback()[1];
EXPECT_EQ(
account_tracker()->PickAccountIdForAccount(kTestGaiaId2, kTestEmail2),
account_info2.account_id);
EXPECT_EQ(kTestGaiaId2, account_info2.gaia);
EXPECT_EQ(kTestEmail2, account_info2.email);
}
TEST_F(IdentityManagerTest, GetAccountsInCookieJarWithNoAccounts) {
base::RunLoop run_loop;
identity_manager_observer()->set_on_accounts_in_cookie_updated_callback(
run_loop.QuitClosure());
gaia_cookie_manager_service()->SetListAccountsResponseNoAccounts();
// Do an initial call to GetAccountsInCookieJar(). This call should return no
// accounts but should also trigger an internal update and eventual
// notification that the accounts in the cookie jar have been updated.
std::vector<AccountInfo> accounts_in_cookie_jar =
identity_manager()->GetAccountsInCookieJar("identity_manager_unittest");
EXPECT_TRUE(accounts_in_cookie_jar.empty());
run_loop.Run();
// The state of the accounts in IdentityManager should now reflect the
// internal update.
accounts_in_cookie_jar =
identity_manager()->GetAccountsInCookieJar("identity_manager_unittest");
EXPECT_TRUE(accounts_in_cookie_jar.empty());
}
TEST_F(IdentityManagerTest, GetAccountsInCookieJarWithOneAccount) {
base::RunLoop run_loop;
identity_manager_observer()->set_on_accounts_in_cookie_updated_callback(
run_loop.QuitClosure());
gaia_cookie_manager_service()->SetListAccountsResponseOneAccount(kTestEmail,
kTestGaiaId);
// Do an initial call to GetAccountsInCookieJar(). This call should return no
// accounts but should also trigger an internal update and eventual
// notification that the accounts in the cookie jar have been updated.
std::vector<AccountInfo> accounts_in_cookie_jar =
identity_manager()->GetAccountsInCookieJar("identity_manager_unittest");
EXPECT_TRUE(accounts_in_cookie_jar.empty());
run_loop.Run();
// The state of the accounts in IdentityManager should now reflect the
// internal update.
accounts_in_cookie_jar =
identity_manager()->GetAccountsInCookieJar("identity_manager_unittest");
EXPECT_EQ(1u, accounts_in_cookie_jar.size());
AccountInfo account_info = accounts_in_cookie_jar[0];
EXPECT_EQ(account_tracker()->PickAccountIdForAccount(kTestGaiaId, kTestEmail),
account_info.account_id);
EXPECT_EQ(kTestGaiaId, account_info.gaia);
EXPECT_EQ(kTestEmail, account_info.email);
}
TEST_F(IdentityManagerTest, GetAccountsInCookieJarWithTwoAccounts) {
base::RunLoop run_loop;
identity_manager_observer()->set_on_accounts_in_cookie_updated_callback(
run_loop.QuitClosure());
gaia_cookie_manager_service()->SetListAccountsResponseTwoAccounts(
kTestEmail, kTestGaiaId, kTestEmail2, kTestGaiaId2);
// Do an initial call to GetAccountsInCookieJar(). This call should return no
// accounts but should also trigger an internal update and eventual
// notification that the accounts in the cookie jar have been updated.
std::vector<AccountInfo> accounts_in_cookie_jar =
identity_manager()->GetAccountsInCookieJar("identity_manager_unittest");
EXPECT_TRUE(accounts_in_cookie_jar.empty());
run_loop.Run();
// The state of the accounts in IdentityManager should now reflect the
// internal update.
accounts_in_cookie_jar =
identity_manager()->GetAccountsInCookieJar("identity_manager_unittest");
EXPECT_EQ(2u, accounts_in_cookie_jar.size());
// Verify not only that both accounts are present but that they are listed in
// the expected order as well.
AccountInfo account_info1 = accounts_in_cookie_jar[0];
EXPECT_EQ(account_tracker()->PickAccountIdForAccount(kTestGaiaId, kTestEmail),
account_info1.account_id);
EXPECT_EQ(kTestGaiaId, account_info1.gaia);
EXPECT_EQ(kTestEmail, account_info1.email);
AccountInfo account_info2 = accounts_in_cookie_jar[1];
EXPECT_EQ(
account_tracker()->PickAccountIdForAccount(kTestGaiaId2, kTestEmail2),
account_info2.account_id);
EXPECT_EQ(kTestGaiaId2, account_info2.gaia);
EXPECT_EQ(kTestEmail2, account_info2.email);
}
} // namespace identity