Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "storage/browser/quota/quota_manager.h" | 5 #include "storage/browser/quota/quota_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <functional> | 8 #include <functional> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 66 // Preserve kMinimumPreserveForSystem disk space for system book-keeping | 66 // Preserve kMinimumPreserveForSystem disk space for system book-keeping |
| 67 // when returning the quota to unlimited apps/extensions. | 67 // when returning the quota to unlimited apps/extensions. |
| 68 // TODO(kinuko): This should be like 10% of the actual disk space. | 68 // TODO(kinuko): This should be like 10% of the actual disk space. |
| 69 // For now we simply use a constant as getting the disk size needs | 69 // For now we simply use a constant as getting the disk size needs |
| 70 // platform-dependent code. (http://crbug.com/178976) | 70 // platform-dependent code. (http://crbug.com/178976) |
| 71 int64 QuotaManager::kMinimumPreserveForSystem = 1024 * kMBytes; | 71 int64 QuotaManager::kMinimumPreserveForSystem = 1024 * kMBytes; |
| 72 | 72 |
| 73 const int QuotaManager::kEvictionIntervalInMilliSeconds = | 73 const int QuotaManager::kEvictionIntervalInMilliSeconds = |
| 74 30 * kMinutesInMilliSeconds; | 74 30 * kMinutesInMilliSeconds; |
| 75 | 75 |
| 76 const char QuotaManager::kTimeSinceOriginEvictedHistogram[] = | |
| 77 "Quota.TimeSinceOriginEvicted"; | |
| 78 | |
| 76 // Heuristics: assuming average cloud server allows a few Gigs storage | 79 // Heuristics: assuming average cloud server allows a few Gigs storage |
| 77 // on the server side and the storage needs to be shared for user data | 80 // on the server side and the storage needs to be shared for user data |
| 78 // and by multiple apps. | 81 // and by multiple apps. |
| 79 int64 QuotaManager::kSyncableStorageDefaultHostQuota = 500 * kMBytes; | 82 int64 QuotaManager::kSyncableStorageDefaultHostQuota = 500 * kMBytes; |
| 80 | 83 |
| 81 namespace { | 84 namespace { |
| 82 | 85 |
| 83 void CountOriginType(const std::set<GURL>& origins, | 86 void CountOriginType(const std::set<GURL>& origins, |
| 84 SpecialStoragePolicy* policy, | 87 SpecialStoragePolicy* policy, |
| 85 size_t* protected_origins, | 88 size_t* protected_origins, |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 145 SpecialStoragePolicy* policy, | 148 SpecialStoragePolicy* policy, |
| 146 GURL* url, | 149 GURL* url, |
| 147 QuotaDatabase* database) { | 150 QuotaDatabase* database) { |
| 148 DCHECK(database); | 151 DCHECK(database); |
| 149 database->GetLRUOrigin(type, *exceptions, policy, url); | 152 database->GetLRUOrigin(type, *exceptions, policy, url); |
| 150 return true; | 153 return true; |
| 151 } | 154 } |
| 152 | 155 |
| 153 bool DeleteOriginInfoOnDBThread(const GURL& origin, | 156 bool DeleteOriginInfoOnDBThread(const GURL& origin, |
| 154 StorageType type, | 157 StorageType type, |
| 158 bool is_eviction, | |
| 155 QuotaDatabase* database) { | 159 QuotaDatabase* database) { |
| 156 DCHECK(database); | 160 DCHECK(database); |
| 157 return database->DeleteOriginInfo(origin, type); | 161 if (!database->DeleteOriginInfo(origin, type)) |
| 162 return false; | |
| 163 | |
| 164 // If the deletion is not due to an eviction, delete the entry in the eviction | |
| 165 // table as well due to privacy concerns. | |
| 166 if (!is_eviction) | |
| 167 return database->DeleteOriginLastEvictionTime(origin, type); | |
| 168 | |
| 169 base::Time last_eviction_time; | |
| 170 if (!database->GetOriginLastEvictionTime(origin, type, &last_eviction_time)) | |
|
michaeln
2015/10/13 21:35:36
it's important to return false only for error cond
calamity
2015/10/15 07:56:43
That's already the behavior. This only returns fal
| |
| 171 return false; | |
| 172 | |
| 173 base::Time now = base::Time::Now(); | |
| 174 if (last_eviction_time != base::Time()) { | |
| 175 UMA_HISTOGRAM_LONG_TIMES(QuotaManager::kTimeSinceOriginEvictedHistogram, | |
| 176 now - last_eviction_time); | |
| 177 } | |
| 178 | |
| 179 if (!database->SetOriginLastEvictionTime(origin, type, now)) | |
| 180 return false; | |
| 181 | |
| 182 return true; | |
| 158 } | 183 } |
| 159 | 184 |
| 160 bool InitializeTemporaryOriginsInfoOnDBThread(const std::set<GURL>* origins, | 185 bool InitializeTemporaryOriginsInfoOnDBThread(const std::set<GURL>* origins, |
| 161 QuotaDatabase* database) { | 186 QuotaDatabase* database) { |
| 162 DCHECK(database); | 187 DCHECK(database); |
| 163 if (database->IsOriginDatabaseBootstrapped()) | 188 if (database->IsOriginDatabaseBootstrapped()) |
| 164 return true; | 189 return true; |
| 165 | 190 |
| 166 // Register existing origins with 0 last time access. | 191 // Register existing origins with 0 last time access. |
| 167 if (database->RegisterInitialOriginInfo(*origins, kStorageTypeTemporary)) { | 192 if (database->RegisterInitialOriginInfo(*origins, kStorageTypeTemporary)) { |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 527 | 552 |
| 528 DISALLOW_COPY_AND_ASSIGN(GetUsageInfoTask); | 553 DISALLOW_COPY_AND_ASSIGN(GetUsageInfoTask); |
| 529 }; | 554 }; |
| 530 | 555 |
| 531 class QuotaManager::OriginDataDeleter : public QuotaTask { | 556 class QuotaManager::OriginDataDeleter : public QuotaTask { |
| 532 public: | 557 public: |
| 533 OriginDataDeleter(QuotaManager* manager, | 558 OriginDataDeleter(QuotaManager* manager, |
| 534 const GURL& origin, | 559 const GURL& origin, |
| 535 StorageType type, | 560 StorageType type, |
| 536 int quota_client_mask, | 561 int quota_client_mask, |
| 562 bool is_eviction, | |
| 537 const StatusCallback& callback) | 563 const StatusCallback& callback) |
| 538 : QuotaTask(manager), | 564 : QuotaTask(manager), |
| 539 origin_(origin), | 565 origin_(origin), |
| 540 type_(type), | 566 type_(type), |
| 541 quota_client_mask_(quota_client_mask), | 567 quota_client_mask_(quota_client_mask), |
| 542 error_count_(0), | 568 error_count_(0), |
| 543 remaining_clients_(-1), | 569 remaining_clients_(-1), |
| 544 skipped_clients_(0), | 570 skipped_clients_(0), |
| 571 is_eviction_(is_eviction), | |
| 545 callback_(callback), | 572 callback_(callback), |
| 546 weak_factory_(this) {} | 573 weak_factory_(this) {} |
| 547 | 574 |
| 548 protected: | 575 protected: |
| 549 void Run() override { | 576 void Run() override { |
| 550 error_count_ = 0; | 577 error_count_ = 0; |
| 551 remaining_clients_ = manager()->clients_.size(); | 578 remaining_clients_ = manager()->clients_.size(); |
| 552 for (QuotaClientList::iterator iter = manager()->clients_.begin(); | 579 for (QuotaClientList::iterator iter = manager()->clients_.begin(); |
| 553 iter != manager()->clients_.end(); ++iter) { | 580 iter != manager()->clients_.end(); ++iter) { |
| 554 if (quota_client_mask_ & (*iter)->id()) { | 581 if (quota_client_mask_ & (*iter)->id()) { |
| 555 (*iter)->DeleteOriginData( | 582 (*iter)->DeleteOriginData( |
| 556 origin_, type_, | 583 origin_, type_, |
| 557 base::Bind(&OriginDataDeleter::DidDeleteOriginData, | 584 base::Bind(&OriginDataDeleter::DidDeleteOriginData, |
| 558 weak_factory_.GetWeakPtr())); | 585 weak_factory_.GetWeakPtr())); |
| 559 } else { | 586 } else { |
| 560 ++skipped_clients_; | 587 ++skipped_clients_; |
| 561 if (--remaining_clients_ == 0) | 588 if (--remaining_clients_ == 0) |
| 562 CallCompleted(); | 589 CallCompleted(); |
| 563 } | 590 } |
| 564 } | 591 } |
| 565 } | 592 } |
| 566 | 593 |
| 567 void Completed() override { | 594 void Completed() override { |
| 568 if (error_count_ == 0) { | 595 if (error_count_ == 0) { |
| 569 // Only remove the entire origin if we didn't skip any client types. | 596 // Only remove the entire origin if we didn't skip any client types. |
| 570 if (skipped_clients_ == 0) | 597 if (skipped_clients_ == 0) |
| 571 manager()->DeleteOriginFromDatabase(origin_, type_); | 598 manager()->DeleteOriginFromDatabase(origin_, type_, is_eviction_); |
| 572 callback_.Run(kQuotaStatusOk); | 599 callback_.Run(kQuotaStatusOk); |
| 573 } else { | 600 } else { |
| 574 callback_.Run(kQuotaErrorInvalidModification); | 601 callback_.Run(kQuotaErrorInvalidModification); |
| 575 } | 602 } |
| 576 DeleteSoon(); | 603 DeleteSoon(); |
| 577 } | 604 } |
| 578 | 605 |
| 579 void Aborted() override { | 606 void Aborted() override { |
| 580 callback_.Run(kQuotaErrorAbort); | 607 callback_.Run(kQuotaErrorAbort); |
| 581 DeleteSoon(); | 608 DeleteSoon(); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 595 QuotaManager* manager() const { | 622 QuotaManager* manager() const { |
| 596 return static_cast<QuotaManager*>(observer()); | 623 return static_cast<QuotaManager*>(observer()); |
| 597 } | 624 } |
| 598 | 625 |
| 599 GURL origin_; | 626 GURL origin_; |
| 600 StorageType type_; | 627 StorageType type_; |
| 601 int quota_client_mask_; | 628 int quota_client_mask_; |
| 602 int error_count_; | 629 int error_count_; |
| 603 int remaining_clients_; | 630 int remaining_clients_; |
| 604 int skipped_clients_; | 631 int skipped_clients_; |
| 632 bool is_eviction_; | |
| 605 StatusCallback callback_; | 633 StatusCallback callback_; |
| 606 | 634 |
| 607 base::WeakPtrFactory<OriginDataDeleter> weak_factory_; | 635 base::WeakPtrFactory<OriginDataDeleter> weak_factory_; |
| 608 DISALLOW_COPY_AND_ASSIGN(OriginDataDeleter); | 636 DISALLOW_COPY_AND_ASSIGN(OriginDataDeleter); |
| 609 }; | 637 }; |
| 610 | 638 |
| 611 class QuotaManager::HostDataDeleter : public QuotaTask { | 639 class QuotaManager::HostDataDeleter : public QuotaTask { |
| 612 public: | 640 public: |
| 613 HostDataDeleter(QuotaManager* manager, | 641 HostDataDeleter(QuotaManager* manager, |
| 614 const std::string& host, | 642 const std::string& host, |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 664 else | 692 else |
| 665 CallCompleted(); | 693 CallCompleted(); |
| 666 } | 694 } |
| 667 } | 695 } |
| 668 | 696 |
| 669 void ScheduleOriginsDeletion() { | 697 void ScheduleOriginsDeletion() { |
| 670 remaining_deleters_ = origins_.size(); | 698 remaining_deleters_ = origins_.size(); |
| 671 for (std::set<GURL>::const_iterator p = origins_.begin(); | 699 for (std::set<GURL>::const_iterator p = origins_.begin(); |
| 672 p != origins_.end(); | 700 p != origins_.end(); |
| 673 ++p) { | 701 ++p) { |
| 674 OriginDataDeleter* deleter = | 702 OriginDataDeleter* deleter = new OriginDataDeleter( |
| 675 new OriginDataDeleter( | 703 manager(), *p, type_, quota_client_mask_, false, |
| 676 manager(), *p, type_, quota_client_mask_, | 704 base::Bind(&HostDataDeleter::DidDeleteOriginData, |
| 677 base::Bind(&HostDataDeleter::DidDeleteOriginData, | 705 weak_factory_.GetWeakPtr())); |
| 678 weak_factory_.GetWeakPtr())); | |
| 679 deleter->Start(); | 706 deleter->Start(); |
| 680 } | 707 } |
| 681 } | 708 } |
| 682 | 709 |
| 683 void DidDeleteOriginData(QuotaStatusCode status) { | 710 void DidDeleteOriginData(QuotaStatusCode status) { |
| 684 DCHECK_GT(remaining_deleters_, 0); | 711 DCHECK_GT(remaining_deleters_, 0); |
| 685 | 712 |
| 686 if (status != kQuotaStatusOk) | 713 if (status != kQuotaStatusOk) |
| 687 ++error_count_; | 714 ++error_count_; |
| 688 | 715 |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 918 | 945 |
| 919 void QuotaManager::SetUsageCacheEnabled(QuotaClient::ID client_id, | 946 void QuotaManager::SetUsageCacheEnabled(QuotaClient::ID client_id, |
| 920 const GURL& origin, | 947 const GURL& origin, |
| 921 StorageType type, | 948 StorageType type, |
| 922 bool enabled) { | 949 bool enabled) { |
| 923 LazyInitialize(); | 950 LazyInitialize(); |
| 924 DCHECK(GetUsageTracker(type)); | 951 DCHECK(GetUsageTracker(type)); |
| 925 GetUsageTracker(type)->SetUsageCacheEnabled(client_id, origin, enabled); | 952 GetUsageTracker(type)->SetUsageCacheEnabled(client_id, origin, enabled); |
| 926 } | 953 } |
| 927 | 954 |
| 928 void QuotaManager::DeleteOriginData( | 955 void QuotaManager::DeleteOriginData(const GURL& origin, |
| 929 const GURL& origin, StorageType type, int quota_client_mask, | 956 StorageType type, |
| 930 const StatusCallback& callback) { | 957 int quota_client_mask, |
| 958 bool is_eviction, | |
| 959 const StatusCallback& callback) { | |
| 931 LazyInitialize(); | 960 LazyInitialize(); |
| 932 | 961 |
| 933 if (origin.is_empty() || clients_.empty()) { | 962 if (origin.is_empty() || clients_.empty()) { |
| 934 callback.Run(kQuotaStatusOk); | 963 callback.Run(kQuotaStatusOk); |
| 935 return; | 964 return; |
| 936 } | 965 } |
| 937 | 966 |
| 938 DCHECK(origin == origin.GetOrigin()); | 967 DCHECK(origin == origin.GetOrigin()); |
| 939 OriginDataDeleter* deleter = | 968 OriginDataDeleter* deleter = new OriginDataDeleter( |
| 940 new OriginDataDeleter(this, origin, type, quota_client_mask, callback); | 969 this, origin, type, quota_client_mask, is_eviction, callback); |
| 941 deleter->Start(); | 970 deleter->Start(); |
| 942 } | 971 } |
| 943 | 972 |
| 944 void QuotaManager::DeleteHostData(const std::string& host, | 973 void QuotaManager::DeleteHostData(const std::string& host, |
| 945 StorageType type, | 974 StorageType type, |
| 946 int quota_client_mask, | 975 int quota_client_mask, |
| 947 const StatusCallback& callback) { | 976 const StatusCallback& callback) { |
| 948 LazyInitialize(); | 977 LazyInitialize(); |
| 949 | 978 |
| 950 if (host.empty() || clients_.empty()) { | 979 if (host.empty() || clients_.empty()) { |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1347 void QuotaManager::StartEviction() { | 1376 void QuotaManager::StartEviction() { |
| 1348 DCHECK(!temporary_storage_evictor_.get()); | 1377 DCHECK(!temporary_storage_evictor_.get()); |
| 1349 temporary_storage_evictor_.reset(new QuotaTemporaryStorageEvictor( | 1378 temporary_storage_evictor_.reset(new QuotaTemporaryStorageEvictor( |
| 1350 this, kEvictionIntervalInMilliSeconds)); | 1379 this, kEvictionIntervalInMilliSeconds)); |
| 1351 if (desired_available_space_ >= 0) | 1380 if (desired_available_space_ >= 0) |
| 1352 temporary_storage_evictor_->set_min_available_disk_space_to_start_eviction( | 1381 temporary_storage_evictor_->set_min_available_disk_space_to_start_eviction( |
| 1353 desired_available_space_); | 1382 desired_available_space_); |
| 1354 temporary_storage_evictor_->Start(); | 1383 temporary_storage_evictor_->Start(); |
| 1355 } | 1384 } |
| 1356 | 1385 |
| 1357 void QuotaManager::DeleteOriginFromDatabase( | 1386 void QuotaManager::DeleteOriginFromDatabase(const GURL& origin, |
| 1358 const GURL& origin, StorageType type) { | 1387 StorageType type, |
| 1388 bool is_eviction) { | |
| 1359 LazyInitialize(); | 1389 LazyInitialize(); |
| 1360 if (db_disabled_) | 1390 if (db_disabled_) |
| 1361 return; | 1391 return; |
| 1362 | 1392 |
| 1363 PostTaskAndReplyWithResultForDBThread( | 1393 PostTaskAndReplyWithResultForDBThread( |
| 1364 FROM_HERE, | 1394 FROM_HERE, |
| 1365 base::Bind(&DeleteOriginInfoOnDBThread, origin, type), | 1395 base::Bind(&DeleteOriginInfoOnDBThread, origin, type, is_eviction), |
| 1366 base::Bind(&QuotaManager::DidDatabaseWork, | 1396 base::Bind(&QuotaManager::DidDatabaseWork, weak_factory_.GetWeakPtr())); |
| 1367 weak_factory_.GetWeakPtr())); | |
| 1368 } | 1397 } |
| 1369 | 1398 |
| 1370 void QuotaManager::DidOriginDataEvicted(QuotaStatusCode status) { | 1399 void QuotaManager::DidOriginDataEvicted(QuotaStatusCode status) { |
| 1371 DCHECK(io_thread_->BelongsToCurrentThread()); | 1400 DCHECK(io_thread_->BelongsToCurrentThread()); |
| 1372 | 1401 |
| 1373 // We only try evict origins that are not in use, so basically | 1402 // We only try evict origins that are not in use, so basically |
| 1374 // deletion attempt for eviction should not fail. Let's record | 1403 // deletion attempt for eviction should not fail. Let's record |
| 1375 // the origin if we get error and exclude it from future eviction | 1404 // the origin if we get error and exclude it from future eviction |
| 1376 // if the error happens consistently (> kThresholdOfErrorsToBeBlacklisted). | 1405 // if the error happens consistently (> kThresholdOfErrorsToBeBlacklisted). |
| 1377 if (status != kQuotaStatusOk) | 1406 if (status != kQuotaStatusOk) |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1438 protected_origins); | 1467 protected_origins); |
| 1439 UMA_HISTOGRAM_COUNTS("Quota.NumberOfUnlimitedPersistentStorageOrigins", | 1468 UMA_HISTOGRAM_COUNTS("Quota.NumberOfUnlimitedPersistentStorageOrigins", |
| 1440 unlimited_origins); | 1469 unlimited_origins); |
| 1441 } | 1470 } |
| 1442 | 1471 |
| 1443 void QuotaManager::GetEvictionOrigin(StorageType type, | 1472 void QuotaManager::GetEvictionOrigin(StorageType type, |
| 1444 const GetOriginCallback& callback) { | 1473 const GetOriginCallback& callback) { |
| 1445 GetLRUOrigin(type, callback); | 1474 GetLRUOrigin(type, callback); |
| 1446 } | 1475 } |
| 1447 | 1476 |
| 1448 void QuotaManager::EvictOriginData(const GURL& origin, | 1477 void QuotaManager::EvictOriginData(const GURL& origin, |
|
michaeln
2015/10/13 21:35:36
The public DeleteOriginData method and this method
calamity
2015/10/15 07:56:43
Done.
| |
| 1449 StorageType type, | 1478 StorageType type, |
| 1450 const EvictOriginDataCallback& callback) { | 1479 const EvictOriginDataCallback& callback) { |
| 1451 DCHECK(io_thread_->BelongsToCurrentThread()); | 1480 DCHECK(io_thread_->BelongsToCurrentThread()); |
| 1452 DCHECK_EQ(type, kStorageTypeTemporary); | 1481 DCHECK_EQ(type, kStorageTypeTemporary); |
| 1453 | 1482 |
| 1454 eviction_context_.evicted_origin = origin; | 1483 eviction_context_.evicted_origin = origin; |
| 1455 eviction_context_.evicted_type = type; | 1484 eviction_context_.evicted_type = type; |
| 1456 eviction_context_.evict_origin_data_callback = callback; | 1485 eviction_context_.evict_origin_data_callback = callback; |
| 1457 | 1486 |
| 1458 DeleteOriginData(origin, type, QuotaClient::kAllClientsMask, | 1487 DeleteOriginData(origin, type, QuotaClient::kAllClientsMask, true, |
| 1459 base::Bind(&QuotaManager::DidOriginDataEvicted, | 1488 base::Bind(&QuotaManager::DidOriginDataEvicted, |
| 1460 weak_factory_.GetWeakPtr())); | 1489 weak_factory_.GetWeakPtr())); |
| 1461 } | 1490 } |
| 1462 | 1491 |
| 1463 void QuotaManager::GetUsageAndQuotaForEviction( | 1492 void QuotaManager::GetUsageAndQuotaForEviction( |
| 1464 const UsageAndQuotaCallback& callback) { | 1493 const UsageAndQuotaCallback& callback) { |
| 1465 DCHECK(io_thread_->BelongsToCurrentThread()); | 1494 DCHECK(io_thread_->BelongsToCurrentThread()); |
| 1466 LazyInitialize(); | 1495 LazyInitialize(); |
| 1467 | 1496 |
| 1468 UsageAndQuotaCallbackDispatcher* dispatcher = | 1497 UsageAndQuotaCallbackDispatcher* dispatcher = |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1625 // |database_|, therefore we can be sure that database_ is alive when this | 1654 // |database_|, therefore we can be sure that database_ is alive when this |
| 1626 // task runs. | 1655 // task runs. |
| 1627 base::PostTaskAndReplyWithResult( | 1656 base::PostTaskAndReplyWithResult( |
| 1628 db_thread_.get(), | 1657 db_thread_.get(), |
| 1629 from_here, | 1658 from_here, |
| 1630 base::Bind(task, base::Unretained(database_.get())), | 1659 base::Bind(task, base::Unretained(database_.get())), |
| 1631 reply); | 1660 reply); |
| 1632 } | 1661 } |
| 1633 | 1662 |
| 1634 } // namespace storage | 1663 } // namespace storage |
| OLD | NEW |