OLD | NEW |
---|---|
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/files/file_path.h" | 12 #include "base/files/file_path.h" |
13 #include "base/json/json_file_value_serializer.h" | 13 #include "base/json/json_file_value_serializer.h" |
14 #include "base/json/json_string_value_serializer.h" | 14 #include "base/json/json_string_value_serializer.h" |
15 #include "base/memory/ref_counted.h" | 15 #include "base/memory/ref_counted.h" |
16 #include "base/message_loop/message_loop_proxy.h" | |
17 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
18 #include "base/prefs/pref_filter.h" | 17 #include "base/prefs/pref_filter.h" |
19 #include "base/sequenced_task_runner.h" | 18 #include "base/sequenced_task_runner.h" |
20 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" |
20 #include "base/task_runner_util.h" | |
21 #include "base/threading/sequenced_worker_pool.h" | 21 #include "base/threading/sequenced_worker_pool.h" |
22 #include "base/values.h" | 22 #include "base/values.h" |
23 | 23 |
24 // Result returned from internal read tasks. | |
25 struct JsonPrefStore::ReadResult { | |
26 public: | |
27 ReadResult(); | |
28 ~ReadResult(); | |
29 | |
30 scoped_ptr<base::Value> value; | |
31 PrefReadError error; | |
32 bool no_dir; | |
33 | |
34 private: | |
35 DISALLOW_COPY_AND_ASSIGN(ReadResult); | |
36 }; | |
37 | |
38 JsonPrefStore::ReadResult::ReadResult() | |
39 : error(PersistentPrefStore::PREF_READ_ERROR_NONE), no_dir(false) { | |
40 } | |
41 | |
42 JsonPrefStore::ReadResult::~ReadResult() { | |
43 } | |
44 | |
24 namespace { | 45 namespace { |
25 | 46 |
26 // Some extensions we'll tack on to copies of the Preferences files. | 47 // Some extensions we'll tack on to copies of the Preferences files. |
27 const base::FilePath::CharType* kBadExtension = FILE_PATH_LITERAL("bad"); | 48 const base::FilePath::CharType kBadExtension[] = FILE_PATH_LITERAL("bad"); |
28 | 49 |
29 // Differentiates file loading between origin thread and passed | 50 PersistentPrefStore::PrefReadError HandleReadErrors( |
30 // (aka file) thread. | |
31 class FileThreadDeserializer | |
32 : public base::RefCountedThreadSafe<FileThreadDeserializer> { | |
33 public: | |
34 FileThreadDeserializer(JsonPrefStore* delegate, | |
35 base::SequencedTaskRunner* sequenced_task_runner) | |
36 : no_dir_(false), | |
37 error_(PersistentPrefStore::PREF_READ_ERROR_NONE), | |
38 delegate_(delegate), | |
39 sequenced_task_runner_(sequenced_task_runner), | |
40 origin_loop_proxy_(base::MessageLoopProxy::current()) { | |
41 } | |
42 | |
43 void Start(const base::FilePath& path, | |
44 const base::FilePath& alternate_path) { | |
45 DCHECK(origin_loop_proxy_->BelongsToCurrentThread()); | |
46 // TODO(gab): This should use PostTaskAndReplyWithResult instead of using | |
47 // the |error_| member to pass data across tasks. | |
48 sequenced_task_runner_->PostTask( | |
49 FROM_HERE, | |
50 base::Bind(&FileThreadDeserializer::ReadFileAndReport, | |
51 this, path, alternate_path)); | |
52 } | |
53 | |
54 // Deserializes JSON on the sequenced task runner. | |
55 void ReadFileAndReport(const base::FilePath& path, | |
56 const base::FilePath& alternate_path) { | |
57 DCHECK(sequenced_task_runner_->RunsTasksOnCurrentThread()); | |
58 | |
59 value_.reset(DoReading(path, alternate_path, &error_, &no_dir_)); | |
60 | |
61 origin_loop_proxy_->PostTask( | |
62 FROM_HERE, | |
63 base::Bind(&FileThreadDeserializer::ReportOnOriginThread, this)); | |
64 } | |
65 | |
66 // Reports deserialization result on the origin thread. | |
67 void ReportOnOriginThread() { | |
68 DCHECK(origin_loop_proxy_->BelongsToCurrentThread()); | |
69 delegate_->OnFileRead(value_.Pass(), error_, no_dir_); | |
70 } | |
71 | |
72 static base::Value* DoReading(const base::FilePath& path, | |
73 const base::FilePath& alternate_path, | |
74 PersistentPrefStore::PrefReadError* error, | |
75 bool* no_dir) { | |
76 if (!base::PathExists(path) && !alternate_path.empty() && | |
77 base::PathExists(alternate_path)) { | |
78 base::Move(alternate_path, path); | |
79 } | |
80 | |
81 int error_code; | |
82 std::string error_msg; | |
83 JSONFileValueSerializer serializer(path); | |
84 base::Value* value = serializer.Deserialize(&error_code, &error_msg); | |
85 HandleErrors(value, path, error_code, error_msg, error); | |
86 *no_dir = !base::PathExists(path.DirName()); | |
87 return value; | |
88 } | |
89 | |
90 static void HandleErrors(const base::Value* value, | |
91 const base::FilePath& path, | |
92 int error_code, | |
93 const std::string& error_msg, | |
94 PersistentPrefStore::PrefReadError* error); | |
95 | |
96 private: | |
97 friend class base::RefCountedThreadSafe<FileThreadDeserializer>; | |
98 ~FileThreadDeserializer() {} | |
99 | |
100 bool no_dir_; | |
101 PersistentPrefStore::PrefReadError error_; | |
102 scoped_ptr<base::Value> value_; | |
103 const scoped_refptr<JsonPrefStore> delegate_; | |
104 const scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_; | |
105 const scoped_refptr<base::MessageLoopProxy> origin_loop_proxy_; | |
106 }; | |
107 | |
108 // static | |
109 void FileThreadDeserializer::HandleErrors( | |
110 const base::Value* value, | 51 const base::Value* value, |
111 const base::FilePath& path, | 52 const base::FilePath& path, |
112 int error_code, | 53 int error_code, |
113 const std::string& error_msg, | 54 const std::string& error_msg) { |
114 PersistentPrefStore::PrefReadError* error) { | |
115 *error = PersistentPrefStore::PREF_READ_ERROR_NONE; | |
116 if (!value) { | 55 if (!value) { |
117 DVLOG(1) << "Error while loading JSON file: " << error_msg | 56 DVLOG(1) << "Error while loading JSON file: " << error_msg |
118 << ", file: " << path.value(); | 57 << ", file: " << path.value(); |
119 switch (error_code) { | 58 switch (error_code) { |
120 case JSONFileValueSerializer::JSON_ACCESS_DENIED: | 59 case JSONFileValueSerializer::JSON_ACCESS_DENIED: |
121 *error = PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED; | 60 return PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED; |
122 break; | 61 break; |
123 case JSONFileValueSerializer::JSON_CANNOT_READ_FILE: | 62 case JSONFileValueSerializer::JSON_CANNOT_READ_FILE: |
124 *error = PersistentPrefStore::PREF_READ_ERROR_FILE_OTHER; | 63 return PersistentPrefStore::PREF_READ_ERROR_FILE_OTHER; |
125 break; | 64 break; |
126 case JSONFileValueSerializer::JSON_FILE_LOCKED: | 65 case JSONFileValueSerializer::JSON_FILE_LOCKED: |
127 *error = PersistentPrefStore::PREF_READ_ERROR_FILE_LOCKED; | 66 return PersistentPrefStore::PREF_READ_ERROR_FILE_LOCKED; |
128 break; | 67 break; |
129 case JSONFileValueSerializer::JSON_NO_SUCH_FILE: | 68 case JSONFileValueSerializer::JSON_NO_SUCH_FILE: |
130 *error = PersistentPrefStore::PREF_READ_ERROR_NO_FILE; | 69 return PersistentPrefStore::PREF_READ_ERROR_NO_FILE; |
131 break; | 70 break; |
132 default: | 71 default: |
133 *error = PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE; | |
134 // JSON errors indicate file corruption of some sort. | 72 // JSON errors indicate file corruption of some sort. |
135 // Since the file is corrupt, move it to the side and continue with | 73 // Since the file is corrupt, move it to the side and continue with |
136 // empty preferences. This will result in them losing their settings. | 74 // empty preferences. This will result in them losing their settings. |
137 // We keep the old file for possible support and debugging assistance | 75 // We keep the old file for possible support and debugging assistance |
138 // as well as to detect if they're seeing these errors repeatedly. | 76 // as well as to detect if they're seeing these errors repeatedly. |
139 // TODO(erikkay) Instead, use the last known good file. | 77 // TODO(erikkay) Instead, use the last known good file. |
140 base::FilePath bad = path.ReplaceExtension(kBadExtension); | 78 base::FilePath bad = path.ReplaceExtension(kBadExtension); |
141 | 79 |
142 // If they've ever had a parse error before, put them in another bucket. | 80 // If they've ever had a parse error before, put them in another bucket. |
143 // TODO(erikkay) if we keep this error checking for very long, we may | 81 // TODO(erikkay) if we keep this error checking for very long, we may |
144 // want to differentiate between recent and long ago errors. | 82 // want to differentiate between recent and long ago errors. |
145 if (base::PathExists(bad)) | 83 bool bad_existed = base::PathExists(bad); |
146 *error = PersistentPrefStore::PREF_READ_ERROR_JSON_REPEAT; | |
147 base::Move(path, bad); | 84 base::Move(path, bad); |
148 break; | 85 return bad_existed ? PersistentPrefStore::PREF_READ_ERROR_JSON_REPEAT |
86 : PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE; | |
149 } | 87 } |
150 } else if (!value->IsType(base::Value::TYPE_DICTIONARY)) { | 88 } else if (!value->IsType(base::Value::TYPE_DICTIONARY)) { |
151 *error = PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE; | 89 return PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE; |
152 } | 90 } |
91 return PersistentPrefStore::PREF_READ_ERROR_NONE; | |
92 } | |
93 | |
94 scoped_ptr<JsonPrefStore::ReadResult> ReadPrefsFromDisk( | |
95 const base::FilePath& path, | |
96 const base::FilePath& alternate_path) { | |
97 if (!base::PathExists(path) && !alternate_path.empty() && | |
98 base::PathExists(alternate_path)) { | |
99 base::Move(alternate_path, path); | |
100 } | |
101 | |
102 int error_code; | |
103 std::string error_msg; | |
104 scoped_ptr<JsonPrefStore::ReadResult> read_result( | |
105 new JsonPrefStore::ReadResult); | |
106 JSONFileValueSerializer serializer(path); | |
107 read_result->value.reset(serializer.Deserialize(&error_code, &error_msg)); | |
108 read_result->error = | |
109 HandleReadErrors(read_result->value.get(), path, error_code, error_msg); | |
110 read_result->no_dir = !base::PathExists(path.DirName()); | |
111 return read_result.Pass(); | |
112 } | |
113 | |
114 // Posts a task to run ReadPrefsFromDisk() on |sequenced_task_runner| which will | |
115 // report back the ReadResult on the origin thread via |on_file_read|. | |
116 void PostAsyncReadTask( | |
Bernhard Bauer
2014/07/22 16:22:00
Could you inline this method?
gab
2014/07/22 16:47:43
Indeed :-)!
| |
117 base::SequencedTaskRunner* sequenced_task_runner, | |
118 const base::FilePath& path, | |
119 const base::FilePath& alternate_path, | |
120 const base::Callback<void(scoped_ptr<JsonPrefStore::ReadResult>)>& | |
121 on_file_read) { | |
122 base::PostTaskAndReplyWithResult( | |
123 sequenced_task_runner, | |
124 FROM_HERE, | |
125 base::Bind(&ReadPrefsFromDisk, path, alternate_path), | |
126 on_file_read); | |
153 } | 127 } |
154 | 128 |
155 } // namespace | 129 } // namespace |
156 | 130 |
131 // static | |
157 scoped_refptr<base::SequencedTaskRunner> JsonPrefStore::GetTaskRunnerForFile( | 132 scoped_refptr<base::SequencedTaskRunner> JsonPrefStore::GetTaskRunnerForFile( |
158 const base::FilePath& filename, | 133 const base::FilePath& filename, |
159 base::SequencedWorkerPool* worker_pool) { | 134 base::SequencedWorkerPool* worker_pool) { |
160 std::string token("json_pref_store-"); | 135 std::string token("json_pref_store-"); |
161 token.append(filename.AsUTF8Unsafe()); | 136 token.append(filename.AsUTF8Unsafe()); |
162 return worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( | 137 return worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( |
163 worker_pool->GetNamedSequenceToken(token), | 138 worker_pool->GetNamedSequenceToken(token), |
164 base::SequencedWorkerPool::BLOCK_SHUTDOWN); | 139 base::SequencedWorkerPool::BLOCK_SHUTDOWN); |
165 } | 140 } |
166 | 141 |
(...skipping 22 matching lines...) Expand all Loading... | |
189 read_only_(false), | 164 read_only_(false), |
190 writer_(filename, sequenced_task_runner), | 165 writer_(filename, sequenced_task_runner), |
191 pref_filter_(pref_filter.Pass()), | 166 pref_filter_(pref_filter.Pass()), |
192 initialized_(false), | 167 initialized_(false), |
193 filtering_in_progress_(false), | 168 filtering_in_progress_(false), |
194 read_error_(PREF_READ_ERROR_NONE) { | 169 read_error_(PREF_READ_ERROR_NONE) { |
195 } | 170 } |
196 | 171 |
197 bool JsonPrefStore::GetValue(const std::string& key, | 172 bool JsonPrefStore::GetValue(const std::string& key, |
198 const base::Value** result) const { | 173 const base::Value** result) const { |
174 DCHECK(CalledOnValidThread()); | |
175 | |
199 base::Value* tmp = NULL; | 176 base::Value* tmp = NULL; |
200 if (!prefs_->Get(key, &tmp)) | 177 if (!prefs_->Get(key, &tmp)) |
201 return false; | 178 return false; |
202 | 179 |
203 if (result) | 180 if (result) |
204 *result = tmp; | 181 *result = tmp; |
205 return true; | 182 return true; |
206 } | 183 } |
207 | 184 |
208 void JsonPrefStore::AddObserver(PrefStore::Observer* observer) { | 185 void JsonPrefStore::AddObserver(PrefStore::Observer* observer) { |
186 DCHECK(CalledOnValidThread()); | |
187 | |
209 observers_.AddObserver(observer); | 188 observers_.AddObserver(observer); |
210 } | 189 } |
211 | 190 |
212 void JsonPrefStore::RemoveObserver(PrefStore::Observer* observer) { | 191 void JsonPrefStore::RemoveObserver(PrefStore::Observer* observer) { |
192 DCHECK(CalledOnValidThread()); | |
193 | |
213 observers_.RemoveObserver(observer); | 194 observers_.RemoveObserver(observer); |
214 } | 195 } |
215 | 196 |
216 bool JsonPrefStore::HasObservers() const { | 197 bool JsonPrefStore::HasObservers() const { |
198 DCHECK(CalledOnValidThread()); | |
199 | |
217 return observers_.might_have_observers(); | 200 return observers_.might_have_observers(); |
218 } | 201 } |
219 | 202 |
220 bool JsonPrefStore::IsInitializationComplete() const { | 203 bool JsonPrefStore::IsInitializationComplete() const { |
204 DCHECK(CalledOnValidThread()); | |
205 | |
221 return initialized_; | 206 return initialized_; |
222 } | 207 } |
223 | 208 |
224 bool JsonPrefStore::GetMutableValue(const std::string& key, | 209 bool JsonPrefStore::GetMutableValue(const std::string& key, |
225 base::Value** result) { | 210 base::Value** result) { |
211 DCHECK(CalledOnValidThread()); | |
212 | |
226 return prefs_->Get(key, result); | 213 return prefs_->Get(key, result); |
227 } | 214 } |
228 | 215 |
229 void JsonPrefStore::SetValue(const std::string& key, base::Value* value) { | 216 void JsonPrefStore::SetValue(const std::string& key, base::Value* value) { |
217 DCHECK(CalledOnValidThread()); | |
218 | |
230 DCHECK(value); | 219 DCHECK(value); |
231 scoped_ptr<base::Value> new_value(value); | 220 scoped_ptr<base::Value> new_value(value); |
232 base::Value* old_value = NULL; | 221 base::Value* old_value = NULL; |
233 prefs_->Get(key, &old_value); | 222 prefs_->Get(key, &old_value); |
234 if (!old_value || !value->Equals(old_value)) { | 223 if (!old_value || !value->Equals(old_value)) { |
235 prefs_->Set(key, new_value.release()); | 224 prefs_->Set(key, new_value.release()); |
236 ReportValueChanged(key); | 225 ReportValueChanged(key); |
237 } | 226 } |
238 } | 227 } |
239 | 228 |
240 void JsonPrefStore::SetValueSilently(const std::string& key, | 229 void JsonPrefStore::SetValueSilently(const std::string& key, |
241 base::Value* value) { | 230 base::Value* value) { |
231 DCHECK(CalledOnValidThread()); | |
232 | |
242 DCHECK(value); | 233 DCHECK(value); |
243 scoped_ptr<base::Value> new_value(value); | 234 scoped_ptr<base::Value> new_value(value); |
244 base::Value* old_value = NULL; | 235 base::Value* old_value = NULL; |
245 prefs_->Get(key, &old_value); | 236 prefs_->Get(key, &old_value); |
246 if (!old_value || !value->Equals(old_value)) { | 237 if (!old_value || !value->Equals(old_value)) { |
247 prefs_->Set(key, new_value.release()); | 238 prefs_->Set(key, new_value.release()); |
248 if (!read_only_) | 239 if (!read_only_) |
249 writer_.ScheduleWrite(this); | 240 writer_.ScheduleWrite(this); |
250 } | 241 } |
251 } | 242 } |
252 | 243 |
253 void JsonPrefStore::RemoveValue(const std::string& key) { | 244 void JsonPrefStore::RemoveValue(const std::string& key) { |
245 DCHECK(CalledOnValidThread()); | |
246 | |
254 if (prefs_->RemovePath(key, NULL)) | 247 if (prefs_->RemovePath(key, NULL)) |
255 ReportValueChanged(key); | 248 ReportValueChanged(key); |
256 } | 249 } |
257 | 250 |
258 void JsonPrefStore::RemoveValueSilently(const std::string& key) { | 251 void JsonPrefStore::RemoveValueSilently(const std::string& key) { |
252 DCHECK(CalledOnValidThread()); | |
253 | |
259 prefs_->RemovePath(key, NULL); | 254 prefs_->RemovePath(key, NULL); |
260 if (!read_only_) | 255 if (!read_only_) |
261 writer_.ScheduleWrite(this); | 256 writer_.ScheduleWrite(this); |
262 } | 257 } |
263 | 258 |
264 bool JsonPrefStore::ReadOnly() const { | 259 bool JsonPrefStore::ReadOnly() const { |
260 DCHECK(CalledOnValidThread()); | |
261 | |
265 return read_only_; | 262 return read_only_; |
266 } | 263 } |
267 | 264 |
268 PersistentPrefStore::PrefReadError JsonPrefStore::GetReadError() const { | 265 PersistentPrefStore::PrefReadError JsonPrefStore::GetReadError() const { |
266 DCHECK(CalledOnValidThread()); | |
267 | |
269 return read_error_; | 268 return read_error_; |
270 } | 269 } |
271 | 270 |
272 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() { | 271 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() { |
272 DCHECK(CalledOnValidThread()); | |
273 | |
273 if (path_.empty()) { | 274 if (path_.empty()) { |
274 OnFileRead( | 275 scoped_ptr<ReadResult> no_file_result; |
275 scoped_ptr<base::Value>(), PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); | 276 no_file_result->error = PREF_READ_ERROR_FILE_NOT_SPECIFIED; |
277 OnFileRead(no_file_result.Pass()); | |
276 return PREF_READ_ERROR_FILE_NOT_SPECIFIED; | 278 return PREF_READ_ERROR_FILE_NOT_SPECIFIED; |
277 } | 279 } |
278 | 280 |
279 PrefReadError error; | 281 OnFileRead(ReadPrefsFromDisk(path_, alternate_path_)); |
280 bool no_dir; | 282 return filtering_in_progress_ ? PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE |
281 scoped_ptr<base::Value> value( | 283 : read_error_; |
282 FileThreadDeserializer::DoReading(path_, alternate_path_, &error, | |
283 &no_dir)); | |
284 OnFileRead(value.Pass(), error, no_dir); | |
285 return filtering_in_progress_ ? PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE : | |
286 error; | |
287 } | 284 } |
288 | 285 |
289 void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) { | 286 void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) { |
287 DCHECK(CalledOnValidThread()); | |
288 | |
290 initialized_ = false; | 289 initialized_ = false; |
291 error_delegate_.reset(error_delegate); | 290 error_delegate_.reset(error_delegate); |
292 if (path_.empty()) { | 291 if (path_.empty()) { |
293 OnFileRead( | 292 scoped_ptr<ReadResult> no_file_result; |
294 scoped_ptr<base::Value>(), PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); | 293 no_file_result->error = PREF_READ_ERROR_FILE_NOT_SPECIFIED; |
294 OnFileRead(no_file_result.Pass()); | |
295 return; | 295 return; |
296 } | 296 } |
297 | 297 |
298 // Start async reading of the preferences file. It will delete itself | 298 PostAsyncReadTask(sequenced_task_runner_, |
299 // in the end. | 299 path_, |
300 scoped_refptr<FileThreadDeserializer> deserializer( | 300 alternate_path_, |
301 new FileThreadDeserializer(this, sequenced_task_runner_.get())); | 301 base::Bind(&JsonPrefStore::OnFileRead, this)); |
302 deserializer->Start(path_, alternate_path_); | |
303 } | 302 } |
304 | 303 |
305 void JsonPrefStore::CommitPendingWrite() { | 304 void JsonPrefStore::CommitPendingWrite() { |
305 DCHECK(CalledOnValidThread()); | |
306 | |
306 if (writer_.HasPendingWrite() && !read_only_) | 307 if (writer_.HasPendingWrite() && !read_only_) |
307 writer_.DoScheduledWrite(); | 308 writer_.DoScheduledWrite(); |
308 } | 309 } |
309 | 310 |
310 void JsonPrefStore::ReportValueChanged(const std::string& key) { | 311 void JsonPrefStore::ReportValueChanged(const std::string& key) { |
312 DCHECK(CalledOnValidThread()); | |
313 | |
311 if (pref_filter_) | 314 if (pref_filter_) |
312 pref_filter_->FilterUpdate(key); | 315 pref_filter_->FilterUpdate(key); |
313 | 316 |
314 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); | 317 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); |
315 | 318 |
316 if (!read_only_) | 319 if (!read_only_) |
317 writer_.ScheduleWrite(this); | 320 writer_.ScheduleWrite(this); |
318 } | 321 } |
319 | 322 |
320 void JsonPrefStore::RegisterOnNextSuccessfulWriteCallback( | 323 void JsonPrefStore::RegisterOnNextSuccessfulWriteCallback( |
321 const base::Closure& on_next_successful_write) { | 324 const base::Closure& on_next_successful_write) { |
325 DCHECK(CalledOnValidThread()); | |
326 | |
322 writer_.RegisterOnNextSuccessfulWriteCallback(on_next_successful_write); | 327 writer_.RegisterOnNextSuccessfulWriteCallback(on_next_successful_write); |
323 } | 328 } |
324 | 329 |
325 void JsonPrefStore::OnFileRead(scoped_ptr<base::Value> value, | 330 void JsonPrefStore::OnFileRead(scoped_ptr<ReadResult> read_result) { |
326 PersistentPrefStore::PrefReadError error, | 331 DCHECK(CalledOnValidThread()); |
327 bool no_dir) { | 332 |
333 DCHECK(read_result); | |
334 | |
328 scoped_ptr<base::DictionaryValue> unfiltered_prefs(new base::DictionaryValue); | 335 scoped_ptr<base::DictionaryValue> unfiltered_prefs(new base::DictionaryValue); |
329 | 336 |
330 read_error_ = error; | 337 read_error_ = read_result->error; |
331 | 338 |
332 bool initialization_successful = !no_dir; | 339 bool initialization_successful = !read_result->no_dir; |
333 | 340 |
334 if (initialization_successful) { | 341 if (initialization_successful) { |
335 switch (read_error_) { | 342 switch (read_error_) { |
336 case PREF_READ_ERROR_ACCESS_DENIED: | 343 case PREF_READ_ERROR_ACCESS_DENIED: |
337 case PREF_READ_ERROR_FILE_OTHER: | 344 case PREF_READ_ERROR_FILE_OTHER: |
338 case PREF_READ_ERROR_FILE_LOCKED: | 345 case PREF_READ_ERROR_FILE_LOCKED: |
339 case PREF_READ_ERROR_JSON_TYPE: | 346 case PREF_READ_ERROR_JSON_TYPE: |
340 case PREF_READ_ERROR_FILE_NOT_SPECIFIED: | 347 case PREF_READ_ERROR_FILE_NOT_SPECIFIED: |
341 read_only_ = true; | 348 read_only_ = true; |
342 break; | 349 break; |
343 case PREF_READ_ERROR_NONE: | 350 case PREF_READ_ERROR_NONE: |
344 DCHECK(value.get()); | 351 DCHECK(read_result->value.get()); |
345 unfiltered_prefs.reset( | 352 unfiltered_prefs.reset( |
346 static_cast<base::DictionaryValue*>(value.release())); | 353 static_cast<base::DictionaryValue*>(read_result->value.release())); |
347 break; | 354 break; |
348 case PREF_READ_ERROR_NO_FILE: | 355 case PREF_READ_ERROR_NO_FILE: |
349 // If the file just doesn't exist, maybe this is first run. In any case | 356 // If the file just doesn't exist, maybe this is first run. In any case |
350 // there's no harm in writing out default prefs in this case. | 357 // there's no harm in writing out default prefs in this case. |
351 break; | 358 break; |
352 case PREF_READ_ERROR_JSON_PARSE: | 359 case PREF_READ_ERROR_JSON_PARSE: |
353 case PREF_READ_ERROR_JSON_REPEAT: | 360 case PREF_READ_ERROR_JSON_REPEAT: |
354 break; | 361 break; |
355 case PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE: | 362 case PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE: |
356 // This is a special error code to be returned by ReadPrefs when it | 363 // This is a special error code to be returned by ReadPrefs when it |
(...skipping 22 matching lines...) Expand all Loading... | |
379 } else { | 386 } else { |
380 FinalizeFileRead(initialization_successful, unfiltered_prefs.Pass(), false); | 387 FinalizeFileRead(initialization_successful, unfiltered_prefs.Pass(), false); |
381 } | 388 } |
382 } | 389 } |
383 | 390 |
384 JsonPrefStore::~JsonPrefStore() { | 391 JsonPrefStore::~JsonPrefStore() { |
385 CommitPendingWrite(); | 392 CommitPendingWrite(); |
386 } | 393 } |
387 | 394 |
388 bool JsonPrefStore::SerializeData(std::string* output) { | 395 bool JsonPrefStore::SerializeData(std::string* output) { |
396 DCHECK(CalledOnValidThread()); | |
397 | |
389 if (pref_filter_) | 398 if (pref_filter_) |
390 pref_filter_->FilterSerializeData(prefs_.get()); | 399 pref_filter_->FilterSerializeData(prefs_.get()); |
391 | 400 |
392 JSONStringValueSerializer serializer(output); | 401 JSONStringValueSerializer serializer(output); |
393 serializer.set_pretty_print(true); | 402 serializer.set_pretty_print(true); |
394 bool result = serializer.Serialize(*prefs_); | 403 bool result = serializer.Serialize(*prefs_); |
395 | 404 |
396 if (result) { | 405 if (result) { |
397 std::string spaceless_basename; | 406 std::string spaceless_basename; |
398 base::ReplaceChars(path_.BaseName().MaybeAsASCII(), " ", "_", | 407 base::ReplaceChars(path_.BaseName().MaybeAsASCII(), " ", "_", |
(...skipping 11 matching lines...) Expand all Loading... | |
410 base::HistogramBase::kUmaTargetedHistogramFlag); | 419 base::HistogramBase::kUmaTargetedHistogramFlag); |
411 histogram->Add(static_cast<int>(output->size()) / 1024); | 420 histogram->Add(static_cast<int>(output->size()) / 1024); |
412 } | 421 } |
413 | 422 |
414 return result; | 423 return result; |
415 } | 424 } |
416 | 425 |
417 void JsonPrefStore::FinalizeFileRead(bool initialization_successful, | 426 void JsonPrefStore::FinalizeFileRead(bool initialization_successful, |
418 scoped_ptr<base::DictionaryValue> prefs, | 427 scoped_ptr<base::DictionaryValue> prefs, |
419 bool schedule_write) { | 428 bool schedule_write) { |
429 DCHECK(CalledOnValidThread()); | |
430 | |
420 filtering_in_progress_ = false; | 431 filtering_in_progress_ = false; |
421 | 432 |
422 if (!initialization_successful) { | 433 if (!initialization_successful) { |
423 FOR_EACH_OBSERVER(PrefStore::Observer, | 434 FOR_EACH_OBSERVER(PrefStore::Observer, |
424 observers_, | 435 observers_, |
425 OnInitializationCompleted(false)); | 436 OnInitializationCompleted(false)); |
426 return; | 437 return; |
427 } | 438 } |
428 | 439 |
429 prefs_ = prefs.Pass(); | 440 prefs_ = prefs.Pass(); |
430 | 441 |
431 initialized_ = true; | 442 initialized_ = true; |
432 | 443 |
433 if (schedule_write && !read_only_) | 444 if (schedule_write && !read_only_) |
434 writer_.ScheduleWrite(this); | 445 writer_.ScheduleWrite(this); |
435 | 446 |
436 if (error_delegate_ && read_error_ != PREF_READ_ERROR_NONE) | 447 if (error_delegate_ && read_error_ != PREF_READ_ERROR_NONE) |
437 error_delegate_->OnError(read_error_); | 448 error_delegate_->OnError(read_error_); |
438 | 449 |
439 FOR_EACH_OBSERVER(PrefStore::Observer, | 450 FOR_EACH_OBSERVER(PrefStore::Observer, |
440 observers_, | 451 observers_, |
441 OnInitializationCompleted(true)); | 452 OnInitializationCompleted(true)); |
442 | 453 |
443 return; | 454 return; |
444 } | 455 } |
OLD | NEW |