13d5ecfaeedfa598de4bf57b29f3c87eb2897512
[platform/framework/web/crosswalk.git] / src / chrome / browser / prefs / tracked / segregated_pref_store.cc
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
39     if (!outer_->on_initialization_.is_null())
40       outer_->on_initialization_.Run();
41
42     if (successful_sub_initializations_ == 2 && outer_->read_error_delegate_) {
43       PersistentPrefStore::PrefReadError read_error = outer_->GetReadError();
44       if (read_error != PersistentPrefStore::PREF_READ_ERROR_NONE)
45         outer_->read_error_delegate_->OnError(read_error);
46     }
47
48     FOR_EACH_OBSERVER(
49         PrefStore::Observer,
50         outer_->observers_,
51         OnInitializationCompleted(successful_sub_initializations_ == 2));
52   }
53 }
54
55 SegregatedPrefStore::SegregatedPrefStore(
56     const scoped_refptr<PersistentPrefStore>& default_pref_store,
57     const scoped_refptr<PersistentPrefStore>& selected_pref_store,
58     const std::set<std::string>& selected_pref_names,
59     const base::Closure& on_initialization)
60     : default_pref_store_(default_pref_store),
61       selected_pref_store_(selected_pref_store),
62       selected_preference_names_(selected_pref_names),
63       on_initialization_(on_initialization),
64       aggregating_observer_(this) {
65
66   default_pref_store_->AddObserver(&aggregating_observer_);
67   selected_pref_store_->AddObserver(&aggregating_observer_);
68 }
69
70 void SegregatedPrefStore::AddObserver(Observer* observer) {
71   observers_.AddObserver(observer);
72 }
73
74 void SegregatedPrefStore::RemoveObserver(Observer* observer) {
75   observers_.RemoveObserver(observer);
76 }
77
78 bool SegregatedPrefStore::HasObservers() const {
79   return observers_.might_have_observers();
80 }
81
82 bool SegregatedPrefStore::IsInitializationComplete() const {
83   return default_pref_store_->IsInitializationComplete() &&
84          selected_pref_store_->IsInitializationComplete();
85 }
86
87 bool SegregatedPrefStore::GetValue(const std::string& key,
88                                    const base::Value** result) const {
89   return StoreForKey(key)->GetValue(key, result);
90 }
91
92 void SegregatedPrefStore::SetValue(const std::string& key, base::Value* value) {
93   StoreForKey(key)->SetValue(key, value);
94 }
95
96 void SegregatedPrefStore::RemoveValue(const std::string& key) {
97   StoreForKey(key)->RemoveValue(key);
98 }
99
100 bool SegregatedPrefStore::GetMutableValue(const std::string& key,
101                                           base::Value** result) {
102   return StoreForKey(key)->GetMutableValue(key, result);
103 }
104
105 void SegregatedPrefStore::ReportValueChanged(const std::string& key) {
106   StoreForKey(key)->ReportValueChanged(key);
107 }
108
109 void SegregatedPrefStore::SetValueSilently(const std::string& key,
110                                            base::Value* value) {
111   StoreForKey(key)->SetValueSilently(key, value);
112 }
113
114 bool SegregatedPrefStore::ReadOnly() const {
115   return selected_pref_store_->ReadOnly() ||
116          default_pref_store_->ReadOnly();
117 }
118
119 PersistentPrefStore::PrefReadError SegregatedPrefStore::GetReadError() const {
120   PersistentPrefStore::PrefReadError read_error =
121       default_pref_store_->GetReadError();
122   if (read_error == PersistentPrefStore::PREF_READ_ERROR_NONE) {
123     read_error = selected_pref_store_->GetReadError();
124     // Ignore NO_FILE from selected_pref_store_.
125     if (read_error == PersistentPrefStore::PREF_READ_ERROR_NO_FILE)
126       read_error = PersistentPrefStore::PREF_READ_ERROR_NONE;
127   }
128   return read_error;
129 }
130
131 PersistentPrefStore::PrefReadError SegregatedPrefStore::ReadPrefs() {
132   default_pref_store_->ReadPrefs();
133   selected_pref_store_->ReadPrefs();
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 const PersistentPrefStore*
155 SegregatedPrefStore::StoreForKey(const std::string& key) const {
156   if (ContainsKey(selected_preference_names_, key) ||
157       selected_pref_store_->GetValue(key, NULL)) {
158     return selected_pref_store_.get();
159   }
160   return default_pref_store_.get();
161 }
162
163 PersistentPrefStore* SegregatedPrefStore::StoreForKey(const std::string& key) {
164   if (ContainsKey(selected_preference_names_, key))
165     return selected_pref_store_.get();
166
167   // Check if this unselected value was previously selected. If so, migrate it
168   // back to the unselected store.
169   // It's hard to do this in a single pass at startup because PrefStore does not
170   // permit us to enumerate its contents.
171   const base::Value* value = NULL;
172   if (selected_pref_store_->GetValue(key, &value)) {
173     scoped_ptr<base::Value> migrated_value(value->DeepCopy());
174     value = NULL;
175     default_pref_store_->SetValue(key, migrated_value.release());
176     default_pref_store_->CommitPendingWrite();
177     selected_pref_store_->RemoveValue(key);
178     selected_pref_store_->CommitPendingWrite();
179   }
180
181   return default_pref_store_.get();
182 }