| OLD | NEW |
| 1 // Copyright (c) 2012 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/indexed_db/indexed_db_context_impl.h" | 5 #include "content/browser/indexed_db/indexed_db_context_impl.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 #include "content/browser/indexed_db/indexed_db_tracing.h" | 29 #include "content/browser/indexed_db/indexed_db_tracing.h" |
| 30 #include "content/browser/indexed_db/indexed_db_transaction.h" | 30 #include "content/browser/indexed_db/indexed_db_transaction.h" |
| 31 #include "content/public/browser/browser_thread.h" | 31 #include "content/public/browser/browser_thread.h" |
| 32 #include "content/public/browser/indexed_db_info.h" | 32 #include "content/public/browser/indexed_db_info.h" |
| 33 #include "content/public/common/content_switches.h" | 33 #include "content/public/common/content_switches.h" |
| 34 #include "storage/browser/database/database_util.h" | 34 #include "storage/browser/database/database_util.h" |
| 35 #include "storage/browser/quota/quota_manager_proxy.h" | 35 #include "storage/browser/quota/quota_manager_proxy.h" |
| 36 #include "storage/browser/quota/special_storage_policy.h" | 36 #include "storage/browser/quota/special_storage_policy.h" |
| 37 #include "storage/common/database/database_identifier.h" | 37 #include "storage/common/database/database_identifier.h" |
| 38 #include "ui/base/text/bytes_formatting.h" | 38 #include "ui/base/text/bytes_formatting.h" |
| 39 #include "url/origin.h" |
| 39 | 40 |
| 40 using base::DictionaryValue; | 41 using base::DictionaryValue; |
| 41 using base::ListValue; | 42 using base::ListValue; |
| 42 using storage::DatabaseUtil; | 43 using storage::DatabaseUtil; |
| 44 using url::Origin; |
| 43 | 45 |
| 44 namespace content { | 46 namespace content { |
| 45 const base::FilePath::CharType IndexedDBContextImpl::kIndexedDBDirectory[] = | 47 const base::FilePath::CharType IndexedDBContextImpl::kIndexedDBDirectory[] = |
| 46 FILE_PATH_LITERAL("IndexedDB"); | 48 FILE_PATH_LITERAL("IndexedDB"); |
| 47 | 49 |
| 48 static const base::FilePath::CharType kBlobExtension[] = | 50 static const base::FilePath::CharType kBlobExtension[] = |
| 49 FILE_PATH_LITERAL(".blob"); | 51 FILE_PATH_LITERAL(".blob"); |
| 50 | 52 |
| 51 static const base::FilePath::CharType kIndexedDBExtension[] = | 53 static const base::FilePath::CharType kIndexedDBExtension[] = |
| 52 FILE_PATH_LITERAL(".indexeddb"); | 54 FILE_PATH_LITERAL(".indexeddb"); |
| 53 | 55 |
| 54 static const base::FilePath::CharType kLevelDBExtension[] = | 56 static const base::FilePath::CharType kLevelDBExtension[] = |
| 55 FILE_PATH_LITERAL(".leveldb"); | 57 FILE_PATH_LITERAL(".leveldb"); |
| 56 | 58 |
| 57 namespace { | 59 namespace { |
| 58 | 60 |
| 59 // This may be called after the IndexedDBContext is destroyed. | 61 // This may be called after the IndexedDBContext is destroyed. |
| 60 void GetAllOriginsAndPaths(const base::FilePath& indexeddb_path, | 62 void GetAllOriginsAndPaths(const base::FilePath& indexeddb_path, |
| 61 std::vector<GURL>* origins, | 63 std::vector<Origin>* origins, |
| 62 std::vector<base::FilePath>* file_paths) { | 64 std::vector<base::FilePath>* file_paths) { |
| 63 // TODO(jsbell): DCHECK that this is running on an IndexedDB thread, | 65 // TODO(jsbell): DCHECK that this is running on an IndexedDB thread, |
| 64 // if a global handle to it is ever available. | 66 // if a global handle to it is ever available. |
| 65 if (indexeddb_path.empty()) | 67 if (indexeddb_path.empty()) |
| 66 return; | 68 return; |
| 67 base::FileEnumerator file_enumerator( | 69 base::FileEnumerator file_enumerator( |
| 68 indexeddb_path, false, base::FileEnumerator::DIRECTORIES); | 70 indexeddb_path, false, base::FileEnumerator::DIRECTORIES); |
| 69 for (base::FilePath file_path = file_enumerator.Next(); !file_path.empty(); | 71 for (base::FilePath file_path = file_enumerator.Next(); !file_path.empty(); |
| 70 file_path = file_enumerator.Next()) { | 72 file_path = file_enumerator.Next()) { |
| 71 if (file_path.Extension() == kLevelDBExtension && | 73 if (file_path.Extension() == kLevelDBExtension && |
| 72 file_path.RemoveExtension().Extension() == kIndexedDBExtension) { | 74 file_path.RemoveExtension().Extension() == kIndexedDBExtension) { |
| 73 std::string origin_id = file_path.BaseName().RemoveExtension() | 75 std::string origin_id = file_path.BaseName().RemoveExtension() |
| 74 .RemoveExtension().MaybeAsASCII(); | 76 .RemoveExtension().MaybeAsASCII(); |
| 75 origins->push_back(storage::GetOriginFromIdentifier(origin_id)); | 77 origins->push_back(Origin(storage::GetOriginFromIdentifier(origin_id))); |
| 76 if (file_paths) | 78 if (file_paths) |
| 77 file_paths->push_back(file_path); | 79 file_paths->push_back(file_path); |
| 78 } | 80 } |
| 79 } | 81 } |
| 80 } | 82 } |
| 81 | 83 |
| 82 // This will be called after the IndexedDBContext is destroyed. | 84 // This will be called after the IndexedDBContext is destroyed. |
| 83 void ClearSessionOnlyOrigins( | 85 void ClearSessionOnlyOrigins( |
| 84 const base::FilePath& indexeddb_path, | 86 const base::FilePath& indexeddb_path, |
| 85 scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy) { | 87 scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy) { |
| 86 // TODO(jsbell): DCHECK that this is running on an IndexedDB thread, | 88 // TODO(jsbell): DCHECK that this is running on an IndexedDB thread, |
| 87 // if a global handle to it is ever available. | 89 // if a global handle to it is ever available. |
| 88 std::vector<GURL> origins; | 90 std::vector<Origin> origins; |
| 89 std::vector<base::FilePath> file_paths; | 91 std::vector<base::FilePath> file_paths; |
| 90 GetAllOriginsAndPaths(indexeddb_path, &origins, &file_paths); | 92 GetAllOriginsAndPaths(indexeddb_path, &origins, &file_paths); |
| 91 DCHECK_EQ(origins.size(), file_paths.size()); | 93 DCHECK_EQ(origins.size(), file_paths.size()); |
| 92 std::vector<base::FilePath>::const_iterator file_path_iter = | 94 auto file_path = file_paths.cbegin(); |
| 93 file_paths.begin(); | 95 auto origin = origins.cbegin(); |
| 94 for (std::vector<GURL>::const_iterator iter = origins.begin(); | 96 for (; origin != origins.cend(); ++origin, ++file_path) { |
| 95 iter != origins.end(); | 97 const GURL origin_url = GURL(origin->Serialize()); |
| 96 ++iter, ++file_path_iter) { | 98 if (!special_storage_policy->IsStorageSessionOnly(origin_url)) |
| 97 if (!special_storage_policy->IsStorageSessionOnly(*iter)) | |
| 98 continue; | 99 continue; |
| 99 if (special_storage_policy->IsStorageProtected(*iter)) | 100 if (special_storage_policy->IsStorageProtected(origin_url)) |
| 100 continue; | 101 continue; |
| 101 base::DeleteFile(*file_path_iter, true); | 102 base::DeleteFile(*file_path, true); |
| 102 } | 103 } |
| 103 } | 104 } |
| 104 | 105 |
| 105 } // namespace | 106 } // namespace |
| 106 | 107 |
| 107 IndexedDBContextImpl::IndexedDBContextImpl( | 108 IndexedDBContextImpl::IndexedDBContextImpl( |
| 108 const base::FilePath& data_path, | 109 const base::FilePath& data_path, |
| 109 storage::SpecialStoragePolicy* special_storage_policy, | 110 storage::SpecialStoragePolicy* special_storage_policy, |
| 110 storage::QuotaManagerProxy* quota_manager_proxy, | 111 storage::QuotaManagerProxy* quota_manager_proxy, |
| 111 base::SequencedTaskRunner* task_runner) | 112 base::SequencedTaskRunner* task_runner) |
| (...skipping 11 matching lines...) Expand all Loading... |
| 123 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 124 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 124 if (!factory_.get()) { | 125 if (!factory_.get()) { |
| 125 // Prime our cache of origins with existing databases so we can | 126 // Prime our cache of origins with existing databases so we can |
| 126 // detect when dbs are newly created. | 127 // detect when dbs are newly created. |
| 127 GetOriginSet(); | 128 GetOriginSet(); |
| 128 factory_ = new IndexedDBFactoryImpl(this); | 129 factory_ = new IndexedDBFactoryImpl(this); |
| 129 } | 130 } |
| 130 return factory_.get(); | 131 return factory_.get(); |
| 131 } | 132 } |
| 132 | 133 |
| 133 std::vector<GURL> IndexedDBContextImpl::GetAllOrigins() { | 134 std::vector<Origin> IndexedDBContextImpl::GetAllOrigins() { |
| 134 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 135 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 135 std::set<GURL>* origins_set = GetOriginSet(); | 136 std::set<Origin>* origins_set = GetOriginSet(); |
| 136 return std::vector<GURL>(origins_set->begin(), origins_set->end()); | 137 return std::vector<Origin>(origins_set->begin(), origins_set->end()); |
| 137 } | 138 } |
| 138 | 139 |
| 139 bool IndexedDBContextImpl::HasOrigin(const GURL& origin) { | 140 bool IndexedDBContextImpl::HasOrigin(const Origin& origin) { |
| 140 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 141 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 141 std::set<GURL>* set = GetOriginSet(); | 142 std::set<Origin>* set = GetOriginSet(); |
| 142 return set->find(origin) != set->end(); | 143 return set->find(origin) != set->end(); |
| 143 } | 144 } |
| 144 | 145 |
| 145 std::vector<IndexedDBInfo> IndexedDBContextImpl::GetAllOriginsInfo() { | 146 std::vector<IndexedDBInfo> IndexedDBContextImpl::GetAllOriginsInfo() { |
| 146 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 147 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 147 std::vector<GURL> origins = GetAllOrigins(); | 148 std::vector<Origin> origins = GetAllOrigins(); |
| 148 std::vector<IndexedDBInfo> result; | 149 std::vector<IndexedDBInfo> result; |
| 149 for (const auto& origin_url : origins) { | 150 for (const auto& origin : origins) { |
| 150 size_t connection_count = GetConnectionCount(origin_url); | 151 size_t connection_count = GetConnectionCount(origin); |
| 151 result.push_back(IndexedDBInfo(origin_url, | 152 result.push_back( |
| 152 GetOriginDiskUsage(origin_url), | 153 IndexedDBInfo(GURL(origin.Serialize()), GetOriginDiskUsage(origin), |
| 153 GetOriginLastModified(origin_url), | 154 GetOriginLastModified(origin), connection_count)); |
| 154 connection_count)); | |
| 155 } | 155 } |
| 156 return result; | 156 return result; |
| 157 } | 157 } |
| 158 | 158 |
| 159 static bool HostNameComparator(const GURL& i, const GURL& j) { | 159 static bool HostNameComparator(const Origin& i, const Origin& j) { |
| 160 return i.host() < j.host(); | 160 return i.host() < j.host(); |
| 161 } | 161 } |
| 162 | 162 |
| 163 base::ListValue* IndexedDBContextImpl::GetAllOriginsDetails() { | 163 base::ListValue* IndexedDBContextImpl::GetAllOriginsDetails() { |
| 164 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 164 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 165 std::vector<GURL> origins = GetAllOrigins(); | 165 std::vector<Origin> origins = GetAllOrigins(); |
| 166 | 166 |
| 167 std::sort(origins.begin(), origins.end(), HostNameComparator); | 167 std::sort(origins.begin(), origins.end(), HostNameComparator); |
| 168 | 168 |
| 169 std::unique_ptr<base::ListValue> list(new base::ListValue()); | 169 std::unique_ptr<base::ListValue> list(new base::ListValue()); |
| 170 for (const auto& origin_url : origins) { | 170 for (const auto& origin : origins) { |
| 171 std::unique_ptr<base::DictionaryValue> info(new base::DictionaryValue()); | 171 std::unique_ptr<base::DictionaryValue> info(new base::DictionaryValue()); |
| 172 info->SetString("url", origin_url.spec()); | 172 info->SetString("url", origin.Serialize()); |
| 173 info->SetString("size", ui::FormatBytes(GetOriginDiskUsage(origin_url))); | 173 info->SetString("size", ui::FormatBytes(GetOriginDiskUsage(origin))); |
| 174 info->SetDouble("last_modified", | 174 info->SetDouble("last_modified", GetOriginLastModified(origin).ToJsTime()); |
| 175 GetOriginLastModified(origin_url).ToJsTime()); | |
| 176 if (!is_incognito()) { | 175 if (!is_incognito()) { |
| 177 std::unique_ptr<base::ListValue> paths(new base::ListValue()); | 176 std::unique_ptr<base::ListValue> paths(new base::ListValue()); |
| 178 for (const base::FilePath& path : GetStoragePaths(origin_url)) | 177 for (const base::FilePath& path : GetStoragePaths(origin)) |
| 179 paths->AppendString(path.value()); | 178 paths->AppendString(path.value()); |
| 180 info->Set("paths", paths.release()); | 179 info->Set("paths", paths.release()); |
| 181 } | 180 } |
| 182 info->SetDouble("connection_count", GetConnectionCount(origin_url)); | 181 info->SetDouble("connection_count", GetConnectionCount(origin)); |
| 183 | 182 |
| 184 // This ends up being O(n^2) since we iterate over all open databases | 183 // This ends up being O(n^2) since we iterate over all open databases |
| 185 // to extract just those in the origin, and we're iterating over all | 184 // to extract just those in the origin, and we're iterating over all |
| 186 // origins in the outer loop. | 185 // origins in the outer loop. |
| 187 | 186 |
| 188 if (factory_.get()) { | 187 if (factory_.get()) { |
| 189 std::pair<IndexedDBFactory::OriginDBMapIterator, | 188 std::pair<IndexedDBFactory::OriginDBMapIterator, |
| 190 IndexedDBFactory::OriginDBMapIterator> range = | 189 IndexedDBFactory::OriginDBMapIterator> |
| 191 factory_->GetOpenDatabasesForOrigin(origin_url); | 190 range = factory_->GetOpenDatabasesForOrigin(origin); |
| 192 // TODO(jsbell): Sort by name? | 191 // TODO(jsbell): Sort by name? |
| 193 std::unique_ptr<base::ListValue> database_list(new base::ListValue()); | 192 std::unique_ptr<base::ListValue> database_list(new base::ListValue()); |
| 194 | 193 |
| 195 for (IndexedDBFactory::OriginDBMapIterator it = range.first; | 194 for (IndexedDBFactory::OriginDBMapIterator it = range.first; |
| 196 it != range.second; | 195 it != range.second; |
| 197 ++it) { | 196 ++it) { |
| 198 const IndexedDBDatabase* db = it->second; | 197 const IndexedDBDatabase* db = it->second; |
| 199 std::unique_ptr<base::DictionaryValue> db_info( | 198 std::unique_ptr<base::DictionaryValue> db_info( |
| 200 new base::DictionaryValue()); | 199 new base::DictionaryValue()); |
| 201 | 200 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 database_list->Append(db_info.release()); | 273 database_list->Append(db_info.release()); |
| 275 } | 274 } |
| 276 info->Set("databases", database_list.release()); | 275 info->Set("databases", database_list.release()); |
| 277 } | 276 } |
| 278 | 277 |
| 279 list->Append(info.release()); | 278 list->Append(info.release()); |
| 280 } | 279 } |
| 281 return list.release(); | 280 return list.release(); |
| 282 } | 281 } |
| 283 | 282 |
| 284 int IndexedDBContextImpl::GetOriginBlobFileCount(const GURL& origin_url) { | 283 int IndexedDBContextImpl::GetOriginBlobFileCount(const Origin& origin) { |
| 285 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 284 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 286 int count = 0; | 285 int count = 0; |
| 287 base::FileEnumerator file_enumerator(GetBlobStorePath(origin_url), true, | 286 base::FileEnumerator file_enumerator(GetBlobStorePath(origin), true, |
| 288 base::FileEnumerator::FILES); | 287 base::FileEnumerator::FILES); |
| 289 for (base::FilePath file_path = file_enumerator.Next(); !file_path.empty(); | 288 for (base::FilePath file_path = file_enumerator.Next(); !file_path.empty(); |
| 290 file_path = file_enumerator.Next()) { | 289 file_path = file_enumerator.Next()) { |
| 291 count++; | 290 count++; |
| 292 } | 291 } |
| 293 return count; | 292 return count; |
| 294 } | 293 } |
| 295 | 294 |
| 295 // TODO(jsbell): Update callers to use url::Origin overload and remove. |
| 296 int64_t IndexedDBContextImpl::GetOriginDiskUsage(const GURL& origin_url) { | 296 int64_t IndexedDBContextImpl::GetOriginDiskUsage(const GURL& origin_url) { |
| 297 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 297 return GetOriginDiskUsage(Origin(origin_url)); |
| 298 if (data_path_.empty() || !HasOrigin(origin_url)) | |
| 299 return 0; | |
| 300 EnsureDiskUsageCacheInitialized(origin_url); | |
| 301 return origin_size_map_[origin_url]; | |
| 302 } | 298 } |
| 303 | 299 |
| 304 base::Time IndexedDBContextImpl::GetOriginLastModified(const GURL& origin_url) { | 300 int64_t IndexedDBContextImpl::GetOriginDiskUsage(const Origin& origin) { |
| 305 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 301 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 306 if (data_path_.empty() || !HasOrigin(origin_url)) | 302 if (data_path_.empty() || !HasOrigin(origin)) |
| 303 return 0; |
| 304 EnsureDiskUsageCacheInitialized(origin); |
| 305 return origin_size_map_[origin]; |
| 306 } |
| 307 |
| 308 base::Time IndexedDBContextImpl::GetOriginLastModified(const Origin& origin) { |
| 309 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 310 if (data_path_.empty() || !HasOrigin(origin)) |
| 307 return base::Time(); | 311 return base::Time(); |
| 308 base::FilePath idb_directory = GetLevelDBPath(origin_url); | 312 base::FilePath idb_directory = GetLevelDBPath(origin); |
| 309 base::File::Info file_info; | 313 base::File::Info file_info; |
| 310 if (!base::GetFileInfo(idb_directory, &file_info)) | 314 if (!base::GetFileInfo(idb_directory, &file_info)) |
| 311 return base::Time(); | 315 return base::Time(); |
| 312 return file_info.last_modified; | 316 return file_info.last_modified; |
| 313 } | 317 } |
| 314 | 318 |
| 319 // TODO(jsbell): Update callers to use url::Origin overload and remove. |
| 315 void IndexedDBContextImpl::DeleteForOrigin(const GURL& origin_url) { | 320 void IndexedDBContextImpl::DeleteForOrigin(const GURL& origin_url) { |
| 321 DeleteForOrigin(Origin(origin_url)); |
| 322 } |
| 323 |
| 324 void IndexedDBContextImpl::DeleteForOrigin(const Origin& origin) { |
| 316 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 325 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 317 ForceClose(origin_url, FORCE_CLOSE_DELETE_ORIGIN); | 326 ForceClose(origin, FORCE_CLOSE_DELETE_ORIGIN); |
| 318 if (data_path_.empty() || !HasOrigin(origin_url)) | 327 if (data_path_.empty() || !HasOrigin(origin)) |
| 319 return; | 328 return; |
| 320 | 329 |
| 321 base::FilePath idb_directory = GetLevelDBPath(origin_url); | 330 base::FilePath idb_directory = GetLevelDBPath(origin); |
| 322 EnsureDiskUsageCacheInitialized(origin_url); | 331 EnsureDiskUsageCacheInitialized(origin); |
| 323 leveldb::Status s = LevelDBDatabase::Destroy(idb_directory); | 332 leveldb::Status s = LevelDBDatabase::Destroy(idb_directory); |
| 324 if (!s.ok()) { | 333 if (!s.ok()) { |
| 325 LOG(WARNING) << "Failed to delete LevelDB database: " | 334 LOG(WARNING) << "Failed to delete LevelDB database: " |
| 326 << idb_directory.AsUTF8Unsafe(); | 335 << idb_directory.AsUTF8Unsafe(); |
| 327 } else { | 336 } else { |
| 328 // LevelDB does not delete empty directories; work around this. | 337 // LevelDB does not delete empty directories; work around this. |
| 329 // TODO(jsbell): Remove when upstream bug is fixed. | 338 // TODO(jsbell): Remove when upstream bug is fixed. |
| 330 // https://code.google.com/p/leveldb/issues/detail?id=209 | 339 // https://code.google.com/p/leveldb/issues/detail?id=209 |
| 331 const bool kNonRecursive = false; | 340 const bool kNonRecursive = false; |
| 332 base::DeleteFile(idb_directory, kNonRecursive); | 341 base::DeleteFile(idb_directory, kNonRecursive); |
| 333 } | 342 } |
| 334 base::DeleteFile(GetBlobStorePath(origin_url), true /* recursive */); | 343 base::DeleteFile(GetBlobStorePath(origin), true /* recursive */); |
| 335 QueryDiskAndUpdateQuotaUsage(origin_url); | 344 QueryDiskAndUpdateQuotaUsage(origin); |
| 336 if (s.ok()) { | 345 if (s.ok()) { |
| 337 RemoveFromOriginSet(origin_url); | 346 RemoveFromOriginSet(origin); |
| 338 origin_size_map_.erase(origin_url); | 347 origin_size_map_.erase(origin); |
| 339 } | 348 } |
| 340 } | 349 } |
| 341 | 350 |
| 351 // TODO(jsbell): Update callers to use url::Origin overload and remove. |
| 342 void IndexedDBContextImpl::CopyOriginData(const GURL& origin_url, | 352 void IndexedDBContextImpl::CopyOriginData(const GURL& origin_url, |
| 343 IndexedDBContext* dest_context) { | 353 IndexedDBContext* dest_context) { |
| 354 CopyOriginData(Origin(origin_url), dest_context); |
| 355 } |
| 356 |
| 357 void IndexedDBContextImpl::CopyOriginData(const Origin& origin, |
| 358 IndexedDBContext* dest_context) { |
| 344 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 359 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 345 | 360 if (data_path_.empty() || !HasOrigin(origin)) |
| 346 if (data_path_.empty() || !HasOrigin(origin_url)) | |
| 347 return; | 361 return; |
| 348 | 362 |
| 349 IndexedDBContextImpl* dest_context_impl = | 363 IndexedDBContextImpl* dest_context_impl = |
| 350 static_cast<IndexedDBContextImpl*>(dest_context); | 364 static_cast<IndexedDBContextImpl*>(dest_context); |
| 351 | 365 |
| 352 ForceClose(origin_url, FORCE_CLOSE_COPY_ORIGIN); | 366 ForceClose(origin, FORCE_CLOSE_COPY_ORIGIN); |
| 353 | 367 |
| 354 // Make sure we're not about to delete our own database. | 368 // Make sure we're not about to delete our own database. |
| 355 CHECK_NE(dest_context_impl->data_path().value(), data_path().value()); | 369 CHECK_NE(dest_context_impl->data_path().value(), data_path().value()); |
| 356 | 370 |
| 357 // Delete any existing storage paths in the destination context. | 371 // Delete any existing storage paths in the destination context. |
| 358 // A previously failed migration may have left behind partially copied | 372 // A previously failed migration may have left behind partially copied |
| 359 // directories. | 373 // directories. |
| 360 for (const base::FilePath& dest_path : | 374 for (const base::FilePath& dest_path : |
| 361 dest_context_impl->GetStoragePaths(origin_url)) | 375 dest_context_impl->GetStoragePaths(origin)) |
| 362 base::DeleteFile(dest_path, true); | 376 base::DeleteFile(dest_path, true); |
| 363 | 377 |
| 364 base::FilePath dest_data_path = dest_context_impl->data_path(); | 378 base::FilePath dest_data_path = dest_context_impl->data_path(); |
| 365 base::CreateDirectory(dest_data_path); | 379 base::CreateDirectory(dest_data_path); |
| 366 | 380 |
| 367 for (const base::FilePath& src_data_path : GetStoragePaths(origin_url)) { | 381 for (const base::FilePath& src_data_path : GetStoragePaths(origin)) { |
| 368 if (base::PathExists(src_data_path)) { | 382 if (base::PathExists(src_data_path)) { |
| 369 base::CopyDirectory(src_data_path, dest_data_path, true); | 383 base::CopyDirectory(src_data_path, dest_data_path, true); |
| 370 } | 384 } |
| 371 } | 385 } |
| 372 } | 386 } |
| 373 | 387 |
| 374 void IndexedDBContextImpl::ForceClose(const GURL origin_url, | 388 void IndexedDBContextImpl::ForceClose(const Origin origin, |
| 375 ForceCloseReason reason) { | 389 ForceCloseReason reason) { |
| 376 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 390 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 377 UMA_HISTOGRAM_ENUMERATION("WebCore.IndexedDB.Context.ForceCloseReason", | 391 UMA_HISTOGRAM_ENUMERATION("WebCore.IndexedDB.Context.ForceCloseReason", |
| 378 reason, | 392 reason, |
| 379 FORCE_CLOSE_REASON_MAX); | 393 FORCE_CLOSE_REASON_MAX); |
| 380 | 394 |
| 381 if (data_path_.empty() || !HasOrigin(origin_url)) | 395 if (data_path_.empty() || !HasOrigin(origin)) |
| 382 return; | 396 return; |
| 383 | 397 |
| 384 if (factory_.get()) | 398 if (factory_.get()) |
| 385 factory_->ForceClose(origin_url); | 399 factory_->ForceClose(origin); |
| 386 DCHECK_EQ(0UL, GetConnectionCount(origin_url)); | 400 DCHECK_EQ(0UL, GetConnectionCount(origin)); |
| 387 } | 401 } |
| 388 | 402 |
| 389 size_t IndexedDBContextImpl::GetConnectionCount(const GURL& origin_url) { | 403 size_t IndexedDBContextImpl::GetConnectionCount(const Origin& origin) { |
| 390 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 404 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 391 if (data_path_.empty() || !HasOrigin(origin_url)) | 405 if (data_path_.empty() || !HasOrigin(origin)) |
| 392 return 0; | 406 return 0; |
| 393 | 407 |
| 394 if (!factory_.get()) | 408 if (!factory_.get()) |
| 395 return 0; | 409 return 0; |
| 396 | 410 |
| 397 return factory_->GetConnectionCount(origin_url); | 411 return factory_->GetConnectionCount(origin); |
| 398 } | 412 } |
| 399 | 413 |
| 400 std::vector<base::FilePath> IndexedDBContextImpl::GetStoragePaths( | 414 std::vector<base::FilePath> IndexedDBContextImpl::GetStoragePaths( |
| 401 const GURL& origin_url) const { | 415 const Origin& origin) const { |
| 402 std::vector<base::FilePath> paths; | 416 std::vector<base::FilePath> paths; |
| 403 paths.push_back(GetLevelDBPath(origin_url)); | 417 paths.push_back(GetLevelDBPath(origin)); |
| 404 paths.push_back(GetBlobStorePath(origin_url)); | 418 paths.push_back(GetBlobStorePath(origin)); |
| 405 return paths; | 419 return paths; |
| 406 } | 420 } |
| 407 | 421 |
| 422 // TODO(jsbell): Update callers to use url::Origin overload and remove. |
| 408 base::FilePath IndexedDBContextImpl::GetFilePathForTesting( | 423 base::FilePath IndexedDBContextImpl::GetFilePathForTesting( |
| 409 const GURL& origin_url) const { | 424 const GURL& origin_url) const { |
| 410 return GetLevelDBPath(origin_url); | 425 return GetFilePathForTesting(Origin(origin_url)); |
| 426 } |
| 427 |
| 428 base::FilePath IndexedDBContextImpl::GetFilePathForTesting( |
| 429 const Origin& origin) const { |
| 430 return GetLevelDBPath(origin); |
| 411 } | 431 } |
| 412 | 432 |
| 413 void IndexedDBContextImpl::SetTaskRunnerForTesting( | 433 void IndexedDBContextImpl::SetTaskRunnerForTesting( |
| 414 base::SequencedTaskRunner* task_runner) { | 434 base::SequencedTaskRunner* task_runner) { |
| 415 DCHECK(!task_runner_.get()); | 435 DCHECK(!task_runner_.get()); |
| 416 task_runner_ = task_runner; | 436 task_runner_ = task_runner; |
| 417 } | 437 } |
| 418 | 438 |
| 419 void IndexedDBContextImpl::ConnectionOpened(const GURL& origin_url, | 439 void IndexedDBContextImpl::ConnectionOpened(const Origin& origin, |
| 420 IndexedDBConnection* connection) { | 440 IndexedDBConnection* connection) { |
| 421 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 441 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 422 quota_manager_proxy()->NotifyStorageAccessed( | 442 quota_manager_proxy()->NotifyStorageAccessed( |
| 423 storage::QuotaClient::kIndexedDatabase, origin_url, | 443 storage::QuotaClient::kIndexedDatabase, GURL(origin.Serialize()), |
| 424 storage::kStorageTypeTemporary); | 444 storage::kStorageTypeTemporary); |
| 425 if (AddToOriginSet(origin_url)) { | 445 if (AddToOriginSet(origin)) { |
| 426 // A newly created db, notify the quota system. | 446 // A newly created db, notify the quota system. |
| 427 QueryDiskAndUpdateQuotaUsage(origin_url); | 447 QueryDiskAndUpdateQuotaUsage(origin); |
| 428 } else { | 448 } else { |
| 429 EnsureDiskUsageCacheInitialized(origin_url); | 449 EnsureDiskUsageCacheInitialized(origin); |
| 430 } | 450 } |
| 431 } | 451 } |
| 432 | 452 |
| 433 void IndexedDBContextImpl::ConnectionClosed(const GURL& origin_url, | 453 void IndexedDBContextImpl::ConnectionClosed(const Origin& origin, |
| 434 IndexedDBConnection* connection) { | 454 IndexedDBConnection* connection) { |
| 435 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 455 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); |
| 436 quota_manager_proxy()->NotifyStorageAccessed( | 456 quota_manager_proxy()->NotifyStorageAccessed( |
| 437 storage::QuotaClient::kIndexedDatabase, origin_url, | 457 storage::QuotaClient::kIndexedDatabase, GURL(origin.Serialize()), |
| 438 storage::kStorageTypeTemporary); | 458 storage::kStorageTypeTemporary); |
| 439 if (factory_.get() && factory_->GetConnectionCount(origin_url) == 0) | 459 if (factory_.get() && factory_->GetConnectionCount(origin) == 0) |
| 440 QueryDiskAndUpdateQuotaUsage(origin_url); | 460 QueryDiskAndUpdateQuotaUsage(origin); |
| 441 } | 461 } |
| 442 | 462 |
| 443 void IndexedDBContextImpl::TransactionComplete(const GURL& origin_url) { | 463 void IndexedDBContextImpl::TransactionComplete(const Origin& origin) { |
| 444 DCHECK(!factory_.get() || factory_->GetConnectionCount(origin_url) > 0); | 464 DCHECK(!factory_.get() || factory_->GetConnectionCount(origin) > 0); |
| 445 QueryDiskAndUpdateQuotaUsage(origin_url); | 465 QueryDiskAndUpdateQuotaUsage(origin); |
| 446 } | 466 } |
| 447 | 467 |
| 448 void IndexedDBContextImpl::DatabaseDeleted(const GURL& origin_url) { | 468 void IndexedDBContextImpl::DatabaseDeleted(const Origin& origin) { |
| 449 AddToOriginSet(origin_url); | 469 AddToOriginSet(origin); |
| 450 QueryDiskAndUpdateQuotaUsage(origin_url); | 470 QueryDiskAndUpdateQuotaUsage(origin); |
| 451 } | 471 } |
| 452 | 472 |
| 453 IndexedDBContextImpl::~IndexedDBContextImpl() { | 473 IndexedDBContextImpl::~IndexedDBContextImpl() { |
| 454 if (factory_.get()) { | 474 if (factory_.get()) { |
| 455 TaskRunner()->PostTask( | 475 TaskRunner()->PostTask( |
| 456 FROM_HERE, base::Bind(&IndexedDBFactory::ContextDestroyed, factory_)); | 476 FROM_HERE, base::Bind(&IndexedDBFactory::ContextDestroyed, factory_)); |
| 457 factory_ = NULL; | 477 factory_ = NULL; |
| 458 } | 478 } |
| 459 | 479 |
| 460 if (data_path_.empty()) | 480 if (data_path_.empty()) |
| (...skipping 11 matching lines...) Expand all Loading... |
| 472 return; | 492 return; |
| 473 | 493 |
| 474 TaskRunner()->PostTask( | 494 TaskRunner()->PostTask( |
| 475 FROM_HERE, | 495 FROM_HERE, |
| 476 base::Bind( | 496 base::Bind( |
| 477 &ClearSessionOnlyOrigins, data_path_, special_storage_policy_)); | 497 &ClearSessionOnlyOrigins, data_path_, special_storage_policy_)); |
| 478 } | 498 } |
| 479 | 499 |
| 480 // static | 500 // static |
| 481 base::FilePath IndexedDBContextImpl::GetBlobStoreFileName( | 501 base::FilePath IndexedDBContextImpl::GetBlobStoreFileName( |
| 482 const GURL& origin_url) { | 502 const Origin& origin) { |
| 483 std::string origin_id = storage::GetIdentifierFromOrigin(origin_url); | 503 std::string origin_id = |
| 504 storage::GetIdentifierFromOrigin(GURL(origin.Serialize())); |
| 484 return base::FilePath() | 505 return base::FilePath() |
| 485 .AppendASCII(origin_id) | 506 .AppendASCII(origin_id) |
| 486 .AddExtension(kIndexedDBExtension) | 507 .AddExtension(kIndexedDBExtension) |
| 487 .AddExtension(kBlobExtension); | 508 .AddExtension(kBlobExtension); |
| 488 } | 509 } |
| 489 | 510 |
| 490 // static | 511 // static |
| 491 base::FilePath IndexedDBContextImpl::GetLevelDBFileName( | 512 base::FilePath IndexedDBContextImpl::GetLevelDBFileName(const Origin& origin) { |
| 492 const GURL& origin_url) { | 513 std::string origin_id = |
| 493 std::string origin_id = storage::GetIdentifierFromOrigin(origin_url); | 514 storage::GetIdentifierFromOrigin(GURL(origin.Serialize())); |
| 494 return base::FilePath() | 515 return base::FilePath() |
| 495 .AppendASCII(origin_id) | 516 .AppendASCII(origin_id) |
| 496 .AddExtension(kIndexedDBExtension) | 517 .AddExtension(kIndexedDBExtension) |
| 497 .AddExtension(kLevelDBExtension); | 518 .AddExtension(kLevelDBExtension); |
| 498 } | 519 } |
| 499 | 520 |
| 500 base::FilePath IndexedDBContextImpl::GetBlobStorePath( | 521 base::FilePath IndexedDBContextImpl::GetBlobStorePath( |
| 501 const GURL& origin_url) const { | 522 const Origin& origin) const { |
| 502 DCHECK(!data_path_.empty()); | 523 DCHECK(!data_path_.empty()); |
| 503 return data_path_.Append(GetBlobStoreFileName(origin_url)); | 524 return data_path_.Append(GetBlobStoreFileName(origin)); |
| 504 } | 525 } |
| 505 | 526 |
| 506 base::FilePath IndexedDBContextImpl::GetLevelDBPath( | 527 base::FilePath IndexedDBContextImpl::GetLevelDBPath( |
| 507 const GURL& origin_url) const { | 528 const Origin& origin) const { |
| 508 DCHECK(!data_path_.empty()); | 529 DCHECK(!data_path_.empty()); |
| 509 return data_path_.Append(GetLevelDBFileName(origin_url)); | 530 return data_path_.Append(GetLevelDBFileName(origin)); |
| 510 } | 531 } |
| 511 | 532 |
| 512 int64_t IndexedDBContextImpl::ReadUsageFromDisk(const GURL& origin_url) const { | 533 int64_t IndexedDBContextImpl::ReadUsageFromDisk(const Origin& origin) const { |
| 513 if (data_path_.empty()) | 534 if (data_path_.empty()) |
| 514 return 0; | 535 return 0; |
| 515 int64_t total_size = 0; | 536 int64_t total_size = 0; |
| 516 for (const base::FilePath& path : GetStoragePaths(origin_url)) | 537 for (const base::FilePath& path : GetStoragePaths(origin)) |
| 517 total_size += base::ComputeDirectorySize(path); | 538 total_size += base::ComputeDirectorySize(path); |
| 518 return total_size; | 539 return total_size; |
| 519 } | 540 } |
| 520 | 541 |
| 521 void IndexedDBContextImpl::EnsureDiskUsageCacheInitialized( | 542 void IndexedDBContextImpl::EnsureDiskUsageCacheInitialized( |
| 522 const GURL& origin_url) { | 543 const Origin& origin) { |
| 523 if (origin_size_map_.find(origin_url) == origin_size_map_.end()) | 544 if (origin_size_map_.find(origin) == origin_size_map_.end()) |
| 524 origin_size_map_[origin_url] = ReadUsageFromDisk(origin_url); | 545 origin_size_map_[origin] = ReadUsageFromDisk(origin); |
| 525 } | 546 } |
| 526 | 547 |
| 527 void IndexedDBContextImpl::QueryDiskAndUpdateQuotaUsage( | 548 void IndexedDBContextImpl::QueryDiskAndUpdateQuotaUsage(const Origin& origin) { |
| 528 const GURL& origin_url) { | 549 int64_t former_disk_usage = origin_size_map_[origin]; |
| 529 int64_t former_disk_usage = origin_size_map_[origin_url]; | 550 int64_t current_disk_usage = ReadUsageFromDisk(origin); |
| 530 int64_t current_disk_usage = ReadUsageFromDisk(origin_url); | |
| 531 int64_t difference = current_disk_usage - former_disk_usage; | 551 int64_t difference = current_disk_usage - former_disk_usage; |
| 532 if (difference) { | 552 if (difference) { |
| 533 origin_size_map_[origin_url] = current_disk_usage; | 553 origin_size_map_[origin] = current_disk_usage; |
| 534 quota_manager_proxy()->NotifyStorageModified( | 554 quota_manager_proxy()->NotifyStorageModified( |
| 535 storage::QuotaClient::kIndexedDatabase, origin_url, | 555 storage::QuotaClient::kIndexedDatabase, GURL(origin.Serialize()), |
| 536 storage::kStorageTypeTemporary, difference); | 556 storage::kStorageTypeTemporary, difference); |
| 537 } | 557 } |
| 538 } | 558 } |
| 539 | 559 |
| 540 std::set<GURL>* IndexedDBContextImpl::GetOriginSet() { | 560 std::set<Origin>* IndexedDBContextImpl::GetOriginSet() { |
| 541 if (!origin_set_) { | 561 if (!origin_set_) { |
| 542 std::vector<GURL> origins; | 562 std::vector<Origin> origins; |
| 543 GetAllOriginsAndPaths(data_path_, &origins, NULL); | 563 GetAllOriginsAndPaths(data_path_, &origins, NULL); |
| 544 origin_set_.reset(new std::set<GURL>(origins.begin(), origins.end())); | 564 origin_set_.reset(new std::set<Origin>(origins.begin(), origins.end())); |
| 545 } | 565 } |
| 546 return origin_set_.get(); | 566 return origin_set_.get(); |
| 547 } | 567 } |
| 548 | 568 |
| 549 void IndexedDBContextImpl::ResetCaches() { | 569 void IndexedDBContextImpl::ResetCaches() { |
| 550 origin_set_.reset(); | 570 origin_set_.reset(); |
| 551 origin_size_map_.clear(); | 571 origin_size_map_.clear(); |
| 552 } | 572 } |
| 553 | 573 |
| 554 base::SequencedTaskRunner* IndexedDBContextImpl::TaskRunner() const { | 574 base::SequencedTaskRunner* IndexedDBContextImpl::TaskRunner() const { |
| 555 return task_runner_.get(); | 575 return task_runner_.get(); |
| 556 } | 576 } |
| 557 | 577 |
| 558 } // namespace content | 578 } // namespace content |
| OLD | NEW |