Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(431)

Side by Side Diff: base/prefs/json_pref_store.cc

Issue 257003007: Introduce a new framework for back-and-forth tracked/protected preferences migration. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix some tests -- more to come Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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"
(...skipping 21 matching lines...) Expand all
32 base::SequencedTaskRunner* sequenced_task_runner) 32 base::SequencedTaskRunner* sequenced_task_runner)
33 : no_dir_(false), 33 : no_dir_(false),
34 error_(PersistentPrefStore::PREF_READ_ERROR_NONE), 34 error_(PersistentPrefStore::PREF_READ_ERROR_NONE),
35 delegate_(delegate), 35 delegate_(delegate),
36 sequenced_task_runner_(sequenced_task_runner), 36 sequenced_task_runner_(sequenced_task_runner),
37 origin_loop_proxy_(base::MessageLoopProxy::current()) { 37 origin_loop_proxy_(base::MessageLoopProxy::current()) {
38 } 38 }
39 39
40 void Start(const base::FilePath& path) { 40 void Start(const base::FilePath& path) {
41 DCHECK(origin_loop_proxy_->BelongsToCurrentThread()); 41 DCHECK(origin_loop_proxy_->BelongsToCurrentThread());
42 // TODO(gab): This should use PostTaskAndReplyWithResult instead of using
43 // the |error_| member to pass data across tasks.
42 sequenced_task_runner_->PostTask( 44 sequenced_task_runner_->PostTask(
43 FROM_HERE, 45 FROM_HERE,
44 base::Bind(&FileThreadDeserializer::ReadFileAndReport, 46 base::Bind(&FileThreadDeserializer::ReadFileAndReport,
45 this, path)); 47 this, path));
46 } 48 }
47 49
48 // Deserializes JSON on the sequenced task runner. 50 // Deserializes JSON on the sequenced task runner.
49 void ReadFileAndReport(const base::FilePath& path) { 51 void ReadFileAndReport(const base::FilePath& path) {
50 DCHECK(sequenced_task_runner_->RunsTasksOnCurrentThread()); 52 DCHECK(sequenced_task_runner_->RunsTasksOnCurrentThread());
51 53
52 value_.reset(DoReading(path, &error_, &no_dir_)); 54 value_.reset(DoReading(path, &error_, &no_dir_));
53 55
54 origin_loop_proxy_->PostTask( 56 origin_loop_proxy_->PostTask(
55 FROM_HERE, 57 FROM_HERE,
56 base::Bind(&FileThreadDeserializer::ReportOnOriginThread, this)); 58 base::Bind(&FileThreadDeserializer::ReportOnOriginThread, this));
57 } 59 }
58 60
59 // Reports deserialization result on the origin thread. 61 // Reports deserialization result on the origin thread.
60 void ReportOnOriginThread() { 62 void ReportOnOriginThread() {
61 DCHECK(origin_loop_proxy_->BelongsToCurrentThread()); 63 DCHECK(origin_loop_proxy_->BelongsToCurrentThread());
62 delegate_->OnFileRead(value_.release(), error_, no_dir_); 64 delegate_->OnFileRead(value_.Pass(), error_, no_dir_);
63 } 65 }
64 66
65 static base::Value* DoReading(const base::FilePath& path, 67 static base::Value* DoReading(const base::FilePath& path,
66 PersistentPrefStore::PrefReadError* error, 68 PersistentPrefStore::PrefReadError* error,
67 bool* no_dir) { 69 bool* no_dir) {
68 int error_code; 70 int error_code;
69 std::string error_msg; 71 std::string error_msg;
70 JSONFileValueSerializer serializer(path); 72 JSONFileValueSerializer serializer(path);
71 base::Value* value = serializer.Deserialize(&error_code, &error_msg); 73 base::Value* value = serializer.Deserialize(&error_code, &error_msg);
72 HandleErrors(value, path, error_code, error_msg, error); 74 HandleErrors(value, path, error_code, error_msg, error);
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 JsonPrefStore::JsonPrefStore(const base::FilePath& filename, 156 JsonPrefStore::JsonPrefStore(const base::FilePath& filename,
155 base::SequencedTaskRunner* sequenced_task_runner, 157 base::SequencedTaskRunner* sequenced_task_runner,
156 scoped_ptr<PrefFilter> pref_filter) 158 scoped_ptr<PrefFilter> pref_filter)
157 : path_(filename), 159 : path_(filename),
158 sequenced_task_runner_(sequenced_task_runner), 160 sequenced_task_runner_(sequenced_task_runner),
159 prefs_(new base::DictionaryValue()), 161 prefs_(new base::DictionaryValue()),
160 read_only_(false), 162 read_only_(false),
161 writer_(filename, sequenced_task_runner), 163 writer_(filename, sequenced_task_runner),
162 pref_filter_(pref_filter.Pass()), 164 pref_filter_(pref_filter.Pass()),
163 initialized_(false), 165 initialized_(false),
164 read_error_(PREF_READ_ERROR_OTHER) {} 166 read_error_(PREF_READ_ERROR_NONE) {
167 }
165 168
166 bool JsonPrefStore::GetValue(const std::string& key, 169 bool JsonPrefStore::GetValue(const std::string& key,
167 const base::Value** result) const { 170 const base::Value** result) const {
168 base::Value* tmp = NULL; 171 base::Value* tmp = NULL;
169 if (!prefs_->Get(key, &tmp)) 172 if (!prefs_->Get(key, &tmp))
170 return false; 173 return false;
171 174
172 if (result) 175 if (result)
173 *result = tmp; 176 *result = tmp;
174 return true; 177 return true;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 if (!read_only_) 220 if (!read_only_)
218 writer_.ScheduleWrite(this); 221 writer_.ScheduleWrite(this);
219 } 222 }
220 } 223 }
221 224
222 void JsonPrefStore::RemoveValue(const std::string& key) { 225 void JsonPrefStore::RemoveValue(const std::string& key) {
223 if (prefs_->RemovePath(key, NULL)) 226 if (prefs_->RemovePath(key, NULL))
224 ReportValueChanged(key); 227 ReportValueChanged(key);
225 } 228 }
226 229
230 void JsonPrefStore::RemoveValueSilently(const std::string& key) {
231 prefs_->RemovePath(key, NULL);
232 if (!read_only_)
233 writer_.ScheduleWrite(this);
234 }
235
227 bool JsonPrefStore::ReadOnly() const { 236 bool JsonPrefStore::ReadOnly() const {
228 return read_only_; 237 return read_only_;
229 } 238 }
230 239
231 PersistentPrefStore::PrefReadError JsonPrefStore::GetReadError() const { 240 PersistentPrefStore::PrefReadError JsonPrefStore::GetReadError() const {
232 return read_error_; 241 return read_error_;
233 } 242 }
234 243
235 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() { 244 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() {
236 if (path_.empty()) { 245 if (path_.empty()) {
237 OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); 246 OnFileRead(
247 scoped_ptr<base::Value>(), PREF_READ_ERROR_FILE_NOT_SPECIFIED, false);
238 return PREF_READ_ERROR_FILE_NOT_SPECIFIED; 248 return PREF_READ_ERROR_FILE_NOT_SPECIFIED;
239 } 249 }
240 250
241 PrefReadError error; 251 PrefReadError error;
242 bool no_dir; 252 bool no_dir;
243 base::Value* value = 253 scoped_ptr<base::Value> value(
244 FileThreadDeserializer::DoReading(path_, &error, &no_dir); 254 FileThreadDeserializer::DoReading(path_, &error, &no_dir));
245 OnFileRead(value, error, no_dir); 255 OnFileRead(value.Pass(), error, no_dir);
246 return error; 256 return error;
247 } 257 }
248 258
249 void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate *error_delegate) { 259 void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) {
250 initialized_ = false; 260 initialized_ = false;
251 error_delegate_.reset(error_delegate); 261 error_delegate_.reset(error_delegate);
252 if (path_.empty()) { 262 if (path_.empty()) {
253 OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); 263 OnFileRead(
264 scoped_ptr<base::Value>(), PREF_READ_ERROR_FILE_NOT_SPECIFIED, false);
254 return; 265 return;
255 } 266 }
256 267
257 // Start async reading of the preferences file. It will delete itself 268 // Start async reading of the preferences file. It will delete itself
258 // in the end. 269 // in the end.
259 scoped_refptr<FileThreadDeserializer> deserializer( 270 scoped_refptr<FileThreadDeserializer> deserializer(
260 new FileThreadDeserializer(this, sequenced_task_runner_.get())); 271 new FileThreadDeserializer(this, sequenced_task_runner_.get()));
261 deserializer->Start(path_); 272 deserializer->Start(path_);
262 } 273 }
263 274
264 void JsonPrefStore::CommitPendingWrite() { 275 void JsonPrefStore::CommitPendingWrite() {
265 if (writer_.HasPendingWrite() && !read_only_) 276 if (writer_.HasPendingWrite() && !read_only_)
266 writer_.DoScheduledWrite(); 277 writer_.DoScheduledWrite();
267 } 278 }
268 279
269 void JsonPrefStore::ReportValueChanged(const std::string& key) { 280 void JsonPrefStore::ReportValueChanged(const std::string& key) {
270 if (pref_filter_) 281 if (pref_filter_)
271 pref_filter_->FilterUpdate(key); 282 pref_filter_->FilterUpdate(key);
272 283
273 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); 284 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key));
274 285
275 if (!read_only_) 286 if (!read_only_)
276 writer_.ScheduleWrite(this); 287 writer_.ScheduleWrite(this);
277 } 288 }
278 289
279 void JsonPrefStore::OnFileRead(base::Value* value_owned, 290 void JsonPrefStore::RegisterOnNextSuccessfulWriteCallback(
291 const base::Closure& on_next_successful_write) {
292 writer_.RegisterOnNextSuccessfulWriteCallback(on_next_successful_write);
293 }
294
295 void JsonPrefStore::OnFileRead(scoped_ptr<base::Value> value,
280 PersistentPrefStore::PrefReadError error, 296 PersistentPrefStore::PrefReadError error,
281 bool no_dir) { 297 bool no_dir) {
282 scoped_ptr<base::Value> value(value_owned); 298 scoped_ptr<base::DictionaryValue> unfiltered_prefs(
299 new base::DictionaryValue);
300
283 read_error_ = error; 301 read_error_ = error;
284 302
285 if (no_dir) { 303 bool initialization_successful = !no_dir;
286 FOR_EACH_OBSERVER(PrefStore::Observer, 304
287 observers_, 305 if (initialization_successful) {
288 OnInitializationCompleted(false)); 306 switch (error) {
289 return; 307 case PREF_READ_ERROR_ACCESS_DENIED:
308 case PREF_READ_ERROR_FILE_OTHER:
309 case PREF_READ_ERROR_FILE_LOCKED:
310 case PREF_READ_ERROR_JSON_TYPE:
311 case PREF_READ_ERROR_FILE_NOT_SPECIFIED:
312 read_only_ = true;
313 break;
314 case PREF_READ_ERROR_NONE:
315 DCHECK(value.get());
316 unfiltered_prefs.reset(
317 static_cast<base::DictionaryValue*>(value.release()));
318 break;
319 case PREF_READ_ERROR_NO_FILE:
320 // If the file just doesn't exist, maybe this is first run. In any case
321 // there's no harm in writing out default prefs in this case.
322 break;
323 case PREF_READ_ERROR_JSON_PARSE:
324 case PREF_READ_ERROR_JSON_REPEAT:
325 break;
326 case PREF_READ_ERROR_MAX_ENUM:
327 NOTREACHED();
328 break;
329 }
290 } 330 }
291 331
292 initialized_ = true; 332 if (pref_filter_) {
293 333 const PrefFilter::PostFilterOnLoadCallback post_filter_on_load_callback(
294 switch (error) { 334 base::Bind(
295 case PREF_READ_ERROR_ACCESS_DENIED: 335 &JsonPrefStore::FinalizeFileRead, this, initialization_successful));
296 case PREF_READ_ERROR_FILE_OTHER: 336 pref_filter_->FilterOnLoad(post_filter_on_load_callback,
297 case PREF_READ_ERROR_FILE_LOCKED: 337 unfiltered_prefs.Pass());
298 case PREF_READ_ERROR_JSON_TYPE: 338 } else {
299 case PREF_READ_ERROR_FILE_NOT_SPECIFIED: 339 FinalizeFileRead(
300 read_only_ = true; 340 initialization_successful, unfiltered_prefs.Pass(), false);
301 break;
302 case PREF_READ_ERROR_NONE:
303 DCHECK(value.get());
304 prefs_.reset(static_cast<base::DictionaryValue*>(value.release()));
305 break;
306 case PREF_READ_ERROR_NO_FILE:
307 // If the file just doesn't exist, maybe this is first run. In any case
308 // there's no harm in writing out default prefs in this case.
309 break;
310 case PREF_READ_ERROR_JSON_PARSE:
311 case PREF_READ_ERROR_JSON_REPEAT:
312 break;
313 default:
314 NOTREACHED() << "Unknown error: " << error;
315 } 341 }
316
317 if (pref_filter_ && pref_filter_->FilterOnLoad(prefs_.get()))
318 writer_.ScheduleWrite(this);
319
320 if (error_delegate_.get() && error != PREF_READ_ERROR_NONE)
321 error_delegate_->OnError(error);
322
323 FOR_EACH_OBSERVER(PrefStore::Observer,
324 observers_,
325 OnInitializationCompleted(true));
326 } 342 }
327 343
328 JsonPrefStore::~JsonPrefStore() { 344 JsonPrefStore::~JsonPrefStore() {
329 CommitPendingWrite(); 345 CommitPendingWrite();
330 } 346 }
331 347
332 bool JsonPrefStore::SerializeData(std::string* output) { 348 bool JsonPrefStore::SerializeData(std::string* output) {
333 if (pref_filter_) 349 if (pref_filter_)
334 pref_filter_->FilterSerializeData(prefs_.get()); 350 pref_filter_->FilterSerializeData(prefs_.get());
335 351
336 JSONStringValueSerializer serializer(output); 352 JSONStringValueSerializer serializer(output);
337 serializer.set_pretty_print(true); 353 serializer.set_pretty_print(true);
338 return serializer.Serialize(*prefs_); 354 return serializer.Serialize(*prefs_);
339 } 355 }
356
357 void JsonPrefStore::FinalizeFileRead(bool initialization_successful,
358 scoped_ptr<base::DictionaryValue> prefs,
359 bool schedule_write) {
360 if (!initialization_successful) {
361 FOR_EACH_OBSERVER(PrefStore::Observer,
362 observers_,
363 OnInitializationCompleted(false));
364 return;
365 }
366
367 prefs_ = prefs.Pass();
368
369 initialized_ = true;
370
371 if (schedule_write && !read_only_)
372 writer_.ScheduleWrite(this);
373
374 if (error_delegate_ && read_error_ != PREF_READ_ERROR_NONE)
375 error_delegate_->OnError(read_error_);
376
377 FOR_EACH_OBSERVER(PrefStore::Observer,
378 observers_,
379 OnInitializationCompleted(true));
380
381 return;
382 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698