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" |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 FROM_HERE, | 54 FROM_HERE, |
55 base::Bind(&FileThreadDeserializer::ReportOnOriginThread, this)); | 55 base::Bind(&FileThreadDeserializer::ReportOnOriginThread, this)); |
56 } | 56 } |
57 | 57 |
58 // Reports deserialization result on the origin thread. | 58 // Reports deserialization result on the origin thread. |
59 void ReportOnOriginThread() { | 59 void ReportOnOriginThread() { |
60 DCHECK(origin_loop_proxy_->BelongsToCurrentThread()); | 60 DCHECK(origin_loop_proxy_->BelongsToCurrentThread()); |
61 delegate_->OnFileRead(value_.release(), error_, no_dir_); | 61 delegate_->OnFileRead(value_.release(), error_, no_dir_); |
62 } | 62 } |
63 | 63 |
64 static Value* DoReading(const base::FilePath& path, | 64 static base::Value* DoReading(const base::FilePath& path, |
65 PersistentPrefStore::PrefReadError* error, | 65 PersistentPrefStore::PrefReadError* error, |
66 bool* no_dir) { | 66 bool* no_dir) { |
67 int error_code; | 67 int error_code; |
68 std::string error_msg; | 68 std::string error_msg; |
69 JSONFileValueSerializer serializer(path); | 69 JSONFileValueSerializer serializer(path); |
70 Value* value = serializer.Deserialize(&error_code, &error_msg); | 70 base::Value* value = serializer.Deserialize(&error_code, &error_msg); |
71 HandleErrors(value, path, error_code, error_msg, error); | 71 HandleErrors(value, path, error_code, error_msg, error); |
72 *no_dir = !file_util::PathExists(path.DirName()); | 72 *no_dir = !file_util::PathExists(path.DirName()); |
73 return value; | 73 return value; |
74 } | 74 } |
75 | 75 |
76 static void HandleErrors(const Value* value, | 76 static void HandleErrors(const base::Value* value, |
77 const base::FilePath& path, | 77 const base::FilePath& path, |
78 int error_code, | 78 int error_code, |
79 const std::string& error_msg, | 79 const std::string& error_msg, |
80 PersistentPrefStore::PrefReadError* error); | 80 PersistentPrefStore::PrefReadError* error); |
81 | 81 |
82 private: | 82 private: |
83 friend class base::RefCountedThreadSafe<FileThreadDeserializer>; | 83 friend class base::RefCountedThreadSafe<FileThreadDeserializer>; |
84 ~FileThreadDeserializer() {} | 84 ~FileThreadDeserializer() {} |
85 | 85 |
86 bool no_dir_; | 86 bool no_dir_; |
87 PersistentPrefStore::PrefReadError error_; | 87 PersistentPrefStore::PrefReadError error_; |
88 scoped_ptr<Value> value_; | 88 scoped_ptr<base::Value> value_; |
89 const scoped_refptr<JsonPrefStore> delegate_; | 89 const scoped_refptr<JsonPrefStore> delegate_; |
90 const scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_; | 90 const scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_; |
91 const scoped_refptr<base::MessageLoopProxy> origin_loop_proxy_; | 91 const scoped_refptr<base::MessageLoopProxy> origin_loop_proxy_; |
92 }; | 92 }; |
93 | 93 |
94 // static | 94 // static |
95 void FileThreadDeserializer::HandleErrors( | 95 void FileThreadDeserializer::HandleErrors( |
96 const Value* value, | 96 const base::Value* value, |
97 const base::FilePath& path, | 97 const base::FilePath& path, |
98 int error_code, | 98 int error_code, |
99 const std::string& error_msg, | 99 const std::string& error_msg, |
100 PersistentPrefStore::PrefReadError* error) { | 100 PersistentPrefStore::PrefReadError* error) { |
101 *error = PersistentPrefStore::PREF_READ_ERROR_NONE; | 101 *error = PersistentPrefStore::PREF_READ_ERROR_NONE; |
102 if (!value) { | 102 if (!value) { |
103 DVLOG(1) << "Error while loading JSON file: " << error_msg | 103 DVLOG(1) << "Error while loading JSON file: " << error_msg |
104 << ", file: " << path.value(); | 104 << ", file: " << path.value(); |
105 switch (error_code) { | 105 switch (error_code) { |
106 case JSONFileValueSerializer::JSON_ACCESS_DENIED: | 106 case JSONFileValueSerializer::JSON_ACCESS_DENIED: |
(...skipping 19 matching lines...) Expand all Loading... |
126 base::FilePath bad = path.ReplaceExtension(kBadExtension); | 126 base::FilePath bad = path.ReplaceExtension(kBadExtension); |
127 | 127 |
128 // If they've ever had a parse error before, put them in another bucket. | 128 // If they've ever had a parse error before, put them in another bucket. |
129 // TODO(erikkay) if we keep this error checking for very long, we may | 129 // TODO(erikkay) if we keep this error checking for very long, we may |
130 // want to differentiate between recent and long ago errors. | 130 // want to differentiate between recent and long ago errors. |
131 if (file_util::PathExists(bad)) | 131 if (file_util::PathExists(bad)) |
132 *error = PersistentPrefStore::PREF_READ_ERROR_JSON_REPEAT; | 132 *error = PersistentPrefStore::PREF_READ_ERROR_JSON_REPEAT; |
133 file_util::Move(path, bad); | 133 file_util::Move(path, bad); |
134 break; | 134 break; |
135 } | 135 } |
136 } else if (!value->IsType(Value::TYPE_DICTIONARY)) { | 136 } else if (!value->IsType(base::Value::TYPE_DICTIONARY)) { |
137 *error = PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE; | 137 *error = PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE; |
138 } | 138 } |
139 } | 139 } |
140 | 140 |
141 } // namespace | 141 } // namespace |
142 | 142 |
143 scoped_refptr<base::SequencedTaskRunner> JsonPrefStore::GetTaskRunnerForFile( | 143 scoped_refptr<base::SequencedTaskRunner> JsonPrefStore::GetTaskRunnerForFile( |
144 const base::FilePath& filename, | 144 const base::FilePath& filename, |
145 base::SequencedWorkerPool* worker_pool) { | 145 base::SequencedWorkerPool* worker_pool) { |
146 std::string token("json_pref_store-"); | 146 std::string token("json_pref_store-"); |
147 token.append(filename.AsUTF8Unsafe()); | 147 token.append(filename.AsUTF8Unsafe()); |
148 return worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( | 148 return worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( |
149 worker_pool->GetNamedSequenceToken(token), | 149 worker_pool->GetNamedSequenceToken(token), |
150 base::SequencedWorkerPool::BLOCK_SHUTDOWN); | 150 base::SequencedWorkerPool::BLOCK_SHUTDOWN); |
151 } | 151 } |
152 | 152 |
153 JsonPrefStore::JsonPrefStore(const base::FilePath& filename, | 153 JsonPrefStore::JsonPrefStore(const base::FilePath& filename, |
154 base::SequencedTaskRunner* sequenced_task_runner) | 154 base::SequencedTaskRunner* sequenced_task_runner) |
155 : path_(filename), | 155 : path_(filename), |
156 sequenced_task_runner_(sequenced_task_runner), | 156 sequenced_task_runner_(sequenced_task_runner), |
157 prefs_(new DictionaryValue()), | 157 prefs_(new base::DictionaryValue()), |
158 read_only_(false), | 158 read_only_(false), |
159 writer_(filename, sequenced_task_runner), | 159 writer_(filename, sequenced_task_runner), |
160 initialized_(false), | 160 initialized_(false), |
161 read_error_(PREF_READ_ERROR_OTHER) {} | 161 read_error_(PREF_READ_ERROR_OTHER) {} |
162 | 162 |
163 bool JsonPrefStore::GetValue(const std::string& key, | 163 bool JsonPrefStore::GetValue(const std::string& key, |
164 const Value** result) const { | 164 const base::Value** result) const { |
165 Value* tmp = NULL; | 165 base::Value* tmp = NULL; |
166 if (!prefs_->Get(key, &tmp)) | 166 if (!prefs_->Get(key, &tmp)) |
167 return false; | 167 return false; |
168 | 168 |
169 if (result) | 169 if (result) |
170 *result = tmp; | 170 *result = tmp; |
171 return true; | 171 return true; |
172 } | 172 } |
173 | 173 |
174 void JsonPrefStore::AddObserver(PrefStore::Observer* observer) { | 174 void JsonPrefStore::AddObserver(PrefStore::Observer* observer) { |
175 observers_.AddObserver(observer); | 175 observers_.AddObserver(observer); |
176 } | 176 } |
177 | 177 |
178 void JsonPrefStore::RemoveObserver(PrefStore::Observer* observer) { | 178 void JsonPrefStore::RemoveObserver(PrefStore::Observer* observer) { |
179 observers_.RemoveObserver(observer); | 179 observers_.RemoveObserver(observer); |
180 } | 180 } |
181 | 181 |
182 size_t JsonPrefStore::NumberOfObservers() const { | 182 size_t JsonPrefStore::NumberOfObservers() const { |
183 return observers_.size(); | 183 return observers_.size(); |
184 } | 184 } |
185 | 185 |
186 bool JsonPrefStore::IsInitializationComplete() const { | 186 bool JsonPrefStore::IsInitializationComplete() const { |
187 return initialized_; | 187 return initialized_; |
188 } | 188 } |
189 | 189 |
190 bool JsonPrefStore::GetMutableValue(const std::string& key, | 190 bool JsonPrefStore::GetMutableValue(const std::string& key, |
191 Value** result) { | 191 base::Value** result) { |
192 return prefs_->Get(key, result); | 192 return prefs_->Get(key, result); |
193 } | 193 } |
194 | 194 |
195 void JsonPrefStore::SetValue(const std::string& key, Value* value) { | 195 void JsonPrefStore::SetValue(const std::string& key, base::Value* value) { |
196 DCHECK(value); | 196 DCHECK(value); |
197 scoped_ptr<Value> new_value(value); | 197 scoped_ptr<base::Value> new_value(value); |
198 Value* old_value = NULL; | 198 base::Value* old_value = NULL; |
199 prefs_->Get(key, &old_value); | 199 prefs_->Get(key, &old_value); |
200 if (!old_value || !value->Equals(old_value)) { | 200 if (!old_value || !value->Equals(old_value)) { |
201 prefs_->Set(key, new_value.release()); | 201 prefs_->Set(key, new_value.release()); |
202 ReportValueChanged(key); | 202 ReportValueChanged(key); |
203 } | 203 } |
204 } | 204 } |
205 | 205 |
206 void JsonPrefStore::SetValueSilently(const std::string& key, Value* value) { | 206 void JsonPrefStore::SetValueSilently(const std::string& key, |
| 207 base::Value* value) { |
207 DCHECK(value); | 208 DCHECK(value); |
208 scoped_ptr<Value> new_value(value); | 209 scoped_ptr<base::Value> new_value(value); |
209 Value* old_value = NULL; | 210 base::Value* old_value = NULL; |
210 prefs_->Get(key, &old_value); | 211 prefs_->Get(key, &old_value); |
211 if (!old_value || !value->Equals(old_value)) { | 212 if (!old_value || !value->Equals(old_value)) { |
212 prefs_->Set(key, new_value.release()); | 213 prefs_->Set(key, new_value.release()); |
213 if (!read_only_) | 214 if (!read_only_) |
214 writer_.ScheduleWrite(this); | 215 writer_.ScheduleWrite(this); |
215 } | 216 } |
216 } | 217 } |
217 | 218 |
218 void JsonPrefStore::RemoveValue(const std::string& key) { | 219 void JsonPrefStore::RemoveValue(const std::string& key) { |
219 if (prefs_->Remove(key, NULL)) | 220 if (prefs_->Remove(key, NULL)) |
(...skipping 13 matching lines...) Expand all Loading... |
233 } | 234 } |
234 | 235 |
235 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() { | 236 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() { |
236 if (path_.empty()) { | 237 if (path_.empty()) { |
237 OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); | 238 OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); |
238 return PREF_READ_ERROR_FILE_NOT_SPECIFIED; | 239 return PREF_READ_ERROR_FILE_NOT_SPECIFIED; |
239 } | 240 } |
240 | 241 |
241 PrefReadError error; | 242 PrefReadError error; |
242 bool no_dir; | 243 bool no_dir; |
243 Value* value = FileThreadDeserializer::DoReading(path_, &error, &no_dir); | 244 base::Value* value = |
| 245 FileThreadDeserializer::DoReading(path_, &error, &no_dir); |
244 OnFileRead(value, error, no_dir); | 246 OnFileRead(value, error, no_dir); |
245 return error; | 247 return error; |
246 } | 248 } |
247 | 249 |
248 void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate *error_delegate) { | 250 void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate *error_delegate) { |
249 initialized_ = false; | 251 initialized_ = false; |
250 error_delegate_.reset(error_delegate); | 252 error_delegate_.reset(error_delegate); |
251 if (path_.empty()) { | 253 if (path_.empty()) { |
252 OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); | 254 OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); |
253 return; | 255 return; |
(...skipping 10 matching lines...) Expand all Loading... |
264 if (writer_.HasPendingWrite() && !read_only_) | 266 if (writer_.HasPendingWrite() && !read_only_) |
265 writer_.DoScheduledWrite(); | 267 writer_.DoScheduledWrite(); |
266 } | 268 } |
267 | 269 |
268 void JsonPrefStore::ReportValueChanged(const std::string& key) { | 270 void JsonPrefStore::ReportValueChanged(const std::string& key) { |
269 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); | 271 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); |
270 if (!read_only_) | 272 if (!read_only_) |
271 writer_.ScheduleWrite(this); | 273 writer_.ScheduleWrite(this); |
272 } | 274 } |
273 | 275 |
274 void JsonPrefStore::OnFileRead(Value* value_owned, | 276 void JsonPrefStore::OnFileRead(base::Value* value_owned, |
275 PersistentPrefStore::PrefReadError error, | 277 PersistentPrefStore::PrefReadError error, |
276 bool no_dir) { | 278 bool no_dir) { |
277 scoped_ptr<Value> value(value_owned); | 279 scoped_ptr<base::Value> value(value_owned); |
278 read_error_ = error; | 280 read_error_ = error; |
279 | 281 |
280 if (no_dir) { | 282 if (no_dir) { |
281 FOR_EACH_OBSERVER(PrefStore::Observer, | 283 FOR_EACH_OBSERVER(PrefStore::Observer, |
282 observers_, | 284 observers_, |
283 OnInitializationCompleted(false)); | 285 OnInitializationCompleted(false)); |
284 return; | 286 return; |
285 } | 287 } |
286 | 288 |
287 initialized_ = true; | 289 initialized_ = true; |
288 | 290 |
289 switch (error) { | 291 switch (error) { |
290 case PREF_READ_ERROR_ACCESS_DENIED: | 292 case PREF_READ_ERROR_ACCESS_DENIED: |
291 case PREF_READ_ERROR_FILE_OTHER: | 293 case PREF_READ_ERROR_FILE_OTHER: |
292 case PREF_READ_ERROR_FILE_LOCKED: | 294 case PREF_READ_ERROR_FILE_LOCKED: |
293 case PREF_READ_ERROR_JSON_TYPE: | 295 case PREF_READ_ERROR_JSON_TYPE: |
294 case PREF_READ_ERROR_FILE_NOT_SPECIFIED: | 296 case PREF_READ_ERROR_FILE_NOT_SPECIFIED: |
295 read_only_ = true; | 297 read_only_ = true; |
296 break; | 298 break; |
297 case PREF_READ_ERROR_NONE: | 299 case PREF_READ_ERROR_NONE: |
298 DCHECK(value.get()); | 300 DCHECK(value.get()); |
299 prefs_.reset(static_cast<DictionaryValue*>(value.release())); | 301 prefs_.reset(static_cast<base::DictionaryValue*>(value.release())); |
300 break; | 302 break; |
301 case PREF_READ_ERROR_NO_FILE: | 303 case PREF_READ_ERROR_NO_FILE: |
302 // If the file just doesn't exist, maybe this is first run. In any case | 304 // If the file just doesn't exist, maybe this is first run. In any case |
303 // there's no harm in writing out default prefs in this case. | 305 // there's no harm in writing out default prefs in this case. |
304 break; | 306 break; |
305 case PREF_READ_ERROR_JSON_PARSE: | 307 case PREF_READ_ERROR_JSON_PARSE: |
306 case PREF_READ_ERROR_JSON_REPEAT: | 308 case PREF_READ_ERROR_JSON_REPEAT: |
307 break; | 309 break; |
308 default: | 310 default: |
309 NOTREACHED() << "Unknown error: " << error; | 311 NOTREACHED() << "Unknown error: " << error; |
310 } | 312 } |
311 | 313 |
312 if (error_delegate_.get() && error != PREF_READ_ERROR_NONE) | 314 if (error_delegate_.get() && error != PREF_READ_ERROR_NONE) |
313 error_delegate_->OnError(error); | 315 error_delegate_->OnError(error); |
314 | 316 |
315 FOR_EACH_OBSERVER(PrefStore::Observer, | 317 FOR_EACH_OBSERVER(PrefStore::Observer, |
316 observers_, | 318 observers_, |
317 OnInitializationCompleted(true)); | 319 OnInitializationCompleted(true)); |
318 } | 320 } |
319 | 321 |
320 JsonPrefStore::~JsonPrefStore() { | 322 JsonPrefStore::~JsonPrefStore() { |
321 CommitPendingWrite(); | 323 CommitPendingWrite(); |
322 } | 324 } |
323 | 325 |
324 bool JsonPrefStore::SerializeData(std::string* output) { | 326 bool JsonPrefStore::SerializeData(std::string* output) { |
325 // TODO(tc): Do we want to prune webkit preferences that match the default | 327 // TODO(tc): Do we want to prune webkit preferences that match the default |
326 // value? | 328 // value? |
327 JSONStringValueSerializer serializer(output); | 329 JSONStringValueSerializer serializer(output); |
328 serializer.set_pretty_print(true); | 330 serializer.set_pretty_print(true); |
329 scoped_ptr<DictionaryValue> copy(prefs_->DeepCopyWithoutEmptyChildren()); | 331 scoped_ptr<base::DictionaryValue> copy( |
| 332 prefs_->DeepCopyWithoutEmptyChildren()); |
330 | 333 |
331 // Iterates |keys_need_empty_value_| and if the key exists in |prefs_|, | 334 // Iterates |keys_need_empty_value_| and if the key exists in |prefs_|, |
332 // ensure its empty ListValue or DictonaryValue is preserved. | 335 // ensure its empty ListValue or DictonaryValue is preserved. |
333 for (std::set<std::string>::const_iterator | 336 for (std::set<std::string>::const_iterator |
334 it = keys_need_empty_value_.begin(); | 337 it = keys_need_empty_value_.begin(); |
335 it != keys_need_empty_value_.end(); | 338 it != keys_need_empty_value_.end(); |
336 ++it) { | 339 ++it) { |
337 const std::string& key = *it; | 340 const std::string& key = *it; |
338 | 341 |
339 base::Value* value = NULL; | 342 base::Value* value = NULL; |
340 if (!prefs_->Get(key, &value)) | 343 if (!prefs_->Get(key, &value)) |
341 continue; | 344 continue; |
342 | 345 |
343 if (value->IsType(base::Value::TYPE_LIST)) { | 346 if (value->IsType(base::Value::TYPE_LIST)) { |
344 const base::ListValue* list = NULL; | 347 const base::ListValue* list = NULL; |
345 if (value->GetAsList(&list) && list->empty()) | 348 if (value->GetAsList(&list) && list->empty()) |
346 copy->Set(key, new base::ListValue); | 349 copy->Set(key, new base::ListValue); |
347 } else if (value->IsType(base::Value::TYPE_DICTIONARY)) { | 350 } else if (value->IsType(base::Value::TYPE_DICTIONARY)) { |
348 const base::DictionaryValue* dict = NULL; | 351 const base::DictionaryValue* dict = NULL; |
349 if (value->GetAsDictionary(&dict) && dict->empty()) | 352 if (value->GetAsDictionary(&dict) && dict->empty()) |
350 copy->Set(key, new base::DictionaryValue); | 353 copy->Set(key, new base::DictionaryValue); |
351 } | 354 } |
352 } | 355 } |
353 | 356 |
354 return serializer.Serialize(*(copy.get())); | 357 return serializer.Serialize(*(copy.get())); |
355 } | 358 } |
OLD | NEW |