// 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/chromeos/settings/device_oauth2_token_service.h"

#include <stdint.h>

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

#include "base/run_loop.h"
#include "base/task/task_scheduler/task_scheduler.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/chromeos/policy/device_policy_builder.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h"
#include "chrome/browser/chromeos/settings/stub_install_attributes.h"
#include "chrome/browser/chromeos/settings/token_encryptor.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/scoped_testing_local_state.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chromeos/cryptohome/system_salt_getter.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/fake_cryptohome_client.h"
#include "chromeos/dbus/fake_session_manager_client.h"
#include "components/ownership/mock_owner_key_util.h"
#include "components/prefs/testing_pref_service.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "google_apis/gaia/gaia_oauth_client.h"
#include "google_apis/gaia/gaia_urls.h"
#include "google_apis/gaia/oauth2_token_service_test_util.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 "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace chromeos {

namespace {

class MockOAuth2TokenServiceObserver : public OAuth2TokenService::Observer {
 public:
  MockOAuth2TokenServiceObserver();
  ~MockOAuth2TokenServiceObserver() override;

  MOCK_METHOD1(OnRefreshTokenAvailable, void(const std::string&));
};

MockOAuth2TokenServiceObserver::MockOAuth2TokenServiceObserver() {
}

MockOAuth2TokenServiceObserver::~MockOAuth2TokenServiceObserver() {
}

}  // namespace

static const int kValidatorUrlFetcherId = gaia::GaiaOAuthClient::kUrlFetcherId;

