| 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 f790ecd8001a750bec29f8337cd165f311fd8745..dd1f33e847fb13702496061685d6f85b7863ad3c 100644
|
| --- a/content/browser/dom_storage/dom_storage_context_impl.cc
|
| +++ b/content/browser/dom_storage/dom_storage_context_impl.cc
|
| @@ -6,171 +6,417 @@
|
|
|
| #include "base/bind.h"
|
| #include "base/bind_helpers.h"
|
| -#include "base/files/file_path.h"
|
| -#include "base/message_loop/message_loop_proxy.h"
|
| -#include "content/browser/dom_storage/session_storage_namespace_impl.h"
|
| -#include "content/public/browser/browser_thread.h"
|
| -#include "webkit/browser/dom_storage/dom_storage_area.h"
|
| -#include "webkit/browser/dom_storage/dom_storage_context.h"
|
| -#include "webkit/browser/dom_storage/dom_storage_task_runner.h"
|
| -
|
| -using dom_storage::DomStorageArea;
|
| -using dom_storage::DomStorageContext;
|
| -using dom_storage::DomStorageTaskRunner;
|
| -using dom_storage::DomStorageWorkerPoolTaskRunner;
|
| +#include "base/file_util.h"
|
| +#include "base/files/file_enumerator.h"
|
| +#include "base/guid.h"
|
| +#include "base/location.h"
|
| +#include "base/time/time.h"
|
| +#include "content/browser/dom_storage/dom_storage_area.h"
|
| +#include "content/browser/dom_storage/dom_storage_database.h"
|
| +#include "content/browser/dom_storage/dom_storage_namespace.h"
|
| +#include "content/browser/dom_storage/dom_storage_task_runner.h"
|
| +#include "content/browser/dom_storage/session_storage_database.h"
|
| +#include "content/common/dom_storage/dom_storage_types.h"
|
| +#include "content/public/browser/dom_storage_context.h"
|
| +#include "content/public/browser/local_storage_usage_info.h"
|
| +#include "content/public/browser/session_storage_usage_info.h"
|
| +#include "webkit/browser/quota/special_storage_policy.h"
|
|
|
| namespace content {
|
| -namespace {
|
|
|
| -const char kLocalStorageDirectory[] = "Local Storage";
|
| -const char kSessionStorageDirectory[] = "Session Storage";
|
| +static const int kSessionStoraceScavengingSeconds = 60;
|
|
|
| -void InvokeLocalStorageUsageCallbackHelper(
|
| - const DOMStorageContext::GetLocalStorageUsageCallback& callback,
|
| - const std::vector<dom_storage::LocalStorageUsageInfo>* infos) {
|
| - callback.Run(*infos);
|
| +DOMStorageContextImpl::DOMStorageContextImpl(
|
| + const base::FilePath& localstorage_directory,
|
| + const base::FilePath& sessionstorage_directory,
|
| + quota::SpecialStoragePolicy* special_storage_policy,
|
| + DOMStorageTaskRunner* task_runner)
|
| + : localstorage_directory_(localstorage_directory),
|
| + sessionstorage_directory_(sessionstorage_directory),
|
| + task_runner_(task_runner),
|
| + is_shutdown_(false),
|
| + force_keep_session_state_(false),
|
| + special_storage_policy_(special_storage_policy),
|
| + scavenging_started_(false) {
|
| + // AtomicSequenceNum starts at 0 but we want to start session
|
| + // namespace ids at one since zero is reserved for the
|
| + // kLocalStorageNamespaceId.
|
| + session_id_sequence_.GetNext();
|
| }
|
|
|
| -void GetLocalStorageUsageHelper(
|
| - base::MessageLoopProxy* reply_loop,
|
| - DomStorageContext* context,
|
| - const DOMStorageContext::GetLocalStorageUsageCallback& callback) {
|
| - std::vector<dom_storage::LocalStorageUsageInfo>* infos =
|
| - new std::vector<dom_storage::LocalStorageUsageInfo>;
|
| - context->GetLocalStorageUsage(infos, true);
|
| - reply_loop->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&InvokeLocalStorageUsageCallbackHelper,
|
| - callback, base::Owned(infos)));
|
| +DOMStorageContextImpl::~DOMStorageContextImpl() {
|
| + if (session_storage_database_.get()) {
|
| + // SessionStorageDatabase shouldn't be deleted right away: deleting it will
|
| + // potentially involve waiting in leveldb::DBImpl::~DBImpl, and waiting
|
| + // shouldn't happen on this thread.
|
| + SessionStorageDatabase* to_release = session_storage_database_.get();
|
| + to_release->AddRef();
|
| + session_storage_database_ = NULL;
|
| + task_runner_->PostShutdownBlockingTask(
|
| + FROM_HERE,
|
| + DOMStorageTaskRunner::COMMIT_SEQUENCE,
|
| + base::Bind(&SessionStorageDatabase::Release,
|
| + base::Unretained(to_release)));
|
| + }
|
| }
|
|
|
| -void InvokeSessionStorageUsageCallbackHelper(
|
| - const DOMStorageContext::GetSessionStorageUsageCallback& callback,
|
| - const std::vector<dom_storage::SessionStorageUsageInfo>* infos) {
|
| - callback.Run(*infos);
|
| +DOMStorageNamespace* DOMStorageContextImpl::GetStorageNamespace(
|
| + int64 namespace_id) {
|
| + if (is_shutdown_)
|
| + return NULL;
|
| + StorageNamespaceMap::iterator found = namespaces_.find(namespace_id);
|
| + if (found == namespaces_.end()) {
|
| + if (namespace_id == kLocalStorageNamespaceId) {
|
| + if (!localstorage_directory_.empty()) {
|
| + if (!file_util::CreateDirectory(localstorage_directory_)) {
|
| + LOG(ERROR) << "Failed to create 'Local Storage' directory,"
|
| + " falling back to in-memory only.";
|
| + localstorage_directory_ = base::FilePath();
|
| + }
|
| + }
|
| + DOMStorageNamespace* local =
|
| + new DOMStorageNamespace(localstorage_directory_, task_runner_.get());
|
| + namespaces_[kLocalStorageNamespaceId] = local;
|
| + return local;
|
| + }
|
| + return NULL;
|
| + }
|
| + return found->second.get();
|
| }
|
|
|
| -void GetSessionStorageUsageHelper(
|
| - base::MessageLoopProxy* reply_loop,
|
| - DomStorageContext* context,
|
| - const DOMStorageContext::GetSessionStorageUsageCallback& callback) {
|
| - std::vector<dom_storage::SessionStorageUsageInfo>* infos =
|
| - new std::vector<dom_storage::SessionStorageUsageInfo>;
|
| - context->GetSessionStorageUsage(infos);
|
| - reply_loop->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&InvokeSessionStorageUsageCallbackHelper,
|
| - callback, base::Owned(infos)));
|
| +void DOMStorageContextImpl::GetLocalStorageUsage(
|
| + std::vector<LocalStorageUsageInfo>* infos,
|
| + bool include_file_info) {
|
| + if (localstorage_directory_.empty())
|
| + return;
|
| + base::FileEnumerator enumerator(localstorage_directory_, false,
|
| + base::FileEnumerator::FILES);
|
| + for (base::FilePath path = enumerator.Next(); !path.empty();
|
| + path = enumerator.Next()) {
|
| + if (path.MatchesExtension(DOMStorageArea::kDatabaseFileExtension)) {
|
| + LocalStorageUsageInfo info;
|
| + info.origin = DOMStorageArea::OriginFromDatabaseFileName(path);
|
| + if (include_file_info) {
|
| + base::FileEnumerator::FileInfo find_info = enumerator.GetInfo();
|
| + info.data_size = find_info.GetSize();
|
| + info.last_modified = find_info.GetLastModifiedTime();
|
| + }
|
| + infos->push_back(info);
|
| + }
|
| + }
|
| }
|
|
|
| -} // namespace
|
| +void DOMStorageContextImpl::GetSessionStorageUsage(
|
| + std::vector<SessionStorageUsageInfo>* infos) {
|
| + if (!session_storage_database_.get())
|
| + return;
|
| + std::map<std::string, std::vector<GURL> > namespaces_and_origins;
|
| + session_storage_database_->ReadNamespacesAndOrigins(
|
| + &namespaces_and_origins);
|
| + for (std::map<std::string, std::vector<GURL> >::const_iterator it =
|
| + namespaces_and_origins.begin();
|
| + it != namespaces_and_origins.end(); ++it) {
|
| + for (std::vector<GURL>::const_iterator origin_it = it->second.begin();
|
| + origin_it != it->second.end(); ++origin_it) {
|
| + SessionStorageUsageInfo info;
|
| + info.persistent_namespace_id = it->first;
|
| + info.origin = *origin_it;
|
| + infos->push_back(info);
|
| + }
|
| + }
|
| +}
|
|
|
| -DOMStorageContextImpl::DOMStorageContextImpl(
|
| - const base::FilePath& data_path,
|
| - quota::SpecialStoragePolicy* special_storage_policy) {
|
| - base::SequencedWorkerPool* worker_pool = BrowserThread::GetBlockingPool();
|
| - context_ = new dom_storage::DomStorageContext(
|
| - data_path.empty() ? data_path
|
| - : data_path.AppendASCII(kLocalStorageDirectory),
|
| - data_path.empty() ? data_path
|
| - : data_path.AppendASCII(kSessionStorageDirectory),
|
| - special_storage_policy,
|
| - new DomStorageWorkerPoolTaskRunner(
|
| - worker_pool,
|
| - worker_pool->GetNamedSequenceToken("dom_storage_primary"),
|
| - worker_pool->GetNamedSequenceToken("dom_storage_commit"),
|
| - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)
|
| - .get()));
|
| +void DOMStorageContextImpl::DeleteLocalStorage(const GURL& origin) {
|
| + DCHECK(!is_shutdown_);
|
| + DOMStorageNamespace* local = GetStorageNamespace(kLocalStorageNamespaceId);
|
| + local->DeleteLocalStorageOrigin(origin);
|
| + // Synthesize a 'cleared' event if the area is open so CachedAreas in
|
| + // renderers get emptied out too.
|
| + DOMStorageArea* area = local->GetOpenStorageArea(origin);
|
| + if (area)
|
| + NotifyAreaCleared(area, origin);
|
| }
|
|
|
| -DOMStorageContextImpl::~DOMStorageContextImpl() {
|
| +void DOMStorageContextImpl::DeleteSessionStorage(
|
| + const SessionStorageUsageInfo& usage_info) {
|
| + DCHECK(!is_shutdown_);
|
| + DOMStorageNamespace* dom_storage_namespace = NULL;
|
| + std::map<std::string, int64>::const_iterator it =
|
| + persistent_namespace_id_to_namespace_id_.find(
|
| + usage_info.persistent_namespace_id);
|
| + if (it != persistent_namespace_id_to_namespace_id_.end()) {
|
| + dom_storage_namespace = GetStorageNamespace(it->second);
|
| + } else {
|
| + int64 namespace_id = AllocateSessionId();
|
| + CreateSessionNamespace(namespace_id, usage_info.persistent_namespace_id);
|
| + dom_storage_namespace = GetStorageNamespace(namespace_id);
|
| + }
|
| + dom_storage_namespace->DeleteSessionStorageOrigin(usage_info.origin);
|
| + // Synthesize a 'cleared' event if the area is open so CachedAreas in
|
| + // renderers get emptied out too.
|
| + DOMStorageArea* area =
|
| + dom_storage_namespace->GetOpenStorageArea(usage_info.origin);
|
| + if (area)
|
| + NotifyAreaCleared(area, usage_info.origin);
|
| }
|
|
|
| -void DOMStorageContextImpl::GetLocalStorageUsage(
|
| - const GetLocalStorageUsageCallback& callback) {
|
| - DCHECK(context_.get());
|
| - context_->task_runner()
|
| - ->PostShutdownBlockingTask(FROM_HERE,
|
| - DomStorageTaskRunner::PRIMARY_SEQUENCE,
|
| - base::Bind(&GetLocalStorageUsageHelper,
|
| - base::MessageLoopProxy::current(),
|
| - context_,
|
| - callback));
|
| +void DOMStorageContextImpl::PurgeMemory() {
|
| + // We can only purge memory from the local storage namespace
|
| + // which is backed by disk.
|
| + // TODO(marja): Purge sessionStorage, too. (Requires changes to the FastClear
|
| + // functionality.)
|
| + StorageNamespaceMap::iterator found =
|
| + namespaces_.find(kLocalStorageNamespaceId);
|
| + if (found != namespaces_.end())
|
| + found->second->PurgeMemory(DOMStorageNamespace::PURGE_AGGRESSIVE);
|
| }
|
|
|
| -void DOMStorageContextImpl::GetSessionStorageUsage(
|
| - const GetSessionStorageUsageCallback& callback) {
|
| - DCHECK(context_.get());
|
| - context_->task_runner()
|
| - ->PostShutdownBlockingTask(FROM_HERE,
|
| - DomStorageTaskRunner::PRIMARY_SEQUENCE,
|
| - base::Bind(&GetSessionStorageUsageHelper,
|
| - base::MessageLoopProxy::current(),
|
| - context_,
|
| - callback));
|
| +void DOMStorageContextImpl::Shutdown() {
|
| + is_shutdown_ = true;
|
| + StorageNamespaceMap::const_iterator it = namespaces_.begin();
|
| + for (; it != namespaces_.end(); ++it)
|
| + it->second->Shutdown();
|
| +
|
| + if (localstorage_directory_.empty() && !session_storage_database_.get())
|
| + return;
|
| +
|
| + // Respect the content policy settings about what to
|
| + // keep and what to discard.
|
| + if (force_keep_session_state_)
|
| + return; // Keep everything.
|
| +
|
| + bool has_session_only_origins =
|
| + special_storage_policy_.get() &&
|
| + special_storage_policy_->HasSessionOnlyOrigins();
|
| +
|
| + if (has_session_only_origins) {
|
| + // We may have to delete something. We continue on the
|
| + // commit sequence after area shutdown tasks have cycled
|
| + // thru that sequence (and closed their database files).
|
| + bool success = task_runner_->PostShutdownBlockingTask(
|
| + FROM_HERE,
|
| + DOMStorageTaskRunner::COMMIT_SEQUENCE,
|
| + base::Bind(&DOMStorageContextImpl::ClearSessionOnlyOrigins, this));
|
| + DCHECK(success);
|
| + }
|
| }
|
|
|
| -void DOMStorageContextImpl::DeleteLocalStorage(const GURL& origin) {
|
| - DCHECK(context_.get());
|
| - context_->task_runner()->PostShutdownBlockingTask(
|
| - FROM_HERE,
|
| - DomStorageTaskRunner::PRIMARY_SEQUENCE,
|
| - base::Bind(&DomStorageContext::DeleteLocalStorage, context_, origin));
|
| +void DOMStorageContextImpl::AddEventObserver(EventObserver* observer) {
|
| + event_observers_.AddObserver(observer);
|
| }
|
|
|
| -void DOMStorageContextImpl::DeleteSessionStorage(
|
| - const dom_storage::SessionStorageUsageInfo& usage_info) {
|
| - DCHECK(context_.get());
|
| - context_->task_runner()->PostShutdownBlockingTask(
|
| - FROM_HERE,
|
| - DomStorageTaskRunner::PRIMARY_SEQUENCE,
|
| - base::Bind(
|
| - &DomStorageContext::DeleteSessionStorage, context_, usage_info));
|
| +void DOMStorageContextImpl::RemoveEventObserver(EventObserver* observer) {
|
| + event_observers_.RemoveObserver(observer);
|
| }
|
|
|
| -void DOMStorageContextImpl::SetSaveSessionStorageOnDisk() {
|
| - DCHECK(context_.get());
|
| - context_->SetSaveSessionStorageOnDisk();
|
| +void DOMStorageContextImpl::NotifyItemSet(
|
| + const DOMStorageArea* area,
|
| + const base::string16& key,
|
| + const base::string16& new_value,
|
| + const base::NullableString16& old_value,
|
| + const GURL& page_url) {
|
| + FOR_EACH_OBSERVER(
|
| + EventObserver, event_observers_,
|
| + OnDOMStorageItemSet(area, key, new_value, old_value, page_url));
|
| }
|
|
|
| -scoped_refptr<SessionStorageNamespace>
|
| -DOMStorageContextImpl::RecreateSessionStorage(
|
| - const std::string& persistent_id) {
|
| - return scoped_refptr<SessionStorageNamespace>(
|
| - new SessionStorageNamespaceImpl(this, persistent_id));
|
| +void DOMStorageContextImpl::NotifyItemRemoved(
|
| + const DOMStorageArea* area,
|
| + const base::string16& key,
|
| + const base::string16& old_value,
|
| + const GURL& page_url) {
|
| + FOR_EACH_OBSERVER(
|
| + EventObserver, event_observers_,
|
| + OnDOMStorageItemRemoved(area, key, old_value, page_url));
|
| +}
|
| +
|
| +void DOMStorageContextImpl::NotifyAreaCleared(
|
| + const DOMStorageArea* area,
|
| + const GURL& page_url) {
|
| + FOR_EACH_OBSERVER(
|
| + EventObserver, event_observers_,
|
| + OnDOMStorageAreaCleared(area, page_url));
|
| +}
|
| +
|
| +std::string DOMStorageContextImpl::AllocatePersistentSessionId() {
|
| + std::string guid = base::GenerateGUID();
|
| + std::replace(guid.begin(), guid.end(), '-', '_');
|
| + return guid;
|
| +}
|
| +
|
| +void DOMStorageContextImpl::CreateSessionNamespace(
|
| + int64 namespace_id,
|
| + const std::string& persistent_namespace_id) {
|
| + if (is_shutdown_)
|
| + return;
|
| + DCHECK(namespace_id != kLocalStorageNamespaceId);
|
| + DCHECK(namespaces_.find(namespace_id) == namespaces_.end());
|
| + namespaces_[namespace_id] = new DOMStorageNamespace(
|
| + namespace_id, persistent_namespace_id, session_storage_database_.get(),
|
| + task_runner_.get());
|
| + persistent_namespace_id_to_namespace_id_[persistent_namespace_id] =
|
| + namespace_id;
|
| +}
|
| +
|
| +void DOMStorageContextImpl::DeleteSessionNamespace(
|
| + int64 namespace_id, bool should_persist_data) {
|
| + DCHECK_NE(kLocalStorageNamespaceId, namespace_id);
|
| + StorageNamespaceMap::const_iterator it = namespaces_.find(namespace_id);
|
| + if (it == namespaces_.end())
|
| + return;
|
| + std::string persistent_namespace_id = it->second->persistent_namespace_id();
|
| + if (session_storage_database_.get()) {
|
| + if (!should_persist_data) {
|
| + task_runner_->PostShutdownBlockingTask(
|
| + FROM_HERE,
|
| + DOMStorageTaskRunner::COMMIT_SEQUENCE,
|
| + base::Bind(
|
| + base::IgnoreResult(&SessionStorageDatabase::DeleteNamespace),
|
| + session_storage_database_,
|
| + persistent_namespace_id));
|
| + } else {
|
| + // Ensure that the data gets committed before we shut down.
|
| + it->second->Shutdown();
|
| + if (!scavenging_started_) {
|
| + // Protect the persistent namespace ID from scavenging.
|
| + protected_persistent_session_ids_.insert(persistent_namespace_id);
|
| + }
|
| + }
|
| + }
|
| + persistent_namespace_id_to_namespace_id_.erase(persistent_namespace_id);
|
| + namespaces_.erase(namespace_id);
|
| +}
|
| +
|
| +void DOMStorageContextImpl::CloneSessionNamespace(
|
| + int64 existing_id, int64 new_id,
|
| + const std::string& new_persistent_id) {
|
| + if (is_shutdown_)
|
| + return;
|
| + DCHECK_NE(kLocalStorageNamespaceId, existing_id);
|
| + DCHECK_NE(kLocalStorageNamespaceId, new_id);
|
| + StorageNamespaceMap::iterator found = namespaces_.find(existing_id);
|
| + if (found != namespaces_.end())
|
| + namespaces_[new_id] = found->second->Clone(new_id, new_persistent_id);
|
| + else
|
| + CreateSessionNamespace(new_id, new_persistent_id);
|
| +}
|
| +
|
| +void DOMStorageContextImpl::ClearSessionOnlyOrigins() {
|
| + if (!localstorage_directory_.empty()) {
|
| + std::vector<LocalStorageUsageInfo> infos;
|
| + const bool kDontIncludeFileInfo = false;
|
| + GetLocalStorageUsage(&infos, kDontIncludeFileInfo);
|
| + for (size_t i = 0; i < infos.size(); ++i) {
|
| + const GURL& origin = infos[i].origin;
|
| + if (special_storage_policy_->IsStorageProtected(origin))
|
| + continue;
|
| + if (!special_storage_policy_->IsStorageSessionOnly(origin))
|
| + continue;
|
| +
|
| + base::FilePath database_file_path = localstorage_directory_.Append(
|
| + DOMStorageArea::DatabaseFileNameFromOrigin(origin));
|
| + sql::Connection::Delete(database_file_path);
|
| + }
|
| + }
|
| + if (session_storage_database_.get()) {
|
| + std::vector<SessionStorageUsageInfo> infos;
|
| + GetSessionStorageUsage(&infos);
|
| + for (size_t i = 0; i < infos.size(); ++i) {
|
| + const GURL& origin = infos[i].origin;
|
| + if (special_storage_policy_->IsStorageProtected(origin))
|
| + continue;
|
| + if (!special_storage_policy_->IsStorageSessionOnly(origin))
|
| + continue;
|
| + session_storage_database_->DeleteArea(infos[i].persistent_namespace_id,
|
| + origin);
|
| + }
|
| + }
|
| +}
|
| +
|
| +void DOMStorageContextImpl::SetSaveSessionStorageOnDisk() {
|
| + DCHECK(namespaces_.empty());
|
| + if (!sessionstorage_directory_.empty()) {
|
| + session_storage_database_ = new SessionStorageDatabase(
|
| + sessionstorage_directory_);
|
| + }
|
| }
|
|
|
| void DOMStorageContextImpl::StartScavengingUnusedSessionStorage() {
|
| - DCHECK(context_.get());
|
| - context_->task_runner()->PostShutdownBlockingTask(
|
| - FROM_HERE,
|
| - DomStorageTaskRunner::PRIMARY_SEQUENCE,
|
| - base::Bind(&DomStorageContext::StartScavengingUnusedSessionStorage,
|
| - context_));
|
| + if (session_storage_database_.get()) {
|
| + task_runner_->PostDelayedTask(
|
| + FROM_HERE, base::Bind(&DOMStorageContextImpl::FindUnusedNamespaces,
|
| + this),
|
| + base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds));
|
| + }
|
| }
|
|
|
| -void DOMStorageContextImpl::PurgeMemory() {
|
| - DCHECK(context_.get());
|
| - context_->task_runner()->PostShutdownBlockingTask(
|
| - FROM_HERE,
|
| - DomStorageTaskRunner::PRIMARY_SEQUENCE,
|
| - base::Bind(&DomStorageContext::PurgeMemory, context_));
|
| +void DOMStorageContextImpl::FindUnusedNamespaces() {
|
| + DCHECK(session_storage_database_.get());
|
| + if (scavenging_started_)
|
| + return;
|
| + scavenging_started_ = true;
|
| + std::set<std::string> namespace_ids_in_use;
|
| + for (StorageNamespaceMap::const_iterator it = namespaces_.begin();
|
| + it != namespaces_.end(); ++it)
|
| + namespace_ids_in_use.insert(it->second->persistent_namespace_id());
|
| + std::set<std::string> protected_persistent_session_ids;
|
| + protected_persistent_session_ids.swap(protected_persistent_session_ids_);
|
| + task_runner_->PostShutdownBlockingTask(
|
| + FROM_HERE, DOMStorageTaskRunner::COMMIT_SEQUENCE,
|
| + base::Bind(
|
| + &DOMStorageContextImpl::FindUnusedNamespacesInCommitSequence,
|
| + this, namespace_ids_in_use, protected_persistent_session_ids));
|
| }
|
|
|
| -void DOMStorageContextImpl::SetForceKeepSessionState() {
|
| - DCHECK(context_.get());
|
| - context_->task_runner()->PostShutdownBlockingTask(
|
| - FROM_HERE,
|
| - DomStorageTaskRunner::PRIMARY_SEQUENCE,
|
| - base::Bind(&DomStorageContext::SetForceKeepSessionState, context_));
|
| +void DOMStorageContextImpl::FindUnusedNamespacesInCommitSequence(
|
| + const std::set<std::string>& namespace_ids_in_use,
|
| + const std::set<std::string>& protected_persistent_session_ids) {
|
| + DCHECK(session_storage_database_.get());
|
| + // Delete all namespaces which don't have an associated DOMStorageNamespace
|
| + // alive.
|
| + std::map<std::string, std::vector<GURL> > namespaces_and_origins;
|
| + session_storage_database_->ReadNamespacesAndOrigins(&namespaces_and_origins);
|
| + for (std::map<std::string, std::vector<GURL> >::const_iterator it =
|
| + namespaces_and_origins.begin();
|
| + it != namespaces_and_origins.end(); ++it) {
|
| + if (namespace_ids_in_use.find(it->first) == namespace_ids_in_use.end() &&
|
| + protected_persistent_session_ids.find(it->first) ==
|
| + protected_persistent_session_ids.end()) {
|
| + deletable_persistent_namespace_ids_.push_back(it->first);
|
| + }
|
| + }
|
| + if (!deletable_persistent_namespace_ids_.empty()) {
|
| + task_runner_->PostDelayedTask(
|
| + FROM_HERE, base::Bind(
|
| + &DOMStorageContextImpl::DeleteNextUnusedNamespace,
|
| + this),
|
| + base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds));
|
| + }
|
| }
|
|
|
| -void DOMStorageContextImpl::Shutdown() {
|
| - DCHECK(context_.get());
|
| - context_->task_runner()->PostShutdownBlockingTask(
|
| - FROM_HERE,
|
| - DomStorageTaskRunner::PRIMARY_SEQUENCE,
|
| - base::Bind(&DomStorageContext::Shutdown, context_));
|
| +void DOMStorageContextImpl::DeleteNextUnusedNamespace() {
|
| + if (is_shutdown_)
|
| + return;
|
| + task_runner_->PostShutdownBlockingTask(
|
| + FROM_HERE, DOMStorageTaskRunner::COMMIT_SEQUENCE,
|
| + base::Bind(
|
| + &DOMStorageContextImpl::DeleteNextUnusedNamespaceInCommitSequence,
|
| + this));
|
| +}
|
| +
|
| +void DOMStorageContextImpl::DeleteNextUnusedNamespaceInCommitSequence() {
|
| + if (deletable_persistent_namespace_ids_.empty())
|
| + return;
|
| + const std::string& persistent_id = deletable_persistent_namespace_ids_.back();
|
| + session_storage_database_->DeleteNamespace(persistent_id);
|
| + deletable_persistent_namespace_ids_.pop_back();
|
| + if (!deletable_persistent_namespace_ids_.empty()) {
|
| + task_runner_->PostDelayedTask(
|
| + FROM_HERE, base::Bind(
|
| + &DOMStorageContextImpl::DeleteNextUnusedNamespace,
|
| + this),
|
| + base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds));
|
| + }
|
| }
|
|
|
| } // namespace content
|
|
|