Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "chrome/common/json_pref_store.h" | 5 #include "chrome/common/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 23 matching lines...) Expand all Loading... | |
| 34 FROM_HERE, | 34 FROM_HERE, |
| 35 NewRunnableMethod(this, | 35 NewRunnableMethod(this, |
| 36 &FileThreadDeserializer::ReadFileAndReport, | 36 &FileThreadDeserializer::ReadFileAndReport, |
| 37 path)); | 37 path)); |
| 38 } | 38 } |
| 39 | 39 |
| 40 // Deserializes JSON on the FILE thread. | 40 // Deserializes JSON on the FILE thread. |
| 41 void ReadFileAndReport(const FilePath& path) { | 41 void ReadFileAndReport(const FilePath& path) { |
| 42 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 42 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 43 | 43 |
| 44 int error_code; | 44 value_.reset(DoReading(path, &error_, &no_dir_)); |
| 45 std::string error_msg; | |
| 46 JSONFileValueSerializer serializer(path); | |
| 47 value_.reset(serializer.Deserialize(&error_code, &error_msg)); | |
| 48 | |
| 49 HandleErrors(value_.get(), path, error_code, error_msg, &error_); | |
| 50 | |
| 51 no_dir_ = !file_util::PathExists(path.DirName()); | |
| 52 | 45 |
| 53 BrowserThread::PostTask( | 46 BrowserThread::PostTask( |
| 54 BrowserThread::UI, | 47 BrowserThread::UI, |
| 55 FROM_HERE, | 48 FROM_HERE, |
| 56 NewRunnableMethod(this, &FileThreadDeserializer::ReportOnUIThread)); | 49 NewRunnableMethod(this, &FileThreadDeserializer::ReportOnUIThread)); |
| 57 } | 50 } |
| 58 | 51 |
| 59 // Reports deserialization result on the UI thread. | 52 // Reports deserialization result on the UI thread. |
| 60 void ReportOnUIThread() { | 53 void ReportOnUIThread() { |
| 61 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 62 delegate_->OnFileRead(value_.release(), error_, no_dir_); | 55 delegate_->OnFileRead(value_.release(), error_, no_dir_); |
| 63 } | 56 } |
| 64 | 57 |
| 58 static Value* DoReading(const FilePath& path, | |
| 59 PersistentPrefStore::PrefReadError* error, | |
| 60 bool* no_dir) { | |
| 61 int error_code; | |
| 62 std::string error_msg; | |
| 63 JSONFileValueSerializer serializer(path); | |
| 64 Value* value = serializer.Deserialize(&error_code, &error_msg); | |
| 65 HandleErrors(value, path, error_code, error_msg, error); | |
| 66 (*no_dir) = !file_util::PathExists(path.DirName()); | |
| 67 return value; | |
| 68 } | |
| 69 | |
| 65 static void HandleErrors(const Value* value, | 70 static void HandleErrors(const Value* value, |
| 66 const FilePath& path, | 71 const FilePath& path, |
| 67 int error_code, | 72 int error_code, |
| 68 const std::string& error_msg, | 73 const std::string& error_msg, |
| 69 PersistentPrefStore::PrefReadError* error); | 74 PersistentPrefStore::PrefReadError* error); |
| 70 | 75 |
| 71 private: | 76 private: |
| 72 friend class base::RefCountedThreadSafe<FileThreadDeserializer>; | 77 friend class base::RefCountedThreadSafe<FileThreadDeserializer>; |
| 73 | 78 |
| 74 bool no_dir_; | 79 bool no_dir_; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 123 } | 128 } |
| 124 } | 129 } |
| 125 | 130 |
| 126 } // namespace | 131 } // namespace |
| 127 | 132 |
| 128 JsonPrefStore::JsonPrefStore(const FilePath& filename, | 133 JsonPrefStore::JsonPrefStore(const FilePath& filename, |
| 129 base::MessageLoopProxy* file_message_loop_proxy) | 134 base::MessageLoopProxy* file_message_loop_proxy) |
| 130 : path_(filename), | 135 : path_(filename), |
| 131 prefs_(new DictionaryValue()), | 136 prefs_(new DictionaryValue()), |
| 132 read_only_(false), | 137 read_only_(false), |
| 133 writer_(filename, file_message_loop_proxy) { | 138 writer_(filename, file_message_loop_proxy), |
| 139 error_(PREF_READ_ERROR_NONE), | |
| 140 is_fatal_(false) { | |
| 134 } | 141 } |
| 135 | 142 |
| 136 JsonPrefStore::~JsonPrefStore() { | 143 JsonPrefStore::~JsonPrefStore() { |
| 137 CommitPendingWrite(); | 144 CommitPendingWrite(); |
| 138 } | 145 } |
| 139 | 146 |
| 140 PrefStore::ReadResult JsonPrefStore::GetValue(const std::string& key, | 147 PrefStore::ReadResult JsonPrefStore::GetValue(const std::string& key, |
| 141 const Value** result) const { | 148 const Value** result) const { |
| 142 Value* tmp = NULL; | 149 Value* tmp = NULL; |
| 143 if (prefs_->Get(key, &tmp)) { | 150 if (prefs_->Get(key, &tmp)) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 186 } | 193 } |
| 187 } | 194 } |
| 188 | 195 |
| 189 bool JsonPrefStore::ReadOnly() const { | 196 bool JsonPrefStore::ReadOnly() const { |
| 190 return read_only_; | 197 return read_only_; |
| 191 } | 198 } |
| 192 | 199 |
| 193 void JsonPrefStore::OnFileRead(Value* value_owned, | 200 void JsonPrefStore::OnFileRead(Value* value_owned, |
| 194 PersistentPrefStore::PrefReadError error, | 201 PersistentPrefStore::PrefReadError error, |
| 195 bool no_dir) { | 202 bool no_dir) { |
| 203 error_ = error; | |
| 204 is_fatal_ = no_dir; | |
| 205 | |
| 196 scoped_ptr<Value> value(value_owned); | 206 scoped_ptr<Value> value(value_owned); |
| 197 switch (error) { | 207 switch (error) { |
| 198 case PREF_READ_ERROR_ACCESS_DENIED: | 208 case PREF_READ_ERROR_ACCESS_DENIED: |
| 199 case PREF_READ_ERROR_FILE_OTHER: | 209 case PREF_READ_ERROR_FILE_OTHER: |
| 200 case PREF_READ_ERROR_FILE_LOCKED: | 210 case PREF_READ_ERROR_FILE_LOCKED: |
| 201 case PREF_READ_ERROR_JSON_TYPE: | 211 case PREF_READ_ERROR_JSON_TYPE: |
| 212 case PREF_READ_ERROR_FILE_NOT_SPECIFIED: | |
| 202 read_only_ = true; | 213 read_only_ = true; |
| 203 break; | 214 break; |
| 204 case PREF_READ_ERROR_NONE: | 215 case PREF_READ_ERROR_NONE: |
| 205 DCHECK(value.get()); | 216 DCHECK(value.get()); |
| 206 prefs_.reset(static_cast<DictionaryValue*>(value.release())); | 217 prefs_.reset(static_cast<DictionaryValue*>(value.release())); |
| 207 break; | 218 break; |
| 208 case PREF_READ_ERROR_NO_FILE: | 219 case PREF_READ_ERROR_NO_FILE: |
| 209 // If the file just doesn't exist, maybe this is first run. In any case | 220 // If the file just doesn't exist, maybe this is first run. In any case |
| 210 // there's no harm in writing out default prefs in this case. | 221 // there's no harm in writing out default prefs in this case. |
| 211 break; | 222 break; |
| 212 case PREF_READ_ERROR_JSON_PARSE: | 223 case PREF_READ_ERROR_JSON_PARSE: |
| 213 case PREF_READ_ERROR_JSON_REPEAT: | 224 case PREF_READ_ERROR_JSON_REPEAT: |
| 214 break; | 225 break; |
| 215 default: | 226 default: |
| 216 NOTREACHED() << "Unknown error: " << error; | 227 NOTREACHED() << "Unknown error: " << error; |
| 217 } | 228 } |
| 218 | 229 |
| 219 if (delegate_) | 230 FOR_EACH_OBSERVER(PrefStore::Observer, |
| 220 delegate_->OnPrefsRead(error, no_dir); | 231 observers_, |
| 232 OnInitializationCompleted()); | |
| 221 } | 233 } |
| 222 | 234 |
| 223 void JsonPrefStore::ReadPrefs(Delegate* delegate) { | 235 void JsonPrefStore::ReadPrefsAsync() { |
|
Mattias Nissler (ping if slow)
2011/04/26 09:04:26
I was wondering before if we could just merge Read
altimofeev
2011/04/27 10:32:08
I remember, and actually thought about it. And the
Mattias Nissler (ping if slow)
2011/04/27 12:16:30
If we do it, we should make sure we don't put addi
| |
| 224 DCHECK(delegate); | |
| 225 delegate_ = delegate; | |
| 226 | |
| 227 if (path_.empty()) { | 236 if (path_.empty()) { |
| 228 read_only_ = true; | 237 OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); |
| 229 delegate_->OnPrefsRead(PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); | |
| 230 return; | 238 return; |
| 231 } | 239 } |
| 232 | 240 |
| 233 // This guarantees that class will not be deleted while JSON is readed. | 241 // This guarantees that class will not be deleted while JSON is readed. |
| 234 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 242 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 235 | 243 |
| 236 // Start async reading of the preferences file. It will delete itself | 244 // Start async reading of the preferences file. It will delete itself |
| 237 // in the end. | 245 // in the end. |
| 238 scoped_refptr<FileThreadDeserializer> deserializer( | 246 scoped_refptr<FileThreadDeserializer> deserializer( |
| 239 new FileThreadDeserializer(this)); | 247 new FileThreadDeserializer(this)); |
| 240 deserializer->Start(path_); | 248 deserializer->Start(path_); |
| 241 } | 249 } |
| 242 | 250 |
| 243 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() { | 251 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() { |
| 244 delegate_ = NULL; | |
| 245 | |
| 246 if (path_.empty()) { | 252 if (path_.empty()) { |
| 247 read_only_ = true; | 253 OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); |
| 248 return PREF_READ_ERROR_FILE_NOT_SPECIFIED; | 254 return error_; |
| 249 } | 255 } |
| 250 | 256 |
| 251 int error_code = 0; | 257 Value* value = FileThreadDeserializer::DoReading(path_, |
| 252 std::string error_msg; | 258 &error_, |
| 259 &is_fatal_); | |
| 260 OnFileRead(value, error_, is_fatal_); | |
| 261 return error_; | |
| 262 } | |
| 253 | 263 |
| 254 JSONFileValueSerializer serializer(path_); | 264 void JsonPrefStore::GetErrors(PrefReadError* error, bool* is_fatal) { |
| 255 scoped_ptr<Value> value(serializer.Deserialize(&error_code, &error_msg)); | 265 (*error) = error_; |
|
Bernhard Bauer
2011/04/25 15:54:10
Nit: the parentheses are not actually necessary, b
altimofeev
2011/04/27 10:32:08
This is the matter of taste, I think. But grep say
| |
| 256 | 266 (*is_fatal) = is_fatal_; |
| 257 PersistentPrefStore::PrefReadError error; | |
| 258 FileThreadDeserializer::HandleErrors(value.get(), | |
| 259 path_, | |
| 260 error_code, | |
| 261 error_msg, | |
| 262 &error); | |
| 263 | |
| 264 OnFileRead(value.release(), error, false); | |
| 265 | |
| 266 return error; | |
| 267 } | 267 } |
| 268 | 268 |
| 269 bool JsonPrefStore::WritePrefs() { | 269 bool JsonPrefStore::WritePrefs() { |
| 270 std::string data; | 270 std::string data; |
| 271 if (!SerializeData(&data)) | 271 if (!SerializeData(&data)) |
| 272 return false; | 272 return false; |
| 273 | 273 |
| 274 // Lie about our ability to save. | 274 // Lie about our ability to save. |
| 275 if (read_only_) | 275 if (read_only_) |
| 276 return true; | 276 return true; |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 296 } | 296 } |
| 297 | 297 |
| 298 bool JsonPrefStore::SerializeData(std::string* output) { | 298 bool JsonPrefStore::SerializeData(std::string* output) { |
| 299 // TODO(tc): Do we want to prune webkit preferences that match the default | 299 // TODO(tc): Do we want to prune webkit preferences that match the default |
| 300 // value? | 300 // value? |
| 301 JSONStringValueSerializer serializer(output); | 301 JSONStringValueSerializer serializer(output); |
| 302 serializer.set_pretty_print(true); | 302 serializer.set_pretty_print(true); |
| 303 scoped_ptr<DictionaryValue> copy(prefs_->DeepCopyWithoutEmptyChildren()); | 303 scoped_ptr<DictionaryValue> copy(prefs_->DeepCopyWithoutEmptyChildren()); |
| 304 return serializer.Serialize(*(copy.get())); | 304 return serializer.Serialize(*(copy.get())); |
| 305 } | 305 } |
| OLD | NEW |