OLD | NEW |
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 | 1 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 2 // found in the LICENSE file. |
4 | 3 |
5 #include "chrome/common/json_pref_store.h" | 4 #include "chrome/common/json_pref_store.h" |
6 | 5 |
7 #include <algorithm> | 6 #include <algorithm> |
8 | 7 |
9 #include "base/bind.h" | 8 #include "base/bind.h" |
10 #include "base/callback.h" | 9 #include "base/callback.h" |
11 #include "base/file_util.h" | 10 #include "base/file_util.h" |
12 #include "base/json/json_file_value_serializer.h" | 11 #include "base/json/json_file_value_serializer.h" |
13 #include "base/json/json_string_value_serializer.h" | 12 #include "base/json/json_string_value_serializer.h" |
14 #include "base/memory/ref_counted.h" | 13 #include "base/memory/ref_counted.h" |
15 #include "base/message_loop_proxy.h" | 14 #include "base/message_loop_proxy.h" |
| 15 #include "base/sequenced_task_runner.h" |
| 16 #include "base/threading/sequenced_worker_pool.h" |
16 #include "base/values.h" | 17 #include "base/values.h" |
17 | 18 |
18 namespace { | 19 namespace { |
19 | 20 |
20 // Some extensions we'll tack on to copies of the Preferences files. | 21 // Some extensions we'll tack on to copies of the Preferences files. |
21 const FilePath::CharType* kBadExtension = FILE_PATH_LITERAL("bad"); | 22 const FilePath::CharType* kBadExtension = FILE_PATH_LITERAL("bad"); |
22 | 23 |
23 // Differentiates file loading between origin thread and passed | 24 // Differentiates file loading between origin thread and passed |
24 // (aka file) thread. | 25 // (aka file) thread. |
25 class FileThreadDeserializer | 26 class FileThreadDeserializer |
26 : public base::RefCountedThreadSafe<FileThreadDeserializer> { | 27 : public base::RefCountedThreadSafe<FileThreadDeserializer> { |
27 public: | 28 public: |
28 FileThreadDeserializer(JsonPrefStore* delegate, | 29 FileThreadDeserializer(JsonPrefStore* delegate, |
29 base::MessageLoopProxy* file_loop_proxy) | 30 base::SequencedTaskRunner* sequenced_task_runner) |
30 : no_dir_(false), | 31 : no_dir_(false), |
31 error_(PersistentPrefStore::PREF_READ_ERROR_NONE), | 32 error_(PersistentPrefStore::PREF_READ_ERROR_NONE), |
32 delegate_(delegate), | 33 delegate_(delegate), |
33 file_loop_proxy_(file_loop_proxy), | 34 sequenced_task_runner_(sequenced_task_runner), |
34 origin_loop_proxy_(base::MessageLoopProxy::current()) { | 35 origin_loop_proxy_(base::MessageLoopProxy::current()) { |
35 } | 36 } |
36 | 37 |
37 void Start(const FilePath& path) { | 38 void Start(const FilePath& path) { |
38 DCHECK(origin_loop_proxy_->BelongsToCurrentThread()); | 39 DCHECK(origin_loop_proxy_->BelongsToCurrentThread()); |
39 file_loop_proxy_->PostTask( | 40 sequenced_task_runner_->PostTask( |
40 FROM_HERE, | 41 FROM_HERE, |
41 base::Bind(&FileThreadDeserializer::ReadFileAndReport, | 42 base::Bind(&FileThreadDeserializer::ReadFileAndReport, |
42 this, path)); | 43 this, path)); |
43 } | 44 } |
44 | 45 |
45 // Deserializes JSON on the file thread. | 46 // Deserializes JSON on the sequenced task runner. |
46 void ReadFileAndReport(const FilePath& path) { | 47 void ReadFileAndReport(const FilePath& path) { |
47 DCHECK(file_loop_proxy_->BelongsToCurrentThread()); | 48 DCHECK(sequenced_task_runner_->RunsTasksOnCurrentThread()); |
48 | 49 |
49 value_.reset(DoReading(path, &error_, &no_dir_)); | 50 value_.reset(DoReading(path, &error_, &no_dir_)); |
50 | 51 |
51 origin_loop_proxy_->PostTask( | 52 origin_loop_proxy_->PostTask( |
52 FROM_HERE, | 53 FROM_HERE, |
53 base::Bind(&FileThreadDeserializer::ReportOnOriginThread, this)); | 54 base::Bind(&FileThreadDeserializer::ReportOnOriginThread, this)); |
54 } | 55 } |
55 | 56 |
56 // Reports deserialization result on the origin thread. | 57 // Reports deserialization result on the origin thread. |
57 void ReportOnOriginThread() { | 58 void ReportOnOriginThread() { |
(...skipping 20 matching lines...) Expand all Loading... |
78 PersistentPrefStore::PrefReadError* error); | 79 PersistentPrefStore::PrefReadError* error); |
79 | 80 |
80 private: | 81 private: |
81 friend class base::RefCountedThreadSafe<FileThreadDeserializer>; | 82 friend class base::RefCountedThreadSafe<FileThreadDeserializer>; |
82 ~FileThreadDeserializer() {} | 83 ~FileThreadDeserializer() {} |
83 | 84 |
84 bool no_dir_; | 85 bool no_dir_; |
85 PersistentPrefStore::PrefReadError error_; | 86 PersistentPrefStore::PrefReadError error_; |
86 scoped_ptr<Value> value_; | 87 scoped_ptr<Value> value_; |
87 scoped_refptr<JsonPrefStore> delegate_; | 88 scoped_refptr<JsonPrefStore> delegate_; |
88 scoped_refptr<base::MessageLoopProxy> file_loop_proxy_; | 89 scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_; |
89 scoped_refptr<base::MessageLoopProxy> origin_loop_proxy_; | 90 scoped_refptr<base::MessageLoopProxy> origin_loop_proxy_; |
90 }; | 91 }; |
91 | 92 |
92 // static | 93 // static |
93 void FileThreadDeserializer::HandleErrors( | 94 void FileThreadDeserializer::HandleErrors( |
94 const Value* value, | 95 const Value* value, |
95 const FilePath& path, | 96 const FilePath& path, |
96 int error_code, | 97 int error_code, |
97 const std::string& error_msg, | 98 const std::string& error_msg, |
98 PersistentPrefStore::PrefReadError* error) { | 99 PersistentPrefStore::PrefReadError* error) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
130 file_util::Move(path, bad); | 131 file_util::Move(path, bad); |
131 break; | 132 break; |
132 } | 133 } |
133 } else if (!value->IsType(Value::TYPE_DICTIONARY)) { | 134 } else if (!value->IsType(Value::TYPE_DICTIONARY)) { |
134 *error = PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE; | 135 *error = PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE; |
135 } | 136 } |
136 } | 137 } |
137 | 138 |
138 } // namespace | 139 } // namespace |
139 | 140 |
| 141 JsonPrefStore* JsonPrefStore::Create( |
| 142 const FilePath& filename, base::SequencedWorkerPool* worker_pool) { |
| 143 // Make sure that write requests for the same set of files don't step on |
| 144 // each other by using parent directory keyed (profile dir) sequenced task |
| 145 // runner. |
| 146 scoped_refptr<base::SequencedTaskRunner> task_runner = |
| 147 worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( |
| 148 worker_pool->GetNamedSequenceToken(filename.DirName().AsUTF8Unsafe()), |
| 149 base::SequencedWorkerPool::BLOCK_SHUTDOWN); |
| 150 return new JsonPrefStore(filename, task_runner.get()); |
| 151 } |
| 152 |
140 JsonPrefStore::JsonPrefStore(const FilePath& filename, | 153 JsonPrefStore::JsonPrefStore(const FilePath& filename, |
141 base::MessageLoopProxy* file_message_loop_proxy) | 154 base::SequencedTaskRunner* sequenced_task_runner) |
142 : path_(filename), | 155 : path_(filename), |
143 file_message_loop_proxy_(file_message_loop_proxy), | 156 sequenced_task_runner_(sequenced_task_runner), |
144 prefs_(new DictionaryValue()), | 157 prefs_(new DictionaryValue()), |
145 read_only_(false), | 158 read_only_(false), |
146 writer_(filename, file_message_loop_proxy), | 159 writer_(filename, sequenced_task_runner), |
147 error_delegate_(NULL), | 160 error_delegate_(NULL), |
148 initialized_(false), | 161 initialized_(false), |
149 read_error_(PREF_READ_ERROR_OTHER) { | 162 read_error_(PREF_READ_ERROR_OTHER) { |
150 } | 163 } |
151 | 164 |
152 PrefStore::ReadResult JsonPrefStore::GetValue(const std::string& key, | 165 PrefStore::ReadResult JsonPrefStore::GetValue(const std::string& key, |
153 const Value** result) const { | 166 const Value** result) const { |
154 Value* tmp = NULL; | 167 Value* tmp = NULL; |
155 if (prefs_->Get(key, &tmp)) { | 168 if (prefs_->Get(key, &tmp)) { |
156 if (result) | 169 if (result) |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 initialized_ = false; | 251 initialized_ = false; |
239 error_delegate_.reset(error_delegate); | 252 error_delegate_.reset(error_delegate); |
240 if (path_.empty()) { | 253 if (path_.empty()) { |
241 OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); | 254 OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); |
242 return; | 255 return; |
243 } | 256 } |
244 | 257 |
245 // Start async reading of the preferences file. It will delete itself | 258 // Start async reading of the preferences file. It will delete itself |
246 // in the end. | 259 // in the end. |
247 scoped_refptr<FileThreadDeserializer> deserializer( | 260 scoped_refptr<FileThreadDeserializer> deserializer( |
248 new FileThreadDeserializer(this, file_message_loop_proxy_.get())); | 261 new FileThreadDeserializer(this, sequenced_task_runner_.get())); |
249 deserializer->Start(path_); | 262 deserializer->Start(path_); |
250 } | 263 } |
251 | 264 |
252 void JsonPrefStore::CommitPendingWrite() { | 265 void JsonPrefStore::CommitPendingWrite() { |
253 if (writer_.HasPendingWrite() && !read_only_) | 266 if (writer_.HasPendingWrite() && !read_only_) |
254 writer_.DoScheduledWrite(); | 267 writer_.DoScheduledWrite(); |
255 } | 268 } |
256 | 269 |
257 void JsonPrefStore::ReportValueChanged(const std::string& key) { | 270 void JsonPrefStore::ReportValueChanged(const std::string& key) { |
258 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); | 271 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 copy->Set(key, new base::ListValue); | 348 copy->Set(key, new base::ListValue); |
336 } else if (value->IsType(base::Value::TYPE_DICTIONARY)) { | 349 } else if (value->IsType(base::Value::TYPE_DICTIONARY)) { |
337 const base::DictionaryValue* dict = NULL; | 350 const base::DictionaryValue* dict = NULL; |
338 if (value->GetAsDictionary(&dict) && dict->empty()) | 351 if (value->GetAsDictionary(&dict) && dict->empty()) |
339 copy->Set(key, new base::DictionaryValue); | 352 copy->Set(key, new base::DictionaryValue); |
340 } | 353 } |
341 } | 354 } |
342 | 355 |
343 return serializer.Serialize(*(copy.get())); | 356 return serializer.Serialize(*(copy.get())); |
344 } | 357 } |
OLD | NEW |