| 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 |