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

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

Issue 9146025: Framing for a DOMStorage backend that does not depend on in-process-webkit. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 8 years, 10 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) 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 "content/browser/in_process_webkit/dom_storage_context.h" 5 #include "webkit/dom_storage/dom_storage_context.h"
6
7 #include <algorithm>
8 6
9 #include "base/bind.h" 7 #include "base/bind.h"
10 #include "base/file_path.h" 8 #include "base/bind_helpers.h"
11 #include "base/file_util.h" 9 #include "base/time.h"
12 #include "base/string_util.h" 10 //#include "webkit/dom_storage/dom_storage_area.h"
13 #include "content/browser/in_process_webkit/dom_storage_area.h" 11 #include "webkit/dom_storage/dom_storage_namespace.h"
14 #include "content/browser/in_process_webkit/dom_storage_namespace.h" 12 #include "webkit/dom_storage/dom_storage_task_runner.h"
15 #include "content/browser/in_process_webkit/webkit_context.h"
16 #include "content/common/dom_storage_common.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
19 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
20 #include "webkit/glue/webkit_glue.h"
21 #include "webkit/quota/special_storage_policy.h" 13 #include "webkit/quota/special_storage_policy.h"
22 14
23 using content::BrowserThread; 15 namespace dom_storage {
24 16
25 using WebKit::WebSecurityOrigin; 17 DomStorageContext::DomStorageContext(
26 18 const FilePath& directory,
27 namespace { 19 quota::SpecialStoragePolicy* special_storage_policy,
28 20 DomStorageTaskRunner* task_runner)
29 void ClearLocalState(const FilePath& domstorage_path, 21 : directory_(directory),
30 quota::SpecialStoragePolicy* special_storage_policy, 22 task_runner_(task_runner) {
31 bool clear_all_databases) { 23 // AtomicSequenceNum starts at 0 but we want to start at one.
benm (inactive) 2012/02/02 16:23:19 ... because of the local storage special id? Maybe
michaeln 2012/02/03 00:33:42 Done.
32 file_util::FileEnumerator file_enumerator( 24 session_id_sequence_.GetNext();
33 domstorage_path, false, file_util::FileEnumerator::FILES);
34 for (FilePath file_path = file_enumerator.Next(); !file_path.empty();
35 file_path = file_enumerator.Next()) {
36 if (file_path.Extension() == DOMStorageContext::kLocalStorageExtension) {
37 GURL origin(WebSecurityOrigin::createFromDatabaseIdentifier(
38 webkit_glue::FilePathToWebString(file_path.BaseName())).toString());
39 if (special_storage_policy->IsStorageProtected(origin))
40 continue;
41 if (!clear_all_databases &&
42 !special_storage_policy->IsStorageSessionOnly(origin)) {
43 continue;
44 }
45 file_util::Delete(file_path, false);
46 }
47 }
48 } 25 }
49 26
50 } // namespace 27 DomStorageContext::~DomStorageContext() {
51
52 const FilePath::CharType DOMStorageContext::kLocalStorageDirectory[] =
53 FILE_PATH_LITERAL("Local Storage");
54
55 const FilePath::CharType DOMStorageContext::kLocalStorageExtension[] =
56 FILE_PATH_LITERAL(".localstorage");
57
58 DOMStorageContext::DOMStorageContext(
59 WebKitContext* webkit_context,
60 quota::SpecialStoragePolicy* special_storage_policy)
61 : last_storage_area_id_(0),
62 last_session_storage_namespace_id_on_ui_thread_(kLocalStorageNamespaceId),
63 last_session_storage_namespace_id_on_io_thread_(kLocalStorageNamespaceId),
64 clear_local_state_on_exit_(false),
65 save_session_state_(false),
66 special_storage_policy_(special_storage_policy) {
67 data_path_ = webkit_context->data_path();
68 } 28 }
69 29
70 DOMStorageContext::~DOMStorageContext() { 30 DomStorageNamespace* DomStorageContext::GetStorageNamespace(
71 // This should not go away until all DOM Storage message filters have gone 31 int64 namespace_id) {
72 // away. And they remove themselves from this list. 32 StorageNamespaceMap::iterator found = namespaces_.find(namespace_id);
73 DCHECK(message_filter_set_.empty()); 33 if (found == namespaces_.end()) {
74 34 if (namespace_id == kLocalStorageNamespaceId) {
75 for (StorageNamespaceMap::iterator iter(storage_namespace_map_.begin()); 35 DomStorageNamespace* local = new DomStorageNamespace(
76 iter != storage_namespace_map_.end(); ++iter) { 36 kLocalStorageNamespaceId, directory_, task_runner_);
77 delete iter->second; 37 namespaces_[kLocalStorageNamespaceId] = local;
38 return local;
39 }
40 return NULL;
78 } 41 }
79 42 return found->second;
80 if (save_session_state_)
81 return;
82
83 bool has_session_only_databases =
84 special_storage_policy_.get() &&
85 special_storage_policy_->HasSessionOnlyOrigins();
86
87 // Clearning only session-only databases, and there are none.
88 if (!clear_local_state_on_exit_ && !has_session_only_databases)
89 return;
90
91 // Not being on the WEBKIT thread here means we are running in a unit test
92 // where no clean up is needed.
93 if (BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)) {
94 ClearLocalState(data_path_.Append(kLocalStorageDirectory),
95 special_storage_policy_,
96 clear_local_state_on_exit_);
97 }
98 } 43 }
99 44
100 int64 DOMStorageContext::AllocateStorageAreaId() { 45 void DomStorageContext::AddEventObserver(EventObserver* observer) {
101 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); 46 event_observers_.AddObserver(observer);
102 return ++last_storage_area_id_;
103 } 47 }
104 48
105 int64 DOMStorageContext::AllocateSessionStorageNamespaceId() { 49 void DomStorageContext::RemoveEventObserver(EventObserver* observer) {
106 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) 50 event_observers_.RemoveObserver(observer);
107 return ++last_session_storage_namespace_id_on_ui_thread_;
108 return --last_session_storage_namespace_id_on_io_thread_;
109 } 51 }
110 52
111 int64 DOMStorageContext::CloneSessionStorage(int64 original_id) { 53 void DomStorageContext::NotifyItemSet(
112 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); 54 const DomStorageArea* area,
113 int64 clone_id = AllocateSessionStorageNamespaceId(); 55 const string16& key,
114 BrowserThread::PostTask( 56 const string16& new_value,
115 BrowserThread::WEBKIT_DEPRECATED, FROM_HERE, 57 const NullableString16& old_value,
116 base::Bind(&DOMStorageContext::CompleteCloningSessionStorage, this, 58 const GURL& page_url) {
117 original_id, clone_id)); 59 FOR_EACH_OBSERVER(
118 return clone_id; 60 EventObserver, event_observers_,
61 OnDomStorageItemSet(area, key, new_value, old_value, page_url));
119 } 62 }
120 63
121 void DOMStorageContext::RegisterStorageArea(DOMStorageArea* storage_area) { 64 void DomStorageContext::NotifyItemRemoved(
122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); 65 const DomStorageArea* area,
123 int64 id = storage_area->id(); 66 const string16& key,
124 DCHECK(!GetStorageArea(id)); 67 const string16& old_value,
125 storage_area_map_[id] = storage_area; 68 const GURL& page_url) {
69 FOR_EACH_OBSERVER(
70 EventObserver, event_observers_,
71 OnDomStorageItemRemoved(area, key, old_value, page_url));
126 } 72 }
127 73
128 void DOMStorageContext::UnregisterStorageArea(DOMStorageArea* storage_area) { 74 void DomStorageContext::NotifyAreaCleared(
129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); 75 const DomStorageArea* area,
130 int64 id = storage_area->id(); 76 const GURL& page_url) {
131 DCHECK(GetStorageArea(id)); 77 FOR_EACH_OBSERVER(
132 storage_area_map_.erase(id); 78 EventObserver, event_observers_,
79 OnDomStorageAreaCleared(area, page_url));
133 } 80 }
134 81
135 DOMStorageArea* DOMStorageContext::GetStorageArea(int64 id) { 82 void DomStorageContext::CreateSessionNamespace(
136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); 83 int64 namespace_id) {
137 StorageAreaMap::iterator iter = storage_area_map_.find(id); 84 DCHECK(namespace_id != kLocalStorageNamespaceId);
138 if (iter == storage_area_map_.end()) 85 DCHECK(namespaces_.find(namespace_id) == namespaces_.end());
139 return NULL; 86 namespaces_[namespace_id] = new DomStorageNamespace(
140 return iter->second; 87 namespace_id, FilePath(), task_runner_);
141 } 88 }
142 89
143 void DOMStorageContext::DeleteSessionStorageNamespace(int64 namespace_id) { 90 void DomStorageContext::DeleteSessionNamespace(
144 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); 91 int64 namespace_id) {
145 StorageNamespaceMap::iterator iter = 92 DCHECK_NE(kLocalStorageNamespaceId, namespace_id);
146 storage_namespace_map_.find(namespace_id); 93 namespaces_.erase(namespace_id);
147 if (iter == storage_namespace_map_.end())
148 return;
149 DCHECK(iter->second->dom_storage_type() == DOM_STORAGE_SESSION);
150 delete iter->second;
151 storage_namespace_map_.erase(iter);
152 } 94 }
153 95
154 DOMStorageNamespace* DOMStorageContext::GetStorageNamespace( 96 void DomStorageContext::CloneSessionNamespace(
155 int64 id, bool allocation_allowed) { 97 int64 existing_id, int64 new_id) {
156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); 98 DCHECK_NE(kLocalStorageNamespaceId, existing_id);
157 StorageNamespaceMap::iterator iter = storage_namespace_map_.find(id); 99 DCHECK_NE(kLocalStorageNamespaceId, new_id);
158 if (iter != storage_namespace_map_.end()) 100 StorageNamespaceMap::iterator found = namespaces_.find(existing_id);
159 return iter->second; 101 if (found != namespaces_.end())
160 if (!allocation_allowed) 102 namespaces_[new_id] = found->second->Clone(new_id);
161 return NULL; 103 else
162 if (id == kLocalStorageNamespaceId) 104 CreateSessionNamespace(new_id);
163 return CreateLocalStorage();
164 return CreateSessionStorage(id);
165 } 105 }
166 106
167 void DOMStorageContext::RegisterMessageFilter( 107 } // namespace dom_storage
168 DOMStorageMessageFilter* message_filter) {
169 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
170 DCHECK(message_filter_set_.find(message_filter) ==
171 message_filter_set_.end());
172 message_filter_set_.insert(message_filter);
173 }
174 108
175 void DOMStorageContext::UnregisterMessageFilter(
176 DOMStorageMessageFilter* message_filter) {
177 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
178 DCHECK(message_filter_set_.find(message_filter) !=
179 message_filter_set_.end());
180 message_filter_set_.erase(message_filter);
181 }
182
183 const DOMStorageContext::MessageFilterSet*
184 DOMStorageContext::GetMessageFilterSet() const {
185 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
186 return &message_filter_set_;
187 }
188
189 void DOMStorageContext::PurgeMemory() {
190 // It is only safe to purge the memory from the LocalStorage namespace,
191 // because it is backed by disk and can be reloaded later. If we purge a
192 // SessionStorage namespace, its data will be gone forever, because it isn't
193 // currently backed by disk.
194 DOMStorageNamespace* local_storage =
195 GetStorageNamespace(kLocalStorageNamespaceId, false);
196 if (local_storage)
197 local_storage->PurgeMemory();
198 }
199
200 void DOMStorageContext::DeleteDataModifiedSince(const base::Time& cutoff) {
201 // Make sure that we don't delete a database that's currently being accessed
202 // by unloading all of the databases temporarily.
203 PurgeMemory();
204
205 file_util::FileEnumerator file_enumerator(
206 data_path_.Append(kLocalStorageDirectory), false,
207 file_util::FileEnumerator::FILES);
208 for (FilePath path = file_enumerator.Next(); !path.value().empty();
209 path = file_enumerator.Next()) {
210 GURL origin(WebSecurityOrigin::createFromDatabaseIdentifier(
211 webkit_glue::FilePathToWebString(path.BaseName())).toString());
212 if (special_storage_policy_->IsStorageProtected(origin))
213 continue;
214
215 file_util::FileEnumerator::FindInfo find_info;
216 file_enumerator.GetFindInfo(&find_info);
217 if (file_util::HasFileBeenModifiedSince(find_info, cutoff))
218 file_util::Delete(path, false);
219 }
220 }
221
222 void DOMStorageContext::DeleteLocalStorageFile(const FilePath& file_path) {
223 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
224
225 // Make sure that we don't delete a database that's currently being accessed
226 // by unloading all of the databases temporarily.
227 // TODO(bulach): both this method and DeleteDataModifiedSince could purge
228 // only the memory used by the specific file instead of all memory at once.
229 // See http://crbug.com/32000
230 PurgeMemory();
231 file_util::Delete(file_path, false);
232 }
233
234 void DOMStorageContext::DeleteLocalStorageForOrigin(const string16& origin_id) {
235 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
236 DeleteLocalStorageFile(GetLocalStorageFilePath(origin_id));
237 }
238
239 void DOMStorageContext::DeleteAllLocalStorageFiles() {
240 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
241
242 // Make sure that we don't delete a database that's currently being accessed
243 // by unloading all of the databases temporarily.
244 PurgeMemory();
245
246 file_util::FileEnumerator file_enumerator(
247 data_path_.Append(kLocalStorageDirectory), false,
248 file_util::FileEnumerator::FILES);
249 for (FilePath file_path = file_enumerator.Next(); !file_path.empty();
250 file_path = file_enumerator.Next()) {
251 if (file_path.Extension() == kLocalStorageExtension)
252 file_util::Delete(file_path, false);
253 }
254 }
255
256 DOMStorageNamespace* DOMStorageContext::CreateLocalStorage() {
257 FilePath dir_path;
258 if (!data_path_.empty())
259 dir_path = data_path_.Append(kLocalStorageDirectory);
260 DOMStorageNamespace* new_namespace =
261 DOMStorageNamespace::CreateLocalStorageNamespace(this, dir_path);
262 RegisterStorageNamespace(new_namespace);
263 return new_namespace;
264 }
265
266 DOMStorageNamespace* DOMStorageContext::CreateSessionStorage(
267 int64 namespace_id) {
268 DOMStorageNamespace* new_namespace =
269 DOMStorageNamespace::CreateSessionStorageNamespace(this, namespace_id);
270 RegisterStorageNamespace(new_namespace);
271 return new_namespace;
272 }
273
274 void DOMStorageContext::RegisterStorageNamespace(
275 DOMStorageNamespace* storage_namespace) {
276 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
277 int64 id = storage_namespace->id();
278 DCHECK(!GetStorageNamespace(id, false));
279 storage_namespace_map_[id] = storage_namespace;
280 }
281
282 /* static */
283 void DOMStorageContext::CompleteCloningSessionStorage(
284 DOMStorageContext* context, int64 existing_id, int64 clone_id) {
285 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
286 DOMStorageNamespace* existing_namespace =
287 context->GetStorageNamespace(existing_id, false);
288 // If nothing exists, then there's nothing to clone.
289 if (existing_namespace)
290 context->RegisterStorageNamespace(existing_namespace->Copy(clone_id));
291 }
292
293 FilePath DOMStorageContext::GetLocalStorageFilePath(
294 const string16& origin_id) const {
295 FilePath storageDir = data_path_.Append(
296 DOMStorageContext::kLocalStorageDirectory);
297 FilePath::StringType id =
298 webkit_glue::WebStringToFilePathString(origin_id);
299 return storageDir.Append(id.append(kLocalStorageExtension));
300 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698