gecko-dev/dom/quota/QuotaManagerService.cpp
Jan Varga df5222926a Bug 1962126 - QM: Align client initialization signatures with origin initialization; r=dom-storage-reviewers,jstutte
Aligns the signatures of client initialization methods with those used for
origin initialization, primarily by adding the aCreateIfNonExistent parameter.

This change prepares the way for supporting delayed creation of client
directories in QuotaManager::OpenClientDirectory, as required by the LSNG quota
client. LSNG delays creation of origin and client directories for performance
reasons, and this refactoring ensures that behavior can be preserved when
client initialization is added to OpenClientDirectory.

Differential Revision: https://phabricator.services.mozilla.com/D246563
2025-05-16 07:00:39 +00:00

1723 lines
51 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "QuotaManagerService.h"
// Local includes
#include "ActorsChild.h"
#include "Client.h"
#include "QuotaManager.h"
#include "QuotaRequests.h"
#include "QuotaResults.h"
// Global includes
#include <cstdint>
#include <cstring>
#include <utility>
#include "MainThreadUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/Atomics.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/Hal.h"
#include "mozilla/MacroForEach.h"
#include "mozilla/Maybe.h"
#include "mozilla/OriginAttributes.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/Unused.h"
#include "mozilla/Variant.h"
#include "mozilla/dom/quota/PrincipalUtils.h"
#include "mozilla/dom/quota/PQuota.h"
#include "mozilla/dom/quota/PersistenceType.h"
#include "mozilla/dom/quota/QuotaUsageRequestChild.h"
#include "mozilla/dom/quota/ResultExtensions.h"
#include "mozilla/fallible.h"
#include "mozilla/hal_sandbox/PHal.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "mozilla/ipc/Endpoint.h"
#include "mozilla/ipc/PBackgroundChild.h"
#include "mozilla/ipc/PBackgroundSharedTypes.h"
#include "nsCOMPtr.h"
#include "nsContentUtils.h"
#include "nsDebug.h"
#include "nsError.h"
#include "nsIObserverService.h"
#include "nsIPrincipal.h"
#include "nsIUserIdleService.h"
#include "nsServiceManagerUtils.h"
#include "nsStringFwd.h"
#include "nsVariant.h"
#include "nsXULAppAPI.h"
#include "nscore.h"
#define PROFILE_BEFORE_CHANGE_QM_OBSERVER_ID "profile-before-change-qm"
namespace mozilla::dom::quota {
using namespace mozilla::ipc;
namespace {
const char kIdleServiceContractId[] = "@mozilla.org/widget/useridleservice;1";
// The number of seconds we will wait after receiving the idle-daily
// notification before beginning maintenance.
const uint32_t kIdleObserverTimeSec = 1;
mozilla::StaticRefPtr<QuotaManagerService> gQuotaManagerService;
mozilla::Atomic<bool> gInitialized(false);
mozilla::Atomic<bool> gClosed(false);
nsresult CheckedPrincipalToPrincipalInfo(nsIPrincipal* aPrincipal,
PrincipalInfo& aPrincipalInfo) {
MOZ_ASSERT(aPrincipal);
nsresult rv = PrincipalToPrincipalInfo(aPrincipal, &aPrincipalInfo);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (NS_WARN_IF(!IsPrincipalInfoValid(aPrincipalInfo))) {
return NS_ERROR_FAILURE;
}
if (aPrincipalInfo.type() != PrincipalInfo::TContentPrincipalInfo &&
aPrincipalInfo.type() != PrincipalInfo::TSystemPrincipalInfo) {
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
template <typename ResponseType>
struct ResponseTypeTraits;
template <>
struct ResponseTypeTraits<BoolResponse> {
static constexpr auto kType = BoolResponse::Tbool;
static RefPtr<nsVariant> CreateVariant(const BoolResponse& aResponse) {
auto variant = MakeRefPtr<nsVariant>();
variant->SetAsBool(aResponse.get_bool());
return variant;
}
};
template <>
struct ResponseTypeTraits<UInt64Response> {
static constexpr auto kType = UInt64Response::Tuint64_t;
static RefPtr<nsVariant> CreateVariant(const UInt64Response& aResponse) {
RefPtr<nsVariant> variant = new nsVariant();
variant->SetAsUint64(aResponse.get_uint64_t());
return variant;
}
};
template <>
struct ResponseTypeTraits<CStringArrayResponse> {
static constexpr auto kType = CStringArrayResponse::TArrayOfnsCString;
static RefPtr<nsVariant> CreateVariant(
const CStringArrayResponse& aResponse) {
const CStringArray& strings = aResponse.get_ArrayOfnsCString();
auto variant = MakeRefPtr<nsVariant>();
if (strings.IsEmpty()) {
MOZ_ALWAYS_SUCCEEDS(variant->SetAsEmptyArray());
} else {
nsTArray<const char*> stringPointers(strings.Length());
std::transform(strings.cbegin(), strings.cend(),
MakeBackInserter(stringPointers),
std::mem_fn(&nsCString::get));
QM_TRY(MOZ_TO_RESULT(variant->SetAsArray(
nsIDataType::VTYPE_CHAR_STR, /* aIID */ nullptr,
stringPointers.Length(), stringPointers.Elements())),
nullptr);
}
return variant;
}
};
template <>
struct ResponseTypeTraits<OriginUsageMetadataArrayResponse> {
static constexpr auto kType =
OriginUsageMetadataArrayResponse::TOriginUsageMetadataArray;
static RefPtr<nsVariant> CreateVariant(
const OriginUsageMetadataArrayResponse& aResponse) {
const OriginUsageMetadataArray& originUsages =
aResponse.get_OriginUsageMetadataArray();
auto variant = MakeRefPtr<nsVariant>();
if (originUsages.IsEmpty()) {
variant->SetAsEmptyArray();
} else {
nsTArray<RefPtr<UsageResult>> usageResults(originUsages.Length());
for (const auto& originUsage : originUsages) {
usageResults.AppendElement(MakeRefPtr<UsageResult>(
originUsage.mOrigin, originUsage.mPersisted, originUsage.mUsage,
originUsage.mLastAccessTime));
}
variant->SetAsArray(
nsIDataType::VTYPE_INTERFACE_IS, &NS_GET_IID(nsIQuotaUsageResult),
usageResults.Length(), static_cast<void*>(usageResults.Elements()));
}
return variant;
}
};
template <>
struct ResponseTypeTraits<UsageInfoResponse> {
static constexpr auto kType = UsageInfoResponse::TUsageInfo;
static RefPtr<nsVariant> CreateVariant(const UsageInfoResponse& aResponse) {
RefPtr<OriginUsageResult> result =
new OriginUsageResult(aResponse.get_UsageInfo());
auto variant = MakeRefPtr<nsVariant>();
variant->SetAsInterface(NS_GET_IID(nsIQuotaOriginUsageResult), result);
return variant;
}
};
template <typename RequestType, typename PromiseType, typename ResponseType>
class ResponsePromiseResolveOrRejectCallback {
public:
explicit ResponsePromiseResolveOrRejectCallback(RefPtr<RequestType> aRequest)
: mRequest(std::move(aRequest)) {}
void operator()(const typename PromiseType::ResolveOrRejectValue& aValue) {
if (aValue.IsResolve()) {
const ResponseType& response = aValue.ResolveValue();
switch (response.type()) {
case ResponseType::Tnsresult:
mRequest->SetError(response.get_nsresult());
break;
case ResponseTypeTraits<ResponseType>::kType: {
RefPtr<nsVariant> variant =
ResponseTypeTraits<ResponseType>::CreateVariant(response);
if (variant) {
mRequest->SetResult(variant);
} else {
mRequest->SetError(NS_ERROR_FAILURE);
}
break;
}
default:
MOZ_CRASH("Unknown response type!");
}
} else {
mRequest->SetError(NS_ERROR_FAILURE);
}
}
private:
RefPtr<RequestType> mRequest;
};
using BoolResponsePromiseResolveOrRejectCallback =
ResponsePromiseResolveOrRejectCallback<Request, BoolResponsePromise,
BoolResponse>;
using UInt64ResponsePromiseResolveOrRejectCallback =
ResponsePromiseResolveOrRejectCallback<Request, UInt64ResponsePromise,
UInt64Response>;
using CStringArrayResponsePromiseResolveOrRejectCallback =
ResponsePromiseResolveOrRejectCallback<Request, CStringArrayResponsePromise,
CStringArrayResponse>;
using OriginUsageMetadataArrayResponsePromiseResolveOrRejectCallback =
ResponsePromiseResolveOrRejectCallback<
UsageRequest, OriginUsageMetadataArrayResponsePromise,
OriginUsageMetadataArrayResponse>;
using UsageInfoResponsePromiseResolveOrRejectCallback =
ResponsePromiseResolveOrRejectCallback<
UsageRequest, UsageInfoResponsePromise, UsageInfoResponse>;
} // namespace
class QuotaManagerService::PendingRequestInfo {
protected:
RefPtr<RequestBase> mRequest;
public:
explicit PendingRequestInfo(RequestBase* aRequest) : mRequest(aRequest) {}
virtual ~PendingRequestInfo() = default;
RequestBase* GetRequest() const { return mRequest; }
virtual nsresult InitiateRequest(QuotaChild* aActor) = 0;
};
class QuotaManagerService::RequestInfo : public PendingRequestInfo {
RequestParams mParams;
public:
RequestInfo(Request* aRequest, const RequestParams& aParams)
: PendingRequestInfo(aRequest), mParams(aParams) {
MOZ_ASSERT(aRequest);
MOZ_ASSERT(aParams.type() != RequestParams::T__None);
}
virtual nsresult InitiateRequest(QuotaChild* aActor) override;
};
class QuotaManagerService::IdleMaintenanceInfo : public PendingRequestInfo {
const bool mStart;
public:
explicit IdleMaintenanceInfo(bool aStart)
: PendingRequestInfo(nullptr), mStart(aStart) {}
virtual nsresult InitiateRequest(QuotaChild* aActor) override;
};
QuotaManagerService::QuotaManagerService()
: mBackgroundActor(nullptr),
mBackgroundActorFailed(false),
mIdleObserverRegistered(false) {
MOZ_ASSERT(NS_IsMainThread());
}
QuotaManagerService::~QuotaManagerService() {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mIdleObserverRegistered);
}
// static
QuotaManagerService* QuotaManagerService::GetOrCreate() {
MOZ_ASSERT(NS_IsMainThread());
if (gClosed) {
MOZ_ASSERT(false, "Calling GetOrCreate() after shutdown!");
return nullptr;
}
if (!gQuotaManagerService) {
RefPtr<QuotaManagerService> instance(new QuotaManagerService());
nsresult rv = instance->Init();
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
if (gInitialized.exchange(true)) {
MOZ_ASSERT(false, "Initialized more than once?!");
}
gQuotaManagerService = instance;
ClearOnShutdown(&gQuotaManagerService);
}
return gQuotaManagerService;
}
// static
QuotaManagerService* QuotaManagerService::Get() {
// Does not return an owning reference.
return gQuotaManagerService;
}
// static
already_AddRefed<QuotaManagerService> QuotaManagerService::FactoryCreate() {
RefPtr<QuotaManagerService> quotaManagerService = GetOrCreate();
return quotaManagerService.forget();
}
void QuotaManagerService::ClearBackgroundActor() {
MOZ_ASSERT(NS_IsMainThread());
mBackgroundActor = nullptr;
}
void QuotaManagerService::AbortOperationsForProcess(
ContentParentId aContentParentId) {
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
nsresult rv = EnsureBackgroundActor();
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
if (NS_WARN_IF(
!mBackgroundActor->SendAbortOperationsForProcess(aContentParentId))) {
return;
}
}
nsresult QuotaManagerService::Init() {
MOZ_ASSERT(NS_IsMainThread());
if (XRE_IsParentProcess()) {
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (NS_WARN_IF(!observerService)) {
return NS_ERROR_FAILURE;
}
nsresult rv = observerService->AddObserver(
this, PROFILE_BEFORE_CHANGE_QM_OBSERVER_ID, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
return NS_OK;
}
void QuotaManagerService::Destroy() {
// Setting the closed flag prevents the service from being recreated.
// Don't set it though if there's no real instance created.
if (gInitialized && gClosed.exchange(true)) {
MOZ_ASSERT(false, "Shutdown more than once?!");
}
delete this;
}
nsresult QuotaManagerService::EnsureBackgroundActor() {
MOZ_ASSERT(NS_IsMainThread());
// Nothing can be done here if we have previously failed to create a
// background actor.
if (mBackgroundActorFailed) {
return NS_ERROR_FAILURE;
}
if (!mBackgroundActor) {
PBackgroundChild* backgroundActor =
BackgroundChild::GetOrCreateForCurrentThread();
if (NS_WARN_IF(!backgroundActor)) {
mBackgroundActorFailed = true;
return NS_ERROR_FAILURE;
}
{
RefPtr<QuotaChild> actor = new QuotaChild(this);
mBackgroundActor = static_cast<QuotaChild*>(
backgroundActor->SendPQuotaConstructor(actor));
}
}
if (!mBackgroundActor) {
mBackgroundActorFailed = true;
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsresult QuotaManagerService::InitiateRequest(PendingRequestInfo& aInfo) {
nsresult rv = EnsureBackgroundActor();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = aInfo.InitiateRequest(mBackgroundActor);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
void QuotaManagerService::PerformIdleMaintenance() {
using namespace mozilla::hal;
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
// If we're running on battery power then skip all idle maintenance since we
// would otherwise be doing lots of disk I/O.
BatteryInformation batteryInfo;
#ifdef MOZ_WIDGET_ANDROID
// Android XPCShell doesn't load the AndroidBridge that is needed to make
// GetCurrentBatteryInformation work...
if (!QuotaManager::IsRunningXPCShellTests())
#endif
{
// In order to give the correct battery level, hal must have registered
// battery observers.
RegisterBatteryObserver(this);
GetCurrentBatteryInformation(&batteryInfo);
UnregisterBatteryObserver(this);
}
// If we're running XPCShell because we always want to be able to test this
// code so pretend that we're always charging.
if (QuotaManager::IsRunningXPCShellTests()) {
batteryInfo.level() = 100;
batteryInfo.charging() = true;
}
if (NS_WARN_IF(!batteryInfo.charging())) {
return;
}
if (QuotaManager::IsRunningXPCShellTests()) {
// We don't want user activity to impact this code if we're running tests.
Unused << Observe(nullptr, OBSERVER_TOPIC_IDLE, nullptr);
} else if (!mIdleObserverRegistered) {
nsCOMPtr<nsIUserIdleService> idleService =
do_GetService(kIdleServiceContractId);
MOZ_ASSERT(idleService);
MOZ_ALWAYS_SUCCEEDS(
idleService->AddIdleObserver(this, kIdleObserverTimeSec));
mIdleObserverRegistered = true;
}
}
void QuotaManagerService::RemoveIdleObserver() {
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
if (mIdleObserverRegistered) {
nsCOMPtr<nsIUserIdleService> idleService =
do_GetService(kIdleServiceContractId);
MOZ_ASSERT(idleService);
// Ignore the return value of RemoveIdleObserver, it may fail if the
// observer has already been unregistered during shutdown.
Unused << idleService->RemoveIdleObserver(this, kIdleObserverTimeSec);
mIdleObserverRegistered = false;
}
}
NS_IMPL_ADDREF(QuotaManagerService)
NS_IMPL_RELEASE_WITH_DESTROY(QuotaManagerService, Destroy())
NS_IMPL_QUERY_INTERFACE(QuotaManagerService, nsIQuotaManagerService,
nsIQuotaManagerServiceInternal, nsIObserver)
NS_IMETHODIMP
QuotaManagerService::StorageName(nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(nsContentUtils::IsCallerChrome());
if (NS_WARN_IF(!StaticPrefs::dom_quotaManager_testing())) {
return NS_ERROR_UNEXPECTED;
}
RefPtr<Request> request = new Request();
StorageNameParams params;
RequestInfo info(request, params);
nsresult rv = InitiateRequest(info);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::StorageInitialized(nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(nsContentUtils::IsCallerChrome());
if (NS_WARN_IF(!StaticPrefs::dom_quotaManager_testing())) {
return NS_ERROR_UNEXPECTED;
}
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
RefPtr<Request> request = new Request();
mBackgroundActor->SendStorageInitialized()->Then(
GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::PersistentStorageInitialized(nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(nsContentUtils::IsCallerChrome());
if (NS_WARN_IF(!StaticPrefs::dom_quotaManager_testing())) {
return NS_ERROR_UNEXPECTED;
}
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
RefPtr<Request> request = new Request();
mBackgroundActor->SendPersistentStorageInitialized()->Then(
GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::TemporaryStorageInitialized(nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(nsContentUtils::IsCallerChrome());
if (NS_WARN_IF(!StaticPrefs::dom_quotaManager_testing())) {
return NS_ERROR_UNEXPECTED;
}
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
RefPtr<Request> request = new Request();
mBackgroundActor->SendTemporaryStorageInitialized()->Then(
GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::TemporaryGroupInitialized(nsIPrincipal* aPrincipal,
nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(nsContentUtils::IsCallerChrome());
QM_TRY(MOZ_TO_RESULT(StaticPrefs::dom_quotaManager_testing()),
NS_ERROR_UNEXPECTED);
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
QM_TRY_INSPECT(const auto& principalInfo,
([&aPrincipal]() -> Result<PrincipalInfo, nsresult> {
PrincipalInfo principalInfo;
QM_TRY(MOZ_TO_RESULT(
PrincipalToPrincipalInfo(aPrincipal, &principalInfo)));
QM_TRY(MOZ_TO_RESULT(IsPrincipalInfoValid(principalInfo)),
Err(NS_ERROR_INVALID_ARG));
return principalInfo;
}()));
RefPtr<Request> request = new Request();
mBackgroundActor->SendTemporaryGroupInitialized(principalInfo)
->Then(GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::PersistentOriginInitialized(nsIPrincipal* aPrincipal,
nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(nsContentUtils::IsCallerChrome());
QM_TRY(MOZ_TO_RESULT(StaticPrefs::dom_quotaManager_testing()),
NS_ERROR_UNEXPECTED);
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
QM_TRY_INSPECT(const auto& principalInfo,
([&aPrincipal]() -> Result<PrincipalInfo, nsresult> {
PrincipalInfo principalInfo;
QM_TRY(MOZ_TO_RESULT(
PrincipalToPrincipalInfo(aPrincipal, &principalInfo)));
QM_TRY(MOZ_TO_RESULT(IsPrincipalInfoValid(principalInfo)),
Err(NS_ERROR_INVALID_ARG));
return principalInfo;
}()));
RefPtr<Request> request = new Request();
mBackgroundActor->SendPersistentOriginInitialized(principalInfo)
->Then(GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::TemporaryOriginInitialized(
const nsACString& aPersistenceType, nsIPrincipal* aPrincipal,
nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(nsContentUtils::IsCallerChrome());
QM_TRY(MOZ_TO_RESULT(StaticPrefs::dom_quotaManager_testing()),
NS_ERROR_UNEXPECTED);
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
QM_TRY_INSPECT(
const auto& persistenceType,
([&aPersistenceType]() -> Result<PersistenceType, nsresult> {
const auto persistenceType =
PersistenceTypeFromString(aPersistenceType, fallible);
QM_TRY(MOZ_TO_RESULT(persistenceType.isSome()),
Err(NS_ERROR_INVALID_ARG));
QM_TRY(
MOZ_TO_RESULT(IsBestEffortPersistenceType(persistenceType.ref())),
Err(NS_ERROR_INVALID_ARG));
return persistenceType.ref();
}()));
QM_TRY_INSPECT(const auto& principalInfo,
([&aPrincipal]() -> Result<PrincipalInfo, nsresult> {
PrincipalInfo principalInfo;
QM_TRY(MOZ_TO_RESULT(
PrincipalToPrincipalInfo(aPrincipal, &principalInfo)));
QM_TRY(MOZ_TO_RESULT(IsPrincipalInfoValid(principalInfo)),
Err(NS_ERROR_INVALID_ARG));
return principalInfo;
}()));
RefPtr<Request> request = new Request();
mBackgroundActor
->SendTemporaryOriginInitialized(persistenceType, principalInfo)
->Then(GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::Init(nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(nsContentUtils::IsCallerChrome());
if (NS_WARN_IF(!StaticPrefs::dom_quotaManager_testing())) {
return NS_ERROR_UNEXPECTED;
}
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
RefPtr<Request> request = new Request();
mBackgroundActor->SendInitializeStorage()->Then(
GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::InitializePersistentStorage(nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(nsContentUtils::IsCallerChrome());
if (NS_WARN_IF(!StaticPrefs::dom_quotaManager_testing())) {
return NS_ERROR_UNEXPECTED;
}
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
RefPtr<Request> request = new Request();
mBackgroundActor->SendInitializePersistentStorage()->Then(
GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::InitTemporaryStorage(nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(nsContentUtils::IsCallerChrome());
if (NS_WARN_IF(!StaticPrefs::dom_quotaManager_testing())) {
return NS_ERROR_UNEXPECTED;
}
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
RefPtr<Request> request = new Request();
mBackgroundActor->SendInitializeTemporaryStorage()->Then(
GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::InitializeAllTemporaryOrigins(nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(nsContentUtils::IsCallerChrome());
if (NS_WARN_IF(!StaticPrefs::dom_quotaManager_testing())) {
return NS_ERROR_UNEXPECTED;
}
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
RefPtr<Request> request = new Request();
mBackgroundActor->SendInitializeAllTemporaryOrigins()->Then(
GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::InitializeTemporaryGroup(nsIPrincipal* aPrincipal,
nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(nsContentUtils::IsCallerChrome());
QM_TRY(MOZ_TO_RESULT(StaticPrefs::dom_quotaManager_testing()),
NS_ERROR_UNEXPECTED);
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
QM_TRY_INSPECT(const auto& principalInfo,
([&aPrincipal]() -> Result<PrincipalInfo, nsresult> {
PrincipalInfo principalInfo;
QM_TRY(MOZ_TO_RESULT(
PrincipalToPrincipalInfo(aPrincipal, &principalInfo)));
QM_TRY(MOZ_TO_RESULT(IsPrincipalInfoValid(principalInfo)),
Err(NS_ERROR_INVALID_ARG));
return principalInfo;
}()));
RefPtr<Request> request = new Request();
mBackgroundActor->SendInitializeTemporaryGroup(principalInfo)
->Then(GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::InitializePersistentOrigin(nsIPrincipal* aPrincipal,
nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(nsContentUtils::IsCallerChrome());
QM_TRY(MOZ_TO_RESULT(StaticPrefs::dom_quotaManager_testing()),
NS_ERROR_UNEXPECTED);
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
QM_TRY_INSPECT(const auto& principalInfo,
([&aPrincipal]() -> Result<PrincipalInfo, nsresult> {
PrincipalInfo principalInfo;
QM_TRY(MOZ_TO_RESULT(
PrincipalToPrincipalInfo(aPrincipal, &principalInfo)));
QM_TRY(MOZ_TO_RESULT(IsPrincipalInfoValid(principalInfo)),
Err(NS_ERROR_INVALID_ARG));
return principalInfo;
}()));
auto request = MakeRefPtr<Request>();
mBackgroundActor->SendInitializePersistentOrigin(principalInfo)
->Then(GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::InitializeTemporaryOrigin(
const nsACString& aPersistenceType, nsIPrincipal* aPrincipal,
bool aCreateIfNonExistent, nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(nsContentUtils::IsCallerChrome());
QM_TRY(MOZ_TO_RESULT(StaticPrefs::dom_quotaManager_testing()),
NS_ERROR_UNEXPECTED);
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
QM_TRY_INSPECT(
const auto& persistenceType,
([&aPersistenceType]() -> Result<PersistenceType, nsresult> {
const auto persistenceType =
PersistenceTypeFromString(aPersistenceType, fallible);
QM_TRY(MOZ_TO_RESULT(persistenceType.isSome()),
Err(NS_ERROR_INVALID_ARG));
QM_TRY(
MOZ_TO_RESULT(IsBestEffortPersistenceType(persistenceType.ref())),
Err(NS_ERROR_INVALID_ARG));
return persistenceType.ref();
}()));
QM_TRY_INSPECT(const auto& principalInfo,
([&aPrincipal]() -> Result<PrincipalInfo, nsresult> {
PrincipalInfo principalInfo;
QM_TRY(MOZ_TO_RESULT(
PrincipalToPrincipalInfo(aPrincipal, &principalInfo)));
QM_TRY(MOZ_TO_RESULT(IsPrincipalInfoValid(principalInfo)),
Err(NS_ERROR_INVALID_ARG));
return principalInfo;
}()));
auto request = MakeRefPtr<Request>();
mBackgroundActor
->SendInitializeTemporaryOrigin(persistenceType, principalInfo,
aCreateIfNonExistent)
->Then(GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::InitializePersistentClient(nsIPrincipal* aPrincipal,
const nsAString& aClientType,
nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(nsContentUtils::IsCallerChrome());
QM_TRY(MOZ_TO_RESULT(StaticPrefs::dom_quotaManager_testing()),
NS_ERROR_UNEXPECTED);
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
QM_TRY_INSPECT(const auto& principalInfo,
([&aPrincipal]() -> Result<PrincipalInfo, nsresult> {
PrincipalInfo principalInfo;
QM_TRY(MOZ_TO_RESULT(
PrincipalToPrincipalInfo(aPrincipal, &principalInfo)));
QM_TRY(MOZ_TO_RESULT(IsPrincipalInfoValid(principalInfo)),
Err(NS_ERROR_INVALID_ARG));
return principalInfo;
}()));
QM_TRY_INSPECT(const auto& clientType,
([&aClientType]() -> Result<Client::Type, nsresult> {
Client::Type clientType;
QM_TRY(MOZ_TO_RESULT(Client::TypeFromText(
aClientType, clientType, fallible)),
Err(NS_ERROR_INVALID_ARG));
return clientType;
}()));
RefPtr<Request> request = new Request();
mBackgroundActor->SendInitializePersistentClient(principalInfo, clientType)
->Then(GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::InitializeTemporaryClient(
const nsACString& aPersistenceType, nsIPrincipal* aPrincipal,
const nsAString& aClientType, bool aCreateIfNonExistent,
nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(nsContentUtils::IsCallerChrome());
QM_TRY(MOZ_TO_RESULT(StaticPrefs::dom_quotaManager_testing()),
NS_ERROR_UNEXPECTED);
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
QM_TRY_INSPECT(
const auto& persistenceType,
([&aPersistenceType]() -> Result<PersistenceType, nsresult> {
const auto persistenceType =
PersistenceTypeFromString(aPersistenceType, fallible);
QM_TRY(MOZ_TO_RESULT(persistenceType.isSome()),
Err(NS_ERROR_INVALID_ARG));
QM_TRY(
MOZ_TO_RESULT(IsBestEffortPersistenceType(persistenceType.ref())),
Err(NS_ERROR_INVALID_ARG));
return persistenceType.ref();
}()));
QM_TRY_INSPECT(const auto& principalInfo,
([&aPrincipal]() -> Result<PrincipalInfo, nsresult> {
PrincipalInfo principalInfo;
QM_TRY(MOZ_TO_RESULT(
PrincipalToPrincipalInfo(aPrincipal, &principalInfo)));
QM_TRY(MOZ_TO_RESULT(IsPrincipalInfoValid(principalInfo)),
Err(NS_ERROR_INVALID_ARG));
return principalInfo;
}()));
QM_TRY_INSPECT(const auto& clientType,
([&aClientType]() -> Result<Client::Type, nsresult> {
Client::Type clientType;
QM_TRY(MOZ_TO_RESULT(Client::TypeFromText(
aClientType, clientType, fallible)),
Err(NS_ERROR_INVALID_ARG));
return clientType;
}()));
RefPtr<Request> request = new Request();
mBackgroundActor
->SendInitializeTemporaryClient(persistenceType, principalInfo,
clientType, aCreateIfNonExistent)
->Then(GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::GetFullOriginMetadata(const nsACString& aPersistenceType,
nsIPrincipal* aPrincipal,
nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(nsContentUtils::IsCallerChrome());
QM_TRY(OkIf(StaticPrefs::dom_quotaManager_testing()), NS_ERROR_UNEXPECTED);
const auto maybePersistenceType =
PersistenceTypeFromString(aPersistenceType, fallible);
QM_TRY(OkIf(maybePersistenceType.isSome()), NS_ERROR_INVALID_ARG);
QM_TRY(OkIf(IsBestEffortPersistenceType(*maybePersistenceType)),
NS_ERROR_INVALID_ARG);
PrincipalInfo principalInfo;
QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(aPrincipal, &principalInfo)));
QM_TRY(OkIf(IsPrincipalInfoValid(principalInfo)), NS_ERROR_INVALID_ARG);
RefPtr<Request> request = new Request();
GetFullOriginMetadataParams params;
params.persistenceType() = *maybePersistenceType;
params.principalInfo() = std::move(principalInfo);
RequestInfo info(request, params);
QM_TRY(MOZ_TO_RESULT(InitiateRequest(info)));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::GetUsage(nsIQuotaUsageCallback* aCallback, bool aGetAll,
nsIQuotaUsageRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aCallback);
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
RefPtr<UsageRequest> request = new UsageRequest(aCallback);
RefPtr<QuotaUsageRequestChild> usageRequestChild =
new QuotaUsageRequestChild(request);
ManagedEndpoint<PQuotaUsageRequestParent> usageRequestParentEndpoint =
mBackgroundActor->OpenPQuotaUsageRequestEndpoint(usageRequestChild);
QM_TRY(MOZ_TO_RESULT(usageRequestParentEndpoint.IsValid()));
mBackgroundActor->SendGetUsage(aGetAll, std::move(usageRequestParentEndpoint))
->Then(GetCurrentSerialEventTarget(), __func__,
OriginUsageMetadataArrayResponsePromiseResolveOrRejectCallback(
request));
request->SetBackgroundActor(usageRequestChild);
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::GetUsageForPrincipal(nsIPrincipal* aPrincipal,
nsIQuotaUsageCallback* aCallback,
nsIQuotaUsageRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(aCallback);
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
QM_TRY_INSPECT(const auto& principalInfo,
([&aPrincipal]() -> Result<PrincipalInfo, nsresult> {
PrincipalInfo principalInfo;
QM_TRY(MOZ_TO_RESULT(
PrincipalToPrincipalInfo(aPrincipal, &principalInfo)));
QM_TRY(MOZ_TO_RESULT(IsPrincipalInfoValid(principalInfo)),
Err(NS_ERROR_INVALID_ARG));
return principalInfo;
}()));
RefPtr<UsageRequest> request = new UsageRequest(aPrincipal, aCallback);
RefPtr<QuotaUsageRequestChild> usageRequestChild =
new QuotaUsageRequestChild(request);
ManagedEndpoint<PQuotaUsageRequestParent> usageRequestParentEndpoint =
mBackgroundActor->OpenPQuotaUsageRequestEndpoint(usageRequestChild);
QM_TRY(MOZ_TO_RESULT(usageRequestParentEndpoint.IsValid()));
mBackgroundActor
->SendGetOriginUsage(principalInfo, std::move(usageRequestParentEndpoint))
->Then(GetCurrentSerialEventTarget(), __func__,
UsageInfoResponsePromiseResolveOrRejectCallback(request));
request->SetBackgroundActor(usageRequestChild);
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::GetCachedUsageForPrincipal(nsIPrincipal* aPrincipal,
nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
QM_TRY_INSPECT(const auto& principalInfo,
([&aPrincipal]() -> Result<PrincipalInfo, nsresult> {
PrincipalInfo principalInfo;
QM_TRY(MOZ_TO_RESULT(
PrincipalToPrincipalInfo(aPrincipal, &principalInfo)));
QM_TRY(MOZ_TO_RESULT(IsPrincipalInfoValid(principalInfo)),
Err(NS_ERROR_INVALID_ARG));
return principalInfo;
}()));
RefPtr<Request> request = new Request();
mBackgroundActor->SendGetCachedOriginUsage(principalInfo)
->Then(GetCurrentSerialEventTarget(), __func__,
UInt64ResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::Clear(nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
if (NS_WARN_IF(!StaticPrefs::dom_quotaManager_testing())) {
return NS_ERROR_UNEXPECTED;
}
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
RefPtr<Request> request = new Request();
mBackgroundActor->SendClearStorage()->Then(
GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::ClearStoragesForPrivateBrowsing(
nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
RefPtr<Request> request = new Request();
mBackgroundActor->SendClearStoragesForPrivateBrowsing()->Then(
GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::ClearStoragesForOriginAttributesPattern(
const nsAString& aPattern, nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
OriginAttributesPattern pattern;
MOZ_ALWAYS_TRUE(pattern.Init(aPattern));
RefPtr<Request> request = new Request();
mBackgroundActor->SendClearStoragesForOriginAttributesPattern(pattern)->Then(
GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::ClearStoragesForPrincipal(
nsIPrincipal* aPrincipal, const nsACString& aPersistenceType,
nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
QM_TRY_INSPECT(
const auto& persistenceType,
([&aPersistenceType]() -> Result<Maybe<PersistenceType>, nsresult> {
if (aPersistenceType.IsVoid()) {
return Maybe<PersistenceType>();
}
const auto persistenceType =
PersistenceTypeFromString(aPersistenceType, fallible);
QM_TRY(MOZ_TO_RESULT(persistenceType.isSome()),
Err(NS_ERROR_INVALID_ARG));
return persistenceType;
}()));
QM_TRY_INSPECT(const auto& principalInfo,
([&aPrincipal]() -> Result<PrincipalInfo, nsresult> {
PrincipalInfo principalInfo;
QM_TRY(MOZ_TO_RESULT(
PrincipalToPrincipalInfo(aPrincipal, &principalInfo)));
QM_TRY(MOZ_TO_RESULT(IsPrincipalInfoValid(principalInfo)),
Err(NS_ERROR_INVALID_ARG));
return principalInfo;
}()));
RefPtr<Request> request = new Request();
mBackgroundActor->SendClearStoragesForOrigin(persistenceType, principalInfo)
->Then(GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::ClearStoragesForClient(nsIPrincipal* aPrincipal,
const nsAString& aClientType,
const nsACString& aPersistenceType,
nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
QM_TRY_INSPECT(
const auto& persistenceType,
([&aPersistenceType]() -> Result<Maybe<PersistenceType>, nsresult> {
if (aPersistenceType.IsVoid()) {
return Maybe<PersistenceType>();
}
const auto persistenceType =
PersistenceTypeFromString(aPersistenceType, fallible);
QM_TRY(MOZ_TO_RESULT(persistenceType.isSome()),
Err(NS_ERROR_INVALID_ARG));
return persistenceType;
}()));
QM_TRY_INSPECT(const auto& principalInfo,
([&aPrincipal]() -> Result<PrincipalInfo, nsresult> {
PrincipalInfo principalInfo;
QM_TRY(MOZ_TO_RESULT(
PrincipalToPrincipalInfo(aPrincipal, &principalInfo)));
QM_TRY(MOZ_TO_RESULT(IsPrincipalInfoValid(principalInfo)),
Err(NS_ERROR_INVALID_ARG));
return principalInfo;
}()));
QM_TRY_INSPECT(const auto& clientType,
([&aClientType]() -> Result<Client::Type, nsresult> {
Client::Type clientType;
QM_TRY(MOZ_TO_RESULT(Client::TypeFromText(
aClientType, clientType, fallible)),
Err(NS_ERROR_INVALID_ARG));
return clientType;
}()));
RefPtr<Request> request = new Request();
mBackgroundActor
->SendClearStoragesForClient(persistenceType, principalInfo, clientType)
->Then(GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::ClearStoragesForOriginPrefix(
nsIPrincipal* aPrincipal, const nsACString& aPersistenceType,
nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
QM_TRY_INSPECT(
const auto& persistenceType,
([&aPersistenceType]() -> Result<Maybe<PersistenceType>, nsresult> {
if (aPersistenceType.IsVoid()) {
return Maybe<PersistenceType>();
}
const auto persistenceType =
PersistenceTypeFromString(aPersistenceType, fallible);
QM_TRY(MOZ_TO_RESULT(persistenceType.isSome()),
Err(NS_ERROR_INVALID_ARG));
return persistenceType;
}()));
QM_TRY_INSPECT(
const auto& principalInfo,
([&aPrincipal]() -> Result<PrincipalInfo, nsresult> {
PrincipalInfo principalInfo;
QM_TRY(MOZ_TO_RESULT(
PrincipalToPrincipalInfo(aPrincipal, &principalInfo)));
QM_TRY(MOZ_TO_RESULT(IsPrincipalInfoValid(principalInfo)),
Err(NS_ERROR_INVALID_ARG));
if (principalInfo.type() == PrincipalInfo::TContentPrincipalInfo) {
nsCString suffix;
principalInfo.get_ContentPrincipalInfo().attrs().CreateSuffix(suffix);
QM_TRY(MOZ_TO_RESULT(suffix.IsEmpty()), Err(NS_ERROR_INVALID_ARG));
}
return principalInfo;
}()));
RefPtr<Request> request = new Request();
mBackgroundActor
->SendClearStoragesForOriginPrefix(persistenceType, principalInfo)
->Then(GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::Reset(nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
if (NS_WARN_IF(!StaticPrefs::dom_quotaManager_testing())) {
return NS_ERROR_UNEXPECTED;
}
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
RefPtr<Request> request = new Request();
mBackgroundActor->SendShutdownStorage()->Then(
GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::ResetStoragesForPrincipal(
nsIPrincipal* aPrincipal, const nsACString& aPersistenceType,
nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
QM_TRY_INSPECT(
const auto& persistenceType,
([&aPersistenceType]() -> Result<Maybe<PersistenceType>, nsresult> {
if (aPersistenceType.IsVoid()) {
return Maybe<PersistenceType>();
}
const auto persistenceType =
PersistenceTypeFromString(aPersistenceType, fallible);
QM_TRY(MOZ_TO_RESULT(persistenceType.isSome()),
Err(NS_ERROR_INVALID_ARG));
return persistenceType;
}()));
QM_TRY_INSPECT(const auto& principalInfo,
([&aPrincipal]() -> Result<PrincipalInfo, nsresult> {
PrincipalInfo principalInfo;
QM_TRY(MOZ_TO_RESULT(
PrincipalToPrincipalInfo(aPrincipal, &principalInfo)));
QM_TRY(MOZ_TO_RESULT(IsPrincipalInfoValid(principalInfo)),
Err(NS_ERROR_INVALID_ARG));
return principalInfo;
}()));
RefPtr<Request> request = new Request();
mBackgroundActor
->SendShutdownStoragesForOrigin(persistenceType, principalInfo)
->Then(GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::ResetStoragesForClient(nsIPrincipal* aPrincipal,
const nsAString& aClientType,
const nsACString& aPersistenceType,
nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
QM_TRY_INSPECT(
const auto& persistenceType,
([&aPersistenceType]() -> Result<Maybe<PersistenceType>, nsresult> {
if (aPersistenceType.IsVoid()) {
return Maybe<PersistenceType>();
}
const auto persistenceType =
PersistenceTypeFromString(aPersistenceType, fallible);
QM_TRY(MOZ_TO_RESULT(persistenceType.isSome()),
Err(NS_ERROR_INVALID_ARG));
return persistenceType;
}()));
QM_TRY_INSPECT(const auto& principalInfo,
([&aPrincipal]() -> Result<PrincipalInfo, nsresult> {
PrincipalInfo principalInfo;
QM_TRY(MOZ_TO_RESULT(
PrincipalToPrincipalInfo(aPrincipal, &principalInfo)));
QM_TRY(MOZ_TO_RESULT(IsPrincipalInfoValid(principalInfo)),
Err(NS_ERROR_INVALID_ARG));
return principalInfo;
}()));
QM_TRY_INSPECT(const auto& clientType,
([&aClientType]() -> Result<Client::Type, nsresult> {
Client::Type clientType;
QM_TRY(MOZ_TO_RESULT(Client::TypeFromText(
aClientType, clientType, fallible)),
Err(NS_ERROR_INVALID_ARG));
return clientType;
}()));
RefPtr<Request> request = new Request();
mBackgroundActor
->SendShutdownStoragesForClient(persistenceType, principalInfo,
clientType)
->Then(GetCurrentSerialEventTarget(), __func__,
BoolResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::Persisted(nsIPrincipal* aPrincipal,
nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(_retval);
RefPtr<Request> request = new Request(aPrincipal);
PersistedParams params;
nsresult rv =
CheckedPrincipalToPrincipalInfo(aPrincipal, params.principalInfo());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
RequestInfo info(request, params);
rv = InitiateRequest(info);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::Persist(nsIPrincipal* aPrincipal,
nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(_retval);
RefPtr<Request> request = new Request(aPrincipal);
PersistParams params;
nsresult rv =
CheckedPrincipalToPrincipalInfo(aPrincipal, params.principalInfo());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
RequestInfo info(request, params);
rv = InitiateRequest(info);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::Estimate(nsIPrincipal* aPrincipal,
nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
RefPtr<Request> request = new Request(aPrincipal);
EstimateParams params;
nsresult rv =
CheckedPrincipalToPrincipalInfo(aPrincipal, params.principalInfo());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
RequestInfo info(request, params);
rv = InitiateRequest(info);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::ListOrigins(nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
auto request = MakeRefPtr<Request>();
mBackgroundActor->SendListOrigins()->Then(
GetCurrentSerialEventTarget(), __func__,
CStringArrayResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::ListCachedOrigins(nsIQuotaRequest** _retval) {
MOZ_ASSERT(NS_IsMainThread());
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
auto request = MakeRefPtr<Request>();
mBackgroundActor->SendListCachedOrigins()->Then(
GetCurrentSerialEventTarget(), __func__,
CStringArrayResponsePromiseResolveOrRejectCallback(request));
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::SetThumbnailPrivateIdentityId(
uint32_t aThumbnailPrivateIdentityId) {
MOZ_ASSERT(NS_IsMainThread());
QM_TRY(MOZ_TO_RESULT(EnsureBackgroundActor()));
mBackgroundActor->SendSetThumbnailPrivateIdentityId(
aThumbnailPrivateIdentityId);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData) {
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
if (!strcmp(aTopic, PROFILE_BEFORE_CHANGE_QM_OBSERVER_ID)) {
RemoveIdleObserver();
return NS_OK;
}
if (!strcmp(aTopic, OBSERVER_TOPIC_IDLE_DAILY)) {
PerformIdleMaintenance();
return NS_OK;
}
if (!strcmp(aTopic, OBSERVER_TOPIC_IDLE)) {
IdleMaintenanceInfo info(/* aStart */ true);
nsresult rv = InitiateRequest(info);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
if (!strcmp(aTopic, OBSERVER_TOPIC_ACTIVE)) {
RemoveIdleObserver();
IdleMaintenanceInfo info(/* aStart */ false);
nsresult rv = InitiateRequest(info);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
MOZ_ASSERT_UNREACHABLE("Should never get here!");
return NS_OK;
}
void QuotaManagerService::Notify(const hal::BatteryInformation& aBatteryInfo) {
// This notification is received when battery data changes. We don't need to
// deal with this notification.
}
nsresult QuotaManagerService::RequestInfo::InitiateRequest(QuotaChild* aActor) {
MOZ_ASSERT(aActor);
auto request = static_cast<Request*>(mRequest.get());
auto actor = new QuotaRequestChild(request);
if (!aActor->SendPQuotaRequestConstructor(actor, mParams)) {
request->SetError(NS_ERROR_FAILURE);
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsresult QuotaManagerService::IdleMaintenanceInfo::InitiateRequest(
QuotaChild* aActor) {
MOZ_ASSERT(aActor);
bool result;
if (mStart) {
result = aActor->SendStartIdleMaintenance();
} else {
result = aActor->SendStopIdleMaintenance();
}
if (!result) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
} // namespace mozilla::dom::quota