mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 01:35:35 +00:00
Bug 1605566 - MessagePort + wasm - part 4 - Implement RefMessageBodyService, r=smaug
Differential Revision: https://phabricator.services.mozilla.com/D59615 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
4da71e81af
commit
6c0733d2e8
@ -67,7 +67,7 @@ class SharedJSAllocatedData final {
|
||||
return sharedData.forget();
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(SharedJSAllocatedData)
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedJSAllocatedData)
|
||||
|
||||
JSStructuredCloneData& Data() { return mData; }
|
||||
size_t DataLength() const { return mData.Size(); }
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "SharedMessagePortMessage.h"
|
||||
#include "RefMessageBodyService.h"
|
||||
|
||||
#include "nsIBFCacheEntry.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
@ -122,7 +123,7 @@ class PostMessageRunnable final : public CancelableRunnable {
|
||||
MarkerTracingType::START);
|
||||
}
|
||||
|
||||
mData->Read(cx, &value, rv);
|
||||
mData->Read(cx, &value, mPort->mRefMessageBodyService, rv);
|
||||
|
||||
if (isTimelineRecording) {
|
||||
end = MakeUnique<MessagePortTimelineMarker>(
|
||||
@ -196,6 +197,7 @@ NS_IMPL_RELEASE_INHERITED(MessagePort, DOMEventTargetHelper)
|
||||
|
||||
MessagePort::MessagePort(nsIGlobalObject* aGlobal, State aState)
|
||||
: DOMEventTargetHelper(aGlobal),
|
||||
mRefMessageBodyService(RefMessageBodyService::GetOrCreate()),
|
||||
mState(aState),
|
||||
mMessageQueueEnabled(false),
|
||||
mIsKeptAlive(false),
|
||||
@ -340,7 +342,8 @@ void MessagePort::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
MarkerTracingType::START);
|
||||
}
|
||||
|
||||
data->Write(aCx, aMessage, transferable, aRv);
|
||||
data->Write(aCx, aMessage, transferable, mIdentifier->uuid(),
|
||||
mRefMessageBodyService, aRv);
|
||||
|
||||
if (isTimelineRecording) {
|
||||
end = MakeUnique<MessagePortTimelineMarker>(
|
||||
@ -489,6 +492,10 @@ void MessagePort::CloseInternal(bool aSoftly) {
|
||||
mMessages.Clear();
|
||||
}
|
||||
|
||||
// Let's inform the RefMessageBodyService that any our shared messages are
|
||||
// now invalid.
|
||||
mRefMessageBodyService->ForgetPort(mIdentifier->uuid());
|
||||
|
||||
if (mState == eStateUnshippedEntangled) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(mUnshippedEntangledPort);
|
||||
|
||||
@ -657,6 +664,11 @@ void MessagePort::Disentangle() {
|
||||
messages);
|
||||
mActor->SendDisentangle(messages);
|
||||
}
|
||||
|
||||
// Let's inform the RefMessageBodyService that any our shared messages are
|
||||
// now invalid.
|
||||
mRefMessageBodyService->ForgetPort(mIdentifier->uuid());
|
||||
|
||||
// Only clear mMessages after the MessageData instances have gone out of scope
|
||||
// because they borrow mMessages' underlying JSStructuredCloneDatas.
|
||||
mMessages.Clear();
|
||||
|
@ -27,6 +27,7 @@ class MessagePortChild;
|
||||
struct PostMessageOptions;
|
||||
class PostMessageRunnable;
|
||||
class SharedMessagePortMessage;
|
||||
class RefMessageBodyService;
|
||||
class StrongWorkerRef;
|
||||
|
||||
// A class to hold a MessagePortIdentifier from
|
||||
@ -207,6 +208,8 @@ class MessagePort final : public DOMEventTargetHelper {
|
||||
|
||||
RefPtr<MessagePort> mUnshippedEntangledPort;
|
||||
|
||||
RefPtr<RefMessageBodyService> mRefMessageBodyService;
|
||||
|
||||
nsTArray<RefPtr<SharedMessagePortMessage>> mMessages;
|
||||
nsTArray<RefPtr<SharedMessagePortMessage>> mMessagesForTheOtherPort;
|
||||
|
||||
|
86
dom/messagechannel/RefMessageBodyService.cpp
Normal file
86
dom/messagechannel/RefMessageBodyService.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
/* -*- 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 "RefMessageBodyService.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
StaticMutex sRefMessageBodyServiceMutex;
|
||||
|
||||
// Raw pointer because the service is kept alive by MessagePorts.
|
||||
// See the CTOR and the DTOR of this object.
|
||||
RefMessageBodyService* sService;
|
||||
|
||||
// static
|
||||
already_AddRefed<RefMessageBodyService> RefMessageBodyService::GetOrCreate() {
|
||||
StaticMutexAutoLock lock(sRefMessageBodyServiceMutex);
|
||||
|
||||
RefPtr<RefMessageBodyService> service = GetOrCreateInternal(lock);
|
||||
return service.forget();
|
||||
}
|
||||
|
||||
// static
|
||||
RefMessageBodyService* RefMessageBodyService::GetOrCreateInternal(
|
||||
const StaticMutexAutoLock& aProofOfLock) {
|
||||
if (!sService) {
|
||||
sService = new RefMessageBodyService();
|
||||
}
|
||||
return sService;
|
||||
}
|
||||
|
||||
RefMessageBodyService::RefMessageBodyService() {
|
||||
MOZ_DIAGNOSTIC_ASSERT(sService == nullptr);
|
||||
}
|
||||
|
||||
RefMessageBodyService::~RefMessageBodyService() {
|
||||
MOZ_DIAGNOSTIC_ASSERT(sService == this);
|
||||
sService = nullptr;
|
||||
}
|
||||
|
||||
nsID RefMessageBodyService::Register(already_AddRefed<RefMessageBody> aBody,
|
||||
ErrorResult& aRv) {
|
||||
RefPtr<RefMessageBody> body = aBody;
|
||||
MOZ_ASSERT(body);
|
||||
|
||||
nsID uuid = {};
|
||||
aRv = nsContentUtils::GenerateUUIDInPlace(uuid);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nsID();
|
||||
}
|
||||
|
||||
StaticMutexAutoLock lock(sRefMessageBodyServiceMutex);
|
||||
GetOrCreateInternal(lock)->mMessages.Put(uuid, body);
|
||||
return uuid;
|
||||
}
|
||||
|
||||
already_AddRefed<RefMessageBody> RefMessageBodyService::Steal(nsID& aID) {
|
||||
StaticMutexAutoLock lock(sRefMessageBodyServiceMutex);
|
||||
if (!sService) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<RefMessageBody> body;
|
||||
sService->mMessages.Remove(aID, getter_AddRefs(body));
|
||||
|
||||
return body.forget();
|
||||
}
|
||||
|
||||
void RefMessageBodyService::ForgetPort(nsID& aPortID) {
|
||||
StaticMutexAutoLock lock(sRefMessageBodyServiceMutex);
|
||||
if (!sService) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto iter = sService->mMessages.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
if (iter.UserData()->PortID() == aPortID) {
|
||||
iter.Remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
62
dom/messagechannel/RefMessageBodyService.h
Normal file
62
dom/messagechannel/RefMessageBodyService.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#ifndef mozilla_dom_RefMessageBodyService_h
|
||||
#define mozilla_dom_RefMessageBodyService_h
|
||||
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/StructuredCloneHolder.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class RefMessageBody final {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefMessageBody)
|
||||
|
||||
RefMessageBody(nsID& aPortID,
|
||||
UniquePtr<ipc::StructuredCloneData>&& aCloneData)
|
||||
: mPortID(aPortID), mCloneData(std::move(aCloneData)) {}
|
||||
|
||||
const nsID& PortID() const { return mPortID; }
|
||||
|
||||
ipc::StructuredCloneData* CloneData() { return mCloneData.get(); }
|
||||
|
||||
private:
|
||||
~RefMessageBody() = default;
|
||||
|
||||
nsID mPortID;
|
||||
UniquePtr<ipc::StructuredCloneData> mCloneData;
|
||||
};
|
||||
|
||||
class RefMessageBodyService final {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefMessageBodyService)
|
||||
|
||||
static already_AddRefed<RefMessageBodyService> GetOrCreate();
|
||||
|
||||
void ForgetPort(nsID& aPortID);
|
||||
|
||||
nsID Register(already_AddRefed<RefMessageBody> aBody, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<RefMessageBody> Steal(nsID& aID);
|
||||
|
||||
private:
|
||||
RefMessageBodyService();
|
||||
~RefMessageBodyService();
|
||||
|
||||
static RefMessageBodyService* GetOrCreateInternal(
|
||||
const StaticMutexAutoLock& aProofOfLock);
|
||||
|
||||
nsRefPtrHashtable<nsIDHashKey, RefMessageBody> mMessages;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_RefMessageBodyService_h
|
@ -4,6 +4,7 @@
|
||||
* 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 "RefMessageBodyService.h"
|
||||
#include "SharedMessagePortMessage.h"
|
||||
#include "MessagePort.h"
|
||||
#include "MessagePortChild.h"
|
||||
@ -19,6 +20,62 @@ using namespace ipc;
|
||||
|
||||
namespace dom {
|
||||
|
||||
SharedMessagePortMessage::SharedMessagePortMessage() : mRefDataId({}) {}
|
||||
|
||||
void SharedMessagePortMessage::Write(
|
||||
JSContext* aCx, JS::Handle<JS::Value> aValue,
|
||||
JS::Handle<JS::Value> aTransfers, nsID& aPortID,
|
||||
RefMessageBodyService* aRefMessageBodyService, ErrorResult& aRv) {
|
||||
MOZ_ASSERT(!mCloneData && !mRefData);
|
||||
MOZ_ASSERT(aRefMessageBodyService);
|
||||
|
||||
mCloneData = MakeUnique<ipc::StructuredCloneData>(
|
||||
JS::StructuredCloneScope::UnknownDestination);
|
||||
mCloneData->Write(aCx, aValue, aTransfers, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mCloneData->CloneScope() == JS::StructuredCloneScope::DifferentProcess) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mCloneData->CloneScope() == JS::StructuredCloneScope::SameProcess);
|
||||
RefPtr<RefMessageBody> refData =
|
||||
new RefMessageBody(aPortID, std::move(mCloneData));
|
||||
|
||||
mRefDataId = aRefMessageBodyService->Register(refData.forget(), aRv);
|
||||
}
|
||||
|
||||
void SharedMessagePortMessage::Read(
|
||||
JSContext* aCx, JS::MutableHandle<JS::Value> aValue,
|
||||
RefMessageBodyService* aRefMessageBodyService, ErrorResult& aRv) {
|
||||
MOZ_ASSERT(aRefMessageBodyService);
|
||||
|
||||
if (mCloneData) {
|
||||
return mCloneData->Read(aCx, aValue, aRv);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mRefData);
|
||||
mRefData = aRefMessageBodyService->Steal(mRefDataId);
|
||||
if (!mRefData) {
|
||||
aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
mRefData->CloneData()->Read(aCx, aValue, aRv);
|
||||
}
|
||||
|
||||
bool SharedMessagePortMessage::TakeTransferredPortsAsSequence(
|
||||
Sequence<OwningNonNull<mozilla::dom::MessagePort>>& aPorts) {
|
||||
if (mCloneData) {
|
||||
return mCloneData->TakeTransferredPortsAsSequence(aPorts);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mRefData);
|
||||
return mRefData->CloneData()->TakeTransferredPortsAsSequence(aPorts);
|
||||
}
|
||||
|
||||
/* static */
|
||||
void SharedMessagePortMessage::FromSharedToMessagesChild(
|
||||
MessagePortChild* aActor,
|
||||
@ -34,18 +91,15 @@ void SharedMessagePortMessage::FromSharedToMessagesChild(
|
||||
for (auto& data : aData) {
|
||||
MessageData* message = aArray.AppendElement();
|
||||
|
||||
if (data->CloneScope() ==
|
||||
StructuredCloneHolder::StructuredCloneScope::DifferentProcess) {
|
||||
if (data->mCloneData) {
|
||||
ClonedMessageData clonedData;
|
||||
data->BuildClonedMessageDataForBackgroundChild(backgroundManager,
|
||||
clonedData);
|
||||
data->mCloneData->BuildClonedMessageDataForBackgroundChild(
|
||||
backgroundManager, clonedData);
|
||||
*message = clonedData;
|
||||
continue;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(data->CloneScope() ==
|
||||
StructuredCloneHolder::StructuredCloneScope::SameProcess);
|
||||
*message = RefMessageData(); // TODO
|
||||
*message = RefMessageData(data->mRefDataId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,10 +117,12 @@ bool SharedMessagePortMessage::FromMessagesToSharedChild(
|
||||
RefPtr<SharedMessagePortMessage> data = new SharedMessagePortMessage();
|
||||
|
||||
if (message.type() == MessageData::TClonedMessageData) {
|
||||
data->StealFromClonedMessageDataForBackgroundChild(message);
|
||||
data->mCloneData = MakeUnique<ipc::StructuredCloneData>(
|
||||
JS::StructuredCloneScope::UnknownDestination);
|
||||
data->mCloneData->StealFromClonedMessageDataForBackgroundChild(message);
|
||||
} else {
|
||||
MOZ_ASSERT(message.type() == MessageData::TRefMessageData);
|
||||
// TODO
|
||||
data->mRefDataId = message.get_RefMessageData().uuid();
|
||||
}
|
||||
|
||||
if (!aData.AppendElement(data, mozilla::fallible)) {
|
||||
@ -94,18 +150,15 @@ bool SharedMessagePortMessage::FromSharedToMessagesParent(
|
||||
for (auto& data : aData) {
|
||||
MessageData* message = aArray.AppendElement(mozilla::fallible);
|
||||
|
||||
if (data->CloneScope() ==
|
||||
StructuredCloneHolder::StructuredCloneScope::DifferentProcess) {
|
||||
if (data->mCloneData) {
|
||||
ClonedMessageData clonedData;
|
||||
data->BuildClonedMessageDataForBackgroundParent(backgroundManager,
|
||||
clonedData);
|
||||
data->mCloneData->BuildClonedMessageDataForBackgroundParent(
|
||||
backgroundManager, clonedData);
|
||||
*message = clonedData;
|
||||
continue;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(data->CloneScope() ==
|
||||
StructuredCloneHolder::StructuredCloneScope::SameProcess);
|
||||
*message = RefMessageData(); // TODO
|
||||
*message = RefMessageData(data->mRefDataId);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -125,10 +178,12 @@ bool SharedMessagePortMessage::FromMessagesToSharedParent(
|
||||
RefPtr<SharedMessagePortMessage> data = new SharedMessagePortMessage();
|
||||
|
||||
if (message.type() == MessageData::TClonedMessageData) {
|
||||
data->StealFromClonedMessageDataForBackgroundParent(message);
|
||||
data->mCloneData = MakeUnique<ipc::StructuredCloneData>(
|
||||
JS::StructuredCloneScope::UnknownDestination);
|
||||
data->mCloneData->StealFromClonedMessageDataForBackgroundParent(message);
|
||||
} else {
|
||||
MOZ_ASSERT(message.type() == MessageData::TRefMessageData);
|
||||
// TODO
|
||||
data->mRefDataId = message.get_RefMessageData().uuid();
|
||||
}
|
||||
|
||||
if (!aData.AppendElement(data, mozilla::fallible)) {
|
||||
|
@ -15,13 +15,14 @@ namespace dom {
|
||||
class MessagePortChild;
|
||||
class MessagePortMessage;
|
||||
class MessagePortParent;
|
||||
class RefMessageBody;
|
||||
class RefMessageBodyService;
|
||||
|
||||
class SharedMessagePortMessage final : public ipc::StructuredCloneData {
|
||||
class SharedMessagePortMessage final {
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(SharedMessagePortMessage)
|
||||
|
||||
SharedMessagePortMessage()
|
||||
: ipc::StructuredCloneData(StructuredCloneScope::UnknownDestination) {}
|
||||
SharedMessagePortMessage();
|
||||
|
||||
// Note that the populated MessageData borrows the underlying
|
||||
// JSStructuredCloneData from the SharedMessagePortMessage, so the caller is
|
||||
@ -49,8 +50,23 @@ class SharedMessagePortMessage final : public ipc::StructuredCloneData {
|
||||
nsTArray<MessageData>& aArray,
|
||||
FallibleTArray<RefPtr<SharedMessagePortMessage>>& aData);
|
||||
|
||||
void Read(JSContext* aCx, JS::MutableHandle<JS::Value> aValue,
|
||||
RefMessageBodyService* aRefMessageBodyService, ErrorResult& aRv);
|
||||
|
||||
void Write(JSContext* aCx, JS::Handle<JS::Value> aValue,
|
||||
JS::Handle<JS::Value> aTransfers, nsID& aPortID,
|
||||
RefMessageBodyService* aRefMessageBodyService, ErrorResult& aRv);
|
||||
|
||||
bool TakeTransferredPortsAsSequence(
|
||||
Sequence<OwningNonNull<mozilla::dom::MessagePort>>& aPorts);
|
||||
|
||||
private:
|
||||
~SharedMessagePortMessage() = default;
|
||||
|
||||
UniquePtr<ipc::StructuredCloneData> mCloneData;
|
||||
|
||||
RefPtr<RefMessageBody> mRefData;
|
||||
nsID mRefDataId;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -22,6 +22,7 @@ UNIFIED_SOURCES += [
|
||||
'MessagePortChild.cpp',
|
||||
'MessagePortParent.cpp',
|
||||
'MessagePortService.cpp',
|
||||
'RefMessageBodyService.cpp',
|
||||
'SharedMessagePortMessage.cpp',
|
||||
]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user