class DeviceOAuth2TokenServiceTest : public testing::Test {
 public:
  DeviceOAuth2TokenServiceTest()
      : scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()),
        test_shared_loader_factory_(
            base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
                &test_url_loader_factory_)) {}
  ~DeviceOAuth2TokenServiceTest() override {}

  // Most tests just want a noop crypto impl with a dummy refresh token value in
  // Local State (if the value is an empty string, it will be ignored).
  void SetUpDefaultValues() {
    SetDeviceRefreshTokenInLocalState("device_refresh_token_4_test");
    SetRobotAccountId("service_acct@g.com");
    CreateService();
    AssertConsumerTokensAndErrors(0, 0);

    base::RunLoop().RunUntilIdle();
  }

  void SetUpWithPendingSalt() {
    fake_cryptohome_client_->set_system_salt(std::vector<uint8_t>());
    fake_cryptohome_client_->SetServiceIsAvailable(false);
    SetUpDefaultValues();
  }

  void SetRobotAccountId(const std::string& account_id) {
    device_policy_.policy_data().set_service_account_identity(account_id);
    device_policy_.Build();
    session_manager_client_.set_device_policy(device_policy_.GetBlob());
    DeviceSettingsService::Get()->Load();
    content::RunAllTasksUntilIdle();
  }

  std::unique_ptr<OAuth2TokenService::Request> StartTokenRequest() {
    return oauth2_service_->StartRequest(oauth2_service_->GetRobotAccountId(),
                                         std::set<std::string>(),
                                         &consumer_);
  }

  void SetUp() override {
    fake_cryptohome_client_ = new FakeCryptohomeClient;
    fake_cryptohome_client_->SetServiceIsAvailable(true);
    fake_cryptohome_client_->set_system_salt(
        FakeCryptohomeClient::GetStubSystemSalt());
    chromeos::DBusThreadManager::GetSetterForTesting()->SetCryptohomeClient(
        std::unique_ptr<CryptohomeClient>(fake_cryptohome_client_));

    SystemSaltGetter::Initialize();

    DeviceSettingsService::Initialize();
    scoped_refptr<ownership::MockOwnerKeyUtil> owner_key_util_(
        new ownership::MockOwnerKeyUtil());
    owner_key_util_->SetPublicKeyFromPrivateKey(
        *device_policy_.GetSigningKey());
    DeviceSettingsService::Get()->SetSessionManager(&session_manager_client_,
                                                    owner_key_util_);

    CrosSettings::Initialize();
  }

  void TearDown() override {
    oauth2_service_.reset();
    test_shared_loader_factory_->Detach();
    CrosSettings::Shutdown();
    TestingBrowserProcess::GetGlobal()->ShutdownBrowserPolicyConnector();
    base::TaskScheduler::GetInstance()->FlushForTesting();
    DeviceSettingsService::Get()->UnsetSessionManager();
    DeviceSettingsService::Shutdown();
    SystemSaltGetter::Shutdown();
    DBusThreadManager::Shutdown();
    base::RunLoop().RunUntilIdle();
  }

  void CreateService() {
    auto delegate = std::make_unique<DeviceOAuth2TokenServiceDelegate>(
        test_shared_loader_factory_, scoped_testing_local_state_.Get());
    delegate->max_refresh_token_validation_retries_ = 0;
    oauth2_service_.reset(new DeviceOAuth2TokenService(std::move(delegate)));
    oauth2_service_->set_max_authorization_token_fetch_retries_for_testing(0);
  }

  // Utility method to set a value in Local State for the device refresh token
  // (it must have a non-empty value or it won't be used).
  void SetDeviceRefreshTokenInLocalState(const std::string& refresh_token) {
    scoped_testing_local_state_.Get()->SetUserPref(
        prefs::kDeviceRobotAnyApiRefreshToken,
        std::make_unique<base::Value>(refresh_token));
  }

  std::string GetValidTokenInfoResponse(const std::string& email) {
    return "{ \"email\": \"" + email + "\","
           "  \"user_id\": \"1234567890\" }";
  }

  bool RefreshTokenIsAvailable() {
    return oauth2_service_->RefreshTokenIsAvailable(
        oauth2_service_->GetRobotAccountId());
  }

  std::string GetRefreshToken() {
    if (!RefreshTokenIsAvailable())
      return std::string();

    return static_cast<DeviceOAuth2TokenServiceDelegate*>(
               oauth2_service_->GetDelegate())
        ->GetRefreshToken(oauth2_service_->GetRobotAccountId());
  }

  // A utility method to return fake URL results, for testing the refresh token
  // validation logic.  For a successful validation attempt, this method will be
  // called three times for the steps listed below (steps 1 and 2 happen in
  // parallel).
  //
  // Step 1a: fetch the access token for the tokeninfo API.
  // Step 1b: call the tokeninfo API.
  // Step 2:  Fetch the access token for the requested scope
  //          (in this case, cloudprint).
  void ReturnOAuthUrlFetchResults(int fetcher_id,
                                  net::HttpStatusCode response_code,
                                  const std::string&  response_string);

  // Generates URL fetch replies with the specified results for requests
  // generated by the token service.
  void PerformURLFetchesWithResults(
      net::HttpStatusCode tokeninfo_access_token_status,
      const std::string& tokeninfo_access_token_response,
      net::HttpStatusCode tokeninfo_fetch_status,
      const std::string& tokeninfo_fetch_response,
      net::HttpStatusCode service_access_token_status,
      const std::string& service_access_token_response);

  // Generates URL fetch replies for the success path.
  void PerformURLFetches();

  void AssertConsumerTokensAndErrors(int num_tokens, int num_errors);

 protected:
  // This is here because DeviceOAuth2TokenService's destructor is private;
  // base::DefaultDeleter therefore doesn't work. However, the test class is
  // declared friend in DeviceOAuth2TokenService, so this deleter works.
  struct TokenServiceDeleter {
    inline void operator()(DeviceOAuth2TokenService* ptr) const {
      delete ptr;
    }
  };

  content::TestBrowserThreadBundle test_browser_thread_bundle_;
  ScopedStubInstallAttributes test_install_attributes_;
  ScopedTestingLocalState scoped_testing_local_state_;
  network::TestURLLoaderFactory test_url_loader_factory_;
  scoped_refptr<network::WeakWrapperSharedURLLoaderFactory>
      test_shared_loader_factory_;
  net::TestURLFetcherFactory factory_;
  FakeCryptohomeClient* fake_cryptohome_client_;
  FakeSessionManagerClient session_manager_client_;
  policy::DevicePolicyBuilder device_policy_;
  std::unique_ptr<DeviceOAuth2TokenService, TokenServiceDeleter>
      oauth2_service_;
  TestingOAuth2TokenServiceConsumer consumer_;
};

