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
3 // found in the LICENSE file.
5 #include "storage/browser/quota/quota_manager.h"
12 #include "base/bind.h"
13 #include "base/bind_helpers.h"
14 #include "base/callback.h"
15 #include "base/command_line.h"
16 #include "base/files/file_path.h"
17 #include "base/files/file_util.h"
18 #include "base/metrics/histogram.h"
19 #include "base/sequenced_task_runner.h"
20 #include "base/single_thread_task_runner.h"
21 #include "base/strings/string_number_conversions.h"
22 #include "base/sys_info.h"
23 #include "base/task_runner_util.h"
24 #include "base/time/time.h"
25 #include "net/base/net_util.h"
26 #include "storage/browser/quota/client_usage_tracker.h"
27 #include "storage/browser/quota/quota_database.h"
28 #include "storage/browser/quota/quota_manager_proxy.h"
29 #include "storage/browser/quota/quota_temporary_storage_evictor.h"
30 #include "storage/browser/quota/storage_monitor.h"
31 #include "storage/browser/quota/usage_tracker.h"
32 #include "storage/common/quota/quota_types.h"
34 #define UMA_HISTOGRAM_MBYTES(name, sample) \
35 UMA_HISTOGRAM_CUSTOM_COUNTS( \
36 (name), static_cast<int>((sample) / kMBytes), \
37 1, 10 * 1024 * 1024 /* 10TB */, 100)
43 const int64 kMBytes
= 1024 * 1024;
44 const int kMinutesInMilliSeconds
= 60 * 1000;
46 const int64 kReportHistogramInterval
= 60 * 60 * 1000; // 1 hour
47 const double kTemporaryQuotaRatioToAvail
= 1.0 / 3.0; // 33%
51 // Arbitrary for now, but must be reasonably small so that
52 // in-memory databases can fit.
53 // TODO(kinuko): Refer SysInfo::AmountOfPhysicalMemory() to determine this.
54 const int64
QuotaManager::kIncognitoDefaultQuotaLimit
= 100 * kMBytes
;
56 const int64
QuotaManager::kNoLimit
= kint64max
;
58 const int QuotaManager::kPerHostTemporaryPortion
= 5; // 20%
60 // Cap size for per-host persistent quota determined by the histogram.
61 // This is a bit lax value because the histogram says nothing about per-host
62 // persistent storage usage and we determined by global persistent storage
63 // usage that is less than 10GB for almost all users.
64 const int64
QuotaManager::kPerHostPersistentQuotaLimit
= 10 * 1024 * kMBytes
;
66 const char QuotaManager::kDatabaseName
[] = "QuotaManager";
68 const int QuotaManager::kThresholdOfErrorsToBeBlacklisted
= 3;
70 // Preserve kMinimumPreserveForSystem disk space for system book-keeping
71 // when returning the quota to unlimited apps/extensions.
72 // TODO(kinuko): This should be like 10% of the actual disk space.
73 // For now we simply use a constant as getting the disk size needs
74 // platform-dependent code. (http://crbug.com/178976)
75 int64
QuotaManager::kMinimumPreserveForSystem
= 1024 * kMBytes
;
77 const int QuotaManager::kEvictionIntervalInMilliSeconds
=
78 30 * kMinutesInMilliSeconds
;
80 // Heuristics: assuming average cloud server allows a few Gigs storage
81 // on the server side and the storage needs to be shared for user data
82 // and by multiple apps.
83 int64
QuotaManager::kSyncableStorageDefaultHostQuota
= 500 * kMBytes
;
87 void CountOriginType(const std::set
<GURL
>& origins
,
88 SpecialStoragePolicy
* policy
,
89 size_t* protected_origins
,
90 size_t* unlimited_origins
) {
91 DCHECK(protected_origins
);
92 DCHECK(unlimited_origins
);
93 *protected_origins
= 0;
94 *unlimited_origins
= 0;
97 for (std::set
<GURL
>::const_iterator itr
= origins
.begin();
100 if (policy
->IsStorageProtected(*itr
))
101 ++*protected_origins
;
102 if (policy
->IsStorageUnlimited(*itr
))
103 ++*unlimited_origins
;
107 bool SetTemporaryGlobalOverrideQuotaOnDBThread(int64
* new_quota
,
108 QuotaDatabase
* database
) {
110 if (!database
->SetQuotaConfigValue(
111 QuotaDatabase::kTemporaryQuotaOverrideKey
, *new_quota
)) {
118 bool GetPersistentHostQuotaOnDBThread(const std::string
& host
,
120 QuotaDatabase
* database
) {
122 database
->GetHostQuota(host
, kStorageTypePersistent
, quota
);
126 bool SetPersistentHostQuotaOnDBThread(const std::string
& host
,
128 QuotaDatabase
* database
) {
130 if (database
->SetHostQuota(host
, kStorageTypePersistent
, *new_quota
))
136 bool InitializeOnDBThread(int64
* temporary_quota_override
,
137 int64
* desired_available_space
,
138 QuotaDatabase
* database
) {
140 database
->GetQuotaConfigValue(QuotaDatabase::kTemporaryQuotaOverrideKey
,
141 temporary_quota_override
);
142 database
->GetQuotaConfigValue(QuotaDatabase::kDesiredAvailableSpaceKey
,
143 desired_available_space
);
147 bool GetLRUOriginOnDBThread(StorageType type
,
148 std::set
<GURL
>* exceptions
,
149 SpecialStoragePolicy
* policy
,
151 QuotaDatabase
* database
) {
153 database
->GetLRUOrigin(type
, *exceptions
, policy
, url
);
157 bool DeleteOriginInfoOnDBThread(const GURL
& origin
,
159 QuotaDatabase
* database
) {
161 return database
->DeleteOriginInfo(origin
, type
);
164 bool InitializeTemporaryOriginsInfoOnDBThread(const std::set
<GURL
>* origins
,
165 QuotaDatabase
* database
) {
167 if (database
->IsOriginDatabaseBootstrapped())
170 // Register existing origins with 0 last time access.
171 if (database
->RegisterInitialOriginInfo(*origins
, kStorageTypeTemporary
)) {
172 database
->SetOriginDatabaseBootstrapped(true);
178 bool UpdateAccessTimeOnDBThread(const GURL
& origin
,
180 base::Time accessed_time
,
181 QuotaDatabase
* database
) {
183 return database
->SetOriginLastAccessTime(origin
, type
, accessed_time
);
186 bool UpdateModifiedTimeOnDBThread(const GURL
& origin
,
188 base::Time modified_time
,
189 QuotaDatabase
* database
) {
191 return database
->SetOriginLastModifiedTime(origin
, type
, modified_time
);
194 int64
CallSystemGetAmountOfFreeDiskSpace(const base::FilePath
& profile_path
) {
195 // Ensure the profile path exists.
196 if (!base::CreateDirectory(profile_path
)) {
197 LOG(WARNING
) << "Create directory failed for path" << profile_path
.value();
200 return base::SysInfo::AmountOfFreeDiskSpace(profile_path
);
203 int64
CalculateTemporaryGlobalQuota(int64 global_limited_usage
,
204 int64 available_space
) {
205 DCHECK_GE(global_limited_usage
, 0);
206 int64 avail_space
= available_space
;
207 if (avail_space
< kint64max
- global_limited_usage
) {
208 // We basically calculate the temporary quota by
209 // [available_space + space_used_for_temp] * kTempQuotaRatio,
210 // but make sure we'll have no overflow.
211 avail_space
+= global_limited_usage
;
213 return avail_space
* kTemporaryQuotaRatioToAvail
;
216 void DispatchTemporaryGlobalQuotaCallback(
217 const QuotaCallback
& callback
,
218 QuotaStatusCode status
,
219 const UsageAndQuota
& usage_and_quota
) {
220 if (status
!= kQuotaStatusOk
) {
221 callback
.Run(status
, 0);
225 callback
.Run(status
, CalculateTemporaryGlobalQuota(
226 usage_and_quota
.global_limited_usage
,
227 usage_and_quota
.available_disk_space
));
230 int64
CalculateQuotaWithDiskSpace(
231 int64 available_disk_space
, int64 usage
, int64 quota
) {
232 if (available_disk_space
< QuotaManager::kMinimumPreserveForSystem
) {
234 << "Running out of disk space for profile."
235 << " QuotaManager starts forbidding further quota consumption.";
240 // No more space; cap the quota to the current usage.
244 available_disk_space
-= QuotaManager::kMinimumPreserveForSystem
;
245 if (available_disk_space
< quota
- usage
)
246 return available_disk_space
+ usage
;
251 int64
CalculateTemporaryHostQuota(int64 host_usage
,
253 int64 global_limited_usage
) {
254 DCHECK_GE(global_limited_usage
, 0);
255 int64 host_quota
= global_quota
/ QuotaManager::kPerHostTemporaryPortion
;
256 if (global_limited_usage
> global_quota
)
257 host_quota
= std::min(host_quota
, host_usage
);
261 void DispatchUsageAndQuotaForWebApps(
265 bool can_query_disk_size
,
266 const QuotaManager::GetUsageAndQuotaCallback
& callback
,
267 QuotaStatusCode status
,
268 const UsageAndQuota
& usage_and_quota
) {
269 if (status
!= kQuotaStatusOk
) {
270 callback
.Run(status
, 0, 0);
274 int64 usage
= usage_and_quota
.usage
;
275 int64 quota
= usage_and_quota
.quota
;
277 if (type
== kStorageTypeTemporary
&& !is_unlimited
) {
278 quota
= CalculateTemporaryHostQuota(
279 usage
, quota
, usage_and_quota
.global_limited_usage
);
283 quota
= std::min(quota
, QuotaManager::kIncognitoDefaultQuotaLimit
);
284 callback
.Run(status
, usage
, quota
);
288 // For apps with unlimited permission or can_query_disk_size is true (and not
289 // in incognito mode).
290 // We assume we can expose the actual disk size for them and cap the quota by
291 // the available disk space.
292 if (is_unlimited
|| can_query_disk_size
) {
295 CalculateQuotaWithDiskSpace(
296 usage_and_quota
.available_disk_space
,
301 callback
.Run(status
, usage
, quota
);
306 UsageAndQuota::UsageAndQuota()
308 global_limited_usage(0),
310 available_disk_space(0) {
313 UsageAndQuota::UsageAndQuota(
315 int64 global_limited_usage
,
317 int64 available_disk_space
)
319 global_limited_usage(global_limited_usage
),
321 available_disk_space(available_disk_space
) {
324 class UsageAndQuotaCallbackDispatcher
326 public base::SupportsWeakPtr
<UsageAndQuotaCallbackDispatcher
> {
328 explicit UsageAndQuotaCallbackDispatcher(QuotaManager
* manager
)
329 : QuotaTask(manager
),
331 has_global_limited_usage_(false),
333 has_available_disk_space_(false),
334 status_(kQuotaStatusUnknown
),
335 usage_and_quota_(-1, -1, -1, -1),
336 waiting_callbacks_(1) {}
338 ~UsageAndQuotaCallbackDispatcher() override
{}
340 void WaitForResults(const QuotaManager::UsageAndQuotaCallback
& callback
) {
341 callback_
= callback
;
345 void set_usage(int64 usage
) {
346 usage_and_quota_
.usage
= usage
;
350 void set_global_limited_usage(int64 global_limited_usage
) {
351 usage_and_quota_
.global_limited_usage
= global_limited_usage
;
352 has_global_limited_usage_
= true;
355 void set_quota(int64 quota
) {
356 usage_and_quota_
.quota
= quota
;
360 void set_available_disk_space(int64 available_disk_space
) {
361 usage_and_quota_
.available_disk_space
= available_disk_space
;
362 has_available_disk_space_
= true;
365 UsageCallback
GetHostUsageCallback() {
366 ++waiting_callbacks_
;
368 return base::Bind(&UsageAndQuotaCallbackDispatcher::DidGetHostUsage
,
372 UsageCallback
GetGlobalLimitedUsageCallback() {
373 ++waiting_callbacks_
;
374 has_global_limited_usage_
= true;
376 &UsageAndQuotaCallbackDispatcher::DidGetGlobalLimitedUsage
,
380 QuotaCallback
GetQuotaCallback() {
381 ++waiting_callbacks_
;
383 return base::Bind(&UsageAndQuotaCallbackDispatcher::DidGetQuota
,
387 QuotaCallback
GetAvailableSpaceCallback() {
388 ++waiting_callbacks_
;
389 has_available_disk_space_
= true;
390 return base::Bind(&UsageAndQuotaCallbackDispatcher::DidGetAvailableSpace
,
395 void DidGetHostUsage(int64 usage
) {
396 if (status_
== kQuotaStatusUnknown
)
397 status_
= kQuotaStatusOk
;
398 usage_and_quota_
.usage
= usage
;
402 void DidGetGlobalLimitedUsage(int64 limited_usage
) {
403 if (status_
== kQuotaStatusUnknown
)
404 status_
= kQuotaStatusOk
;
405 usage_and_quota_
.global_limited_usage
= limited_usage
;
409 void DidGetQuota(QuotaStatusCode status
, int64 quota
) {
410 if (status_
== kQuotaStatusUnknown
|| status_
== kQuotaStatusOk
)
412 usage_and_quota_
.quota
= quota
;
416 void DidGetAvailableSpace(QuotaStatusCode status
, int64 space
) {
418 if (status_
== kQuotaStatusUnknown
|| status_
== kQuotaStatusOk
)
420 usage_and_quota_
.available_disk_space
= space
;
424 void Run() override
{
425 // We initialize waiting_callbacks to 1 so that we won't run
426 // the completion callback until here even some of the callbacks
427 // are dispatched synchronously.
431 void Aborted() override
{
432 callback_
.Run(kQuotaErrorAbort
, UsageAndQuota());
436 void Completed() override
{
437 DCHECK(!has_usage_
|| usage_and_quota_
.usage
>= 0);
438 DCHECK(!has_global_limited_usage_
||
439 usage_and_quota_
.global_limited_usage
>= 0);
440 DCHECK(!has_quota_
|| usage_and_quota_
.quota
>= 0);
441 DCHECK(!has_available_disk_space_
||
442 usage_and_quota_
.available_disk_space
>= 0);
444 callback_
.Run(status_
, usage_and_quota_
);
448 void CheckCompleted() {
449 if (--waiting_callbacks_
<= 0)
453 // For sanity checks, they're checked only when DCHECK is on.
455 bool has_global_limited_usage_
;
457 bool has_available_disk_space_
;
459 QuotaStatusCode status_
;
460 UsageAndQuota usage_and_quota_
;
461 QuotaManager::UsageAndQuotaCallback callback_
;
462 int waiting_callbacks_
;
464 DISALLOW_COPY_AND_ASSIGN(UsageAndQuotaCallbackDispatcher
);
467 class QuotaManager::GetUsageInfoTask
: public QuotaTask
{
470 QuotaManager
* manager
,
471 const GetUsageInfoCallback
& callback
)
472 : QuotaTask(manager
),
474 weak_factory_(this) {
478 void Run() override
{
479 remaining_trackers_
= 3;
480 // This will populate cached hosts and usage info.
481 manager()->GetUsageTracker(kStorageTypeTemporary
)->GetGlobalUsage(
482 base::Bind(&GetUsageInfoTask::DidGetGlobalUsage
,
483 weak_factory_
.GetWeakPtr(),
484 kStorageTypeTemporary
));
485 manager()->GetUsageTracker(kStorageTypePersistent
)->GetGlobalUsage(
486 base::Bind(&GetUsageInfoTask::DidGetGlobalUsage
,
487 weak_factory_
.GetWeakPtr(),
488 kStorageTypePersistent
));
489 manager()->GetUsageTracker(kStorageTypeSyncable
)->GetGlobalUsage(
490 base::Bind(&GetUsageInfoTask::DidGetGlobalUsage
,
491 weak_factory_
.GetWeakPtr(),
492 kStorageTypeSyncable
));
495 void Completed() override
{
496 callback_
.Run(entries_
);
500 void Aborted() override
{
501 callback_
.Run(UsageInfoEntries());
506 void AddEntries(StorageType type
, UsageTracker
* tracker
) {
507 std::map
<std::string
, int64
> host_usage
;
508 tracker
->GetCachedHostsUsage(&host_usage
);
509 for (std::map
<std::string
, int64
>::const_iterator iter
= host_usage
.begin();
510 iter
!= host_usage
.end();
512 entries_
.push_back(UsageInfo(iter
->first
, type
, iter
->second
));
514 if (--remaining_trackers_
== 0)
518 void DidGetGlobalUsage(StorageType type
, int64
, int64
) {
519 DCHECK(manager()->GetUsageTracker(type
));
520 AddEntries(type
, manager()->GetUsageTracker(type
));
523 QuotaManager
* manager() const {
524 return static_cast<QuotaManager
*>(observer());
527 GetUsageInfoCallback callback_
;
528 UsageInfoEntries entries_
;
529 int remaining_trackers_
;
530 base::WeakPtrFactory
<GetUsageInfoTask
> weak_factory_
;
532 DISALLOW_COPY_AND_ASSIGN(GetUsageInfoTask
);
535 class QuotaManager::OriginDataDeleter
: public QuotaTask
{
537 OriginDataDeleter(QuotaManager
* manager
,
540 int quota_client_mask
,
541 const StatusCallback
& callback
)
542 : QuotaTask(manager
),
545 quota_client_mask_(quota_client_mask
),
547 remaining_clients_(-1),
550 weak_factory_(this) {}
553 void Run() override
{
555 remaining_clients_
= manager()->clients_
.size();
556 for (QuotaClientList::iterator iter
= manager()->clients_
.begin();
557 iter
!= manager()->clients_
.end(); ++iter
) {
558 if (quota_client_mask_
& (*iter
)->id()) {
559 (*iter
)->DeleteOriginData(
561 base::Bind(&OriginDataDeleter::DidDeleteOriginData
,
562 weak_factory_
.GetWeakPtr()));
565 if (--remaining_clients_
== 0)
571 void Completed() override
{
572 if (error_count_
== 0) {
573 // Only remove the entire origin if we didn't skip any client types.
574 if (skipped_clients_
== 0)
575 manager()->DeleteOriginFromDatabase(origin_
, type_
);
576 callback_
.Run(kQuotaStatusOk
);
578 callback_
.Run(kQuotaErrorInvalidModification
);
583 void Aborted() override
{
584 callback_
.Run(kQuotaErrorAbort
);
589 void DidDeleteOriginData(QuotaStatusCode status
) {
590 DCHECK_GT(remaining_clients_
, 0);
592 if (status
!= kQuotaStatusOk
)
595 if (--remaining_clients_
== 0)
599 QuotaManager
* manager() const {
600 return static_cast<QuotaManager
*>(observer());
605 int quota_client_mask_
;
607 int remaining_clients_
;
608 int skipped_clients_
;
609 StatusCallback callback_
;
611 base::WeakPtrFactory
<OriginDataDeleter
> weak_factory_
;
612 DISALLOW_COPY_AND_ASSIGN(OriginDataDeleter
);
615 class QuotaManager::HostDataDeleter
: public QuotaTask
{
617 HostDataDeleter(QuotaManager
* manager
,
618 const std::string
& host
,
620 int quota_client_mask
,
621 const StatusCallback
& callback
)
622 : QuotaTask(manager
),
625 quota_client_mask_(quota_client_mask
),
627 remaining_clients_(-1),
628 remaining_deleters_(-1),
630 weak_factory_(this) {}
633 void Run() override
{
635 remaining_clients_
= manager()->clients_
.size();
636 for (QuotaClientList::iterator iter
= manager()->clients_
.begin();
637 iter
!= manager()->clients_
.end(); ++iter
) {
638 (*iter
)->GetOriginsForHost(
640 base::Bind(&HostDataDeleter::DidGetOriginsForHost
,
641 weak_factory_
.GetWeakPtr()));
645 void Completed() override
{
646 if (error_count_
== 0) {
647 callback_
.Run(kQuotaStatusOk
);
649 callback_
.Run(kQuotaErrorInvalidModification
);
654 void Aborted() override
{
655 callback_
.Run(kQuotaErrorAbort
);
660 void DidGetOriginsForHost(const std::set
<GURL
>& origins
) {
661 DCHECK_GT(remaining_clients_
, 0);
663 origins_
.insert(origins
.begin(), origins
.end());
665 if (--remaining_clients_
== 0) {
666 if (!origins_
.empty())
667 ScheduleOriginsDeletion();
673 void ScheduleOriginsDeletion() {
674 remaining_deleters_
= origins_
.size();
675 for (std::set
<GURL
>::const_iterator p
= origins_
.begin();
678 OriginDataDeleter
* deleter
=
679 new OriginDataDeleter(
680 manager(), *p
, type_
, quota_client_mask_
,
681 base::Bind(&HostDataDeleter::DidDeleteOriginData
,
682 weak_factory_
.GetWeakPtr()));
687 void DidDeleteOriginData(QuotaStatusCode status
) {
688 DCHECK_GT(remaining_deleters_
, 0);
690 if (status
!= kQuotaStatusOk
)
693 if (--remaining_deleters_
== 0)
697 QuotaManager
* manager() const {
698 return static_cast<QuotaManager
*>(observer());
703 int quota_client_mask_
;
704 std::set
<GURL
> origins_
;
706 int remaining_clients_
;
707 int remaining_deleters_
;
708 StatusCallback callback_
;
710 base::WeakPtrFactory
<HostDataDeleter
> weak_factory_
;
711 DISALLOW_COPY_AND_ASSIGN(HostDataDeleter
);
714 class QuotaManager::GetModifiedSinceHelper
{
716 bool GetModifiedSinceOnDBThread(StorageType type
,
717 base::Time modified_since
,
718 QuotaDatabase
* database
) {
720 return database
->GetOriginsModifiedSince(type
, &origins_
, modified_since
);
723 void DidGetModifiedSince(const base::WeakPtr
<QuotaManager
>& manager
,
724 const GetOriginsCallback
& callback
,
728 // The operation was aborted.
729 callback
.Run(std::set
<GURL
>(), type
);
732 manager
->DidDatabaseWork(success
);
733 callback
.Run(origins_
, type
);
737 std::set
<GURL
> origins_
;
740 class QuotaManager::DumpQuotaTableHelper
{
742 bool DumpQuotaTableOnDBThread(QuotaDatabase
* database
) {
744 return database
->DumpQuotaTable(
745 base::Bind(&DumpQuotaTableHelper::AppendEntry
, base::Unretained(this)));
748 void DidDumpQuotaTable(const base::WeakPtr
<QuotaManager
>& manager
,
749 const DumpQuotaTableCallback
& callback
,
752 // The operation was aborted.
753 callback
.Run(QuotaTableEntries());
756 manager
->DidDatabaseWork(success
);
757 callback
.Run(entries_
);
761 bool AppendEntry(const QuotaTableEntry
& entry
) {
762 entries_
.push_back(entry
);
766 QuotaTableEntries entries_
;
769 class QuotaManager::DumpOriginInfoTableHelper
{
771 bool DumpOriginInfoTableOnDBThread(QuotaDatabase
* database
) {
773 return database
->DumpOriginInfoTable(
774 base::Bind(&DumpOriginInfoTableHelper::AppendEntry
,
775 base::Unretained(this)));
778 void DidDumpOriginInfoTable(const base::WeakPtr
<QuotaManager
>& manager
,
779 const DumpOriginInfoTableCallback
& callback
,
782 // The operation was aborted.
783 callback
.Run(OriginInfoTableEntries());
786 manager
->DidDatabaseWork(success
);
787 callback
.Run(entries_
);
791 bool AppendEntry(const OriginInfoTableEntry
& entry
) {
792 entries_
.push_back(entry
);
796 OriginInfoTableEntries entries_
;
799 // QuotaManager ---------------------------------------------------------------
801 QuotaManager::QuotaManager(
803 const base::FilePath
& profile_path
,
804 const scoped_refptr
<base::SingleThreadTaskRunner
>& io_thread
,
805 const scoped_refptr
<base::SequencedTaskRunner
>& db_thread
,
806 const scoped_refptr
<SpecialStoragePolicy
>& special_storage_policy
)
807 : is_incognito_(is_incognito
),
808 profile_path_(profile_path
),
809 proxy_(new QuotaManagerProxy(this, io_thread
)),
811 eviction_disabled_(false),
812 io_thread_(io_thread
),
813 db_thread_(db_thread
),
814 temporary_quota_initialized_(false),
815 temporary_quota_override_(-1),
816 desired_available_space_(-1),
817 special_storage_policy_(special_storage_policy
),
818 get_disk_space_fn_(&CallSystemGetAmountOfFreeDiskSpace
),
819 storage_monitor_(new StorageMonitor(this)),
820 weak_factory_(this) {
823 void QuotaManager::GetUsageInfo(const GetUsageInfoCallback
& callback
) {
825 GetUsageInfoTask
* get_usage_info
= new GetUsageInfoTask(this, callback
);
826 get_usage_info
->Start();
829 void QuotaManager::GetUsageAndQuotaForWebApps(
832 const GetUsageAndQuotaCallback
& callback
) {
833 if (type
!= kStorageTypeTemporary
&&
834 type
!= kStorageTypePersistent
&&
835 type
!= kStorageTypeSyncable
) {
836 callback
.Run(kQuotaErrorNotSupported
, 0, 0);
840 DCHECK(origin
== origin
.GetOrigin());
843 bool unlimited
= IsStorageUnlimited(origin
, type
);
844 bool can_query_disk_size
= CanQueryDiskSize(origin
);
846 UsageAndQuotaCallbackDispatcher
* dispatcher
=
847 new UsageAndQuotaCallbackDispatcher(this);
849 UsageAndQuota usage_and_quota
;
851 dispatcher
->set_quota(kNoLimit
);
853 if (type
== kStorageTypeTemporary
) {
854 GetUsageTracker(type
)->GetGlobalLimitedUsage(
855 dispatcher
->GetGlobalLimitedUsageCallback());
856 GetTemporaryGlobalQuota(dispatcher
->GetQuotaCallback());
857 } else if (type
== kStorageTypePersistent
) {
858 GetPersistentHostQuota(net::GetHostOrSpecFromURL(origin
),
859 dispatcher
->GetQuotaCallback());
861 dispatcher
->set_quota(kSyncableStorageDefaultHostQuota
);
865 DCHECK(GetUsageTracker(type
));
866 GetUsageTracker(type
)->GetHostUsage(net::GetHostOrSpecFromURL(origin
),
867 dispatcher
->GetHostUsageCallback());
869 if (!is_incognito_
&& (unlimited
|| can_query_disk_size
))
870 GetAvailableSpace(dispatcher
->GetAvailableSpaceCallback());
872 dispatcher
->WaitForResults(base::Bind(
873 &DispatchUsageAndQuotaForWebApps
,
874 type
, is_incognito_
, unlimited
, can_query_disk_size
,
878 void QuotaManager::GetUsageAndQuota(
879 const GURL
& origin
, StorageType type
,
880 const GetUsageAndQuotaCallback
& callback
) {
881 DCHECK(origin
== origin
.GetOrigin());
883 if (IsStorageUnlimited(origin
, type
)) {
884 callback
.Run(kQuotaStatusOk
, 0, kNoLimit
);
888 GetUsageAndQuotaForWebApps(origin
, type
, callback
);
891 void QuotaManager::NotifyStorageAccessed(
892 QuotaClient::ID client_id
,
893 const GURL
& origin
, StorageType type
) {
894 DCHECK(origin
== origin
.GetOrigin());
895 NotifyStorageAccessedInternal(client_id
, origin
, type
, base::Time::Now());
898 void QuotaManager::NotifyStorageModified(
899 QuotaClient::ID client_id
,
900 const GURL
& origin
, StorageType type
, int64 delta
) {
901 DCHECK(origin
== origin
.GetOrigin());
902 NotifyStorageModifiedInternal(client_id
, origin
, type
, delta
,
906 void QuotaManager::NotifyOriginInUse(const GURL
& origin
) {
907 DCHECK(io_thread_
->BelongsToCurrentThread());
908 origins_in_use_
[origin
]++;
911 void QuotaManager::NotifyOriginNoLongerInUse(const GURL
& origin
) {
912 DCHECK(io_thread_
->BelongsToCurrentThread());
913 DCHECK(IsOriginInUse(origin
));
914 int& count
= origins_in_use_
[origin
];
916 origins_in_use_
.erase(origin
);
919 void QuotaManager::SetUsageCacheEnabled(QuotaClient::ID client_id
,
924 DCHECK(GetUsageTracker(type
));
925 GetUsageTracker(type
)->SetUsageCacheEnabled(client_id
, origin
, enabled
);
928 void QuotaManager::DeleteOriginData(
929 const GURL
& origin
, StorageType type
, int quota_client_mask
,
930 const StatusCallback
& callback
) {
933 if (origin
.is_empty() || clients_
.empty()) {
934 callback
.Run(kQuotaStatusOk
);
938 DCHECK(origin
== origin
.GetOrigin());
939 OriginDataDeleter
* deleter
=
940 new OriginDataDeleter(this, origin
, type
, quota_client_mask
, callback
);
944 void QuotaManager::DeleteHostData(const std::string
& host
,
946 int quota_client_mask
,
947 const StatusCallback
& callback
) {
950 if (host
.empty() || clients_
.empty()) {
951 callback
.Run(kQuotaStatusOk
);
955 HostDataDeleter
* deleter
=
956 new HostDataDeleter(this, host
, type
, quota_client_mask
, callback
);
960 void QuotaManager::GetAvailableSpace(const AvailableSpaceCallback
& callback
) {
961 if (!available_space_callbacks_
.Add(callback
))
964 PostTaskAndReplyWithResult(db_thread_
.get(),
966 base::Bind(get_disk_space_fn_
, profile_path_
),
967 base::Bind(&QuotaManager::DidGetAvailableSpace
,
968 weak_factory_
.GetWeakPtr()));
971 void QuotaManager::GetTemporaryGlobalQuota(const QuotaCallback
& callback
) {
973 if (!temporary_quota_initialized_
) {
974 db_initialization_callbacks_
.Add(base::Bind(
975 &QuotaManager::GetTemporaryGlobalQuota
,
976 weak_factory_
.GetWeakPtr(), callback
));
980 if (temporary_quota_override_
> 0) {
981 callback
.Run(kQuotaStatusOk
, temporary_quota_override_
);
985 UsageAndQuotaCallbackDispatcher
* dispatcher
=
986 new UsageAndQuotaCallbackDispatcher(this);
987 GetUsageTracker(kStorageTypeTemporary
)->
988 GetGlobalLimitedUsage(dispatcher
->GetGlobalLimitedUsageCallback());
989 GetAvailableSpace(dispatcher
->GetAvailableSpaceCallback());
990 dispatcher
->WaitForResults(
991 base::Bind(&DispatchTemporaryGlobalQuotaCallback
, callback
));
994 void QuotaManager::SetTemporaryGlobalOverrideQuota(
995 int64 new_quota
, const QuotaCallback
& callback
) {
999 if (!callback
.is_null())
1000 callback
.Run(kQuotaErrorInvalidModification
, -1);
1005 if (!callback
.is_null())
1006 callback
.Run(kQuotaErrorInvalidAccess
, -1);
1010 int64
* new_quota_ptr
= new int64(new_quota
);
1011 PostTaskAndReplyWithResultForDBThread(
1013 base::Bind(&SetTemporaryGlobalOverrideQuotaOnDBThread
,
1014 base::Unretained(new_quota_ptr
)),
1015 base::Bind(&QuotaManager::DidSetTemporaryGlobalOverrideQuota
,
1016 weak_factory_
.GetWeakPtr(),
1018 base::Owned(new_quota_ptr
)));
1021 void QuotaManager::GetPersistentHostQuota(const std::string
& host
,
1022 const QuotaCallback
& callback
) {
1025 // This could happen if we are called on file:///.
1026 // TODO(kinuko) We may want to respect --allow-file-access-from-files
1027 // command line switch.
1028 callback
.Run(kQuotaStatusOk
, 0);
1032 if (!persistent_host_quota_callbacks_
.Add(host
, callback
))
1035 int64
* quota_ptr
= new int64(0);
1036 PostTaskAndReplyWithResultForDBThread(
1038 base::Bind(&GetPersistentHostQuotaOnDBThread
,
1040 base::Unretained(quota_ptr
)),
1041 base::Bind(&QuotaManager::DidGetPersistentHostQuota
,
1042 weak_factory_
.GetWeakPtr(),
1044 base::Owned(quota_ptr
)));
1047 void QuotaManager::SetPersistentHostQuota(const std::string
& host
,
1049 const QuotaCallback
& callback
) {
1052 // This could happen if we are called on file:///.
1053 callback
.Run(kQuotaErrorNotSupported
, 0);
1057 if (new_quota
< 0) {
1058 callback
.Run(kQuotaErrorInvalidModification
, -1);
1062 if (kPerHostPersistentQuotaLimit
< new_quota
) {
1063 // Cap the requested size at the per-host quota limit.
1064 new_quota
= kPerHostPersistentQuotaLimit
;
1068 callback
.Run(kQuotaErrorInvalidAccess
, -1);
1072 int64
* new_quota_ptr
= new int64(new_quota
);
1073 PostTaskAndReplyWithResultForDBThread(
1075 base::Bind(&SetPersistentHostQuotaOnDBThread
,
1077 base::Unretained(new_quota_ptr
)),
1078 base::Bind(&QuotaManager::DidSetPersistentHostQuota
,
1079 weak_factory_
.GetWeakPtr(),
1082 base::Owned(new_quota_ptr
)));
1085 void QuotaManager::GetGlobalUsage(StorageType type
,
1086 const GlobalUsageCallback
& callback
) {
1088 DCHECK(GetUsageTracker(type
));
1089 GetUsageTracker(type
)->GetGlobalUsage(callback
);
1092 void QuotaManager::GetHostUsage(const std::string
& host
,
1094 const UsageCallback
& callback
) {
1096 DCHECK(GetUsageTracker(type
));
1097 GetUsageTracker(type
)->GetHostUsage(host
, callback
);
1100 void QuotaManager::GetHostUsage(const std::string
& host
,
1102 QuotaClient::ID client_id
,
1103 const UsageCallback
& callback
) {
1105 DCHECK(GetUsageTracker(type
));
1106 ClientUsageTracker
* tracker
=
1107 GetUsageTracker(type
)->GetClientTracker(client_id
);
1112 tracker
->GetHostUsage(host
, callback
);
1115 bool QuotaManager::IsTrackingHostUsage(StorageType type
,
1116 QuotaClient::ID client_id
) const {
1117 UsageTracker
* tracker
= GetUsageTracker(type
);
1118 return tracker
&& tracker
->GetClientTracker(client_id
);
1121 void QuotaManager::GetStatistics(
1122 std::map
<std::string
, std::string
>* statistics
) {
1124 if (temporary_storage_evictor_
) {
1125 std::map
<std::string
, int64
> stats
;
1126 temporary_storage_evictor_
->GetStatistics(&stats
);
1127 for (std::map
<std::string
, int64
>::iterator p
= stats
.begin();
1130 (*statistics
)[p
->first
] = base::Int64ToString(p
->second
);
1134 bool QuotaManager::IsStorageUnlimited(const GURL
& origin
,
1135 StorageType type
) const {
1136 // For syncable storage we should always enforce quota (since the
1137 // quota must be capped by the server limit).
1138 if (type
== kStorageTypeSyncable
)
1140 if (type
== kStorageTypeQuotaNotManaged
)
1142 return special_storage_policy_
.get() &&
1143 special_storage_policy_
->IsStorageUnlimited(origin
);
1146 void QuotaManager::GetOriginsModifiedSince(StorageType type
,
1147 base::Time modified_since
,
1148 const GetOriginsCallback
& callback
) {
1150 GetModifiedSinceHelper
* helper
= new GetModifiedSinceHelper
;
1151 PostTaskAndReplyWithResultForDBThread(
1153 base::Bind(&GetModifiedSinceHelper::GetModifiedSinceOnDBThread
,
1154 base::Unretained(helper
),
1157 base::Bind(&GetModifiedSinceHelper::DidGetModifiedSince
,
1158 base::Owned(helper
),
1159 weak_factory_
.GetWeakPtr(),
1164 bool QuotaManager::ResetUsageTracker(StorageType type
) {
1165 DCHECK(GetUsageTracker(type
));
1166 if (GetUsageTracker(type
)->IsWorking())
1169 case kStorageTypeTemporary
:
1170 temporary_usage_tracker_
.reset(new UsageTracker(
1171 clients_
, kStorageTypeTemporary
, special_storage_policy_
.get(),
1172 storage_monitor_
.get()));
1174 case kStorageTypePersistent
:
1175 persistent_usage_tracker_
.reset(new UsageTracker(
1176 clients_
, kStorageTypePersistent
, special_storage_policy_
.get(),
1177 storage_monitor_
.get()));
1179 case kStorageTypeSyncable
:
1180 syncable_usage_tracker_
.reset(new UsageTracker(
1181 clients_
, kStorageTypeSyncable
, special_storage_policy_
.get(),
1182 storage_monitor_
.get()));
1190 void QuotaManager::AddStorageObserver(
1191 StorageObserver
* observer
, const StorageObserver::MonitorParams
& params
) {
1193 storage_monitor_
->AddObserver(observer
, params
);
1196 void QuotaManager::RemoveStorageObserver(StorageObserver
* observer
) {
1198 storage_monitor_
->RemoveObserver(observer
);
1201 void QuotaManager::RemoveStorageObserverForFilter(
1202 StorageObserver
* observer
, const StorageObserver::Filter
& filter
) {
1204 storage_monitor_
->RemoveObserverForFilter(observer
, filter
);
1207 QuotaManager::~QuotaManager() {
1208 proxy_
->manager_
= NULL
;
1209 std::for_each(clients_
.begin(), clients_
.end(),
1210 std::mem_fun(&QuotaClient::OnQuotaManagerDestroyed
));
1212 db_thread_
->DeleteSoon(FROM_HERE
, database_
.release());
1215 QuotaManager::EvictionContext::EvictionContext()
1216 : evicted_type(kStorageTypeUnknown
) {
1219 QuotaManager::EvictionContext::~EvictionContext() {
1222 void QuotaManager::LazyInitialize() {
1223 DCHECK(io_thread_
->BelongsToCurrentThread());
1225 // Initialization seems to be done already.
1229 // Use an empty path to open an in-memory only databse for incognito.
1230 database_
.reset(new QuotaDatabase(is_incognito_
? base::FilePath() :
1231 profile_path_
.AppendASCII(kDatabaseName
)));
1233 temporary_usage_tracker_
.reset(new UsageTracker(
1234 clients_
, kStorageTypeTemporary
, special_storage_policy_
.get(),
1235 storage_monitor_
.get()));
1236 persistent_usage_tracker_
.reset(new UsageTracker(
1237 clients_
, kStorageTypePersistent
, special_storage_policy_
.get(),
1238 storage_monitor_
.get()));
1239 syncable_usage_tracker_
.reset(new UsageTracker(
1240 clients_
, kStorageTypeSyncable
, special_storage_policy_
.get(),
1241 storage_monitor_
.get()));
1243 int64
* temporary_quota_override
= new int64(-1);
1244 int64
* desired_available_space
= new int64(-1);
1245 PostTaskAndReplyWithResultForDBThread(
1247 base::Bind(&InitializeOnDBThread
,
1248 base::Unretained(temporary_quota_override
),
1249 base::Unretained(desired_available_space
)),
1250 base::Bind(&QuotaManager::DidInitialize
,
1251 weak_factory_
.GetWeakPtr(),
1252 base::Owned(temporary_quota_override
),
1253 base::Owned(desired_available_space
)));
1256 void QuotaManager::RegisterClient(QuotaClient
* client
) {
1257 DCHECK(!database_
.get());
1258 clients_
.push_back(client
);
1261 UsageTracker
* QuotaManager::GetUsageTracker(StorageType type
) const {
1263 case kStorageTypeTemporary
:
1264 return temporary_usage_tracker_
.get();
1265 case kStorageTypePersistent
:
1266 return persistent_usage_tracker_
.get();
1267 case kStorageTypeSyncable
:
1268 return syncable_usage_tracker_
.get();
1269 case kStorageTypeQuotaNotManaged
:
1271 case kStorageTypeUnknown
:
1277 void QuotaManager::GetCachedOrigins(
1278 StorageType type
, std::set
<GURL
>* origins
) {
1281 DCHECK(GetUsageTracker(type
));
1282 GetUsageTracker(type
)->GetCachedOrigins(origins
);
1285 void QuotaManager::NotifyStorageAccessedInternal(
1286 QuotaClient::ID client_id
,
1287 const GURL
& origin
, StorageType type
,
1288 base::Time accessed_time
) {
1290 if (type
== kStorageTypeTemporary
&& !lru_origin_callback_
.is_null()) {
1291 // Record the accessed origins while GetLRUOrigin task is runing
1292 // to filter out them from eviction.
1293 access_notified_origins_
.insert(origin
);
1298 PostTaskAndReplyWithResultForDBThread(
1300 base::Bind(&UpdateAccessTimeOnDBThread
, origin
, type
, accessed_time
),
1301 base::Bind(&QuotaManager::DidDatabaseWork
,
1302 weak_factory_
.GetWeakPtr()));
1305 void QuotaManager::NotifyStorageModifiedInternal(
1306 QuotaClient::ID client_id
,
1310 base::Time modified_time
) {
1312 DCHECK(GetUsageTracker(type
));
1313 GetUsageTracker(type
)->UpdateUsageCache(client_id
, origin
, delta
);
1315 PostTaskAndReplyWithResultForDBThread(
1317 base::Bind(&UpdateModifiedTimeOnDBThread
, origin
, type
, modified_time
),
1318 base::Bind(&QuotaManager::DidDatabaseWork
,
1319 weak_factory_
.GetWeakPtr()));
1322 void QuotaManager::DumpQuotaTable(const DumpQuotaTableCallback
& callback
) {
1323 DumpQuotaTableHelper
* helper
= new DumpQuotaTableHelper
;
1324 PostTaskAndReplyWithResultForDBThread(
1326 base::Bind(&DumpQuotaTableHelper::DumpQuotaTableOnDBThread
,
1327 base::Unretained(helper
)),
1328 base::Bind(&DumpQuotaTableHelper::DidDumpQuotaTable
,
1329 base::Owned(helper
),
1330 weak_factory_
.GetWeakPtr(),
1334 void QuotaManager::DumpOriginInfoTable(
1335 const DumpOriginInfoTableCallback
& callback
) {
1336 DumpOriginInfoTableHelper
* helper
= new DumpOriginInfoTableHelper
;
1337 PostTaskAndReplyWithResultForDBThread(
1339 base::Bind(&DumpOriginInfoTableHelper::DumpOriginInfoTableOnDBThread
,
1340 base::Unretained(helper
)),
1341 base::Bind(&DumpOriginInfoTableHelper::DidDumpOriginInfoTable
,
1342 base::Owned(helper
),
1343 weak_factory_
.GetWeakPtr(),
1347 void QuotaManager::StartEviction() {
1348 DCHECK(!temporary_storage_evictor_
.get());
1349 temporary_storage_evictor_
.reset(new QuotaTemporaryStorageEvictor(
1350 this, kEvictionIntervalInMilliSeconds
));
1351 if (desired_available_space_
>= 0)
1352 temporary_storage_evictor_
->set_min_available_disk_space_to_start_eviction(
1353 desired_available_space_
);
1354 temporary_storage_evictor_
->Start();
1357 void QuotaManager::DeleteOriginFromDatabase(
1358 const GURL
& origin
, StorageType type
) {
1363 PostTaskAndReplyWithResultForDBThread(
1365 base::Bind(&DeleteOriginInfoOnDBThread
, origin
, type
),
1366 base::Bind(&QuotaManager::DidDatabaseWork
,
1367 weak_factory_
.GetWeakPtr()));
1370 void QuotaManager::DidOriginDataEvicted(QuotaStatusCode status
) {
1371 DCHECK(io_thread_
->BelongsToCurrentThread());
1373 // We only try evict origins that are not in use, so basically
1374 // deletion attempt for eviction should not fail. Let's record
1375 // the origin if we get error and exclude it from future eviction
1376 // if the error happens consistently (> kThresholdOfErrorsToBeBlacklisted).
1377 if (status
!= kQuotaStatusOk
)
1378 origins_in_error_
[eviction_context_
.evicted_origin
]++;
1380 eviction_context_
.evict_origin_data_callback
.Run(status
);
1381 eviction_context_
.evict_origin_data_callback
.Reset();
1384 void QuotaManager::ReportHistogram() {
1385 GetGlobalUsage(kStorageTypeTemporary
,
1387 &QuotaManager::DidGetTemporaryGlobalUsageForHistogram
,
1388 weak_factory_
.GetWeakPtr()));
1389 GetGlobalUsage(kStorageTypePersistent
,
1391 &QuotaManager::DidGetPersistentGlobalUsageForHistogram
,
1392 weak_factory_
.GetWeakPtr()));
1395 void QuotaManager::DidGetTemporaryGlobalUsageForHistogram(
1397 int64 unlimited_usage
) {
1398 UMA_HISTOGRAM_MBYTES("Quota.GlobalUsageOfTemporaryStorage", usage
);
1400 std::set
<GURL
> origins
;
1401 GetCachedOrigins(kStorageTypeTemporary
, &origins
);
1403 size_t num_origins
= origins
.size();
1404 size_t protected_origins
= 0;
1405 size_t unlimited_origins
= 0;
1406 CountOriginType(origins
,
1407 special_storage_policy_
.get(),
1409 &unlimited_origins
);
1411 UMA_HISTOGRAM_COUNTS("Quota.NumberOfTemporaryStorageOrigins",
1413 UMA_HISTOGRAM_COUNTS("Quota.NumberOfProtectedTemporaryStorageOrigins",
1415 UMA_HISTOGRAM_COUNTS("Quota.NumberOfUnlimitedTemporaryStorageOrigins",
1419 void QuotaManager::DidGetPersistentGlobalUsageForHistogram(
1421 int64 unlimited_usage
) {
1422 UMA_HISTOGRAM_MBYTES("Quota.GlobalUsageOfPersistentStorage", usage
);
1424 std::set
<GURL
> origins
;
1425 GetCachedOrigins(kStorageTypePersistent
, &origins
);
1427 size_t num_origins
= origins
.size();
1428 size_t protected_origins
= 0;
1429 size_t unlimited_origins
= 0;
1430 CountOriginType(origins
,
1431 special_storage_policy_
.get(),
1433 &unlimited_origins
);
1435 UMA_HISTOGRAM_COUNTS("Quota.NumberOfPersistentStorageOrigins",
1437 UMA_HISTOGRAM_COUNTS("Quota.NumberOfProtectedPersistentStorageOrigins",
1439 UMA_HISTOGRAM_COUNTS("Quota.NumberOfUnlimitedPersistentStorageOrigins",
1443 void QuotaManager::GetLRUOrigin(
1445 const GetLRUOriginCallback
& callback
) {
1447 // This must not be called while there's an in-flight task.
1448 DCHECK(lru_origin_callback_
.is_null());
1449 lru_origin_callback_
= callback
;
1451 lru_origin_callback_
.Run(GURL());
1452 lru_origin_callback_
.Reset();
1456 std::set
<GURL
>* exceptions
= new std::set
<GURL
>;
1457 for (std::map
<GURL
, int>::const_iterator p
= origins_in_use_
.begin();
1458 p
!= origins_in_use_
.end();
1461 exceptions
->insert(p
->first
);
1463 for (std::map
<GURL
, int>::const_iterator p
= origins_in_error_
.begin();
1464 p
!= origins_in_error_
.end();
1466 if (p
->second
> QuotaManager::kThresholdOfErrorsToBeBlacklisted
)
1467 exceptions
->insert(p
->first
);
1470 GURL
* url
= new GURL
;
1471 PostTaskAndReplyWithResultForDBThread(
1473 base::Bind(&GetLRUOriginOnDBThread
,
1475 base::Owned(exceptions
),
1476 special_storage_policy_
,
1477 base::Unretained(url
)),
1478 base::Bind(&QuotaManager::DidGetLRUOrigin
,
1479 weak_factory_
.GetWeakPtr(),
1483 void QuotaManager::EvictOriginData(
1486 const EvictOriginDataCallback
& callback
) {
1487 DCHECK(io_thread_
->BelongsToCurrentThread());
1488 DCHECK_EQ(type
, kStorageTypeTemporary
);
1490 eviction_context_
.evicted_origin
= origin
;
1491 eviction_context_
.evicted_type
= type
;
1492 eviction_context_
.evict_origin_data_callback
= callback
;
1494 DeleteOriginData(origin
, type
, QuotaClient::kAllClientsMask
,
1495 base::Bind(&QuotaManager::DidOriginDataEvicted
,
1496 weak_factory_
.GetWeakPtr()));
1499 void QuotaManager::GetUsageAndQuotaForEviction(
1500 const UsageAndQuotaCallback
& callback
) {
1501 DCHECK(io_thread_
->BelongsToCurrentThread());
1504 UsageAndQuotaCallbackDispatcher
* dispatcher
=
1505 new UsageAndQuotaCallbackDispatcher(this);
1506 GetUsageTracker(kStorageTypeTemporary
)->
1507 GetGlobalLimitedUsage(dispatcher
->GetGlobalLimitedUsageCallback());
1508 GetTemporaryGlobalQuota(dispatcher
->GetQuotaCallback());
1509 GetAvailableSpace(dispatcher
->GetAvailableSpaceCallback());
1510 dispatcher
->WaitForResults(callback
);
1513 void QuotaManager::DidSetTemporaryGlobalOverrideQuota(
1514 const QuotaCallback
& callback
,
1515 const int64
* new_quota
,
1517 QuotaStatusCode status
= kQuotaErrorInvalidAccess
;
1518 DidDatabaseWork(success
);
1520 temporary_quota_override_
= *new_quota
;
1521 status
= kQuotaStatusOk
;
1524 if (callback
.is_null())
1527 callback
.Run(status
, *new_quota
);
1530 void QuotaManager::DidGetPersistentHostQuota(const std::string
& host
,
1533 DidDatabaseWork(success
);
1534 persistent_host_quota_callbacks_
.Run(host
, kQuotaStatusOk
, *quota
);
1537 void QuotaManager::DidSetPersistentHostQuota(const std::string
& host
,
1538 const QuotaCallback
& callback
,
1539 const int64
* new_quota
,
1541 DidDatabaseWork(success
);
1542 callback
.Run(success
? kQuotaStatusOk
: kQuotaErrorInvalidAccess
, *new_quota
);
1545 void QuotaManager::DidInitialize(int64
* temporary_quota_override
,
1546 int64
* desired_available_space
,
1548 temporary_quota_override_
= *temporary_quota_override
;
1549 desired_available_space_
= *desired_available_space
;
1550 temporary_quota_initialized_
= true;
1551 DidDatabaseWork(success
);
1553 histogram_timer_
.Start(FROM_HERE
,
1554 base::TimeDelta::FromMilliseconds(
1555 kReportHistogramInterval
),
1556 this, &QuotaManager::ReportHistogram
);
1558 db_initialization_callbacks_
.Run();
1559 GetTemporaryGlobalQuota(
1560 base::Bind(&QuotaManager::DidGetInitialTemporaryGlobalQuota
,
1561 weak_factory_
.GetWeakPtr()));
1564 void QuotaManager::DidGetLRUOrigin(const GURL
* origin
,
1566 DidDatabaseWork(success
);
1567 // Make sure the returned origin is (still) not in the origin_in_use_ set
1568 // and has not been accessed since we posted the task.
1569 if (origins_in_use_
.find(*origin
) != origins_in_use_
.end() ||
1570 access_notified_origins_
.find(*origin
) != access_notified_origins_
.end())
1571 lru_origin_callback_
.Run(GURL());
1573 lru_origin_callback_
.Run(*origin
);
1574 access_notified_origins_
.clear();
1575 lru_origin_callback_
.Reset();
1578 void QuotaManager::DidGetInitialTemporaryGlobalQuota(
1579 QuotaStatusCode status
, int64 quota_unused
) {
1580 if (eviction_disabled_
)
1583 std::set
<GURL
>* origins
= new std::set
<GURL
>;
1584 temporary_usage_tracker_
->GetCachedOrigins(origins
);
1585 // This will call the StartEviction() when initial origin registration
1587 PostTaskAndReplyWithResultForDBThread(
1589 base::Bind(&InitializeTemporaryOriginsInfoOnDBThread
,
1590 base::Owned(origins
)),
1591 base::Bind(&QuotaManager::DidInitializeTemporaryOriginsInfo
,
1592 weak_factory_
.GetWeakPtr()));
1595 void QuotaManager::DidInitializeTemporaryOriginsInfo(bool success
) {
1596 DidDatabaseWork(success
);
1601 void QuotaManager::DidGetAvailableSpace(int64 space
) {
1602 available_space_callbacks_
.Run(kQuotaStatusOk
, space
);
1605 void QuotaManager::DidDatabaseWork(bool success
) {
1606 db_disabled_
= !success
;
1609 void QuotaManager::DeleteOnCorrectThread() const {
1610 if (!io_thread_
->BelongsToCurrentThread() &&
1611 io_thread_
->DeleteSoon(FROM_HERE
, this)) {
1617 void QuotaManager::PostTaskAndReplyWithResultForDBThread(
1618 const tracked_objects::Location
& from_here
,
1619 const base::Callback
<bool(QuotaDatabase
*)>& task
,
1620 const base::Callback
<void(bool)>& reply
) {
1621 // Deleting manager will post another task to DB thread to delete
1622 // |database_|, therefore we can be sure that database_ is alive when this
1624 base::PostTaskAndReplyWithResult(
1627 base::Bind(task
, base::Unretained(database_
.get())),
1631 } // namespace storage