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

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. Created 8 years, 6 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 "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/location.h" 10 #include "base/location.h"
11 #include "base/time.h" 11 #include "base/time.h"
12 #include "chrome/common/guid.h" // FIXME: layering violation?
12 #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"
13 #include "webkit/dom_storage/dom_storage_namespace.h" 15 #include "webkit/dom_storage/dom_storage_namespace.h"
14 #include "webkit/dom_storage/dom_storage_task_runner.h" 16 #include "webkit/dom_storage/dom_storage_task_runner.h"
15 #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"
16 #include "webkit/quota/special_storage_policy.h" 19 #include "webkit/quota/special_storage_policy.h"
17 20
18 using file_util::FileEnumerator; 21 using file_util::FileEnumerator;
19 22
20 namespace dom_storage { 23 namespace dom_storage {
21 24
22 DomStorageContext::UsageInfo::UsageInfo() : data_size(0) {} 25 DomStorageContext::UsageInfo::UsageInfo() : data_size(0) {}
23 DomStorageContext::UsageInfo::~UsageInfo() {} 26 DomStorageContext::UsageInfo::~UsageInfo() {}
24 27
25 DomStorageContext::DomStorageContext( 28 DomStorageContext::DomStorageContext(
26 const FilePath& localstorage_directory, 29 const FilePath& localstorage_directory,
27 const FilePath& sessionstorage_directory, 30 const FilePath& sessionstorage_directory,
28 quota::SpecialStoragePolicy* special_storage_policy, 31 quota::SpecialStoragePolicy* special_storage_policy,
29 DomStorageTaskRunner* task_runner) 32 DomStorageTaskRunner* task_runner)
30 : localstorage_directory_(localstorage_directory), 33 : localstorage_directory_(localstorage_directory),
31 sessionstorage_directory_(sessionstorage_directory), 34 sessionstorage_directory_(sessionstorage_directory),
32 task_runner_(task_runner), 35 task_runner_(task_runner),
33 is_shutdown_(false), 36 is_shutdown_(false),
34 force_keep_session_state_(false), 37 force_keep_session_state_(false),
35 special_storage_policy_(special_storage_policy) { 38 special_storage_policy_(special_storage_policy) {
36 // AtomicSequenceNum starts at 0 but we want to start session 39 // AtomicSequenceNum starts at 0 but we want to start session
37 // namespace ids at one since zero is reserved for the 40 // namespace ids at one since zero is reserved for the
38 // kLocalStorageNamespaceId. 41 // kLocalStorageNamespaceId.
39 session_id_sequence_.GetNext(); 42 session_id_sequence_.GetNext();
43 if (!sessionstorage_directory_.empty()) {
44 session_storage_database_ = new SessionStorageDatabase(
45 sessionstorage_directory_);
46 }
40 } 47 }
41 48
42 DomStorageContext::~DomStorageContext() { 49 DomStorageContext::~DomStorageContext() {
43 } 50 }
44 51
45 DomStorageNamespace* DomStorageContext::GetStorageNamespace( 52 DomStorageNamespace* DomStorageContext::GetStorageNamespace(
46 int64 namespace_id) { 53 int64 namespace_id) {
47 if (is_shutdown_) 54 if (is_shutdown_)
48 return NULL; 55 return NULL;
49 StorageNamespaceMap::iterator found = namespaces_.find(namespace_id); 56 StorageNamespaceMap::iterator found = namespaces_.find(namespace_id);
(...skipping 29 matching lines...) Expand all
79 info.origin = DomStorageArea::OriginFromDatabaseFileName(path); 86 info.origin = DomStorageArea::OriginFromDatabaseFileName(path);
80 if (include_file_info) { 87 if (include_file_info) {
81 FileEnumerator::FindInfo find_info; 88 FileEnumerator::FindInfo find_info;
82 enumerator.GetFindInfo(&find_info); 89 enumerator.GetFindInfo(&find_info);
83 info.data_size = FileEnumerator::GetFilesize(find_info); 90 info.data_size = FileEnumerator::GetFilesize(find_info);
84 info.last_modified = FileEnumerator::GetLastModifiedTime(find_info); 91 info.last_modified = FileEnumerator::GetLastModifiedTime(find_info);
85 } 92 }
86 infos->push_back(info); 93 infos->push_back(info);
87 } 94 }
88 } 95 }
96 // FIXME(marja): Get usage infos for sessionStorage (crbug.com/123599).
89 } 97 }
90 98
91 void DomStorageContext::DeleteOrigin(const GURL& origin) { 99 void DomStorageContext::DeleteOrigin(const GURL& origin) {
92 DCHECK(!is_shutdown_); 100 DCHECK(!is_shutdown_);
93 DomStorageNamespace* local = GetStorageNamespace(kLocalStorageNamespaceId); 101 DomStorageNamespace* local = GetStorageNamespace(kLocalStorageNamespaceId);
94 local->DeleteOrigin(origin); 102 local->DeleteOrigin(origin);
95 } 103 }
96 104
97 void DomStorageContext::PurgeMemory() { 105 void DomStorageContext::PurgeMemory() {
98 // We can only purge memory from the local storage namespace 106 // We can only purge memory from the local storage namespace
99 // which is backed by disk. 107 // which is backed by disk.
100 StorageNamespaceMap::iterator found = 108 StorageNamespaceMap::iterator found =
101 namespaces_.find(kLocalStorageNamespaceId); 109 namespaces_.find(kLocalStorageNamespaceId);
102 if (found != namespaces_.end()) 110 if (found != namespaces_.end())
103 found->second->PurgeMemory(); 111 found->second->PurgeMemory();
104 } 112 }
105 113
106 void DomStorageContext::Shutdown() { 114 void DomStorageContext::Shutdown() {
107 is_shutdown_ = true; 115 is_shutdown_ = true;
108 StorageNamespaceMap::const_iterator it = namespaces_.begin(); 116 StorageNamespaceMap::const_iterator it = namespaces_.begin();
109 for (; it != namespaces_.end(); ++it) 117 for (; it != namespaces_.end(); ++it)
110 it->second->Shutdown(); 118 it->second->Shutdown();
111 119
120 // Delete data from sessionStorage. If the previous exit was unclean, the
121 // session storage backing might contain leftover data. Delete it now.
122 if (session_storage_database_.get()) {
123 bool success = task_runner_->PostShutdownBlockingTask(
124 FROM_HERE,
125 DomStorageTaskRunner::COMMIT_SEQUENCE,
126 base::Bind(&DomStorageContext::DeleteLeftoverDataInCommitSequence,
127 this));
128 DCHECK(success);
129 }
130
131 // Delete data from localStorage.
112 if (localstorage_directory_.empty()) 132 if (localstorage_directory_.empty())
113 return; 133 return;
114 134
115 // Respect the content policy settings about what to 135 // Respect the content policy settings about what to
116 // keep and what to discard. 136 // keep and what to discard.
117 if (force_keep_session_state_) 137 if (force_keep_session_state_)
118 return; // Keep everything. 138 return; // Keep everything.
119 139
120 bool has_session_only_origins = 140 bool has_session_only_origins =
121 special_storage_policy_.get() && 141 special_storage_policy_.get() &&
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 } 183 }
164 184
165 void DomStorageContext::NotifyAreaCleared( 185 void DomStorageContext::NotifyAreaCleared(
166 const DomStorageArea* area, 186 const DomStorageArea* area,
167 const GURL& page_url) { 187 const GURL& page_url) {
168 FOR_EACH_OBSERVER( 188 FOR_EACH_OBSERVER(
169 EventObserver, event_observers_, 189 EventObserver, event_observers_,
170 OnDomStorageAreaCleared(area, page_url)); 190 OnDomStorageAreaCleared(area, page_url));
171 } 191 }
172 192
193 std::string DomStorageContext::AllocatePersistentSessionId() {
194 std::string guid = guid::GenerateGUID();
195 std::replace(guid.begin(), guid.end(), '-', '_');
196 return guid;
197 }
198
173 void DomStorageContext::CreateSessionNamespace( 199 void DomStorageContext::CreateSessionNamespace(
174 int64 namespace_id) { 200 int64 namespace_id,
201 const std::string& persistent_namespace_id) {
175 if (is_shutdown_) 202 if (is_shutdown_)
176 return; 203 return;
177 DCHECK(namespace_id != kLocalStorageNamespaceId); 204 DCHECK(namespace_id != kLocalStorageNamespaceId);
178 DCHECK(namespaces_.find(namespace_id) == namespaces_.end()); 205 DCHECK(namespaces_.find(namespace_id) == namespaces_.end());
179 namespaces_[namespace_id] = new DomStorageNamespace( 206 namespaces_[namespace_id] = new DomStorageNamespace(
180 namespace_id, task_runner_); 207 namespace_id, persistent_namespace_id, session_storage_database_.get(),
208 task_runner_);
181 } 209 }
182 210
183 void DomStorageContext::DeleteSessionNamespace( 211 void DomStorageContext::DeleteSessionNamespace(
184 int64 namespace_id) { 212 int64 namespace_id) {
185 DCHECK_NE(kLocalStorageNamespaceId, namespace_id); 213 DCHECK_NE(kLocalStorageNamespaceId, namespace_id);
214 StorageNamespaceMap::const_iterator it = namespaces_.find(namespace_id);
215 if (it == namespaces_.end())
216 return;
217 std::string persistent_namespace_id = it->second->persistent_namespace_id();
218 if (session_storage_database_.get()) {
219 if (doomed_persistent_session_ids_.find(persistent_namespace_id) !=
220 doomed_persistent_session_ids_.end()) {
221 bool success = task_runner_->PostShutdownBlockingTask(
222 FROM_HERE,
223 DomStorageTaskRunner::COMMIT_SEQUENCE,
224 base::Bind(
225 base::IgnoreResult(&SessionStorageDatabase::DeleteNamespace),
226 session_storage_database_,
227 persistent_namespace_id));
228 DCHECK(success);
229 } else {
230 // Protect the persistent namespace ID from leftover data deletion
231 // (DeleteLeftoverDataInCommitSequence).
232 protected_persistent_session_ids_.insert(persistent_namespace_id);
233 }
234 }
186 namespaces_.erase(namespace_id); 235 namespaces_.erase(namespace_id);
236 doomed_persistent_session_ids_.erase(persistent_namespace_id);
187 } 237 }
188 238
189 void DomStorageContext::CloneSessionNamespace( 239 void DomStorageContext::CloneSessionNamespace(
190 int64 existing_id, int64 new_id) { 240 int64 existing_id, int64 new_id,
241 const std::string& new_persistent_id) {
191 if (is_shutdown_) 242 if (is_shutdown_)
192 return; 243 return;
193 DCHECK_NE(kLocalStorageNamespaceId, existing_id); 244 DCHECK_NE(kLocalStorageNamespaceId, existing_id);
194 DCHECK_NE(kLocalStorageNamespaceId, new_id); 245 DCHECK_NE(kLocalStorageNamespaceId, new_id);
195 StorageNamespaceMap::iterator found = namespaces_.find(existing_id); 246 StorageNamespaceMap::iterator found = namespaces_.find(existing_id);
196 if (found != namespaces_.end()) 247 if (found != namespaces_.end())
197 namespaces_[new_id] = found->second->Clone(new_id); 248 namespaces_[new_id] = found->second->Clone(new_id, new_persistent_id);
198 else 249 else
199 CreateSessionNamespace(new_id); 250 CreateSessionNamespace(new_id, new_persistent_id);
251 }
252
253 void DomStorageContext::DoomSessionStorage(
254 const std::string& persistent_namespace_id) {
255 doomed_persistent_session_ids_.insert(persistent_namespace_id);
200 } 256 }
201 257
202 void DomStorageContext::ClearSessionOnlyOrigins() { 258 void DomStorageContext::ClearSessionOnlyOrigins() {
203 std::vector<UsageInfo> infos; 259 std::vector<UsageInfo> infos;
204 const bool kDontIncludeFileInfo = false; 260 const bool kDontIncludeFileInfo = false;
205 GetUsageInfo(&infos, kDontIncludeFileInfo); 261 GetUsageInfo(&infos, kDontIncludeFileInfo);
206 for (size_t i = 0; i < infos.size(); ++i) { 262 for (size_t i = 0; i < infos.size(); ++i) {
207 const GURL& origin = infos[i].origin; 263 const GURL& origin = infos[i].origin;
208 if (special_storage_policy_->IsStorageProtected(origin)) 264 if (special_storage_policy_->IsStorageProtected(origin))
209 continue; 265 continue;
210 if (!special_storage_policy_->IsStorageSessionOnly(origin)) 266 if (!special_storage_policy_->IsStorageSessionOnly(origin))
211 continue; 267 continue;
212 268
213 const bool kNotRecursive = false; 269 const bool kNotRecursive = false;
214 FilePath database_file_path = localstorage_directory_.Append( 270 FilePath database_file_path = localstorage_directory_.Append(
215 DomStorageArea::DatabaseFileNameFromOrigin(origin)); 271 DomStorageArea::DatabaseFileNameFromOrigin(origin));
216 file_util::Delete(database_file_path, kNotRecursive); 272 file_util::Delete(database_file_path, kNotRecursive);
217 file_util::Delete( 273 file_util::Delete(
218 DomStorageDatabase::GetJournalFilePath(database_file_path), 274 DomStorageDatabase::GetJournalFilePath(database_file_path),
219 kNotRecursive); 275 kNotRecursive);
220 } 276 }
221 } 277 }
222 278
279 void DomStorageContext::DeleteLeftoverDataInCommitSequence() {
280 DCHECK(session_storage_database_.get());
281 // Delete all namespaces which don't have an associated DomStorageNamespace
282 // alive.
283 std::set<std::string> namespace_ids_in_use;
284 for (StorageNamespaceMap::const_iterator it = namespaces_.begin();
285 it != namespaces_.end(); ++it)
286 namespace_ids_in_use.insert(it->second->persistent_namespace_id());
287
288 std::vector<std::string> namespace_ids;
289 session_storage_database_->ReadNamespaceIds(&namespace_ids);
290 for (std::vector<std::string>::const_iterator it = namespace_ids.begin();
291 it != namespace_ids.end(); ++it) {
292 if (namespace_ids_in_use.find(*it) == namespace_ids_in_use.end() &&
293 protected_persistent_session_ids_.find(*it) ==
294 protected_persistent_session_ids_.end())
295 session_storage_database_->DeleteNamespace(*it);
296 }
297 }
298
223 } // namespace dom_storage 299 } // namespace dom_storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698