Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(123)

Side by Side Diff: content/browser/dom_storage/dom_storage_context_impl.cc

Issue 22297005: Move webkit/{browser,common}/dom_storage into content/ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/files/file_path.h" 9 #include "base/file_util.h"
10 #include "base/message_loop/message_loop_proxy.h" 10 #include "base/files/file_enumerator.h"
11 #include "content/browser/dom_storage/session_storage_namespace_impl.h" 11 #include "base/guid.h"
12 #include "content/public/browser/browser_thread.h" 12 #include "base/location.h"
13 #include "webkit/browser/dom_storage/dom_storage_area.h" 13 #include "base/time/time.h"
14 #include "webkit/browser/dom_storage/dom_storage_context.h" 14 #include "content/browser/dom_storage/dom_storage_area.h"
15 #include "webkit/browser/dom_storage/dom_storage_task_runner.h" 15 #include "content/browser/dom_storage/dom_storage_database.h"
16 16 #include "content/browser/dom_storage/dom_storage_namespace.h"
17 using dom_storage::DomStorageArea; 17 #include "content/browser/dom_storage/dom_storage_task_runner.h"
18 using dom_storage::DomStorageContext; 18 #include "content/browser/dom_storage/session_storage_database.h"
19 using dom_storage::DomStorageTaskRunner; 19 #include "content/common/dom_storage/dom_storage_types.h"
20 using dom_storage::DomStorageWorkerPoolTaskRunner; 20 #include "content/public/browser/dom_storage_context.h"
21 #include "content/public/browser/local_storage_usage_info.h"
22 #include "content/public/browser/session_storage_usage_info.h"
23 #include "webkit/browser/quota/special_storage_policy.h"
21 24
22 namespace content { 25 namespace content {
23 namespace { 26
24 27 static const int kSessionStoraceScavengingSeconds = 60;
25 const char kLocalStorageDirectory[] = "Local Storage";
26 const char kSessionStorageDirectory[] = "Session Storage";
27
28 void InvokeLocalStorageUsageCallbackHelper(
29 const DOMStorageContext::GetLocalStorageUsageCallback& callback,
30 const std::vector<dom_storage::LocalStorageUsageInfo>* infos) {
31 callback.Run(*infos);
32 }
33
34 void GetLocalStorageUsageHelper(
35 base::MessageLoopProxy* reply_loop,
36 DomStorageContext* context,
37 const DOMStorageContext::GetLocalStorageUsageCallback& callback) {
38 std::vector<dom_storage::LocalStorageUsageInfo>* infos =
39 new std::vector<dom_storage::LocalStorageUsageInfo>;
40 context->GetLocalStorageUsage(infos, true);
41 reply_loop->PostTask(
42 FROM_HERE,
43 base::Bind(&InvokeLocalStorageUsageCallbackHelper,
44 callback, base::Owned(infos)));
45 }
46
47 void InvokeSessionStorageUsageCallbackHelper(
48 const DOMStorageContext::GetSessionStorageUsageCallback& callback,
49 const std::vector<dom_storage::SessionStorageUsageInfo>* infos) {
50 callback.Run(*infos);
51 }
52
53 void GetSessionStorageUsageHelper(
54 base::MessageLoopProxy* reply_loop,
55 DomStorageContext* context,
56 const DOMStorageContext::GetSessionStorageUsageCallback& callback) {
57 std::vector<dom_storage::SessionStorageUsageInfo>* infos =
58 new std::vector<dom_storage::SessionStorageUsageInfo>;
59 context->GetSessionStorageUsage(infos);
60 reply_loop->PostTask(
61 FROM_HERE,
62 base::Bind(&InvokeSessionStorageUsageCallbackHelper,
63 callback, base::Owned(infos)));
64 }
65
66 } // namespace
67 28
68 DOMStorageContextImpl::DOMStorageContextImpl( 29 DOMStorageContextImpl::DOMStorageContextImpl(
69 const base::FilePath& data_path, 30 const base::FilePath& localstorage_directory,
70 quota::SpecialStoragePolicy* special_storage_policy) { 31 const base::FilePath& sessionstorage_directory,
71 base::SequencedWorkerPool* worker_pool = BrowserThread::GetBlockingPool(); 32 quota::SpecialStoragePolicy* special_storage_policy,
72 context_ = new dom_storage::DomStorageContext( 33 DOMStorageTaskRunner* task_runner)
73 data_path.empty() ? data_path 34 : localstorage_directory_(localstorage_directory),
74 : data_path.AppendASCII(kLocalStorageDirectory), 35 sessionstorage_directory_(sessionstorage_directory),
75 data_path.empty() ? data_path 36 task_runner_(task_runner),
76 : data_path.AppendASCII(kSessionStorageDirectory), 37 is_shutdown_(false),
77 special_storage_policy, 38 force_keep_session_state_(false),
78 new DomStorageWorkerPoolTaskRunner( 39 special_storage_policy_(special_storage_policy),
79 worker_pool, 40 scavenging_started_(false) {
80 worker_pool->GetNamedSequenceToken("dom_storage_primary"), 41 // AtomicSequenceNum starts at 0 but we want to start session
81 worker_pool->GetNamedSequenceToken("dom_storage_commit"), 42 // namespace ids at one since zero is reserved for the
82 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO) 43 // kLocalStorageNamespaceId.
83 .get())); 44 session_id_sequence_.GetNext();
84 } 45 }
85 46
86 DOMStorageContextImpl::~DOMStorageContextImpl() { 47 DOMStorageContextImpl::~DOMStorageContextImpl() {
48 if (session_storage_database_.get()) {
49 // SessionStorageDatabase shouldn't be deleted right away: deleting it will
50 // potentially involve waiting in leveldb::DBImpl::~DBImpl, and waiting
51 // shouldn't happen on this thread.
52 SessionStorageDatabase* to_release = session_storage_database_.get();
53 to_release->AddRef();
54 session_storage_database_ = NULL;
55 task_runner_->PostShutdownBlockingTask(
56 FROM_HERE,
57 DOMStorageTaskRunner::COMMIT_SEQUENCE,
58 base::Bind(&SessionStorageDatabase::Release,
59 base::Unretained(to_release)));
60 }
61 }
62
63 DOMStorageNamespace* DOMStorageContextImpl::GetStorageNamespace(
64 int64 namespace_id) {
65 if (is_shutdown_)
66 return NULL;
67 StorageNamespaceMap::iterator found = namespaces_.find(namespace_id);
68 if (found == namespaces_.end()) {
69 if (namespace_id == kLocalStorageNamespaceId) {
70 if (!localstorage_directory_.empty()) {
71 if (!file_util::CreateDirectory(localstorage_directory_)) {
72 LOG(ERROR) << "Failed to create 'Local Storage' directory,"
73 " falling back to in-memory only.";
74 localstorage_directory_ = base::FilePath();
75 }
76 }
77 DOMStorageNamespace* local =
78 new DOMStorageNamespace(localstorage_directory_, task_runner_.get());
79 namespaces_[kLocalStorageNamespaceId] = local;
80 return local;
81 }
82 return NULL;
83 }
84 return found->second.get();
87 } 85 }
88 86
89 void DOMStorageContextImpl::GetLocalStorageUsage( 87 void DOMStorageContextImpl::GetLocalStorageUsage(
90 const GetLocalStorageUsageCallback& callback) { 88 std::vector<LocalStorageUsageInfo>* infos,
91 DCHECK(context_.get()); 89 bool include_file_info) {
92 context_->task_runner() 90 if (localstorage_directory_.empty())
93 ->PostShutdownBlockingTask(FROM_HERE, 91 return;
94 DomStorageTaskRunner::PRIMARY_SEQUENCE, 92 base::FileEnumerator enumerator(localstorage_directory_, false,
95 base::Bind(&GetLocalStorageUsageHelper, 93 base::FileEnumerator::FILES);
96 base::MessageLoopProxy::current(), 94 for (base::FilePath path = enumerator.Next(); !path.empty();
97 context_, 95 path = enumerator.Next()) {
98 callback)); 96 if (path.MatchesExtension(DOMStorageArea::kDatabaseFileExtension)) {
97 LocalStorageUsageInfo info;
98 info.origin = DOMStorageArea::OriginFromDatabaseFileName(path);
99 if (include_file_info) {
100 base::FileEnumerator::FileInfo find_info = enumerator.GetInfo();
101 info.data_size = find_info.GetSize();
102 info.last_modified = find_info.GetLastModifiedTime();
103 }
104 infos->push_back(info);
105 }
106 }
99 } 107 }
100 108
101 void DOMStorageContextImpl::GetSessionStorageUsage( 109 void DOMStorageContextImpl::GetSessionStorageUsage(
102 const GetSessionStorageUsageCallback& callback) { 110 std::vector<SessionStorageUsageInfo>* infos) {
103 DCHECK(context_.get()); 111 if (!session_storage_database_.get())
104 context_->task_runner() 112 return;
105 ->PostShutdownBlockingTask(FROM_HERE, 113 std::map<std::string, std::vector<GURL> > namespaces_and_origins;
106 DomStorageTaskRunner::PRIMARY_SEQUENCE, 114 session_storage_database_->ReadNamespacesAndOrigins(
107 base::Bind(&GetSessionStorageUsageHelper, 115 &namespaces_and_origins);
108 base::MessageLoopProxy::current(), 116 for (std::map<std::string, std::vector<GURL> >::const_iterator it =
109 context_, 117 namespaces_and_origins.begin();
110 callback)); 118 it != namespaces_and_origins.end(); ++it) {
119 for (std::vector<GURL>::const_iterator origin_it = it->second.begin();
120 origin_it != it->second.end(); ++origin_it) {
121 SessionStorageUsageInfo info;
122 info.persistent_namespace_id = it->first;
123 info.origin = *origin_it;
124 infos->push_back(info);
125 }
126 }
111 } 127 }
112 128
113 void DOMStorageContextImpl::DeleteLocalStorage(const GURL& origin) { 129 void DOMStorageContextImpl::DeleteLocalStorage(const GURL& origin) {
114 DCHECK(context_.get()); 130 DCHECK(!is_shutdown_);
115 context_->task_runner()->PostShutdownBlockingTask( 131 DOMStorageNamespace* local = GetStorageNamespace(kLocalStorageNamespaceId);
116 FROM_HERE, 132 local->DeleteLocalStorageOrigin(origin);
117 DomStorageTaskRunner::PRIMARY_SEQUENCE, 133 // Synthesize a 'cleared' event if the area is open so CachedAreas in
118 base::Bind(&DomStorageContext::DeleteLocalStorage, context_, origin)); 134 // renderers get emptied out too.
135 DOMStorageArea* area = local->GetOpenStorageArea(origin);
136 if (area)
137 NotifyAreaCleared(area, origin);
119 } 138 }
120 139
121 void DOMStorageContextImpl::DeleteSessionStorage( 140 void DOMStorageContextImpl::DeleteSessionStorage(
122 const dom_storage::SessionStorageUsageInfo& usage_info) { 141 const SessionStorageUsageInfo& usage_info) {
123 DCHECK(context_.get()); 142 DCHECK(!is_shutdown_);
124 context_->task_runner()->PostShutdownBlockingTask( 143 DOMStorageNamespace* dom_storage_namespace = NULL;
125 FROM_HERE, 144 std::map<std::string, int64>::const_iterator it =
126 DomStorageTaskRunner::PRIMARY_SEQUENCE, 145 persistent_namespace_id_to_namespace_id_.find(
146 usage_info.persistent_namespace_id);
147 if (it != persistent_namespace_id_to_namespace_id_.end()) {
148 dom_storage_namespace = GetStorageNamespace(it->second);
149 } else {
150 int64 namespace_id = AllocateSessionId();
151 CreateSessionNamespace(namespace_id, usage_info.persistent_namespace_id);
152 dom_storage_namespace = GetStorageNamespace(namespace_id);
153 }
154 dom_storage_namespace->DeleteSessionStorageOrigin(usage_info.origin);
155 // Synthesize a 'cleared' event if the area is open so CachedAreas in
156 // renderers get emptied out too.
157 DOMStorageArea* area =
158 dom_storage_namespace->GetOpenStorageArea(usage_info.origin);
159 if (area)
160 NotifyAreaCleared(area, usage_info.origin);
161 }
162
163 void DOMStorageContextImpl::PurgeMemory() {
164 // We can only purge memory from the local storage namespace
165 // which is backed by disk.
166 // TODO(marja): Purge sessionStorage, too. (Requires changes to the FastClear
167 // functionality.)
168 StorageNamespaceMap::iterator found =
169 namespaces_.find(kLocalStorageNamespaceId);
170 if (found != namespaces_.end())
171 found->second->PurgeMemory(DOMStorageNamespace::PURGE_AGGRESSIVE);
172 }
173
174 void DOMStorageContextImpl::Shutdown() {
175 is_shutdown_ = true;
176 StorageNamespaceMap::const_iterator it = namespaces_.begin();
177 for (; it != namespaces_.end(); ++it)
178 it->second->Shutdown();
179
180 if (localstorage_directory_.empty() && !session_storage_database_.get())
181 return;
182
183 // Respect the content policy settings about what to
184 // keep and what to discard.
185 if (force_keep_session_state_)
186 return; // Keep everything.
187
188 bool has_session_only_origins =
189 special_storage_policy_.get() &&
190 special_storage_policy_->HasSessionOnlyOrigins();
191
192 if (has_session_only_origins) {
193 // We may have to delete something. We continue on the
194 // commit sequence after area shutdown tasks have cycled
195 // thru that sequence (and closed their database files).
196 bool success = task_runner_->PostShutdownBlockingTask(
197 FROM_HERE,
198 DOMStorageTaskRunner::COMMIT_SEQUENCE,
199 base::Bind(&DOMStorageContextImpl::ClearSessionOnlyOrigins, this));
200 DCHECK(success);
201 }
202 }
203
204 void DOMStorageContextImpl::AddEventObserver(EventObserver* observer) {
205 event_observers_.AddObserver(observer);
206 }
207
208 void DOMStorageContextImpl::RemoveEventObserver(EventObserver* observer) {
209 event_observers_.RemoveObserver(observer);
210 }
211
212 void DOMStorageContextImpl::NotifyItemSet(
213 const DOMStorageArea* area,
214 const base::string16& key,
215 const base::string16& new_value,
216 const base::NullableString16& old_value,
217 const GURL& page_url) {
218 FOR_EACH_OBSERVER(
219 EventObserver, event_observers_,
220 OnDOMStorageItemSet(area, key, new_value, old_value, page_url));
221 }
222
223 void DOMStorageContextImpl::NotifyItemRemoved(
224 const DOMStorageArea* area,
225 const base::string16& key,
226 const base::string16& old_value,
227 const GURL& page_url) {
228 FOR_EACH_OBSERVER(
229 EventObserver, event_observers_,
230 OnDOMStorageItemRemoved(area, key, old_value, page_url));
231 }
232
233 void DOMStorageContextImpl::NotifyAreaCleared(
234 const DOMStorageArea* area,
235 const GURL& page_url) {
236 FOR_EACH_OBSERVER(
237 EventObserver, event_observers_,
238 OnDOMStorageAreaCleared(area, page_url));
239 }
240
241 std::string DOMStorageContextImpl::AllocatePersistentSessionId() {
242 std::string guid = base::GenerateGUID();
243 std::replace(guid.begin(), guid.end(), '-', '_');
244 return guid;
245 }
246
247 void DOMStorageContextImpl::CreateSessionNamespace(
248 int64 namespace_id,
249 const std::string& persistent_namespace_id) {
250 if (is_shutdown_)
251 return;
252 DCHECK(namespace_id != kLocalStorageNamespaceId);
253 DCHECK(namespaces_.find(namespace_id) == namespaces_.end());
254 namespaces_[namespace_id] = new DOMStorageNamespace(
255 namespace_id, persistent_namespace_id, session_storage_database_.get(),
256 task_runner_.get());
257 persistent_namespace_id_to_namespace_id_[persistent_namespace_id] =
258 namespace_id;
259 }
260
261 void DOMStorageContextImpl::DeleteSessionNamespace(
262 int64 namespace_id, bool should_persist_data) {
263 DCHECK_NE(kLocalStorageNamespaceId, namespace_id);
264 StorageNamespaceMap::const_iterator it = namespaces_.find(namespace_id);
265 if (it == namespaces_.end())
266 return;
267 std::string persistent_namespace_id = it->second->persistent_namespace_id();
268 if (session_storage_database_.get()) {
269 if (!should_persist_data) {
270 task_runner_->PostShutdownBlockingTask(
271 FROM_HERE,
272 DOMStorageTaskRunner::COMMIT_SEQUENCE,
273 base::Bind(
274 base::IgnoreResult(&SessionStorageDatabase::DeleteNamespace),
275 session_storage_database_,
276 persistent_namespace_id));
277 } else {
278 // Ensure that the data gets committed before we shut down.
279 it->second->Shutdown();
280 if (!scavenging_started_) {
281 // Protect the persistent namespace ID from scavenging.
282 protected_persistent_session_ids_.insert(persistent_namespace_id);
283 }
284 }
285 }
286 persistent_namespace_id_to_namespace_id_.erase(persistent_namespace_id);
287 namespaces_.erase(namespace_id);
288 }
289
290 void DOMStorageContextImpl::CloneSessionNamespace(
291 int64 existing_id, int64 new_id,
292 const std::string& new_persistent_id) {
293 if (is_shutdown_)
294 return;
295 DCHECK_NE(kLocalStorageNamespaceId, existing_id);
296 DCHECK_NE(kLocalStorageNamespaceId, new_id);
297 StorageNamespaceMap::iterator found = namespaces_.find(existing_id);
298 if (found != namespaces_.end())
299 namespaces_[new_id] = found->second->Clone(new_id, new_persistent_id);
300 else
301 CreateSessionNamespace(new_id, new_persistent_id);
302 }
303
304 void DOMStorageContextImpl::ClearSessionOnlyOrigins() {
305 if (!localstorage_directory_.empty()) {
306 std::vector<LocalStorageUsageInfo> infos;
307 const bool kDontIncludeFileInfo = false;
308 GetLocalStorageUsage(&infos, kDontIncludeFileInfo);
309 for (size_t i = 0; i < infos.size(); ++i) {
310 const GURL& origin = infos[i].origin;
311 if (special_storage_policy_->IsStorageProtected(origin))
312 continue;
313 if (!special_storage_policy_->IsStorageSessionOnly(origin))
314 continue;
315
316 base::FilePath database_file_path = localstorage_directory_.Append(
317 DOMStorageArea::DatabaseFileNameFromOrigin(origin));
318 sql::Connection::Delete(database_file_path);
319 }
320 }
321 if (session_storage_database_.get()) {
322 std::vector<SessionStorageUsageInfo> infos;
323 GetSessionStorageUsage(&infos);
324 for (size_t i = 0; i < infos.size(); ++i) {
325 const GURL& origin = infos[i].origin;
326 if (special_storage_policy_->IsStorageProtected(origin))
327 continue;
328 if (!special_storage_policy_->IsStorageSessionOnly(origin))
329 continue;
330 session_storage_database_->DeleteArea(infos[i].persistent_namespace_id,
331 origin);
332 }
333 }
334 }
335
336 void DOMStorageContextImpl::SetSaveSessionStorageOnDisk() {
337 DCHECK(namespaces_.empty());
338 if (!sessionstorage_directory_.empty()) {
339 session_storage_database_ = new SessionStorageDatabase(
340 sessionstorage_directory_);
341 }
342 }
343
344 void DOMStorageContextImpl::StartScavengingUnusedSessionStorage() {
345 if (session_storage_database_.get()) {
346 task_runner_->PostDelayedTask(
347 FROM_HERE, base::Bind(&DOMStorageContextImpl::FindUnusedNamespaces,
348 this),
349 base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds));
350 }
351 }
352
353 void DOMStorageContextImpl::FindUnusedNamespaces() {
354 DCHECK(session_storage_database_.get());
355 if (scavenging_started_)
356 return;
357 scavenging_started_ = true;
358 std::set<std::string> namespace_ids_in_use;
359 for (StorageNamespaceMap::const_iterator it = namespaces_.begin();
360 it != namespaces_.end(); ++it)
361 namespace_ids_in_use.insert(it->second->persistent_namespace_id());
362 std::set<std::string> protected_persistent_session_ids;
363 protected_persistent_session_ids.swap(protected_persistent_session_ids_);
364 task_runner_->PostShutdownBlockingTask(
365 FROM_HERE, DOMStorageTaskRunner::COMMIT_SEQUENCE,
127 base::Bind( 366 base::Bind(
128 &DomStorageContext::DeleteSessionStorage, context_, usage_info)); 367 &DOMStorageContextImpl::FindUnusedNamespacesInCommitSequence,
129 } 368 this, namespace_ids_in_use, protected_persistent_session_ids));
130 369 }
131 void DOMStorageContextImpl::SetSaveSessionStorageOnDisk() { 370
132 DCHECK(context_.get()); 371 void DOMStorageContextImpl::FindUnusedNamespacesInCommitSequence(
133 context_->SetSaveSessionStorageOnDisk(); 372 const std::set<std::string>& namespace_ids_in_use,
134 } 373 const std::set<std::string>& protected_persistent_session_ids) {
135 374 DCHECK(session_storage_database_.get());
136 scoped_refptr<SessionStorageNamespace> 375 // Delete all namespaces which don't have an associated DOMStorageNamespace
137 DOMStorageContextImpl::RecreateSessionStorage( 376 // alive.
138 const std::string& persistent_id) { 377 std::map<std::string, std::vector<GURL> > namespaces_and_origins;
139 return scoped_refptr<SessionStorageNamespace>( 378 session_storage_database_->ReadNamespacesAndOrigins(&namespaces_and_origins);
140 new SessionStorageNamespaceImpl(this, persistent_id)); 379 for (std::map<std::string, std::vector<GURL> >::const_iterator it =
141 } 380 namespaces_and_origins.begin();
142 381 it != namespaces_and_origins.end(); ++it) {
143 void DOMStorageContextImpl::StartScavengingUnusedSessionStorage() { 382 if (namespace_ids_in_use.find(it->first) == namespace_ids_in_use.end() &&
144 DCHECK(context_.get()); 383 protected_persistent_session_ids.find(it->first) ==
145 context_->task_runner()->PostShutdownBlockingTask( 384 protected_persistent_session_ids.end()) {
146 FROM_HERE, 385 deletable_persistent_namespace_ids_.push_back(it->first);
147 DomStorageTaskRunner::PRIMARY_SEQUENCE, 386 }
148 base::Bind(&DomStorageContext::StartScavengingUnusedSessionStorage, 387 }
149 context_)); 388 if (!deletable_persistent_namespace_ids_.empty()) {
150 } 389 task_runner_->PostDelayedTask(
151 390 FROM_HERE, base::Bind(
152 void DOMStorageContextImpl::PurgeMemory() { 391 &DOMStorageContextImpl::DeleteNextUnusedNamespace,
153 DCHECK(context_.get()); 392 this),
154 context_->task_runner()->PostShutdownBlockingTask( 393 base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds));
155 FROM_HERE, 394 }
156 DomStorageTaskRunner::PRIMARY_SEQUENCE, 395 }
157 base::Bind(&DomStorageContext::PurgeMemory, context_)); 396
158 } 397 void DOMStorageContextImpl::DeleteNextUnusedNamespace() {
159 398 if (is_shutdown_)
160 void DOMStorageContextImpl::SetForceKeepSessionState() { 399 return;
161 DCHECK(context_.get()); 400 task_runner_->PostShutdownBlockingTask(
162 context_->task_runner()->PostShutdownBlockingTask( 401 FROM_HERE, DOMStorageTaskRunner::COMMIT_SEQUENCE,
163 FROM_HERE, 402 base::Bind(
164 DomStorageTaskRunner::PRIMARY_SEQUENCE, 403 &DOMStorageContextImpl::DeleteNextUnusedNamespaceInCommitSequence,
165 base::Bind(&DomStorageContext::SetForceKeepSessionState, context_)); 404 this));
166 } 405 }
167 406
168 void DOMStorageContextImpl::Shutdown() { 407 void DOMStorageContextImpl::DeleteNextUnusedNamespaceInCommitSequence() {
169 DCHECK(context_.get()); 408 if (deletable_persistent_namespace_ids_.empty())
170 context_->task_runner()->PostShutdownBlockingTask( 409 return;
171 FROM_HERE, 410 const std::string& persistent_id = deletable_persistent_namespace_ids_.back();
172 DomStorageTaskRunner::PRIMARY_SEQUENCE, 411 session_storage_database_->DeleteNamespace(persistent_id);
173 base::Bind(&DomStorageContext::Shutdown, context_)); 412 deletable_persistent_namespace_ids_.pop_back();
413 if (!deletable_persistent_namespace_ids_.empty()) {
414 task_runner_->PostDelayedTask(
415 FROM_HERE, base::Bind(
416 &DOMStorageContextImpl::DeleteNextUnusedNamespace,
417 this),
418 base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds));
419 }
174 } 420 }
175 421
176 } // namespace content 422 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698