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

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 ios compile for realz?! 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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 value_.reset(DoReading(path, &error_, &no_dir_)); 52 value_.reset(DoReading(path, &error_, &no_dir_));
53 53
54 origin_loop_proxy_->PostTask( 54 origin_loop_proxy_->PostTask(
55 FROM_HERE, 55 FROM_HERE,
56 base::Bind(&FileThreadDeserializer::ReportOnOriginThread, this)); 56 base::Bind(&FileThreadDeserializer::ReportOnOriginThread, this));
57 } 57 }
58 58
59 // Reports deserialization result on the origin thread. 59 // Reports deserialization result on the origin thread.
60 void ReportOnOriginThread() { 60 void ReportOnOriginThread() {
61 DCHECK(origin_loop_proxy_->BelongsToCurrentThread()); 61 DCHECK(origin_loop_proxy_->BelongsToCurrentThread());
62 delegate_->OnFileRead(value_.release(), error_, no_dir_); 62 // TODO(gab): There is a race condition in error reporting here as |error_|
63 // is initialized on the origin thread, set on the task runner's thread in
64 // HandleErrors(), and then read here on the origin thread again with no
65 // synchronization barriers (which means we potentially report
66 // PREF_READ_ERROR_NONE when there actually was an error).
Bernhard Bauer 2014/05/01 12:37:09 Huh, why is that? Doing PostTask should guarantee
gab 2014/05/01 15:34:54 Right, not a race condition in the sense that they
Bernhard Bauer 2014/05/01 20:16:00 I think it's already correct as it currently is, o
gab 2014/05/02 04:15:01 Oh I see, this is very well hidden side-effect of
67 delegate_->OnFileRead(value_.Pass(), error_, no_dir_);
63 } 68 }
64 69
65 static base::Value* DoReading(const base::FilePath& path, 70 static base::Value* DoReading(const base::FilePath& path,
66 PersistentPrefStore::PrefReadError* error, 71 PersistentPrefStore::PrefReadError* error,
67 bool* no_dir) { 72 bool* no_dir) {
68 int error_code; 73 int error_code;
69 std::string error_msg; 74 std::string error_msg;
70 JSONFileValueSerializer serializer(path); 75 JSONFileValueSerializer serializer(path);
71 base::Value* value = serializer.Deserialize(&error_code, &error_msg); 76 base::Value* value = serializer.Deserialize(&error_code, &error_msg);
72 HandleErrors(value, path, error_code, error_msg, error); 77 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, 159 JsonPrefStore::JsonPrefStore(const base::FilePath& filename,
155 base::SequencedTaskRunner* sequenced_task_runner, 160 base::SequencedTaskRunner* sequenced_task_runner,
156 scoped_ptr<PrefFilter> pref_filter) 161 scoped_ptr<PrefFilter> pref_filter)
157 : path_(filename), 162 : path_(filename),
158 sequenced_task_runner_(sequenced_task_runner), 163 sequenced_task_runner_(sequenced_task_runner),
159 prefs_(new base::DictionaryValue()), 164 prefs_(new base::DictionaryValue()),
160 read_only_(false), 165 read_only_(false),
161 writer_(filename, sequenced_task_runner), 166 writer_(filename, sequenced_task_runner),
162 pref_filter_(pref_filter.Pass()), 167 pref_filter_(pref_filter.Pass()),
163 initialized_(false), 168 initialized_(false),
164 read_error_(PREF_READ_ERROR_OTHER) {} 169 read_error_(PREF_READ_ERROR_NONE),
170 weak_factory_(this) {}
165 171
166 bool JsonPrefStore::GetValue(const std::string& key, 172 bool JsonPrefStore::GetValue(const std::string& key,
167 const base::Value** result) const { 173 const base::Value** result) const {
168 base::Value* tmp = NULL; 174 base::Value* tmp = NULL;
169 if (!prefs_->Get(key, &tmp)) 175 if (!prefs_->Get(key, &tmp))
170 return false; 176 return false;
171 177
172 if (result) 178 if (result)
173 *result = tmp; 179 *result = tmp;
174 return true; 180 return true;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 if (!read_only_) 223 if (!read_only_)
218 writer_.ScheduleWrite(this); 224 writer_.ScheduleWrite(this);
219 } 225 }
220 } 226 }
221 227
222 void JsonPrefStore::RemoveValue(const std::string& key) { 228 void JsonPrefStore::RemoveValue(const std::string& key) {
223 if (prefs_->RemovePath(key, NULL)) 229 if (prefs_->RemovePath(key, NULL))
224 ReportValueChanged(key); 230 ReportValueChanged(key);
225 } 231 }
226 232
233 void JsonPrefStore::RemoveValueSilently(const std::string& key) {
234 prefs_->RemovePath(key, NULL);
235 if (!read_only_)
236 writer_.ScheduleWrite(this);
237 }
238
227 bool JsonPrefStore::ReadOnly() const { 239 bool JsonPrefStore::ReadOnly() const {
228 return read_only_; 240 return read_only_;
229 } 241 }
230 242
231 PersistentPrefStore::PrefReadError JsonPrefStore::GetReadError() const { 243 PersistentPrefStore::PrefReadError JsonPrefStore::GetReadError() const {
232 return read_error_; 244 return read_error_;
233 } 245 }
234 246
235 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() { 247 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() {
236 if (path_.empty()) { 248 if (path_.empty()) {
237 OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); 249 OnFileRead(
250 scoped_ptr<base::Value>(), PREF_READ_ERROR_FILE_NOT_SPECIFIED, false);
238 return PREF_READ_ERROR_FILE_NOT_SPECIFIED; 251 return PREF_READ_ERROR_FILE_NOT_SPECIFIED;
239 } 252 }
240 253
241 PrefReadError error; 254 PrefReadError error;
242 bool no_dir; 255 bool no_dir;
243 base::Value* value = 256 scoped_ptr<base::Value> value(
244 FileThreadDeserializer::DoReading(path_, &error, &no_dir); 257 FileThreadDeserializer::DoReading(path_, &error, &no_dir));
245 OnFileRead(value, error, no_dir); 258 OnFileRead(value.Pass(), error, no_dir);
246 return error; 259 return error;
247 } 260 }
248 261
249 void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate *error_delegate) { 262 void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) {
250 initialized_ = false; 263 initialized_ = false;
251 error_delegate_.reset(error_delegate); 264 error_delegate_.reset(error_delegate);
252 if (path_.empty()) { 265 if (path_.empty()) {
253 OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); 266 OnFileRead(
267 scoped_ptr<base::Value>(), PREF_READ_ERROR_FILE_NOT_SPECIFIED, false);
254 return; 268 return;
255 } 269 }
256 270
257 // Start async reading of the preferences file. It will delete itself 271 // Start async reading of the preferences file. It will delete itself
258 // in the end. 272 // in the end.
259 scoped_refptr<FileThreadDeserializer> deserializer( 273 scoped_refptr<FileThreadDeserializer> deserializer(
260 new FileThreadDeserializer(this, sequenced_task_runner_.get())); 274 new FileThreadDeserializer(this, sequenced_task_runner_.get()));
261 deserializer->Start(path_); 275 deserializer->Start(path_);
262 } 276 }
263 277
264 void JsonPrefStore::CommitPendingWrite() { 278 void JsonPrefStore::CommitPendingWrite() {
265 if (writer_.HasPendingWrite() && !read_only_) 279 if (writer_.HasPendingWrite() && !read_only_)
266 writer_.DoScheduledWrite(); 280 writer_.DoScheduledWrite();
267 } 281 }
268 282
269 void JsonPrefStore::ReportValueChanged(const std::string& key) { 283 void JsonPrefStore::ReportValueChanged(const std::string& key) {
270 if (pref_filter_) 284 if (pref_filter_)
271 pref_filter_->FilterUpdate(key); 285 pref_filter_->FilterUpdate(key);
272 286
273 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); 287 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key));
274 288
275 if (!read_only_) 289 if (!read_only_)
276 writer_.ScheduleWrite(this); 290 writer_.ScheduleWrite(this);
277 } 291 }
278 292
279 void JsonPrefStore::OnFileRead(base::Value* value_owned, 293 void JsonPrefStore::RegisterOnNextSuccessfulWriteCallback(
294 const base::Closure& on_next_successful_write) {
295 writer_.RegisterOnNextSuccessfulWriteCallback(on_next_successful_write);
296 }
297
298 void JsonPrefStore::InterceptNextFileRead(
299 const OnFileReadInterceptor& on_file_read_interceptor) {
300 DCHECK(on_file_read_interceptor_.is_null());
301 on_file_read_interceptor_ = on_file_read_interceptor;
302 }
303
304 void JsonPrefStore::OnFileRead(scoped_ptr<base::Value> value,
280 PersistentPrefStore::PrefReadError error, 305 PersistentPrefStore::PrefReadError error,
281 bool no_dir) { 306 bool no_dir) {
282 scoped_ptr<base::Value> value(value_owned); 307 scoped_ptr<base::DictionaryValue> unprocessed_prefs(
308 new base::DictionaryValue);
309
283 read_error_ = error; 310 read_error_ = error;
284 311
285 if (no_dir) { 312 bool initialization_successful = !no_dir;
286 FOR_EACH_OBSERVER(PrefStore::Observer, 313
287 observers_, 314 if (initialization_successful) {
288 OnInitializationCompleted(false)); 315 switch (error) {
289 return; 316 case PREF_READ_ERROR_ACCESS_DENIED:
317 case PREF_READ_ERROR_FILE_OTHER:
318 case PREF_READ_ERROR_FILE_LOCKED:
319 case PREF_READ_ERROR_JSON_TYPE:
320 case PREF_READ_ERROR_FILE_NOT_SPECIFIED:
321 read_only_ = true;
322 break;
323 case PREF_READ_ERROR_NONE:
324 DCHECK(value.get());
325 unprocessed_prefs.reset(
326 static_cast<base::DictionaryValue*>(value.release()));
327 break;
328 case PREF_READ_ERROR_NO_FILE:
329 // If the file just doesn't exist, maybe this is first run. In any case
330 // there's no harm in writing out default prefs in this case.
331 break;
332 case PREF_READ_ERROR_JSON_PARSE:
333 case PREF_READ_ERROR_JSON_REPEAT:
334 break;
335 case PREF_READ_ERROR_MAX_ENUM:
336 NOTREACHED();
337 break;
338 }
290 } 339 }
291 340
292 initialized_ = true; 341 if (on_file_read_interceptor_.is_null()) {
293 342 FinalizeFileRead(initialization_successful, unprocessed_prefs.Pass(),
294 switch (error) { 343 false);
295 case PREF_READ_ERROR_ACCESS_DENIED: 344 } else {
296 case PREF_READ_ERROR_FILE_OTHER: 345 const FinalizePrefsReadCallback finalize_file_read(
297 case PREF_READ_ERROR_FILE_LOCKED: 346 base::Bind(&JsonPrefStore::FinalizeFileRead, this,
298 case PREF_READ_ERROR_JSON_TYPE: 347 initialization_successful));
299 case PREF_READ_ERROR_FILE_NOT_SPECIFIED: 348 on_file_read_interceptor_.Run(unprocessed_prefs.Pass(),
300 read_only_ = true; 349 finalize_file_read);
301 break; 350 on_file_read_interceptor_.Reset();
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 } 351 }
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 } 352 }
327 353
328 JsonPrefStore::~JsonPrefStore() { 354 JsonPrefStore::~JsonPrefStore() {
329 CommitPendingWrite(); 355 CommitPendingWrite();
330 } 356 }
331 357
332 bool JsonPrefStore::SerializeData(std::string* output) { 358 bool JsonPrefStore::SerializeData(std::string* output) {
333 if (pref_filter_) 359 if (pref_filter_)
334 pref_filter_->FilterSerializeData(prefs_.get()); 360 pref_filter_->FilterSerializeData(prefs_.get());
335 361
336 JSONStringValueSerializer serializer(output); 362 JSONStringValueSerializer serializer(output);
337 serializer.set_pretty_print(true); 363 serializer.set_pretty_print(true);
338 return serializer.Serialize(*prefs_); 364 return serializer.Serialize(*prefs_);
339 } 365 }
366
367 base::WeakPtr<JsonPrefStore> JsonPrefStore::FinalizeFileRead(
368 bool initialization_successful,
369 scoped_ptr<base::DictionaryValue> prefs,
370 bool schedule_write) {
371 if (!initialization_successful) {
372 FOR_EACH_OBSERVER(PrefStore::Observer,
373 observers_,
374 OnInitializationCompleted(false));
375 return weak_factory_.GetWeakPtr();
376 }
377
378 prefs_ = prefs.Pass();
379
380 initialized_ = true;
381
382 bool had_filter_modification =
383 pref_filter_ && pref_filter_->FilterOnLoad(prefs_.get());
384
385 if ((schedule_write || had_filter_modification) && !read_only_)
386 writer_.ScheduleWrite(this);
387
388 if (error_delegate_ && read_error_ != PREF_READ_ERROR_NONE)
389 error_delegate_->OnError(read_error_);
390
391 FOR_EACH_OBSERVER(PrefStore::Observer,
392 observers_,
393 OnInitializationCompleted(true));
394
395 return weak_factory_.GetWeakPtr();
396 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698