| Index: components/user_prefs/tracked/pref_hash_filter.cc
|
| diff --git a/components/user_prefs/tracked/pref_hash_filter.cc b/components/user_prefs/tracked/pref_hash_filter.cc
|
| index 2f0c6e71f5f38fb0f878f5d0c3c64fb2207efe83..f0dac5255a84b7c783a5f931673951eec9ce5777 100644
|
| --- a/components/user_prefs/tracked/pref_hash_filter.cc
|
| +++ b/components/user_prefs/tracked/pref_hash_filter.cc
|
| @@ -8,8 +8,11 @@
|
| #include <algorithm>
|
| #include <utility>
|
|
|
| +#include "base/bind.h"
|
| +#include "base/callback.h"
|
| #include "base/logging.h"
|
| #include "base/macros.h"
|
| +#include "base/memory/ptr_util.h"
|
| #include "base/metrics/histogram.h"
|
| #include "base/strings/string_number_conversions.h"
|
| #include "base/time/time.h"
|
| @@ -51,12 +54,18 @@ void CleanupDeprecatedTrackedPreferences(
|
|
|
| PrefHashFilter::PrefHashFilter(
|
| std::unique_ptr<PrefHashStore> pref_hash_store,
|
| + std::unique_ptr<PrefHashStore> external_validation_hash_store,
|
| + std::unique_ptr<HashStoreContents> external_validation_hash_store_contents,
|
| const std::vector<TrackedPreferenceMetadata>& tracked_preferences,
|
| const base::Closure& on_reset_on_load,
|
| TrackedPreferenceValidationDelegate* delegate,
|
| size_t reporting_ids_count,
|
| bool report_super_mac_validity)
|
| : pref_hash_store_(std::move(pref_hash_store)),
|
| + external_validation_hash_store_(
|
| + std::move(external_validation_hash_store)),
|
| + external_validation_hash_store_contents_(
|
| + external_validation_hash_store_contents.release()),
|
| on_reset_on_load_(on_reset_on_load),
|
| report_super_mac_validity_(report_super_mac_validity) {
|
| DCHECK(pref_hash_store_);
|
| @@ -132,14 +141,14 @@ void PrefHashFilter::ClearResetTime(PrefService* user_prefs) {
|
| }
|
|
|
| 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(std::unique_ptr<HashStoreContents>(
|
| - new DictionaryHashStoreContents(pref_store_contents))));
|
| + pref_hash_store_->BeginTransaction(&dictionary_contents));
|
| for (TrackedPreferencesMap::const_iterator it = tracked_paths_.begin();
|
| it != tracked_paths_.end(); ++it) {
|
| const std::string& initialized_path = it->first;
|
| const TrackedPreference* initialized_preference = it->second;
|
| - const base::Value* value = NULL;
|
| + const base::Value* value = nullptr;
|
| pref_store_contents->Get(initialized_path, &value);
|
| initialized_preference->OnNewValue(value, hash_store_transaction.get());
|
| }
|
| @@ -156,30 +165,47 @@ void PrefHashFilter::FilterUpdate(const std::string& path) {
|
| // 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).
|
| -void PrefHashFilter::FilterSerializeData(
|
| +base::Callback<void(bool)> PrefHashFilter::FilterSerializeData(
|
| base::DictionaryValue* pref_store_contents) {
|
| + // Generate the post-write callback before modifying any hashes.
|
| + base::Callback<void(bool)> callback =
|
| + GetOnWriteSynchronousCallback(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(std::unique_ptr<HashStoreContents>(
|
| - new DictionaryHashStoreContents(pref_store_contents))));
|
| + pref_hash_store_->BeginTransaction(&dictionary_contents));
|
| +
|
| + std::unique_ptr<PrefHashStoreTransaction>
|
| + external_validation_hash_store_transaction =
|
| + external_validation_hash_store_ &&
|
| + external_validation_hash_store_contents_
|
| + ? external_validation_hash_store_->BeginTransaction(
|
| + external_validation_hash_store_contents_.get())
|
| + : nullptr;
|
| +
|
| 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 = NULL;
|
| + const base::Value* value = nullptr;
|
| pref_store_contents->Get(changed_path, &value);
|
| changed_preference->OnNewValue(value, hash_store_transaction.get());
|
| +
|
| + // Clear prefs in the external store. They will be repopulated when
|
| + // |callback| is run.
|
| + if (external_validation_hash_store_transaction)
|
| + external_validation_hash_store_transaction->ClearHash(changed_path);
|
| }
|
| changed_paths_.clear();
|
| }
|
| - // TODO(gab): Remove this histogram by Feb 21 2014; after sufficient timing
|
| - // data has been gathered from the wild to be confident this doesn't
|
| - // significantly affect performance on the UI thread.
|
| UMA_HISTOGRAM_TIMES("Settings.FilterSerializeDataTime",
|
| base::TimeTicks::Now() - checkpoint);
|
| }
|
| +
|
| + return callback;
|
| }
|
|
|
| void PrefHashFilter::FinalizeFilterOnLoad(
|
| @@ -191,9 +217,17 @@ void PrefHashFilter::FinalizeFilterOnLoad(
|
|
|
| bool did_reset = false;
|
| {
|
| + DictionaryHashStoreContents dictionary_contents(pref_store_contents.get());
|
| std::unique_ptr<PrefHashStoreTransaction> hash_store_transaction(
|
| - pref_hash_store_->BeginTransaction(std::unique_ptr<HashStoreContents>(
|
| - new DictionaryHashStoreContents(pref_store_contents.get()))));
|
| + pref_hash_store_->BeginTransaction(&dictionary_contents));
|
| +
|
| + std::unique_ptr<PrefHashStoreTransaction>
|
| + external_validation_hash_store_transaction =
|
| + external_validation_hash_store_ &&
|
| + external_validation_hash_store_contents_
|
| + ? external_validation_hash_store_->BeginTransaction(
|
| + external_validation_hash_store_contents_.get())
|
| + : nullptr;
|
|
|
| CleanupDeprecatedTrackedPreferences(
|
| pref_store_contents.get(), hash_store_transaction.get());
|
| @@ -205,8 +239,9 @@ void PrefHashFilter::FinalizeFilterOnLoad(
|
|
|
| for (TrackedPreferencesMap::const_iterator it = tracked_paths_.begin();
|
| it != tracked_paths_.end(); ++it) {
|
| - if (it->second->EnforceAndReport(pref_store_contents.get(),
|
| - hash_store_transaction.get())) {
|
| + if (it->second->EnforceAndReport(
|
| + pref_store_contents.get(), hash_store_transaction.get(),
|
| + external_validation_hash_store_transaction.get())) {
|
| did_reset = true;
|
| prefs_altered = true;
|
| }
|
| @@ -225,12 +260,84 @@ void PrefHashFilter::FinalizeFilterOnLoad(
|
| on_reset_on_load_.Run();
|
| }
|
|
|
| - // TODO(gab): Remove this histogram by Feb 21 2014; after sufficient timing
|
| - // data has been gathered from the wild to be confident this doesn't
|
| - // significantly affect startup.
|
| 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::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::StringValue* 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());
|
| + }
|
| + }
|
| +}
|
| +
|
| +base::Callback<void(bool)> PrefHashFilter::GetOnWriteSynchronousCallback(
|
| + base::DictionaryValue* pref_store_contents) {
|
| + if (changed_paths_.empty() || !external_validation_hash_store_ ||
|
| + !external_validation_hash_store_contents_) {
|
| + return base::Callback<void(bool)>();
|
| + }
|
| +
|
| + std::unique_ptr<base::DictionaryValue> changed_paths_macs(
|
| + new 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;
|
| + const base::Value* value = nullptr;
|
| + pref_store_contents->Get(changed_path, &value);
|
| +
|
| + if (changed_preference->GetType() == TrackedPreferenceType::ATOMIC) {
|
| + changed_paths_macs->SetStringWithoutPathExpansion(
|
| + changed_path,
|
| + external_validation_hash_store_->ComputeMac(changed_path, value));
|
| + } else if (changed_preference->GetType() == TrackedPreferenceType::SPLIT) {
|
| + const base::DictionaryValue* dict_value = nullptr;
|
| + if (value && value->GetAsDictionary(&dict_value)) {
|
| + changed_paths_macs->SetWithoutPathExpansion(
|
| + changed_path, external_validation_hash_store_->ComputeSplitMacs(
|
| + changed_path, dict_value));
|
| + }
|
| + } else {
|
| + NOTREACHED() << "Unsupported TrackedPreferenceType";
|
| + }
|
| + }
|
| +
|
| + return base::Bind(
|
| + &FlushToExternalStore,
|
| + base::Passed(external_validation_hash_store_contents_->MakeCopy()),
|
| + base::Passed(&changed_paths_macs));
|
| +}
|
|
|