| 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, 1, 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       1, 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 | 
|---|