// 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 "services/preferences/tracked/pref_hash_filter.h"

#include <stdint.h>
#include <algorithm>
#include <utility>

#include "base/bind.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "base/values.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/pref_store.h"
#include "services/preferences/public/cpp/tracked/pref_names.h"
#include "services/preferences/tracked/dictionary_hash_store_contents.h"
#include "services/preferences/tracked/pref_hash_store.h"
#include "services/preferences/tracked/pref_hash_store_transaction.h"
#include "services/preferences/tracked/tracked_atomic_preference.h"
#include "services/preferences/tracked/tracked_split_preference.h"

namespace {

void CleanupDeprecatedTrackedPreferences(
    base::DictionaryValue* pref_store_contents,
    PrefHashStoreTransaction* hash_store_transaction) {
  // Add deprecated previously tracked preferences below for them to be cleaned
  // up from both the pref files and the hash store.
  static const char* const kDeprecatedTrackedPreferences[] = {
      // TODO(a-v-y): Remove in M60+,
      "default_search_provider.search_url", "default_search_provider.name",
      "default_search_provider.keyword"};

  for (size_t i = 0; i < arraysize(kDeprecatedTrackedPreferences); ++i) {
    const char* key = kDeprecatedTrackedPreferences[i];
    pref_store_contents->Remove(key, NULL);
    hash_store_transaction->ClearHash(key);
  }
}

}  // namespace

using PrefTrackingStrategy =
    prefs::mojom::TrackedPreferenceMetadata::PrefTrackingStrategy;

PrefHashFilter::PrefHashFilter(
    std::unique_ptr<PrefHashStore> pref_hash_store,
    StoreContentsPair external_validation_hash_store_pair,
    const std::vector<prefs::mojom::TrackedPreferenceMetadataPtr>&
        tracked_preferences,
    prefs::mojom::ResetOnLoadObserverPtr reset_on_load_observer,
    prefs::mojom::TrackedPreferenceValidationDelegate* delegate,
    size_t reporting_ids_count,
    bool report_super_mac_validity)
    : pref_hash_store_(std::move(pref_hash_store)),
      external_validation_hash_store_pair_(
          external_validation_hash_store_pair.first
              ? base::make_optional(
                    std::move(external_validation_hash_store_pair))
              : base::nullopt),
      reset_on_load_observer_(std::move(reset_on_load_observer)),
      report_super_mac_validity_(report_super_mac_validity) {
  DCHECK(pref_hash_store_);
  DCHECK_GE(reporting_ids_count, tracked_preferences.size());
  // Verify that, if |external_validation_hash_store_pair_| is present, both its
  // items are non-null.
  DCHECK(!external_validation_hash_store_pair_.has_value() ||
         (external_validation_hash_store_pair_->first &&
          external_validation_hash_store_pair_->second));

  for (size_t i = 0; i < tracked_preferences.size(); ++i) {
    const prefs::mojom::TrackedPreferenceMetadata& metadata =
        *tracked_preferences[i];

    std::unique_ptr<TrackedPreference> tracked_preference;
    switch (metadata.strategy) {
      case PrefTrackingStrategy::ATOMIC:
        tracked_preference.reset(new TrackedAtomicPreference(
            metadata.name, metadata.reporting_id, reporting_ids_count,
            metadata.enforcement_level, metadata.value_type, delegate));
        break;
      case PrefTrackingStrategy::SPLIT:
        tracked_preference.reset(new TrackedSplitPreference(
            metadata.name, metadata.reporting_id, reporting_ids_count,
            metadata.enforcement_level, metadata.value_type, delegate));
        break;
    }
    DCHECK(tracked_preference);

    bool is_new = tracked_paths_
                      .insert(std::make_pair(metadata.name,
                                             std::move(tracked_preference)))
                      .second;
    DCHECK(is_new);
  }
}

PrefHashFilter::~PrefHashFilter() {
  // Ensure new values for all |changed_paths_| have been flushed to
  // |pref_hash_store_| already.
  DCHECK(changed_paths_.empty());
}

// static
void PrefHashFilter::RegisterProfilePrefs(
    user_prefs::PrefRegistrySyncable* registry) {
  // See GetResetTime for why this is a StringPref and not Int64Pref.
  registry->RegisterStringPref(
      user_prefs::kPreferenceResetTime,
      base::Int64ToString(base::Time().ToInternalValue()));
}

// static
base::Time PrefHashFilter::GetResetTime(PrefService* user_prefs) {
  // Provide our own implementation (identical to the PrefService::GetInt64) in
  // order to ensure it remains consistent with the way we store this value
  // (which we do via a PrefStore, preventing us from reusing
  // PrefService::SetInt64).
  int64_t internal_value = base::Time().ToInternalValue();
  if (!base::StringToInt64(
          user_prefs->GetString(user_prefs::kPreferenceResetTime),
          &internal_value)) {
    // Somehow the value stored on disk is not a valid int64_t.
    NOTREACHED();
    return base::Time();
  }
  return base::Time::FromInternalValue(internal_value);
}

