OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "content/browser/leveldb_wrapper_impl.h" | 5 #include "content/browser/leveldb_wrapper_impl.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "mojo/common/common_type_converters.h" |
8 | 9 |
9 namespace content { | 10 namespace content { |
10 | 11 |
11 LevelDBWrapperImpl::LevelDBWrapperImpl( | 12 LevelDBWrapperImpl::LevelDBWrapperImpl( |
12 leveldb::LevelDBDatabase* database, | 13 leveldb::LevelDBDatabase* database, |
13 const std::string& prefix, | 14 const std::string& prefix, |
| 15 size_t max_size, |
14 const base::Closure& no_bindings_callback) | 16 const base::Closure& no_bindings_callback) |
15 : prefix_(prefix), | 17 : prefix_(prefix), |
16 no_bindings_callback_(no_bindings_callback), | 18 no_bindings_callback_(no_bindings_callback), |
17 database_(database) { | 19 database_(database), |
| 20 bytes_used_(0), |
| 21 max_size_(max_size) { |
18 bindings_.set_connection_error_handler(base::Bind( | 22 bindings_.set_connection_error_handler(base::Bind( |
19 &LevelDBWrapperImpl::OnConnectionError, base::Unretained(this))); | 23 &LevelDBWrapperImpl::OnConnectionError, base::Unretained(this))); |
20 } | 24 } |
21 | 25 |
22 void LevelDBWrapperImpl::Bind(mojom::LevelDBWrapperRequest request) { | 26 void LevelDBWrapperImpl::Bind(mojom::LevelDBWrapperRequest request) { |
23 bindings_.AddBinding(this, std::move(request)); | 27 bindings_.AddBinding(this, std::move(request)); |
24 } | 28 } |
25 | 29 |
| 30 void LevelDBWrapperImpl::AddObserver(mojom::LevelDBObserverPtr observer) { |
| 31 observers_.AddInterfacePtr(std::move(observer)); |
| 32 } |
| 33 |
26 LevelDBWrapperImpl::~LevelDBWrapperImpl() {} | 34 LevelDBWrapperImpl::~LevelDBWrapperImpl() {} |
27 | 35 |
28 void LevelDBWrapperImpl::Put(mojo::Array<uint8_t> key, | 36 void LevelDBWrapperImpl::Put(mojo::Array<uint8_t> key, |
29 mojo::Array<uint8_t> value, | 37 mojo::Array<uint8_t> value, |
30 const mojo::String& source, | 38 const mojo::String& source, |
31 const PutCallback& callback) { | 39 const PutCallback& callback) { |
32 NOTIMPLEMENTED(); | 40 bool has_old_item = false; |
33 callback.Run(leveldb::DatabaseError::NOT_SUPPORTED); | 41 mojo::Array<uint8_t> old_value; |
| 42 size_t old_item_size = 0; |
| 43 auto found = map_.find(key); |
| 44 if (found != map_.end()) { |
| 45 old_value = std::move(found->second); |
| 46 old_item_size = key.size() + old_value.size(); |
| 47 has_old_item = true; |
| 48 } |
| 49 size_t new_item_size = key.size() + value.size(); |
| 50 size_t new_bytes_used = bytes_used_ - old_item_size + new_item_size; |
| 51 |
| 52 // Only check quota if the size is increasing, this allows |
| 53 // shrinking changes to pre-existing maps that are over budget. |
| 54 if (new_item_size > old_item_size && new_bytes_used > max_size_) { |
| 55 callback.Run(false); |
| 56 return; |
| 57 } |
| 58 |
| 59 map_[key.Clone()] = value.Clone(); |
| 60 bytes_used_ = new_bytes_used; |
| 61 if (!has_old_item) { |
| 62 // We added a new key/value pair. |
| 63 observers_.ForAllPtrs( |
| 64 [&key, &value, &source](mojom::LevelDBObserver* observer) { |
| 65 observer->KeyAdded(key.Clone(), value.Clone(), source); |
| 66 }); |
| 67 } else { |
| 68 // We changed the value for an existing key. |
| 69 observers_.ForAllPtrs( |
| 70 [&key, &value, &source, &old_value](mojom::LevelDBObserver* observer) { |
| 71 observer->KeyChanged( |
| 72 key.Clone(), value.Clone(), old_value.Clone(), source); |
| 73 }); |
| 74 } |
| 75 callback.Run(true); |
34 } | 76 } |
35 | 77 |
36 void LevelDBWrapperImpl::Delete(mojo::Array<uint8_t> key, | 78 void LevelDBWrapperImpl::Delete(mojo::Array<uint8_t> key, |
37 const mojo::String& source, | 79 const mojo::String& source, |
38 const DeleteCallback& callback) { | 80 const DeleteCallback& callback) { |
39 NOTIMPLEMENTED(); | 81 auto found = map_.find(key); |
40 callback.Run(leveldb::DatabaseError::NOT_SUPPORTED); | 82 if (found == map_.end()) { |
| 83 callback.Run(true); |
| 84 return; |
| 85 } |
| 86 |
| 87 mojo::Array<uint8_t> old_value = std::move(found->second); |
| 88 map_.erase(found); |
| 89 bytes_used_ -= key.size() + old_value.size(); |
| 90 observers_.ForAllPtrs( |
| 91 [&key, &source, &old_value](mojom::LevelDBObserver* observer) { |
| 92 observer->KeyDeleted( |
| 93 key.Clone(), old_value.Clone(), source); |
| 94 }); |
| 95 callback.Run(true); |
41 } | 96 } |
42 | 97 |
43 void LevelDBWrapperImpl::DeleteAll(mojom::LevelDBObserverPtr observer, | 98 void LevelDBWrapperImpl::DeleteAll(const mojo::String& source, |
44 const mojo::String& source, | |
45 const DeleteAllCallback& callback) { | 99 const DeleteAllCallback& callback) { |
46 // TODO(jam): store observer and call it when changes occur. | 100 map_.clear(); |
47 NOTIMPLEMENTED(); | 101 bytes_used_ = 0; |
48 callback.Run(leveldb::DatabaseError::NOT_SUPPORTED); | 102 observers_.ForAllPtrs( |
| 103 [&source](mojom::LevelDBObserver* observer) { |
| 104 observer->AllDeleted(source); |
| 105 }); |
| 106 callback.Run(true); |
49 } | 107 } |
50 | 108 |
51 void LevelDBWrapperImpl::Get(mojo::Array<uint8_t> key, | 109 void LevelDBWrapperImpl::Get(mojo::Array<uint8_t> key, |
52 const GetCallback& callback) { | 110 const GetCallback& callback) { |
53 NOTIMPLEMENTED(); | 111 auto found = map_.find(key); |
54 callback.Run(leveldb::DatabaseError::NOT_SUPPORTED, mojo::Array<uint8_t>()); | 112 if (found == map_.end()) { |
| 113 callback.Run(false, mojo::Array<uint8_t>()); |
| 114 return; |
| 115 } |
| 116 callback.Run(true, found->second.Clone()); |
55 } | 117 } |
56 | 118 |
57 void LevelDBWrapperImpl::GetAll(mojom::LevelDBObserverPtr observer, | 119 void LevelDBWrapperImpl::GetAll(const mojo::String& source, |
58 const GetAllCallback& callback) { | 120 const GetAllCallback& callback) { |
59 // TODO(jam): store observer and call it when changes occur. | 121 |
60 NOTIMPLEMENTED(); | 122 mojo::Array<mojom::KeyValuePtr> all(map_.size()); |
61 callback.Run(leveldb::DatabaseError::NOT_SUPPORTED, | 123 for (const auto& it : map_) { |
62 mojo::Array<mojom::KeyValuePtr>()); | 124 mojom::KeyValuePtr kv = mojom::KeyValue::New(); |
| 125 kv->key = it.first.Clone(); |
| 126 kv->value = it.second.Clone(); |
| 127 all.push_back(std::move(kv)); |
| 128 } |
| 129 callback.Run(leveldb::DatabaseError::OK, std::move(all)); |
| 130 observers_.ForAllPtrs( |
| 131 [source](mojom::LevelDBObserver* observer) { |
| 132 observer->GetAllComplete(source); |
| 133 }); |
63 } | 134 } |
64 | 135 |
65 void LevelDBWrapperImpl::OnConnectionError() { | 136 void LevelDBWrapperImpl::OnConnectionError() { |
66 if (!bindings_.empty()) | 137 if (!bindings_.empty()) |
67 return; | 138 return; |
68 | 139 |
69 no_bindings_callback_.Run(); | 140 no_bindings_callback_.Run(); |
70 } | 141 } |
71 | 142 |
72 } // namespace content | 143 } // namespace content |
OLD | NEW |