Chromium Code Reviews| 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" |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 #include "storage/browser/quota/special_storage_policy.h" | 28 #include "storage/browser/quota/special_storage_policy.h" |
| 29 | 29 |
| 30 namespace content { | 30 namespace content { |
| 31 | 31 |
| 32 static const int kSessionStoraceScavengingSeconds = 60; | 32 static const int kSessionStoraceScavengingSeconds = 60; |
| 33 | 33 |
| 34 // Offset the session storage namespace ids generated by different contexts | 34 // Offset the session storage namespace ids generated by different contexts |
| 35 // to help identify when an id from one is mistakenly used in another. | 35 // to help identify when an id from one is mistakenly used in another. |
| 36 static int g_session_id_offset_sequence = 1; | 36 static int g_session_id_offset_sequence = 1; |
| 37 | 37 |
| 38 // Helper class that posts the memory pressure notification on dom storage task | |
| 39 // runner. | |
| 40 class DOMStorageContextImpl::DOMStorageMemoryPressureListener { | |
| 41 public: | |
| 42 DOMStorageMemoryPressureListener(DOMStorageTaskRunner* task_runner, | |
| 43 DOMStorageContextImpl* context) | |
| 44 : task_runner_(task_runner), | |
| 45 context_(context), | |
| 46 listener_( | |
| 47 base::Bind(&DOMStorageMemoryPressureListener::OnMemoryPressure, | |
| 48 base::Unretained(this))) {} | |
| 49 | |
| 50 void OnMemoryPressure( | |
| 51 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { | |
| 52 base::AutoLock lock(lock_); | |
| 53 if (task_runner_) { | |
| 54 task_runner_->PostTask( | |
| 55 FROM_HERE, base::Bind(&DOMStorageContextImpl::PurgeMemory, context_, | |
| 56 memory_pressure_level)); | |
| 57 } | |
| 58 } | |
| 59 | |
| 60 void Shutdown() { | |
| 61 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
| |
| 62 task_runner_ = nullptr; | |
| 63 context_ = nullptr; | |
| 64 } | |
| 65 | |
| 66 private: | |
| 67 scoped_refptr<DOMStorageTaskRunner> task_runner_; | |
| 68 scoped_refptr<DOMStorageContextImpl> context_; | |
| 69 base::MemoryPressureListener listener_; | |
| 70 base::Lock lock_; | |
| 71 }; | |
| 72 | |
| 38 DOMStorageContextImpl::DOMStorageContextImpl( | 73 DOMStorageContextImpl::DOMStorageContextImpl( |
| 39 const base::FilePath& localstorage_directory, | 74 const base::FilePath& localstorage_directory, |
| 40 const base::FilePath& sessionstorage_directory, | 75 const base::FilePath& sessionstorage_directory, |
| 41 storage::SpecialStoragePolicy* special_storage_policy, | 76 storage::SpecialStoragePolicy* special_storage_policy, |
| 42 DOMStorageTaskRunner* task_runner) | 77 DOMStorageTaskRunner* task_runner) |
| 43 : localstorage_directory_(localstorage_directory), | 78 : localstorage_directory_(localstorage_directory), |
| 44 sessionstorage_directory_(sessionstorage_directory), | 79 sessionstorage_directory_(sessionstorage_directory), |
| 45 task_runner_(task_runner), | 80 task_runner_(task_runner), |
| 46 session_id_offset_(abs((g_session_id_offset_sequence++ % 10)) * 1000), | 81 session_id_offset_(abs((g_session_id_offset_sequence++ % 10)) * 1000), |
| 47 is_shutdown_(false), | 82 is_shutdown_(false), |
| 48 force_keep_session_state_(false), | 83 force_keep_session_state_(false), |
| 49 special_storage_policy_(special_storage_policy), | 84 special_storage_policy_(special_storage_policy), |
| 50 scavenging_started_(false) { | 85 scavenging_started_(false) { |
| 51 // AtomicSequenceNum starts at 0 but we want to start session | 86 // AtomicSequenceNum starts at 0 but we want to start session |
| 52 // namespace ids at one since zero is reserved for the | 87 // namespace ids at one since zero is reserved for the |
| 53 // kLocalStorageNamespaceId. | 88 // kLocalStorageNamespaceId. |
| 54 session_id_sequence_.GetNext(); | 89 session_id_sequence_.GetNext(); |
| 55 | 90 |
| 56 // Tests may run without task runners. | 91 // Tests may run without task runners. |
| 57 if (task_runner_) { | 92 if (task_runner_) { |
| 93 // Created for each DOMStorageContextImpl object and is leaked since | |
| 94 // destruction is not thread safe. | |
| 95 leaked_memory_pressure_listener_ = | |
| 96 new DOMStorageMemoryPressureListener(task_runner, this); | |
| 97 | |
| 58 // Registering dump provider is safe even outside the task runner. | 98 // Registering dump provider is safe even outside the task runner. |
| 59 base::trace_event::MemoryDumpManager::GetInstance() | 99 base::trace_event::MemoryDumpManager::GetInstance() |
| 60 ->RegisterDumpProviderWithSequencedTaskRunner( | 100 ->RegisterDumpProviderWithSequencedTaskRunner( |
| 61 this, "DOMStorage", task_runner_->GetSequencedTaskRunner( | 101 this, "DOMStorage", task_runner_->GetSequencedTaskRunner( |
| 62 DOMStorageTaskRunner::PRIMARY_SEQUENCE), | 102 DOMStorageTaskRunner::PRIMARY_SEQUENCE), |
| 63 base::trace_event::MemoryDumpProvider::Options()); | 103 base::trace_event::MemoryDumpProvider::Options()); |
| 64 } | 104 } |
| 65 } | 105 } |
| 66 | 106 |
| 67 DOMStorageContextImpl::~DOMStorageContextImpl() { | 107 DOMStorageContextImpl::~DOMStorageContextImpl() { |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 186 entry.second->Flush(); | 226 entry.second->Flush(); |
| 187 } | 227 } |
| 188 | 228 |
| 189 void DOMStorageContextImpl::Shutdown() { | 229 void DOMStorageContextImpl::Shutdown() { |
| 190 DCHECK(!task_runner_ || task_runner_->IsRunningOnPrimarySequence()); | 230 DCHECK(!task_runner_ || task_runner_->IsRunningOnPrimarySequence()); |
| 191 is_shutdown_ = true; | 231 is_shutdown_ = true; |
| 192 StorageNamespaceMap::const_iterator it = namespaces_.begin(); | 232 StorageNamespaceMap::const_iterator it = namespaces_.begin(); |
| 193 for (; it != namespaces_.end(); ++it) | 233 for (; it != namespaces_.end(); ++it) |
| 194 it->second->Shutdown(); | 234 it->second->Shutdown(); |
| 195 | 235 |
| 236 leaked_memory_pressure_listener_->Shutdown(); | |
| 237 | |
| 196 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( | 238 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( |
| 197 this); | 239 this); |
| 198 | 240 |
| 199 if (localstorage_directory_.empty() && !session_storage_database_.get()) | 241 if (localstorage_directory_.empty() && !session_storage_database_.get()) |
| 200 return; | 242 return; |
| 201 | 243 |
| 202 // Respect the content policy settings about what to | 244 // Respect the content policy settings about what to |
| 203 // keep and what to discard. | 245 // keep and what to discard. |
| 204 if (force_keep_session_state_) | 246 if (force_keep_session_state_) |
| 205 return; // Keep everything. | 247 return; // Keep everything. |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 367 | 409 |
| 368 void DOMStorageContextImpl::StartScavengingUnusedSessionStorage() { | 410 void DOMStorageContextImpl::StartScavengingUnusedSessionStorage() { |
| 369 if (session_storage_database_.get()) { | 411 if (session_storage_database_.get()) { |
| 370 task_runner_->PostDelayedTask( | 412 task_runner_->PostDelayedTask( |
| 371 FROM_HERE, base::Bind(&DOMStorageContextImpl::FindUnusedNamespaces, | 413 FROM_HERE, base::Bind(&DOMStorageContextImpl::FindUnusedNamespaces, |
| 372 this), | 414 this), |
| 373 base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds)); | 415 base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds)); |
| 374 } | 416 } |
| 375 } | 417 } |
| 376 | 418 |
| 419 void DOMStorageContextImpl::PurgeMemory( | |
| 420 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { | |
| 421 if (is_shutdown_) | |
| 422 return; | |
| 423 | |
| 424 DOMStorageNamespace::PurgeOption option = DOMStorageNamespace::PURGE_UNOPENED; | |
| 425 if (memory_pressure_level == | |
| 426 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) | |
| 427 option = DOMStorageNamespace::PURGE_AGGRESSIVE; | |
| 428 for (const auto& it : namespaces_) | |
| 429 it.second->PurgeMemory(option); | |
| 430 } | |
| 431 | |
| 377 bool DOMStorageContextImpl::OnMemoryDump( | 432 bool DOMStorageContextImpl::OnMemoryDump( |
| 378 const base::trace_event::MemoryDumpArgs& args, | 433 const base::trace_event::MemoryDumpArgs& args, |
| 379 base::trace_event::ProcessMemoryDump* pmd) { | 434 base::trace_event::ProcessMemoryDump* pmd) { |
| 380 for (const auto& it : namespaces_) { | 435 for (const auto& it : namespaces_) { |
| 381 it.second->OnMemoryDump(pmd); | 436 it.second->OnMemoryDump(pmd); |
| 382 } | 437 } |
| 383 if (session_storage_database_) | 438 if (session_storage_database_) |
| 384 session_storage_database_->OnMemoryDump(pmd); | 439 session_storage_database_->OnMemoryDump(pmd); |
| 385 return true; | 440 return true; |
| 386 } | 441 } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 448 if (!deletable_persistent_namespace_ids_.empty()) { | 503 if (!deletable_persistent_namespace_ids_.empty()) { |
| 449 task_runner_->PostDelayedTask( | 504 task_runner_->PostDelayedTask( |
| 450 FROM_HERE, base::Bind( | 505 FROM_HERE, base::Bind( |
| 451 &DOMStorageContextImpl::DeleteNextUnusedNamespace, | 506 &DOMStorageContextImpl::DeleteNextUnusedNamespace, |
| 452 this), | 507 this), |
| 453 base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds)); | 508 base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds)); |
| 454 } | 509 } |
| 455 } | 510 } |
| 456 | 511 |
| 457 } // namespace content | 512 } // namespace content |
| OLD | NEW |