| Index: content/browser/leveldb_wrapper_impl.cc
|
| diff --git a/content/browser/leveldb_wrapper_impl.cc b/content/browser/leveldb_wrapper_impl.cc
|
| index ed58624dfd412ec64593382036509dfb431a15d0..0d3938915f87adfc8878088f1c3e85ad37f1730b 100644
|
| --- a/content/browser/leveldb_wrapper_impl.cc
|
| +++ b/content/browser/leveldb_wrapper_impl.cc
|
| @@ -5,16 +5,20 @@
|
| #include "content/browser/leveldb_wrapper_impl.h"
|
|
|
| #include "base/bind.h"
|
| +#include "mojo/common/common_type_converters.h"
|
|
|
| namespace content {
|
|
|
| LevelDBWrapperImpl::LevelDBWrapperImpl(
|
| leveldb::LevelDBDatabase* database,
|
| const std::string& prefix,
|
| + size_t max_size,
|
| const base::Closure& no_bindings_callback)
|
| : prefix_(prefix),
|
| no_bindings_callback_(no_bindings_callback),
|
| - database_(database) {
|
| + database_(database),
|
| + bytes_used_(0),
|
| + max_size_(max_size) {
|
| bindings_.set_connection_error_handler(base::Bind(
|
| &LevelDBWrapperImpl::OnConnectionError, base::Unretained(this)));
|
| }
|
| @@ -23,43 +27,110 @@ void LevelDBWrapperImpl::Bind(mojom::LevelDBWrapperRequest request) {
|
| bindings_.AddBinding(this, std::move(request));
|
| }
|
|
|
| +void LevelDBWrapperImpl::AddObserver(mojom::LevelDBObserverPtr observer) {
|
| + observers_.AddInterfacePtr(std::move(observer));
|
| +}
|
| +
|
| LevelDBWrapperImpl::~LevelDBWrapperImpl() {}
|
|
|
| void LevelDBWrapperImpl::Put(mojo::Array<uint8_t> key,
|
| mojo::Array<uint8_t> value,
|
| const mojo::String& source,
|
| const PutCallback& callback) {
|
| - NOTIMPLEMENTED();
|
| - callback.Run(leveldb::DatabaseError::NOT_SUPPORTED);
|
| + bool has_old_item = false;
|
| + mojo::Array<uint8_t> old_value;
|
| + size_t old_item_size = 0;
|
| + auto found = map_.find(key);
|
| + if (found != map_.end()) {
|
| + old_value = std::move(found->second);
|
| + old_item_size = key.size() + old_value.size();
|
| + has_old_item = true;
|
| + }
|
| + size_t new_item_size = key.size() + value.size();
|
| + size_t new_bytes_used = bytes_used_ - old_item_size + new_item_size;
|
| +
|
| + // Only check quota if the size is increasing, this allows
|
| + // shrinking changes to pre-existing maps that are over budget.
|
| + if (new_item_size > old_item_size && new_bytes_used > max_size_) {
|
| + callback.Run(false);
|
| + return;
|
| + }
|
| +
|
| + map_[key.Clone()] = value.Clone();
|
| + bytes_used_ = new_bytes_used;
|
| + if (!has_old_item) {
|
| + // We added a new key/value pair.
|
| + observers_.ForAllPtrs(
|
| + [&key, &value, &source](mojom::LevelDBObserver* observer) {
|
| + observer->KeyAdded(key.Clone(), value.Clone(), source);
|
| + });
|
| + } else {
|
| + // We changed the value for an existing key.
|
| + observers_.ForAllPtrs(
|
| + [&key, &value, &source, &old_value](mojom::LevelDBObserver* observer) {
|
| + observer->KeyChanged(
|
| + key.Clone(), value.Clone(), old_value.Clone(), source);
|
| + });
|
| + }
|
| + callback.Run(true);
|
| }
|
|
|
| void LevelDBWrapperImpl::Delete(mojo::Array<uint8_t> key,
|
| const mojo::String& source,
|
| const DeleteCallback& callback) {
|
| - NOTIMPLEMENTED();
|
| - callback.Run(leveldb::DatabaseError::NOT_SUPPORTED);
|
| + auto found = map_.find(key);
|
| + if (found == map_.end()) {
|
| + callback.Run(true);
|
| + return;
|
| + }
|
| +
|
| + mojo::Array<uint8_t> old_value = std::move(found->second);
|
| + map_.erase(found);
|
| + bytes_used_ -= key.size() + old_value.size();
|
| + observers_.ForAllPtrs(
|
| + [&key, &source, &old_value](mojom::LevelDBObserver* observer) {
|
| + observer->KeyDeleted(
|
| + key.Clone(), old_value.Clone(), source);
|
| + });
|
| + callback.Run(true);
|
| }
|
|
|
| -void LevelDBWrapperImpl::DeleteAll(mojom::LevelDBObserverPtr observer,
|
| - const mojo::String& source,
|
| +void LevelDBWrapperImpl::DeleteAll(const mojo::String& source,
|
| const DeleteAllCallback& callback) {
|
| - // TODO(jam): store observer and call it when changes occur.
|
| - NOTIMPLEMENTED();
|
| - callback.Run(leveldb::DatabaseError::NOT_SUPPORTED);
|
| + map_.clear();
|
| + bytes_used_ = 0;
|
| + observers_.ForAllPtrs(
|
| + [&source](mojom::LevelDBObserver* observer) {
|
| + observer->AllDeleted(source);
|
| + });
|
| + callback.Run(true);
|
| }
|
|
|
| void LevelDBWrapperImpl::Get(mojo::Array<uint8_t> key,
|
| const GetCallback& callback) {
|
| - NOTIMPLEMENTED();
|
| - callback.Run(leveldb::DatabaseError::NOT_SUPPORTED, mojo::Array<uint8_t>());
|
| + auto found = map_.find(key);
|
| + if (found == map_.end()) {
|
| + callback.Run(false, mojo::Array<uint8_t>());
|
| + return;
|
| + }
|
| + callback.Run(true, found->second.Clone());
|
| }
|
|
|
| -void LevelDBWrapperImpl::GetAll(mojom::LevelDBObserverPtr observer,
|
| +void LevelDBWrapperImpl::GetAll(const mojo::String& source,
|
| const GetAllCallback& callback) {
|
| - // TODO(jam): store observer and call it when changes occur.
|
| - NOTIMPLEMENTED();
|
| - callback.Run(leveldb::DatabaseError::NOT_SUPPORTED,
|
| - mojo::Array<mojom::KeyValuePtr>());
|
| +
|
| + mojo::Array<mojom::KeyValuePtr> all(map_.size());
|
| + for (const auto& it : map_) {
|
| + mojom::KeyValuePtr kv = mojom::KeyValue::New();
|
| + kv->key = it.first.Clone();
|
| + kv->value = it.second.Clone();
|
| + all.push_back(std::move(kv));
|
| + }
|
| + callback.Run(leveldb::DatabaseError::OK, std::move(all));
|
| + observers_.ForAllPtrs(
|
| + [source](mojom::LevelDBObserver* observer) {
|
| + observer->GetAllComplete(source);
|
| + });
|
| }
|
|
|
| void LevelDBWrapperImpl::OnConnectionError() {
|
|
|