// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/sync/sync_ui_util.h"

#include <utility>

#include "base/feature_list.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
#include "chrome/browser/signin/chrome_signin_client_factory.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/signin/signin_util.h"
#include "chrome/browser/sync/sync_service_factory.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/singleton_tabs.h"
#include "chrome/grit/chromium_strings.h"
#include "chrome/grit/generated_resources.h"
#include "components/password_manager/core/browser/password_manager_features_util.h"
#include "components/prefs/pref_service.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/strings/grit/components_strings.h"
#include "components/sync/base/features.h"
#include "components/sync/service/sync_service.h"
#include "components/sync/service/sync_user_settings.h"
#include "google_apis/gaia/gaia_urls.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "net/base/url_util.h"
#include "ui/base/l10n/l10n_util.h"

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/constants/ash_features.h"
#endif

namespace {

SyncStatusLabels GetStatusForUnrecoverableError(
    bool is_user_clear_primary_account_allowed) {
#if !BUILDFLAG(IS_CHROMEOS_ASH)
  int status_label_string_id =
      is_user_clear_primary_account_allowed
          ? IDS_SYNC_STATUS_UNRECOVERABLE_ERROR
          :
          // The message for managed accounts is the same as that on ChromeOS.
          IDS_SYNC_STATUS_UNRECOVERABLE_ERROR_NEEDS_SIGNOUT;
#else
  int status_label_string_id =
      IDS_SYNC_STATUS_UNRECOVERABLE_ERROR_NEEDS_SIGNOUT;
#endif

  return {SyncStatusMessageType::kSyncError, status_label_string_id,
          IDS_SYNC_RELOGIN_BUTTON, SyncStatusActionType::kReauthenticate};
}

SyncStatusLabels GetSyncStatusLabelsImpl(
    const syncer::SyncService* service,
    bool is_user_clear_primary_account_allowed,
    const GoogleServiceAuthError& auth_error) {
  DCHECK(service);
  DCHECK(!auth_error.IsTransientError());

  if (!service->HasSyncConsent()) {
    return {SyncStatusMessageType::kPreSynced, IDS_SETTINGS_EMPTY_STRING,
            IDS_SETTINGS_EMPTY_STRING, SyncStatusActionType::kNoAction};
  }

  // If local Sync were enabled, then the SyncService shouldn't report having a
  // primary (or any) account.
  DCHECK(!service->IsLocalSyncEnabled());

  // First check if Chrome needs to be updated.
  if (service->RequiresClientUpgrade()) {
    return {SyncStatusMessageType::kSyncError, IDS_SYNC_UPGRADE_CLIENT,
            IDS_SYNC_UPGRADE_CLIENT_BUTTON,
            SyncStatusActionType::kUpgradeClient};
  }

  // Then check for an unrecoverable error.
  if (service->HasUnrecoverableError()) {
    return GetStatusForUnrecoverableError(
        is_user_clear_primary_account_allowed);
  }

  // Then check for an auth error.
  if (auth_error.state() != GoogleServiceAuthError::NONE) {
    DCHECK(auth_error.IsPersistentError());
    return {SyncStatusMessageType::kSyncError, IDS_SYNC_RELOGIN_ERROR,
            IDS_SYNC_RELOGIN_BUTTON, SyncStatusActionType::kReauthenticate};
  }

  // Check if Sync is disabled by policy.
  if (service->HasDisableReason(
          syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY)) {
    // TODO(crbug.com/911153): Is SyncStatusMessageType::kSynced correct for
    // this case?
    return {SyncStatusMessageType::kSynced,
            IDS_SIGNED_IN_WITH_SYNC_DISABLED_BY_POLICY,
            IDS_SETTINGS_EMPTY_STRING, SyncStatusActionType::kNoAction};
  }

  // Check to see if sync has been disabled via the dashboard and needs to be
  // set up once again.
#if BUILDFLAG(IS_CHROMEOS_ASH)
  if (service->IsSyncFeatureDisabledViaDashboard()) {
    return {SyncStatusMessageType::kSyncError,
            IDS_SIGNED_IN_WITH_SYNC_STOPPED_VIA_DASHBOARD,
            IDS_SETTINGS_EMPTY_STRING, SyncStatusActionType::kNoAction};
  }
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

  if (service->GetUserSettings()->IsInitialSyncFeatureSetupComplete()) {
    // Check for a passphrase error.
    if (service->GetUserSettings()
            ->IsPassphraseRequiredForPreferredDataTypes()) {
      // TODO(mastiz): This should return
      // SyncStatusMessageType::kPasswordsOnlySyncError if only passwords are
      // encrypted as per IsEncryptEverythingEnabled().
      return {SyncStatusMessageType::kSyncError, IDS_SYNC_STATUS_NEEDS_PASSWORD,
              IDS_SYNC_STATUS_NEEDS_PASSWORD_BUTTON,
              SyncStatusActionType::kEnterPassphrase};
    }

    if (service->IsSyncFeatureActive() &&
        service->GetUserSettings()
            ->IsTrustedVaultKeyRequiredForPreferredDataTypes()) {
      return {service->GetUserSettings()->IsEncryptEverythingEnabled()
                  ? SyncStatusMessageType::kSyncError
                  : SyncStatusMessageType::kPasswordsOnlySyncError,
              IDS_SETTINGS_EMPTY_STRING, IDS_SYNC_STATUS_NEEDS_KEYS_BUTTON,
              SyncStatusActionType::kRetrieveTrustedVaultKeys};
    }

    // At this point, there is no Sync error.
    if (service->IsSyncFeatureActive()) {
      return {SyncStatusMessageType::kSynced,
              service->GetUserSettings()->IsSyncEverythingEnabled()
                  ? IDS_SYNC_ACCOUNT_SYNCING
                  : IDS_SYNC_ACCOUNT_SYNCING_CUSTOM_DATA_TYPES,
              IDS_SETTINGS_EMPTY_STRING, SyncStatusActionType::kNoAction};
    } else {
      // Sync is still initializing.
      return {SyncStatusMessageType::kSynced, IDS_SETTINGS_EMPTY_STRING,
              IDS_SETTINGS_EMPTY_STRING, SyncStatusActionType::kNoAction};
    }
  }

  // If first setup is in progress, show an "in progress" message.
  if (service->IsSetupInProgress()) {
    return {SyncStatusMessageType::kPreSynced, IDS_SYNC_SETUP_IN_PROGRESS,
            IDS_SETTINGS_EMPTY_STRING, SyncStatusActionType::kNoAction};
  }

  // At this point we've ruled out all other cases - all that's left is a
  // missing Sync confirmation.
  DCHECK(ShouldRequestSyncConfirmation(service));
  return {SyncStatusMessageType::kSyncError, IDS_SYNC_SETTINGS_NOT_CONFIRMED,
          IDS_SYNC_ERROR_USER_MENU_CONFIRM_SYNC_SETTINGS_BUTTON,
          SyncStatusActionType::kConfirmSyncSettings};
}

void FocusWebContents(Browser* browser) {
  content::WebContents* const contents =
      browser->tab_strip_model()->GetActiveWebContents();
  if (contents) {
    contents->Focus();
  }
}

void OpenTabForSyncTrustedVaultUserAction(Browser* browser, const GURL& url) {
  DCHECK(browser);
  FocusWebContents(browser);

  NavigateParams params(GetSingletonTabNavigateParams(browser, url));
  // Allow the window to close itself.
  params.opened_by_another_window = true;
  Navigate(&params);
}

absl::optional<AvatarSyncErrorType> GetTrustedVaultError(
    const syncer::SyncService* sync_service,
    const PrefService* pref_service) {
  if (ShouldShowSyncKeysMissingError(sync_service, pref_service)) {
    return sync_service->GetUserSettings()->IsEncryptEverythingEnabled()
               ? AvatarSyncErrorType::kTrustedVaultKeyMissingForEverythingError
               : AvatarSyncErrorType::kTrustedVaultKeyMissingForPasswordsError;
  }

  if (ShouldShowTrustedVaultDegradedRecoverabilityError(sync_service,
                                                        pref_service)) {
    return sync_service->GetUserSettings()->IsEncryptEverythingEnabled()
               ? AvatarSyncErrorType::
                     kTrustedVaultRecoverabilityDegradedForEverythingError
               : AvatarSyncErrorType::
                     kTrustedVaultRecoverabilityDegradedForPasswordsError;
  }

  return absl::nullopt;
}

}  // namespace

