summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-09 01:17:45 +0000
committerkalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-09 01:17:45 +0000
commit228b2ed855f581569f0b73f8b82dc999da394950 (patch)
tree11e9ec3e2a6cb1ef8f71bc66c5e34011f494667d
parent46a12790106b3cfb9e7fe8bcc26cb82eab2d0c15 (diff)
downloadchromium_src-228b2ed855f581569f0b73f8b82dc999da394950.zip
chromium_src-228b2ed855f581569f0b73f8b82dc999da394950.tar.gz
chromium_src-228b2ed855f581569f0b73f8b82dc999da394950.tar.bz2
Make the settings API code internally synchronous (no change to the API itself)
and push the asynchronous component (running on the FILE thread) up the stack to ExtensionSettingsApi. BUG= TEST=existing unit tests Review URL: http://codereview.chromium.org/7838007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@100311 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/extension_settings.cc7
-rw-r--r--chrome/browser/extensions/extension_settings_api.cc110
-rw-r--r--chrome/browser/extensions/extension_settings_api.h46
-rw-r--r--chrome/browser/extensions/extension_settings_leveldb_storage.cc606
-rw-r--r--chrome/browser/extensions/extension_settings_leveldb_storage.h40
-rw-r--r--chrome/browser/extensions/extension_settings_noop_storage.cc71
-rw-r--r--chrome/browser/extensions/extension_settings_noop_storage.h19
-rw-r--r--chrome/browser/extensions/extension_settings_storage.cc38
-rw-r--r--chrome/browser/extensions/extension_settings_storage.h127
-rw-r--r--chrome/browser/extensions/extension_settings_storage_cache.cc303
-rw-r--r--chrome/browser/extensions/extension_settings_storage_cache.h35
-rw-r--r--chrome/browser/extensions/extension_settings_storage_unittest.cc380
-rw-r--r--chrome/browser/extensions/extension_settings_storage_unittest.h24
-rw-r--r--chrome/chrome_browser.gypi1
14 files changed, 684 insertions, 1123 deletions
diff --git a/chrome/browser/extensions/extension_settings.cc b/chrome/browser/extensions/extension_settings.cc
index eb8f6e1..c3c3238 100644
--- a/chrome/browser/extensions/extension_settings.cc
+++ b/chrome/browser/extensions/extension_settings.cc
@@ -17,13 +17,12 @@
#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
ExtensionSettings::ExtensionSettings(const FilePath& base_path)
- : base_path_(base_path) {
-}
+ : base_path_(base_path) {}
ExtensionSettings::~ExtensionSettings() {
std::map<std::string, ExtensionSettingsStorage*>::iterator it;
for (it = storage_objs_.begin(); it != storage_objs_.end(); ++it) {
- it->second->DeleteSoon();
+ BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, it->second);
}
}
@@ -154,7 +153,7 @@ void ExtensionSettings::EndCreationOfStorage(
if (existing == storage_objs_.end()) {
storage_objs_[extension_id] = storage;
} else {
- storage->DeleteSoon();
+ BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, storage);
storage = existing->second;
DCHECK(storage != NULL);
}
diff --git a/chrome/browser/extensions/extension_settings_api.cc b/chrome/browser/extensions/extension_settings_api.cc
index 411d3b3..79bf586 100644
--- a/chrome/browser/extensions/extension_settings_api.cc
+++ b/chrome/browser/extensions/extension_settings_api.cc
@@ -7,101 +7,107 @@
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_settings_api.h"
#include "chrome/browser/profiles/profile.h"
+#include "content/browser/browser_thread.h"
namespace {
const char* kUnsupportedArgumentType = "Unsupported argument type";
} // namespace
-// StorageResultCallback
-
-SettingsFunction::StorageResultCallback::StorageResultCallback(
- SettingsFunction* settings_function)
- : settings_function_(settings_function) {
-}
-
-SettingsFunction::StorageResultCallback::~StorageResultCallback() {
-}
-
-void SettingsFunction::StorageResultCallback::OnSuccess(
- DictionaryValue* settings) {
- settings_function_->result_.reset(settings);
- settings_function_->SendResponse(true);
-}
-
-void SettingsFunction::StorageResultCallback::OnFailure(
- const std::string& message) {
- settings_function_->error_ = message;
- settings_function_->SendResponse(false);
-}
-
// SettingsFunction
bool SettingsFunction::RunImpl() {
profile()->GetExtensionService()->extension_settings()->GetStorage(
extension_id(),
- base::Bind(&SettingsFunction::RunWithStorage, this));
+ base::Bind(&SettingsFunction::RunOnUIThreadWithStorage, this));
return true;
}
-void SettingsFunction::RunWithStorage(ExtensionSettingsStorage* storage) {
- // Mimic how RunImpl() is handled in extensions code.
- if (!RunWithStorageImpl(storage)) {
- SendResponse(false);
+void SettingsFunction::RunOnUIThreadWithStorage(
+ ExtensionSettingsStorage* storage) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ BrowserThread::PostTask(
+ BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&SettingsFunction::RunOnFileThreadWithStorage, this, storage));
+}
+
+void SettingsFunction::RunOnFileThreadWithStorage(
+ ExtensionSettingsStorage* storage) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ bool success = RunOnFileThreadImpl(storage);
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&SettingsFunction::SendResponse, this, success));
+}
+
+bool SettingsFunction::UseResult(
+ const ExtensionSettingsStorage::Result& storage_result) {
+ if (storage_result.HasError()) {
+ error_ = storage_result.GetError();
+ return false;
}
+ DictionaryValue* settings = storage_result.GetSettings();
+ result_.reset(settings == NULL ? NULL : settings->DeepCopy());
+ return true;
}
// Concrete settings functions
-bool GetSettingsFunction::RunWithStorageImpl(
+// Adds all StringValues from a ListValue to a vector of strings.
+static void AddAllStringValues(
+ const ListValue& from, std::vector<std::string>* to) {
+ DCHECK(to->empty());
+ std::string as_string;
+ for (ListValue::const_iterator it = from.begin(); it != from.end(); ++it) {
+ if ((*it)->GetAsString(&as_string)) {
+ to->push_back(as_string);
+ }
+ }
+}
+
+bool GetSettingsFunction::RunOnFileThreadImpl(
ExtensionSettingsStorage* storage) {
Value *input;
EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &input));
-
std::string as_string;
ListValue* as_list;
if (input->IsType(Value::TYPE_NULL)) {
- storage->Get(new StorageResultCallback(this));
+ return UseResult(storage->Get());
} else if (input->GetAsString(&as_string)) {
- storage->Get(as_string, new StorageResultCallback(this));
+ return UseResult(storage->Get(as_string));
} else if (input->GetAsList(&as_list)) {
- storage->Get(*as_list, new StorageResultCallback(this));
- } else {
- error_ = kUnsupportedArgumentType;
- return false;
+ std::vector<std::string> string_list;
+ AddAllStringValues(*as_list, &string_list);
+ return UseResult(storage->Get(string_list));
}
-
- return true;
+ return UseResult(ExtensionSettingsStorage::Result(kUnsupportedArgumentType));
}
-bool SetSettingsFunction::RunWithStorageImpl(
+bool SetSettingsFunction::RunOnFileThreadImpl(
ExtensionSettingsStorage* storage) {
DictionaryValue *input;
EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &input));
- storage->Set(*input, new StorageResultCallback(this));
- return true;
+ return UseResult(storage->Set(*input));
}
-bool RemoveSettingsFunction::RunWithStorageImpl(
+bool RemoveSettingsFunction::RunOnFileThreadImpl(
ExtensionSettingsStorage* storage) {
Value *input;
EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &input));
-
std::string as_string;
ListValue* as_list;
if (input->GetAsString(&as_string)) {
- storage->Remove(as_string, new StorageResultCallback(this));
+ return UseResult(storage->Remove(as_string));
} else if (input->GetAsList(&as_list)) {
- storage->Remove(*as_list, new StorageResultCallback(this));
- } else {
- error_ = kUnsupportedArgumentType;
- return false;
+ std::vector<std::string> string_list;
+ AddAllStringValues(*as_list, &string_list);
+ return UseResult(storage->Remove(string_list));
}
-
- return true;
+ return UseResult(ExtensionSettingsStorage::Result(kUnsupportedArgumentType));
}
-bool ClearSettingsFunction::RunWithStorageImpl(
+bool ClearSettingsFunction::RunOnFileThreadImpl(
ExtensionSettingsStorage* storage) {
- storage->Clear(new StorageResultCallback(this));
- return true;
+ return UseResult(storage->Clear());
}
diff --git a/chrome/browser/extensions/extension_settings_api.h b/chrome/browser/extensions/extension_settings_api.h
index 6ddfd87..1c03539 100644
--- a/chrome/browser/extensions/extension_settings_api.h
+++ b/chrome/browser/extensions/extension_settings_api.h
@@ -14,33 +14,27 @@
// Superclass of all settings functions.
class SettingsFunction : public AsyncExtensionFunction {
public:
- // Extension settings function implementations should do their work here, and
- // either run a StorageResultCallback or fill the function result / call
- // SendResponse themselves.
- // The exception is that implementations can return false to immediately
- // call SendResponse(false), for compliance with EXTENSION_FUNCTION_VALIDATE.
- virtual bool RunWithStorageImpl(ExtensionSettingsStorage* storage) = 0;
+ // Extension settings function implementations should do their work here.
+ // This runs on the FILE thread.
+ //
+ // Implementations should fill in args themselves, though (like RunImpl)
+ // may return false to imply failure.
+ virtual bool RunOnFileThreadImpl(ExtensionSettingsStorage* storage) = 0;
+ protected:
virtual bool RunImpl() OVERRIDE;
- // Callback from all storage methods (Get/Set/Remove/Clear) which sets the
- // appropriate fields of the extension function (result/error) and sends a
- // response.
- // Declared here to access to the protected members of ExtensionFunction.
- class StorageResultCallback : public ExtensionSettingsStorage::Callback {
- public:
- explicit StorageResultCallback(SettingsFunction* settings_function);
- virtual ~StorageResultCallback();
- virtual void OnSuccess(DictionaryValue* settings) OVERRIDE;
- virtual void OnFailure(const std::string& message) OVERRIDE;
-
- private:
- scoped_refptr<SettingsFunction> settings_function_;
- };
+ // Sets error_ or result_ depending on the value of a storage Result, and
+ // returns whether the Result implies success (i.e. !error).
+ bool UseResult(const ExtensionSettingsStorage::Result& storage_result);
private:
- // Callback method from GetStorage(); delegates to RunWithStorageImpl.
- void RunWithStorage(ExtensionSettingsStorage* storage);
+ // Callback from GetStorage.
+ void RunOnUIThreadWithStorage(ExtensionSettingsStorage* storage);
+
+ // Called from RunOnUIThreadWithStorage. Runs RunOnFileThreadImpl and sends
+ // a response (on the UI thread) with its return value.
+ void RunOnFileThreadWithStorage(ExtensionSettingsStorage* storage);
};
class GetSettingsFunction : public SettingsFunction {
@@ -48,7 +42,7 @@ class GetSettingsFunction : public SettingsFunction {
DECLARE_EXTENSION_FUNCTION_NAME("experimental.settings.get");
protected:
- virtual bool RunWithStorageImpl(ExtensionSettingsStorage* storage) OVERRIDE;
+ virtual bool RunOnFileThreadImpl(ExtensionSettingsStorage* storage) OVERRIDE;
};
class SetSettingsFunction : public SettingsFunction {
@@ -56,7 +50,7 @@ class SetSettingsFunction : public SettingsFunction {
DECLARE_EXTENSION_FUNCTION_NAME("experimental.settings.set");
protected:
- virtual bool RunWithStorageImpl(ExtensionSettingsStorage* storage) OVERRIDE;
+ virtual bool RunOnFileThreadImpl(ExtensionSettingsStorage* storage) OVERRIDE;
};
class RemoveSettingsFunction : public SettingsFunction {
@@ -64,7 +58,7 @@ class RemoveSettingsFunction : public SettingsFunction {
DECLARE_EXTENSION_FUNCTION_NAME("experimental.settings.remove");
protected:
- virtual bool RunWithStorageImpl(ExtensionSettingsStorage* storage) OVERRIDE;
+ virtual bool RunOnFileThreadImpl(ExtensionSettingsStorage* storage) OVERRIDE;
};
class ClearSettingsFunction : public SettingsFunction {
@@ -72,7 +66,7 @@ class ClearSettingsFunction : public SettingsFunction {
DECLARE_EXTENSION_FUNCTION_NAME("experimental.settings.clear");
protected:
- virtual bool RunWithStorageImpl(ExtensionSettingsStorage* storage) OVERRIDE;
+ virtual bool RunOnFileThreadImpl(ExtensionSettingsStorage* storage) OVERRIDE;
};
#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_SETTINGS_API_H_
diff --git a/chrome/browser/extensions/extension_settings_leveldb_storage.cc b/chrome/browser/extensions/extension_settings_leveldb_storage.cc
index 5fcc99b..5ce5ad3 100644
--- a/chrome/browser/extensions/extension_settings_leveldb_storage.cc
+++ b/chrome/browser/extensions/extension_settings_leveldb_storage.cc
@@ -15,491 +15,231 @@
#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
namespace {
-
// Generic error message sent to extensions on failure.
const char* kGenericOnFailureMessage = "Extension settings failed";
+} // namespace
-// General closure type for computing a value on the FILE thread and calling
-// back on the UI thread. The *OnFileThread methods should run on the file
-// thread, all others should run on the UI thread.
-//
-// Subclasses should implement RunOnFileThread(), manipulating settings_
-// or error_, then call either SucceedOnFileThread() or FailOnFileThread().
-class ResultClosure {
- public:
- // Ownership of callback and settings are taken.
- // Settings may be NULL (for Remove/Clear).
- ResultClosure(
- leveldb::DB* db,
- DictionaryValue* settings,
- ExtensionSettingsStorage::Callback* callback)
- : db_(db), settings_(settings), callback_(callback) {}
-
- virtual ~ResultClosure() {}
-
- void Run() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- BrowserThread::PostTask(
- BrowserThread::FILE,
- FROM_HERE,
- base::Bind(&ResultClosure::RunOnFileThread, base::Unretained(this)));
- }
-
- protected:
- virtual void RunOnFileThread() = 0;
-
- void SucceedOnFileThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&ResultClosure::Succeed, base::Unretained(this)));
- }
+/* static */
+ExtensionSettingsLeveldbStorage* ExtensionSettingsLeveldbStorage::Create(
+ const FilePath& base_path,
+ const std::string& extension_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ FilePath path = base_path.AppendASCII(extension_id);
- void FailOnFileThread(std::string error) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- error_ = error;
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&ResultClosure::Fail, base::Unretained(this)));
- }
+#if defined(OS_POSIX)
+ std::string os_path(path.value());
+#elif defined(OS_WIN)
+ std::string os_path = base::SysWideToUTF8(path.value());
+#endif
- // Helper for the Get() methods; reads a single key from the database using
- // an existing leveldb options object.
- // Returns whether the read was successful, in which case the given settings
- // will have the value set. Otherwise, error will be set.
- bool ReadFromDb(
- leveldb::ReadOptions options,
- const std::string& key,
- DictionaryValue* settings,
- std::string* error) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- std::string value_as_json;
- leveldb::Status s = db_->Get(options, key, &value_as_json);
- if (s.ok()) {
- base::JSONReader json_reader;
- Value* value = json_reader.JsonToValue(value_as_json, false, false);
- if (value != NULL) {
- settings->SetWithoutPathExpansion(key, value);
- return true;
- } else {
- // TODO(kalman): clear the offending non-JSON value from the database.
- LOG(ERROR) << "Invalid JSON: " << value_as_json;
- *error = "Invalid JSON";
- return false;
- }
- } else if (s.IsNotFound()) {
- // Despite there being no value, it was still a success.
- return true;
- } else {
- LOG(ERROR) << "Error reading from database: " << s.ToString();
- *error = s.ToString();
- return false;
- }
+ leveldb::Options options;
+ options.create_if_missing = true;
+ leveldb::DB* db;
+ leveldb::Status status = leveldb::DB::Open(options, os_path, &db);
+ if (!status.ok()) {
+ LOG(WARNING) << "Failed to create leveldb at " << path.value() <<
+ ": " << status.ToString();
+ return NULL;
}
+ return new ExtensionSettingsLeveldbStorage(db);
+}
- // The leveldb database this closure interacts with. Owned by an
- // ExtensionSettingsLeveldbStorage instance, but only accessed from the FILE
- // thread part of the closure (RunOnFileThread), and only deleted on the FILE
- // thread from DeleteSoon() method, guaranteed to run afterwards (see
- // marked_for_deletion_).
- leveldb::DB* db_;
-
- scoped_ptr<DictionaryValue> settings_;
- std::string error_;
-
- private:
- void Succeed() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- callback_->OnSuccess(settings_.release());
- delete this;
- }
+ExtensionSettingsLeveldbStorage::ExtensionSettingsLeveldbStorage(
+ leveldb::DB* db) : db_(db) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+}
- void Fail() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- callback_->OnFailure(error_);
- delete this;
- }
+ExtensionSettingsLeveldbStorage::~ExtensionSettingsLeveldbStorage() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+}
- scoped_ptr<ExtensionSettingsStorage::Callback> callback_;
-
- DISALLOW_COPY_AND_ASSIGN(ResultClosure);
-};
-
-// Result closure for Get(key).
-class Get1ResultClosure : public ResultClosure {
- public:
- Get1ResultClosure(
- leveldb::DB* db,
- ExtensionSettingsStorage::Callback* callback,
- const std::string& key)
- : ResultClosure(db, new DictionaryValue(), callback), key_(key) {}
-
- protected:
- virtual void RunOnFileThread() OVERRIDE {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- if (ReadFromDb(leveldb::ReadOptions(), key_, settings_.get(), &error_)) {
- SucceedOnFileThread();
- } else {
- FailOnFileThread(kGenericOnFailureMessage);
- }
+ExtensionSettingsStorage::Result ExtensionSettingsLeveldbStorage::Get(
+ const std::string& key) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ scoped_ptr<DictionaryValue> settings(new DictionaryValue());
+ if (!ReadFromDb(leveldb::ReadOptions(), key, settings.get())) {
+ return Result(kGenericOnFailureMessage);
}
+ return Result(settings.release());
+}
- private:
- std::string key_;
-};
-
-// Result closure for Get(keys).
-class Get2ResultClosure : public ResultClosure {
- public:
- // Ownership of keys is taken.
- Get2ResultClosure(
- leveldb::DB* db,
- ExtensionSettingsStorage::Callback* callback,
- ListValue* keys)
- : ResultClosure(db, new DictionaryValue(), callback), keys_(keys) {}
-
- protected:
- virtual void RunOnFileThread() OVERRIDE {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- leveldb::ReadOptions options;
- // All interaction with the db is done on the same thread, so snapshotting
- // isn't strictly necessary. This is just defensive.
- options.snapshot = db_->GetSnapshot();
- bool success = true;
- std::string key;
-
- for (ListValue::const_iterator it = keys_->begin();
- success && it != keys_->end(); ++it) {
- if ((*it)->GetAsString(&key)) {
- if (!ReadFromDb(options, key, settings_.get(), &error_)) {
- success = false;
- }
- }
- }
- db_->ReleaseSnapshot(options.snapshot);
+ExtensionSettingsStorage::Result ExtensionSettingsLeveldbStorage::Get(
+ const std::vector<std::string>& keys) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ leveldb::ReadOptions options;
+ // All interaction with the db is done on the same thread, so snapshotting
+ // isn't strictly necessary. This is just defensive.
+ scoped_ptr<DictionaryValue> settings(new DictionaryValue());
+ bool success = true;
- if (success) {
- SucceedOnFileThread();
- } else {
- FailOnFileThread(kGenericOnFailureMessage);
- }
+ options.snapshot = db_->GetSnapshot();
+ for (std::vector<std::string>::const_iterator it = keys.begin();
+ success && it != keys.end(); ++it) {
+ success &= ReadFromDb(options, *it, settings.get());
}
+ db_->ReleaseSnapshot(options.snapshot);
- private:
- scoped_ptr<ListValue> keys_;
-};
-
-// Result closure for Get() .
-class Get3ResultClosure : public ResultClosure {
- public:
- Get3ResultClosure(
- leveldb::DB* db,
- ExtensionSettingsStorage::Callback* callback)
- : ResultClosure(db, new DictionaryValue(), callback) {
+ if (!success) {
+ return Result(kGenericOnFailureMessage);
}
- protected:
- virtual void RunOnFileThread() OVERRIDE {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- base::JSONReader json_reader;
- leveldb::ReadOptions options = leveldb::ReadOptions();
- // All interaction with the db is done on the same thread, so snapshotting
- // isn't strictly necessary. This is just defensive.
- options.snapshot = db_->GetSnapshot();
- scoped_ptr<leveldb::Iterator> it(db_->NewIterator(options));
-
- for (it->SeekToFirst(); it->Valid(); it->Next()) {
- Value* value =
- json_reader.JsonToValue(it->value().ToString(), false, false);
- if (value != NULL) {
- settings_->SetWithoutPathExpansion(it->key().ToString(), value);
- } else {
- // TODO(kalman): clear the offending non-JSON value from the database.
- LOG(ERROR) << "Invalid JSON: " << it->value().ToString();
- }
- }
- db_->ReleaseSnapshot(options.snapshot);
+ return Result(settings.release());
+}
- if (!it->status().ok()) {
- LOG(ERROR) << "DB iteration failed: " << it->status().ToString();
- FailOnFileThread(kGenericOnFailureMessage);
- } else {
- SucceedOnFileThread();
- }
- }
-};
-
-// Result closure for Set(key, value).
-class Set1ResultClosure : public ResultClosure {
- public:
- // Ownership of the value is taken.
- Set1ResultClosure(
- leveldb::DB* db,
- ExtensionSettingsStorage::Callback* callback,
- const std::string& key,
- Value* value)
- : ResultClosure(db, new DictionaryValue(), callback),
- key_(key),
- value_(value) {}
-
- protected:
- virtual void RunOnFileThread() OVERRIDE {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- std::string value_as_json;
- base::JSONWriter::Write(value_.get(), false, &value_as_json);
- leveldb::Status status =
- db_->Put(leveldb::WriteOptions(), key_, value_as_json);
- if (status.ok()) {
- settings_->SetWithoutPathExpansion(key_, value_.release());
- SucceedOnFileThread();
+ExtensionSettingsStorage::Result ExtensionSettingsLeveldbStorage::Get() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ base::JSONReader json_reader;
+ leveldb::ReadOptions options = leveldb::ReadOptions();
+ // All interaction with the db is done on the same thread, so snapshotting
+ // isn't strictly necessary. This is just defensive.
+ scoped_ptr<DictionaryValue> settings(new DictionaryValue());
+
+ options.snapshot = db_->GetSnapshot();
+ scoped_ptr<leveldb::Iterator> it(db_->NewIterator(options));
+ for (it->SeekToFirst(); it->Valid(); it->Next()) {
+ Value* value =
+ json_reader.JsonToValue(it->value().ToString(), false, false);
+ if (value != NULL) {
+ settings->SetWithoutPathExpansion(it->key().ToString(), value);
} else {
- LOG(WARNING) << "DB write failed: " << status.ToString();
- FailOnFileThread(kGenericOnFailureMessage);
+ // TODO(kalman): clear the offending non-JSON value from the database.
+ LOG(ERROR) << "Invalid JSON: " << it->value().ToString();
}
}
+ db_->ReleaseSnapshot(options.snapshot);
- private:
- std::string key_;
- scoped_ptr<Value> value_;
-};
-
-// Result callback for Set(values).
-class Set2ResultClosure : public ResultClosure {
- public:
- // Ownership of values is taken.
- Set2ResultClosure(
- leveldb::DB* db,
- ExtensionSettingsStorage::Callback* callback,
- DictionaryValue* values)
- : ResultClosure(db, new DictionaryValue(), callback), values_(values) {
+ if (!it->status().ok()) {
+ LOG(ERROR) << "DB iteration failed: " << it->status().ToString();
+ return Result(kGenericOnFailureMessage);
}
- protected:
- virtual void RunOnFileThread() OVERRIDE {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- // Gather keys since a dictionary can't be modified during iteration.
- std::vector<std::string> keys;
- for (DictionaryValue::key_iterator it = values_->begin_keys();
- it != values_->end_keys(); ++it) {
- keys.push_back(*it);
- }
- // Write values while transferring ownership from values_ to settings_.
- std::string value_as_json;
- leveldb::WriteBatch batch;
- for (unsigned i = 0; i < keys.size(); ++i) {
- Value* value = NULL;
- values_->RemoveWithoutPathExpansion(keys[i], &value);
- base::JSONWriter::Write(value, false, &value_as_json);
- batch.Put(keys[i], value_as_json);
- settings_->SetWithoutPathExpansion(keys[i], value);
- }
- DCHECK(values_->empty());
-
- leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch);
- if (status.ok()) {
- SucceedOnFileThread();
- } else {
- LOG(WARNING) << "DB batch write failed: " << status.ToString();
- FailOnFileThread(kGenericOnFailureMessage);
- }
- }
+ return Result(settings.release());
+}
- private:
- scoped_ptr<DictionaryValue> values_; // will be empty on destruction
-};
-
-// Result closure for Remove(key).
-class Remove1ResultClosure : public ResultClosure {
- public:
- Remove1ResultClosure(
- leveldb::DB* db,
- ExtensionSettingsStorage::Callback* callback,
- const std::string& key)
- : ResultClosure(db, NULL, callback), key_(key) {
- }
+ExtensionSettingsStorage::Result ExtensionSettingsLeveldbStorage::Set(
+ const std::string& key, const Value& value) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ std::string value_as_json;
+ base::JSONWriter::Write(&value, false, &value_as_json);
- protected:
- virtual void RunOnFileThread() OVERRIDE {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- leveldb::Status status = db_->Delete(leveldb::WriteOptions(), key_);
- if (status.ok() || status.IsNotFound()) {
- SucceedOnFileThread();
- } else {
- LOG(WARNING) << "DB delete failed: " << status.ToString();
- FailOnFileThread(kGenericOnFailureMessage);
- }
+ leveldb::Status status =
+ db_->Put(leveldb::WriteOptions(), key, value_as_json);
+ if (!status.ok()) {
+ LOG(WARNING) << "DB write failed: " << status.ToString();
+ return Result(kGenericOnFailureMessage);
}
- private:
- std::string key_;
-};
-
-// Result closure for Remove(keys).
-class Remove2ResultClosure : public ResultClosure {
- public:
- // Ownership of keys is taken.
- Remove2ResultClosure(
- leveldb::DB* db,
- ExtensionSettingsStorage::Callback* callback,
- ListValue* keys)
- : ResultClosure(db, NULL, callback), keys_(keys) {
- }
+ DictionaryValue* settings = new DictionaryValue();
+ settings->SetWithoutPathExpansion(key, value.DeepCopy());
+ return Result(settings);
+}
- protected:
- virtual void RunOnFileThread() OVERRIDE {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- std::string key;
- leveldb::WriteBatch batch;
- for (ListValue::const_iterator it = keys_->begin();
- it != keys_->end(); ++it) {
- if ((*it)->GetAsString(&key)) {
- batch.Delete(key);
- }
- }
+ExtensionSettingsStorage::Result ExtensionSettingsLeveldbStorage::Set(
+ const DictionaryValue& settings) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ std::string value_as_json;
+ leveldb::WriteBatch batch;
- leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch);
- if (status.ok() || status.IsNotFound()) {
- SucceedOnFileThread();
- } else {
- LOG(WARNING) << "DB batch delete failed: " << status.ToString();
- FailOnFileThread(kGenericOnFailureMessage);
- }
+ for (DictionaryValue::key_iterator it = settings.begin_keys();
+ it != settings.end_keys(); ++it) {
+ Value* value;
+ settings.GetWithoutPathExpansion(*it, &value);
+ base::JSONWriter::Write(value, false, &value_as_json);
+ batch.Put(*it, value_as_json);
}
- private:
- scoped_ptr<ListValue> keys_;
-};
-
-// Result closure for Clear().
-class ClearResultClosure : public ResultClosure {
- public:
- ClearResultClosure(leveldb::DB* db,
- ExtensionSettingsStorage::Callback* callback)
- : ResultClosure(db, NULL, callback) {
+ leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch);
+ if (!status.ok()) {
+ LOG(WARNING) << "DB batch write failed: " << status.ToString();
+ return Result(kGenericOnFailureMessage);
}
- protected:
- virtual void RunOnFileThread() OVERRIDE {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- leveldb::ReadOptions options;
- // All interaction with the db is done on the same thread, so snapshotting
- // isn't strictly necessary. This is just defensive.
- options.snapshot = db_->GetSnapshot();
- scoped_ptr<leveldb::Iterator> it(db_->NewIterator(options));
- leveldb::WriteBatch batch;
-
- for (it->SeekToFirst(); it->Valid(); it->Next()) {
- batch.Delete(it->key());
- }
- db_->ReleaseSnapshot(options.snapshot);
-
- if (it->status().ok()) {
- leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch);
- if (status.ok() || status.IsNotFound()) {
- SucceedOnFileThread();
- } else {
- LOG(WARNING) << "Clear failed: " << status.ToString();
- FailOnFileThread(kGenericOnFailureMessage);
- }
- } else {
- LOG(WARNING) << "Clear iteration failed: " << it->status().ToString();
- FailOnFileThread(kGenericOnFailureMessage);
- }
+ return Result(settings.DeepCopy());
+}
+
+ExtensionSettingsStorage::Result ExtensionSettingsLeveldbStorage::Remove(
+ const std::string& key) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ leveldb::Status status = db_->Delete(leveldb::WriteOptions(), key);
+ if (!status.ok() && !status.IsNotFound()) {
+ LOG(WARNING) << "DB delete failed: " << status.ToString();
+ return Result(kGenericOnFailureMessage);
}
-};
-} // namespace
+ return Result(NULL);
+}
-/* static */
-ExtensionSettingsLeveldbStorage* ExtensionSettingsLeveldbStorage::Create(
- const FilePath& base_path,
- const std::string& extension_id) {
+ExtensionSettingsStorage::Result ExtensionSettingsLeveldbStorage::Remove(
+ const std::vector<std::string>& keys) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- FilePath path = base_path.AppendASCII(extension_id);
-
-#if defined(OS_POSIX)
- std::string os_path(path.value());
-#elif defined(OS_WIN)
- std::string os_path = base::SysWideToUTF8(path.value());
-#endif
+ leveldb::WriteBatch batch;
+ for (std::vector<std::string>::const_iterator it = keys.begin();
+ it != keys.end(); ++it) {
+ batch.Delete(*it);
+ }
- leveldb::Options options;
- options.create_if_missing = true;
- leveldb::DB* db;
- leveldb::Status status = leveldb::DB::Open(options, os_path, &db);
- if (!status.ok()) {
- LOG(WARNING) << "Failed to create leveldb at " << path.value() <<
- ": " << status.ToString();
- return NULL;
+ leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch);
+ if (!status.ok() && !status.IsNotFound()) {
+ LOG(WARNING) << "DB batch delete failed: " << status.ToString();
+ return Result(kGenericOnFailureMessage);
}
- return new ExtensionSettingsLeveldbStorage(db);
-}
-ExtensionSettingsLeveldbStorage::ExtensionSettingsLeveldbStorage(
- leveldb::DB* db)
- : db_(db), marked_for_deletion_(false) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ return Result(NULL);
}
-ExtensionSettingsLeveldbStorage::~ExtensionSettingsLeveldbStorage() {
+ExtensionSettingsStorage::Result ExtensionSettingsLeveldbStorage::Clear() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-}
+ leveldb::ReadOptions options;
+ // All interaction with the db is done on the same thread, so snapshotting
+ // isn't strictly necessary. This is just defensive.
+ leveldb::WriteBatch batch;
-void ExtensionSettingsLeveldbStorage::DeleteSoon() {
- CHECK(!marked_for_deletion_);
- marked_for_deletion_ = true;
- BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, this);
-}
+ options.snapshot = db_->GetSnapshot();
+ scoped_ptr<leveldb::Iterator> it(db_->NewIterator(options));
+ for (it->SeekToFirst(); it->Valid(); it->Next()) {
+ batch.Delete(it->key());
+ }
+ db_->ReleaseSnapshot(options.snapshot);
-void ExtensionSettingsLeveldbStorage::Get(
- const std::string& key, ExtensionSettingsStorage::Callback* callback) {
- CHECK(!marked_for_deletion_);
- (new Get1ResultClosure(db_.get(), callback, key))->Run();
-}
+ if (!it->status().ok()) {
+ LOG(WARNING) << "Clear iteration failed: " << it->status().ToString();
+ return Result(kGenericOnFailureMessage);
+ }
-void ExtensionSettingsLeveldbStorage::Get(
- const ListValue& keys, ExtensionSettingsStorage::Callback* callback) {
- CHECK(!marked_for_deletion_);
- (new Get2ResultClosure(db_.get(), callback, keys.DeepCopy()))->Run();
-}
+ leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch);
+ if (!status.ok() && !status.IsNotFound()) {
+ LOG(WARNING) << "Clear failed: " << status.ToString();
+ return Result(kGenericOnFailureMessage);
+ }
-void ExtensionSettingsLeveldbStorage::Get(
- ExtensionSettingsStorage::Callback* callback) {
- CHECK(!marked_for_deletion_);
- (new Get3ResultClosure(db_.get(), callback))->Run();
+ return Result(NULL);
}
-void ExtensionSettingsLeveldbStorage::Set(
+bool ExtensionSettingsLeveldbStorage::ReadFromDb(
+ leveldb::ReadOptions options,
const std::string& key,
- const Value& value,
- ExtensionSettingsStorage::Callback* callback) {
- CHECK(!marked_for_deletion_);
- (new Set1ResultClosure(db_.get(), callback, key, value.DeepCopy()))->Run();
-}
+ DictionaryValue* settings) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ std::string value_as_json;
+ leveldb::Status s = db_->Get(options, key, &value_as_json);
-void ExtensionSettingsLeveldbStorage::Set(
- const DictionaryValue& values,
- ExtensionSettingsStorage::Callback* callback) {
- CHECK(!marked_for_deletion_);
- (new Set2ResultClosure(db_.get(), callback, values.DeepCopy()))->Run();
-}
+ if (s.IsNotFound()) {
+ // Despite there being no value, it was still a success.
+ return true;
+ }
-void ExtensionSettingsLeveldbStorage::Remove(
- const std::string& key, ExtensionSettingsStorage::Callback *callback) {
- CHECK(!marked_for_deletion_);
- (new Remove1ResultClosure(db_.get(), callback, key))->Run();
-}
+ if (!s.ok()) {
+ LOG(ERROR) << "Error reading from database: " << s.ToString();
+ return false;
+ }
-void ExtensionSettingsLeveldbStorage::Remove(
- const ListValue& keys, ExtensionSettingsStorage::Callback *callback) {
- CHECK(!marked_for_deletion_);
- (new Remove2ResultClosure(db_.get(), callback, keys.DeepCopy()))->Run();
-}
+ Value* value = base::JSONReader().JsonToValue(value_as_json, false, false);
+ if (value == NULL) {
+ // TODO(kalman): clear the offending non-JSON value from the database.
+ LOG(ERROR) << "Invalid JSON in database: " << value_as_json;
+ return false;
+ }
-void ExtensionSettingsLeveldbStorage::Clear(
- ExtensionSettingsStorage::Callback* callback) {
- CHECK(!marked_for_deletion_);
- (new ClearResultClosure(db_.get(), callback))->Run();
+ settings->SetWithoutPathExpansion(key, value);
+ return true;
}
diff --git a/chrome/browser/extensions/extension_settings_leveldb_storage.h b/chrome/browser/extensions/extension_settings_leveldb_storage.h
index 79bbed3..5090f9a 100644
--- a/chrome/browser/extensions/extension_settings_leveldb_storage.h
+++ b/chrome/browser/extensions/extension_settings_leveldb_storage.h
@@ -17,44 +17,46 @@
#include "third_party/leveldatabase/src/include/leveldb/db.h"
// Extension settings storage object, backed by a leveldb database.
+//
// No caching is done; that should be handled by wrapping with an
// ExtensionSettingsStorageCache.
+// All methods must be run on the FILE thread.
class ExtensionSettingsLeveldbStorage : public ExtensionSettingsStorage {
public:
// Tries to create a leveldb storage area for an extension at a base path.
// Returns NULL if creation fails.
- // Must be run on the FILE thread.
static ExtensionSettingsLeveldbStorage* Create(
const FilePath& base_path, const std::string& extension_id);
- // Can be run on any thread.
- virtual void DeleteSoon() OVERRIDE;
+ // Must be deleted on the FILE thread.
+ virtual ~ExtensionSettingsLeveldbStorage();
- virtual void Get(const std::string& key, Callback* callback) OVERRIDE;
- virtual void Get(const ListValue& keys, Callback* callback) OVERRIDE;
- virtual void Get(Callback* callback) OVERRIDE;
- virtual void Set(
- const std::string& key, const Value& value, Callback* callback) OVERRIDE;
- virtual void Set(const DictionaryValue& values, Callback* callback) OVERRIDE;
- virtual void Remove(const std::string& key, Callback* callback) OVERRIDE;
- virtual void Remove(const ListValue& keys, Callback* callback) OVERRIDE;
- virtual void Clear(Callback *callback) OVERRIDE;
+ // ExtensionSettingsStorage implementation.
+ virtual Result Get(const std::string& key) OVERRIDE;
+ virtual Result Get(const std::vector<std::string>& keys) OVERRIDE;
+ virtual Result Get() OVERRIDE;
+ virtual Result Set(const std::string& key, const Value& value) OVERRIDE;
+ virtual Result Set(const DictionaryValue& settings) OVERRIDE;
+ virtual Result Remove(const std::string& key) OVERRIDE;
+ virtual Result Remove(const std::vector<std::string>& keys) OVERRIDE;
+ virtual Result Clear() OVERRIDE;
private:
// Ownership of db is taken.
explicit ExtensionSettingsLeveldbStorage(leveldb::DB* db);
- // This must only be deleted on the FILE thread.
- friend class DeleteTask<ExtensionSettingsLeveldbStorage>;
- virtual ~ExtensionSettingsLeveldbStorage();
+ // Reads a key from the database, settings the resulting key/value pair in
+ // a given settings object if successful.
+ // Returns whether the get was successful.
+ bool ReadFromDb(
+ leveldb::ReadOptions options,
+ const std::string& key,
+ // Ownership NOT taken.
+ DictionaryValue* settings);
// leveldb backend.
scoped_ptr<leveldb::DB> db_;
- // Whether this has or is about to be deleted on the FILE thread.
- // Used to prevent any use of this after DeleteSoon() is called.
- bool marked_for_deletion_;
-
DISALLOW_COPY_AND_ASSIGN(ExtensionSettingsLeveldbStorage);
};
diff --git a/chrome/browser/extensions/extension_settings_noop_storage.cc b/chrome/browser/extensions/extension_settings_noop_storage.cc
index b950be2..3e1199b 100644
--- a/chrome/browser/extensions/extension_settings_noop_storage.cc
+++ b/chrome/browser/extensions/extension_settings_noop_storage.cc
@@ -4,69 +4,42 @@
#include "chrome/browser/extensions/extension_settings_noop_storage.h"
-#include "base/bind.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop.h"
-#include "base/task.h"
-
-static void CallOnSuccess(
- ExtensionSettingsStorage::Callback* callback, DictionaryValue* settings) {
- callback->OnSuccess(settings);
- delete callback;
-}
-
-static void Succeed(
- ExtensionSettingsStorage::Callback* callback, DictionaryValue* settings) {
- MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&CallOnSuccess, callback, settings));
-}
-
-void ExtensionSettingsNoopStorage::DeleteSoon() {
- delete this;
-}
-
-void ExtensionSettingsNoopStorage::Get(
- const std::string& key, ExtensionSettingsStorage::Callback* callback) {
- Succeed(callback, new DictionaryValue());
+ExtensionSettingsStorage::Result ExtensionSettingsNoopStorage::Get(
+ const std::string& key) {
+ return Result(new DictionaryValue());
}
-void ExtensionSettingsNoopStorage::Get(
- const ListValue& keys, ExtensionSettingsStorage::Callback* callback) {
- Succeed(callback, new DictionaryValue());
+ExtensionSettingsStorage::Result ExtensionSettingsNoopStorage::Get(
+ const std::vector<std::string>& keys) {
+ return Result(new DictionaryValue());
}
-void ExtensionSettingsNoopStorage::Get(
- ExtensionSettingsStorage::Callback* callback) {
- Succeed(callback, new DictionaryValue());
+ExtensionSettingsStorage::Result ExtensionSettingsNoopStorage::Get() {
+ return Result(new DictionaryValue());
}
-void ExtensionSettingsNoopStorage::Set(
- const std::string& key,
- const Value& value,
- ExtensionSettingsStorage::Callback* callback) {
+ExtensionSettingsStorage::Result ExtensionSettingsNoopStorage::Set(
+ const std::string& key, const Value& value) {
DictionaryValue* settings = new DictionaryValue();
settings->SetWithoutPathExpansion(key, value.DeepCopy());
- Succeed(callback, settings);
+ return Result(settings);
}
-void ExtensionSettingsNoopStorage::Set(
- const DictionaryValue& values,
- ExtensionSettingsStorage::Callback* callback) {
- Succeed(callback, values.DeepCopy());
+ExtensionSettingsStorage::Result ExtensionSettingsNoopStorage::Set(
+ const DictionaryValue& settings) {
+ return Result(settings.DeepCopy());
}
-void ExtensionSettingsNoopStorage::Remove(
- const std::string& key, ExtensionSettingsStorage::Callback *callback) {
- Succeed(callback, NULL);
+ExtensionSettingsStorage::Result ExtensionSettingsNoopStorage::Remove(
+ const std::string& key) {
+ return Result(NULL);
}
-void ExtensionSettingsNoopStorage::Remove(
- const ListValue& keys, ExtensionSettingsStorage::Callback *callback) {
- Succeed(callback, NULL);
+ExtensionSettingsStorage::Result ExtensionSettingsNoopStorage::Remove(
+ const std::vector<std::string>& keys) {
+ return Result(NULL);
}
-void ExtensionSettingsNoopStorage::Clear(
- ExtensionSettingsStorage::Callback* callback) {
- Succeed(callback, NULL);
+ExtensionSettingsStorage::Result ExtensionSettingsNoopStorage::Clear() {
+ return Result(NULL);
}
diff --git a/chrome/browser/extensions/extension_settings_noop_storage.h b/chrome/browser/extensions/extension_settings_noop_storage.h
index 2112991..0396273 100644
--- a/chrome/browser/extensions/extension_settings_noop_storage.h
+++ b/chrome/browser/extensions/extension_settings_noop_storage.h
@@ -16,16 +16,15 @@ class ExtensionSettingsNoopStorage : public ExtensionSettingsStorage {
public:
ExtensionSettingsNoopStorage() {}
- virtual void DeleteSoon() OVERRIDE;
- virtual void Get(const std::string& key, Callback* callback) OVERRIDE;
- virtual void Get(const ListValue& keys, Callback* callback) OVERRIDE;
- virtual void Get(Callback* callback) OVERRIDE;
- virtual void Set(
- const std::string& key, const Value& value, Callback* callback) OVERRIDE;
- virtual void Set(const DictionaryValue& values, Callback* callback) OVERRIDE;
- virtual void Remove(const std::string& key, Callback* callback) OVERRIDE;
- virtual void Remove(const ListValue& keys, Callback* callback) OVERRIDE;
- virtual void Clear(Callback *callback) OVERRIDE;
+ // ExtensionSettingsStorage implementation.
+ virtual Result Get(const std::string& key) OVERRIDE;
+ virtual Result Get(const std::vector<std::string>& keys) OVERRIDE;
+ virtual Result Get() OVERRIDE;
+ virtual Result Set(const std::string& key, const Value& value) OVERRIDE;
+ virtual Result Set(const DictionaryValue& values) OVERRIDE;
+ virtual Result Remove(const std::string& key) OVERRIDE;
+ virtual Result Remove(const std::vector<std::string>& keys) OVERRIDE;
+ virtual Result Clear() OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(ExtensionSettingsNoopStorage);
diff --git a/chrome/browser/extensions/extension_settings_storage.cc b/chrome/browser/extensions/extension_settings_storage.cc
new file mode 100644
index 0000000..1e318b5
--- /dev/null
+++ b/chrome/browser/extensions/extension_settings_storage.cc
@@ -0,0 +1,38 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "chrome/browser/extensions/extension_settings_storage.h"
+
+// Implementation of ExtensionSettingsStorage::Result
+
+ExtensionSettingsStorage::Result::Result(DictionaryValue* settings)
+ : inner_(new Inner(settings, std::string())) {}
+
+ExtensionSettingsStorage::Result::Result(const std::string& error)
+ : inner_(new Inner(NULL, error)) {
+ DCHECK(!error.empty());
+}
+
+ExtensionSettingsStorage::Result::~Result() {}
+
+DictionaryValue* ExtensionSettingsStorage::Result::GetSettings() const {
+ DCHECK(!HasError());
+ return inner_->settings_.get();
+}
+
+bool ExtensionSettingsStorage::Result::HasError() const {
+ return !inner_->error_.empty();
+}
+
+const std::string& ExtensionSettingsStorage::Result::GetError() const {
+ DCHECK(HasError());
+ return inner_->error_;
+}
+
+ExtensionSettingsStorage::Result::Inner::Inner(
+ DictionaryValue* settings, const std::string& error)
+ : settings_(settings), error_(error) {}
+
+ExtensionSettingsStorage::Result::Inner::~Inner() {}
diff --git a/chrome/browser/extensions/extension_settings_storage.h b/chrome/browser/extensions/extension_settings_storage.h
index b1542c4..5918ab2 100644
--- a/chrome/browser/extensions/extension_settings_storage.h
+++ b/chrome/browser/extensions/extension_settings_storage.h
@@ -6,30 +6,16 @@
#define CHROME_BROWSER_EXTENSIONS_EXTENSION_SETTINGS_STORAGE_H_
#pragma once
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/values.h"
// Interface for extension settings storage classes.
//
-// All asynchrous methods *must* run in a message loop, i.e. the callbacks may
-// not be run from the calling method, but must be PostTask'ed (whether to
-// one's own thread or to e.g. the FILE thread).
+// All methods *must* be run on the FILE thread, inclusing construction and
+// destructions.
class ExtensionSettingsStorage {
public:
- // Asynchronous results of Set/Get/Remove. Exactly one of OnSuccess or
- // OnFailure will eventually be called.
- // Callback objects will be deleted after running.
- class Callback {
- public:
- virtual ~Callback() {}
-
- // Indicates the storage operation was successful. Settings value will be
- // non-NULL. Ownership is passed to the callback.
- virtual void OnSuccess(DictionaryValue* settings) = 0;
-
- // Indicates the storage operation failed. Messages describes the failure.
- virtual void OnFailure(const std::string& message) = 0;
- };
-
// The different types of extension settings storage.
enum Type {
NONE,
@@ -37,47 +23,74 @@ class ExtensionSettingsStorage {
LEVELDB
};
+ // The result of an operation.
+ //
+ // Supports lightweight copying.
+ class Result {
+ public:
+ // Ownership of settings taken.
+ explicit Result(DictionaryValue* settings);
+ explicit Result(const std::string& error);
+ ~Result();
+
+ // The dictionary result of the computation. NULL does not imply invalid;
+ // HasError() should be used to test this.
+ // Wwnership remains with with the Result.
+ DictionaryValue* GetSettings() const;
+
+ // Whether there was an error in the computation. If so, the results of
+ // GetSettings and ReleaseSettings are not valid.
+ bool HasError() const;
+
+ // Gets the error message, if any.
+ const std::string& GetError() const;
+
+ private:
+ struct Inner : public base::RefCountedThreadSafe<Inner> {
+ // Empty error implies no error.
+ Inner(DictionaryValue* settings, const std::string& error);
+ ~Inner();
+
+ const scoped_ptr<DictionaryValue> settings_;
+ const std::string error_;
+ };
+
+ const scoped_refptr<Inner> inner_;
+ };
+
virtual ~ExtensionSettingsStorage() {}
- // Destroys this settings storage object. This is needed as a separate
- // interface method as opposed to just using the destructor, since
- // destruction may need to be done asynchronously (e.g. on the FILE thread).
- virtual void DeleteSoon() = 0;
-
- // Gets a single value from storage. Callback with a dictionary mapping the
- // key to its value, if any.
- virtual void Get(const std::string& key, Callback* callback) = 0;
-
- // Gets multiple values from storage. Callback with a dictionary mapping
- // each key to its value, if any.
- virtual void Get(const ListValue& keys, Callback* callback) = 0;
-
- // Gets all values from storage. Callback with a dictionary mapping every
- // key to its value.
- virtual void Get(Callback* callback) = 0;
-
- // Sets a single key to a new value. Callback with a dictionary mapping the
- // key to its new value; on success, this is guaranteed to be the given key
- // to the given new value.
- virtual void Set(const std::string& key, const Value& value,
- Callback* callback) = 0;
-
- // Sets multiple keys to new values. Callback with a dictionary mapping each
- // key to its new value; on success, this is guaranteed to be each given key
- // to its given new value.
- virtual void Set(const DictionaryValue& values, Callback* callback) = 0;
-
- // Removes a key from the map. Callback with a dictionary mapping the key
- // to its new value; on success, this will be an empty map.
- virtual void Remove(const std::string& key, Callback* callback) = 0;
-
- // Removes multiple keys from the map. Callback with a dictionary mapping
- // each key to its new value; on success, this will be an empty map.
- virtual void Remove(const ListValue& keys, Callback* callback) = 0;
-
- // Clears the storage. Callback with a dictionary mapping every key in
- // storage to its value; on success, this will be an empty map.
- virtual void Clear(Callback *callback) = 0;
+ // Gets a single value from storage.
+ // If successful, result maps the key to its value.
+ virtual Result Get(const std::string& key) = 0;
+
+ // Gets multiple values from storage.
+ // If successful, result maps each key to its value.
+ virtual Result Get(const std::vector<std::string>& keys) = 0;
+
+ // Gets all values from storage.
+ // If successful, result maps every key to its value.
+ virtual Result Get() = 0;
+
+ // Sets a single key to a new value.
+ // If successful, result maps the key to the given value.
+ virtual Result Set(const std::string& key, const Value& value) = 0;
+
+ // Sets multiple keys to new values.
+ // If successful, result is identical to the given dictionary.
+ virtual Result Set(const DictionaryValue& values) = 0;
+
+ // Removes a key from the storage.
+ // If successful, result value is NULL.
+ virtual Result Remove(const std::string& key) = 0;
+
+ // Removes multiple keys from the storage.
+ // If successful, result value is NULL.
+ virtual Result Remove(const std::vector<std::string>& keys) = 0;
+
+ // Clears the storage.
+ // If successful, result value is NULL.
+ virtual Result Clear() = 0;
};
#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_SETTINGS_STORAGE_H_
diff --git a/chrome/browser/extensions/extension_settings_storage_cache.cc b/chrome/browser/extensions/extension_settings_storage_cache.cc
index 66ef5c9..2b5cedab 100644
--- a/chrome/browser/extensions/extension_settings_storage_cache.cc
+++ b/chrome/browser/extensions/extension_settings_storage_cache.cc
@@ -4,255 +4,129 @@
#include "chrome/browser/extensions/extension_settings_storage_cache.h"
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop.h"
-#include "base/task.h"
-#include "base/json/json_writer.h"
-
-namespace {
+ExtensionSettingsStorageCache::ExtensionSettingsStorageCache(
+ ExtensionSettingsStorage* delegate) : delegate_(delegate) {}
-void RemoveAllWithoutPathExpansion(
- DictionaryValue* from, const ListValue* keys_to_remove) {
- std::string key;
- for (ListValue::const_iterator it = keys_to_remove->begin();
- it != keys_to_remove->end(); ++it) {
- if ((*it)->GetAsString(&key)) {
- from->RemoveWithoutPathExpansion(key, NULL);
- }
- }
-}
+ExtensionSettingsStorageCache::~ExtensionSettingsStorageCache() {}
-// Callback which delegates to a given callback but caches any result if
-// successful. Takes an optional parameter of existing settings to merge with
-// before returning to the callback (may be NULL) and an optional parameter of
-// keys to remove from the cache post-success (may be NULL).
-class CacheModifyingCallback : public ExtensionSettingsStorage::Callback {
- public:
- // Takes ownership of callback, existing, and keys_to_remove.
- CacheModifyingCallback(
- ExtensionSettingsStorage::Callback* delegate,
- base::WeakPtr<DictionaryValue> cache,
- DictionaryValue* existing,
- ListValue* keys_to_remove)
- : delegate_(delegate),
- cache_(cache),
- existing_(existing),
- keys_to_remove_(keys_to_remove) {
- }
-
- static CacheModifyingCallback* Create(
- ExtensionSettingsStorage::Callback* delegate,
- base::WeakPtr<DictionaryValue> cache_ptr_) {
- return new CacheModifyingCallback(
- delegate,
- cache_ptr_,
- NULL,
- NULL);
+ExtensionSettingsStorage::Result ExtensionSettingsStorageCache::Get(
+ const std::string& key) {
+ Value *value;
+ if (GetFromCache(key, &value)) {
+ DictionaryValue* settings = new DictionaryValue();
+ settings->SetWithoutPathExpansion(key, value);
+ return Result(settings);
}
- static CacheModifyingCallback* Create(
- ExtensionSettingsStorage::Callback* delegate,
- base::WeakPtr<DictionaryValue> cache_ptr_,
- DictionaryValue* existing) {
- return new CacheModifyingCallback(
- delegate,
- cache_ptr_,
- existing,
- NULL);
+ Result result = delegate_->Get(key);
+ if (result.HasError()) {
+ return result;
}
- static CacheModifyingCallback* Create(
- ExtensionSettingsStorage::Callback* delegate,
- base::WeakPtr<DictionaryValue> cache_ptr_,
- ListValue* remove) {
- return new CacheModifyingCallback(
- delegate,
- cache_ptr_,
- NULL,
- remove);
- }
+ cache_.MergeDictionary(result.GetSettings());
+ return result;
+}
- virtual void OnSuccess(DictionaryValue* settings) OVERRIDE {
- // Note checking that the weak reference to the cache is still valid.
- // It might be NULL if the owning ExtensionSettingsStorageCache has been
- // deleted.
- // Also, settings may be NULL for Remove/Clear.
- if (settings != NULL && cache_.get() != NULL) {
- cache_->MergeDictionary(settings);
- }
- if (settings != NULL && existing_ != NULL) {
- settings->MergeDictionary(existing_.get());
+ExtensionSettingsStorage::Result ExtensionSettingsStorageCache::Get(
+ const std::vector<std::string>& keys) {
+ scoped_ptr<DictionaryValue> from_cache(new DictionaryValue());
+ std::vector<std::string> missing_keys;
+
+ for (std::vector<std::string>::const_iterator it = keys.begin();
+ it != keys.end(); ++it) {
+ Value *value;
+ if (GetFromCache(*it, &value)) {
+ from_cache->SetWithoutPathExpansion(*it, value);
+ } else {
+ missing_keys.push_back(*it);
}
- if (cache_.get() != NULL && keys_to_remove_ != NULL) {
- RemoveAllWithoutPathExpansion(cache_, keys_to_remove_.get());
- }
- delegate_->OnSuccess(settings);
}
- virtual void OnFailure(const std::string& message) OVERRIDE {
- delegate_->OnFailure(message);
+ if (missing_keys.empty()) {
+ return Result(from_cache.release());
}
- private:
- scoped_ptr<ExtensionSettingsStorage::Callback> delegate_;
- base::WeakPtr<DictionaryValue> cache_;
- scoped_ptr<DictionaryValue> existing_;
- scoped_ptr<ListValue> keys_to_remove_;
-};
-
-} // namespace
+ Result result = delegate_->Get(keys);
+ if (result.HasError()) {
+ return result;
+ }
-ExtensionSettingsStorageCache::ExtensionSettingsStorageCache(
- ExtensionSettingsStorage* delegate)
- : delegate_(delegate), cache_ptr_factory_(&cache_) {
+ cache_.MergeDictionary(result.GetSettings());
+ result.GetSettings()->MergeDictionary(from_cache.get());
+ return result;
}
-ExtensionSettingsStorageCache::~ExtensionSettingsStorageCache() {
-}
+ExtensionSettingsStorage::Result ExtensionSettingsStorageCache::Get() {
+ Result result = delegate_->Get();
+ if (result.HasError()) {
+ return result;
+ }
-void ExtensionSettingsStorageCache::DeleteSoon() {
- delegate_->DeleteSoon();
- delete this;
+ cache_.MergeDictionary(result.GetSettings());
+ // Hack so that the cached settings are used when the delegate is a no-op
+ // storage, in which case Get() will always return empty settings.
+ if (result.GetSettings()->empty()) {
+ return Result(cache_.DeepCopy());
+ }
+
+ return result;
}
-void ExtensionSettingsStorageCache::Get(const std::string& key,
- ExtensionSettingsStorageCache::Callback* callback) {
- Value *value;
- if (GetFromCache(key, &value)) {
- DictionaryValue* settings = new DictionaryValue();
- settings->SetWithoutPathExpansion(key, value);
- MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(
- &ExtensionSettingsStorageCache::Callback::OnSuccess,
- base::Unretained(callback),
- settings));
- } else {
- delegate_->Get(
- key,
- CacheModifyingCallback::Create(
- callback,
- cache_ptr_factory_.GetWeakPtr()));
+ExtensionSettingsStorage::Result ExtensionSettingsStorageCache::Set(
+ const std::string& key, const Value& value) {
+ Result result = delegate_->Set(key, value);
+ if (result.HasError()) {
+ return result;
}
-}
-void ExtensionSettingsStorageCache::Get(const ListValue& keys,
- ExtensionSettingsStorageCache::Callback* callback) {
- std::string key;
- DictionaryValue* settings = new DictionaryValue();
- ListValue missing_keys;
+ cache_.MergeDictionary(result.GetSettings());
+ return result;
+}
- for (ListValue::const_iterator it = keys.begin(); it != keys.end(); ++it) {
- if ((*it)->GetAsString(&key)) {
- Value *value;
- if (GetFromCache(key, &value)) {
- settings->SetWithoutPathExpansion(key, value);
- } else {
- missing_keys.Append(Value::CreateStringValue(key));
- }
- }
+ExtensionSettingsStorage::Result ExtensionSettingsStorageCache::Set(
+ const DictionaryValue& settings) {
+ Result result = delegate_->Set(settings);
+ if (result.HasError()) {
+ return result;
}
- if (missing_keys.empty()) {
- MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(
- &ExtensionSettingsStorageCache::Callback::OnSuccess,
- base::Unretained(callback),
- settings));
- } else {
- delegate_->Get(
- missing_keys,
- CacheModifyingCallback::Create(
- callback,
- cache_ptr_factory_.GetWeakPtr(),
- settings));
- }
+ cache_.MergeDictionary(result.GetSettings());
+ return result;
}
-void ExtensionSettingsStorageCache::Get(
- ExtensionSettingsStorageCache::Callback* callback) {
- // Copy the cache when passing in, as a semi-hack so that caching a no-op
- // storage object works (which always returns empty from Get()).
- delegate_->Get(
- CacheModifyingCallback::Create(
- callback,
- cache_ptr_factory_.GetWeakPtr(),
- cache_.DeepCopy()));
-}
+ExtensionSettingsStorage::Result ExtensionSettingsStorageCache::Remove(
+ const std::string& key) {
+ Result result = delegate_->Remove(key);
+ if (result.HasError()) {
+ return result;
+ }
-void ExtensionSettingsStorageCache::Set(
- const std::string& key,
- const Value& value,
- ExtensionSettingsStorageCache::Callback* callback) {
- // Invalidate the cached entry first, in case the set fails.
cache_.RemoveWithoutPathExpansion(key, NULL);
- delegate_->Set(
- key,
- value,
- CacheModifyingCallback::Create(
- callback,
- cache_ptr_factory_.GetWeakPtr()));
+ return result;
}
-void ExtensionSettingsStorageCache::Set(
- const DictionaryValue& values,
- ExtensionSettingsStorageCache::Callback* callback) {
- // Invalidate the cached entries first, in case the set fails.
- for (DictionaryValue::key_iterator it = values.begin_keys();
- it != values.end_keys(); ++it) {
- cache_.RemoveWithoutPathExpansion(*it, NULL);
+ExtensionSettingsStorage::Result ExtensionSettingsStorageCache::Remove(
+ const std::vector<std::string>& keys) {
+ Result result = delegate_->Remove(keys);
+ if (result.HasError()) {
+ return result;
}
- delegate_->Set(
- values,
- CacheModifyingCallback::Create(
- callback,
- cache_ptr_factory_.GetWeakPtr()));
-}
-void ExtensionSettingsStorageCache::Remove(
- const std::string& key,
- ExtensionSettingsStorageCache::Callback *callback) {
- // Invalidate the cached entry first, in case the remove fails.
- // We will also need to do if after the callback, to avoid race conditions
- // whether other API calls fill the cache on the UI thread.
- // This would be a good time to use structured cloning...
- cache_.RemoveWithoutPathExpansion(key, NULL);
- ListValue* key_list = new ListValue();
- key_list->Append(Value::CreateStringValue(key));
- delegate_->Remove(
- key,
- CacheModifyingCallback::Create(
- callback,
- cache_ptr_factory_.GetWeakPtr(),
- key_list));
+ for (std::vector<std::string>::const_iterator it = keys.begin();
+ it != keys.end(); ++it) {
+ cache_.RemoveWithoutPathExpansion(*it, NULL);
+ }
+ return result;
}
-void ExtensionSettingsStorageCache::Remove(
- const ListValue& keys,
- ExtensionSettingsStorageCache::Callback *callback) {
- std::string key;
- // Invalidate each cached entry first, in case the remove fails.
- // We will also need to do if after the callback, to avoid race conditions
- // whether other API calls fill the cache on the UI thread.
- RemoveAllWithoutPathExpansion(&cache_, &keys);
- delegate_->Remove(
- keys,
- CacheModifyingCallback::Create(
- callback,
- cache_ptr_factory_.GetWeakPtr(),
- keys.DeepCopy()));
-}
+ExtensionSettingsStorage::Result ExtensionSettingsStorageCache::Clear() {
+ Result result = delegate_->Clear();
+ if (result.HasError()) {
+ return result;
+ }
-void ExtensionSettingsStorageCache::Clear(
- ExtensionSettingsStorageCache::Callback* callback) {
cache_.Clear();
- delegate_->Clear(
- CacheModifyingCallback::Create(
- callback,
- cache_ptr_factory_.GetWeakPtr()));
+ return result;
}
bool ExtensionSettingsStorageCache::GetFromCache(
@@ -261,6 +135,7 @@ bool ExtensionSettingsStorageCache::GetFromCache(
if (!cache_.GetWithoutPathExpansion(key, &cached_value)) {
return false;
}
+
*value = cached_value->DeepCopy();
return true;
}
diff --git a/chrome/browser/extensions/extension_settings_storage_cache.h b/chrome/browser/extensions/extension_settings_storage_cache.h
index 460f44c..3e4e5d1 100644
--- a/chrome/browser/extensions/extension_settings_storage_cache.h
+++ b/chrome/browser/extensions/extension_settings_storage_cache.h
@@ -7,6 +7,7 @@
#pragma once
#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/extensions/extension_settings_storage.h"
@@ -15,38 +16,34 @@
//
// Calls to Get() will return from the cache if an entry is present, or be
// passed to the delegate and the result cached if not.
-//
// Calls to Set() / Clear() / Remove() are written through to the delegate,
// then stored in the cache if successful.
class ExtensionSettingsStorageCache : public ExtensionSettingsStorage {
public:
- // Creates a cache around a delegate. Ownership of the delegate is taken.
+ // Ownership of delegate taken.
explicit ExtensionSettingsStorageCache(ExtensionSettingsStorage* delegate);
+ virtual ~ExtensionSettingsStorageCache();
- virtual void DeleteSoon() OVERRIDE;
-
- virtual void Get(const std::string& key, Callback* callback) OVERRIDE;
- virtual void Get(const ListValue& keys, Callback* callback) OVERRIDE;
- virtual void Get(Callback* callback) OVERRIDE;
- virtual void Set(
- const std::string& key, const Value& value, Callback* callback) OVERRIDE;
- virtual void Set(const DictionaryValue& values, Callback* callback) OVERRIDE;
- virtual void Remove(const std::string& key, Callback* callback) OVERRIDE;
- virtual void Remove(const ListValue& keys, Callback* callback) OVERRIDE;
- virtual void Clear(Callback *callback) OVERRIDE;
+ // ExtensionSettingsStorage implementation.
+ virtual Result Get(const std::string& key) OVERRIDE;
+ virtual Result Get(const std::vector<std::string>& keys) OVERRIDE;
+ virtual Result Get() OVERRIDE;
+ virtual Result Set(const std::string& key, const Value& value) OVERRIDE;
+ virtual Result Set(const DictionaryValue& settings) OVERRIDE;
+ virtual Result Remove(const std::string& key) OVERRIDE;
+ virtual Result Remove(const std::vector<std::string>& keys) OVERRIDE;
+ virtual Result Clear() OVERRIDE;
private:
- // Delete with DeleteSoon().
- virtual ~ExtensionSettingsStorageCache();
-
// Returns whether the value was found in the cache.
// Ownership of value is released to the caller and placed in value.
bool GetFromCache(const std::string& key, Value** value);
- // Deleted in DeleteSoon().
- ExtensionSettingsStorage* delegate_;
+ // Storage that the cache is wrapping.
+ scoped_ptr<ExtensionSettingsStorage> delegate_;
+
+ // The in-memory cache of settings from the delegate.
DictionaryValue cache_;
- base::WeakPtrFactory<DictionaryValue> cache_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ExtensionSettingsStorageCache);
};
diff --git a/chrome/browser/extensions/extension_settings_storage_unittest.cc b/chrome/browser/extensions/extension_settings_storage_unittest.cc
index ccbbf16..5b51f3f 100644
--- a/chrome/browser/extensions/extension_settings_storage_unittest.cc
+++ b/chrome/browser/extensions/extension_settings_storage_unittest.cc
@@ -13,116 +13,79 @@
#include "chrome/browser/extensions/extension_settings.h"
#include "content/browser/browser_thread.h"
-// Define macro to get the __LINE__ expansion.
-#define NEW_CALLBACK(expected) \
- (new AssertEqualsCallback((expected), __LINE__))
-
-namespace {
+// Gets the pretty-printed JSON for a value.
+static std::string GetJSON(const Value& value) {
+ std::string json;
+ base::JSONWriter::Write(&value, true, &json);
+ return json;
+}
-// Callback from storage methods which performs the test assertions.
-class AssertEqualsCallback : public ExtensionSettingsStorage::Callback {
- public:
- AssertEqualsCallback(DictionaryValue* expected, int line)
- : expected_(expected), line_(line), called_(false) {
+// Returns whether the result of a storage operation is an expected value.
+testing::AssertionResult SettingsEq(
+ const char* expected_expr, const char* actual_expr,
+ DictionaryValue* expected, ExtensionSettingsStorage::Result actual) {
+ if (actual.HasError()) {
+ return testing::AssertionFailure() <<
+ "Expected: " << GetJSON(*expected) <<
+ ", actual has error: " << actual.GetError();
}
-
- ~AssertEqualsCallback() {
- // Need to DCHECK since ASSERT_* can't be used from destructors.
- DCHECK(called_);
+ if (expected == actual.GetSettings()) {
+ return testing::AssertionSuccess();
}
-
- virtual void OnSuccess(DictionaryValue* actual) OVERRIDE {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- ASSERT_FALSE(called_) << "Callback has already been called";
- called_ = true;
- if (expected_ == NULL) {
- ASSERT_TRUE(actual == NULL) << "Values are different:\n" <<
- "Line: " << line_ << "\n" <<
- "Expected: NULL\n" <<
- "Got: " << GetJson(actual);
- } else {
- ASSERT_TRUE(expected_->Equals(actual)) << "Values are different:\n" <<
- "Line: " << line_ << "\n" <<
- "Expected: " << GetJson(expected_) <<
- "Got: " << GetJson(actual);
- delete actual;
- }
+ if (expected == NULL && actual.GetSettings() != NULL) {
+ return testing::AssertionFailure() <<
+ "Expected NULL, actual: " << GetJSON(*actual.GetSettings());
}
-
- virtual void OnFailure(const std::string& message) OVERRIDE {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- ASSERT_FALSE(called_) << "Callback has already been called";
- called_ = true;
- // No tests allow failure (yet).
- ASSERT_TRUE(false) << "Callback failed on line " << line_;
+ if (expected != NULL && actual.GetSettings() == NULL) {
+ return testing::AssertionFailure() <<
+ "Expected: " << GetJSON(*expected) << ", actual NULL";
}
-
- private:
- std::string GetJson(Value* value) {
- std::string json;
- base::JSONWriter::Write(value, true, &json);
- return json;
+ if (!expected->Equals(actual.GetSettings())) {
+ return testing::AssertionFailure() <<
+ "Expected: " << GetJSON(*expected) <<
+ ", actual: " << GetJSON(*actual.GetSettings());
}
-
- DictionaryValue* expected_;
- int line_;
- bool called_;
-};
-
-} // namespace
+ return testing::AssertionSuccess();
+}
ExtensionSettingsStorageTest::ExtensionSettingsStorageTest()
- : key1_("foo"), key2_("bar"), key3_("baz") {
+ : key1_("foo"),
+ key2_("bar"),
+ key3_("baz"),
+ empty_dict_(new DictionaryValue),
+ dict1_(new DictionaryValue),
+ dict12_(new DictionaryValue),
+ dict123_(new DictionaryValue) {
val1_.reset(Value::CreateStringValue(key1_ + "Value"));
val2_.reset(Value::CreateStringValue(key2_ + "Value"));
val3_.reset(Value::CreateStringValue(key3_ + "Value"));
- emptyList_.reset(new ListValue());
+ list1_.push_back(key1_);
+ list2_.push_back(key2_);
+ list12_.push_back(key1_);
+ list12_.push_back(key2_);
+ list13_.push_back(key1_);
+ list13_.push_back(key3_);
+ list123_.push_back(key1_);
+ list123_.push_back(key2_);
+ list123_.push_back(key3_);
- list1_.reset(new ListValue());
- list1_->Append(Value::CreateStringValue(key1_));
-
- list2_.reset(new ListValue());
- list2_->Append(Value::CreateStringValue(key2_));
-
- list12_.reset(new ListValue());
- list12_->Append(Value::CreateStringValue(key1_));
- list12_->Append(Value::CreateStringValue(key2_));
-
- list13_.reset(new ListValue());
- list13_->Append(Value::CreateStringValue(key1_));
- list13_->Append(Value::CreateStringValue(key3_));
-
- list123_.reset(new ListValue());
- list123_->Append(Value::CreateStringValue(key1_));
- list123_->Append(Value::CreateStringValue(key2_));
- list123_->Append(Value::CreateStringValue(key3_));
-
- emptyDict_.reset(new DictionaryValue());
-
- dict1_.reset(new DictionaryValue());
dict1_->Set(key1_, val1_->DeepCopy());
-
- dict12_.reset(new DictionaryValue());
dict12_->Set(key1_, val1_->DeepCopy());
dict12_->Set(key2_, val2_->DeepCopy());
-
- dict123_.reset(new DictionaryValue());
dict123_->Set(key1_, val1_->DeepCopy());
dict123_->Set(key2_, val2_->DeepCopy());
dict123_->Set(key3_, val3_->DeepCopy());
}
-ExtensionSettingsStorageTest::~ExtensionSettingsStorageTest() {
-}
+ExtensionSettingsStorageTest::~ExtensionSettingsStorageTest() {}
void ExtensionSettingsStorageTest::SetUp() {
- ui_message_loop_ = new MessageLoopForUI();
- // Use the same message loop for the UI and FILE threads, giving a test
- // pattern where storage API calls get posted to the same message loop (the
- // current one), then all run with MessageLoop::current()->RunAllPending().
- ui_thread_ = new BrowserThread(BrowserThread::UI, MessageLoop::current());
- file_thread_ = new BrowserThread(BrowserThread::FILE, MessageLoop::current());
+ ui_message_loop_.reset(new MessageLoopForUI());
+ ui_thread_.reset(
+ new BrowserThread(BrowserThread::UI, MessageLoop::current()));
+ file_thread_.reset(
+ new BrowserThread(BrowserThread::FILE, MessageLoop::current()));
FilePath temp_dir;
file_util::CreateNewTempDirectory(FilePath::StringType(), &temp_dir);
@@ -139,153 +102,124 @@ void ExtensionSettingsStorageTest::SetUp() {
DCHECK(storage_ != NULL);
}
-void ExtensionSettingsStorageTest::TearDown() {
- settings_ = NULL;
- delete file_thread_;
- delete ui_thread_;
- delete ui_message_loop_;
-}
-
void ExtensionSettingsStorageTest::SetStorage(
ExtensionSettingsStorage* storage) {
storage_ = storage;
}
TEST_P(ExtensionSettingsStorageTest, GetWhenEmpty) {
- storage_->Get(key1_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(key2_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(key3_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(*emptyList_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(*list1_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(*list123_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(NEW_CALLBACK(emptyDict_.get()));
- MessageLoop::current()->RunAllPending();
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(key1_));
+ ASSERT_PRED_FORMAT2(SettingsEq,
+ empty_dict_.get(), storage_->Get(empty_list_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(list123_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get());
}
TEST_P(ExtensionSettingsStorageTest, GetWithSingleValue) {
- storage_->Set(key1_, *val1_, NEW_CALLBACK(dict1_.get()));
- MessageLoop::current()->RunAllPending();
-
- storage_->Get(key1_, NEW_CALLBACK(dict1_.get()));
- storage_->Get(key2_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(key3_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(*emptyList_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(*list1_, NEW_CALLBACK(dict1_.get()));
- storage_->Get(*list2_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(*list123_, NEW_CALLBACK(dict1_.get()));
- storage_->Get(NEW_CALLBACK(dict1_.get()));
- MessageLoop::current()->RunAllPending();
+ ASSERT_PRED_FORMAT2(SettingsEq, dict1_.get(), storage_->Set(key1_, *val1_));
+
+ ASSERT_PRED_FORMAT2(SettingsEq, dict1_.get(), storage_->Get(key1_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(key2_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(key3_));
+ ASSERT_PRED_FORMAT2(SettingsEq,
+ empty_dict_.get(), storage_->Get(empty_list_));
+ ASSERT_PRED_FORMAT2(SettingsEq, dict1_.get(), storage_->Get(list123_));
+ ASSERT_PRED_FORMAT2(SettingsEq, dict1_.get(), storage_->Get());
}
TEST_P(ExtensionSettingsStorageTest, GetWithMultipleValues) {
- storage_->Set(*dict12_, NEW_CALLBACK(dict12_.get()));
- MessageLoop::current()->RunAllPending();
-
- storage_->Get(key1_, NEW_CALLBACK(dict1_.get()));
- storage_->Get(key3_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(*emptyList_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(*list1_, NEW_CALLBACK(dict1_.get()));
- storage_->Get(*list13_, NEW_CALLBACK(dict1_.get()));
- storage_->Get(*list12_, NEW_CALLBACK(dict12_.get()));
- storage_->Get(*list123_, NEW_CALLBACK(dict12_.get()));
- storage_->Get(NEW_CALLBACK(dict12_.get()));
- MessageLoop::current()->RunAllPending();
+ ASSERT_PRED_FORMAT2(SettingsEq, dict12_.get(), storage_->Set(*dict12_));
+
+ ASSERT_PRED_FORMAT2(SettingsEq, dict1_.get(), storage_->Get(key1_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(key3_));
+ ASSERT_PRED_FORMAT2(SettingsEq,
+ empty_dict_.get(), storage_->Get(empty_list_));
+ ASSERT_PRED_FORMAT2(SettingsEq, dict12_.get(), storage_->Get(list123_));
+ ASSERT_PRED_FORMAT2(SettingsEq, dict12_.get(), storage_->Get());
}
TEST_P(ExtensionSettingsStorageTest, RemoveWhenEmpty) {
- storage_->Remove(key1_, NEW_CALLBACK(NULL));
- MessageLoop::current()->RunAllPending();
+ ASSERT_PRED_FORMAT2(SettingsEq, NULL, storage_->Remove(key1_));
- storage_->Get(key1_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(*list1_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(NEW_CALLBACK(emptyDict_.get()));
- MessageLoop::current()->RunAllPending();
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(key1_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(list1_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get());
}
TEST_P(ExtensionSettingsStorageTest, RemoveWithSingleValue) {
- storage_->Set(key1_, *val1_, NEW_CALLBACK(dict1_.get()));
- MessageLoop::current()->RunAllPending();
- storage_->Remove(key1_, NEW_CALLBACK(NULL));
- MessageLoop::current()->RunAllPending();
-
- storage_->Get(key1_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(key2_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(*list1_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(*list12_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(NEW_CALLBACK(emptyDict_.get()));
- MessageLoop::current()->RunAllPending();
+ ASSERT_PRED_FORMAT2(SettingsEq, dict1_.get(), storage_->Set(*dict1_));
+ ASSERT_PRED_FORMAT2(SettingsEq, NULL, storage_->Remove(key1_));
+
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(key1_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(key2_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(list1_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(list12_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get());
}
TEST_P(ExtensionSettingsStorageTest, RemoveWithMultipleValues) {
- storage_->Set(*dict123_, NEW_CALLBACK(dict123_.get()));
- MessageLoop::current()->RunAllPending();
- storage_->Remove(key3_, NEW_CALLBACK(NULL));
- MessageLoop::current()->RunAllPending();
-
- storage_->Get(key1_, NEW_CALLBACK(dict1_.get()));
- storage_->Get(key3_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(*emptyList_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(*list1_, NEW_CALLBACK(dict1_.get()));
- storage_->Get(*list13_, NEW_CALLBACK(dict1_.get()));
- storage_->Get(*list12_, NEW_CALLBACK(dict12_.get()));
- storage_->Get(*list123_, NEW_CALLBACK(dict12_.get()));
- storage_->Get(NEW_CALLBACK(dict12_.get()));
-
- storage_->Remove(*list2_, NEW_CALLBACK(NULL));
- MessageLoop::current()->RunAllPending();
-
- storage_->Get(key1_, NEW_CALLBACK(dict1_.get()));
- storage_->Get(key2_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(key3_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(*emptyList_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(*list1_, NEW_CALLBACK(dict1_.get()));
- storage_->Get(*list2_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(*list123_, NEW_CALLBACK(dict1_.get()));
- storage_->Get(NEW_CALLBACK(dict1_.get()));
- MessageLoop::current()->RunAllPending();
+ ASSERT_PRED_FORMAT2(SettingsEq, dict123_.get(), storage_->Set(*dict123_));
+ ASSERT_PRED_FORMAT2(SettingsEq, NULL, storage_->Remove(key3_));
+
+ ASSERT_PRED_FORMAT2(SettingsEq, dict1_.get(), storage_->Get(key1_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(key3_));
+ ASSERT_PRED_FORMAT2(SettingsEq,
+ empty_dict_.get(), storage_->Get(empty_list_));
+ ASSERT_PRED_FORMAT2(SettingsEq, dict1_.get(), storage_->Get(list1_));
+ ASSERT_PRED_FORMAT2(SettingsEq, dict12_.get(), storage_->Get(list12_));
+ ASSERT_PRED_FORMAT2(SettingsEq, dict1_.get(), storage_->Get(list13_));
+ ASSERT_PRED_FORMAT2(SettingsEq, dict12_.get(), storage_->Get(list123_));
+ ASSERT_PRED_FORMAT2(SettingsEq, dict12_.get(), storage_->Get());
+
+ ASSERT_PRED_FORMAT2(SettingsEq, NULL, storage_->Remove(list12_));
+
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(key1_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(key3_));
+ ASSERT_PRED_FORMAT2(SettingsEq,
+ empty_dict_.get(), storage_->Get(empty_list_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(list1_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(list12_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(list13_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(list123_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get());
}
TEST_P(ExtensionSettingsStorageTest, SetWhenOverwriting) {
- DictionaryValue key1Val2;
- key1Val2.Set(key1_, val2_->DeepCopy());
- storage_->Set(key1_, *val2_, NEW_CALLBACK(&key1Val2));
- MessageLoop::current()->RunAllPending();
-
- storage_->Set(*dict12_, NEW_CALLBACK(dict12_.get()));
- MessageLoop::current()->RunAllPending();
-
- storage_->Get(key1_, NEW_CALLBACK(dict1_.get()));
- storage_->Get(key3_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(*emptyList_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(*list1_, NEW_CALLBACK(dict1_.get()));
- storage_->Get(*list13_, NEW_CALLBACK(dict1_.get()));
- storage_->Get(*list12_, NEW_CALLBACK(dict12_.get()));
- storage_->Get(*list123_, NEW_CALLBACK(dict12_.get()));
- storage_->Get(NEW_CALLBACK(dict12_.get()));
- MessageLoop::current()->RunAllPending();
+ DictionaryValue key1_val2;
+ key1_val2.Set(key1_, val2_->DeepCopy());
+ ASSERT_PRED_FORMAT2(SettingsEq, &key1_val2, storage_->Set(key1_, *val2_));
+ ASSERT_PRED_FORMAT2(SettingsEq, dict12_.get(), storage_->Set(*dict12_));
+
+ ASSERT_PRED_FORMAT2(SettingsEq, dict1_.get(), storage_->Get(key1_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(key3_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(),
+ storage_->Get(empty_list_));
+ ASSERT_PRED_FORMAT2(SettingsEq, dict1_.get(), storage_->Get(list1_));
+ ASSERT_PRED_FORMAT2(SettingsEq, dict12_.get(), storage_->Get(list12_));
+ ASSERT_PRED_FORMAT2(SettingsEq, dict1_.get(), storage_->Get(list13_));
+ ASSERT_PRED_FORMAT2(SettingsEq, dict12_.get(), storage_->Get(list123_));
+ ASSERT_PRED_FORMAT2(SettingsEq, dict12_.get(), storage_->Get());
}
TEST_P(ExtensionSettingsStorageTest, ClearWhenEmpty) {
- storage_->Clear(NEW_CALLBACK(NULL));
- MessageLoop::current()->RunAllPending();
+ ASSERT_PRED_FORMAT2(SettingsEq, NULL, storage_->Clear());
- storage_->Get(key1_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(*list1_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(NEW_CALLBACK(emptyDict_.get()));
- MessageLoop::current()->RunAllPending();
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(key1_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(),
+ storage_->Get(empty_list_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(list123_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get());
}
TEST_P(ExtensionSettingsStorageTest, ClearWhenNotEmpty) {
- storage_->Set(*dict12_, NEW_CALLBACK(dict12_.get()));
- MessageLoop::current()->RunAllPending();
-
- storage_->Clear(NEW_CALLBACK(NULL));
- MessageLoop::current()->RunAllPending();
-
- storage_->Get(key1_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(*list1_, NEW_CALLBACK(emptyDict_.get()));
- storage_->Get(NEW_CALLBACK(emptyDict_.get()));
- MessageLoop::current()->RunAllPending();
+ ASSERT_PRED_FORMAT2(SettingsEq, dict12_.get(), storage_->Set(*dict12_));
+ ASSERT_PRED_FORMAT2(SettingsEq, NULL, storage_->Clear());
+
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(key1_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(),
+ storage_->Get(empty_list_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(list123_));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get());
}
// Dots should be allowed in key names; they shouldn't be interpreted as
@@ -293,31 +227,24 @@ TEST_P(ExtensionSettingsStorageTest, ClearWhenNotEmpty) {
TEST_P(ExtensionSettingsStorageTest, DotsInKeyNames) {
std::string dot_key("foo.bar");
StringValue dot_value("baz.qux");
- ListValue dot_list;
- dot_list.Append(Value::CreateStringValue(dot_key));
+ std::vector<std::string> dot_list;
+ dot_list.push_back(dot_key);
DictionaryValue dot_dict;
dot_dict.SetWithoutPathExpansion(dot_key, dot_value.DeepCopy());
- storage_->Set(dot_key, dot_value, NEW_CALLBACK(&dot_dict));
- MessageLoop::current()->RunAllPending();
-
- storage_->Get(dot_key, NEW_CALLBACK(&dot_dict));
- MessageLoop::current()->RunAllPending();
-
- storage_->Remove(dot_key, NEW_CALLBACK(NULL));
- MessageLoop::current()->RunAllPending();
-
- storage_->Set(dot_dict, NEW_CALLBACK(&dot_dict));
- MessageLoop::current()->RunAllPending();
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(dot_key));
- storage_->Get(dot_list, NEW_CALLBACK(&dot_dict));
- MessageLoop::current()->RunAllPending();
+ ASSERT_PRED_FORMAT2(SettingsEq, &dot_dict, storage_->Set(dot_key, dot_value));
+ ASSERT_PRED_FORMAT2(SettingsEq, &dot_dict, storage_->Get(dot_key));
- storage_->Remove(dot_list, NEW_CALLBACK(NULL));
- MessageLoop::current()->RunAllPending();
+ ASSERT_PRED_FORMAT2(SettingsEq, NULL, storage_->Remove(dot_key));
+ ASSERT_PRED_FORMAT2(SettingsEq, &dot_dict, storage_->Set(dot_dict));
+ ASSERT_PRED_FORMAT2(SettingsEq, &dot_dict, storage_->Get(dot_list));
+ ASSERT_PRED_FORMAT2(SettingsEq, &dot_dict, storage_->Get());
- storage_->Get(NEW_CALLBACK(emptyDict_.get()));
- MessageLoop::current()->RunAllPending();
+ ASSERT_PRED_FORMAT2(SettingsEq, NULL, storage_->Remove(dot_list));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get(dot_key));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get());
}
TEST_P(ExtensionSettingsStorageTest, DotsInKeyNamesWithDicts) {
@@ -326,12 +253,7 @@ TEST_P(ExtensionSettingsStorageTest, DotsInKeyNamesWithDicts) {
outer_dict.Set("foo", inner_dict);
inner_dict->Set("bar", Value::CreateStringValue("baz"));
- storage_->Set(outer_dict, NEW_CALLBACK(&outer_dict));
- MessageLoop::current()->RunAllPending();
-
- storage_->Get("foo", NEW_CALLBACK(&outer_dict));
- MessageLoop::current()->RunAllPending();
-
- storage_->Get("foo.bar", NEW_CALLBACK(emptyDict_.get()));
- MessageLoop::current()->RunAllPending();
+ ASSERT_PRED_FORMAT2(SettingsEq, &outer_dict, storage_->Set(outer_dict));
+ ASSERT_PRED_FORMAT2(SettingsEq, &outer_dict, storage_->Get("foo"));
+ ASSERT_PRED_FORMAT2(SettingsEq, empty_dict_.get(), storage_->Get("foo.bar"));
}
diff --git a/chrome/browser/extensions/extension_settings_storage_unittest.h b/chrome/browser/extensions/extension_settings_storage_unittest.h
index 4fac5af..e13c80a 100644
--- a/chrome/browser/extensions/extension_settings_storage_unittest.h
+++ b/chrome/browser/extensions/extension_settings_storage_unittest.h
@@ -31,7 +31,6 @@ class ExtensionSettingsStorageTest
virtual ~ExtensionSettingsStorageTest();
virtual void SetUp() OVERRIDE;
- virtual void TearDown() OVERRIDE;
protected:
ExtensionSettingsStorage* storage_;
@@ -39,16 +38,19 @@ class ExtensionSettingsStorageTest
std::string key1_;
std::string key2_;
std::string key3_;
+
scoped_ptr<Value> val1_;
scoped_ptr<Value> val2_;
scoped_ptr<Value> val3_;
- scoped_ptr<ListValue> emptyList_;
- scoped_ptr<ListValue> list1_;
- scoped_ptr<ListValue> list2_;
- scoped_ptr<ListValue> list12_;
- scoped_ptr<ListValue> list13_;
- scoped_ptr<ListValue> list123_;
- scoped_ptr<DictionaryValue> emptyDict_;
+
+ std::vector<std::string> empty_list_;
+ std::vector<std::string> list1_;
+ std::vector<std::string> list2_;
+ std::vector<std::string> list12_;
+ std::vector<std::string> list13_;
+ std::vector<std::string> list123_;
+
+ scoped_ptr<DictionaryValue> empty_dict_;
scoped_ptr<DictionaryValue> dict1_;
scoped_ptr<DictionaryValue> dict12_;
scoped_ptr<DictionaryValue> dict123_;
@@ -57,9 +59,9 @@ class ExtensionSettingsStorageTest
void SetStorage(ExtensionSettingsStorage* storage);
scoped_refptr<ExtensionSettings> settings_;
- MessageLoopForUI* ui_message_loop_;
- BrowserThread* ui_thread_;
- BrowserThread* file_thread_;
+ scoped_ptr<MessageLoopForUI> ui_message_loop_;
+ scoped_ptr<BrowserThread> ui_thread_;
+ scoped_ptr<BrowserThread> file_thread_;
};
#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_SETTINGS_STORAGE_UNITTEST_H_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 2f0454f..1bd0b95 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1073,6 +1073,7 @@
'browser/extensions/extension_settings_api.h',
'browser/extensions/extension_settings_noop_storage.cc',
'browser/extensions/extension_settings_noop_storage.h',
+ 'browser/extensions/extension_settings_storage.cc',
'browser/extensions/extension_settings_storage.h',
'browser/extensions/extension_settings_storage_cache.cc',
'browser/extensions/extension_settings_storage_cache.h',