// static
void PrefHashFilter::ClearResetTime(PrefService* user_prefs) {
  user_prefs->ClearPref(user_prefs::kPreferenceResetTime);
}

void PrefHashFilter::Initialize(base::DictionaryValue* pref_store_contents) {
  DictionaryHashStoreContents dictionary_contents(pref_store_contents);
  std::unique_ptr<PrefHashStoreTransaction> hash_store_transaction(
      pref_hash_store_->BeginTransaction(&dictionary_contents));
  for (auto it = tracked_paths_.begin(); it != tracked_paths_.end(); ++it) {
    const std::string& initialized_path = it->first;
    const TrackedPreference* initialized_preference = it->second.get();
    const base::Value* value = nullptr;
    pref_store_contents->Get(initialized_path, &value);
    initialized_preference->OnNewValue(value, hash_store_transaction.get());
  }
}

// Marks |path| has having changed if it is part of |tracked_paths_|. A new hash
// will be stored for it the next time FilterSerializeData() is invoked.
void PrefHashFilter::FilterUpdate(const std::string& path) {
  auto it = tracked_paths_.find(path);
  if (it != tracked_paths_.end())
    changed_paths_.insert(std::make_pair(path, it->second.get()));
}

// Updates the stored hashes for |changed_paths_| before serializing data to
// disk. This is required as storing the hash everytime a pref's value changes
// is too expensive (see perf regression @ http://crbug.com/331273).
PrefFilter::OnWriteCallbackPair PrefHashFilter::FilterSerializeData(
    base::DictionaryValue* pref_store_contents) {
  // Generate the callback pair before clearing |changed_paths_|.
  PrefFilter::OnWriteCallbackPair callback_pair =
      GetOnWriteSynchronousCallbacks(pref_store_contents);

  if (!changed_paths_.empty()) {
    base::TimeTicks checkpoint = base::TimeTicks::Now();
    {
      DictionaryHashStoreContents dictionary_contents(pref_store_contents);
      std::unique_ptr<PrefHashStoreTransaction> hash_store_transaction(
          pref_hash_store_->BeginTransaction(&dictionary_contents));

      std::unique_ptr<PrefHashStoreTransaction>
          external_validation_hash_store_transaction;
      if (external_validation_hash_store_pair_) {
        external_validation_hash_store_transaction =
            external_validation_hash_store_pair_->first->BeginTransaction(
                external_validation_hash_store_pair_->second.get());
      }

      for (ChangedPathsMap::const_iterator it = changed_paths_.begin();
           it != changed_paths_.end(); ++it) {
        const std::string& changed_path = it->first;
        const TrackedPreference* changed_preference = it->second;
        const base::Value* value = nullptr;
        pref_store_contents->Get(changed_path, &value);
        changed_preference->OnNewValue(value, hash_store_transaction.get());
      }
      changed_paths_.clear();
    }
    UMA_HISTOGRAM_TIMES("Settings.FilterSerializeDataTime",
                        base::TimeTicks::Now() - checkpoint);
  }

  return callback_pair;
}

void PrefHashFilter::FinalizeFilterOnLoad(
    const PostFilterOnLoadCallback& post_filter_on_load_callback,
    std::unique_ptr<base::DictionaryValue> pref_store_contents,
    bool prefs_altered) {
  DCHECK(pref_store_contents);
  base::TimeTicks checkpoint = base::TimeTicks::Now();

  bool did_reset = false;
  {
    DictionaryHashStoreContents dictionary_contents(pref_store_contents.get());
    std::unique_ptr<PrefHashStoreTransaction> hash_store_transaction(
        pref_hash_store_->BeginTransaction(&dictionary_contents));

    std::unique_ptr<PrefHashStoreTransaction>
        external_validation_hash_store_transaction;
    if (external_validation_hash_store_pair_) {
      external_validation_hash_store_transaction =
          external_validation_hash_store_pair_->first->BeginTransaction(
              external_validation_hash_store_pair_->second.get());
    }

    CleanupDeprecatedTrackedPreferences(pref_store_contents.get(),
                                        hash_store_transaction.get());

    if (report_super_mac_validity_) {
      UMA_HISTOGRAM_BOOLEAN("Settings.HashesDictionaryTrusted",
                            hash_store_transaction->IsSuperMACValid());
    }

    for (auto it = tracked_paths_.begin(); it != tracked_paths_.end(); ++it) {
      if (it->second->EnforceAndReport(
              pref_store_contents.get(), hash_store_transaction.get(),
              external_validation_hash_store_transaction.get())) {
        did_reset = true;
        prefs_altered = true;
      }
    }
    if (hash_store_transaction->StampSuperMac())
      prefs_altered = true;
  }

  if (did_reset) {
    pref_store_contents->SetString(
        user_prefs::kPreferenceResetTime,
        base::Int64ToString(base::Time::Now().ToInternalValue()));
    FilterUpdate(user_prefs::kPreferenceResetTime);

    if (reset_on_load_observer_)
      reset_on_load_observer_->OnResetOnLoad();
  }
  reset_on_load_observer_.reset();

  UMA_HISTOGRAM_TIMES("Settings.FilterOnLoadTime",
                      base::TimeTicks::Now() - checkpoint);

  post_filter_on_load_callback.Run(std::move(pref_store_contents),
                                   prefs_altered);
}

