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

Side by Side Diff: webkit/dom_storage/dom_storage_context.cc

Issue 12398008: Purge in-memory localStorage areas if the # of areas exceeds the limit (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: update Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "webkit/dom_storage/dom_storage_context.h" 5 #include "webkit/dom_storage/dom_storage_context.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/file_util.h" 9 #include "base/file_util.h"
10 #include "base/guid.h" 10 #include "base/guid.h"
11 #include "base/location.h" 11 #include "base/location.h"
12 #include "base/time.h" 12 #include "base/time.h"
13 #include "webkit/dom_storage/dom_storage_area.h" 13 #include "webkit/dom_storage/dom_storage_area.h"
14 #include "webkit/dom_storage/dom_storage_database.h" 14 #include "webkit/dom_storage/dom_storage_database.h"
15 #include "webkit/dom_storage/dom_storage_host.h"
15 #include "webkit/dom_storage/dom_storage_namespace.h" 16 #include "webkit/dom_storage/dom_storage_namespace.h"
16 #include "webkit/dom_storage/dom_storage_task_runner.h" 17 #include "webkit/dom_storage/dom_storage_task_runner.h"
17 #include "webkit/dom_storage/dom_storage_types.h" 18 #include "webkit/dom_storage/dom_storage_types.h"
18 #include "webkit/dom_storage/session_storage_database.h" 19 #include "webkit/dom_storage/session_storage_database.h"
19 #include "webkit/quota/special_storage_policy.h" 20 #include "webkit/quota/special_storage_policy.h"
20 21
21 using file_util::FileEnumerator; 22 using file_util::FileEnumerator;
22 23
23 namespace dom_storage { 24 namespace dom_storage {
24 25
25 static const int kSessionStoraceScavengingSeconds = 60; 26 static const int kSessionStoraceScavengingSeconds = 60;
26 27
27 DomStorageContext::DomStorageContext( 28 DomStorageContext::DomStorageContext(
28 const base::FilePath& localstorage_directory, 29 const base::FilePath& localstorage_directory,
29 const base::FilePath& sessionstorage_directory, 30 const base::FilePath& sessionstorage_directory,
30 quota::SpecialStoragePolicy* special_storage_policy, 31 quota::SpecialStoragePolicy* special_storage_policy,
31 DomStorageTaskRunner* task_runner) 32 DomStorageTaskRunner* task_runner)
32 : localstorage_directory_(localstorage_directory), 33 : localstorage_directory_(localstorage_directory),
33 sessionstorage_directory_(sessionstorage_directory), 34 sessionstorage_directory_(sessionstorage_directory),
34 task_runner_(task_runner), 35 task_runner_(task_runner),
35 is_shutdown_(false), 36 is_shutdown_(false),
36 force_keep_session_state_(false), 37 force_keep_session_state_(false),
37 special_storage_policy_(special_storage_policy), 38 special_storage_policy_(special_storage_policy),
38 scavenging_started_(false) { 39 scavenging_started_(false),
40 total_area_size_(-1) {
39 // AtomicSequenceNum starts at 0 but we want to start session 41 // AtomicSequenceNum starts at 0 but we want to start session
40 // namespace ids at one since zero is reserved for the 42 // namespace ids at one since zero is reserved for the
41 // kLocalStorageNamespaceId. 43 // kLocalStorageNamespaceId.
42 session_id_sequence_.GetNext(); 44 session_id_sequence_.GetNext();
43 } 45 }
44 46
45 DomStorageContext::~DomStorageContext() { 47 DomStorageContext::~DomStorageContext() {
46 if (session_storage_database_.get()) { 48 if (session_storage_database_.get()) {
47 // SessionStorageDatabase shouldn't be deleted right away: deleting it will 49 // SessionStorageDatabase shouldn't be deleted right away: deleting it will
48 // potentially involve waiting in leveldb::DBImpl::~DBImpl, and waiting 50 // potentially involve waiting in leveldb::DBImpl::~DBImpl, and waiting
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 void DomStorageContext::RemoveEventObserver(EventObserver* observer) { 209 void DomStorageContext::RemoveEventObserver(EventObserver* observer) {
208 event_observers_.RemoveObserver(observer); 210 event_observers_.RemoveObserver(observer);
209 } 211 }
210 212
211 void DomStorageContext::NotifyItemSet( 213 void DomStorageContext::NotifyItemSet(
212 const DomStorageArea* area, 214 const DomStorageArea* area,
213 const string16& key, 215 const string16& key,
214 const string16& new_value, 216 const string16& new_value,
215 const NullableString16& old_value, 217 const NullableString16& old_value,
216 const GURL& page_url) { 218 const GURL& page_url) {
219 InvalidateInMemoryAreaSize();
217 FOR_EACH_OBSERVER( 220 FOR_EACH_OBSERVER(
218 EventObserver, event_observers_, 221 EventObserver, event_observers_,
219 OnDomStorageItemSet(area, key, new_value, old_value, page_url)); 222 OnDomStorageItemSet(area, key, new_value, old_value, page_url));
220 } 223 }
221 224
222 void DomStorageContext::NotifyItemRemoved( 225 void DomStorageContext::NotifyItemRemoved(
223 const DomStorageArea* area, 226 const DomStorageArea* area,
224 const string16& key, 227 const string16& key,
225 const string16& old_value, 228 const string16& old_value,
226 const GURL& page_url) { 229 const GURL& page_url) {
230 InvalidateInMemoryAreaSize();
227 FOR_EACH_OBSERVER( 231 FOR_EACH_OBSERVER(
228 EventObserver, event_observers_, 232 EventObserver, event_observers_,
229 OnDomStorageItemRemoved(area, key, old_value, page_url)); 233 OnDomStorageItemRemoved(area, key, old_value, page_url));
230 } 234 }
231 235
232 void DomStorageContext::NotifyAreaCleared( 236 void DomStorageContext::NotifyAreaCleared(
233 const DomStorageArea* area, 237 const DomStorageArea* area,
234 const GURL& page_url) { 238 const GURL& page_url) {
239 InvalidateInMemoryAreaSize();
235 FOR_EACH_OBSERVER( 240 FOR_EACH_OBSERVER(
236 EventObserver, event_observers_, 241 EventObserver, event_observers_,
237 OnDomStorageAreaCleared(area, page_url)); 242 OnDomStorageAreaCleared(area, page_url));
238 } 243 }
239 244
240 std::string DomStorageContext::AllocatePersistentSessionId() { 245 std::string DomStorageContext::AllocatePersistentSessionId() {
241 std::string guid = base::GenerateGUID(); 246 std::string guid = base::GenerateGUID();
242 std::replace(guid.begin(), guid.end(), '-', '_'); 247 std::replace(guid.begin(), guid.end(), '-', '_');
243 return guid; 248 return guid;
244 } 249 }
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 } 350 }
346 351
347 void DomStorageContext::StartScavengingUnusedSessionStorage() { 352 void DomStorageContext::StartScavengingUnusedSessionStorage() {
348 if (session_storage_database_.get()) { 353 if (session_storage_database_.get()) {
349 task_runner_->PostDelayedTask( 354 task_runner_->PostDelayedTask(
350 FROM_HERE, base::Bind(&DomStorageContext::FindUnusedNamespaces, this), 355 FROM_HERE, base::Bind(&DomStorageContext::FindUnusedNamespaces, this),
351 base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds)); 356 base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds));
352 } 357 }
353 } 358 }
354 359
360 bool DomStorageContext::CanSetItem(
361 DomStorageHost* host,
362 int connection_id,
363 const string16& key,
364 const string16& value) {
365 DCHECK(host);
366 if (GetRemainingCacheSize() >= static_cast<int64>(kPerAreaQuota))
367 return true;
368 // Go through the slower check only if the memory is getting tight.
369 // TODO(kinuko,michaeln): Purge cache memory if we're caching too many areas.
370 NullableString16 old_value = host->GetAreaItem(connection_id, key);
371 int64 increase = value.size();
372 if (old_value.is_null())
373 increase += key.size();
374 else
375 increase -= old_value.string().size();
376 return static_cast<int64>(increase * sizeof(char16)) <=
377 GetRemainingCacheSize();
378 }
379
355 void DomStorageContext::FindUnusedNamespaces() { 380 void DomStorageContext::FindUnusedNamespaces() {
356 DCHECK(session_storage_database_.get()); 381 DCHECK(session_storage_database_.get());
357 if (scavenging_started_) 382 if (scavenging_started_)
358 return; 383 return;
359 scavenging_started_ = true; 384 scavenging_started_ = true;
360 std::set<std::string> namespace_ids_in_use; 385 std::set<std::string> namespace_ids_in_use;
361 for (StorageNamespaceMap::const_iterator it = namespaces_.begin(); 386 for (StorageNamespaceMap::const_iterator it = namespaces_.begin();
362 it != namespaces_.end(); ++it) 387 it != namespaces_.end(); ++it)
363 namespace_ids_in_use.insert(it->second->persistent_namespace_id()); 388 namespace_ids_in_use.insert(it->second->persistent_namespace_id());
364 std::set<std::string> protected_persistent_session_ids; 389 std::set<std::string> protected_persistent_session_ids;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 deletable_persistent_namespace_ids_.pop_back(); 439 deletable_persistent_namespace_ids_.pop_back();
415 if (!deletable_persistent_namespace_ids_.empty()) { 440 if (!deletable_persistent_namespace_ids_.empty()) {
416 task_runner_->PostDelayedTask( 441 task_runner_->PostDelayedTask(
417 FROM_HERE, base::Bind( 442 FROM_HERE, base::Bind(
418 &DomStorageContext::DeleteNextUnusedNamespace, 443 &DomStorageContext::DeleteNextUnusedNamespace,
419 this), 444 this),
420 base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds)); 445 base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds));
421 } 446 }
422 } 447 }
423 448
449 int64 DomStorageContext::GetRemainingCacheSize() {
450 if (total_area_size_ < 0) {
Mike West 2013/03/06 13:41:11 I don't see where you're updating total_area_size_
451 total_area_size_ = 0;
452 // Naively add-up the area size for each connection.
453 std::set<DomStorageArea*> visited_areas;
454 for (StorageNamespaceMap::const_iterator itr = namespaces_.begin();
455 itr != namespaces_.end(); ++itr) {
456 const DomStorageNamespace::AreaMap& map = itr->second->GetAreaMap();
457 for (DomStorageNamespace::AreaMap::const_iterator map_itr = map.begin();
458 map_itr != map.end(); ++map_itr) {
459 // We don't care open_count_ here, since we don't purge memory (yet).
460 DomStorageArea* area = map_itr->second.area_;
461 DCHECK(area);
462 if (visited_areas.insert(area).second)
463 total_area_size_ += area->GetMapSize();
464 }
465 }
466 }
467 return kMaxInMemoryAreaSize - total_area_size_;
468 }
469
424 } // namespace dom_storage 470 } // namespace dom_storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698