1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file. 4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/prefs/leveldb_pref_store.h" 6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/bind.h" 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/callback.h" 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/json/json_string_value_serializer.h" 11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/location.h" 12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/metrics/sparse_histogram.h" 13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/sequenced_task_runner.h" 14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/task_runner_util.h" 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/threading/thread_restrictions.h" 16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/time/time.h" 17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/values.h" 18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "third_party/leveldatabase/env_chromium.h" 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "third_party/leveldatabase/src/include/leveldb/db.h" 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "third_party/leveldatabase/src/include/leveldb/write_batch.h" 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace { 23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)enum ErrorMasks { 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) OPENED = 1 << 0, 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DESTROYED = 1 << 1, 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) REPAIRED = 1 << 2, 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DESTROY_FAILED = 1 << 3, 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) REPAIR_FAILED = 1 << 4, 30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) IO_ERROR = 1 << 5, 31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DATA_LOST = 1 << 6, 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ITER_NOT_OK = 1 << 7, 33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FILE_NOT_SPECIFIED = 1 << 8, 34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PersistentPrefStore::PrefReadError IntToPrefReadError(int error) { 37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(error); 38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (error == FILE_NOT_SPECIFIED) 39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return PersistentPrefStore::PREF_READ_ERROR_FILE_NOT_SPECIFIED; 40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (error == OPENED) 41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return PersistentPrefStore::PREF_READ_ERROR_NONE; 42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (error & IO_ERROR) 43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return PersistentPrefStore::PREF_READ_ERROR_LEVELDB_IO; 44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (error & OPENED) 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return PersistentPrefStore::PREF_READ_ERROR_LEVELDB_CORRUPTION; 46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return PersistentPrefStore::PREF_READ_ERROR_LEVELDB_CORRUPTION_READ_ONLY; 47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // namespace 50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)struct LevelDBPrefStore::ReadingResults { 52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ReadingResults() : no_dir(true), error(0) {} 53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool no_dir; 54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<leveldb::DB> db; 55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<PrefValueMap> value_map; 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int error; 57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// An instance of this class is created on the UI thread but is used 60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// exclusively on the FILE thread. 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class LevelDBPrefStore::FileThreadSerializer { 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public: 63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) explicit FileThreadSerializer(scoped_ptr<leveldb::DB> db) : db_(db.Pass()) {} 64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void WriteToDatabase( 65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::map<std::string, std::string>* keys_to_set, 66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::set<std::string>* keys_to_delete) { 67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(keys_to_set->size() > 0 || keys_to_delete->size() > 0); 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) leveldb::WriteBatch batch; 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (std::map<std::string, std::string>::iterator iter = 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) keys_to_set->begin(); 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) iter != keys_to_set->end(); 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) iter++) { 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) batch.Put(iter->first, iter->second); 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (std::set<std::string>::iterator iter = keys_to_delete->begin(); 77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) iter != keys_to_delete->end(); 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) iter++) { 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) batch.Delete(*iter); 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); 83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // DCHECK is fine; the corresponding error is ignored in JsonPrefStore. 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // There's also no API available to surface the error back up to the caller. 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(dgrogan): UMA? 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(status.ok()) << status.ToString(); 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private: 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<leveldb::DB> db_; 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(FileThreadSerializer); 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool MoveDirectoryAside(const base::FilePath& path) { 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::FilePath bad_path = path.AppendASCII(".bad"); 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!base::Move(path, bad_path)) { 98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::DeleteFile(bad_path, true); 99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return true; 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/* static */ 105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void LevelDBPrefStore::OpenDB(const base::FilePath& path, 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ReadingResults* reading_results) { 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_EQ(0, reading_results->error); 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) leveldb::Options options; 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) options.create_if_missing = true; 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) leveldb::DB* db; 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) while (1) { 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) leveldb::Status status = 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) leveldb::DB::Open(options, path.AsUTF8Unsafe(), &db); 114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (status.ok()) { 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reading_results->db.reset(db); 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reading_results->error |= OPENED; 117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (leveldb_env::IsIOError(status)) { 120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reading_results->error |= IO_ERROR; 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (reading_results->error & DESTROYED) 124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(!(reading_results->error & REPAIR_FAILED)); 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!(reading_results->error & REPAIRED)) { 128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) status = leveldb::RepairDB(path.AsUTF8Unsafe(), options); 129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (status.ok()) { 130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reading_results->error |= REPAIRED; 131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reading_results->error |= REPAIR_FAILED; 134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!MoveDirectoryAside(path)) { 136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) status = leveldb::DestroyDB(path.AsUTF8Unsafe(), options); 137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!status.ok()) { 138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reading_results->error |= DESTROY_FAILED; 139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reading_results->error |= DESTROYED; 143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(reading_results->error); 145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(!((reading_results->error & OPENED) && 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) (reading_results->error & DESTROY_FAILED))); 147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(reading_results->error != (REPAIR_FAILED | OPENED)); 148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/* static */ 151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)scoped_ptr<LevelDBPrefStore::ReadingResults> LevelDBPrefStore::DoReading( 152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& path) { 153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<ReadingResults> reading_results(new ReadingResults); 156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reading_results->no_dir = !base::PathExists(path.DirName()); 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) OpenDB(path, reading_results.get()); 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!reading_results->db) { 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(!(reading_results->error & OPENED)); 161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return reading_results.Pass(); 162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(reading_results->error & OPENED); 165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reading_results->value_map.reset(new PrefValueMap); 166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<leveldb::Iterator> it( 167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reading_results->db->NewIterator(leveldb::ReadOptions())); 168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(dgrogan): Is it really necessary to check it->status() each iteration? 169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (it->SeekToFirst(); it->Valid() && it->status().ok(); it->Next()) { 170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string value_string = it->value().ToString(); 171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) JSONStringValueSerializer deserializer(value_string); 172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string error_message; 173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int error_code; 174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Value* json_value = 175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) deserializer.Deserialize(&error_code, &error_message); 176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (json_value) { 177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reading_results->value_map->SetValue(it->key().ToString(), json_value); 178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DLOG(ERROR) << "Invalid json for key " << it->key().ToString() 180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) << ": " << error_message; 181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reading_results->error |= DATA_LOST; 182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!it->status().ok()) 186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reading_results->error |= ITER_NOT_OK; 187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return reading_results.Pass(); 189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)LevelDBPrefStore::LevelDBPrefStore( 192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& filename, 193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::SequencedTaskRunner* sequenced_task_runner) 194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : path_(filename), 195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) sequenced_task_runner_(sequenced_task_runner), 196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) original_task_runner_(base::MessageLoopProxy::current()), 197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) read_only_(false), 198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) initialized_(false), 199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) read_error_(PREF_READ_ERROR_NONE), 200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) weak_ptr_factory_(this) {} 201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)LevelDBPrefStore::~LevelDBPrefStore() { 203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CommitPendingWrite(); 204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) sequenced_task_runner_->DeleteSoon(FROM_HERE, serializer_.release()); 205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool LevelDBPrefStore::GetValue(const std::string& key, 208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::Value** result) const { 209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(initialized_); 210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::Value* tmp = NULL; 211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!prefs_.GetValue(key, &tmp)) { 212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (result) 216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *result = tmp; 217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return true; 218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Callers of GetMutableValue have to also call ReportValueChanged. 221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool LevelDBPrefStore::GetMutableValue(const std::string& key, 222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Value** result) { 223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(initialized_); 224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return prefs_.GetValue(key, result); 225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void LevelDBPrefStore::AddObserver(PrefStore::Observer* observer) { 228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) observers_.AddObserver(observer); 229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void LevelDBPrefStore::RemoveObserver(PrefStore::Observer* observer) { 232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) observers_.RemoveObserver(observer); 233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool LevelDBPrefStore::HasObservers() const { 236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return observers_.might_have_observers(); 237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool LevelDBPrefStore::IsInitializationComplete() const { return initialized_; } 240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void LevelDBPrefStore::PersistFromUIThread() { 242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (read_only_) 243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(serializer_); 245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<std::set<std::string> > keys_to_delete(new std::set<std::string>); 247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) keys_to_delete->swap(keys_to_delete_); 248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<std::map<std::string, std::string> > keys_to_set( 250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) new std::map<std::string, std::string>); 251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) keys_to_set->swap(keys_to_set_); 252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) sequenced_task_runner_->PostTask( 254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&LevelDBPrefStore::FileThreadSerializer::WriteToDatabase, 256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Unretained(serializer_.get()), 257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Owned(keys_to_set.release()), 258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Owned(keys_to_delete.release()))); 259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void LevelDBPrefStore::ScheduleWrite() { 262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!timer_.IsRunning()) { 263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) timer_.Start(FROM_HERE, 264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::TimeDelta::FromSeconds(10), 265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this, 266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &LevelDBPrefStore::PersistFromUIThread); 267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void LevelDBPrefStore::SetValue(const std::string& key, base::Value* value) { 271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetValueInternal(key, value, true /*notify*/); 272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void LevelDBPrefStore::SetValueSilently(const std::string& key, 275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Value* value) { 276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetValueInternal(key, value, false /*notify*/); 277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)static std::string Serialize(base::Value* value) { 280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string value_string; 281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) JSONStringValueSerializer serializer(&value_string); 282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool serialized_ok = serializer.Serialize(*value); 283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(serialized_ok); 284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return value_string; 285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void LevelDBPrefStore::SetValueInternal(const std::string& key, 288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Value* value, 289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool notify) { 290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(initialized_); 291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(value); 292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<base::Value> new_value(value); 293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Value* old_value = NULL; 294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) prefs_.GetValue(key, &old_value); 295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!old_value || !value->Equals(old_value)) { 296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string value_string = Serialize(value); 297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) prefs_.SetValue(key, new_value.release()); 298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MarkForInsertion(key, value_string); 299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (notify) 300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NotifyObservers(key); 301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void LevelDBPrefStore::RemoveValue(const std::string& key) { 305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(initialized_); 306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (prefs_.RemoveValue(key)) { 307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MarkForDeletion(key); 308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NotifyObservers(key); 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool LevelDBPrefStore::ReadOnly() const { return read_only_; } 313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PersistentPrefStore::PrefReadError LevelDBPrefStore::GetReadError() const { 315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return read_error_; 316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PersistentPrefStore::PrefReadError LevelDBPrefStore::ReadPrefs() { 319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(!initialized_); 320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<ReadingResults> reading_results; 321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (path_.empty()) { 322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reading_results.reset(new ReadingResults); 323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reading_results->error = FILE_NOT_SPECIFIED; 324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reading_results = DoReading(path_); 326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PrefReadError error = IntToPrefReadError(reading_results->error); 329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) OnStorageRead(reading_results.Pass()); 330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return error; 331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void LevelDBPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) { 334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_EQ(false, initialized_); 335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) error_delegate_.reset(error_delegate); 336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (path_.empty()) { 337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<ReadingResults> reading_results(new ReadingResults); 338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reading_results->error = FILE_NOT_SPECIFIED; 339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) OnStorageRead(reading_results.Pass()); 340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 3421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PostTaskAndReplyWithResult(sequenced_task_runner_.get(), 343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&LevelDBPrefStore::DoReading, path_), 345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&LevelDBPrefStore::OnStorageRead, 346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr())); 347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void LevelDBPrefStore::CommitPendingWrite() { 350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (timer_.IsRunning()) { 351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) timer_.Stop(); 352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PersistFromUIThread(); 353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void LevelDBPrefStore::MarkForDeletion(const std::string& key) { 357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (read_only_) 358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) keys_to_delete_.insert(key); 360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Need to erase in case there's a set operation in the same batch that would 361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // clobber this delete. 362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) keys_to_set_.erase(key); 363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ScheduleWrite(); 364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 365cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void LevelDBPrefStore::MarkForInsertion(const std::string& key, 367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::string& value) { 368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (read_only_) 369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) keys_to_set_[key] = value; 371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Need to erase in case there's a delete operation in the same batch that 372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // would clobber this set. 373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) keys_to_delete_.erase(key); 374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ScheduleWrite(); 375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 377cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void LevelDBPrefStore::ReportValueChanged(const std::string& key) { 378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Value* new_value = NULL; 379cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool contains_value = prefs_.GetValue(key, &new_value); 380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(contains_value); 381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string value_string = Serialize(new_value); 382cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) MarkForInsertion(key, value_string); 383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NotifyObservers(key); 384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 385cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void LevelDBPrefStore::NotifyObservers(const std::string& key) { 387cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); 388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void LevelDBPrefStore::OnStorageRead( 391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<LevelDBPrefStore::ReadingResults> reading_results) { 392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) UMA_HISTOGRAM_SPARSE_SLOWLY("LevelDBPrefStore.ReadErrors", 393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reading_results->error); 394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) read_error_ = IntToPrefReadError(reading_results->error); 395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (reading_results->no_dir) { 397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FOR_EACH_OBSERVER( 398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PrefStore::Observer, observers_, OnInitializationCompleted(false)); 399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) initialized_ = true; 403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (reading_results->db) { 405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(reading_results->value_map); 406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) serializer_.reset(new FileThreadSerializer(reading_results->db.Pass())); 407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) prefs_.Swap(reading_results->value_map.get()); 408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) read_only_ = true; 410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(dgrogan): Call pref_filter_->FilterOnLoad 413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (error_delegate_.get() && read_error_ != PREF_READ_ERROR_NONE) 415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) error_delegate_->OnError(read_error_); 416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FOR_EACH_OBSERVER( 418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PrefStore::Observer, observers_, OnInitializationCompleted(true)); 419cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 420