Files
sousa-gecko/dom/ipc/jsactor/JSProcessActorProtocol.cpp
T
Nika Layzell c51090b135 Bug 2052614 - Add a structured RemoteType representation. r=ipc-reviewers,necko-reviewers,geckoview-reviewers,extension-reviewers,media-playback-reviewers,webrtc-reviewers,places-reviewers,layout-reviewers,dom-worker-reviewers,ai-platform-reviewers,sandbox-reviewers,janerik,emilio,hiro,kershaw,bwc,asuth,mccr8,alwu,nordzilla,valentin,bobowen
Replace bare remote type strings in C++ process-selection plumbing with
a RemoteType type which stores the parsed kind, isolation URI, and
process selection attributes directly.

This preserves the existing serialized string form for IPC and JS-facing
APIs, while making native callers use explicit predicates and structured
fields instead of manually parsing remote type prefixes and suffixes.

No JS-exposed API for parsing or otherwise interpreting remote types are
currently exposed in this patch. My current expectation is that this
will likely look like a `nsIRemoteType` interface which wraps this
`RemoteType` value type, exposing helpful getters for JS callers.

Differential Revision: https://phabricator.services.mozilla.com/D310442
2026-08-31 23:49:43 +00:00

138 lines
4.5 KiB
C++

/* 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 "mozilla/dom/JSProcessActorProtocol.h"
#include "JSActorProtocolUtils.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/InProcessChild.h"
#include "mozilla/dom/JSActorBinding.h"
#include "mozilla/dom/JSProcessActorBinding.h"
#include "mozilla/dom/PContent.h"
#include "nsContentUtils.h"
namespace mozilla::dom {
NS_IMPL_CYCLE_COLLECTING_ADDREF(JSProcessActorProtocol)
NS_IMPL_CYCLE_COLLECTING_RELEASE(JSProcessActorProtocol)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(JSProcessActorProtocol)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION(JSProcessActorProtocol)
/* static */ already_AddRefed<JSProcessActorProtocol>
JSProcessActorProtocol::FromIPC(const JSProcessActorInfo& aInfo) {
MOZ_DIAGNOSTIC_ASSERT(XRE_IsContentProcess());
RefPtr<JSProcessActorProtocol> proto =
new JSProcessActorProtocol(aInfo.name());
JSActorProtocolUtils::FromIPCShared(proto, aInfo);
// Content processes aren't the parent process, so this flag is irrelevant and
// not propagated.
proto->mIncludeParent = false;
return proto.forget();
}
JSProcessActorInfo JSProcessActorProtocol::ToIPC() {
MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess());
JSProcessActorInfo info;
JSActorProtocolUtils::ToIPCShared(info, this);
return info;
}
already_AddRefed<JSProcessActorProtocol>
JSProcessActorProtocol::FromWebIDLOptions(const nsACString& aName,
const ProcessActorOptions& aOptions,
ErrorResult& aRv) {
MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess());
RefPtr<JSProcessActorProtocol> proto = new JSProcessActorProtocol(aName);
if (!JSActorProtocolUtils::FromWebIDLOptionsShared(proto, aOptions, aRv)) {
return nullptr;
}
proto->mIncludeParent = aOptions.mIncludeParent;
proto->mLoadInDevToolsLoader = aOptions.mLoadInDevToolsLoader;
return proto.forget();
}
NS_IMETHODIMP JSProcessActorProtocol::Observe(nsISupports* aSubject,
const char* aTopic,
const char16_t* aData) {
MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
RefPtr<JSActorManager> manager;
if (XRE_IsParentProcess()) {
manager = InProcessChild::Singleton();
} else {
manager = ContentChild::GetSingleton();
}
// Ensure our actor is present.
AutoJSAPI jsapi;
jsapi.Init();
RefPtr<JSActor> actor = manager->GetActor(jsapi.cx(), mName, IgnoreErrors());
if (!actor || NS_WARN_IF(!actor->GetWrapperPreserveColor())) {
return NS_OK;
}
// Build a observer callback.
JS::Rooted<JSObject*> global(jsapi.cx(),
JS::GetNonCCWObjectGlobal(actor->GetWrapper()));
RefPtr<MozObserverCallback> observerCallback =
new MozObserverCallback(actor->GetWrapper(), global, nullptr, nullptr);
observerCallback->Observe(aSubject, nsDependentCString(aTopic),
aData ? nsDependentString(aData) : VoidString());
return NS_OK;
}
void JSProcessActorProtocol::AddObservers() {
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
for (auto& topic : mChild.mObservers) {
// This makes the observer service hold an owning reference to the
// JSProcessActorProtocol. The JSWindowActorProtocol objects will be living
// for the full lifetime of the content process, thus the extra strong
// referencec doesn't have a negative impact.
os->AddObserver(this, topic.get(), false);
}
}
void JSProcessActorProtocol::RemoveObservers() {
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
for (auto& topic : mChild.mObservers) {
os->RemoveObserver(this, topic.get());
}
}
bool JSProcessActorProtocol::Matches(const RemoteType& aRemoteType,
ErrorResult& aRv) {
if (!mIncludeParent && aRemoteType.IsNotRemote()) {
aRv.ThrowNotSupportedError(nsPrintfCString(
"Process protocol '%s' doesn't match the parent process", mName.get()));
return false;
}
if (!RemoteTypeMatches(aRemoteType)) {
aRv.ThrowNotSupportedError(nsPrintfCString(
"Process protocol '%s' doesn't support remote type '%s'", mName.get(),
aRemoteType.Stringify().get()));
return false;
}
LogMatch(aRemoteType);
return true;
}
} // namespace mozilla::dom