// static
void PrefHashFilter::ClearFromExternalStore(
    HashStoreContents* external_validation_hash_store_contents,
    const base::DictionaryValue* changed_paths_and_macs) {
  DCHECK(!changed_paths_and_macs->empty());

  for (base::DictionaryValue::Iterator it(*changed_paths_and_macs);
       !it.IsAtEnd(); it.Advance()) {
    external_validation_hash_store_contents->RemoveEntry(it.key());
  }
}

// static
void PrefHashFilter::FlushToExternalStore(
    std::unique_ptr<HashStoreContents> external_validation_hash_store_contents,
    std::unique_ptr<base::DictionaryValue> changed_paths_and_macs,
    bool write_success) {
  DCHECK(!changed_paths_and_macs->empty());
  DCHECK(external_validation_hash_store_contents);
  if (!write_success)
    return;

  for (base::DictionaryValue::Iterator it(*changed_paths_and_macs);
       !it.IsAtEnd(); it.Advance()) {
    const std::string& changed_path = it.key();

    const base::DictionaryValue* split_values = nullptr;
    if (it.value().GetAsDictionary(&split_values)) {
      for (base::DictionaryValue::Iterator inner_it(*split_values);
           !inner_it.IsAtEnd(); inner_it.Advance()) {
        std::string mac;
        bool is_string = inner_it.value().GetAsString(&mac);
        DCHECK(is_string);

        external_validation_hash_store_contents->SetSplitMac(
            changed_path, inner_it.key(), mac);
      }
    } else {
      const base::Value* value_as_string;
      bool is_string = it.value().GetAsString(&value_as_string);
      DCHECK(is_string);

      external_validation_hash_store_contents->SetMac(
          changed_path, value_as_string->GetString());
    }
  }
}

PrefFilter::OnWriteCallbackPair PrefHashFilter::GetOnWriteSynchronousCallbacks(
    base::DictionaryValue* pref_store_contents) {
  if (changed_paths_.empty() || !external_validation_hash_store_pair_) {
    return std::make_pair(base::Closure(),
                          base::Callback<void(bool success)>());
  }

  std::unique_ptr<base::DictionaryValue> changed_paths_macs =
      base::MakeUnique<base::DictionaryValue>();

  for (ChangedPathsMap::const_iterator it = changed_paths_.begin();
       it != changed_paths_.end(); ++it) {
    const std::string& changed_path = it->first;
    const TrackedPreference* changed_preference = it->second;

    switch (changed_preference->GetType()) {
      case TrackedPreferenceType::ATOMIC: {
        const base::Value* new_value = nullptr;
        pref_store_contents->Get(changed_path, &new_value);
        changed_paths_macs->SetStringWithoutPathExpansion(
            changed_path,
            external_validation_hash_store_pair_->first->ComputeMac(
                changed_path, new_value));
        break;
      }
      case TrackedPreferenceType::SPLIT: {
        const base::DictionaryValue* dict_value = nullptr;
        pref_store_contents->GetDictionary(changed_path, &dict_value);
        changed_paths_macs->SetWithoutPathExpansion(
            changed_path,
            external_validation_hash_store_pair_->first->ComputeSplitMacs(
                changed_path, dict_value));
        break;
      }
    }
  }

  DCHECK(external_validation_hash_store_pair_->second->IsCopyable())
      << "External HashStoreContents must be copyable as it needs to be used "
         "off-thread";

  std::unique_ptr<HashStoreContents> hash_store_contents_copy =
      external_validation_hash_store_pair_->second->MakeCopy();

  // We can use raw pointers for the first callback instead of making more
  // copies as it will be executed in sequence before the second callback,
  // which owns the pointers.
  HashStoreContents* raw_contents = hash_store_contents_copy.get();
  base::DictionaryValue* raw_changed_paths_macs = changed_paths_macs.get();

  return std::make_pair(
      base::Bind(&ClearFromExternalStore, base::Unretained(raw_contents),
                 base::Unretained(raw_changed_paths_macs)),
      base::Bind(&FlushToExternalStore, base::Passed(&hash_store_contents_copy),
                 base::Passed(&changed_paths_macs)));
}
