OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "base/prefs/json_pref_store.h" | 5 #include "base/prefs/json_pref_store.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
11 #include "base/file_util.h" | 11 #include "base/file_util.h" |
12 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
13 #include "base/json/json_file_value_serializer.h" | 13 #include "base/json/json_file_value_serializer.h" |
14 #include "base/json/json_string_value_serializer.h" | 14 #include "base/json/json_string_value_serializer.h" |
15 #include "base/memory/ref_counted.h" | 15 #include "base/memory/ref_counted.h" |
16 #include "base/message_loop/message_loop_proxy.h" | |
17 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
18 #include "base/prefs/pref_filter.h" | 17 #include "base/prefs/pref_filter.h" |
19 #include "base/sequenced_task_runner.h" | 18 #include "base/sequenced_task_runner.h" |
20 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" |
| 20 #include "base/task_runner_util.h" |
21 #include "base/threading/sequenced_worker_pool.h" | 21 #include "base/threading/sequenced_worker_pool.h" |
22 #include "base/values.h" | 22 #include "base/values.h" |
23 | 23 |
| 24 // Result returned from internal read tasks. |
| 25 struct JsonPrefStore::ReadResult { |
| 26 public: |
| 27 ReadResult(); |
| 28 ~ReadResult(); |
| 29 |
| 30 scoped_ptr<base::Value> value; |
| 31 PrefReadError error; |
| 32 bool no_dir; |
| 33 |
| 34 private: |
| 35 DISALLOW_COPY_AND_ASSIGN(ReadResult); |
| 36 }; |
| 37 |
| 38 JsonPrefStore::ReadResult::ReadResult() |
| 39 : error(PersistentPrefStore::PREF_READ_ERROR_NONE), no_dir(false) { |
| 40 } |
| 41 |
| 42 JsonPrefStore::ReadResult::~ReadResult() { |
| 43 } |
| 44 |
24 namespace { | 45 namespace { |
25 | 46 |
26 // Some extensions we'll tack on to copies of the Preferences files. | 47 // Some extensions we'll tack on to copies of the Preferences files. |
27 const base::FilePath::CharType* kBadExtension = FILE_PATH_LITERAL("bad"); | 48 const base::FilePath::CharType kBadExtension[] = FILE_PATH_LITERAL("bad"); |
28 | 49 |
29 // Differentiates file loading between origin thread and passed | 50 PersistentPrefStore::PrefReadError HandleReadErrors( |
30 // (aka file) thread. | |
31 class FileThreadDeserializer | |
32 : public base::RefCountedThreadSafe<FileThreadDeserializer> { | |
33 public: | |
34 FileThreadDeserializer(JsonPrefStore* delegate, | |
35 base::SequencedTaskRunner* sequenced_task_runner) | |
36 : no_dir_(false), | |
37 error_(PersistentPrefStore::PREF_READ_ERROR_NONE), | |
38 delegate_(delegate), | |
39 sequenced_task_runner_(sequenced_task_runner), | |
40 origin_loop_proxy_(base::MessageLoopProxy::current()) { | |
41 } | |
42 | |
43 void Start(const base::FilePath& path, | |
44 const base::FilePath& alternate_path) { | |
45 DCHECK(origin_loop_proxy_->BelongsToCurrentThread()); | |
46 // TODO(gab): This should use PostTaskAndReplyWithResult instead of using | |
47 // the |error_| member to pass data across tasks. | |
48 sequenced_task_runner_->PostTask( | |
49 FROM_HERE, | |
50 base::Bind(&FileThreadDeserializer::ReadFileAndReport, | |
51 this, path, alternate_path)); | |
52 } | |
53 | |
54 // Deserializes JSON on the sequenced task runner. | |
55 void ReadFileAndReport(const base::FilePath& path, | |
56 const base::FilePath& alternate_path) { | |
57 DCHECK(sequenced_task_runner_->RunsTasksOnCurrentThread()); | |
58 | |
59 value_.reset(DoReading(path, alternate_path, &error_, &no_dir_)); | |
60 | |
61 origin_loop_proxy_->PostTask( | |
62 FROM_HERE, | |
63 base::Bind(&FileThreadDeserializer::ReportOnOriginThread, this)); | |
64 } | |
65 | |
66 // Reports deserialization result on the origin thread. | |
67 void ReportOnOriginThread() { | |
68 DCHECK(origin_loop_proxy_->BelongsToCurrentThread()); | |
69 delegate_->OnFileRead(value_.Pass(), error_, no_dir_); | |
70 } | |
71 | |
72 static base::Value* DoReading(const base::FilePath& path, | |
73 const base::FilePath& alternate_path, | |
74 PersistentPrefStore::PrefReadError* error, | |
75 bool* no_dir) { | |
76 if (!base::PathExists(path) && !alternate_path.empty() && | |
77 base::PathExists(alternate_path)) { | |
78 base::Move(alternate_path, path); | |
79 } | |
80 | |
81 int error_code; | |
82 std::string error_msg; | |
83 JSONFileValueSerializer serializer(path); | |
84 base::Value* value = serializer.Deserialize(&error_code, &error_msg); | |
85 HandleErrors(value, path, error_code, error_msg, error); | |
86 *no_dir = !base::PathExists(path.DirName()); | |
87 return value; | |
88 } | |
89 | |
90 static void HandleErrors(const base::Value* value, | |
91 const base::FilePath& path, | |
92 int error_code, | |
93 const std::string& error_msg, | |
94 PersistentPrefStore::PrefReadError* error); | |
95 | |
96 private: | |
97 friend class base::RefCountedThreadSafe<FileThreadDeserializer>; | |
98 ~FileThreadDeserializer() {} | |
99 | |
100 bool no_dir_; | |
101 PersistentPrefStore::PrefReadError error_; | |
102 scoped_ptr<base::Value> value_; | |
103 const scoped_refptr<JsonPrefStore> delegate_; | |
104 const scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_; | |
105 const scoped_refptr<base::MessageLoopProxy> origin_loop_proxy_; | |
106 }; | |
107 | |
108 // static | |
109 void FileThreadDeserializer::HandleErrors( | |
110 const base::Value* value, | 51 const base::Value* value, |
111 const base::FilePath& path, | 52 const base::FilePath& path, |
112 int error_code, | 53 int error_code, |
113 const std::string& error_msg, | 54 const std::string& error_msg) { |
114 PersistentPrefStore::PrefReadError* error) { | |
115 *error = PersistentPrefStore::PREF_READ_ERROR_NONE; | |
116 if (!value) { | 55 if (!value) { |
117 DVLOG(1) << "Error while loading JSON file: " << error_msg | 56 DVLOG(1) << "Error while loading JSON file: " << error_msg |
118 << ", file: " << path.value(); | 57 << ", file: " << path.value(); |
119 switch (error_code) { | 58 switch (error_code) { |
120 case JSONFileValueSerializer::JSON_ACCESS_DENIED: | 59 case JSONFileValueSerializer::JSON_ACCESS_DENIED: |
121 *error = PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED; | 60 return PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED; |
122 break; | 61 break; |
123 case JSONFileValueSerializer::JSON_CANNOT_READ_FILE: | 62 case JSONFileValueSerializer::JSON_CANNOT_READ_FILE: |
124 *error = PersistentPrefStore::PREF_READ_ERROR_FILE_OTHER; | 63 return PersistentPrefStore::PREF_READ_ERROR_FILE_OTHER; |
125 break; | 64 break; |
126 case JSONFileValueSerializer::JSON_FILE_LOCKED: | 65 case JSONFileValueSerializer::JSON_FILE_LOCKED: |
127 *error = PersistentPrefStore::PREF_READ_ERROR_FILE_LOCKED; | 66 return PersistentPrefStore::PREF_READ_ERROR_FILE_LOCKED; |
128 break; | 67 break; |
129 case JSONFileValueSerializer::JSON_NO_SUCH_FILE: | 68 case JSONFileValueSerializer::JSON_NO_SUCH_FILE: |
130 *error = PersistentPrefStore::PREF_READ_ERROR_NO_FILE; | 69 return PersistentPrefStore::PREF_READ_ERROR_NO_FILE; |
131 break; | 70 break; |
132 default: | 71 default: |
133 *error = PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE; | |
134 // JSON errors indicate file corruption of some sort. | 72 // JSON errors indicate file corruption of some sort. |
135 // Since the file is corrupt, move it to the side and continue with | 73 // Since the file is corrupt, move it to the side and continue with |
136 // empty preferences. This will result in them losing their settings. | 74 // empty preferences. This will result in them losing their settings. |
137 // We keep the old file for possible support and debugging assistance | 75 // We keep the old file for possible support and debugging assistance |
138 // as well as to detect if they're seeing these errors repeatedly. | 76 // as well as to detect if they're seeing these errors repeatedly. |
139 // TODO(erikkay) Instead, use the last known good file. | 77 // TODO(erikkay) Instead, use the last known good file. |
140 base::FilePath bad = path.ReplaceExtension(kBadExtension); | 78 base::FilePath bad = path.ReplaceExtension(kBadExtension); |
141 | 79 |
142 // If they've ever had a parse error before, put them in another bucket. | 80 // If they've ever had a parse error before, put them in another bucket. |
143 // TODO(erikkay) if we keep this error checking for very long, we may | 81 // TODO(erikkay) if we keep this error checking for very long, we may |
144 // want to differentiate between recent and long ago errors. | 82 // want to differentiate between recent and long ago errors. |
145 if (base::PathExists(bad)) | 83 bool bad_existed = base::PathExists(bad); |
146 *error = PersistentPrefStore::PREF_READ_ERROR_JSON_REPEAT; | |
147 base::Move(path, bad); | 84 base::Move(path, bad); |
148 break; | 85 return bad_existed ? PersistentPrefStore::PREF_READ_ERROR_JSON_REPEAT |
| 86 : PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE; |
149 } | 87 } |
150 } else if (!value->IsType(base::Value::TYPE_DICTIONARY)) { | 88 } else if (!value->IsType(base::Value::TYPE_DICTIONARY)) { |
151 *error = PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE; | 89 return PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE; |
152 } | 90 } |
| 91 return PersistentPrefStore::PREF_READ_ERROR_NONE; |
| 92 } |
| 93 |
| 94 scoped_ptr<JsonPrefStore::ReadResult> ReadPrefsFromDisk( |
| 95 const base::FilePath& path, |
| 96 const base::FilePath& alternate_path) { |
| 97 if (!base::PathExists(path) && !alternate_path.empty() && |
| 98 base::PathExists(alternate_path)) { |
| 99 base::Move(alternate_path, path); |
| 100 } |
| 101 |
| 102 int error_code; |
| 103 std::string error_msg; |
| 104 scoped_ptr<JsonPrefStore::ReadResult> read_result( |
| 105 new JsonPrefStore::ReadResult); |
| 106 JSONFileValueSerializer serializer(path); |
| 107 read_result->value.reset(serializer.Deserialize(&error_code, &error_msg)); |
| 108 read_result->error = |
| 109 HandleReadErrors(read_result->value.get(), path, error_code, error_msg); |
| 110 read_result->no_dir = !base::PathExists(path.DirName()); |
| 111 return read_result.Pass(); |
153 } | 112 } |
154 | 113 |
155 } // namespace | 114 } // namespace |
156 | 115 |
| 116 // static |
157 scoped_refptr<base::SequencedTaskRunner> JsonPrefStore::GetTaskRunnerForFile( | 117 scoped_refptr<base::SequencedTaskRunner> JsonPrefStore::GetTaskRunnerForFile( |
158 const base::FilePath& filename, | 118 const base::FilePath& filename, |
159 base::SequencedWorkerPool* worker_pool) { | 119 base::SequencedWorkerPool* worker_pool) { |
160 std::string token("json_pref_store-"); | 120 std::string token("json_pref_store-"); |
161 token.append(filename.AsUTF8Unsafe()); | 121 token.append(filename.AsUTF8Unsafe()); |
162 return worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( | 122 return worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( |
163 worker_pool->GetNamedSequenceToken(token), | 123 worker_pool->GetNamedSequenceToken(token), |
164 base::SequencedWorkerPool::BLOCK_SHUTDOWN); | 124 base::SequencedWorkerPool::BLOCK_SHUTDOWN); |
165 } | 125 } |
166 | 126 |
(...skipping 22 matching lines...) Expand all Loading... |
189 read_only_(false), | 149 read_only_(false), |
190 writer_(filename, sequenced_task_runner), | 150 writer_(filename, sequenced_task_runner), |
191 pref_filter_(pref_filter.Pass()), | 151 pref_filter_(pref_filter.Pass()), |
192 initialized_(false), | 152 initialized_(false), |
193 filtering_in_progress_(false), | 153 filtering_in_progress_(false), |
194 read_error_(PREF_READ_ERROR_NONE) { | 154 read_error_(PREF_READ_ERROR_NONE) { |
195 } | 155 } |
196 | 156 |
197 bool JsonPrefStore::GetValue(const std::string& key, | 157 bool JsonPrefStore::GetValue(const std::string& key, |
198 const base::Value** result) const { | 158 const base::Value** result) const { |
| 159 DCHECK(CalledOnValidThread()); |
| 160 |
199 base::Value* tmp = NULL; | 161 base::Value* tmp = NULL; |
200 if (!prefs_->Get(key, &tmp)) | 162 if (!prefs_->Get(key, &tmp)) |
201 return false; | 163 return false; |
202 | 164 |
203 if (result) | 165 if (result) |
204 *result = tmp; | 166 *result = tmp; |
205 return true; | 167 return true; |
206 } | 168 } |
207 | 169 |
208 void JsonPrefStore::AddObserver(PrefStore::Observer* observer) { | 170 void JsonPrefStore::AddObserver(PrefStore::Observer* observer) { |
| 171 DCHECK(CalledOnValidThread()); |
| 172 |
209 observers_.AddObserver(observer); | 173 observers_.AddObserver(observer); |
210 } | 174 } |
211 | 175 |
212 void JsonPrefStore::RemoveObserver(PrefStore::Observer* observer) { | 176 void JsonPrefStore::RemoveObserver(PrefStore::Observer* observer) { |
| 177 DCHECK(CalledOnValidThread()); |
| 178 |
213 observers_.RemoveObserver(observer); | 179 observers_.RemoveObserver(observer); |
214 } | 180 } |
215 | 181 |
216 bool JsonPrefStore::HasObservers() const { | 182 bool JsonPrefStore::HasObservers() const { |
| 183 DCHECK(CalledOnValidThread()); |
| 184 |
217 return observers_.might_have_observers(); | 185 return observers_.might_have_observers(); |
218 } | 186 } |
219 | 187 |
220 bool JsonPrefStore::IsInitializationComplete() const { | 188 bool JsonPrefStore::IsInitializationComplete() const { |
| 189 DCHECK(CalledOnValidThread()); |
| 190 |
221 return initialized_; | 191 return initialized_; |
222 } | 192 } |
223 | 193 |
224 bool JsonPrefStore::GetMutableValue(const std::string& key, | 194 bool JsonPrefStore::GetMutableValue(const std::string& key, |
225 base::Value** result) { | 195 base::Value** result) { |
| 196 DCHECK(CalledOnValidThread()); |
| 197 |
226 return prefs_->Get(key, result); | 198 return prefs_->Get(key, result); |
227 } | 199 } |
228 | 200 |
229 void JsonPrefStore::SetValue(const std::string& key, base::Value* value) { | 201 void JsonPrefStore::SetValue(const std::string& key, base::Value* value) { |
| 202 DCHECK(CalledOnValidThread()); |
| 203 |
230 DCHECK(value); | 204 DCHECK(value); |
231 scoped_ptr<base::Value> new_value(value); | 205 scoped_ptr<base::Value> new_value(value); |
232 base::Value* old_value = NULL; | 206 base::Value* old_value = NULL; |
233 prefs_->Get(key, &old_value); | 207 prefs_->Get(key, &old_value); |
234 if (!old_value || !value->Equals(old_value)) { | 208 if (!old_value || !value->Equals(old_value)) { |
235 prefs_->Set(key, new_value.release()); | 209 prefs_->Set(key, new_value.release()); |
236 ReportValueChanged(key); | 210 ReportValueChanged(key); |
237 } | 211 } |
238 } | 212 } |
239 | 213 |
240 void JsonPrefStore::SetValueSilently(const std::string& key, | 214 void JsonPrefStore::SetValueSilently(const std::string& key, |
241 base::Value* value) { | 215 base::Value* value) { |
| 216 DCHECK(CalledOnValidThread()); |
| 217 |
242 DCHECK(value); | 218 DCHECK(value); |
243 scoped_ptr<base::Value> new_value(value); | 219 scoped_ptr<base::Value> new_value(value); |
244 base::Value* old_value = NULL; | 220 base::Value* old_value = NULL; |
245 prefs_->Get(key, &old_value); | 221 prefs_->Get(key, &old_value); |
246 if (!old_value || !value->Equals(old_value)) { | 222 if (!old_value || !value->Equals(old_value)) { |
247 prefs_->Set(key, new_value.release()); | 223 prefs_->Set(key, new_value.release()); |
248 if (!read_only_) | 224 if (!read_only_) |
249 writer_.ScheduleWrite(this); | 225 writer_.ScheduleWrite(this); |
250 } | 226 } |
251 } | 227 } |
252 | 228 |
253 void JsonPrefStore::RemoveValue(const std::string& key) { | 229 void JsonPrefStore::RemoveValue(const std::string& key) { |
| 230 DCHECK(CalledOnValidThread()); |
| 231 |
254 if (prefs_->RemovePath(key, NULL)) | 232 if (prefs_->RemovePath(key, NULL)) |
255 ReportValueChanged(key); | 233 ReportValueChanged(key); |
256 } | 234 } |
257 | 235 |
258 void JsonPrefStore::RemoveValueSilently(const std::string& key) { | 236 void JsonPrefStore::RemoveValueSilently(const std::string& key) { |
| 237 DCHECK(CalledOnValidThread()); |
| 238 |
259 prefs_->RemovePath(key, NULL); | 239 prefs_->RemovePath(key, NULL); |
260 if (!read_only_) | 240 if (!read_only_) |
261 writer_.ScheduleWrite(this); | 241 writer_.ScheduleWrite(this); |
262 } | 242 } |
263 | 243 |
264 bool JsonPrefStore::ReadOnly() const { | 244 bool JsonPrefStore::ReadOnly() const { |
| 245 DCHECK(CalledOnValidThread()); |
| 246 |
265 return read_only_; | 247 return read_only_; |
266 } | 248 } |
267 | 249 |
268 PersistentPrefStore::PrefReadError JsonPrefStore::GetReadError() const { | 250 PersistentPrefStore::PrefReadError JsonPrefStore::GetReadError() const { |
| 251 DCHECK(CalledOnValidThread()); |
| 252 |
269 return read_error_; | 253 return read_error_; |
270 } | 254 } |
271 | 255 |
272 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() { | 256 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() { |
| 257 DCHECK(CalledOnValidThread()); |
| 258 |
273 if (path_.empty()) { | 259 if (path_.empty()) { |
274 OnFileRead( | 260 scoped_ptr<ReadResult> no_file_result; |
275 scoped_ptr<base::Value>(), PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); | 261 no_file_result->error = PREF_READ_ERROR_FILE_NOT_SPECIFIED; |
| 262 OnFileRead(no_file_result.Pass()); |
276 return PREF_READ_ERROR_FILE_NOT_SPECIFIED; | 263 return PREF_READ_ERROR_FILE_NOT_SPECIFIED; |
277 } | 264 } |
278 | 265 |
279 PrefReadError error; | 266 OnFileRead(ReadPrefsFromDisk(path_, alternate_path_)); |
280 bool no_dir; | 267 return filtering_in_progress_ ? PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE |
281 scoped_ptr<base::Value> value( | 268 : read_error_; |
282 FileThreadDeserializer::DoReading(path_, alternate_path_, &error, | |
283 &no_dir)); | |
284 OnFileRead(value.Pass(), error, no_dir); | |
285 return filtering_in_progress_ ? PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE : | |
286 error; | |
287 } | 269 } |
288 | 270 |
289 void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) { | 271 void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) { |
| 272 DCHECK(CalledOnValidThread()); |
| 273 |
290 initialized_ = false; | 274 initialized_ = false; |
291 error_delegate_.reset(error_delegate); | 275 error_delegate_.reset(error_delegate); |
292 if (path_.empty()) { | 276 if (path_.empty()) { |
293 OnFileRead( | 277 scoped_ptr<ReadResult> no_file_result; |
294 scoped_ptr<base::Value>(), PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); | 278 no_file_result->error = PREF_READ_ERROR_FILE_NOT_SPECIFIED; |
| 279 OnFileRead(no_file_result.Pass()); |
295 return; | 280 return; |
296 } | 281 } |
297 | 282 |
298 // Start async reading of the preferences file. It will delete itself | 283 base::PostTaskAndReplyWithResult( |
299 // in the end. | 284 sequenced_task_runner_, |
300 scoped_refptr<FileThreadDeserializer> deserializer( | 285 FROM_HERE, |
301 new FileThreadDeserializer(this, sequenced_task_runner_.get())); | 286 base::Bind(&ReadPrefsFromDisk, path_, alternate_path_), |
302 deserializer->Start(path_, alternate_path_); | 287 base::Bind(&JsonPrefStore::OnFileRead, this)); |
303 } | 288 } |
304 | 289 |
305 void JsonPrefStore::CommitPendingWrite() { | 290 void JsonPrefStore::CommitPendingWrite() { |
| 291 DCHECK(CalledOnValidThread()); |
| 292 |
306 if (writer_.HasPendingWrite() && !read_only_) | 293 if (writer_.HasPendingWrite() && !read_only_) |
307 writer_.DoScheduledWrite(); | 294 writer_.DoScheduledWrite(); |
308 } | 295 } |
309 | 296 |
310 void JsonPrefStore::ReportValueChanged(const std::string& key) { | 297 void JsonPrefStore::ReportValueChanged(const std::string& key) { |
| 298 DCHECK(CalledOnValidThread()); |
| 299 |
311 if (pref_filter_) | 300 if (pref_filter_) |
312 pref_filter_->FilterUpdate(key); | 301 pref_filter_->FilterUpdate(key); |
313 | 302 |
314 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); | 303 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); |
315 | 304 |
316 if (!read_only_) | 305 if (!read_only_) |
317 writer_.ScheduleWrite(this); | 306 writer_.ScheduleWrite(this); |
318 } | 307 } |
319 | 308 |
320 void JsonPrefStore::RegisterOnNextSuccessfulWriteCallback( | 309 void JsonPrefStore::RegisterOnNextSuccessfulWriteCallback( |
321 const base::Closure& on_next_successful_write) { | 310 const base::Closure& on_next_successful_write) { |
| 311 DCHECK(CalledOnValidThread()); |
| 312 |
322 writer_.RegisterOnNextSuccessfulWriteCallback(on_next_successful_write); | 313 writer_.RegisterOnNextSuccessfulWriteCallback(on_next_successful_write); |
323 } | 314 } |
324 | 315 |
325 void JsonPrefStore::OnFileRead(scoped_ptr<base::Value> value, | 316 void JsonPrefStore::OnFileRead(scoped_ptr<ReadResult> read_result) { |
326 PersistentPrefStore::PrefReadError error, | 317 DCHECK(CalledOnValidThread()); |
327 bool no_dir) { | 318 |
| 319 DCHECK(read_result); |
| 320 |
328 scoped_ptr<base::DictionaryValue> unfiltered_prefs(new base::DictionaryValue); | 321 scoped_ptr<base::DictionaryValue> unfiltered_prefs(new base::DictionaryValue); |
329 | 322 |
330 read_error_ = error; | 323 read_error_ = read_result->error; |
331 | 324 |
332 bool initialization_successful = !no_dir; | 325 bool initialization_successful = !read_result->no_dir; |
333 | 326 |
334 if (initialization_successful) { | 327 if (initialization_successful) { |
335 switch (read_error_) { | 328 switch (read_error_) { |
336 case PREF_READ_ERROR_ACCESS_DENIED: | 329 case PREF_READ_ERROR_ACCESS_DENIED: |
337 case PREF_READ_ERROR_FILE_OTHER: | 330 case PREF_READ_ERROR_FILE_OTHER: |
338 case PREF_READ_ERROR_FILE_LOCKED: | 331 case PREF_READ_ERROR_FILE_LOCKED: |
339 case PREF_READ_ERROR_JSON_TYPE: | 332 case PREF_READ_ERROR_JSON_TYPE: |
340 case PREF_READ_ERROR_FILE_NOT_SPECIFIED: | 333 case PREF_READ_ERROR_FILE_NOT_SPECIFIED: |
341 read_only_ = true; | 334 read_only_ = true; |
342 break; | 335 break; |
343 case PREF_READ_ERROR_NONE: | 336 case PREF_READ_ERROR_NONE: |
344 DCHECK(value.get()); | 337 DCHECK(read_result->value.get()); |
345 unfiltered_prefs.reset( | 338 unfiltered_prefs.reset( |
346 static_cast<base::DictionaryValue*>(value.release())); | 339 static_cast<base::DictionaryValue*>(read_result->value.release())); |
347 break; | 340 break; |
348 case PREF_READ_ERROR_NO_FILE: | 341 case PREF_READ_ERROR_NO_FILE: |
349 // If the file just doesn't exist, maybe this is first run. In any case | 342 // If the file just doesn't exist, maybe this is first run. In any case |
350 // there's no harm in writing out default prefs in this case. | 343 // there's no harm in writing out default prefs in this case. |
351 break; | 344 break; |
352 case PREF_READ_ERROR_JSON_PARSE: | 345 case PREF_READ_ERROR_JSON_PARSE: |
353 case PREF_READ_ERROR_JSON_REPEAT: | 346 case PREF_READ_ERROR_JSON_REPEAT: |
354 break; | 347 break; |
355 case PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE: | 348 case PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE: |
356 // This is a special error code to be returned by ReadPrefs when it | 349 // This is a special error code to be returned by ReadPrefs when it |
(...skipping 22 matching lines...) Expand all Loading... |
379 } else { | 372 } else { |
380 FinalizeFileRead(initialization_successful, unfiltered_prefs.Pass(), false); | 373 FinalizeFileRead(initialization_successful, unfiltered_prefs.Pass(), false); |
381 } | 374 } |
382 } | 375 } |
383 | 376 |
384 JsonPrefStore::~JsonPrefStore() { | 377 JsonPrefStore::~JsonPrefStore() { |
385 CommitPendingWrite(); | 378 CommitPendingWrite(); |
386 } | 379 } |
387 | 380 |
388 bool JsonPrefStore::SerializeData(std::string* output) { | 381 bool JsonPrefStore::SerializeData(std::string* output) { |
| 382 DCHECK(CalledOnValidThread()); |
| 383 |
389 if (pref_filter_) | 384 if (pref_filter_) |
390 pref_filter_->FilterSerializeData(prefs_.get()); | 385 pref_filter_->FilterSerializeData(prefs_.get()); |
391 | 386 |
392 JSONStringValueSerializer serializer(output); | 387 JSONStringValueSerializer serializer(output); |
393 serializer.set_pretty_print(true); | 388 serializer.set_pretty_print(true); |
394 bool result = serializer.Serialize(*prefs_); | 389 bool result = serializer.Serialize(*prefs_); |
395 | 390 |
396 if (result) { | 391 if (result) { |
397 std::string spaceless_basename; | 392 std::string spaceless_basename; |
398 base::ReplaceChars(path_.BaseName().MaybeAsASCII(), " ", "_", | 393 base::ReplaceChars(path_.BaseName().MaybeAsASCII(), " ", "_", |
(...skipping 11 matching lines...) Expand all Loading... |
410 base::HistogramBase::kUmaTargetedHistogramFlag); | 405 base::HistogramBase::kUmaTargetedHistogramFlag); |
411 histogram->Add(static_cast<int>(output->size()) / 1024); | 406 histogram->Add(static_cast<int>(output->size()) / 1024); |
412 } | 407 } |
413 | 408 |
414 return result; | 409 return result; |
415 } | 410 } |
416 | 411 |
417 void JsonPrefStore::FinalizeFileRead(bool initialization_successful, | 412 void JsonPrefStore::FinalizeFileRead(bool initialization_successful, |
418 scoped_ptr<base::DictionaryValue> prefs, | 413 scoped_ptr<base::DictionaryValue> prefs, |
419 bool schedule_write) { | 414 bool schedule_write) { |
| 415 DCHECK(CalledOnValidThread()); |
| 416 |
420 filtering_in_progress_ = false; | 417 filtering_in_progress_ = false; |
421 | 418 |
422 if (!initialization_successful) { | 419 if (!initialization_successful) { |
423 FOR_EACH_OBSERVER(PrefStore::Observer, | 420 FOR_EACH_OBSERVER(PrefStore::Observer, |
424 observers_, | 421 observers_, |
425 OnInitializationCompleted(false)); | 422 OnInitializationCompleted(false)); |
426 return; | 423 return; |
427 } | 424 } |
428 | 425 |
429 prefs_ = prefs.Pass(); | 426 prefs_ = prefs.Pass(); |
430 | 427 |
431 initialized_ = true; | 428 initialized_ = true; |
432 | 429 |
433 if (schedule_write && !read_only_) | 430 if (schedule_write && !read_only_) |
434 writer_.ScheduleWrite(this); | 431 writer_.ScheduleWrite(this); |
435 | 432 |
436 if (error_delegate_ && read_error_ != PREF_READ_ERROR_NONE) | 433 if (error_delegate_ && read_error_ != PREF_READ_ERROR_NONE) |
437 error_delegate_->OnError(read_error_); | 434 error_delegate_->OnError(read_error_); |
438 | 435 |
439 FOR_EACH_OBSERVER(PrefStore::Observer, | 436 FOR_EACH_OBSERVER(PrefStore::Observer, |
440 observers_, | 437 observers_, |
441 OnInitializationCompleted(true)); | 438 OnInitializationCompleted(true)); |
442 | 439 |
443 return; | 440 return; |
444 } | 441 } |
OLD | NEW |