// Copyright 2014 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/login/enrollment/enterprise_enrollment_helper_impl.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_process_platform_part.h"
#include "chrome/browser/chromeos/login/enrollment/enrollment_uma.h"
#include "chrome/browser/chromeos/login/startup_utils.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/policy/device_cloud_policy_initializer.h"
#include "chrome/browser/chromeos/policy/enrollment_status_chromeos.h"
#include "chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "google_apis/gaia/gaia_auth_consumer.h"
#include "google_apis/gaia/gaia_auth_fetcher.h"
#include "google_apis/gaia/gaia_constants.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"

namespace {

// A helper class that takes care of asynchronously revoking a given token.
class TokenRevoker : public GaiaAuthConsumer {
 public:
  TokenRevoker();
  ~TokenRevoker() override;

  void Start(const std::string& token);

  // GaiaAuthConsumer:
  void OnOAuth2RevokeTokenCompleted(
      GaiaAuthConsumer::TokenRevocationStatus status) override;

 private:
  GaiaAuthFetcher gaia_fetcher_;

  DISALLOW_COPY_AND_ASSIGN(TokenRevoker);
};

TokenRevoker::TokenRevoker()
    : gaia_fetcher_(this,
                    GaiaConstants::kChromeOSSource,
                    g_browser_process->system_network_context_manager()
                        ->GetSharedURLLoaderFactory()) {}

TokenRevoker::~TokenRevoker() {}

void TokenRevoker::Start(const std::string& token) {
  gaia_fetcher_.StartRevokeOAuth2Token(token);
}

void TokenRevoker::OnOAuth2RevokeTokenCompleted(
    GaiaAuthConsumer::TokenRevocationStatus status) {
  base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
}

}  // namespace

namespace chromeos {

EnterpriseEnrollmentHelperImpl::EnterpriseEnrollmentHelperImpl(
    EnrollmentStatusConsumer* status_consumer,
    ActiveDirectoryJoinDelegate* ad_join_delegate,
    const policy::EnrollmentConfig& enrollment_config,
    const std::string& enrolling_user_domain)
    : EnterpriseEnrollmentHelper(status_consumer),
      enrollment_config_(enrollment_config),
      enrolling_user_domain_(enrolling_user_domain),
      ad_join_delegate_(ad_join_delegate),
      weak_ptr_factory_(this) {
  // Init the TPM if it has not been done until now (in debug build we might
  // have not done that yet).
  DBusThreadManager::Get()->GetCryptohomeClient()->TpmCanAttemptOwnership(
      EmptyVoidDBusMethodCallback());
}

EnterpriseEnrollmentHelperImpl::~EnterpriseEnrollmentHelperImpl() {
  DCHECK(
      g_browser_process->IsShuttingDown() ||
      oauth_status_ == OAUTH_NOT_STARTED ||
      (oauth_status_ == OAUTH_FINISHED && (success_ || oauth_data_cleared_)));
}

void EnterpriseEnrollmentHelperImpl::EnrollUsingAuthCode(
    const std::string& auth_code,
    bool fetch_additional_token) {
  DCHECK(oauth_status_ == OAUTH_NOT_STARTED);
  oauth_status_ = OAUTH_STARTED_WITH_AUTH_CODE;
  oauth_fetcher_.reset(policy::PolicyOAuth2TokenFetcher::CreateInstance());
  oauth_fetcher_->StartWithAuthCode(
      auth_code,
      g_browser_process->system_network_context_manager()
          ->GetSharedURLLoaderFactory(),
      base::Bind(&EnterpriseEnrollmentHelperImpl::OnTokenFetched,
                 weak_ptr_factory_.GetWeakPtr(),
                 fetch_additional_token /* is_additional_token */));
}

void EnterpriseEnrollmentHelperImpl::EnrollUsingToken(
    const std::string& token) {
  DCHECK(oauth_status_ != OAUTH_STARTED_WITH_TOKEN);
  if (oauth_status_ == OAUTH_NOT_STARTED)
    oauth_status_ = OAUTH_STARTED_WITH_TOKEN;
  DoEnroll(token);
}

void EnterpriseEnrollmentHelperImpl::EnrollUsingAttestation() {
  CHECK(enrollment_config_.is_mode_attestation());
  DoEnroll("");  // The token is not used in attestation mode.
}

void EnterpriseEnrollmentHelperImpl::EnrollForOfflineDemo() {
  CHECK_EQ(enrollment_config_.mode,
           policy::EnrollmentConfig::MODE_OFFLINE_DEMO);
  DoEnroll("");  // The token is not used in offline demo mode.
}

void EnterpriseEnrollmentHelperImpl::ClearAuth(const base::Closure& callback) {
  if (oauth_status_ != OAUTH_NOT_STARTED) {
    // Do not revoke the additional token if enrollment has finished
    // successfully.
    if (!success_ && additional_token_.length())
      (new TokenRevoker())->Start(additional_token_);

    if (oauth_fetcher_) {
      if (!oauth_fetcher_->OAuth2AccessToken().empty())
        (new TokenRevoker())->Start(oauth_fetcher_->OAuth2AccessToken());

      if (!oauth_fetcher_->OAuth2RefreshToken().empty())
        (new TokenRevoker())->Start(oauth_fetcher_->OAuth2RefreshToken());

      oauth_fetcher_.reset();
    } else if (oauth_token_.length()) {
      // EnrollUsingToken was called.
      (new TokenRevoker())->Start(oauth_token_);
    }
  }

  chromeos::ProfileHelper::Get()->ClearSigninProfile(
      base::Bind(&EnterpriseEnrollmentHelperImpl::OnSigninProfileCleared,
                 weak_ptr_factory_.GetWeakPtr(), callback));
}

bool EnterpriseEnrollmentHelperImpl::ShouldCheckLicenseType() const {
  // The license selection dialog is not used when doing Zero Touch or setting
  // up offline demo-mode, or when forced to enroll by server.
  if (enrollment_config_.is_mode_attestation() ||
      enrollment_config_.mode == policy::EnrollmentConfig::MODE_SERVER_FORCED ||
      enrollment_config_.mode == policy::EnrollmentConfig::MODE_OFFLINE_DEMO) {
    return false;
  }
  return !base::CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kEnterpriseDisableLicenseTypeSelection);
}

void EnterpriseEnrollmentHelperImpl::DoEnroll(const std::string& token) {
  DCHECK(token == oauth_token_ || oauth_token_.empty());
  DCHECK(enrollment_config_.is_mode_attestation() ||
         enrollment_config_.mode ==
             policy::EnrollmentConfig::MODE_OFFLINE_DEMO ||
         oauth_status_ == OAUTH_STARTED_WITH_AUTH_CODE ||
         oauth_status_ == OAUTH_STARTED_WITH_TOKEN);
  oauth_token_ = token;
  policy::BrowserPolicyConnectorChromeOS* connector =
      g_browser_process->platform_part()->browser_policy_connector_chromeos();
  // Re-enrollment is not implemented for Active Directory.
  if (connector->IsCloudManaged() &&
      connector->GetEnterpriseEnrollmentDomain() != enrolling_user_domain_) {
    LOG(ERROR) << "Trying to re-enroll to a different domain than "
               << connector->GetEnterpriseEnrollmentDomain();
    UMA(policy::kMetricEnrollmentPrecheckDomainMismatch);
    if (oauth_status_ != OAUTH_NOT_STARTED)
      oauth_status_ = OAUTH_FINISHED;
    status_consumer()->OnOtherError(OTHER_ERROR_DOMAIN_MISMATCH);
    return;
  }

  connector->ScheduleServiceInitialization(0);
  policy::DeviceCloudPolicyInitializer* dcp_initializer =
      connector->GetDeviceCloudPolicyInitializer();
  CHECK(dcp_initializer);
  dcp_initializer->PrepareEnrollment(
      connector->device_management_service(), ad_join_delegate_,
      enrollment_config_, token,
      base::Bind(&EnterpriseEnrollmentHelperImpl::OnEnrollmentFinished,
                 weak_ptr_factory_.GetWeakPtr()));
  if (ShouldCheckLicenseType()) {
    dcp_initializer->CheckAvailableLicenses(
        base::Bind(&EnterpriseEnrollmentHelperImpl::OnLicenseMapObtained,
                   weak_ptr_factory_.GetWeakPtr()));
  } else {
    dcp_initializer->StartEnrollment();
  }
}

