Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(213)

Side by Side Diff: chrome/browser/extensions/extension_settings_leveldb_storage.cc

Issue 8177022: Add onChanged events to the extension settings API, both from sync and between (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/extension_settings_leveldb_storage.h" 5 #include "chrome/browser/extensions/extension_settings_leveldb_storage.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/compiler_specific.h" 8 #include "base/compiler_specific.h"
9 #include "base/json/json_reader.h" 9 #include "base/json/json_reader.h"
10 #include "base/json/json_writer.h" 10 #include "base/json/json_writer.h"
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 const std::string& key) { 80 const std::string& key) {
81 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 81 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
82 scoped_ptr<Value> setting; 82 scoped_ptr<Value> setting;
83 if (!ReadFromDb(leveldb::ReadOptions(), key, &setting)) { 83 if (!ReadFromDb(leveldb::ReadOptions(), key, &setting)) {
84 return Result(kGenericOnFailureMessage); 84 return Result(kGenericOnFailureMessage);
85 } 85 }
86 DictionaryValue* settings = new DictionaryValue(); 86 DictionaryValue* settings = new DictionaryValue();
87 if (setting.get()) { 87 if (setting.get()) {
88 settings->SetWithoutPathExpansion(key, setting.release()); 88 settings->SetWithoutPathExpansion(key, setting.release());
89 } 89 }
90 return Result(settings, NULL); 90 return Result(settings, NULL, NULL);
91 } 91 }
92 92
93 ExtensionSettingsStorage::Result ExtensionSettingsLeveldbStorage::Get( 93 ExtensionSettingsStorage::Result ExtensionSettingsLeveldbStorage::Get(
94 const std::vector<std::string>& keys) { 94 const std::vector<std::string>& keys) {
95 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 95 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
96 leveldb::ReadOptions options; 96 leveldb::ReadOptions options;
97 scoped_ptr<DictionaryValue> settings(new DictionaryValue()); 97 scoped_ptr<DictionaryValue> settings(new DictionaryValue());
98 98
99 // All interaction with the db is done on the same thread, so snapshotting 99 // All interaction with the db is done on the same thread, so snapshotting
100 // isn't strictly necessary. This is just defensive. 100 // isn't strictly necessary. This is just defensive.
101 ScopedSnapshot snapshot(db_.get()); 101 ScopedSnapshot snapshot(db_.get());
102 options.snapshot = snapshot.get(); 102 options.snapshot = snapshot.get();
103 for (std::vector<std::string>::const_iterator it = keys.begin(); 103 for (std::vector<std::string>::const_iterator it = keys.begin();
104 it != keys.end(); ++it) { 104 it != keys.end(); ++it) {
105 scoped_ptr<Value> setting; 105 scoped_ptr<Value> setting;
106 if (!ReadFromDb(options, *it, &setting)) { 106 if (!ReadFromDb(options, *it, &setting)) {
107 return Result(kGenericOnFailureMessage); 107 return Result(kGenericOnFailureMessage);
108 } 108 }
109 if (setting.get()) { 109 if (setting.get()) {
110 settings->SetWithoutPathExpansion(*it, setting.release()); 110 settings->SetWithoutPathExpansion(*it, setting.release());
111 } 111 }
112 } 112 }
113 113
114 return Result(settings.release(), NULL); 114 return Result(settings.release(), NULL, NULL);
115 } 115 }
116 116
117 ExtensionSettingsStorage::Result ExtensionSettingsLeveldbStorage::Get() { 117 ExtensionSettingsStorage::Result ExtensionSettingsLeveldbStorage::Get() {
118 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 118 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
119 base::JSONReader json_reader; 119 base::JSONReader json_reader;
120 leveldb::ReadOptions options = leveldb::ReadOptions(); 120 leveldb::ReadOptions options = leveldb::ReadOptions();
121 // All interaction with the db is done on the same thread, so snapshotting 121 // All interaction with the db is done on the same thread, so snapshotting
122 // isn't strictly necessary. This is just defensive. 122 // isn't strictly necessary. This is just defensive.
123 scoped_ptr<DictionaryValue> settings(new DictionaryValue()); 123 scoped_ptr<DictionaryValue> settings(new DictionaryValue());
124 124
125 ScopedSnapshot snapshot(db_.get()); 125 ScopedSnapshot snapshot(db_.get());
126 options.snapshot = snapshot.get(); 126 options.snapshot = snapshot.get();
127 scoped_ptr<leveldb::Iterator> it(db_->NewIterator(options)); 127 scoped_ptr<leveldb::Iterator> it(db_->NewIterator(options));
128 for (it->SeekToFirst(); it->Valid(); it->Next()) { 128 for (it->SeekToFirst(); it->Valid(); it->Next()) {
129 Value* value = 129 Value* value =
130 json_reader.JsonToValue(it->value().ToString(), false, false); 130 json_reader.JsonToValue(it->value().ToString(), false, false);
131 if (value != NULL) { 131 if (value != NULL) {
132 settings->SetWithoutPathExpansion(it->key().ToString(), value); 132 settings->SetWithoutPathExpansion(it->key().ToString(), value);
133 } else { 133 } else {
134 // TODO(kalman): clear the offending non-JSON value from the database. 134 // TODO(kalman): clear the offending non-JSON value from the database.
135 LOG(ERROR) << "Invalid JSON: " << it->value().ToString(); 135 LOG(ERROR) << "Invalid JSON: " << it->value().ToString();
136 } 136 }
137 } 137 }
138 138
139 if (!it->status().ok()) { 139 if (!it->status().ok()) {
140 LOG(ERROR) << "DB iteration failed: " << it->status().ToString(); 140 LOG(ERROR) << "DB iteration failed: " << it->status().ToString();
141 return Result(kGenericOnFailureMessage); 141 return Result(kGenericOnFailureMessage);
142 } 142 }
143 143
144 return Result(settings.release(), NULL); 144 return Result(settings.release(), NULL, NULL);
145 } 145 }
146 146
147 ExtensionSettingsStorage::Result ExtensionSettingsLeveldbStorage::Set( 147 ExtensionSettingsStorage::Result ExtensionSettingsLeveldbStorage::Set(
148 const std::string& key, const Value& value) { 148 const std::string& key, const Value& value) {
149 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 149 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
150 DictionaryValue settings; 150 DictionaryValue settings;
151 settings.SetWithoutPathExpansion(key, value.DeepCopy()); 151 settings.SetWithoutPathExpansion(key, value.DeepCopy());
152 return Set(settings); 152 return Set(settings);
153 } 153 }
154 154
155 ExtensionSettingsStorage::Result ExtensionSettingsLeveldbStorage::Set( 155 ExtensionSettingsStorage::Result ExtensionSettingsLeveldbStorage::Set(
156 const DictionaryValue& settings) { 156 const DictionaryValue& settings) {
157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
158 scoped_ptr<DictionaryValue> old_settings(new DictionaryValue());
158 scoped_ptr<std::set<std::string> > changed_keys(new std::set<std::string>()); 159 scoped_ptr<std::set<std::string> > changed_keys(new std::set<std::string>());
159 std::string value_as_json; 160 std::string value_as_json;
160 leveldb::WriteBatch batch; 161 leveldb::WriteBatch batch;
161 162
162 for (DictionaryValue::key_iterator it = settings.begin_keys(); 163 for (DictionaryValue::key_iterator it = settings.begin_keys();
163 it != settings.end_keys(); ++it) { 164 it != settings.end_keys(); ++it) {
164 scoped_ptr<Value> original_value; 165 scoped_ptr<Value> old_value;
165 if (!ReadFromDb(leveldb::ReadOptions(), *it, &original_value)) { 166 if (!ReadFromDb(leveldb::ReadOptions(), *it, &old_value)) {
166 return Result(kGenericOnFailureMessage); 167 return Result(kGenericOnFailureMessage);
167 } 168 }
168 169
169 Value* new_value = NULL; 170 Value* new_value = NULL;
170 settings.GetWithoutPathExpansion(*it, &new_value); 171 settings.GetWithoutPathExpansion(*it, &new_value);
171 if (!original_value.get() || !original_value->Equals(new_value)) { 172 if (!old_value.get() || !old_value->Equals(new_value)) {
172 changed_keys->insert(*it); 173 changed_keys->insert(*it);
173 base::JSONWriter::Write(new_value, false, &value_as_json); 174 base::JSONWriter::Write(new_value, false, &value_as_json);
174 batch.Put(*it, value_as_json); 175 batch.Put(*it, value_as_json);
175 } 176 }
177
178 if (old_value.get()) {
179 old_settings->SetWithoutPathExpansion(*it, old_value.release());
180 }
176 } 181 }
177 182
178 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); 183 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch);
179 if (!status.ok()) { 184 if (!status.ok()) {
180 LOG(WARNING) << "DB batch write failed: " << status.ToString(); 185 LOG(WARNING) << "DB batch write failed: " << status.ToString();
181 return Result(kGenericOnFailureMessage); 186 return Result(kGenericOnFailureMessage);
182 } 187 }
183 188
184 return Result(settings.DeepCopy(), changed_keys.release()); 189 return Result(
190 settings.DeepCopy(), old_settings.release(), changed_keys.release());
185 } 191 }
186 192
187 ExtensionSettingsStorage::Result ExtensionSettingsLeveldbStorage::Remove( 193 ExtensionSettingsStorage::Result ExtensionSettingsLeveldbStorage::Remove(
188 const std::string& key) { 194 const std::string& key) {
189 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 195 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
190 std::vector<std::string> keys; 196 std::vector<std::string> keys;
191 keys.push_back(key); 197 keys.push_back(key);
192 return Remove(keys); 198 return Remove(keys);
193 } 199 }
194 200
195 ExtensionSettingsStorage::Result ExtensionSettingsLeveldbStorage::Remove( 201 ExtensionSettingsStorage::Result ExtensionSettingsLeveldbStorage::Remove(
196 const std::vector<std::string>& keys) { 202 const std::vector<std::string>& keys) {
197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 203 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
204 scoped_ptr<DictionaryValue> old_settings(new DictionaryValue());
198 scoped_ptr<std::set<std::string> > changed_keys(new std::set<std::string>()); 205 scoped_ptr<std::set<std::string> > changed_keys(new std::set<std::string>());
199 206
200 leveldb::WriteBatch batch; 207 leveldb::WriteBatch batch;
201 for (std::vector<std::string>::const_iterator it = keys.begin(); 208 for (std::vector<std::string>::const_iterator it = keys.begin();
202 it != keys.end(); ++it) { 209 it != keys.end(); ++it) {
203 scoped_ptr<Value> original_value; 210 scoped_ptr<Value> old_value;
204 if (!ReadFromDb(leveldb::ReadOptions(), *it, &original_value)) { 211 if (!ReadFromDb(leveldb::ReadOptions(), *it, &old_value)) {
205 return Result(kGenericOnFailureMessage); 212 return Result(kGenericOnFailureMessage);
206 } 213 }
207 214
208 if (original_value.get()) { 215 if (old_value.get()) {
209 changed_keys->insert(*it); 216 changed_keys->insert(*it);
217 old_settings->SetWithoutPathExpansion(*it, old_value.release());
210 batch.Delete(*it); 218 batch.Delete(*it);
211 } 219 }
212 } 220 }
213 221
214 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); 222 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch);
215 if (!status.ok() && !status.IsNotFound()) { 223 if (!status.ok() && !status.IsNotFound()) {
216 LOG(WARNING) << "DB batch delete failed: " << status.ToString(); 224 LOG(WARNING) << "DB batch delete failed: " << status.ToString();
217 return Result(kGenericOnFailureMessage); 225 return Result(kGenericOnFailureMessage);
218 } 226 }
219 227
220 return Result(NULL, changed_keys.release()); 228 return Result(NULL, old_settings.release(), changed_keys.release());
221 } 229 }
222 230
223 ExtensionSettingsStorage::Result ExtensionSettingsLeveldbStorage::Clear() { 231 ExtensionSettingsStorage::Result ExtensionSettingsLeveldbStorage::Clear() {
224 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
233 scoped_ptr<DictionaryValue> old_settings(new DictionaryValue());
225 scoped_ptr<std::set<std::string> > changed_keys(new std::set<std::string>()); 234 scoped_ptr<std::set<std::string> > changed_keys(new std::set<std::string>());
226 leveldb::ReadOptions options; 235 leveldb::ReadOptions options;
227 // All interaction with the db is done on the same thread, so snapshotting 236 // All interaction with the db is done on the same thread, so snapshotting
228 // isn't strictly necessary. This is just defensive. 237 // isn't strictly necessary. This is just defensive.
229 leveldb::WriteBatch batch; 238 leveldb::WriteBatch batch;
230 239
231 ScopedSnapshot snapshot(db_.get()); 240 ScopedSnapshot snapshot(db_.get());
232 options.snapshot = snapshot.get(); 241 options.snapshot = snapshot.get();
233 scoped_ptr<leveldb::Iterator> it(db_->NewIterator(options)); 242 scoped_ptr<leveldb::Iterator> it(db_->NewIterator(options));
234 for (it->SeekToFirst(); it->Valid(); it->Next()) { 243 for (it->SeekToFirst(); it->Valid(); it->Next()) {
235 changed_keys->insert(it->key().ToString()); 244 const std::string key = it->key().ToString();
236 batch.Delete(it->key()); 245 const std::string old_value_as_json = it->value().ToString();
246 changed_keys->insert(key);
247 Value* old_value =
248 base::JSONReader().JsonToValue(old_value_as_json, false, false);
Matt Perry 2011/10/07 22:39:52 I don't understand this conversion to/from json. W
not at google - send to devlin 2011/10/10 01:00:16 I don't understand... what conversion?
Matt Perry 2011/10/10 20:37:15 old_value is the same as it->value()->DeepCopy(),
not at google - send to devlin 2011/10/10 22:57:53 Still puzzled, "it" is a leveldb iterator, it->val
Matt Perry 2011/10/10 23:01:17 Oops, my mistake! Reading comprehension fail... Ig
not at google - send to devlin 2011/10/11 03:58:48 np
249 if (old_value) {
250 old_settings->SetWithoutPathExpansion(key, old_value);
251 } else {
252 // TODO(kalman): clear the offending non-JSON value from the database.
253 LOG(ERROR) << "Invalid JSON in database: " << old_value_as_json;
254 }
255 batch.Delete(key);
237 } 256 }
238 257
239 if (!it->status().ok()) { 258 if (!it->status().ok()) {
240 LOG(WARNING) << "Clear iteration failed: " << it->status().ToString(); 259 LOG(WARNING) << "Clear iteration failed: " << it->status().ToString();
241 return Result(kGenericOnFailureMessage); 260 return Result(kGenericOnFailureMessage);
242 } 261 }
243 262
244 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); 263 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch);
245 if (!status.ok() && !status.IsNotFound()) { 264 if (!status.ok() && !status.IsNotFound()) {
246 LOG(WARNING) << "Clear failed: " << status.ToString(); 265 LOG(WARNING) << "Clear failed: " << status.ToString();
247 return Result(kGenericOnFailureMessage); 266 return Result(kGenericOnFailureMessage);
248 } 267 }
249 268
250 return Result(NULL, changed_keys.release()); 269 return Result(NULL, old_settings.release(), changed_keys.release());
251 } 270 }
252 271
253 bool ExtensionSettingsLeveldbStorage::ReadFromDb( 272 bool ExtensionSettingsLeveldbStorage::ReadFromDb(
254 leveldb::ReadOptions options, 273 leveldb::ReadOptions options,
255 const std::string& key, 274 const std::string& key,
256 scoped_ptr<Value>* setting) { 275 scoped_ptr<Value>* setting) {
257 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 276 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
258 DCHECK(setting != NULL); 277 DCHECK(setting != NULL);
259 std::string value_as_json; 278 std::string value_as_json;
260 leveldb::Status s = db_->Get(options, key, &value_as_json); 279 leveldb::Status s = db_->Get(options, key, &value_as_json);
(...skipping 11 matching lines...) Expand all
272 Value* value = base::JSONReader().JsonToValue(value_as_json, false, false); 291 Value* value = base::JSONReader().JsonToValue(value_as_json, false, false);
273 if (value == NULL) { 292 if (value == NULL) {
274 // TODO(kalman): clear the offending non-JSON value from the database. 293 // TODO(kalman): clear the offending non-JSON value from the database.
275 LOG(ERROR) << "Invalid JSON in database: " << value_as_json; 294 LOG(ERROR) << "Invalid JSON in database: " << value_as_json;
276 return false; 295 return false;
277 } 296 }
278 297
279 setting->reset(value); 298 setting->reset(value);
280 return true; 299 return true;
281 } 300 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698