Source code

Revision control

Copy as Markdown

Other Tools

/* -*- 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 "ActorsChild.h"
#include "ErrorList.h"
#include "LSDatabase.h"
#include "LSObserver.h"
#include "LSSnapshot.h"
#include "LocalStorageCommon.h"
#include "mozilla/Assertions.h"
#include "mozilla/Result.h"
#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/dom/LSValue.h"
#include "mozilla/dom/Storage.h"
#include "mozilla/dom/quota/QuotaCommon.h"
#include "mozilla/dom/quota/ThreadUtils.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "nsCOMPtr.h"
namespace mozilla::dom {
/*******************************************************************************
* LSDatabaseChild
******************************************************************************/
LSDatabaseChild::LSDatabaseChild(LSDatabase* aDatabase) : mDatabase(aDatabase) {
AssertIsOnOwningThread();
MOZ_ASSERT(aDatabase);
MOZ_COUNT_CTOR(LSDatabaseChild);
}
LSDatabaseChild::~LSDatabaseChild() {
AssertIsOnOwningThread();
MOZ_COUNT_DTOR(LSDatabaseChild);
}
void LSDatabaseChild::Shutdown() {
AssertIsOnOwningThread();
if (mDatabase) {
mDatabase->ClearActor();
mDatabase = nullptr;
Close();
}
}
void LSDatabaseChild::ActorDestroy(ActorDestroyReason aWhy) {
AssertIsOnOwningThread();
if (mDatabase) {
mDatabase->ClearActor();
#ifdef DEBUG
mDatabase = nullptr;
#endif
}
}
mozilla::ipc::IPCResult LSDatabaseChild::RecvRequestAllowToClose() {
AssertIsOnOwningThread();
if (mDatabase) {
mDatabase->RequestAllowToClose();
// TODO: A new datastore will be prepared at first LocalStorage API
// synchronous call. It would be better to start preparing a new
// datastore right here, but asynchronously.
// However, we probably shouldn't do that if we are shutting down.
}
return IPC_OK();
}
PBackgroundLSSnapshotChild* LSDatabaseChild::AllocPBackgroundLSSnapshotChild(
const nsAString& aDocumentURI, const nsAString& aKey,
const bool& aIncreasePeakUsage, const int64_t& aMinSize,
LSSnapshotInitInfo* aInitInfo) {
MOZ_CRASH("PBackgroundLSSnapshotChild actor should be manually constructed!");
}
bool LSDatabaseChild::DeallocPBackgroundLSSnapshotChild(
PBackgroundLSSnapshotChild* aActor) {
MOZ_ASSERT(aActor);
delete aActor;
return true;
}
/*******************************************************************************
* LSObserverChild
******************************************************************************/
LSObserverChild::LSObserverChild(LSObserver* aObserver) : mObserver(aObserver) {
AssertIsOnOwningThread();
MOZ_ASSERT(aObserver);
MOZ_COUNT_CTOR(LSObserverChild);
}
LSObserverChild::~LSObserverChild() {
AssertIsOnOwningThread();
MOZ_COUNT_DTOR(LSObserverChild);
}
void LSObserverChild::SendDeleteMeInternal() {
AssertIsOnOwningThread();
if (mObserver) {
mObserver->ClearActor();
mObserver = nullptr;
MOZ_ALWAYS_TRUE(PBackgroundLSObserverChild::SendDeleteMe());
}
}
void LSObserverChild::ActorDestroy(ActorDestroyReason aWhy) {
AssertIsOnOwningThread();
if (mObserver) {
mObserver->ClearActor();
#ifdef DEBUG
mObserver = nullptr;
#endif
}
}
mozilla::ipc::IPCResult LSObserverChild::RecvObserve(
const PrincipalInfo& aPrincipalInfo, const uint32_t& aPrivateBrowsingId,
const nsAString& aDocumentURI, const nsAString& aKey,
const LSValue& aOldValue, const LSValue& aNewValue) {
AssertIsOnOwningThread();
if (!mObserver) {
return IPC_OK();
}
QM_TRY_INSPECT(const auto& principal,
PrincipalInfoToPrincipal(aPrincipalInfo),
IPC_FAIL(this, "PrincipalInfoToPrincipal failed!"));
Storage::NotifyChange(/* aStorage */ nullptr, principal, aKey,
aOldValue.AsString(), aNewValue.AsString(),
/* aStorageType */ kLocalStorageType, aDocumentURI,
/* aIsPrivate */ !!aPrivateBrowsingId,
/* aImmediateDispatch */ true);
return IPC_OK();
}
/*******************************************************************************
* LocalStorageRequestChild
******************************************************************************/
LSRequestChild::LSRequestChild() : mFinishing(false) {
AssertIsOnOwningThread();
MOZ_COUNT_CTOR(LSRequestChild);
}
LSRequestChild::~LSRequestChild() {
AssertIsOnOwningThread();
MOZ_ASSERT(!mCallback);
MOZ_COUNT_DTOR(LSRequestChild);
}
void LSRequestChild::SetCallback(LSRequestChildCallback* aCallback) {
AssertIsOnOwningThread();
MOZ_ASSERT(aCallback);
MOZ_ASSERT(!mCallback);
MOZ_ASSERT(Manager());
mCallback = aCallback;
}
bool LSRequestChild::Finishing() const {
AssertIsOnOwningThread();
return mFinishing;
}
void LSRequestChild::ActorDestroy(ActorDestroyReason aWhy) {
AssertIsOnOwningThread();
if (mCallback) {
MOZ_ASSERT(aWhy != Deletion);
mCallback->OnResponse(NS_ERROR_FAILURE);
mCallback = nullptr;
}
}
mozilla::ipc::IPCResult LSRequestChild::Recv__delete__(
LSRequestResponse&& aResponse) {
AssertIsOnOwningThread();
MOZ_ASSERT(mCallback);
mCallback->OnResponse(std::move(aResponse));
mCallback = nullptr;
return IPC_OK();
}
mozilla::ipc::IPCResult LSRequestChild::RecvReady() {
AssertIsOnOwningThread();
mFinishing = true;
quota::SleepIfEnabled(
StaticPrefs::dom_storage_requestFinalization_pauseOnDOMFileThreadMs());
// We only expect this to return false if the channel has been closed, but
// PBackground's channel never gets shutdown.
MOZ_ALWAYS_TRUE(SendFinish());
return IPC_OK();
}
/*******************************************************************************
* LSSimpleRequestChild
******************************************************************************/
LSSimpleRequestChild::LSSimpleRequestChild() {
AssertIsOnOwningThread();
MOZ_COUNT_CTOR(LSSimpleRequestChild);
}
LSSimpleRequestChild::~LSSimpleRequestChild() {
AssertIsOnOwningThread();
MOZ_ASSERT(!mCallback);
MOZ_COUNT_DTOR(LSSimpleRequestChild);
}
void LSSimpleRequestChild::SetCallback(
LSSimpleRequestChildCallback* aCallback) {
AssertIsOnOwningThread();
MOZ_ASSERT(aCallback);
MOZ_ASSERT(!mCallback);
MOZ_ASSERT(Manager());
mCallback = aCallback;
}
void LSSimpleRequestChild::ActorDestroy(ActorDestroyReason aWhy) {
AssertIsOnOwningThread();
if (mCallback) {
MOZ_ASSERT(aWhy != Deletion);
mCallback->OnResponse(NS_ERROR_FAILURE);
mCallback = nullptr;
}
}
mozilla::ipc::IPCResult LSSimpleRequestChild::Recv__delete__(
const LSSimpleRequestResponse& aResponse) {
AssertIsOnOwningThread();
MOZ_ASSERT(mCallback);
mCallback->OnResponse(aResponse);
mCallback = nullptr;
return IPC_OK();
}
/*******************************************************************************
* LSSnapshotChild
******************************************************************************/
LSSnapshotChild::LSSnapshotChild(LSSnapshot* aSnapshot) : mSnapshot(aSnapshot) {
AssertIsOnOwningThread();
MOZ_ASSERT(aSnapshot);
MOZ_COUNT_CTOR(LSSnapshotChild);
}
LSSnapshotChild::~LSSnapshotChild() {
AssertIsOnOwningThread();
MOZ_COUNT_DTOR(LSSnapshotChild);
}
void LSSnapshotChild::SendDeleteMeInternal() {
AssertIsOnOwningThread();
if (mSnapshot) {
mSnapshot->ClearActor();
mSnapshot = nullptr;
MOZ_ALWAYS_TRUE(PBackgroundLSSnapshotChild::SendDeleteMe());
}
}
void LSSnapshotChild::ActorDestroy(ActorDestroyReason aWhy) {
AssertIsOnOwningThread();
if (mSnapshot) {
mSnapshot->ClearActor();
#ifdef DEBUG
mSnapshot = nullptr;
#endif
}
}
mozilla::ipc::IPCResult LSSnapshotChild::RecvMarkDirty() {
AssertIsOnOwningThread();
if (!mSnapshot) {
return IPC_OK();
}
mSnapshot->MarkDirty();
return IPC_OK();
}
} // namespace mozilla::dom