| 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 |