Index: content/browser/dom_storage/dom_storage_context_impl.cc |
diff --git a/content/browser/dom_storage/dom_storage_context_impl.cc b/content/browser/dom_storage/dom_storage_context_impl.cc |
index 1e6afa770e521e38a77f85825d066a4760759e4e..26a2da93845a20522f9eb3634d11b90660835233 100644 |
--- a/content/browser/dom_storage/dom_storage_context_impl.cc |
+++ b/content/browser/dom_storage/dom_storage_context_impl.cc |
@@ -13,6 +13,8 @@ |
#include "base/files/file_util.h" |
#include "base/guid.h" |
#include "base/location.h" |
+#include "base/metrics/histogram.h" |
+#include "base/sys_info.h" |
#include "base/time/time.h" |
#include "base/trace_event/memory_dump_manager.h" |
#include "base/trace_event/process_memory_dump.h" |
@@ -28,12 +30,39 @@ |
#include "storage/browser/quota/special_storage_policy.h" |
namespace content { |
+namespace { |
-static const int kSessionStoraceScavengingSeconds = 60; |
+// Limits on the cache size and number of areas in memory, over which the areas |
+// are purged. |
+#if defined(OS_ANDROID) |
+const unsigned kMaxStorageAreaCount = 20; |
+const size_t kMaxCacheSize = 2 * 1024 * 1024; |
+#else |
+const unsigned kMaxStorageAreaCount = 100; |
+const size_t kMaxCacheSize = 20 * 1024 * 1024; |
+#endif |
+ |
+const int kSessionStoraceScavengingSeconds = 60; |
// Offset the session storage namespace ids generated by different contexts |
// to help identify when an id from one is mistakenly used in another. |
-static int g_session_id_offset_sequence = 1; |
+int g_session_id_offset_sequence = 1; |
+ |
+// Aggregates statistics from all the namespaces. |
+DOMStorageNamespace::UsageStatistics GetTotalNamespaceStatistics( |
+ const DOMStorageContextImpl::StorageNamespaceMap& namespace_map) { |
+ DOMStorageNamespace::UsageStatistics total_stats = {0}; |
+ for (const auto& it : namespace_map) { |
+ DOMStorageNamespace::UsageStatistics stats = |
+ it.second->GetUsageStatistics(); |
+ total_stats.total_cache_size += stats.total_cache_size; |
+ total_stats.total_area_count += stats.total_area_count; |
+ total_stats.inactive_area_count += stats.inactive_area_count; |
+ } |
+ return total_stats; |
+} |
+ |
+} // namespace |
DOMStorageContextImpl::DOMStorageContextImpl( |
const base::FilePath& localstorage_directory, |
@@ -47,7 +76,8 @@ DOMStorageContextImpl::DOMStorageContextImpl( |
is_shutdown_(false), |
force_keep_session_state_(false), |
special_storage_policy_(special_storage_policy), |
- scavenging_started_(false) { |
+ scavenging_started_(false), |
+ is_low_end_device_(base::SysInfo::IsLowEndDevice()) { |
// AtomicSequenceNum starts at 0 but we want to start session |
// namespace ids at one since zero is reserved for the |
// kLocalStorageNamespaceId. |
@@ -396,6 +426,45 @@ void DOMStorageContextImpl::StartScavengingUnusedSessionStorage() { |
} |
} |
+void DOMStorageContextImpl::PurgeMemory(PurgeOption purge_option) { |
+ if (is_shutdown_) |
+ return; |
+ |
+ DOMStorageNamespace::UsageStatistics initial_stats = |
+ GetTotalNamespaceStatistics(namespaces_); |
+ |
+ // Track the total localStorage cache size. |
+ UMA_HISTOGRAM_CUSTOM_COUNTS("LocalStorage.BrowserLocalStorageCacheSizeInKB", |
+ initial_stats.total_cache_size / 1024, 0, 100000, |
+ 50); |
+ |
+ if (purge_option == PURGE_IF_NEEDED) { |
+ // Purging is done based on the cache sizes without including the database |
+ // size since it can be expensive trying to estimate the sqlite usage for |
+ // all databases. For low end devices purge all inactive areas. |
+ bool should_purge = |
+ (is_low_end_device_ && initial_stats.inactive_area_count) || |
+ initial_stats.total_cache_size > kMaxCacheSize || |
+ initial_stats.total_area_count > kMaxStorageAreaCount; |
+ if (!should_purge) |
+ return; |
+ |
+ purge_option = PURGE_UNOPENED; |
+ } |
+ |
+ bool aggressively = purge_option == PURGE_AGGRESSIVE; |
+ for (const auto& it : namespaces_) |
+ it.second->PurgeMemory(aggressively); |
+ |
+ // Track the size of cache purged. |
+ UMA_HISTOGRAM_CUSTOM_COUNTS( |
+ "LocalStorage.BrowserLocalStorageCachePurgedInKB", |
+ (initial_stats.total_cache_size - |
+ GetTotalNamespaceStatistics(namespaces_).total_cache_size) / |
+ 1024, |
+ 0, 100000, 50); |
+} |
+ |
bool DOMStorageContextImpl::OnMemoryDump( |
const base::trace_event::MemoryDumpArgs& args, |
base::trace_event::ProcessMemoryDump* pmd) { |