// 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 "base/message_loop/message_loop.h"
#include "base/prefs/testing_pref_service.h"
#include "base/run_loop.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/fake_dbus_thread_manager.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_thread.h"
#include "google_apis/gaia/gaia_oauth_client.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 "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using ::testing::_;
using ::testing::AnyNumber;
using ::testing::Return;
using ::testing::ReturnArg;
using ::testing::StrEq;
using ::testing::StrictMock;

namespace chromeos {

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

class TestDeviceOAuth2TokenService : public DeviceOAuth2TokenService {
 public:
  explicit TestDeviceOAuth2TokenService(net::URLRequestContextGetter* getter,
                                        PrefService* local_state,
                                        TokenEncryptor* token_encryptor)
      : DeviceOAuth2TokenService(getter,
                                 local_state,
                                 token_encryptor) {
  }
  void SetRobotAccountIdPolicyValue(const std::string& id) {
    robot_account_id_ = id;
  }

  // Skip calling into the policy subsystem and return our test value.
  virtual std::string GetRobotAccountId() OVERRIDE {
    return robot_account_id_;
  }

 private:
  std::string robot_account_id_;
  DISALLOW_COPY_AND_ASSIGN(TestDeviceOAuth2TokenService);
};

class MockTokenEncryptor : public TokenEncryptor {
 public:
  MOCK_METHOD1(EncryptWithSystemSalt, std::string(const std::string&));
  MOCK_METHOD1(DecryptWithSystemSalt, std::string(const std::string&));
};

class DeviceOAuth2TokenServiceTest : public testing::Test {
 public:
  DeviceOAuth2TokenServiceTest()
      : ui_thread_(content::BrowserThread::UI, &message_loop_),
        scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()),
        request_context_getter_(new net::TestURLRequestContextGetter(
            message_loop_.message_loop_proxy())),
        mock_token_encryptor_(new StrictMock<MockTokenEncryptor>),
        oauth2_service_(request_context_getter_.get(),
                        scoped_testing_local_state_.Get(),
                        mock_token_encryptor_) {
    oauth2_service_.max_refresh_token_validation_retries_ = 0;
    oauth2_service_.set_max_authorization_token_fetch_retries_for_testing(0);
  }
  virtual ~DeviceOAuth2TokenServiceTest() {}

  // 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");
    oauth2_service_.SetRobotAccountIdPolicyValue("service_acct@g.com");
    AssertConsumerTokensAndErrors(0, 0);

    // Returns the input token as-is.
    EXPECT_CALL(*mock_token_encryptor_, DecryptWithSystemSalt(_))
        .WillRepeatedly(ReturnArg<0>());
  }

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

  virtual void SetUp() OVERRIDE {
    // TODO(xiyuan): Remove this when cleaning up the system salt load temp fix.
    scoped_ptr<FakeDBusThreadManager> fake_dbus_thread_manager(
        new FakeDBusThreadManager);
    DBusThreadManager::InitializeForTesting(fake_dbus_thread_manager.release());
    SystemSaltGetter::Initialize();
  }

  virtual void TearDown() OVERRIDE {
    SystemSaltGetter::Shutdown();
    DBusThreadManager::Shutdown();
    base::RunLoop().RunUntilIdle();
  }

  // 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()->SetManagedPref(
        prefs::kDeviceRobotAnyApiRefreshToken,
        Value::CreateStringValue(refresh_token));
  }

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

  // 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);

  void AssertConsumerTokensAndErrors(int num_tokens, int num_errors);

 protected:
  base::MessageLoop message_loop_;
  content::TestBrowserThread ui_thread_;
  ScopedTestingLocalState scoped_testing_local_state_;
  scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
  net::TestURLFetcherFactory factory_;
  // Owned by oauth2_service_.
  StrictMock<MockTokenEncryptor>* mock_token_encryptor_;
  TestDeviceOAuth2TokenService 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);
  ASSERT_TRUE(fetcher);
  fetcher->set_response_code(response_code);
  fetcher->SetResponseString(response_string);
  fetcher->delegate()->OnURLFetchComplete(fetcher);
}

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