void DeviceOAuth2TokenServiceTest::ReturnOAuthUrlFetchResults(
    int fetcher_id,
    net::HttpStatusCode response_code,
    const std::string& response_string) {
  net::TestURLFetcher* fetcher = factory_.GetFetcherByID(fetcher_id);
  if (fetcher) {
    factory_.RemoveFetcherFromMap(fetcher_id);
    fetcher->set_response_code(response_code);
    fetcher->SetResponseString(response_string);
    fetcher->delegate()->OnURLFetchComplete(fetcher);
    base::RunLoop().RunUntilIdle();
  }
}

void DeviceOAuth2TokenServiceTest::PerformURLFetchesWithResults(
    net::HttpStatusCode tokeninfo_access_token_status,
    const std::string& tokeninfo_access_token_response,
    net::HttpStatusCode tokeninfo_fetch_status,
    const std::string& tokeninfo_fetch_response,
    net::HttpStatusCode service_access_token_status,
    const std::string& service_access_token_response) {
  test_url_loader_factory_.AddResponse(
      GaiaUrls::GetInstance()->oauth2_token_url().spec(),
      service_access_token_response, service_access_token_status);

  // This sends a response to the OAuth token request made by
  // GaiaOAuthClient::Core, that should eventually be ported to SimpleURLLoader.
  ReturnOAuthUrlFetchResults(
      kValidatorUrlFetcherId,
      tokeninfo_access_token_status,
      tokeninfo_access_token_response);

  ReturnOAuthUrlFetchResults(
      kValidatorUrlFetcherId,
      tokeninfo_fetch_status,
      tokeninfo_fetch_response);
}

void DeviceOAuth2TokenServiceTest::PerformURLFetches() {
  PerformURLFetchesWithResults(
      net::HTTP_OK, GetValidTokenResponse("tokeninfo_access_token", 3600),
      net::HTTP_OK, GetValidTokenInfoResponse("service_acct@g.com"),
      net::HTTP_OK, GetValidTokenResponse("scoped_access_token", 3600));
}

void DeviceOAuth2TokenServiceTest::AssertConsumerTokensAndErrors(
    int num_tokens,
    int num_errors) {
  EXPECT_EQ(num_tokens, consumer_.number_of_successful_tokens_);
  EXPECT_EQ(num_errors, consumer_.number_of_errors_);
}

TEST_F(DeviceOAuth2TokenServiceTest, SaveEncryptedToken) {
  CreateService();

  oauth2_service_->SetAndSaveRefreshToken(
      "test-token", DeviceOAuth2TokenService::StatusCallback());
  EXPECT_EQ("test-token", GetRefreshToken());
}

TEST_F(DeviceOAuth2TokenServiceTest, SaveEncryptedTokenEarly) {
  // Set a new refresh token without the system salt available.
  SetUpWithPendingSalt();

  oauth2_service_->SetAndSaveRefreshToken(
      "test-token", DeviceOAuth2TokenService::StatusCallback());
  EXPECT_EQ("test-token", GetRefreshToken());

  // Make the system salt available.
  fake_cryptohome_client_->set_system_salt(
      FakeCryptohomeClient::GetStubSystemSalt());
  fake_cryptohome_client_->SetServiceIsAvailable(true);
  base::RunLoop().RunUntilIdle();

  // The original token should still be present.
  EXPECT_EQ("test-token", GetRefreshToken());

  // Reloading shouldn't change the token either.
  CreateService();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ("test-token", GetRefreshToken());
}

TEST_F(DeviceOAuth2TokenServiceTest, RefreshTokenValidation_Success) {
  SetUpDefaultValues();
  std::unique_ptr<OAuth2TokenService::Request> request = StartTokenRequest();

  PerformURLFetches();
  AssertConsumerTokensAndErrors(1, 0);

  EXPECT_EQ("scoped_access_token", consumer_.last_token_);
}

TEST_F(DeviceOAuth2TokenServiceTest, RefreshTokenValidation_SuccessAsyncLoad) {
  SetUpWithPendingSalt();

  std::unique_ptr<OAuth2TokenService::Request> request = StartTokenRequest();
  PerformURLFetches();
  AssertConsumerTokensAndErrors(0, 0);

  fake_cryptohome_client_->set_system_salt(
      FakeCryptohomeClient::GetStubSystemSalt());
  fake_cryptohome_client_->SetServiceIsAvailable(true);
  base::RunLoop().RunUntilIdle();

  PerformURLFetches();
  AssertConsumerTokensAndErrors(1, 0);

  EXPECT_EQ("scoped_access_token", consumer_.last_token_);
}

TEST_F(DeviceOAuth2TokenServiceTest, RefreshTokenValidation_Cancel) {
  SetUpDefaultValues();
  std::unique_ptr<OAuth2TokenService::Request> request = StartTokenRequest();
  request.reset();

  PerformURLFetches();

  // Test succeeds if this line is reached without a crash.
}

TEST_F(DeviceOAuth2TokenServiceTest, RefreshTokenValidation_NoSalt) {
  fake_cryptohome_client_->set_system_salt(std::vector<uint8_t>());
  fake_cryptohome_client_->SetServiceIsAvailable(true);
  SetUpDefaultValues();

  EXPECT_FALSE(RefreshTokenIsAvailable());

  std::unique_ptr<OAuth2TokenService::Request> request = StartTokenRequest();
  base::RunLoop().RunUntilIdle();

  AssertConsumerTokensAndErrors(0, 1);
}

TEST_F(DeviceOAuth2TokenServiceTest,
       RefreshTokenValidation_Failure_TokenInfoAccessTokenHttpError) {
  SetUpDefaultValues();
  std::unique_ptr<OAuth2TokenService::Request> request = StartTokenRequest();

  PerformURLFetchesWithResults(
      net::HTTP_UNAUTHORIZED, "",
      net::HTTP_OK, GetValidTokenInfoResponse("service_acct@g.com"),
      net::HTTP_OK, GetValidTokenResponse("ignored", 3600));

  AssertConsumerTokensAndErrors(0, 1);
}

TEST_F(DeviceOAuth2TokenServiceTest,
       RefreshTokenValidation_Failure_TokenInfoAccessTokenInvalidResponse) {
  SetUpDefaultValues();
  std::unique_ptr<OAuth2TokenService::Request> request = StartTokenRequest();

  PerformURLFetchesWithResults(
      net::HTTP_OK, "invalid response",
      net::HTTP_OK, GetValidTokenInfoResponse("service_acct@g.com"),
      net::HTTP_OK, GetValidTokenResponse("ignored", 3600));

  AssertConsumerTokensAndErrors(0, 1);
}

TEST_F(DeviceOAuth2TokenServiceTest,
       RefreshTokenValidation_Failure_TokenInfoApiCallHttpError) {
  SetUpDefaultValues();
  std::unique_ptr<OAuth2TokenService::Request> request = StartTokenRequest();

  PerformURLFetchesWithResults(
      net::HTTP_OK, GetValidTokenResponse("tokeninfo_access_token", 3600),
      net::HTTP_INTERNAL_SERVER_ERROR, "",
      net::HTTP_OK, GetValidTokenResponse("ignored", 3600));

  AssertConsumerTokensAndErrors(0, 1);
}

