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

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

Powered by Google App Engine
This is Rietveld 408576698