Commit 386e6e51 authored by Mihai Sardarescu's avatar Mihai Sardarescu Committed by Commit Bot

Avoid useless fetches of user ID from GCM account tracker.

For every account available in the account tracker service, both the
Gaia ID and the email are available. The GCM AccountTracker was fetching
again the gaia ID from the server on every start-up and every time a new
account was added to the profile. This CL removes this useless fetch
and changed the GCM AccountTracker to reuse the information already
available in the IdentityManager.

Additional clean-up to completely remove the GCM AccountTracker would
also be good, but I do not know this code well enough to do this cleanup.

Fixed: 1028522

Change-Id: I77790a3203a94ea8c7baf19ca0eb2449b096b630
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1944492Reviewed-by: default avatarColin Blundell <blundell@chromium.org>
Commit-Queue: Mihai Sardarescu <msarda@chromium.org>
Cr-Commit-Position: refs/heads/master@{#720515}
parent d7e0ca7c
...@@ -4,22 +4,15 @@ ...@@ -4,22 +4,15 @@
#include "components/gcm_driver/account_tracker.h" #include "components/gcm_driver/account_tracker.h"
#include "base/bind.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#include "components/signin/public/identity_manager/access_token_info.h" #include "components/signin/public/identity_manager/access_token_info.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace gcm { namespace gcm {
AccountTracker::AccountTracker( AccountTracker::AccountTracker(signin::IdentityManager* identity_manager)
signin::IdentityManager* identity_manager, : identity_manager_(identity_manager), shutdown_called_(false) {
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
: identity_manager_(identity_manager),
url_loader_factory_(std::move(url_loader_factory)),
shutdown_called_(false) {
identity_manager_->AddObserver(this); identity_manager_->AddObserver(this);
} }
...@@ -29,14 +22,9 @@ AccountTracker::~AccountTracker() { ...@@ -29,14 +22,9 @@ AccountTracker::~AccountTracker() {
void AccountTracker::Shutdown() { void AccountTracker::Shutdown() {
shutdown_called_ = true; shutdown_called_ = true;
user_info_requests_.clear();
identity_manager_->RemoveObserver(this); identity_manager_->RemoveObserver(this);
} }
bool AccountTracker::IsAllUserInfoFetched() const {
return user_info_requests_.empty();
}
void AccountTracker::AddObserver(Observer* observer) { void AccountTracker::AddObserver(Observer* observer) {
observer_list_.AddObserver(observer); observer_list_.AddObserver(observer);
} }
...@@ -45,23 +33,25 @@ void AccountTracker::RemoveObserver(Observer* observer) { ...@@ -45,23 +33,25 @@ void AccountTracker::RemoveObserver(Observer* observer) {
observer_list_.RemoveObserver(observer); observer_list_.RemoveObserver(observer);
} }
std::vector<AccountIds> AccountTracker::GetAccounts() const { std::vector<CoreAccountInfo> AccountTracker::GetAccounts() const {
const CoreAccountId active_account_id = const CoreAccountId active_account_id =
identity_manager_->GetPrimaryAccountId(); identity_manager_->GetPrimaryAccountId();
std::vector<AccountIds> accounts; std::vector<CoreAccountInfo> accounts;
for (auto it = accounts_.begin(); it != accounts_.end(); ++it) { for (auto it = accounts_.begin(); it != accounts_.end(); ++it) {
const AccountState& state = it->second; const AccountState& state = it->second;
bool is_visible = state.is_signed_in && !state.ids.gaia.empty(); DCHECK(!state.account.account_id.empty());
DCHECK(!state.account.gaia.empty());
DCHECK(!state.account.email.empty());
bool is_visible = state.is_signed_in;
if (it->first == active_account_id) { if (it->first == active_account_id) {
if (is_visible) if (is_visible)
accounts.insert(accounts.begin(), state.ids); accounts.insert(accounts.begin(), state.account);
else else
return std::vector<AccountIds>(); return std::vector<CoreAccountInfo>();
} else if (is_visible) { } else if (is_visible) {
accounts.push_back(state.ids); accounts.push_back(state.account);
} }
} }
return accounts; return accounts;
...@@ -77,6 +67,7 @@ void AccountTracker::OnRefreshTokenUpdatedForAccount( ...@@ -77,6 +67,7 @@ void AccountTracker::OnRefreshTokenUpdatedForAccount(
return; return;
DVLOG(1) << "AVAILABLE " << account_info.account_id; DVLOG(1) << "AVAILABLE " << account_info.account_id;
StartTrackingAccount(account_info);
UpdateSignInState(account_info.account_id, /*is_signed_in=*/true); UpdateSignInState(account_info.account_id, /*is_signed_in=*/true);
} }
...@@ -99,6 +90,7 @@ void AccountTracker::OnPrimaryAccountSet( ...@@ -99,6 +90,7 @@ void AccountTracker::OnPrimaryAccountSet(
DVLOG(1) << "LOGIN " << accounts.size() << " accounts available."; DVLOG(1) << "LOGIN " << accounts.size() << " accounts available.";
for (const CoreAccountInfo& account_info : accounts) { for (const CoreAccountInfo& account_info : accounts) {
StartTrackingAccount(account_info);
UpdateSignInState(account_info.account_id, /*is_signed_in=*/true); UpdateSignInState(account_info.account_id, /*is_signed_in=*/true);
} }
} }
...@@ -110,50 +102,38 @@ void AccountTracker::OnPrimaryAccountCleared( ...@@ -110,50 +102,38 @@ void AccountTracker::OnPrimaryAccountCleared(
StopTrackingAllAccounts(); StopTrackingAllAccounts();
} }
void AccountTracker::NotifySignInChanged(const AccountState& account) { void AccountTracker::UpdateSignInState(const CoreAccountId& account_id,
DCHECK(!account.ids.gaia.empty());
for (auto& observer : observer_list_)
observer.OnAccountSignInChanged(account.ids, account.is_signed_in);
}
void AccountTracker::UpdateSignInState(const CoreAccountId& account_key,
bool is_signed_in) { bool is_signed_in) {
StartTrackingAccount(account_key); if (!is_signed_in && !base::Contains(accounts_, account_id))
AccountState& account = accounts_[account_key]; return;
bool needs_gaia_id = account.ids.gaia.empty();
bool was_signed_in = account.is_signed_in;
account.is_signed_in = is_signed_in;
if (needs_gaia_id && is_signed_in) DCHECK(base::Contains(accounts_, account_id));
StartFetchingUserInfo(account_key); AccountState& account = accounts_[account_id];
if (account.is_signed_in == is_signed_in)
return;
if (!needs_gaia_id && (was_signed_in != is_signed_in)) account.is_signed_in = is_signed_in;
NotifySignInChanged(account); for (auto& observer : observer_list_)
observer.OnAccountSignInChanged(account.account, account.is_signed_in);
} }
void AccountTracker::StartTrackingAccount(const CoreAccountId& account_key) { void AccountTracker::StartTrackingAccount(const CoreAccountInfo& account) {
if (!base::Contains(accounts_, account_key)) { if (base::Contains(accounts_, account.account_id))
DVLOG(1) << "StartTracking " << account_key; return;
DVLOG(1) << "StartTracking " << account.account_id;
AccountState account_state; AccountState account_state;
account_state.ids.account_key = account_key; account_state.account = account;
account_state.ids.email = account_key.ToString();
account_state.is_signed_in = false; account_state.is_signed_in = false;
accounts_.insert(std::make_pair(account_key, account_state)); accounts_.insert(std::make_pair(account.account_id, account_state));
}
} }
void AccountTracker::StopTrackingAccount(const CoreAccountId account_key) { void AccountTracker::StopTrackingAccount(const CoreAccountId account_id) {
DVLOG(1) << "StopTracking " << account_key; DVLOG(1) << "StopTracking " << account_id;
if (base::Contains(accounts_, account_key)) { if (base::Contains(accounts_, account_id)) {
AccountState& account = accounts_[account_key]; UpdateSignInState(account_id, /*is_signed_in=*/false);
if (!account.ids.gaia.empty()) { accounts_.erase(account_id);
UpdateSignInState(account_key, /*is_signed_in=*/false);
}
accounts_.erase(account_key);
} }
if (base::Contains(user_info_requests_, account_key))
DeleteFetcher(user_info_requests_[account_key].get());
} }
void AccountTracker::StopTrackingAllAccounts() { void AccountTracker::StopTrackingAllAccounts() {
...@@ -161,117 +141,4 @@ void AccountTracker::StopTrackingAllAccounts() { ...@@ -161,117 +141,4 @@ void AccountTracker::StopTrackingAllAccounts() {
StopTrackingAccount(accounts_.begin()->first); StopTrackingAccount(accounts_.begin()->first);
} }
void AccountTracker::StartFetchingUserInfo(const CoreAccountId& account_key) {
if (base::Contains(user_info_requests_, account_key)) {
DeleteFetcher(user_info_requests_[account_key].get());
}
DVLOG(1) << "StartFetching " << account_key;
AccountIdFetcher* fetcher = new AccountIdFetcher(
identity_manager_, url_loader_factory_, this, account_key);
user_info_requests_[account_key] = base::WrapUnique(fetcher);
fetcher->Start();
}
void AccountTracker::OnUserInfoFetchSuccess(AccountIdFetcher* fetcher,
const std::string& gaia_id) {
const CoreAccountId& account_key = fetcher->account_key();
DCHECK(base::Contains(accounts_, account_key));
AccountState& account = accounts_[account_key];
account.ids.gaia = gaia_id;
if (account.is_signed_in)
NotifySignInChanged(account);
DeleteFetcher(fetcher);
}
void AccountTracker::OnUserInfoFetchFailure(AccountIdFetcher* fetcher) {
LOG(WARNING) << "Failed to get UserInfo for " << fetcher->account_key();
CoreAccountId key = fetcher->account_key();
DeleteFetcher(fetcher);
StopTrackingAccount(key);
}
void AccountTracker::DeleteFetcher(AccountIdFetcher* fetcher) {
DVLOG(1) << "DeleteFetcher " << fetcher->account_key();
const CoreAccountId& account_key = fetcher->account_key();
DCHECK(base::Contains(user_info_requests_, account_key));
DCHECK_EQ(fetcher, user_info_requests_[account_key].get());
user_info_requests_.erase(account_key);
}
AccountIdFetcher::AccountIdFetcher(
signin::IdentityManager* identity_manager,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
AccountTracker* tracker,
const CoreAccountId& account_key)
: identity_manager_(identity_manager),
url_loader_factory_(std::move(url_loader_factory)),
tracker_(tracker),
account_key_(account_key) {
TRACE_EVENT_ASYNC_BEGIN1("identity", "AccountIdFetcher", this, "account_key",
account_key.ToString());
}
AccountIdFetcher::~AccountIdFetcher() {
TRACE_EVENT_ASYNC_END0("identity", "AccountIdFetcher", this);
}
void AccountIdFetcher::Start() {
identity::ScopeSet scopes;
scopes.insert("https://www.googleapis.com/auth/userinfo.profile");
access_token_fetcher_ = identity_manager_->CreateAccessTokenFetcherForAccount(
account_key_, "gaia_account_tracker", scopes,
base::BindOnce(&AccountIdFetcher::AccessTokenFetched,
base::Unretained(this)),
signin::AccessTokenFetcher::Mode::kImmediate);
}
void AccountIdFetcher::AccessTokenFetched(
GoogleServiceAuthError error,
signin::AccessTokenInfo access_token_info) {
access_token_fetcher_.reset();
if (error != GoogleServiceAuthError::AuthErrorNone()) {
TRACE_EVENT_ASYNC_STEP_PAST1("identity", "AccountIdFetcher", this,
"AccessTokenFetched",
"google_service_auth_error", error.ToString());
LOG(ERROR) << "AccessTokenFetched error: " << error.ToString();
tracker_->OnUserInfoFetchFailure(this);
return;
}
TRACE_EVENT_ASYNC_STEP_PAST0("identity", "AccountIdFetcher", this,
"AccessTokenFetched");
gaia_oauth_client_.reset(new gaia::GaiaOAuthClient(url_loader_factory_));
const int kMaxGetUserIdRetries = 3;
gaia_oauth_client_->GetUserId(access_token_info.token, kMaxGetUserIdRetries,
this);
}
void AccountIdFetcher::OnGetUserIdResponse(const std::string& gaia_id) {
TRACE_EVENT_ASYNC_STEP_PAST1("identity", "AccountIdFetcher", this,
"OnGetUserIdResponse", "gaia_id", gaia_id);
tracker_->OnUserInfoFetchSuccess(this, gaia_id);
}
void AccountIdFetcher::OnOAuthError() {
TRACE_EVENT_ASYNC_STEP_PAST0("identity", "AccountIdFetcher", this,
"OnOAuthError");
LOG(ERROR) << "OnOAuthError";
tracker_->OnUserInfoFetchFailure(this);
}
void AccountIdFetcher::OnNetworkError(int response_code) {
TRACE_EVENT_ASYNC_STEP_PAST1("identity", "AccountIdFetcher", this,
"OnNetworkError", "response_code",
response_code);
LOG(ERROR) << "OnNetworkError " << response_code;
tracker_->OnUserInfoFetchFailure(this);
}
} // namespace gcm } // namespace gcm
...@@ -10,52 +10,22 @@ ...@@ -10,52 +10,22 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "base/memory/scoped_refptr.h"
#include "base/observer_list.h" #include "base/observer_list.h"
#include "components/signin/public/identity_manager/access_token_fetcher.h"
#include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/identity_manager.h"
#include "google_apis/gaia/core_account_id.h" #include "google_apis/gaia/core_account_id.h"
#include "google_apis/gaia/gaia_oauth_client.h"
class GoogleServiceAuthError;
namespace signin {
struct AccessTokenInfo;
}
namespace network {
class SharedURLLoaderFactory;
}
namespace gcm { namespace gcm {
struct AccountIds {
CoreAccountId account_key; // The account ID used by IdentityManager.
std::string gaia;
std::string email;
};
class AccountIdFetcher;
// The AccountTracker keeps track of what accounts exist on the // The AccountTracker keeps track of what accounts exist on the
// profile and the state of their credentials. The tracker fetches the // profile and the state of their credentials.
// gaia ID of each account it knows about.
//
// The AccountTracker maintains these invariants:
// 1. Events are only fired after the gaia ID has been fetched.
// 2. Add/Remove and SignIn/SignOut pairs are always generated in order.
// 3. SignIn follows Add, and there will be a SignOut between SignIn & Remove.
// 4. If there is no primary account, there are no other accounts.
class AccountTracker : public signin::IdentityManager::Observer { class AccountTracker : public signin::IdentityManager::Observer {
public: public:
AccountTracker( explicit AccountTracker(signin::IdentityManager* identity_manager);
signin::IdentityManager* identity_manager,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
~AccountTracker() override; ~AccountTracker() override;
class Observer { class Observer {
public: public:
virtual void OnAccountSignInChanged(const AccountIds& ids, virtual void OnAccountSignInChanged(const CoreAccountInfo& account,
bool is_signed_in) = 0; bool is_signed_in) = 0;
}; };
...@@ -64,20 +34,14 @@ class AccountTracker : public signin::IdentityManager::Observer { ...@@ -64,20 +34,14 @@ class AccountTracker : public signin::IdentityManager::Observer {
void AddObserver(Observer* observer); void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer); void RemoveObserver(Observer* observer);
// Returns the list of accounts that are signed in, and for which gaia IDs // Returns the list of accounts that are signed in, and for which gaia account
// have been fetched. The primary account for the profile will be first // have been fetched. The primary account for the profile will be first
// in the vector. Additional accounts will be in order of their gaia IDs. // in the vector. Additional accounts will be in order of their gaia account.
std::vector<AccountIds> GetAccounts() const; std::vector<CoreAccountInfo> GetAccounts() const;
// Indicates if all user information has been fetched. If the result is false,
// there are still unfinished fetchers.
virtual bool IsAllUserInfoFetched() const;
private: private:
friend class AccountIdFetcher;
struct AccountState { struct AccountState {
AccountIds ids; CoreAccountInfo account;
bool is_signed_in; bool is_signed_in;
}; };
...@@ -91,65 +55,26 @@ class AccountTracker : public signin::IdentityManager::Observer { ...@@ -91,65 +55,26 @@ class AccountTracker : public signin::IdentityManager::Observer {
void OnRefreshTokenRemovedForAccount( void OnRefreshTokenRemovedForAccount(
const CoreAccountId& account_id) override; const CoreAccountId& account_id) override;
void OnUserInfoFetchSuccess(AccountIdFetcher* fetcher, // Add |account_info| to the lists of accounts tracked by this AccountTracker.
const std::string& gaia_id); void StartTrackingAccount(const CoreAccountInfo& account_info);
void OnUserInfoFetchFailure(AccountIdFetcher* fetcher);
void NotifySignInChanged(const AccountState& account);
void UpdateSignInState(const CoreAccountId& account_key, bool is_signed_in); // Stops tracking |account_id|. Notifies all observers if the account was
// previously signed in.
void StartTrackingAccount(const CoreAccountId& account_key); void StopTrackingAccount(const CoreAccountId account_id);
// Note: |account_key| is passed by value here, because the original
// object may be stored in |accounts_| and if so, it will be destroyed
// after erasing the key from the map.
void StopTrackingAccount(const CoreAccountId account_key);
// Stops tracking all accounts.
void StopTrackingAllAccounts(); void StopTrackingAllAccounts();
void StartFetchingUserInfo(const CoreAccountId& account_key);
void DeleteFetcher(AccountIdFetcher* fetcher); // Updates the is_signed_in corresponding to the given account. Notifies all
// observers of the signed in state changes.
void UpdateSignInState(const CoreAccountId& account_id, bool is_signed_in);
signin::IdentityManager* identity_manager_; signin::IdentityManager* identity_manager_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
std::map<CoreAccountId, std::unique_ptr<AccountIdFetcher>>
user_info_requests_;
std::map<CoreAccountId, AccountState> accounts_; std::map<CoreAccountId, AccountState> accounts_;
base::ObserverList<Observer>::Unchecked observer_list_; base::ObserverList<Observer>::Unchecked observer_list_;
bool shutdown_called_; bool shutdown_called_;
}; };
class AccountIdFetcher : public gaia::GaiaOAuthClient::Delegate {
public:
AccountIdFetcher(
signin::IdentityManager* identity_manager,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
AccountTracker* tracker,
const CoreAccountId& account_key);
~AccountIdFetcher() override;
const CoreAccountId& account_key() { return account_key_; }
void Start();
void AccessTokenFetched(GoogleServiceAuthError error,
signin::AccessTokenInfo access_token_info);
// gaia::GaiaOAuthClient::Delegate implementation.
void OnGetUserIdResponse(const std::string& gaia_id) override;
void OnOAuthError() override;
void OnNetworkError(int response_code) override;
private:
signin::IdentityManager* identity_manager_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
AccountTracker* tracker_;
const CoreAccountId account_key_;
std::unique_ptr<signin::AccessTokenFetcher> access_token_fetcher_;
std::unique_ptr<gaia::GaiaOAuthClient> gaia_oauth_client_;
};
} // namespace gcm } // namespace gcm
#endif // COMPONENTS_GCM_DRIVER_ACCOUNT_TRACKER_H_ #endif // COMPONENTS_GCM_DRIVER_ACCOUNT_TRACKER_H_
...@@ -11,24 +11,14 @@ ...@@ -11,24 +11,14 @@
#include "base/test/task_environment.h" #include "base/test/task_environment.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "components/signin/public/identity_manager/identity_test_environment.h" #include "components/signin/public/identity_manager/identity_test_environment.h"
#include "google_apis/gaia/gaia_oauth_client.h"
#include "net/http/http_status_code.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "services/network/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace { namespace {
const char kOAuthURL[] = "https://www.googleapis.com/oauth2/v1/userinfo";
const char kPrimaryAccountEmail[] = "primary_account@example.com"; const char kPrimaryAccountEmail[] = "primary_account@example.com";
enum TrackingEventType { SIGN_IN, SIGN_OUT }; enum TrackingEventType { SIGN_IN, SIGN_OUT };
std::string AccountKeyToObfuscatedId(const CoreAccountId& account_id) {
return "obfid-" + account_id.ToString();
}
class TrackingEvent { class TrackingEvent {
public: public:
TrackingEvent(TrackingEventType type, TrackingEvent(TrackingEventType type,
...@@ -36,10 +26,10 @@ class TrackingEvent { ...@@ -36,10 +26,10 @@ class TrackingEvent {
const std::string& gaia_id) const std::string& gaia_id)
: type_(type), account_id_(account_id), gaia_id_(gaia_id) {} : type_(type), account_id_(account_id), gaia_id_(gaia_id) {}
TrackingEvent(TrackingEventType type, const CoreAccountId& account_id) TrackingEvent(TrackingEventType type, const CoreAccountInfo& account_info)
: type_(type), : type_(type),
account_id_(account_id), account_id_(account_info.account_id),
gaia_id_(AccountKeyToObfuscatedId(account_id)) {} gaia_id_(account_info.gaia) {}
bool operator==(const TrackingEvent& event) const { bool operator==(const TrackingEvent& event) const {
return type_ == event.type_ && account_id_ == event.account_id_ && return type_ == event.type_ && account_id_ == event.account_id_ &&
...@@ -120,7 +110,7 @@ class AccountTrackerObserver : public AccountTracker::Observer { ...@@ -120,7 +110,7 @@ class AccountTrackerObserver : public AccountTracker::Observer {
void SortEventsByUser(); void SortEventsByUser();
// AccountTracker::Observer implementation // AccountTracker::Observer implementation
void OnAccountSignInChanged(const AccountIds& ids, void OnAccountSignInChanged(const CoreAccountInfo& account,
bool is_signed_in) override; bool is_signed_in) override;
private: private:
...@@ -130,10 +120,11 @@ class AccountTrackerObserver : public AccountTracker::Observer { ...@@ -130,10 +120,11 @@ class AccountTrackerObserver : public AccountTracker::Observer {
std::vector<TrackingEvent> events_; std::vector<TrackingEvent> events_;
}; };
void AccountTrackerObserver::OnAccountSignInChanged(const AccountIds& ids, void AccountTrackerObserver::OnAccountSignInChanged(
const CoreAccountInfo& account,
bool is_signed_in) { bool is_signed_in) {
events_.push_back(TrackingEvent(is_signed_in ? SIGN_IN : SIGN_OUT, events_.push_back(TrackingEvent(is_signed_in ? SIGN_IN : SIGN_OUT,
ids.account_key, ids.gaia)); account.account_id, account.gaia));
} }
void AccountTrackerObserver::Clear() { void AccountTrackerObserver::Clear() {
...@@ -241,10 +232,8 @@ class AccountTrackerTest : public testing::Test { ...@@ -241,10 +232,8 @@ class AccountTrackerTest : public testing::Test {
~AccountTrackerTest() override {} ~AccountTrackerTest() override {}
void SetUp() override { void SetUp() override {
account_tracker_.reset(new AccountTracker( account_tracker_.reset(
identity_test_env_.identity_manager(), new AccountTracker(identity_test_env_.identity_manager()));
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&test_url_loader_factory_)));
account_tracker_->AddObserver(&observer_); account_tracker_->AddObserver(&observer_);
} }
...@@ -265,8 +254,8 @@ class AccountTrackerTest : public testing::Test { ...@@ -265,8 +254,8 @@ class AccountTrackerTest : public testing::Test {
// the underlying GoogleSigninSucceeded callback is never sent). Tests that // the underlying GoogleSigninSucceeded callback is never sent). Tests that
// exercise functionality dependent on that callback firing are not relevant // exercise functionality dependent on that callback firing are not relevant
// on ChromeOS and should simply not run on that platform. // on ChromeOS and should simply not run on that platform.
CoreAccountId SetActiveAccount(const std::string& email) { CoreAccountInfo SetActiveAccount(const std::string& email) {
return identity_test_env_.SetPrimaryAccount(email).account_id; return identity_test_env_.SetPrimaryAccount(email);
} }
// Helpers that go through a logout flow. // Helpers that go through a logout flow.
...@@ -286,8 +275,8 @@ class AccountTrackerTest : public testing::Test { ...@@ -286,8 +275,8 @@ class AccountTrackerTest : public testing::Test {
} }
#endif #endif
CoreAccountId AddAccountWithToken(const std::string& email) { CoreAccountInfo AddAccountWithToken(const std::string& email) {
return identity_test_env_.MakeAccountAvailable(email).account_id; return identity_test_env_.MakeAccountAvailable(email);
} }
void NotifyTokenAvailable(const CoreAccountId& account_id) { void NotifyTokenAvailable(const CoreAccountId& account_id) {
...@@ -298,74 +287,30 @@ class AccountTrackerTest : public testing::Test { ...@@ -298,74 +287,30 @@ class AccountTrackerTest : public testing::Test {
identity_test_env_.RemoveRefreshTokenForAccount(account_id); identity_test_env_.RemoveRefreshTokenForAccount(account_id);
} }
// Helpers to fake access token and user info fetching CoreAccountInfo SetupPrimaryLogin() {
void IssueAccessToken(const CoreAccountId& account_id) {
identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
account_id, "access_token-" + account_id.ToString(), base::Time::Max());
}
std::string GetValidTokenInfoResponse(const CoreAccountId& account_id) {
return std::string("{ \"id\": \"") + AccountKeyToObfuscatedId(account_id) +
"\" }";
}
void ReturnOAuthUrlFetchResults(net::HttpStatusCode response_code,
const std::string& response_string);
void ReturnOAuthUrlFetchSuccess(const CoreAccountId& account_id);
void ReturnOAuthUrlFetchFailure(const CoreAccountId& account_id);
CoreAccountId SetupPrimaryLogin() {
// Initial setup for tests that start with a signed in profile. // Initial setup for tests that start with a signed in profile.
CoreAccountId primary_account_id = SetActiveAccount(kPrimaryAccountEmail); CoreAccountInfo primary_account = SetActiveAccount(kPrimaryAccountEmail);
NotifyTokenAvailable(primary_account_id); NotifyTokenAvailable(primary_account.account_id);
ReturnOAuthUrlFetchSuccess(primary_account_id);
observer()->Clear(); observer()->Clear();
return primary_account_id; return primary_account;
}
network::TestURLLoaderFactory* test_url_loader_factory() {
return &test_url_loader_factory_;
} }
private: private:
// net:: stuff needs IO message loop. // net:: stuff needs IO message loop.
base::test::SingleThreadTaskEnvironment task_environment_{ base::test::SingleThreadTaskEnvironment task_environment_{
base::test::SingleThreadTaskEnvironment::MainThreadType::IO}; base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
network::TestURLLoaderFactory test_url_loader_factory_;
signin::IdentityTestEnvironment identity_test_env_; signin::IdentityTestEnvironment identity_test_env_;
std::unique_ptr<AccountTracker> account_tracker_; std::unique_ptr<AccountTracker> account_tracker_;
AccountTrackerObserver observer_; AccountTrackerObserver observer_;
}; };
void AccountTrackerTest::ReturnOAuthUrlFetchResults(
net::HttpStatusCode response_code,
const std::string& response_string) {
EXPECT_TRUE(test_url_loader_factory()->SimulateResponseForPendingRequest(
GURL(kOAuthURL), network::URLLoaderCompletionStatus(net::OK),
network::CreateURLResponseHead(response_code), response_string));
}
void AccountTrackerTest::ReturnOAuthUrlFetchSuccess(
const CoreAccountId& account_id) {
IssueAccessToken(account_id);
ReturnOAuthUrlFetchResults(net::HTTP_OK,
GetValidTokenInfoResponse(account_id));
}
void AccountTrackerTest::ReturnOAuthUrlFetchFailure(
const CoreAccountId& account_id) {
IssueAccessToken(account_id);
ReturnOAuthUrlFetchResults(net::HTTP_BAD_REQUEST, "");
}
// Primary tests just involve the Active account // Primary tests just involve the Active account
TEST_F(AccountTrackerTest, PrimaryNoEventsBeforeLogin) { TEST_F(AccountTrackerTest, PrimaryNoEventsBeforeLogin) {
CoreAccountId account_id = AddAccountWithToken("me@dummy.com"); CoreAccountInfo account = AddAccountWithToken("me@dummy.com");
NotifyTokenRevoked(account_id); NotifyTokenRevoked(account.account_id);
// Logout is not possible on ChromeOS. // Logout is not possible on ChromeOS.
#if !defined(OS_CHROMEOS) #if !defined(OS_CHROMEOS)
...@@ -376,36 +321,29 @@ TEST_F(AccountTrackerTest, PrimaryNoEventsBeforeLogin) { ...@@ -376,36 +321,29 @@ TEST_F(AccountTrackerTest, PrimaryNoEventsBeforeLogin) {
} }
TEST_F(AccountTrackerTest, PrimaryLoginThenTokenAvailable) { TEST_F(AccountTrackerTest, PrimaryLoginThenTokenAvailable) {
CoreAccountId primary_account_id = SetActiveAccount(kPrimaryAccountEmail); CoreAccountInfo primary_account = SetActiveAccount(kPrimaryAccountEmail);
NotifyTokenAvailable(primary_account_id); NotifyTokenAvailable(primary_account.account_id);
EXPECT_TRUE(observer()->CheckEvents()); EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, primary_account)));
ReturnOAuthUrlFetchSuccess(primary_account_id);
EXPECT_TRUE(
observer()->CheckEvents(TrackingEvent(SIGN_IN, primary_account_id)));
} }
TEST_F(AccountTrackerTest, PrimaryRevoke) { TEST_F(AccountTrackerTest, PrimaryRevoke) {
CoreAccountId primary_account_id = SetActiveAccount(kPrimaryAccountEmail); CoreAccountInfo primary_account = SetActiveAccount(kPrimaryAccountEmail);
NotifyTokenAvailable(primary_account_id); NotifyTokenAvailable(primary_account.account_id);
ReturnOAuthUrlFetchSuccess(primary_account_id);
observer()->Clear(); observer()->Clear();
NotifyTokenRevoked(primary_account_id); NotifyTokenRevoked(primary_account.account_id);
EXPECT_TRUE( EXPECT_TRUE(
observer()->CheckEvents(TrackingEvent(SIGN_OUT, primary_account_id))); observer()->CheckEvents(TrackingEvent(SIGN_OUT, primary_account)));
} }
TEST_F(AccountTrackerTest, PrimaryRevokeThenTokenAvailable) { TEST_F(AccountTrackerTest, PrimaryRevokeThenTokenAvailable) {
CoreAccountId primary_account_id = SetActiveAccount(kPrimaryAccountEmail); CoreAccountInfo primary_account = SetActiveAccount(kPrimaryAccountEmail);
NotifyTokenAvailable(primary_account_id); NotifyTokenAvailable(primary_account.account_id);
ReturnOAuthUrlFetchSuccess(primary_account_id); NotifyTokenRevoked(primary_account.account_id);
NotifyTokenRevoked(primary_account_id);
observer()->Clear(); observer()->Clear();
NotifyTokenAvailable(primary_account_id); NotifyTokenAvailable(primary_account.account_id);
EXPECT_TRUE( EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, primary_account)));
observer()->CheckEvents(TrackingEvent(SIGN_IN, primary_account_id)));
} }
// These tests exercise true login/logout, which are not possible on ChromeOS. // These tests exercise true login/logout, which are not possible on ChromeOS.
...@@ -414,17 +352,15 @@ TEST_F(AccountTrackerTest, PrimaryTokenAvailableThenLogin) { ...@@ -414,17 +352,15 @@ TEST_F(AccountTrackerTest, PrimaryTokenAvailableThenLogin) {
AddAccountWithToken(kPrimaryAccountEmail); AddAccountWithToken(kPrimaryAccountEmail);
EXPECT_TRUE(observer()->CheckEvents()); EXPECT_TRUE(observer()->CheckEvents());
CoreAccountId primary_account_id = SetActiveAccount(kPrimaryAccountEmail); CoreAccountInfo primary_account = SetActiveAccount(kPrimaryAccountEmail);
ReturnOAuthUrlFetchSuccess(primary_account_id); EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, primary_account)));
EXPECT_TRUE(
observer()->CheckEvents(TrackingEvent(SIGN_IN, primary_account_id)));
} }
TEST_F(AccountTrackerTest, PrimaryTokenAvailableAndRevokedThenLogin) { TEST_F(AccountTrackerTest, PrimaryTokenAvailableAndRevokedThenLogin) {
CoreAccountId primary_account_id = AddAccountWithToken(kPrimaryAccountEmail); CoreAccountInfo primary_account = AddAccountWithToken(kPrimaryAccountEmail);
EXPECT_TRUE(observer()->CheckEvents()); EXPECT_TRUE(observer()->CheckEvents());
NotifyTokenRevoked(primary_account_id); NotifyTokenRevoked(primary_account.account_id);
EXPECT_TRUE(observer()->CheckEvents()); EXPECT_TRUE(observer()->CheckEvents());
SetActiveAccount(kPrimaryAccountEmail); SetActiveAccount(kPrimaryAccountEmail);
...@@ -432,9 +368,8 @@ TEST_F(AccountTrackerTest, PrimaryTokenAvailableAndRevokedThenLogin) { ...@@ -432,9 +368,8 @@ TEST_F(AccountTrackerTest, PrimaryTokenAvailableAndRevokedThenLogin) {
} }
TEST_F(AccountTrackerTest, PrimaryRevokeThenLogin) { TEST_F(AccountTrackerTest, PrimaryRevokeThenLogin) {
CoreAccountId primary_account_id = SetActiveAccount(kPrimaryAccountEmail); CoreAccountInfo primary_account = SetActiveAccount(kPrimaryAccountEmail);
NotifyTokenAvailable(primary_account_id); NotifyTokenAvailable(primary_account.account_id);
ReturnOAuthUrlFetchSuccess(primary_account_id);
NotifyLogoutOfAllAccounts(); NotifyLogoutOfAllAccounts();
observer()->Clear(); observer()->Clear();
...@@ -443,32 +378,18 @@ TEST_F(AccountTrackerTest, PrimaryRevokeThenLogin) { ...@@ -443,32 +378,18 @@ TEST_F(AccountTrackerTest, PrimaryRevokeThenLogin) {
} }
TEST_F(AccountTrackerTest, PrimaryLogoutThenRevoke) { TEST_F(AccountTrackerTest, PrimaryLogoutThenRevoke) {
CoreAccountId primary_account_id = SetActiveAccount(kPrimaryAccountEmail); CoreAccountInfo primary_account = SetActiveAccount(kPrimaryAccountEmail);
NotifyTokenAvailable(primary_account_id); NotifyTokenAvailable(primary_account.account_id);
ReturnOAuthUrlFetchSuccess(primary_account_id);
observer()->Clear(); observer()->Clear();
NotifyLogoutOfAllAccounts(); NotifyLogoutOfAllAccounts();
EXPECT_TRUE( EXPECT_TRUE(
observer()->CheckEvents(TrackingEvent(SIGN_OUT, primary_account_id))); observer()->CheckEvents(TrackingEvent(SIGN_OUT, primary_account)));
NotifyTokenRevoked(primary_account_id); NotifyTokenRevoked(primary_account.account_id);
EXPECT_TRUE(observer()->CheckEvents()); EXPECT_TRUE(observer()->CheckEvents());
} }
TEST_F(AccountTrackerTest, PrimaryLogoutFetchCancelAvailable) {
CoreAccountId primary_account_id = SetActiveAccount(kPrimaryAccountEmail);
NotifyTokenAvailable(primary_account_id);
// TokenAvailable kicks off a fetch. Logout without satisfying it.
NotifyLogoutOfAllAccounts();
EXPECT_TRUE(observer()->CheckEvents());
SetActiveAccount(kPrimaryAccountEmail);
NotifyTokenAvailable(primary_account_id);
ReturnOAuthUrlFetchSuccess(primary_account_id);
EXPECT_TRUE(
observer()->CheckEvents(TrackingEvent(SIGN_IN, primary_account_id)));
}
#endif #endif
// Non-primary accounts // Non-primary accounts
...@@ -476,153 +397,67 @@ TEST_F(AccountTrackerTest, PrimaryLogoutFetchCancelAvailable) { ...@@ -476,153 +397,67 @@ TEST_F(AccountTrackerTest, PrimaryLogoutFetchCancelAvailable) {
TEST_F(AccountTrackerTest, Available) { TEST_F(AccountTrackerTest, Available) {
SetupPrimaryLogin(); SetupPrimaryLogin();
CoreAccountId account_id = AddAccountWithToken("user@example.com"); CoreAccountInfo account = AddAccountWithToken("user@example.com");
EXPECT_TRUE(observer()->CheckEvents()); EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, account)));
ReturnOAuthUrlFetchSuccess(account_id);
EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, account_id)));
} }
TEST_F(AccountTrackerTest, AvailableRevokeAvailable) { TEST_F(AccountTrackerTest, AvailableRevokeAvailable) {
SetupPrimaryLogin(); SetupPrimaryLogin();
CoreAccountId account_id = AddAccountWithToken("user@example.com"); CoreAccountInfo account = AddAccountWithToken("user@example.com");
ReturnOAuthUrlFetchSuccess(account_id); NotifyTokenRevoked(account.account_id);
NotifyTokenRevoked(account_id); EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, account),
EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, account_id), TrackingEvent(SIGN_OUT, account)));
TrackingEvent(SIGN_OUT, account_id)));
NotifyTokenAvailable(account_id);
EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, account_id)));
}
TEST_F(AccountTrackerTest, AvailableRevokeAvailableWithPendingFetch) {
SetupPrimaryLogin();
CoreAccountId account_id = AddAccountWithToken("user@example.com");
NotifyTokenRevoked(account_id);
EXPECT_TRUE(observer()->CheckEvents());
NotifyTokenAvailable(account_id); NotifyTokenAvailable(account.account_id);
ReturnOAuthUrlFetchSuccess(account_id); EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, account)));
EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, account_id)));
} }
TEST_F(AccountTrackerTest, AvailableRevokeRevoke) { TEST_F(AccountTrackerTest, AvailableRevokeRevoke) {
SetupPrimaryLogin(); SetupPrimaryLogin();
CoreAccountId account_id = AddAccountWithToken("user@example.com"); CoreAccountInfo account = AddAccountWithToken("user@example.com");
ReturnOAuthUrlFetchSuccess(account_id); NotifyTokenRevoked(account.account_id);
NotifyTokenRevoked(account_id); EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, account),
EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, account_id), TrackingEvent(SIGN_OUT, account)));
TrackingEvent(SIGN_OUT, account_id)));
NotifyTokenRevoked(account_id); NotifyTokenRevoked(account.account_id);
EXPECT_TRUE(observer()->CheckEvents()); EXPECT_TRUE(observer()->CheckEvents());
} }
TEST_F(AccountTrackerTest, AvailableAvailable) { TEST_F(AccountTrackerTest, AvailableAvailable) {
SetupPrimaryLogin(); SetupPrimaryLogin();
CoreAccountId account_id = AddAccountWithToken("user@example.com"); CoreAccountInfo account = AddAccountWithToken("user@example.com");
ReturnOAuthUrlFetchSuccess(account_id); EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, account)));
EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, account_id)));
NotifyTokenAvailable(account_id); NotifyTokenAvailable(account.account_id);
EXPECT_TRUE(observer()->CheckEvents()); EXPECT_TRUE(observer()->CheckEvents());
} }
TEST_F(AccountTrackerTest, TwoAccounts) { TEST_F(AccountTrackerTest, TwoAccounts) {
SetupPrimaryLogin(); SetupPrimaryLogin();
CoreAccountId alpha_account_id = AddAccountWithToken("alpha@example.com"); CoreAccountInfo alpha_account = AddAccountWithToken("alpha@example.com");
ReturnOAuthUrlFetchSuccess(alpha_account_id); EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, alpha_account)));
EXPECT_TRUE(
observer()->CheckEvents(TrackingEvent(SIGN_IN, alpha_account_id)));
CoreAccountId beta_account_id = AddAccountWithToken("beta@example.com");
ReturnOAuthUrlFetchSuccess(beta_account_id);
EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, beta_account_id)));
NotifyTokenRevoked(alpha_account_id);
EXPECT_TRUE(
observer()->CheckEvents(TrackingEvent(SIGN_OUT, alpha_account_id)));
NotifyTokenRevoked(beta_account_id);
EXPECT_TRUE(
observer()->CheckEvents(TrackingEvent(SIGN_OUT, beta_account_id)));
}
TEST_F(AccountTrackerTest, AvailableTokenFetchFailAvailable) {
SetupPrimaryLogin();
CoreAccountId account_id = AddAccountWithToken("user@example.com");
ReturnOAuthUrlFetchFailure(account_id);
EXPECT_TRUE(observer()->CheckEvents());
NotifyTokenAvailable(account_id);
ReturnOAuthUrlFetchSuccess(account_id);
EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, account_id)));
}
// These tests exercise true login/logout, which are not possible on ChromeOS.
#if !defined(OS_CHROMEOS)
TEST_F(AccountTrackerTest, MultiSignOutSignIn) {
CoreAccountId primary_account_id = SetupPrimaryLogin();
CoreAccountId alpha_account_id = AddAccountWithToken("alpha@example.com");
ReturnOAuthUrlFetchSuccess(alpha_account_id);
CoreAccountId beta_account_id = AddAccountWithToken("beta@example.com");
ReturnOAuthUrlFetchSuccess(beta_account_id);
observer()->SortEventsByUser(); CoreAccountInfo beta_account = AddAccountWithToken("beta@example.com");
EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, alpha_account_id), EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_IN, beta_account)));
TrackingEvent(SIGN_IN, beta_account_id)));
// Log out of the primary account only (allows for testing that the account NotifyTokenRevoked(alpha_account.account_id);
// tracker preserves knowledge of "beta@example.com"). EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_OUT, alpha_account)));
NotifyLogoutOfPrimaryAccountOnly();
observer()->SortEventsByUser();
EXPECT_TRUE(
observer()->CheckEvents(TrackingEvent(SIGN_OUT, alpha_account_id),
TrackingEvent(SIGN_OUT, beta_account_id),
TrackingEvent(SIGN_OUT, primary_account_id)));
// No events fire at all while profile is signed out.
NotifyTokenRevoked(alpha_account_id);
CoreAccountId gamma_account_id = AddAccountWithToken("gamma@example.com");
EXPECT_TRUE(observer()->CheckEvents());
// Signing the profile in again will resume tracking all accounts.
SetActiveAccount(kPrimaryAccountEmail);
NotifyTokenAvailable(primary_account_id);
ReturnOAuthUrlFetchSuccess(beta_account_id);
ReturnOAuthUrlFetchSuccess(gamma_account_id);
ReturnOAuthUrlFetchSuccess(primary_account_id);
observer()->SortEventsByUser();
EXPECT_TRUE(
observer()->CheckEvents(TrackingEvent(SIGN_IN, beta_account_id),
TrackingEvent(SIGN_IN, gamma_account_id),
TrackingEvent(SIGN_IN, primary_account_id)));
// Revoking the primary token does not affect other accounts. NotifyTokenRevoked(beta_account.account_id);
NotifyTokenRevoked(primary_account_id); EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_OUT, beta_account)));
EXPECT_TRUE(
observer()->CheckEvents(TrackingEvent(SIGN_OUT, primary_account_id)));
NotifyTokenAvailable(primary_account_id);
EXPECT_TRUE(
observer()->CheckEvents(TrackingEvent(SIGN_IN, primary_account_id)));
} }
#endif
// Primary/non-primary interactions // Primary/non-primary interactions
TEST_F(AccountTrackerTest, MultiNoEventsBeforeLogin) { TEST_F(AccountTrackerTest, MultiNoEventsBeforeLogin) {
CoreAccountId account_id1 = AddAccountWithToken("user@example.com"); CoreAccountInfo account1 = AddAccountWithToken("user@example.com");
CoreAccountId account_id2 = AddAccountWithToken("user2@example.com"); CoreAccountInfo account2 = AddAccountWithToken("user2@example.com");
NotifyTokenRevoked(account_id2); NotifyTokenRevoked(account2.account_id);
NotifyTokenRevoked(account_id1); NotifyTokenRevoked(account2.account_id);
// Logout is not possible on ChromeOS. // Logout is not possible on ChromeOS.
#if !defined(OS_CHROMEOS) #if !defined(OS_CHROMEOS)
...@@ -633,97 +468,76 @@ TEST_F(AccountTrackerTest, MultiNoEventsBeforeLogin) { ...@@ -633,97 +468,76 @@ TEST_F(AccountTrackerTest, MultiNoEventsBeforeLogin) {
} }
TEST_F(AccountTrackerTest, MultiRevokePrimaryDoesNotRemoveAllAccounts) { TEST_F(AccountTrackerTest, MultiRevokePrimaryDoesNotRemoveAllAccounts) {
CoreAccountId primary_account_id = SetActiveAccount(kPrimaryAccountEmail); CoreAccountInfo primary_account = SetActiveAccount(kPrimaryAccountEmail);
NotifyTokenAvailable(primary_account_id); NotifyTokenAvailable(primary_account.account_id);
ReturnOAuthUrlFetchSuccess(primary_account_id); CoreAccountInfo account = AddAccountWithToken("user@example.com");
CoreAccountId account_id = AddAccountWithToken("user@example.com");
ReturnOAuthUrlFetchSuccess(account_id);
observer()->Clear(); observer()->Clear();
NotifyTokenRevoked(primary_account_id); NotifyTokenRevoked(primary_account.account_id);
observer()->SortEventsByUser(); observer()->SortEventsByUser();
EXPECT_TRUE( EXPECT_TRUE(
observer()->CheckEvents(TrackingEvent(SIGN_OUT, primary_account_id))); observer()->CheckEvents(TrackingEvent(SIGN_OUT, primary_account)));
} }
TEST_F(AccountTrackerTest, GetAccountsPrimary) { TEST_F(AccountTrackerTest, GetAccountsPrimary) {
CoreAccountId primary_account_id = SetupPrimaryLogin(); CoreAccountInfo primary_account = SetupPrimaryLogin();
std::vector<AccountIds> ids = account_tracker()->GetAccounts(); std::vector<CoreAccountInfo> account = account_tracker()->GetAccounts();
EXPECT_EQ(1ul, ids.size()); EXPECT_EQ(1ul, account.size());
EXPECT_EQ(primary_account_id, ids[0].account_key); EXPECT_EQ(primary_account.account_id, account[0].account_id);
EXPECT_EQ(AccountKeyToObfuscatedId(primary_account_id), ids[0].gaia); EXPECT_EQ(primary_account.gaia, account[0].gaia);
EXPECT_EQ(primary_account.email, account[0].email);
} }
TEST_F(AccountTrackerTest, GetAccountsSignedOut) { TEST_F(AccountTrackerTest, GetAccountsSignedOut) {
std::vector<AccountIds> ids = account_tracker()->GetAccounts(); std::vector<CoreAccountInfo> accounts = account_tracker()->GetAccounts();
EXPECT_EQ(0ul, ids.size()); EXPECT_EQ(0ul, accounts.size());
} }
TEST_F(AccountTrackerTest, GetAccountsOnlyReturnAccountsWithTokens) { TEST_F(AccountTrackerTest, GetMultipleAccounts) {
CoreAccountId primary_account_id = SetupPrimaryLogin(); CoreAccountInfo primary_account = SetupPrimaryLogin();
CoreAccountInfo alpha_account = AddAccountWithToken("alpha@example.com");
CoreAccountInfo beta_account = AddAccountWithToken("beta@example.com");
CoreAccountId alpha_account_id = AddAccountWithToken("alpha@example.com"); std::vector<CoreAccountInfo> account = account_tracker()->GetAccounts();
CoreAccountId beta_account_id = AddAccountWithToken("beta@example.com"); EXPECT_EQ(3ul, account.size());
ReturnOAuthUrlFetchSuccess(beta_account_id); EXPECT_EQ(primary_account.account_id, account[0].account_id);
EXPECT_EQ(primary_account.email, account[0].email);
EXPECT_EQ(primary_account.gaia, account[0].gaia);
std::vector<AccountIds> ids = account_tracker()->GetAccounts(); EXPECT_EQ(alpha_account.account_id, account[1].account_id);
EXPECT_EQ(2ul, ids.size()); EXPECT_EQ(alpha_account.email, account[1].email);
EXPECT_EQ(primary_account_id, ids[0].account_key); EXPECT_EQ(alpha_account.gaia, account[1].gaia);
EXPECT_EQ(AccountKeyToObfuscatedId(primary_account_id), ids[0].gaia);
EXPECT_EQ(beta_account_id, ids[1].account_key);
EXPECT_EQ(AccountKeyToObfuscatedId(beta_account_id), ids[1].gaia);
}
TEST_F(AccountTrackerTest, GetAccountsSortOrder) {
CoreAccountId primary_account_id = SetupPrimaryLogin();
CoreAccountId zeta_account_id = AddAccountWithToken("zeta@example.com"); EXPECT_EQ(beta_account.account_id, account[2].account_id);
ReturnOAuthUrlFetchSuccess(zeta_account_id); EXPECT_EQ(beta_account.email, account[2].email);
CoreAccountId alpha_account_id = AddAccountWithToken("alpha@example.com"); EXPECT_EQ(beta_account.gaia, account[2].gaia);
ReturnOAuthUrlFetchSuccess(alpha_account_id);
// The primary account will be first in the vector. Remaining accounts
// will be sorted by gaia ID.
std::vector<AccountIds> ids = account_tracker()->GetAccounts();
EXPECT_EQ(3ul, ids.size());
EXPECT_EQ(primary_account_id, ids[0].account_key);
EXPECT_EQ(AccountKeyToObfuscatedId(primary_account_id), ids[0].gaia);
EXPECT_EQ(alpha_account_id, ids[1].account_key);
EXPECT_EQ(AccountKeyToObfuscatedId(alpha_account_id), ids[1].gaia);
EXPECT_EQ(zeta_account_id, ids[2].account_key);
EXPECT_EQ(AccountKeyToObfuscatedId(zeta_account_id), ids[2].gaia);
} }
TEST_F(AccountTrackerTest, GetAccountsReturnNothingWhenPrimarySignedOut) { TEST_F(AccountTrackerTest, GetAccountsReturnNothingWhenPrimarySignedOut) {
CoreAccountId primary_account_id = SetupPrimaryLogin(); CoreAccountInfo primary_account = SetupPrimaryLogin();
CoreAccountId zeta_account_id = AddAccountWithToken("zeta@example.com"); CoreAccountInfo zeta_account = AddAccountWithToken("zeta@example.com");
ReturnOAuthUrlFetchSuccess(zeta_account_id); CoreAccountInfo alpha_account = AddAccountWithToken("alpha@example.com");
CoreAccountId alpha_account_id = AddAccountWithToken("alpha@example.com");
ReturnOAuthUrlFetchSuccess(alpha_account_id);
NotifyTokenRevoked(primary_account_id); NotifyTokenRevoked(primary_account.account_id);
std::vector<AccountIds> ids = account_tracker()->GetAccounts(); std::vector<CoreAccountInfo> account = account_tracker()->GetAccounts();
EXPECT_EQ(0ul, ids.size()); EXPECT_EQ(0ul, account.size());
} }
// This test exercises true login/logout, which are not possible on ChromeOS. // This test exercises true login/logout, which are not possible on ChromeOS.
#if !defined(OS_CHROMEOS) #if !defined(OS_CHROMEOS)
TEST_F(AccountTrackerTest, MultiLogoutRemovesAllAccounts) { TEST_F(AccountTrackerTest, MultiLogoutRemovesAllAccounts) {
CoreAccountId primary_account_id = SetActiveAccount(kPrimaryAccountEmail); CoreAccountInfo primary_account = SetActiveAccount(kPrimaryAccountEmail);
NotifyTokenAvailable(primary_account_id); NotifyTokenAvailable(primary_account.account_id);
ReturnOAuthUrlFetchSuccess(primary_account_id); CoreAccountInfo account = AddAccountWithToken("user@example.com");
CoreAccountId account_id = AddAccountWithToken("user@example.com");
ReturnOAuthUrlFetchSuccess(account_id);
observer()->Clear(); observer()->Clear();
NotifyLogoutOfAllAccounts(); NotifyLogoutOfAllAccounts();
observer()->SortEventsByUser(); observer()->SortEventsByUser();
EXPECT_TRUE( EXPECT_TRUE(observer()->CheckEvents(TrackingEvent(SIGN_OUT, primary_account),
observer()->CheckEvents(TrackingEvent(SIGN_OUT, primary_account_id), TrackingEvent(SIGN_OUT, account)));
TrackingEvent(SIGN_OUT, account_id)));
} }
#endif #endif
......
...@@ -72,12 +72,12 @@ void GCMAccountTracker::Start() { ...@@ -72,12 +72,12 @@ void GCMAccountTracker::Start() {
account_tracker_->AddObserver(this); account_tracker_->AddObserver(this);
driver_->AddConnectionObserver(this); driver_->AddConnectionObserver(this);
std::vector<AccountIds> accounts = account_tracker_->GetAccounts(); std::vector<CoreAccountInfo> accounts = account_tracker_->GetAccounts();
for (std::vector<AccountIds>::const_iterator iter = accounts.begin(); for (std::vector<CoreAccountInfo>::const_iterator iter = accounts.begin();
iter != accounts.end(); ++iter) { iter != accounts.end(); ++iter) {
if (!iter->email.empty()) { if (!iter->email.empty()) {
account_infos_.insert(std::make_pair( account_infos_.insert(std::make_pair(
iter->account_key, AccountInfo(iter->email, TOKEN_NEEDED))); iter->account_id, AccountInfo(iter->email, TOKEN_NEEDED)));
} }
} }
...@@ -104,12 +104,12 @@ void GCMAccountTracker::ScheduleReportTokens() { ...@@ -104,12 +104,12 @@ void GCMAccountTracker::ScheduleReportTokens() {
GetTimeToNextTokenReporting()); GetTimeToNextTokenReporting());
} }
void GCMAccountTracker::OnAccountSignInChanged(const AccountIds& ids, void GCMAccountTracker::OnAccountSignInChanged(const CoreAccountInfo& account,
bool is_signed_in) { bool is_signed_in) {
if (is_signed_in) if (is_signed_in)
OnAccountSignedIn(ids); OnAccountSignedIn(account);
else else
OnAccountSignedOut(ids); OnAccountSignedOut(account);
} }
void GCMAccountTracker::OnAccessTokenFetchCompleteForAccount( void GCMAccountTracker::OnAccessTokenFetchCompleteForAccount(
...@@ -163,11 +163,9 @@ void GCMAccountTracker::ReportTokens() { ...@@ -163,11 +163,9 @@ void GCMAccountTracker::ReportTokens() {
return; return;
} }
// Wait for AccountTracker to be done with fetching the user info, as // Wait for all of the pending token requests from GCMAccountTracker to be
// well as all of the pending token requests from GCMAccountTracker to be done // done before you report the results.
// before you report the results. if (!pending_token_requests_.empty()) {
if (!account_tracker_->IsAllUserInfoFetched() ||
!pending_token_requests_.empty()) {
return; return;
} }
...@@ -311,13 +309,13 @@ void GCMAccountTracker::GetToken(AccountInfos::iterator& account_iter) { ...@@ -311,13 +309,13 @@ void GCMAccountTracker::GetToken(AccountInfos::iterator& account_iter) {
account_iter->second.state = GETTING_TOKEN; account_iter->second.state = GETTING_TOKEN;
} }
void GCMAccountTracker::OnAccountSignedIn(const AccountIds& ids) { void GCMAccountTracker::OnAccountSignedIn(const CoreAccountInfo& account) {
DVLOG(1) << "Account signed in: " << ids.email; DVLOG(1) << "Account signed in: " << account.email;
auto iter = account_infos_.find(ids.account_key); auto iter = account_infos_.find(account.account_id);
if (iter == account_infos_.end()) { if (iter == account_infos_.end()) {
DCHECK(!ids.email.empty()); DCHECK(!account.email.empty());
account_infos_.insert( account_infos_.insert(std::make_pair(
std::make_pair(ids.account_key, AccountInfo(ids.email, TOKEN_NEEDED))); account.account_id, AccountInfo(account.email, TOKEN_NEEDED)));
} else if (iter->second.state == ACCOUNT_REMOVED) { } else if (iter->second.state == ACCOUNT_REMOVED) {
iter->second.state = TOKEN_NEEDED; iter->second.state = TOKEN_NEEDED;
} }
...@@ -325,9 +323,9 @@ void GCMAccountTracker::OnAccountSignedIn(const AccountIds& ids) { ...@@ -325,9 +323,9 @@ void GCMAccountTracker::OnAccountSignedIn(const AccountIds& ids) {
GetAllNeededTokens(); GetAllNeededTokens();
} }
void GCMAccountTracker::OnAccountSignedOut(const AccountIds& ids) { void GCMAccountTracker::OnAccountSignedOut(const CoreAccountInfo& account) {
DVLOG(1) << "Account signed out: " << ids.email; DVLOG(1) << "Account signed out: " << account.email;
auto iter = account_infos_.find(ids.account_key); auto iter = account_infos_.find(account.account_id);
if (iter == account_infos_.end()) if (iter == account_infos_.end())
return; return;
...@@ -338,7 +336,7 @@ void GCMAccountTracker::OnAccountSignedOut(const AccountIds& ids) { ...@@ -338,7 +336,7 @@ void GCMAccountTracker::OnAccountSignedOut(const AccountIds& ids) {
// re-added and a new access token request made, we do not break this class' // re-added and a new access token request made, we do not break this class'
// invariant that there is at most one ongoing access token request per // invariant that there is at most one ongoing access token request per
// account. // account.
pending_token_requests_.erase(ids.account_key); pending_token_requests_.erase(account.account_id);
ReportTokens(); ReportTokens();
} }
......
...@@ -96,12 +96,12 @@ class GCMAccountTracker : public AccountTracker::Observer, ...@@ -96,12 +96,12 @@ class GCMAccountTracker : public AccountTracker::Observer,
private: private:
friend class GCMAccountTrackerTest; friend class GCMAccountTrackerTest;
// Maps account keys to account states. Keyed by account_ids as used by // Maps account keys to account states. Keyed by account_id as used by
// IdentityManager. // IdentityManager.
typedef std::map<CoreAccountId, AccountInfo> AccountInfos; typedef std::map<CoreAccountId, AccountInfo> AccountInfos;
// AccountTracker::Observer overrides. // AccountTracker::Observer overrides.
void OnAccountSignInChanged(const AccountIds& ids, void OnAccountSignInChanged(const CoreAccountInfo& account,
bool is_signed_in) override; bool is_signed_in) override;
void OnAccessTokenFetchCompleteForAccount( void OnAccessTokenFetchCompleteForAccount(
...@@ -136,8 +136,8 @@ class GCMAccountTracker : public AccountTracker::Observer, ...@@ -136,8 +136,8 @@ class GCMAccountTracker : public AccountTracker::Observer,
void GetToken(AccountInfos::iterator& account_iter); void GetToken(AccountInfos::iterator& account_iter);
// Handling of actual sign in and sign out for accounts. // Handling of actual sign in and sign out for accounts.
void OnAccountSignedIn(const AccountIds& ids); void OnAccountSignedIn(const CoreAccountInfo& account);
void OnAccountSignedOut(const AccountIds& ids); void OnAccountSignedOut(const CoreAccountInfo& account);
// Account tracker. // Account tracker.
std::unique_ptr<AccountTracker> account_tracker_; std::unique_ptr<AccountTracker> account_tracker_;
......
...@@ -25,27 +25,16 @@ namespace gcm { ...@@ -25,27 +25,16 @@ namespace gcm {
namespace { namespace {
const char kOAuthURL[] = "https://www.googleapis.com/oauth2/v1/userinfo";
const char kEmail1[] = "account_1@me.com"; const char kEmail1[] = "account_1@me.com";
const char kEmail2[] = "account_2@me.com"; const char kEmail2[] = "account_2@me.com";
std::string AccountIdToObfuscatedId(const CoreAccountId& account_id) {
return "obfid-" + account_id.ToString();
}
std::string GetValidTokenInfoResponse(const CoreAccountId& account_id) {
return std::string("{ \"id\": \"") + AccountIdToObfuscatedId(account_id) +
"\" }";
}
std::string MakeAccessToken(const CoreAccountId& account_id) { std::string MakeAccessToken(const CoreAccountId& account_id) {
return "access_token-" + account_id.ToString(); return "access_token-" + account_id.ToString();
} }
GCMClient::AccountTokenInfo MakeAccountToken(const CoreAccountId& account_id) { GCMClient::AccountTokenInfo MakeAccountToken(const CoreAccountInfo& account) {
GCMClient::AccountTokenInfo token_info; GCMClient::AccountTokenInfo token_info;
token_info.account_id = account_id; token_info.account_id = account.account_id;
// TODO(https://crbug.com/856170): This *should* be expected to be the email // TODO(https://crbug.com/856170): This *should* be expected to be the email
// address for the given account, but there is a bug in AccountTracker that // address for the given account, but there is a bug in AccountTracker that
...@@ -54,8 +43,8 @@ GCMClient::AccountTokenInfo MakeAccountToken(const CoreAccountId& account_id) { ...@@ -54,8 +43,8 @@ GCMClient::AccountTokenInfo MakeAccountToken(const CoreAccountId& account_id) {
// production code actually does :). If/when that bug gets fixed, this // production code actually does :). If/when that bug gets fixed, this
// function should be changed to take in the email address as well as the // function should be changed to take in the email address as well as the
// account ID and populate this field with the email address. // account ID and populate this field with the email address.
token_info.email = account_id.ToString(); token_info.email = account.email;
token_info.access_token = MakeAccessToken(account_id); token_info.access_token = MakeAccessToken(account.account_id);
return token_info; return token_info;
} }
...@@ -170,17 +159,9 @@ class GCMAccountTrackerTest : public testing::Test { ...@@ -170,17 +159,9 @@ class GCMAccountTrackerTest : public testing::Test {
GCMAccountTrackerTest(); GCMAccountTrackerTest();
~GCMAccountTrackerTest() override; ~GCMAccountTrackerTest() override;
// Helpers to pass fake info to the tracker. Tests should have either a pair // Helpers to pass fake info to the tracker.
// of Start(Primary)/FinishAccountAddition or Add(Primary)Account per CoreAccountInfo AddAccount(const std::string& email);
// account. Don't mix. Any methods that return an std::string are returning CoreAccountInfo SetPrimaryAccount(const std::string& email);
// the account ID of the newly-added account, which can then be passed into
// any methods that take in an account ID.
// Call to RemoveAccount is not mandatory.
CoreAccountId StartAccountAddition(const std::string& email);
CoreAccountId StartPrimaryAccountAddition(const std::string& email);
void FinishAccountAddition(const CoreAccountId& account_id);
CoreAccountId AddAccount(const std::string& email);
CoreAccountId AddPrimaryAccount(const std::string& email);
void RemoveAccount(const CoreAccountId& account_id); void RemoveAccount(const CoreAccountId& account_id);
// Helpers for dealing with OAuth2 access token requests. // Helpers for dealing with OAuth2 access token requests.
...@@ -212,10 +193,8 @@ class GCMAccountTrackerTest : public testing::Test { ...@@ -212,10 +193,8 @@ class GCMAccountTrackerTest : public testing::Test {
}; };
GCMAccountTrackerTest::GCMAccountTrackerTest() { GCMAccountTrackerTest::GCMAccountTrackerTest() {
std::unique_ptr<AccountTracker> gaia_account_tracker(new AccountTracker( std::unique_ptr<AccountTracker> gaia_account_tracker(
identity_test_env_.identity_manager(), new AccountTracker(identity_test_env_.identity_manager()));
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&test_url_loader_factory_)));
tracker_.reset(new GCMAccountTracker(std::move(gaia_account_tracker), tracker_.reset(new GCMAccountTracker(std::move(gaia_account_tracker),
identity_test_env_.identity_manager(), identity_test_env_.identity_manager(),
...@@ -227,12 +206,11 @@ GCMAccountTrackerTest::~GCMAccountTrackerTest() { ...@@ -227,12 +206,11 @@ GCMAccountTrackerTest::~GCMAccountTrackerTest() {
tracker_->Shutdown(); tracker_->Shutdown();
} }
CoreAccountId GCMAccountTrackerTest::StartAccountAddition( CoreAccountInfo GCMAccountTrackerTest::AddAccount(const std::string& email) {
const std::string& email) { return identity_test_env_.MakeAccountAvailable(email);
return identity_test_env_.MakeAccountAvailable(email).account_id;
} }
CoreAccountId GCMAccountTrackerTest::StartPrimaryAccountAddition( CoreAccountInfo GCMAccountTrackerTest::SetPrimaryAccount(
const std::string& email) { const std::string& email) {
// NOTE: Setting of the primary account info must be done first on ChromeOS // NOTE: Setting of the primary account info must be done first on ChromeOS
// to ensure that AccountTracker and GCMAccountTracker respond as expected // to ensure that AccountTracker and GCMAccountTracker respond as expected
...@@ -241,33 +219,7 @@ CoreAccountId GCMAccountTrackerTest::StartPrimaryAccountAddition( ...@@ -241,33 +219,7 @@ CoreAccountId GCMAccountTrackerTest::StartPrimaryAccountAddition(
// setting of the primary account is done afterward to check that the flow // setting of the primary account is done afterward to check that the flow
// that ensues from the GoogleSigninSucceeded callback firing works as // that ensues from the GoogleSigninSucceeded callback firing works as
// expected. // expected.
return identity_test_env_.MakePrimaryAccountAvailable(email).account_id; return identity_test_env_.MakePrimaryAccountAvailable(email);
}
void GCMAccountTrackerTest::FinishAccountAddition(
const CoreAccountId& account_id) {
IssueAccessToken(account_id);
EXPECT_TRUE(test_url_loader_factory()->IsPending(kOAuthURL));
test_url_loader_factory()->SimulateResponseForPendingRequest(
GURL(kOAuthURL), network::URLLoaderCompletionStatus(net::OK),
network::CreateURLResponseHead(net::HTTP_OK),
GetValidTokenInfoResponse(account_id));
GetValidTokenInfoResponse(account_id);
}
CoreAccountId GCMAccountTrackerTest::AddPrimaryAccount(
const std::string& email) {
CoreAccountId account_id = StartPrimaryAccountAddition(email);
FinishAccountAddition(account_id);
return account_id;
}
CoreAccountId GCMAccountTrackerTest::AddAccount(const std::string& email) {
CoreAccountId account_id = StartAccountAddition(email);
FinishAccountAddition(account_id);
return account_id;
} }
void GCMAccountTrackerTest::RemoveAccount(const CoreAccountId& account_id) { void GCMAccountTrackerTest::RemoveAccount(const CoreAccountId& account_id) {
...@@ -315,43 +267,35 @@ TEST_F(GCMAccountTrackerTest, NoAccounts) { ...@@ -315,43 +267,35 @@ TEST_F(GCMAccountTrackerTest, NoAccounts) {
// with a specific scope. In this scenario, the underlying account tracker is // with a specific scope. In this scenario, the underlying account tracker is
// still working when the CompleteCollectingTokens is called for the first time. // still working when the CompleteCollectingTokens is called for the first time.
TEST_F(GCMAccountTrackerTest, SingleAccount) { TEST_F(GCMAccountTrackerTest, SingleAccount) {
CoreAccountId account_id1 = StartPrimaryAccountAddition(kEmail1); CoreAccountInfo account1 = SetPrimaryAccount(kEmail1);
tracker()->Start(); tracker()->Start();
// We don't have any accounts to report, but given the inner account tracker
// is still working we don't make a call with empty accounts list.
EXPECT_FALSE(driver()->update_accounts_called()); EXPECT_FALSE(driver()->update_accounts_called());
// This concludes the work of inner account tracker. IssueAccessToken(account1.account_id);
FinishAccountAddition(account_id1);
IssueAccessToken(account_id1);
EXPECT_TRUE(driver()->update_accounts_called()); EXPECT_TRUE(driver()->update_accounts_called());
std::vector<GCMClient::AccountTokenInfo> expected_accounts; std::vector<GCMClient::AccountTokenInfo> expected_accounts;
expected_accounts.push_back(MakeAccountToken(account_id1)); expected_accounts.push_back(MakeAccountToken(account1));
VerifyAccountTokens(expected_accounts, driver()->accounts()); VerifyAccountTokens(expected_accounts, driver()->accounts());
} }
TEST_F(GCMAccountTrackerTest, MultipleAccounts) { TEST_F(GCMAccountTrackerTest, MultipleAccounts) {
CoreAccountId account_id1 = StartPrimaryAccountAddition(kEmail1); CoreAccountInfo account1 = SetPrimaryAccount(kEmail1);
CoreAccountInfo account2 = AddAccount(kEmail2);
CoreAccountId account_id2 = StartAccountAddition(kEmail2);
tracker()->Start(); tracker()->Start();
EXPECT_FALSE(driver()->update_accounts_called()); EXPECT_FALSE(driver()->update_accounts_called());
FinishAccountAddition(account_id1); IssueAccessToken(account1.account_id);
IssueAccessToken(account_id1);
EXPECT_FALSE(driver()->update_accounts_called()); EXPECT_FALSE(driver()->update_accounts_called());
FinishAccountAddition(account_id2); IssueAccessToken(account2.account_id);
IssueAccessToken(account_id2);
EXPECT_TRUE(driver()->update_accounts_called()); EXPECT_TRUE(driver()->update_accounts_called());
std::vector<GCMClient::AccountTokenInfo> expected_accounts; std::vector<GCMClient::AccountTokenInfo> expected_accounts;
expected_accounts.push_back(MakeAccountToken(account_id1)); expected_accounts.push_back(MakeAccountToken(account1));
expected_accounts.push_back(MakeAccountToken(account_id2)); expected_accounts.push_back(MakeAccountToken(account2));
VerifyAccountTokens(expected_accounts, driver()->accounts()); VerifyAccountTokens(expected_accounts, driver()->accounts());
} }
...@@ -359,88 +303,88 @@ TEST_F(GCMAccountTrackerTest, AccountAdded) { ...@@ -359,88 +303,88 @@ TEST_F(GCMAccountTrackerTest, AccountAdded) {
tracker()->Start(); tracker()->Start();
driver()->ResetResults(); driver()->ResetResults();
CoreAccountId account_id1 = AddPrimaryAccount(kEmail1); CoreAccountInfo account1 = SetPrimaryAccount(kEmail1);
EXPECT_FALSE(driver()->update_accounts_called()); EXPECT_FALSE(driver()->update_accounts_called());
IssueAccessToken(account_id1); IssueAccessToken(account1.account_id);
EXPECT_TRUE(driver()->update_accounts_called()); EXPECT_TRUE(driver()->update_accounts_called());
std::vector<GCMClient::AccountTokenInfo> expected_accounts; std::vector<GCMClient::AccountTokenInfo> expected_accounts;
expected_accounts.push_back(MakeAccountToken(account_id1)); expected_accounts.push_back(MakeAccountToken(account1));
VerifyAccountTokens(expected_accounts, driver()->accounts()); VerifyAccountTokens(expected_accounts, driver()->accounts());
} }
TEST_F(GCMAccountTrackerTest, AccountRemoved) { TEST_F(GCMAccountTrackerTest, AccountRemoved) {
CoreAccountId account_id1 = AddPrimaryAccount(kEmail1); CoreAccountInfo account1 = SetPrimaryAccount(kEmail1);
CoreAccountId account_id2 = AddAccount(kEmail2); CoreAccountInfo account2 = AddAccount(kEmail2);
tracker()->Start(); tracker()->Start();
IssueAccessToken(account_id1); IssueAccessToken(account1.account_id);
IssueAccessToken(account_id2); IssueAccessToken(account2.account_id);
EXPECT_TRUE(driver()->update_accounts_called()); EXPECT_TRUE(driver()->update_accounts_called());
driver()->ResetResults(); driver()->ResetResults();
EXPECT_FALSE(driver()->update_accounts_called()); EXPECT_FALSE(driver()->update_accounts_called());
RemoveAccount(account_id2); RemoveAccount(account2.account_id);
EXPECT_TRUE(driver()->update_accounts_called()); EXPECT_TRUE(driver()->update_accounts_called());
std::vector<GCMClient::AccountTokenInfo> expected_accounts; std::vector<GCMClient::AccountTokenInfo> expected_accounts;
expected_accounts.push_back(MakeAccountToken(account_id1)); expected_accounts.push_back(MakeAccountToken(account1));
VerifyAccountTokens(expected_accounts, driver()->accounts()); VerifyAccountTokens(expected_accounts, driver()->accounts());
} }
TEST_F(GCMAccountTrackerTest, GetTokenFailed) { TEST_F(GCMAccountTrackerTest, GetTokenFailed) {
CoreAccountId account_id1 = AddPrimaryAccount(kEmail1); CoreAccountInfo account1 = SetPrimaryAccount(kEmail1);
CoreAccountId account_id2 = AddAccount(kEmail2); CoreAccountInfo account2 = AddAccount(kEmail2);
tracker()->Start(); tracker()->Start();
IssueAccessToken(account_id1); IssueAccessToken(account1.account_id);
EXPECT_FALSE(driver()->update_accounts_called()); EXPECT_FALSE(driver()->update_accounts_called());
IssueError(account_id2); IssueError(account2.account_id);
// Failed token is not retried any more. Account marked as removed. // Failed token is not retried any more. Account marked as removed.
EXPECT_EQ(0UL, tracker()->get_pending_token_request_count()); EXPECT_EQ(0UL, tracker()->get_pending_token_request_count());
EXPECT_TRUE(driver()->update_accounts_called()); EXPECT_TRUE(driver()->update_accounts_called());
std::vector<GCMClient::AccountTokenInfo> expected_accounts; std::vector<GCMClient::AccountTokenInfo> expected_accounts;
expected_accounts.push_back(MakeAccountToken(account_id1)); expected_accounts.push_back(MakeAccountToken(account1));
VerifyAccountTokens(expected_accounts, driver()->accounts()); VerifyAccountTokens(expected_accounts, driver()->accounts());
} }
TEST_F(GCMAccountTrackerTest, GetTokenFailedAccountRemoved) { TEST_F(GCMAccountTrackerTest, GetTokenFailedAccountRemoved) {
CoreAccountId account_id1 = AddPrimaryAccount(kEmail1); CoreAccountInfo account1 = SetPrimaryAccount(kEmail1);
CoreAccountId account_id2 = AddAccount(kEmail2); CoreAccountInfo account2 = AddAccount(kEmail2);
tracker()->Start(); tracker()->Start();
IssueAccessToken(account_id1); IssueAccessToken(account1.account_id);
driver()->ResetResults(); driver()->ResetResults();
RemoveAccount(account_id2); RemoveAccount(account2.account_id);
IssueError(account_id2); IssueError(account2.account_id);
EXPECT_TRUE(driver()->update_accounts_called()); EXPECT_TRUE(driver()->update_accounts_called());
std::vector<GCMClient::AccountTokenInfo> expected_accounts; std::vector<GCMClient::AccountTokenInfo> expected_accounts;
expected_accounts.push_back(MakeAccountToken(account_id1)); expected_accounts.push_back(MakeAccountToken(account1));
VerifyAccountTokens(expected_accounts, driver()->accounts()); VerifyAccountTokens(expected_accounts, driver()->accounts());
} }
TEST_F(GCMAccountTrackerTest, AccountRemovedWhileRequestsPending) { TEST_F(GCMAccountTrackerTest, AccountRemovedWhileRequestsPending) {
CoreAccountId account_id1 = AddPrimaryAccount(kEmail1); CoreAccountInfo account1 = SetPrimaryAccount(kEmail1);
CoreAccountId account_id2 = AddAccount(kEmail2); CoreAccountInfo account2 = AddAccount(kEmail2);
tracker()->Start(); tracker()->Start();
IssueAccessToken(account_id1); IssueAccessToken(account1.account_id);
EXPECT_FALSE(driver()->update_accounts_called()); EXPECT_FALSE(driver()->update_accounts_called());
RemoveAccount(account_id2); RemoveAccount(account2.account_id);
IssueAccessToken(account_id2); IssueAccessToken(account2.account_id);
EXPECT_TRUE(driver()->update_accounts_called()); EXPECT_TRUE(driver()->update_accounts_called());
std::vector<GCMClient::AccountTokenInfo> expected_accounts; std::vector<GCMClient::AccountTokenInfo> expected_accounts;
expected_accounts.push_back(MakeAccountToken(account_id1)); expected_accounts.push_back(MakeAccountToken(account1));
VerifyAccountTokens(expected_accounts, driver()->accounts()); VerifyAccountTokens(expected_accounts, driver()->accounts());
} }
...@@ -456,9 +400,8 @@ TEST_F(GCMAccountTrackerTest, TrackerObservesConnection) { ...@@ -456,9 +400,8 @@ TEST_F(GCMAccountTrackerTest, TrackerObservesConnection) {
// Makes sure that token fetching happens only after connection is established. // Makes sure that token fetching happens only after connection is established.
TEST_F(GCMAccountTrackerTest, PostponeTokenFetchingUntilConnected) { TEST_F(GCMAccountTrackerTest, PostponeTokenFetchingUntilConnected) {
driver()->SetConnected(false); driver()->SetConnected(false);
CoreAccountId account_id1 = StartPrimaryAccountAddition(kEmail1); CoreAccountInfo account1 = SetPrimaryAccount(kEmail1);
tracker()->Start(); tracker()->Start();
FinishAccountAddition(account_id1);
EXPECT_EQ(0UL, tracker()->get_pending_token_request_count()); EXPECT_EQ(0UL, tracker()->get_pending_token_request_count());
driver()->SetConnected(true); driver()->SetConnected(true);
...@@ -467,16 +410,14 @@ TEST_F(GCMAccountTrackerTest, PostponeTokenFetchingUntilConnected) { ...@@ -467,16 +410,14 @@ TEST_F(GCMAccountTrackerTest, PostponeTokenFetchingUntilConnected) {
} }
TEST_F(GCMAccountTrackerTest, InvalidateExpiredTokens) { TEST_F(GCMAccountTrackerTest, InvalidateExpiredTokens) {
CoreAccountId account_id1 = StartPrimaryAccountAddition(kEmail1); CoreAccountInfo account1 = SetPrimaryAccount(kEmail1);
CoreAccountId account_id2 = StartAccountAddition(kEmail2); CoreAccountInfo account2 = AddAccount(kEmail2);
tracker()->Start(); tracker()->Start();
FinishAccountAddition(account_id1);
FinishAccountAddition(account_id2);
EXPECT_EQ(2UL, tracker()->get_pending_token_request_count()); EXPECT_EQ(2UL, tracker()->get_pending_token_request_count());
IssueExpiredAccessToken(account_id1); IssueExpiredAccessToken(account1.account_id);
IssueAccessToken(account_id2); IssueAccessToken(account2.account_id);
// Because the first token is expired, we expect the sanitize to kick in and // Because the first token is expired, we expect the sanitize to kick in and
// clean it up before the SetAccessToken is called. This also means a new // clean it up before the SetAccessToken is called. This also means a new
// token request will be issued // token request will be issued
...@@ -491,17 +432,15 @@ TEST_F(GCMAccountTrackerTest, IsTokenFetchingRequired) { ...@@ -491,17 +432,15 @@ TEST_F(GCMAccountTrackerTest, IsTokenFetchingRequired) {
tracker()->Start(); tracker()->Start();
driver()->SetConnected(false); driver()->SetConnected(false);
EXPECT_FALSE(IsFetchingRequired()); EXPECT_FALSE(IsFetchingRequired());
CoreAccountId account_id1 = StartPrimaryAccountAddition(kEmail1); CoreAccountInfo account1 = SetPrimaryAccount(kEmail1);
FinishAccountAddition(account_id1);
EXPECT_TRUE(IsFetchingRequired()); EXPECT_TRUE(IsFetchingRequired());
driver()->SetConnected(true); driver()->SetConnected(true);
EXPECT_FALSE(IsFetchingRequired()); // Indicates that fetching has started. EXPECT_FALSE(IsFetchingRequired()); // Indicates that fetching has started.
IssueAccessToken(account_id1); IssueAccessToken(account1.account_id);
EXPECT_FALSE(IsFetchingRequired()); EXPECT_FALSE(IsFetchingRequired());
CoreAccountId account_id2 = StartAccountAddition(kEmail2); CoreAccountInfo account2 = AddAccount(kEmail2);
FinishAccountAddition(account_id2);
EXPECT_FALSE(IsFetchingRequired()); // Indicates that fetching has started. EXPECT_FALSE(IsFetchingRequired()); // Indicates that fetching has started.
// Disconnect the driver again so that the access token request being // Disconnect the driver again so that the access token request being
...@@ -511,7 +450,7 @@ TEST_F(GCMAccountTrackerTest, IsTokenFetchingRequired) { ...@@ -511,7 +450,7 @@ TEST_F(GCMAccountTrackerTest, IsTokenFetchingRequired) {
// because GCMAccountTracker didn't detect that a new access token needs to be // because GCMAccountTracker didn't detect that a new access token needs to be
// fetched). // fetched).
driver()->SetConnected(false); driver()->SetConnected(false);
IssueExpiredAccessToken(account_id2); IssueExpiredAccessToken(account2.account_id);
// Make sure that if the token was expired it is marked as being needed again. // Make sure that if the token was expired it is marked as being needed again.
EXPECT_TRUE(IsFetchingRequired()); EXPECT_TRUE(IsFetchingRequired());
...@@ -551,12 +490,12 @@ TEST_F(GCMAccountTrackerTest, IsTokenReportingRequired) { ...@@ -551,12 +490,12 @@ TEST_F(GCMAccountTrackerTest, IsTokenReportingRequired) {
driver()->SetLastTokenFetchTime(base::Time::Now()); driver()->SetLastTokenFetchTime(base::Time::Now());
EXPECT_FALSE(IsTokenReportingRequired()); EXPECT_FALSE(IsTokenReportingRequired());
CoreAccountId account_id1 = AddPrimaryAccount(kEmail1); CoreAccountInfo account1 = SetPrimaryAccount(kEmail1);
IssueAccessToken(account_id1); IssueAccessToken(account1.account_id);
driver()->ResetResults(); driver()->ResetResults();
// Reporting was triggered, which means testing for required will give false, // Reporting was triggered, which means testing for required will give false,
// but we have the update call. // but we have the update call.
RemoveAccount(account_id1); RemoveAccount(account1.account_id);
EXPECT_TRUE(driver()->update_accounts_called()); EXPECT_TRUE(driver()->update_accounts_called());
EXPECT_FALSE(IsTokenReportingRequired()); EXPECT_FALSE(IsTokenReportingRequired());
} }
......
...@@ -112,7 +112,7 @@ void GCMProfileService::IdentityObserver::StartAccountTracker( ...@@ -112,7 +112,7 @@ void GCMProfileService::IdentityObserver::StartAccountTracker(
return; return;
std::unique_ptr<AccountTracker> gaia_account_tracker( std::unique_ptr<AccountTracker> gaia_account_tracker(
new AccountTracker(identity_manager_, std::move(url_loader_factory))); new AccountTracker(identity_manager_));
gcm_account_tracker_.reset(new GCMAccountTracker( gcm_account_tracker_.reset(new GCMAccountTracker(
std::move(gaia_account_tracker), identity_manager_, driver_)); std::move(gaia_account_tracker), identity_manager_, driver_));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment