| OLD | NEW |
| 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 } | |
| OLD | NEW |