SyncStatusLabels GetSyncStatusLabels(
    syncer::SyncService* sync_service,
    signin::IdentityManager* identity_manager,
    bool is_user_clear_primary_account_allowed) {
  if (!sync_service) {
    // This can happen if Sync is disabled via the command line.
    return {SyncStatusMessageType::kPreSynced, IDS_SETTINGS_EMPTY_STRING,
            IDS_SETTINGS_EMPTY_STRING, SyncStatusActionType::kNoAction};
  }
  DCHECK(identity_manager);
  CoreAccountInfo account_info = sync_service->GetAccountInfo();
  GoogleServiceAuthError auth_error =
      identity_manager->GetErrorStateOfRefreshTokenForAccount(
          account_info.account_id);
  return GetSyncStatusLabelsImpl(
      sync_service, is_user_clear_primary_account_allowed, auth_error);
}

SyncStatusLabels GetSyncStatusLabels(Profile* profile) {
  CHECK(profile);
  signin::IdentityManager* identity_manager =
      IdentityManagerFactory::GetForProfile(profile);
  CHECK(identity_manager);
  return GetSyncStatusLabels(
      SyncServiceFactory::GetForProfile(profile), identity_manager,
      ChromeSigninClientFactory::GetForProfile(profile)
          ->IsClearPrimaryAccountAllowed(identity_manager->HasPrimaryAccount(
              signin::ConsentLevel::kSync)));
}

