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

Side by Side Diff: content/browser/dom_storage/dom_storage_context_impl_new.cc

Issue 9695013: DOMStorageContextImpl that's implemented in terms of the new dom_storage classes. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 9 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/in_process_webkit/dom_storage_context_impl.h" 5 #include "content/browser/dom_storage/dom_storage_context_impl_new.h"
6 6
7 #include <algorithm> 7 #ifdef ENABLE_NEW_DOM_STORAGE_BACKEND
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/file_path.h" 10 #include "base/bind_helpers.h"
11 #include "base/file_util.h" 11 #include "base/message_loop_proxy.h"
12 #include "base/string_util.h"
13 #include "content/browser/in_process_webkit/dom_storage_area.h"
14 #include "content/browser/in_process_webkit/dom_storage_namespace.h"
15 #include "content/common/dom_storage_common.h"
16 #include "content/public/browser/browser_thread.h" 12 #include "content/public/browser/browser_thread.h"
17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
18 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" 13 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
14 #include "webkit/database/database_util.h"
15 #include "webkit/dom_storage/dom_storage_area.h"
16 #include "webkit/dom_storage/dom_storage_context.h"
17 #include "webkit/dom_storage/dom_storage_task_runner.h"
19 #include "webkit/glue/webkit_glue.h" 18 #include "webkit/glue/webkit_glue.h"
20 #include "webkit/quota/special_storage_policy.h"
21 19
22 using content::BrowserThread; 20 using content::BrowserThread;
23 using content::DOMStorageContext; 21 using content::DOMStorageContext;
24 using WebKit::WebSecurityOrigin; 22 using dom_storage::DomStorageArea;
25 23 using dom_storage::DomStorageContext;
26 const FilePath::CharType DOMStorageContextImpl::kLocalStorageDirectory[] = 24 using dom_storage::DomStorageWorkerPoolTaskRunner;
27 FILE_PATH_LITERAL("Local Storage"); 25 using webkit_database::DatabaseUtil;
28
29 const FilePath::CharType DOMStorageContextImpl::kLocalStorageExtension[] =
30 FILE_PATH_LITERAL(".localstorage");
31 26
32 namespace { 27 namespace {
33 28
34 void ClearLocalState(const FilePath& domstorage_path, 29 const char kLocalStorageDirectory[] = "Local Storage";
35 quota::SpecialStoragePolicy* special_storage_policy, 30
36 bool clear_all_databases) { 31 // TODO(michaeln): Fix the content layer api, FilePaths and
37 file_util::FileEnumerator file_enumerator( 32 // string16 origin_ids are just wrong. Then get rid of
38 domstorage_path, false, file_util::FileEnumerator::FILES); 33 // this conversion non-sense. Most of the includes are just
39 for (FilePath file_path = file_enumerator.Next(); !file_path.empty(); 34 // to support that non-sense.
40 file_path = file_enumerator.Next()) { 35
41 if (file_path.Extension() == 36 GURL OriginIdToGURL(const string16& origin_id) {
42 DOMStorageContextImpl::kLocalStorageExtension) { 37 return DatabaseUtil::GetOriginFromIdentifier(origin_id);
43 GURL origin(WebSecurityOrigin::createFromDatabaseIdentifier(
44 webkit_glue::FilePathToWebString(file_path.BaseName())).toString());
45 if (special_storage_policy &&
46 special_storage_policy->IsStorageProtected(origin))
47 continue;
48 if (!clear_all_databases &&
49 !special_storage_policy->IsStorageSessionOnly(origin)) {
50 continue;
51 }
52 file_util::Delete(file_path, false);
53 }
54 }
55 } 38 }
56 39
57 } // namespace 40 FilePath OriginToFullFilePath(const FilePath& directory,
41 const GURL& origin) {
42 return directory.Append(DomStorageArea::DatabaseFileNameFromOrigin(origin));
43 }
44
45 GURL FilePathToOrigin(const FilePath& path) {
46 DCHECK(path.MatchesExtension(DomStorageArea::kDatabaseFileExtension));
47 return OriginIdToGURL(
48 webkit_glue::FilePathToWebString(path.BaseName().RemoveExtension()));
49 }
50
51 void InvokeAllStorageFilesCallbackHelper(
52 const DOMStorageContext::GetAllStorageFilesCallback& callback,
53 const std::vector<FilePath>& file_paths) {
54 callback.Run(file_paths);
55 }
56
57 void GetAllStorageFilesHelper(
58 base::MessageLoopProxy* reply_loop,
59 DomStorageContext* context,
60 const DOMStorageContext::GetAllStorageFilesCallback& callback) {
61 std::vector<DomStorageContext::UsageInfo> infos;
62 context->GetUsageInfo(&infos);
63
64 std::vector<FilePath> paths;
65 for (size_t i = 0; i < infos.size(); ++i) {
66 paths.push_back(
67 OriginToFullFilePath(context->directory(), infos[i].origin));
68 }
69
70 reply_loop->PostTask(
71 FROM_HERE,
72 base::Bind(&InvokeAllStorageFilesCallbackHelper,
73 callback, paths));
74 }
75
76 }
58 77
59 DOMStorageContextImpl::DOMStorageContextImpl( 78 DOMStorageContextImpl::DOMStorageContextImpl(
60 const FilePath& data_path, 79 const FilePath& data_path,
61 quota::SpecialStoragePolicy* special_storage_policy) 80 quota::SpecialStoragePolicy* special_storage_policy) {
62 : last_storage_area_id_(0), 81 base::SequencedWorkerPool* worker_pool = BrowserThread::GetBlockingPool();
63 last_session_storage_namespace_id_on_ui_thread_(kLocalStorageNamespaceId), 82 context_ = new dom_storage::DomStorageContext(
64 last_session_storage_namespace_id_on_io_thread_(kLocalStorageNamespaceId), 83 data_path.empty() ?
65 clear_local_state_on_exit_(false), 84 data_path : data_path.AppendASCII(kLocalStorageDirectory),
66 save_session_state_(false), 85 special_storage_policy,
67 special_storage_policy_(special_storage_policy), 86 new DomStorageWorkerPoolTaskRunner(
68 webkit_message_loop_( 87 worker_pool,
69 BrowserThread::GetMessageLoopProxyForThread( 88 worker_pool->GetNamedSequenceToken("dom_storage"),
70 BrowserThread::WEBKIT_DEPRECATED)) { 89 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)));
71 data_path_ = data_path;
72 } 90 }
73 91
74 DOMStorageContextImpl::~DOMStorageContextImpl() { 92 DOMStorageContextImpl::~DOMStorageContextImpl() {
75 // This should not go away until all DOM Storage message filters have gone
76 // away. And they remove themselves from this list.
77 DCHECK(message_filter_set_.empty());
78
79 for (StorageNamespaceMap::iterator iter(storage_namespace_map_.begin());
80 iter != storage_namespace_map_.end(); ++iter) {
81 delete iter->second;
82 }
83
84 if (save_session_state_)
85 return;
86
87 bool has_session_only_databases =
88 special_storage_policy_.get() &&
89 special_storage_policy_->HasSessionOnlyOrigins();
90
91 // Clearning only session-only databases, and there are none.
92 if (!clear_local_state_on_exit_ && !has_session_only_databases)
93 return;
94
95 // Not being on the WEBKIT thread here means we are running in a unit test
96 // where no clean up is needed.
97 if (BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)) {
98 ClearLocalState(data_path_.Append(kLocalStorageDirectory),
99 special_storage_policy_,
100 clear_local_state_on_exit_);
101 }
102 } 93 }
103 94
104 int64 DOMStorageContextImpl::AllocateStorageAreaId() { 95 void DOMStorageContextImpl::GetAllStorageFiles(
105 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); 96 const GetAllStorageFilesCallback& callback) {
106 return ++last_storage_area_id_; 97 DCHECK(context_);
98 context_->task_runner()->PostTask(
99 FROM_HERE,
100 base::Bind(&GetAllStorageFilesHelper,
101 base::MessageLoopProxy::current(),
102 context_, callback));
107 } 103 }
108 104
109 int64 DOMStorageContextImpl::AllocateSessionStorageNamespaceId() { 105 FilePath DOMStorageContextImpl::GetFilePath(const string16& origin_id) const {
110 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) 106 DCHECK(context_);
111 return ++last_session_storage_namespace_id_on_ui_thread_; 107 return OriginToFullFilePath(context_->directory(), OriginIdToGURL(origin_id));
112 return --last_session_storage_namespace_id_on_io_thread_;
113 } 108 }
114 109
115 int64 DOMStorageContextImpl::CloneSessionStorage(int64 original_id) { 110 void DOMStorageContextImpl::DeleteForOrigin(const string16& origin_id) {
116 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); 111 DCHECK(context_);
117 int64 clone_id = AllocateSessionStorageNamespaceId(); 112 context_->task_runner()->PostTask(
118 BrowserThread::PostTask( 113 FROM_HERE,
119 BrowserThread::WEBKIT_DEPRECATED, FROM_HERE, 114 base::Bind(&DomStorageContext::DeleteOrigin, context_,
120 base::Bind(&DOMStorageContextImpl::CompleteCloningSessionStorage, 115 OriginIdToGURL(origin_id)));
121 this, original_id, clone_id)); 116 }
117
118 void DOMStorageContextImpl::DeleteLocalStorageFile(const FilePath& file_path) {
119 DCHECK(context_);
120 context_->task_runner()->PostTask(
121 FROM_HERE,
122 base::Bind(&DomStorageContext::DeleteOrigin, context_,
123 FilePathToOrigin(file_path)));
124 }
125
126 void DOMStorageContextImpl::DeleteDataModifiedSince(const base::Time& cutoff) {
127 DCHECK(context_);
128 context_->task_runner()->PostTask(
129 FROM_HERE,
130 base::Bind(&DomStorageContext::DeleteDataModifiedSince, context_,
131 cutoff));
132 }
133
134 void DOMStorageContextImpl::PurgeMemory() {
135 DCHECK(context_);
136 context_->task_runner()->PostTask(
137 FROM_HERE,
138 base::Bind(&DomStorageContext::PurgeMemory, context_));
139 }
140
141 void DOMStorageContextImpl::SetClearLocalState(bool clear_local_state) {
142 DCHECK(context_);
143 context_->task_runner()->PostTask(
144 FROM_HERE,
145 base::Bind(&DomStorageContext::SetClearLocalState, context_,
146 clear_local_state));
147 }
148
149 void DOMStorageContextImpl::SaveSessionState() {
150 DCHECK(context_);
151 context_->task_runner()->PostTask(
152 FROM_HERE,
153 base::Bind(&DomStorageContext::SaveSessionState, context_));
154 }
155
156 void DOMStorageContextImpl::Shutdown() {
157 DCHECK(context_);
158 context_->task_runner()->PostTask(
159 FROM_HERE,
160 base::Bind(&DomStorageContext::Shutdown, context_));
161 }
162
163 int64 DOMStorageContextImpl::LeakyCloneSessionStorage(
164 int64 existing_namespace_id) {
165 DCHECK(context_);
166 int64 clone_id = context_->AllocateSessionId();
167 context_->task_runner()->PostTask(
168 FROM_HERE,
169 base::Bind(&DomStorageContext::CloneSessionNamespace, context_,
170 existing_namespace_id, clone_id));
122 return clone_id; 171 return clone_id;
123 } 172 }
124 173
125 void DOMStorageContextImpl::RegisterStorageArea(DOMStorageArea* storage_area) { 174 #endif // ENABLE_NEW_DOM_STORAGE_BACKEND
126 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
127 int64 id = storage_area->id();
128 DCHECK(!GetStorageArea(id));
129 storage_area_map_[id] = storage_area;
130 }
131
132 void DOMStorageContextImpl::UnregisterStorageArea(
133 DOMStorageArea* storage_area) {
134 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
135 int64 id = storage_area->id();
136 DCHECK(GetStorageArea(id));
137 storage_area_map_.erase(id);
138 }
139
140 DOMStorageArea* DOMStorageContextImpl::GetStorageArea(int64 id) {
141 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
142 StorageAreaMap::iterator iter = storage_area_map_.find(id);
143 if (iter == storage_area_map_.end())
144 return NULL;
145 return iter->second;
146 }
147
148 void DOMStorageContextImpl::DeleteSessionStorageNamespace(int64 namespace_id) {
149 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED) ||
150 !BrowserThread::IsMessageLoopValid(BrowserThread::WEBKIT_DEPRECATED));
151 StorageNamespaceMap::iterator iter =
152 storage_namespace_map_.find(namespace_id);
153 if (iter == storage_namespace_map_.end())
154 return;
155 DCHECK(iter->second->dom_storage_type() == DOM_STORAGE_SESSION);
156 delete iter->second;
157 storage_namespace_map_.erase(iter);
158 }
159
160 DOMStorageNamespace* DOMStorageContextImpl::GetStorageNamespace(
161 int64 id, bool allocation_allowed) {
162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
163 StorageNamespaceMap::iterator iter = storage_namespace_map_.find(id);
164 if (iter != storage_namespace_map_.end())
165 return iter->second;
166 if (!allocation_allowed)
167 return NULL;
168 if (id == kLocalStorageNamespaceId)
169 return CreateLocalStorage();
170 return CreateSessionStorage(id);
171 }
172
173 void DOMStorageContextImpl::RegisterMessageFilter(
174 DOMStorageMessageFilter* message_filter) {
175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
176 DCHECK(message_filter_set_.find(message_filter) ==
177 message_filter_set_.end());
178 message_filter_set_.insert(message_filter);
179 }
180
181 void DOMStorageContextImpl::UnregisterMessageFilter(
182 DOMStorageMessageFilter* message_filter) {
183 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
184 DCHECK(message_filter_set_.find(message_filter) !=
185 message_filter_set_.end());
186 message_filter_set_.erase(message_filter);
187 }
188
189 const DOMStorageContextImpl::MessageFilterSet*
190 DOMStorageContextImpl::GetMessageFilterSet() const {
191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
192 return &message_filter_set_;
193 }
194
195 void DOMStorageContextImpl::PurgeMemory() {
196 // It is only safe to purge the memory from the LocalStorage namespace,
197 // because it is backed by disk and can be reloaded later. If we purge a
198 // SessionStorage namespace, its data will be gone forever, because it isn't
199 // currently backed by disk.
200 DOMStorageNamespace* local_storage =
201 GetStorageNamespace(kLocalStorageNamespaceId, false);
202 if (local_storage)
203 local_storage->PurgeMemory();
204 }
205
206 void DOMStorageContextImpl::DeleteDataModifiedSince(const base::Time& cutoff) {
207 // Make sure that we don't delete a database that's currently being accessed
208 // by unloading all of the databases temporarily.
209 PurgeMemory();
210
211 file_util::FileEnumerator file_enumerator(
212 data_path_.Append(kLocalStorageDirectory), false,
213 file_util::FileEnumerator::FILES);
214 for (FilePath path = file_enumerator.Next(); !path.value().empty();
215 path = file_enumerator.Next()) {
216 GURL origin(WebSecurityOrigin::createFromDatabaseIdentifier(
217 webkit_glue::FilePathToWebString(path.BaseName())).toString());
218 if (special_storage_policy_->IsStorageProtected(origin))
219 continue;
220
221 file_util::FileEnumerator::FindInfo find_info;
222 file_enumerator.GetFindInfo(&find_info);
223 if (file_util::HasFileBeenModifiedSince(find_info, cutoff))
224 file_util::Delete(path, false);
225 }
226 }
227
228 void DOMStorageContextImpl::DeleteLocalStorageFile(const FilePath& file_path) {
229 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
230
231 // Make sure that we don't delete a database that's currently being accessed
232 // by unloading all of the databases temporarily.
233 // TODO(bulach): both this method and DeleteDataModifiedSince could purge
234 // only the memory used by the specific file instead of all memory at once.
235 // See http://crbug.com/32000
236 PurgeMemory();
237 file_util::Delete(file_path, false);
238 }
239
240 void DOMStorageContextImpl::DeleteForOrigin(const string16& origin_id) {
241 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
242 DeleteLocalStorageFile(GetFilePath(origin_id));
243 }
244
245 void DOMStorageContextImpl::DeleteAllLocalStorageFiles() {
246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
247
248 // Make sure that we don't delete a database that's currently being accessed
249 // by unloading all of the databases temporarily.
250 PurgeMemory();
251
252 file_util::FileEnumerator file_enumerator(
253 data_path_.Append(kLocalStorageDirectory), false,
254 file_util::FileEnumerator::FILES);
255 for (FilePath file_path = file_enumerator.Next(); !file_path.empty();
256 file_path = file_enumerator.Next()) {
257 if (file_path.Extension() == kLocalStorageExtension)
258 file_util::Delete(file_path, false);
259 }
260 }
261
262 DOMStorageNamespace* DOMStorageContextImpl::CreateLocalStorage() {
263 FilePath dir_path;
264 if (!data_path_.empty())
265 dir_path = data_path_.Append(kLocalStorageDirectory);
266 DOMStorageNamespace* new_namespace =
267 DOMStorageNamespace::CreateLocalStorageNamespace(this, dir_path);
268 RegisterStorageNamespace(new_namespace);
269 return new_namespace;
270 }
271
272 DOMStorageNamespace* DOMStorageContextImpl::CreateSessionStorage(
273 int64 namespace_id) {
274 DOMStorageNamespace* new_namespace =
275 DOMStorageNamespace::CreateSessionStorageNamespace(this, namespace_id);
276 RegisterStorageNamespace(new_namespace);
277 return new_namespace;
278 }
279
280 void DOMStorageContextImpl::RegisterStorageNamespace(
281 DOMStorageNamespace* storage_namespace) {
282 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
283 int64 id = storage_namespace->id();
284 DCHECK(!GetStorageNamespace(id, false));
285 storage_namespace_map_[id] = storage_namespace;
286 }
287
288 void DOMStorageContextImpl::CompleteCloningSessionStorage(
289 int64 existing_id, int64 clone_id) {
290 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
291 DOMStorageNamespace* existing_namespace =
292 GetStorageNamespace(existing_id, false);
293 // If nothing exists, then there's nothing to clone.
294 if (existing_namespace)
295 RegisterStorageNamespace(existing_namespace->Copy(clone_id));
296 }
297
298 base::SequencedTaskRunner* DOMStorageContextImpl::task_runner() const {
299 return webkit_message_loop_;
300 }
301
302 std::vector<FilePath> DOMStorageContextImpl::GetAllStorageFiles() {
303 std::vector<FilePath> files;
304 file_util::FileEnumerator file_enumerator(
305 data_path_.Append(kLocalStorageDirectory), false,
306 file_util::FileEnumerator::FILES);
307 for (FilePath file_path = file_enumerator.Next(); !file_path.empty();
308 file_path = file_enumerator.Next()) {
309 if (file_path.Extension() == kLocalStorageExtension)
310 files.push_back(file_path);
311 }
312 return files;
313 }
314
315 FilePath DOMStorageContextImpl::GetFilePath(const string16& origin_id) const {
316 FilePath storage_dir = data_path_.Append(kLocalStorageDirectory);
317 FilePath::StringType id = webkit_glue::WebStringToFilePathString(origin_id);
318 return storage_dir.Append(id.append(kLocalStorageExtension));
319 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698