// Copyright 2018 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/chromeos/oauth2_token_service_delegate.h"

#include <memory>
#include <set>
#include <string>
#include <utility>

#include "base/bind.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/stl_util.h"
#include "base/test/scoped_task_environment.h"
#include "chromeos/account_manager/account_manager.h"
#include "components/signin/core/browser/account_info.h"
#include "components/signin/core/browser/account_tracker_service.h"
#include "components/signin/core/browser/signin_pref_names.h"
#include "components/signin/core/browser/test_signin_client.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "google_apis/gaia/gaia_urls.h"
#include "google_apis/gaia/oauth2_access_token_consumer.h"
#include "google_apis/gaia/oauth2_token_service.h"
#include "google_apis/gaia/oauth2_token_service_test_util.h"
#include "services/network/test/test_network_connection_tracker.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace chromeos {

namespace {

using account_manager::AccountType::ACCOUNT_TYPE_GAIA;
using account_manager::AccountType::ACCOUNT_TYPE_ACTIVE_DIRECTORY;

constexpr char kGaiaId[] = "gaia-id";
constexpr char kGaiaToken[] = "gaia-token";
constexpr char kUserEmail[] = "user@gmail.com";

class AccessTokenConsumer : public OAuth2AccessTokenConsumer {
 public:
  AccessTokenConsumer() = default;
  ~AccessTokenConsumer() override = default;

  void OnGetTokenSuccess(const TokenResponse& token_response) override {
    ++num_access_token_fetch_success_;
  }

  void OnGetTokenFailure(const GoogleServiceAuthError& error) override {
    ++num_access_token_fetch_failure_;
  }

  int num_access_token_fetch_success_ = 0;
  int num_access_token_fetch_failure_ = 0;

 private:
  DISALLOW_COPY_AND_ASSIGN(AccessTokenConsumer);
};

class TokenServiceObserver : public OAuth2TokenService::Observer {
 public:
  // |delegate| is a non-owning pointer to an |OAuth2TokenServiceDelegate| that
  // MUST outlive |this| instance.
  explicit TokenServiceObserver(OAuth2TokenServiceDelegate* delegate)
      : delegate_(delegate) {
    delegate_->AddObserver(this);
  }

  ~TokenServiceObserver() override { delegate_->RemoveObserver(this); }

  void StartBatchChanges() {
    EXPECT_FALSE(is_inside_batch_);
    is_inside_batch_ = true;

    // Start a new batch
    batch_change_records_.emplace_back(std::vector<std::string>());
  }

  void OnEndBatchChanges() override {
    EXPECT_TRUE(is_inside_batch_);
    is_inside_batch_ = false;
  }

  void OnRefreshTokenAvailable(const std::string& account_id) override {
    if (!is_inside_batch_)
      StartBatchChanges();

    // We should not be seeing any cached errors for a freshly updated account,
    // except when they have been generated by us (i.e.
    // CREDENTIALS_REJECTED_BY_CLIENT).
    const GoogleServiceAuthError error = delegate_->GetAuthError(account_id);
    EXPECT_TRUE((error == GoogleServiceAuthError::AuthErrorNone()) ||
                (error.state() ==
                     GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS &&
                 error.GetInvalidGaiaCredentialsReason() ==
                     GoogleServiceAuthError::InvalidGaiaCredentialsReason::
                         CREDENTIALS_REJECTED_BY_CLIENT));

    account_ids_.insert(account_id);

    // Record the |account_id| in the last batch.
    batch_change_records_.rbegin()->emplace_back(account_id);
  }

  void OnRefreshTokenRevoked(const std::string& account_id) override {
    if (!is_inside_batch_)
      StartBatchChanges();

    account_ids_.erase(account_id);
    // Record the |account_id| in the last batch.
    batch_change_records_.rbegin()->emplace_back(account_id);
  }

  void OnAuthErrorChanged(const std::string& account_id,
                          const GoogleServiceAuthError& auth_error) override {
    last_err_account_id_ = account_id;
    last_err_ = auth_error;
  }

  std::string last_err_account_id_;
  GoogleServiceAuthError last_err_;
  std::set<std::string> account_ids_;
  bool is_inside_batch_ = false;

