// Copyright 2013 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 "chrome/browser/extensions/api/identity/account_tracker.h" #include <algorithm> #include <vector> #include "base/strings/stringprintf.h" #include "chrome/browser/signin/fake_profile_oauth2_token_service.h" #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h" #include "chrome/browser/signin/fake_signin_manager.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/test/base/testing_profile.h" #include "components/signin/core/browser/signin_manager_base.h" #include "content/public/test/test_browser_thread_bundle.h" #include "google_apis/gaia/gaia_oauth_client.h" #include "net/http/http_status_code.h" #include "net/url_request/test_url_fetcher_factory.h" #include "net/url_request/url_fetcher_delegate.h" #include "net/url_request/url_request_test_util.h" #include "testing/gtest/include/gtest/gtest.h" // TODO(courage): Account removal really only applies to the primary account, // because that's the only account tracked by the SigninManager. Many of the // tests here remove non-primary accounts. They still properly test the account // state machine, but it may be confusing to readers. Update these tests to // avoid causing confusion. namespace { const char kPrimaryAccountKey[] = "primary_account@example.com"; const char kFakeGaiaId[] = "8675309"; enum TrackingEventType { ADDED, REMOVED, SIGN_IN, SIGN_OUT }; class TrackingEvent { public: TrackingEvent(TrackingEventType type, const std::string& account_key, const std::string& gaia_id) : type_(type), account_key_(account_key), gaia_id_(gaia_id) {} TrackingEvent(TrackingEventType type, const std::string& account_key) : type_(type), account_key_(account_key), gaia_id_(kFakeGaiaId) {} bool operator==(const TrackingEvent& event) const { return type_ == event.type_ && account_key_ == event.account_key_ && gaia_id_ == event.gaia_id_; } std::string ToString() const { const char * typestr = "INVALID"; switch (type_) { case ADDED: typestr = "ADD"; break; case REMOVED: typestr = "REM"; break; case SIGN_IN: typestr = " IN"; break; case SIGN_OUT: typestr = "OUT"; break; } return base::StringPrintf("{ type: %s, email: %s, gaia: %s }", typestr, account_key_.c_str(), gaia_id_.c_str()); } private: friend bool CompareByUser(TrackingEvent a, TrackingEvent b); TrackingEventType type_; std::string account_key_; std::string gaia_id_; }; bool CompareByUser(TrackingEvent a, TrackingEvent b) { return a.account_key_ < b.account_key_; } std::string Str(const std::vector<TrackingEvent>& events) { std::string str = "["; bool needs_comma = false; for (std::vector<TrackingEvent>::const_iterator it = events.begin(); it != events.end(); ++it) { if (needs_comma) str += ",\n "; needs_comma = true; str += it->ToString(); } str += "]"; return str; } } // namespace namespace extensions { class AccountTrackerObserver : public AccountTracker::Observer { public: AccountTrackerObserver() {} virtual ~AccountTrackerObserver() {} testing::AssertionResult CheckEvents(); testing::AssertionResult CheckEvents(const TrackingEvent& e1); testing::AssertionResult CheckEvents(const TrackingEvent& e1, const TrackingEvent& e2); testing::AssertionResult CheckEvents(const TrackingEvent& e1, const TrackingEvent& e2, const TrackingEvent& e3); testing::AssertionResult CheckEvents(const TrackingEvent& e1, const TrackingEvent& e2, const TrackingEvent& e3, const TrackingEvent& e4); testing::AssertionResult CheckEvents(const TrackingEvent& e1, const TrackingEvent& e2, const TrackingEvent& e3, const TrackingEvent& e4, const TrackingEvent& e5); testing::AssertionResult CheckEvents(const TrackingEvent& e1, const TrackingEvent& e2, const TrackingEvent& e3, const TrackingEvent& e4, const TrackingEvent& e5, const TrackingEvent& e6); void SortEventsByUser(); // AccountTracker::Observer implementation virtual void OnAccountAdded(const AccountIds& ids) OVERRIDE; virtual void OnAccountRemoved(const AccountIds& ids) OVERRIDE; virtual void OnAccountSignInChanged(const AccountIds& ids, bool is_signed_in) OVERRIDE; private: testing::AssertionResult CheckEvents( const std::vector<TrackingEvent>& events); std::vector<TrackingEvent> events_; }; void AccountTrackerObserver::OnAccountAdded(const AccountIds& ids) { events_.push_back(TrackingEvent(ADDED, ids.email, ids.gaia)); } void AccountTrackerObserver::OnAccountRemoved(const AccountIds& ids) { events_.push_back(TrackingEvent(REMOVED, ids.email, ids.gaia)); } void AccountTrackerObserver::OnAccountSignInChanged(const AccountIds& ids, bool is_signed_in) { events_.push_back( TrackingEvent(is_signed_in ? SIGN_IN : SIGN_OUT, ids.email, ids.gaia)); } void AccountTrackerObserver::SortEventsByUser() { std::stable_sort(events_.begin(), events_.end(), CompareByUser); } testing::AssertionResult AccountTrackerObserver::CheckEvents() { std::vector<TrackingEvent> events; return CheckEvents(events); } testing::AssertionResult AccountTrackerObserver::CheckEvents( const TrackingEvent& e1) { std::vector<TrackingEvent> events; events.push_back(e1); return CheckEvents(events); } testing::AssertionResult AccountTrackerObserver::CheckEvents( const TrackingEvent& e1, const TrackingEvent& e2) { std::vector<TrackingEvent> events; events.push_back(e1); events.push_back(e2); return CheckEvents(events); } testing::AssertionResult AccountTrackerObserver::CheckEvents( const TrackingEvent& e1, const TrackingEvent& e2, const TrackingEvent& e3) { std::vector<TrackingEvent> events; events.push_back(e1); events.push_back(e2); events.push_back(e3); return CheckEvents(events); } testing::AssertionResult AccountTrackerObserver::CheckEvents( const TrackingEvent& e1, const TrackingEvent& e2, const TrackingEvent& e3, const TrackingEvent& e4) { std::vector<TrackingEvent> events; events.push_back(e1); events.push_back(e2); events.push_back(e3); events.push_back(e4); return CheckEvents(events); } testing::AssertionResult AccountTrackerObserver::CheckEvents( const TrackingEvent& e1, const TrackingEvent& e2, const TrackingEvent& e3, const TrackingEvent& e4, const TrackingEvent& e5) { std::vector<TrackingEvent> events; events.push_back(e1); events.push_back(e2); events.push_back(e3); events.push_back(e4); events.push_back(e5); return CheckEvents(events); } testing::AssertionResult AccountTrackerObserver::CheckEvents( const TrackingEvent& e1, const TrackingEvent& e2, const TrackingEvent& e3, const TrackingEvent& e4, const TrackingEvent& e5, const TrackingEvent& e6) { std::vector<TrackingEvent> events; events.push_back(e1); events.push_back(e2); events.push_back(e3); events.push_back(e4); events.push_back(e5); events.push_back(e6); return CheckEvents(events); } testing::AssertionResult AccountTrackerObserver::CheckEvents( const std::vector<TrackingEvent>& events) { std::string maybe_newline = (events.size() + events_.size()) > 2 ? "\n" : ""; testing::AssertionResult result( (events_ == events) ? testing::AssertionSuccess() : (testing::AssertionFailure() << "Expected " << maybe_newline << Str(events) << ", " << maybe_newline << "Got " << maybe_newline << Str(events_))); events_.clear(); return result; } class IdentityAccountTrackerTest : public testing::Test { public: IdentityAccountTrackerTest() {} virtual ~IdentityAccountTrackerTest() {} virtual void SetUp() OVERRIDE { TestingProfile::Builder builder; builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(), BuildFakeProfileOAuth2TokenService); builder.AddTestingFactory(SigninManagerFactory::GetInstance(), FakeSigninManagerBase::Build); test_profile_ = builder.Build(); fake_oauth2_token_service_ = static_cast<FakeProfileOAuth2TokenService*>( ProfileOAuth2TokenServiceFactory::GetForProfile(test_profile_.get())); fake_signin_manager_ = static_cast<FakeSigninManagerForTesting*>( SigninManagerFactory::GetForProfile(test_profile_.get())); fake_signin_manager_->SetAuthenticatedUsername(kPrimaryAccountKey); account_tracker_.reset(new AccountTracker(test_profile_.get())); account_tracker_->AddObserver(&observer_); } virtual void TearDown() OVERRIDE { account_tracker_->RemoveObserver(&observer_); account_tracker_->Shutdown(); } Profile* profile() { return test_profile_.get(); } AccountTrackerObserver* observer() { return &observer_; } AccountTracker* account_tracker() { return account_tracker_.get(); } // Helpers to pass fake events to the tracker. void NotifyRemoveAccount(const std::string& username) { #if !defined(OS_CHROMEOS) if (username == kPrimaryAccountKey) fake_signin_manager_->SignOut(); else account_tracker()->GoogleSignedOut(username); #else account_tracker()->GoogleSignedOut(username); #endif } void NotifyTokenAvailable(const std::string& username) { fake_oauth2_token_service_->IssueRefreshTokenForUser(username, "refresh_token"); #if !defined(OS_CHROMEOS) if (username == kPrimaryAccountKey) fake_signin_manager_->OnExternalSigninCompleted(username); #endif } void NotifyTokenRevoked(const std::string& username) { fake_oauth2_token_service_->IssueRefreshTokenForUser(username, std::string()); } // Helpers to fake access token and user info fetching void IssueAccessToken() { fake_oauth2_token_service_->IssueTokenForAllPendingRequests( "access_token", base::Time::Max()); } std::string GetValidTokenInfoResponse(const std::string email) { return std::string("{ \"id\": \"") + kFakeGaiaId + "\" }"; } void ReturnOAuthUrlFetchResults(int fetcher_id, net::HttpStatusCode response_code, const std::string& response_string); void ReturnOAuthUrlFetchSuccess(const std::string& account_key); void ReturnOAuthUrlFetchFailure(const std::string& account_key); private: scoped_ptr<TestingProfile> test_profile_; net::TestURLFetcherFactory test_fetcher_factory_; FakeProfileOAuth2TokenService* fake_oauth2_token_service_; FakeSigninManagerForTesting* fake_signin_manager_; content::TestBrowserThreadBundle thread_bundle_; scoped_ptr<AccountTracker> account_tracker_; AccountTrackerObserver observer_; }; void IdentityAccountTrackerTest::ReturnOAuthUrlFetchResults( int fetcher_id, net::HttpStatusCode response_code, const std::string& response_string) { net::TestURLFetcher* fetcher = test_fetcher_factory_.GetFetcherByID(fetcher_id); ASSERT_TRUE(fetcher); fetcher->set_response_code(response_code); fetcher->SetResponseString(response_string); fetcher->delegate()->OnURLFetchComplete(fetcher); } void IdentityAccountTrackerTest::ReturnOAuthUrlFetchSuccess( const std::string& account_key) { IssueAccessToken(); ReturnOAuthUrlFetchResults(gaia::GaiaOAuthClient::kUrlFetcherId, net::HTTP_OK, GetValidTokenInfoResponse(account_key)); } void IdentityAccountTrackerTest::ReturnOAuthUrlFetchFailure( const std::string& account_key) { IssueAccessToken(); ReturnOAuthUrlFetchResults( gaia::GaiaOAuthClient::kUrlFetcherId, net::HTTP_BAD_REQUEST, ""); } TEST_F(IdentityAccountTrackerTest, Available) { NotifyTokenAvailable("user@example.com"); EXPECT_TRUE(observer()->CheckEvents()); ReturnOAuthUrlFetchSuccess("user@example.com"); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(ADDED, "user@example.com", kFakeGaiaId), TrackingEvent(SIGN_IN, "user@example.com", kFakeGaiaId))); } TEST_F(IdentityAccountTrackerTest, Revoke) { account_tracker()->OnRefreshTokenRevoked("user@example.com"); EXPECT_TRUE(observer()->CheckEvents()); } TEST_F(IdentityAccountTrackerTest, Remove) { NotifyRemoveAccount("user@example.com"); EXPECT_TRUE(observer()->CheckEvents()); } TEST_F(IdentityAccountTrackerTest, AvailableRemoveFetchCancelAvailable) { NotifyTokenAvailable("user@example.com"); NotifyRemoveAccount("user@example.com"); EXPECT_TRUE(observer()->CheckEvents()); NotifyTokenAvailable("user@example.com"); ReturnOAuthUrlFetchSuccess("user@example.com"); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(ADDED, "user@example.com", kFakeGaiaId), TrackingEvent(SIGN_IN, "user@example.com", kFakeGaiaId))); } TEST_F(IdentityAccountTrackerTest, AvailableRemoveAvailable) { NotifyTokenAvailable("user@example.com"); ReturnOAuthUrlFetchSuccess("user@example.com"); NotifyRemoveAccount("user@example.com"); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(ADDED, "user@example.com", kFakeGaiaId), TrackingEvent(SIGN_IN, "user@example.com", kFakeGaiaId), TrackingEvent(SIGN_OUT, "user@example.com", kFakeGaiaId), TrackingEvent(REMOVED, "user@example.com", kFakeGaiaId))); NotifyTokenAvailable("user@example.com"); ReturnOAuthUrlFetchSuccess("user@example.com"); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(ADDED, "user@example.com", kFakeGaiaId), TrackingEvent(SIGN_IN, "user@example.com", kFakeGaiaId))); } TEST_F(IdentityAccountTrackerTest, AvailableRevokeAvailable) { NotifyTokenAvailable("user@example.com"); ReturnOAuthUrlFetchSuccess("user@example.com"); NotifyTokenRevoked("user@example.com"); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(ADDED, "user@example.com", kFakeGaiaId), TrackingEvent(SIGN_IN, "user@example.com", kFakeGaiaId), TrackingEvent(SIGN_OUT, "user@example.com", kFakeGaiaId))); NotifyTokenAvailable("user@example.com"); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(SIGN_IN, "user@example.com", kFakeGaiaId))); } TEST_F(IdentityAccountTrackerTest, AvailableRevokeAvailableWithPendingFetch) { NotifyTokenAvailable("user@example.com"); NotifyTokenRevoked("user@example.com"); EXPECT_TRUE(observer()->CheckEvents()); NotifyTokenAvailable("user@example.com"); ReturnOAuthUrlFetchSuccess("user@example.com"); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(ADDED, "user@example.com", kFakeGaiaId), TrackingEvent(SIGN_IN, "user@example.com", kFakeGaiaId))); } TEST_F(IdentityAccountTrackerTest, AvailableRevokeRemove) { NotifyTokenAvailable("user@example.com"); ReturnOAuthUrlFetchSuccess("user@example.com"); NotifyTokenRevoked("user@example.com"); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(ADDED, "user@example.com", kFakeGaiaId), TrackingEvent(SIGN_IN, "user@example.com", kFakeGaiaId), TrackingEvent(SIGN_OUT, "user@example.com", kFakeGaiaId))); NotifyRemoveAccount("user@example.com"); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(REMOVED, "user@example.com", kFakeGaiaId))); } TEST_F(IdentityAccountTrackerTest, AvailableRevokeRevoke) { NotifyTokenAvailable("user@example.com"); ReturnOAuthUrlFetchSuccess("user@example.com"); NotifyTokenRevoked("user@example.com"); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(ADDED, "user@example.com", kFakeGaiaId), TrackingEvent(SIGN_IN, "user@example.com", kFakeGaiaId), TrackingEvent(SIGN_OUT, "user@example.com", kFakeGaiaId))); NotifyTokenRevoked("user@example.com"); EXPECT_TRUE(observer()->CheckEvents()); } TEST_F(IdentityAccountTrackerTest, AvailableAvailable) { NotifyTokenAvailable("user@example.com"); ReturnOAuthUrlFetchSuccess("user@example.com"); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(ADDED, "user@example.com", kFakeGaiaId), TrackingEvent(SIGN_IN, "user@example.com", kFakeGaiaId))); NotifyTokenAvailable("user@example.com"); EXPECT_TRUE(observer()->CheckEvents()); } TEST_F(IdentityAccountTrackerTest, TwoAccounts) { NotifyTokenAvailable("alpha@example.com"); ReturnOAuthUrlFetchSuccess("alpha@example.com"); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(ADDED, "alpha@example.com", kFakeGaiaId), TrackingEvent(SIGN_IN, "alpha@example.com", kFakeGaiaId))); NotifyTokenAvailable("beta@example.com"); ReturnOAuthUrlFetchSuccess("beta@example.com"); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(ADDED, "beta@example.com", kFakeGaiaId), TrackingEvent(SIGN_IN, "beta@example.com", kFakeGaiaId))); NotifyRemoveAccount("alpha@example.com"); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(SIGN_OUT, "alpha@example.com", kFakeGaiaId), TrackingEvent(REMOVED, "alpha@example.com", kFakeGaiaId))); NotifyRemoveAccount("beta@example.com"); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(SIGN_OUT, "beta@example.com", kFakeGaiaId), TrackingEvent(REMOVED, "beta@example.com", kFakeGaiaId))); } TEST_F(IdentityAccountTrackerTest, GlobalErrors) { NotifyTokenAvailable("alpha@example.com"); ReturnOAuthUrlFetchSuccess("alpha@example.com"); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(ADDED, "alpha@example.com", kFakeGaiaId), TrackingEvent(SIGN_IN, "alpha@example.com", kFakeGaiaId))); NotifyTokenAvailable("beta@example.com"); ReturnOAuthUrlFetchSuccess("beta@example.com"); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(ADDED, "beta@example.com", kFakeGaiaId), TrackingEvent(SIGN_IN, "beta@example.com", kFakeGaiaId))); EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(), account_tracker()->GetAuthStatus()); account_tracker()->ReportAuthError( "beta@example.com", GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED)); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(SIGN_OUT, "beta@example.com", kFakeGaiaId))); EXPECT_EQ(GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED), account_tracker()->GetAuthStatus()); account_tracker()->ReportAuthError( "alpha@example.com", GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED)); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(SIGN_OUT, "alpha@example.com", kFakeGaiaId))); EXPECT_EQ(GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED), account_tracker()->GetAuthStatus()); NotifyRemoveAccount("alpha@example.com"); EXPECT_EQ(GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED), account_tracker()->GetAuthStatus()); NotifyTokenAvailable("beta@example.com"); EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(), account_tracker()->GetAuthStatus()); } TEST_F(IdentityAccountTrackerTest, AvailableTokenFetchFailAvailable) { NotifyTokenAvailable("alpha@example.com"); ReturnOAuthUrlFetchFailure("alpha@example.com"); EXPECT_TRUE(observer()->CheckEvents()); NotifyTokenAvailable("user@example.com"); ReturnOAuthUrlFetchSuccess("user@example.com"); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(ADDED, "user@example.com", kFakeGaiaId), TrackingEvent(SIGN_IN, "user@example.com", kFakeGaiaId))); } // The Chrome OS fake sign-in manager doesn't do sign-in or sign-out. #if !defined(OS_CHROMEOS) TEST_F(IdentityAccountTrackerTest, PrimarySignOutSignIn) { // Initial sign-in wasn't tracked due to test set-up, so there are no events. NotifyRemoveAccount(kPrimaryAccountKey); EXPECT_TRUE(observer()->CheckEvents()); NotifyTokenAvailable(kPrimaryAccountKey); ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(ADDED, kPrimaryAccountKey, kFakeGaiaId), TrackingEvent(SIGN_IN, kPrimaryAccountKey, kFakeGaiaId))); NotifyRemoveAccount(kPrimaryAccountKey); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(SIGN_OUT, kPrimaryAccountKey, kFakeGaiaId), TrackingEvent(REMOVED, kPrimaryAccountKey, kFakeGaiaId))); } TEST_F(IdentityAccountTrackerTest, PrimarySignOutSignInTwoAccounts) { NotifyTokenAvailable("alpha@example.com"); ReturnOAuthUrlFetchSuccess("alpha@example.com"); NotifyTokenAvailable("beta@example.com"); ReturnOAuthUrlFetchSuccess("beta@example.com"); observer()->SortEventsByUser(); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(ADDED, "alpha@example.com", kFakeGaiaId), TrackingEvent(SIGN_IN, "alpha@example.com", kFakeGaiaId), TrackingEvent(ADDED, "beta@example.com", kFakeGaiaId), TrackingEvent(SIGN_IN, "beta@example.com", kFakeGaiaId))); // Initial sign-in wasn't tracked due to test set-up, so there are no events // for that account yet. NotifyRemoveAccount(kPrimaryAccountKey); observer()->SortEventsByUser(); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(SIGN_OUT, "alpha@example.com", kFakeGaiaId), TrackingEvent(REMOVED, "alpha@example.com", kFakeGaiaId), TrackingEvent(SIGN_OUT, "beta@example.com", kFakeGaiaId), TrackingEvent(REMOVED, "beta@example.com", kFakeGaiaId))); // No events fire at all while profile is signed out. NotifyTokenRevoked("alpha@example.com"); NotifyTokenAvailable("gamma@example.com"); EXPECT_TRUE(observer()->CheckEvents()); // Signing the profile in again will resume tracking all accounts. NotifyTokenAvailable(kPrimaryAccountKey); ReturnOAuthUrlFetchSuccess("beta@example.com"); ReturnOAuthUrlFetchSuccess("gamma@example.com"); ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey); observer()->SortEventsByUser(); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(ADDED, "beta@example.com", kFakeGaiaId), TrackingEvent(SIGN_IN, "beta@example.com", kFakeGaiaId), TrackingEvent(ADDED, "gamma@example.com", kFakeGaiaId), TrackingEvent(SIGN_IN, "gamma@example.com", kFakeGaiaId), TrackingEvent(ADDED, kPrimaryAccountKey, kFakeGaiaId), TrackingEvent(SIGN_IN, kPrimaryAccountKey, kFakeGaiaId))); // Revoking the primary token does not affect other accounts. NotifyTokenRevoked(kPrimaryAccountKey); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(SIGN_OUT, kPrimaryAccountKey, kFakeGaiaId))); NotifyTokenAvailable(kPrimaryAccountKey); EXPECT_TRUE(observer()->CheckEvents( TrackingEvent(SIGN_IN, kPrimaryAccountKey, kFakeGaiaId))); } #endif // !defined(OS_CHROMEOS) } // namespace extensions