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 |