summaryrefslogtreecommitdiffstats
path: root/dom/quota/QuotaManagerService.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/quota/QuotaManagerService.cpp')
-rw-r--r--dom/quota/QuotaManagerService.cpp845
1 files changed, 845 insertions, 0 deletions
diff --git a/dom/quota/QuotaManagerService.cpp b/dom/quota/QuotaManagerService.cpp
new file mode 100644
index 000000000..fb5f0f3a1
--- /dev/null
+++ b/dom/quota/QuotaManagerService.cpp
@@ -0,0 +1,845 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=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"
+
+#include "ActorsChild.h"
+#include "mozilla/BasePrincipal.h"
+#include "mozilla/ClearOnShutdown.h"
+#include "mozilla/Hal.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/Unused.h"
+#include "mozilla/ipc/BackgroundChild.h"
+#include "mozilla/ipc/BackgroundParent.h"
+#include "mozilla/ipc/BackgroundUtils.h"
+#include "mozilla/ipc/PBackgroundChild.h"
+#include "nsIIdleService.h"
+#include "nsIIPCBackgroundChildCreateCallback.h"
+#include "nsIObserverService.h"
+#include "nsIScriptSecurityManager.h"
+#include "nsXULAppAPI.h"
+#include "QuotaManager.h"
+#include "QuotaRequests.h"
+
+#define PROFILE_BEFORE_CHANGE_QM_OBSERVER_ID "profile-before-change-qm"
+
+namespace mozilla {
+namespace dom {
+namespace quota {
+
+using namespace mozilla::ipc;
+
+namespace {
+
+// Preference that is used to enable testing features.
+const char kTestingPref[] = "dom.quotaManager.testing";
+
+const char kIdleServiceContractId[] = "@mozilla.org/widget/idleservice;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);
+mozilla::Atomic<bool> gTestingMode(false);
+
+void
+TestingPrefChangedCallback(const char* aPrefName,
+ void* aClosure)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(!strcmp(aPrefName, kTestingPref));
+ MOZ_ASSERT(!aClosure);
+
+ gTestingMode = Preferences::GetBool(aPrefName);
+}
+
+class AbortOperationsRunnable final
+ : public Runnable
+{
+ ContentParentId mContentParentId;
+
+public:
+ explicit AbortOperationsRunnable(ContentParentId aContentParentId)
+ : mContentParentId(aContentParentId)
+ { }
+
+private:
+ NS_DECL_NSIRUNNABLE
+};
+
+} // namespace
+
+class QuotaManagerService::BackgroundCreateCallback final
+ : public nsIIPCBackgroundChildCreateCallback
+{
+ RefPtr<QuotaManagerService> mService;
+
+public:
+ explicit
+ BackgroundCreateCallback(QuotaManagerService* aService)
+ : mService(aService)
+ {
+ MOZ_ASSERT(aService);
+ }
+
+ NS_DECL_ISUPPORTS
+
+private:
+ ~BackgroundCreateCallback()
+ { }
+
+ NS_DECL_NSIIPCBACKGROUNDCHILDCREATECALLBACK
+};
+
+class QuotaManagerService::PendingRequestInfo
+{
+protected:
+ RefPtr<RequestBase> mRequest;
+
+public:
+ explicit PendingRequestInfo(RequestBase* aRequest)
+ : mRequest(aRequest)
+ { }
+
+ virtual ~PendingRequestInfo()
+ { }
+
+ RequestBase*
+ GetRequest() const
+ {
+ return mRequest;
+ }
+
+ virtual nsresult
+ InitiateRequest(QuotaChild* aActor) = 0;
+};
+
+class QuotaManagerService::UsageRequestInfo
+ : public PendingRequestInfo
+{
+ UsageRequestParams mParams;
+
+public:
+ UsageRequestInfo(UsageRequest* aRequest,
+ const UsageRequestParams& aParams)
+ : PendingRequestInfo(aRequest)
+ , mParams(aParams)
+ {
+ MOZ_ASSERT(aRequest);
+ MOZ_ASSERT(aParams.type() != UsageRequestParams::T__None);
+ }
+
+ virtual nsresult
+ InitiateRequest(QuotaChild* aActor) override;
+};
+
+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
+QuotaManagerService*
+QuotaManagerService::FactoryCreate()
+{
+ // Returns a raw pointer that carries an owning reference! Lame, but the
+ // singleton factory macros force this.
+ QuotaManagerService* quotaManagerService = GetOrCreate();
+ NS_IF_ADDREF(quotaManagerService);
+ return quotaManagerService;
+}
+
+void
+QuotaManagerService::ClearBackgroundActor()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ mBackgroundActor = nullptr;
+}
+
+void
+QuotaManagerService::NoteLiveManager(QuotaManager* aManager)
+{
+ MOZ_ASSERT(XRE_IsParentProcess());
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(aManager);
+
+ mBackgroundThread = aManager->OwningThread();
+}
+
+void
+QuotaManagerService::NoteShuttingDownManager()
+{
+ MOZ_ASSERT(XRE_IsParentProcess());
+ MOZ_ASSERT(NS_IsMainThread());
+
+ mBackgroundThread = nullptr;
+}
+
+void
+QuotaManagerService::AbortOperationsForProcess(ContentParentId aContentParentId)
+{
+ MOZ_ASSERT(XRE_IsParentProcess());
+ MOZ_ASSERT(NS_IsMainThread());
+
+ if (!mBackgroundThread) {
+ return;
+ }
+
+ RefPtr<AbortOperationsRunnable> runnable =
+ new AbortOperationsRunnable(aContentParentId);
+
+ MOZ_ALWAYS_SUCCEEDS(
+ mBackgroundThread->Dispatch(runnable, NS_DISPATCH_NORMAL));
+}
+
+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;
+ }
+ }
+
+ Preferences::RegisterCallbackAndCall(TestingPrefChangedCallback,
+ kTestingPref);
+
+ 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?!");
+ }
+
+ Preferences::UnregisterCallback(TestingPrefChangedCallback, kTestingPref);
+
+ delete this;
+}
+
+nsresult
+QuotaManagerService::InitiateRequest(nsAutoPtr<PendingRequestInfo>& aInfo)
+{
+ // Nothing can be done here if we have previously failed to create a
+ // background actor.
+ if (mBackgroundActorFailed) {
+ return NS_ERROR_FAILURE;
+ }
+
+ if (!mBackgroundActor && mPendingRequests.IsEmpty()) {
+ if (PBackgroundChild* actor = BackgroundChild::GetForCurrentThread()) {
+ BackgroundActorCreated(actor);
+ } else {
+ // We need to start the sequence to create a background actor for this
+ // thread.
+ RefPtr<BackgroundCreateCallback> cb = new BackgroundCreateCallback(this);
+ if (NS_WARN_IF(!BackgroundChild::GetOrCreateForCurrentThread(cb))) {
+ return NS_ERROR_FAILURE;
+ }
+ }
+ }
+
+ // If we already have a background actor then we can start this request now.
+ if (mBackgroundActor) {
+ nsresult rv = aInfo->InitiateRequest(mBackgroundActor);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ } else {
+ mPendingRequests.AppendElement(aInfo.forget());
+ }
+
+ return NS_OK;
+}
+
+nsresult
+QuotaManagerService::BackgroundActorCreated(PBackgroundChild* aBackgroundActor)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(aBackgroundActor);
+ MOZ_ASSERT(!mBackgroundActor);
+ MOZ_ASSERT(!mBackgroundActorFailed);
+
+ {
+ QuotaChild* actor = new QuotaChild(this);
+
+ mBackgroundActor =
+ static_cast<QuotaChild*>(aBackgroundActor->SendPQuotaConstructor(actor));
+ }
+
+ if (NS_WARN_IF(!mBackgroundActor)) {
+ BackgroundActorFailed();
+ return NS_ERROR_FAILURE;
+ }
+
+ nsresult rv = NS_OK;
+
+ for (uint32_t index = 0, count = mPendingRequests.Length();
+ index < count;
+ index++) {
+ nsAutoPtr<PendingRequestInfo> info(mPendingRequests[index].forget());
+
+ nsresult rv2 = info->InitiateRequest(mBackgroundActor);
+
+ // Warn for every failure, but just return the first failure if there are
+ // multiple failures.
+ if (NS_WARN_IF(NS_FAILED(rv2)) && NS_SUCCEEDED(rv)) {
+ rv = rv2;
+ }
+ }
+
+ mPendingRequests.Clear();
+
+ return rv;
+}
+
+void
+QuotaManagerService::BackgroundActorFailed()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(!mPendingRequests.IsEmpty());
+ MOZ_ASSERT(!mBackgroundActor);
+ MOZ_ASSERT(!mBackgroundActorFailed);
+
+ mBackgroundActorFailed = true;
+
+ for (uint32_t index = 0, count = mPendingRequests.Length();
+ index < count;
+ index++) {
+ nsAutoPtr<PendingRequestInfo> info(mPendingRequests[index].forget());
+
+ RequestBase* request = info->GetRequest();
+ if (request) {
+ request->SetError(NS_ERROR_FAILURE);
+ }
+ }
+
+ mPendingRequests.Clear();
+}
+
+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
+ {
+ GetCurrentBatteryInformation(&batteryInfo);
+ }
+
+ // 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<nsIIdleService> 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<nsIIdleService> idleService =
+ do_GetService(kIdleServiceContractId);
+ MOZ_ASSERT(idleService);
+
+ MOZ_ALWAYS_SUCCEEDS(
+ idleService->RemoveIdleObserver(this, kIdleObserverTimeSec));
+
+ mIdleObserverRegistered = false;
+ }
+}
+
+NS_IMPL_ADDREF(QuotaManagerService)
+NS_IMPL_RELEASE_WITH_DESTROY(QuotaManagerService, Destroy())
+NS_IMPL_QUERY_INTERFACE(QuotaManagerService,
+ nsIQuotaManagerService,
+ nsIObserver)
+
+NS_IMETHODIMP
+QuotaManagerService::GetUsage(nsIQuotaUsageCallback* aCallback,
+ bool aGetAll,
+ nsIQuotaUsageRequest** _retval)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(aCallback);
+
+ RefPtr<UsageRequest> request = new UsageRequest(aCallback);
+
+ AllUsageParams params;
+
+ params.getAll() = aGetAll;
+
+ nsAutoPtr<PendingRequestInfo> info(new UsageRequestInfo(request, params));
+
+ nsresult rv = InitiateRequest(info);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ request.forget(_retval);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+QuotaManagerService::GetUsageForPrincipal(nsIPrincipal* aPrincipal,
+ nsIQuotaUsageCallback* aCallback,
+ bool aGetGroupUsage,
+ nsIQuotaUsageRequest** _retval)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(aPrincipal);
+ MOZ_ASSERT(aCallback);
+
+ RefPtr<UsageRequest> request = new UsageRequest(aPrincipal, aCallback);
+
+ OriginUsageParams params;
+
+ PrincipalInfo& principalInfo = params.principalInfo();
+ nsresult rv = PrincipalToPrincipalInfo(aPrincipal, &principalInfo);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ if (principalInfo.type() != PrincipalInfo::TContentPrincipalInfo &&
+ principalInfo.type() != PrincipalInfo::TSystemPrincipalInfo) {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ params.getGroupUsage() = aGetGroupUsage;
+
+ nsAutoPtr<PendingRequestInfo> info(new UsageRequestInfo(request, params));
+
+ rv = InitiateRequest(info);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ request.forget(_retval);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+QuotaManagerService::Clear(nsIQuotaRequest** _retval)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(nsContentUtils::IsCallerChrome());
+
+ if (NS_WARN_IF(!gTestingMode)) {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ RefPtr<Request> request = new Request();
+
+ ClearAllParams params;
+
+ nsAutoPtr<PendingRequestInfo> info(new RequestInfo(request, params));
+
+ nsresult rv = InitiateRequest(info);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ request.forget(_retval);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+QuotaManagerService::ClearStoragesForPrincipal(nsIPrincipal* aPrincipal,
+ const nsACString& aPersistenceType,
+ bool aClearAll,
+ nsIQuotaRequest** _retval)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(aPrincipal);
+ MOZ_ASSERT(nsContentUtils::IsCallerChrome());
+
+ nsCString suffix;
+ BasePrincipal::Cast(aPrincipal)->OriginAttributesRef().CreateSuffix(suffix);
+
+ if (NS_WARN_IF(aClearAll && !suffix.IsEmpty())) {
+ // The originAttributes should be default originAttributes when the
+ // aClearAll flag is set.
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ RefPtr<Request> request = new Request(aPrincipal);
+
+ ClearOriginParams params;
+
+ PrincipalInfo& principalInfo = params.principalInfo();
+
+ nsresult rv = PrincipalToPrincipalInfo(aPrincipal, &principalInfo);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ if (principalInfo.type() != PrincipalInfo::TContentPrincipalInfo &&
+ principalInfo.type() != PrincipalInfo::TSystemPrincipalInfo) {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ Nullable<PersistenceType> persistenceType;
+ rv = NullablePersistenceTypeFromText(aPersistenceType, &persistenceType);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ if (persistenceType.IsNull()) {
+ params.persistenceTypeIsExplicit() = false;
+ } else {
+ params.persistenceType() = persistenceType.Value();
+ params.persistenceTypeIsExplicit() = true;
+ }
+
+ params.clearAll() = aClearAll;
+
+ nsAutoPtr<PendingRequestInfo> info(new RequestInfo(request, params));
+
+ rv = InitiateRequest(info);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ request.forget(_retval);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+QuotaManagerService::Reset(nsIQuotaRequest** _retval)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(nsContentUtils::IsCallerChrome());
+
+ if (NS_WARN_IF(!gTestingMode)) {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ RefPtr<Request> request = new Request();
+
+ ResetAllParams params;
+
+ nsAutoPtr<PendingRequestInfo> info(new RequestInfo(request, params));
+
+ nsresult rv = InitiateRequest(info);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ request.forget(_retval);
+ 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, "clear-origin-attributes-data")) {
+ RefPtr<Request> request = new Request();
+
+ ClearOriginsParams requestParams;
+ requestParams.pattern() = nsDependentString(aData);
+
+ nsAutoPtr<PendingRequestInfo> info(new RequestInfo(request, requestParams));
+
+ nsresult rv = InitiateRequest(info);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ return NS_OK;
+ }
+
+ if (!strcmp(aTopic, OBSERVER_TOPIC_IDLE_DAILY)) {
+ PerformIdleMaintenance();
+ return NS_OK;
+ }
+
+ if (!strcmp(aTopic, OBSERVER_TOPIC_IDLE)) {
+ nsAutoPtr<PendingRequestInfo> info(
+ new IdleMaintenanceInfo(/* 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();
+
+ nsAutoPtr<PendingRequestInfo> info(
+ new IdleMaintenanceInfo(/* 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;
+}
+
+NS_IMETHODIMP
+AbortOperationsRunnable::Run()
+{
+ AssertIsOnBackgroundThread();
+
+ if (QuotaManager::IsShuttingDown()) {
+ return NS_OK;
+ }
+
+ QuotaManager* quotaManager = QuotaManager::Get();
+ if (!quotaManager) {
+ return NS_OK;
+ }
+
+ quotaManager->AbortOperationsForProcess(mContentParentId);
+
+ return NS_OK;
+}
+
+NS_IMPL_ISUPPORTS(QuotaManagerService::BackgroundCreateCallback,
+ nsIIPCBackgroundChildCreateCallback)
+
+void
+QuotaManagerService::
+BackgroundCreateCallback::ActorCreated(PBackgroundChild* aActor)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(aActor);
+ MOZ_ASSERT(mService);
+
+ RefPtr<QuotaManagerService> service;
+ mService.swap(service);
+
+ service->BackgroundActorCreated(aActor);
+}
+
+void
+QuotaManagerService::
+BackgroundCreateCallback::ActorFailed()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(mService);
+
+ RefPtr<QuotaManagerService> service;
+ mService.swap(service);
+
+ service->BackgroundActorFailed();
+}
+
+nsresult
+QuotaManagerService::
+UsageRequestInfo::InitiateRequest(QuotaChild* aActor)
+{
+ MOZ_ASSERT(aActor);
+
+ auto request = static_cast<UsageRequest*>(mRequest.get());
+
+ auto actor = new QuotaUsageRequestChild(request);
+
+ if (!aActor->SendPQuotaUsageRequestConstructor(actor, mParams)) {
+ request->SetError(NS_ERROR_FAILURE);
+ return NS_ERROR_FAILURE;
+ }
+
+ request->SetBackgroundActor(actor);
+
+ return NS_OK;
+}
+
+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 quota
+} // namespace dom
+} // namespace mozilla