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 dad99c8462873eab07bc6e1dd36da7e62687eaac..57339445794fec2b820572957e5a3faad711fddf 100644 |
--- a/content/browser/dom_storage/dom_storage_context_impl.cc |
+++ b/content/browser/dom_storage/dom_storage_context_impl.cc |
@@ -35,6 +35,41 @@ static const int kSessionStoraceScavengingSeconds = 60; |
// to help identify when an id from one is mistakenly used in another. |
static int g_session_id_offset_sequence = 1; |
+// Helper class that posts the memory pressure notification on dom storage task |
+// runner. |
+class DOMStorageContextImpl::DOMStorageMemoryPressureListener { |
+ public: |
+ DOMStorageMemoryPressureListener(DOMStorageTaskRunner* task_runner, |
+ DOMStorageContextImpl* context) |
+ : task_runner_(task_runner), |
+ context_(context), |
+ listener_( |
+ base::Bind(&DOMStorageMemoryPressureListener::OnMemoryPressure, |
+ base::Unretained(this))) {} |
+ |
+ void OnMemoryPressure( |
+ base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { |
+ base::AutoLock lock(lock_); |
+ if (task_runner_) { |
+ task_runner_->PostTask( |
+ FROM_HERE, base::Bind(&DOMStorageContextImpl::PurgeMemory, context_, |
+ memory_pressure_level)); |
+ } |
+ } |
+ |
+ void Shutdown() { |
+ base::AutoLock lock(lock_); |
michaeln
2016/05/09 21:50:31
Lets avoid leaks and locks for this. Having a sepa
ssid
2016/05/10 02:04:16
listener in DOMStorageContextWrapper sounds like a
|
+ task_runner_ = nullptr; |
+ context_ = nullptr; |
+ } |
+ |
+ private: |
+ scoped_refptr<DOMStorageTaskRunner> task_runner_; |
+ scoped_refptr<DOMStorageContextImpl> context_; |
+ base::MemoryPressureListener listener_; |
+ base::Lock lock_; |
+}; |
+ |
DOMStorageContextImpl::DOMStorageContextImpl( |
const base::FilePath& localstorage_directory, |
const base::FilePath& sessionstorage_directory, |
@@ -55,6 +90,11 @@ DOMStorageContextImpl::DOMStorageContextImpl( |
// Tests may run without task runners. |
if (task_runner_) { |
+ // Created for each DOMStorageContextImpl object and is leaked since |
+ // destruction is not thread safe. |
+ leaked_memory_pressure_listener_ = |
+ new DOMStorageMemoryPressureListener(task_runner, this); |
+ |
// Registering dump provider is safe even outside the task runner. |
base::trace_event::MemoryDumpManager::GetInstance() |
->RegisterDumpProviderWithSequencedTaskRunner( |
@@ -193,6 +233,8 @@ void DOMStorageContextImpl::Shutdown() { |
for (; it != namespaces_.end(); ++it) |
it->second->Shutdown(); |
+ leaked_memory_pressure_listener_->Shutdown(); |
+ |
base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( |
this); |
@@ -374,6 +416,19 @@ void DOMStorageContextImpl::StartScavengingUnusedSessionStorage() { |
} |
} |
+void DOMStorageContextImpl::PurgeMemory( |
+ base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { |
+ if (is_shutdown_) |
+ return; |
+ |
+ DOMStorageNamespace::PurgeOption option = DOMStorageNamespace::PURGE_UNOPENED; |
+ if (memory_pressure_level == |
+ base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) |
+ option = DOMStorageNamespace::PURGE_AGGRESSIVE; |
+ for (const auto& it : namespaces_) |
+ it.second->PurgeMemory(option); |
+} |
+ |
bool DOMStorageContextImpl::OnMemoryDump( |
const base::trace_event::MemoryDumpArgs& args, |
base::trace_event::ProcessMemoryDump* pmd) { |