Bug 1462162 - Filter local storage cache synchronization messages based on origin; r=asuth

This patch adds a new IPDL protocol PBackgroundLocalStorageCache. It is used by LocalStorageCache object to broadcast changes in local storage cache to other content processes. Each origin has its own PBackgroundLocalStorageCache, so now we can notify content processes that actually have a local storage cache for given origin. This greatly improves performance and reduces memory footprint especialy when local storage changes carry big strings and/or happen very quickly (before this patch all child processes were blindly notified).
This commit is contained in:
Jan Varga 2018-07-14 08:34:14 +02:00
parent 5adedd4945
commit 5f8daf01d9
15 changed files with 626 additions and 147 deletions

View file

@ -134,7 +134,7 @@ LocalStorage::SetItem(const nsAString& aKey, const nsAString& aData,
}
if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) {
BroadcastChangeNotification(aKey, old, aData);
OnChange(aKey, old, aData);
}
}
@ -154,7 +154,7 @@ LocalStorage::RemoveItem(const nsAString& aKey, nsIPrincipal& aSubjectPrincipal,
}
if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) {
BroadcastChangeNotification(aKey, old, VoidString());
OnChange(aKey, old, VoidString());
}
}
@ -172,47 +172,24 @@ LocalStorage::Clear(nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv)
}
if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) {
BroadcastChangeNotification(VoidString(), VoidString(), VoidString());
OnChange(VoidString(), VoidString(), VoidString());
}
}
void
LocalStorage::BroadcastChangeNotification(const nsAString& aKey,
const nsAString& aOldValue,
const nsAString& aNewValue)
LocalStorage::OnChange(const nsAString& aKey,
const nsAString& aOldValue,
const nsAString& aNewValue)
{
if (Principal()) {
// We want to send a message to the parent in order to broadcast the
// StorageEvent correctly to any child process.
PBackgroundChild* actor = BackgroundChild::GetForCurrentThread();
MOZ_ASSERT(actor);
PrincipalInfo principalInfo;
nsresult rv = PrincipalToPrincipalInfo(Principal(), &principalInfo);
if (!NS_WARN_IF(NS_FAILED(rv))) {
Unused << NS_WARN_IF(!actor->SendBroadcastLocalStorageChange(
mDocumentURI, nsString(aKey), nsString(aOldValue), nsString(aNewValue),
principalInfo, mIsPrivate));
}
}
DispatchStorageEvent(mDocumentURI, aKey, aOldValue, aNewValue,
Principal(), mIsPrivate, this, false);
}
/* static */ void
LocalStorage::DispatchStorageEvent(const nsAString& aDocumentURI,
const nsAString& aKey,
const nsAString& aOldValue,
const nsAString& aNewValue,
nsIPrincipal* aPrincipal,
bool aIsPrivate,
Storage* aStorage,
bool aImmediateDispatch)
{
NotifyChange(aStorage, aPrincipal, aKey, aOldValue, aNewValue,
u"localStorage", aDocumentURI, aIsPrivate, aImmediateDispatch);
NotifyChange(/* aStorage */ this,
Principal(),
aKey,
aOldValue,
aNewValue,
/* aStorageType */ u"localStorage",
mDocumentURI,
mIsPrivate,
/* aImmediateDispatch */ false);
}
void

View file

@ -36,6 +36,12 @@ public:
return mCache;
}
const nsString&
DocumentURI() const
{
return mDocumentURI;
}
bool PrincipalEquals(nsIPrincipal* aPrincipal);
LocalStorage(nsPIDOMWindowInner* aWindow,
@ -77,24 +83,6 @@ public:
bool IsPrivate() const { return mIsPrivate; }
// aStorage can be null if this method is called by ContentChild.
//
// aImmediateDispatch is for use by (main-thread) IPC code so that PContent
// ordering can be maintained. Without this, the event would be enqueued and
// run in a future turn of the event loop, potentially allowing other PContent
// Recv* methods to trigger script that wants to assume our localstorage
// changes have already been applied. This is the case for message manager
// messages which are used by ContentTask testing logic and webextensions.
static void
DispatchStorageEvent(const nsAString& aDocumentURI,
const nsAString& aKey,
const nsAString& aOldValue,
const nsAString& aNewValue,
nsIPrincipal* aPrincipal,
bool aIsPrivate,
Storage* aStorage,
bool aImmediateDispatch);
void
ApplyEvent(StorageEvent* aStorageEvent);
@ -115,9 +103,9 @@ private:
// Whether this storage is running in private-browsing window.
bool mIsPrivate : 1;
void BroadcastChangeNotification(const nsAString& aKey,
const nsAString& aOldValue,
const nsAString& aNewValue);
void OnChange(const nsAString& aKey,
const nsAString& aOldValue,
const nsAString& aNewValue);
};
} // namespace dom

