Index: net/sdch/sdch_owner.cc |
diff --git a/net/sdch/sdch_owner.cc b/net/sdch/sdch_owner.cc |
index bfb2dd91b65f0a81d85ee57653c375231b4e097a..03e268e1343ddd2f2d0e456e9fadc1270222d5b7 100644 |
--- a/net/sdch/sdch_owner.cc |
+++ b/net/sdch/sdch_owner.cc |
@@ -11,8 +11,6 @@ |
#include "base/logging.h" |
#include "base/macros.h" |
#include "base/metrics/histogram_macros.h" |
-#include "base/prefs/persistent_pref_store.h" |
-#include "base/prefs/value_map_pref_store.h" |
#include "base/strings/string_util.h" |
#include "base/time/default_clock.h" |
#include "base/values.h" |
@@ -23,19 +21,6 @@ namespace net { |
namespace { |
-enum PersistenceFailureReason { |
- // File didn't exist; is being created. |
- PERSISTENCE_FAILURE_REASON_NO_FILE = 1, |
- |
- // Error reading in information, but should be able to write. |
- PERSISTENCE_FAILURE_REASON_READ_FAILED = 2, |
- |
- // Error leading to abort on attempted persistence. |
- PERSISTENCE_FAILURE_REASON_WRITE_FAILED = 3, |
- |
- PERSISTENCE_FAILURE_REASON_MAX = 4 |
-}; |
- |
// Dictionaries that haven't been touched in 24 hours may be evicted |
// to make room for new dictionaries. |
const int kFreshnessLifetimeHours = 24; |
@@ -43,9 +28,11 @@ const int kFreshnessLifetimeHours = 24; |
// Dictionaries that have never been used only stay fresh for one hour. |
const int kNeverUsedFreshnessLifetimeHours = 1; |
-void RecordPersistenceFailure(PersistenceFailureReason failure_reason) { |
- UMA_HISTOGRAM_ENUMERATION("Sdch3.PersistenceFailureReason", failure_reason, |
- PERSISTENCE_FAILURE_REASON_MAX); |
+void RecordPersistenceFailure( |
+ SdchOwner::PrefStorage::ReadError failure_reason) { |
+ UMA_HISTOGRAM_ENUMERATION( |
+ "Sdch3.PersistenceFailureReason", failure_reason, |
+ SdchOwner::PrefStorage::PERSISTENCE_FAILURE_REASON_MAX); |
} |
// Schema specifications and access routines. |
@@ -54,7 +41,7 @@ void RecordPersistenceFailure(PersistenceFailureReason failure_reason) { |
// stack systems that want to persist data over browser restarts, and so |
// use of it must be namespace restricted. |
// Schema: |
-// pref_store_->GetValue(kPreferenceName) -> Dictionary { |
+// pref_store_->GetValue() -> Dictionary { |
// 'version' -> 2 [int] |
// 'dictionaries' -> Dictionary { |
// server_hash -> { |
@@ -65,7 +52,6 @@ void RecordPersistenceFailure(PersistenceFailureReason failure_reason) { |
// 'size' -> size [int] |
// } |
// } |
-const char kPreferenceName[] = "SDCH"; |
const char kVersionKey[] = "version"; |
const char kDictionariesKey[] = "dictionaries"; |
const char kDictionaryUrlKey[] = "url"; |
@@ -76,19 +62,49 @@ const char kDictionarySizeKey[] = "size"; |
const int kVersion = 2; |
+// A simple implementation of pref storage that just stores the value in |
+// memory. |
+class ValueMapPrefStorage : public SdchOwner::PrefStorage { |
+ public: |
+ ValueMapPrefStorage() {} |
+ ~ValueMapPrefStorage() override {} |
+ |
+ ReadError GetReadError() const override { return PERSISTENCE_FAILURE_NONE; } |
+ |
+ bool GetValue(const base::DictionaryValue** result) const override { |
+ *result = &storage_; |
+ return true; |
+ } |
+ bool GetMutableValue(base::DictionaryValue** result) override { |
+ *result = &storage_; |
+ return true; |
+ } |
+ void SetValue(scoped_ptr<base::DictionaryValue> value) override { |
+ storage_.Clear(); |
+ storage_.MergeDictionary(value.get()); |
+ } |
+ |
+ void ReportValueChanged() override {} |
+ |
+ // This storage class requires no special initialization. |
+ bool IsInitializationComplete() override { return true; } |
+ void StartObservingInit(SdchOwner* observer) override {} |
+ void StopObservingInit() override {} |
+ |
+ private: |
+ base::DictionaryValue storage_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ValueMapPrefStorage); |
+}; |
+ |
// This function returns store[kPreferenceName/kDictionariesKey]. The caller |
// is responsible for making sure any needed calls to |
// |store->ReportValueChanged()| occur. |
base::DictionaryValue* GetPersistentStoreDictionaryMap( |
- WriteablePrefStore* store) { |
- base::Value* result = nullptr; |
- bool success = store->GetMutableValue(kPreferenceName, &result); |
- DCHECK(success); |
- |
+ SdchOwner::PrefStorage* store) { |
base::DictionaryValue* preference_dictionary = nullptr; |
- success = result->GetAsDictionary(&preference_dictionary); |
+ bool success = store->GetMutableValue(&preference_dictionary); |
DCHECK(success); |
- DCHECK(preference_dictionary); |
base::DictionaryValue* dictionary_list_dictionary = nullptr; |
success = preference_dictionary->GetDictionary(kDictionariesKey, |
@@ -102,13 +118,12 @@ base::DictionaryValue* GetPersistentStoreDictionaryMap( |
// This function initializes a pref store with an empty version of the |
// above schema, removing anything previously in the store under |
// kPreferenceName. |
-void InitializePrefStore(WriteablePrefStore* store) { |
+void InitializePrefStore(SdchOwner::PrefStorage* store) { |
scoped_ptr<base::DictionaryValue> empty_store(new base::DictionaryValue); |
empty_store->SetInteger(kVersionKey, kVersion); |
empty_store->Set(kDictionariesKey, |
make_scoped_ptr(new base::DictionaryValue)); |
- store->SetValue(kPreferenceName, std::move(empty_store), |
- WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); |
+ store->SetValue(std::move(empty_store)); |
} |
// A class to allow iteration over all dictionaries in the pref store, and |
@@ -122,7 +137,7 @@ void InitializePrefStore(WriteablePrefStore* store) { |
// pref store schema. |
class DictionaryPreferenceIterator { |
public: |
- explicit DictionaryPreferenceIterator(WriteablePrefStore* pref_store); |
+ explicit DictionaryPreferenceIterator(SdchOwner::PrefStorage* pref_store); |
bool IsAtEnd() const; |
void Advance(); |
@@ -152,7 +167,7 @@ class DictionaryPreferenceIterator { |
}; |
DictionaryPreferenceIterator::DictionaryPreferenceIterator( |
- WriteablePrefStore* pref_store) |
+ SdchOwner::PrefStorage* pref_store) |
: use_count_(0), |
size_(0), |
dictionary_iterator_(*GetPersistentStoreDictionaryMap(pref_store)) { |
@@ -215,21 +230,19 @@ bool DictionaryPreferenceIterator::TryLoadDictionary() { |
return true; |
} |
-// Triggers a ReportValueChanged() on the specified WriteablePrefStore |
-// when the object goes out of scope. |
+// Triggers a ReportValueChanged() when the object goes out of scope. |
class ScopedPrefNotifier { |
public: |
// Caller must guarantee lifetime of |*pref_store| exceeds the |
// lifetime of this object. |
- ScopedPrefNotifier(WriteablePrefStore* pref_store) |
- : pref_store_(pref_store) {} |
- ~ScopedPrefNotifier() { |
- pref_store_->ReportValueChanged( |
- kPreferenceName, WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); |
+ ScopedPrefNotifier(SdchOwner::PrefStorage* pref_store) |
+ : pref_store_(pref_store) { |
+ DCHECK(pref_store); |
} |
+ ~ScopedPrefNotifier() { pref_store_->ReportValueChanged(); } |
private: |
- WriteablePrefStore* pref_store_; |
+ SdchOwner::PrefStorage* pref_store_; |
DISALLOW_COPY_AND_ASSIGN(ScopedPrefNotifier); |
}; |
@@ -245,6 +258,8 @@ const size_t SdchOwner::kMaxTotalDictionarySize = 2 * 500 * 1000; |
const size_t SdchOwner::kMaxTotalDictionarySize = 20 * 1000 * 1000; |
#endif |
+SdchOwner::PrefStorage::~PrefStorage() {} |
+ |
// Somewhat arbitrary, but we assume a dictionary smaller than |
// 50K isn't going to do anyone any good. Note that this still doesn't |
// prevent download and addition unless there is less than this |
@@ -287,7 +302,7 @@ SdchOwner::SdchOwner(SdchManager* sdch_manager, URLRequestContext* context) |
// SdchOwner, the SdchOwner object will be available |
// for the lifetime of |memory_pressure_listener_|. |
base::Unretained(this))), |
- in_memory_pref_store_(new ValueMapPrefStore()), |
+ in_memory_pref_store_(new ValueMapPrefStorage()), |
external_pref_store_(nullptr), |
pref_store_(in_memory_pref_store_.get()), |
creation_time_(clock_->Now()) { |
@@ -309,8 +324,8 @@ SdchOwner::~SdchOwner() { |
// This object only observes the external store during loading, |
// i.e. before it's made the default preferences store. |
- if (external_pref_store_) |
- external_pref_store_->RemoveObserver(this); |
+ if (external_pref_store_ && pref_store_ != external_pref_store_.get()) |
+ external_pref_store_->StopObservingInit(); |
int64_t object_lifetime = (clock_->Now() - creation_time_).InMilliseconds(); |
for (const auto& val : consumed_byte_seconds_) { |
@@ -321,16 +336,16 @@ SdchOwner::~SdchOwner() { |
val / object_lifetime); |
} |
} |
- |
} |
-void SdchOwner::EnablePersistentStorage(PersistentPrefStore* pref_store) { |
+void SdchOwner::EnablePersistentStorage(scoped_ptr<PrefStorage> pref_store) { |
DCHECK(!external_pref_store_); |
- external_pref_store_ = pref_store; |
- external_pref_store_->AddObserver(this); |
+ DCHECK(pref_store); |
+ external_pref_store_ = std::move(pref_store); |
+ external_pref_store_->StartObservingInit(this); |
if (external_pref_store_->IsInitializationComplete()) |
- OnInitializationCompleted(true); |
+ OnPrefStorageInitializationComplete(true); |
} |
void SdchOwner::SetMaxTotalDictionarySize(size_t max_total_dictionary_size) { |
@@ -581,12 +596,8 @@ void SdchOwner::OnClearDictionaries() { |
InitializePrefStore(pref_store_); |
} |
-void SdchOwner::OnPrefValueChanged(const std::string& key) { |
-} |
- |
-void SdchOwner::OnInitializationCompleted(bool succeeded) { |
- PersistentPrefStore::PrefReadError error = |
- external_pref_store_->GetReadError(); |
+void SdchOwner::OnPrefStorageInitializationComplete(bool succeeded) { |
+ PrefStorage::ReadError error = external_pref_store_->GetReadError(); |
// Errors on load are self-correcting; if dictionaries were not |
// persisted from the last instance of the browser, they will be |
// faulted in by user action over time. However, if a load error |
@@ -594,73 +605,38 @@ void SdchOwner::OnInitializationCompleted(bool succeeded) { |
// the in memory pref store is left in place. |
if (!succeeded) { |
// Failure means a write failed, since read failures are recoverable. |
- DCHECK_NE( |
- error, |
- PersistentPrefStore::PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE); |
- DCHECK_NE(error, |
- PersistentPrefStore::PREF_READ_ERROR_MAX_ENUM); |
- |
- LOG(ERROR) << "Pref store write failed: " << error; |
- external_pref_store_->RemoveObserver(this); |
+ external_pref_store_->StopObservingInit(); |
external_pref_store_ = nullptr; |
- RecordPersistenceFailure(PERSISTENCE_FAILURE_REASON_WRITE_FAILED); |
+ RecordPersistenceFailure( |
+ PrefStorage::PERSISTENCE_FAILURE_REASON_WRITE_FAILED); |
return; |
} |
- switch (external_pref_store_->GetReadError()) { |
- case PersistentPrefStore::PREF_READ_ERROR_NONE: |
- break; |
- |
- case PersistentPrefStore::PREF_READ_ERROR_NO_FILE: |
- // First time reading; the file will be created. |
- RecordPersistenceFailure(PERSISTENCE_FAILURE_REASON_NO_FILE); |
- break; |
- |
- case PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE: |
- case PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE: |
- case PersistentPrefStore::PREF_READ_ERROR_FILE_OTHER: |
- case PersistentPrefStore::PREF_READ_ERROR_FILE_LOCKED: |
- case PersistentPrefStore::PREF_READ_ERROR_JSON_REPEAT: |
- RecordPersistenceFailure(PERSISTENCE_FAILURE_REASON_READ_FAILED); |
- break; |
- |
- case PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED: |
- case PersistentPrefStore::PREF_READ_ERROR_FILE_NOT_SPECIFIED: |
- case PersistentPrefStore::PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE: |
- case PersistentPrefStore::PREF_READ_ERROR_MAX_ENUM: |
- // Shouldn't ever happen. ACCESS_DENIED and FILE_NOT_SPECIFIED should |
- // imply !succeeded, and TASK_INCOMPLETE should never be delivered. |
- NOTREACHED(); |
- break; |
- } |
+ if (error != PrefStorage::PERSISTENCE_FAILURE_NONE) |
+ RecordPersistenceFailure(error); |
// Load in what was stored before chrome exited previously. |
- const base::Value* sdch_persistence_value = nullptr; |
const base::DictionaryValue* sdch_persistence_dictionary = nullptr; |
// The GetPersistentStore() routine above assumes data formatted |
// according to the schema described at the top of this file. Since |
// this data comes from disk, to avoid disk corruption resulting in |
// persistent chrome errors this code avoids those assupmtions. |
- if (external_pref_store_->GetValue(kPreferenceName, |
- &sdch_persistence_value) && |
- sdch_persistence_value->GetAsDictionary(&sdch_persistence_dictionary)) { |
+ if (external_pref_store_->GetValue(&sdch_persistence_dictionary)) |
SchedulePersistedDictionaryLoads(*sdch_persistence_dictionary); |
- } |
// Reset the persistent store and update it with the accumulated |
// information from the local store. |
- InitializePrefStore(external_pref_store_); |
+ InitializePrefStore(external_pref_store_.get()); |
- ScopedPrefNotifier scoped_pref_notifier(external_pref_store_); |
- GetPersistentStoreDictionaryMap(external_pref_store_) |
+ ScopedPrefNotifier scoped_pref_notifier(external_pref_store_.get()); |
+ GetPersistentStoreDictionaryMap(external_pref_store_.get()) |
->Swap(GetPersistentStoreDictionaryMap(in_memory_pref_store_.get())); |
// This object can stop waiting on (i.e. observing) the external preference |
// store and switch over to using it as the primary preference store. |
- pref_store_ = external_pref_store_; |
- external_pref_store_->RemoveObserver(this); |
- external_pref_store_ = nullptr; |
+ pref_store_ = external_pref_store_.get(); |
+ external_pref_store_->StopObservingInit(); |
in_memory_pref_store_ = nullptr; |
} |