SyncStatusMessageType GetSyncStatusMessageType(Profile* profile) {
  return GetSyncStatusLabels(profile).message_type;
}

absl::optional<AvatarSyncErrorType> GetAvatarSyncErrorType(Profile* profile) {
  const syncer::SyncService* service =
      SyncServiceFactory::GetForProfile(profile);
  if (!service) {
    return absl::nullopt;
  }

  if (!service->HasSyncConsent()) {
    // Only trusted vault errors can be shown if the account isn't a consented
    // primary account.
    // Note the condition checked is not IsInitialSyncFeatureSetupComplete(),
    // because the setup incomplete case is treated separately below. See the
    // comment in ShouldRequestSyncConfirmation() about dashboard resets.
    return GetTrustedVaultError(service, profile->GetPrefs());
  }

  // RequiresClientUpgrade() is unrecoverable, but is treated separately below.
  if (service->HasUnrecoverableError() && !service->RequiresClientUpgrade()) {
    // Display different messages and buttons for managed accounts.
    if (!ChromeSigninClientFactory::GetForProfile(profile)
             ->IsClearPrimaryAccountAllowed(
                 IdentityManagerFactory::GetForProfile(profile)
                     ->HasPrimaryAccount(signin::ConsentLevel::kSync))) {
      return AvatarSyncErrorType::kManagedUserUnrecoverableError;
    }
    return AvatarSyncErrorType::kUnrecoverableError;
  }

  if (service->GetTransportState() ==
      syncer::SyncService::TransportState::PAUSED) {
    return AvatarSyncErrorType::kSyncPaused;
  }

  if (service->RequiresClientUpgrade()) {
    return AvatarSyncErrorType::kUpgradeClientError;
  }

  if (ShouldShowSyncPassphraseError(service)) {
    return AvatarSyncErrorType::kPassphraseError;
  }

  const absl::optional<AvatarSyncErrorType> trusted_vault_error =
      GetTrustedVaultError(service, profile->GetPrefs());
  if (trusted_vault_error) {
    return trusted_vault_error;
  }

  if (ShouldRequestSyncConfirmation(service)) {
    return AvatarSyncErrorType::kSettingsUnconfirmedError;
  }

  return absl::nullopt;
}

