Bug 1467852 Align LoadInfo::mServiceWorkerTaintingSynthesized handling with other service worker fields. r=valentin
authorBen Kelly <ben@wanderview.com>
Sun, 10 Jun 2018 18:44:38 -0700
changeset 422290 29598a3b4cc09aef566178a33b3c5d7dbd36da17
parent 422289 9f1a58e8b2a7e33e2f4693ac3088f451f58c8b81
child 422291 09d892dcaca7f8700a08f14b3b075b769bd82c5d
push id34122
push userebalazs@mozilla.com
push dateMon, 11 Jun 2018 09:37:00 +0000
treeherdermozilla-central@9941eb8c3b29 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvalentin
bugs1467852
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1467852 Align LoadInfo::mServiceWorkerTaintingSynthesized handling with other service worker fields. r=valentin
netwerk/base/LoadInfo.cpp
netwerk/base/LoadInfo.h
netwerk/base/nsILoadInfo.idl
netwerk/protocol/http/HttpChannelChild.cpp
netwerk/protocol/http/InterceptedHttpChannel.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,
--- a/netwerk/base/LoadInfo.h
+++ b/netwerk/base/LoadInfo.h
@@ -78,24 +78,16 @@ public:
   // nsBaseChannel::Redirect()
   already_AddRefed<nsILoadInfo>
   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<nsILoadInfo> 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.
--- a/netwerk/base/nsILoadInfo.idl
+++ b/netwerk/base/nsILoadInfo.idl
@@ -39,16 +39,17 @@ native OriginAttributes(mozilla::OriginA
 [ref] native PrincipalArrayRef(const nsTArray<nsCOMPtr<nsIPrincipal>>);
 [ref] native const_ClientInfoRef(const mozilla::dom::ClientInfo);
       native UniqueClientSource(mozilla::UniquePtr<mozilla::dom::ClientSource>);
       native UniqueClientSourceMove(mozilla::UniquePtr<mozilla::dom::ClientSource>&&);
 [ref] native const_MaybeClientInfoRef(const mozilla::Maybe<mozilla::dom::ClientInfo>);
 [ref] native const_ServiceWorkerDescriptorRef(const mozilla::dom::ServiceWorkerDescriptor);
 [ref] native const_MaybeServiceWorkerDescriptorRef(const mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor>);
 [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);
 };
--- 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<nsIHttpChannelChild> channelChild = do_QueryInterface(newChannel);
     if (mSecurityInfo && channelChild) {
       HttpChannelChild* httpChannelChild = static_cast<HttpChannelChild*>(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<nsILoadInfo> newChannelLoadInfo;
+      Unused << newChannel->GetLoadInfo(getter_AddRefs(newChannelLoadInfo));
+      if (newChannelLoadInfo) {
+        newChannelLoadInfo->SynthesizeServiceWorkerTainting(mLoadInfo->GetTainting());
+      }
+    }
+
     nsCOMPtr<nsIEventTarget> target = GetNeckoTarget();
     MOZ_ASSERT(target);
 
     rv = gHttpHandler->AsyncOnChannelRedirect(this,
                                               newChannel,
                                               redirectFlag,
                                               target);
   }
--- 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<nsILoadInfo> 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)) {