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

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: comment nit 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
« no previous file with comments | « base/prefs/json_pref_store.h ('k') | base/prefs/json_pref_store_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 filtering_in_progress_(false),
167 read_error_(PREF_READ_ERROR_NONE) {
168 }
165 169
166 bool JsonPrefStore::GetValue(const std::string& key, 170 bool JsonPrefStore::GetValue(const std::string& key,
167 const base::Value** result) const { 171 const base::Value** result) const {
168 base::Value* tmp = NULL; 172 base::Value* tmp = NULL;
169 if (!prefs_->Get(key, &tmp)) 173 if (!prefs_->Get(key, &tmp))
170 return false; 174 return false;
171 175
172 if (result) 176 if (result)
173 *result = tmp; 177 *result = tmp;
174 return true; 178 return true;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 if (!read_only_) 221 if (!read_only_)
218 writer_.ScheduleWrite(this); 222 writer_.ScheduleWrite(this);
219 } 223 }
220 } 224 }
221 225
222 void JsonPrefStore::RemoveValue(const std::string& key) { 226 void JsonPrefStore::RemoveValue(const std::string& key) {
223 if (prefs_->RemovePath(key, NULL)) 227 if (prefs_->RemovePath(key, NULL))
224 ReportValueChanged(key); 228 ReportValueChanged(key);
225 } 229 }
226 230
231 void JsonPrefStore::RemoveValueSilently(const std::string& key) {
232 prefs_->RemovePath(key, NULL);
233 if (!read_only_)
234 writer_.ScheduleWrite(this);
235 }
236
227 bool JsonPrefStore::ReadOnly() const { 237 bool JsonPrefStore::ReadOnly() const {
228 return read_only_; 238 return read_only_;
229 } 239 }
230 240
231 PersistentPrefStore::PrefReadError JsonPrefStore::GetReadError() const { 241 PersistentPrefStore::PrefReadError JsonPrefStore::GetReadError() const {
232 return read_error_; 242 return read_error_;
233 } 243 }
234 244
235 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() { 245 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() {
236 if (path_.empty()) { 246 if (path_.empty()) {
237 OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); 247 OnFileRead(
248 scoped_ptr<base::Value>(), PREF_READ_ERROR_FILE_NOT_SPECIFIED, false);
238 return PREF_READ_ERROR_FILE_NOT_SPECIFIED; 249 return PREF_READ_ERROR_FILE_NOT_SPECIFIED;
239 } 250 }
240 251
241 PrefReadError error; 252 PrefReadError error;
242 bool no_dir; 253 bool no_dir;
243 base::Value* value = 254 scoped_ptr<base::Value> value(
244 FileThreadDeserializer::DoReading(path_, &error, &no_dir); 255 FileThreadDeserializer::DoReading(path_, &error, &no_dir));
245 OnFileRead(value, error, no_dir); 256 OnFileRead(value.Pass(), error, no_dir);
246 return error; 257 return filtering_in_progress_ ? PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE :
258 error;
247 } 259 }
248 260
249 void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate *error_delegate) { 261 void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) {
250 initialized_ = false; 262 initialized_ = false;
251 error_delegate_.reset(error_delegate); 263 error_delegate_.reset(error_delegate);
252 if (path_.empty()) { 264 if (path_.empty()) {
253 OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); 265 OnFileRead(
266 scoped_ptr<base::Value>(), PREF_READ_ERROR_FILE_NOT_SPECIFIED, false);
254 return; 267 return;
255 } 268 }
256 269
257 // Start async reading of the preferences file. It will delete itself 270 // Start async reading of the preferences file. It will delete itself
258 // in the end. 271 // in the end.
259 scoped_refptr<FileThreadDeserializer> deserializer( 272 scoped_refptr<FileThreadDeserializer> deserializer(
260 new FileThreadDeserializer(this, sequenced_task_runner_.get())); 273 new FileThreadDeserializer(this, sequenced_task_runner_.get()));
261 deserializer->Start(path_); 274 deserializer->Start(path_);
262 } 275 }
263 276
264 void JsonPrefStore::CommitPendingWrite() { 277 void JsonPrefStore::CommitPendingWrite() {
265 if (writer_.HasPendingWrite() && !read_only_) 278 if (writer_.HasPendingWrite() && !read_only_)
266 writer_.DoScheduledWrite(); 279 writer_.DoScheduledWrite();
267 } 280 }
268 281
269 void JsonPrefStore::ReportValueChanged(const std::string& key) { 282 void JsonPrefStore::ReportValueChanged(const std::string& key) {
270 if (pref_filter_) 283 if (pref_filter_)
271 pref_filter_->FilterUpdate(key); 284 pref_filter_->FilterUpdate(key);
272 285
273 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); 286 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key));
274 287
275 if (!read_only_) 288 if (!read_only_)
276 writer_.ScheduleWrite(this); 289 writer_.ScheduleWrite(this);
277 } 290 }
278 291
279 void JsonPrefStore::OnFileRead(base::Value* value_owned, 292 void JsonPrefStore::RegisterOnNextSuccessfulWriteCallback(
293 const base::Closure& on_next_successful_write) {
294 writer_.RegisterOnNextSuccessfulWriteCallback(on_next_successful_write);
295 }
296
297 void JsonPrefStore::OnFileRead(scoped_ptr<base::Value> value,
280 PersistentPrefStore::PrefReadError error, 298 PersistentPrefStore::PrefReadError error,
281 bool no_dir) { 299 bool no_dir) {
282 scoped_ptr<base::Value> value(value_owned); 300 scoped_ptr<base::DictionaryValue> unfiltered_prefs(new base::DictionaryValue);
301
283 read_error_ = error; 302 read_error_ = error;
284 303
285 if (no_dir) { 304 bool initialization_successful = !no_dir;
286 FOR_EACH_OBSERVER(PrefStore::Observer, 305
287 observers_, 306 if (initialization_successful) {
288 OnInitializationCompleted(false)); 307 switch (read_error_) {
289 return; 308 case PREF_READ_ERROR_ACCESS_DENIED:
309 case PREF_READ_ERROR_FILE_OTHER:
310 case PREF_READ_ERROR_FILE_LOCKED:
311 case PREF_READ_ERROR_JSON_TYPE:
312 case PREF_READ_ERROR_FILE_NOT_SPECIFIED:
313 read_only_ = true;
314 break;
315 case PREF_READ_ERROR_NONE:
316 DCHECK(value.get());
317 unfiltered_prefs.reset(
318 static_cast<base::DictionaryValue*>(value.release()));
319 break;
320 case PREF_READ_ERROR_NO_FILE:
321 // If the file just doesn't exist, maybe this is first run. In any case
322 // there's no harm in writing out default prefs in this case.
323 break;
324 case PREF_READ_ERROR_JSON_PARSE:
325 case PREF_READ_ERROR_JSON_REPEAT:
326 break;
327 case PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE:
328 // This is a special error code to be returned by ReadPrefs when it
329 // can't complete synchronously, it should never be returned by the read
330 // operation itself.
331 NOTREACHED();
332 break;
333 case PREF_READ_ERROR_MAX_ENUM:
334 NOTREACHED();
335 break;
336 }
290 } 337 }
291 338
292 initialized_ = true; 339 if (pref_filter_) {
293 340 filtering_in_progress_ = true;
294 switch (error) { 341 const PrefFilter::PostFilterOnLoadCallback post_filter_on_load_callback(
295 case PREF_READ_ERROR_ACCESS_DENIED: 342 base::Bind(
296 case PREF_READ_ERROR_FILE_OTHER: 343 &JsonPrefStore::FinalizeFileRead, this, initialization_successful));
297 case PREF_READ_ERROR_FILE_LOCKED: 344 pref_filter_->FilterOnLoad(post_filter_on_load_callback,
298 case PREF_READ_ERROR_JSON_TYPE: 345 unfiltered_prefs.Pass());
299 case PREF_READ_ERROR_FILE_NOT_SPECIFIED: 346 } else {
300 read_only_ = true; 347 FinalizeFileRead(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 } 348 }
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 } 349 }
327 350
328 JsonPrefStore::~JsonPrefStore() { 351 JsonPrefStore::~JsonPrefStore() {
329 CommitPendingWrite(); 352 CommitPendingWrite();
330 } 353 }
331 354
332 bool JsonPrefStore::SerializeData(std::string* output) { 355 bool JsonPrefStore::SerializeData(std::string* output) {
333 if (pref_filter_) 356 if (pref_filter_)
334 pref_filter_->FilterSerializeData(prefs_.get()); 357 pref_filter_->FilterSerializeData(prefs_.get());
335 358
336 JSONStringValueSerializer serializer(output); 359 JSONStringValueSerializer serializer(output);
337 serializer.set_pretty_print(true); 360 serializer.set_pretty_print(true);
338 return serializer.Serialize(*prefs_); 361 return serializer.Serialize(*prefs_);
339 } 362 }
363
364 void JsonPrefStore::FinalizeFileRead(bool initialization_successful,
365 scoped_ptr<base::DictionaryValue> prefs,
366 bool schedule_write) {
367 filtering_in_progress_ = false;
368
369 if (!initialization_successful) {
370 FOR_EACH_OBSERVER(PrefStore::Observer,
371 observers_,
372 OnInitializationCompleted(false));
373 return;
374 }
375
376 prefs_ = prefs.Pass();
377
378 initialized_ = true;
379
380 if (schedule_write && !read_only_)
381 writer_.ScheduleWrite(this);
382
383 if (error_delegate_ && read_error_ != PREF_READ_ERROR_NONE)
384 error_delegate_->OnError(read_error_);
385
386 FOR_EACH_OBSERVER(PrefStore::Observer,
387 observers_,
388 OnInitializationCompleted(true));
389
390 return;
391 }
OLDNEW
« no previous file with comments | « base/prefs/json_pref_store.h ('k') | base/prefs/json_pref_store_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698