1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch// Use of this source code is governed by a BSD-style license that can be 306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch// found in the LICENSE file. 406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch#include "chrome/common/json_pref_store.h" 606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch#include <algorithm> 806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/bind.h" 10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/callback.h" 1106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch#include "base/file_util.h" 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/ref_counted.h" 1306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch#include "base/values.h" 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/browser_thread.h" 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/json_value_serializer.h" 1606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 1706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdochnamespace { 1806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 1906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch// Some extensions we'll tack on to copies of the Preferences files. 2006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdochconst FilePath::CharType* kBadExtension = FILE_PATH_LITERAL("bad"); 2106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Differentiates file loading between UI and FILE threads. 23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass FileThreadDeserializer 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : public base::RefCountedThreadSafe<FileThreadDeserializer> { 25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public: 26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen explicit FileThreadDeserializer(JsonPrefStore* delegate) 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : delegate_(delegate) { 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void Start(const FilePath& path) { 31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BrowserThread::PostTask( 33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BrowserThread::FILE, 34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FROM_HERE, 35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NewRunnableMethod(this, 36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &FileThreadDeserializer::ReadFileAndReport, 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen path)); 38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Deserializes JSON on the FILE thread. 41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void ReadFileAndReport(const FilePath& path) { 42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int error_code; 45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string error_msg; 46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen JSONFileValueSerializer serializer(path); 47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen value_.reset(serializer.Deserialize(&error_code, &error_msg)); 48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen HandleErrors(value_.get(), path, error_code, error_msg, &error_); 50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen no_dir_ = !file_util::PathExists(path.DirName()); 52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BrowserThread::PostTask( 54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BrowserThread::UI, 55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FROM_HERE, 56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NewRunnableMethod(this, &FileThreadDeserializer::ReportOnUIThread)); 57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Reports deserialization result on the UI thread. 60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void ReportOnUIThread() { 61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delegate_->OnFileRead(value_.release(), error_, no_dir_); 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static void HandleErrors(const Value* value, 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const FilePath& path, 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int error_code, 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& error_msg, 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PersistentPrefStore::PrefReadError* error); 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen private: 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen friend class base::RefCountedThreadSafe<FileThreadDeserializer>; 73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool no_dir_; 75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PersistentPrefStore::PrefReadError error_; 76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_ptr<Value> value_; 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_refptr<JsonPrefStore> delegate_; 78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static 81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid FileThreadDeserializer::HandleErrors( 82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const Value* value, 83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const FilePath& path, 84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int error_code, 85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& error_msg, 86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PersistentPrefStore::PrefReadError* error) { 87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *error = PersistentPrefStore::PREF_READ_ERROR_NONE; 88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!value) { 89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DLOG(ERROR) << "Error while loading JSON file: " << error_msg; 90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen switch (error_code) { 91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case JSONFileValueSerializer::JSON_ACCESS_DENIED: 92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *error = PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED; 93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case JSONFileValueSerializer::JSON_CANNOT_READ_FILE: 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *error = PersistentPrefStore::PREF_READ_ERROR_FILE_OTHER; 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case JSONFileValueSerializer::JSON_FILE_LOCKED: 98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *error = PersistentPrefStore::PREF_READ_ERROR_FILE_LOCKED; 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case JSONFileValueSerializer::JSON_NO_SUCH_FILE: 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *error = PersistentPrefStore::PREF_READ_ERROR_NO_FILE; 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen default: 104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *error = PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE; 105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // JSON errors indicate file corruption of some sort. 106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Since the file is corrupt, move it to the side and continue with 107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // empty preferences. This will result in them losing their settings. 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We keep the old file for possible support and debugging assistance 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // as well as to detect if they're seeing these errors repeatedly. 110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(erikkay) Instead, use the last known good file. 111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FilePath bad = path.ReplaceExtension(kBadExtension); 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If they've ever had a parse error before, put them in another bucket. 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(erikkay) if we keep this error checking for very long, we may 115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // want to differentiate between recent and long ago errors. 116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (file_util::PathExists(bad)) 117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *error = PersistentPrefStore::PREF_READ_ERROR_JSON_REPEAT; 118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen file_util::Move(path, bad); 119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else if (!value->IsType(Value::TYPE_DICTIONARY)) { 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *error = PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE; 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 12606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch} // namespace 12706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 12806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen MurdochJsonPrefStore::JsonPrefStore(const FilePath& filename, 12906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch base::MessageLoopProxy* file_message_loop_proxy) 13006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch : path_(filename), 13106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch prefs_(new DictionaryValue()), 13206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch read_only_(false), 13306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch writer_(filename, file_message_loop_proxy) { 13406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch} 13506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 13606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen MurdochJsonPrefStore::~JsonPrefStore() { 137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CommitPendingWrite(); 13806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch} 13906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 14021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenPrefStore::ReadResult JsonPrefStore::GetValue(const std::string& key, 141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const Value** result) const { 142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Value* tmp = NULL; 143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (prefs_->Get(key, &tmp)) { 144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *result = tmp; 145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return READ_OK; 146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return READ_NO_VALUE; 14821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 14921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 15021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid JsonPrefStore::AddObserver(PrefStore::Observer* observer) { 15121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen observers_.AddObserver(observer); 15221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 15321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 15421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid JsonPrefStore::RemoveObserver(PrefStore::Observer* observer) { 15521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen observers_.RemoveObserver(observer); 15621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 15721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenPrefStore::ReadResult JsonPrefStore::GetMutableValue(const std::string& key, 159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Value** result) { 160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return prefs_->Get(key, result) ? READ_OK : READ_NO_VALUE; 161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 16321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid JsonPrefStore::SetValue(const std::string& key, Value* value) { 16421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(value); 16521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen scoped_ptr<Value> new_value(value); 16621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen Value* old_value = NULL; 16721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen prefs_->Get(key, &old_value); 16821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!old_value || !value->Equals(old_value)) { 16921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen prefs_->Set(key, new_value.release()); 17021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); 17121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 17221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 17321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 17421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid JsonPrefStore::SetValueSilently(const std::string& key, Value* value) { 17521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(value); 17621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen scoped_ptr<Value> new_value(value); 17721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen Value* old_value = NULL; 17821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen prefs_->Get(key, &old_value); 17921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!old_value || !value->Equals(old_value)) 18021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen prefs_->Set(key, new_value.release()); 18121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 18221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 18321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid JsonPrefStore::RemoveValue(const std::string& key) { 18421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (prefs_->Remove(key, NULL)) { 18521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); 18621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 18721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 18821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 18921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool JsonPrefStore::ReadOnly() const { 19021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return read_only_; 19121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 19221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid JsonPrefStore::OnFileRead(Value* value_owned, 194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PersistentPrefStore::PrefReadError error, 195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool no_dir) { 196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_ptr<Value> value(value_owned); 197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen switch (error) { 198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case PREF_READ_ERROR_ACCESS_DENIED: 199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case PREF_READ_ERROR_FILE_OTHER: 200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case PREF_READ_ERROR_FILE_LOCKED: 201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case PREF_READ_ERROR_JSON_TYPE: 202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen read_only_ = true; 203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case PREF_READ_ERROR_NONE: 205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(value.get()); 206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen prefs_.reset(static_cast<DictionaryValue*>(value.release())); 207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case PREF_READ_ERROR_NO_FILE: 209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If the file just doesn't exist, maybe this is first run. In any case 210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // there's no harm in writing out default prefs in this case. 211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case PREF_READ_ERROR_JSON_PARSE: 213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case PREF_READ_ERROR_JSON_REPEAT: 214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen default: 216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NOTREACHED() << "Unknown error: " << error; 217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (delegate_) 220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delegate_->OnPrefsRead(error, no_dir); 221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid JsonPrefStore::ReadPrefs(Delegate* delegate) { 224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(delegate); 225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delegate_ = delegate; 226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (path_.empty()) { 228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen read_only_ = true; 229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delegate_->OnPrefsRead(PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); 230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // This guarantees that class will not be deleted while JSON is readed. 234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Start async reading of the preferences file. It will delete itself 237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // in the end. 238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_refptr<FileThreadDeserializer> deserializer( 239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new FileThreadDeserializer(this)); 240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen deserializer->Start(path_); 241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 24321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenPersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() { 244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delegate_ = NULL; 245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (path_.empty()) { 2473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick read_only_ = true; 2483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return PREF_READ_ERROR_FILE_NOT_SPECIFIED; 2493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 25006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 25106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch int error_code = 0; 25206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch std::string error_msg; 25306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen JSONFileValueSerializer serializer(path_); 255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_ptr<Value> value(serializer.Deserialize(&error_code, &error_msg)); 25606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen PersistentPrefStore::PrefReadError error; 258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FileThreadDeserializer::HandleErrors(value.get(), 259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen path_, 260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen error_code, 261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen error_msg, 262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &error); 26306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnFileRead(value.release(), error, false); 26506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return error; 26706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch} 26806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 26906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdochbool JsonPrefStore::WritePrefs() { 27006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch std::string data; 27106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch if (!SerializeData(&data)) 27206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch return false; 27306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 27406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch // Lie about our ability to save. 27506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch if (read_only_) 27606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch return true; 27706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 27806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch writer_.WriteNow(data); 27906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch return true; 28006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch} 28106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 28206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdochvoid JsonPrefStore::ScheduleWritePrefs() { 28306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch if (read_only_) 28406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch return; 28506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 28606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch writer_.ScheduleWrite(this); 28706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch} 28806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid JsonPrefStore::CommitPendingWrite() { 290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (writer_.HasPendingWrite() && !read_only_) 291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen writer_.DoScheduledWrite(); 292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 294dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid JsonPrefStore::ReportValueChanged(const std::string& key) { 295dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); 296dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 297dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 29806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdochbool JsonPrefStore::SerializeData(std::string* output) { 29906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch // TODO(tc): Do we want to prune webkit preferences that match the default 30006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch // value? 30106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch JSONStringValueSerializer serializer(output); 30206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch serializer.set_pretty_print(true); 30306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch scoped_ptr<DictionaryValue> copy(prefs_->DeepCopyWithoutEmptyChildren()); 30406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch return serializer.Serialize(*(copy.get())); 30506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch} 306