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