author | Nika Layzell <nika@thelayzells.com> |
Wed, 08 Jul 2020 14:22:22 +0000 | |
changeset 539380 | d7810f45f0cbbf63ec61112e4d5c16433640775b |
parent 539379 | d3c935827ef7694b50f5b2d9fc2665d27f9c27c2 |
child 539381 | 5907260fa4688e06eb4b07982ed23fc2d476d8e3 |
push id | 37579 |
push user | dluca@mozilla.com |
push date | Wed, 08 Jul 2020 21:49:35 +0000 |
treeherder | mozilla-central@ee89deeb4fb6 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | kmag |
bugs | 1649477 |
milestone | 80.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -4291,25 +4291,21 @@ already_AddRefed<JSActor> ContentChild:: "mManager was already initialized once!"); actor->Init(aName, this); return actor.forget(); } IPCResult ContentChild::RecvRawMessage(const JSActorMessageMeta& aMeta, const ClonedMessageData& aData, const ClonedMessageData& aStack) { - RefPtr<JSProcessActorChild> actor; - GetActor(aMeta.actorName(), getter_AddRefs(actor)); - if (actor) { - StructuredCloneData data; - data.BorrowFromClonedMessageDataForChild(aData); - StructuredCloneData stack; - stack.BorrowFromClonedMessageDataForChild(aStack); - actor->ReceiveRawMessage(aMeta, std::move(data), std::move(stack)); - } + StructuredCloneData data; + data.BorrowFromClonedMessageDataForChild(aData); + StructuredCloneData stack; + stack.BorrowFromClonedMessageDataForChild(aStack); + ReceiveRawMessage(aMeta, std::move(data), std::move(stack)); return IPC_OK(); } NS_IMETHODIMP ContentChild::GetCanSend(bool* aCanSend) { *aCanSend = CanSend(); return NS_OK; }
--- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -6850,25 +6850,21 @@ NS_IMETHODIMP ContentParent::GetChildID( NS_IMETHODIMP ContentParent::GetOsPid(int32_t* aOut) { *aOut = Pid(); return NS_OK; } IPCResult ContentParent::RecvRawMessage(const JSActorMessageMeta& aMeta, const ClonedMessageData& aData, const ClonedMessageData& aStack) { - RefPtr<JSProcessActorParent> actor; - GetActor(aMeta.actorName(), getter_AddRefs(actor)); - if (actor) { - StructuredCloneData data; - data.BorrowFromClonedMessageDataForParent(aData); - StructuredCloneData stack; - stack.BorrowFromClonedMessageDataForParent(aStack); - actor->ReceiveRawMessage(aMeta, std::move(data), std::move(stack)); - } + StructuredCloneData data; + data.BorrowFromClonedMessageDataForParent(aData); + StructuredCloneData stack; + stack.BorrowFromClonedMessageDataForParent(aStack); + ReceiveRawMessage(aMeta, std::move(data), std::move(stack)); return IPC_OK(); } NS_IMETHODIMP ContentParent::GetActor(const nsACString& aName, JSProcessActorParent** retval) { ErrorResult error; RefPtr<JSProcessActorParent> actor = JSActorManager::GetActor(aName, error).downcast<JSProcessActorParent>();
--- a/dom/ipc/WindowGlobalChild.cpp +++ b/dom/ipc/WindowGlobalChild.cpp @@ -543,26 +543,16 @@ IPCResult WindowGlobalChild::RecvRawMess StructuredCloneData data; data.BorrowFromClonedMessageDataForChild(aData); StructuredCloneData stack; stack.BorrowFromClonedMessageDataForChild(aStack); ReceiveRawMessage(aMeta, std::move(data), std::move(stack)); return IPC_OK(); } -void WindowGlobalChild::ReceiveRawMessage(const JSActorMessageMeta& aMeta, - StructuredCloneData&& aData, - StructuredCloneData&& aStack) { - RefPtr<JSWindowActorChild> actor = - GetActor(aMeta.actorName(), IgnoreErrors()); - if (actor) { - actor->ReceiveRawMessage(aMeta, std::move(aData), std::move(aStack)); - } -} - void WindowGlobalChild::SetDocumentURI(nsIURI* aDocumentURI) { #ifdef MOZ_GECKO_PROFILER // Registers a DOM Window with the profiler. It re-registers the same Inner // Window ID with different URIs because when a Browsing context is first // loaded, the first url loaded in it will be about:blank. This call keeps the // first non-about:blank registration of window and discards the previous one. uint64_t embedderInnerWindowID = 0; if (BrowsingContext()->GetParent()) {
--- a/dom/ipc/WindowGlobalChild.h +++ b/dom/ipc/WindowGlobalChild.h @@ -84,20 +84,16 @@ class WindowGlobalChild final : public W // Get the other side of this actor if it is an in-process actor. Returns // |nullptr| if the actor has been torn down, or is not in-process. already_AddRefed<WindowGlobalParent> GetParentActor(); // Get this actor's manager if it is not an in-process actor. Returns // |nullptr| if the actor has been torn down, or is in-process. already_AddRefed<BrowserChild> GetBrowserChild(); - void ReceiveRawMessage(const JSActorMessageMeta& aMeta, - ipc::StructuredCloneData&& aData, - ipc::StructuredCloneData&& aStack); - // Get a JS actor object by name. already_AddRefed<JSWindowActorChild> GetActor(const nsACString& aName, ErrorResult& aRv); // Create and initialize the WindowGlobalChild object. static already_AddRefed<WindowGlobalChild> Create( nsGlobalWindowInner* aWindow); static already_AddRefed<WindowGlobalChild> CreateDisconnected(
--- a/dom/ipc/WindowGlobalParent.cpp +++ b/dom/ipc/WindowGlobalParent.cpp @@ -420,26 +420,16 @@ IPCResult WindowGlobalParent::RecvRawMes StructuredCloneData data; data.BorrowFromClonedMessageDataForParent(aData); StructuredCloneData stack; stack.BorrowFromClonedMessageDataForParent(aStack); ReceiveRawMessage(aMeta, std::move(data), std::move(stack)); return IPC_OK(); } -void WindowGlobalParent::ReceiveRawMessage(const JSActorMessageMeta& aMeta, - StructuredCloneData&& aData, - StructuredCloneData&& aStack) { - RefPtr<JSWindowActorParent> actor = - GetActor(aMeta.actorName(), IgnoreErrors()); - if (actor) { - actor->ReceiveRawMessage(aMeta, std::move(aData), std::move(aStack)); - } -} - const nsAString& WindowGlobalParent::GetRemoteType() { if (RefPtr<BrowserParent> browserParent = GetBrowserParent()) { return browserParent->Manager()->GetRemoteType(); } return VoidString(); }
--- a/dom/ipc/WindowGlobalParent.h +++ b/dom/ipc/WindowGlobalParent.h @@ -90,20 +90,16 @@ class WindowGlobalParent final : public ErrorResult& aRv); // Get this actor's manager if it is not an in-process actor. Returns // |nullptr| if the actor has been torn down, or is in-process. already_AddRefed<BrowserParent> GetBrowserParent(); ContentParent* GetContentParent(); - void ReceiveRawMessage(const JSActorMessageMeta& aMeta, - ipc::StructuredCloneData&& aData, - ipc::StructuredCloneData&& aStack); - // The principal of this WindowGlobal. This value will not change over the // lifetime of the WindowGlobal object, even to reflect changes in // |document.domain|. nsIPrincipal* DocumentPrincipal() { return mDocumentPrincipal; } nsIPrincipal* ContentBlockingAllowListPrincipal() { return mDocContentBlockingAllowListPrincipal; }
--- a/dom/ipc/jsactor/JSActor.cpp +++ b/dom/ipc/jsactor/JSActor.cpp @@ -8,16 +8,17 @@ #include "mozilla/dom/JSActorBinding.h" #include "mozilla/Attributes.h" #include "mozilla/Telemetry.h" #include "mozilla/dom/ClonedErrorHolder.h" #include "mozilla/dom/ClonedErrorHolderBinding.h" #include "mozilla/dom/DOMException.h" #include "mozilla/dom/DOMExceptionBinding.h" +#include "mozilla/dom/JSActorManager.h" #include "mozilla/dom/MessageManagerBinding.h" #include "mozilla/dom/PWindowGlobal.h" #include "mozilla/dom/Promise.h" #include "js/Promise.h" #include "xpcprivate.h" #include "nsASCIIMask.h" #include "nsICrashReporter.h" @@ -44,51 +45,29 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(JSActor) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWrappedJS) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingQueries) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(JSActor) -// RAII class to ensure that, if we crash while handling a message, the -// crash will be annotated with the name of the actor and the message. -struct MOZ_RAII AutoAnnotateMessageInCaseOfCrash { - AutoAnnotateMessageInCaseOfCrash(const nsCString& aActorName, - const nsCString& aMessageName) { - CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::JSActorName, - aActorName); - CrashReporter::AnnotateCrashReport( - CrashReporter::Annotation::JSActorMessage, aMessageName); - } - ~AutoAnnotateMessageInCaseOfCrash() { - CrashReporter::RemoveCrashReportAnnotation( - CrashReporter::Annotation::JSActorMessage); - CrashReporter::RemoveCrashReportAnnotation( - CrashReporter::Annotation::JSActorName); - } -}; - JSActor::JSActor(nsISupports* aGlobal) { mGlobal = do_QueryInterface(aGlobal); if (!mGlobal) { mGlobal = xpc::NativeGlobal(xpc::PrivilegedJunkScope()); } } void JSActor::StartDestroy() { - AutoAnnotateMessageInCaseOfCrash guard(/* aActorName = */ mName, - "<WillDestroy>"_ns); InvokeCallback(CallbackFunction::WillDestroy); mCanSend = false; } void JSActor::AfterDestroy() { - AutoAnnotateMessageInCaseOfCrash guard(/* aActorName = */ mName, - "<DidDestroy>"_ns); mCanSend = false; // Take our queries out, in case somehow rejecting promises can trigger // additions or removals. nsRefPtrHashtable<nsUint64HashKey, Promise> pendingQueries; mPendingQueries.SwapElements(pendingQueries); for (auto& entry : pendingQueries) { entry.GetData()->MaybeReject(NS_ERROR_NOT_AVAILABLE); @@ -254,79 +233,16 @@ already_AddRefed<Promise> JSActor::SendQ meta.kind() = JSActorMessageKind::Query; mPendingQueries.Put(meta.queryId(), RefPtr{promise}); SendRawMessage(meta, std::move(data), CaptureJSStack(aCx), aRv); return promise.forget(); } -#define CHILD_DIAGNOSTIC_ASSERT(test, msg) \ - do { \ - if (XRE_IsParentProcess()) { \ - MOZ_ASSERT(test, msg); \ - } else { \ - MOZ_DIAGNOSTIC_ASSERT(test, msg); \ - } \ - } while (0) - -void JSActor::ReceiveRawMessage(const JSActorMessageMeta& aMetadata, - ipc::StructuredCloneData&& aData, - ipc::StructuredCloneData&& aStack) { - MOZ_ASSERT(nsContentUtils::IsSafeToRunScript()); - AutoAnnotateMessageInCaseOfCrash guard( - /* aActorName = */ mName, - NS_LossyConvertUTF16toASCII(aMetadata.messageName())); - - AutoEntryScript aes(GetParentObject(), "JSActor message handler"); - JSContext* cx = aes.cx(); - - // Read the message into a JS object from IPC. - ErrorResult error; - JS::Rooted<JS::Value> data(cx); - aData.Read(cx, &data, error); - if (NS_WARN_IF(error.Failed())) { - CHILD_DIAGNOSTIC_ASSERT(false, "Should not receive non-decodable data"); - MOZ_ALWAYS_TRUE(error.MaybeSetPendingException(cx)); - return; - } - - JS::Rooted<JSObject*> stack(cx); - Maybe<JS::AutoSetAsyncStackForNewCalls> stackSetter; - { - JS::Rooted<JS::Value> stackVal(cx); - aStack.Read(cx, &stackVal, IgnoreErrors()); - if (stackVal.isObject()) { - stack = &stackVal.toObject(); - if (!js::IsSavedFrame(stack)) { - CHILD_DIAGNOSTIC_ASSERT(false, "Stack must be a SavedFrame object"); - return; - } - stackSetter.emplace(cx, stack, "JSActor query"); - } - } - - switch (aMetadata.kind()) { - case JSActorMessageKind::QueryResolve: - case JSActorMessageKind::QueryReject: - ReceiveQueryReply(cx, aMetadata, data, error); - break; - - case JSActorMessageKind::Message: - case JSActorMessageKind::Query: - ReceiveMessageOrQuery(cx, aMetadata, data, error); - break; - - default: - MOZ_ASSERT_UNREACHABLE(); - } - - Unused << error.MaybeSetPendingException(cx); -} - void JSActor::ReceiveMessageOrQuery(JSContext* aCx, const JSActorMessageMeta& aMetadata, JS::Handle<JS::Value> aData, ErrorResult& aRv) { // The argument which we want to pass to IPC. RootedDictionary<ReceiveMessageArgument> argument(aCx); argument.mTarget = this; argument.mName = aMetadata.messageName(); @@ -399,16 +315,32 @@ void JSActor::ReceiveQueryReply(JSContex if (aMetadata.kind() == JSActorMessageKind::QueryResolve) { promise->MaybeResolve(data); } else { promise->MaybeReject(data); } } +void JSActor::SendRawMessageInProcess(const JSActorMessageMeta& aMeta, + ipc::StructuredCloneData&& aData, + ipc::StructuredCloneData&& aStack, + OtherSideCallback&& aGetOtherSide) { + MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess()); + NS_DispatchToMainThread(NS_NewRunnableFunction( + "JSActor Async Message", + [aMeta, data{std::move(aData)}, stack{std::move(aStack)}, + getOtherSide{std::move(aGetOtherSide)}]() mutable { + if (RefPtr<JSActorManager> otherSide = getOtherSide()) { + otherSide->ReceiveRawMessage(aMeta, std::move(data), + std::move(stack)); + } + })); +} + // Native handler for our generated promise which is used to handle Queries and // send the reply when their promises have been resolved. JSActor::QueryHandler::QueryHandler(JSActor* aActor, const JSActorMessageMeta& aMetadata, Promise* aPromise) : mActor(aActor), mPromise(aPromise), mMessageName(aMetadata.messageName()),
--- a/dom/ipc/jsactor/JSActor.h +++ b/dom/ipc/jsactor/JSActor.h @@ -48,36 +48,39 @@ class JSActor : public nsISupports, publ void SendAsyncMessage(JSContext* aCx, const nsAString& aMessageName, JS::Handle<JS::Value> aObj, ErrorResult& aRv); already_AddRefed<Promise> SendQuery(JSContext* aCx, const nsAString& aMessageName, JS::Handle<JS::Value> aObj, ErrorResult& aRv); - void ReceiveRawMessage(const JSActorMessageMeta& aMetadata, - ipc::StructuredCloneData&& aData, - ipc::StructuredCloneData&& aStack); - nsIGlobalObject* GetParentObject() const { return mGlobal; }; protected: // Send the message described by the structured clone data |aData|, and the // message metadata |aMetadata|. The underlying transport should call the // |ReceiveMessage| method on the other side asynchronously. virtual void SendRawMessage(const JSActorMessageMeta& aMetadata, ipc::StructuredCloneData&& aData, ipc::StructuredCloneData&& aStack, ErrorResult& aRv) = 0; // Check if a message is so large that IPC will probably crash if we try to // send it. If it is too large, record telemetry about the message. static bool AllowMessage(const JSActorMessageMeta& aMetadata, size_t aDataLength); + // Helper method to send an in-process raw message. + using OtherSideCallback = std::function<already_AddRefed<JSActorManager>()>; + static void SendRawMessageInProcess(const JSActorMessageMeta& aMeta, + ipc::StructuredCloneData&& aData, + ipc::StructuredCloneData&& aStack, + OtherSideCallback&& aGetOtherSide); + virtual ~JSActor() = default; void SetName(const nsACString& aName); bool CanSend() const { return mCanSend; } void StartDestroy(); void AfterDestroy(); @@ -89,20 +92,21 @@ class JSActor : public nsISupports, publ private: friend class JSActorManager; friend class ::nsQueryActorChild; // for QueryInterfaceActor friend class ::nsQueryActorParent; // for QueryInterfaceActor nsresult QueryInterfaceActor(const nsIID& aIID, void** aPtr); + // Called by JSActorManager when they receive raw message data destined for + // this actor. void ReceiveMessageOrQuery(JSContext* aCx, const JSActorMessageMeta& aMetadata, JS::Handle<JS::Value> aData, ErrorResult& aRv); - void ReceiveQueryReply(JSContext* aCx, const JSActorMessageMeta& aMetadata, JS::Handle<JS::Value> aData, ErrorResult& aRv); // Helper object used while processing query messages to send the final reply // message. class QueryHandler final : public PromiseNativeHandler { public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS
--- a/dom/ipc/jsactor/JSActorManager.cpp +++ b/dom/ipc/jsactor/JSActorManager.cpp @@ -72,19 +72,18 @@ already_AddRefed<JSActor> JSActorManager nsAutoCString ctorName(aName); ctorName.Append(isParent ? "Parent"_ns : "Child"_ns); if (!JS_GetProperty(cx, exports, ctorName.get(), &ctor)) { aRv.NoteJSContextException(cx); return nullptr; } if (NS_WARN_IF(!ctor.isObject())) { - aRv.ThrowNotFoundError( - nsPrintfCString("Could not find actor constructor '%s'", - PromiseFlatCString(ctorName).get())); + aRv.ThrowNotFoundError(nsPrintfCString( + "Could not find actor constructor '%s'", ctorName.get())); return nullptr; } // Invoke the constructor loaded from the module. if (!JS::Construct(cx, ctor, JS::HandleValueArray::empty(), &actorObj)) { aRv.NoteJSContextException(cx); return nullptr; } @@ -94,36 +93,124 @@ already_AddRefed<JSActor> JSActorManager RefPtr<JSActor> actor = InitJSActor(actorObj, aName, aRv); if (aRv.Failed()) { return nullptr; } mJSActors.Put(aName, RefPtr{actor}); return actor.forget(); } +#define CHILD_DIAGNOSTIC_ASSERT(test, msg) \ + do { \ + if (XRE_IsParentProcess()) { \ + MOZ_ASSERT(test, msg); \ + } else { \ + MOZ_DIAGNOSTIC_ASSERT(test, msg); \ + } \ + } while (0) + +void JSActorManager::ReceiveRawMessage(const JSActorMessageMeta& aMetadata, + ipc::StructuredCloneData&& aData, + ipc::StructuredCloneData&& aStack) { + MOZ_ASSERT(nsContentUtils::IsSafeToRunScript()); + + CrashReporter::AutoAnnotateCrashReport autoActorName( + CrashReporter::Annotation::JSActorName, aMetadata.actorName()); + CrashReporter::AutoAnnotateCrashReport autoMessageName( + CrashReporter::Annotation::JSActorMessage, + NS_LossyConvertUTF16toASCII(aMetadata.messageName())); + + // We're going to be running JS. Enter the privileged junk realm so we can set + // up our JS state correctly. + AutoEntryScript aes(xpc::PrivilegedJunkScope(), "JSActor message handler"); + JSContext* cx = aes.cx(); + + // Ensure any errors reported to `error` are set on the scope, so they're + // reported. + ErrorResult error; + auto autoSetException = + MakeScopeExit([&] { Unused << error.MaybeSetPendingException(cx); }); + + // If an async stack was provided, set up our async stack state. + JS::Rooted<JSObject*> stack(cx); + Maybe<JS::AutoSetAsyncStackForNewCalls> stackSetter; + { + JS::Rooted<JS::Value> stackVal(cx); + aStack.Read(cx, &stackVal, error); + if (error.Failed()) { + return; + } + + if (stackVal.isObject()) { + stack = &stackVal.toObject(); + if (!js::IsSavedFrame(stack)) { + CHILD_DIAGNOSTIC_ASSERT(false, "Stack must be a SavedFrame object"); + error.ThrowDataError("Actor async stack must be a SavedFrame object"); + return; + } + stackSetter.emplace(cx, stack, "JSActor query"); + } + } + + RefPtr<JSActor> actor = GetActor(aMetadata.actorName(), error); + if (error.Failed()) { + return; + } + + JS::Rooted<JS::Value> data(cx); + aData.Read(cx, &data, error); + if (error.Failed()) { + CHILD_DIAGNOSTIC_ASSERT(false, "Should not receive non-decodable data"); + return; + } + + switch (aMetadata.kind()) { + case JSActorMessageKind::QueryResolve: + case JSActorMessageKind::QueryReject: + actor->ReceiveQueryReply(cx, aMetadata, data, error); + break; + + case JSActorMessageKind::Message: + case JSActorMessageKind::Query: + actor->ReceiveMessageOrQuery(cx, aMetadata, data, error); + break; + + default: + MOZ_ASSERT_UNREACHABLE(); + } +} + void JSActorManager::JSActorWillDestroy() { MOZ_ASSERT(nsContentUtils::IsSafeToRunScript()); + CrashReporter::AutoAnnotateCrashReport autoMessageName( + CrashReporter::Annotation::JSActorMessage, "<WillDestroy>"_ns); // Make a copy so that we can avoid potential iterator invalidation when // calling the user-provided Destroy() methods. nsTArray<RefPtr<JSActor>> actors(mJSActors.Count()); for (auto& entry : mJSActors) { actors.AppendElement(entry.GetData()); } for (auto& actor : actors) { + CrashReporter::AutoAnnotateCrashReport autoActorName( + CrashReporter::Annotation::JSActorName, actor->Name()); actor->StartDestroy(); } } void JSActorManager::JSActorDidDestroy() { MOZ_ASSERT(nsContentUtils::IsSafeToRunScript()); + CrashReporter::AutoAnnotateCrashReport autoMessageName( + CrashReporter::Annotation::JSActorMessage, "<DidDestroy>"_ns); // Swap the table with `mJSActors` so that we don't invalidate it while // iterating. nsRefPtrHashtable<nsCStringHashKey, JSActor> actors; mJSActors.SwapElements(actors); for (auto& entry : actors) { + CrashReporter::AutoAnnotateCrashReport autoActorName( + CrashReporter::Annotation::JSActorName, entry.GetData()->Name()); entry.GetData()->AfterDestroy(); } } } // namespace dom } // namespace mozilla
--- a/dom/ipc/jsactor/JSActorManager.h +++ b/dom/ipc/jsactor/JSActorManager.h @@ -27,16 +27,23 @@ class JSActorManager : public nsISupport /** * Get or create an actor by it's name. * * Will return an error if the actor fails to be constructed, or `nullptr` if * actor creation was vetoed by a constraint. */ already_AddRefed<JSActor> GetActor(const nsACString& aName, ErrorResult& aRv); + /** + * Handle receiving a raw message from the other side. + */ + void ReceiveRawMessage(const JSActorMessageMeta& aMetadata, + ipc::StructuredCloneData&& aData, + ipc::StructuredCloneData&& aStack); + protected: /** * Lifecycle methods which will fire the `willDestroy` and `didDestroy` * methods on relevant actors. */ void JSActorWillDestroy(); void JSActorDidDestroy();
--- a/dom/ipc/jsactor/JSProcessActorChild.cpp +++ b/dom/ipc/jsactor/JSProcessActorChild.cpp @@ -23,49 +23,16 @@ NS_INTERFACE_MAP_END_INHERITING(JSActor) NS_IMPL_ADDREF_INHERITED(JSProcessActorChild, JSActor) NS_IMPL_RELEASE_INHERITED(JSProcessActorChild, JSActor) JSObject* JSProcessActorChild::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { return JSProcessActorChild_Binding::Wrap(aCx, this, aGivenProto); } -namespace { - -class AsyncMessageToProcessParent : public Runnable { - public: - AsyncMessageToProcessParent(const JSActorMessageMeta& aMetadata, - ipc::StructuredCloneData&& aData, - ipc::StructuredCloneData&& aStack) - : mozilla::Runnable("InProcessParent::HandleAsyncMessage"), - mMetadata(aMetadata), - mData(std::move(aData)), - mStack(std::move(aStack)) {} - - NS_IMETHOD Run() override { - MOZ_ASSERT(NS_IsMainThread(), "Should be called on the main thread."); - if (auto* parent = InProcessParent::Singleton()) { - RefPtr<JSProcessActorParent> actor; - parent->GetActor(mMetadata.actorName(), getter_AddRefs(actor)); - if (actor) { - actor->ReceiveRawMessage(mMetadata, std::move(mData), - std::move(mStack)); - } - } - return NS_OK; - } - - private: - JSActorMessageMeta mMetadata; - ipc::StructuredCloneData mData; - ipc::StructuredCloneData mStack; -}; - -} // namespace - void JSProcessActorChild::SendRawMessage(const JSActorMessageMeta& aMeta, ipc::StructuredCloneData&& aData, ipc::StructuredCloneData&& aStack, ErrorResult& aRv) { if (NS_WARN_IF(!CanSend() || !mManager || !mManager->GetCanSend())) { aRv.ThrowInvalidStateError("JSProcessActorChild cannot send at the moment"); return; } @@ -78,19 +45,19 @@ void JSProcessActorChild::SendRawMessage PromiseFlatCString(aMeta.actorName()).get())); return; } // If the parent side is in the same process, we have a PInProcess manager, // and can dispatch the message directly to the event loop. ContentChild* contentChild = mManager->AsContentChild(); if (!contentChild) { - MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess()); - NS_DispatchToMainThread(MakeAndAddRef<AsyncMessageToProcessParent>( - aMeta, std::move(aData), std::move(aStack))); + SendRawMessageInProcess(aMeta, std::move(aData), std::move(aStack), []() { + return do_AddRef(InProcessParent::Singleton()); + }); return; } ClonedMessageData msgData; ClonedMessageData stackData; if (NS_WARN_IF( !aData.BuildClonedMessageDataForChild(contentChild, msgData)) || NS_WARN_IF(
--- a/dom/ipc/jsactor/JSProcessActorParent.cpp +++ b/dom/ipc/jsactor/JSProcessActorParent.cpp @@ -34,49 +34,16 @@ void JSProcessActorParent::Init(const ns SetName(aName); mManager = aManager; InvokeCallback(CallbackFunction::ActorCreated); } JSProcessActorParent::~JSProcessActorParent() { MOZ_ASSERT(!mManager); } -namespace { - -class AsyncMessageToProcessChild : public Runnable { - public: - AsyncMessageToProcessChild(const JSActorMessageMeta& aMetadata, - ipc::StructuredCloneData&& aData, - ipc::StructuredCloneData&& aStack) - : mozilla::Runnable("InProcessChild::HandleAsyncMessage"), - mMetadata(aMetadata), - mData(std::move(aData)), - mStack(std::move(aStack)) {} - - NS_IMETHOD Run() override { - MOZ_ASSERT(NS_IsMainThread(), "Should be called on the main thread."); - if (auto* child = InProcessChild::Singleton()) { - RefPtr<JSProcessActorChild> actor; - child->GetActor(mMetadata.actorName(), getter_AddRefs(actor)); - if (actor) { - actor->ReceiveRawMessage(mMetadata, std::move(mData), - std::move(mStack)); - } - } - return NS_OK; - } - - private: - JSActorMessageMeta mMetadata; - ipc::StructuredCloneData mData; - ipc::StructuredCloneData mStack; -}; - -} // namespace - void JSProcessActorParent::SendRawMessage(const JSActorMessageMeta& aMeta, ipc::StructuredCloneData&& aData, ipc::StructuredCloneData&& aStack, ErrorResult& aRv) { if (NS_WARN_IF(!CanSend() || !mManager || !mManager->GetCanSend())) { aRv.ThrowInvalidStateError( nsPrintfCString("Actor '%s' cannot send message '%s' during shutdown.", PromiseFlatCString(aMeta.actorName()).get(), @@ -92,18 +59,19 @@ void JSProcessActorParent::SendRawMessag NS_ConvertUTF16toUTF8(aMeta.messageName()).get())); return; } // If the parent side is in the same process, we have a PInProcess manager, // and can dispatch the message directly to the event loop. ContentParent* contentParent = mManager->AsContentParent(); if (!contentParent) { - NS_DispatchToMainThread(MakeAndAddRef<AsyncMessageToProcessChild>( - aMeta, std::move(aData), std::move(aStack))); + SendRawMessageInProcess(aMeta, std::move(aData), std::move(aStack), []() { + return do_AddRef(InProcessChild::Singleton()); + }); return; } // Cross-process case - send data over ContentParent to other side. ClonedMessageData msgData; ClonedMessageData stackData; if (NS_WARN_IF( !aData.BuildClonedMessageDataForParent(contentParent, msgData)) ||
--- a/dom/ipc/jsactor/JSWindowActorChild.cpp +++ b/dom/ipc/jsactor/JSWindowActorChild.cpp @@ -30,61 +30,29 @@ void JSWindowActorChild::Init(const nsAC WindowGlobalChild* aManager) { MOZ_ASSERT(!mManager, "Cannot Init() a JSWindowActorChild twice!"); SetName(aName); mManager = aManager; InvokeCallback(CallbackFunction::ActorCreated); } -namespace { - -class AsyncMessageToParent : public Runnable { - public: - AsyncMessageToParent(const JSActorMessageMeta& aMetadata, - ipc::StructuredCloneData&& aData, - ipc::StructuredCloneData&& aStack, - WindowGlobalChild* aManager) - : mozilla::Runnable("WindowGlobalParent::HandleAsyncMessage"), - mMetadata(aMetadata), - mData(std::move(aData)), - mStack(std::move(aStack)), - mManager(aManager) {} - - NS_IMETHOD Run() override { - MOZ_ASSERT(NS_IsMainThread(), "Should be called on the main thread."); - RefPtr<WindowGlobalParent> parent = mManager->GetParentActor(); - if (parent) { - parent->ReceiveRawMessage(mMetadata, std::move(mData), std::move(mStack)); - } - return NS_OK; - } - - private: - JSActorMessageMeta mMetadata; - ipc::StructuredCloneData mData; - ipc::StructuredCloneData mStack; - RefPtr<WindowGlobalChild> mManager; -}; - -} // anonymous namespace - void JSWindowActorChild::SendRawMessage(const JSActorMessageMeta& aMeta, ipc::StructuredCloneData&& aData, ipc::StructuredCloneData&& aStack, ErrorResult& aRv) { if (NS_WARN_IF(!CanSend() || !mManager || !mManager->CanSend())) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return; } if (mManager->IsInProcess()) { - nsCOMPtr<nsIRunnable> runnable = new AsyncMessageToParent( - aMeta, std::move(aData), std::move(aStack), mManager); - NS_DispatchToMainThread(runnable.forget()); + SendRawMessageInProcess( + aMeta, std::move(aData), std::move(aStack), + [manager{mManager}]() { return manager->GetParentActor(); }); return; } if (NS_WARN_IF( !AllowMessage(aMeta, aData.DataLength() + aStack.DataLength()))) { aRv.Throw(NS_ERROR_UNEXPECTED); return; }
--- a/dom/ipc/jsactor/JSWindowActorParent.cpp +++ b/dom/ipc/jsactor/JSWindowActorParent.cpp @@ -69,19 +69,19 @@ void JSWindowActorParent::SendRawMessage ipc::StructuredCloneData&& aStack, ErrorResult& aRv) { if (NS_WARN_IF(!CanSend() || !mManager || !mManager->CanSend())) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return; } if (mManager->IsInProcess()) { - nsCOMPtr<nsIRunnable> runnable = new AsyncMessageToChild( - aMeta, std::move(aData), std::move(aStack), mManager); - NS_DispatchToMainThread(runnable.forget()); + SendRawMessageInProcess( + aMeta, std::move(aData), std::move(aStack), + [manager{mManager}]() { return manager->GetChildActor(); }); return; } if (NS_WARN_IF( !AllowMessage(aMeta, aData.DataLength() + aStack.DataLength()))) { aRv.Throw(NS_ERROR_UNEXPECTED); return; }