std::u16string GetAvatarSyncErrorDescription(AvatarSyncErrorType error,
                                             bool is_sync_feature_enabled) {
  switch (error) {
    case AvatarSyncErrorType::kSyncPaused:
      return l10n_util::GetStringUTF16(IDS_PROFILES_DICE_SYNC_PAUSED_TITLE);
    case AvatarSyncErrorType::kTrustedVaultKeyMissingForPasswordsError:
      return l10n_util::GetStringUTF16(
          is_sync_feature_enabled
              ? IDS_SYNC_ERROR_PASSWORDS_USER_MENU_TITLE
              : IDS_SYNC_ERROR_PASSWORDS_USER_MENU_TITLE_SIGNED_IN_ONLY);
    case AvatarSyncErrorType::
        kTrustedVaultRecoverabilityDegradedForPasswordsError:
      return l10n_util::GetStringUTF16(
          IDS_SYNC_ERROR_RECOVERABILITY_DEGRADED_FOR_PASSWORDS_USER_MENU_TITLE);
    case AvatarSyncErrorType::
        kTrustedVaultRecoverabilityDegradedForEverythingError:
      return l10n_util::GetStringUTF16(
          IDS_SYNC_ERROR_RECOVERABILITY_DEGRADED_FOR_EVERYTHING_USER_MENU_TITLE);
    case AvatarSyncErrorType::kSettingsUnconfirmedError:
    case AvatarSyncErrorType::kManagedUserUnrecoverableError:
    case AvatarSyncErrorType::kUnrecoverableError:
    case AvatarSyncErrorType::kUpgradeClientError:
    case AvatarSyncErrorType::kPassphraseError:
    case AvatarSyncErrorType::kTrustedVaultKeyMissingForEverythingError:
      return l10n_util::GetStringUTF16(IDS_SYNC_ERROR_USER_MENU_TITLE);
  }
}

bool ShouldRequestSyncConfirmation(const syncer::SyncService* service) {
  // This method mostly handles two situations:
  // 1. The initial Sync setup was aborted without actually disabling Sync
  //    again. That generally shouldn't happen, but it might if Chrome crashed
  //    while the setup was ongoing, or due to past bugs in the setup flow.
  // 2. Sync was reset from the dashboard. That usually signs out the user too,
  //    but it doesn't on ChromeOS, or for managed (enterprise) accounts where
  //    sign-out is prohibited.
  // Note that we do not check IsSyncRequested() here: In situation 1 it'd
  // usually be true, but in situation 2 it's false. Note that while there is a
  // primary account, IsSyncRequested() can only be false if Sync was reset from
  // the dashboard.
  return !service->IsLocalSyncEnabled() && service->HasSyncConsent() &&
         !service->IsSetupInProgress() &&
         !service->GetUserSettings()->IsInitialSyncFeatureSetupComplete();
}

bool ShouldShowSyncPassphraseError(const syncer::SyncService* service) {
  const syncer::SyncUserSettings* settings = service->GetUserSettings();
  return settings->IsInitialSyncFeatureSetupComplete() &&
         settings->IsPassphraseRequiredForPreferredDataTypes();
}

