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

Side by Side Diff: webkit/dom_storage/dom_storage_context.cc

Issue 9963107: Persist sessionStorage on disk. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Code review (pkasting) Created 8 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
« no previous file with comments | « webkit/dom_storage/dom_storage_context.h ('k') | webkit/dom_storage/dom_storage_namespace.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "webkit/dom_storage/dom_storage_context.h" 5 #include "webkit/dom_storage/dom_storage_context.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/file_util.h" 9 #include "base/file_util.h"
10 #include "base/guid.h" 10 #include "base/guid.h"
11 #include "base/location.h" 11 #include "base/location.h"
12 #include "base/time.h" 12 #include "base/time.h"
13 #include "webkit/dom_storage/dom_storage_area.h" 13 #include "webkit/dom_storage/dom_storage_area.h"
14 #include "webkit/dom_storage/dom_storage_database.h" 14 #include "webkit/dom_storage/dom_storage_database.h"
15 #include "webkit/dom_storage/dom_storage_namespace.h" 15 #include "webkit/dom_storage/dom_storage_namespace.h"
16 #include "webkit/dom_storage/dom_storage_task_runner.h" 16 #include "webkit/dom_storage/dom_storage_task_runner.h"
17 #include "webkit/dom_storage/dom_storage_types.h" 17 #include "webkit/dom_storage/dom_storage_types.h"
18 #include "webkit/dom_storage/session_storage_database.h"
18 #include "webkit/quota/special_storage_policy.h" 19 #include "webkit/quota/special_storage_policy.h"
19 20
20 using file_util::FileEnumerator; 21 using file_util::FileEnumerator;
21 22
22 namespace dom_storage { 23 namespace dom_storage {
23 24
25 static const int kSessionStoraceScavengingSeconds = 60;
26
24 DomStorageContext::UsageInfo::UsageInfo() : data_size(0) {} 27 DomStorageContext::UsageInfo::UsageInfo() : data_size(0) {}
25 DomStorageContext::UsageInfo::~UsageInfo() {} 28 DomStorageContext::UsageInfo::~UsageInfo() {}
26 29
27 DomStorageContext::DomStorageContext( 30 DomStorageContext::DomStorageContext(
28 const FilePath& localstorage_directory, 31 const FilePath& localstorage_directory,
29 const FilePath& sessionstorage_directory, 32 const FilePath& sessionstorage_directory,
30 quota::SpecialStoragePolicy* special_storage_policy, 33 quota::SpecialStoragePolicy* special_storage_policy,
31 DomStorageTaskRunner* task_runner) 34 DomStorageTaskRunner* task_runner)
32 : localstorage_directory_(localstorage_directory), 35 : localstorage_directory_(localstorage_directory),
33 sessionstorage_directory_(sessionstorage_directory), 36 sessionstorage_directory_(sessionstorage_directory),
34 task_runner_(task_runner), 37 task_runner_(task_runner),
35 is_shutdown_(false), 38 is_shutdown_(false),
36 force_keep_session_state_(false), 39 force_keep_session_state_(false),
37 special_storage_policy_(special_storage_policy) { 40 special_storage_policy_(special_storage_policy),
41 scavenging_started_(false) {
38 // AtomicSequenceNum starts at 0 but we want to start session 42 // AtomicSequenceNum starts at 0 but we want to start session
39 // namespace ids at one since zero is reserved for the 43 // namespace ids at one since zero is reserved for the
40 // kLocalStorageNamespaceId. 44 // kLocalStorageNamespaceId.
41 session_id_sequence_.GetNext(); 45 session_id_sequence_.GetNext();
42 } 46 }
43 47
44 DomStorageContext::~DomStorageContext() { 48 DomStorageContext::~DomStorageContext() {
45 } 49 }
46 50
47 DomStorageNamespace* DomStorageContext::GetStorageNamespace( 51 DomStorageNamespace* DomStorageContext::GetStorageNamespace(
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 info.origin = DomStorageArea::OriginFromDatabaseFileName(path); 85 info.origin = DomStorageArea::OriginFromDatabaseFileName(path);
82 if (include_file_info) { 86 if (include_file_info) {
83 FileEnumerator::FindInfo find_info; 87 FileEnumerator::FindInfo find_info;
84 enumerator.GetFindInfo(&find_info); 88 enumerator.GetFindInfo(&find_info);
85 info.data_size = FileEnumerator::GetFilesize(find_info); 89 info.data_size = FileEnumerator::GetFilesize(find_info);
86 info.last_modified = FileEnumerator::GetLastModifiedTime(find_info); 90 info.last_modified = FileEnumerator::GetLastModifiedTime(find_info);
87 } 91 }
88 infos->push_back(info); 92 infos->push_back(info);
89 } 93 }
90 } 94 }
95 // TODO(marja): Get usage infos for sessionStorage (crbug.com/123599).
91 } 96 }
92 97
93 void DomStorageContext::DeleteOrigin(const GURL& origin) { 98 void DomStorageContext::DeleteOrigin(const GURL& origin) {
94 DCHECK(!is_shutdown_); 99 DCHECK(!is_shutdown_);
95 DomStorageNamespace* local = GetStorageNamespace(kLocalStorageNamespaceId); 100 DomStorageNamespace* local = GetStorageNamespace(kLocalStorageNamespaceId);
96 local->DeleteOrigin(origin); 101 local->DeleteOrigin(origin);
97 } 102 }
98 103
99 void DomStorageContext::PurgeMemory() { 104 void DomStorageContext::PurgeMemory() {
100 // We can only purge memory from the local storage namespace 105 // We can only purge memory from the local storage namespace
101 // which is backed by disk. 106 // which is backed by disk.
102 StorageNamespaceMap::iterator found = 107 StorageNamespaceMap::iterator found =
103 namespaces_.find(kLocalStorageNamespaceId); 108 namespaces_.find(kLocalStorageNamespaceId);
104 if (found != namespaces_.end()) 109 if (found != namespaces_.end())
105 found->second->PurgeMemory(); 110 found->second->PurgeMemory();
106 } 111 }
107 112
108 void DomStorageContext::Shutdown() { 113 void DomStorageContext::Shutdown() {
109 is_shutdown_ = true; 114 is_shutdown_ = true;
110 StorageNamespaceMap::const_iterator it = namespaces_.begin(); 115 StorageNamespaceMap::const_iterator it = namespaces_.begin();
111 for (; it != namespaces_.end(); ++it) 116 for (; it != namespaces_.end(); ++it)
112 it->second->Shutdown(); 117 it->second->Shutdown();
113 118
114 if (localstorage_directory_.empty()) 119 if (localstorage_directory_.empty() && !session_storage_database_.get())
115 return; 120 return;
116 121
117 // Respect the content policy settings about what to 122 // Respect the content policy settings about what to
118 // keep and what to discard. 123 // keep and what to discard.
119 if (force_keep_session_state_) 124 if (force_keep_session_state_)
120 return; // Keep everything. 125 return; // Keep everything.
121 126
122 bool has_session_only_origins = 127 bool has_session_only_origins =
123 special_storage_policy_.get() && 128 special_storage_policy_.get() &&
124 special_storage_policy_->HasSessionOnlyOrigins(); 129 special_storage_policy_->HasSessionOnlyOrigins();
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 } 184 }
180 185
181 void DomStorageContext::CreateSessionNamespace( 186 void DomStorageContext::CreateSessionNamespace(
182 int64 namespace_id, 187 int64 namespace_id,
183 const std::string& persistent_namespace_id) { 188 const std::string& persistent_namespace_id) {
184 if (is_shutdown_) 189 if (is_shutdown_)
185 return; 190 return;
186 DCHECK(namespace_id != kLocalStorageNamespaceId); 191 DCHECK(namespace_id != kLocalStorageNamespaceId);
187 DCHECK(namespaces_.find(namespace_id) == namespaces_.end()); 192 DCHECK(namespaces_.find(namespace_id) == namespaces_.end());
188 namespaces_[namespace_id] = new DomStorageNamespace( 193 namespaces_[namespace_id] = new DomStorageNamespace(
189 namespace_id, persistent_namespace_id, task_runner_); 194 namespace_id, persistent_namespace_id, session_storage_database_.get(),
195 task_runner_);
190 } 196 }
191 197
192 void DomStorageContext::DeleteSessionNamespace( 198 void DomStorageContext::DeleteSessionNamespace(
193 int64 namespace_id, bool should_persist_data) { 199 int64 namespace_id, bool should_persist_data) {
194 DCHECK_NE(kLocalStorageNamespaceId, namespace_id); 200 DCHECK_NE(kLocalStorageNamespaceId, namespace_id);
195 // TODO(marja): Protect the sessionStorage data (once it's written on disk). 201 StorageNamespaceMap::const_iterator it = namespaces_.find(namespace_id);
202 if (it == namespaces_.end())
203 return;
204 if (session_storage_database_.get()) {
205 std::string persistent_namespace_id = it->second->persistent_namespace_id();
206 if (!should_persist_data) {
207 task_runner_->PostShutdownBlockingTask(
208 FROM_HERE,
209 DomStorageTaskRunner::COMMIT_SEQUENCE,
210 base::Bind(
211 base::IgnoreResult(&SessionStorageDatabase::DeleteNamespace),
212 session_storage_database_,
213 persistent_namespace_id));
214 } else if (!scavenging_started_) {
215 // Protect the persistent namespace ID from scavenging.
216 protected_persistent_session_ids_.insert(persistent_namespace_id);
217 }
218 }
196 namespaces_.erase(namespace_id); 219 namespaces_.erase(namespace_id);
197 } 220 }
198 221
199 void DomStorageContext::CloneSessionNamespace( 222 void DomStorageContext::CloneSessionNamespace(
200 int64 existing_id, int64 new_id, 223 int64 existing_id, int64 new_id,
201 const std::string& new_persistent_id) { 224 const std::string& new_persistent_id) {
202 if (is_shutdown_) 225 if (is_shutdown_)
203 return; 226 return;
204 DCHECK_NE(kLocalStorageNamespaceId, existing_id); 227 DCHECK_NE(kLocalStorageNamespaceId, existing_id);
205 DCHECK_NE(kLocalStorageNamespaceId, new_id); 228 DCHECK_NE(kLocalStorageNamespaceId, new_id);
206 StorageNamespaceMap::iterator found = namespaces_.find(existing_id); 229 StorageNamespaceMap::iterator found = namespaces_.find(existing_id);
207 if (found != namespaces_.end()) 230 if (found != namespaces_.end())
208 namespaces_[new_id] = found->second->Clone(new_id, new_persistent_id); 231 namespaces_[new_id] = found->second->Clone(new_id, new_persistent_id);
209 else 232 else
210 CreateSessionNamespace(new_id, new_persistent_id); 233 CreateSessionNamespace(new_id, new_persistent_id);
211 } 234 }
212 235
213 void DomStorageContext::ClearSessionOnlyOrigins() { 236 void DomStorageContext::ClearSessionOnlyOrigins() {
214 std::vector<UsageInfo> infos; 237 if (!localstorage_directory_.empty()) {
215 const bool kDontIncludeFileInfo = false; 238 std::vector<UsageInfo> infos;
216 GetUsageInfo(&infos, kDontIncludeFileInfo); 239 const bool kDontIncludeFileInfo = false;
217 for (size_t i = 0; i < infos.size(); ++i) { 240 GetUsageInfo(&infos, kDontIncludeFileInfo);
218 const GURL& origin = infos[i].origin; 241 for (size_t i = 0; i < infos.size(); ++i) {
219 if (special_storage_policy_->IsStorageProtected(origin)) 242 const GURL& origin = infos[i].origin;
220 continue; 243 if (special_storage_policy_->IsStorageProtected(origin))
221 if (!special_storage_policy_->IsStorageSessionOnly(origin)) 244 continue;
222 continue; 245 if (!special_storage_policy_->IsStorageSessionOnly(origin))
246 continue;
223 247
224 const bool kNotRecursive = false; 248 const bool kNotRecursive = false;
225 FilePath database_file_path = localstorage_directory_.Append( 249 FilePath database_file_path = localstorage_directory_.Append(
226 DomStorageArea::DatabaseFileNameFromOrigin(origin)); 250 DomStorageArea::DatabaseFileNameFromOrigin(origin));
227 file_util::Delete(database_file_path, kNotRecursive); 251 file_util::Delete(database_file_path, kNotRecursive);
228 file_util::Delete( 252 file_util::Delete(
229 DomStorageDatabase::GetJournalFilePath(database_file_path), 253 DomStorageDatabase::GetJournalFilePath(database_file_path),
230 kNotRecursive); 254 kNotRecursive);
255 }
256 }
257 if (session_storage_database_.get()) {
258 std::vector<std::string> namespace_ids;
259 session_storage_database_->ReadNamespaceIds(&namespace_ids);
260 for (std::vector<std::string>::const_iterator it = namespace_ids.begin();
261 it != namespace_ids.end(); ++it) {
262 std::vector<GURL> origins;
263 session_storage_database_->ReadOriginsInNamespace(*it, &origins);
264
265 for (std::vector<GURL>::const_iterator origin_it = origins.begin();
266 origin_it != origins.end(); ++origin_it) {
267 if (special_storage_policy_->IsStorageProtected(*origin_it))
268 continue;
269 if (!special_storage_policy_->IsStorageSessionOnly(*origin_it))
270 continue;
271 session_storage_database_->DeleteArea(*it, *origin_it);
272 }
273 }
231 } 274 }
232 } 275 }
233 276
277 void DomStorageContext::SetSaveSessionStorageOnDisk() {
278 DCHECK(namespaces_.empty());
279 if (!sessionstorage_directory_.empty()) {
280 session_storage_database_ = new SessionStorageDatabase(
281 sessionstorage_directory_);
282 }
283 }
284
285 void DomStorageContext::StartScavengingUnusedSessionStorage() {
286 if (session_storage_database_.get()) {
287 task_runner_->PostDelayedTask(
288 FROM_HERE, base::Bind(&DomStorageContext::FindUnusedNamespaces, this),
289 base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds));
290 }
291 }
292
293 void DomStorageContext::FindUnusedNamespaces() {
294 DCHECK(session_storage_database_.get());
295 DCHECK(!scavenging_started_);
296 scavenging_started_ = true;
297 std::set<std::string> namespace_ids_in_use;
298 for (StorageNamespaceMap::const_iterator it = namespaces_.begin();
299 it != namespaces_.end(); ++it)
300 namespace_ids_in_use.insert(it->second->persistent_namespace_id());
301 std::set<std::string> protected_persistent_session_ids;
302 protected_persistent_session_ids.swap(protected_persistent_session_ids_);
303 task_runner_->PostShutdownBlockingTask(
304 FROM_HERE, DomStorageTaskRunner::COMMIT_SEQUENCE,
305 base::Bind(
306 &DomStorageContext::FindUnusedNamespacesInCommitSequence,
307 this, namespace_ids_in_use, protected_persistent_session_ids));
308 }
309
310 void DomStorageContext::FindUnusedNamespacesInCommitSequence(
311 const std::set<std::string>& namespace_ids_in_use,
312 const std::set<std::string>& protected_persistent_session_ids) {
313 DCHECK(session_storage_database_.get());
314 // Delete all namespaces which don't have an associated DomStorageNamespace
315 // alive.
316 std::vector<std::string> namespace_ids;
317 session_storage_database_->ReadNamespaceIds(&namespace_ids);
318 for (std::vector<std::string>::const_iterator it = namespace_ids.begin();
319 it != namespace_ids.end(); ++it) {
320 if (namespace_ids_in_use.find(*it) == namespace_ids_in_use.end() &&
321 protected_persistent_session_ids.find(*it) ==
322 protected_persistent_session_ids.end()) {
323 deletable_persistent_namespace_ids_.push_back(*it);
324 }
325 }
326 if (!deletable_persistent_namespace_ids_.empty()) {
327 task_runner_->PostDelayedTask(
328 FROM_HERE, base::Bind(
329 &DomStorageContext::DeleteNextUnusedNamespace,
330 this),
331 base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds));
332 }
333 }
334
335 void DomStorageContext::DeleteNextUnusedNamespace() {
336 if (is_shutdown_)
337 return;
338 task_runner_->PostShutdownBlockingTask(
339 FROM_HERE, DomStorageTaskRunner::COMMIT_SEQUENCE,
340 base::Bind(
341 &DomStorageContext::DeleteNextUnusedNamespaceInCommitSequence,
342 this));
343 }
344
345 void DomStorageContext::DeleteNextUnusedNamespaceInCommitSequence() {
346 const std::string& persistent_id = deletable_persistent_namespace_ids_.back();
347 session_storage_database_->DeleteNamespace(persistent_id);
348 deletable_persistent_namespace_ids_.pop_back();
349 if (!deletable_persistent_namespace_ids_.empty()) {
350 task_runner_->PostDelayedTask(
351 FROM_HERE, base::Bind(
352 &DomStorageContext::DeleteNextUnusedNamespace,
353 this),
354 base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds));
355 }
356 }
357
234 } // namespace dom_storage 358 } // namespace dom_storage
OLDNEW
« no previous file with comments | « webkit/dom_storage/dom_storage_context.h ('k') | webkit/dom_storage/dom_storage_namespace.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698