| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/sdch/sdch_owner.h" | 5 #include "net/sdch/sdch_owner.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/debug/alias.h" | 10 #include "base/debug/alias.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/macros.h" | 12 #include "base/macros.h" |
| 13 #include "base/metrics/histogram_macros.h" | 13 #include "base/metrics/histogram_macros.h" |
| 14 #include "base/prefs/persistent_pref_store.h" | |
| 15 #include "base/prefs/value_map_pref_store.h" | |
| 16 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
| 17 #include "base/time/default_clock.h" | 15 #include "base/time/default_clock.h" |
| 18 #include "base/values.h" | 16 #include "base/values.h" |
| 19 #include "net/base/sdch_manager.h" | 17 #include "net/base/sdch_manager.h" |
| 20 #include "net/base/sdch_net_log_params.h" | 18 #include "net/base/sdch_net_log_params.h" |
| 21 | 19 |
| 22 namespace net { | 20 namespace net { |
| 23 | 21 |
| 24 namespace { | 22 namespace { |
| 25 | 23 |
| 26 enum PersistenceFailureReason { | |
| 27 // File didn't exist; is being created. | |
| 28 PERSISTENCE_FAILURE_REASON_NO_FILE = 1, | |
| 29 | |
| 30 // Error reading in information, but should be able to write. | |
| 31 PERSISTENCE_FAILURE_REASON_READ_FAILED = 2, | |
| 32 | |
| 33 // Error leading to abort on attempted persistence. | |
| 34 PERSISTENCE_FAILURE_REASON_WRITE_FAILED = 3, | |
| 35 | |
| 36 PERSISTENCE_FAILURE_REASON_MAX = 4 | |
| 37 }; | |
| 38 | |
| 39 // Dictionaries that haven't been touched in 24 hours may be evicted | 24 // Dictionaries that haven't been touched in 24 hours may be evicted |
| 40 // to make room for new dictionaries. | 25 // to make room for new dictionaries. |
| 41 const int kFreshnessLifetimeHours = 24; | 26 const int kFreshnessLifetimeHours = 24; |
| 42 | 27 |
| 43 // Dictionaries that have never been used only stay fresh for one hour. | 28 // Dictionaries that have never been used only stay fresh for one hour. |
| 44 const int kNeverUsedFreshnessLifetimeHours = 1; | 29 const int kNeverUsedFreshnessLifetimeHours = 1; |
| 45 | 30 |
| 46 void RecordPersistenceFailure(PersistenceFailureReason failure_reason) { | 31 void RecordPersistenceFailure( |
| 47 UMA_HISTOGRAM_ENUMERATION("Sdch3.PersistenceFailureReason", failure_reason, | 32 SdchOwner::PrefStorage::ReadError failure_reason) { |
| 48 PERSISTENCE_FAILURE_REASON_MAX); | 33 UMA_HISTOGRAM_ENUMERATION( |
| 34 "Sdch3.PersistenceFailureReason", failure_reason, |
| 35 SdchOwner::PrefStorage::PERSISTENCE_FAILURE_REASON_MAX); |
| 49 } | 36 } |
| 50 | 37 |
| 51 // Schema specifications and access routines. | 38 // Schema specifications and access routines. |
| 52 | 39 |
| 53 // The persistent prefs store is conceptually shared with any other network | 40 // The persistent prefs store is conceptually shared with any other network |
| 54 // stack systems that want to persist data over browser restarts, and so | 41 // stack systems that want to persist data over browser restarts, and so |
| 55 // use of it must be namespace restricted. | 42 // use of it must be namespace restricted. |
| 56 // Schema: | 43 // Schema: |
| 57 // pref_store_->GetValue(kPreferenceName) -> Dictionary { | 44 // pref_store_->GetValue() -> Dictionary { |
| 58 // 'version' -> 2 [int] | 45 // 'version' -> 2 [int] |
| 59 // 'dictionaries' -> Dictionary { | 46 // 'dictionaries' -> Dictionary { |
| 60 // server_hash -> { | 47 // server_hash -> { |
| 61 // 'url' -> URL [string] | 48 // 'url' -> URL [string] |
| 62 // 'last_used' -> seconds since unix epoch [double] | 49 // 'last_used' -> seconds since unix epoch [double] |
| 63 // 'created_time' -> seconds since unix epoch [double] | 50 // 'created_time' -> seconds since unix epoch [double] |
| 64 // 'use_count' -> use count [int] | 51 // 'use_count' -> use count [int] |
| 65 // 'size' -> size [int] | 52 // 'size' -> size [int] |
| 66 // } | 53 // } |
| 67 // } | 54 // } |
| 68 const char kPreferenceName[] = "SDCH"; | |
| 69 const char kVersionKey[] = "version"; | 55 const char kVersionKey[] = "version"; |
| 70 const char kDictionariesKey[] = "dictionaries"; | 56 const char kDictionariesKey[] = "dictionaries"; |
| 71 const char kDictionaryUrlKey[] = "url"; | 57 const char kDictionaryUrlKey[] = "url"; |
| 72 const char kDictionaryLastUsedKey[] = "last_used"; | 58 const char kDictionaryLastUsedKey[] = "last_used"; |
| 73 const char kDictionaryCreatedTimeKey[] = "created_time"; | 59 const char kDictionaryCreatedTimeKey[] = "created_time"; |
| 74 const char kDictionaryUseCountKey[] = "use_count"; | 60 const char kDictionaryUseCountKey[] = "use_count"; |
| 75 const char kDictionarySizeKey[] = "size"; | 61 const char kDictionarySizeKey[] = "size"; |
| 76 | 62 |
| 77 const int kVersion = 2; | 63 const int kVersion = 2; |
| 78 | 64 |
| 65 // A simple implementation of pref storage that just stores the value in |
| 66 // memory. |
| 67 class ValueMapPrefStorage : public SdchOwner::PrefStorage { |
| 68 public: |
| 69 ValueMapPrefStorage() {} |
| 70 ~ValueMapPrefStorage() override {} |
| 71 |
| 72 ReadError GetReadError() const override { return PERSISTENCE_FAILURE_NONE; } |
| 73 |
| 74 bool GetValue(const base::DictionaryValue** result) const override { |
| 75 *result = &storage_; |
| 76 return true; |
| 77 } |
| 78 bool GetMutableValue(base::DictionaryValue** result) override { |
| 79 *result = &storage_; |
| 80 return true; |
| 81 } |
| 82 void SetValue(scoped_ptr<base::DictionaryValue> value) override { |
| 83 storage_.Clear(); |
| 84 storage_.MergeDictionary(value.get()); |
| 85 } |
| 86 |
| 87 void ReportValueChanged() override {} |
| 88 |
| 89 // This storage class requires no special initialization. |
| 90 bool IsInitializationComplete() override { return true; } |
| 91 void StartObservingInit(SdchOwner* observer) override {} |
| 92 void StopObservingInit() override {} |
| 93 |
| 94 private: |
| 95 base::DictionaryValue storage_; |
| 96 |
| 97 DISALLOW_COPY_AND_ASSIGN(ValueMapPrefStorage); |
| 98 }; |
| 99 |
| 79 // This function returns store[kPreferenceName/kDictionariesKey]. The caller | 100 // This function returns store[kPreferenceName/kDictionariesKey]. The caller |
| 80 // is responsible for making sure any needed calls to | 101 // is responsible for making sure any needed calls to |
| 81 // |store->ReportValueChanged()| occur. | 102 // |store->ReportValueChanged()| occur. |
| 82 base::DictionaryValue* GetPersistentStoreDictionaryMap( | 103 base::DictionaryValue* GetPersistentStoreDictionaryMap( |
| 83 WriteablePrefStore* store) { | 104 SdchOwner::PrefStorage* store) { |
| 84 base::Value* result = nullptr; | 105 base::DictionaryValue* preference_dictionary = nullptr; |
| 85 bool success = store->GetMutableValue(kPreferenceName, &result); | 106 bool success = store->GetMutableValue(&preference_dictionary); |
| 86 DCHECK(success); | 107 DCHECK(success); |
| 87 | 108 |
| 88 base::DictionaryValue* preference_dictionary = nullptr; | |
| 89 success = result->GetAsDictionary(&preference_dictionary); | |
| 90 DCHECK(success); | |
| 91 DCHECK(preference_dictionary); | |
| 92 | |
| 93 base::DictionaryValue* dictionary_list_dictionary = nullptr; | 109 base::DictionaryValue* dictionary_list_dictionary = nullptr; |
| 94 success = preference_dictionary->GetDictionary(kDictionariesKey, | 110 success = preference_dictionary->GetDictionary(kDictionariesKey, |
| 95 &dictionary_list_dictionary); | 111 &dictionary_list_dictionary); |
| 96 DCHECK(success); | 112 DCHECK(success); |
| 97 DCHECK(dictionary_list_dictionary); | 113 DCHECK(dictionary_list_dictionary); |
| 98 | 114 |
| 99 return dictionary_list_dictionary; | 115 return dictionary_list_dictionary; |
| 100 } | 116 } |
| 101 | 117 |
| 102 // This function initializes a pref store with an empty version of the | 118 // This function initializes a pref store with an empty version of the |
| 103 // above schema, removing anything previously in the store under | 119 // above schema, removing anything previously in the store under |
| 104 // kPreferenceName. | 120 // kPreferenceName. |
| 105 void InitializePrefStore(WriteablePrefStore* store) { | 121 void InitializePrefStore(SdchOwner::PrefStorage* store) { |
| 106 scoped_ptr<base::DictionaryValue> empty_store(new base::DictionaryValue); | 122 scoped_ptr<base::DictionaryValue> empty_store(new base::DictionaryValue); |
| 107 empty_store->SetInteger(kVersionKey, kVersion); | 123 empty_store->SetInteger(kVersionKey, kVersion); |
| 108 empty_store->Set(kDictionariesKey, | 124 empty_store->Set(kDictionariesKey, |
| 109 make_scoped_ptr(new base::DictionaryValue)); | 125 make_scoped_ptr(new base::DictionaryValue)); |
| 110 store->SetValue(kPreferenceName, std::move(empty_store), | 126 store->SetValue(std::move(empty_store)); |
| 111 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); | |
| 112 } | 127 } |
| 113 | 128 |
| 114 // A class to allow iteration over all dictionaries in the pref store, and | 129 // A class to allow iteration over all dictionaries in the pref store, and |
| 115 // easy lookup of the information associated with those dictionaries. | 130 // easy lookup of the information associated with those dictionaries. |
| 116 // Note that this is an "Iterator" in the same sense (and for the same | 131 // Note that this is an "Iterator" in the same sense (and for the same |
| 117 // reasons) that base::Dictionary::Iterator is an iterator--it allows | 132 // reasons) that base::Dictionary::Iterator is an iterator--it allows |
| 118 // iterating over all the dictionaries in the preference store, but it | 133 // iterating over all the dictionaries in the preference store, but it |
| 119 // does not allow use as an STL iterator because the container it | 134 // does not allow use as an STL iterator because the container it |
| 120 // is iterating over does not export begin()/end() methods. This iterator can | 135 // is iterating over does not export begin()/end() methods. This iterator can |
| 121 // only be safely used on sanitized pref stores that are known to conform to the | 136 // only be safely used on sanitized pref stores that are known to conform to the |
| 122 // pref store schema. | 137 // pref store schema. |
| 123 class DictionaryPreferenceIterator { | 138 class DictionaryPreferenceIterator { |
| 124 public: | 139 public: |
| 125 explicit DictionaryPreferenceIterator(WriteablePrefStore* pref_store); | 140 explicit DictionaryPreferenceIterator(SdchOwner::PrefStorage* pref_store); |
| 126 | 141 |
| 127 bool IsAtEnd() const; | 142 bool IsAtEnd() const; |
| 128 void Advance(); | 143 void Advance(); |
| 129 | 144 |
| 130 const std::string& server_hash() const { return server_hash_; } | 145 const std::string& server_hash() const { return server_hash_; } |
| 131 const GURL& url() const { return url_; } | 146 const GURL& url() const { return url_; } |
| 132 base::Time last_used() const { return last_used_; } | 147 base::Time last_used() const { return last_used_; } |
| 133 base::Time created_time() const { return created_time_; } | 148 base::Time created_time() const { return created_time_; } |
| 134 int use_count() const { return use_count_; } | 149 int use_count() const { return use_count_; } |
| 135 int size() const { return size_; } | 150 int size() const { return size_; } |
| 136 | 151 |
| 137 private: | 152 private: |
| 138 // Load Dictionary silently skipping any that are malformed. | 153 // Load Dictionary silently skipping any that are malformed. |
| 139 void LoadNextDictionary(); | 154 void LoadNextDictionary(); |
| 140 // Try to load Dictionary from current iterator's position. Returns true if | 155 // Try to load Dictionary from current iterator's position. Returns true if |
| 141 // succeeded. | 156 // succeeded. |
| 142 bool TryLoadDictionary(); | 157 bool TryLoadDictionary(); |
| 143 | 158 |
| 144 std::string server_hash_; | 159 std::string server_hash_; |
| 145 GURL url_; | 160 GURL url_; |
| 146 base::Time last_used_; | 161 base::Time last_used_; |
| 147 base::Time created_time_; | 162 base::Time created_time_; |
| 148 int use_count_; | 163 int use_count_; |
| 149 int size_; | 164 int size_; |
| 150 | 165 |
| 151 base::DictionaryValue::Iterator dictionary_iterator_; | 166 base::DictionaryValue::Iterator dictionary_iterator_; |
| 152 }; | 167 }; |
| 153 | 168 |
| 154 DictionaryPreferenceIterator::DictionaryPreferenceIterator( | 169 DictionaryPreferenceIterator::DictionaryPreferenceIterator( |
| 155 WriteablePrefStore* pref_store) | 170 SdchOwner::PrefStorage* pref_store) |
| 156 : use_count_(0), | 171 : use_count_(0), |
| 157 size_(0), | 172 size_(0), |
| 158 dictionary_iterator_(*GetPersistentStoreDictionaryMap(pref_store)) { | 173 dictionary_iterator_(*GetPersistentStoreDictionaryMap(pref_store)) { |
| 159 LoadNextDictionary(); | 174 LoadNextDictionary(); |
| 160 } | 175 } |
| 161 | 176 |
| 162 bool DictionaryPreferenceIterator::IsAtEnd() const { | 177 bool DictionaryPreferenceIterator::IsAtEnd() const { |
| 163 return dictionary_iterator_.IsAtEnd(); | 178 return dictionary_iterator_.IsAtEnd(); |
| 164 } | 179 } |
| 165 | 180 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 | 223 |
| 209 double created_time_seconds = 0; | 224 double created_time_seconds = 0; |
| 210 success = dict->GetDouble(kDictionaryCreatedTimeKey, &created_time_seconds); | 225 success = dict->GetDouble(kDictionaryCreatedTimeKey, &created_time_seconds); |
| 211 if (!success) | 226 if (!success) |
| 212 return false; | 227 return false; |
| 213 created_time_ = base::Time::FromDoubleT(created_time_seconds); | 228 created_time_ = base::Time::FromDoubleT(created_time_seconds); |
| 214 | 229 |
| 215 return true; | 230 return true; |
| 216 } | 231 } |
| 217 | 232 |
| 218 // Triggers a ReportValueChanged() on the specified WriteablePrefStore | 233 // Triggers a ReportValueChanged() when the object goes out of scope. |
| 219 // when the object goes out of scope. | |
| 220 class ScopedPrefNotifier { | 234 class ScopedPrefNotifier { |
| 221 public: | 235 public: |
| 222 // Caller must guarantee lifetime of |*pref_store| exceeds the | 236 // Caller must guarantee lifetime of |*pref_store| exceeds the |
| 223 // lifetime of this object. | 237 // lifetime of this object. |
| 224 ScopedPrefNotifier(WriteablePrefStore* pref_store) | 238 ScopedPrefNotifier(SdchOwner::PrefStorage* pref_store) |
| 225 : pref_store_(pref_store) {} | 239 : pref_store_(pref_store) { |
| 226 ~ScopedPrefNotifier() { | 240 DCHECK(pref_store); |
| 227 pref_store_->ReportValueChanged( | |
| 228 kPreferenceName, WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); | |
| 229 } | 241 } |
| 242 ~ScopedPrefNotifier() { pref_store_->ReportValueChanged(); } |
| 230 | 243 |
| 231 private: | 244 private: |
| 232 WriteablePrefStore* pref_store_; | 245 SdchOwner::PrefStorage* pref_store_; |
| 233 | 246 |
| 234 DISALLOW_COPY_AND_ASSIGN(ScopedPrefNotifier); | 247 DISALLOW_COPY_AND_ASSIGN(ScopedPrefNotifier); |
| 235 }; | 248 }; |
| 236 | 249 |
| 237 } // namespace | 250 } // namespace |
| 238 | 251 |
| 239 // Adjust SDCH limits downwards for mobile. | 252 // Adjust SDCH limits downwards for mobile. |
| 240 #if defined(OS_ANDROID) || defined(OS_IOS) | 253 #if defined(OS_ANDROID) || defined(OS_IOS) |
| 241 // static | 254 // static |
| 242 const size_t SdchOwner::kMaxTotalDictionarySize = 2 * 500 * 1000; | 255 const size_t SdchOwner::kMaxTotalDictionarySize = 2 * 500 * 1000; |
| 243 #else | 256 #else |
| 244 // static | 257 // static |
| 245 const size_t SdchOwner::kMaxTotalDictionarySize = 20 * 1000 * 1000; | 258 const size_t SdchOwner::kMaxTotalDictionarySize = 20 * 1000 * 1000; |
| 246 #endif | 259 #endif |
| 247 | 260 |
| 261 SdchOwner::PrefStorage::~PrefStorage() {} |
| 262 |
| 248 // Somewhat arbitrary, but we assume a dictionary smaller than | 263 // Somewhat arbitrary, but we assume a dictionary smaller than |
| 249 // 50K isn't going to do anyone any good. Note that this still doesn't | 264 // 50K isn't going to do anyone any good. Note that this still doesn't |
| 250 // prevent download and addition unless there is less than this | 265 // prevent download and addition unless there is less than this |
| 251 // amount of space available in storage. | 266 // amount of space available in storage. |
| 252 const size_t SdchOwner::kMinSpaceForDictionaryFetch = 50 * 1000; | 267 const size_t SdchOwner::kMinSpaceForDictionaryFetch = 50 * 1000; |
| 253 | 268 |
| 254 void SdchOwner::RecordDictionaryFate(enum DictionaryFate fate) { | 269 void SdchOwner::RecordDictionaryFate(enum DictionaryFate fate) { |
| 255 UMA_HISTOGRAM_ENUMERATION("Sdch3.DictionaryFate", fate, DICTIONARY_FATE_MAX); | 270 UMA_HISTOGRAM_ENUMERATION("Sdch3.DictionaryFate", fate, DICTIONARY_FATE_MAX); |
| 256 } | 271 } |
| 257 | 272 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 280 total_dictionary_bytes_(0), | 295 total_dictionary_bytes_(0), |
| 281 clock_(new base::DefaultClock), | 296 clock_(new base::DefaultClock), |
| 282 max_total_dictionary_size_(kMaxTotalDictionarySize), | 297 max_total_dictionary_size_(kMaxTotalDictionarySize), |
| 283 min_space_for_dictionary_fetch_(kMinSpaceForDictionaryFetch), | 298 min_space_for_dictionary_fetch_(kMinSpaceForDictionaryFetch), |
| 284 memory_pressure_listener_( | 299 memory_pressure_listener_( |
| 285 base::Bind(&SdchOwner::OnMemoryPressure, | 300 base::Bind(&SdchOwner::OnMemoryPressure, |
| 286 // Because |memory_pressure_listener_| is owned by | 301 // Because |memory_pressure_listener_| is owned by |
| 287 // SdchOwner, the SdchOwner object will be available | 302 // SdchOwner, the SdchOwner object will be available |
| 288 // for the lifetime of |memory_pressure_listener_|. | 303 // for the lifetime of |memory_pressure_listener_|. |
| 289 base::Unretained(this))), | 304 base::Unretained(this))), |
| 290 in_memory_pref_store_(new ValueMapPrefStore()), | 305 in_memory_pref_store_(new ValueMapPrefStorage()), |
| 291 external_pref_store_(nullptr), | 306 external_pref_store_(nullptr), |
| 292 pref_store_(in_memory_pref_store_.get()), | 307 pref_store_(in_memory_pref_store_.get()), |
| 293 creation_time_(clock_->Now()) { | 308 creation_time_(clock_->Now()) { |
| 294 manager_->AddObserver(this); | 309 manager_->AddObserver(this); |
| 295 InitializePrefStore(pref_store_); | 310 InitializePrefStore(pref_store_); |
| 296 } | 311 } |
| 297 | 312 |
| 298 SdchOwner::~SdchOwner() { | 313 SdchOwner::~SdchOwner() { |
| 299 for (DictionaryPreferenceIterator it(pref_store_); !it.IsAtEnd(); | 314 for (DictionaryPreferenceIterator it(pref_store_); !it.IsAtEnd(); |
| 300 it.Advance()) { | 315 it.Advance()) { |
| 301 int new_uses = it.use_count() - use_counts_at_load_[it.server_hash()]; | 316 int new_uses = it.use_count() - use_counts_at_load_[it.server_hash()]; |
| 302 DictionaryFate fate = IsPersistingDictionaries() ? | 317 DictionaryFate fate = IsPersistingDictionaries() ? |
| 303 DICTIONARY_FATE_UNLOAD_FOR_DESTRUCTION : | 318 DICTIONARY_FATE_UNLOAD_FOR_DESTRUCTION : |
| 304 DICTIONARY_FATE_EVICT_FOR_DESTRUCTION; | 319 DICTIONARY_FATE_EVICT_FOR_DESTRUCTION; |
| 305 RecordDictionaryEvictionOrUnload(it.server_hash(), it.size(), new_uses, | 320 RecordDictionaryEvictionOrUnload(it.server_hash(), it.size(), new_uses, |
| 306 fate); | 321 fate); |
| 307 } | 322 } |
| 308 manager_->RemoveObserver(this); | 323 manager_->RemoveObserver(this); |
| 309 | 324 |
| 310 // This object only observes the external store during loading, | 325 // This object only observes the external store during loading, |
| 311 // i.e. before it's made the default preferences store. | 326 // i.e. before it's made the default preferences store. |
| 312 if (external_pref_store_) | 327 if (external_pref_store_ && pref_store_ != external_pref_store_.get()) |
| 313 external_pref_store_->RemoveObserver(this); | 328 external_pref_store_->StopObservingInit(); |
| 314 | 329 |
| 315 int64_t object_lifetime = (clock_->Now() - creation_time_).InMilliseconds(); | 330 int64_t object_lifetime = (clock_->Now() - creation_time_).InMilliseconds(); |
| 316 for (const auto& val : consumed_byte_seconds_) { | 331 for (const auto& val : consumed_byte_seconds_) { |
| 317 if (object_lifetime > 0) { | 332 if (object_lifetime > 0) { |
| 318 // Objects that are created and immediately destroyed don't add any memory | 333 // Objects that are created and immediately destroyed don't add any memory |
| 319 // pressure over time (and also cause a crash here). | 334 // pressure over time (and also cause a crash here). |
| 320 UMA_HISTOGRAM_MEMORY_KB("Sdch3.TimeWeightedMemoryUse", | 335 UMA_HISTOGRAM_MEMORY_KB("Sdch3.TimeWeightedMemoryUse", |
| 321 val / object_lifetime); | 336 val / object_lifetime); |
| 322 } | 337 } |
| 323 } | 338 } |
| 324 | |
| 325 } | 339 } |
| 326 | 340 |
| 327 void SdchOwner::EnablePersistentStorage(PersistentPrefStore* pref_store) { | 341 void SdchOwner::EnablePersistentStorage(scoped_ptr<PrefStorage> pref_store) { |
| 328 DCHECK(!external_pref_store_); | 342 DCHECK(!external_pref_store_); |
| 329 external_pref_store_ = pref_store; | 343 DCHECK(pref_store); |
| 330 external_pref_store_->AddObserver(this); | 344 external_pref_store_ = std::move(pref_store); |
| 345 external_pref_store_->StartObservingInit(this); |
| 331 | 346 |
| 332 if (external_pref_store_->IsInitializationComplete()) | 347 if (external_pref_store_->IsInitializationComplete()) |
| 333 OnInitializationCompleted(true); | 348 OnPrefStorageInitializationComplete(true); |
| 334 } | 349 } |
| 335 | 350 |
| 336 void SdchOwner::SetMaxTotalDictionarySize(size_t max_total_dictionary_size) { | 351 void SdchOwner::SetMaxTotalDictionarySize(size_t max_total_dictionary_size) { |
| 337 max_total_dictionary_size_ = max_total_dictionary_size; | 352 max_total_dictionary_size_ = max_total_dictionary_size; |
| 338 } | 353 } |
| 339 | 354 |
| 340 void SdchOwner::SetMinSpaceForDictionaryFetch( | 355 void SdchOwner::SetMinSpaceForDictionaryFetch( |
| 341 size_t min_space_for_dictionary_fetch) { | 356 size_t min_space_for_dictionary_fetch) { |
| 342 min_space_for_dictionary_fetch_ = min_space_for_dictionary_fetch; | 357 min_space_for_dictionary_fetch_ = min_space_for_dictionary_fetch; |
| 343 } | 358 } |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 base::Unretained(this), base::Time(), base::Time::Now(), 0)); | 589 base::Unretained(this), base::Time(), base::Time::Now(), 0)); |
| 575 } | 590 } |
| 576 | 591 |
| 577 void SdchOwner::OnClearDictionaries() { | 592 void SdchOwner::OnClearDictionaries() { |
| 578 total_dictionary_bytes_ = 0; | 593 total_dictionary_bytes_ = 0; |
| 579 fetcher_->Cancel(); | 594 fetcher_->Cancel(); |
| 580 | 595 |
| 581 InitializePrefStore(pref_store_); | 596 InitializePrefStore(pref_store_); |
| 582 } | 597 } |
| 583 | 598 |
| 584 void SdchOwner::OnPrefValueChanged(const std::string& key) { | 599 void SdchOwner::OnPrefStorageInitializationComplete(bool succeeded) { |
| 585 } | 600 PrefStorage::ReadError error = external_pref_store_->GetReadError(); |
| 586 | |
| 587 void SdchOwner::OnInitializationCompleted(bool succeeded) { | |
| 588 PersistentPrefStore::PrefReadError error = | |
| 589 external_pref_store_->GetReadError(); | |
| 590 // Errors on load are self-correcting; if dictionaries were not | 601 // Errors on load are self-correcting; if dictionaries were not |
| 591 // persisted from the last instance of the browser, they will be | 602 // persisted from the last instance of the browser, they will be |
| 592 // faulted in by user action over time. However, if a load error | 603 // faulted in by user action over time. However, if a load error |
| 593 // means that the dictionary information won't be able to be persisted, | 604 // means that the dictionary information won't be able to be persisted, |
| 594 // the in memory pref store is left in place. | 605 // the in memory pref store is left in place. |
| 595 if (!succeeded) { | 606 if (!succeeded) { |
| 596 // Failure means a write failed, since read failures are recoverable. | 607 // Failure means a write failed, since read failures are recoverable. |
| 597 DCHECK_NE( | 608 external_pref_store_->StopObservingInit(); |
| 598 error, | |
| 599 PersistentPrefStore::PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE); | |
| 600 DCHECK_NE(error, | |
| 601 PersistentPrefStore::PREF_READ_ERROR_MAX_ENUM); | |
| 602 | |
| 603 LOG(ERROR) << "Pref store write failed: " << error; | |
| 604 external_pref_store_->RemoveObserver(this); | |
| 605 external_pref_store_ = nullptr; | 609 external_pref_store_ = nullptr; |
| 606 RecordPersistenceFailure(PERSISTENCE_FAILURE_REASON_WRITE_FAILED); | 610 RecordPersistenceFailure( |
| 611 PrefStorage::PERSISTENCE_FAILURE_REASON_WRITE_FAILED); |
| 607 return; | 612 return; |
| 608 } | 613 } |
| 609 switch (external_pref_store_->GetReadError()) { | |
| 610 case PersistentPrefStore::PREF_READ_ERROR_NONE: | |
| 611 break; | |
| 612 | 614 |
| 613 case PersistentPrefStore::PREF_READ_ERROR_NO_FILE: | 615 if (error != PrefStorage::PERSISTENCE_FAILURE_NONE) |
| 614 // First time reading; the file will be created. | 616 RecordPersistenceFailure(error); |
| 615 RecordPersistenceFailure(PERSISTENCE_FAILURE_REASON_NO_FILE); | |
| 616 break; | |
| 617 | |
| 618 case PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE: | |
| 619 case PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE: | |
| 620 case PersistentPrefStore::PREF_READ_ERROR_FILE_OTHER: | |
| 621 case PersistentPrefStore::PREF_READ_ERROR_FILE_LOCKED: | |
| 622 case PersistentPrefStore::PREF_READ_ERROR_JSON_REPEAT: | |
| 623 RecordPersistenceFailure(PERSISTENCE_FAILURE_REASON_READ_FAILED); | |
| 624 break; | |
| 625 | |
| 626 case PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED: | |
| 627 case PersistentPrefStore::PREF_READ_ERROR_FILE_NOT_SPECIFIED: | |
| 628 case PersistentPrefStore::PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE: | |
| 629 case PersistentPrefStore::PREF_READ_ERROR_MAX_ENUM: | |
| 630 // Shouldn't ever happen. ACCESS_DENIED and FILE_NOT_SPECIFIED should | |
| 631 // imply !succeeded, and TASK_INCOMPLETE should never be delivered. | |
| 632 NOTREACHED(); | |
| 633 break; | |
| 634 } | |
| 635 | |
| 636 | 617 |
| 637 // Load in what was stored before chrome exited previously. | 618 // Load in what was stored before chrome exited previously. |
| 638 const base::Value* sdch_persistence_value = nullptr; | |
| 639 const base::DictionaryValue* sdch_persistence_dictionary = nullptr; | 619 const base::DictionaryValue* sdch_persistence_dictionary = nullptr; |
| 640 | 620 |
| 641 // The GetPersistentStore() routine above assumes data formatted | 621 // The GetPersistentStore() routine above assumes data formatted |
| 642 // according to the schema described at the top of this file. Since | 622 // according to the schema described at the top of this file. Since |
| 643 // this data comes from disk, to avoid disk corruption resulting in | 623 // this data comes from disk, to avoid disk corruption resulting in |
| 644 // persistent chrome errors this code avoids those assupmtions. | 624 // persistent chrome errors this code avoids those assupmtions. |
| 645 if (external_pref_store_->GetValue(kPreferenceName, | 625 if (external_pref_store_->GetValue(&sdch_persistence_dictionary)) |
| 646 &sdch_persistence_value) && | |
| 647 sdch_persistence_value->GetAsDictionary(&sdch_persistence_dictionary)) { | |
| 648 SchedulePersistedDictionaryLoads(*sdch_persistence_dictionary); | 626 SchedulePersistedDictionaryLoads(*sdch_persistence_dictionary); |
| 649 } | |
| 650 | 627 |
| 651 // Reset the persistent store and update it with the accumulated | 628 // Reset the persistent store and update it with the accumulated |
| 652 // information from the local store. | 629 // information from the local store. |
| 653 InitializePrefStore(external_pref_store_); | 630 InitializePrefStore(external_pref_store_.get()); |
| 654 | 631 |
| 655 ScopedPrefNotifier scoped_pref_notifier(external_pref_store_); | 632 ScopedPrefNotifier scoped_pref_notifier(external_pref_store_.get()); |
| 656 GetPersistentStoreDictionaryMap(external_pref_store_) | 633 GetPersistentStoreDictionaryMap(external_pref_store_.get()) |
| 657 ->Swap(GetPersistentStoreDictionaryMap(in_memory_pref_store_.get())); | 634 ->Swap(GetPersistentStoreDictionaryMap(in_memory_pref_store_.get())); |
| 658 | 635 |
| 659 // This object can stop waiting on (i.e. observing) the external preference | 636 // This object can stop waiting on (i.e. observing) the external preference |
| 660 // store and switch over to using it as the primary preference store. | 637 // store and switch over to using it as the primary preference store. |
| 661 pref_store_ = external_pref_store_; | 638 pref_store_ = external_pref_store_.get(); |
| 662 external_pref_store_->RemoveObserver(this); | 639 external_pref_store_->StopObservingInit(); |
| 663 external_pref_store_ = nullptr; | |
| 664 in_memory_pref_store_ = nullptr; | 640 in_memory_pref_store_ = nullptr; |
| 665 } | 641 } |
| 666 | 642 |
| 667 void SdchOwner::SetClockForTesting(scoped_ptr<base::Clock> clock) { | 643 void SdchOwner::SetClockForTesting(scoped_ptr<base::Clock> clock) { |
| 668 clock_ = std::move(clock); | 644 clock_ = std::move(clock); |
| 669 } | 645 } |
| 670 | 646 |
| 671 int SdchOwner::GetDictionaryCountForTesting() const { | 647 int SdchOwner::GetDictionaryCountForTesting() const { |
| 672 int count = 0; | 648 int count = 0; |
| 673 for (DictionaryPreferenceIterator it(pref_store_); !it.IsAtEnd(); | 649 for (DictionaryPreferenceIterator it(pref_store_); !it.IsAtEnd(); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 760 } | 736 } |
| 761 | 737 |
| 762 return true; | 738 return true; |
| 763 } | 739 } |
| 764 | 740 |
| 765 bool SdchOwner::IsPersistingDictionaries() const { | 741 bool SdchOwner::IsPersistingDictionaries() const { |
| 766 return in_memory_pref_store_.get() != nullptr; | 742 return in_memory_pref_store_.get() != nullptr; |
| 767 } | 743 } |
| 768 | 744 |
| 769 } // namespace net | 745 } // namespace net |
| OLD | NEW |