/* -*- 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/. */
/* static */ void ChromeUtils::ReleaseAssert(GlobalObject& aGlobal, bool aCondition, const nsAString& aMessage) { // If the condition didn't fail, which is the likely case, immediately return. if (MOZ_LIKELY(aCondition)) { return;
}
// Extract the current stack from the JS runtime to embed in the crash reason.
nsAutoCString filename;
uint32_t lineNo = 0;
if (opt.mCaptureStack) { // If we will be capturing a stack, change the category of the // ChromeUtils.addProfilerMarker label automatically added by the webidl // binding from DOM to PROFILER so that this function doesn't appear in // the marker stack.
JSContext* cx = aGlobal.Context();
ProfilingStack* stack = js::GetContextProfilingStackIfEnabled(cx); if (MOZ_LIKELY(stack)) {
uint32_t sp = stack->stackPointer; if (MOZ_LIKELY(sp > 0)) {
js::ProfilingStackFrame& frame = stack->frames[sp - 1]; if (frame.isLabelFrame() && "ChromeUtils"_ns.Equals(frame.label()) && "addProfilerMarker"_ns.Equals(frame.dynamicString())) {
frame.setLabelCategory(JS::ProfilingCategoryPair::PROFILER);
}
}
}
/* static */ bool ChromeUtils::IsISOStyleDate(GlobalObject& aGlobal, const nsACString& aStr) { // aStr is a UTF-8 string, however we can cast to JS::Latin1Chars // because JS::IsISOStyleDate handles ASCII only return JS::IsISOStyleDate(aGlobal.Context(),
JS::Latin1Chars(aStr.Data(), aStr.Length()));
}
{ // cx represents our current Realm, so it makes sense to use it for the // CheckedUnwrapDynamic call. We do want CheckedUnwrapDynamic, in case // someone is shallow-cloning a Window.
JS::Rooted<JSObject*> obj(cx, js::CheckedUnwrapDynamic(aObj, cx)); if (!obj) {
js::ReportAccessDenied(cx); return;
}
if (js::IsScriptedProxy(obj)) {
JS_ReportErrorASCII(cx, "Shallow cloning a proxy object is not allowed"); return;
}
JS::Rooted<Maybe<JS::PropertyDescriptor>> desc(cx);
JS::Rooted<JS::PropertyKey> id(cx); for (jsid idVal : ids) {
id = idVal; if (!JS_GetOwnPropertyDescriptorById(cx, obj, id, &desc)) { continue;
} if (desc.isNothing() || desc->isAccessorDescriptor()) { continue;
}
valuesIds.infallibleAppend(id);
values.infallibleAppend(desc->value());
}
}
JS::Rooted<JSObject*> obj(cx);
{
Maybe<JSAutoRealm> ar; if (aTarget) { // Our target could be anything, so we want CheckedUnwrapDynamic here. // "cx" represents the current Realm when we were called from bindings, so // we can just use that.
JS::Rooted<JSObject*> target(cx, js::CheckedUnwrapDynamic(aTarget, cx)); if (!target) {
js::ReportAccessDenied(cx); return;
}
ar.emplace(cx, target);
}
obj = JS_NewPlainObject(cx); if (!obj) { return;
}
JS::Rooted<JS::Value> value(cx);
JS::Rooted<JS::PropertyKey> id(cx); for (uint32_t i = 0; i < valuesIds.length(); i++) {
id = valuesIds[i];
value = values[i];
// MOZ_CAN_RUN_SCRIPT_BOUNDARY until Runnable::Run is MOZ_CAN_RUN_SCRIPT. // See bug 1535398.
MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD Run() override { if (mCallback) {
CancelTimer();
auto deadline = mDeadline - TimeStamp::ProcessCreation();
ErrorResult rv;
RefPtr<IdleDeadline> idleDeadline = new IdleDeadline(mParent, mTimedOut, deadline.ToMilliseconds());
if (mozJSModuleLoader::IsSharedSystemGlobal(global)) { return mozJSModuleLoader::Get();
} if (mozJSModuleLoader::IsDevToolsLoaderGlobal(global)) { return mozJSModuleLoader::GetOrCreateDevToolsLoader(aCx);
}
if (loader::NonSharedGlobalSyncModuleLoaderScope::IsActive()) {
mozJSModuleLoader* moduleloader =
loader::NonSharedGlobalSyncModuleLoaderScope::ActiveLoader();
if (!moduleloader->IsLoaderGlobal(global->GetGlobalJSObject())) {
JS_ReportErrorASCII(aCx, "global: \"current\" option cannot be used for " "different global while other importESModule " "with global: \"current\" is on the stack"); return nullptr;
}
return moduleloader;
}
RefPtr targetModuleLoader = global->GetModuleLoader(aCx); if (!targetModuleLoader) { // Sandbox without associated window returns nullptr for GetModuleLoader.
JS_ReportErrorASCII(aCx, "No ModuleLoader found for the current context"); return nullptr;
}
if (targetModuleLoader->HasFetchingModules()) { if (!NS_IsMainThread()) {
JS_ReportErrorASCII(aCx, "ChromeUtils.importESModule cannot be used in worker " "when there is ongoing dynamic import"); return nullptr;
}
if (!mozilla::SpinEventLoopUntil( "importESModule for current global"_ns, [&]() -> bool { return !targetModuleLoader->HasFetchingModules();
})) {
JS_ReportErrorASCII(aCx, "Failed to wait for ongoing module requests"); return nullptr;
}
}
if (NS_IsMainThread()) {
nsCOMPtr<nsIGlobalObject> global =
do_QueryInterface(aGlobal.GetAsSupports());
if (mozJSModuleLoader::IsDevToolsLoaderGlobal(global) &&
!aOptions.mGlobal.WasPassed()) {
JS_ReportErrorASCII(aCx, "ChromeUtils.importESModule: global option is " "required in DevTools distinct global"); returnfalse;
}
}
if (!JS_WrapObject(cx, &moduleNamespace)) {
aRv.Throw(NS_ERROR_FAILURE); return;
}
aRetval.set(moduleNamespace);
if (maybeSyncLoaderScope) {
maybeSyncLoaderScope->Finish();
}
}
// An integer encoding for ImportESModuleOptionsDictionary, to pass the value // to the lazy getters. class EncodedOptions { public: explicit EncodedOptions(const ImportESModuleOptionsDictionary& aOptions) { if (aOptions.mGlobal.WasPassed()) {
mValue = uint32_t(aOptions.mGlobal.Value()) + 1;
} else {
mValue = 0;
}
}
// The property id of the getter. // Used by all lazy getters. staticconst size_t SLOT_ID = 0;
// The URI of the module to import. // Used by ChromeUtils.defineESModuleGetters. staticconst size_t SLOT_URI = 1;
// An array object that contians values for PARAM_INDEX_TARGET and // PARAM_INDEX_LAMBDA. // Used by ChromeUtils.defineLazyGetter. staticconst size_t SLOT_PARAMS = 1;
// The EncodedOptions value. // Used by ChromeUtils.defineESModuleGetters. staticconst size_t SLOT_OPTIONS = 2;
JS::Rooted<JS::Value> paramsVal(
aCx, js::GetFunctionNativeReserved(callee, SLOT_PARAMS)); if (paramsVal.isUndefined()) {
args.rval().setUndefined(); returntrue;
} // Avoid calling the lambda multiple times, in case of: // * the getter function is retrieved from property descriptor and called // * the lambda gets the property again // * the getter function throws and accessed again
js::SetFunctionNativeReserved(callee, SLOT_PARAMS, JS::UndefinedHandleValue);
JS::Rooted<JS::PropertyKey> funId(aCx); if (id.isAtom()) {
funId = id;
} else { // Don't care int and symbol cases.
funId = JS::PropertyKey::NonIntAtom(JS_GetEmptyString(aCx));
}
rv = thirdPartyUtil->IsThirdPartyURI(topLevelURI, resourceURI,
&foreignResource); if (NS_FAILED(rv)) { // we fallback to assuming the resource is foreign if there is an error
foreignResource = true;
fallback = true;
}
} else { // Assume we have a foreign resource if the resource was not provided
foreignResource = true;
fallback = true;
}
// aForeignContext is whether or not this is a foreign context. // foreignResource is whether or not the resource is cross-site to the top // level. So we need to validate that a false foreign context doesn't have a // same-site resource. That is impossible! if (aForeignContext.WasPassed() && !aForeignContext.Value() &&
foreignResource && !fallback) {
aPartitionKey.Truncate();
aRv.Throw(nsresult::NS_ERROR_INVALID_ARG); return;
}
if (NS_WARN_IF(!aPrincipal)) {
MOZ_LOG(gMlsLog, LogLevel::Error, ("Principal is null"));
aRv.Throw(NS_ERROR_FAILURE); return;
}
// Get the profile directory
nsCOMPtr<nsIFile> file;
aRv = NS_GetSpecialDirectory("ProfD", getter_AddRefs(file)); if (NS_WARN_IF(aRv.Failed())) {
MOZ_LOG(gMlsLog, LogLevel::Error, ("Failed to get profile directory"));
aRv.Throw(NS_ERROR_FAILURE); return;
}
// Append the 'mls' directory
aRv = file->AppendNative("mls"_ns); if (NS_WARN_IF(aRv.Failed())) {
MOZ_LOG(gMlsLog, LogLevel::Error,
("Failed to append 'mls' to directory path"));
aRv.Throw(NS_ERROR_FAILURE); return;
}
bool exists;
aRv = file->Exists(&exists); if (NS_WARN_IF(aRv.Failed())) {
MOZ_LOG(gMlsLog, LogLevel::Error,
("Failed to check if 'mls' directory exists"));
aRv.Throw(NS_ERROR_FAILURE); return;
}
// If the 'mls' directory does not exist, we exit early if (!exists) {
MOZ_LOG(gMlsLog, LogLevel::Error, ("'mls' directory does not exist")); return;
}
// Get the storage origin key
nsAutoCString originKey;
aRv = aPrincipal->GetStorageOriginKey(originKey); if (NS_WARN_IF(aRv.Failed())) {
MOZ_LOG(gMlsLog, LogLevel::Error, ("Failed to get storage origin key"));
aRv.Throw(NS_ERROR_FAILURE); return;
}
// Get the origin attributes suffix
nsAutoCString originAttrSuffix;
aRv = aPrincipal->GetOriginSuffix(originAttrSuffix); if (NS_WARN_IF(aRv.Failed())) {
MOZ_LOG(gMlsLog, LogLevel::Error,
("Failed to get origin attributes suffix"));
aRv.Throw(NS_ERROR_FAILURE); return;
}
// Construct the full origin key
nsAutoCString fullOriginKey = originKey + originAttrSuffix;
// We append the full origin key to the file path
aRv = file->AppendNative(fullOriginKey); if (NS_WARN_IF(aRv.Failed())) {
MOZ_LOG(gMlsLog, LogLevel::Error,
("Failed to append full origin key to the file path"));
aRv.Throw(NS_ERROR_FAILURE); return;
}
// Remove the directory recursively
aRv = file->Remove(/* recursive */ true); if (NS_WARN_IF(aRv.Failed())) {
MOZ_LOG(gMlsLog, LogLevel::Error,
("Failed to remove : %s", file->HumanReadablePath().get()));
aRv.Throw(NS_ERROR_FAILURE); return;
}
MOZ_LOG(gMlsLog, LogLevel::Debug,
("Successfully cleared MLS state for principal"));
}
// Get the profile directory
nsCOMPtr<nsIFile> file;
aRv = NS_GetSpecialDirectory("ProfD", getter_AddRefs(file)); if (NS_WARN_IF(aRv.Failed())) {
MOZ_LOG(gMlsLog, LogLevel::Error, ("Failed to get profile directory"));
aRv.Throw(NS_ERROR_FAILURE); return;
}
// Append the 'mls' directory
aRv = file->AppendNative("mls"_ns); if (NS_WARN_IF(aRv.Failed())) {
MOZ_LOG(gMlsLog, LogLevel::Error,
("Failed to append 'mls' to directory path"));
aRv.Throw(NS_ERROR_FAILURE); return;
}
bool exists;
aRv = file->Exists(&exists); if (NS_WARN_IF(aRv.Failed())) {
MOZ_LOG(gMlsLog, LogLevel::Error,
("Failed to check if 'mls' directory exists"));
aRv.Throw(NS_ERROR_FAILURE); return;
}
// If the 'mls' directory does not exist, we exit early if (!exists) {
MOZ_LOG(gMlsLog, LogLevel::Error, ("'mls' directory does not exist")); return;
}
// Check if the schemeless site is empty if (NS_WARN_IF(aSchemelessSite.IsEmpty())) {
MOZ_LOG(gMlsLog, LogLevel::Error, ("Schemeless site is empty"));
aRv.Throw(NS_ERROR_INVALID_ARG); return;
}
// Site pattern
OriginAttributesPattern pattern(aPattern);
// Partition pattern // This pattern is used to (additionally) clear state partitioned under // aSchemelessSite.
OriginAttributesPattern partitionPattern = pattern;
partitionPattern.mPartitionKeyPattern.Construct();
partitionPattern.mPartitionKeyPattern.Value().mBaseDomain.Construct(
NS_ConvertUTF8toUTF16(aSchemelessSite));
// Reverse the base domain using the existing function
nsAutoCString targetReversedBaseDomain(aSchemelessSite);
std::reverse(targetReversedBaseDomain.BeginWriting(),
targetReversedBaseDomain.EndWriting());
MOZ_LOG(gMlsLog, LogLevel::Debug,
("Reversed base domain: %s", targetReversedBaseDomain.get()));
// Enumerate files in the 'mls' directory
nsCOMPtr<nsIDirectoryEnumerator> dirEnum;
aRv = file->GetDirectoryEntries(getter_AddRefs(dirEnum)); if (NS_WARN_IF(aRv.Failed())) {
MOZ_LOG(gMlsLog, LogLevel::Error,
("Failed to get directory entries in 'mls' directory"));
aRv.Throw(NS_ERROR_FAILURE); return;
}
// Iterate through all entries in the directory
nsCOMPtr<nsIFile> entry; while (NS_SUCCEEDED(dirEnum->GetNextFile(getter_AddRefs(entry))) && entry) {
nsAutoCString entryName;
aRv = entry->GetNativeLeafName(entryName); if (NS_WARN_IF(aRv.Failed())) {
MOZ_LOG(gMlsLog, LogLevel::Error,
("Failed to get native leaf name for entry")); continue;
}
// Find the position of .sqlite.enc or .key in the entry name
int32_t sqliteEncPos = entryName.RFind(".sqlite.enc");
int32_t keyPos = entryName.RFind(".key");
// Remove the .sqlite.enc or .key suffix from the entryName if (sqliteEncPos != kNotFound) {
entryName.SetLength(sqliteEncPos);
} elseif (keyPos != kNotFound) {
entryName.SetLength(keyPos);
}
// Decode the entry name
nsAutoCString decodedEntryName;
aRv = mozilla::Base64Decode(entryName, decodedEntryName); if (NS_WARN_IF(aRv.Failed())) {
MOZ_LOG(gMlsLog, LogLevel::Debug,
("Failed to decode entry name: %s", entryName.get())); continue;
}
// Find the origin attributes suffix in the entry name by taking the // value of the entry name after the ^ separator
int32_t separatorPos = decodedEntryName.FindChar('^');
// We extract the origin attributes suffix from the entry name
nsAutoCString originSuffix;
originSuffix.Assign(Substring(decodedEntryName, separatorPos));
// Populate the origin attributes from the suffix
OriginAttributes originAttrs; if (NS_WARN_IF(!originAttrs.PopulateFromSuffix(originSuffix))) {
MOZ_LOG(gMlsLog, LogLevel::Error,
("Failed to populate origin attributes from suffix")); continue;
}
// Check if the entry name starts with the reversed base domain if (StringBeginsWith(decodedEntryName, targetReversedBaseDomain)) {
MOZ_LOG(gMlsLog, LogLevel::Debug,
("Entry file: %s", entry->HumanReadablePath().get()));
// If there is a valid origin attributes suffix, we remove the entry // only if it matches. if (pattern.Matches(originAttrs)) {
aRv = entry->Remove(/* recursive */ false); if (NS_WARN_IF(aRv.Failed())) {
MOZ_LOG(gMlsLog, LogLevel::Error,
("Failed to remove file: %s", decodedEntryName.get()));
}
MOZ_LOG(gMlsLog, LogLevel::Debug,
("Removed file: %s", decodedEntryName.get()));
}
}
// If there is a valid origin attributes suffix, we remove the entry // only if it matches. We are checking for state partitioned under // aSchemelessSite. if (partitionPattern.Matches(originAttrs)) {
aRv = entry->Remove(/* recursive */ false); if (NS_WARN_IF(aRv.Failed())) {
MOZ_LOG(gMlsLog, LogLevel::Error,
("Failed to remove file: %s", decodedEntryName.get()));
}
MOZ_LOG(gMlsLog, LogLevel::Debug,
("Removed file: %s", decodedEntryName.get()));
}
}
// Close the directory enumerator
dirEnum->Close();
}
// Get the profile directory
nsCOMPtr<nsIFile> file;
aRv = NS_GetSpecialDirectory("ProfD", getter_AddRefs(file)); if (NS_WARN_IF(aRv.Failed())) {
MOZ_LOG(gMlsLog, LogLevel::Error, ("Failed to get profile directory")); return;
}
// Append the 'mls' directory
aRv = file->AppendNative("mls"_ns); if (NS_WARN_IF(aRv.Failed())) {
MOZ_LOG(gMlsLog, LogLevel::Error,
("Failed to append 'mls' to directory path")); return;
}
// Check if the directory exists bool exists;
aRv = file->Exists(&exists); if (NS_WARN_IF(aRv.Failed() || !exists)) {
MOZ_LOG(gMlsLog, LogLevel::Debug, ("'mls' directory does not exist")); return;
}
// Remove the MLS directory recursively
aRv = file->Remove(/* recursive */ true); if (NS_WARN_IF(aRv.Failed())) {
MOZ_LOG(gMlsLog, LogLevel::Error, ("Failed to remove MLS directory")); return;
}
#define PROCTYPE_TO_WEBIDL_CASE(_procType, _webidl) \ case mozilla::ProcType::_procType: \ return WebIDLProcType::_webidl
static WebIDLProcType ProcTypeToWebIDL(mozilla::ProcType aType) { // Max is the value of the last enum, not the length, so add one.
static_assert( static_cast<size_t>(MaxContiguousEnumValue<WebIDLProcType>::value) == static_cast<size_t>(ProcType::Max), "In order for this static cast to be okay, " "WebIDLProcType must match ProcType exactly");
// These must match the similar ones in E10SUtils.sys.mjs, RemoteTypes.h, // ProcInfo.h and ChromeUtils.webidl switch (aType) {
PROCTYPE_TO_WEBIDL_CASE(Web, Web);
PROCTYPE_TO_WEBIDL_CASE(WebIsolated, WebIsolated);
PROCTYPE_TO_WEBIDL_CASE(File, File);
PROCTYPE_TO_WEBIDL_CASE(Extension, Extension);
PROCTYPE_TO_WEBIDL_CASE(PrivilegedAbout, Privilegedabout);
PROCTYPE_TO_WEBIDL_CASE(PrivilegedMozilla, Privilegedmozilla);
PROCTYPE_TO_WEBIDL_CASE(WebCOOPCOEP, WithCoopCoep);
PROCTYPE_TO_WEBIDL_CASE(WebServiceWorker, WebServiceWorker);
PROCTYPE_TO_WEBIDL_CASE(Inference, Inference);
MOZ_ASSERT(false, "Unhandled case in ProcTypeToWebIDL"); return WebIDLProcType::Unknown;
}
#undef PROCTYPE_TO_WEBIDL_CASE
/* static */
already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal,
ErrorResult& aRv) { // This function will use IPDL to enable threads info on macOS // see https://bugzilla.mozilla.org/show_bug.cgi?id=1529023 if (!XRE_IsParentProcess()) {
aRv.Throw(NS_ERROR_FAILURE); return nullptr;
} // Prepare the JS promise that will hold our response.
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
MOZ_ASSERT(global);
RefPtr<Promise> domPromise = Promise::Create(global, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr;
}
MOZ_ASSERT(domPromise);
// Get a list of processes to examine and pre-fill them with available info. // Note that this is subject to race conditions: just because we have a // process in the list doesn't mean that the process will still be alive when // we attempt to get its information. Followup code MUST be able to fail // gracefully on some processes and still return whichever information is // available.
// Get all the content parents. // Note that this array includes even the long dead content parents, so we // might have some garbage, especially with Fission. // SAFETY NOTE: `contentParents` is only valid if used synchronously. // Anything else and you may end up dealing with dangling pointers.
nsTArray<ContentParent*> contentParents;
ContentParent::GetAll(contentParents);
// Prepare our background request. // We reserve one more slot for the browser process itself.
nsTArray<ProcInfoRequest> requests(contentParents.Length() + 1); // Requesting process info for the browser process itself.
requests.EmplaceBack( /* aPid = */ base::GetCurrentProcId(), /* aProcessType = */ ProcType::Browser, /* aOrigin = */ ""_ns, /* aWindowInfo = */ nsTArray<WindowInfo>(), /* aUtilityInfo = */ nsTArray<UtilityInfo>());
// First handle non-ContentParent processes.
mozilla::ipc::GeckoChildProcessHost::GetAll(
[&requests](mozilla::ipc::GeckoChildProcessHost* aGeckoProcess) {
base::ProcessId childPid = aGeckoProcess->GetChildProcessId(); if (childPid == 0) { // Something went wrong with this process, it may be dead already, // fail gracefully. return;
}
mozilla::ProcType type = mozilla::ProcType::Unknown;
switch (aGeckoProcess->GetProcessType()) { case GeckoProcessType::GeckoProcessType_Content: { // These processes are handled separately. return;
}
// Attach utility actor information to the process.
nsTArray<UtilityInfo> utilityActors; if (aGeckoProcess->GetProcessType() ==
GeckoProcessType::GeckoProcessType_Utility) {
RefPtr<mozilla::ipc::UtilityProcessManager> upm =
mozilla::ipc::UtilityProcessManager::GetSingleton(); if (!utilityActors.AppendElements(upm->GetActors(aGeckoProcess),
fallible)) {
NS_WARNING("Error adding actors"); return;
}
}
requests.EmplaceBack( /* aPid = */ childPid, /* aProcessType = */ type, /* aOrigin = */ ""_ns, /* aWindowInfo = */ nsTArray<WindowInfo>(), // Without a // ContentProcess, no // DOM windows. /* aUtilityInfo = */ std::move(utilityActors), /* aChild = */ 0 // Without a ContentProcess, no ChildId. #ifdef XP_DARWIN
, /* aChildTask = */ aGeckoProcess->GetChildTask() #endif// XP_DARWIN
);
});
// Now handle ContentParents. for (constauto* contentParent : contentParents) { if (!contentParent || !contentParent->Process()) { // Presumably, the process is dead or dying. continue;
}
base::ProcessId pid = contentParent->Process()->GetChildProcessId(); if (pid == 0) { // Presumably, the process is dead or dying. continue;
} if (contentParent->Process()->GetProcessType() !=
GeckoProcessType::GeckoProcessType_Content) { // We're probably racing against a process changing type. // We'll get it in the next call, skip it for the moment. continue;
}
// Since this code is executed synchronously on the main thread, // processes cannot die while we're in this loop.
mozilla::ProcType type = mozilla::ProcType::Unknown;
// Convert the remoteType into a ProcType. // Ideally, the remoteType should be strongly typed // upstream, this would make the conversion less brittle. const nsAutoCString remoteType(contentParent->GetRemoteType()); if (StringBeginsWith(remoteType, FISSION_WEB_REMOTE_TYPE)) { // WARNING: Do not change the order, as // `DEFAULT_REMOTE_TYPE` is a prefix of // `FISSION_WEB_REMOTE_TYPE`.
type = mozilla::ProcType::WebIsolated;
} elseif (StringBeginsWith(remoteType, SERVICEWORKER_REMOTE_TYPE)) {
type = mozilla::ProcType::WebServiceWorker;
} elseif (StringBeginsWith(remoteType,
WITH_COOP_COEP_REMOTE_TYPE_PREFIX)) {
type = mozilla::ProcType::WebCOOPCOEP;
} elseif (remoteType == FILE_REMOTE_TYPE) {
type = mozilla::ProcType::File;
} elseif (remoteType == EXTENSION_REMOTE_TYPE) {
type = mozilla::ProcType::Extension;
} elseif (remoteType == PRIVILEGEDABOUT_REMOTE_TYPE) {
type = mozilla::ProcType::PrivilegedAbout;
} elseif (remoteType == PRIVILEGEDMOZILLA_REMOTE_TYPE) {
type = mozilla::ProcType::PrivilegedMozilla;
} elseif (remoteType == PREALLOC_REMOTE_TYPE) {
type = mozilla::ProcType::Preallocated;
} elseif (remoteType == INFERENCE_REMOTE_TYPE) {
type = mozilla::ProcType::Inference;
} elseif (StringBeginsWith(remoteType, DEFAULT_REMOTE_TYPE)) {
type = mozilla::ProcType::Web;
} else {
MOZ_CRASH_UNSAFE_PRINTF("Unknown remoteType '%s'", remoteType.get());
}
// By convention, everything after '=' is the origin.
nsAutoCString origin;
nsACString::const_iterator cursor;
nsACString::const_iterator end;
remoteType.BeginReading(cursor);
remoteType.EndReading(end); if (FindCharInReadable('=', cursor, end)) {
origin = Substring(++cursor, end);
}
// Attach DOM window information to the process.
nsTArray<WindowInfo> windows; for (constauto& browserParentWrapperKey :
contentParent->ManagedPBrowserParent()) { for (constauto& windowGlobalParentWrapperKey :
browserParentWrapperKey->ManagedPWindowGlobalParent()) { // WindowGlobalParent is the only immediate subclass of // PWindowGlobalParent. auto* windowGlobalParent = static_cast<WindowGlobalParent*>(windowGlobalParentWrapperKey);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.