OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this |
2 // source code is governed by a BSD-style license that can be found in the | 2 // source code is governed by a BSD-style license that can be found in the |
3 // LICENSE file. | 3 // LICENSE file. |
4 | 4 |
5 #include "chrome/browser/in_process_webkit/dom_storage_context.h" | 5 #include "chrome/browser/in_process_webkit/dom_storage_context.h" |
6 | 6 |
7 #include "base/file_path.h" | 7 #include "base/file_path.h" |
8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
9 #include "chrome/browser/chrome_thread.h" | 9 #include "chrome/browser/chrome_thread.h" |
10 #include "chrome/browser/in_process_webkit/dom_storage_area.h" | 10 #include "chrome/browser/in_process_webkit/dom_storage_area.h" |
11 #include "chrome/browser/in_process_webkit/dom_storage_namespace.h" | 11 #include "chrome/browser/in_process_webkit/dom_storage_namespace.h" |
12 #include "chrome/browser/in_process_webkit/webkit_context.h" | 12 #include "chrome/browser/in_process_webkit/webkit_context.h" |
| 13 #include "chrome/common/dom_storage_common.h" |
13 | 14 |
14 static const char* kLocalStorageDirectory = "Local Storage"; | 15 static const char* kLocalStorageDirectory = "Local Storage"; |
15 | 16 |
16 // TODO(jorlow): Remove after Chrome 4 ships. | 17 // TODO(jorlow): Remove after Chrome 4 ships. |
17 static void MigrateLocalStorageDirectory(const FilePath& data_path) { | 18 static void MigrateLocalStorageDirectory(const FilePath& data_path) { |
18 FilePath new_path = data_path.AppendASCII(kLocalStorageDirectory); | 19 FilePath new_path = data_path.AppendASCII(kLocalStorageDirectory); |
19 FilePath old_path = data_path.AppendASCII("localStorage"); | 20 FilePath old_path = data_path.AppendASCII("localStorage"); |
20 if (!file_util::DirectoryExists(new_path) && | 21 if (!file_util::DirectoryExists(new_path) && |
21 file_util::DirectoryExists(old_path)) { | 22 file_util::DirectoryExists(old_path)) { |
22 file_util::Move(old_path, new_path); | 23 file_util::Move(old_path, new_path); |
23 } | 24 } |
24 } | 25 } |
25 | 26 |
26 DOMStorageContext::DOMStorageContext(WebKitContext* webkit_context) | 27 DOMStorageContext::DOMStorageContext(WebKitContext* webkit_context) |
27 : last_storage_area_id_(kFirstStorageAreaId), | 28 : last_storage_area_id_(0), |
28 last_storage_namespace_id_(kFirstStorageNamespaceId), | 29 last_session_storage_namespace_id_on_ui_thread_(kLocalStorageNamespaceId), |
| 30 last_session_storage_namespace_id_on_io_thread_(kLocalStorageNamespaceId), |
29 webkit_context_(webkit_context) { | 31 webkit_context_(webkit_context) { |
30 } | 32 } |
31 | 33 |
32 DOMStorageContext::~DOMStorageContext() { | 34 DOMStorageContext::~DOMStorageContext() { |
33 // This should not go away until all DOM Storage Dispatcher hosts have gone | 35 // This should not go away until all DOM Storage Dispatcher hosts have gone |
34 // away. And they remove themselves from this list. | 36 // away. And they remove themselves from this list. |
35 DCHECK(dispatcher_host_set_.empty()); | 37 DCHECK(dispatcher_host_set_.empty()); |
36 | 38 |
37 // If we don't have any work to do on the WebKit thread, bail. | 39 for (StorageNamespaceMap::iterator iter(storage_namespace_map_.begin()); |
38 if (storage_namespace_map_.empty()) | 40 iter != storage_namespace_map_.end(); ++iter) { |
39 return; | 41 delete iter->second; |
40 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); | 42 } |
41 | |
42 // The storage namespace destructor unregisters the storage namespace, so | |
43 // our iterator becomes invalid. Thus we just keep deleting the first item | |
44 // until there are none left. | |
45 while (!storage_namespace_map_.empty()) | |
46 delete storage_namespace_map_.begin()->second; | |
47 } | 43 } |
48 | 44 |
49 DOMStorageNamespace* DOMStorageContext::LocalStorage() { | 45 int64 DOMStorageContext::AllocateStorageAreaId() { |
50 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); | 46 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); |
51 DOMStorageNamespace* storage_namespace = GetStorageNamespace( | 47 return ++last_storage_area_id_; |
52 kLocalStorageNamespaceId); | |
53 if (storage_namespace) | |
54 return storage_namespace; | |
55 | |
56 FilePath data_path = webkit_context_->data_path(); | |
57 FilePath dir_path; | |
58 if (!data_path.empty()) { | |
59 MigrateLocalStorageDirectory(data_path); | |
60 dir_path = data_path.AppendASCII(kLocalStorageDirectory); | |
61 } | |
62 return DOMStorageNamespace::CreateLocalStorageNamespace(this, dir_path); | |
63 } | 48 } |
64 | 49 |
65 DOMStorageNamespace* DOMStorageContext::NewSessionStorage() { | 50 int64 DOMStorageContext::AllocateSessionStorageNamespaceId() { |
66 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); | 51 if (ChromeThread::CurrentlyOn(ChromeThread::UI)) |
67 return DOMStorageNamespace::CreateSessionStorageNamespace(this); | 52 return ++last_session_storage_namespace_id_on_ui_thread_; |
| 53 return --last_session_storage_namespace_id_on_io_thread_; |
| 54 } |
| 55 |
| 56 int64 DOMStorageContext::CloneSessionStorage(int64 original_id) { |
| 57 DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); |
| 58 int64 clone_id = AllocateSessionStorageNamespaceId(); |
| 59 ChromeThread::PostTask( |
| 60 ChromeThread::WEBKIT, FROM_HERE, NewRunnableFunction( |
| 61 &DOMStorageContext::CompleteCloningSessionStorage, |
| 62 this, original_id, clone_id)); |
| 63 return clone_id; |
68 } | 64 } |
69 | 65 |
70 void DOMStorageContext::RegisterStorageArea(DOMStorageArea* storage_area) { | 66 void DOMStorageContext::RegisterStorageArea(DOMStorageArea* storage_area) { |
71 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); | 67 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); |
72 int64 id = storage_area->id(); | 68 int64 id = storage_area->id(); |
73 DCHECK(!GetStorageArea(id)); | 69 DCHECK(!GetStorageArea(id)); |
74 storage_area_map_[id] = storage_area; | 70 storage_area_map_[id] = storage_area; |
75 } | 71 } |
76 | 72 |
77 void DOMStorageContext::UnregisterStorageArea(DOMStorageArea* storage_area) { | 73 void DOMStorageContext::UnregisterStorageArea(DOMStorageArea* storage_area) { |
78 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); | 74 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); |
79 int64 id = storage_area->id(); | 75 int64 id = storage_area->id(); |
80 DCHECK(GetStorageArea(id)); | 76 DCHECK(GetStorageArea(id)); |
81 storage_area_map_.erase(id); | 77 storage_area_map_.erase(id); |
82 } | 78 } |
83 | 79 |
84 DOMStorageArea* DOMStorageContext::GetStorageArea(int64 id) { | 80 DOMStorageArea* DOMStorageContext::GetStorageArea(int64 id) { |
85 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); | 81 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); |
86 StorageAreaMap::iterator iter = storage_area_map_.find(id); | 82 StorageAreaMap::iterator iter = storage_area_map_.find(id); |
87 if (iter == storage_area_map_.end()) | 83 if (iter == storage_area_map_.end()) |
88 return NULL; | 84 return NULL; |
89 return iter->second; | 85 return iter->second; |
90 } | 86 } |
91 | 87 |
92 void DOMStorageContext::RegisterStorageNamespace( | 88 void DOMStorageContext::DeleteSessionStorageNamespace(int64 namespace_id) { |
93 DOMStorageNamespace* storage_namespace) { | |
94 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); | 89 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); |
95 int64 id = storage_namespace->id(); | 90 StorageNamespaceMap::iterator iter = |
96 DCHECK(!GetStorageNamespace(id)); | 91 storage_namespace_map_.find(namespace_id); |
97 storage_namespace_map_[id] = storage_namespace; | 92 if (iter == storage_namespace_map_.end()) |
| 93 return; |
| 94 DCHECK(iter->second->dom_storage_type() == DOM_STORAGE_SESSION); |
| 95 delete iter->second; |
| 96 storage_namespace_map_.erase(iter); |
98 } | 97 } |
99 | 98 |
100 void DOMStorageContext::UnregisterStorageNamespace( | 99 DOMStorageNamespace* DOMStorageContext::GetStorageNamespace( |
101 DOMStorageNamespace* storage_namespace) { | 100 int64 id, bool allocation_allowed) { |
102 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); | |
103 int64 id = storage_namespace->id(); | |
104 DCHECK(GetStorageNamespace(id)); | |
105 storage_namespace_map_.erase(id); | |
106 } | |
107 | |
108 DOMStorageNamespace* DOMStorageContext::GetStorageNamespace(int64 id) { | |
109 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); | 101 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); |
110 StorageNamespaceMap::iterator iter = storage_namespace_map_.find(id); | 102 StorageNamespaceMap::iterator iter = storage_namespace_map_.find(id); |
111 if (iter == storage_namespace_map_.end()) | 103 if (iter != storage_namespace_map_.end()) |
| 104 return iter->second; |
| 105 if (!allocation_allowed) |
112 return NULL; | 106 return NULL; |
113 return iter->second; | 107 if (id == kLocalStorageNamespaceId) |
| 108 return CreateLocalStorage(); |
| 109 return CreateSessionStorage(id); |
114 } | 110 } |
115 | 111 |
116 void DOMStorageContext::RegisterDispatcherHost( | 112 void DOMStorageContext::RegisterDispatcherHost( |
117 DOMStorageDispatcherHost* dispatcher_host) { | 113 DOMStorageDispatcherHost* dispatcher_host) { |
118 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); | 114 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); |
119 DCHECK(dispatcher_host_set_.find(dispatcher_host) == | 115 DCHECK(dispatcher_host_set_.find(dispatcher_host) == |
120 dispatcher_host_set_.end()); | 116 dispatcher_host_set_.end()); |
121 dispatcher_host_set_.insert(dispatcher_host); | 117 dispatcher_host_set_.insert(dispatcher_host); |
122 } | 118 } |
123 | 119 |
(...skipping 10 matching lines...) Expand all Loading... |
134 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); | 130 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); |
135 return &dispatcher_host_set_; | 131 return &dispatcher_host_set_; |
136 } | 132 } |
137 | 133 |
138 void DOMStorageContext::PurgeMemory() { | 134 void DOMStorageContext::PurgeMemory() { |
139 // It is only safe to purge the memory from the LocalStorage namespace, | 135 // It is only safe to purge the memory from the LocalStorage namespace, |
140 // because it is backed by disk and can be reloaded later. If we purge a | 136 // because it is backed by disk and can be reloaded later. If we purge a |
141 // SessionStorage namespace, its data will be gone forever, because it isn't | 137 // SessionStorage namespace, its data will be gone forever, because it isn't |
142 // currently backed by disk. | 138 // currently backed by disk. |
143 DOMStorageNamespace* local_storage = | 139 DOMStorageNamespace* local_storage = |
144 GetStorageNamespace(kLocalStorageNamespaceId); | 140 GetStorageNamespace(kLocalStorageNamespaceId, false); |
145 if (local_storage) | 141 if (local_storage) |
146 local_storage->PurgeMemory(); | 142 local_storage->PurgeMemory(); |
147 } | 143 } |
148 | 144 |
149 void DOMStorageContext::DeleteDataModifiedSince(const base::Time& cutoff) { | 145 void DOMStorageContext::DeleteDataModifiedSince(const base::Time& cutoff) { |
150 // Make sure that we don't delete a database that's currently being accessed | 146 // Make sure that we don't delete a database that's currently being accessed |
151 // by unloading all of the databases temporarily. | 147 // by unloading all of the databases temporarily. |
152 PurgeMemory(); | 148 PurgeMemory(); |
153 | 149 |
154 file_util::FileEnumerator file_enumerator( | 150 file_util::FileEnumerator file_enumerator( |
155 webkit_context_->data_path().AppendASCII(kLocalStorageDirectory), false, | 151 webkit_context_->data_path().AppendASCII(kLocalStorageDirectory), false, |
156 file_util::FileEnumerator::FILES); | 152 file_util::FileEnumerator::FILES); |
157 for (FilePath path = file_enumerator.Next(); !path.value().empty(); | 153 for (FilePath path = file_enumerator.Next(); !path.value().empty(); |
158 path = file_enumerator.Next()) { | 154 path = file_enumerator.Next()) { |
159 file_util::FileEnumerator::FindInfo find_info; | 155 file_util::FileEnumerator::FindInfo find_info; |
160 file_enumerator.GetFindInfo(&find_info); | 156 file_enumerator.GetFindInfo(&find_info); |
161 if (file_util::HasFileBeenModifiedSince(find_info, cutoff)) | 157 if (file_util::HasFileBeenModifiedSince(find_info, cutoff)) |
162 file_util::Delete(path, false); | 158 file_util::Delete(path, false); |
163 } | 159 } |
164 } | 160 } |
| 161 |
| 162 DOMStorageNamespace* DOMStorageContext::CreateLocalStorage() { |
| 163 FilePath data_path = webkit_context_->data_path(); |
| 164 FilePath dir_path; |
| 165 if (!data_path.empty()) { |
| 166 MigrateLocalStorageDirectory(data_path); |
| 167 dir_path = data_path.AppendASCII(kLocalStorageDirectory); |
| 168 } |
| 169 DOMStorageNamespace* new_namespace = |
| 170 DOMStorageNamespace::CreateLocalStorageNamespace(this, dir_path); |
| 171 RegisterStorageNamespace(new_namespace); |
| 172 return new_namespace; |
| 173 } |
| 174 |
| 175 DOMStorageNamespace* DOMStorageContext::CreateSessionStorage( |
| 176 int64 namespace_id) { |
| 177 DOMStorageNamespace* new_namespace = |
| 178 DOMStorageNamespace::CreateSessionStorageNamespace(this, namespace_id); |
| 179 RegisterStorageNamespace(new_namespace); |
| 180 return new_namespace; |
| 181 } |
| 182 |
| 183 void DOMStorageContext::RegisterStorageNamespace( |
| 184 DOMStorageNamespace* storage_namespace) { |
| 185 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); |
| 186 int64 id = storage_namespace->id(); |
| 187 DCHECK(!GetStorageNamespace(id, false)); |
| 188 storage_namespace_map_[id] = storage_namespace; |
| 189 } |
| 190 |
| 191 /* static */ |
| 192 void DOMStorageContext::CompleteCloningSessionStorage( |
| 193 DOMStorageContext* context, int64 existing_id, int64 clone_id) { |
| 194 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT)); |
| 195 DOMStorageNamespace* existing_namespace = |
| 196 context->GetStorageNamespace(existing_id, false); |
| 197 // If nothing exists, then there's nothing to clone. |
| 198 if (existing_namespace) |
| 199 context->RegisterStorageNamespace(existing_namespace->Copy(clone_id)); |
| 200 } |
OLD | NEW |