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

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

Issue 90563003: Fix a race condition in preference metric reporting. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Comments, tidying. Created 7 years 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"
11 #include "base/file_util.h" 11 #include "base/file_util.h"
12 #include "base/json/json_file_value_serializer.h" 12 #include "base/json/json_file_value_serializer.h"
13 #include "base/json/json_string_value_serializer.h" 13 #include "base/json/json_string_value_serializer.h"
14 #include "base/memory/ref_counted.h" 14 #include "base/memory/ref_counted.h"
15 #include "base/message_loop/message_loop_proxy.h" 15 #include "base/message_loop/message_loop_proxy.h"
16 #include "base/prefs/pref_filter.h"
16 #include "base/sequenced_task_runner.h" 17 #include "base/sequenced_task_runner.h"
17 #include "base/threading/sequenced_worker_pool.h" 18 #include "base/threading/sequenced_worker_pool.h"
18 #include "base/values.h" 19 #include "base/values.h"
19 20
20 namespace { 21 namespace {
21 22
22 // Some extensions we'll tack on to copies of the Preferences files. 23 // Some extensions we'll tack on to copies of the Preferences files.
23 const base::FilePath::CharType* kBadExtension = FILE_PATH_LITERAL("bad"); 24 const base::FilePath::CharType* kBadExtension = FILE_PATH_LITERAL("bad");
24 25
25 // Differentiates file loading between origin thread and passed 26 // Differentiates file loading between origin thread and passed
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 const base::FilePath& filename, 145 const base::FilePath& filename,
145 base::SequencedWorkerPool* worker_pool) { 146 base::SequencedWorkerPool* worker_pool) {
146 std::string token("json_pref_store-"); 147 std::string token("json_pref_store-");
147 token.append(filename.AsUTF8Unsafe()); 148 token.append(filename.AsUTF8Unsafe());
148 return worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( 149 return worker_pool->GetSequencedTaskRunnerWithShutdownBehavior(
149 worker_pool->GetNamedSequenceToken(token), 150 worker_pool->GetNamedSequenceToken(token),
150 base::SequencedWorkerPool::BLOCK_SHUTDOWN); 151 base::SequencedWorkerPool::BLOCK_SHUTDOWN);
151 } 152 }
152 153
153 JsonPrefStore::JsonPrefStore(const base::FilePath& filename, 154 JsonPrefStore::JsonPrefStore(const base::FilePath& filename,
154 base::SequencedTaskRunner* sequenced_task_runner) 155 base::SequencedTaskRunner* sequenced_task_runner,
156 scoped_ptr<PrefFilter> pref_filter)
155 : path_(filename), 157 : path_(filename),
156 sequenced_task_runner_(sequenced_task_runner), 158 sequenced_task_runner_(sequenced_task_runner),
157 prefs_(new base::DictionaryValue()), 159 prefs_(new base::DictionaryValue()),
158 read_only_(false), 160 read_only_(false),
159 writer_(filename, sequenced_task_runner), 161 writer_(filename, sequenced_task_runner),
162 pref_filter_(pref_filter.Pass()),
160 initialized_(false), 163 initialized_(false),
161 read_error_(PREF_READ_ERROR_OTHER) {} 164 read_error_(PREF_READ_ERROR_OTHER) {}
162 165
163 bool JsonPrefStore::GetValue(const std::string& key, 166 bool JsonPrefStore::GetValue(const std::string& key,
164 const base::Value** result) const { 167 const base::Value** result) const {
165 base::Value* tmp = NULL; 168 base::Value* tmp = NULL;
166 if (!prefs_->Get(key, &tmp)) 169 if (!prefs_->Get(key, &tmp))
167 return false; 170 return false;
168 171
169 if (result) 172 if (result)
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 new FileThreadDeserializer(this, sequenced_task_runner_.get())); 264 new FileThreadDeserializer(this, sequenced_task_runner_.get()));
262 deserializer->Start(path_); 265 deserializer->Start(path_);
263 } 266 }
264 267
265 void JsonPrefStore::CommitPendingWrite() { 268 void JsonPrefStore::CommitPendingWrite() {
266 if (writer_.HasPendingWrite() && !read_only_) 269 if (writer_.HasPendingWrite() && !read_only_)
267 writer_.DoScheduledWrite(); 270 writer_.DoScheduledWrite();
268 } 271 }
269 272
270 void JsonPrefStore::ReportValueChanged(const std::string& key) { 273 void JsonPrefStore::ReportValueChanged(const std::string& key) {
271 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); 274 // We don't notify observers about changes during initialization (i.e., due to
275 // filters).
276 if (initialized_) {
277 if (pref_filter_.get())
278 pref_filter_->FilterUpdate(this, key);
279 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key));
280 }
281
272 if (!read_only_) 282 if (!read_only_)
273 writer_.ScheduleWrite(this); 283 writer_.ScheduleWrite(this);
274 } 284 }
275 285
276 void JsonPrefStore::OnFileRead(base::Value* value_owned, 286 void JsonPrefStore::OnFileRead(base::Value* value_owned,
277 PersistentPrefStore::PrefReadError error, 287 PersistentPrefStore::PrefReadError error,
278 bool no_dir) { 288 bool no_dir) {
279 scoped_ptr<base::Value> value(value_owned); 289 scoped_ptr<base::Value> value(value_owned);
280 read_error_ = error; 290 read_error_ = error;
281 291
282 if (no_dir) { 292 if (no_dir) {
283 FOR_EACH_OBSERVER(PrefStore::Observer, 293 FOR_EACH_OBSERVER(PrefStore::Observer,
gab 2013/12/04 22:22:30 What about in this case? Should we not do/report s
erikwright (departed) 2013/12/05 23:48:00 If the store is missing but the directory is there
284 observers_, 294 observers_,
285 OnInitializationCompleted(false)); 295 OnInitializationCompleted(false));
286 return; 296 return;
287 } 297 }
288 298
289 initialized_ = true;
290
291 switch (error) { 299 switch (error) {
292 case PREF_READ_ERROR_ACCESS_DENIED: 300 case PREF_READ_ERROR_ACCESS_DENIED:
293 case PREF_READ_ERROR_FILE_OTHER: 301 case PREF_READ_ERROR_FILE_OTHER:
294 case PREF_READ_ERROR_FILE_LOCKED: 302 case PREF_READ_ERROR_FILE_LOCKED:
295 case PREF_READ_ERROR_JSON_TYPE: 303 case PREF_READ_ERROR_JSON_TYPE:
296 case PREF_READ_ERROR_FILE_NOT_SPECIFIED: 304 case PREF_READ_ERROR_FILE_NOT_SPECIFIED:
297 read_only_ = true; 305 read_only_ = true;
298 break; 306 break;
299 case PREF_READ_ERROR_NONE: 307 case PREF_READ_ERROR_NONE:
300 DCHECK(value.get()); 308 DCHECK(value.get());
301 prefs_.reset(static_cast<base::DictionaryValue*>(value.release())); 309 prefs_.reset(static_cast<base::DictionaryValue*>(value.release()));
310 if (pref_filter_.get())
311 pref_filter_->FilterOnLoad(this);
302 break; 312 break;
303 case PREF_READ_ERROR_NO_FILE: 313 case PREF_READ_ERROR_NO_FILE:
304 // If the file just doesn't exist, maybe this is first run. In any case 314 // If the file just doesn't exist, maybe this is first run. In any case
305 // there's no harm in writing out default prefs in this case. 315 // there's no harm in writing out default prefs in this case.
306 break; 316 break;
307 case PREF_READ_ERROR_JSON_PARSE: 317 case PREF_READ_ERROR_JSON_PARSE:
308 case PREF_READ_ERROR_JSON_REPEAT: 318 case PREF_READ_ERROR_JSON_REPEAT:
309 break; 319 break;
310 default: 320 default:
311 NOTREACHED() << "Unknown error: " << error; 321 NOTREACHED() << "Unknown error: " << error;
312 } 322 }
313 323
324 initialized_ = true;
325
314 if (error_delegate_.get() && error != PREF_READ_ERROR_NONE) 326 if (error_delegate_.get() && error != PREF_READ_ERROR_NONE)
315 error_delegate_->OnError(error); 327 error_delegate_->OnError(error);
316 328
317 FOR_EACH_OBSERVER(PrefStore::Observer, 329 FOR_EACH_OBSERVER(PrefStore::Observer,
318 observers_, 330 observers_,
319 OnInitializationCompleted(true)); 331 OnInitializationCompleted(true));
320 } 332 }
321 333
322 JsonPrefStore::~JsonPrefStore() { 334 JsonPrefStore::~JsonPrefStore() {
323 CommitPendingWrite(); 335 CommitPendingWrite();
(...skipping 25 matching lines...) Expand all
349 copy->Set(key, new base::ListValue); 361 copy->Set(key, new base::ListValue);
350 } else if (value->IsType(base::Value::TYPE_DICTIONARY)) { 362 } else if (value->IsType(base::Value::TYPE_DICTIONARY)) {
351 const base::DictionaryValue* dict = NULL; 363 const base::DictionaryValue* dict = NULL;
352 if (value->GetAsDictionary(&dict) && dict->empty()) 364 if (value->GetAsDictionary(&dict) && dict->empty())
353 copy->Set(key, new base::DictionaryValue); 365 copy->Set(key, new base::DictionaryValue);
354 } 366 }
355 } 367 }
356 368
357 return serializer.Serialize(*(copy.get())); 369 return serializer.Serialize(*(copy.get()));
358 } 370 }
OLDNEW
« no previous file with comments | « base/prefs/json_pref_store.h ('k') | base/prefs/pref_filter.h » ('j') | base/prefs/pref_filter.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698