| 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(); |
| 153 } | 112 } |
| 154 | 113 |
| 155 } // namespace | 114 } // namespace |
| 156 | 115 |
| 116 // static |
| 157 scoped_refptr<base::SequencedTaskRunner> JsonPrefStore::GetTaskRunnerForFile( | 117 scoped_refptr<base::SequencedTaskRunner> JsonPrefStore::GetTaskRunnerForFile( |
| 158 const base::FilePath& filename, | 118 const base::FilePath& filename, |
| 159 base::SequencedWorkerPool* worker_pool) { | 119 base::SequencedWorkerPool* worker_pool) { |
| 160 std::string token("json_pref_store-"); | 120 std::string token("json_pref_store-"); |
| 161 token.append(filename.AsUTF8Unsafe()); | 121 token.append(filename.AsUTF8Unsafe()); |
| 162 return worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( | 122 return worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( |
| 163 worker_pool->GetNamedSequenceToken(token), | 123 worker_pool->GetNamedSequenceToken(token), |
| 164 base::SequencedWorkerPool::BLOCK_SHUTDOWN); | 124 base::SequencedWorkerPool::BLOCK_SHUTDOWN); |
| 165 } | 125 } |
| 166 | 126 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 189 read_only_(false), | 149 read_only_(false), |
| 190 writer_(filename, sequenced_task_runner), | 150 writer_(filename, sequenced_task_runner), |
| 191 pref_filter_(pref_filter.Pass()), | 151 pref_filter_(pref_filter.Pass()), |
| 192 initialized_(false), | 152 initialized_(false), |
| 193 filtering_in_progress_(false), | 153 filtering_in_progress_(false), |
| 194 read_error_(PREF_READ_ERROR_NONE) { | 154 read_error_(PREF_READ_ERROR_NONE) { |
| 195 } | 155 } |
| 196 | 156 |
| 197 bool JsonPrefStore::GetValue(const std::string& key, | 157 bool JsonPrefStore::GetValue(const std::string& key, |
| 198 const base::Value** result) const { | 158 const base::Value** result) const { |
| 159 DCHECK(CalledOnValidThread()); |
| 160 |
| 199 base::Value* tmp = NULL; | 161 base::Value* tmp = NULL; |
| 200 if (!prefs_->Get(key, &tmp)) | 162 if (!prefs_->Get(key, &tmp)) |
| 201 return false; | 163 return false; |
| 202 | 164 |
| 203 if (result) | 165 if (result) |
| 204 *result = tmp; | 166 *result = tmp; |
| 205 return true; | 167 return true; |
| 206 } | 168 } |
| 207 | 169 |
| 208 void JsonPrefStore::AddObserver(PrefStore::Observer* observer) { | 170 void JsonPrefStore::AddObserver(PrefStore::Observer* observer) { |
| 171 DCHECK(CalledOnValidThread()); |
| 172 |
| 209 observers_.AddObserver(observer); | 173 observers_.AddObserver(observer); |
| 210 } | 174 } |
| 211 | 175 |
| 212 void JsonPrefStore::RemoveObserver(PrefStore::Observer* observer) { | 176 void JsonPrefStore::RemoveObserver(PrefStore::Observer* observer) { |
| 177 DCHECK(CalledOnValidThread()); |
| 178 |
| 213 observers_.RemoveObserver(observer); | 179 observers_.RemoveObserver(observer); |
| 214 } | 180 } |
| 215 | 181 |
| 216 bool JsonPrefStore::HasObservers() const { | 182 bool JsonPrefStore::HasObservers() const { |
| 183 DCHECK(CalledOnValidThread()); |
| 184 |
| 217 return observers_.might_have_observers(); | 185 return observers_.might_have_observers(); |
| 218 } | 186 } |
| 219 | 187 |
| 220 bool JsonPrefStore::IsInitializationComplete() const { | 188 bool JsonPrefStore::IsInitializationComplete() const { |
| 189 DCHECK(CalledOnValidThread()); |
| 190 |
| 221 return initialized_; | 191 return initialized_; |
| 222 } | 192 } |
| 223 | 193 |
| 224 bool JsonPrefStore::GetMutableValue(const std::string& key, | 194 bool JsonPrefStore::GetMutableValue(const std::string& key, |
| 225 base::Value** result) { | 195 base::Value** result) { |
| 196 DCHECK(CalledOnValidThread()); |
| 197 |
| 226 return prefs_->Get(key, result); | 198 return prefs_->Get(key, result); |
| 227 } | 199 } |
| 228 | 200 |
| 229 void JsonPrefStore::SetValue(const std::string& key, base::Value* value) { | 201 void JsonPrefStore::SetValue(const std::string& key, base::Value* value) { |
| 202 DCHECK(CalledOnValidThread()); |
| 203 |
| 230 DCHECK(value); | 204 DCHECK(value); |
| 231 scoped_ptr<base::Value> new_value(value); | 205 scoped_ptr<base::Value> new_value(value); |
| 232 base::Value* old_value = NULL; | 206 base::Value* old_value = NULL; |
| 233 prefs_->Get(key, &old_value); | 207 prefs_->Get(key, &old_value); |
| 234 if (!old_value || !value->Equals(old_value)) { | 208 if (!old_value || !value->Equals(old_value)) { |
| 235 prefs_->Set(key, new_value.release()); | 209 prefs_->Set(key, new_value.release()); |
| 236 ReportValueChanged(key); | 210 ReportValueChanged(key); |
| 237 } | 211 } |
| 238 } | 212 } |
| 239 | 213 |
| 240 void JsonPrefStore::SetValueSilently(const std::string& key, | 214 void JsonPrefStore::SetValueSilently(const std::string& key, |
| 241 base::Value* value) { | 215 base::Value* value) { |
| 216 DCHECK(CalledOnValidThread()); |
| 217 |
| 242 DCHECK(value); | 218 DCHECK(value); |
| 243 scoped_ptr<base::Value> new_value(value); | 219 scoped_ptr<base::Value> new_value(value); |
| 244 base::Value* old_value = NULL; | 220 base::Value* old_value = NULL; |
| 245 prefs_->Get(key, &old_value); | 221 prefs_->Get(key, &old_value); |
| 246 if (!old_value || !value->Equals(old_value)) { | 222 if (!old_value || !value->Equals(old_value)) { |
| 247 prefs_->Set(key, new_value.release()); | 223 prefs_->Set(key, new_value.release()); |
| 248 if (!read_only_) | 224 if (!read_only_) |
| 249 writer_.ScheduleWrite(this); | 225 writer_.ScheduleWrite(this); |
| 250 } | 226 } |
| 251 } | 227 } |
| 252 | 228 |
| 253 void JsonPrefStore::RemoveValue(const std::string& key) { | 229 void JsonPrefStore::RemoveValue(const std::string& key) { |
| 230 DCHECK(CalledOnValidThread()); |
| 231 |
| 254 if (prefs_->RemovePath(key, NULL)) | 232 if (prefs_->RemovePath(key, NULL)) |
| 255 ReportValueChanged(key); | 233 ReportValueChanged(key); |
| 256 } | 234 } |
| 257 | 235 |
| 258 void JsonPrefStore::RemoveValueSilently(const std::string& key) { | 236 void JsonPrefStore::RemoveValueSilently(const std::string& key) { |
| 237 DCHECK(CalledOnValidThread()); |
| 238 |
| 259 prefs_->RemovePath(key, NULL); | 239 prefs_->RemovePath(key, NULL); |
| 260 if (!read_only_) | 240 if (!read_only_) |
| 261 writer_.ScheduleWrite(this); | 241 writer_.ScheduleWrite(this); |
| 262 } | 242 } |
| 263 | 243 |
| 264 bool JsonPrefStore::ReadOnly() const { | 244 bool JsonPrefStore::ReadOnly() const { |
| 245 DCHECK(CalledOnValidThread()); |
| 246 |
| 265 return read_only_; | 247 return read_only_; |
| 266 } | 248 } |
| 267 | 249 |
| 268 PersistentPrefStore::PrefReadError JsonPrefStore::GetReadError() const { | 250 PersistentPrefStore::PrefReadError JsonPrefStore::GetReadError() const { |
| 251 DCHECK(CalledOnValidThread()); |
| 252 |
| 269 return read_error_; | 253 return read_error_; |
| 270 } | 254 } |
| 271 | 255 |
| 272 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() { | 256 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() { |
| 257 DCHECK(CalledOnValidThread()); |
| 258 |
| 273 if (path_.empty()) { | 259 if (path_.empty()) { |
| 274 OnFileRead( | 260 scoped_ptr<ReadResult> no_file_result; |
| 275 scoped_ptr<base::Value>(), PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); | 261 no_file_result->error = PREF_READ_ERROR_FILE_NOT_SPECIFIED; |
| 262 OnFileRead(no_file_result.Pass()); |
| 276 return PREF_READ_ERROR_FILE_NOT_SPECIFIED; | 263 return PREF_READ_ERROR_FILE_NOT_SPECIFIED; |
| 277 } | 264 } |
| 278 | 265 |
| 279 PrefReadError error; | 266 OnFileRead(ReadPrefsFromDisk(path_, alternate_path_)); |
| 280 bool no_dir; | 267 return filtering_in_progress_ ? PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE |
| 281 scoped_ptr<base::Value> value( | 268 : 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 } | 269 } |
| 288 | 270 |
| 289 void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) { | 271 void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) { |
| 272 DCHECK(CalledOnValidThread()); |
| 273 |
| 290 initialized_ = false; | 274 initialized_ = false; |
| 291 error_delegate_.reset(error_delegate); | 275 error_delegate_.reset(error_delegate); |
| 292 if (path_.empty()) { | 276 if (path_.empty()) { |
| 293 OnFileRead( | 277 scoped_ptr<ReadResult> no_file_result; |
| 294 scoped_ptr<base::Value>(), PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); | 278 no_file_result->error = PREF_READ_ERROR_FILE_NOT_SPECIFIED; |
| 279 OnFileRead(no_file_result.Pass()); |
| 295 return; | 280 return; |
| 296 } | 281 } |
| 297 | 282 |
| 298 // Start async reading of the preferences file. It will delete itself | 283 base::PostTaskAndReplyWithResult( |
| 299 // in the end. | 284 sequenced_task_runner_, |
| 300 scoped_refptr<FileThreadDeserializer> deserializer( | 285 FROM_HERE, |
| 301 new FileThreadDeserializer(this, sequenced_task_runner_.get())); | 286 base::Bind(&ReadPrefsFromDisk, path_, alternate_path_), |
| 302 deserializer->Start(path_, alternate_path_); | 287 base::Bind(&JsonPrefStore::OnFileRead, this)); |
| 303 } | 288 } |
| 304 | 289 |
| 305 void JsonPrefStore::CommitPendingWrite() { | 290 void JsonPrefStore::CommitPendingWrite() { |
| 291 DCHECK(CalledOnValidThread()); |
| 292 |
| 306 if (writer_.HasPendingWrite() && !read_only_) | 293 if (writer_.HasPendingWrite() && !read_only_) |
| 307 writer_.DoScheduledWrite(); | 294 writer_.DoScheduledWrite(); |
| 308 } | 295 } |
| 309 | 296 |
| 310 void JsonPrefStore::ReportValueChanged(const std::string& key) { | 297 void JsonPrefStore::ReportValueChanged(const std::string& key) { |
| 298 DCHECK(CalledOnValidThread()); |
| 299 |
| 311 if (pref_filter_) | 300 if (pref_filter_) |
| 312 pref_filter_->FilterUpdate(key); | 301 pref_filter_->FilterUpdate(key); |
| 313 | 302 |
| 314 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); | 303 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); |
| 315 | 304 |
| 316 if (!read_only_) | 305 if (!read_only_) |
| 317 writer_.ScheduleWrite(this); | 306 writer_.ScheduleWrite(this); |
| 318 } | 307 } |
| 319 | 308 |
| 320 void JsonPrefStore::RegisterOnNextSuccessfulWriteCallback( | 309 void JsonPrefStore::RegisterOnNextSuccessfulWriteCallback( |
| 321 const base::Closure& on_next_successful_write) { | 310 const base::Closure& on_next_successful_write) { |
| 311 DCHECK(CalledOnValidThread()); |
| 312 |
| 322 writer_.RegisterOnNextSuccessfulWriteCallback(on_next_successful_write); | 313 writer_.RegisterOnNextSuccessfulWriteCallback(on_next_successful_write); |
| 323 } | 314 } |
| 324 | 315 |
| 325 void JsonPrefStore::OnFileRead(scoped_ptr<base::Value> value, | 316 void JsonPrefStore::OnFileRead(scoped_ptr<ReadResult> read_result) { |
| 326 PersistentPrefStore::PrefReadError error, | 317 DCHECK(CalledOnValidThread()); |
| 327 bool no_dir) { | 318 |
| 319 DCHECK(read_result); |
| 320 |
| 328 scoped_ptr<base::DictionaryValue> unfiltered_prefs(new base::DictionaryValue); | 321 scoped_ptr<base::DictionaryValue> unfiltered_prefs(new base::DictionaryValue); |
| 329 | 322 |
| 330 read_error_ = error; | 323 read_error_ = read_result->error; |
| 331 | 324 |
| 332 bool initialization_successful = !no_dir; | 325 bool initialization_successful = !read_result->no_dir; |
| 333 | 326 |
| 334 if (initialization_successful) { | 327 if (initialization_successful) { |
| 335 switch (read_error_) { | 328 switch (read_error_) { |
| 336 case PREF_READ_ERROR_ACCESS_DENIED: | 329 case PREF_READ_ERROR_ACCESS_DENIED: |
| 337 case PREF_READ_ERROR_FILE_OTHER: | 330 case PREF_READ_ERROR_FILE_OTHER: |
| 338 case PREF_READ_ERROR_FILE_LOCKED: | 331 case PREF_READ_ERROR_FILE_LOCKED: |
| 339 case PREF_READ_ERROR_JSON_TYPE: | 332 case PREF_READ_ERROR_JSON_TYPE: |
| 340 case PREF_READ_ERROR_FILE_NOT_SPECIFIED: | 333 case PREF_READ_ERROR_FILE_NOT_SPECIFIED: |
| 341 read_only_ = true; | 334 read_only_ = true; |
| 342 break; | 335 break; |
| 343 case PREF_READ_ERROR_NONE: | 336 case PREF_READ_ERROR_NONE: |
| 344 DCHECK(value.get()); | 337 DCHECK(read_result->value.get()); |
| 345 unfiltered_prefs.reset( | 338 unfiltered_prefs.reset( |
| 346 static_cast<base::DictionaryValue*>(value.release())); | 339 static_cast<base::DictionaryValue*>(read_result->value.release())); |
| 347 break; | 340 break; |
| 348 case PREF_READ_ERROR_NO_FILE: | 341 case PREF_READ_ERROR_NO_FILE: |
| 349 // If the file just doesn't exist, maybe this is first run. In any case | 342 // 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. | 343 // there's no harm in writing out default prefs in this case. |
| 351 break; | 344 break; |
| 352 case PREF_READ_ERROR_JSON_PARSE: | 345 case PREF_READ_ERROR_JSON_PARSE: |
| 353 case PREF_READ_ERROR_JSON_REPEAT: | 346 case PREF_READ_ERROR_JSON_REPEAT: |
| 354 break; | 347 break; |
| 355 case PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE: | 348 case PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE: |
| 356 // This is a special error code to be returned by ReadPrefs when it | 349 // This is a special error code to be returned by ReadPrefs when it |
| (...skipping 22 matching lines...) Expand all Loading... |
| 379 } else { | 372 } else { |
| 380 FinalizeFileRead(initialization_successful, unfiltered_prefs.Pass(), false); | 373 FinalizeFileRead(initialization_successful, unfiltered_prefs.Pass(), false); |
| 381 } | 374 } |
| 382 } | 375 } |
| 383 | 376 |
| 384 JsonPrefStore::~JsonPrefStore() { | 377 JsonPrefStore::~JsonPrefStore() { |
| 385 CommitPendingWrite(); | 378 CommitPendingWrite(); |
| 386 } | 379 } |
| 387 | 380 |
| 388 bool JsonPrefStore::SerializeData(std::string* output) { | 381 bool JsonPrefStore::SerializeData(std::string* output) { |
| 382 DCHECK(CalledOnValidThread()); |
| 383 |
| 389 if (pref_filter_) | 384 if (pref_filter_) |
| 390 pref_filter_->FilterSerializeData(prefs_.get()); | 385 pref_filter_->FilterSerializeData(prefs_.get()); |
| 391 | 386 |
| 392 JSONStringValueSerializer serializer(output); | 387 JSONStringValueSerializer serializer(output); |
| 393 serializer.set_pretty_print(true); | 388 serializer.set_pretty_print(true); |
| 394 bool result = serializer.Serialize(*prefs_); | 389 bool result = serializer.Serialize(*prefs_); |
| 395 | 390 |
| 396 if (result) { | 391 if (result) { |
| 397 std::string spaceless_basename; | 392 std::string spaceless_basename; |
| 398 base::ReplaceChars(path_.BaseName().MaybeAsASCII(), " ", "_", | 393 base::ReplaceChars(path_.BaseName().MaybeAsASCII(), " ", "_", |
| (...skipping 11 matching lines...) Expand all Loading... |
| 410 base::HistogramBase::kUmaTargetedHistogramFlag); | 405 base::HistogramBase::kUmaTargetedHistogramFlag); |
| 411 histogram->Add(static_cast<int>(output->size()) / 1024); | 406 histogram->Add(static_cast<int>(output->size()) / 1024); |
| 412 } | 407 } |
| 413 | 408 |
| 414 return result; | 409 return result; |
| 415 } | 410 } |
| 416 | 411 |
| 417 void JsonPrefStore::FinalizeFileRead(bool initialization_successful, | 412 void JsonPrefStore::FinalizeFileRead(bool initialization_successful, |
| 418 scoped_ptr<base::DictionaryValue> prefs, | 413 scoped_ptr<base::DictionaryValue> prefs, |
| 419 bool schedule_write) { | 414 bool schedule_write) { |
| 415 DCHECK(CalledOnValidThread()); |
| 416 |
| 420 filtering_in_progress_ = false; | 417 filtering_in_progress_ = false; |
| 421 | 418 |
| 422 if (!initialization_successful) { | 419 if (!initialization_successful) { |
| 423 FOR_EACH_OBSERVER(PrefStore::Observer, | 420 FOR_EACH_OBSERVER(PrefStore::Observer, |
| 424 observers_, | 421 observers_, |
| 425 OnInitializationCompleted(false)); | 422 OnInitializationCompleted(false)); |
| 426 return; | 423 return; |
| 427 } | 424 } |
| 428 | 425 |
| 429 prefs_ = prefs.Pass(); | 426 prefs_ = prefs.Pass(); |
| 430 | 427 |
| 431 initialized_ = true; | 428 initialized_ = true; |
| 432 | 429 |
| 433 if (schedule_write && !read_only_) | 430 if (schedule_write && !read_only_) |
| 434 writer_.ScheduleWrite(this); | 431 writer_.ScheduleWrite(this); |
| 435 | 432 |
| 436 if (error_delegate_ && read_error_ != PREF_READ_ERROR_NONE) | 433 if (error_delegate_ && read_error_ != PREF_READ_ERROR_NONE) |
| 437 error_delegate_->OnError(read_error_); | 434 error_delegate_->OnError(read_error_); |
| 438 | 435 |
| 439 FOR_EACH_OBSERVER(PrefStore::Observer, | 436 FOR_EACH_OBSERVER(PrefStore::Observer, |
| 440 observers_, | 437 observers_, |
| 441 OnInitializationCompleted(true)); | 438 OnInitializationCompleted(true)); |
| 442 | 439 |
| 443 return; | 440 return; |
| 444 } | 441 } |
| OLD | NEW |