blob: ae0cbd5df7d4f34300627c097bcf7ac8678aaf81 [file] [log] [blame]
// 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 <stddef.h>
#include <map>
#include <memory>
#include <set>
#include <unordered_map>
#include <vector>
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/optional.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/preferences/public/mojom/preferences.mojom.h"
#include "services/preferences/tracked/hash_store_contents.h"
#include "services/preferences/tracked/interceptable_pref_filter.h"
#include "services/preferences/tracked/pref_hash_store.h"
#include "services/preferences/tracked/tracked_preference.h"
class PrefService;
namespace base {
class DictionaryValue;
class Time;
} // namespace base
namespace prefs {
namespace mojom {
class TrackedPreferenceValidationDelegate;
namespace user_prefs {
class PrefRegistrySyncable;
} // namespace user_prefs
// Intercepts preference values as they are loaded from disk and verifies them
// using a PrefHashStore. Keeps the PrefHashStore contents up to date as values
// are changed.
class PrefHashFilter : public InterceptablePrefFilter {
using StoreContentsPair = std::pair<std::unique_ptr<PrefHashStore>,
// Constructs a PrefHashFilter tracking the specified |tracked_preferences|
// using |pref_hash_store| to check/store hashes. An optional |delegate| is
// notified of the status of each preference as it is checked.
// If |reset_on_load_observer| is provided, it will be notified if a reset
// occurs in FilterOnLoad.
// |reporting_ids_count| is the count of all possible IDs (possibly greater
// than |tracked_preferences.size()|).
// |external_validation_hash_store_pair_| will be used (if non-null) to
// perform extra validations without triggering resets.
PrefHashFilter(std::unique_ptr<PrefHashStore> pref_hash_store,
StoreContentsPair external_validation_hash_store_pair_,
const std::vector<prefs::mojom::TrackedPreferenceMetadataPtr>&
prefs::mojom::TrackedPreferenceValidationDelegate* delegate,
size_t reporting_ids_count);
~PrefHashFilter() override;
// Registers required user preferences.
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
// Retrieves the time of the last reset event, if any, for the provided user
// preferences. If no reset has occurred, Returns a null |Time|.
static base::Time GetResetTime(PrefService* user_prefs);
// Clears the time of the last reset event, if any, for the provided user
// preferences.
static void ClearResetTime(PrefService* user_prefs);
// Initializes the PrefHashStore with hashes of the tracked preferences in
// |pref_store_contents|. |pref_store_contents| will be the |storage| passed
// to PrefHashStore::BeginTransaction().
void Initialize(base::DictionaryValue* pref_store_contents);
// PrefFilter remaining implementation.
void FilterUpdate(const std::string& path) override;
OnWriteCallbackPair FilterSerializeData(
base::DictionaryValue* pref_store_contents) override;
void OnStoreDeletionFromDisk() override;
// InterceptablePrefFilter implementation.
void FinalizeFilterOnLoad(
PostFilterOnLoadCallback post_filter_on_load_callback,
std::unique_ptr<base::DictionaryValue> pref_store_contents,
bool prefs_altered) override;
// Helper function to generate FilterSerializeData()'s pre-write and
// post-write callbacks. The returned callbacks are thread-safe.
OnWriteCallbackPair GetOnWriteSynchronousCallbacks(
base::DictionaryValue* pref_store_contents);
// Clears the MACs contained in |external_validation_hash_store_contents|
// which are present in |paths_to_clear|.
static void ClearFromExternalStore(
HashStoreContents* external_validation_hash_store_contents,
const base::DictionaryValue* changed_paths_and_macs);
// Flushes the MACs contained in |changed_paths_and_mac| to
// external_hash_store_contents if |write_success|, otherwise discards the
// changes.
static void FlushToExternalStore(
std::unique_ptr<HashStoreContents> external_hash_store_contents,
std::unique_ptr<base::DictionaryValue> changed_paths_and_macs,
bool write_success);
// Callback to be invoked only once (and subsequently reset) on the next
// FilterOnLoad event. It will be allowed to modify the |prefs| handed to
// FilterOnLoad before handing them back to this PrefHashFilter.
FilterOnLoadInterceptor filter_on_load_interceptor_;
// A map of paths to TrackedPreferences; this map owns this individual
// TrackedPreference objects.
using TrackedPreferencesMap =
std::unordered_map<std::string, std::unique_ptr<TrackedPreference>>;
// A map from changed paths to their corresponding TrackedPreferences (which
// aren't owned by this map).
using ChangedPathsMap = std::map<std::string, const TrackedPreference*>;
std::unique_ptr<PrefHashStore> pref_hash_store_;
// A store and contents on which to perform extra validations without
// triggering resets.
// Will be null if the platform does not support external validation.
base::Optional<StoreContentsPair> external_validation_hash_store_pair_;
// Notified if a reset occurs in a call to FilterOnLoad.
mojo::Remote<prefs::mojom::ResetOnLoadObserver> reset_on_load_observer_;
TrackedPreferencesMap tracked_paths_;
// The set of all paths whose value has changed since the last call to
// FilterSerializeData.
ChangedPathsMap changed_paths_;