void EnterpriseEnrollmentHelperImpl::UseLicenseType(policy::LicenseType type) {
  DCHECK(type != policy::LicenseType::UNKNOWN);
  policy::DeviceCloudPolicyInitializer* dcp_initializer =
      g_browser_process->platform_part()
          ->browser_policy_connector_chromeos()
          ->GetDeviceCloudPolicyInitializer();

  CHECK(dcp_initializer);
  dcp_initializer->StartEnrollmentWithLicense(type);
}

void EnterpriseEnrollmentHelperImpl::GetDeviceAttributeUpdatePermission() {
  policy::BrowserPolicyConnectorChromeOS* connector =
      g_browser_process->platform_part()->browser_policy_connector_chromeos();
  // Don't update device attributes for Active Directory management.
  if (connector->IsActiveDirectoryManaged()) {
    OnDeviceAttributeUpdatePermission(false);
    return;
  }
  policy::DeviceCloudPolicyManagerChromeOS* policy_manager =
      connector->GetDeviceCloudPolicyManager();
  policy::CloudPolicyClient* client = policy_manager->core()->client();

  client->GetDeviceAttributeUpdatePermission(
      oauth_token_,
      base::Bind(
          &EnterpriseEnrollmentHelperImpl::OnDeviceAttributeUpdatePermission,
          weak_ptr_factory_.GetWeakPtr()));
}

void EnterpriseEnrollmentHelperImpl::UpdateDeviceAttributes(
    const std::string& asset_id,
    const std::string& location) {
  policy::BrowserPolicyConnectorChromeOS* connector =
      g_browser_process->platform_part()->browser_policy_connector_chromeos();
  policy::DeviceCloudPolicyManagerChromeOS* policy_manager =
      connector->GetDeviceCloudPolicyManager();
  policy::CloudPolicyClient* client = policy_manager->core()->client();

  client->UpdateDeviceAttributes(
      oauth_token_, asset_id, location,
      base::Bind(
          &EnterpriseEnrollmentHelperImpl::OnDeviceAttributeUploadCompleted,
          weak_ptr_factory_.GetWeakPtr()));
}

void EnterpriseEnrollmentHelperImpl::OnTokenFetched(
    bool is_additional_token,
    const std::string& token,
    const GoogleServiceAuthError& error) {
  if (error.state() != GoogleServiceAuthError::NONE) {
    ReportAuthStatus(error);
    oauth_status_ = OAUTH_FINISHED;
    status_consumer()->OnAuthError(error);
    return;
  }

  if (!is_additional_token) {
    EnrollUsingToken(token);
    return;
  }

  additional_token_ = token;
  std::string refresh_token = oauth_fetcher_->OAuth2RefreshToken();
  oauth_fetcher_.reset(policy::PolicyOAuth2TokenFetcher::CreateInstance());
  oauth_fetcher_->StartWithRefreshToken(
      refresh_token,
      g_browser_process->system_network_context_manager()
          ->GetSharedURLLoaderFactory(),
      base::Bind(&EnterpriseEnrollmentHelperImpl::OnTokenFetched,
                 weak_ptr_factory_.GetWeakPtr(),
                 false /* is_additional_token */));
}

