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