Index: chrome/browser/prefs/pref_hash_store_impl.cc |
diff --git a/chrome/browser/prefs/pref_hash_store_impl.cc b/chrome/browser/prefs/pref_hash_store_impl.cc |
index 096cbd9470b739d71403d929c9c5a1d745db16de..2f18adeef8f09e1362f781e997cf1ed3291678ac 100644 |
--- a/chrome/browser/prefs/pref_hash_store_impl.cc |
+++ b/chrome/browser/prefs/pref_hash_store_impl.cc |
@@ -10,23 +10,6 @@ |
#include "chrome/browser/prefs/pref_hash_store_transaction.h" |
#include "chrome/browser/prefs/tracked/hash_store_contents.h" |
-namespace { |
- |
-// Returns true if the dictionary of hashes stored in |contents| is trusted |
-// (which implies unknown values can be trusted as newly tracked values). |
-bool IsHashDictionaryTrusted(const PrefHashCalculator& calculator, |
- const HashStoreContents& contents) { |
- const base::DictionaryValue* store_contents = contents.GetContents(); |
- std::string super_mac = contents.GetSuperMac(); |
- // The store must be initialized and have a valid super MAC to be trusted. |
- return store_contents && !super_mac.empty() && |
- calculator.Validate(contents.hash_store_id(), |
- store_contents, |
- super_mac) == PrefHashCalculator::VALID; |
-} |
- |
-} // namespace |
- |
class PrefHashStoreImpl::PrefHashStoreTransactionImpl |
: public PrefHashStoreTransaction { |
public: |
@@ -40,6 +23,12 @@ class PrefHashStoreImpl::PrefHashStoreTransactionImpl |
const base::Value* value) const OVERRIDE; |
virtual void StoreHash(const std::string& path, |
const base::Value* value) OVERRIDE; |
+ virtual const base::Value* GetHash(const std::string& path) const OVERRIDE; |
+ virtual void ImportHash(const std::string& path, |
+ const base::Value* hash) OVERRIDE; |
+ virtual void ClearHash(const std::string& path) OVERRIDE; |
+ virtual bool StampSuperMac() OVERRIDE; |
+ |
virtual ValueState CheckSplitValue( |
const std::string& path, |
const base::DictionaryValue* initial_split_value, |
@@ -53,47 +42,43 @@ class PrefHashStoreImpl::PrefHashStoreTransactionImpl |
std::map<std::string, std::string>* split_macs) const; |
PrefHashStoreImpl* outer_; |
bool has_changed_; |
+ bool super_mac_dirty_; |
DISALLOW_COPY_AND_ASSIGN(PrefHashStoreTransactionImpl); |
}; |
PrefHashStoreImpl::PrefHashStoreImpl(const std::string& seed, |
const std::string& device_id, |
- scoped_ptr<HashStoreContents> contents) |
+ bool use_super_mac) |
: pref_hash_calculator_(seed, device_id), |
- contents_(contents.Pass()), |
- initial_hashes_dictionary_trusted_( |
- IsHashDictionaryTrusted(pref_hash_calculator_, *contents_)), |
+ use_super_mac_(use_super_mac), |
+ checked_super_mac_(false), |
+ initial_hashes_dictionary_trusted_(false), |
has_pending_write_(false) { |
- DCHECK(contents_); |
- UMA_HISTOGRAM_BOOLEAN("Settings.HashesDictionaryTrusted", |
- initial_hashes_dictionary_trusted_); |
} |
PrefHashStoreImpl::~PrefHashStoreImpl() {} |
+void PrefHashStoreImpl::SetHashStoreContents( |
+ scoped_ptr<HashStoreContents> contents) { |
+ contents_ = contents.Pass(); |
+ |
+} |
+ |
+bool PrefHashStoreImpl::IsInitialized() const { |
+ return contents_->IsInitialized(); |
+} |
+ |
void PrefHashStoreImpl::Reset() { |
contents_->Reset(); |
} |
scoped_ptr<PrefHashStoreTransaction> PrefHashStoreImpl::BeginTransaction() { |
+ CheckSuperMac(); |
return scoped_ptr<PrefHashStoreTransaction>( |
new PrefHashStoreTransactionImpl(this)); |
} |
-PrefHashStoreImpl::StoreVersion PrefHashStoreImpl::GetCurrentVersion() const { |
- if (!contents_->IsInitialized()) |
- return VERSION_UNINITIALIZED; |
- |
- int current_version; |
- if (!contents_->GetVersion(¤t_version)) { |
- return VERSION_PRE_MIGRATION; |
- } |
- |
- DCHECK_GT(current_version, VERSION_PRE_MIGRATION); |
- return static_cast<StoreVersion>(current_version); |
-} |
- |
void PrefHashStoreImpl::CommitPendingWrite() { |
if (has_pending_write_) { |
contents_->CommitPendingWrite(); |
@@ -101,36 +86,58 @@ void PrefHashStoreImpl::CommitPendingWrite() { |
} |
} |
+bool PrefHashStoreImpl::CheckSuperMac() { |
+ if (checked_super_mac_ || !use_super_mac_) |
+ return initial_hashes_dictionary_trusted_; |
+ |
+ const base::DictionaryValue* store_contents = contents_->GetContents(); |
+ std::string super_mac = contents_->GetSuperMac(); |
+ // The store must be initialized and have a valid super MAC to be trusted. |
+ initial_hashes_dictionary_trusted_ = |
+ store_contents && !super_mac.empty() && |
+ pref_hash_calculator_.Validate(contents_->hash_store_id(), |
+ store_contents, |
+ super_mac) == PrefHashCalculator::VALID; |
+ |
+ checked_super_mac_ = true; |
+ |
+ UMA_HISTOGRAM_BOOLEAN("Settings.HashesDictionaryTrusted", |
+ initial_hashes_dictionary_trusted_); |
+ |
+ return initial_hashes_dictionary_trusted_; |
+} |
+ |
PrefHashStoreImpl::PrefHashStoreTransactionImpl::PrefHashStoreTransactionImpl( |
- PrefHashStoreImpl* outer) : outer_(outer), has_changed_(false) { |
+ PrefHashStoreImpl* outer) |
+ : outer_(outer), has_changed_(false), super_mac_dirty_(false) { |
} |
PrefHashStoreImpl::PrefHashStoreTransactionImpl:: |
~PrefHashStoreTransactionImpl() { |
- // Update the super MAC if and only if the hashes dictionary has been |
- // modified in this transaction. |
if (has_changed_) { |
- // Get the dictionary of hashes (or NULL if it doesn't exist). |
- const base::DictionaryValue* hashes_dict = outer_->contents_->GetContents(); |
- outer_->contents_->SetSuperMac(outer_->pref_hash_calculator_.Calculate( |
- outer_->contents_->hash_store_id(), hashes_dict)); |
+ // Update the super MAC if and only if the hashes dictionary has been |
+ // modified in this transaction. Imports do not necessarily affect the super |
+ // MAC (will not transition it from invalid to valid). |
+ if (outer_->use_super_mac_ && super_mac_dirty_) { |
+ // Get the dictionary of hashes (or NULL if it doesn't exist). |
+ const base::DictionaryValue* hashes_dict = |
+ outer_->contents_->GetContents(); |
+ outer_->contents_->SetSuperMac(outer_->pref_hash_calculator_.Calculate( |
+ outer_->contents_->hash_store_id(), hashes_dict)); |
+ } |
outer_->has_pending_write_ = true; |
} |
+} |
- // Mark this hash store has having been updated to the latest version (in |
- // practice only initialization transactions will actually do this, but |
- // since they always occur before minor update transaction it's okay |
- // to unconditionally do this here). Only do this if this store's version |
- // isn't already at VERSION_LATEST (to avoid scheduling a write when |
- // unecessary). Note, this is outside of |if (has_changed)| to also seed |
- // version number of otherwise unchanged profiles. |
- int current_version; |
- if (!outer_->contents_->GetVersion(¤t_version) || |
- current_version != VERSION_LATEST) { |
- outer_->contents_->SetVersion(VERSION_LATEST); |
- outer_->has_pending_write_ = true; |
- } |
+const base::Value* PrefHashStoreImpl::PrefHashStoreTransactionImpl::GetHash( |
+ const std::string& path) const { |
+ const base::DictionaryValue* hashed_prefs = outer_->contents_->GetContents(); |
+ |
+ const base::Value* last_hash = NULL; |
+ if (hashed_prefs) |
+ hashed_prefs->Get(path, &last_hash); |
+ return last_hash; |
} |
PrefHashStoreTransaction::ValueState |
@@ -172,6 +179,35 @@ void PrefHashStoreImpl::PrefHashStoreTransactionImpl::StoreHash( |
outer_->pref_hash_calculator_.Calculate(path, new_value); |
(*outer_->contents_->GetMutableContents())->SetString(path, mac); |
has_changed_ = true; |
+ super_mac_dirty_ = true; |
+} |
+ |
+void PrefHashStoreImpl::PrefHashStoreTransactionImpl::ImportHash( |
+ const std::string& path, |
+ const base::Value* hash) { |
+ if (!hash) |
+ (*outer_->contents_->GetMutableContents())->RemovePath(path, NULL); |
+ else |
+ (*outer_->contents_->GetMutableContents())->Set(path, hash->DeepCopy()); |
+ has_changed_ = true; |
+ super_mac_dirty_ = |
+ super_mac_dirty_ || outer_->initial_hashes_dictionary_trusted_; |
+} |
+ |
+void PrefHashStoreImpl::PrefHashStoreTransactionImpl::ClearHash( |
+ const std::string& path) { |
+ (*outer_->contents_->GetMutableContents())->RemovePath(path, NULL); |
+ has_changed_ = true; |
+ super_mac_dirty_ = |
+ super_mac_dirty_ || outer_->initial_hashes_dictionary_trusted_; |
+} |
+ |
+bool PrefHashStoreImpl::PrefHashStoreTransactionImpl::StampSuperMac() { |
+ if (!outer_->use_super_mac_ || outer_->initial_hashes_dictionary_trusted_) |
+ return false; |
+ has_changed_ = true; |
+ super_mac_dirty_ = true; |
+ return true; |
} |
PrefHashStoreTransaction::ValueState |
@@ -272,6 +308,7 @@ void PrefHashStoreImpl::PrefHashStoreTransactionImpl::StoreSplitHash( |
} |
} |
has_changed_ = true; |
+ super_mac_dirty_ = true; |
} |
bool PrefHashStoreImpl::PrefHashStoreTransactionImpl::GetSplitMacs( |