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 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 special_storage_policy_(special_storage_policy), | 115 special_storage_policy_(special_storage_policy), |
116 quota_manager_proxy_(quota_manager_proxy), | 116 quota_manager_proxy_(quota_manager_proxy), |
117 task_runner_(task_runner) { | 117 task_runner_(task_runner) { |
118 IDB_TRACE("init"); | 118 IDB_TRACE("init"); |
119 if (!data_path.empty()) | 119 if (!data_path.empty()) |
120 data_path_ = data_path.Append(kIndexedDBDirectory); | 120 data_path_ = data_path.Append(kIndexedDBDirectory); |
121 quota_manager_proxy->RegisterClient(new IndexedDBQuotaClient(this)); | 121 quota_manager_proxy->RegisterClient(new IndexedDBQuotaClient(this)); |
122 } | 122 } |
123 | 123 |
124 IndexedDBFactory* IndexedDBContextImpl::GetIDBFactory() { | 124 IndexedDBFactory* IndexedDBContextImpl::GetIDBFactory() { |
125 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 125 DCHECK(TaskRunner()->RunsTasksInCurrentSequence()); |
126 if (!factory_.get()) { | 126 if (!factory_.get()) { |
127 // Prime our cache of origins with existing databases so we can | 127 // Prime our cache of origins with existing databases so we can |
128 // detect when dbs are newly created. | 128 // detect when dbs are newly created. |
129 GetOriginSet(); | 129 GetOriginSet(); |
130 factory_ = new IndexedDBFactoryImpl(this); | 130 factory_ = new IndexedDBFactoryImpl(this); |
131 } | 131 } |
132 return factory_.get(); | 132 return factory_.get(); |
133 } | 133 } |
134 | 134 |
135 std::vector<Origin> IndexedDBContextImpl::GetAllOrigins() { | 135 std::vector<Origin> IndexedDBContextImpl::GetAllOrigins() { |
136 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 136 DCHECK(TaskRunner()->RunsTasksInCurrentSequence()); |
137 std::set<Origin>* origins_set = GetOriginSet(); | 137 std::set<Origin>* origins_set = GetOriginSet(); |
138 return std::vector<Origin>(origins_set->begin(), origins_set->end()); | 138 return std::vector<Origin>(origins_set->begin(), origins_set->end()); |
139 } | 139 } |
140 | 140 |
141 bool IndexedDBContextImpl::HasOrigin(const Origin& origin) { | 141 bool IndexedDBContextImpl::HasOrigin(const Origin& origin) { |
142 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 142 DCHECK(TaskRunner()->RunsTasksInCurrentSequence()); |
143 std::set<Origin>* set = GetOriginSet(); | 143 std::set<Origin>* set = GetOriginSet(); |
144 return set->find(origin) != set->end(); | 144 return set->find(origin) != set->end(); |
145 } | 145 } |
146 | 146 |
147 std::vector<IndexedDBInfo> IndexedDBContextImpl::GetAllOriginsInfo() { | 147 std::vector<IndexedDBInfo> IndexedDBContextImpl::GetAllOriginsInfo() { |
148 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 148 DCHECK(TaskRunner()->RunsTasksInCurrentSequence()); |
149 std::vector<Origin> origins = GetAllOrigins(); | 149 std::vector<Origin> origins = GetAllOrigins(); |
150 std::vector<IndexedDBInfo> result; | 150 std::vector<IndexedDBInfo> result; |
151 for (const auto& origin : origins) { | 151 for (const auto& origin : origins) { |
152 size_t connection_count = GetConnectionCount(origin); | 152 size_t connection_count = GetConnectionCount(origin); |
153 result.push_back(IndexedDBInfo(origin.GetURL(), GetOriginDiskUsage(origin), | 153 result.push_back(IndexedDBInfo(origin.GetURL(), GetOriginDiskUsage(origin), |
154 GetOriginLastModified(origin), | 154 GetOriginLastModified(origin), |
155 connection_count)); | 155 connection_count)); |
156 } | 156 } |
157 return result; | 157 return result; |
158 } | 158 } |
159 | 159 |
160 static bool HostNameComparator(const Origin& i, const Origin& j) { | 160 static bool HostNameComparator(const Origin& i, const Origin& j) { |
161 return i.host() < j.host(); | 161 return i.host() < j.host(); |
162 } | 162 } |
163 | 163 |
164 base::ListValue* IndexedDBContextImpl::GetAllOriginsDetails() { | 164 base::ListValue* IndexedDBContextImpl::GetAllOriginsDetails() { |
165 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 165 DCHECK(TaskRunner()->RunsTasksInCurrentSequence()); |
166 std::vector<Origin> origins = GetAllOrigins(); | 166 std::vector<Origin> origins = GetAllOrigins(); |
167 | 167 |
168 std::sort(origins.begin(), origins.end(), HostNameComparator); | 168 std::sort(origins.begin(), origins.end(), HostNameComparator); |
169 | 169 |
170 std::unique_ptr<base::ListValue> list(base::MakeUnique<base::ListValue>()); | 170 std::unique_ptr<base::ListValue> list(base::MakeUnique<base::ListValue>()); |
171 for (const auto& origin : origins) { | 171 for (const auto& origin : origins) { |
172 std::unique_ptr<base::DictionaryValue> info( | 172 std::unique_ptr<base::DictionaryValue> info( |
173 base::MakeUnique<base::DictionaryValue>()); | 173 base::MakeUnique<base::DictionaryValue>()); |
174 info->SetString("url", origin.Serialize()); | 174 info->SetString("url", origin.Serialize()); |
175 info->SetString("size", ui::FormatBytes(GetOriginDiskUsage(origin))); | 175 info->SetString("size", ui::FormatBytes(GetOriginDiskUsage(origin))); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 } | 269 } |
270 info->Set("databases", database_list.release()); | 270 info->Set("databases", database_list.release()); |
271 } | 271 } |
272 | 272 |
273 list->Append(std::move(info)); | 273 list->Append(std::move(info)); |
274 } | 274 } |
275 return list.release(); | 275 return list.release(); |
276 } | 276 } |
277 | 277 |
278 int IndexedDBContextImpl::GetOriginBlobFileCount(const Origin& origin) { | 278 int IndexedDBContextImpl::GetOriginBlobFileCount(const Origin& origin) { |
279 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 279 DCHECK(TaskRunner()->RunsTasksInCurrentSequence()); |
280 int count = 0; | 280 int count = 0; |
281 base::FileEnumerator file_enumerator(GetBlobStorePath(origin), true, | 281 base::FileEnumerator file_enumerator(GetBlobStorePath(origin), true, |
282 base::FileEnumerator::FILES); | 282 base::FileEnumerator::FILES); |
283 for (base::FilePath file_path = file_enumerator.Next(); !file_path.empty(); | 283 for (base::FilePath file_path = file_enumerator.Next(); !file_path.empty(); |
284 file_path = file_enumerator.Next()) { | 284 file_path = file_enumerator.Next()) { |
285 count++; | 285 count++; |
286 } | 286 } |
287 return count; | 287 return count; |
288 } | 288 } |
289 | 289 |
290 // TODO(jsbell): Update callers to use url::Origin overload and remove. | 290 // TODO(jsbell): Update callers to use url::Origin overload and remove. |
291 int64_t IndexedDBContextImpl::GetOriginDiskUsage(const GURL& origin_url) { | 291 int64_t IndexedDBContextImpl::GetOriginDiskUsage(const GURL& origin_url) { |
292 return GetOriginDiskUsage(Origin(origin_url)); | 292 return GetOriginDiskUsage(Origin(origin_url)); |
293 } | 293 } |
294 | 294 |
295 int64_t IndexedDBContextImpl::GetOriginDiskUsage(const Origin& origin) { | 295 int64_t IndexedDBContextImpl::GetOriginDiskUsage(const Origin& origin) { |
296 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 296 DCHECK(TaskRunner()->RunsTasksInCurrentSequence()); |
297 if (data_path_.empty() || !HasOrigin(origin)) | 297 if (data_path_.empty() || !HasOrigin(origin)) |
298 return 0; | 298 return 0; |
299 EnsureDiskUsageCacheInitialized(origin); | 299 EnsureDiskUsageCacheInitialized(origin); |
300 return origin_size_map_[origin]; | 300 return origin_size_map_[origin]; |
301 } | 301 } |
302 | 302 |
303 base::Time IndexedDBContextImpl::GetOriginLastModified(const Origin& origin) { | 303 base::Time IndexedDBContextImpl::GetOriginLastModified(const Origin& origin) { |
304 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 304 DCHECK(TaskRunner()->RunsTasksInCurrentSequence()); |
305 if (data_path_.empty() || !HasOrigin(origin)) | 305 if (data_path_.empty() || !HasOrigin(origin)) |
306 return base::Time(); | 306 return base::Time(); |
307 base::FilePath idb_directory = GetLevelDBPath(origin); | 307 base::FilePath idb_directory = GetLevelDBPath(origin); |
308 base::File::Info file_info; | 308 base::File::Info file_info; |
309 if (!base::GetFileInfo(idb_directory, &file_info)) | 309 if (!base::GetFileInfo(idb_directory, &file_info)) |
310 return base::Time(); | 310 return base::Time(); |
311 return file_info.last_modified; | 311 return file_info.last_modified; |
312 } | 312 } |
313 | 313 |
314 // TODO(jsbell): Update callers to use url::Origin overload and remove. | 314 // TODO(jsbell): Update callers to use url::Origin overload and remove. |
315 void IndexedDBContextImpl::DeleteForOrigin(const GURL& origin_url) { | 315 void IndexedDBContextImpl::DeleteForOrigin(const GURL& origin_url) { |
316 DeleteForOrigin(Origin(origin_url)); | 316 DeleteForOrigin(Origin(origin_url)); |
317 } | 317 } |
318 | 318 |
319 void IndexedDBContextImpl::DeleteForOrigin(const Origin& origin) { | 319 void IndexedDBContextImpl::DeleteForOrigin(const Origin& origin) { |
320 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 320 DCHECK(TaskRunner()->RunsTasksInCurrentSequence()); |
321 ForceClose(origin, FORCE_CLOSE_DELETE_ORIGIN); | 321 ForceClose(origin, FORCE_CLOSE_DELETE_ORIGIN); |
322 if (data_path_.empty() || !HasOrigin(origin)) | 322 if (data_path_.empty() || !HasOrigin(origin)) |
323 return; | 323 return; |
324 | 324 |
325 base::FilePath idb_directory = GetLevelDBPath(origin); | 325 base::FilePath idb_directory = GetLevelDBPath(origin); |
326 EnsureDiskUsageCacheInitialized(origin); | 326 EnsureDiskUsageCacheInitialized(origin); |
327 leveldb::Status s = LevelDBDatabase::Destroy(idb_directory); | 327 leveldb::Status s = LevelDBDatabase::Destroy(idb_directory); |
328 if (!s.ok()) { | 328 if (!s.ok()) { |
329 LOG(WARNING) << "Failed to delete LevelDB database: " | 329 LOG(WARNING) << "Failed to delete LevelDB database: " |
330 << idb_directory.AsUTF8Unsafe(); | 330 << idb_directory.AsUTF8Unsafe(); |
(...skipping 13 matching lines...) Expand all Loading... |
344 } | 344 } |
345 | 345 |
346 // TODO(jsbell): Update callers to use url::Origin overload and remove. | 346 // TODO(jsbell): Update callers to use url::Origin overload and remove. |
347 void IndexedDBContextImpl::CopyOriginData(const GURL& origin_url, | 347 void IndexedDBContextImpl::CopyOriginData(const GURL& origin_url, |
348 IndexedDBContext* dest_context) { | 348 IndexedDBContext* dest_context) { |
349 CopyOriginData(Origin(origin_url), dest_context); | 349 CopyOriginData(Origin(origin_url), dest_context); |
350 } | 350 } |
351 | 351 |
352 void IndexedDBContextImpl::CopyOriginData(const Origin& origin, | 352 void IndexedDBContextImpl::CopyOriginData(const Origin& origin, |
353 IndexedDBContext* dest_context) { | 353 IndexedDBContext* dest_context) { |
354 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 354 DCHECK(TaskRunner()->RunsTasksInCurrentSequence()); |
355 if (data_path_.empty() || !HasOrigin(origin)) | 355 if (data_path_.empty() || !HasOrigin(origin)) |
356 return; | 356 return; |
357 | 357 |
358 IndexedDBContextImpl* dest_context_impl = | 358 IndexedDBContextImpl* dest_context_impl = |
359 static_cast<IndexedDBContextImpl*>(dest_context); | 359 static_cast<IndexedDBContextImpl*>(dest_context); |
360 | 360 |
361 ForceClose(origin, FORCE_CLOSE_COPY_ORIGIN); | 361 ForceClose(origin, FORCE_CLOSE_COPY_ORIGIN); |
362 | 362 |
363 // Make sure we're not about to delete our own database. | 363 // Make sure we're not about to delete our own database. |
364 CHECK_NE(dest_context_impl->data_path().value(), data_path().value()); | 364 CHECK_NE(dest_context_impl->data_path().value(), data_path().value()); |
(...skipping 10 matching lines...) Expand all Loading... |
375 | 375 |
376 for (const base::FilePath& src_data_path : GetStoragePaths(origin)) { | 376 for (const base::FilePath& src_data_path : GetStoragePaths(origin)) { |
377 if (base::PathExists(src_data_path)) { | 377 if (base::PathExists(src_data_path)) { |
378 base::CopyDirectory(src_data_path, dest_data_path, true); | 378 base::CopyDirectory(src_data_path, dest_data_path, true); |
379 } | 379 } |
380 } | 380 } |
381 } | 381 } |
382 | 382 |
383 void IndexedDBContextImpl::ForceClose(const Origin origin, | 383 void IndexedDBContextImpl::ForceClose(const Origin origin, |
384 ForceCloseReason reason) { | 384 ForceCloseReason reason) { |
385 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 385 DCHECK(TaskRunner()->RunsTasksInCurrentSequence()); |
386 UMA_HISTOGRAM_ENUMERATION("WebCore.IndexedDB.Context.ForceCloseReason", | 386 UMA_HISTOGRAM_ENUMERATION("WebCore.IndexedDB.Context.ForceCloseReason", |
387 reason, | 387 reason, |
388 FORCE_CLOSE_REASON_MAX); | 388 FORCE_CLOSE_REASON_MAX); |
389 | 389 |
390 if (data_path_.empty() || !HasOrigin(origin)) | 390 if (data_path_.empty() || !HasOrigin(origin)) |
391 return; | 391 return; |
392 | 392 |
393 if (factory_.get()) | 393 if (factory_.get()) |
394 factory_->ForceClose(origin); | 394 factory_->ForceClose(origin); |
395 DCHECK_EQ(0UL, GetConnectionCount(origin)); | 395 DCHECK_EQ(0UL, GetConnectionCount(origin)); |
396 } | 396 } |
397 | 397 |
398 size_t IndexedDBContextImpl::GetConnectionCount(const Origin& origin) { | 398 size_t IndexedDBContextImpl::GetConnectionCount(const Origin& origin) { |
399 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 399 DCHECK(TaskRunner()->RunsTasksInCurrentSequence()); |
400 if (data_path_.empty() || !HasOrigin(origin)) | 400 if (data_path_.empty() || !HasOrigin(origin)) |
401 return 0; | 401 return 0; |
402 | 402 |
403 if (!factory_.get()) | 403 if (!factory_.get()) |
404 return 0; | 404 return 0; |
405 | 405 |
406 return factory_->GetConnectionCount(origin); | 406 return factory_->GetConnectionCount(origin); |
407 } | 407 } |
408 | 408 |
409 std::vector<base::FilePath> IndexedDBContextImpl::GetStoragePaths( | 409 std::vector<base::FilePath> IndexedDBContextImpl::GetStoragePaths( |
(...skipping 16 matching lines...) Expand all Loading... |
426 } | 426 } |
427 | 427 |
428 void IndexedDBContextImpl::SetTaskRunnerForTesting( | 428 void IndexedDBContextImpl::SetTaskRunnerForTesting( |
429 base::SequencedTaskRunner* task_runner) { | 429 base::SequencedTaskRunner* task_runner) { |
430 DCHECK(!task_runner_.get()); | 430 DCHECK(!task_runner_.get()); |
431 task_runner_ = task_runner; | 431 task_runner_ = task_runner; |
432 } | 432 } |
433 | 433 |
434 void IndexedDBContextImpl::ConnectionOpened(const Origin& origin, | 434 void IndexedDBContextImpl::ConnectionOpened(const Origin& origin, |
435 IndexedDBConnection* connection) { | 435 IndexedDBConnection* connection) { |
436 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 436 DCHECK(TaskRunner()->RunsTasksInCurrentSequence()); |
437 quota_manager_proxy()->NotifyStorageAccessed( | 437 quota_manager_proxy()->NotifyStorageAccessed( |
438 storage::QuotaClient::kIndexedDatabase, origin.GetURL(), | 438 storage::QuotaClient::kIndexedDatabase, origin.GetURL(), |
439 storage::kStorageTypeTemporary); | 439 storage::kStorageTypeTemporary); |
440 if (AddToOriginSet(origin)) { | 440 if (AddToOriginSet(origin)) { |
441 // A newly created db, notify the quota system. | 441 // A newly created db, notify the quota system. |
442 QueryDiskAndUpdateQuotaUsage(origin); | 442 QueryDiskAndUpdateQuotaUsage(origin); |
443 } else { | 443 } else { |
444 EnsureDiskUsageCacheInitialized(origin); | 444 EnsureDiskUsageCacheInitialized(origin); |
445 } | 445 } |
446 } | 446 } |
447 | 447 |
448 void IndexedDBContextImpl::ConnectionClosed(const Origin& origin, | 448 void IndexedDBContextImpl::ConnectionClosed(const Origin& origin, |
449 IndexedDBConnection* connection) { | 449 IndexedDBConnection* connection) { |
450 DCHECK(TaskRunner()->RunsTasksOnCurrentThread()); | 450 DCHECK(TaskRunner()->RunsTasksInCurrentSequence()); |
451 quota_manager_proxy()->NotifyStorageAccessed( | 451 quota_manager_proxy()->NotifyStorageAccessed( |
452 storage::QuotaClient::kIndexedDatabase, origin.GetURL(), | 452 storage::QuotaClient::kIndexedDatabase, origin.GetURL(), |
453 storage::kStorageTypeTemporary); | 453 storage::kStorageTypeTemporary); |
454 if (factory_.get() && factory_->GetConnectionCount(origin) == 0) | 454 if (factory_.get() && factory_->GetConnectionCount(origin) == 0) |
455 QueryDiskAndUpdateQuotaUsage(origin); | 455 QueryDiskAndUpdateQuotaUsage(origin); |
456 } | 456 } |
457 | 457 |
458 void IndexedDBContextImpl::TransactionComplete(const Origin& origin) { | 458 void IndexedDBContextImpl::TransactionComplete(const Origin& origin) { |
459 DCHECK(!factory_.get() || factory_->GetConnectionCount(origin) > 0); | 459 DCHECK(!factory_.get() || factory_->GetConnectionCount(origin) > 0); |
460 QueryDiskAndUpdateQuotaUsage(origin); | 460 QueryDiskAndUpdateQuotaUsage(origin); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
563 void IndexedDBContextImpl::ResetCaches() { | 563 void IndexedDBContextImpl::ResetCaches() { |
564 origin_set_.reset(); | 564 origin_set_.reset(); |
565 origin_size_map_.clear(); | 565 origin_size_map_.clear(); |
566 } | 566 } |
567 | 567 |
568 base::SequencedTaskRunner* IndexedDBContextImpl::TaskRunner() const { | 568 base::SequencedTaskRunner* IndexedDBContextImpl::TaskRunner() const { |
569 return task_runner_.get(); | 569 return task_runner_.get(); |
570 } | 570 } |
571 | 571 |
572 } // namespace content | 572 } // namespace content |
OLD | NEW |