TEST_F(DeviceOAuth2TokenServiceTest,
       RefreshTokenValidation_Failure_TokenInfoApiCallInvalidResponse) {
  SetUpDefaultValues();
  std::unique_ptr<OAuth2TokenService::Request> request = StartTokenRequest();

  PerformURLFetchesWithResults(
      net::HTTP_OK, GetValidTokenResponse("tokeninfo_access_token", 3600),
      net::HTTP_OK, "invalid response",
      net::HTTP_OK, GetValidTokenResponse("ignored", 3600));

  AssertConsumerTokensAndErrors(0, 1);
}

TEST_F(DeviceOAuth2TokenServiceTest,
       RefreshTokenValidation_Failure_CloudPrintAccessTokenHttpError) {
  SetUpDefaultValues();
  std::unique_ptr<OAuth2TokenService::Request> request = StartTokenRequest();

  PerformURLFetchesWithResults(
      net::HTTP_OK, GetValidTokenResponse("tokeninfo_access_token", 3600),
      net::HTTP_OK, GetValidTokenInfoResponse("service_acct@g.com"),
      net::HTTP_BAD_REQUEST, "");

  AssertConsumerTokensAndErrors(0, 1);
}

TEST_F(DeviceOAuth2TokenServiceTest,
       RefreshTokenValidation_Failure_CloudPrintAccessTokenInvalidResponse) {
  SetUpDefaultValues();
  std::unique_ptr<OAuth2TokenService::Request> request = StartTokenRequest();

  PerformURLFetchesWithResults(
      net::HTTP_OK, GetValidTokenResponse("tokeninfo_access_token", 3600),
      net::HTTP_OK, GetValidTokenInfoResponse("service_acct@g.com"),
      net::HTTP_OK, "invalid request");

  AssertConsumerTokensAndErrors(0, 1);
}

TEST_F(DeviceOAuth2TokenServiceTest, RefreshTokenValidation_Failure_BadOwner) {
  SetUpDefaultValues();
  std::unique_ptr<OAuth2TokenService::Request> request = StartTokenRequest();

  SetRobotAccountId("WRONG_service_acct@g.com");

  PerformURLFetchesWithResults(
      net::HTTP_OK, GetValidTokenResponse("tokeninfo_access_token", 3600),
      net::HTTP_OK, GetValidTokenInfoResponse("service_acct@g.com"),
      net::HTTP_OK, GetValidTokenResponse("ignored", 3600));

  AssertConsumerTokensAndErrors(0, 1);
}

TEST_F(DeviceOAuth2TokenServiceTest, RefreshTokenValidation_Retry) {
  SetUpDefaultValues();
  std::unique_ptr<OAuth2TokenService::Request> request = StartTokenRequest();

  PerformURLFetchesWithResults(
      net::HTTP_INTERNAL_SERVER_ERROR, "",
      net::HTTP_OK, GetValidTokenInfoResponse("service_acct@g.com"),
      net::HTTP_OK, GetValidTokenResponse("ignored", 3600));

  AssertConsumerTokensAndErrors(0, 1);

  // Retry should succeed.
  request = StartTokenRequest();
  PerformURLFetches();
  AssertConsumerTokensAndErrors(1, 1);
}

TEST_F(DeviceOAuth2TokenServiceTest, DoNotAnnounceTokenWithoutAccountID) {
  CreateService();

  testing::StrictMock<MockOAuth2TokenServiceObserver> observer;
  oauth2_service_->AddObserver(&observer);

  // Make a token available during enrollment. Verify that the token is not
  // announced yet.
  oauth2_service_->SetAndSaveRefreshToken(
      "test-token", DeviceOAuth2TokenService::StatusCallback());
  testing::Mock::VerifyAndClearExpectations(&observer);

  // Also make the robot account ID available. Verify that the token is
  // announced now.
  EXPECT_CALL(observer, OnRefreshTokenAvailable("robot@example.com"));
  SetRobotAccountId("robot@example.com");
  testing::Mock::VerifyAndClearExpectations(&observer);

  oauth2_service_->RemoveObserver(&observer);
}

}  // namespace chromeos