TEST_F(DeviceOAuth2TokenServiceTest, SaveEncryptedToken) {
  EXPECT_CALL(*mock_token_encryptor_, DecryptWithSystemSalt(StrEq("")))
      .Times(1)
      .WillOnce(Return(""));
  EXPECT_CALL(*mock_token_encryptor_,
              EncryptWithSystemSalt(StrEq("test-token")))
      .Times(1)
      .WillOnce(Return("encrypted"));
  EXPECT_CALL(*mock_token_encryptor_,
              DecryptWithSystemSalt(StrEq("encrypted")))
      .Times(1)
      .WillOnce(Return("test-token"));

  ASSERT_EQ("", oauth2_service_.GetRefreshToken(
                    oauth2_service_.GetRobotAccountId()));
  oauth2_service_.SetAndSaveRefreshToken("test-token");
  ASSERT_EQ("test-token", oauth2_service_.GetRefreshToken(
                              oauth2_service_.GetRobotAccountId()));

  // This call won't invoke decrypt again, since the value is cached.
  ASSERT_EQ("test-token", oauth2_service_.GetRefreshToken(
                              oauth2_service_.GetRobotAccountId()));
}

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

  ReturnOAuthUrlFetchResults(
      kValidatorUrlFetcherId,
      net::HTTP_OK,
      GetValidTokenResponse("tokeninfo_access_token", 3600));

  ReturnOAuthUrlFetchResults(
      kValidatorUrlFetcherId,
      net::HTTP_OK,
      GetValidTokenInfoResponse("service_acct@g.com"));

  ReturnOAuthUrlFetchResults(
      kOAuthTokenServiceUrlFetcherId,
      net::HTTP_OK,
      GetValidTokenResponse("scoped_access_token", 3600));

  AssertConsumerTokensAndErrors(1, 0);

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

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

  ReturnOAuthUrlFetchResults(
      kValidatorUrlFetcherId,
      net::HTTP_UNAUTHORIZED,
      "");

  // TokenInfo API call skipped (error returned in previous step).

  // CloudPrint access token fetch is successful, but consumer still given error
  // due to bad refresh token.
  ReturnOAuthUrlFetchResults(
      kOAuthTokenServiceUrlFetcherId,
      net::HTTP_OK,
      GetValidTokenResponse("ignored_scoped_access_token", 3600));

  AssertConsumerTokensAndErrors(0, 1);
}

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

  ReturnOAuthUrlFetchResults(
      kValidatorUrlFetcherId,
      net::HTTP_OK,
      "invalid response");

  // TokenInfo API call skipped (error returned in previous step).

  ReturnOAuthUrlFetchResults(
      kOAuthTokenServiceUrlFetcherId,
      net::HTTP_OK,
      GetValidTokenResponse("ignored_scoped_access_token", 3600));

  // CloudPrint access token fetch is successful, but consumer still given error
  // due to bad refresh token.
  AssertConsumerTokensAndErrors(0, 1);
}

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

  ReturnOAuthUrlFetchResults(
      kValidatorUrlFetcherId,
      net::HTTP_OK,
      GetValidTokenResponse("tokeninfo_access_token", 3600));

  ReturnOAuthUrlFetchResults(
      kValidatorUrlFetcherId,
      net::HTTP_INTERNAL_SERVER_ERROR,
      "");

  ReturnOAuthUrlFetchResults(
      kOAuthTokenServiceUrlFetcherId,
      net::HTTP_OK,
      GetValidTokenResponse("ignored_scoped_access_token", 3600));

  // CloudPrint access token fetch is successful, but consumer still given error
  // due to bad refresh token.
  AssertConsumerTokensAndErrors(0, 1);
}

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

  ReturnOAuthUrlFetchResults(
      kValidatorUrlFetcherId,
      net::HTTP_OK,
      GetValidTokenResponse("tokeninfo_access_token", 3600));

  ReturnOAuthUrlFetchResults(
      kValidatorUrlFetcherId,
      net::HTTP_OK,
      "invalid response");

  ReturnOAuthUrlFetchResults(
      kOAuthTokenServiceUrlFetcherId,
      net::HTTP_OK,
      GetValidTokenResponse("ignored_scoped_access_token", 3600));

  // CloudPrint access token fetch is successful, but consumer still given error
  // due to bad refresh token.
  AssertConsumerTokensAndErrors(0, 1);
}

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

  ReturnOAuthUrlFetchResults(
      kValidatorUrlFetcherId,
      net::HTTP_OK,
      GetValidTokenResponse("tokeninfo_access_token", 3600));

  ReturnOAuthUrlFetchResults(
      kValidatorUrlFetcherId,
      net::HTTP_OK,
      GetValidTokenInfoResponse("service_acct@g.com"));

  ReturnOAuthUrlFetchResults(
      kOAuthTokenServiceUrlFetcherId,
      net::HTTP_BAD_REQUEST,
      "");

  AssertConsumerTokensAndErrors(0, 1);
}

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

  ReturnOAuthUrlFetchResults(
      kValidatorUrlFetcherId,
      net::HTTP_OK,
      GetValidTokenResponse("tokeninfo_access_token", 3600));

  ReturnOAuthUrlFetchResults(
      kValidatorUrlFetcherId,
      net::HTTP_OK,
      GetValidTokenInfoResponse("service_acct@g.com"));

  ReturnOAuthUrlFetchResults(
      kOAuthTokenServiceUrlFetcherId,
      net::HTTP_OK,
      "invalid request");

  AssertConsumerTokensAndErrors(0, 1);
}

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

  oauth2_service_.SetRobotAccountIdPolicyValue("WRONG_service_acct@g.com");

  // The requested token comes in before any of the validation calls complete,
  // but the consumer still gets an error, since the results don't get returned
  // until validation is over.
  ReturnOAuthUrlFetchResults(
      kOAuthTokenServiceUrlFetcherId,
      net::HTTP_OK,
      GetValidTokenResponse("ignored_scoped_access_token", 3600));
  AssertConsumerTokensAndErrors(0, 0);

  ReturnOAuthUrlFetchResults(
      kValidatorUrlFetcherId,
      net::HTTP_OK,
      GetValidTokenResponse("tokeninfo_access_token", 3600));
  AssertConsumerTokensAndErrors(0, 0);

  ReturnOAuthUrlFetchResults(
      kValidatorUrlFetcherId,
      net::HTTP_OK,
      GetValidTokenInfoResponse("service_acct@g.com"));

  // All fetches were successful, but consumer still given error since
  // the token owner doesn't match the policy value.
  AssertConsumerTokensAndErrors(0, 1);
}

}  // namespace chromeos
