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

Side by Side Diff: content/renderer/dom_storage/local_storage_cached_area.cc

Issue 1837883003: Some fleshing out the mojo based localstorage implementation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/renderer/dom_storage/local_storage_cached_area.h" 5 #include "content/renderer/dom_storage/local_storage_cached_area.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/metrics/histogram_macros.h" 8 #include "base/metrics/histogram_macros.h"
9 #include "base/rand_util.h"
10 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_split.h" 11 #include "base/strings/string_split.h"
10 #include "base/time/time.h" 12 #include "base/time/time.h"
11 #include "content/common/dom_storage/dom_storage_map.h" 13 #include "content/common/dom_storage/dom_storage_map.h"
12 #include "content/common/storage_partition_service.mojom.h" 14 #include "content/common/storage_partition_service.mojom.h"
13 #include "content/renderer/dom_storage/local_storage_area.h" 15 #include "content/renderer/dom_storage/local_storage_area.h"
14 #include "content/renderer/dom_storage/local_storage_cached_areas.h" 16 #include "content/renderer/dom_storage/local_storage_cached_areas.h"
15 #include "mojo/common/common_type_converters.h" 17 #include "mojo/common/common_type_converters.h"
16 #include "third_party/WebKit/public/platform/WebURL.h" 18 #include "third_party/WebKit/public/platform/WebURL.h"
17 #include "third_party/WebKit/public/web/WebStorageEventDispatcher.h" 19 #include "third_party/WebKit/public/web/WebStorageEventDispatcher.h"
18 #include "url/gurl.h" 20 #include "url/gurl.h"
(...skipping 15 matching lines...) Expand all
34 base::SPLIT_WANT_ALL); 36 base::SPLIT_WANT_ALL);
35 DCHECK_EQ(result.size(), 2u); 37 DCHECK_EQ(result.size(), 2u);
36 *page_url = GURL(result[0]); 38 *page_url = GURL(result[0]);
37 *storage_area_id = result[1]; 39 *storage_area_id = result[1];
38 } 40 }
39 41
40 LocalStorageCachedArea::LocalStorageCachedArea( 42 LocalStorageCachedArea::LocalStorageCachedArea(
41 const url::Origin& origin, 43 const url::Origin& origin,
42 mojom::StoragePartitionService* storage_partition_service, 44 mojom::StoragePartitionService* storage_partition_service,
43 LocalStorageCachedAreas* cached_areas) 45 LocalStorageCachedAreas* cached_areas)
44 : origin_(origin), binding_(this), cached_areas_(cached_areas) { 46 : origin_(origin), binding_(this),
47 cached_areas_(cached_areas), weak_factory_(this) {
45 storage_partition_service->OpenLocalStorage( 48 storage_partition_service->OpenLocalStorage(
46 origin_, mojo::GetProxy(&leveldb_)); 49 origin_, binding_.CreateInterfacePtrAndBind(), mojo::GetProxy(&leveldb_));
47 } 50 }
48 51
49 LocalStorageCachedArea::~LocalStorageCachedArea() { 52 LocalStorageCachedArea::~LocalStorageCachedArea() {
50 cached_areas_->CacheAreaClosed(this); 53 cached_areas_->CacheAreaClosed(this);
51 } 54 }
52 55
53 unsigned LocalStorageCachedArea::GetLength() { 56 unsigned LocalStorageCachedArea::GetLength() {
54 EnsureLoaded(); 57 EnsureLoaded();
55 return map_->Length(); 58 return map_->Length();
56 } 59 }
(...skipping 22 matching lines...) Expand all
79 base::NullableString16 unused; 82 base::NullableString16 unused;
80 if (!map_->SetItem(key, value, &unused)) 83 if (!map_->SetItem(key, value, &unused))
81 return false; 84 return false;
82 85
83 // Ignore mutations to |key| until OnSetItemComplete. 86 // Ignore mutations to |key| until OnSetItemComplete.
84 ignore_key_mutations_[key]++; 87 ignore_key_mutations_[key]++;
85 leveldb_->Put(mojo::Array<uint8_t>::From(key), 88 leveldb_->Put(mojo::Array<uint8_t>::From(key),
86 mojo::Array<uint8_t>::From(value), 89 mojo::Array<uint8_t>::From(value),
87 PackSource(page_url, storage_area_id), 90 PackSource(page_url, storage_area_id),
88 base::Bind(&LocalStorageCachedArea::OnSetItemComplete, 91 base::Bind(&LocalStorageCachedArea::OnSetItemComplete,
89 base::Unretained(this), key)); 92 weak_factory_.GetWeakPtr(), key));
90 return true; 93 return true;
91 } 94 }
92 95
93 void LocalStorageCachedArea::RemoveItem(const base::string16& key, 96 void LocalStorageCachedArea::RemoveItem(const base::string16& key,
94 const GURL& page_url, 97 const GURL& page_url,
95 const std::string& storage_area_id) { 98 const std::string& storage_area_id) {
96 EnsureLoaded(); 99 EnsureLoaded();
97 base::string16 unused; 100 base::string16 unused;
98 if (!map_->RemoveItem(key, &unused)) 101 if (!map_->RemoveItem(key, &unused))
99 return; 102 return;
100 103
101 // Ignore mutations to |key| until OnRemoveItemComplete. 104 // Ignore mutations to |key| until OnRemoveItemComplete.
102 ignore_key_mutations_[key]++; 105 ignore_key_mutations_[key]++;
103 leveldb_->Delete(mojo::Array<uint8_t>::From(key), 106 leveldb_->Delete(mojo::Array<uint8_t>::From(key),
104 PackSource(page_url, storage_area_id), 107 PackSource(page_url, storage_area_id),
105 base::Bind(&LocalStorageCachedArea::OnRemoveItemComplete, 108 base::Bind(&LocalStorageCachedArea::OnRemoveItemComplete,
106 base::Unretained(this), key)); 109 weak_factory_.GetWeakPtr(), key));
107 } 110 }
108 111
109 void LocalStorageCachedArea::Clear(const GURL& page_url, 112 void LocalStorageCachedArea::Clear(const GURL& page_url,
110 const std::string& storage_area_id) { 113 const std::string& storage_area_id) {
111 // No need to prime the cache in this case. 114 // No need to prime the cache in this case.
112 115
113 Reset(); 116 Reset();
114 map_ = new DOMStorageMap(kPerStorageAreaQuota); 117 map_ = new DOMStorageMap(kPerStorageAreaQuota);
115 118 ignore_all_mutations_ = true;
116 leveldb_->DeleteAll(binding_.CreateInterfacePtrAndBind(), 119 leveldb_->DeleteAll(PackSource(page_url, storage_area_id),
117 PackSource(page_url, storage_area_id),
118 base::Bind(&LocalStorageCachedArea::OnClearComplete, 120 base::Bind(&LocalStorageCachedArea::OnClearComplete,
119 base::Unretained(this))); 121 weak_factory_.GetWeakPtr()));
120 } 122 }
121 123
122 void LocalStorageCachedArea::AreaCreated(LocalStorageArea* area) { 124 void LocalStorageCachedArea::AreaCreated(LocalStorageArea* area) {
123 areas_[area->id()] = area; 125 areas_[area->id()] = area;
124 } 126 }
125 127
126 void LocalStorageCachedArea::AreaDestroyed(LocalStorageArea* area) { 128 void LocalStorageCachedArea::AreaDestroyed(LocalStorageArea* area) {
127 areas_.erase(area->id()); 129 areas_.erase(area->id());
128 } 130 }
129 131
132 void LocalStorageCachedArea::KeyAdded(mojo::Array<uint8_t> key,
133 mojo::Array<uint8_t> value,
134 const mojo::String& source) {
135 base::NullableString16 null_value;
136 KeyAddedOrChanged(std::move(key), std::move(value),
137 null_value, source);
138 }
139
130 void LocalStorageCachedArea::KeyChanged(mojo::Array<uint8_t> key, 140 void LocalStorageCachedArea::KeyChanged(mojo::Array<uint8_t> key,
131 mojo::Array<uint8_t> new_value, 141 mojo::Array<uint8_t> new_value,
132 mojo::Array<uint8_t> old_value, 142 mojo::Array<uint8_t> old_value,
133 const mojo::String& source) { 143 const mojo::String& source) {
134 GURL page_url; 144 base::NullableString16 old_value_str(old_value.To<base::string16>(), false);
135 std::string storage_area_id; 145 KeyAddedOrChanged(std::move(key), std::move(new_value),
136 UnpackSource(source, &page_url, &storage_area_id); 146 old_value_str, source);
137
138 base::string16 key_string = key.To<base::string16>();
139 base::string16 new_value_string = new_value.To<base::string16>();
140
141 blink::WebStorageArea* originating_area = nullptr;
142 if (areas_.find(storage_area_id) != areas_.end()) {
143 // The source storage area is in this process.
144 originating_area = areas_[storage_area_id];
145 } else {
146 // This was from another process or the storage area is gone. If the former,
147 // apply it to our cache if we haven't already changed it and are waiting
148 // for the confirmation callback. In the latter case, we won't do anything
149 // because ignore_key_mutations_ won't be updated until the callback runs.
150 if (ignore_key_mutations_.find(key_string) != ignore_key_mutations_.end()) {
151 // We turn off quota checking here to accomodate the over budget allowance
152 // that's provided in the browser process.
153 base::NullableString16 unused;
154 map_->set_quota(std::numeric_limits<int32_t>::max());
155 map_->SetItem(key_string, new_value_string, &unused);
156 map_->set_quota(kPerStorageAreaQuota);
157 }
158 }
159
160 blink::WebStorageEventDispatcher::dispatchLocalStorageEvent(
161 key_string, old_value.To<base::string16>(), new_value_string,
162 GURL(origin_.Serialize()), page_url, originating_area);
163 } 147 }
164 148
165 void LocalStorageCachedArea::KeyDeleted(mojo::Array<uint8_t> key, 149 void LocalStorageCachedArea::KeyDeleted(mojo::Array<uint8_t> key,
166 mojo::Array<uint8_t> old_value, 150 mojo::Array<uint8_t> old_value,
167 const mojo::String& source) { 151 const mojo::String& source) {
168 GURL page_url; 152 GURL page_url;
169 std::string storage_area_id; 153 std::string storage_area_id;
170 UnpackSource(source, &page_url, &storage_area_id); 154 UnpackSource(source, &page_url, &storage_area_id);
171 155
172 base::string16 key_string = key.To<base::string16>(); 156 base::string16 key_string = key.To<base::string16>();
173 157
174 blink::WebStorageArea* originating_area = nullptr; 158 blink::WebStorageArea* originating_area = nullptr;
175 if (areas_.find(storage_area_id) != areas_.end()) { 159 if (areas_.find(storage_area_id) != areas_.end()) {
176 // The source storage area is in this process. 160 // The source storage area is in this process.
177 originating_area = areas_[storage_area_id]; 161 originating_area = areas_[storage_area_id];
178 } else { 162 } else if (map_ && !ignore_all_mutations_) {
179 // This was from another process or the storage area is gone. If the former, 163 // This was from another process or the storage area is gone. If the former,
180 // remove it from our cache if we haven't already changed it and are waiting 164 // remove it from our cache if we haven't already changed it and are waiting
181 // for the confirmation callback. In the latter case, we won't do anything 165 // for the confirmation callback. In the latter case, we won't do anything
182 // because ignore_key_mutations_ won't be updated until the callback runs. 166 // because ignore_key_mutations_ won't be updated until the callback runs.
183 if (ignore_key_mutations_.find(key_string) != ignore_key_mutations_.end()) { 167 if (ignore_key_mutations_.find(key_string) != ignore_key_mutations_.end()) {
184 base::string16 unused; 168 base::string16 unused;
185 map_->RemoveItem(key_string, &unused); 169 map_->RemoveItem(key_string, &unused);
186 } 170 }
187 } 171 }
188 172
189 blink::WebStorageEventDispatcher::dispatchLocalStorageEvent( 173 blink::WebStorageEventDispatcher::dispatchLocalStorageEvent(
190 key_string, old_value.To<base::string16>(), base::NullableString16(), 174 key_string, old_value.To<base::string16>(), base::NullableString16(),
191 GURL(origin_.Serialize()), page_url, originating_area); 175 GURL(origin_.Serialize()), page_url, originating_area);
192 } 176 }
193 177
194 void LocalStorageCachedArea::AllDeleted(const mojo::String& source) { 178 void LocalStorageCachedArea::AllDeleted(const mojo::String& source) {
195 GURL page_url; 179 GURL page_url;
196 std::string storage_area_id; 180 std::string storage_area_id;
197 UnpackSource(source, &page_url, &storage_area_id); 181 UnpackSource(source, &page_url, &storage_area_id);
198 182
199 blink::WebStorageArea* originating_area = nullptr; 183 blink::WebStorageArea* originating_area = nullptr;
200 if (areas_.find(storage_area_id) != areas_.end()) { 184 if (areas_.find(storage_area_id) != areas_.end()) {
201 // The source storage area is in this process. 185 // The source storage area is in this process.
202 originating_area = areas_[storage_area_id]; 186 originating_area = areas_[storage_area_id];
203 } else { 187 } else if (map_ && !ignore_all_mutations_) {
204 scoped_refptr<DOMStorageMap> old = map_; 188 scoped_refptr<DOMStorageMap> old = map_;
205 map_ = new DOMStorageMap(kPerStorageAreaQuota); 189 map_ = new DOMStorageMap(kPerStorageAreaQuota);
206 190
207 // We have to retain local additions which happened after this clear 191 // We have to retain local additions which happened after this clear
208 // operation from another process. 192 // operation from another process.
209 auto iter = ignore_key_mutations_.begin(); 193 auto iter = ignore_key_mutations_.begin();
210 while (iter != ignore_key_mutations_.end()) { 194 while (iter != ignore_key_mutations_.end()) {
211 base::NullableString16 value = old->GetItem(iter->first); 195 base::NullableString16 value = old->GetItem(iter->first);
212 if (!value.is_null()) { 196 if (!value.is_null()) {
213 base::NullableString16 unused; 197 base::NullableString16 unused;
214 map_->SetItem(iter->first, value.string(), &unused); 198 map_->SetItem(iter->first, value.string(), &unused);
215 } 199 }
216 ++iter; 200 ++iter;
217 } 201 }
218 } 202 }
219 203
220 blink::WebStorageEventDispatcher::dispatchLocalStorageEvent( 204 blink::WebStorageEventDispatcher::dispatchLocalStorageEvent(
221 base::NullableString16(), base::NullableString16(), 205 base::NullableString16(), base::NullableString16(),
222 base::NullableString16(), GURL(origin_.Serialize()), page_url, 206 base::NullableString16(), GURL(origin_.Serialize()), page_url,
223 originating_area); 207 originating_area);
224 } 208 }
225 209
210 void LocalStorageCachedArea::GetAllComplete(const mojo::String& source) {
211 // Since the GetAll method is synchronous, we need this asynchronously
212 // delivered notification to avoid applying changes to the returned array
213 // that we already have.
214 if (source.To<std::string>() == get_all_request_id_) {
215 DCHECK(ignore_all_mutations_);
216 DCHECK(!get_all_request_id_.empty());
217 ignore_all_mutations_ = false;
218 get_all_request_id_.clear();
219 }
220 }
221
222 void LocalStorageCachedArea::KeyAddedOrChanged(
223 mojo::Array<uint8_t> key,
224 mojo::Array<uint8_t> new_value,
225 const base::NullableString16& old_value,
226 const mojo::String& source) {
227 GURL page_url;
228 std::string storage_area_id;
229 UnpackSource(source, &page_url, &storage_area_id);
230
231 base::string16 key_string = key.To<base::string16>();
232 base::string16 new_value_string = new_value.To<base::string16>();
233
234 blink::WebStorageArea* originating_area = nullptr;
235 if (areas_.find(storage_area_id) != areas_.end()) {
236 // The source storage area is in this process.
237 originating_area = areas_[storage_area_id];
238 } else if (map_ && !ignore_all_mutations_) {
239 // This was from another process or the storage area is gone. If the former,
240 // apply it to our cache if we haven't already changed it and are waiting
241 // for the confirmation callback. In the latter case, we won't do anything
242 // because ignore_key_mutations_ won't be updated until the callback runs.
243 if (ignore_key_mutations_.find(key_string) != ignore_key_mutations_.end()) {
244 // We turn off quota checking here to accomodate the over budget allowance
245 // that's provided in the browser process.
246 base::NullableString16 unused;
247 map_->set_quota(std::numeric_limits<int32_t>::max());
248 map_->SetItem(key_string, new_value_string, &unused);
249 map_->set_quota(kPerStorageAreaQuota);
250 }
251 }
252
253 blink::WebStorageEventDispatcher::dispatchLocalStorageEvent(
254 key_string, old_value, new_value_string,
255 GURL(origin_.Serialize()), page_url, originating_area);
256
257 }
258
226 void LocalStorageCachedArea::EnsureLoaded() { 259 void LocalStorageCachedArea::EnsureLoaded() {
227 if (map_) 260 if (map_)
228 return; 261 return;
229 262
230 base::TimeTicks before = base::TimeTicks::Now(); 263 base::TimeTicks before = base::TimeTicks::Now();
264 ignore_all_mutations_ = true;
265 get_all_request_id_ = base::Uint64ToString(base::RandUint64());
231 leveldb::DatabaseError status = leveldb::DatabaseError::OK; 266 leveldb::DatabaseError status = leveldb::DatabaseError::OK;
232 mojo::Array<content::mojom::KeyValuePtr> data; 267 mojo::Array<content::mojom::KeyValuePtr> data;
233 leveldb_->GetAll(binding_.CreateInterfacePtrAndBind(), &status, &data); 268 leveldb_->GetAll(get_all_request_id_, &status, &data);
234 269
235 DOMStorageValuesMap values; 270 DOMStorageValuesMap values;
236 for (size_t i = 0; i < data.size(); ++i) { 271 for (size_t i = 0; i < data.size(); ++i) {
237 values[data[i]->key.To<base::string16>()] = 272 values[data[i]->key.To<base::string16>()] =
238 base::NullableString16(data[i]->value.To<base::string16>(), false); 273 base::NullableString16(data[i]->value.To<base::string16>(), false);
239 } 274 }
240 275
241 map_ = new DOMStorageMap(kPerStorageAreaQuota); 276 map_ = new DOMStorageMap(kPerStorageAreaQuota);
242 map_->SwapValues(&values); 277 map_->SwapValues(&values);
243 278
(...skipping 13 matching lines...) Expand all
257 } else if (local_storage_size_kb < 1000) { 292 } else if (local_storage_size_kb < 1000) {
258 UMA_HISTOGRAM_TIMES("LocalStorage.MojoTimeToPrimeFor100KBTo1MB", 293 UMA_HISTOGRAM_TIMES("LocalStorage.MojoTimeToPrimeFor100KBTo1MB",
259 time_to_prime); 294 time_to_prime);
260 } else { 295 } else {
261 UMA_HISTOGRAM_TIMES("LocalStorage.MojoTimeToPrimeFor1MBTo5MB", 296 UMA_HISTOGRAM_TIMES("LocalStorage.MojoTimeToPrimeFor1MBTo5MB",
262 time_to_prime); 297 time_to_prime);
263 } 298 }
264 } 299 }
265 300
266 void LocalStorageCachedArea::OnSetItemComplete(const base::string16& key, 301 void LocalStorageCachedArea::OnSetItemComplete(const base::string16& key,
267 leveldb::DatabaseError result) { 302 bool success) {
268 if (result != leveldb::DatabaseError::OK) { 303 if (!success) {
269 Reset(); 304 Reset();
270 return; 305 return;
271 } 306 }
272 307
273 auto found = ignore_key_mutations_.find(key); 308 auto found = ignore_key_mutations_.find(key);
274 DCHECK(found != ignore_key_mutations_.end()); 309 DCHECK(found != ignore_key_mutations_.end());
275 if (--found->second == 0) 310 if (--found->second == 0)
276 ignore_key_mutations_.erase(found); 311 ignore_key_mutations_.erase(found);
277 } 312 }
278 313
279 void LocalStorageCachedArea::OnRemoveItemComplete( 314 void LocalStorageCachedArea::OnRemoveItemComplete(
280 const base::string16& key, leveldb::DatabaseError result) { 315 const base::string16& key, bool success) {
281 DCHECK_EQ(result, leveldb::DatabaseError::OK); 316 DCHECK(success);
282 auto found = ignore_key_mutations_.find(key); 317 auto found = ignore_key_mutations_.find(key);
283 DCHECK(found != ignore_key_mutations_.end()); 318 DCHECK(found != ignore_key_mutations_.end());
284 if (--found->second == 0) 319 if (--found->second == 0)
285 ignore_key_mutations_.erase(found); 320 ignore_key_mutations_.erase(found);
286 } 321 }
287 322
288 void LocalStorageCachedArea::OnClearComplete(leveldb::DatabaseError result) { 323 void LocalStorageCachedArea::OnClearComplete(bool success) {
289 DCHECK_EQ(result, leveldb::DatabaseError::OK); 324 DCHECK(success);
325 DCHECK(ignore_all_mutations_);
326 ignore_all_mutations_ = false;
290 } 327 }
291 328
292 void LocalStorageCachedArea::Reset() { 329 void LocalStorageCachedArea::Reset() {
293 binding_.Close();
294 map_ = NULL; 330 map_ = NULL;
295 ignore_key_mutations_.clear(); 331 ignore_key_mutations_.clear();
332 ignore_all_mutations_ = false;
333 weak_factory_.InvalidateWeakPtrs();
296 } 334 }
297 335
298 } // namespace content 336 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/dom_storage/local_storage_cached_area.h ('k') | mojo/public/cpp/bindings/array.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698