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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/prefs/tracked/segregated_pref_store.h" 6 7 #include "base/logging.h" 8 #include "base/stl_util.h" 9 #include "base/values.h" 10 11 SegregatedPrefStore::AggregatingObserver::AggregatingObserver( 12 SegregatedPrefStore* outer) 13 : outer_(outer), 14 failed_sub_initializations_(0), 15 successful_sub_initializations_(0) {} 16 17 void SegregatedPrefStore::AggregatingObserver::OnPrefValueChanged( 18 const std::string& key) { 19 // There is no need to tell clients about changes if they have not yet been 20 // told about initialization. 21 if (failed_sub_initializations_ + successful_sub_initializations_ < 2) 22 return; 23 24 FOR_EACH_OBSERVER( 25 PrefStore::Observer, outer_->observers_, OnPrefValueChanged(key)); 26 } 27 28 void SegregatedPrefStore::AggregatingObserver::OnInitializationCompleted( 29 bool succeeded) { 30 if (succeeded) 31 ++successful_sub_initializations_; 32 else 33 ++failed_sub_initializations_; 34 35 DCHECK_LE(failed_sub_initializations_ + successful_sub_initializations_, 2); 36 37 if (failed_sub_initializations_ + successful_sub_initializations_ == 2) { 38 if (successful_sub_initializations_ == 2 && outer_->read_error_delegate_) { 39 PersistentPrefStore::PrefReadError read_error = outer_->GetReadError(); 40 if (read_error != PersistentPrefStore::PREF_READ_ERROR_NONE) 41 outer_->read_error_delegate_->OnError(read_error); 42 } 43 44 FOR_EACH_OBSERVER( 45 PrefStore::Observer, 46 outer_->observers_, 47 OnInitializationCompleted(successful_sub_initializations_ == 2)); 48 } 49 } 50 51 SegregatedPrefStore::SegregatedPrefStore( 52 const scoped_refptr<PersistentPrefStore>& default_pref_store, 53 const scoped_refptr<PersistentPrefStore>& selected_pref_store, 54 const std::set<std::string>& selected_pref_names) 55 : default_pref_store_(default_pref_store), 56 selected_pref_store_(selected_pref_store), 57 selected_preference_names_(selected_pref_names), 58 aggregating_observer_(this) { 59 default_pref_store_->AddObserver(&aggregating_observer_); 60 selected_pref_store_->AddObserver(&aggregating_observer_); 61 } 62 63 void SegregatedPrefStore::AddObserver(Observer* observer) { 64 observers_.AddObserver(observer); 65 } 66 67 void SegregatedPrefStore::RemoveObserver(Observer* observer) { 68 observers_.RemoveObserver(observer); 69 } 70 71 bool SegregatedPrefStore::HasObservers() const { 72 return observers_.might_have_observers(); 73 } 74 75 bool SegregatedPrefStore::IsInitializationComplete() const { 76 return default_pref_store_->IsInitializationComplete() && 77 selected_pref_store_->IsInitializationComplete(); 78 } 79 80 bool SegregatedPrefStore::GetValue(const std::string& key, 81 const base::Value** result) const { 82 return StoreForKey(key)->GetValue(key, result); 83 } 84 85 void SegregatedPrefStore::SetValue(const std::string& key, base::Value* value) { 86 StoreForKey(key)->SetValue(key, value); 87 } 88 89 void SegregatedPrefStore::RemoveValue(const std::string& key) { 90 StoreForKey(key)->RemoveValue(key); 91 } 92 93 bool SegregatedPrefStore::GetMutableValue(const std::string& key, 94 base::Value** result) { 95 return StoreForKey(key)->GetMutableValue(key, result); 96 } 97 98 void SegregatedPrefStore::ReportValueChanged(const std::string& key) { 99 StoreForKey(key)->ReportValueChanged(key); 100 } 101 102 void SegregatedPrefStore::SetValueSilently(const std::string& key, 103 base::Value* value) { 104 StoreForKey(key)->SetValueSilently(key, value); 105 } 106 107 bool SegregatedPrefStore::ReadOnly() const { 108 return selected_pref_store_->ReadOnly() || 109 default_pref_store_->ReadOnly(); 110 } 111 112 PersistentPrefStore::PrefReadError SegregatedPrefStore::GetReadError() const { 113 PersistentPrefStore::PrefReadError read_error = 114 default_pref_store_->GetReadError(); 115 if (read_error == PersistentPrefStore::PREF_READ_ERROR_NONE) { 116 read_error = selected_pref_store_->GetReadError(); 117 // Ignore NO_FILE from selected_pref_store_. 118 if (read_error == PersistentPrefStore::PREF_READ_ERROR_NO_FILE) 119 read_error = PersistentPrefStore::PREF_READ_ERROR_NONE; 120 } 121 return read_error; 122 } 123 124 PersistentPrefStore::PrefReadError SegregatedPrefStore::ReadPrefs() { 125 // Note: Both of these stores own PrefFilters which makes ReadPrefs 126 // asynchronous. This is okay in this case as only the first call will be 127 // truly asynchronous, the second call will then unblock the migration in 128 // TrackedPreferencesMigrator and complete synchronously. 129 default_pref_store_->ReadPrefs(); 130 PersistentPrefStore::PrefReadError selected_store_read_error = 131 selected_pref_store_->ReadPrefs(); 132 DCHECK_NE(PersistentPrefStore::PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE, 133 selected_store_read_error); 134 135 return GetReadError(); 136 } 137 138 void SegregatedPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) { 139 read_error_delegate_.reset(error_delegate); 140 default_pref_store_->ReadPrefsAsync(NULL); 141 selected_pref_store_->ReadPrefsAsync(NULL); 142 } 143 144 void SegregatedPrefStore::CommitPendingWrite() { 145 default_pref_store_->CommitPendingWrite(); 146 selected_pref_store_->CommitPendingWrite(); 147 } 148 149 SegregatedPrefStore::~SegregatedPrefStore() { 150 default_pref_store_->RemoveObserver(&aggregating_observer_); 151 selected_pref_store_->RemoveObserver(&aggregating_observer_); 152 } 153 154 PersistentPrefStore* SegregatedPrefStore::StoreForKey(const std::string& key) { 155 return ContainsKey(selected_preference_names_, key) ? selected_pref_store_ 156 : default_pref_store_; 157 } 158 159 const PersistentPrefStore* SegregatedPrefStore::StoreForKey( 160 const std::string& key) const { 161 return ContainsKey(selected_preference_names_, key) ? selected_pref_store_ 162 : default_pref_store_; 163 } 164