bool ShouldShowSyncKeysMissingError(const syncer::SyncService* sync_service,
                                    const PrefService* pref_service) {
  const syncer::SyncUserSettings* settings = sync_service->GetUserSettings();
  if (!settings->IsTrustedVaultKeyRequiredForPreferredDataTypes()) {
    return false;
  }

  if (settings->IsInitialSyncFeatureSetupComplete()) {
    return true;
  }

  // On desktop transport mode, IsTrustedVaultKeyRequiredForPreferredDataTypes()
  // returns true even if the user isn't trying to sync any of the encrypted
  // types. The check below tries to avoid showing an unexpected "You couldn't
  // sync X" error in that case. It works fine if IsEncryptEverythingEnabled()
  // is false, since PASSWORDS is the only one of AlwaysEncryptedUserTypes()
  // currently supporting transport mode. Otherwise, it should really be OR-ed
  // with other checks.
  // TODO(crbug.com/1447083): Once the Desktop precondition for
  // EnablePasswordsAccountStorage becomes "PASSWORDS is a selected type", and
  // not a PreconditionState of the controller, this function can be replaced
  // with a single IsTrustedVaultKeyRequiredForPreferredDataTypes() check.
  //
  // WARNING: Must match CredentialModelTypeController::GetPreconditionState().
  return password_manager::features_util::IsOptedInForAccountStorage(
      pref_service, sync_service);
}

bool ShouldShowTrustedVaultDegradedRecoverabilityError(
    const syncer::SyncService* sync_service,
    const PrefService* pref_service) {
  const syncer::SyncUserSettings* settings = sync_service->GetUserSettings();
  if (!settings->IsTrustedVaultRecoverabilityDegraded()) {
    return false;
  }

  if (settings->IsInitialSyncFeatureSetupComplete()) {
    return true;
  }

  // On desktop transport mode, IsTrustedVaultRecoverabilityDegraded() returns
  // true even if the user isn't trying to sync any of the encrypted types. The
  // check below tries to avoid unnecessarily showing the error in that case. It
  // works fine if IsEncryptEverythingEnabled() is false, since PASSWORDS is the
  // only one of AlwaysEncryptedUserTypes() currently supporting transport mode.
  // Otherwise, it should really be OR-ed with other checks.
  // TODO(crbug.com/1447083): Once the Desktop precondition for
  // EnablePasswordsAccountStorage becomes "PASSWORDS is a selected type", and
  // not a PreconditionState of the controller, this function can be replaced
  // with a single IsTrustedVaultRecoverabilityDegraded() check.
  //
  // WARNING: Must match CredentialModelTypeController::GetPreconditionState().
  return password_manager::features_util::IsOptedInForAccountStorage(
      pref_service, sync_service);
}

void OpenTabForSyncKeyRetrieval(
    Browser* browser,
    syncer::TrustedVaultUserActionTriggerForUMA trigger) {
  RecordKeyRetrievalTrigger(trigger);
  const GURL continue_url =
      GURL(UIThreadSearchTermsData().GoogleBaseURLValue());
  GURL retrieval_url =
      GaiaUrls::GetInstance()->signin_chrome_sync_keys_retrieval_url();
  if (continue_url.is_valid()) {
    retrieval_url = net::AppendQueryParameter(retrieval_url, "continue",
                                              continue_url.spec());
  }
  OpenTabForSyncTrustedVaultUserAction(browser, retrieval_url);
}

void OpenTabForSyncKeyRecoverabilityDegraded(
    Browser* browser,
    syncer::TrustedVaultUserActionTriggerForUMA trigger) {
  RecordRecoverabilityDegradedFixTrigger(trigger);
  const GURL continue_url =
      GURL(UIThreadSearchTermsData().GoogleBaseURLValue());
  GURL url = GaiaUrls::GetInstance()
                 ->signin_chrome_sync_keys_recoverability_degraded_url();
  if (continue_url.is_valid()) {
    url = net::AppendQueryParameter(url, "continue", continue_url.spec());
  }
  OpenTabForSyncTrustedVaultUserAction(browser, url);
}