View file

@ -75,7 +75,8 @@ NS_IMETHODIMP_(void) LocalStorageCacheBridge::Release(void)
// LocalStorageCache
LocalStorageCache::LocalStorageCache(const nsACString* aOriginNoSuffix)
: mOriginNoSuffix(*aOriginNoSuffix)
: mActor(nullptr)
, mOriginNoSuffix(*aOriginNoSuffix)
, mMonitor("LocalStorageCache")
, mLoaded(false)
, mLoadResult(NS_OK)
@ -89,6 +90,11 @@ LocalStorageCache::LocalStorageCache(const nsACString* aOriginNoSuffix)
LocalStorageCache::~LocalStorageCache()
{
if (mActor) {
mActor->SendDeleteMeInternal();
MOZ_ASSERT(!mActor, "SendDeleteMeInternal should have cleared!");
}
if (mManager) {
mManager->DropCache(this);
}
@ -96,6 +102,16 @@ LocalStorageCache::~LocalStorageCache()
MOZ_COUNT_DTOR(LocalStorageCache);
}
void
LocalStorageCache::SetActor(LocalStorageCacheChild* aActor)
{
AssertIsOnOwningThread();
MOZ_ASSERT(aActor);
MOZ_ASSERT(!mActor);
mActor = aActor;
}
NS_IMETHODIMP_(void)
LocalStorageCache::Release(void)
{
@ -152,6 +168,28 @@ LocalStorageCache::Init(LocalStorageManager* aManager,
mUsage = aManager->GetOriginUsage(mQuotaOriginScope);
}
void
LocalStorageCache::NotifyObservers(const LocalStorage* aStorage,
const nsString& aKey,
const nsString& aOldValue,
const nsString& aNewValue)
{
AssertIsOnOwningThread();
MOZ_ASSERT(aStorage);
if (!mActor) {
return;
}
// We want to send a message to the parent in order to broadcast the
// StorageEvent correctly to any child process.
Unused << mActor->SendNotify(aStorage->DocumentURI(),
aKey,
aOldValue,
aNewValue);
}
inline bool
LocalStorageCache::Persist(const LocalStorage* aStorage) const
{
@ -401,7 +439,13 @@ LocalStorageCache::SetItem(const LocalStorage* aStorage, const nsAString& aKey,
data.mKeys.Put(aKey, aValue);
if (aSource == ContentMutation && Persist(aStorage)) {
if (aSource != ContentMutation) {
return NS_OK;
}
NotifyObservers(aStorage, nsString(aKey), aOld, aValue);
if (Persist(aStorage)) {
StorageDBChild* storageChild = StorageDBChild::Get();
if (!storageChild) {
NS_ERROR("Writing to localStorage after the database has been shut down"
@ -443,7 +487,13 @@ LocalStorageCache::RemoveItem(const LocalStorage* aStorage,
Unused << ProcessUsageDelta(aStorage, delta, aSource);
data.mKeys.Remove(aKey);
if (aSource == ContentMutation && Persist(aStorage)) {
if (aSource != ContentMutation) {
return NS_OK;
}
NotifyObservers(aStorage, nsString(aKey), aOld, VoidString());
if (Persist(aStorage)) {
StorageDBChild* storageChild = StorageDBChild::Get();
if (!storageChild) {
NS_ERROR("Writing to localStorage after the database has been shut down"
@ -485,7 +535,15 @@ LocalStorageCache::Clear(const LocalStorage* aStorage,
data.mKeys.Clear();
}
if (aSource == ContentMutation && Persist(aStorage) && (refresh || hadData)) {
if (aSource != ContentMutation) {
return hadData ? NS_OK : NS_SUCCESS_DOM_NO_OPERATION;
}
if (hadData) {
NotifyObservers(aStorage, VoidString(), VoidString(), VoidString());
}
if (Persist(aStorage) && (refresh || hadData)) {
StorageDBChild* storageChild = StorageDBChild::Get();
if (!storageChild) {
NS_ERROR("Writing to localStorage after the database has been shut down"

View file

@ -21,6 +21,7 @@ namespace mozilla {
namespace dom {
class LocalStorage;
class LocalStorageCacheChild;
class LocalStorageManager;
class StorageUsage;
class StorageDBBridge;
@ -76,6 +77,23 @@ protected:
class LocalStorageCache : public LocalStorageCacheBridge
{
public:
void
AssertIsOnOwningThread() const
{
NS_ASSERT_OWNINGTHREAD(LocalStorage);
}
void
SetActor(LocalStorageCacheChild* aActor);
void
ClearActor()
{
AssertIsOnOwningThread();
mActor = nullptr;
}
NS_IMETHOD_(void) Release(void) override;
enum MutationSource {
@ -181,6 +199,13 @@ private:
// Helper to get one of the 3 data sets (regular, private, session)
Data& DataSet(const LocalStorage* aStorage);
// Used for firing storage events and synchronization of caches in other
// content processes.
void NotifyObservers(const LocalStorage* aStorage,
const nsString& aKey,
const nsString& aOldValue,
const nsString& aNewValue);
// Whether the storage change is about to persist
bool Persist(const LocalStorage* aStorage) const;
@ -210,6 +235,14 @@ private:
// Obtained from the manager during initialization (Init method).
RefPtr<StorageUsage> mUsage;
// The LocalStorageCacheChild is created at the same time of this class.
// In normal operation, the actor will be synchronously cleared in our
// destructor when we tell it to delete itself. In a shutdown-related edge
// case in the parent process for JSM's, it is possible for the actor to be
// destroyed while this class remains alive, in which case it will be nulled
// out.
LocalStorageCacheChild* mActor;
// The origin this cache belongs to in the "DB format", i.e. reversed
nsCString mOriginNoSuffix;

View file

@ -246,9 +246,38 @@ LocalStorageManager::GetStorageInternal(CreateMode aCreateMode,
}
}
PBackgroundChild* backgroundActor =
BackgroundChild::GetOrCreateForCurrentThread();
if (NS_WARN_IF(!backgroundActor)) {
return NS_ERROR_FAILURE;
}
PrincipalInfo principalInfo;
rv = mozilla::ipc::PrincipalToPrincipalInfo(aPrincipal, &principalInfo);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
uint32_t privateBrowsingId;
rv = aPrincipal->GetPrivateBrowsingId(&privateBrowsingId);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// There is always a single instance of a cache per scope
// in a single instance of a DOM storage manager.
cache = PutCache(originAttrSuffix, originKey, aPrincipal);
LocalStorageCacheChild* actor = new LocalStorageCacheChild(cache);
MOZ_ALWAYS_TRUE(
backgroundActor->SendPBackgroundLocalStorageCacheConstructor(
actor,
principalInfo,
originKey,
privateBrowsingId));
cache->SetActor(actor);
}
if (aRetval) {

View file

@ -0,0 +1,41 @@
/* 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 protocol PBackground;
include PBackgroundSharedTypes;
namespace mozilla {
namespace dom {
async protocol PBackgroundLocalStorageCache
{
manager PBackground;
parent:
async DeleteMe();
async Notify(nsString documentURI,
nsString key,
nsString oldValue,
nsString newValue);
child:
// The principalInfo and privateBrowsingId could instead be retained by the
// LocalStorageCacheChild/LocalStorageCache instead of being re-transmitted.
// However, these changes are a temporary optimization intended for uplift,
// and this constant factor overhead is very small compared to the upside of
// filtering.
async Observe(PrincipalInfo principalInfo,
uint32_t privateBrowsingId,
nsString documentURI,
nsString key,
nsString oldValue,
nsString newValue);
async __delete__();
};
} // namespace dom
} // namespace mozilla

View file

@ -111,6 +111,15 @@ public:
bool IsSessionOnly() const { return mIsSessionOnly; }
// aStorage can be null if this method is called by LocalStorageCacheChild.
//
// aImmediateDispatch is for use by child IPC code (LocalStorageCacheChild)
// so that PBackground ordering can be maintained. Without this, the event
// would be/ enqueued and run in a future turn of the event loop, potentially
// allowing other PBackground Recv* methods to trigger script that wants to
// assume our localstorage changes have already been applied. This is the
// case for message manager messages which are used by ContentTask testing
// logic and webextensions.
static void
NotifyChange(Storage* aStorage, nsIPrincipal* aPrincipal,
const nsAString& aKey, const nsAString& aOldValue,

View file

@ -23,6 +23,11 @@ namespace dom {
namespace {
typedef nsClassHashtable<nsCStringHashKey, nsTArray<LocalStorageCacheParent*>>
LocalStorageCacheParentHashtable;
StaticAutoPtr<LocalStorageCacheParentHashtable> gLocalStorageCacheParents;
StorageDBChild* sStorageChild = nullptr;
// False until we shut the storage child down.
@ -30,6 +35,77 @@ bool sStorageChildDown = false;
}
LocalStorageCacheChild::LocalStorageCacheChild(LocalStorageCache* aCache)
: mCache(aCache)
{
AssertIsOnOwningThread();
MOZ_ASSERT(aCache);
aCache->AssertIsOnOwningThread();
MOZ_COUNT_CTOR(LocalStorageCacheChild);
}
LocalStorageCacheChild::~LocalStorageCacheChild()
{
AssertIsOnOwningThread();
MOZ_COUNT_DTOR(LocalStorageCacheChild);
}
void
LocalStorageCacheChild::SendDeleteMeInternal()
{
AssertIsOnOwningThread();
if (mCache) {
mCache->ClearActor();
mCache = nullptr;
MOZ_ALWAYS_TRUE(PBackgroundLocalStorageCacheChild::SendDeleteMe());
}
}
void
LocalStorageCacheChild::ActorDestroy(ActorDestroyReason aWhy)
{
AssertIsOnOwningThread();
if (mCache) {
mCache->ClearActor();
mCache = nullptr;
}
}
mozilla::ipc::IPCResult
LocalStorageCacheChild::RecvObserve(const PrincipalInfo& aPrincipalInfo,
const uint32_t& aPrivateBrowsingId,
const nsString& aDocumentURI,
const nsString& aKey,
const nsString& aOldValue,
const nsString& aNewValue)
{
AssertIsOnOwningThread();
nsresult rv;
nsCOMPtr<nsIPrincipal> principal =
PrincipalInfoToPrincipal(aPrincipalInfo, &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return IPC_FAIL_NO_REASON(this);
}
Storage::NotifyChange(/* aStorage */ nullptr,
principal,
aKey,
aOldValue,
aNewValue,
/* aStorageType */ u"localStorage",
aDocumentURI,
/* aIsPrivate */ !!aPrivateBrowsingId,
/* aImmediateDispatch */ true);
return IPC_OK();
}
// ----------------------------------------------------------------------------
// Child
// ----------------------------------------------------------------------------
@ -396,6 +472,88 @@ ShutdownObserver::Observe(nsISupports* aSubject,
return NS_OK;
}
LocalStorageCacheParent::LocalStorageCacheParent(
const PrincipalInfo& aPrincipalInfo,
const nsACString& aOriginKey,
uint32_t aPrivateBrowsingId)
: mPrincipalInfo(aPrincipalInfo)
, mOriginKey(aOriginKey)
, mPrivateBrowsingId(aPrivateBrowsingId)
, mActorDestroyed(false)
{
AssertIsOnBackgroundThread();
}
LocalStorageCacheParent::~LocalStorageCacheParent()
{
MOZ_ASSERT(mActorDestroyed);
}
void
LocalStorageCacheParent::ActorDestroy(ActorDestroyReason aWhy)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(!mActorDestroyed);
mActorDestroyed = true;
MOZ_ASSERT(gLocalStorageCacheParents);
nsTArray<LocalStorageCacheParent*>* array;
gLocalStorageCacheParents->Get(mOriginKey, &array);
MOZ_ASSERT(array);
array->RemoveElement(this);
if (array->IsEmpty()) {
gLocalStorageCacheParents->Remove(mOriginKey);
}
if (!gLocalStorageCacheParents->Count()) {
gLocalStorageCacheParents = nullptr;
}
}
mozilla::ipc::IPCResult
LocalStorageCacheParent::RecvDeleteMe()
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(!mActorDestroyed);
IProtocol* mgr = Manager();
if (!PBackgroundLocalStorageCacheParent::Send__delete__(this)) {
return IPC_FAIL_NO_REASON(mgr);
}
return IPC_OK();
}
mozilla::ipc::IPCResult
LocalStorageCacheParent::RecvNotify(const nsString& aDocumentURI,
const nsString& aKey,
const nsString& aOldValue,
const nsString& aNewValue)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(gLocalStorageCacheParents);
nsTArray<LocalStorageCacheParent*>* array;
gLocalStorageCacheParents->Get(mOriginKey, &array);
MOZ_ASSERT(array);
for (LocalStorageCacheParent* localStorageCacheParent : *array) {
if (localStorageCacheParent != this) {
Unused << localStorageCacheParent->SendObserve(mPrincipalInfo,
mPrivateBrowsingId,
aDocumentURI,
aKey,
aOldValue,
aNewValue);
}
}
return IPC_OK();
}
// ----------------------------------------------------------------------------
// Parent
// ----------------------------------------------------------------------------
@ -1228,6 +1386,66 @@ ObserverSink::Observe(const char* aTopic,
* Exported functions
******************************************************************************/
PBackgroundLocalStorageCacheParent*
AllocPBackgroundLocalStorageCacheParent(
const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
const nsCString& aOriginKey,
const uint32_t& aPrivateBrowsingId)
{
AssertIsOnBackgroundThread();
RefPtr<LocalStorageCacheParent> actor =
new LocalStorageCacheParent(aPrincipalInfo, aOriginKey, aPrivateBrowsingId);
// Transfer ownership to IPDL.
return actor.forget().take();
}
mozilla::ipc::IPCResult
RecvPBackgroundLocalStorageCacheConstructor(
mozilla::ipc::PBackgroundParent* aBackgroundActor,
PBackgroundLocalStorageCacheParent* aActor,
const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
const nsCString& aOriginKey,
const uint32_t& aPrivateBrowsingId)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor);
auto* actor = static_cast<LocalStorageCacheParent*>(aActor);
if (!gLocalStorageCacheParents) {
gLocalStorageCacheParents = new LocalStorageCacheParentHashtable();
}
nsTArray<LocalStorageCacheParent*>* array;
if (!gLocalStorageCacheParents->Get(aOriginKey, &array)) {
array = new nsTArray<LocalStorageCacheParent*>();
gLocalStorageCacheParents->Put(aOriginKey, array);
}
array->AppendElement(actor);
// We are currently trusting the content process not to lie to us. It is
// future work to consult the ClientManager to determine whether this is a
// legitimate origin for the content process.
return IPC_OK();
}
bool
DeallocPBackgroundLocalStorageCacheParent(
PBackgroundLocalStorageCacheParent* aActor)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor);
// Transfer ownership back from IPDL.
RefPtr<LocalStorageCacheParent> actor =
dont_AddRef(static_cast<LocalStorageCacheParent*>(aActor));
return true;
}
PBackgroundStorageParent*
AllocPBackgroundStorageParent(const nsString& aProfilePath)
{

View file

@ -7,6 +7,8 @@
#ifndef mozilla_dom_StorageIPC_h
#define mozilla_dom_StorageIPC_h
#include "mozilla/dom/PBackgroundLocalStorageCacheChild.h"
#include "mozilla/dom/PBackgroundLocalStorageCacheParent.h"
#include "mozilla/dom/PBackgroundStorageChild.h"
#include "mozilla/dom/PBackgroundStorageParent.h"
#include "StorageDBThread.h"
@ -19,11 +21,65 @@ namespace mozilla {
class OriginAttributesPattern;
namespace ipc {
class BackgroundChildImpl;
class PrincipalInfo;
} // namespace ipc
namespace dom {
class LocalStorageManager;
class PBackgroundStorageParent;
class LocalStorageCacheChild final
: public PBackgroundLocalStorageCacheChild
{
friend class mozilla::ipc::BackgroundChildImpl;
friend class LocalStorageCache;
friend class LocalStorageManager;
// LocalStorageCache effectively owns this instance, although IPC handles its
// allocation/deallocation. When the LocalStorageCache destructor runs, it
// will invoke SendDeleteMeInternal() which will trigger both instances to
// drop their mutual references and cause IPC to destroy the actor after the
// DeleteMe round-trip.
LocalStorageCache* MOZ_NON_OWNING_REF mCache;
NS_DECL_OWNINGTHREAD
public:
void
AssertIsOnOwningThread() const
{
NS_ASSERT_OWNINGTHREAD(LocalStorageCacheChild);
}
private:
// Only created by LocalStorageManager.
explicit LocalStorageCacheChild(LocalStorageCache* aCache);
// Only destroyed by mozilla::ipc::BackgroundChildImpl.
~LocalStorageCacheChild();
// Only called by LocalStorageCache.
void
SendDeleteMeInternal();
// IPDL methods are only called by IPDL.
void
ActorDestroy(ActorDestroyReason aWhy) override;
mozilla::ipc::IPCResult
RecvObserve(const PrincipalInfo& aPrincipalInfo,
const uint32_t& aPrivateBrowsingId,
const nsString& aDocumentURI,
const nsString& aKey,
const nsString& aOldValue,
const nsString& aNewValue) override;
};
// Child side of the IPC protocol, exposes as DB interface but
// is responsible to send all requests to the parent process
// and expects asynchronous answers. Those are then transparently
@ -126,6 +182,39 @@ private:
bool mIPCOpen;
};
class LocalStorageCacheParent final
: public PBackgroundLocalStorageCacheParent
{
const PrincipalInfo mPrincipalInfo;
const nsCString mOriginKey;
uint32_t mPrivateBrowsingId;
bool mActorDestroyed;
public:
// Created in AllocPBackgroundLocalStorageCacheParent.
LocalStorageCacheParent(const PrincipalInfo& aPrincipalInfo,
const nsACString& aOriginKey,
uint32_t aPrivateBrowsingId);
NS_INLINE_DECL_REFCOUNTING(mozilla::dom::LocalStorageCacheParent)
private:
// Reference counted.
~LocalStorageCacheParent();
// IPDL methods are only called by IPDL.
void
ActorDestroy(ActorDestroyReason aWhy) override;
mozilla::ipc::IPCResult
RecvDeleteMe() override;
mozilla::ipc::IPCResult
RecvNotify(const nsString& aDocumentURI,
const nsString& aKey,
const nsString& aOldValue,
const nsString& aNewValue) override;
};
// Receives async requests from child processes and is responsible
// to send back responses from the DB thread. Exposes as a fake
@ -283,6 +372,24 @@ private:
bool mIPCOpen;
};
PBackgroundLocalStorageCacheParent*
AllocPBackgroundLocalStorageCacheParent(
const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
const nsCString& aOriginKey,
const uint32_t& aPrivateBrowsingId);
mozilla::ipc::IPCResult
RecvPBackgroundLocalStorageCacheConstructor(
mozilla::ipc::PBackgroundParent* aBackgroundActor,
PBackgroundLocalStorageCacheParent* aActor,
const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
const nsCString& aOriginKey,
const uint32_t& aPrivateBrowsingId);
bool
DeallocPBackgroundLocalStorageCacheParent(
PBackgroundLocalStorageCacheParent* aActor);
PBackgroundStorageParent*
AllocPBackgroundStorageParent(const nsString& aProfilePath);

View file

@ -36,6 +36,7 @@ UNIFIED_SOURCES += [
]
IPDL_SOURCES += [
'PBackgroundLocalStorageCache.ipdl',
'PBackgroundStorage.ipdl',
]

View file

@ -219,6 +219,26 @@ BackgroundChildImpl::DeallocPBackgroundIndexedDBUtilsChild(
return true;
}
BackgroundChildImpl::PBackgroundLocalStorageCacheChild*
BackgroundChildImpl::AllocPBackgroundLocalStorageCacheChild(
const PrincipalInfo& aPrincipalInfo,
const nsCString& aOriginKey,
const uint32_t& aPrivateBrowsingId)
{
MOZ_CRASH("PBackgroundLocalStorageChild actors should be manually "
"constructed!");
}
bool
BackgroundChildImpl::DeallocPBackgroundLocalStorageCacheChild(
PBackgroundLocalStorageCacheChild* aActor)
{
MOZ_ASSERT(aActor);
delete aActor;
return true;
}
BackgroundChildImpl::PBackgroundStorageChild*
BackgroundChildImpl::AllocPBackgroundStorageChild(const nsString& aProfilePath)
{
@ -715,32 +735,6 @@ BackgroundChildImpl::DeallocPServiceWorkerRegistrationChild(PServiceWorkerRegist
return dom::DeallocServiceWorkerRegistrationChild(aActor);
}
mozilla::ipc::IPCResult
BackgroundChildImpl::RecvDispatchLocalStorageChange(
const nsString& aDocumentURI,
const nsString& aKey,
const nsString& aOldValue,
const nsString& aNewValue,
const PrincipalInfo& aPrincipalInfo,
const bool& aIsPrivate)
{
if (!NS_IsMainThread()) {
return IPC_OK();
}
nsresult rv;
nsCOMPtr<nsIPrincipal> principal =
PrincipalInfoToPrincipal(aPrincipalInfo, &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return IPC_FAIL_NO_REASON(this);
}
LocalStorage::DispatchStorageEvent(aDocumentURI, aKey, aOldValue, aNewValue,
principal, aIsPrivate, nullptr, true);
return IPC_OK();
}
bool
BackgroundChildImpl::GetMessageSchedulerGroups(const Message& aMsg, SchedulerGroupSet& aGroups)
{

View file

@ -70,6 +70,17 @@ protected:
DeallocPBackgroundIndexedDBUtilsChild(PBackgroundIndexedDBUtilsChild* aActor)
override;
virtual PBackgroundLocalStorageCacheChild*
AllocPBackgroundLocalStorageCacheChild(const PrincipalInfo& aPrincipalInfo,
const nsCString& aOriginKey,
const uint32_t& aPrivateBrowsingId)
override;
virtual bool
DeallocPBackgroundLocalStorageCacheChild(
PBackgroundLocalStorageCacheChild* aActor)
override;
virtual PBackgroundStorageChild*
AllocPBackgroundStorageChild(const nsString& aProfilePath) override;
@ -227,14 +238,6 @@ protected:
virtual bool
DeallocPHttpBackgroundChannelChild(PHttpBackgroundChannelChild* aActor) override;
virtual mozilla::ipc::IPCResult
RecvDispatchLocalStorageChange(const nsString& aDocumentURI,
const nsString& aKey,
const nsString& aOldValue,
const nsString& aNewValue,
const PrincipalInfo& aPrincipalInfo,
const bool& aIsPrivate) override;
bool
GetMessageSchedulerGroups(const Message& aMsg, SchedulerGroupSet& aGroups) override;

View file

@ -252,6 +252,52 @@ BackgroundParentImpl::RecvFlushPendingFileDeletions()
return IPC_OK();
}
BackgroundParentImpl::PBackgroundLocalStorageCacheParent*
BackgroundParentImpl::AllocPBackgroundLocalStorageCacheParent(
const PrincipalInfo& aPrincipalInfo,
const nsCString& aOriginKey,
const uint32_t& aPrivateBrowsingId)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
return
mozilla::dom::AllocPBackgroundLocalStorageCacheParent(aPrincipalInfo,
aOriginKey,
aPrivateBrowsingId);
}
mozilla::ipc::IPCResult
BackgroundParentImpl::RecvPBackgroundLocalStorageCacheConstructor(
PBackgroundLocalStorageCacheParent* aActor,
const PrincipalInfo& aPrincipalInfo,
const nsCString& aOriginKey,
const uint32_t& aPrivateBrowsingId)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor);
return
mozilla::dom::RecvPBackgroundLocalStorageCacheConstructor(
this,
aActor,
aPrincipalInfo,
aOriginKey,
aPrivateBrowsingId);
}
bool
BackgroundParentImpl::DeallocPBackgroundLocalStorageCacheParent(
PBackgroundLocalStorageCacheParent* aActor)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor);
return mozilla::dom::DeallocPBackgroundLocalStorageCacheParent(aActor);
}
auto
BackgroundParentImpl::AllocPBackgroundStorageParent(const nsString& aProfilePath)
-> PBackgroundStorageParent*
@ -285,34 +331,6 @@ BackgroundParentImpl::DeallocPBackgroundStorageParent(
return mozilla::dom::DeallocPBackgroundStorageParent(aActor);
}
mozilla::ipc::IPCResult
BackgroundParentImpl::RecvBroadcastLocalStorageChange(
const nsString& aDocumentURI,
const nsString& aKey,
const nsString& aOldValue,
const nsString& aNewValue,
const PrincipalInfo& aPrincipalInfo,
const bool& aIsPrivate)
{
// Let's inform the StorageActivityService about this change.
dom::StorageActivityService::SendActivity(aPrincipalInfo);
nsTArray<PBackgroundParent*> liveActorArray;
if (NS_WARN_IF(!BackgroundParent::GetLiveActorArray(this, liveActorArray))) {
return IPC_FAIL_NO_REASON(this);
}
for (auto* liveActor : liveActorArray) {
if (liveActor != this) {
Unused << liveActor->SendDispatchLocalStorageChange(
nsString(aDocumentURI), nsString(aKey), nsString(aOldValue),
nsString(aNewValue), aPrincipalInfo, aIsPrivate);
}
}
return IPC_OK();
}
PPendingIPCBlobParent*
BackgroundParentImpl::AllocPPendingIPCBlobParent(const IPCBlob& aBlob)
{

View file

@ -63,6 +63,25 @@ protected:
virtual mozilla::ipc::IPCResult
RecvFlushPendingFileDeletions() override;
virtual PBackgroundLocalStorageCacheParent*
AllocPBackgroundLocalStorageCacheParent(const PrincipalInfo& aPrincipalInfo,
const nsCString& aOriginKey,
const uint32_t& aPrivateBrowsingId)
override;
virtual mozilla::ipc::IPCResult
RecvPBackgroundLocalStorageCacheConstructor(
PBackgroundLocalStorageCacheParent* aActor,
const PrincipalInfo& aPrincipalInfo,
const nsCString& aOriginKey,
const uint32_t& aPrivateBrowsingId)
override;
virtual bool
DeallocPBackgroundLocalStorageCacheParent(
PBackgroundLocalStorageCacheParent* aActor)
override;
virtual PBackgroundStorageParent*
AllocPBackgroundStorageParent(const nsString& aProfilePath) override;
@ -73,14 +92,6 @@ protected:
virtual bool
DeallocPBackgroundStorageParent(PBackgroundStorageParent* aActor) override;
virtual mozilla::ipc::IPCResult
RecvBroadcastLocalStorageChange(const nsString& aDocumentURI,
const nsString& aKey,
const nsString& aOldValue,
const nsString& aNewValue,
const PrincipalInfo& aPrincipalInfo,
const bool& aIsPrivate) override;
virtual PPendingIPCBlobParent*
AllocPPendingIPCBlobParent(const IPCBlob& aBlob) override;

View file

@ -5,6 +5,7 @@
include protocol PAsmJSCacheEntry;
include protocol PBackgroundIDBFactory;
include protocol PBackgroundIndexedDBUtils;
include protocol PBackgroundLocalStorageCache;
include protocol PBackgroundStorage;
include protocol PBackgroundTest;
include protocol PBroadcastChannel;
@ -65,6 +66,7 @@ sync protocol PBackground
manages PAsmJSCacheEntry;
manages PBackgroundIDBFactory;
manages PBackgroundIndexedDBUtils;
manages PBackgroundLocalStorageCache;
manages PBackgroundStorage;
manages PBackgroundTest;
manages PBroadcastChannel;
@ -106,14 +108,11 @@ parent:
// Use only for testing!
async FlushPendingFileDeletions();
async PBackgroundStorage(nsString profilePath);
async PBackgroundLocalStorageCache(PrincipalInfo principalInfo,
nsCString originKey,
uint32_t privateBrowsingId);
async BroadcastLocalStorageChange(nsString documentURI,
nsString key,
nsString oldValue,
nsString newValue,
PrincipalInfo principalInfo,
bool isPrivate);
async PBackgroundStorage(nsString profilePath);
async PVsync();
@ -175,13 +174,6 @@ child:
async PPendingIPCBlob(IPCBlob blob);
async DispatchLocalStorageChange(nsString documentURI,
nsString key,
nsString oldValue,
nsString newValue,
PrincipalInfo principalInfo,
bool isPrivate);
both:
// PIPCBlobInputStream is created on the parent side only if the child starts
// a migration.