  // Records batch changes for later verification. Each index of this vector
  // represents a batch change. Each batch change is a vector of account ids for
  // which |OnRefreshTokenAvailable| is called.
  std::vector<std::vector<std::string>> batch_change_records_;

  // Non-owning pointer.
  OAuth2TokenServiceDelegate* const delegate_;
};

}  // namespace

class CrOSOAuthDelegateTest : public testing::Test {
 public:
  CrOSOAuthDelegateTest() {}
  ~CrOSOAuthDelegateTest() override = default;

 protected:
  void SetUp() override {
    ASSERT_TRUE(tmp_dir_.CreateUniqueTempDir());
    AccountTrackerService::RegisterPrefs(pref_service_.registry());

    client_ = std::make_unique<TestSigninClient>(&pref_service_);
    account_manager_.Initialize(tmp_dir_.GetPath(),
                                client_->GetURLLoaderFactory(),
                                immediate_callback_runner_);
    task_environment_.RunUntilIdle();

    account_tracker_service_.Initialize(&pref_service_, base::FilePath());

    account_info_ = CreateAccountInfoTestFixture(kGaiaId, kUserEmail);
    account_tracker_service_.SeedAccountInfo(account_info_);
    gaia_account_key_ = {account_info_.gaia, ACCOUNT_TYPE_GAIA};
    ad_account_key_ = {"object-guid", ACCOUNT_TYPE_ACTIVE_DIRECTORY};

    delegate_ = std::make_unique<ChromeOSOAuth2TokenServiceDelegate>(
        &account_tracker_service_,
        network::TestNetworkConnectionTracker::GetInstance(),
        &account_manager_);
    delegate_->LoadCredentials(
        account_info_.account_id /* primary_account_id */);
  }

  AccountInfo CreateAccountInfoTestFixture(const std::string& gaia_id,
                                           const std::string& email) {
    AccountInfo account_info;

    account_info.gaia = gaia_id;
    account_info.email = email;
    account_info.full_name = "name";
    account_info.given_name = "name";
    account_info.hosted_domain = "example.com";
    account_info.locale = "en";
    account_info.picture_url = "https://example.com";
    account_info.is_child_account = false;
    account_info.account_id = account_tracker_service_.PickAccountIdForAccount(
        account_info.gaia, account_info.email);

    // Cannot use |ASSERT_TRUE| due to a |void| return type in an |ASSERT_TRUE|
    // branch.
    EXPECT_TRUE(account_info.IsValid());

    return account_info;
  }

  void AddSuccessfulOAuthTokenResponse() {
    client_->test_url_loader_factory()->AddResponse(
        GaiaUrls::GetInstance()->oauth2_token_url().spec(),
        GetValidTokenResponse("token", 3600));
  }

  base::test::ScopedTaskEnvironment task_environment_;

  base::ScopedTempDir tmp_dir_;
  AccountInfo account_info_;
  AccountManager::AccountKey gaia_account_key_;
  AccountManager::AccountKey ad_account_key_;
  AccountTrackerService account_tracker_service_;
  AccountManager account_manager_;
  std::unique_ptr<ChromeOSOAuth2TokenServiceDelegate> delegate_;
  AccountManager::DelayNetworkCallRunner immediate_callback_runner_ =
      base::BindRepeating(
          [](base::OnceClosure closure) -> void { std::move(closure).Run(); });
  sync_preferences::TestingPrefServiceSyncable pref_service_;
  std::unique_ptr<TestSigninClient> client_;

 private:
  DISALLOW_COPY_AND_ASSIGN(CrOSOAuthDelegateTest);
};

TEST_F(CrOSOAuthDelegateTest,
       RefreshTokenIsAvailableReturnsTrueForValidGaiaTokens) {
  EXPECT_EQ(OAuth2TokenServiceDelegate::LoadCredentialsState::
                LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
            delegate_->load_credentials_state());

  EXPECT_FALSE(delegate_->RefreshTokenIsAvailable(account_info_.account_id));
  EXPECT_FALSE(
      base::ContainsValue(delegate_->GetAccounts(), account_info_.account_id));

  account_manager_.UpsertAccount(gaia_account_key_, kUserEmail, kGaiaToken);

  EXPECT_TRUE(delegate_->RefreshTokenIsAvailable(account_info_.account_id));
  EXPECT_TRUE(
      base::ContainsValue(delegate_->GetAccounts(), account_info_.account_id));
}

