# HG changeset patch # User Ben Kelly # Parent e0595117ff5bda3a63a72ad7b3b8754fec4fb4f0 Bug 1467852 Align LoadInfo::mServiceWorkerTaintingSynthesized handling with other service worker fields. r=valentin diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp --- a/netwerk/base/LoadInfo.cpp +++ b/netwerk/base/LoadInfo.cpp @@ -391,17 +391,18 @@ LoadInfo::LoadInfo(const LoadInfo& rhs) rhs.mRedirectChainIncludingInternalRedirects) , mRedirectChain(rhs.mRedirectChain) , mAncestorPrincipals(rhs.mAncestorPrincipals) , mAncestorOuterWindowIDs(rhs.mAncestorOuterWindowIDs) , mCorsUnsafeHeaders(rhs.mCorsUnsafeHeaders) , mForcePreflight(rhs.mForcePreflight) , mIsPreflight(rhs.mIsPreflight) , mLoadTriggeredFromExternal(rhs.mLoadTriggeredFromExternal) - , mServiceWorkerTaintingSynthesized(rhs.mServiceWorkerTaintingSynthesized) + // mServiceWorkerTaintingSynthesized must be handled specially during redirect + , mServiceWorkerTaintingSynthesized(false) { } LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, nsIPrincipal* aTriggeringPrincipal, nsIPrincipal* aPrincipalToInherit, nsIPrincipal* aSandboxedLoadingPrincipal, nsIURI* aResultPrincipalURI, diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h --- a/netwerk/base/LoadInfo.h +++ b/netwerk/base/LoadInfo.h @@ -78,24 +78,16 @@ public: // nsBaseChannel::Redirect() already_AddRefed CloneWithNewSecFlags(nsSecurityFlags aSecurityFlags) const; // creates a copy of the loadinfo which is appropriate to use for a // separate request. I.e. not for a redirect or an inner channel, but // when a separate request is made with the same security properties. already_AddRefed CloneForNewRequest() const; - // The service worker and fetch specifications require returning the - // exact tainting level of the Response passed to FetchEvent.respondWith(). - // This method allows us to override the tainting level in that case. - // - // NOTE: This should not be used outside of service worker code! Use - // nsILoadInfo::MaybeIncreaseTainting() instead. - void SynthesizeServiceWorkerTainting(LoadTainting aTainting); - void SetIsPreflight(); void SetUpgradeInsecureRequests(); void SetBrowserUpgradeInsecureRequests(); void SetBrowserWouldUpgradeInsecureRequests(); private: // private constructor that is only allowed to be called from within // HttpChannelParent and FTPChannelParent declared as friends undeneath. diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl --- a/netwerk/base/nsILoadInfo.idl +++ b/netwerk/base/nsILoadInfo.idl @@ -39,16 +39,17 @@ native OriginAttributes(mozilla::OriginA [ref] native PrincipalArrayRef(const nsTArray>); [ref] native const_ClientInfoRef(const mozilla::dom::ClientInfo); native UniqueClientSource(mozilla::UniquePtr); native UniqueClientSourceMove(mozilla::UniquePtr&&); [ref] native const_MaybeClientInfoRef(const mozilla::Maybe); [ref] native const_ServiceWorkerDescriptorRef(const mozilla::dom::ServiceWorkerDescriptor); [ref] native const_MaybeServiceWorkerDescriptorRef(const mozilla::Maybe); [ptr] native PerformanceStoragePtr(mozilla::dom::PerformanceStorage); + native LoadTainting(mozilla::LoadTainting); typedef unsigned long nsSecurityFlags; /** * The LoadInfo object contains information about a network load, why it * was started, and how we plan on using the resulting response. * If a network request is redirected, the new channel will receive a new * LoadInfo object. The new object will contain mostly the same @@ -986,9 +987,19 @@ interface nsILoadInfo : nsISupports [noscript, nostdcall, notxpcom] void SetPerformanceStorage(in PerformanceStoragePtr aPerformanceStorage); /** * Get the PerformanceStorage. */ [noscript, nostdcall, notxpcom] PerformanceStoragePtr GetPerformanceStorage(); + + /* The service worker and fetch specifications require returning the + * exact tainting level of the Response passed to FetchEvent.respondWith(). + * This method allows us to override the tainting level in that case. + * + * NOTE: This should not be used outside of service worker code! Use + * nsILoadInfo::MaybeIncreaseTainting() instead. + */ + [noscript, nostdcall, notxpcom] + void SynthesizeServiceWorkerTainting(in LoadTainting aTainting); }; diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/HttpChannelChild.cpp --- a/netwerk/protocol/http/HttpChannelChild.cpp +++ b/netwerk/protocol/http/HttpChannelChild.cpp @@ -1803,16 +1803,20 @@ HttpChannelChild::Redirect1Begin(const u void HttpChannelChild::BeginNonIPCRedirect(nsIURI* responseURI, const nsHttpResponseHead* responseHead, bool aResponseRedirected) { LOG(("HttpChannelChild::BeginNonIPCRedirect [this=%p]\n", this)); + // This method is only used by child-side service workers. It should not be + // used by new code. We want to remove it in the future. + MOZ_DIAGNOSTIC_ASSERT(mSynthesizedResponse); + // If the response has been redirected, propagate all the URLs to content. // Thus, the exact value of the redirect flag does not matter as long as it's // not REDIRECT_INTERNAL. const uint32_t redirectFlag = aResponseRedirected ? nsIChannelEventSink::REDIRECT_TEMPORARY : nsIChannelEventSink::REDIRECT_INTERNAL; @@ -1828,16 +1832,30 @@ HttpChannelChild::BeginNonIPCRedirect(ns // is a synthesized response that has its own security info, the pre-redirect channel // has already received it and it must be propagated to the post-redirect channel. nsCOMPtr channelChild = do_QueryInterface(newChannel); if (mSecurityInfo && channelChild) { HttpChannelChild* httpChannelChild = static_cast(channelChild.get()); httpChannelChild->OverrideSecurityInfoForNonIPCRedirect(mSecurityInfo); } + // Normally we don't propagate the LoadInfo's service worker tainting + // synthesis flag on redirect. A real redirect normally will want to allow + // normal tainting to proceed from its starting taint. For this particular + // redirect, though, we are performing a redirect to communicate the URL of + // the service worker synthetic response itself. This redirect still represents + // the synthetic response, so we must preserve the flag. + if (mLoadInfo && mLoadInfo->GetServiceWorkerTaintingSynthesized()) { + nsCOMPtr newChannelLoadInfo; + Unused << newChannel->GetLoadInfo(getter_AddRefs(newChannelLoadInfo)); + if (newChannelLoadInfo) { + newChannelLoadInfo->SynthesizeServiceWorkerTainting(mLoadInfo->GetTainting()); + } + } + nsCOMPtr target = GetNeckoTarget(); MOZ_ASSERT(target); rv = gHttpHandler->AsyncOnChannelRedirect(this, newChannel, redirectFlag, target); } diff --git a/netwerk/protocol/http/InterceptedHttpChannel.cpp b/netwerk/protocol/http/InterceptedHttpChannel.cpp --- a/netwerk/protocol/http/InterceptedHttpChannel.cpp +++ b/netwerk/protocol/http/InterceptedHttpChannel.cpp @@ -267,16 +267,27 @@ InterceptedHttpChannel::RedirectForRespo uint32_t flags = aResponseRedirected ? nsIChannelEventSink::REDIRECT_TEMPORARY : nsIChannelEventSink::REDIRECT_INTERNAL; nsCOMPtr redirectLoadInfo = CloneLoadInfoForRedirect(aResponseURI, flags); newChannel->SetLoadInfo(redirectLoadInfo); NS_ENSURE_SUCCESS(rv, rv); + // Normally we don't propagate the LoadInfo's service worker tainting + // synthesis flag on redirect. A real redirect normally will want to allow + // normal tainting to proceed from its starting taint. For this particular + // redirect, though, we are performing a redirect to communicate the URL of + // the service worker synthetic response itself. This redirect still represents + // the synthetic response, so we must preserve the flag. + if (redirectLoadInfo && mLoadInfo && + mLoadInfo->GetServiceWorkerTaintingSynthesized()) { + redirectLoadInfo->SynthesizeServiceWorkerTainting(mLoadInfo->GetTainting()); + } + rv = SetupReplacementChannel(aResponseURI, newChannel, true, flags); NS_ENSURE_SUCCESS(rv, rv); mRedirectChannel = newChannel; rv = gHttpHandler->AsyncOnChannelRedirect(this, mRedirectChannel, flags); if (NS_FAILED(rv)) {