Bug 1467852 Align LoadInfo::mServiceWorkerTaintingSynthesized handling with other service worker fields. r=valentin a=abillings
authorBen Kelly <ben@wanderview.com>
Sun, 10 Jun 2018 18:44:53 -0700
changeset 473716 44883c246d62061847e07dcba4fd88f55eb45362
parent 473715 13af68f9e6d0b394945dfe041b4ef5108abfddb9
child 473717 5b5e620e33ee59c1820d1bef687f015d63c2185c
push id1728
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:12:27 +0000
treeherdermozilla-release@c296fde26f5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvalentin, abillings
bugs1467852
milestone61.0
Bug 1467852 Align LoadInfo::mServiceWorkerTaintingSynthesized handling with other service worker fields. r=valentin a=abillings
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
@@ -395,17 +395,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
@@ -998,9 +999,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
@@ -1815,16 +1815,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;
 
 
@@ -1840,16 +1844,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)) {