TEST_F(CrOSOAuthDelegateTest,
       RefreshTokenIsAvailableReturnsTrueForInvalidGaiaTokens) {
  EXPECT_EQ(OAuth2TokenServiceDelegate::LoadCredentialsState::
                LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
            delegate_->load_credentials_state());

  EXPECT_FALSE(delegate_->RefreshTokenIsAvailable(account_info_.account_id));
  EXPECT_FALSE(
      base::ContainsValue(delegate_->GetAccounts(), account_info_.account_id));

  account_manager_.UpsertAccount(gaia_account_key_, kUserEmail,
                                 AccountManager::kInvalidToken);

  EXPECT_TRUE(delegate_->RefreshTokenIsAvailable(account_info_.account_id));
  EXPECT_TRUE(
      base::ContainsValue(delegate_->GetAccounts(), account_info_.account_id));
}

TEST_F(CrOSOAuthDelegateTest, ObserversAreNotifiedOnAuthErrorChange) {
  TokenServiceObserver observer(delegate_.get());
  auto error =
      GoogleServiceAuthError(GoogleServiceAuthError::State::SERVICE_ERROR);

  delegate_->UpdateAuthError(account_info_.account_id, error);
  EXPECT_EQ(error, delegate_->GetAuthError(account_info_.account_id));
  EXPECT_EQ(account_info_.account_id, observer.last_err_account_id_);
  EXPECT_EQ(error, observer.last_err_);
}

TEST_F(CrOSOAuthDelegateTest, ObserversAreNotifiedOnCredentialsInsertion) {
  TokenServiceObserver observer(delegate_.get());
  delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);

  EXPECT_EQ(1UL, observer.account_ids_.size());
  EXPECT_EQ(account_info_.account_id, *observer.account_ids_.begin());
  EXPECT_EQ(account_info_.account_id, observer.last_err_account_id_);
  EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(), observer.last_err_);
}

TEST_F(CrOSOAuthDelegateTest,
       ObserversDoNotSeeCachedErrorsOnCredentialsUpdate) {
  TokenServiceObserver observer(delegate_.get());
  auto error =
      GoogleServiceAuthError(GoogleServiceAuthError::State::SERVICE_ERROR);
  delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);
  // Deliberately add an error.
  delegate_->UpdateAuthError(account_info_.account_id, error);

  // Update credentials. The delegate will check if see cached errors.
  delegate_->UpdateCredentials(account_info_.account_id, "new-token");
}

TEST_F(CrOSOAuthDelegateTest, DummyTokensArePreEmptivelyRejected) {
  TokenServiceObserver observer(delegate_.get());
  delegate_->UpdateCredentials(account_info_.account_id,
                               AccountManager::kInvalidToken);

  const GoogleServiceAuthError error =
      delegate_->GetAuthError(account_info_.account_id);
  EXPECT_EQ(GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS,
            error.state());
  EXPECT_EQ(GoogleServiceAuthError::InvalidGaiaCredentialsReason::
                CREDENTIALS_REJECTED_BY_CLIENT,
            error.GetInvalidGaiaCredentialsReason());

  // Observer notification should also have notified about the same error.
  EXPECT_EQ(error, observer.last_err_);
  EXPECT_EQ(account_info_.account_id, observer.last_err_account_id_);
}

TEST_F(CrOSOAuthDelegateTest, ObserversAreNotifiedOnCredentialsUpdate) {
  TokenServiceObserver observer(delegate_.get());
  delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);

  EXPECT_EQ(1UL, observer.account_ids_.size());
  EXPECT_EQ(account_info_.account_id, *observer.account_ids_.begin());
  EXPECT_EQ(account_info_.account_id, observer.last_err_account_id_);
  EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(), observer.last_err_);
}

TEST_F(CrOSOAuthDelegateTest,
       ObserversAreNotNotifiedIfCredentialsAreNotUpdated) {
  TokenServiceObserver observer(delegate_.get());

  delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);
  observer.account_ids_.clear();
  observer.last_err_account_id_ = std::string();
  delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);

  EXPECT_TRUE(observer.account_ids_.empty());
  EXPECT_EQ(std::string(), observer.last_err_account_id_);
}

