1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "MessagePort.h"
9 #include "MessageEvent.h"
10 #include "MessagePortChild.h"
11 #include "mozilla/dom/BlobBinding.h"
12 #include "mozilla/dom/Event.h"
13 #include "mozilla/dom/File.h"
14 #include "mozilla/dom/MessageChannel.h"
15 #include "mozilla/dom/MessageEventBinding.h"
16 #include "mozilla/dom/MessagePortBinding.h"
17 #include "mozilla/dom/MessagePortChild.h"
18 #include "mozilla/dom/PMessagePort.h"
19 #include "mozilla/dom/RootedDictionary.h"
20 #include "mozilla/dom/ScriptSettings.h"
21 #include "mozilla/dom/StructuredCloneTags.h"
22 #include "mozilla/dom/WorkerCommon.h"
23 #include "mozilla/dom/WorkerRef.h"
24 #include "mozilla/dom/WorkerScope.h"
25 #include "mozilla/ipc/BackgroundChild.h"
26 #include "mozilla/dom/RefMessageBodyService.h"
27 #include "mozilla/dom/SharedMessageBody.h"
28 #include "mozilla/ipc/PBackgroundChild.h"
29 #include "mozilla/ScopeExit.h"
30 #include "mozilla/Unused.h"
31 #include "nsContentUtils.h"
32 #include "nsPresContext.h"
38 namespace mozilla::dom
{
40 void UniqueMessagePortId::ForceClose() {
41 if (!mIdentifier
.neutered()) {
42 MessagePort::ForceClose(mIdentifier
);
43 mIdentifier
.neutered() = true;
47 class PostMessageRunnable final
: public CancelableRunnable
{
48 friend class MessagePort
;
51 PostMessageRunnable(MessagePort
* aPort
, SharedMessageBody
* aData
)
52 : CancelableRunnable("dom::PostMessageRunnable"),
61 NS_ASSERT_OWNINGTHREAD(Runnable
);
63 // The port can be cycle collected while this runnable is pending in
69 MOZ_ASSERT(mPort
->mPostMessageRunnable
== this);
73 // We must check if we were waiting for this message in order to shutdown
75 mPort
->UpdateMustKeepAlive();
77 mPort
->mPostMessageRunnable
= nullptr;
83 nsresult
Cancel() override
{
84 NS_ASSERT_OWNINGTHREAD(Runnable
);
92 void DispatchMessage() const {
93 NS_ASSERT_OWNINGTHREAD(Runnable
);
95 if (NS_FAILED(mPort
->CheckCurrentGlobalCorrectness())) {
99 nsCOMPtr
<nsIGlobalObject
> globalObject
= mPort
->GetParentObject();
102 if (!globalObject
|| !jsapi
.Init(globalObject
)) {
103 NS_WARNING("Failed to initialize AutoJSAPI object.");
107 JSContext
* cx
= jsapi
.cx();
109 IgnoredErrorResult rv
;
110 JS::Rooted
<JS::Value
> value(cx
);
112 mData
->Read(cx
, &value
, mPort
->mRefMessageBodyService
,
113 SharedMessageBody::ReadMethod::StealRefMessageBody
, rv
);
115 if (NS_WARN_IF(rv
.Failed())) {
116 JS_ClearPendingException(cx
);
117 mPort
->DispatchError();
122 RefPtr
<MessageEvent
> event
=
123 new MessageEvent(mPort
->GetOwnerWindow(), nullptr, nullptr);
125 Sequence
<OwningNonNull
<MessagePort
>> ports
;
126 if (!mData
->TakeTransferredPortsAsSequence(ports
)) {
127 mPort
->DispatchError();
131 event
->InitMessageEvent(nullptr, u
"message"_ns
, CanBubble::eNo
,
132 Cancelable::eNo
, value
, u
""_ns
, u
""_ns
, nullptr,
134 event
->SetTrusted(true);
136 mPort
->DispatchEvent(*event
);
140 ~PostMessageRunnable() = default;
142 RefPtr
<MessagePort
> mPort
;
143 RefPtr
<SharedMessageBody
> mData
;
146 NS_IMPL_CYCLE_COLLECTION_CLASS(MessagePort
)
148 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MessagePort
,
149 DOMEventTargetHelper
)
150 if (tmp
->mPostMessageRunnable
) {
151 NS_IMPL_CYCLE_COLLECTION_UNLINK(mPostMessageRunnable
->mPort
);
154 NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessagesForTheOtherPort
);
157 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
159 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MessagePort
,
160 DOMEventTargetHelper
)
161 if (tmp
->mPostMessageRunnable
) {
162 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPostMessageRunnable
->mPort
);
165 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mUnshippedEntangledPort
);
166 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
168 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MessagePort
)
169 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper
)
171 NS_IMPL_ADDREF_INHERITED(MessagePort
, DOMEventTargetHelper
)
172 NS_IMPL_RELEASE_INHERITED(MessagePort
, DOMEventTargetHelper
)
174 MessagePort::MessagePort(nsIGlobalObject
* aGlobal
, State aState
)
175 : DOMEventTargetHelper(aGlobal
),
176 mRefMessageBodyService(RefMessageBodyService::GetOrCreate()),
178 mMessageQueueEnabled(false),
180 mHasBeenTransferredOrClosed(false) {
183 mIdentifier
= MakeUnique
<MessagePortIdentifier
>();
184 mIdentifier
->neutered() = true;
185 mIdentifier
->sequenceId() = 0;
188 MessagePort::~MessagePort() {
192 mActor
->SetPort(nullptr);
195 MOZ_ASSERT(!mWorkerRef
);
199 already_AddRefed
<MessagePort
> MessagePort::Create(nsIGlobalObject
* aGlobal
,
201 const nsID
& aDestinationUUID
,
205 RefPtr
<MessagePort
> mp
=
206 new MessagePort(aGlobal
, eStateInitializingUnshippedEntangled
);
207 mp
->Initialize(aUUID
, aDestinationUUID
, 1 /* 0 is an invalid sequence ID */,
208 false /* Neutered */, aRv
);
213 already_AddRefed
<MessagePort
> MessagePort::Create(
214 nsIGlobalObject
* aGlobal
, UniqueMessagePortId
& aIdentifier
,
218 RefPtr
<MessagePort
> mp
= new MessagePort(aGlobal
, eStateEntangling
);
219 mp
->Initialize(aIdentifier
.uuid(), aIdentifier
.destinationUuid(),
220 aIdentifier
.sequenceId(), aIdentifier
.neutered(), aRv
);
221 aIdentifier
.neutered() = true;
225 void MessagePort::UnshippedEntangle(RefPtr
<MessagePort
>& aEntangledPort
) {
226 MOZ_DIAGNOSTIC_ASSERT(aEntangledPort
);
227 MOZ_DIAGNOSTIC_ASSERT(!mUnshippedEntangledPort
);
229 if (mState
== eStateInitializingUnshippedEntangled
) {
230 mUnshippedEntangledPort
= aEntangledPort
;
231 mState
= eStateUnshippedEntangled
;
233 MOZ_ASSERT_UNREACHABLE("Should not have been called.");
237 void MessagePort::Initialize(const nsID
& aUUID
, const nsID
& aDestinationUUID
,
238 uint32_t aSequenceID
, bool aNeutered
,
240 MOZ_ASSERT(mIdentifier
);
241 mIdentifier
->uuid() = aUUID
;
242 mIdentifier
->destinationUuid() = aDestinationUUID
;
243 mIdentifier
->sequenceId() = aSequenceID
;
246 // If this port is neutered we don't want to keep it alive artificially nor
247 // we want to add listeners or WorkerRefs.
248 mState
= eStateDisentangled
;
252 if (mState
== eStateEntangling
) {
253 if (!ConnectToPBackground()) {
254 aRv
.Throw(NS_ERROR_FAILURE
);
258 MOZ_ASSERT(mState
== eStateInitializingUnshippedEntangled
);
261 // The port has to keep itself alive until it's entangled.
262 UpdateMustKeepAlive();
264 if (WorkerPrivate
* workerPrivate
= GetCurrentThreadWorkerPrivate()) {
265 RefPtr
<MessagePort
> self
= this;
267 // When the callback is executed, we cannot process messages anymore because
268 // we cannot dispatch new runnables. Let's force a Close().
269 RefPtr
<StrongWorkerRef
> strongWorkerRef
= StrongWorkerRef::Create(
270 workerPrivate
, "MessagePort", [self
]() { self
->CloseForced(); });
271 if (NS_WARN_IF(!strongWorkerRef
)) {
272 // The worker is shutting down.
274 aRv
.Throw(NS_ERROR_FAILURE
);
278 MOZ_ASSERT(!mWorkerRef
);
279 mWorkerRef
= std::move(strongWorkerRef
);
283 JSObject
* MessagePort::WrapObject(JSContext
* aCx
,
284 JS::Handle
<JSObject
*> aGivenProto
) {
285 return MessagePort_Binding::Wrap(aCx
, this, aGivenProto
);
288 void MessagePort::PostMessage(JSContext
* aCx
, JS::Handle
<JS::Value
> aMessage
,
289 const Sequence
<JSObject
*>& aTransferable
,
291 // We *must* clone the data here, or the JS::Value could be modified
294 // Here we want to check if the transerable object list contains
296 for (uint32_t i
= 0; i
< aTransferable
.Length(); ++i
) {
297 JS::Rooted
<JSObject
*> object(aCx
, aTransferable
[i
]);
302 MessagePort
* port
= nullptr;
303 nsresult rv
= UNWRAP_OBJECT(MessagePort
, &object
, port
);
304 if (NS_SUCCEEDED(rv
) && port
== this) {
305 aRv
.Throw(NS_ERROR_DOM_DATA_CLONE_ERR
);
310 JS::Rooted
<JS::Value
> transferable(aCx
, JS::UndefinedValue());
312 aRv
= nsContentUtils::CreateJSValueFromSequenceOfObject(aCx
, aTransferable
,
314 if (NS_WARN_IF(aRv
.Failed())) {
318 Maybe
<nsID
> agentClusterId
;
319 nsCOMPtr
<nsIGlobalObject
> global
= GetOwnerGlobal();
321 agentClusterId
= global
->GetAgentClusterId();
324 RefPtr
<SharedMessageBody
> data
= new SharedMessageBody(
325 StructuredCloneHolder::TransferringSupported
, agentClusterId
);
327 data
->Write(aCx
, aMessage
, transferable
, mIdentifier
->uuid(),
328 mRefMessageBodyService
, aRv
);
330 if (NS_WARN_IF(aRv
.Failed())) {
334 // This message has to be ignored.
335 if (mState
> eStateEntangled
) {
339 if (mState
== eStateInitializingUnshippedEntangled
) {
340 MOZ_ASSERT_UNREACHABLE(
341 "Should be eStateUnshippedEntangled or eStateDisentangled by now.");
345 // If we are unshipped we are connected to the other port on the same thread.
346 if (mState
== eStateUnshippedEntangled
) {
347 MOZ_DIAGNOSTIC_ASSERT(mUnshippedEntangledPort
);
348 mUnshippedEntangledPort
->mMessages
.AppendElement(data
);
349 mUnshippedEntangledPort
->Dispatch();
353 // Not entangled yet, but already closed/disentangled.
354 if (mState
== eStateEntanglingForDisentangle
||
355 mState
== eStateEntanglingForClose
) {
359 RemoveDocFromBFCache();
361 // Not entangled yet.
362 if (mState
== eStateEntangling
) {
363 mMessagesForTheOtherPort
.AppendElement(data
);
368 MOZ_ASSERT(mMessagesForTheOtherPort
.IsEmpty());
370 AutoTArray
<RefPtr
<SharedMessageBody
>, 1> array
;
371 array
.AppendElement(data
);
373 AutoTArray
<MessageData
, 1> messages
;
374 // note: `messages` will borrow the underlying buffer, but this is okay
375 // because reverse destruction order means `messages` will be destroyed prior
376 // to `array`/`data`.
377 SharedMessageBody::FromSharedToMessagesChild(mActor
->Manager(), array
,
379 mActor
->SendPostMessages(messages
);
382 void MessagePort::PostMessage(JSContext
* aCx
, JS::Handle
<JS::Value
> aMessage
,
383 const StructuredSerializeOptions
& aOptions
,
385 PostMessage(aCx
, aMessage
, aOptions
.mTransfer
, aRv
);
388 void MessagePort::Start() {
389 if (mMessageQueueEnabled
) {
393 mMessageQueueEnabled
= true;
397 void MessagePort::Dispatch() {
398 if (!mMessageQueueEnabled
|| mMessages
.IsEmpty() || mPostMessageRunnable
) {
403 case eStateInitializingUnshippedEntangled
:
404 MOZ_ASSERT_UNREACHABLE(
405 "Should be eStateUnshippedEntangled or eStateDisentangled by now.");
408 case eStateUnshippedEntangled
:
409 // Everything is fine here. We have messages because the other
410 // port populates our queue directly.
413 case eStateEntangling
:
414 // Everything is fine here as well. We have messages because the other
415 // port populated our queue directly when we were in the
416 // eStateUnshippedEntangled state.
419 case eStateEntanglingForDisentangle
:
420 // Here we don't want to ship messages because these messages must be
421 // delivered by the cloned version of this one. They will be sent in the
422 // SendDisentangle().
425 case eStateEntanglingForClose
:
426 // We still want to deliver messages if we are closing. These messages
427 // are here from the previous eStateUnshippedEntangled state.
430 case eStateEntangled
:
431 // This port is up and running.
434 case eStateDisentangling
:
435 // If we are in the process to disentangle the port, we cannot dispatch
436 // messages. They will be sent to the cloned version of this port via
437 // SendDisentangle();
440 case eStateDisentangled
:
441 MOZ_CRASH("This cannot happen.");
442 // It cannot happen because Disentangle should take off all the pending
446 case eStateDisentangledForClose
:
447 // If we are here is because the port has been closed. We can still
448 // process the pending messages.
452 RefPtr
<SharedMessageBody
> data
= mMessages
.ElementAt(0);
453 mMessages
.RemoveElementAt(0);
455 mPostMessageRunnable
= new PostMessageRunnable(this, data
);
456 MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(mPostMessageRunnable
));
459 void MessagePort::Close() {
460 mHasBeenTransferredOrClosed
= true;
461 CloseInternal(true /* aSoftly */);
464 void MessagePort::CloseForced() { CloseInternal(false /* aSoftly */); }
466 void MessagePort::CloseInternal(bool aSoftly
) {
467 // If we have some messages to send but we don't want a 'soft' close, we have
468 // to flush them now.
473 // Let's inform the RefMessageBodyService that any our shared messages are
475 mRefMessageBodyService
->ForgetPort(mIdentifier
->uuid());
477 if (mState
== eStateInitializingUnshippedEntangled
) {
478 // We can end up here if we failed to create our WorkerRef. Our Create
479 // method will end up returning an error and MessageChannel will not bother
480 // creating our counterpart port or calling UnshippedEntangle (and we
482 mState
= eStateDisentangledForClose
;
484 UpdateMustKeepAlive();
488 if (mState
== eStateUnshippedEntangled
) {
489 MOZ_DIAGNOSTIC_ASSERT(mUnshippedEntangledPort
);
491 // This avoids loops.
492 RefPtr
<MessagePort
> port
= std::move(mUnshippedEntangledPort
);
494 mState
= eStateDisentangledForClose
;
495 port
->CloseInternal(aSoftly
);
497 UpdateMustKeepAlive();
501 // Not entangled yet, we have to wait.
502 if (mState
== eStateEntangling
) {
503 mState
= eStateEntanglingForClose
;
507 // Not entangled but already cloned or closed
508 if (mState
== eStateEntanglingForDisentangle
||
509 mState
== eStateEntanglingForClose
) {
513 // Maybe we were already closing the port but softly. In this case we call
514 // UpdateMustKeepAlive() to consider the empty pending message queue.
515 if (mState
== eStateDisentangledForClose
&& !aSoftly
) {
516 UpdateMustKeepAlive();
520 if (mState
> eStateEntangled
) {
524 // We don't care about stopping the sending of messages because from now all
525 // the incoming messages will be ignored.
526 mState
= eStateDisentangledForClose
;
531 mActor
->SetPort(nullptr);
534 UpdateMustKeepAlive();
537 EventHandlerNonNull
* MessagePort::GetOnmessage() {
538 return GetEventHandler(nsGkAtoms::onmessage
);
541 void MessagePort::SetOnmessage(EventHandlerNonNull
* aCallback
) {
542 SetEventHandler(nsGkAtoms::onmessage
, aCallback
);
544 // When using onmessage, the call to start() is implied.
548 // This method is called when the PMessagePortChild actor is entangled to
549 // another actor. It receives a list of messages to be dispatch. It can be that
550 // we were waiting for this entangling step in order to disentangle the port or
552 void MessagePort::Entangled(nsTArray
<MessageData
>& aMessages
) {
553 MOZ_ASSERT(mState
== eStateEntangling
||
554 mState
== eStateEntanglingForDisentangle
||
555 mState
== eStateEntanglingForClose
);
557 State oldState
= mState
;
558 mState
= eStateEntangled
;
560 // If we have pending messages, these have to be sent.
561 if (!mMessagesForTheOtherPort
.IsEmpty()) {
563 nsTArray
<MessageData
> messages
;
564 SharedMessageBody::FromSharedToMessagesChild(
565 mActor
->Manager(), mMessagesForTheOtherPort
, messages
);
566 mActor
->SendPostMessages(messages
);
568 // Because `messages` borrow the underlying JSStructuredCloneData buffers,
569 // only clear after `messages` have gone out of scope.
570 mMessagesForTheOtherPort
.Clear();
573 // We must convert the messages into SharedMessageBodys to avoid leaks.
574 FallibleTArray
<RefPtr
<SharedMessageBody
>> data
;
576 !SharedMessageBody::FromMessagesToSharedChild(aMessages
, data
))) {
581 // If the next step is to close the port, we do it ignoring the received
583 if (oldState
== eStateEntanglingForClose
) {
588 mMessages
.AppendElements(data
);
590 // We were waiting for the entangling callback in order to disentangle this
591 // port immediately after.
592 if (oldState
== eStateEntanglingForDisentangle
) {
593 StartDisentangling();
600 void MessagePort::StartDisentangling() {
602 MOZ_ASSERT(mState
== eStateEntangled
);
604 mState
= eStateDisentangling
;
606 // Sending this message we communicate to the parent actor that we don't want
607 // to receive any new messages. It is possible that a message has been
608 // already sent but not received yet. So we have to collect all of them and
609 // we send them in the SendDispatch() request.
610 mActor
->SendStopSendingData();
613 void MessagePort::MessagesReceived(nsTArray
<MessageData
>& aMessages
) {
614 MOZ_ASSERT(mState
== eStateEntangled
|| mState
== eStateDisentangling
||
615 // This last step can happen only if Close() has been called
616 // manually. At this point SendClose() is sent but we can still
617 // receive something until the Closing request is processed.
618 mState
== eStateDisentangledForClose
);
619 MOZ_ASSERT(mMessagesForTheOtherPort
.IsEmpty());
621 RemoveDocFromBFCache();
623 FallibleTArray
<RefPtr
<SharedMessageBody
>> data
;
625 !SharedMessageBody::FromMessagesToSharedChild(aMessages
, data
))) {
630 mMessages
.AppendElements(data
);
632 if (mState
== eStateEntangled
) {
637 void MessagePort::StopSendingDataConfirmed() {
638 MOZ_ASSERT(mState
== eStateDisentangling
);
644 void MessagePort::Disentangle() {
645 MOZ_ASSERT(mState
== eStateDisentangling
);
648 mState
= eStateDisentangled
;
651 nsTArray
<MessageData
> messages
;
652 SharedMessageBody::FromSharedToMessagesChild(mActor
->Manager(), mMessages
,
654 mActor
->SendDisentangle(messages
);
657 // Let's inform the RefMessageBodyService that any our shared messages are
659 mRefMessageBodyService
->ForgetPort(mIdentifier
->uuid());
661 // Only clear mMessages after the MessageData instances have gone out of scope
662 // because they borrow mMessages' underlying JSStructuredCloneDatas.
665 mActor
->SetPort(nullptr);
668 UpdateMustKeepAlive();
671 void MessagePort::CloneAndDisentangle(UniqueMessagePortId
& aIdentifier
) {
672 MOZ_ASSERT(mIdentifier
);
673 MOZ_ASSERT(!mHasBeenTransferredOrClosed
);
675 mHasBeenTransferredOrClosed
= true;
677 // We can clone a port that has already been transfered. In this case, on the
678 // otherside will have a neutered port. Here we set neutered to true so that
679 // we are safe in case a early return.
680 aIdentifier
.neutered() = true;
682 if (mState
> eStateEntangled
) {
686 // We already have a 'next step'. We have to consider this port as already
687 // cloned/closed/disentangled.
688 if (mState
== eStateEntanglingForDisentangle
||
689 mState
== eStateEntanglingForClose
) {
693 aIdentifier
.uuid() = mIdentifier
->uuid();
694 aIdentifier
.destinationUuid() = mIdentifier
->destinationUuid();
695 aIdentifier
.sequenceId() = mIdentifier
->sequenceId() + 1;
696 aIdentifier
.neutered() = false;
698 // We have to entangle first.
699 if (mState
== eStateUnshippedEntangled
) {
700 MOZ_ASSERT(mUnshippedEntangledPort
);
701 MOZ_ASSERT(mMessagesForTheOtherPort
.IsEmpty());
703 RefPtr
<MessagePort
> port
= std::move(mUnshippedEntangledPort
);
705 // Disconnect the entangled port and connect it to PBackground.
706 if (!port
->ConnectToPBackground()) {
707 // We are probably shutting down. We cannot proceed.
708 mState
= eStateDisentangled
;
709 UpdateMustKeepAlive();
713 // In this case, we don't need to be connected to the PBackground service.
714 if (mMessages
.IsEmpty()) {
715 aIdentifier
.sequenceId() = mIdentifier
->sequenceId();
717 mState
= eStateDisentangled
;
718 UpdateMustKeepAlive();
722 // Register this component to PBackground.
723 if (!ConnectToPBackground()) {
724 // We are probably shutting down. We cannot proceed.
728 mState
= eStateEntanglingForDisentangle
;
732 // Not entangled yet, we have to wait.
733 if (mState
== eStateEntangling
) {
734 mState
= eStateEntanglingForDisentangle
;
738 MOZ_ASSERT(mState
== eStateEntangled
);
739 StartDisentangling();
742 void MessagePort::Closed() {
743 if (mState
>= eStateDisentangled
) {
747 mState
= eStateDisentangledForClose
;
750 mActor
->SetPort(nullptr);
754 UpdateMustKeepAlive();
757 bool MessagePort::ConnectToPBackground() {
758 RefPtr
<MessagePort
> self
= this;
759 auto raii
= MakeScopeExit([self
] {
760 self
->mState
= eStateDisentangled
;
761 self
->UpdateMustKeepAlive();
764 mozilla::ipc::PBackgroundChild
* actorChild
=
765 mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread();
766 if (NS_WARN_IF(!actorChild
)) {
770 PMessagePortChild
* actor
= actorChild
->SendPMessagePortConstructor(
771 mIdentifier
->uuid(), mIdentifier
->destinationUuid(),
772 mIdentifier
->sequenceId());
773 if (NS_WARN_IF(!actor
)) {
777 mActor
= static_cast<MessagePortChild
*>(actor
);
780 mActor
->SetPort(this);
781 mState
= eStateEntangling
;
787 void MessagePort::UpdateMustKeepAlive() {
788 if (mState
>= eStateDisentangled
&& mMessages
.IsEmpty() && mIsKeptAlive
) {
789 mIsKeptAlive
= false;
791 // The DTOR of this WorkerRef will release the worker for us.
792 mWorkerRef
= nullptr;
798 if (mState
< eStateDisentangled
&& !mIsKeptAlive
) {
804 void MessagePort::DisconnectFromOwner() {
806 DOMEventTargetHelper::DisconnectFromOwner();
809 void MessagePort::RemoveDocFromBFCache() {
810 if (!NS_IsMainThread()) {
814 if (nsPIDOMWindowInner
* window
= GetOwnerWindow()) {
815 window
->RemoveFromBFCacheSync();
820 void MessagePort::ForceClose(const MessagePortIdentifier
& aIdentifier
) {
821 mozilla::ipc::PBackgroundChild
* actorChild
=
822 mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread();
823 if (NS_WARN_IF(!actorChild
)) {
824 MOZ_CRASH("Failed to create a PBackgroundChild actor!");
827 Unused
<< actorChild
->SendMessagePortForceClose(aIdentifier
.uuid(),
828 aIdentifier
.destinationUuid(),
829 aIdentifier
.sequenceId());
832 void MessagePort::DispatchError() {
833 nsCOMPtr
<nsIGlobalObject
> globalObject
= GetParentObject();
836 if (!globalObject
|| !jsapi
.Init(globalObject
)) {
837 NS_WARNING("Failed to initialize AutoJSAPI object.");
841 RootedDictionary
<MessageEventInit
> init(jsapi
.cx());
842 init
.mBubbles
= false;
843 init
.mCancelable
= false;
845 RefPtr
<Event
> event
=
846 MessageEvent::Constructor(this, u
"messageerror"_ns
, init
);
847 event
->SetTrusted(true);
849 DispatchEvent(*event
);
852 } // namespace mozilla::dom