/* -*- 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/ContentPrincipal.h" #include "mozilla/NullPrincipal.h" #include "mozilla/ipc/PBackgroundSharedTypes.h" #include "mozilla/ipc/URIUtils.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" namespace mozilla { using mozilla::BasePrincipal; using mozilla::Maybe; using mozilla::dom::ServiceWorkerDescriptor; using namespace mozilla::net; namespace ipc { already_AddRefed PrincipalInfoToPrincipal( const PrincipalInfo& aPrincipalInfo, nsresult* aOptionalResult) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aPrincipalInfo.type() != PrincipalInfo::T__None); nsresult stackResult; nsresult& rv = aOptionalResult ? *aOptionalResult : stackResult; nsCOMPtr secMan = nsContentUtils::GetSecurityManager(); if (!secMan) { return nullptr; } nsCOMPtr principal; switch (aPrincipalInfo.type()) { case PrincipalInfo::TSystemPrincipalInfo: { rv = secMan->GetSystemPrincipal(getter_AddRefs(principal)); if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; } return principal.forget(); } 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 nullptr; } principal = NullPrincipal::Create(info.attrs(), uri); return principal.forget(); } 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 nullptr; } OriginAttributes attrs; if (info.attrs().mAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID) { attrs = info.attrs(); } principal = BasePrincipal::CreateCodebasePrincipal(uri, attrs); if (NS_WARN_IF(!principal)) { return nullptr; } // Origin must match what the_new_principal.getOrigin returns. nsAutoCString originNoSuffix; rv = principal->GetOriginNoSuffix(originNoSuffix); if (NS_WARN_IF(NS_FAILED(rv)) || !info.originNoSuffix().Equals(originNoSuffix)) { MOZ_CRASH("Origin must be available when deserialized"); } if (info.domain()) { nsCOMPtr domain; rv = NS_NewURI(getter_AddRefs(domain), *info.domain()); if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; } rv = principal->SetDomain(domain); if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; } } if (info.securityPolicies().Length() > 0) { nsCOMPtr csp = do_CreateInstance(NS_CSPCONTEXT_CONTRACTID, &rv); if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; } rv = csp->SetRequestContext(nullptr, principal); if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; } static_cast(csp.get())->SetIPCPolicies( info.securityPolicies()); principal->SetCsp(csp); } if (!info.baseDomain().IsVoid()) { nsAutoCString baseDomain; rv = principal->GetBaseDomain(baseDomain); if (NS_WARN_IF(NS_FAILED(rv)) || !info.baseDomain().Equals(baseDomain)) { MOZ_CRASH("Base domain must be available when deserialized"); } } return principal.forget(); } case PrincipalInfo::TExpandedPrincipalInfo: { const ExpandedPrincipalInfo& info = aPrincipalInfo.get_ExpandedPrincipalInfo(); nsTArray> allowlist; nsCOMPtr alPrincipal; for (uint32_t i = 0; i < info.allowlist().Length(); i++) { alPrincipal = PrincipalInfoToPrincipal(info.allowlist()[i], &rv); if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; } // append that principal to the allowlist allowlist.AppendElement(alPrincipal); } RefPtr expandedPrincipal = ExpandedPrincipal::Create(allowlist, info.attrs()); if (!expandedPrincipal) { NS_WARNING("could not instantiate expanded principal"); return nullptr; } principal = expandedPrincipal; return principal.forget(); } default: MOZ_CRASH("Unknown PrincipalInfo type!"); } MOZ_CRASH("Should never get here!"); } nsresult PopulateContentSecurityPolicies( nsIContentSecurityPolicy* aCSP, nsTArray& aPolicies) { MOZ_ASSERT(aCSP); MOZ_ASSERT(aPolicies.IsEmpty()); MOZ_ASSERT(NS_IsMainThread()); uint32_t count = 0; nsresult rv = aCSP->GetPolicyCount(&count); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } for (uint32_t i = 0; i < count; ++i) { const nsCSPPolicy* policy = aCSP->GetPolicy(i); MOZ_ASSERT(policy); nsAutoString policyString; policy->toString(policyString); aPolicies.AppendElement( ContentSecurityPolicy(policyString, policy->getReportOnlyFlag(), policy->getDeliveredViaMetaTagFlag())); } return NS_OK; } nsresult PrincipalToPrincipalInfo(nsIPrincipal* aPrincipal, PrincipalInfo* aPrincipalInfo) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aPrincipal); MOZ_ASSERT(aPrincipalInfo); if (aPrincipal->GetIsNullPrincipal()) { nsCOMPtr uri; nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (NS_WARN_IF(!uri)) { return NS_ERROR_FAILURE; } nsAutoCString spec; rv = uri->GetSpec(spec); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } *aPrincipalInfo = NullPrincipalInfo(aPrincipal->OriginAttributesRef(), spec); return NS_OK; } nsCOMPtr secMan = nsContentUtils::GetSecurityManager(); if (!secMan) { return NS_ERROR_FAILURE; } bool isSystemPrincipal; nsresult rv = secMan->IsSystemPrincipal(aPrincipal, &isSystemPrincipal); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (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); 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; } // must be a content principal nsCOMPtr uri; rv = aPrincipal->GetURI(getter_AddRefs(uri)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (NS_WARN_IF(!uri)) { return NS_ERROR_FAILURE; } nsAutoCString spec; rv = uri->GetSpec(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; } } nsCOMPtr csp; rv = aPrincipal->GetCsp(getter_AddRefs(csp)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } nsTArray policies; if (csp) { PopulateContentSecurityPolicies(csp, policies); } // This attribute is not crucial. nsCString baseDomain; if (NS_FAILED(aPrincipal->GetBaseDomain(baseDomain))) { NS_WARNING("Failed to get base domain!"); baseDomain.SetIsVoid(true); } *aPrincipalInfo = ContentPrincipalInfo(aPrincipal->OriginAttributesRef(), originNoSuffix, spec, domain, std::move(policies), baseDomain); return NS_OK; } bool IsPincipalInfoPrivate(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) { nsresult rv; nsCOMPtr principal = PrincipalInfoToPrincipal(aRHEntryInfo.principalInfo(), &rv); if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; } 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) { if (!aLoadInfo) { // if there is no loadInfo, then there is nothing to serialize *aOptionalLoadInfoArgs = Nothing(); return NS_OK; } nsresult rv = NS_OK; Maybe loadingPrincipalInfo; if (aLoadInfo->LoadingPrincipal()) { PrincipalInfo loadingPrincipalInfoTemp; rv = PrincipalToPrincipalInfo(aLoadInfo->LoadingPrincipal(), &loadingPrincipalInfoTemp); NS_ENSURE_SUCCESS(rv, rv); loadingPrincipalInfo = Some(loadingPrincipalInfoTemp); } PrincipalInfo triggeringPrincipalInfo; rv = PrincipalToPrincipalInfo(aLoadInfo->TriggeringPrincipal(), &triggeringPrincipalInfo); NS_ENSURE_SUCCESS(rv, rv); Maybe principalToInheritInfo; if (aLoadInfo->PrincipalToInherit()) { PrincipalInfo principalToInheritInfoTemp; rv = PrincipalToPrincipalInfo(aLoadInfo->PrincipalToInherit(), &principalToInheritInfoTemp); NS_ENSURE_SUCCESS(rv, rv); principalToInheritInfo = Some(principalToInheritInfoTemp); } Maybe sandboxedLoadingPrincipalInfo; if (aLoadInfo->GetLoadingSandboxed()) { PrincipalInfo sandboxedLoadingPrincipalInfoTemp; rv = PrincipalToPrincipalInfo(aLoadInfo->GetSandboxedLoadingPrincipal(), &sandboxedLoadingPrincipalInfoTemp); NS_ENSURE_SUCCESS(rv, rv); sandboxedLoadingPrincipalInfo = Some(sandboxedLoadingPrincipalInfoTemp); } Maybe topLevelPrincipalInfo; if (aLoadInfo->GetTopLevelPrincipal()) { PrincipalInfo topLevelPrincipalInfoTemp; rv = PrincipalToPrincipalInfo(aLoadInfo->GetTopLevelPrincipal(), &topLevelPrincipalInfoTemp); NS_ENSURE_SUCCESS(rv, rv); topLevelPrincipalInfo = Some(topLevelPrincipalInfoTemp); } Maybe topLevelStorageAreaPrincipalInfo; if (aLoadInfo->GetTopLevelStorageAreaPrincipal()) { PrincipalInfo topLevelStorageAreaPrincipalInfoTemp; rv = PrincipalToPrincipalInfo(aLoadInfo->GetTopLevelStorageAreaPrincipal(), &topLevelStorageAreaPrincipalInfoTemp); NS_ENSURE_SUCCESS(rv, rv); topLevelStorageAreaPrincipalInfo = Some(topLevelStorageAreaPrincipalInfoTemp); } 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); } nsTArray ancestorPrincipals; ancestorPrincipals.SetCapacity(aLoadInfo->AncestorPrincipals().Length()); for (const auto& principal : aLoadInfo->AncestorPrincipals()) { rv = PrincipalToPrincipalInfo(principal, ancestorPrincipals.AppendElement()); 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()); } OptionalIPCServiceWorkerDescriptor ipcController = mozilla::void_t(); const Maybe& controller = aLoadInfo->GetController(); if (controller.isSome()) { ipcController = controller.ref().ToIPC(); } nsAutoString cspNonce; Unused << NS_WARN_IF(NS_FAILED(aLoadInfo->GetCspNonce(cspNonce))); *aOptionalLoadInfoArgs = Some(LoadInfoArgs( loadingPrincipalInfo, triggeringPrincipalInfo, principalToInheritInfo, sandboxedLoadingPrincipalInfo, topLevelPrincipalInfo, topLevelStorageAreaPrincipalInfo, optionalResultPrincipalURI, aLoadInfo->GetSecurityFlags(), aLoadInfo->InternalContentPolicyType(), static_cast(aLoadInfo->GetTainting()), aLoadInfo->GetUpgradeInsecureRequests(), aLoadInfo->GetBrowserUpgradeInsecureRequests(), aLoadInfo->GetBrowserWouldUpgradeInsecureRequests(), aLoadInfo->GetVerifySignedContent(), aLoadInfo->GetEnforceSRI(), aLoadInfo->GetForceAllowDataURI(), aLoadInfo->GetAllowInsecureRedirectToDataURI(), aLoadInfo->GetSkipContentPolicyCheckForWebRequest(), aLoadInfo->GetForceInheritPrincipalDropped(), aLoadInfo->GetInnerWindowID(), aLoadInfo->GetOuterWindowID(), aLoadInfo->GetParentOuterWindowID(), aLoadInfo->GetTopOuterWindowID(), aLoadInfo->GetFrameOuterWindowID(), aLoadInfo->GetBrowsingContextID(), aLoadInfo->GetFrameBrowsingContextID(), aLoadInfo->GetInitialSecurityCheckDone(), aLoadInfo->GetIsInThirdPartyContext(), aLoadInfo->GetIsDocshellReload(), aLoadInfo->GetSendCSPViolationEvents(), aLoadInfo->GetOriginAttributes(), redirectChainIncludingInternalRedirects, redirectChain, ancestorPrincipals, aLoadInfo->AncestorOuterWindowIDs(), ipcClientInfo, ipcReservedClientInfo, ipcInitialClientInfo, ipcController, aLoadInfo->CorsUnsafeHeaders(), aLoadInfo->GetForcePreflight(), aLoadInfo->GetIsPreflight(), aLoadInfo->GetLoadTriggeredFromExternal(), aLoadInfo->GetServiceWorkerTaintingSynthesized(), aLoadInfo->GetDocumentHasUserInteracted(), aLoadInfo->GetDocumentHasLoaded(), cspNonce, aLoadInfo->GetIsFromProcessingFrameAttributes(), aLoadInfo->GetOpenerPolicy())); return NS_OK; } nsresult LoadInfoArgsToLoadInfo( const Maybe& aOptionalLoadInfoArgs, nsILoadInfo** outLoadInfo) { if (aOptionalLoadInfoArgs.isNothing()) { *outLoadInfo = nullptr; return NS_OK; } const LoadInfoArgs& loadInfoArgs = aOptionalLoadInfoArgs.ref(); nsresult rv = NS_OK; nsCOMPtr loadingPrincipal; if (loadInfoArgs.requestingPrincipalInfo().isSome()) { loadingPrincipal = PrincipalInfoToPrincipal( loadInfoArgs.requestingPrincipalInfo().ref(), &rv); NS_ENSURE_SUCCESS(rv, rv); } NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr triggeringPrincipal = PrincipalInfoToPrincipal(loadInfoArgs.triggeringPrincipalInfo(), &rv); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr principalToInherit; if (loadInfoArgs.principalToInheritInfo().isSome()) { principalToInherit = PrincipalInfoToPrincipal( loadInfoArgs.principalToInheritInfo().ref(), &rv); NS_ENSURE_SUCCESS(rv, rv); } nsCOMPtr sandboxedLoadingPrincipal; if (loadInfoArgs.sandboxedLoadingPrincipalInfo().isSome()) { sandboxedLoadingPrincipal = PrincipalInfoToPrincipal( loadInfoArgs.sandboxedLoadingPrincipalInfo().ref(), &rv); NS_ENSURE_SUCCESS(rv, rv); } nsCOMPtr topLevelPrincipal; if (loadInfoArgs.topLevelPrincipalInfo().isSome()) { topLevelPrincipal = PrincipalInfoToPrincipal( loadInfoArgs.topLevelPrincipalInfo().ref(), &rv); NS_ENSURE_SUCCESS(rv, rv); } nsCOMPtr topLevelStorageAreaPrincipal; if (loadInfoArgs.topLevelStorageAreaPrincipalInfo().isSome()) { topLevelStorageAreaPrincipal = PrincipalInfoToPrincipal( loadInfoArgs.topLevelStorageAreaPrincipalInfo().ref(), &rv); NS_ENSURE_SUCCESS(rv, rv); } 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; ancestorPrincipals.SetCapacity(loadInfoArgs.ancestorPrincipals().Length()); for (const PrincipalInfo& principalInfo : loadInfoArgs.ancestorPrincipals()) { nsCOMPtr ancestorPrincipal = PrincipalInfoToPrincipal(principalInfo, &rv); NS_ENSURE_SUCCESS(rv, rv); ancestorPrincipals.AppendElement(ancestorPrincipal.forget()); } 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().type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) { controller.emplace(ServiceWorkerDescriptor( loadInfoArgs.controller().get_IPCServiceWorkerDescriptor())); } RefPtr loadInfo = new mozilla::LoadInfo( loadingPrincipal, triggeringPrincipal, principalToInherit, sandboxedLoadingPrincipal, topLevelPrincipal, topLevelStorageAreaPrincipal, resultPrincipalURI, clientInfo, reservedClientInfo, initialClientInfo, controller, loadInfoArgs.securityFlags(), loadInfoArgs.contentPolicyType(), static_cast(loadInfoArgs.tainting()), loadInfoArgs.upgradeInsecureRequests(), loadInfoArgs.browserUpgradeInsecureRequests(), loadInfoArgs.browserWouldUpgradeInsecureRequests(), loadInfoArgs.verifySignedContent(), loadInfoArgs.enforceSRI(), loadInfoArgs.forceAllowDataURI(), loadInfoArgs.allowInsecureRedirectToDataURI(), loadInfoArgs.skipContentPolicyCheckForWebRequest(), loadInfoArgs.forceInheritPrincipalDropped(), loadInfoArgs.innerWindowID(), loadInfoArgs.outerWindowID(), loadInfoArgs.parentOuterWindowID(), loadInfoArgs.topOuterWindowID(), loadInfoArgs.frameOuterWindowID(), loadInfoArgs.browsingContextID(), loadInfoArgs.frameBrowsingContextID(), loadInfoArgs.initialSecurityCheckDone(), loadInfoArgs.isInThirdPartyContext(), loadInfoArgs.isDocshellReload(), loadInfoArgs.sendCSPViolationEvents(), loadInfoArgs.originAttributes(), redirectChainIncludingInternalRedirects, redirectChain, std::move(ancestorPrincipals), loadInfoArgs.ancestorOuterWindowIDs(), loadInfoArgs.corsUnsafeHeaders(), loadInfoArgs.forcePreflight(), loadInfoArgs.isPreflight(), loadInfoArgs.loadTriggeredFromExternal(), loadInfoArgs.serviceWorkerTaintingSynthesized(), loadInfoArgs.documentHasUserInteracted(), loadInfoArgs.documentHasLoaded(), loadInfoArgs.cspNonce()); if (loadInfoArgs.isFromProcessingFrameAttributes()) { loadInfo->SetIsFromProcessingFrameAttributes(); } loadInfo->SetOpenerPolicy(loadInfoArgs.openerPolicy()); loadInfo.forget(outLoadInfo); return NS_OK; } void LoadInfoToParentLoadInfoForwarder( nsILoadInfo* aLoadInfo, ParentLoadInfoForwarderArgs* aForwarderArgsOut) { if (!aLoadInfo) { *aForwarderArgsOut = ParentLoadInfoForwarderArgs( false, void_t(), nsILoadInfo::TAINTING_BASIC, false, // serviceWorkerTaintingSynthesized false, // documentHasUserInteracted false, // documentHasLoaded nsILoadInfo::OPENER_POLICY_NULL); return; } OptionalIPCServiceWorkerDescriptor ipcController = void_t(); Maybe controller(aLoadInfo->GetController()); if (controller.isSome()) { ipcController = controller.ref().ToIPC(); } uint32_t tainting = nsILoadInfo::TAINTING_BASIC; Unused << aLoadInfo->GetTainting(&tainting); nsILoadInfo::CrossOriginOpenerPolicy openerPolicy = aLoadInfo->GetOpenerPolicy(); *aForwarderArgsOut = ParentLoadInfoForwarderArgs( aLoadInfo->GetAllowInsecureRedirectToDataURI(), ipcController, tainting, aLoadInfo->GetServiceWorkerTaintingSynthesized(), aLoadInfo->GetDocumentHasUserInteracted(), aLoadInfo->GetDocumentHasLoaded(), openerPolicy); } nsresult MergeParentLoadInfoForwarder( ParentLoadInfoForwarderArgs const& aForwarderArgs, nsILoadInfo* aLoadInfo) { if (!aLoadInfo) { return NS_OK; } nsresult rv; rv = aLoadInfo->SetAllowInsecureRedirectToDataURI( aForwarderArgs.allowInsecureRedirectToDataURI()); NS_ENSURE_SUCCESS(rv, rv); aLoadInfo->ClearController(); auto& controller = aForwarderArgs.controller(); if (controller.type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) { aLoadInfo->SetController( ServiceWorkerDescriptor(controller.get_IPCServiceWorkerDescriptor())); } if (aForwarderArgs.serviceWorkerTaintingSynthesized()) { aLoadInfo->SynthesizeServiceWorkerTainting( static_cast(aForwarderArgs.tainting())); } else { aLoadInfo->MaybeIncreaseTainting(aForwarderArgs.tainting()); } MOZ_ALWAYS_SUCCEEDS( aLoadInfo->SetOpenerPolicy(aForwarderArgs.openerPolicy())); MOZ_ALWAYS_SUCCEEDS(aLoadInfo->SetDocumentHasUserInteracted( aForwarderArgs.documentHasUserInteracted())); MOZ_ALWAYS_SUCCEEDS( aLoadInfo->SetDocumentHasLoaded(aForwarderArgs.documentHasLoaded())); return NS_OK; } void LoadInfoToChildLoadInfoForwarder( nsILoadInfo* aLoadInfo, ChildLoadInfoForwarderArgs* aForwarderArgsOut) { if (!aLoadInfo) { *aForwarderArgsOut = ChildLoadInfoForwarderArgs(Nothing(), Nothing(), void_t()); return; } 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()); } OptionalIPCServiceWorkerDescriptor ipcController = void_t(); Maybe controller(aLoadInfo->GetController()); if (controller.isSome()) { ipcController = controller.ref().ToIPC(); } *aForwarderArgsOut = ChildLoadInfoForwarderArgs(ipcReserved, ipcInitial, ipcController); } nsresult MergeChildLoadInfoForwarder( const ChildLoadInfoForwarderArgs& aForwarderArgs, nsILoadInfo* aLoadInfo) { if (!aLoadInfo) { return NS_OK; } 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.type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) { aLoadInfo->SetController( ServiceWorkerDescriptor(controller.get_IPCServiceWorkerDescriptor())); } return NS_OK; } } // namespace ipc } // namespace mozilla