TEST_F(CrOSOAuthDelegateTest,
       BatchChangeObserversAreNotifiedOnCredentialsUpdate) {
  TokenServiceObserver observer(delegate_.get());
  delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);

  EXPECT_EQ(1UL, observer.batch_change_records_.size());
  EXPECT_EQ(1UL, observer.batch_change_records_[0].size());
  EXPECT_EQ(account_info_.account_id, observer.batch_change_records_[0][0]);
}

// If observers register themselves with |OAuth2TokenServiceDelegate| before
// |AccountManager| has been initialized, they should receive all the accounts
// stored in |AccountManager| in a single batch.
TEST_F(CrOSOAuthDelegateTest, BatchChangeObserversAreNotifiedOncePerBatch) {
  // Setup
  AccountInfo account1 = CreateAccountInfoTestFixture(
      "1" /* gaia_id */, "user1@example.com" /* email */);
  AccountInfo account2 = CreateAccountInfoTestFixture(
      "2" /* gaia_id */, "user2@example.com" /* email */);

  account_tracker_service_.SeedAccountInfo(account1);
  account_tracker_service_.SeedAccountInfo(account2);
  account_manager_.UpsertAccount(
      AccountManager::AccountKey{account1.gaia, ACCOUNT_TYPE_GAIA},
      "user1@example.com", "token1");
  account_manager_.UpsertAccount(
      AccountManager::AccountKey{account2.gaia, ACCOUNT_TYPE_GAIA},
      "user2@example.com", "token2");
  task_environment_.RunUntilIdle();

  AccountManager account_manager;
  // AccountManager will not be fully initialized until
  // |task_environment_.RunUntilIdle()| is called.
  account_manager.Initialize(tmp_dir_.GetPath(), client_->GetURLLoaderFactory(),
                             immediate_callback_runner_);

  // Register callbacks before AccountManager has been fully initialized.
  auto delegate = std::make_unique<ChromeOSOAuth2TokenServiceDelegate>(
      &account_tracker_service_,
      network::TestNetworkConnectionTracker::GetInstance(), &account_manager);
  delegate->LoadCredentials(account1.account_id /* primary_account_id */);
  TokenServiceObserver observer(delegate.get());
  // Wait until AccountManager is fully initialized.
  task_environment_.RunUntilIdle();

  // Tests

  // The observer should receive 3 batch change callbacks:
  // First - A batch of all accounts stored in AccountManager: because of the
  // delegate's invocation of |AccountManager::GetAccounts| in its constructor.
  // Followed by 2 updates for the individual accounts (|account1| and
  // |account2|): because of the delegate's registration as an
  // |AccountManager::Observer| before |AccountManager| has been fully
  // initialized.
  EXPECT_EQ(3UL, observer.batch_change_records_.size());

  const std::vector<std::string>& first_batch =
      observer.batch_change_records_[0];
  EXPECT_EQ(2UL, first_batch.size());
  EXPECT_TRUE(base::ContainsValue(first_batch, account1.account_id));
  EXPECT_TRUE(base::ContainsValue(first_batch, account2.account_id));
}

TEST_F(CrOSOAuthDelegateTest, GetAccountsShouldNotReturnAdAccounts) {
  EXPECT_TRUE(delegate_->GetAccounts().empty());

  // Insert an Active Directory account into AccountManager.
  account_manager_.UpsertAccount(ad_account_key_, kUserEmail,
                                 AccountManager::kActiveDirectoryDummyToken);

  // OAuth delegate should not return Active Directory accounts.
  EXPECT_TRUE(delegate_->GetAccounts().empty());
}

TEST_F(CrOSOAuthDelegateTest, GetAccountsReturnsGaiaAccounts) {
  EXPECT_TRUE(delegate_->GetAccounts().empty());

  account_manager_.UpsertAccount(gaia_account_key_, kUserEmail, kGaiaToken);

  std::vector<std::string> accounts = delegate_->GetAccounts();
  EXPECT_EQ(1UL, accounts.size());
  EXPECT_EQ(account_info_.account_id, accounts[0]);
}

