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

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: Rebase. 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 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 new FileThreadDeserializer(this, sequenced_task_runner_.get())); 260 new FileThreadDeserializer(this, sequenced_task_runner_.get()));
258 deserializer->Start(path_); 261 deserializer->Start(path_);
259 } 262 }
260 263
261 void JsonPrefStore::CommitPendingWrite() { 264 void JsonPrefStore::CommitPendingWrite() {
262 if (writer_.HasPendingWrite() && !read_only_) 265 if (writer_.HasPendingWrite() && !read_only_)
263 writer_.DoScheduledWrite(); 266 writer_.DoScheduledWrite();
264 } 267 }
265 268
266 void JsonPrefStore::ReportValueChanged(const std::string& key) { 269 void JsonPrefStore::ReportValueChanged(const std::string& key) {
267 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); 270 // Don't notify observers about changes during initialization (i.e., due to
271 // filters).
272 if (initialized_) {
273 if (pref_filter_.get())
Bernhard Bauer 2013/12/10 16:52:07 Nit: scoped_ptr has a bool() operator, so the .get
274 pref_filter_->FilterUpdate(this, key);
275 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key));
276 }
277
268 if (!read_only_) 278 if (!read_only_)
269 writer_.ScheduleWrite(this); 279 writer_.ScheduleWrite(this);
270 } 280 }
271 281
272 void JsonPrefStore::OnFileRead(base::Value* value_owned, 282 void JsonPrefStore::OnFileRead(base::Value* value_owned,
273 PersistentPrefStore::PrefReadError error, 283 PersistentPrefStore::PrefReadError error,
274 bool no_dir) { 284 bool no_dir) {
275 scoped_ptr<base::Value> value(value_owned); 285 scoped_ptr<base::Value> value(value_owned);
276 read_error_ = error; 286 read_error_ = error;
277 287
278 if (no_dir) { 288 if (no_dir) {
279 FOR_EACH_OBSERVER(PrefStore::Observer, 289 FOR_EACH_OBSERVER(PrefStore::Observer,
280 observers_, 290 observers_,
281 OnInitializationCompleted(false)); 291 OnInitializationCompleted(false));
282 return; 292 return;
283 } 293 }
284 294
285 initialized_ = true;
286
287 switch (error) { 295 switch (error) {
288 case PREF_READ_ERROR_ACCESS_DENIED: 296 case PREF_READ_ERROR_ACCESS_DENIED:
289 case PREF_READ_ERROR_FILE_OTHER: 297 case PREF_READ_ERROR_FILE_OTHER:
290 case PREF_READ_ERROR_FILE_LOCKED: 298 case PREF_READ_ERROR_FILE_LOCKED:
291 case PREF_READ_ERROR_JSON_TYPE: 299 case PREF_READ_ERROR_JSON_TYPE:
292 case PREF_READ_ERROR_FILE_NOT_SPECIFIED: 300 case PREF_READ_ERROR_FILE_NOT_SPECIFIED:
293 read_only_ = true; 301 read_only_ = true;
294 break; 302 break;
295 case PREF_READ_ERROR_NONE: 303 case PREF_READ_ERROR_NONE:
296 DCHECK(value.get()); 304 DCHECK(value.get());
297 prefs_.reset(static_cast<base::DictionaryValue*>(value.release())); 305 prefs_.reset(static_cast<base::DictionaryValue*>(value.release()));
306 if (pref_filter_.get())
307 pref_filter_->FilterOnLoad(this);
298 break; 308 break;
299 case PREF_READ_ERROR_NO_FILE: 309 case PREF_READ_ERROR_NO_FILE:
300 // If the file just doesn't exist, maybe this is first run. In any case 310 // If the file just doesn't exist, maybe this is first run. In any case
301 // there's no harm in writing out default prefs in this case. 311 // there's no harm in writing out default prefs in this case.
302 break; 312 break;
303 case PREF_READ_ERROR_JSON_PARSE: 313 case PREF_READ_ERROR_JSON_PARSE:
304 case PREF_READ_ERROR_JSON_REPEAT: 314 case PREF_READ_ERROR_JSON_REPEAT:
305 break; 315 break;
306 default: 316 default:
307 NOTREACHED() << "Unknown error: " << error; 317 NOTREACHED() << "Unknown error: " << error;
308 } 318 }
309 319
320 initialized_ = true;
321
310 if (error_delegate_.get() && error != PREF_READ_ERROR_NONE) 322 if (error_delegate_.get() && error != PREF_READ_ERROR_NONE)
311 error_delegate_->OnError(error); 323 error_delegate_->OnError(error);
312 324
313 FOR_EACH_OBSERVER(PrefStore::Observer, 325 FOR_EACH_OBSERVER(PrefStore::Observer,
314 observers_, 326 observers_,
315 OnInitializationCompleted(true)); 327 OnInitializationCompleted(true));
316 } 328 }
317 329
318 JsonPrefStore::~JsonPrefStore() { 330 JsonPrefStore::~JsonPrefStore() {
319 CommitPendingWrite(); 331 CommitPendingWrite();
320 } 332 }
321 333
322 bool JsonPrefStore::SerializeData(std::string* output) { 334 bool JsonPrefStore::SerializeData(std::string* output) {
323 JSONStringValueSerializer serializer(output); 335 JSONStringValueSerializer serializer(output);
324 serializer.set_pretty_print(true); 336 serializer.set_pretty_print(true);
325 return serializer.Serialize(*prefs_); 337 return serializer.Serialize(*prefs_);
326 } 338 }
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