void EnterpriseEnrollmentHelperImpl::OnEnrollmentFinished(
    policy::EnrollmentStatus status) {
  ReportEnrollmentStatus(status);
  if (oauth_status_ != OAUTH_NOT_STARTED)
    oauth_status_ = OAUTH_FINISHED;
  if (status.status() == policy::EnrollmentStatus::SUCCESS) {
    success_ = true;
    StartupUtils::MarkOobeCompleted();
    status_consumer()->OnDeviceEnrolled(additional_token_);
  } else {
    status_consumer()->OnEnrollmentError(status);
  }
}

void EnterpriseEnrollmentHelperImpl::OnLicenseMapObtained(
    const EnrollmentLicenseMap& licenses) {
  int count = 0;
  policy::LicenseType license_type = policy::LicenseType::UNKNOWN;
  for (const auto& it : licenses) {
    if (it.second > 0) {
      count++;
      license_type = it.first;
    }
  }
  if (count == 0) {
    // No user license type selection allowed, start usual enrollment.
    policy::BrowserPolicyConnectorChromeOS* connector =
        g_browser_process->platform_part()->browser_policy_connector_chromeos();
    policy::DeviceCloudPolicyInitializer* dcp_initializer =
        connector->GetDeviceCloudPolicyInitializer();
    CHECK(dcp_initializer);
    dcp_initializer->StartEnrollment();
  } else if (count == 1) {
    UseLicenseType(license_type);
  } else {
    status_consumer()->OnMultipleLicensesAvailable(licenses);
  }
}

void EnterpriseEnrollmentHelperImpl::OnDeviceAttributeUpdatePermission(
    bool granted) {
  status_consumer()->OnDeviceAttributeUpdatePermission(granted);
}

void EnterpriseEnrollmentHelperImpl::OnDeviceAttributeUploadCompleted(
    bool success) {
  status_consumer()->OnDeviceAttributeUploadCompleted(success);
}

void EnterpriseEnrollmentHelperImpl::ReportAuthStatus(
    const GoogleServiceAuthError& error) {
  switch (error.state()) {
    case GoogleServiceAuthError::NONE:
    case GoogleServiceAuthError::CAPTCHA_REQUIRED:
    case GoogleServiceAuthError::TWO_FACTOR:
    case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
    case GoogleServiceAuthError::REQUEST_CANCELED:
    case GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE:
    case GoogleServiceAuthError::SERVICE_ERROR:
    case GoogleServiceAuthError::WEB_LOGIN_REQUIRED:
      UMA(policy::kMetricEnrollmentLoginFailed);
      LOG(ERROR) << "Auth error " << error.state();
      break;
    case GoogleServiceAuthError::USER_NOT_SIGNED_UP:
      UMA(policy::kMetricEnrollmentAccountNotSignedUp);
      LOG(ERROR) << "Account not signed up " << error.state();
      break;
    case GoogleServiceAuthError::ACCOUNT_DELETED:
      UMA(policy::kMetricEnrollmentAccountDeleted);
      LOG(ERROR) << "Account deleted " << error.state();
      break;
    case GoogleServiceAuthError::ACCOUNT_DISABLED:
      UMA(policy::kMetricEnrollmentAccountDisabled);
      LOG(ERROR) << "Account disabled " << error.state();
      break;
    case GoogleServiceAuthError::CONNECTION_FAILED:
    case GoogleServiceAuthError::SERVICE_UNAVAILABLE:
      UMA(policy::kMetricEnrollmentNetworkFailed);
      LOG(WARNING) << "Network error " << error.state();
      break;
    case GoogleServiceAuthError::HOSTED_NOT_ALLOWED_DEPRECATED:
    case GoogleServiceAuthError::NUM_STATES:
      NOTREACHED();
      break;
  }
}