// |GetAccounts| should return all known Gaia accounts, whether or not they have
// a "valid" refresh token stored against them.
TEST_F(CrOSOAuthDelegateTest, GetAccountsReturnsGaiaAccountsWithInvalidTokens) {
  EXPECT_TRUE(delegate_->GetAccounts().empty());

  account_manager_.UpsertAccount(gaia_account_key_, kUserEmail,
                                 AccountManager::kInvalidToken);

  std::vector<std::string> accounts = delegate_->GetAccounts();
  EXPECT_EQ(1UL, accounts.size());
  EXPECT_EQ(account_info_.account_id, accounts[0]);
}

TEST_F(CrOSOAuthDelegateTest,
       RefreshTokenMustBeAvailableForAllAccountsReturnedByGetAccounts) {
  EXPECT_EQ(OAuth2TokenServiceDelegate::LoadCredentialsState::
                LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
            delegate_->load_credentials_state());
  EXPECT_TRUE(delegate_->GetAccounts().empty());
  const std::string kUserEmail2 = "random-email2@example.com";
  const std::string kUserEmail3 = "random-email3@example.com";

  // Insert 2 Gaia accounts and 1 Active Directory Account. Of the 2 Gaia
  // accounts, 1 has a valid refresh token and 1 has a dummy token.
  account_manager_.UpsertAccount(gaia_account_key_, kUserEmail, kGaiaToken);

  AccountManager::AccountKey gaia_account_key2{"random-gaia-id",
                                               ACCOUNT_TYPE_GAIA};
  account_tracker_service_.SeedAccountInfo(
      CreateAccountInfoTestFixture(gaia_account_key2.id, kUserEmail2));
  account_manager_.UpsertAccount(gaia_account_key2, kUserEmail2,
                                 AccountManager::kInvalidToken);

  account_manager_.UpsertAccount(ad_account_key_, kUserEmail3,
                                 AccountManager::kActiveDirectoryDummyToken);

  // Verify.
  const std::vector<std::string> accounts = delegate_->GetAccounts();
  // 2 Gaia accounts should be returned.
  EXPECT_EQ(2UL, accounts.size());
  // And |RefreshTokenIsAvailable| should return true for these accounts.
  for (const std::string& account : accounts) {
    EXPECT_TRUE(delegate_->RefreshTokenIsAvailable(account));
  }
}

TEST_F(CrOSOAuthDelegateTest, UpdateCredentialsSucceeds) {
  EXPECT_TRUE(delegate_->GetAccounts().empty());

  delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);

  std::vector<std::string> accounts = delegate_->GetAccounts();
  EXPECT_EQ(1UL, accounts.size());
  EXPECT_EQ(account_info_.account_id, accounts[0]);
}

TEST_F(CrOSOAuthDelegateTest, ObserversAreNotifiedOnAccountRemoval) {
  delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);

  TokenServiceObserver observer(delegate_.get());
  account_manager_.RemoveAccount(gaia_account_key_);

  EXPECT_EQ(1UL, observer.batch_change_records_.size());
  EXPECT_EQ(1UL, observer.batch_change_records_[0].size());
  EXPECT_EQ(account_info_.account_id, observer.batch_change_records_[0][0]);
  EXPECT_TRUE(observer.account_ids_.empty());
}

TEST_F(CrOSOAuthDelegateTest,
       SigninErrorObserversAreNotifiedOnAuthErrorChange) {
  auto error =
      GoogleServiceAuthError(GoogleServiceAuthError::State::SERVICE_ERROR);

  delegate_->UpdateAuthError(account_info_.account_id, error);

  EXPECT_EQ(error, delegate_->GetAuthError(account_info_.account_id));
}

TEST_F(CrOSOAuthDelegateTest, TransientErrorsAreNotShown) {
  auto transient_error = GoogleServiceAuthError(
      GoogleServiceAuthError::State::SERVICE_UNAVAILABLE);
  EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(),
            delegate_->GetAuthError(account_info_.account_id));

  delegate_->UpdateAuthError(account_info_.account_id, transient_error);

  EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(),
            delegate_->GetAuthError(account_info_.account_id));
}

