OLD | NEW |
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 "content/browser/dom_storage/dom_storage_context_impl.h" | 5 #include "content/browser/dom_storage/dom_storage_context_impl.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdlib.h> | 8 #include <stdlib.h> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
12 #include "base/files/file_enumerator.h" | 12 #include "base/files/file_enumerator.h" |
13 #include "base/files/file_util.h" | 13 #include "base/files/file_util.h" |
14 #include "base/guid.h" | 14 #include "base/guid.h" |
15 #include "base/location.h" | 15 #include "base/location.h" |
| 16 #include "base/metrics/histogram.h" |
| 17 #include "base/sys_info.h" |
16 #include "base/time/time.h" | 18 #include "base/time/time.h" |
17 #include "base/trace_event/memory_dump_manager.h" | 19 #include "base/trace_event/memory_dump_manager.h" |
18 #include "base/trace_event/process_memory_dump.h" | 20 #include "base/trace_event/process_memory_dump.h" |
19 #include "content/browser/dom_storage/dom_storage_area.h" | 21 #include "content/browser/dom_storage/dom_storage_area.h" |
20 #include "content/browser/dom_storage/dom_storage_database.h" | 22 #include "content/browser/dom_storage/dom_storage_database.h" |
21 #include "content/browser/dom_storage/dom_storage_namespace.h" | 23 #include "content/browser/dom_storage/dom_storage_namespace.h" |
22 #include "content/browser/dom_storage/dom_storage_task_runner.h" | 24 #include "content/browser/dom_storage/dom_storage_task_runner.h" |
23 #include "content/browser/dom_storage/session_storage_database.h" | 25 #include "content/browser/dom_storage/session_storage_database.h" |
24 #include "content/common/dom_storage/dom_storage_types.h" | 26 #include "content/common/dom_storage/dom_storage_types.h" |
25 #include "content/public/browser/dom_storage_context.h" | 27 #include "content/public/browser/dom_storage_context.h" |
26 #include "content/public/browser/local_storage_usage_info.h" | 28 #include "content/public/browser/local_storage_usage_info.h" |
27 #include "content/public/browser/session_storage_usage_info.h" | 29 #include "content/public/browser/session_storage_usage_info.h" |
28 #include "storage/browser/quota/special_storage_policy.h" | 30 #include "storage/browser/quota/special_storage_policy.h" |
29 | 31 |
30 namespace content { | 32 namespace content { |
| 33 namespace { |
31 | 34 |
32 static const int kSessionStoraceScavengingSeconds = 60; | 35 // Limits on the cache size and number of areas in memory, over which the areas |
| 36 // are purged. |
| 37 #if defined(OS_ANDROID) |
| 38 const unsigned kMaxStorageAreaCount = 20; |
| 39 const size_t kMaxCacheSize = 2 * 1024 * 1024; |
| 40 #else |
| 41 const unsigned kMaxStorageAreaCount = 100; |
| 42 const size_t kMaxCacheSize = 20 * 1024 * 1024; |
| 43 #endif |
| 44 |
| 45 const int kSessionStoraceScavengingSeconds = 60; |
33 | 46 |
34 // Offset the session storage namespace ids generated by different contexts | 47 // Offset the session storage namespace ids generated by different contexts |
35 // to help identify when an id from one is mistakenly used in another. | 48 // to help identify when an id from one is mistakenly used in another. |
36 static int g_session_id_offset_sequence = 1; | 49 int g_session_id_offset_sequence = 1; |
| 50 |
| 51 // Aggregates statistics from all the namespaces. |
| 52 DOMStorageNamespace::UsageStatistics GetTotalNamespaceStatistics( |
| 53 const DOMStorageContextImpl::StorageNamespaceMap& namespace_map) { |
| 54 DOMStorageNamespace::UsageStatistics total_stats = {0}; |
| 55 for (const auto& it : namespace_map) { |
| 56 DOMStorageNamespace::UsageStatistics stats = |
| 57 it.second->GetUsageStatistics(); |
| 58 total_stats.total_cache_size += stats.total_cache_size; |
| 59 total_stats.total_area_count += stats.total_area_count; |
| 60 total_stats.inactive_area_count += stats.inactive_area_count; |
| 61 } |
| 62 return total_stats; |
| 63 } |
| 64 |
| 65 } // namespace |
37 | 66 |
38 DOMStorageContextImpl::DOMStorageContextImpl( | 67 DOMStorageContextImpl::DOMStorageContextImpl( |
39 const base::FilePath& localstorage_directory, | 68 const base::FilePath& localstorage_directory, |
40 const base::FilePath& sessionstorage_directory, | 69 const base::FilePath& sessionstorage_directory, |
41 storage::SpecialStoragePolicy* special_storage_policy, | 70 storage::SpecialStoragePolicy* special_storage_policy, |
42 DOMStorageTaskRunner* task_runner) | 71 DOMStorageTaskRunner* task_runner) |
43 : localstorage_directory_(localstorage_directory), | 72 : localstorage_directory_(localstorage_directory), |
44 sessionstorage_directory_(sessionstorage_directory), | 73 sessionstorage_directory_(sessionstorage_directory), |
45 task_runner_(task_runner), | 74 task_runner_(task_runner), |
46 session_id_offset_(abs((g_session_id_offset_sequence++ % 10)) * 1000), | 75 session_id_offset_(abs((g_session_id_offset_sequence++ % 10)) * 1000), |
47 is_shutdown_(false), | 76 is_shutdown_(false), |
48 force_keep_session_state_(false), | 77 force_keep_session_state_(false), |
49 special_storage_policy_(special_storage_policy), | 78 special_storage_policy_(special_storage_policy), |
50 scavenging_started_(false) { | 79 scavenging_started_(false), |
| 80 is_low_end_device_(base::SysInfo::IsLowEndDevice()) { |
51 // AtomicSequenceNum starts at 0 but we want to start session | 81 // AtomicSequenceNum starts at 0 but we want to start session |
52 // namespace ids at one since zero is reserved for the | 82 // namespace ids at one since zero is reserved for the |
53 // kLocalStorageNamespaceId. | 83 // kLocalStorageNamespaceId. |
54 session_id_sequence_.GetNext(); | 84 session_id_sequence_.GetNext(); |
55 | 85 |
56 // Tests may run without task runners. | 86 // Tests may run without task runners. |
57 if (task_runner_) { | 87 if (task_runner_) { |
58 // Registering dump provider is safe even outside the task runner. | 88 // Registering dump provider is safe even outside the task runner. |
59 base::trace_event::MemoryDumpManager::GetInstance() | 89 base::trace_event::MemoryDumpManager::GetInstance() |
60 ->RegisterDumpProviderWithSequencedTaskRunner( | 90 ->RegisterDumpProviderWithSequencedTaskRunner( |
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 | 419 |
390 void DOMStorageContextImpl::StartScavengingUnusedSessionStorage() { | 420 void DOMStorageContextImpl::StartScavengingUnusedSessionStorage() { |
391 if (session_storage_database_.get()) { | 421 if (session_storage_database_.get()) { |
392 task_runner_->PostDelayedTask( | 422 task_runner_->PostDelayedTask( |
393 FROM_HERE, base::Bind(&DOMStorageContextImpl::FindUnusedNamespaces, | 423 FROM_HERE, base::Bind(&DOMStorageContextImpl::FindUnusedNamespaces, |
394 this), | 424 this), |
395 base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds)); | 425 base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds)); |
396 } | 426 } |
397 } | 427 } |
398 | 428 |
| 429 void DOMStorageContextImpl::PurgeMemory(PurgeOption purge_option) { |
| 430 if (is_shutdown_) |
| 431 return; |
| 432 |
| 433 DOMStorageNamespace::UsageStatistics initial_stats = |
| 434 GetTotalNamespaceStatistics(namespaces_); |
| 435 |
| 436 // Track the total localStorage cache size. |
| 437 UMA_HISTOGRAM_CUSTOM_COUNTS("LocalStorage.BrowserLocalStorageCacheSizeInKB", |
| 438 initial_stats.total_cache_size / 1024, 0, 100000, |
| 439 50); |
| 440 |
| 441 if (purge_option == PURGE_IF_NEEDED) { |
| 442 // Purging is done based on the cache sizes without including the database |
| 443 // size since it can be expensive trying to estimate the sqlite usage for |
| 444 // all databases. For low end devices purge all inactive areas. |
| 445 bool should_purge = |
| 446 (is_low_end_device_ && initial_stats.inactive_area_count) || |
| 447 initial_stats.total_cache_size > kMaxCacheSize || |
| 448 initial_stats.total_area_count > kMaxStorageAreaCount; |
| 449 if (!should_purge) |
| 450 return; |
| 451 |
| 452 purge_option = PURGE_UNOPENED; |
| 453 } |
| 454 |
| 455 bool aggressively = purge_option == PURGE_AGGRESSIVE; |
| 456 for (const auto& it : namespaces_) |
| 457 it.second->PurgeMemory(aggressively); |
| 458 |
| 459 // Track the size of cache purged. |
| 460 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 461 "LocalStorage.BrowserLocalStorageCachePurgedInKB", |
| 462 (initial_stats.total_cache_size - |
| 463 GetTotalNamespaceStatistics(namespaces_).total_cache_size) / |
| 464 1024, |
| 465 0, 100000, 50); |
| 466 } |
| 467 |
399 bool DOMStorageContextImpl::OnMemoryDump( | 468 bool DOMStorageContextImpl::OnMemoryDump( |
400 const base::trace_event::MemoryDumpArgs& args, | 469 const base::trace_event::MemoryDumpArgs& args, |
401 base::trace_event::ProcessMemoryDump* pmd) { | 470 base::trace_event::ProcessMemoryDump* pmd) { |
402 for (const auto& it : namespaces_) { | 471 for (const auto& it : namespaces_) { |
403 it.second->OnMemoryDump(pmd); | 472 it.second->OnMemoryDump(pmd); |
404 } | 473 } |
405 if (session_storage_database_) | 474 if (session_storage_database_) |
406 session_storage_database_->OnMemoryDump(pmd); | 475 session_storage_database_->OnMemoryDump(pmd); |
407 return true; | 476 return true; |
408 } | 477 } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
470 if (!deletable_persistent_namespace_ids_.empty()) { | 539 if (!deletable_persistent_namespace_ids_.empty()) { |
471 task_runner_->PostDelayedTask( | 540 task_runner_->PostDelayedTask( |
472 FROM_HERE, base::Bind( | 541 FROM_HERE, base::Bind( |
473 &DOMStorageContextImpl::DeleteNextUnusedNamespace, | 542 &DOMStorageContextImpl::DeleteNextUnusedNamespace, |
474 this), | 543 this), |
475 base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds)); | 544 base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds)); |
476 } | 545 } |
477 } | 546 } |
478 | 547 |
479 } // namespace content | 548 } // namespace content |
OLD | NEW |