OLD | NEW |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |