#include "storage/browser/quota/quota_manager_impl.h"
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <cstdint>
#include <functional>
#include <limits>
#include <memory>
#include <utility>
#include "base/barrier_callback.h"
#include "base/barrier_closure.h"
#include "base/check_op.h"
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
#include "base/functional/concurrent_callbacks.h"
#include "base/functional/concurrent_closures.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/not_fatal_until.h"
#include "base/numerics/safe_conversions.h"
#include "base/rand_util.h"
#include "base/sequence_checker.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/system/sys_info.h"
#include "base/task/bind_post_task.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/thread_annotations.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "base/types/pass_key.h"
#include "components/services/storage/public/cpp/buckets/bucket_locator.h"
#include "components/services/storage/public/cpp/buckets/constants.h"
#include "components/services/storage/public/mojom/quota_client.mojom.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "sql/error_delegate_util.h"
#include "sql/sqlite_result_code.h"
#include "sql/sqlite_result_code_values.h"
#include "storage/browser/quota/client_usage_tracker.h"
#include "storage/browser/quota/quota_availability.h"
#include "storage/browser/quota/quota_callbacks.h"
#include "storage/browser/quota/quota_client_type.h"
#include "storage/browser/quota/quota_features.h"
#include "storage/browser/quota/quota_macros.h"
#include "storage/browser/quota/quota_manager_observer.mojom-forward.h"
#include "storage/browser/quota/quota_manager_observer.mojom.h"
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/browser/quota/quota_override_handle.h"
#include "storage/browser/quota/quota_temporary_storage_evictor.h"
#include "storage/browser/quota/usage_tracker.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h"
#include "third_party/blink/public/mojom/storage_key/storage_key.mojom.h"
#include "url/origin.h"
StorageKey;
StorageType;
namespace storage {
namespace {
enum class DatabaseDisabledReason { … };
constexpr int64_t kReportHistogramInterval = …;
constexpr double kStoragePressureThresholdRatio = …;
constexpr base::TimeDelta kStoragePressureCheckDiskStatsInterval = …;
int64_t RandomizeByPercent(int64_t value, int percent) { … }
bool IsSupportedType(StorageType type) { … }
bool IsSupportedIncognitoType(StorageType type) { … }
void ReportDatabaseDisabledReason(DatabaseDisabledReason reason) { … }
void DidGetUsageAndQuotaStripBreakdown(
QuotaManagerImpl::UsageAndQuotaCallback callback,
blink::mojom::QuotaStatusCode status,
int64_t usage,
int64_t quota,
blink::mojom::UsageBreakdownPtr usage_breakdown) { … }
void DidGetUsageAndQuotaStripOverride(
QuotaManagerImpl::UsageAndQuotaWithBreakdownCallback callback,
blink::mojom::QuotaStatusCode status,
int64_t usage,
int64_t quota,
bool is_override_enabled,
blink::mojom::UsageBreakdownPtr usage_breakdown) { … }
}
int64_t QuotaManagerImpl::kSyncableStorageDefaultStorageKeyQuota = …;
constexpr int64_t QuotaManagerImpl::kGBytes;
constexpr int64_t QuotaManagerImpl::kNoLimit;
constexpr int QuotaManagerImpl::kEvictionIntervalInMilliSeconds;
constexpr int QuotaManagerImpl::kThresholdOfErrorsToBeDenylisted;
constexpr int QuotaManagerImpl::kThresholdRandomizationPercent;
constexpr char QuotaManagerImpl::kDatabaseName[];
constexpr char QuotaManagerImpl::kEvictedBucketAccessedCountHistogram[];
constexpr char QuotaManagerImpl::kEvictedBucketDaysSinceAccessHistogram[];
QuotaManagerImpl::QuotaOverride::QuotaOverride() = default;
QuotaManagerImpl::QuotaOverride::~QuotaOverride() = default;
class QuotaManagerImpl::UsageAndQuotaInfoGatherer : public QuotaTask { … };
class QuotaManagerImpl::EvictionRoundInfoHelper { … };
class QuotaManagerImpl::GetUsageInfoTask : public QuotaTask { … };
class QuotaManagerImpl::StorageKeyGathererTask { … };
class QuotaManagerImpl::BucketDataDeleter { … };
class QuotaManagerImpl::BucketSetDataDeleter { … };
class QuotaManagerImpl::StorageCleanupHelper : public QuotaTask { … };
class QuotaManagerImpl::DumpBucketTableHelper { … };
QuotaManagerImpl::QuotaManagerImpl(
bool is_incognito,
const base::FilePath& profile_path,
scoped_refptr<base::SingleThreadTaskRunner> io_thread,
base::RepeatingClosure quota_change_callback,
scoped_refptr<SpecialStoragePolicy> special_storage_policy,
const GetQuotaSettingsFunc& get_settings_function)
: … { … }
void QuotaManagerImpl::SetQuotaSettings(const QuotaSettings& settings) { … }
void QuotaManagerImpl::UpdateOrCreateBucket(
const BucketInitParams& bucket_params,
base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback) { … }
void QuotaManagerImpl::GetOrCreateBucketDeprecated(
const BucketInitParams& bucket_params,
blink::mojom::StorageType storage_type,
base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback) { … }
void QuotaManagerImpl::CreateBucketForTesting(
const StorageKey& storage_key,
const std::string& bucket_name,
blink::mojom::StorageType storage_type,
base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback) { … }
void QuotaManagerImpl::GetBucketByNameUnsafe(
const StorageKey& storage_key,
const std::string& bucket_name,
blink::mojom::StorageType type,
base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback) { … }
void QuotaManagerImpl::GetBucketById(
const BucketId& bucket_id,
base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback) { … }
void QuotaManagerImpl::GetStorageKeysForType(blink::mojom::StorageType type,
GetStorageKeysCallback callback) { … }
void QuotaManagerImpl::GetBucketsForType(
blink::mojom::StorageType type,
base::OnceCallback<void(QuotaErrorOr<std::set<BucketInfo>>)> callback) { … }
void QuotaManagerImpl::GetBucketsForHost(
const std::string& host,
blink::mojom::StorageType type,
base::OnceCallback<void(QuotaErrorOr<std::set<BucketInfo>>)> callback) { … }
void QuotaManagerImpl::GetBucketsForStorageKey(
const StorageKey& storage_key,
blink::mojom::StorageType type,
base::OnceCallback<void(QuotaErrorOr<std::set<BucketInfo>>)> callback,
bool delete_expired) { … }
void QuotaManagerImpl::GetUsageInfo(GetUsageInfoCallback callback) { … }
void QuotaManagerImpl::GetUsageAndQuotaForWebApps(
const StorageKey& storage_key,
StorageType type,
UsageAndQuotaCallback callback) { … }
void QuotaManagerImpl::GetUsageAndQuotaWithBreakdown(
const StorageKey& storage_key,
StorageType type,
UsageAndQuotaWithBreakdownCallback callback) { … }
void QuotaManagerImpl::GetUsageAndQuotaForDevtools(
const StorageKey& storage_key,
StorageType type,
UsageAndQuotaForDevtoolsCallback callback) { … }
void QuotaManagerImpl::GetUsageAndQuota(const StorageKey& storage_key,
StorageType type,
UsageAndQuotaCallback callback) { … }
void QuotaManagerImpl::GetBucketUsageAndQuota(BucketId id,
UsageAndQuotaCallback callback) { … }
void QuotaManagerImpl::GetBucketSpaceRemaining(
const BucketLocator& bucket,
base::OnceCallback<void(QuotaErrorOr<int64_t>)> callback) { … }
void QuotaManagerImpl::OnClientWriteFailed(const StorageKey& storage_key) { … }
void QuotaManagerImpl::SetUsageCacheEnabled(QuotaClientType client_id,
const StorageKey& storage_key,
StorageType type,
bool enabled) { … }
void QuotaManagerImpl::DeleteBucketData(const BucketLocator& bucket,
QuotaClientTypes quota_client_types,
StatusCallback callback) { … }
void QuotaManagerImpl::FindAndDeleteBucketData(const StorageKey& storage_key,
const std::string& bucket_name,
StatusCallback callback) { … }
void QuotaManagerImpl::UpdateBucketExpiration(
BucketId bucket,
const base::Time& expiration,
base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback) { … }
void QuotaManagerImpl::UpdateBucketPersistence(
BucketId bucket,
bool persistent,
base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback) { … }
void QuotaManagerImpl::PerformStorageCleanup(
StorageType type,
QuotaClientTypes quota_client_types,
base::OnceClosure callback) { … }
void QuotaManagerImpl::DeleteHostData(const std::string& host,
StorageType type,
StatusCallback callback) { … }
void QuotaManagerImpl::DeleteStorageKeyData(
const blink::StorageKey& storage_key,
blink::mojom::StorageType type,
StatusCallback callback) { … }
void QuotaManagerImpl::DidDeleteBuckets(
base::WeakPtr<QuotaManagerImpl> quota_manager,
StatusCallback callback,
BucketSetDataDeleter* deleter,
blink::mojom::QuotaStatusCode status_code) { … }
void QuotaManagerImpl::BindInternalsHandler(
mojo::PendingReceiver<mojom::QuotaInternalsHandler> receiver) { … }
void QuotaManagerImpl::GetDiskAvailabilityAndTempPoolSize(
GetDiskAvailabilityAndTempPoolSizeCallback callback) { … }
void QuotaManagerImpl::UpdateQuotaInternalsDiskAvailability(
base::OnceClosure barrier_callback,
AccumulateQuotaInternalsInfo* info,
int64_t total_space,
int64_t available_space) { … }
void QuotaManagerImpl::UpdateQuotaInternalsTempPoolSpace(
base::OnceClosure barrier_callback,
AccumulateQuotaInternalsInfo* info,
const QuotaSettings& settings) { … }
void QuotaManagerImpl::FinallySendDiskAvailabilityAndTempPoolSize(
GetDiskAvailabilityAndTempPoolSizeCallback callback,
std::unique_ptr<AccumulateQuotaInternalsInfo> info) { … }
void QuotaManagerImpl::GetStatistics(GetStatisticsCallback callback) { … }
void QuotaManagerImpl::GetGlobalUsage(StorageType type,
UsageCallback callback) { … }
void QuotaManagerImpl::GetGlobalUsageForInternals(
blink::mojom::StorageType storage_type,
GetGlobalUsageForInternalsCallback callback) { … }
void QuotaManagerImpl::GetStorageKeyUsageWithBreakdown(
const blink::StorageKey& storage_key,
StorageType type,
UsageWithBreakdownCallback callback) { … }
void QuotaManagerImpl::GetBucketUsageWithBreakdown(
const BucketLocator& bucket,
UsageWithBreakdownCallback callback) { … }
bool QuotaManagerImpl::IsStorageUnlimited(const StorageKey& storage_key,
StorageType type) const { … }
int64_t QuotaManagerImpl::GetQuotaForStorageKey(
const StorageKey& storage_key,
StorageType type,
const QuotaSettings& settings) const { … }
void QuotaManagerImpl::GetBucketsModifiedBetween(StorageType type,
base::Time begin,
base::Time end,
GetBucketsCallback callback) { … }
bool QuotaManagerImpl::ResetUsageTracker(StorageType type) { … }
QuotaManagerImpl::~QuotaManagerImpl() { … }
void QuotaManagerImpl::EnsureDatabaseOpened() { … }
void QuotaManagerImpl::MaybeBootstrapDatabase() { … }
void QuotaManagerImpl::DidGetBootstrapFlag(bool is_database_bootstrapped) { … }
void QuotaManagerImpl::BootstrapDatabase() { … }
void QuotaManagerImpl::DidGetStorageKeysForBootstrap(
StorageKeysByType storage_keys_by_type) { … }
void QuotaManagerImpl::DidBootstrapDatabase(QuotaError error) { … }
void QuotaManagerImpl::DidSetDatabaseBootstrapped(QuotaError error) { … }
void QuotaManagerImpl::RunDatabaseCallbacks() { … }
void QuotaManagerImpl::RegisterClient(
mojo::PendingRemote<mojom::QuotaClient> client,
QuotaClientType client_type,
const std::vector<blink::mojom::StorageType>& storage_types) { … }
UsageTracker* QuotaManagerImpl::GetUsageTracker(StorageType type) const { … }
void QuotaManagerImpl::NotifyBucketAccessed(const BucketLocator& bucket,
base::Time access_time) { … }
void QuotaManagerImpl::NotifyBucketModified(QuotaClientType client_id,
const BucketLocator& bucket,
std::optional<int64_t> delta,
base::Time modification_time,
base::OnceClosure callback) { … }
void QuotaManagerImpl::DumpBucketTable(DumpBucketTableCallback callback) { … }
void QuotaManagerImpl::RetrieveBucketsTable(
RetrieveBucketsTableCallback callback) { … }
void QuotaManagerImpl::RetrieveBucketUsageForBucketTable(
RetrieveBucketsTableCallback callback,
BucketTableEntries entries) { … }
void QuotaManagerImpl::AddBucketTableEntry(
mojom::BucketTableEntryPtr entry,
base::OnceCallback<void(mojom::BucketTableEntryPtr)> callback,
int64_t usage,
blink::mojom::UsageBreakdownPtr bucket_usage_breakdown) { … }
void QuotaManagerImpl::OnDbError(int error_code) { … }
void QuotaManagerImpl::OnFullDiskError(std::optional<StorageKey> storage_key) { … }
void QuotaManagerImpl::NotifyWriteFailed(const blink::StorageKey& storage_key) { … }
void QuotaManagerImpl::StartEviction() { … }
void QuotaManagerImpl::DeleteBucketFromDatabase(
const BucketLocator& bucket,
bool commit_immediately,
base::OnceCallback<void(QuotaErrorOr<mojom::BucketTableEntryPtr>)>
callback) { … }
void QuotaManagerImpl::DidEvictBucketData(
BucketId evicted_bucket_id,
base::RepeatingCallback<void(bool)> barrier,
QuotaErrorOr<mojom::BucketTableEntryPtr> entry) { … }
void QuotaManagerImpl::DeleteBucketDataInternal(
const BucketLocator& bucket,
QuotaClientTypes quota_client_types,
base::OnceCallback<void(QuotaErrorOr<mojom::BucketTableEntryPtr>)>
callback) { … }
void QuotaManagerImpl::DidDeleteBucketData(
base::WeakPtr<QuotaManagerImpl> quota_manager,
base::OnceCallback<void(QuotaErrorOr<mojom::BucketTableEntryPtr>)> callback,
BucketDataDeleter* deleter,
QuotaErrorOr<mojom::BucketTableEntryPtr> result) { … }
void QuotaManagerImpl::DidDeleteBucketForRecreation(
const BucketInitParams& params,
base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback,
BucketInfo bucket_info,
QuotaErrorOr<mojom::BucketTableEntryPtr> result) { … }
void QuotaManagerImpl::MaybeRunStoragePressureCallback(
const StorageKey& storage_key,
int64_t total_space,
int64_t available_space) { … }
void QuotaManagerImpl::SimulateStoragePressure(const url::Origin& origin_url) { … }
void QuotaManagerImpl::IsSimulateStoragePressureAvailable(
IsSimulateStoragePressureAvailableCallback callback) { … }
void QuotaManagerImpl::DetermineStoragePressure(int64_t total_space,
int64_t free_space) { … }
void QuotaManagerImpl::SetStoragePressureCallback(
base::RepeatingCallback<void(const StorageKey&)>
storage_pressure_callback) { … }
int QuotaManagerImpl::GetOverrideHandleId() { … }
void QuotaManagerImpl::OverrideQuotaForStorageKey(
int handle_id,
const StorageKey& storage_key,
std::optional<int64_t> quota_size) { … }
void QuotaManagerImpl::WithdrawOverridesForHandle(int handle_id) { … }
std::optional<int64_t> QuotaManagerImpl::GetQuotaOverrideForStorageKey(
const StorageKey& storage_key) { … }
void QuotaManagerImpl::SetQuotaChangeCallbackForTesting(
base::RepeatingClosure storage_pressure_event_callback) { … }
void QuotaManagerImpl::CorruptDatabaseForTesting(
base::OnceCallback<void(const base::FilePath&)> corrupter,
base::OnceCallback<void(QuotaError)> callback) { … }
void QuotaManagerImpl::ReportHistogram() { … }
void QuotaManagerImpl::DidGetTemporaryGlobalUsageForHistogram(
int64_t usage,
int64_t unlimited_usage) { … }
void QuotaManagerImpl::DidGetStorageCapacityForHistogram(
int64_t usage,
int64_t total_space,
int64_t available_space) { … }
void QuotaManagerImpl::DidDumpBucketTableForHistogram(
BucketTableEntries entries) { … }
std::set<BucketId> QuotaManagerImpl::GetEvictionBucketExceptions() { … }
void QuotaManagerImpl::DidGetEvictionBuckets(
GetBucketsCallback callback,
const std::set<BucketLocator>& buckets) { … }
void QuotaManagerImpl::GetEvictionBuckets(int64_t target_usage,
GetBucketsCallback callback) { … }
void QuotaManagerImpl::EvictExpiredBuckets(StatusCallback done) { … }
void QuotaManagerImpl::EvictBucketData(
const std::set<BucketLocator>& buckets,
base::OnceCallback<void(int)> on_eviction_done) { … }
void QuotaManagerImpl::GetEvictionRoundInfo(
EvictionRoundInfoCallback callback) { … }
void QuotaManagerImpl::DidGetEvictionRoundInfo() { … }
void QuotaManagerImpl::GetBucketsForEvictionFromDatabase(
int64_t target_usage,
std::map<BucketLocator, int64_t> usage_map,
GetBucketsCallback callback) { … }
void QuotaManagerImpl::DidGetBucketsForEvictionFromDatabase(
GetBucketsCallback callback,
QuotaErrorOr<std::set<BucketLocator>> result) { … }
void QuotaManagerImpl::GetQuotaSettings(QuotaSettingsCallback callback) { … }
void QuotaManagerImpl::DidGetSettings(std::optional<QuotaSettings> settings) { … }
void QuotaManagerImpl::GetStorageCapacity(StorageCapacityCallback callback) { … }
void QuotaManagerImpl::ContinueIncognitoGetStorageCapacity(
const QuotaSettings& settings) { … }
void QuotaManagerImpl::DidGetStorageCapacity(
const QuotaAvailability& quota_usage) { … }
void QuotaManagerImpl::DidRecoverOrRazeForReBootstrap(bool success) { … }
void QuotaManagerImpl::NotifyUpdatedBucket(
const QuotaErrorOr<BucketInfo>& result) { … }
void QuotaManagerImpl::OnBucketDeleted(
base::OnceCallback<void(QuotaErrorOr<mojom::BucketTableEntryPtr>)> callback,
QuotaErrorOr<mojom::BucketTableEntryPtr> result) { … }
void QuotaManagerImpl::DidGetQuotaSettingsForBucketCreation(
const BucketInitParams& bucket_params,
base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback,
const QuotaSettings& settings) { … }
void QuotaManagerImpl::DidGetBucket(
bool notify_update_bucket,
base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback,
QuotaErrorOr<BucketInfo> result) { … }
void QuotaManagerImpl::DidGetBucketCheckExpiration(
const BucketInitParams& params,
base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback,
QuotaErrorOr<BucketInfo> result) { … }
void QuotaManagerImpl::DidGetBucketForDeletion(
StatusCallback callback,
QuotaErrorOr<BucketInfo> result) { … }
void QuotaManagerImpl::DidGetBucketForUsageAndQuota(
UsageAndQuotaCallback callback,
QuotaErrorOr<BucketInfo> result) { … }
void QuotaManagerImpl::DidGetStorageKeys(
GetStorageKeysCallback callback,
QuotaErrorOr<std::set<StorageKey>> result) { … }
void QuotaManagerImpl::DidGetBuckets(
base::OnceCallback<void(QuotaErrorOr<std::set<BucketInfo>>)> callback,
QuotaErrorOr<std::set<BucketInfo>> result) { … }
void QuotaManagerImpl::DidGetBucketsCheckExpiration(
base::OnceCallback<void(QuotaErrorOr<std::set<BucketInfo>>)> callback,
QuotaErrorOr<std::set<BucketInfo>> result) { … }
void QuotaManagerImpl::DidGetModifiedBetween(
GetBucketsCallback callback,
QuotaErrorOr<std::set<BucketLocator>> result) { … }
template <typename ValueType>
void QuotaManagerImpl::PostTaskAndReplyWithResultForDBThread(
base::OnceCallback<QuotaErrorOr<ValueType>(QuotaDatabase*)> task,
base::OnceCallback<void(QuotaErrorOr<ValueType>)> reply,
const base::Location& from_here,
bool is_bootstrap_task) { … }
void QuotaManagerImpl::PostTaskAndReplyWithResultForDBThread(
base::OnceCallback<QuotaError(QuotaDatabase*)> task,
base::OnceCallback<void(QuotaError)> reply,
const base::Location& from_here,
bool is_bootstrap_task) { … }
QuotaAvailability QuotaManagerImpl::CallGetVolumeInfo(
GetVolumeInfoFn get_volume_info_fn,
const base::FilePath& path) { … }
QuotaAvailability QuotaManagerImpl::GetVolumeInfo(const base::FilePath& path) { … }
void QuotaManagerImpl::AddObserver(
mojo::PendingRemote<storage::mojom::QuotaManagerObserver> observer) { … }
}