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

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 clear_local_state_(false), 37 clear_local_state_(false),
35 save_session_state_(false), 38 save_session_state_(false),
36 special_storage_policy_(special_storage_policy) { 39 special_storage_policy_(special_storage_policy) {
37 // AtomicSequenceNum starts at 0 but we want to start session 40 // AtomicSequenceNum starts at 0 but we want to start session
38 // namespace ids at one since zero is reserved for the 41 // namespace ids at one since zero is reserved for the
39 // kLocalStorageNamespaceId. 42 // kLocalStorageNamespaceId.
40 session_id_sequence_.GetNext(); 43 session_id_sequence_.GetNext();
44 if (!sessionstorage_directory_.empty()) {
45 session_storage_database_ = new SessionStorageDatabase(
46 sessionstorage_directory_);
47 }
41 } 48 }
42 49
43 DomStorageContext::~DomStorageContext() { 50 DomStorageContext::~DomStorageContext() {
44 } 51 }
45 52
46 DomStorageNamespace* DomStorageContext::GetStorageNamespace( 53 DomStorageNamespace* DomStorageContext::GetStorageNamespace(
47 int64 namespace_id) { 54 int64 namespace_id) {
48 if (is_shutdown_) 55 if (is_shutdown_)
49 return NULL; 56 return NULL;
50 StorageNamespaceMap::iterator found = namespaces_.find(namespace_id); 57 StorageNamespaceMap::iterator found = namespaces_.find(namespace_id);
(...skipping 29 matching lines...) Expand all
80 info.origin = DomStorageArea::OriginFromDatabaseFileName(path); 87 info.origin = DomStorageArea::OriginFromDatabaseFileName(path);
81 if (include_file_info) { 88 if (include_file_info) {
82 FileEnumerator::FindInfo find_info; 89 FileEnumerator::FindInfo find_info;
83 enumerator.GetFindInfo(&find_info); 90 enumerator.GetFindInfo(&find_info);
84 info.data_size = FileEnumerator::GetFilesize(find_info); 91 info.data_size = FileEnumerator::GetFilesize(find_info);
85 info.last_modified = FileEnumerator::GetLastModifiedTime(find_info); 92 info.last_modified = FileEnumerator::GetLastModifiedTime(find_info);
86 } 93 }
87 infos->push_back(info); 94 infos->push_back(info);
88 } 95 }
89 } 96 }
97 // FIXME(marja): Get usage infos for sessionStorage (crbug.com/123599).
90 } 98 }
91 99
92 void DomStorageContext::DeleteOrigin(const GURL& origin) { 100 void DomStorageContext::DeleteOrigin(const GURL& origin) {
93 DCHECK(!is_shutdown_); 101 DCHECK(!is_shutdown_);
94 DomStorageNamespace* local = GetStorageNamespace(kLocalStorageNamespaceId); 102 DomStorageNamespace* local = GetStorageNamespace(kLocalStorageNamespaceId);
95 local->DeleteOrigin(origin); 103 local->DeleteOrigin(origin);
96 } 104 }
97 105
98 void DomStorageContext::DeleteDataModifiedSince(const base::Time& cutoff) { 106 void DomStorageContext::DeleteDataModifiedSince(const base::Time& cutoff) {
99 std::vector<UsageInfo> infos; 107 std::vector<UsageInfo> infos;
(...skipping 17 matching lines...) Expand all
117 if (found != namespaces_.end()) 125 if (found != namespaces_.end())
118 found->second->PurgeMemory(); 126 found->second->PurgeMemory();
119 } 127 }
120 128
121 void DomStorageContext::Shutdown() { 129 void DomStorageContext::Shutdown() {
122 is_shutdown_ = true; 130 is_shutdown_ = true;
123 StorageNamespaceMap::const_iterator it = namespaces_.begin(); 131 StorageNamespaceMap::const_iterator it = namespaces_.begin();
124 for (; it != namespaces_.end(); ++it) 132 for (; it != namespaces_.end(); ++it)
125 it->second->Shutdown(); 133 it->second->Shutdown();
126 134
135 // Delete data from sessionStorage. If the previous exit was unclean, the
136 // session storage backing might contain leftover data. Delete it now.
137 if (session_storage_database_.get()) {
138 bool success = task_runner_->PostShutdownBlockingTask(
139 FROM_HERE,
140 DomStorageTaskRunner::COMMIT_SEQUENCE,
141 base::Bind(&DomStorageContext::DeleteLeftoverDataInCommitSequence,
142 this));
143 DCHECK(success);
144 }
145
146 // Delete data from localStorage.
127 if (localstorage_directory_.empty()) 147 if (localstorage_directory_.empty())
128 return; 148 return;
129 149
130 // Respect the content policy settings about what to 150 // Respect the content policy settings about what to
131 // keep and what to discard. 151 // keep and what to discard.
132 if (save_session_state_) 152 if (save_session_state_)
133 return; // Keep everything. 153 return; // Keep everything.
134 154
135 bool has_session_only_origins = 155 bool has_session_only_origins =
136 special_storage_policy_.get() && 156 special_storage_policy_.get() &&
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 } 198 }
179 199
180 void DomStorageContext::NotifyAreaCleared( 200 void DomStorageContext::NotifyAreaCleared(
181 const DomStorageArea* area, 201 const DomStorageArea* area,
182 const GURL& page_url) { 202 const GURL& page_url) {
183 FOR_EACH_OBSERVER( 203 FOR_EACH_OBSERVER(
184 EventObserver, event_observers_, 204 EventObserver, event_observers_,
185 OnDomStorageAreaCleared(area, page_url)); 205 OnDomStorageAreaCleared(area, page_url));
186 } 206 }
187 207
208 std::string DomStorageContext::AllocatePersistentSessionId() {
209 std::string guid = guid::GenerateGUID();
210 std::replace(guid.begin(), guid.end(), '-', '_');
211 return guid;
212 }
213
188 void DomStorageContext::CreateSessionNamespace( 214 void DomStorageContext::CreateSessionNamespace(
189 int64 namespace_id) { 215 int64 namespace_id,
216 const std::string& persistent_namespace_id) {
190 if (is_shutdown_) 217 if (is_shutdown_)
191 return; 218 return;
192 DCHECK(namespace_id != kLocalStorageNamespaceId); 219 DCHECK(namespace_id != kLocalStorageNamespaceId);
193 DCHECK(namespaces_.find(namespace_id) == namespaces_.end()); 220 DCHECK(namespaces_.find(namespace_id) == namespaces_.end());
194 namespaces_[namespace_id] = new DomStorageNamespace( 221 namespaces_[namespace_id] = new DomStorageNamespace(
195 namespace_id, task_runner_); 222 namespace_id, persistent_namespace_id, session_storage_database_.get(),
223 task_runner_);
196 } 224 }
197 225
198 void DomStorageContext::DeleteSessionNamespace( 226 void DomStorageContext::DeleteSessionNamespace(
199 int64 namespace_id) { 227 int64 namespace_id) {
200 DCHECK_NE(kLocalStorageNamespaceId, namespace_id); 228 DCHECK_NE(kLocalStorageNamespaceId, namespace_id);
229 StorageNamespaceMap::const_iterator it = namespaces_.find(namespace_id);
230 if (it == namespaces_.end())
231 return;
232 if (session_storage_database_.get()) {
233 if (deletable_session_storages_.find(namespace_id) !=
234 deletable_session_storages_.end()) {
235 bool success = task_runner_->PostShutdownBlockingTask(
236 FROM_HERE,
237 DomStorageTaskRunner::COMMIT_SEQUENCE,
238 base::Bind(
239 base::IgnoreResult(&SessionStorageDatabase::DeleteNamespace),
240 session_storage_database_,
241 it->second->persistent_namespace_id()));
242 DCHECK(success);
243 } else {
244 // Protect the persistent namespace ID from leftover data deletion
245 // (DeleteLeftoverDataInCommitSequence).
246 protected_session_storages_.insert(it->second->persistent_namespace_id());
247 }
248 }
201 namespaces_.erase(namespace_id); 249 namespaces_.erase(namespace_id);
250 deletable_session_storages_.erase(namespace_id);
202 } 251 }
203 252
204 void DomStorageContext::CloneSessionNamespace( 253 void DomStorageContext::CloneSessionNamespace(
205 int64 existing_id, int64 new_id) { 254 int64 existing_id, int64 new_id,
255 const std::string& new_persistent_id) {
206 if (is_shutdown_) 256 if (is_shutdown_)
207 return; 257 return;
208 DCHECK_NE(kLocalStorageNamespaceId, existing_id); 258 DCHECK_NE(kLocalStorageNamespaceId, existing_id);
209 DCHECK_NE(kLocalStorageNamespaceId, new_id); 259 DCHECK_NE(kLocalStorageNamespaceId, new_id);
210 StorageNamespaceMap::iterator found = namespaces_.find(existing_id); 260 StorageNamespaceMap::iterator found = namespaces_.find(existing_id);
211 if (found != namespaces_.end()) 261 if (found != namespaces_.end())
212 namespaces_[new_id] = found->second->Clone(new_id); 262 namespaces_[new_id] = found->second->Clone(new_id, new_persistent_id);
213 else 263 else
214 CreateSessionNamespace(new_id); 264 CreateSessionNamespace(new_id, new_persistent_id);
265 }
266
267 void DomStorageContext::DoomSessionStorage(int64 namespace_id) {
268 deletable_session_storages_.insert(namespace_id);
215 } 269 }
216 270
217 void DomStorageContext::ClearLocalStateInCommitSequence() { 271 void DomStorageContext::ClearLocalStateInCommitSequence() {
218 std::vector<UsageInfo> infos; 272 std::vector<UsageInfo> infos;
219 const bool kDontIncludeFileInfo = false; 273 const bool kDontIncludeFileInfo = false;
220 GetUsageInfo(&infos, kDontIncludeFileInfo); 274 GetUsageInfo(&infos, kDontIncludeFileInfo);
221 for (size_t i = 0; i < infos.size(); ++i) { 275 for (size_t i = 0; i < infos.size(); ++i) {
222 const GURL& origin = infos[i].origin; 276 const GURL& origin = infos[i].origin;
223 if (special_storage_policy_ && 277 if (special_storage_policy_ &&
224 special_storage_policy_->IsStorageProtected(origin)) 278 special_storage_policy_->IsStorageProtected(origin))
225 continue; 279 continue;
226 if (!clear_local_state_ && 280 if (!clear_local_state_ &&
227 !special_storage_policy_->IsStorageSessionOnly(origin)) 281 !special_storage_policy_->IsStorageSessionOnly(origin))
228 continue; 282 continue;
229 283
230 const bool kNotRecursive = false; 284 const bool kNotRecursive = false;
231 FilePath database_file_path = localstorage_directory_.Append( 285 FilePath database_file_path = localstorage_directory_.Append(
232 DomStorageArea::DatabaseFileNameFromOrigin(origin)); 286 DomStorageArea::DatabaseFileNameFromOrigin(origin));
233 file_util::Delete(database_file_path, kNotRecursive); 287 file_util::Delete(database_file_path, kNotRecursive);
234 file_util::Delete( 288 file_util::Delete(
235 DomStorageDatabase::GetJournalFilePath(database_file_path), 289 DomStorageDatabase::GetJournalFilePath(database_file_path),
236 kNotRecursive); 290 kNotRecursive);
237 } 291 }
238 } 292 }
239 293
294 void DomStorageContext::DeleteLeftoverDataInCommitSequence() {
295 DCHECK(session_storage_database_.get());
296 // Delete all namespaces which don't have an associated DomStorageNamespace
297 // alive.
298 std::set<std::string> namespace_ids_in_use;
299 for (StorageNamespaceMap::const_iterator it = namespaces_.begin();
300 it != namespaces_.end(); ++it)
301 namespace_ids_in_use.insert(it->second->persistent_namespace_id());
302
303 std::vector<std::string> namespace_ids;
304 session_storage_database_->ReadNamespaceIds(&namespace_ids);
305 for (std::vector<std::string>::const_iterator it = namespace_ids.begin();
306 it != namespace_ids.end(); ++it) {
307 if (namespace_ids_in_use.find(*it) == namespace_ids_in_use.end() &&
308 protected_session_storages_.find(*it) ==
309 protected_session_storages_.end())
310 session_storage_database_->DeleteNamespace(*it);
311 }
312 }
313
240 } // namespace dom_storage 314 } // namespace dom_storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698