/* -*- 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 "BackgroundUtils.h" #include "MainThreadUtils.h" #include "mozilla/Assertions.h" #include "mozilla/BasePrincipal.h" #include "mozilla/ContentPrincipal.h" #include "mozilla/NullPrincipal.h" #include "mozilla/ipc/PBackgroundSharedTypes.h" #include "mozilla/ipc/URIUtils.h" #include "mozilla/net/CookieJarSettings.h" #include "mozilla/net/NeckoChannelParams.h" #include "ExpandedPrincipal.h" #include "nsIScriptSecurityManager.h" #include "nsIURI.h" #include "nsNetUtil.h" #include "mozilla/LoadInfo.h" #include "nsContentUtils.h" #include "nsString.h" #include "nsTArray.h" #include "mozilla/nsRedirectHistoryEntry.h" #include "URIUtils.h" #include "mozilla/dom/nsCSPUtils.h" #include "mozilla/dom/nsCSPContext.h" #include "mozilla/dom/BrowsingContext.h" #include "mozilla/dom/CanonicalBrowsingContext.h" #include "mozilla/dom/Document.h" #include "mozilla/dom/WindowGlobalParent.h" namespace mozilla { using mozilla::BasePrincipal; using mozilla::Maybe; using mozilla::dom::BrowsingContext; using mozilla::dom::ServiceWorkerDescriptor; using namespace mozilla::net; namespace ipc { Result, nsresult> PrincipalInfoToPrincipal( const PrincipalInfo& aPrincipalInfo) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aPrincipalInfo.type() != PrincipalInfo::T__None); nsCOMPtr secMan = nsContentUtils::GetSecurityManager(); if (!secMan) { return Err(NS_ERROR_NULL_POINTER); } nsCOMPtr principal; nsresult rv; switch (aPrincipalInfo.type()) { case PrincipalInfo::TSystemPrincipalInfo: { rv = secMan->GetSystemPrincipal(getter_AddRefs(principal)); if (NS_WARN_IF(NS_FAILED(rv))) { return Err(rv); } return principal; } case PrincipalInfo::TNullPrincipalInfo: { const NullPrincipalInfo& info = aPrincipalInfo.get_NullPrincipalInfo(); nsCOMPtr uri; rv = NS_NewURI(getter_AddRefs(uri), info.spec()); if (NS_WARN_IF(NS_FAILED(rv))) { return Err(rv); } principal = NullPrincipal::Create(info.attrs(), uri); return principal; } case PrincipalInfo::TContentPrincipalInfo: { const ContentPrincipalInfo& info = aPrincipalInfo.get_ContentPrincipalInfo(); nsCOMPtr uri; rv = NS_NewURI(getter_AddRefs(uri), info.spec()); if (NS_WARN_IF(NS_FAILED(rv))) { return Err(rv); } principal = BasePrincipal::CreateContentPrincipal(uri, info.attrs()); if (NS_WARN_IF(!principal)) { return Err(NS_ERROR_NULL_POINTER); } // Origin must match what the_new_principal.getOrigin returns. nsAutoCString originNoSuffix; rv = principal->GetOriginNoSuffix(originNoSuffix); if (NS_WARN_IF(NS_FAILED(rv))) { return Err(rv); } if (NS_WARN_IF(!info.originNoSuffix().Equals(originNoSuffix))) { return Err(NS_ERROR_FAILURE); } if (info.domain()) { nsCOMPtr domain; rv = NS_NewURI(getter_AddRefs(domain), *info.domain()); if (NS_WARN_IF(NS_FAILED(rv))) { return Err(rv); } rv = principal->SetDomain(domain); if (NS_WARN_IF(NS_FAILED(rv))) { return Err(rv); } } if (!info.baseDomain().IsVoid()) { nsAutoCString baseDomain; rv = principal->GetBaseDomain(baseDomain); if (NS_WARN_IF(NS_FAILED(rv))) { return Err(rv); } if (NS_WARN_IF(!info.baseDomain().Equals(baseDomain))) { return Err(NS_ERROR_FAILURE); } } return principal; } case PrincipalInfo::TExpandedPrincipalInfo: { const ExpandedPrincipalInfo& info = aPrincipalInfo.get_ExpandedPrincipalInfo(); nsTArray> allowlist; nsCOMPtr alPrincipal; for (uint32_t i = 0; i < info.allowlist().Length(); i++) { auto principalOrErr = PrincipalInfoToPrincipal(info.allowlist()[i]); if (NS_WARN_IF(principalOrErr.isErr())) { nsresult ret = principalOrErr.unwrapErr(); return Err(ret); } // append that principal to the allowlist allowlist.AppendElement(principalOrErr.unwrap()); } RefPtr expandedPrincipal = ExpandedPrincipal::Create(allowlist, info.attrs()); if (!expandedPrincipal) { return Err(NS_ERROR_FAILURE); } principal = expandedPrincipal; return principal; } default: return Err(NS_ERROR_FAILURE); } return Err(NS_ERROR_FAILURE); } already_AddRefed CSPInfoToCSP( const CSPInfo& aCSPInfo, Document* aRequestingDoc, nsresult* aOptionalResult) { MOZ_ASSERT(NS_IsMainThread()); nsresult stackResult; nsresult& rv = aOptionalResult ? *aOptionalResult : stackResult; RefPtr csp = new nsCSPContext(); if (aRequestingDoc) { rv = csp->SetRequestContextWithDocument(aRequestingDoc); if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; } } else { auto principalOrErr = PrincipalInfoToPrincipal(aCSPInfo.requestPrincipalInfo()); if (NS_WARN_IF(principalOrErr.isErr())) { return nullptr; } nsCOMPtr selfURI; if (!aCSPInfo.selfURISpec().IsEmpty()) { rv = NS_NewURI(getter_AddRefs(selfURI), aCSPInfo.selfURISpec()); if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; } } nsCOMPtr principal = principalOrErr.unwrap(); rv = csp->SetRequestContextWithPrincipal( principal, selfURI, aCSPInfo.referrer(), aCSPInfo.innerWindowID()); if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; } } csp->SetSkipAllowInlineStyleCheck(aCSPInfo.skipAllowInlineStyleCheck()); for (uint32_t i = 0; i < aCSPInfo.policyInfos().Length(); i++) { csp->AddIPCPolicy(aCSPInfo.policyInfos()[i]); } return csp.forget(); } nsresult CSPToCSPInfo(nsIContentSecurityPolicy* aCSP, CSPInfo* aCSPInfo) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aCSP); MOZ_ASSERT(aCSPInfo); if (!aCSP || !aCSPInfo) { return NS_ERROR_FAILURE; } nsCOMPtr requestPrincipal = aCSP->GetRequestPrincipal(); PrincipalInfo requestingPrincipalInfo; nsresult rv = PrincipalToPrincipalInfo(requestPrincipal, &requestingPrincipalInfo); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } nsCOMPtr selfURI = aCSP->GetSelfURI(); nsAutoCString selfURISpec; if (selfURI) { selfURI->GetSpec(selfURISpec); } nsAutoString referrer; aCSP->GetReferrer(referrer); uint64_t windowID = aCSP->GetInnerWindowID(); bool skipAllowInlineStyleCheck = aCSP->GetSkipAllowInlineStyleCheck(); nsTArray policies; static_cast(aCSP)->SerializePolicies(policies); *aCSPInfo = CSPInfo(std::move(policies), requestingPrincipalInfo, selfURISpec, referrer, windowID, skipAllowInlineStyleCheck); return NS_OK; } nsresult PrincipalToPrincipalInfo(nsIPrincipal* aPrincipal, PrincipalInfo* aPrincipalInfo, bool aSkipBaseDomain) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aPrincipal); MOZ_ASSERT(aPrincipalInfo); nsresult rv; if (aPrincipal->GetIsNullPrincipal()) { nsAutoCString spec; rv = aPrincipal->GetAsciiSpec(spec); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } *aPrincipalInfo = NullPrincipalInfo(aPrincipal->OriginAttributesRef(), spec); return NS_OK; } if (aPrincipal->IsSystemPrincipal()) { *aPrincipalInfo = SystemPrincipalInfo(); return NS_OK; } // might be an expanded principal auto* basePrin = BasePrincipal::Cast(aPrincipal); if (basePrin->Is()) { auto* expanded = basePrin->As(); nsTArray allowlistInfo; PrincipalInfo info; for (auto& prin : expanded->AllowList()) { rv = PrincipalToPrincipalInfo(prin, &info, aSkipBaseDomain); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } // append that spec to the allowlist allowlistInfo.AppendElement(info); } *aPrincipalInfo = ExpandedPrincipalInfo(aPrincipal->OriginAttributesRef(), std::move(allowlistInfo)); return NS_OK; } nsAutoCString spec; rv = aPrincipal->GetAsciiSpec(spec); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } nsCString originNoSuffix; rv = aPrincipal->GetOriginNoSuffix(originNoSuffix); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } nsCOMPtr domainUri; rv = aPrincipal->GetDomain(getter_AddRefs(domainUri)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } Maybe domain; if (domainUri) { domain.emplace(); rv = domainUri->GetSpec(domain.ref()); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } } // This attribute is not crucial. nsCString baseDomain; if (aSkipBaseDomain) { baseDomain.SetIsVoid(true); } else { if (NS_FAILED(aPrincipal->GetBaseDomain(baseDomain))) { // No warning here. Some principal URLs do not have a base-domain. baseDomain.SetIsVoid(true); } } *aPrincipalInfo = ContentPrincipalInfo(aPrincipal->OriginAttributesRef(), originNoSuffix, spec, domain, baseDomain); return NS_OK; } bool IsPrincipalInfoPrivate(const PrincipalInfo& aPrincipalInfo) { if (aPrincipalInfo.type() != ipc::PrincipalInfo::TContentPrincipalInfo) { return false; } const ContentPrincipalInfo& info = aPrincipalInfo.get_ContentPrincipalInfo(); return !!info.attrs().mPrivateBrowsingId; } already_AddRefed RHEntryInfoToRHEntry( const RedirectHistoryEntryInfo& aRHEntryInfo) { auto principalOrErr = PrincipalInfoToPrincipal(aRHEntryInfo.principalInfo()); if (NS_WARN_IF(principalOrErr.isErr())) { return nullptr; } nsCOMPtr principal = principalOrErr.unwrap(); nsCOMPtr referrerUri = DeserializeURI(aRHEntryInfo.referrerUri()); nsCOMPtr entry = new nsRedirectHistoryEntry( principal, referrerUri, aRHEntryInfo.remoteAddress()); return entry.forget(); } nsresult RHEntryToRHEntryInfo(nsIRedirectHistoryEntry* aRHEntry, RedirectHistoryEntryInfo* aRHEntryInfo) { MOZ_ASSERT(aRHEntry); MOZ_ASSERT(aRHEntryInfo); nsresult rv; aRHEntry->GetRemoteAddress(aRHEntryInfo->remoteAddress()); nsCOMPtr referrerUri; rv = aRHEntry->GetReferrerURI(getter_AddRefs(referrerUri)); NS_ENSURE_SUCCESS(rv, rv); SerializeURI(referrerUri, aRHEntryInfo->referrerUri()); nsCOMPtr principal; rv = aRHEntry->GetPrincipal(getter_AddRefs(principal)); NS_ENSURE_SUCCESS(rv, rv); return PrincipalToPrincipalInfo(principal, &aRHEntryInfo->principalInfo()); } nsresult LoadInfoToLoadInfoArgs(nsILoadInfo* aLoadInfo, Maybe* aOptionalLoadInfoArgs) { nsresult rv = NS_OK; Maybe loadingPrincipalInfo; if (nsIPrincipal* loadingPrin = aLoadInfo->GetLoadingPrincipal()) { loadingPrincipalInfo.emplace(); rv = PrincipalToPrincipalInfo(loadingPrin, loadingPrincipalInfo.ptr()); NS_ENSURE_SUCCESS(rv, rv); } PrincipalInfo triggeringPrincipalInfo; rv = PrincipalToPrincipalInfo(aLoadInfo->TriggeringPrincipal(), &triggeringPrincipalInfo); NS_ENSURE_SUCCESS(rv, rv); Maybe principalToInheritInfo; if (nsIPrincipal* principalToInherit = aLoadInfo->PrincipalToInherit()) { principalToInheritInfo.emplace(); rv = PrincipalToPrincipalInfo(principalToInherit, principalToInheritInfo.ptr()); NS_ENSURE_SUCCESS(rv, rv); } Maybe sandboxedLoadingPrincipalInfo; if (aLoadInfo->GetLoadingSandboxed()) { sandboxedLoadingPrincipalInfo.emplace(); rv = PrincipalToPrincipalInfo(aLoadInfo->GetSandboxedLoadingPrincipal(), sandboxedLoadingPrincipalInfo.ptr()); NS_ENSURE_SUCCESS(rv, rv); } Maybe topLevelPrincipalInfo; if (nsIPrincipal* topLevenPrin = aLoadInfo->GetTopLevelPrincipal()) { topLevelPrincipalInfo.emplace(); rv = PrincipalToPrincipalInfo(topLevenPrin, topLevelPrincipalInfo.ptr()); NS_ENSURE_SUCCESS(rv, rv); } Maybe topLevelStorageAreaPrincipalInfo; if (nsIPrincipal* prin = aLoadInfo->GetTopLevelStorageAreaPrincipal()) { topLevelStorageAreaPrincipalInfo.emplace(); rv = PrincipalToPrincipalInfo(prin, topLevelStorageAreaPrincipalInfo.ptr()); NS_ENSURE_SUCCESS(rv, rv); } Maybe optionalResultPrincipalURI; nsCOMPtr resultPrincipalURI; Unused << aLoadInfo->GetResultPrincipalURI( getter_AddRefs(resultPrincipalURI)); if (resultPrincipalURI) { SerializeURI(resultPrincipalURI, optionalResultPrincipalURI); } nsTArray redirectChainIncludingInternalRedirects; for (const nsCOMPtr& redirectEntry : aLoadInfo->RedirectChainIncludingInternalRedirects()) { RedirectHistoryEntryInfo* entry = redirectChainIncludingInternalRedirects.AppendElement(); rv = RHEntryToRHEntryInfo(redirectEntry, entry); NS_ENSURE_SUCCESS(rv, rv); } nsTArray redirectChain; for (const nsCOMPtr& redirectEntry : aLoadInfo->RedirectChain()) { RedirectHistoryEntryInfo* entry = redirectChain.AppendElement(); rv = RHEntryToRHEntryInfo(redirectEntry, entry); NS_ENSURE_SUCCESS(rv, rv); } Maybe ipcClientInfo; const Maybe& clientInfo = aLoadInfo->GetClientInfo(); if (clientInfo.isSome()) { ipcClientInfo.emplace(clientInfo.ref().ToIPC()); } Maybe ipcReservedClientInfo; const Maybe& reservedClientInfo = aLoadInfo->GetReservedClientInfo(); if (reservedClientInfo.isSome()) { ipcReservedClientInfo.emplace(reservedClientInfo.ref().ToIPC()); } Maybe ipcInitialClientInfo; const Maybe& initialClientInfo = aLoadInfo->GetInitialClientInfo(); if (initialClientInfo.isSome()) { ipcInitialClientInfo.emplace(initialClientInfo.ref().ToIPC()); } Maybe ipcController; const Maybe& controller = aLoadInfo->GetController(); if (controller.isSome()) { ipcController.emplace(controller.ref().ToIPC()); } nsAutoString cspNonce; Unused << NS_WARN_IF(NS_FAILED(aLoadInfo->GetCspNonce(cspNonce))); nsCOMPtr cookieJarSettings; rv = aLoadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings)); NS_ENSURE_SUCCESS(rv, rv); CookieJarSettingsArgs cookieJarSettingsArgs; static_cast(cookieJarSettings.get()) ->Serialize(cookieJarSettingsArgs); Maybe maybeCspToInheritInfo; nsCOMPtr cspToInherit = aLoadInfo->GetCspToInherit(); if (cspToInherit) { CSPInfo cspToInheritInfo; Unused << NS_WARN_IF( NS_FAILED(CSPToCSPInfo(cspToInherit, &cspToInheritInfo))); maybeCspToInheritInfo.emplace(cspToInheritInfo); } *aOptionalLoadInfoArgs = Some(LoadInfoArgs( loadingPrincipalInfo, triggeringPrincipalInfo, principalToInheritInfo, sandboxedLoadingPrincipalInfo, topLevelPrincipalInfo, topLevelStorageAreaPrincipalInfo, optionalResultPrincipalURI, aLoadInfo->GetSecurityFlags(), aLoadInfo->GetSandboxFlags(), aLoadInfo->GetTriggeringSandboxFlags(), aLoadInfo->InternalContentPolicyType(), static_cast(aLoadInfo->GetTainting()), aLoadInfo->GetBlockAllMixedContent(), aLoadInfo->GetUpgradeInsecureRequests(), aLoadInfo->GetBrowserUpgradeInsecureRequests(), aLoadInfo->GetBrowserDidUpgradeInsecureRequests(), aLoadInfo->GetBrowserWouldUpgradeInsecureRequests(), aLoadInfo->GetForceAllowDataURI(), aLoadInfo->GetAllowInsecureRedirectToDataURI(), aLoadInfo->GetBypassCORSChecks(), aLoadInfo->GetSkipContentPolicyCheckForWebRequest(), aLoadInfo->GetOriginalFrameSrcLoad(), aLoadInfo->GetForceInheritPrincipalDropped(), aLoadInfo->GetInnerWindowID(), aLoadInfo->GetBrowsingContextID(), aLoadInfo->GetFrameBrowsingContextID(), aLoadInfo->GetInitialSecurityCheckDone(), aLoadInfo->GetIsInThirdPartyContext(), aLoadInfo->GetIsThirdPartyContextToTopWindow(), aLoadInfo->GetIsFormSubmission(), aLoadInfo->GetSendCSPViolationEvents(), aLoadInfo->GetOriginAttributes(), redirectChainIncludingInternalRedirects, redirectChain, ipcClientInfo, ipcReservedClientInfo, ipcInitialClientInfo, ipcController, aLoadInfo->CorsUnsafeHeaders(), aLoadInfo->GetForcePreflight(), aLoadInfo->GetIsPreflight(), aLoadInfo->GetLoadTriggeredFromExternal(), aLoadInfo->GetServiceWorkerTaintingSynthesized(), aLoadInfo->GetDocumentHasUserInteracted(), aLoadInfo->GetAllowListFutureDocumentsCreatedFromThisRedirectChain(), cspNonce, aLoadInfo->GetSkipContentSniffing(), aLoadInfo->GetHttpsOnlyStatus(), aLoadInfo->GetHasValidUserGestureActivation(), aLoadInfo->GetAllowDeprecatedSystemRequests(), aLoadInfo->GetIsInDevToolsContext(), aLoadInfo->GetParserCreatedScript(), aLoadInfo->GetIsFromProcessingFrameAttributes(), cookieJarSettingsArgs, aLoadInfo->GetRequestBlockingReason(), maybeCspToInheritInfo, aLoadInfo->GetHasStoragePermission(), aLoadInfo->GetLoadingEmbedderPolicy())); return NS_OK; } nsresult LoadInfoArgsToLoadInfo( const Maybe& aOptionalLoadInfoArgs, nsILoadInfo** outLoadInfo) { return LoadInfoArgsToLoadInfo(aOptionalLoadInfoArgs, nullptr, outLoadInfo); } nsresult LoadInfoArgsToLoadInfo( const Maybe& aOptionalLoadInfoArgs, nsINode* aCspToInheritLoadingContext, nsILoadInfo** outLoadInfo) { RefPtr loadInfo; nsresult rv = LoadInfoArgsToLoadInfo(aOptionalLoadInfoArgs, aCspToInheritLoadingContext, getter_AddRefs(loadInfo)); NS_ENSURE_SUCCESS(rv, rv); loadInfo.forget(outLoadInfo); return NS_OK; } nsresult LoadInfoArgsToLoadInfo( const Maybe& aOptionalLoadInfoArgs, LoadInfo** outLoadInfo) { return LoadInfoArgsToLoadInfo(aOptionalLoadInfoArgs, nullptr, outLoadInfo); } nsresult LoadInfoArgsToLoadInfo( const Maybe& aOptionalLoadInfoArgs, nsINode* aCspToInheritLoadingContext, LoadInfo** outLoadInfo) { if (aOptionalLoadInfoArgs.isNothing()) { *outLoadInfo = nullptr; return NS_OK; } const LoadInfoArgs& loadInfoArgs = aOptionalLoadInfoArgs.ref(); nsCOMPtr loadingPrincipal; if (loadInfoArgs.requestingPrincipalInfo().isSome()) { auto loadingPrincipalOrErr = PrincipalInfoToPrincipal(loadInfoArgs.requestingPrincipalInfo().ref()); if (NS_WARN_IF(loadingPrincipalOrErr.isErr())) { return loadingPrincipalOrErr.unwrapErr(); } loadingPrincipal = loadingPrincipalOrErr.unwrap(); } auto triggeringPrincipalOrErr = PrincipalInfoToPrincipal(loadInfoArgs.triggeringPrincipalInfo()); if (NS_WARN_IF(triggeringPrincipalOrErr.isErr())) { return triggeringPrincipalOrErr.unwrapErr(); } nsCOMPtr triggeringPrincipal = triggeringPrincipalOrErr.unwrap(); nsCOMPtr principalToInherit; nsCOMPtr flattenedPrincipalToInherit; if (loadInfoArgs.principalToInheritInfo().isSome()) { auto principalToInheritOrErr = PrincipalInfoToPrincipal(loadInfoArgs.principalToInheritInfo().ref()); if (NS_WARN_IF(principalToInheritOrErr.isErr())) { return principalToInheritOrErr.unwrapErr(); } flattenedPrincipalToInherit = principalToInheritOrErr.unwrap(); } if (XRE_IsContentProcess()) { auto targetBrowsingContextId = loadInfoArgs.frameBrowsingContextID() ? loadInfoArgs.frameBrowsingContextID() : loadInfoArgs.browsingContextID(); if (RefPtr bc = BrowsingContext::Get(targetBrowsingContextId)) { nsCOMPtr originalTriggeringPrincipal; nsCOMPtr originalPrincipalToInherit; Tie(originalTriggeringPrincipal, originalPrincipalToInherit) = bc->GetTriggeringAndInheritPrincipalsForCurrentLoad(); if (originalTriggeringPrincipal && originalTriggeringPrincipal->Equals(triggeringPrincipal)) { triggeringPrincipal = originalTriggeringPrincipal; } if (originalPrincipalToInherit && (loadInfoArgs.securityFlags() & nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL) && originalPrincipalToInherit->Equals(flattenedPrincipalToInherit)) { principalToInherit = originalPrincipalToInherit; } } } if (!principalToInherit && loadInfoArgs.principalToInheritInfo().isSome()) { principalToInherit = flattenedPrincipalToInherit; } nsCOMPtr sandboxedLoadingPrincipal; if (loadInfoArgs.sandboxedLoadingPrincipalInfo().isSome()) { auto sandboxedLoadingPrincipalOrErr = PrincipalInfoToPrincipal( loadInfoArgs.sandboxedLoadingPrincipalInfo().ref()); if (NS_WARN_IF(sandboxedLoadingPrincipalOrErr.isErr())) { return sandboxedLoadingPrincipalOrErr.unwrapErr(); } sandboxedLoadingPrincipal = sandboxedLoadingPrincipalOrErr.unwrap(); } nsresult rv = NS_OK; nsCOMPtr topLevelPrincipal; if (loadInfoArgs.topLevelPrincipalInfo().isSome()) { auto topLevelPrincipalOrErr = PrincipalInfoToPrincipal(loadInfoArgs.topLevelPrincipalInfo().ref()); if (NS_WARN_IF(topLevelPrincipalOrErr.isErr())) { return topLevelPrincipalOrErr.unwrapErr(); } topLevelPrincipal = topLevelPrincipalOrErr.unwrap(); } nsCOMPtr topLevelStorageAreaPrincipal; if (loadInfoArgs.topLevelStorageAreaPrincipalInfo().isSome()) { auto topLevelStorageAreaPrincipalOrErr = PrincipalInfoToPrincipal( loadInfoArgs.topLevelStorageAreaPrincipalInfo().ref()); if (NS_WARN_IF(topLevelStorageAreaPrincipalOrErr.isErr())) { return topLevelStorageAreaPrincipalOrErr.unwrapErr(); } topLevelStorageAreaPrincipal = topLevelStorageAreaPrincipalOrErr.unwrap(); } nsCOMPtr resultPrincipalURI; if (loadInfoArgs.resultPrincipalURI().isSome()) { resultPrincipalURI = DeserializeURI(loadInfoArgs.resultPrincipalURI()); NS_ENSURE_TRUE(resultPrincipalURI, NS_ERROR_UNEXPECTED); } RedirectHistoryArray redirectChainIncludingInternalRedirects; for (const RedirectHistoryEntryInfo& entryInfo : loadInfoArgs.redirectChainIncludingInternalRedirects()) { nsCOMPtr redirectHistoryEntry = RHEntryInfoToRHEntry(entryInfo); NS_ENSURE_SUCCESS(rv, rv); redirectChainIncludingInternalRedirects.AppendElement( redirectHistoryEntry.forget()); } RedirectHistoryArray redirectChain; for (const RedirectHistoryEntryInfo& entryInfo : loadInfoArgs.redirectChain()) { nsCOMPtr redirectHistoryEntry = RHEntryInfoToRHEntry(entryInfo); NS_ENSURE_SUCCESS(rv, rv); redirectChain.AppendElement(redirectHistoryEntry.forget()); } nsTArray> ancestorPrincipals; nsTArray ancestorBrowsingContextIDs; if (XRE_IsParentProcess() && (nsContentUtils::InternalContentPolicyTypeToExternal( loadInfoArgs.contentPolicyType()) != ExtContentPolicy::TYPE_DOCUMENT)) { // Only fill out ancestor principals and browsing context IDs when we // are deserializing LoadInfoArgs to be LoadInfo for a subresource RefPtr parentBC = BrowsingContext::Get(loadInfoArgs.browsingContextID()); if (parentBC) { LoadInfo::ComputeAncestors(parentBC->Canonical(), ancestorPrincipals, ancestorBrowsingContextIDs); } } Maybe clientInfo; if (loadInfoArgs.clientInfo().isSome()) { clientInfo.emplace(ClientInfo(loadInfoArgs.clientInfo().ref())); } Maybe reservedClientInfo; if (loadInfoArgs.reservedClientInfo().isSome()) { reservedClientInfo.emplace( ClientInfo(loadInfoArgs.reservedClientInfo().ref())); } Maybe initialClientInfo; if (loadInfoArgs.initialClientInfo().isSome()) { initialClientInfo.emplace( ClientInfo(loadInfoArgs.initialClientInfo().ref())); } // We can have an initial client info or a reserved client info, but not both. MOZ_DIAGNOSTIC_ASSERT(reservedClientInfo.isNothing() || initialClientInfo.isNothing()); NS_ENSURE_TRUE( reservedClientInfo.isNothing() || initialClientInfo.isNothing(), NS_ERROR_UNEXPECTED); Maybe controller; if (loadInfoArgs.controller().isSome()) { controller.emplace( ServiceWorkerDescriptor(loadInfoArgs.controller().ref())); } nsCOMPtr cookieJarSettings; CookieJarSettings::Deserialize(loadInfoArgs.cookieJarSettings(), getter_AddRefs(cookieJarSettings)); nsCOMPtr cspToInherit; Maybe cspToInheritInfo = loadInfoArgs.cspToInheritInfo(); if (cspToInheritInfo.isSome()) { nsCOMPtr doc = do_QueryInterface(aCspToInheritLoadingContext); cspToInherit = CSPInfoToCSP(cspToInheritInfo.ref(), doc); } // Restore the loadingContext for frames using the BrowsingContext's // embedder element. Note that this only works if the embedder is // same-process, so won't be fission compatible. nsCOMPtr loadingContext; RefPtr frameBrowsingContext = BrowsingContext::Get(loadInfoArgs.frameBrowsingContextID()); if (frameBrowsingContext) { loadingContext = frameBrowsingContext->GetEmbedderElement(); } RefPtr loadInfo = new mozilla::LoadInfo( loadingPrincipal, triggeringPrincipal, principalToInherit, sandboxedLoadingPrincipal, topLevelPrincipal, topLevelStorageAreaPrincipal, resultPrincipalURI, cookieJarSettings, cspToInherit, clientInfo, reservedClientInfo, initialClientInfo, controller, loadInfoArgs.securityFlags(), loadInfoArgs.sandboxFlags(), loadInfoArgs.triggeringSandboxFlags(), loadInfoArgs.contentPolicyType(), static_cast(loadInfoArgs.tainting()), loadInfoArgs.blockAllMixedContent(), loadInfoArgs.upgradeInsecureRequests(), loadInfoArgs.browserUpgradeInsecureRequests(), loadInfoArgs.browserDidUpgradeInsecureRequests(), loadInfoArgs.browserWouldUpgradeInsecureRequests(), loadInfoArgs.forceAllowDataURI(), loadInfoArgs.allowInsecureRedirectToDataURI(), loadInfoArgs.bypassCORSChecks(), loadInfoArgs.skipContentPolicyCheckForWebRequest(), loadInfoArgs.originalFrameSrcLoad(), loadInfoArgs.forceInheritPrincipalDropped(), loadInfoArgs.innerWindowID(), loadInfoArgs.browsingContextID(), loadInfoArgs.frameBrowsingContextID(), loadInfoArgs.initialSecurityCheckDone(), loadInfoArgs.isInThirdPartyContext(), loadInfoArgs.isThirdPartyContextToTopWindow(), loadInfoArgs.isFormSubmission(), loadInfoArgs.sendCSPViolationEvents(), loadInfoArgs.originAttributes(), std::move(redirectChainIncludingInternalRedirects), std::move(redirectChain), std::move(ancestorPrincipals), ancestorBrowsingContextIDs, loadInfoArgs.corsUnsafeHeaders(), loadInfoArgs.forcePreflight(), loadInfoArgs.isPreflight(), loadInfoArgs.loadTriggeredFromExternal(), loadInfoArgs.serviceWorkerTaintingSynthesized(), loadInfoArgs.documentHasUserInteracted(), loadInfoArgs.allowListFutureDocumentsCreatedFromThisRedirectChain(), loadInfoArgs.cspNonce(), loadInfoArgs.skipContentSniffing(), loadInfoArgs.httpsOnlyStatus(), loadInfoArgs.hasValidUserGestureActivation(), loadInfoArgs.allowDeprecatedSystemRequests(), loadInfoArgs.isInDevToolsContext(), loadInfoArgs.parserCreatedScript(), loadInfoArgs.hasStoragePermission(), loadInfoArgs.requestBlockingReason(), loadingContext, loadInfoArgs.loadingEmbedderPolicy()); if (loadInfoArgs.isFromProcessingFrameAttributes()) { loadInfo->SetIsFromProcessingFrameAttributes(); } loadInfo.forget(outLoadInfo); return NS_OK; } void LoadInfoToParentLoadInfoForwarder( nsILoadInfo* aLoadInfo, ParentLoadInfoForwarderArgs* aForwarderArgsOut) { Maybe ipcController; Maybe controller(aLoadInfo->GetController()); if (controller.isSome()) { ipcController.emplace(controller.ref().ToIPC()); } uint32_t tainting = nsILoadInfo::TAINTING_BASIC; Unused << aLoadInfo->GetTainting(&tainting); Maybe cookieJarSettingsArgs; nsCOMPtr cookieJarSettings; nsresult rv = aLoadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings)); CookieJarSettings* cs = static_cast(cookieJarSettings.get()); if (NS_SUCCEEDED(rv) && cookieJarSettings && cs->HasBeenChanged()) { CookieJarSettingsArgs args; cs->Serialize(args); cookieJarSettingsArgs = Some(args); } *aForwarderArgsOut = ParentLoadInfoForwarderArgs( aLoadInfo->GetAllowInsecureRedirectToDataURI(), aLoadInfo->GetBypassCORSChecks(), ipcController, tainting, aLoadInfo->GetSkipContentSniffing(), aLoadInfo->GetHttpsOnlyStatus(), aLoadInfo->GetHasValidUserGestureActivation(), aLoadInfo->GetAllowDeprecatedSystemRequests(), aLoadInfo->GetIsInDevToolsContext(), aLoadInfo->GetParserCreatedScript(), aLoadInfo->GetTriggeringSandboxFlags(), aLoadInfo->GetServiceWorkerTaintingSynthesized(), aLoadInfo->GetDocumentHasUserInteracted(), aLoadInfo->GetAllowListFutureDocumentsCreatedFromThisRedirectChain(), cookieJarSettingsArgs, aLoadInfo->GetRequestBlockingReason(), aLoadInfo->GetHasStoragePermission(), aLoadInfo->GetIsThirdPartyContextToTopWindow(), aLoadInfo->GetIsInThirdPartyContext()); } nsresult MergeParentLoadInfoForwarder( ParentLoadInfoForwarderArgs const& aForwarderArgs, nsILoadInfo* aLoadInfo) { nsresult rv; rv = aLoadInfo->SetAllowInsecureRedirectToDataURI( aForwarderArgs.allowInsecureRedirectToDataURI()); NS_ENSURE_SUCCESS(rv, rv); rv = aLoadInfo->SetBypassCORSChecks(aForwarderArgs.bypassCORSChecks()); NS_ENSURE_SUCCESS(rv, rv); aLoadInfo->ClearController(); auto& controller = aForwarderArgs.controller(); if (controller.isSome()) { aLoadInfo->SetController(ServiceWorkerDescriptor(controller.ref())); } if (aForwarderArgs.serviceWorkerTaintingSynthesized()) { aLoadInfo->SynthesizeServiceWorkerTainting( static_cast(aForwarderArgs.tainting())); } else { aLoadInfo->MaybeIncreaseTainting(aForwarderArgs.tainting()); } rv = aLoadInfo->SetSkipContentSniffing(aForwarderArgs.skipContentSniffing()); NS_ENSURE_SUCCESS(rv, rv); rv = aLoadInfo->SetHttpsOnlyStatus(aForwarderArgs.httpsOnlyStatus()); NS_ENSURE_SUCCESS(rv, rv); rv = aLoadInfo->SetTriggeringSandboxFlags( aForwarderArgs.triggeringSandboxFlags()); NS_ENSURE_SUCCESS(rv, rv); rv = aLoadInfo->SetHasValidUserGestureActivation( aForwarderArgs.hasValidUserGestureActivation()); NS_ENSURE_SUCCESS(rv, rv); rv = aLoadInfo->SetAllowDeprecatedSystemRequests( aForwarderArgs.allowDeprecatedSystemRequests()); NS_ENSURE_SUCCESS(rv, rv); rv = aLoadInfo->SetIsInDevToolsContext(aForwarderArgs.isInDevToolsContext()); NS_ENSURE_SUCCESS(rv, rv); rv = aLoadInfo->SetParserCreatedScript(aForwarderArgs.parserCreatedScript()); NS_ENSURE_SUCCESS(rv, rv); MOZ_ALWAYS_SUCCEEDS(aLoadInfo->SetDocumentHasUserInteracted( aForwarderArgs.documentHasUserInteracted())); MOZ_ALWAYS_SUCCEEDS( aLoadInfo->SetAllowListFutureDocumentsCreatedFromThisRedirectChain( aForwarderArgs .allowListFutureDocumentsCreatedFromThisRedirectChain())); MOZ_ALWAYS_SUCCEEDS(aLoadInfo->SetRequestBlockingReason( aForwarderArgs.requestBlockingReason())); const Maybe& cookieJarSettingsArgs = aForwarderArgs.cookieJarSettings(); if (cookieJarSettingsArgs.isSome()) { nsCOMPtr cookieJarSettings; nsresult rv = aLoadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings)); if (NS_SUCCEEDED(rv) && cookieJarSettings) { static_cast(cookieJarSettings.get()) ->Merge(cookieJarSettingsArgs.ref()); } } rv = aLoadInfo->SetHasStoragePermission(aForwarderArgs.hasStoragePermission()); NS_ENSURE_SUCCESS(rv, rv); rv = aLoadInfo->SetIsThirdPartyContextToTopWindow( aForwarderArgs.isThirdPartyContextToTopWindow()); NS_ENSURE_SUCCESS(rv, rv); rv = aLoadInfo->SetIsInThirdPartyContext( aForwarderArgs.isInThirdPartyContext()); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } void LoadInfoToChildLoadInfoForwarder( nsILoadInfo* aLoadInfo, ChildLoadInfoForwarderArgs* aForwarderArgsOut) { Maybe ipcReserved; Maybe reserved(aLoadInfo->GetReservedClientInfo()); if (reserved.isSome()) { ipcReserved.emplace(reserved.ref().ToIPC()); } Maybe ipcInitial; Maybe initial(aLoadInfo->GetInitialClientInfo()); if (initial.isSome()) { ipcInitial.emplace(initial.ref().ToIPC()); } Maybe ipcController; Maybe controller(aLoadInfo->GetController()); if (controller.isSome()) { ipcController.emplace(controller.ref().ToIPC()); } *aForwarderArgsOut = ChildLoadInfoForwarderArgs(ipcReserved, ipcInitial, ipcController, aLoadInfo->GetRequestBlockingReason()); } nsresult MergeChildLoadInfoForwarder( const ChildLoadInfoForwarderArgs& aForwarderArgs, nsILoadInfo* aLoadInfo) { Maybe reservedClientInfo; auto& ipcReserved = aForwarderArgs.reservedClientInfo(); if (ipcReserved.isSome()) { reservedClientInfo.emplace(ClientInfo(ipcReserved.ref())); } Maybe initialClientInfo; auto& ipcInitial = aForwarderArgs.initialClientInfo(); if (ipcInitial.isSome()) { initialClientInfo.emplace(ClientInfo(ipcInitial.ref())); } // There should only be at most one reserved or initial ClientInfo. if (NS_WARN_IF(reservedClientInfo.isSome() && initialClientInfo.isSome())) { return NS_ERROR_FAILURE; } // If we received no reserved or initial ClientInfo, then we must not // already have one set. There are no use cases where this should // happen and we don't have a way to clear the current value. if (NS_WARN_IF(reservedClientInfo.isNothing() && initialClientInfo.isNothing() && (aLoadInfo->GetReservedClientInfo().isSome() || aLoadInfo->GetInitialClientInfo().isSome()))) { return NS_ERROR_FAILURE; } if (reservedClientInfo.isSome()) { // We need to override here instead of simply set the value. This // allows us to change the reserved client. This is necessary when // the ClientChannelHelper created a new reserved client in the // child-side of the redirect. aLoadInfo->OverrideReservedClientInfoInParent(reservedClientInfo.ref()); } else if (initialClientInfo.isSome()) { aLoadInfo->SetInitialClientInfo(initialClientInfo.ref()); } aLoadInfo->ClearController(); auto& controller = aForwarderArgs.controller(); if (controller.isSome()) { aLoadInfo->SetController(ServiceWorkerDescriptor(controller.ref())); } uint32_t blockingReason = aForwarderArgs.requestBlockingReason(); if (blockingReason) { // We only want to override when non-null, so that any earlier set non-null // value is not reverted to 0. aLoadInfo->SetRequestBlockingReason(blockingReason); } return NS_OK; } } // namespace ipc } // namespace mozilla