// Copyright 2015 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_delegate.h"

#include <string>
#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/memory/weak_ptr.h"
#include "base/values.h"
#include "chrome/browser/chromeos/settings/token_encryptor.h"
#include "chrome/common/pref_names.h"
#include "chromeos/cryptohome/system_salt_getter.h"
#include "chromeos/settings/cros_settings_names.h"
#include "components/policy/proto/device_management_backend.pb.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "google_apis/gaia/gaia_constants.h"
#include "google_apis/gaia/gaia_urls.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "google_apis/gaia/oauth2_access_token_fetcher_impl.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"

namespace chromeos {

void DeviceOAuth2TokenServiceDelegate::OnServiceAccountIdentityChanged() {
  if (!GetRobotAccountId().empty() && !refresh_token_.empty())
    FireRefreshTokenAvailable(GetRobotAccountId());
}

DeviceOAuth2TokenServiceDelegate::DeviceOAuth2TokenServiceDelegate(
    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
    PrefService* local_state)
    : url_loader_factory_(url_loader_factory),
      local_state_(local_state),
      state_(STATE_LOADING),
      max_refresh_token_validation_retries_(3),
      validation_requested_(false),
      validation_status_delegate_(nullptr),
      service_account_identity_subscription_(
          CrosSettings::Get()->AddSettingsObserver(
              kServiceAccountIdentity,
              base::Bind(&DeviceOAuth2TokenServiceDelegate::
                             OnServiceAccountIdentityChanged,
                         base::Unretained(this)))),
      weak_ptr_factory_(this) {
  // Pull in the system salt.
  SystemSaltGetter::Get()->GetSystemSalt(
      base::Bind(&DeviceOAuth2TokenServiceDelegate::DidGetSystemSalt,
                 weak_ptr_factory_.GetWeakPtr()));
}

DeviceOAuth2TokenServiceDelegate::~DeviceOAuth2TokenServiceDelegate() {
  FlushTokenSaveCallbacks(false);
}

void DeviceOAuth2TokenServiceDelegate::SetAndSaveRefreshToken(
    const std::string& refresh_token,
    const StatusCallback& result_callback) {
  ReportServiceError(GoogleServiceAuthError::REQUEST_CANCELED);

  bool waiting_for_salt = state_ == STATE_LOADING;
  refresh_token_ = refresh_token;
  state_ = STATE_VALIDATION_PENDING;

  // If the robot account ID is not available yet, do not announce the token. It
  // will be done from OnServiceAccountIdentityChanged() once the robot account
  // ID becomes available as well.
  if (!GetRobotAccountId().empty())
    FireRefreshTokenAvailable(GetRobotAccountId());

  token_save_callbacks_.push_back(result_callback);
  if (!waiting_for_salt) {
    if (system_salt_.empty())
      FlushTokenSaveCallbacks(false);
    else
      EncryptAndSaveToken();
  }
}

bool DeviceOAuth2TokenServiceDelegate::RefreshTokenIsAvailable(
    const std::string& account_id) const {
  switch (state_) {
    case STATE_NO_TOKEN:
    case STATE_TOKEN_INVALID:
      return false;
    case STATE_LOADING:
    case STATE_VALIDATION_PENDING:
    case STATE_VALIDATION_STARTED:
    case STATE_TOKEN_VALID:
      return account_id == GetRobotAccountId();
  }

  NOTREACHED() << "Unhandled state " << state_;
  return false;
}

std::string DeviceOAuth2TokenServiceDelegate::GetRobotAccountId() const {
  std::string result;
  CrosSettings::Get()->GetString(kServiceAccountIdentity, &result);
  return result;
}

void DeviceOAuth2TokenServiceDelegate::OnRefreshTokenResponse(
    const std::string& access_token,
    int expires_in_seconds) {
  gaia_oauth_client_->GetTokenInfo(access_token,
                                   max_refresh_token_validation_retries_, this);
}

void DeviceOAuth2TokenServiceDelegate::OnGetTokenInfoResponse(
    std::unique_ptr<base::DictionaryValue> token_info) {
  std::string gaia_robot_id;
  token_info->GetString("email", &gaia_robot_id);
  gaia_oauth_client_.reset();

  CheckRobotAccountId(gaia_robot_id);
}

void DeviceOAuth2TokenServiceDelegate::OnOAuthError() {
  gaia_oauth_client_.reset();
  state_ = STATE_TOKEN_INVALID;
  ReportServiceError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
}

void DeviceOAuth2TokenServiceDelegate::OnNetworkError(int response_code) {
  gaia_oauth_client_.reset();

  // Go back to pending validation state. That'll allow a retry on subsequent
  // token minting requests.
  state_ = STATE_VALIDATION_PENDING;
  ReportServiceError(GoogleServiceAuthError::CONNECTION_FAILED);
}

std::string DeviceOAuth2TokenServiceDelegate::GetRefreshToken(
    const std::string& account_id) const {
  switch (state_) {
    case STATE_LOADING:
    case STATE_NO_TOKEN:
    case STATE_TOKEN_INVALID:
      // This shouldn't happen: GetRefreshToken() is only called for actual
      // token minting operations. In above states, requests are either queued
      // or short-circuited to signal error immediately, so no actual token
      // minting via OAuth2TokenService::FetchOAuth2Token should be triggered.
      NOTREACHED();
      return std::string();
    case STATE_VALIDATION_PENDING:
    case STATE_VALIDATION_STARTED:
    case STATE_TOKEN_VALID:
      return refresh_token_;
  }

  NOTREACHED() << "Unhandled state " << state_;
  return std::string();
}

scoped_refptr<network::SharedURLLoaderFactory>
DeviceOAuth2TokenServiceDelegate::GetURLLoaderFactory() const {
  return url_loader_factory_;
}

OAuth2AccessTokenFetcher*
DeviceOAuth2TokenServiceDelegate::CreateAccessTokenFetcher(
    const std::string& account_id,
    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
    OAuth2AccessTokenConsumer* consumer) {
  std::string refresh_token = GetRefreshToken(account_id);
  DCHECK(!refresh_token.empty());
  return new OAuth2AccessTokenFetcherImpl(consumer, url_loader_factory,
                                          refresh_token);
}

void DeviceOAuth2TokenServiceDelegate::DidGetSystemSalt(
    const std::string& system_salt) {
  system_salt_ = system_salt;

  // Bail out if system salt is not available.
  if (system_salt_.empty()) {
    LOG(ERROR) << "Failed to get system salt.";
    FlushTokenSaveCallbacks(false);
    state_ = STATE_NO_TOKEN;
    FireRefreshTokensLoaded();
    return;
  }

  // If the token has been set meanwhile, write it to |local_state_|.
  if (!refresh_token_.empty()) {
    EncryptAndSaveToken();
    FireRefreshTokensLoaded();
    return;
  }

  // Otherwise, load the refresh token from |local_state_|.
  std::string encrypted_refresh_token =
      local_state_->GetString(prefs::kDeviceRobotAnyApiRefreshToken);
  if (!encrypted_refresh_token.empty()) {
    CryptohomeTokenEncryptor encryptor(system_salt_);
    refresh_token_ = encryptor.DecryptWithSystemSalt(encrypted_refresh_token);
    if (refresh_token_.empty()) {
      LOG(ERROR) << "Failed to decrypt refresh token.";
      state_ = STATE_NO_TOKEN;
      FireRefreshTokensLoaded();
      return;
    }
  }

  state_ = STATE_VALIDATION_PENDING;

  // If there are pending requests, start a validation.
  if (validation_requested_)
    StartValidation();

  // Announce the token.
  FireRefreshTokenAvailable(GetRobotAccountId());
  FireRefreshTokensLoaded();
}

void DeviceOAuth2TokenServiceDelegate::CheckRobotAccountId(
    const std::string& gaia_robot_id) {
  // Make sure the value returned by GetRobotAccountId has been validated
  // against current device settings.
  switch (CrosSettings::Get()->PrepareTrustedValues(
      base::Bind(&DeviceOAuth2TokenServiceDelegate::CheckRobotAccountId,
                 weak_ptr_factory_.GetWeakPtr(), gaia_robot_id))) {
    case CrosSettingsProvider::TRUSTED:
      // All good, compare account ids below.
      break;
    case CrosSettingsProvider::TEMPORARILY_UNTRUSTED:
      // The callback passed to PrepareTrustedValues above will trigger a
      // re-check eventually.
      return;
    case CrosSettingsProvider::PERMANENTLY_UNTRUSTED:
      // There's no trusted account id, which is equivalent to no token present.
      LOG(WARNING) << "Device settings permanently untrusted.";
      state_ = STATE_NO_TOKEN;
      ReportServiceError(GoogleServiceAuthError::USER_NOT_SIGNED_UP);
      return;
  }

  std::string policy_robot_id = GetRobotAccountId();
  if (policy_robot_id == gaia_robot_id) {
    state_ = STATE_TOKEN_VALID;
    ReportServiceError(GoogleServiceAuthError::NONE);
  } else {
    if (gaia_robot_id.empty()) {
      LOG(WARNING) << "Device service account owner in policy is empty.";
    } else {
      LOG(WARNING) << "Device service account owner in policy does not match "
                   << "refresh token owner \"" << gaia_robot_id << "\".";
    }
    state_ = STATE_TOKEN_INVALID;
    ReportServiceError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
  }
}

void DeviceOAuth2TokenServiceDelegate::EncryptAndSaveToken() {
  DCHECK_NE(state_, STATE_LOADING);

  CryptohomeTokenEncryptor encryptor(system_salt_);
  std::string encrypted_refresh_token =
      encryptor.EncryptWithSystemSalt(refresh_token_);
  bool result = true;
  if (encrypted_refresh_token.empty()) {
    LOG(ERROR) << "Failed to encrypt refresh token; save aborted.";
    result = false;
  } else {
    local_state_->SetString(prefs::kDeviceRobotAnyApiRefreshToken,
                            encrypted_refresh_token);
  }

  FlushTokenSaveCallbacks(result);
}

void DeviceOAuth2TokenServiceDelegate::StartValidation() {
  DCHECK_EQ(state_, STATE_VALIDATION_PENDING);
  DCHECK(!gaia_oauth_client_);

  state_ = STATE_VALIDATION_STARTED;

  gaia_oauth_client_ =
      std::make_unique<gaia::GaiaOAuthClient>(url_loader_factory_);

  GaiaUrls* gaia_urls = GaiaUrls::GetInstance();
  gaia::OAuthClientInfo client_info;
  client_info.client_id = gaia_urls->oauth2_chrome_client_id();
  client_info.client_secret = gaia_urls->oauth2_chrome_client_secret();

  gaia_oauth_client_->RefreshToken(
      client_info, refresh_token_,
      std::vector<std::string>(1, GaiaConstants::kOAuthWrapBridgeUserInfoScope),
      max_refresh_token_validation_retries_, this);
}

void DeviceOAuth2TokenServiceDelegate::FlushTokenSaveCallbacks(bool result) {
  std::vector<StatusCallback> callbacks;
  callbacks.swap(token_save_callbacks_);
  for (std::vector<StatusCallback>::iterator callback(callbacks.begin());
       callback != callbacks.end(); ++callback) {
    if (!callback->is_null())
      callback->Run(result);
  }
}

void DeviceOAuth2TokenServiceDelegate::RequestValidation() {
  validation_requested_ = true;
}

void DeviceOAuth2TokenServiceDelegate::SetValidationStatusDelegate(
    ValidationStatusDelegate* delegate) {
  validation_status_delegate_ = delegate;
}

void DeviceOAuth2TokenServiceDelegate::ReportServiceError(
    GoogleServiceAuthError::State error) {
  if (validation_status_delegate_) {
    validation_status_delegate_->OnValidationCompleted(error);
  }
}

}  // namespace chromeos