void EnterpriseEnrollmentHelperImpl::ReportEnrollmentStatus(
    policy::EnrollmentStatus status) {
  switch (status.status()) {
    case policy::EnrollmentStatus::SUCCESS:
      UMA(policy::kMetricEnrollmentOK);
      return;
    case policy::EnrollmentStatus::REGISTRATION_FAILED:
    case policy::EnrollmentStatus::POLICY_FETCH_FAILED:
      switch (status.client_status()) {
        case policy::DM_STATUS_SUCCESS:
          NOTREACHED();
          break;
        case policy::DM_STATUS_REQUEST_INVALID:
          UMA(policy::kMetricEnrollmentRegisterPolicyPayloadInvalid);
          break;
        case policy::DM_STATUS_SERVICE_DEVICE_NOT_FOUND:
          UMA(policy::kMetricEnrollmentRegisterPolicyDeviceNotFound);
          break;
        case policy::DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID:
          UMA(policy::kMetricEnrollmentRegisterPolicyDMTokenInvalid);
          break;
        case policy::DM_STATUS_SERVICE_ACTIVATION_PENDING:
          UMA(policy::kMetricEnrollmentRegisterPolicyActivationPending);
          break;
        case policy::DM_STATUS_SERVICE_DEVICE_ID_CONFLICT:
          UMA(policy::kMetricEnrollmentRegisterPolicyDeviceIdConflict);
          break;
        case policy::DM_STATUS_SERVICE_POLICY_NOT_FOUND:
          UMA(policy::kMetricEnrollmentRegisterPolicyNotFound);
          break;
        case policy::DM_STATUS_REQUEST_FAILED:
          UMA(policy::kMetricEnrollmentRegisterPolicyRequestFailed);
          break;
        case policy::DM_STATUS_TEMPORARY_UNAVAILABLE:
          UMA(policy::kMetricEnrollmentRegisterPolicyTempUnavailable);
          break;
        case policy::DM_STATUS_HTTP_STATUS_ERROR:
          UMA(policy::kMetricEnrollmentRegisterPolicyHttpError);
          break;
        case policy::DM_STATUS_RESPONSE_DECODING_ERROR:
          UMA(policy::kMetricEnrollmentRegisterPolicyResponseInvalid);
          break;
        case policy::DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED:
          UMA(policy::kMetricEnrollmentNotSupported);
          break;
        case policy::DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER:
          UMA(policy::kMetricEnrollmentRegisterPolicyInvalidSerial);
          break;
        case policy::DM_STATUS_SERVICE_MISSING_LICENSES:
          UMA(policy::kMetricEnrollmentRegisterPolicyMissingLicenses);
          break;
        case policy::DM_STATUS_SERVICE_DEPROVISIONED:
          UMA(policy::kMetricEnrollmentRegisterPolicyDeprovisioned);
          break;
        case policy::DM_STATUS_SERVICE_DOMAIN_MISMATCH:
          UMA(policy::kMetricEnrollmentRegisterPolicyDomainMismatch);
          break;
        case policy::DM_STATUS_CANNOT_SIGN_REQUEST:
          UMA(policy::kMetricEnrollmentRegisterCannotSignRequest);
          break;
        case policy::DM_STATUS_SERVICE_ARC_DISABLED:
          NOTREACHED();
          break;
      }
      break;
    case policy::EnrollmentStatus::REGISTRATION_BAD_MODE:
      UMA(policy::kMetricEnrollmentInvalidEnrollmentMode);
      break;
    case policy::EnrollmentStatus::NO_STATE_KEYS:
      UMA(policy::kMetricEnrollmentNoStateKeys);
      break;
    case policy::EnrollmentStatus::VALIDATION_FAILED:
      UMA(policy::kMetricEnrollmentPolicyValidationFailed);
      break;
    case policy::EnrollmentStatus::STORE_ERROR:
      UMA(policy::kMetricEnrollmentCloudPolicyStoreError);
      break;
    case policy::EnrollmentStatus::LOCK_ERROR:
      switch (status.lock_status()) {
        case InstallAttributes::LOCK_SUCCESS:
        case InstallAttributes::LOCK_NOT_READY:
          NOTREACHED();
          break;
        case InstallAttributes::LOCK_TIMEOUT:
          UMA(policy::kMetricEnrollmentLockboxTimeoutError);
          break;
        case InstallAttributes::LOCK_BACKEND_INVALID:
          UMA(policy::kMetricEnrollmentLockBackendInvalid);
          break;
        case InstallAttributes::LOCK_ALREADY_LOCKED:
          UMA(policy::kMetricEnrollmentLockAlreadyLocked);
          break;
        case InstallAttributes::LOCK_SET_ERROR:
          UMA(policy::kMetricEnrollmentLockSetError);
          break;
        case InstallAttributes::LOCK_FINALIZE_ERROR:
          UMA(policy::kMetricEnrollmentLockFinalizeError);
          break;
        case InstallAttributes::LOCK_READBACK_ERROR:
          UMA(policy::kMetricEnrollmentLockReadbackError);
          break;
        case InstallAttributes::LOCK_WRONG_DOMAIN:
          UMA(policy::kMetricEnrollmentLockDomainMismatch);
          break;
        case InstallAttributes::LOCK_WRONG_MODE:
          UMA(policy::kMetricEnrollmentLockModeMismatch);
          break;
      }
      break;
    case policy::EnrollmentStatus::ROBOT_AUTH_FETCH_FAILED:
      UMA(policy::kMetricEnrollmentRobotAuthCodeFetchFailed);
      break;
    case policy::EnrollmentStatus::ROBOT_REFRESH_FETCH_FAILED:
      UMA(policy::kMetricEnrollmentRobotRefreshTokenFetchFailed);
      break;
    case policy::EnrollmentStatus::ROBOT_REFRESH_STORE_FAILED:
      UMA(policy::kMetricEnrollmentRobotRefreshTokenStoreFailed);
      break;
    case policy::EnrollmentStatus::ATTRIBUTE_UPDATE_FAILED:
      UMA(policy::kMetricEnrollmentAttributeUpdateFailed);
      break;
    case policy::EnrollmentStatus::REGISTRATION_CERT_FETCH_FAILED:
      UMA(policy::kMetricEnrollmentRegistrationCertificateFetchFailed);
      break;
    case policy::EnrollmentStatus::NO_MACHINE_IDENTIFICATION:
      UMA(policy::kMetricEnrollmentNoDeviceIdentification);
      break;
    case policy::EnrollmentStatus::ACTIVE_DIRECTORY_POLICY_FETCH_FAILED:
      UMA(policy::kMetricEnrollmentActiveDirectoryPolicyFetchFailed);
      break;
    case policy::EnrollmentStatus::DM_TOKEN_STORE_FAILED:
      UMA(policy::kMetricEnrollmentStoreDMTokenFailed);
      break;
    case policy::EnrollmentStatus::LICENSE_REQUEST_FAILED:
      UMA(policy::kMetricEnrollmentLicenseRequestFailed);
      break;
    case policy::EnrollmentStatus::OFFLINE_POLICY_LOAD_FAILED:
    case policy::EnrollmentStatus::OFFLINE_POLICY_DECODING_FAILED:
      UMA(policy::kMetricEnrollmentRegisterPolicyResponseInvalid);
      break;
  }
}

void EnterpriseEnrollmentHelperImpl::UMA(policy::MetricEnrollment sample) {
  EnrollmentUMA(sample, enrollment_config_.mode);
}

void EnterpriseEnrollmentHelperImpl::OnSigninProfileCleared(
    const base::Closure& callback) {
  oauth_data_cleared_ = true;
  callback.Run();
}

}  // namespace chromeos
