summaryrefslogtreecommitdiff
path: root/chromium/components/user_prefs
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-01-04 14:17:57 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-01-05 10:05:06 +0000
commit39d357e3248f80abea0159765ff39554affb40db (patch)
treeaba0e6bfb76de0244bba0f5fdbd64b830dd6e621 /chromium/components/user_prefs
parent87778abf5a1f89266f37d1321b92a21851d8244d (diff)
downloadqtwebengine-chromium-39d357e3248f80abea0159765ff39554affb40db.tar.gz
BASELINE: Update Chromium to 55.0.2883.105
And updates ninja to 1.7.2 Change-Id: I20d43c737f82764d857ada9a55586901b18b9243 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/components/user_prefs')
-rw-r--r--chromium/components/user_prefs/tracked/BUILD.gn9
-rw-r--r--chromium/components/user_prefs/tracked/dictionary_hash_store_contents.cc127
-rw-r--r--chromium/components/user_prefs/tracked/dictionary_hash_store_contents.h22
-rw-r--r--chromium/components/user_prefs/tracked/hash_store_contents.h73
-rw-r--r--chromium/components/user_prefs/tracked/mock_validation_delegate.cc27
-rw-r--r--chromium/components/user_prefs/tracked/mock_validation_delegate.h29
-rw-r--r--chromium/components/user_prefs/tracked/pref_hash_calculator_unittest.cc7
-rw-r--r--chromium/components/user_prefs/tracked/pref_hash_filter.cc172
-rw-r--r--chromium/components/user_prefs/tracked/pref_hash_filter.h37
-rw-r--r--chromium/components/user_prefs/tracked/pref_hash_filter_unittest.cc360
-rw-r--r--chromium/components/user_prefs/tracked/pref_hash_store.h22
-rw-r--r--chromium/components/user_prefs/tracked/pref_hash_store_impl.cc153
-rw-r--r--chromium/components/user_prefs/tracked/pref_hash_store_impl.h20
-rw-r--r--chromium/components/user_prefs/tracked/pref_hash_store_impl_unittest.cc106
-rw-r--r--chromium/components/user_prefs/tracked/pref_hash_store_transaction.h8
-rw-r--r--chromium/components/user_prefs/tracked/pref_service_hash_store_contents.cc146
-rw-r--r--chromium/components/user_prefs/tracked/pref_service_hash_store_contents.h72
-rw-r--r--chromium/components/user_prefs/tracked/pref_service_hash_store_contents_unittest.cc152
-rw-r--r--chromium/components/user_prefs/tracked/registry_hash_store_contents_win.cc182
-rw-r--r--chromium/components/user_prefs/tracked/registry_hash_store_contents_win.h49
-rw-r--r--chromium/components/user_prefs/tracked/registry_hash_store_contents_win_unittest.cc119
-rw-r--r--chromium/components/user_prefs/tracked/segregated_pref_store.cc10
-rw-r--r--chromium/components/user_prefs/tracked/segregated_pref_store_unittest.cc12
-rw-r--r--chromium/components/user_prefs/tracked/tracked_atomic_preference.cc34
-rw-r--r--chromium/components/user_prefs/tracked/tracked_atomic_preference.h7
-rw-r--r--chromium/components/user_prefs/tracked/tracked_preference.h12
-rw-r--r--chromium/components/user_prefs/tracked/tracked_preference_helper.cc72
-rw-r--r--chromium/components/user_prefs/tracked/tracked_preference_helper.h5
-rw-r--r--chromium/components/user_prefs/tracked/tracked_preference_histogram_names.cc1
-rw-r--r--chromium/components/user_prefs/tracked/tracked_preference_histogram_names.h1
-rw-r--r--chromium/components/user_prefs/tracked/tracked_preference_validation_delegate.h3
-rw-r--r--chromium/components/user_prefs/tracked/tracked_preferences_migration.cc58
-rw-r--r--chromium/components/user_prefs/tracked/tracked_preferences_migration.h12
-rw-r--r--chromium/components/user_prefs/tracked/tracked_preferences_migration_unittest.cc255
-rw-r--r--chromium/components/user_prefs/tracked/tracked_split_preference.cc41
-rw-r--r--chromium/components/user_prefs/tracked/tracked_split_preference.h7
36 files changed, 1447 insertions, 975 deletions
diff --git a/chromium/components/user_prefs/tracked/BUILD.gn b/chromium/components/user_prefs/tracked/BUILD.gn
index 3afd2bc7744..d2108c61762 100644
--- a/chromium/components/user_prefs/tracked/BUILD.gn
+++ b/chromium/components/user_prefs/tracked/BUILD.gn
@@ -23,8 +23,8 @@ static_library("user_prefs_tracked") {
"pref_hash_store_transaction.h",
"pref_names.cc",
"pref_names.h",
- "pref_service_hash_store_contents.cc",
- "pref_service_hash_store_contents.h",
+ "registry_hash_store_contents_win.cc",
+ "registry_hash_store_contents_win.h",
"segregated_pref_store.cc",
"segregated_pref_store.h",
"tracked_atomic_preference.cc",
@@ -56,7 +56,7 @@ static_library("user_prefs_tracked") {
]
}
-source_set("user_prefs_tracked_test_support") {
+static_library("user_prefs_tracked_test_support") {
testonly = true
sources = [
"mock_validation_delegate.cc",
@@ -76,7 +76,7 @@ source_set("unit_tests") {
"pref_hash_calculator_unittest.cc",
"pref_hash_filter_unittest.cc",
"pref_hash_store_impl_unittest.cc",
- "pref_service_hash_store_contents_unittest.cc",
+ "registry_hash_store_contents_win_unittest.cc",
"segregated_pref_store_unittest.cc",
"tracked_preferences_migration_unittest.cc",
]
@@ -85,6 +85,7 @@ source_set("unit_tests") {
":user_prefs_tracked",
":user_prefs_tracked_test_support",
"//base:base",
+ "//base/test:test_support",
"//components/prefs:test_support",
"//testing/gtest",
]
diff --git a/chromium/components/user_prefs/tracked/dictionary_hash_store_contents.cc b/chromium/components/user_prefs/tracked/dictionary_hash_store_contents.cc
index 899cafabec1..288c1bf45db 100644
--- a/chromium/components/user_prefs/tracked/dictionary_hash_store_contents.cc
+++ b/chromium/components/user_prefs/tracked/dictionary_hash_store_contents.cc
@@ -12,42 +12,10 @@
#include "components/prefs/persistent_pref_store.h"
namespace {
-
const char kPreferenceMACs[] = "protection.macs";
const char kSuperMACPref[] = "protection.super_mac";
-
-class MutablePreferenceMacDictionary
- : public HashStoreContents::MutableDictionary {
- public:
- explicit MutablePreferenceMacDictionary(base::DictionaryValue* storage);
-
- // MutableDictionary implementation
- base::DictionaryValue* operator->() override;
-
- private:
- base::DictionaryValue* storage_;
-
- DISALLOW_COPY_AND_ASSIGN(MutablePreferenceMacDictionary);
-};
-
-MutablePreferenceMacDictionary::MutablePreferenceMacDictionary(
- base::DictionaryValue* storage)
- : storage_(storage) {
}
-base::DictionaryValue* MutablePreferenceMacDictionary::operator->() {
- base::DictionaryValue* mac_dictionary = NULL;
-
- if (!storage_->GetDictionary(kPreferenceMACs, &mac_dictionary)) {
- mac_dictionary = new base::DictionaryValue;
- storage_->Set(kPreferenceMACs, mac_dictionary);
- }
-
- return mac_dictionary;
-}
-
-} // namespace
-
DictionaryHashStoreContents::DictionaryHashStoreContents(
base::DictionaryValue* storage)
: storage_(storage) {
@@ -60,28 +28,82 @@ void DictionaryHashStoreContents::RegisterProfilePrefs(
registry->RegisterStringPref(kSuperMACPref, std::string());
}
-std::string DictionaryHashStoreContents::hash_store_id() const {
- return "";
+bool DictionaryHashStoreContents::IsCopyable() const {
+ return false;
+}
+
+std::unique_ptr<HashStoreContents> DictionaryHashStoreContents::MakeCopy()
+ const {
+ NOTREACHED() << "DictionaryHashStoreContents does not support MakeCopy";
+ return nullptr;
+}
+
+base::StringPiece DictionaryHashStoreContents::GetUMASuffix() const {
+ // To stay consistent with existing reported data, do not append a suffix
+ // when reporting UMA stats for this content.
+ return base::StringPiece();
}
void DictionaryHashStoreContents::Reset() {
storage_->Remove(kPreferenceMACs, NULL);
}
-bool DictionaryHashStoreContents::IsInitialized() const {
- return storage_->GetDictionary(kPreferenceMACs, NULL);
+bool DictionaryHashStoreContents::GetMac(const std::string& path,
+ std::string* out_value) {
+ const base::DictionaryValue* macs_dict = GetContents();
+ if (macs_dict)
+ return macs_dict->GetString(path, out_value);
+
+ return false;
}
-const base::DictionaryValue* DictionaryHashStoreContents::GetContents() const {
- const base::DictionaryValue* mac_dictionary = NULL;
- storage_->GetDictionary(kPreferenceMACs, &mac_dictionary);
- return mac_dictionary;
+bool DictionaryHashStoreContents::GetSplitMacs(
+ const std::string& path,
+ std::map<std::string, std::string>* split_macs) {
+ DCHECK(split_macs);
+ DCHECK(split_macs->empty());
+
+ const base::DictionaryValue* macs_dict = GetContents();
+ const base::DictionaryValue* split_macs_dict = NULL;
+ if (!macs_dict || !macs_dict->GetDictionary(path, &split_macs_dict))
+ return false;
+ for (base::DictionaryValue::Iterator it(*split_macs_dict); !it.IsAtEnd();
+ it.Advance()) {
+ std::string mac_string;
+ if (!it.value().GetAsString(&mac_string)) {
+ NOTREACHED();
+ continue;
+ }
+ split_macs->insert(make_pair(it.key(), mac_string));
+ }
+ return true;
}
-std::unique_ptr<HashStoreContents::MutableDictionary>
-DictionaryHashStoreContents::GetMutableContents() {
- return std::unique_ptr<MutableDictionary>(
- new MutablePreferenceMacDictionary(storage_));
+void DictionaryHashStoreContents::SetMac(const std::string& path,
+ const std::string& value) {
+ base::DictionaryValue* macs_dict = GetMutableContents(true);
+ macs_dict->SetString(path, value);
+}
+
+void DictionaryHashStoreContents::SetSplitMac(const std::string& path,
+ const std::string& split_path,
+ const std::string& value) {
+ // DictionaryValue handles a '.' delimiter.
+ SetMac(path + '.' + split_path, value);
+}
+
+void DictionaryHashStoreContents::ImportEntry(const std::string& path,
+ const base::Value* in_value) {
+ base::DictionaryValue* macs_dict = GetMutableContents(true);
+ macs_dict->Set(path, in_value->DeepCopy());
+}
+
+bool DictionaryHashStoreContents::RemoveEntry(const std::string& path) {
+ base::DictionaryValue* macs_dict = GetMutableContents(false);
+ if (macs_dict)
+ return macs_dict->RemovePath(path, NULL);
+
+ return false;
}
std::string DictionaryHashStoreContents::GetSuperMac() const {
@@ -93,3 +115,20 @@ std::string DictionaryHashStoreContents::GetSuperMac() const {
void DictionaryHashStoreContents::SetSuperMac(const std::string& super_mac) {
storage_->SetString(kSuperMACPref, super_mac);
}
+
+const base::DictionaryValue* DictionaryHashStoreContents::GetContents() const {
+ const base::DictionaryValue* macs_dict = NULL;
+ storage_->GetDictionary(kPreferenceMACs, &macs_dict);
+ return macs_dict;
+}
+
+base::DictionaryValue* DictionaryHashStoreContents::GetMutableContents(
+ bool create_if_null) {
+ base::DictionaryValue* macs_dict = NULL;
+ storage_->GetDictionary(kPreferenceMACs, &macs_dict);
+ if (!macs_dict && create_if_null) {
+ macs_dict = new base::DictionaryValue;
+ storage_->Set(kPreferenceMACs, macs_dict);
+ }
+ return macs_dict;
+}
diff --git a/chromium/components/user_prefs/tracked/dictionary_hash_store_contents.h b/chromium/components/user_prefs/tracked/dictionary_hash_store_contents.h
index b47d0e0bce4..f231c257bdd 100644
--- a/chromium/components/user_prefs/tracked/dictionary_hash_store_contents.h
+++ b/chromium/components/user_prefs/tracked/dictionary_hash_store_contents.h
@@ -5,12 +5,12 @@
#ifndef COMPONENTS_USER_PREFS_TRACKED_DICTIONARY_HASH_STORE_CONTENTS_H_
#define COMPONENTS_USER_PREFS_TRACKED_DICTIONARY_HASH_STORE_CONTENTS_H_
-#include "base/compiler_specific.h"
#include "base/macros.h"
#include "components/user_prefs/tracked/hash_store_contents.h"
namespace base {
class DictionaryValue;
+class Value;
} // namespace base
namespace user_prefs {
@@ -31,17 +31,31 @@ class DictionaryHashStoreContents : public HashStoreContents {
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
// HashStoreContents implementation
- std::string hash_store_id() const override;
+ bool IsCopyable() const override;
+ std::unique_ptr<HashStoreContents> MakeCopy() const override;
+ base::StringPiece GetUMASuffix() const override;
void Reset() override;
- bool IsInitialized() const override;
+ bool GetMac(const std::string& path, std::string* out_value) override;
+ bool GetSplitMacs(const std::string& path,
+ std::map<std::string, std::string>* split_macs) override;
+ void SetMac(const std::string& path, const std::string& value) override;
+ void SetSplitMac(const std::string& path,
+ const std::string& split_path,
+ const std::string& value) override;
+ void ImportEntry(const std::string& path,
+ const base::Value* in_value) override;
+ bool RemoveEntry(const std::string& path) override;
const base::DictionaryValue* GetContents() const override;
- std::unique_ptr<MutableDictionary> GetMutableContents() override;
std::string GetSuperMac() const override;
void SetSuperMac(const std::string& super_mac) override;
private:
base::DictionaryValue* storage_;
+ // Helper function to get a mutable version of the macs from |storage_|,
+ // creating it if needed and |create_if_null| is true.
+ base::DictionaryValue* GetMutableContents(bool create_if_null);
+
DISALLOW_COPY_AND_ASSIGN(DictionaryHashStoreContents);
};
diff --git a/chromium/components/user_prefs/tracked/hash_store_contents.h b/chromium/components/user_prefs/tracked/hash_store_contents.h
index 94323843cc1..9cc8abba090 100644
--- a/chromium/components/user_prefs/tracked/hash_store_contents.h
+++ b/chromium/components/user_prefs/tracked/hash_store_contents.h
@@ -5,12 +5,15 @@
#ifndef COMPONENTS_USER_PREFS_TRACKED_HASH_STORE_CONTENTS_H_
#define COMPONENTS_USER_PREFS_TRACKED_HASH_STORE_CONTENTS_H_
+#include <map>
#include <memory>
#include <string>
+#include "base/strings/string_piece.h"
namespace base {
class DictionaryValue;
+class Value;
} // namespace base
// Provides access to the contents of a preference hash store. The store
@@ -19,41 +22,65 @@ class DictionaryValue;
// MACs.
// Version: a client-defined version number for the format of Contents.
// Super MAC: a MAC that authenticates the entirety of Contents.
-// Legacy hash stores may have an ID that was incorporated into MAC
-// calculations. The ID, if any, is available via |hash_store_id()|.
class HashStoreContents {
public:
- // Used to modify a DictionaryValue stored in the preference hash store. The
- // MutableDictionary should be destroyed when modifications are complete in
- // order to allow them to be committed to the underlying storage.
- class MutableDictionary {
- public:
- virtual ~MutableDictionary() {}
- // Returns the DictionaryValue, which will be created if it does not already
- // exist.
- virtual base::DictionaryValue* operator->() = 0;
- };
-
virtual ~HashStoreContents() {}
- // Returns the hash-store ID. May be empty.
- virtual std::string hash_store_id() const = 0;
+ // Returns true if this implementation of HashStoreContents can be copied via
+ // MakeCopy().
+ virtual bool IsCopyable() const = 0;
+
+ // Returns a copy of this HashStoreContents. Must only be called on
+ // lightweight implementations (which return true from IsCopyable()) and only
+ // in scenarios where a copy cannot be avoided.
+ virtual std::unique_ptr<HashStoreContents> MakeCopy() const = 0;
+
+ // Returns the suffix to be appended to UMA histograms for this store type.
+ // The returned value must either be an empty string or one of the values in
+ // histograms.xml's TrackedPreferencesExternalValidators.
+ virtual base::StringPiece GetUMASuffix() const = 0;
// Discards all data related to this hash store.
virtual void Reset() = 0;
- // Indicates whether any data is currently stored for this hash store.
- virtual bool IsInitialized() const = 0;
+ // Outputs the MAC validating the preference at path. Returns true if a MAC
+ // was successfully read and false otherwise.
+ virtual bool GetMac(const std::string& path, std::string* out_value) = 0;
- // Retrieves the contents of this hash store. May return NULL if the hash
- // store has not been initialized.
- virtual const base::DictionaryValue* GetContents() const = 0;
+ // Outputs the MACS validating the split preference at path. Returns true if
+ // MACS were successfully read and false otherwise.
+ virtual bool GetSplitMacs(const std::string& path,
+ std::map<std::string, std::string>* out_value) = 0;
+
+ // Set the MAC validating the preference at path.
+ virtual void SetMac(const std::string& path, const std::string& value) = 0;
- // Provides mutable access to the contents of this hash store.
- virtual std::unique_ptr<MutableDictionary> GetMutableContents() = 0;
+ // Set the MAC validating the split preference at path and split_path.
+ // For example, |path| is 'extension' and |split_path| is some extenson id.
+ virtual void SetSplitMac(const std::string& path,
+ const std::string& split_path,
+ const std::string& value) = 0;
+
+ // Sets the MAC for the preference at |path|.
+ // If |path| is a split preference |in_value| must be a DictionaryValue whose
+ // keys are keys in the split preference and whose values are MACs of the
+ // corresponding values in the split preference.
+ // If |path| is an atomic preference |in_value| must be a StringValue
+ // containing a MAC of the preference value.
+ virtual void ImportEntry(const std::string& path,
+ const base::Value* in_value) = 0;
+
+ // Removes the MAC (for atomic preferences) or MACs (for split preferences)
+ // at |path|. Returns true if there was an entry at |path| which was
+ // successfully removed.
+ virtual bool RemoveEntry(const std::string& path) = 0;
+
+ // Only needed if this store supports super MACs.
+ virtual const base::DictionaryValue* GetContents() const = 0;
// Retrieves the super MAC value previously stored by SetSuperMac. May be
- // empty if no super MAC has been stored.
+ // empty if no super MAC has been stored or if this store does not support
+ // super MACs.
virtual std::string GetSuperMac() const = 0;
// Stores a super MAC value for this hash store.
diff --git a/chromium/components/user_prefs/tracked/mock_validation_delegate.cc b/chromium/components/user_prefs/tracked/mock_validation_delegate.cc
index d2936af55be..e0e88283c48 100644
--- a/chromium/components/user_prefs/tracked/mock_validation_delegate.cc
+++ b/chromium/components/user_prefs/tracked/mock_validation_delegate.cc
@@ -20,6 +20,16 @@ size_t MockValidationDelegate::CountValidationsOfState(
return count;
}
+size_t MockValidationDelegate::CountExternalValidationsOfState(
+ PrefHashStoreTransaction::ValueState value_state) const {
+ size_t count = 0;
+ for (size_t i = 0; i < validations_.size(); ++i) {
+ if (validations_[i].external_validation_value_state == value_state)
+ ++count;
+ }
+ return count;
+}
+
const MockValidationDelegate::ValidationEvent*
MockValidationDelegate::GetEventForPath(const std::string& pref_path) const {
for (size_t i = 0; i < validations_.size(); ++i) {
@@ -33,26 +43,31 @@ void MockValidationDelegate::OnAtomicPreferenceValidation(
const std::string& pref_path,
const base::Value* value,
PrefHashStoreTransaction::ValueState value_state,
+ PrefHashStoreTransaction::ValueState external_validation_value_state,
bool is_personal) {
- RecordValidation(pref_path, value_state, is_personal,
- PrefHashFilter::TRACKING_STRATEGY_ATOMIC);
+ RecordValidation(pref_path, value_state, external_validation_value_state,
+ is_personal, PrefHashFilter::TRACKING_STRATEGY_ATOMIC);
}
void MockValidationDelegate::OnSplitPreferenceValidation(
const std::string& pref_path,
const base::DictionaryValue* dict_value,
const std::vector<std::string>& invalid_keys,
+ const std::vector<std::string>& external_validation_invalid_keys,
PrefHashStoreTransaction::ValueState value_state,
+ PrefHashStoreTransaction::ValueState external_validation_value_state,
bool is_personal) {
- RecordValidation(pref_path, value_state, is_personal,
- PrefHashFilter::TRACKING_STRATEGY_SPLIT);
+ RecordValidation(pref_path, value_state, external_validation_value_state,
+ is_personal, PrefHashFilter::TRACKING_STRATEGY_SPLIT);
}
void MockValidationDelegate::RecordValidation(
const std::string& pref_path,
PrefHashStoreTransaction::ValueState value_state,
+ PrefHashStoreTransaction::ValueState external_validation_value_state,
bool is_personal,
PrefHashFilter::PrefTrackingStrategy strategy) {
- validations_.push_back(
- ValidationEvent(pref_path, value_state, is_personal, strategy));
+ validations_.push_back(ValidationEvent(pref_path, value_state,
+ external_validation_value_state,
+ is_personal, strategy));
}
diff --git a/chromium/components/user_prefs/tracked/mock_validation_delegate.h b/chromium/components/user_prefs/tracked/mock_validation_delegate.h
index 0b8cb12ce43..de95f0599ed 100644
--- a/chromium/components/user_prefs/tracked/mock_validation_delegate.h
+++ b/chromium/components/user_prefs/tracked/mock_validation_delegate.h
@@ -20,17 +20,21 @@
class MockValidationDelegate : public TrackedPreferenceValidationDelegate {
public:
struct ValidationEvent {
- ValidationEvent(const std::string& path,
- PrefHashStoreTransaction::ValueState state,
- bool is_personal,
- PrefHashFilter::PrefTrackingStrategy tracking_strategy)
+ ValidationEvent(
+ const std::string& path,
+ PrefHashStoreTransaction::ValueState state,
+ PrefHashStoreTransaction::ValueState external_validation_state,
+ bool is_personal,
+ PrefHashFilter::PrefTrackingStrategy tracking_strategy)
: pref_path(path),
value_state(state),
+ external_validation_value_state(external_validation_state),
is_personal(is_personal),
strategy(tracking_strategy) {}
std::string pref_path;
PrefHashStoreTransaction::ValueState value_state;
+ PrefHashStoreTransaction::ValueState external_validation_value_state;
bool is_personal;
PrefHashFilter::PrefTrackingStrategy strategy;
};
@@ -45,6 +49,10 @@ class MockValidationDelegate : public TrackedPreferenceValidationDelegate {
size_t CountValidationsOfState(
PrefHashStoreTransaction::ValueState value_state) const;
+ // Returns the number of external validations of a given value state.
+ size_t CountExternalValidationsOfState(
+ PrefHashStoreTransaction::ValueState value_state) const;
+
// Returns the event for the preference with a given path.
const ValidationEvent* GetEventForPath(const std::string& pref_path) const;
@@ -53,20 +61,25 @@ class MockValidationDelegate : public TrackedPreferenceValidationDelegate {
const std::string& pref_path,
const base::Value* value,
PrefHashStoreTransaction::ValueState value_state,
+ PrefHashStoreTransaction::ValueState external_validation_value_state,
bool is_personal) override;
void OnSplitPreferenceValidation(
const std::string& pref_path,
const base::DictionaryValue* dict_value,
const std::vector<std::string>& invalid_keys,
+ const std::vector<std::string>& external_validation_invalid_keys,
PrefHashStoreTransaction::ValueState value_state,
+ PrefHashStoreTransaction::ValueState external_validation_value_state,
bool is_personal) override;
private:
// Adds a new validation event.
- void RecordValidation(const std::string& pref_path,
- PrefHashStoreTransaction::ValueState value_state,
- bool is_personal,
- PrefHashFilter::PrefTrackingStrategy strategy);
+ void RecordValidation(
+ const std::string& pref_path,
+ PrefHashStoreTransaction::ValueState value_state,
+ PrefHashStoreTransaction::ValueState external_validation_value_state,
+ bool is_personal,
+ PrefHashFilter::PrefTrackingStrategy strategy);
std::vector<ValidationEvent> validations_;
diff --git a/chromium/components/user_prefs/tracked/pref_hash_calculator_unittest.cc b/chromium/components/user_prefs/tracked/pref_hash_calculator_unittest.cc
index a2de0466ef2..1b3ecd793f5 100644
--- a/chromium/components/user_prefs/tracked/pref_hash_calculator_unittest.cc
+++ b/chromium/components/user_prefs/tracked/pref_hash_calculator_unittest.cc
@@ -8,6 +8,7 @@
#include <string>
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -91,9 +92,9 @@ TEST(PrefHashCalculatorTest, CatchHashChanges) {
nested_empty_dict->Set("a", new base::DictionaryValue);
nested_empty_dict->Set("b", new base::ListValue);
std::unique_ptr<base::ListValue> nested_empty_list(new base::ListValue);
- nested_empty_list->Append(new base::DictionaryValue);
- nested_empty_list->Append(new base::ListValue);
- nested_empty_list->Append(nested_empty_dict->DeepCopy());
+ nested_empty_list->Append(base::MakeUnique<base::DictionaryValue>());
+ nested_empty_list->Append(base::MakeUnique<base::ListValue>());
+ nested_empty_list->Append(nested_empty_dict->CreateDeepCopy());
// A dictionary with an empty dictionary, an empty list, and nested empty
// dictionaries/lists in it.
diff --git a/chromium/components/user_prefs/tracked/pref_hash_filter.cc b/chromium/components/user_prefs/tracked/pref_hash_filter.cc
index 2f0c6e71f5f..1101080cd76 100644
--- a/chromium/components/user_prefs/tracked/pref_hash_filter.cc
+++ b/chromium/components/user_prefs/tracked/pref_hash_filter.cc
@@ -8,9 +8,11 @@
#include <algorithm>
#include <utility>
+#include "base/bind.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/metrics/histogram.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"
@@ -51,16 +53,27 @@ void CleanupDeprecatedTrackedPreferences(
PrefHashFilter::PrefHashFilter(
std::unique_ptr<PrefHashStore> pref_hash_store,
+ StoreContentsPair external_validation_hash_store_pair,
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_pair_(
+ external_validation_hash_store_pair.first
+ ? base::make_optional(
+ std::move(external_validation_hash_store_pair))
+ : base::nullopt),
on_reset_on_load_(on_reset_on_load),
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 TrackedPreferenceMetadata& metadata = tracked_preferences[i];
@@ -132,14 +145,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 +169,42 @@ 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(
+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(std::unique_ptr<HashStoreContents>(
- new DictionaryHashStoreContents(pref_store_contents))));
+ 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 = NULL;
+ const base::Value* value = nullptr;
pref_store_contents->Get(changed_path, &value);
changed_preference->OnNewValue(value, hash_store_transaction.get());
}
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_pair;
}
void PrefHashFilter::FinalizeFilterOnLoad(
@@ -191,9 +216,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;
+ 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());
@@ -205,8 +238,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 +259,114 @@ 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::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::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());
+ }
+ }
+}
+
+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)));
+}
diff --git a/chromium/components/user_prefs/tracked/pref_hash_filter.h b/chromium/components/user_prefs/tracked/pref_hash_filter.h
index 8652a7f817c..07c92db9506 100644
--- a/chromium/components/user_prefs/tracked/pref_hash_filter.h
+++ b/chromium/components/user_prefs/tracked/pref_hash_filter.h
@@ -15,7 +15,10 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/containers/scoped_ptr_hash_map.h"
+#include "base/files/file_path.h"
#include "base/macros.h"
+#include "base/optional.h"
+#include "components/user_prefs/tracked/hash_store_contents.h"
#include "components/user_prefs/tracked/interceptable_pref_filter.h"
#include "components/user_prefs/tracked/tracked_preference.h"
@@ -64,6 +67,9 @@ class PrefHashFilter : public InterceptablePrefFilter {
ValueType value_type;
};
+ using StoreContentsPair = std::pair<std::unique_ptr<PrefHashStore>,
+ std::unique_ptr<HashStoreContents>>;
+
// 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.
@@ -73,8 +79,11 @@ class PrefHashFilter : public InterceptablePrefFilter {
// than |tracked_preferences.size()|). If |report_super_mac_validity| is true,
// the state of the super MAC will be reported via UMA during
// FinalizeFilterOnLoad.
+ // |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<TrackedPreferenceMetadata>& tracked_preferences,
const base::Closure& on_reset_on_load,
TrackedPreferenceValidationDelegate* delegate,
@@ -101,7 +110,8 @@ class PrefHashFilter : public InterceptablePrefFilter {
// PrefFilter remaining implementation.
void FilterUpdate(const std::string& path) override;
- void FilterSerializeData(base::DictionaryValue* pref_store_contents) override;
+ OnWriteCallbackPair FilterSerializeData(
+ base::DictionaryValue* pref_store_contents) override;
private:
// InterceptablePrefFilter implementation.
@@ -110,6 +120,25 @@ class PrefHashFilter : public InterceptablePrefFilter {
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.
@@ -120,12 +149,18 @@ class PrefHashFilter : public InterceptablePrefFilter {
typedef base::ScopedPtrHashMap<std::string,
std::unique_ptr<TrackedPreference>>
TrackedPreferencesMap;
+
// A map from changed paths to their corresponding TrackedPreferences (which
// aren't owned by this map).
typedef std::map<std::string, const TrackedPreference*> ChangedPathsMap;
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.
+ const base::Optional<StoreContentsPair> external_validation_hash_store_pair_;
+
// Invoked if a reset occurs in a call to FilterOnLoad.
const base::Closure on_reset_on_load_;
diff --git a/chromium/components/user_prefs/tracked/pref_hash_filter_unittest.cc b/chromium/components/user_prefs/tracked/pref_hash_filter_unittest.cc
index 97201b5a1e6..1d3afd4b9fc 100644
--- a/chromium/components/user_prefs/tracked/pref_hash_filter_unittest.cc
+++ b/chromium/components/user_prefs/tracked/pref_hash_filter_unittest.cc
@@ -18,7 +18,7 @@
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_base.h"
#include "base/metrics/histogram_samples.h"
#include "base/metrics/statistics_recorder.h"
@@ -157,7 +157,12 @@ class MockPrefHashStore : public PrefHashStore {
// PrefHashStore implementation.
std::unique_ptr<PrefHashStoreTransaction> BeginTransaction(
- std::unique_ptr<HashStoreContents> storage) override;
+ HashStoreContents* storage) override;
+ std::string ComputeMac(const std::string& path,
+ const base::Value* new_value) override;
+ std::unique_ptr<base::DictionaryValue> ComputeSplitMacs(
+ const std::string& path,
+ const base::DictionaryValue* split_values) override;
private:
// A MockPrefHashStoreTransaction is handed to the caller on
@@ -175,6 +180,7 @@ class MockPrefHashStore : public PrefHashStore {
}
// PrefHashStoreTransaction implementation.
+ base::StringPiece GetStoreUMASuffix() const override;
PrefHashStoreTransaction::ValueState CheckValue(
const std::string& path,
const base::Value* value) const override;
@@ -247,12 +253,29 @@ void MockPrefHashStore::SetInvalidKeysResult(
}
std::unique_ptr<PrefHashStoreTransaction> MockPrefHashStore::BeginTransaction(
- std::unique_ptr<HashStoreContents> storage) {
+ HashStoreContents* storage) {
EXPECT_FALSE(transaction_active_);
return std::unique_ptr<PrefHashStoreTransaction>(
new MockPrefHashStoreTransaction(this));
}
+std::string MockPrefHashStore::ComputeMac(const std::string& path,
+ const base::Value* new_value) {
+ return "atomic mac for: " + path;
+};
+
+std::unique_ptr<base::DictionaryValue> MockPrefHashStore::ComputeSplitMacs(
+ const std::string& path,
+ const base::DictionaryValue* split_values) {
+ std::unique_ptr<base::DictionaryValue> macs_dict(new base::DictionaryValue);
+ for (base::DictionaryValue::Iterator it(*split_values); !it.IsAtEnd();
+ it.Advance()) {
+ macs_dict->SetStringWithoutPathExpansion(
+ it.key(), "split mac for: " + path + "/" + it.key());
+ }
+ return macs_dict;
+};
+
PrefHashStoreTransaction::ValueState MockPrefHashStore::RecordCheckValue(
const std::string& path,
const base::Value* value,
@@ -279,6 +302,11 @@ void MockPrefHashStore::RecordStoreHash(
.second);
}
+base::StringPiece
+MockPrefHashStore::MockPrefHashStoreTransaction::GetStoreUMASuffix() const {
+ return "unused";
+}
+
PrefHashStoreTransaction::ValueState
MockPrefHashStore::MockPrefHashStoreTransaction::CheckValue(
const std::string& path,
@@ -359,6 +387,189 @@ std::vector<PrefHashFilter::TrackedPreferenceMetadata> GetConfiguration(
return configuration;
}
+class MockHashStoreContents : public HashStoreContents {
+ public:
+ MockHashStoreContents(){};
+
+ // Returns the number of hashes stored.
+ size_t stored_hashes_count() const { return dictionary_.size(); }
+
+ // Returns the number of paths cleared.
+ size_t cleared_paths_count() const { return removed_entries_.size(); }
+
+ // Returns the stored MAC for an Atomic preference.
+ std::string GetStoredMac(const std::string& path) const;
+ // Returns the stored MAC for a Split preference.
+ std::string GetStoredSplitMac(const std::string& path,
+ const std::string& split_path) const;
+
+ // HashStoreContents implementation.
+ bool IsCopyable() const override;
+ std::unique_ptr<HashStoreContents> MakeCopy() const override;
+ base::StringPiece GetUMASuffix() const override;
+ void Reset() override;
+ bool GetMac(const std::string& path, std::string* out_value) override;
+ bool GetSplitMacs(const std::string& path,
+ std::map<std::string, std::string>* split_macs) override;
+ void SetMac(const std::string& path, const std::string& value) override;
+ void SetSplitMac(const std::string& path,
+ const std::string& split_path,
+ const std::string& value) override;
+ void ImportEntry(const std::string& path,
+ const base::Value* in_value) override;
+ bool RemoveEntry(const std::string& path) override;
+ const base::DictionaryValue* GetContents() const override;
+ std::string GetSuperMac() const override;
+ void SetSuperMac(const std::string& super_mac) override;
+
+ private:
+ MockHashStoreContents(MockHashStoreContents* origin_mock);
+
+ // Records calls to this mock's SetMac/SetSplitMac methods.
+ void RecordSetMac(const std::string& path, const std::string& mac) {
+ dictionary_.SetStringWithoutPathExpansion(path, mac);
+ }
+ void RecordSetSplitMac(const std::string& path,
+ const std::string& split_path,
+ const std::string& mac) {
+ base::DictionaryValue* mac_dict = nullptr;
+ dictionary_.GetDictionaryWithoutPathExpansion(path, &mac_dict);
+ if (!mac_dict) {
+ mac_dict = new base::DictionaryValue;
+ dictionary_.SetWithoutPathExpansion(path, mac_dict);
+ }
+ mac_dict->SetStringWithoutPathExpansion(split_path, mac);
+ }
+
+ // Records a call to this mock's RemoveEntry method.
+ void RecordRemoveEntry(const std::string& path) {
+ // Don't expect the same pref to be cleared more than once.
+ EXPECT_EQ(removed_entries_.end(), removed_entries_.find(path));
+ removed_entries_.insert(path);
+ }
+
+ base::DictionaryValue dictionary_;
+ std::set<std::string> removed_entries_;
+
+ // The code being tested copies its HashStoreContents for use in a callback
+ // which can be executed during shutdown. To be able to capture the behavior
+ // of the copy, we make it forward calls to the mock it was created from.
+ // Once set, |origin_mock_| must outlive this instance.
+ MockHashStoreContents* origin_mock_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockHashStoreContents);
+};
+
+std::string MockHashStoreContents::GetStoredMac(const std::string& path) const {
+ const base::Value* out_value;
+ if (dictionary_.GetWithoutPathExpansion(path, &out_value)) {
+ const base::StringValue* value_as_string;
+ EXPECT_TRUE(out_value->GetAsString(&value_as_string));
+
+ return value_as_string->GetString();
+ }
+
+ return std::string();
+}
+
+std::string MockHashStoreContents::GetStoredSplitMac(
+ const std::string& path,
+ const std::string& split_path) const {
+ const base::Value* out_value;
+ if (dictionary_.GetWithoutPathExpansion(path, &out_value)) {
+ const base::DictionaryValue* value_as_dict;
+ EXPECT_TRUE(out_value->GetAsDictionary(&value_as_dict));
+
+ if (value_as_dict->GetWithoutPathExpansion(split_path, &out_value)) {
+ const base::StringValue* value_as_string;
+ EXPECT_TRUE(out_value->GetAsString(&value_as_string));
+
+ return value_as_string->GetString();
+ }
+ }
+
+ return std::string();
+}
+
+MockHashStoreContents::MockHashStoreContents(MockHashStoreContents* origin_mock)
+ : origin_mock_(origin_mock) {}
+
+bool MockHashStoreContents::IsCopyable() const {
+ return true;
+}
+
+std::unique_ptr<HashStoreContents> MockHashStoreContents::MakeCopy() const {
+ // Return a new MockHashStoreContents which forwards all requests to this
+ // mock instance.
+ return std::unique_ptr<HashStoreContents>(
+ new MockHashStoreContents(const_cast<MockHashStoreContents*>(this)));
+}
+
+base::StringPiece MockHashStoreContents::GetUMASuffix() const {
+ return "Unused";
+}
+
+void MockHashStoreContents::Reset() {
+ ADD_FAILURE() << "Unexpected call.";
+}
+
+bool MockHashStoreContents::GetMac(const std::string& path,
+ std::string* out_value) {
+ ADD_FAILURE() << "Unexpected call.";
+ return false;
+}
+
+bool MockHashStoreContents::GetSplitMacs(
+ const std::string& path,
+ std::map<std::string, std::string>* split_macs) {
+ ADD_FAILURE() << "Unexpected call.";
+ return false;
+}
+
+void MockHashStoreContents::SetMac(const std::string& path,
+ const std::string& value) {
+ if (origin_mock_)
+ origin_mock_->RecordSetMac(path, value);
+ else
+ RecordSetMac(path, value);
+}
+
+void MockHashStoreContents::SetSplitMac(const std::string& path,
+ const std::string& split_path,
+ const std::string& value) {
+ if (origin_mock_)
+ origin_mock_->RecordSetSplitMac(path, split_path, value);
+ else
+ RecordSetSplitMac(path, split_path, value);
+}
+
+void MockHashStoreContents::ImportEntry(const std::string& path,
+ const base::Value* in_value) {
+ ADD_FAILURE() << "Unexpected call.";
+}
+
+bool MockHashStoreContents::RemoveEntry(const std::string& path) {
+ if (origin_mock_)
+ origin_mock_->RecordRemoveEntry(path);
+ else
+ RecordRemoveEntry(path);
+ return true;
+}
+
+const base::DictionaryValue* MockHashStoreContents::GetContents() const {
+ ADD_FAILURE() << "Unexpected call.";
+ return nullptr;
+}
+
+std::string MockHashStoreContents::GetSuperMac() const {
+ ADD_FAILURE() << "Unexpected call.";
+ return std::string();
+}
+
+void MockHashStoreContents::SetSuperMac(const std::string& super_mac) {
+ ADD_FAILURE() << "Unexpected call.";
+}
+
class PrefHashFilterTest
: public testing::TestWithParam<PrefHashFilter::EnforcementLevel> {
public:
@@ -386,9 +597,22 @@ class PrefHashFilterTest
PrefHashFilter::TrackedPreferenceMetadata>& configuration) {
std::unique_ptr<MockPrefHashStore> temp_mock_pref_hash_store(
new MockPrefHashStore);
+ std::unique_ptr<MockPrefHashStore>
+ temp_mock_external_validation_pref_hash_store(new MockPrefHashStore);
+ std::unique_ptr<MockHashStoreContents>
+ temp_mock_external_validation_hash_store_contents(
+ new MockHashStoreContents);
mock_pref_hash_store_ = temp_mock_pref_hash_store.get();
+ mock_external_validation_pref_hash_store_ =
+ temp_mock_external_validation_pref_hash_store.get();
+ mock_external_validation_hash_store_contents_ =
+ temp_mock_external_validation_hash_store_contents.get();
pref_hash_filter_.reset(new PrefHashFilter(
- std::move(temp_mock_pref_hash_store), configuration,
+ std::move(temp_mock_pref_hash_store),
+ PrefHashFilter::StoreContentsPair(
+ std::move(temp_mock_external_validation_pref_hash_store),
+ std::move(temp_mock_external_validation_hash_store_contents)),
+ configuration,
base::Bind(&PrefHashFilterTest::RecordReset, base::Unretained(this)),
&mock_validation_delegate_, arraysize(kTestTrackedPrefs), true));
}
@@ -414,6 +638,8 @@ class PrefHashFilterTest
}
MockPrefHashStore* mock_pref_hash_store_;
+ MockPrefHashStore* mock_external_validation_pref_hash_store_;
+ MockHashStoreContents* mock_external_validation_hash_store_contents_;
std::unique_ptr<base::DictionaryValue> pref_store_contents_;
MockValidationDelegate mock_validation_delegate_;
std::unique_ptr<PrefHashFilter> pref_hash_filter_;
@@ -1035,6 +1261,132 @@ TEST_P(PrefHashFilterTest, DontResetReportOnly) {
}
}
+TEST_P(PrefHashFilterTest, CallFilterSerializeDataCallbacks) {
+ base::DictionaryValue root_dict;
+ // Ownership of the following values is transfered to |root_dict|.
+ base::Value* int_value1 = new base::FundamentalValue(1);
+ base::Value* int_value2 = new base::FundamentalValue(2);
+ base::DictionaryValue* dict_value = new base::DictionaryValue;
+ dict_value->Set("a", new base::FundamentalValue(true));
+ root_dict.Set(kAtomicPref, int_value1);
+ root_dict.Set(kAtomicPref2, int_value2);
+ root_dict.Set(kSplitPref, dict_value);
+
+ // Skip updating kAtomicPref2.
+ pref_hash_filter_->FilterUpdate(kAtomicPref);
+ pref_hash_filter_->FilterUpdate(kSplitPref);
+
+ PrefHashFilter::OnWriteCallbackPair callbacks =
+ pref_hash_filter_->FilterSerializeData(&root_dict);
+
+ ASSERT_FALSE(callbacks.first.is_null());
+
+ // Prefs should be cleared from the external validation store only once the
+ // before-write callback is run.
+ ASSERT_EQ(
+ 0u, mock_external_validation_hash_store_contents_->cleared_paths_count());
+ callbacks.first.Run();
+ ASSERT_EQ(
+ 2u, mock_external_validation_hash_store_contents_->cleared_paths_count());
+
+ // No pref write should occur before the after-write callback is run.
+ ASSERT_EQ(
+ 0u, mock_external_validation_hash_store_contents_->stored_hashes_count());
+
+ callbacks.second.Run(true);
+
+ ASSERT_EQ(
+ 2u, mock_external_validation_hash_store_contents_->stored_hashes_count());
+ ASSERT_EQ(
+ "atomic mac for: atomic_pref",
+ mock_external_validation_hash_store_contents_->GetStoredMac(kAtomicPref));
+ ASSERT_EQ("split mac for: split_pref/a",
+ mock_external_validation_hash_store_contents_->GetStoredSplitMac(
+ kSplitPref, "a"));
+
+ // The callbacks should write directly to the contents without going through
+ // a pref hash store.
+ ASSERT_EQ(0u,
+ mock_external_validation_pref_hash_store_->stored_paths_count());
+}
+
+TEST_P(PrefHashFilterTest, CallFilterSerializeDataCallbacksWithFailure) {
+ base::DictionaryValue root_dict;
+ // Ownership of the following values is transfered to |root_dict|.
+ base::Value* int_value1 = new base::FundamentalValue(1);
+ root_dict.Set(kAtomicPref, int_value1);
+
+ // Only update kAtomicPref.
+ pref_hash_filter_->FilterUpdate(kAtomicPref);
+
+ PrefHashFilter::OnWriteCallbackPair callbacks =
+ pref_hash_filter_->FilterSerializeData(&root_dict);
+
+ ASSERT_FALSE(callbacks.first.is_null());
+
+ callbacks.first.Run();
+
+ // The pref should have been cleared from the external validation store.
+ ASSERT_EQ(
+ 1u, mock_external_validation_hash_store_contents_->cleared_paths_count());
+
+ callbacks.second.Run(false);
+
+ // Expect no writes to the external validation hash store contents.
+ ASSERT_EQ(0u,
+ mock_external_validation_pref_hash_store_->stored_paths_count());
+ ASSERT_EQ(
+ 0u, mock_external_validation_hash_store_contents_->stored_hashes_count());
+}
+
+TEST_P(PrefHashFilterTest, ExternalValidationValueChanged) {
+ // Ownership of this value is transfered to |pref_store_contents_|.
+ base::Value* int_value = new base::FundamentalValue(1234);
+ pref_store_contents_->Set(kAtomicPref, int_value);
+
+ base::DictionaryValue* dict_value = new base::DictionaryValue;
+ dict_value->SetString("a", "foo");
+ dict_value->SetInteger("b", 1234);
+ dict_value->SetInteger("c", 56);
+ dict_value->SetBoolean("d", false);
+ pref_store_contents_->Set(kSplitPref, dict_value);
+
+ mock_external_validation_pref_hash_store_->SetCheckResult(
+ kAtomicPref, PrefHashStoreTransaction::CHANGED);
+ mock_external_validation_pref_hash_store_->SetCheckResult(
+ kSplitPref, PrefHashStoreTransaction::CHANGED);
+
+ std::vector<std::string> mock_invalid_keys;
+ mock_invalid_keys.push_back("a");
+ mock_invalid_keys.push_back("c");
+ mock_external_validation_pref_hash_store_->SetInvalidKeysResult(
+ kSplitPref, mock_invalid_keys);
+
+ DoFilterOnLoad(false);
+
+ ASSERT_EQ(arraysize(kTestTrackedPrefs),
+ mock_external_validation_pref_hash_store_->checked_paths_count());
+ ASSERT_EQ(2u,
+ mock_external_validation_pref_hash_store_->stored_paths_count());
+ ASSERT_EQ(
+ 1u, mock_external_validation_pref_hash_store_->transactions_performed());
+
+ ASSERT_EQ(arraysize(kTestTrackedPrefs),
+ mock_validation_delegate_.recorded_validations_count());
+
+ // Regular validation should not have any CHANGED prefs.
+ ASSERT_EQ(arraysize(kTestTrackedPrefs),
+ mock_validation_delegate_.CountValidationsOfState(
+ PrefHashStoreTransaction::UNCHANGED));
+
+ // External validation should have two CHANGED prefs (kAtomic and kSplit).
+ ASSERT_EQ(2u, mock_validation_delegate_.CountExternalValidationsOfState(
+ PrefHashStoreTransaction::CHANGED));
+ ASSERT_EQ(arraysize(kTestTrackedPrefs) - 2u,
+ mock_validation_delegate_.CountExternalValidationsOfState(
+ PrefHashStoreTransaction::UNCHANGED));
+}
+
INSTANTIATE_TEST_CASE_P(PrefHashFilterTestInstance,
PrefHashFilterTest,
testing::Values(PrefHashFilter::NO_ENFORCEMENT,
diff --git a/chromium/components/user_prefs/tracked/pref_hash_store.h b/chromium/components/user_prefs/tracked/pref_hash_store.h
index 2fdc617301a..67808fd3939 100644
--- a/chromium/components/user_prefs/tracked/pref_hash_store.h
+++ b/chromium/components/user_prefs/tracked/pref_hash_store.h
@@ -6,6 +6,10 @@
#define COMPONENTS_PREFS_TRACKED_PREF_HASH_STORE_H_
#include <memory>
+#include <string>
+
+#include "base/values.h"
+#include "components/user_prefs/tracked/pref_hash_store_transaction.h"
class HashStoreContents;
class PrefHashStoreTransaction;
@@ -21,8 +25,24 @@ class PrefHashStore {
// of operations on the hash store. |storage| MAY be used as the backing store
// depending on the implementation. Therefore the HashStoreContents used for
// related transactions should correspond to the same underlying data store.
+ // |storage| must outlive the returned transaction.
virtual std::unique_ptr<PrefHashStoreTransaction> BeginTransaction(
- std::unique_ptr<HashStoreContents> storage) = 0;
+ HashStoreContents* storage) = 0;
+
+ // Computes the MAC to be associated with |path| and |value| in this store.
+ // PrefHashStoreTransaction typically uses this internally but it's also
+ // exposed for users that want to compute MACs ahead of time for asynchronous
+ // operations.
+ virtual std::string ComputeMac(const std::string& path,
+ const base::Value* value) = 0;
+
+ // Computes the MAC to be associated with |path| and |split_values| in this
+ // store. PrefHashStoreTransaction typically uses this internally but it's
+ // also exposed for users that want to compute MACs ahead of time for
+ // asynchronous operations.
+ virtual std::unique_ptr<base::DictionaryValue> ComputeSplitMacs(
+ const std::string& path,
+ const base::DictionaryValue* split_values) = 0;
};
#endif // COMPONENTS_PREFS_TRACKED_PREF_HASH_STORE_H_
diff --git a/chromium/components/user_prefs/tracked/pref_hash_store_impl.cc b/chromium/components/user_prefs/tracked/pref_hash_store_impl.cc
index c756d6f28f7..80438d6954a 100644
--- a/chromium/components/user_prefs/tracked/pref_hash_store_impl.cc
+++ b/chromium/components/user_prefs/tracked/pref_hash_store_impl.cc
@@ -10,9 +10,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/histogram.h"
-#include "base/values.h"
#include "components/user_prefs/tracked/hash_store_contents.h"
-#include "components/user_prefs/tracked/pref_hash_store_transaction.h"
class PrefHashStoreImpl::PrefHashStoreTransactionImpl
: public PrefHashStoreTransaction {
@@ -20,10 +18,11 @@ class PrefHashStoreImpl::PrefHashStoreTransactionImpl
// Constructs a PrefHashStoreTransactionImpl which can use the private
// members of its |outer| PrefHashStoreImpl.
PrefHashStoreTransactionImpl(PrefHashStoreImpl* outer,
- std::unique_ptr<HashStoreContents> storage);
+ HashStoreContents* storage);
~PrefHashStoreTransactionImpl() override;
// PrefHashStoreTransaction implementation.
+ base::StringPiece GetStoreUMASuffix() const override;
ValueState CheckValue(const std::string& path,
const base::Value* value) const override;
void StoreHash(const std::string& path, const base::Value* value) override;
@@ -40,23 +39,8 @@ class PrefHashStoreImpl::PrefHashStoreTransactionImpl
bool StampSuperMac() override;
private:
- bool GetSplitMacs(const std::string& path,
- std::map<std::string, std::string>* split_macs) const;
-
- HashStoreContents* contents() {
- return outer_->legacy_hash_store_contents_
- ? outer_->legacy_hash_store_contents_.get()
- : contents_.get();
- }
-
- const HashStoreContents* contents() const {
- return outer_->legacy_hash_store_contents_
- ? outer_->legacy_hash_store_contents_.get()
- : contents_.get();
- }
-
PrefHashStoreImpl* outer_;
- std::unique_ptr<HashStoreContents> contents_;
+ HashStoreContents* contents_;
bool super_mac_valid_;
bool super_mac_dirty_;
@@ -73,20 +57,44 @@ PrefHashStoreImpl::PrefHashStoreImpl(const std::string& seed,
PrefHashStoreImpl::~PrefHashStoreImpl() {
}
-void PrefHashStoreImpl::set_legacy_hash_store_contents(
- std::unique_ptr<HashStoreContents> legacy_hash_store_contents) {
- legacy_hash_store_contents_ = std::move(legacy_hash_store_contents);
-}
-
std::unique_ptr<PrefHashStoreTransaction> PrefHashStoreImpl::BeginTransaction(
- std::unique_ptr<HashStoreContents> storage) {
+ HashStoreContents* storage) {
return std::unique_ptr<PrefHashStoreTransaction>(
new PrefHashStoreTransactionImpl(this, std::move(storage)));
}
+std::string PrefHashStoreImpl::ComputeMac(const std::string& path,
+ const base::Value* value) {
+ return pref_hash_calculator_.Calculate(path, value);
+}
+
+std::unique_ptr<base::DictionaryValue> PrefHashStoreImpl::ComputeSplitMacs(
+ const std::string& path,
+ const base::DictionaryValue* split_values) {
+ DCHECK(split_values);
+
+ std::string keyed_path(path);
+ keyed_path.push_back('.');
+ const size_t common_part_length = keyed_path.length();
+
+ std::unique_ptr<base::DictionaryValue> split_macs(new base::DictionaryValue);
+
+ for (base::DictionaryValue::Iterator it(*split_values); !it.IsAtEnd();
+ it.Advance()) {
+ // Keep the common part from the old |keyed_path| and replace the key to
+ // get the new |keyed_path|.
+ keyed_path.replace(common_part_length, std::string::npos, it.key());
+
+ split_macs->SetStringWithoutPathExpansion(
+ it.key(), ComputeMac(keyed_path, &it.value()));
+ }
+
+ return split_macs;
+}
+
PrefHashStoreImpl::PrefHashStoreTransactionImpl::PrefHashStoreTransactionImpl(
PrefHashStoreImpl* outer,
- std::unique_ptr<HashStoreContents> storage)
+ HashStoreContents* storage)
: outer_(outer),
contents_(std::move(storage)),
super_mac_valid_(false),
@@ -94,40 +102,36 @@ PrefHashStoreImpl::PrefHashStoreTransactionImpl::PrefHashStoreTransactionImpl(
if (!outer_->use_super_mac_)
return;
- // The store must be initialized and have a valid super MAC to be trusted.
-
- const base::DictionaryValue* store_contents = contents()->GetContents();
- if (!store_contents)
- return;
-
- std::string super_mac = contents()->GetSuperMac();
+ // The store must have a valid super MAC to be trusted.
+ std::string super_mac = contents_->GetSuperMac();
if (super_mac.empty())
return;
- super_mac_valid_ = outer_->pref_hash_calculator_.Validate(
- contents()->hash_store_id(), store_contents,
- super_mac) == PrefHashCalculator::VALID;
+ super_mac_valid_ =
+ outer_->pref_hash_calculator_.Validate(
+ "", contents_->GetContents(), super_mac) == PrefHashCalculator::VALID;
}
PrefHashStoreImpl::PrefHashStoreTransactionImpl::
~PrefHashStoreTransactionImpl() {
if (super_mac_dirty_ && outer_->use_super_mac_) {
// Get the dictionary of hashes (or NULL if it doesn't exist).
- const base::DictionaryValue* hashes_dict = contents()->GetContents();
- contents()->SetSuperMac(outer_->pref_hash_calculator_.Calculate(
- contents()->hash_store_id(), hashes_dict));
+ const base::DictionaryValue* hashes_dict = contents_->GetContents();
+ contents_->SetSuperMac(outer_->ComputeMac("", hashes_dict));
}
}
+base::StringPiece
+PrefHashStoreImpl::PrefHashStoreTransactionImpl::GetStoreUMASuffix() const {
+ return contents_->GetUMASuffix();
+}
+
PrefHashStoreTransaction::ValueState
PrefHashStoreImpl::PrefHashStoreTransactionImpl::CheckValue(
const std::string& path,
const base::Value* initial_value) const {
- const base::DictionaryValue* hashes_dict = contents()->GetContents();
-
std::string last_hash;
- if (hashes_dict)
- hashes_dict->GetString(path, &last_hash);
+ contents_->GetMac(path, &last_hash);
if (last_hash.empty()) {
// In the absence of a hash for this pref, always trust a NULL value, but
@@ -158,9 +162,8 @@ PrefHashStoreImpl::PrefHashStoreTransactionImpl::CheckValue(
void PrefHashStoreImpl::PrefHashStoreTransactionImpl::StoreHash(
const std::string& path,
const base::Value* new_value) {
- const std::string mac =
- outer_->pref_hash_calculator_.Calculate(path, new_value);
- (*contents()->GetMutableContents())->SetString(path, mac);
+ const std::string mac = outer_->ComputeMac(path, new_value);
+ contents_->SetMac(path, mac);
super_mac_dirty_ = true;
}
@@ -172,7 +175,7 @@ PrefHashStoreImpl::PrefHashStoreTransactionImpl::CheckSplitValue(
DCHECK(invalid_keys && invalid_keys->empty());
std::map<std::string, std::string> split_macs;
- const bool has_hashes = GetSplitMacs(path, &split_macs);
+ const bool has_hashes = contents_->GetSplitMacs(path, &split_macs);
// Treat NULL and empty the same; otherwise we would need to store a hash for
// the entire dictionary (or some other special beacon) to differentiate these
@@ -232,53 +235,30 @@ PrefHashStoreImpl::PrefHashStoreTransactionImpl::CheckSplitValue(
void PrefHashStoreImpl::PrefHashStoreTransactionImpl::StoreSplitHash(
const std::string& path,
const base::DictionaryValue* split_value) {
- std::unique_ptr<HashStoreContents::MutableDictionary> mutable_dictionary =
- contents()->GetMutableContents();
- (*mutable_dictionary)->Remove(path, NULL);
+ contents_->RemoveEntry(path);
if (split_value) {
- std::string keyed_path(path);
- keyed_path.push_back('.');
- const size_t common_part_length = keyed_path.length();
- for (base::DictionaryValue::Iterator it(*split_value); !it.IsAtEnd();
- it.Advance()) {
- // Keep the common part from the old |keyed_path| and replace the key to
- // get the new |keyed_path|.
- keyed_path.replace(common_part_length, std::string::npos, it.key());
- (*mutable_dictionary)
- ->SetString(keyed_path, outer_->pref_hash_calculator_.Calculate(
- keyed_path, &it.value()));
- }
- }
- super_mac_dirty_ = true;
-}
+ std::unique_ptr<base::DictionaryValue> split_macs =
+ outer_->ComputeSplitMacs(path, split_value);
-bool PrefHashStoreImpl::PrefHashStoreTransactionImpl::GetSplitMacs(
- const std::string& key,
- std::map<std::string, std::string>* split_macs) const {
- DCHECK(split_macs);
- DCHECK(split_macs->empty());
+ for (base::DictionaryValue::Iterator it(*split_macs); !it.IsAtEnd();
+ it.Advance()) {
+ const base::StringValue* value_as_string;
+ bool is_string = it.value().GetAsString(&value_as_string);
+ DCHECK(is_string);
- const base::DictionaryValue* hashes_dict = contents()->GetContents();
- const base::DictionaryValue* split_mac_dictionary = NULL;
- if (!hashes_dict || !hashes_dict->GetDictionary(key, &split_mac_dictionary))
- return false;
- for (base::DictionaryValue::Iterator it(*split_mac_dictionary); !it.IsAtEnd();
- it.Advance()) {
- std::string mac_string;
- if (!it.value().GetAsString(&mac_string)) {
- NOTREACHED();
- continue;
+ contents_->SetSplitMac(path, it.key(), value_as_string->GetString());
}
- split_macs->insert(make_pair(it.key(), mac_string));
}
- return true;
+ super_mac_dirty_ = true;
}
bool PrefHashStoreImpl::PrefHashStoreTransactionImpl::HasHash(
const std::string& path) const {
- const base::DictionaryValue* hashes_dict = contents()->GetContents();
- return hashes_dict && hashes_dict->Get(path, NULL);
+ std::string out_value;
+ std::map<std::string, std::string> out_values;
+ return contents_->GetMac(path, &out_value) ||
+ contents_->GetSplitMacs(path, &out_values);
}
void PrefHashStoreImpl::PrefHashStoreTransactionImpl::ImportHash(
@@ -286,7 +266,7 @@ void PrefHashStoreImpl::PrefHashStoreTransactionImpl::ImportHash(
const base::Value* hash) {
DCHECK(hash);
- (*contents()->GetMutableContents())->Set(path, hash->DeepCopy());
+ contents_->ImportEntry(path, hash);
if (super_mac_valid_)
super_mac_dirty_ = true;
@@ -294,8 +274,7 @@ void PrefHashStoreImpl::PrefHashStoreTransactionImpl::ImportHash(
void PrefHashStoreImpl::PrefHashStoreTransactionImpl::ClearHash(
const std::string& path) {
- if ((*contents()->GetMutableContents())->RemovePath(path, NULL) &&
- super_mac_valid_) {
+ if (contents_->RemoveEntry(path) && super_mac_valid_) {
super_mac_dirty_ = true;
}
}
diff --git a/chromium/components/user_prefs/tracked/pref_hash_store_impl.h b/chromium/components/user_prefs/tracked/pref_hash_store_impl.h
index 254d8f3f89f..1b5682eed4e 100644
--- a/chromium/components/user_prefs/tracked/pref_hash_store_impl.h
+++ b/chromium/components/user_prefs/tracked/pref_hash_store_impl.h
@@ -5,17 +5,11 @@
#ifndef COMPONENTS_USER_PREFS_TRACKED_PREF_HASH_STORE_IMPL_H_
#define COMPONENTS_USER_PREFS_TRACKED_PREF_HASH_STORE_IMPL_H_
-#include <memory>
-#include <string>
-
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "components/user_prefs/tracked/pref_hash_calculator.h"
#include "components/user_prefs/tracked/pref_hash_store.h"
-class HashStoreContents;
-class PrefHashStoreTransaction;
-
// Implements PrefHashStoreImpl by storing preference hashes in a
// HashStoreContents.
class PrefHashStoreImpl : public PrefHashStore {
@@ -41,24 +35,24 @@ class PrefHashStoreImpl : public PrefHashStore {
~PrefHashStoreImpl() override;
- // Provides an external HashStoreContents implementation to be used.
- // BeginTransaction() will ignore |storage| if this is provided.
- void set_legacy_hash_store_contents(
- std::unique_ptr<HashStoreContents> legacy_hash_store_contents);
-
// Clears the contents of this PrefHashStore. |IsInitialized()| will return
// false after this call.
void Reset();
// PrefHashStore implementation.
std::unique_ptr<PrefHashStoreTransaction> BeginTransaction(
- std::unique_ptr<HashStoreContents> storage) override;
+ HashStoreContents* storage) override;
+
+ std::string ComputeMac(const std::string& path,
+ const base::Value* new_value) override;
+ std::unique_ptr<base::DictionaryValue> ComputeSplitMacs(
+ const std::string& path,
+ const base::DictionaryValue* split_values) override;
private:
class PrefHashStoreTransactionImpl;
const PrefHashCalculator pref_hash_calculator_;
- std::unique_ptr<HashStoreContents> legacy_hash_store_contents_;
bool use_super_mac_;
DISALLOW_COPY_AND_ASSIGN(PrefHashStoreImpl);
diff --git a/chromium/components/user_prefs/tracked/pref_hash_store_impl_unittest.cc b/chromium/components/user_prefs/tracked/pref_hash_store_impl_unittest.cc
index 10867e66d45..f5d92182a53 100644
--- a/chromium/components/user_prefs/tracked/pref_hash_store_impl_unittest.cc
+++ b/chromium/components/user_prefs/tracked/pref_hash_store_impl_unittest.cc
@@ -15,16 +15,60 @@
#include "testing/gtest/include/gtest/gtest.h"
class PrefHashStoreImplTest : public testing::Test {
+ public:
+ PrefHashStoreImplTest() : contents_(&pref_store_contents_) {}
+
protected:
- std::unique_ptr<HashStoreContents> CreateHashStoreContents() {
- return std::unique_ptr<HashStoreContents>(
- new DictionaryHashStoreContents(&pref_store_contents_));
- }
+ HashStoreContents* GetHashStoreContents() { return &contents_; }
private:
base::DictionaryValue pref_store_contents_;
+ // Must be declared after |pref_store_contents_| as it needs to be outlived
+ // by it.
+ DictionaryHashStoreContents contents_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrefHashStoreImplTest);
};
+TEST_F(PrefHashStoreImplTest, ComputeMac) {
+ base::StringValue string_1("string1");
+ base::StringValue string_2("string2");
+ PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true);
+
+ std::string computed_mac_1 = pref_hash_store.ComputeMac("path1", &string_1);
+ std::string computed_mac_2 = pref_hash_store.ComputeMac("path1", &string_2);
+ std::string computed_mac_3 = pref_hash_store.ComputeMac("path2", &string_1);
+
+ // Quick sanity checks here, see pref_hash_calculator_unittest.cc for more
+ // complete tests.
+ EXPECT_EQ(computed_mac_1, pref_hash_store.ComputeMac("path1", &string_1));
+ EXPECT_NE(computed_mac_1, computed_mac_2);
+ EXPECT_NE(computed_mac_1, computed_mac_3);
+ EXPECT_EQ(64U, computed_mac_1.size());
+}
+
+TEST_F(PrefHashStoreImplTest, ComputeSplitMacs) {
+ base::DictionaryValue dict;
+ dict.Set("a", new base::StringValue("string1"));
+ dict.Set("b", new base::StringValue("string2"));
+ PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true);
+
+ std::unique_ptr<base::DictionaryValue> computed_macs =
+ pref_hash_store.ComputeSplitMacs("foo.bar", &dict);
+
+ std::string mac_1;
+ std::string mac_2;
+ ASSERT_TRUE(computed_macs->GetString("a", &mac_1));
+ ASSERT_TRUE(computed_macs->GetString("b", &mac_2));
+
+ EXPECT_EQ(2U, computed_macs->size());
+
+ base::StringValue string_1("string1");
+ base::StringValue string_2("string2");
+ EXPECT_EQ(pref_hash_store.ComputeMac("foo.bar.a", &string_1), mac_1);
+ EXPECT_EQ(pref_hash_store.ComputeMac("foo.bar.b", &string_2), mac_2);
+}
+
TEST_F(PrefHashStoreImplTest, AtomicHashStoreAndCheck) {
base::StringValue string_1("string1");
base::StringValue string_2("string2");
@@ -33,7 +77,7 @@ TEST_F(PrefHashStoreImplTest, AtomicHashStoreAndCheck) {
// 32 NULL bytes is the seed that was used to generate the legacy hash.
PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true);
std::unique_ptr<PrefHashStoreTransaction> transaction(
- pref_hash_store.BeginTransaction(CreateHashStoreContents()));
+ pref_hash_store.BeginTransaction(GetHashStoreContents()));
// Only NULL should be trusted in the absence of a hash.
EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE,
@@ -63,14 +107,14 @@ TEST_F(PrefHashStoreImplTest, AtomicHashStoreAndCheck) {
transaction->CheckValue("path1", &dict));
}
- ASSERT_FALSE(CreateHashStoreContents()->GetSuperMac().empty());
+ ASSERT_FALSE(GetHashStoreContents()->GetSuperMac().empty());
{
// |pref_hash_store2| should trust its initial hashes dictionary and thus
// trust new unknown values.
PrefHashStoreImpl pref_hash_store2(std::string(32, 0), "device_id", true);
std::unique_ptr<PrefHashStoreTransaction> transaction(
- pref_hash_store2.BeginTransaction(CreateHashStoreContents()));
+ pref_hash_store2.BeginTransaction(GetHashStoreContents()));
EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE,
transaction->CheckValue("new_path", &string_1));
EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE,
@@ -80,14 +124,14 @@ TEST_F(PrefHashStoreImplTest, AtomicHashStoreAndCheck) {
}
// Manually corrupt the super MAC.
- CreateHashStoreContents()->SetSuperMac(std::string(64, 'A'));
+ GetHashStoreContents()->SetSuperMac(std::string(64, 'A'));
{
// |pref_hash_store3| should no longer trust its initial hashes dictionary
// and thus shouldn't trust non-NULL unknown values.
PrefHashStoreImpl pref_hash_store3(std::string(32, 0), "device_id", true);
std::unique_ptr<PrefHashStoreTransaction> transaction(
- pref_hash_store3.BeginTransaction(CreateHashStoreContents()));
+ pref_hash_store3.BeginTransaction(GetHashStoreContents()));
EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE,
transaction->CheckValue("new_path", &string_1));
EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE,
@@ -105,7 +149,7 @@ TEST_F(PrefHashStoreImplTest, ImportExportOperations) {
{
PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true);
std::unique_ptr<PrefHashStoreTransaction> transaction(
- pref_hash_store.BeginTransaction(CreateHashStoreContents()));
+ pref_hash_store.BeginTransaction(GetHashStoreContents()));
ASSERT_FALSE(transaction->IsSuperMACValid());
ASSERT_FALSE(transaction->HasHash("path1"));
@@ -122,7 +166,7 @@ TEST_F(PrefHashStoreImplTest, ImportExportOperations) {
// Make a copy of the stored hash for future use.
const base::Value* hash = NULL;
- ASSERT_TRUE(CreateHashStoreContents()->GetContents()->Get("path1", &hash));
+ ASSERT_TRUE(GetHashStoreContents()->GetContents()->Get("path1", &hash));
std::unique_ptr<base::Value> path_1_string_1_hash_copy(hash->DeepCopy());
hash = NULL;
@@ -130,7 +174,7 @@ TEST_F(PrefHashStoreImplTest, ImportExportOperations) {
{
PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true);
std::unique_ptr<PrefHashStoreTransaction> transaction(
- pref_hash_store.BeginTransaction(CreateHashStoreContents()));
+ pref_hash_store.BeginTransaction(GetHashStoreContents()));
ASSERT_TRUE(transaction->IsSuperMACValid());
ASSERT_TRUE(transaction->HasHash("path1"));
@@ -149,18 +193,18 @@ TEST_F(PrefHashStoreImplTest, ImportExportOperations) {
{
PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true);
std::unique_ptr<PrefHashStoreTransaction> transaction(
- pref_hash_store.BeginTransaction(CreateHashStoreContents()));
+ pref_hash_store.BeginTransaction(GetHashStoreContents()));
ASSERT_TRUE(transaction->IsSuperMACValid());
ASSERT_FALSE(transaction->HasHash("path1"));
}
// Invalidate the super MAC.
- CreateHashStoreContents()->SetSuperMac(std::string());
+ GetHashStoreContents()->SetSuperMac(std::string());
{
PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true);
std::unique_ptr<PrefHashStoreTransaction> transaction(
- pref_hash_store.BeginTransaction(CreateHashStoreContents()));
+ pref_hash_store.BeginTransaction(GetHashStoreContents()));
ASSERT_FALSE(transaction->IsSuperMACValid());
ASSERT_FALSE(transaction->HasHash("path1"));
@@ -178,7 +222,7 @@ TEST_F(PrefHashStoreImplTest, ImportExportOperations) {
{
PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true);
std::unique_ptr<PrefHashStoreTransaction> transaction(
- pref_hash_store.BeginTransaction(CreateHashStoreContents()));
+ pref_hash_store.BeginTransaction(GetHashStoreContents()));
ASSERT_FALSE(transaction->IsSuperMACValid());
ASSERT_TRUE(transaction->HasHash("path1"));
EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED,
@@ -196,7 +240,7 @@ TEST_F(PrefHashStoreImplTest, ImportExportOperations) {
{
PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true);
std::unique_ptr<PrefHashStoreTransaction> transaction(
- pref_hash_store.BeginTransaction(CreateHashStoreContents()));
+ pref_hash_store.BeginTransaction(GetHashStoreContents()));
ASSERT_FALSE(transaction->IsSuperMACValid());
// Test StampSuperMac.
@@ -207,7 +251,7 @@ TEST_F(PrefHashStoreImplTest, ImportExportOperations) {
{
PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true);
std::unique_ptr<PrefHashStoreTransaction> transaction(
- pref_hash_store.BeginTransaction(CreateHashStoreContents()));
+ pref_hash_store.BeginTransaction(GetHashStoreContents()));
ASSERT_TRUE(transaction->IsSuperMACValid());
// Store the hash of a different value to test an "over-import".
@@ -221,7 +265,7 @@ TEST_F(PrefHashStoreImplTest, ImportExportOperations) {
{
PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true);
std::unique_ptr<PrefHashStoreTransaction> transaction(
- pref_hash_store.BeginTransaction(CreateHashStoreContents()));
+ pref_hash_store.BeginTransaction(GetHashStoreContents()));
ASSERT_TRUE(transaction->IsSuperMACValid());
// "Over-import". An import should preserve validity.
@@ -236,7 +280,7 @@ TEST_F(PrefHashStoreImplTest, ImportExportOperations) {
{
PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true);
std::unique_ptr<PrefHashStoreTransaction> transaction(
- pref_hash_store.BeginTransaction(CreateHashStoreContents()));
+ pref_hash_store.BeginTransaction(GetHashStoreContents()));
ASSERT_TRUE(transaction->IsSuperMACValid());
EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED,
transaction->CheckValue("path1", &string_1));
@@ -253,19 +297,19 @@ TEST_F(PrefHashStoreImplTest, SuperMACDisabled) {
// Pass |use_super_mac| => false.
PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", false);
std::unique_ptr<PrefHashStoreTransaction> transaction(
- pref_hash_store.BeginTransaction(CreateHashStoreContents()));
+ pref_hash_store.BeginTransaction(GetHashStoreContents()));
transaction->StoreHash("path1", &string_2);
EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED,
transaction->CheckValue("path1", &string_2));
}
- ASSERT_TRUE(CreateHashStoreContents()->GetSuperMac().empty());
+ ASSERT_TRUE(GetHashStoreContents()->GetSuperMac().empty());
{
PrefHashStoreImpl pref_hash_store2(std::string(32, 0), "device_id", false);
std::unique_ptr<PrefHashStoreTransaction> transaction(
- pref_hash_store2.BeginTransaction(CreateHashStoreContents()));
+ pref_hash_store2.BeginTransaction(GetHashStoreContents()));
EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE,
transaction->CheckValue("new_path", &string_1));
}
@@ -289,7 +333,7 @@ TEST_F(PrefHashStoreImplTest, SplitHashStoreAndCheck) {
{
PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true);
std::unique_ptr<PrefHashStoreTransaction> transaction(
- pref_hash_store.BeginTransaction(CreateHashStoreContents()));
+ pref_hash_store.BeginTransaction(GetHashStoreContents()));
// No hashes stored yet and hashes dictionary is empty (and thus not
// trusted).
@@ -359,21 +403,21 @@ TEST_F(PrefHashStoreImplTest, SplitHashStoreAndCheck) {
// trust new unknown values.
PrefHashStoreImpl pref_hash_store2(std::string(32, 0), "device_id", true);
std::unique_ptr<PrefHashStoreTransaction> transaction(
- pref_hash_store2.BeginTransaction(CreateHashStoreContents()));
+ pref_hash_store2.BeginTransaction(GetHashStoreContents()));
EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE,
transaction->CheckSplitValue("new_path", &dict, &invalid_keys));
EXPECT_TRUE(invalid_keys.empty());
}
// Manually corrupt the super MAC.
- CreateHashStoreContents()->SetSuperMac(std::string(64, 'A'));
+ GetHashStoreContents()->SetSuperMac(std::string(64, 'A'));
{
// |pref_hash_store3| should no longer trust its initial hashes dictionary
// and thus shouldn't trust unknown values.
PrefHashStoreImpl pref_hash_store3(std::string(32, 0), "device_id", true);
std::unique_ptr<PrefHashStoreTransaction> transaction(
- pref_hash_store3.BeginTransaction(CreateHashStoreContents()));
+ pref_hash_store3.BeginTransaction(GetHashStoreContents()));
EXPECT_EQ(PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE,
transaction->CheckSplitValue("new_path", &dict, &invalid_keys));
EXPECT_TRUE(invalid_keys.empty());
@@ -388,7 +432,7 @@ TEST_F(PrefHashStoreImplTest, EmptyAndNULLSplitDict) {
{
PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true);
std::unique_ptr<PrefHashStoreTransaction> transaction(
- pref_hash_store.BeginTransaction(CreateHashStoreContents()));
+ pref_hash_store.BeginTransaction(GetHashStoreContents()));
// Store hashes for a random dict to be overwritten below.
base::DictionaryValue initial_dict;
@@ -424,7 +468,7 @@ TEST_F(PrefHashStoreImplTest, EmptyAndNULLSplitDict) {
// update the stored hash of hashes).
PrefHashStoreImpl pref_hash_store2(std::string(32, 0), "device_id", true);
std::unique_ptr<PrefHashStoreTransaction> transaction(
- pref_hash_store2.BeginTransaction(CreateHashStoreContents()));
+ pref_hash_store2.BeginTransaction(GetHashStoreContents()));
base::DictionaryValue tested_dict;
tested_dict.Set("a", new base::StringValue("foo"));
@@ -454,7 +498,7 @@ TEST_F(PrefHashStoreImplTest, TrustedUnknownSplitValueFromExistingAtomic) {
{
PrefHashStoreImpl pref_hash_store(std::string(32, 0), "device_id", true);
std::unique_ptr<PrefHashStoreTransaction> transaction(
- pref_hash_store.BeginTransaction(CreateHashStoreContents()));
+ pref_hash_store.BeginTransaction(GetHashStoreContents()));
transaction->StoreHash("path1", &string);
EXPECT_EQ(PrefHashStoreTransaction::UNCHANGED,
@@ -465,7 +509,7 @@ TEST_F(PrefHashStoreImplTest, TrustedUnknownSplitValueFromExistingAtomic) {
// Load a new |pref_hash_store2| in which the hashes dictionary is trusted.
PrefHashStoreImpl pref_hash_store2(std::string(32, 0), "device_id", true);
std::unique_ptr<PrefHashStoreTransaction> transaction(
- pref_hash_store2.BeginTransaction(CreateHashStoreContents()));
+ pref_hash_store2.BeginTransaction(GetHashStoreContents()));
std::vector<std::string> invalid_keys;
EXPECT_EQ(PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE,
transaction->CheckSplitValue("path1", &dict, &invalid_keys));
diff --git a/chromium/components/user_prefs/tracked/pref_hash_store_transaction.h b/chromium/components/user_prefs/tracked/pref_hash_store_transaction.h
index b8e2cf75e75..55d99d2d03f 100644
--- a/chromium/components/user_prefs/tracked/pref_hash_store_transaction.h
+++ b/chromium/components/user_prefs/tracked/pref_hash_store_transaction.h
@@ -8,6 +8,8 @@
#include <string>
#include <vector>
+#include "base/strings/string_piece.h"
+
namespace base {
class DictionaryValue;
class Value;
@@ -36,11 +38,17 @@ class PrefHashStoreTransaction {
TRUSTED_UNKNOWN_VALUE,
// NULL values are inherently trusted.
TRUSTED_NULL_VALUE,
+ // This transaction's store type is not supported.
+ UNSUPPORTED,
};
// Finalizes any remaining work after the transaction has been performed.
virtual ~PrefHashStoreTransaction() {}
+ // Returns the suffix to be appended to UMA histograms for the store contained
+ // in this transaction.
+ virtual base::StringPiece GetStoreUMASuffix() const = 0;
+
// Checks |initial_value| against the existing stored value hash.
virtual ValueState CheckValue(const std::string& path,
const base::Value* initial_value) const = 0;
diff --git a/chromium/components/user_prefs/tracked/pref_service_hash_store_contents.cc b/chromium/components/user_prefs/tracked/pref_service_hash_store_contents.cc
deleted file mode 100644
index d175541281f..00000000000
--- a/chromium/components/user_prefs/tracked/pref_service_hash_store_contents.cc
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright 2014 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/user_prefs/tracked/pref_service_hash_store_contents.h"
-
-#include "base/values.h"
-#include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/pref_service.h"
-#include "components/prefs/scoped_user_pref_update.h"
-
-namespace {
-
-// Implements get-or-create of a dictionary value and holds a
-// DictionaryPrefUpdate.
-class PrefServiceMutableDictionary
- : public HashStoreContents::MutableDictionary {
- public:
- // Creates an instance that provides mutable access to a dictionary value
- // named |key| that is a child of |kProfilePreferenceHashes| in
- // |prefs|.
- PrefServiceMutableDictionary(const std::string& key,
- PrefService* pref_service);
-
- // HashStoreContents::MutableDictionary implementation
- base::DictionaryValue* operator->() override;
-
- private:
- const std::string key_;
- DictionaryPrefUpdate update_;
-};
-
-PrefServiceMutableDictionary::PrefServiceMutableDictionary(
- const std::string& key,
- PrefService* pref_service)
- : key_(key),
- update_(pref_service,
- PrefServiceHashStoreContents::kProfilePreferenceHashes) {
- DCHECK(!key_.empty());
-}
-
-base::DictionaryValue* PrefServiceMutableDictionary::operator->() {
- base::DictionaryValue* dictionary = NULL;
- if (!update_->GetDictionaryWithoutPathExpansion(key_, &dictionary)) {
- dictionary = new base::DictionaryValue;
- update_->SetWithoutPathExpansion(key_, dictionary);
- }
- return dictionary;
-}
-
-} // namespace
-
-// static
-const char PrefServiceHashStoreContents::kProfilePreferenceHashes[] =
- "profile.preference_hashes";
-
-// static
-const char PrefServiceHashStoreContents::kHashOfHashesDict[] = "hash_of_hashes";
-
-// static
-const char PrefServiceHashStoreContents::kStoreVersionsDict[] =
- "store_versions";
-
-PrefServiceHashStoreContents::PrefServiceHashStoreContents(
- const std::string& hash_store_id,
- PrefService* pref_service)
- : hash_store_id_(hash_store_id), pref_service_(pref_service) {
- // TODO(erikwright): Remove in M40+.
- DictionaryPrefUpdate update(pref_service_, kProfilePreferenceHashes);
- update->RemovePath(kStoreVersionsDict, NULL);
-}
-
-// static
-void PrefServiceHashStoreContents::RegisterPrefs(PrefRegistrySimple* registry) {
- // Register the top level dictionary to map profile names to dictionaries of
- // tracked preferences.
- registry->RegisterDictionaryPref(kProfilePreferenceHashes);
-}
-
-// static
-void PrefServiceHashStoreContents::ResetAllPrefHashStores(
- PrefService* pref_service) {
- pref_service->ClearPref(kProfilePreferenceHashes);
-}
-
-std::string PrefServiceHashStoreContents::hash_store_id() const {
- return hash_store_id_;
-}
-
-void PrefServiceHashStoreContents::Reset() {
- DictionaryPrefUpdate update(pref_service_, kProfilePreferenceHashes);
-
- update->RemoveWithoutPathExpansion(hash_store_id_, NULL);
-
- // Remove this store's entry in the kHashOfHashesDict.
- base::DictionaryValue* hash_of_hashes_dict;
- if (update->GetDictionaryWithoutPathExpansion(kHashOfHashesDict,
- &hash_of_hashes_dict)) {
- hash_of_hashes_dict->RemoveWithoutPathExpansion(hash_store_id_, NULL);
- if (hash_of_hashes_dict->empty())
- update->RemovePath(kHashOfHashesDict, NULL);
- }
-
- if (update->empty())
- pref_service_->ClearPref(kProfilePreferenceHashes);
-}
-
-bool PrefServiceHashStoreContents::IsInitialized() const {
- const base::DictionaryValue* pref_hash_dicts =
- pref_service_->GetDictionary(kProfilePreferenceHashes);
- return pref_hash_dicts->GetDictionaryWithoutPathExpansion(hash_store_id_,
- NULL);
-}
-
-const base::DictionaryValue* PrefServiceHashStoreContents::GetContents() const {
- const base::DictionaryValue* pref_hash_dicts =
- pref_service_->GetDictionary(kProfilePreferenceHashes);
- const base::DictionaryValue* hashes_dict = NULL;
- pref_hash_dicts->GetDictionaryWithoutPathExpansion(hash_store_id_,
- &hashes_dict);
- return hashes_dict;
-}
-
-std::unique_ptr<HashStoreContents::MutableDictionary>
-PrefServiceHashStoreContents::GetMutableContents() {
- return std::unique_ptr<HashStoreContents::MutableDictionary>(
- new PrefServiceMutableDictionary(hash_store_id_, pref_service_));
-}
-
-std::string PrefServiceHashStoreContents::GetSuperMac() const {
- const base::DictionaryValue* pref_hash_dicts =
- pref_service_->GetDictionary(kProfilePreferenceHashes);
- const base::DictionaryValue* hash_of_hashes_dict = NULL;
- std::string hash_of_hashes;
- if (pref_hash_dicts->GetDictionaryWithoutPathExpansion(
- kHashOfHashesDict, &hash_of_hashes_dict)) {
- hash_of_hashes_dict->GetStringWithoutPathExpansion(hash_store_id_,
- &hash_of_hashes);
- }
- return hash_of_hashes;
-}
-
-void PrefServiceHashStoreContents::SetSuperMac(const std::string& super_mac) {
- PrefServiceMutableDictionary(kHashOfHashesDict, pref_service_)
- ->SetStringWithoutPathExpansion(hash_store_id_, super_mac);
-}
diff --git a/chromium/components/user_prefs/tracked/pref_service_hash_store_contents.h b/chromium/components/user_prefs/tracked/pref_service_hash_store_contents.h
deleted file mode 100644
index 05417d81c8e..00000000000
--- a/chromium/components/user_prefs/tracked/pref_service_hash_store_contents.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2014 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.
-
-#ifndef COMPONENTS_USER_PREFS_TRACKED_PREF_SERVICE_HASH_STORE_CONTENTS_H_
-#define COMPONENTS_USER_PREFS_TRACKED_PREF_SERVICE_HASH_STORE_CONTENTS_H_
-
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "components/user_prefs/tracked/hash_store_contents.h"
-
-class PrefRegistrySimple;
-class PrefService;
-
-// Implements HashStoreContents by storing hashes in a PrefService. Multiple
-// separate hash stores may coexist in the PrefService by using distinct hash
-// store IDs.
-// TODO(erikwright): This class is only used to recreate preference state as in
-// M35, to test migration behaviour. Remove this class when
-// ProfilePrefStoreManagerTest no longer depends on it.
-class PrefServiceHashStoreContents : public HashStoreContents {
- public:
- // Constructs a HashStoreContents that stores hashes in |pref_service|.
- // Multiple hash stores can use the same |pref_service| with distinct
- // |hash_store_id|s.
- //
- // |pref_service| must have previously been configured using |RegisterPrefs|.
- PrefServiceHashStoreContents(const std::string& hash_store_id,
- PrefService* pref_service);
-
- // A dictionary pref which maps profile names to dictionary values which hold
- // hashes of profile prefs that we track to detect changes that happen outside
- // of Chrome.
- static const char kProfilePreferenceHashes[];
-
- // The name of a dict that is stored as a child of
- // |prefs::kProfilePreferenceHashes|. Each child node is a string whose name
- // is a hash store ID and whose value is the super MAC for the corresponding
- // hash store.
- static const char kHashOfHashesDict[];
-
- // The name of a dict that is stored as a child of
- // |prefs::kProfilePreferenceHashes|. Each child node is a number whose name
- // is a hash store ID and whose value is the version of the corresponding
- // hash store.
- static const char kStoreVersionsDict[];
-
- // Registers required preferences.
- static void RegisterPrefs(PrefRegistrySimple* registry);
-
- // Deletes stored hashes for all profiles from |pref_service|.
- static void ResetAllPrefHashStores(PrefService* pref_service);
-
- // HashStoreContents implementation
- std::string hash_store_id() const override;
- void Reset() override;
- bool IsInitialized() const override;
- const base::DictionaryValue* GetContents() const override;
- std::unique_ptr<MutableDictionary> GetMutableContents() override;
- std::string GetSuperMac() const override;
- void SetSuperMac(const std::string& super_mac) override;
-
- private:
- const std::string hash_store_id_;
- PrefService* pref_service_;
-
- DISALLOW_COPY_AND_ASSIGN(PrefServiceHashStoreContents);
-};
-
-#endif // COMPONENTS_PREFS_TRACKED_PREF_SERVICE_HASH_STORE_CONTENTS_H_
diff --git a/chromium/components/user_prefs/tracked/pref_service_hash_store_contents_unittest.cc b/chromium/components/user_prefs/tracked/pref_service_hash_store_contents_unittest.cc
deleted file mode 100644
index 3cfb10542af..00000000000
--- a/chromium/components/user_prefs/tracked/pref_service_hash_store_contents_unittest.cc
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright 2014 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/user_prefs/tracked/pref_service_hash_store_contents.h"
-
-#include <string>
-
-#include "base/values.h"
-#include "components/prefs/pref_service.h"
-#include "components/prefs/testing_pref_service.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-class PrefServiceHashStoreContentsTest : public testing::Test {
- public:
- void SetUp() override {
- PrefServiceHashStoreContents::RegisterPrefs(local_state_.registry());
- }
-
- protected:
- TestingPrefServiceSimple local_state_;
-};
-
-TEST_F(PrefServiceHashStoreContentsTest, hash_store_id) {
- PrefServiceHashStoreContents contents("store_id", &local_state_);
- ASSERT_EQ("store_id", contents.hash_store_id());
-}
-
-TEST_F(PrefServiceHashStoreContentsTest, IsInitialized) {
- {
- PrefServiceHashStoreContents contents("store_id", &local_state_);
- ASSERT_FALSE(contents.IsInitialized());
- (*contents.GetMutableContents())->Set("foo", new base::StringValue("bar"));
- ASSERT_TRUE(contents.IsInitialized());
- }
- {
- PrefServiceHashStoreContents contents("store_id", &local_state_);
- ASSERT_TRUE(contents.IsInitialized());
- PrefServiceHashStoreContents other_contents("other_store_id",
- &local_state_);
- ASSERT_FALSE(other_contents.IsInitialized());
- }
-}
-
-TEST_F(PrefServiceHashStoreContentsTest, Reset) {
- ASSERT_FALSE(local_state_.GetUserPrefValue(
- PrefServiceHashStoreContents::kProfilePreferenceHashes));
-
- {
- PrefServiceHashStoreContents contents("store_id", &local_state_);
- ASSERT_FALSE(contents.IsInitialized());
- (*contents.GetMutableContents())->Set("foo", new base::StringValue("bar"));
- ASSERT_TRUE(contents.IsInitialized());
- PrefServiceHashStoreContents other_contents("other_store_id",
- &local_state_);
- (*other_contents.GetMutableContents())
- ->Set("foo", new base::StringValue("bar"));
- }
-
- ASSERT_TRUE(local_state_.GetUserPrefValue(
- PrefServiceHashStoreContents::kProfilePreferenceHashes));
-
- {
- PrefServiceHashStoreContents contents("store_id", &local_state_);
- ASSERT_TRUE(contents.IsInitialized());
- contents.Reset();
- ASSERT_FALSE(contents.IsInitialized());
- }
-
- ASSERT_TRUE(local_state_.GetUserPrefValue(
- PrefServiceHashStoreContents::kProfilePreferenceHashes));
-
- {
- PrefServiceHashStoreContents contents("store_id", &local_state_);
- ASSERT_FALSE(contents.IsInitialized());
- PrefServiceHashStoreContents other_contents("other_store_id",
- &local_state_);
- ASSERT_TRUE(other_contents.IsInitialized());
- }
-
- {
- PrefServiceHashStoreContents other_contents("other_store_id",
- &local_state_);
- other_contents.Reset();
- }
-
- ASSERT_FALSE(local_state_.GetUserPrefValue(
- PrefServiceHashStoreContents::kProfilePreferenceHashes));
-}
-
-TEST_F(PrefServiceHashStoreContentsTest, GetAndSetContents) {
- {
- PrefServiceHashStoreContents contents("store_id", &local_state_);
- ASSERT_EQ(NULL, contents.GetContents());
- (*contents.GetMutableContents())->Set("foo", new base::StringValue("bar"));
- ASSERT_FALSE(contents.GetContents() == NULL);
- std::string actual_value;
- ASSERT_TRUE(contents.GetContents()->GetString("foo", &actual_value));
- ASSERT_EQ("bar", actual_value);
- PrefServiceHashStoreContents other_contents("other_store_id",
- &local_state_);
- ASSERT_EQ(NULL, other_contents.GetContents());
- }
- {
- PrefServiceHashStoreContents contents("store_id", &local_state_);
- ASSERT_FALSE(contents.GetContents() == NULL);
- }
-}
-
-TEST_F(PrefServiceHashStoreContentsTest, GetAndSetSuperMac) {
- {
- PrefServiceHashStoreContents contents("store_id", &local_state_);
- ASSERT_TRUE(contents.GetSuperMac().empty());
- (*contents.GetMutableContents())->Set("foo", new base::StringValue("bar"));
- ASSERT_TRUE(contents.GetSuperMac().empty());
- contents.SetSuperMac("0123456789");
- ASSERT_EQ("0123456789", contents.GetSuperMac());
- }
- {
- PrefServiceHashStoreContents contents("store_id", &local_state_);
- ASSERT_EQ("0123456789", contents.GetSuperMac());
- PrefServiceHashStoreContents other_contents("other_store_id",
- &local_state_);
- ASSERT_TRUE(other_contents.GetSuperMac().empty());
- }
-}
-
-TEST_F(PrefServiceHashStoreContentsTest, ResetAllPrefHashStores) {
- {
- PrefServiceHashStoreContents contents_1("store_id_1", &local_state_);
- PrefServiceHashStoreContents contents_2("store_id_2", &local_state_);
- (*contents_1.GetMutableContents())
- ->Set("foo", new base::StringValue("bar"));
- (*contents_2.GetMutableContents())
- ->Set("foo", new base::StringValue("bar"));
- }
- {
- PrefServiceHashStoreContents contents_1("store_id_1", &local_state_);
- PrefServiceHashStoreContents contents_2("store_id_2", &local_state_);
- ASSERT_TRUE(contents_1.IsInitialized());
- ASSERT_TRUE(contents_2.IsInitialized());
- }
-
- PrefServiceHashStoreContents::ResetAllPrefHashStores(&local_state_);
-
- {
- PrefServiceHashStoreContents contents_1("store_id_1", &local_state_);
- PrefServiceHashStoreContents contents_2("store_id_2", &local_state_);
- ASSERT_FALSE(contents_1.IsInitialized());
- ASSERT_FALSE(contents_2.IsInitialized());
- }
-}
diff --git a/chromium/components/user_prefs/tracked/registry_hash_store_contents_win.cc b/chromium/components/user_prefs/tracked/registry_hash_store_contents_win.cc
new file mode 100644
index 00000000000..03d789839c5
--- /dev/null
+++ b/chromium/components/user_prefs/tracked/registry_hash_store_contents_win.cc
@@ -0,0 +1,182 @@
+// Copyright (c) 2016 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/user_prefs/tracked/registry_hash_store_contents_win.h"
+
+#include <windows.h>
+
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "base/win/registry.h"
+#include "components/user_prefs/tracked/tracked_preference_histogram_names.h"
+
+using base::win::RegistryValueIterator;
+
+namespace {
+
+constexpr size_t kMacSize = 64;
+
+base::string16 GetSplitPrefKeyName(const base::string16& reg_key_name,
+ const std::string& split_key_name) {
+ return reg_key_name + L"\\" + base::UTF8ToUTF16(split_key_name);
+}
+
+bool ReadMacFromRegistry(const base::win::RegKey& key,
+ const std::string& value_name,
+ std::string* out_mac) {
+ base::string16 string_value;
+ if (key.ReadValue(base::UTF8ToUTF16(value_name).c_str(), &string_value) ==
+ ERROR_SUCCESS &&
+ string_value.size() == kMacSize) {
+ out_mac->assign(base::UTF16ToUTF8(string_value));
+ return true;
+ }
+ return false;
+}
+
+// Removes |value_name| under |reg_key_name|. Returns true if found and
+// successfully removed.
+bool ClearAtomicMac(const base::string16& reg_key_name,
+ const std::string& value_name) {
+ base::win::RegKey key;
+ if (key.Open(HKEY_CURRENT_USER, reg_key_name.c_str(),
+ KEY_SET_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
+ return key.DeleteValue(base::UTF8ToUTF16(value_name).c_str()) ==
+ ERROR_SUCCESS;
+ }
+ return false;
+}
+
+// Deletes |split_key_name| under |reg_key_name|. Returns true if found and
+// successfully removed.
+bool ClearSplitMac(const base::string16& reg_key_name,
+ const std::string& split_key_name) {
+ base::win::RegKey key;
+ if (key.Open(HKEY_CURRENT_USER,
+ GetSplitPrefKeyName(reg_key_name, split_key_name).c_str(),
+ KEY_SET_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
+ return key.DeleteKey(L"") == ERROR_SUCCESS;
+ }
+ return false;
+}
+
+} // namespace
+
+RegistryHashStoreContentsWin::RegistryHashStoreContentsWin(
+ const base::string16& registry_path,
+ const base::string16& store_key)
+ : preference_key_name_(registry_path + L"\\PreferenceMACs\\" + store_key) {}
+
+RegistryHashStoreContentsWin::RegistryHashStoreContentsWin(
+ const RegistryHashStoreContentsWin& other) = default;
+
+bool RegistryHashStoreContentsWin::IsCopyable() const {
+ return true;
+}
+
+std::unique_ptr<HashStoreContents> RegistryHashStoreContentsWin::MakeCopy()
+ const {
+ return base::WrapUnique(new RegistryHashStoreContentsWin(*this));
+}
+
+base::StringPiece RegistryHashStoreContentsWin::GetUMASuffix() const {
+ return user_prefs::tracked::kTrackedPrefRegistryValidationSuffix;
+}
+
+void RegistryHashStoreContentsWin::Reset() {
+ base::win::RegKey key;
+ if (key.Open(HKEY_CURRENT_USER, preference_key_name_.c_str(),
+ KEY_SET_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
+ LONG result = key.DeleteKey(L"");
+ DCHECK(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND) << result;
+ }
+}
+
+bool RegistryHashStoreContentsWin::GetMac(const std::string& path,
+ std::string* out_value) {
+ base::win::RegKey key;
+ if (key.Open(HKEY_CURRENT_USER, preference_key_name_.c_str(),
+ KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
+ return ReadMacFromRegistry(key, path, out_value);
+ }
+
+ return false;
+}
+
+bool RegistryHashStoreContentsWin::GetSplitMacs(
+ const std::string& path,
+ std::map<std::string, std::string>* split_macs) {
+ DCHECK(split_macs);
+ DCHECK(split_macs->empty());
+
+ RegistryValueIterator iter_key(
+ HKEY_CURRENT_USER,
+ GetSplitPrefKeyName(preference_key_name_, path).c_str());
+
+ for (; iter_key.Valid(); ++iter_key) {
+ split_macs->insert(make_pair(base::UTF16ToUTF8(iter_key.Name()),
+ base::UTF16ToUTF8(iter_key.Value())));
+ }
+
+ return !split_macs->empty();
+}
+
+void RegistryHashStoreContentsWin::SetMac(const std::string& path,
+ const std::string& value) {
+ base::win::RegKey key;
+ DCHECK_EQ(kMacSize, value.size());
+
+ if (key.Create(HKEY_CURRENT_USER, preference_key_name_.c_str(),
+ KEY_SET_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
+ key.WriteValue(base::UTF8ToUTF16(path).c_str(),
+ base::UTF8ToUTF16(value).c_str());
+ }
+}
+
+void RegistryHashStoreContentsWin::SetSplitMac(const std::string& path,
+ const std::string& split_path,
+ const std::string& value) {
+ base::win::RegKey key;
+ DCHECK_EQ(kMacSize, value.size());
+
+ if (key.Create(HKEY_CURRENT_USER,
+ GetSplitPrefKeyName(preference_key_name_, path).c_str(),
+ KEY_SET_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
+ key.WriteValue(base::UTF8ToUTF16(split_path).c_str(),
+ base::UTF8ToUTF16(value).c_str());
+ }
+}
+
+bool RegistryHashStoreContentsWin::RemoveEntry(const std::string& path) {
+ return ClearAtomicMac(preference_key_name_, path) ||
+ ClearSplitMac(preference_key_name_, path);
+}
+
+void RegistryHashStoreContentsWin::ImportEntry(const std::string& path,
+ const base::Value* in_value) {
+ NOTREACHED()
+ << "RegistryHashStoreContents does not support the ImportEntry operation";
+}
+
+const base::DictionaryValue* RegistryHashStoreContentsWin::GetContents() const {
+ NOTREACHED()
+ << "RegistryHashStoreContents does not support the GetContents operation";
+ return NULL;
+}
+
+std::string RegistryHashStoreContentsWin::GetSuperMac() const {
+ NOTREACHED()
+ << "RegistryHashStoreContents does not support the GetSuperMac operation";
+ return NULL;
+}
+
+void RegistryHashStoreContentsWin::SetSuperMac(const std::string& super_mac) {
+ NOTREACHED()
+ << "RegistryHashStoreContents does not support the SetSuperMac operation";
+}
diff --git a/chromium/components/user_prefs/tracked/registry_hash_store_contents_win.h b/chromium/components/user_prefs/tracked/registry_hash_store_contents_win.h
new file mode 100644
index 00000000000..b44898ef698
--- /dev/null
+++ b/chromium/components/user_prefs/tracked/registry_hash_store_contents_win.h
@@ -0,0 +1,49 @@
+// Copyright 2016 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.
+
+#ifndef COMPONENTS_USER_PREFS_TRACKED_PREF_REGISTRY_HASH_STORE_CONTENTS_WIN_H_
+#define COMPONENTS_USER_PREFS_TRACKED_PREF_REGISTRY_HASH_STORE_CONTENTS_WIN_H_
+
+#include "base/macros.h"
+#include "base/strings/string16.h"
+#include "components/user_prefs/tracked/hash_store_contents.h"
+
+// Implements HashStoreContents by storing MACs in the Windows registry.
+class RegistryHashStoreContentsWin : public HashStoreContents {
+ public:
+ // Constructs a RegistryHashStoreContents which acts on a registry entry
+ // defined by |registry_path| and |store_key|.
+ explicit RegistryHashStoreContentsWin(const base::string16& registry_path,
+ const base::string16& store_key);
+
+ // HashStoreContents overrides:
+ bool IsCopyable() const override;
+ std::unique_ptr<HashStoreContents> MakeCopy() const override;
+ base::StringPiece GetUMASuffix() const override;
+ void Reset() override;
+ bool GetMac(const std::string& path, std::string* out_value) override;
+ bool GetSplitMacs(const std::string& path,
+ std::map<std::string, std::string>* split_macs) override;
+ void SetMac(const std::string& path, const std::string& value) override;
+ void SetSplitMac(const std::string& path,
+ const std::string& split_path,
+ const std::string& value) override;
+ bool RemoveEntry(const std::string& path) override;
+
+ // Unsupported HashStoreContents overrides:
+ void ImportEntry(const std::string& path,
+ const base::Value* in_value) override;
+ const base::DictionaryValue* GetContents() const override;
+ std::string GetSuperMac() const override;
+ void SetSuperMac(const std::string& super_mac) override;
+
+ private:
+ // Helper constructor for |MakeCopy|.
+ explicit RegistryHashStoreContentsWin(
+ const RegistryHashStoreContentsWin& other);
+
+ const base::string16 preference_key_name_;
+};
+
+#endif // COMPONENTS_USER_PREFS_TRACKED_PREF_REGISTRY_HASH_STORE_CONTENTS_H_
diff --git a/chromium/components/user_prefs/tracked/registry_hash_store_contents_win_unittest.cc b/chromium/components/user_prefs/tracked/registry_hash_store_contents_win_unittest.cc
new file mode 100644
index 00000000000..a34d7ade788
--- /dev/null
+++ b/chromium/components/user_prefs/tracked/registry_hash_store_contents_win_unittest.cc
@@ -0,0 +1,119 @@
+// Copyright (c) 2016 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/user_prefs/tracked/registry_hash_store_contents_win.h"
+
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/test_reg_util_win.h"
+#include "base/values.h"
+#include "base/win/registry.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+constexpr base::char16 kRegistryPath[] = L"Foo\\TestStore";
+constexpr base::char16 kStoreKey[] = L"test_store_key";
+
+// Hex-encoded MACs are 64 characters long.
+constexpr char kTestStringA[] =
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+constexpr char kTestStringB[] =
+ "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
+
+constexpr char kAtomicPrefPath[] = "path1";
+constexpr char kSplitPrefPath[] = "extension";
+
+class RegistryHashStoreContentsWinTest : public testing::Test {
+ protected:
+ RegistryHashStoreContentsWinTest() {}
+
+ void SetUp() override {
+ registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER);
+
+ contents.reset(new RegistryHashStoreContentsWin(kRegistryPath, kStoreKey));
+ }
+
+ std::unique_ptr<HashStoreContents> contents;
+
+ private:
+ registry_util::RegistryOverrideManager registry_override_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(RegistryHashStoreContentsWinTest);
+};
+
+} // namespace
+
+TEST_F(RegistryHashStoreContentsWinTest, TestSetAndGetMac) {
+ std::string stored_mac;
+ EXPECT_FALSE(contents->GetMac(kAtomicPrefPath, &stored_mac));
+
+ contents->SetMac(kAtomicPrefPath, kTestStringA);
+
+ EXPECT_TRUE(contents->GetMac(kAtomicPrefPath, &stored_mac));
+ EXPECT_EQ(kTestStringA, stored_mac);
+}
+
+TEST_F(RegistryHashStoreContentsWinTest, TestSetAndGetSplitMacs) {
+ std::map<std::string, std::string> split_macs;
+ EXPECT_FALSE(contents->GetSplitMacs(kSplitPrefPath, &split_macs));
+
+ contents->SetSplitMac(kSplitPrefPath, "a", kTestStringA);
+ contents->SetSplitMac(kSplitPrefPath, "b", kTestStringB);
+
+ EXPECT_TRUE(contents->GetSplitMacs(kSplitPrefPath, &split_macs));
+ EXPECT_EQ(2U, split_macs.size());
+ EXPECT_EQ(kTestStringA, split_macs.at("a"));
+ EXPECT_EQ(kTestStringB, split_macs.at("b"));
+}
+
+TEST_F(RegistryHashStoreContentsWinTest, TestRemoveAtomicMac) {
+ contents->SetMac(kAtomicPrefPath, kTestStringA);
+
+ std::string stored_mac;
+ EXPECT_TRUE(contents->GetMac(kAtomicPrefPath, &stored_mac));
+ EXPECT_EQ(kTestStringA, stored_mac);
+
+ contents->RemoveEntry(kAtomicPrefPath);
+
+ EXPECT_FALSE(contents->GetMac(kAtomicPrefPath, &stored_mac));
+}
+
+TEST_F(RegistryHashStoreContentsWinTest, TestRemoveSplitMacs) {
+ contents->SetSplitMac(kSplitPrefPath, "a", kTestStringA);
+ contents->SetSplitMac(kSplitPrefPath, "b", kTestStringB);
+
+ std::map<std::string, std::string> split_macs;
+ EXPECT_TRUE(contents->GetSplitMacs(kSplitPrefPath, &split_macs));
+ EXPECT_EQ(2U, split_macs.size());
+
+ contents->RemoveEntry(kSplitPrefPath);
+
+ split_macs.clear();
+ EXPECT_FALSE(contents->GetSplitMacs(kSplitPrefPath, &split_macs));
+ EXPECT_EQ(0U, split_macs.size());
+}
+
+TEST_F(RegistryHashStoreContentsWinTest, TestReset) {
+ contents->SetMac(kAtomicPrefPath, kTestStringA);
+ contents->SetSplitMac(kSplitPrefPath, "a", kTestStringA);
+
+ std::string stored_mac;
+ EXPECT_TRUE(contents->GetMac(kAtomicPrefPath, &stored_mac));
+ EXPECT_EQ(kTestStringA, stored_mac);
+
+ std::map<std::string, std::string> split_macs;
+ EXPECT_TRUE(contents->GetSplitMacs(kSplitPrefPath, &split_macs));
+ EXPECT_EQ(1U, split_macs.size());
+
+ contents->Reset();
+
+ stored_mac.clear();
+ EXPECT_FALSE(contents->GetMac(kAtomicPrefPath, &stored_mac));
+ EXPECT_TRUE(stored_mac.empty());
+
+ split_macs.clear();
+ EXPECT_FALSE(contents->GetSplitMacs(kSplitPrefPath, &split_macs));
+ EXPECT_EQ(0U, split_macs.size());
+}
diff --git a/chromium/components/user_prefs/tracked/segregated_pref_store.cc b/chromium/components/user_prefs/tracked/segregated_pref_store.cc
index c5a6e25c2f3..af8dfe34be7 100644
--- a/chromium/components/user_prefs/tracked/segregated_pref_store.cc
+++ b/chromium/components/user_prefs/tracked/segregated_pref_store.cc
@@ -166,14 +166,16 @@ SegregatedPrefStore::~SegregatedPrefStore() {
}
PersistentPrefStore* SegregatedPrefStore::StoreForKey(const std::string& key) {
- return (ContainsKey(selected_preference_names_, key)
+ return (base::ContainsKey(selected_preference_names_, key)
? selected_pref_store_
- : default_pref_store_).get();
+ : default_pref_store_)
+ .get();
}
const PersistentPrefStore* SegregatedPrefStore::StoreForKey(
const std::string& key) const {
- return (ContainsKey(selected_preference_names_, key)
+ return (base::ContainsKey(selected_preference_names_, key)
? selected_pref_store_
- : default_pref_store_).get();
+ : default_pref_store_)
+ .get();
}
diff --git a/chromium/components/user_prefs/tracked/segregated_pref_store_unittest.cc b/chromium/components/user_prefs/tracked/segregated_pref_store_unittest.cc
index f3efce22f72..5d32d027d5e 100644
--- a/chromium/components/user_prefs/tracked/segregated_pref_store_unittest.cc
+++ b/chromium/components/user_prefs/tracked/segregated_pref_store_unittest.cc
@@ -104,10 +104,10 @@ TEST_F(SegregatedPrefStoreTest, StoreValues) {
// Properly stores new values.
segregated_store_->SetValue(kSelectedPref,
- base::WrapUnique(new base::StringValue(kValue1)),
+ base::MakeUnique<base::StringValue>(kValue1),
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
segregated_store_->SetValue(kUnselectedPref,
- base::WrapUnique(new base::StringValue(kValue2)),
+ base::MakeUnique<base::StringValue>(kValue2),
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
ASSERT_TRUE(selected_store_->GetValue(kSelectedPref, NULL));
@@ -129,10 +129,10 @@ TEST_F(SegregatedPrefStoreTest, StoreValues) {
TEST_F(SegregatedPrefStoreTest, ReadValues) {
selected_store_->SetValue(kSelectedPref,
- base::WrapUnique(new base::StringValue(kValue1)),
+ base::MakeUnique<base::StringValue>(kValue1),
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
default_store_->SetValue(kUnselectedPref,
- base::WrapUnique(new base::StringValue(kValue2)),
+ base::MakeUnique<base::StringValue>(kValue2),
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
// Works properly with values that are already there.
@@ -157,11 +157,11 @@ TEST_F(SegregatedPrefStoreTest, Observer) {
EXPECT_TRUE(observer_.initialization_success);
EXPECT_TRUE(observer_.changed_keys.empty());
segregated_store_->SetValue(kSelectedPref,
- base::WrapUnique(new base::StringValue(kValue1)),
+ base::MakeUnique<base::StringValue>(kValue1),
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
observer_.VerifyAndResetChangedKey(kSelectedPref);
segregated_store_->SetValue(kUnselectedPref,
- base::WrapUnique(new base::StringValue(kValue2)),
+ base::MakeUnique<base::StringValue>(kValue2),
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
observer_.VerifyAndResetChangedKey(kUnselectedPref);
}
diff --git a/chromium/components/user_prefs/tracked/tracked_atomic_preference.cc b/chromium/components/user_prefs/tracked/tracked_atomic_preference.cc
index 4eb4b6129d2..e2b76784b81 100644
--- a/chromium/components/user_prefs/tracked/tracked_atomic_preference.cc
+++ b/chromium/components/user_prefs/tracked/tracked_atomic_preference.cc
@@ -24,6 +24,10 @@ TrackedAtomicPreference::TrackedAtomicPreference(
delegate_(delegate) {
}
+TrackedPreferenceType TrackedAtomicPreference::GetType() const {
+ return TrackedPreferenceType::ATOMIC;
+}
+
void TrackedAtomicPreference::OnNewValue(
const base::Value* value,
PrefHashStoreTransaction* transaction) const {
@@ -32,20 +36,31 @@ void TrackedAtomicPreference::OnNewValue(
bool TrackedAtomicPreference::EnforceAndReport(
base::DictionaryValue* pref_store_contents,
- PrefHashStoreTransaction* transaction) const {
+ PrefHashStoreTransaction* transaction,
+ PrefHashStoreTransaction* external_validation_transaction) const {
const base::Value* value = NULL;
pref_store_contents->Get(pref_path_, &value);
PrefHashStoreTransaction::ValueState value_state =
transaction->CheckValue(pref_path_, value);
+ helper_.ReportValidationResult(value_state, transaction->GetStoreUMASuffix());
- helper_.ReportValidationResult(value_state);
+ PrefHashStoreTransaction::ValueState external_validation_value_state =
+ PrefHashStoreTransaction::UNSUPPORTED;
+ if (external_validation_transaction) {
+ external_validation_value_state =
+ external_validation_transaction->CheckValue(pref_path_, value);
+ helper_.ReportValidationResult(
+ external_validation_value_state,
+ external_validation_transaction->GetStoreUMASuffix());
+ }
- TrackedPreferenceHelper::ResetAction reset_action =
- helper_.GetAction(value_state);
if (delegate_) {
delegate_->OnAtomicPreferenceValidation(pref_path_, value, value_state,
+ external_validation_value_state,
helper_.IsPersonal());
}
+ TrackedPreferenceHelper::ResetAction reset_action =
+ helper_.GetAction(value_state);
helper_.ReportAction(reset_action);
bool was_reset = false;
@@ -61,5 +76,16 @@ bool TrackedAtomicPreference::EnforceAndReport(
transaction->StoreHash(pref_path_, new_value);
}
+ // Update MACs in the external store if there is one and there either was a
+ // reset or external validation failed.
+ if (external_validation_transaction &&
+ (was_reset ||
+ external_validation_value_state !=
+ PrefHashStoreTransaction::UNCHANGED)) {
+ const base::Value* new_value = nullptr;
+ pref_store_contents->Get(pref_path_, &new_value);
+ external_validation_transaction->StoreHash(pref_path_, new_value);
+ }
+
return was_reset;
}
diff --git a/chromium/components/user_prefs/tracked/tracked_atomic_preference.h b/chromium/components/user_prefs/tracked/tracked_atomic_preference.h
index 04bd0eaae85..e279af85947 100644
--- a/chromium/components/user_prefs/tracked/tracked_atomic_preference.h
+++ b/chromium/components/user_prefs/tracked/tracked_atomic_preference.h
@@ -30,10 +30,13 @@ class TrackedAtomicPreference : public TrackedPreference {
TrackedPreferenceValidationDelegate* delegate);
// TrackedPreference implementation.
+ TrackedPreferenceType GetType() const override;
void OnNewValue(const base::Value* value,
PrefHashStoreTransaction* transaction) const override;
- bool EnforceAndReport(base::DictionaryValue* pref_store_contents,
- PrefHashStoreTransaction* transaction) const override;
+ bool EnforceAndReport(
+ base::DictionaryValue* pref_store_contents,
+ PrefHashStoreTransaction* transaction,
+ PrefHashStoreTransaction* external_validation_transaction) const override;
private:
const std::string pref_path_;
diff --git a/chromium/components/user_prefs/tracked/tracked_preference.h b/chromium/components/user_prefs/tracked/tracked_preference.h
index 4773ac1cd3c..97666a0fcf8 100644
--- a/chromium/components/user_prefs/tracked/tracked_preference.h
+++ b/chromium/components/user_prefs/tracked/tracked_preference.h
@@ -12,12 +12,16 @@ class DictionaryValue;
class Value;
}
+enum class TrackedPreferenceType { ATOMIC, SPLIT };
+
// A TrackedPreference tracks changes to an individual preference, reporting and
// reacting to them according to preference-specific and browser-wide policies.
class TrackedPreference {
public:
virtual ~TrackedPreference() {}
+ virtual TrackedPreferenceType GetType() const = 0;
+
// Notifies the underlying TrackedPreference about its new |value| which
// can update hashes in the corresponding hash store via |transaction|.
virtual void OnNewValue(const base::Value* value,
@@ -27,10 +31,14 @@ class TrackedPreference {
// is valid. Responds to verification failures according to
// preference-specific and browser-wide policy and reports results to via UMA.
// May use |transaction| to check/modify hashes in the corresponding hash
- // store.
+ // store. Performs validation and reports results without enforcing for
+ // |external_validation_transaction|. This call assumes exclusive access to
+ // |external_validation_transaction| and its associated state and as such
+ // should only be called before any other subsystem is made aware of it.
virtual bool EnforceAndReport(
base::DictionaryValue* pref_store_contents,
- PrefHashStoreTransaction* transaction) const = 0;
+ PrefHashStoreTransaction* transaction,
+ PrefHashStoreTransaction* external_validation_transaction) const = 0;
};
#endif // COMPONENTS_USER_PREFS_TRACKED_TRACKED_PREFERENCE_H_
diff --git a/chromium/components/user_prefs/tracked/tracked_preference_helper.cc b/chromium/components/user_prefs/tracked/tracked_preference_helper.cc
index f2e6883cf8a..fb36a2a1518 100644
--- a/chromium/components/user_prefs/tracked/tracked_preference_helper.cc
+++ b/chromium/components/user_prefs/tracked/tracked_preference_helper.cc
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "base/metrics/histogram.h"
+#include "base/metrics/histogram_macros.h"
#include "components/user_prefs/tracked/tracked_preference_histogram_names.h"
TrackedPreferenceHelper::TrackedPreferenceHelper(
@@ -37,6 +38,10 @@ TrackedPreferenceHelper::ResetAction TrackedPreferenceHelper::GetAction(
case PrefHashStoreTransaction::SECURE_LEGACY:
// Accept secure legacy device ID based hashes.
return DONT_RESET;
+ case PrefHashStoreTransaction::UNSUPPORTED:
+ NOTREACHED()
+ << "GetAction should not be called with an UNSUPPORTED value state";
+ return DONT_RESET;
case PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE: // Falls through.
case PrefHashStoreTransaction::CHANGED:
return enforce_ ? DO_RESET : WANTED_RESET;
@@ -51,46 +56,53 @@ bool TrackedPreferenceHelper::IsPersonal() const {
}
void TrackedPreferenceHelper::ReportValidationResult(
- PrefHashStoreTransaction::ValueState value_state) const {
+ PrefHashStoreTransaction::ValueState value_state,
+ base::StringPiece validation_type_suffix) const {
+ const char* histogram_name = nullptr;
switch (value_state) {
case PrefHashStoreTransaction::UNCHANGED:
- UMA_HISTOGRAM_ENUMERATION(
- user_prefs::tracked::kTrackedPrefHistogramUnchanged, reporting_id_,
- reporting_ids_count_);
- return;
+ histogram_name = user_prefs::tracked::kTrackedPrefHistogramUnchanged;
+ break;
case PrefHashStoreTransaction::CLEARED:
- UMA_HISTOGRAM_ENUMERATION(
- user_prefs::tracked::kTrackedPrefHistogramCleared, reporting_id_,
- reporting_ids_count_);
- return;
+ histogram_name = user_prefs::tracked::kTrackedPrefHistogramCleared;
+ break;
case PrefHashStoreTransaction::SECURE_LEGACY:
- UMA_HISTOGRAM_ENUMERATION(
- user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
- reporting_id_, reporting_ids_count_);
- return;
+ histogram_name =
+ user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId;
+ break;
case PrefHashStoreTransaction::CHANGED:
- UMA_HISTOGRAM_ENUMERATION(
- user_prefs::tracked::kTrackedPrefHistogramChanged, reporting_id_,
- reporting_ids_count_);
- return;
+ histogram_name = user_prefs::tracked::kTrackedPrefHistogramChanged;
+ break;
case PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE:
- UMA_HISTOGRAM_ENUMERATION(
- user_prefs::tracked::kTrackedPrefHistogramInitialized, reporting_id_,
- reporting_ids_count_);
- return;
+ histogram_name = user_prefs::tracked::kTrackedPrefHistogramInitialized;
+ break;
case PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE:
- UMA_HISTOGRAM_ENUMERATION(
- user_prefs::tracked::kTrackedPrefHistogramTrustedInitialized,
- reporting_id_, reporting_ids_count_);
- return;
+ histogram_name =
+ user_prefs::tracked::kTrackedPrefHistogramTrustedInitialized;
+ break;
case PrefHashStoreTransaction::TRUSTED_NULL_VALUE:
- UMA_HISTOGRAM_ENUMERATION(
- user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
- reporting_id_, reporting_ids_count_);
+ histogram_name =
+ user_prefs::tracked::kTrackedPrefHistogramNullInitialized;
+ break;
+ case PrefHashStoreTransaction::UNSUPPORTED:
+ NOTREACHED() << "ReportValidationResult should not be called with an "
+ "UNSUPPORTED value state";
return;
}
- NOTREACHED() << "Unexpected PrefHashStoreTransaction::ValueState: "
- << value_state;
+ DCHECK(histogram_name);
+
+ std::string full_histogram_name(histogram_name);
+ if (!validation_type_suffix.empty()) {
+ full_histogram_name.push_back('.');
+ validation_type_suffix.AppendToString(&full_histogram_name);
+ }
+
+ // Using FactoryGet to allow dynamic histogram names. This is equivalent to
+ // UMA_HISTOGRAM_ENUMERATION(name, reporting_id_, reporting_ids_count_);
+ base::HistogramBase* histogram = base::LinearHistogram::FactoryGet(
+ full_histogram_name, 1, reporting_ids_count_, reporting_ids_count_ + 1,
+ base::HistogramBase::kUmaTargetedHistogramFlag);
+ histogram->Add(reporting_id_);
}
void TrackedPreferenceHelper::ReportAction(ResetAction reset_action) const {
diff --git a/chromium/components/user_prefs/tracked/tracked_preference_helper.h b/chromium/components/user_prefs/tracked/tracked_preference_helper.h
index 883e3e8f789..57b35fb32a3 100644
--- a/chromium/components/user_prefs/tracked/tracked_preference_helper.h
+++ b/chromium/components/user_prefs/tracked/tracked_preference_helper.h
@@ -42,8 +42,9 @@ class TrackedPreferenceHelper {
bool IsPersonal() const;
// Reports |value_state| via UMA under |reporting_id_|.
- void ReportValidationResult(
- PrefHashStoreTransaction::ValueState value_state) const;
+ // |validation_type_suffix| is appended to the reported histogram's name.
+ void ReportValidationResult(PrefHashStoreTransaction::ValueState value_state,
+ base::StringPiece validation_type_suffix) const;
// Reports |reset_action| via UMA under |reporting_id_|.
void ReportAction(ResetAction reset_action) const;
diff --git a/chromium/components/user_prefs/tracked/tracked_preference_histogram_names.cc b/chromium/components/user_prefs/tracked/tracked_preference_histogram_names.cc
index deb4236dd1a..431bb9a31cf 100644
--- a/chromium/components/user_prefs/tracked/tracked_preference_histogram_names.cc
+++ b/chromium/components/user_prefs/tracked/tracked_preference_histogram_names.cc
@@ -25,6 +25,7 @@ const char kTrackedPrefHistogramWantedReset[] =
const char kTrackedPrefHistogramReset[] = "Settings.TrackedPreferenceReset";
const char kTrackedSplitPrefHistogramChanged[] =
"Settings.TrackedSplitPreferenceChanged.";
+const char kTrackedPrefRegistryValidationSuffix[] = "FromRegistry";
} // namespace tracked
} // namespace user_prefs
diff --git a/chromium/components/user_prefs/tracked/tracked_preference_histogram_names.h b/chromium/components/user_prefs/tracked/tracked_preference_histogram_names.h
index c5a82a557b5..31b9ce30448 100644
--- a/chromium/components/user_prefs/tracked/tracked_preference_histogram_names.h
+++ b/chromium/components/user_prefs/tracked/tracked_preference_histogram_names.h
@@ -18,6 +18,7 @@ extern const char kTrackedPrefHistogramNullInitialized[];
extern const char kTrackedPrefHistogramWantedReset[];
extern const char kTrackedPrefHistogramReset[];
extern const char kTrackedSplitPrefHistogramChanged[];
+extern const char kTrackedPrefRegistryValidationSuffix[];
} // namespace tracked
} // namespace user_prefs
diff --git a/chromium/components/user_prefs/tracked/tracked_preference_validation_delegate.h b/chromium/components/user_prefs/tracked/tracked_preference_validation_delegate.h
index 8ea9c80a0a5..d010df5aee3 100644
--- a/chromium/components/user_prefs/tracked/tracked_preference_validation_delegate.h
+++ b/chromium/components/user_prefs/tracked/tracked_preference_validation_delegate.h
@@ -28,6 +28,7 @@ class TrackedPreferenceValidationDelegate {
const std::string& pref_path,
const base::Value* value,
PrefHashStoreTransaction::ValueState value_state,
+ PrefHashStoreTransaction::ValueState external_validation_value_state,
bool is_personal) = 0;
// Notifies observes of the result (|value_state|) of checking the split
@@ -37,7 +38,9 @@ class TrackedPreferenceValidationDelegate {
const std::string& pref_path,
const base::DictionaryValue* dict_value,
const std::vector<std::string>& invalid_keys,
+ const std::vector<std::string>& external_validation_invalid_keys,
PrefHashStoreTransaction::ValueState value_state,
+ PrefHashStoreTransaction::ValueState external_validation_value_state,
bool is_personal) = 0;
};
diff --git a/chromium/components/user_prefs/tracked/tracked_preferences_migration.cc b/chromium/components/user_prefs/tracked/tracked_preferences_migration.cc
index 0835a1450a0..50299141ed5 100644
--- a/chromium/components/user_prefs/tracked/tracked_preferences_migration.cc
+++ b/chromium/components/user_prefs/tracked/tracked_preferences_migration.cc
@@ -36,7 +36,6 @@ class TrackedPreferencesMigrator
register_on_successful_protected_store_write_callback,
std::unique_ptr<PrefHashStore> unprotected_pref_hash_store,
std::unique_ptr<PrefHashStore> protected_pref_hash_store,
- std::unique_ptr<HashStoreContents> legacy_pref_hash_store,
InterceptablePrefFilter* unprotected_pref_filter,
InterceptablePrefFilter* protected_pref_filter);
@@ -79,7 +78,6 @@ class TrackedPreferencesMigrator
std::unique_ptr<PrefHashStore> unprotected_pref_hash_store_;
std::unique_ptr<PrefHashStore> protected_pref_hash_store_;
- std::unique_ptr<HashStoreContents> legacy_pref_hash_store_;
std::unique_ptr<base::DictionaryValue> unprotected_prefs_;
std::unique_ptr<base::DictionaryValue> protected_prefs_;
@@ -122,10 +120,9 @@ void ScheduleSourcePrefStoreCleanup(
void CleanupMigratedHashes(const std::set<std::string>& migrated_pref_names,
PrefHashStore* origin_pref_hash_store,
base::DictionaryValue* origin_pref_store) {
+ DictionaryHashStoreContents dictionary_contents(origin_pref_store);
std::unique_ptr<PrefHashStoreTransaction> transaction(
- origin_pref_hash_store->BeginTransaction(
- std::unique_ptr<HashStoreContents>(
- new DictionaryHashStoreContents(origin_pref_store))));
+ origin_pref_hash_store->BeginTransaction(&dictionary_contents));
for (std::set<std::string>::const_iterator it = migrated_pref_names.begin();
it != migrated_pref_names.end();
++it) {
@@ -141,17 +138,13 @@ void MigratePrefsFromOldToNewStore(const std::set<std::string>& pref_names,
base::DictionaryValue* old_store,
base::DictionaryValue* new_store,
PrefHashStore* new_hash_store,
- HashStoreContents* legacy_hash_store,
bool* old_store_needs_cleanup,
- bool* new_store_altered,
- bool* used_legacy_pref_hashes) {
+ bool* new_store_altered) {
const base::DictionaryValue* old_hash_store_contents =
DictionaryHashStoreContents(old_store).GetContents();
- const base::DictionaryValue* legacy_hash_store_contents =
- legacy_hash_store->GetContents();
+ DictionaryHashStoreContents dictionary_contents(new_store);
std::unique_ptr<PrefHashStoreTransaction> new_hash_store_transaction(
- new_hash_store->BeginTransaction(std::unique_ptr<HashStoreContents>(
- new DictionaryHashStoreContents(new_store))));
+ new_hash_store->BeginTransaction(&dictionary_contents));
for (std::set<std::string>::const_iterator it = pref_names.begin();
it != pref_names.end();
@@ -186,11 +179,6 @@ void MigratePrefsFromOldToNewStore(const std::set<std::string>& pref_names,
const base::Value* old_hash = NULL;
if (old_hash_store_contents)
old_hash_store_contents->Get(pref_name, &old_hash);
- if (!old_hash && legacy_hash_store_contents) {
- legacy_hash_store_contents->Get(pref_name, &old_hash);
- if (old_hash)
- *used_legacy_pref_hashes = true;
- }
if (old_hash) {
new_hash_store_transaction->ImportHash(pref_name, old_hash);
*new_store_altered = true;
@@ -219,7 +207,6 @@ TrackedPreferencesMigrator::TrackedPreferencesMigrator(
register_on_successful_protected_store_write_callback,
std::unique_ptr<PrefHashStore> unprotected_pref_hash_store,
std::unique_ptr<PrefHashStore> protected_pref_hash_store,
- std::unique_ptr<HashStoreContents> legacy_pref_hash_store,
InterceptablePrefFilter* unprotected_pref_filter,
InterceptablePrefFilter* protected_pref_filter)
: unprotected_pref_names_(unprotected_pref_names),
@@ -231,8 +218,7 @@ TrackedPreferencesMigrator::TrackedPreferencesMigrator(
register_on_successful_protected_store_write_callback_(
register_on_successful_protected_store_write_callback),
unprotected_pref_hash_store_(std::move(unprotected_pref_hash_store)),
- protected_pref_hash_store_(std::move(protected_pref_hash_store)),
- legacy_pref_hash_store_(std::move(legacy_pref_hash_store)) {
+ protected_pref_hash_store_(std::move(protected_pref_hash_store)) {
// The callbacks bound below will own this TrackedPreferencesMigrator by
// reference.
unprotected_pref_filter->InterceptNextFilterOnLoad(
@@ -271,29 +257,18 @@ void TrackedPreferencesMigrator::MigrateIfReady() {
if (!protected_prefs_ || !unprotected_prefs_)
return;
- bool used_legacy_pref_hashes = false;
bool protected_prefs_need_cleanup = false;
bool unprotected_prefs_altered = false;
- MigratePrefsFromOldToNewStore(unprotected_pref_names_,
- protected_prefs_.get(),
- unprotected_prefs_.get(),
- unprotected_pref_hash_store_.get(),
- legacy_pref_hash_store_.get(),
- &protected_prefs_need_cleanup,
- &unprotected_prefs_altered,
- &used_legacy_pref_hashes);
+ MigratePrefsFromOldToNewStore(
+ unprotected_pref_names_, protected_prefs_.get(), unprotected_prefs_.get(),
+ unprotected_pref_hash_store_.get(), &protected_prefs_need_cleanup,
+ &unprotected_prefs_altered);
bool unprotected_prefs_need_cleanup = false;
bool protected_prefs_altered = false;
- MigratePrefsFromOldToNewStore(protected_pref_names_,
- unprotected_prefs_.get(),
- protected_prefs_.get(),
- protected_pref_hash_store_.get(),
- legacy_pref_hash_store_.get(),
- &unprotected_prefs_need_cleanup,
- &protected_prefs_altered,
- &used_legacy_pref_hashes);
- UMA_HISTOGRAM_BOOLEAN("Settings.MigratedHashesFromLocalState",
- used_legacy_pref_hashes);
+ MigratePrefsFromOldToNewStore(
+ protected_pref_names_, unprotected_prefs_.get(), protected_prefs_.get(),
+ protected_pref_hash_store_.get(), &unprotected_prefs_need_cleanup,
+ &protected_prefs_altered);
if (!unprotected_prefs_altered && !protected_prefs_altered) {
// Clean up any MACs that might have been previously migrated from the
@@ -308,7 +283,6 @@ void TrackedPreferencesMigrator::MigrateIfReady() {
CleanupMigratedHashes(protected_pref_names_,
unprotected_pref_hash_store_.get(),
unprotected_prefs_.get());
- legacy_pref_hash_store_->Reset();
}
// Hand the processed prefs back to their respective filters.
@@ -354,7 +328,6 @@ void SetupTrackedPreferencesMigration(
register_on_successful_protected_store_write_callback,
std::unique_ptr<PrefHashStore> unprotected_pref_hash_store,
std::unique_ptr<PrefHashStore> protected_pref_hash_store,
- std::unique_ptr<HashStoreContents> legacy_pref_hash_store,
InterceptablePrefFilter* unprotected_pref_filter,
InterceptablePrefFilter* protected_pref_filter) {
scoped_refptr<TrackedPreferencesMigrator> prefs_migrator(
@@ -364,7 +337,6 @@ void SetupTrackedPreferencesMigration(
register_on_successful_unprotected_store_write_callback,
register_on_successful_protected_store_write_callback,
std::move(unprotected_pref_hash_store),
- std::move(protected_pref_hash_store),
- std::move(legacy_pref_hash_store), unprotected_pref_filter,
+ std::move(protected_pref_hash_store), unprotected_pref_filter,
protected_pref_filter));
}
diff --git a/chromium/components/user_prefs/tracked/tracked_preferences_migration.h b/chromium/components/user_prefs/tracked/tracked_preferences_migration.h
index 3b5939228bb..3c96668a88d 100644
--- a/chromium/components/user_prefs/tracked/tracked_preferences_migration.h
+++ b/chromium/components/user_prefs/tracked/tracked_preferences_migration.h
@@ -23,12 +23,11 @@ class PrefHashStore;
// (un)protected_store_cleaner| and
// |register_on_successful_(un)protected_store_write_callback| are used to do
// post-migration cleanup tasks. Those should be bound to weak pointers to avoid
-// blocking shutdown. |(un)protected_pref_hash_store| and
-// |legacy_pref_hash_store| are used to migrate MACs along with their protected
-// preferences and/or from the legacy location in Local State. Migrated MACs
-// will only be cleared from their old location in a subsequent run. The
-// migration framework is resilient to a failed cleanup (it will simply try
-// again in the next Chrome run).
+// blocking shutdown. |(un)protected_pref_hash_store| is used to migrate MACs
+// along with their protected preferences. Migrated MACs will only be cleared
+// from their old location in a subsequent run. The migration framework is
+// resilient to a failed cleanup (it will simply try again in the next Chrome
+// run).
void SetupTrackedPreferencesMigration(
const std::set<std::string>& unprotected_pref_names,
const std::set<std::string>& protected_pref_names,
@@ -41,7 +40,6 @@ void SetupTrackedPreferencesMigration(
register_on_successful_protected_store_write_callback,
std::unique_ptr<PrefHashStore> unprotected_pref_hash_store,
std::unique_ptr<PrefHashStore> protected_pref_hash_store,
- std::unique_ptr<HashStoreContents> legacy_pref_hash_store,
InterceptablePrefFilter* unprotected_pref_filter,
InterceptablePrefFilter* protected_pref_filter);
diff --git a/chromium/components/user_prefs/tracked/tracked_preferences_migration_unittest.cc b/chromium/components/user_prefs/tracked/tracked_preferences_migration_unittest.cc
index 534ee21cd47..b1137543d3c 100644
--- a/chromium/components/user_prefs/tracked/tracked_preferences_migration_unittest.cc
+++ b/chromium/components/user_prefs/tracked/tracked_preferences_migration_unittest.cc
@@ -22,7 +22,6 @@
#include "components/user_prefs/tracked/pref_hash_store.h"
#include "components/user_prefs/tracked/pref_hash_store_impl.h"
#include "components/user_prefs/tracked/pref_hash_store_transaction.h"
-#include "components/user_prefs/tracked/pref_service_hash_store_contents.h"
#include "components/user_prefs/tracked/tracked_preferences_migration.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -48,9 +47,11 @@ class SimpleInterceptablePrefFilter : public InterceptablePrefFilter {
public:
// PrefFilter remaining implementation.
void FilterUpdate(const std::string& path) override { ADD_FAILURE(); }
- void FilterSerializeData(
+ OnWriteCallbackPair FilterSerializeData(
base::DictionaryValue* pref_store_contents) override {
ADD_FAILURE();
+ return std::make_pair(base::Closure(),
+ base::Callback<void(bool success)>());
}
private:
@@ -87,7 +88,6 @@ class TrackedPreferencesMigrationTest : public testing::Test {
protected_store_migration_complete_(false) {}
void SetUp() override {
- PrefServiceHashStoreContents::RegisterPrefs(local_state_.registry());
Reset();
}
@@ -123,9 +123,6 @@ class TrackedPreferencesMigrationTest : public testing::Test {
new PrefHashStoreImpl(kSeed, kDeviceId, false)),
std::unique_ptr<PrefHashStore>(
new PrefHashStoreImpl(kSeed, kDeviceId, true)),
- std::unique_ptr<HashStoreContents>(
- new PrefServiceHashStoreContents(kHashStoreId, &local_state_)),
-
&mock_unprotected_pref_filter_, &mock_protected_pref_filter_);
// Verify initial expectations are met.
@@ -147,16 +144,6 @@ class TrackedPreferencesMigrationTest : public testing::Test {
PresetStoreValueHash(store_id, key, value);
}
- // Sets |key| to |value| in the test store identified by |store_id| before
- // migration begins. Stores the value hash in Local State as in M36 and
- // earlier.
- void PresetLegacyStoreValue(MockPrefStoreID store_id,
- const std::string& key,
- const std::string value) {
- PresetStoreValueOnly(store_id, key, value);
- PresetLegacyValueHash(key, value);
- }
-
// Stores a hash for |key| and |value| in the hash store identified by
// |store_id| before migration begins.
void PresetStoreValueHash(MockPrefStoreID store_id,
@@ -177,24 +164,8 @@ class TrackedPreferencesMigrationTest : public testing::Test {
DCHECK(store);
base::StringValue string_value(value);
- pref_hash_store
- ->BeginTransaction(std::unique_ptr<HashStoreContents>(
- new DictionaryHashStoreContents(store)))
- ->StoreHash(key, &string_value);
- }
-
- // Stores a hash for |key| and |value| in the legacy hash store in
- // local_state.
- void PresetLegacyValueHash(const std::string& key,
- const std::string value) {
- std::unique_ptr<PrefHashStore> pref_hash_store(
- new PrefHashStoreImpl(kSeed, kDeviceId, true));
-
- base::StringValue string_value(value);
- PrefHashStoreImpl(kSeed, kDeviceId, true)
- .BeginTransaction(std::unique_ptr<HashStoreContents>(
- new PrefServiceHashStoreContents(kHashStoreId, &local_state_)))
- ->StoreHash(key, &string_value);
+ DictionaryHashStoreContents contents(store);
+ pref_hash_store->BeginTransaction(&contents)->StoreHash(key, &string_value);
}
// Returns true if the store opposite to |store_id| is observed for its next
@@ -255,16 +226,6 @@ class TrackedPreferencesMigrationTest : public testing::Test {
static_cast<std::string*>(NULL));
}
- // Determines whether |expected_pref_in_hash_store| has a hash in the Local
- // State hash store.
- bool ContainsLegacyHash(const std::string& expected_pref_in_hash_store) {
- const base::DictionaryValue* hash_store_contents =
- PrefServiceHashStoreContents(kHashStoreId, &local_state_).GetContents();
- return hash_store_contents &&
- hash_store_contents->GetString(expected_pref_in_hash_store,
- static_cast<std::string*>(NULL));
- }
-
// Both stores need to hand their prefs over in order for migration to kick
// in.
void HandPrefsToMigrator(MockPrefStoreID store_id) {
@@ -396,7 +357,6 @@ class TrackedPreferencesMigrationTest : public testing::Test {
store->SetString(key, value);
}
- static const char kHashStoreId[];
static const char kSeed[];
static const char kDeviceId[];
@@ -421,9 +381,6 @@ class TrackedPreferencesMigrationTest : public testing::Test {
};
// static
-const char TrackedPreferencesMigrationTest::kHashStoreId[] = "hash-store-id";
-
-// static
const char TrackedPreferencesMigrationTest::kSeed[] = "seed";
// static
@@ -482,208 +439,6 @@ TEST_F(TrackedPreferencesMigrationTest, NoMigrationRequired) {
EXPECT_FALSE(ContainsHash(MOCK_PROTECTED_PREF_STORE, kUnprotectedPref));
}
-TEST_F(TrackedPreferencesMigrationTest, LegacyHashMigrationOnly) {
- PresetLegacyStoreValue(
- MOCK_UNPROTECTED_PREF_STORE, kUnprotectedPref, kUnprotectedPrefValue);
- PresetLegacyStoreValue(
- MOCK_PROTECTED_PREF_STORE, kProtectedPref, kProtectedPrefValue);
-
- EXPECT_FALSE(ContainsHash(MOCK_UNPROTECTED_PREF_STORE, kUnprotectedPref));
- EXPECT_FALSE(ContainsHash(MOCK_UNPROTECTED_PREF_STORE, kProtectedPref));
-
- EXPECT_FALSE(ContainsHash(MOCK_PROTECTED_PREF_STORE, kProtectedPref));
- EXPECT_FALSE(ContainsHash(MOCK_PROTECTED_PREF_STORE, kUnprotectedPref));
-
- EXPECT_TRUE(ContainsLegacyHash(kProtectedPref));
- EXPECT_TRUE(ContainsLegacyHash(kUnprotectedPref));
-
- // Hand unprotected prefs to the migrator which should wait for the protected
- // prefs.
- HandPrefsToMigrator(MOCK_UNPROTECTED_PREF_STORE);
- EXPECT_FALSE(HasPrefs(MOCK_UNPROTECTED_PREF_STORE));
- EXPECT_TRUE(HasPrefs(MOCK_PROTECTED_PREF_STORE));
- EXPECT_FALSE(MigrationCompleted());
-
- // Hand protected prefs to the migrator which should proceed with the
- // migration synchronously.
- HandPrefsToMigrator(MOCK_PROTECTED_PREF_STORE);
- EXPECT_TRUE(MigrationCompleted());
-
- // Prefs should have been handed back over.
- EXPECT_TRUE(HasPrefs(MOCK_UNPROTECTED_PREF_STORE));
- EXPECT_TRUE(HasPrefs(MOCK_PROTECTED_PREF_STORE));
-
- // There is no pending cleanup task for the modern hash stores.
- EXPECT_FALSE(
- WasOnSuccessfulWriteCallbackRegistered(MOCK_UNPROTECTED_PREF_STORE));
- EXPECT_FALSE(
- WasOnSuccessfulWriteCallbackRegistered(MOCK_PROTECTED_PREF_STORE));
-
- // Both stores were modified as hashes were moved from Local State.
- EXPECT_TRUE(StoreModifiedByMigration(MOCK_UNPROTECTED_PREF_STORE));
- EXPECT_TRUE(StoreModifiedByMigration(MOCK_PROTECTED_PREF_STORE));
-
- base::StringPairs expected_unprotected_values;
- expected_unprotected_values.push_back(
- std::make_pair(kUnprotectedPref, kUnprotectedPrefValue));
- VerifyValuesStored(MOCK_UNPROTECTED_PREF_STORE, expected_unprotected_values);
-
- base::StringPairs expected_protected_values;
- expected_protected_values.push_back(
- std::make_pair(kProtectedPref, kProtectedPrefValue));
- VerifyValuesStored(MOCK_PROTECTED_PREF_STORE, expected_protected_values);
-
- EXPECT_TRUE(ContainsHash(MOCK_UNPROTECTED_PREF_STORE, kUnprotectedPref));
- EXPECT_FALSE(ContainsHash(MOCK_UNPROTECTED_PREF_STORE, kProtectedPref));
-
- EXPECT_TRUE(ContainsHash(MOCK_PROTECTED_PREF_STORE, kProtectedPref));
- EXPECT_FALSE(ContainsHash(MOCK_PROTECTED_PREF_STORE, kUnprotectedPref));
-
- // The Local State hash store will not be reset until the next run.
- EXPECT_TRUE(ContainsLegacyHash(kProtectedPref));
- EXPECT_TRUE(ContainsLegacyHash(kUnprotectedPref));
-
- Reset();
-
- HandPrefsToMigrator(MOCK_UNPROTECTED_PREF_STORE);
- HandPrefsToMigrator(MOCK_PROTECTED_PREF_STORE);
- EXPECT_TRUE(MigrationCompleted());
-
- // Neither store was modified.
- EXPECT_FALSE(StoreModifiedByMigration(MOCK_UNPROTECTED_PREF_STORE));
- EXPECT_FALSE(StoreModifiedByMigration(MOCK_PROTECTED_PREF_STORE));
-
- EXPECT_TRUE(ContainsHash(MOCK_UNPROTECTED_PREF_STORE, kUnprotectedPref));
- EXPECT_FALSE(ContainsHash(MOCK_UNPROTECTED_PREF_STORE, kProtectedPref));
-
- EXPECT_TRUE(ContainsHash(MOCK_PROTECTED_PREF_STORE, kProtectedPref));
- EXPECT_FALSE(ContainsHash(MOCK_PROTECTED_PREF_STORE, kUnprotectedPref));
-
- EXPECT_FALSE(ContainsLegacyHash(kProtectedPref));
- EXPECT_FALSE(ContainsLegacyHash(kUnprotectedPref));
-}
-
-TEST_F(TrackedPreferencesMigrationTest, FullMigrationWithLegacyHashStore) {
- // Store some values with matching MACs in Local State.
- PresetLegacyStoreValue(
- MOCK_UNPROTECTED_PREF_STORE, kUnprotectedPref, kUnprotectedPrefValue);
- PresetLegacyStoreValue(MOCK_UNPROTECTED_PREF_STORE,
- kPreviouslyUnprotectedPref,
- kPreviouslyUnprotectedPrefValue);
- PresetLegacyStoreValue(
- MOCK_PROTECTED_PREF_STORE, kProtectedPref, kProtectedPrefValue);
- PresetLegacyStoreValue(MOCK_PROTECTED_PREF_STORE,
- kPreviouslyProtectedPref,
- kPreviouslyProtectedPrefValue);
-
- // Verify that there are no MACs in Preferences or Secure Preferences.
- EXPECT_FALSE(ContainsHash(MOCK_UNPROTECTED_PREF_STORE, kUnprotectedPref));
- EXPECT_FALSE(
- ContainsHash(MOCK_UNPROTECTED_PREF_STORE, kPreviouslyUnprotectedPref));
- EXPECT_FALSE(ContainsHash(MOCK_UNPROTECTED_PREF_STORE, kProtectedPref));
- EXPECT_FALSE(
- ContainsHash(MOCK_UNPROTECTED_PREF_STORE, kPreviouslyProtectedPref));
-
- EXPECT_FALSE(ContainsHash(MOCK_PROTECTED_PREF_STORE, kUnprotectedPref));
- EXPECT_FALSE(
- ContainsHash(MOCK_PROTECTED_PREF_STORE, kPreviouslyUnprotectedPref));
- EXPECT_FALSE(ContainsHash(MOCK_PROTECTED_PREF_STORE, kProtectedPref));
- EXPECT_FALSE(
- ContainsHash(MOCK_PROTECTED_PREF_STORE, kPreviouslyProtectedPref));
-
- // Verify that there are MACs in Local State.
- EXPECT_TRUE(ContainsLegacyHash(kUnprotectedPref));
- EXPECT_TRUE(ContainsLegacyHash(kPreviouslyUnprotectedPref));
- EXPECT_TRUE(ContainsLegacyHash(kProtectedPref));
- EXPECT_TRUE(ContainsLegacyHash(kPreviouslyProtectedPref));
-
- // Perform a first-pass migration.
- HandPrefsToMigrator(MOCK_UNPROTECTED_PREF_STORE);
- HandPrefsToMigrator(MOCK_PROTECTED_PREF_STORE);
- EXPECT_TRUE(MigrationCompleted());
-
- // All values should have been moved to their preferred locations, including
- // MACs.
- base::StringPairs expected_unprotected_values;
- expected_unprotected_values.push_back(
- std::make_pair(kUnprotectedPref, kUnprotectedPrefValue));
- expected_unprotected_values.push_back(
- std::make_pair(kPreviouslyProtectedPref, kPreviouslyProtectedPrefValue));
- base::StringPairs expected_protected_values;
- expected_protected_values.push_back(
- std::make_pair(kProtectedPref, kProtectedPrefValue));
- expected_protected_values.push_back(std::make_pair(
- kPreviouslyUnprotectedPref, kPreviouslyUnprotectedPrefValue));
-
- VerifyValuesStored(MOCK_UNPROTECTED_PREF_STORE, expected_unprotected_values);
- VerifyValuesStored(MOCK_PROTECTED_PREF_STORE, expected_protected_values);
-
- EXPECT_TRUE(ContainsHash(MOCK_UNPROTECTED_PREF_STORE, kUnprotectedPref));
- EXPECT_TRUE(
- ContainsHash(MOCK_UNPROTECTED_PREF_STORE, kPreviouslyProtectedPref));
- EXPECT_TRUE(
- ContainsHash(MOCK_PROTECTED_PREF_STORE, kPreviouslyUnprotectedPref));
- EXPECT_TRUE(ContainsHash(MOCK_PROTECTED_PREF_STORE, kProtectedPref));
-
- EXPECT_FALSE(ContainsHash(MOCK_UNPROTECTED_PREF_STORE, kProtectedPref));
- EXPECT_FALSE(ContainsHash(MOCK_PROTECTED_PREF_STORE, kUnprotectedPref));
-
- EXPECT_FALSE(
- ContainsHash(MOCK_UNPROTECTED_PREF_STORE, kPreviouslyUnprotectedPref));
- EXPECT_FALSE(
- ContainsHash(MOCK_PROTECTED_PREF_STORE, kPreviouslyProtectedPref));
-
- // Removing the values from their previous locations is deferred until the new
- // locations are persisted.
- EXPECT_TRUE(ContainsLegacyHash(kUnprotectedPref));
- EXPECT_TRUE(ContainsLegacyHash(kPreviouslyUnprotectedPref));
- EXPECT_TRUE(ContainsLegacyHash(kProtectedPref));
- EXPECT_TRUE(ContainsLegacyHash(kPreviouslyProtectedPref));
-
- EXPECT_TRUE(
- WasOnSuccessfulWriteCallbackRegistered(MOCK_UNPROTECTED_PREF_STORE));
- EXPECT_TRUE(
- WasOnSuccessfulWriteCallbackRegistered(MOCK_PROTECTED_PREF_STORE));
-
- SimulateSuccessfulWrite(MOCK_UNPROTECTED_PREF_STORE);
- SimulateSuccessfulWrite(MOCK_PROTECTED_PREF_STORE);
-
- Reset();
-
- HandPrefsToMigrator(MOCK_UNPROTECTED_PREF_STORE);
- HandPrefsToMigrator(MOCK_PROTECTED_PREF_STORE);
- EXPECT_TRUE(MigrationCompleted());
-
- // In this run the MACs should have been removed from their previous
- // locations. There is no more pending action.
- EXPECT_FALSE(
- WasOnSuccessfulWriteCallbackRegistered(MOCK_UNPROTECTED_PREF_STORE));
- EXPECT_FALSE(
- WasOnSuccessfulWriteCallbackRegistered(MOCK_PROTECTED_PREF_STORE));
-
- EXPECT_TRUE(ContainsHash(MOCK_UNPROTECTED_PREF_STORE, kUnprotectedPref));
- EXPECT_FALSE(
- ContainsHash(MOCK_UNPROTECTED_PREF_STORE, kPreviouslyUnprotectedPref));
- EXPECT_FALSE(ContainsHash(MOCK_UNPROTECTED_PREF_STORE, kProtectedPref));
- EXPECT_TRUE(
- ContainsHash(MOCK_UNPROTECTED_PREF_STORE, kPreviouslyProtectedPref));
-
- EXPECT_FALSE(ContainsHash(MOCK_PROTECTED_PREF_STORE, kUnprotectedPref));
- EXPECT_TRUE(
- ContainsHash(MOCK_PROTECTED_PREF_STORE, kPreviouslyUnprotectedPref));
- EXPECT_TRUE(ContainsHash(MOCK_PROTECTED_PREF_STORE, kProtectedPref));
- EXPECT_FALSE(
- ContainsHash(MOCK_PROTECTED_PREF_STORE, kPreviouslyProtectedPref));
-
- EXPECT_FALSE(ContainsLegacyHash(kUnprotectedPref));
- EXPECT_FALSE(ContainsLegacyHash(kPreviouslyUnprotectedPref));
- EXPECT_FALSE(ContainsLegacyHash(kProtectedPref));
- EXPECT_FALSE(ContainsLegacyHash(kPreviouslyProtectedPref));
-
- VerifyValuesStored(MOCK_UNPROTECTED_PREF_STORE, expected_unprotected_values);
- VerifyValuesStored(MOCK_PROTECTED_PREF_STORE, expected_protected_values);
-}
-
TEST_F(TrackedPreferencesMigrationTest, FullMigration) {
PresetStoreValue(
MOCK_UNPROTECTED_PREF_STORE, kUnprotectedPref, kUnprotectedPrefValue);
diff --git a/chromium/components/user_prefs/tracked/tracked_split_preference.cc b/chromium/components/user_prefs/tracked/tracked_split_preference.cc
index 37bac10b760..2094d97b71e 100644
--- a/chromium/components/user_prefs/tracked/tracked_split_preference.cc
+++ b/chromium/components/user_prefs/tracked/tracked_split_preference.cc
@@ -27,6 +27,10 @@ TrackedSplitPreference::TrackedSplitPreference(
delegate_(delegate) {
}
+TrackedPreferenceType TrackedSplitPreference::GetType() const {
+ return TrackedPreferenceType::SPLIT;
+}
+
void TrackedSplitPreference::OnNewValue(
const base::Value* value,
PrefHashStoreTransaction* transaction) const {
@@ -40,7 +44,8 @@ void TrackedSplitPreference::OnNewValue(
bool TrackedSplitPreference::EnforceAndReport(
base::DictionaryValue* pref_store_contents,
- PrefHashStoreTransaction* transaction) const {
+ PrefHashStoreTransaction* transaction,
+ PrefHashStoreTransaction* external_validation_transaction) const {
base::DictionaryValue* dict_value = NULL;
if (!pref_store_contents->GetDictionary(pref_path_, &dict_value) &&
pref_store_contents->Get(pref_path_, NULL)) {
@@ -56,14 +61,27 @@ bool TrackedSplitPreference::EnforceAndReport(
if (value_state == PrefHashStoreTransaction::CHANGED)
helper_.ReportSplitPreferenceChangedCount(invalid_keys.size());
- helper_.ReportValidationResult(value_state);
+ helper_.ReportValidationResult(value_state, transaction->GetStoreUMASuffix());
+
+ PrefHashStoreTransaction::ValueState external_validation_value_state =
+ PrefHashStoreTransaction::UNSUPPORTED;
+ std::vector<std::string> external_validation_invalid_keys;
+ if (external_validation_transaction) {
+ external_validation_value_state =
+ external_validation_transaction->CheckSplitValue(
+ pref_path_, dict_value, &external_validation_invalid_keys);
+ helper_.ReportValidationResult(
+ external_validation_value_state,
+ external_validation_transaction->GetStoreUMASuffix());
+ }
- TrackedPreferenceHelper::ResetAction reset_action =
- helper_.GetAction(value_state);
if (delegate_) {
- delegate_->OnSplitPreferenceValidation(pref_path_, dict_value, invalid_keys,
- value_state, helper_.IsPersonal());
+ delegate_->OnSplitPreferenceValidation(
+ pref_path_, dict_value, invalid_keys, external_validation_invalid_keys,
+ value_state, external_validation_value_state, helper_.IsPersonal());
}
+ TrackedPreferenceHelper::ResetAction reset_action =
+ helper_.GetAction(value_state);
helper_.ReportAction(reset_action);
bool was_reset = false;
@@ -88,5 +106,16 @@ bool TrackedSplitPreference::EnforceAndReport(
transaction->StoreSplitHash(pref_path_, new_dict_value);
}
+ // Update MACs in the external store if there is one and there either was a
+ // reset or external validation failed.
+ if (external_validation_transaction &&
+ (was_reset ||
+ external_validation_value_state !=
+ PrefHashStoreTransaction::UNCHANGED)) {
+ const base::DictionaryValue* new_dict_value = nullptr;
+ pref_store_contents->GetDictionary(pref_path_, &new_dict_value);
+ external_validation_transaction->StoreSplitHash(pref_path_, new_dict_value);
+ }
+
return was_reset;
}
diff --git a/chromium/components/user_prefs/tracked/tracked_split_preference.h b/chromium/components/user_prefs/tracked/tracked_split_preference.h
index f2700a4ddab..359c8e1f570 100644
--- a/chromium/components/user_prefs/tracked/tracked_split_preference.h
+++ b/chromium/components/user_prefs/tracked/tracked_split_preference.h
@@ -33,10 +33,13 @@ class TrackedSplitPreference : public TrackedPreference {
TrackedPreferenceValidationDelegate* delegate);
// TrackedPreference implementation.
+ TrackedPreferenceType GetType() const override;
void OnNewValue(const base::Value* value,
PrefHashStoreTransaction* transaction) const override;
- bool EnforceAndReport(base::DictionaryValue* pref_store_contents,
- PrefHashStoreTransaction* transaction) const override;
+ bool EnforceAndReport(
+ base::DictionaryValue* pref_store_contents,
+ PrefHashStoreTransaction* transaction,
+ PrefHashStoreTransaction* external_validation_transaction) const override;
private:
const std::string pref_path_;