// Copyright 2017 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 "components/ukm/observers/sync_disable_observer.h"

#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "components/sync/driver/sync_token_status.h"
#include "components/sync/engine/connection_status.h"
#include "components/unified_consent/feature.h"
#include "components/unified_consent/url_keyed_data_collection_consent_helper.h"

using unified_consent::UrlKeyedDataCollectionConsentHelper;

namespace ukm {

const base::Feature kUkmCheckAuthErrorFeature{"UkmCheckAuthError",
                                              base::FEATURE_ENABLED_BY_DEFAULT};

namespace {

enum DisableInfo {
  DISABLED_BY_NONE,
  DISABLED_BY_HISTORY,
  DISABLED_BY_INITIALIZED,
  DISABLED_BY_HISTORY_INITIALIZED,
  DISABLED_BY_CONNECTED,
  DISABLED_BY_HISTORY_CONNECTED,
  DISABLED_BY_INITIALIZED_CONNECTED,
  DISABLED_BY_HISTORY_INITIALIZED_CONNECTED,
  DISABLED_BY_PASSPHRASE,
  DISABLED_BY_HISTORY_PASSPHRASE,
  DISABLED_BY_INITIALIZED_PASSPHRASE,
  DISABLED_BY_HISTORY_INITIALIZED_PASSPHRASE,
  DISABLED_BY_CONNECTED_PASSPHRASE,
  DISABLED_BY_HISTORY_CONNECTED_PASSPHRASE,
  DISABLED_BY_INITIALIZED_CONNECTED_PASSPHRASE,
  DISABLED_BY_HISTORY_INITIALIZED_CONNECTED_PASSPHRASE,
  DISABLED_BY_ANONYMIZED_DATA_COLLECTION,
  MAX_DISABLE_INFO
};

void RecordDisableInfo(DisableInfo info) {
  UMA_HISTOGRAM_ENUMERATION("UKM.SyncDisable.Info", info, MAX_DISABLE_INFO);
}

}  // namespace

SyncDisableObserver::SyncDisableObserver() : sync_observer_(this) {}

SyncDisableObserver::~SyncDisableObserver() {
  for (const auto& entry : consent_helpers_) {
    entry.second->RemoveObserver(this);
  }
}

bool SyncDisableObserver::SyncState::AllowsUkm() const {
  if (anonymized_data_collection_state == DataCollectionState::kIgnored)
    return history_enabled && initialized && connected && !passphrase_protected;
  else
    return anonymized_data_collection_state == DataCollectionState::kEnabled;
}

bool SyncDisableObserver::SyncState::AllowsUkmWithExtension() const {
  return AllowsUkm() && extensions_enabled && initialized && connected &&
         !passphrase_protected;
}

// static
SyncDisableObserver::SyncState SyncDisableObserver::GetSyncState(
    syncer::SyncService* sync_service,
    UrlKeyedDataCollectionConsentHelper* consent_helper) {
  syncer::SyncTokenStatus status = sync_service->GetSyncTokenStatus();
  SyncState state;
  state.history_enabled = sync_service->GetPreferredDataTypes().Has(
      syncer::HISTORY_DELETE_DIRECTIVES);
  state.extensions_enabled =
      sync_service->GetPreferredDataTypes().Has(syncer::EXTENSIONS);
  state.initialized = sync_service->IsEngineInitialized();
  state.connected = !base::FeatureList::IsEnabled(kUkmCheckAuthErrorFeature) ||
                    status.connection_status == syncer::CONNECTION_OK;
  state.passphrase_protected =
      state.initialized && sync_service->IsUsingSecondaryPassphrase();
  if (consent_helper) {
    state.anonymized_data_collection_state =
        consent_helper->IsEnabled() ? DataCollectionState::kEnabled
                                    : DataCollectionState::kDisabled;
  }
  return state;
}

void SyncDisableObserver::ObserveServiceForSyncDisables(
    syncer::SyncService* sync_service,
    PrefService* prefs) {
  std::unique_ptr<UrlKeyedDataCollectionConsentHelper> consent_helper;
  if (unified_consent::IsUnifiedConsentFeatureEnabled()) {
    consent_helper = UrlKeyedDataCollectionConsentHelper::
        NewAnonymizedDataCollectionConsentHelper(prefs, sync_service);
  }

  SyncState state = GetSyncState(sync_service, consent_helper.get());
  previous_states_[sync_service] = state;

  if (consent_helper) {
    consent_helper->AddObserver(this);
    consent_helpers_[sync_service] = std::move(consent_helper);
  }
  sync_observer_.Add(sync_service);
  UpdateAllProfileEnabled(false);
}

void SyncDisableObserver::UpdateAllProfileEnabled(bool must_purge) {
  bool all_sync_states_allow_ukm = CheckSyncStateOnAllProfiles();
  bool all_sync_states_allow_extension_ukm =
      all_sync_states_allow_ukm && CheckSyncStateForExtensionsOnAllProfiles();
  // Any change in sync settings needs to call OnSyncPrefsChanged so that the
  // new settings take effect.
  if (must_purge || (all_sync_states_allow_ukm != all_sync_states_allow_ukm_) ||
      (all_sync_states_allow_extension_ukm !=
       all_sync_states_allow_extension_ukm_)) {
    all_sync_states_allow_ukm_ = all_sync_states_allow_ukm;
    all_sync_states_allow_extension_ukm_ = all_sync_states_allow_extension_ukm;
    OnSyncPrefsChanged(must_purge);
  }
}

bool SyncDisableObserver::CheckSyncStateOnAllProfiles() {
  if (previous_states_.empty())
    return false;
  for (const auto& kv : previous_states_) {
    const SyncDisableObserver::SyncState& state = kv.second;
    if (!state.AllowsUkm()) {
      int disabled_by = 0;
      if (state.anonymized_data_collection_state ==
          DataCollectionState::kIgnored) {
        if (!state.history_enabled)
          disabled_by |= 1 << 0;
        if (!state.initialized)
          disabled_by |= 1 << 1;
        if (!state.connected)
          disabled_by |= 1 << 2;
        if (state.passphrase_protected)
          disabled_by |= 1 << 3;
      } else {
        DCHECK_EQ(DataCollectionState::kDisabled,
                  state.anonymized_data_collection_state);
        disabled_by |= 1 << 4;
      }
      RecordDisableInfo(DisableInfo(disabled_by));
      return false;
    }
  }
  RecordDisableInfo(DISABLED_BY_NONE);
  return true;
}

bool SyncDisableObserver::CheckSyncStateForExtensionsOnAllProfiles() {
  if (previous_states_.empty())
    return false;
  for (const auto& kv : previous_states_) {
    const SyncDisableObserver::SyncState& state = kv.second;
    if (!state.extensions_enabled)
      return false;
  }
  return true;
}

void SyncDisableObserver::OnStateChanged(syncer::SyncService* sync) {
  UrlKeyedDataCollectionConsentHelper* consent_helper = nullptr;
  auto found = consent_helpers_.find(sync);
  if (found != consent_helpers_.end())
    consent_helper = found->second.get();
  UpdateSyncState(sync, consent_helper);
}

void SyncDisableObserver::OnUrlKeyedDataCollectionConsentStateChanged(
    unified_consent::UrlKeyedDataCollectionConsentHelper* consent_helper) {
  DCHECK(consent_helper);
  syncer::SyncService* sync_service = nullptr;
  for (const auto& entry : consent_helpers_) {
    if (consent_helper == entry.second.get()) {
      sync_service = entry.first;
      break;
    }
  }
  DCHECK(sync_service);
  UpdateSyncState(sync_service, consent_helper);
}

void SyncDisableObserver::UpdateSyncState(
    syncer::SyncService* sync,
    UrlKeyedDataCollectionConsentHelper* consent_helper) {
  DCHECK(base::ContainsKey(previous_states_, sync));
  const SyncDisableObserver::SyncState& previous_state = previous_states_[sync];
  DCHECK(previous_state.anonymized_data_collection_state ==
             DataCollectionState::kIgnored ||
         consent_helper);
  SyncDisableObserver::SyncState state = GetSyncState(sync, consent_helper);
  // Trigger a purge if sync state no longer allows UKM.
  bool must_purge = previous_state.AllowsUkm() && !state.AllowsUkm();
  previous_states_[sync] = state;
  UpdateAllProfileEnabled(must_purge);
}

void SyncDisableObserver::OnSyncShutdown(syncer::SyncService* sync) {
  DCHECK(base::ContainsKey(previous_states_, sync));
  auto found = consent_helpers_.find(sync);
  if (found != consent_helpers_.end()) {
    found->second->RemoveObserver(this);
    consent_helpers_.erase(found);
  }
  sync_observer_.Remove(sync);
  previous_states_.erase(sync);
  UpdateAllProfileEnabled(false);
}

bool SyncDisableObserver::SyncStateAllowsUkm() {
  return all_sync_states_allow_ukm_;
}

bool SyncDisableObserver::SyncStateAllowsExtensionUkm() {
  return all_sync_states_allow_extension_ukm_;
}

}  // namespace ukm