TEST_F(CrOSOAuthDelegateTest, BackOffIsTriggerredForTransientErrors) {
  delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);
  auto transient_error = GoogleServiceAuthError(
      GoogleServiceAuthError::State::SERVICE_UNAVAILABLE);
  delegate_->UpdateAuthError(account_info_.account_id, transient_error);
  // Add a dummy success response. The actual network call has not been made
  // yet.
  AddSuccessfulOAuthTokenResponse();

  // Transient error should repeat until backoff period expires.
  AccessTokenConsumer access_token_consumer;
  EXPECT_EQ(0, access_token_consumer.num_access_token_fetch_success_);
  EXPECT_EQ(0, access_token_consumer.num_access_token_fetch_failure_);
  std::vector<std::string> scopes{"scope"};
  std::unique_ptr<OAuth2AccessTokenFetcher> fetcher(
      delegate_->CreateAccessTokenFetcher(account_info_.account_id,
                                          delegate_->GetURLLoaderFactory(),
                                          &access_token_consumer));
  task_environment_.RunUntilIdle();
  fetcher->Start("client_id", "client_secret", scopes);
  task_environment_.RunUntilIdle();
  EXPECT_EQ(0, access_token_consumer.num_access_token_fetch_success_);
  EXPECT_EQ(1, access_token_consumer.num_access_token_fetch_failure_);
  // Expect a positive backoff time.
  EXPECT_GT(delegate_->backoff_entry_.GetTimeUntilRelease(), base::TimeDelta());

  // Pretend that backoff has expired and try again.
  delegate_->backoff_entry_.SetCustomReleaseTime(base::TimeTicks());
  fetcher.reset(delegate_->CreateAccessTokenFetcher(
      account_info_.account_id, delegate_->GetURLLoaderFactory(),
      &access_token_consumer));
  fetcher->Start("client_id", "client_secret", scopes);
  task_environment_.RunUntilIdle();
  EXPECT_EQ(1, access_token_consumer.num_access_token_fetch_success_);
  EXPECT_EQ(1, access_token_consumer.num_access_token_fetch_failure_);
}

TEST_F(CrOSOAuthDelegateTest, BackOffIsResetOnNetworkChange) {
  delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);
  auto transient_error = GoogleServiceAuthError(
      GoogleServiceAuthError::State::SERVICE_UNAVAILABLE);
  delegate_->UpdateAuthError(account_info_.account_id, transient_error);
  // Add a dummy success response. The actual network call has not been made
  // yet.
  AddSuccessfulOAuthTokenResponse();

  // Transient error should repeat until backoff period expires.
  AccessTokenConsumer access_token_consumer;
  EXPECT_EQ(0, access_token_consumer.num_access_token_fetch_success_);
  EXPECT_EQ(0, access_token_consumer.num_access_token_fetch_failure_);
  std::vector<std::string> scopes{"scope"};
  std::unique_ptr<OAuth2AccessTokenFetcher> fetcher(
      delegate_->CreateAccessTokenFetcher(account_info_.account_id,
                                          delegate_->GetURLLoaderFactory(),
                                          &access_token_consumer));
  task_environment_.RunUntilIdle();
  fetcher->Start("client_id", "client_secret", scopes);
  task_environment_.RunUntilIdle();
  EXPECT_EQ(0, access_token_consumer.num_access_token_fetch_success_);
  EXPECT_EQ(1, access_token_consumer.num_access_token_fetch_failure_);
  // Expect a positive backoff time.
  EXPECT_GT(delegate_->backoff_entry_.GetTimeUntilRelease(), base::TimeDelta());

  // Notify of network change and ensure that request now runs.
  delegate_->OnConnectionChanged(
      network::mojom::ConnectionType::CONNECTION_WIFI);
  fetcher.reset(delegate_->CreateAccessTokenFetcher(
      account_info_.account_id, delegate_->GetURLLoaderFactory(),
      &access_token_consumer));
  fetcher->Start("client_id", "client_secret", scopes);
  task_environment_.RunUntilIdle();
  EXPECT_EQ(1, access_token_consumer.num_access_token_fetch_success_);
  EXPECT_EQ(1, access_token_consumer.num_access_token_fetch_failure_);
}

}  // namespace chromeos
