Browse Source

More serviceworker backports

Ian Neal 5 months ago
parent
commit
42734a7d95
29 changed files with 5576 additions and 57 deletions
  1. 259 0
      mozilla-release/patches/1231211-01-60a1.patch
  2. 542 0
      mozilla-release/patches/1231211-02-60a1.patch
  3. 266 0
      mozilla-release/patches/1231211-03-60a1.patch
  4. 32 0
      mozilla-release/patches/1231211-04-60a1.patch
  5. 63 0
      mozilla-release/patches/1231211-05-60a1.patch
  6. 36 0
      mozilla-release/patches/1231211-06-60a1.patch
  7. 112 0
      mozilla-release/patches/1231211-07-60a1.patch
  8. 57 0
      mozilla-release/patches/1231211-08-60a1.patch
  9. 421 0
      mozilla-release/patches/1231211-09-60a1.patch
  10. 296 0
      mozilla-release/patches/1231211-10-60a1.patch
  11. 253 0
      mozilla-release/patches/1231211-11-60a1.patch
  12. 1025 0
      mozilla-release/patches/1231211-12-60a1.patch
  13. 334 0
      mozilla-release/patches/1231211-13-60a1.patch
  14. 188 0
      mozilla-release/patches/1231211-14-60a1.patch
  15. 216 0
      mozilla-release/patches/1231211-15no16-60a1.patch
  16. 56 0
      mozilla-release/patches/1231211-17-60a1.patch
  17. 162 0
      mozilla-release/patches/1231211-18-60a1.patch
  18. 64 0
      mozilla-release/patches/1231211-19-60a1.patch
  19. 42 0
      mozilla-release/patches/1231211-20-60a1.patch
  20. 14 14
      mozilla-release/patches/1252998-04-61a1.patch
  21. 60 0
      mozilla-release/patches/1424300-1-59a1.patch
  22. 162 0
      mozilla-release/patches/1424300-2-59a1.patch
  23. 157 0
      mozilla-release/patches/1424300-3-59a1.patch
  24. 421 0
      mozilla-release/patches/1424571-59a1.patch
  25. 61 0
      mozilla-release/patches/1431814-1no2-60a1.patch
  26. 171 0
      mozilla-release/patches/1432640-60a1.patch
  27. 3 3
      mozilla-release/patches/1440511-01-60a1.patch
  28. 78 40
      mozilla-release/patches/1465585-3-std-62a1.patch
  29. 25 0
      mozilla-release/patches/series

+ 259 - 0
mozilla-release/patches/1231211-01-60a1.patch

@@ -0,0 +1,259 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1516721931 18000
+# Node ID d1567cc8c742e7c48fcedee3c735e9507c6dbc5c
+# Parent  3cf2f2eb5675766e5e285e7765bcdc4769e91f68
+Bug 1231211 P1 Allow docshell reload state to be set on LoadInfo. r=valentin
+
+diff --git a/ipc/glue/BackgroundUtils.cpp b/ipc/glue/BackgroundUtils.cpp
+--- a/ipc/glue/BackgroundUtils.cpp
++++ b/ipc/glue/BackgroundUtils.cpp
+@@ -384,16 +384,17 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoa
+       aLoadInfo->GetInnerWindowID(),
+       aLoadInfo->GetOuterWindowID(),
+       aLoadInfo->GetParentOuterWindowID(),
+       aLoadInfo->GetTopOuterWindowID(),
+       aLoadInfo->GetFrameOuterWindowID(),
+       aLoadInfo->GetEnforceSecurity(),
+       aLoadInfo->GetInitialSecurityCheckDone(),
+       aLoadInfo->GetIsInThirdPartyContext(),
++      aLoadInfo->GetIsDocshellReload(),
+       aLoadInfo->GetOriginAttributes(),
+       redirectChainIncludingInternalRedirects,
+       redirectChain,
+       ancestorPrincipals,
+       aLoadInfo->AncestorOuterWindowIDs(),
+       aLoadInfo->CorsUnsafeHeaders(),
+       aLoadInfo->GetForcePreflight(),
+       aLoadInfo->GetIsPreflight(),
+@@ -490,16 +491,17 @@ LoadInfoArgsToLoadInfo(const OptionalLoa
+                           loadInfoArgs.innerWindowID(),
+                           loadInfoArgs.outerWindowID(),
+                           loadInfoArgs.parentOuterWindowID(),
+                           loadInfoArgs.topOuterWindowID(),
+                           loadInfoArgs.frameOuterWindowID(),
+                           loadInfoArgs.enforceSecurity(),
+                           loadInfoArgs.initialSecurityCheckDone(),
+                           loadInfoArgs.isInThirdPartyContext(),
++                          loadInfoArgs.isDocshellReload(),
+                           loadInfoArgs.originAttributes(),
+                           redirectChainIncludingInternalRedirects,
+                           redirectChain,
+                           Move(ancestorPrincipals),
+                           loadInfoArgs.ancestorOuterWindowIDs(),
+                           loadInfoArgs.corsUnsafeHeaders(),
+                           loadInfoArgs.forcePreflight(),
+                           loadInfoArgs.isPreflight(),
+diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp
+--- a/netwerk/base/LoadInfo.cpp
++++ b/netwerk/base/LoadInfo.cpp
+@@ -65,16 +65,17 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadin
+   , mInnerWindowID(0)
+   , mOuterWindowID(0)
+   , mParentOuterWindowID(0)
+   , mTopOuterWindowID(0)
+   , mFrameOuterWindowID(0)
+   , mEnforceSecurity(false)
+   , mInitialSecurityCheckDone(false)
+   , mIsThirdPartyContext(false)
++  , mIsDocshellReload(false)
+   , mForcePreflight(false)
+   , mIsPreflight(false)
+   , mLoadTriggeredFromExternal(false)
+   , mServiceWorkerTaintingSynthesized(false)
+ {
+   MOZ_ASSERT(mLoadingPrincipal);
+   MOZ_ASSERT(mTriggeringPrincipal);
+ 
+@@ -251,16 +252,17 @@ LoadInfo::LoadInfo(nsPIDOMWindowOuter* a
+   , mInnerWindowID(0)
+   , mOuterWindowID(0)
+   , mParentOuterWindowID(0)
+   , mTopOuterWindowID(0)
+   , mFrameOuterWindowID(0)
+   , mEnforceSecurity(false)
+   , mInitialSecurityCheckDone(false)
+   , mIsThirdPartyContext(false) // NB: TYPE_DOCUMENT implies not third-party.
++  , mIsDocshellReload(false)
+   , mForcePreflight(false)
+   , mIsPreflight(false)
+   , mLoadTriggeredFromExternal(false)
+   , mServiceWorkerTaintingSynthesized(false)
+ {
+   // Top-level loads are never third-party
+   // Grab the information we can out of the window.
+   MOZ_ASSERT(aOuterWindow);
+@@ -322,16 +324,17 @@ LoadInfo::LoadInfo(const LoadInfo& rhs)
+   , mInnerWindowID(rhs.mInnerWindowID)
+   , mOuterWindowID(rhs.mOuterWindowID)
+   , mParentOuterWindowID(rhs.mParentOuterWindowID)
+   , mTopOuterWindowID(rhs.mTopOuterWindowID)
+   , mFrameOuterWindowID(rhs.mFrameOuterWindowID)
+   , mEnforceSecurity(rhs.mEnforceSecurity)
+   , mInitialSecurityCheckDone(rhs.mInitialSecurityCheckDone)
+   , mIsThirdPartyContext(rhs.mIsThirdPartyContext)
++  , mIsDocshellReload(rhs.mIsDocshellReload)
+   , mOriginAttributes(rhs.mOriginAttributes)
+   , mRedirectChainIncludingInternalRedirects(
+       rhs.mRedirectChainIncludingInternalRedirects)
+   , mRedirectChain(rhs.mRedirectChain)
+   , mAncestorPrincipals(rhs.mAncestorPrincipals)
+   , mAncestorOuterWindowIDs(rhs.mAncestorOuterWindowIDs)
+   , mCorsUnsafeHeaders(rhs.mCorsUnsafeHeaders)
+   , mForcePreflight(rhs.mForcePreflight)
+@@ -357,16 +360,17 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadin
+                    uint64_t aInnerWindowID,
+                    uint64_t aOuterWindowID,
+                    uint64_t aParentOuterWindowID,
+                    uint64_t aTopOuterWindowID,
+                    uint64_t aFrameOuterWindowID,
+                    bool aEnforceSecurity,
+                    bool aInitialSecurityCheckDone,
+                    bool aIsThirdPartyContext,
++                   bool aIsDocshellReload,
+                    const OriginAttributes& aOriginAttributes,
+                    RedirectHistoryArray& aRedirectChainIncludingInternalRedirects,
+                    RedirectHistoryArray& aRedirectChain,
+                    nsTArray<nsCOMPtr<nsIPrincipal>>&& aAncestorPrincipals,
+                    const nsTArray<uint64_t>& aAncestorOuterWindowIDs,
+                    const nsTArray<nsCString>& aCorsUnsafeHeaders,
+                    bool aForcePreflight,
+                    bool aIsPreflight,
+@@ -387,16 +391,17 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadin
+   , mInnerWindowID(aInnerWindowID)
+   , mOuterWindowID(aOuterWindowID)
+   , mParentOuterWindowID(aParentOuterWindowID)
+   , mTopOuterWindowID(aTopOuterWindowID)
+   , mFrameOuterWindowID(aFrameOuterWindowID)
+   , mEnforceSecurity(aEnforceSecurity)
+   , mInitialSecurityCheckDone(aInitialSecurityCheckDone)
+   , mIsThirdPartyContext(aIsThirdPartyContext)
++  , mIsDocshellReload(aIsDocshellReload)
+   , mOriginAttributes(aOriginAttributes)
+   , mAncestorPrincipals(Move(aAncestorPrincipals))
+   , mAncestorOuterWindowIDs(aAncestorOuterWindowIDs)
+   , mCorsUnsafeHeaders(aCorsUnsafeHeaders)
+   , mForcePreflight(aForcePreflight)
+   , mIsPreflight(aIsPreflight)
+   , mLoadTriggeredFromExternal(aLoadTriggeredFromExternal)
+   , mServiceWorkerTaintingSynthesized(aServiceWorkerTaintingSynthesized)
+@@ -716,16 +721,30 @@ NS_IMETHODIMP
+ LoadInfo::GetLoadErrorPage(bool* aResult)
+ {
+   *aResult =
+     (mSecurityFlags & nsILoadInfo::SEC_LOAD_ERROR_PAGE);
+   return NS_OK;
+ }
+ 
+ NS_IMETHODIMP
++LoadInfo::GetIsDocshellReload(bool* aResult)
++{
++  *aResult = mIsDocshellReload;
++  return NS_OK;
++}
++
++NS_IMETHODIMP
++LoadInfo::SetIsDocshellReload(bool aValue)
++{
++  mIsDocshellReload = aValue;
++  return NS_OK;
++}
++
++NS_IMETHODIMP
+ LoadInfo::GetExternalContentPolicyType(nsContentPolicyType* aResult)
+ {
+   *aResult = nsContentUtils::InternalContentPolicyTypeToExternal(mInternalContentPolicyType);
+   return NS_OK;
+ }
+ 
+ nsContentPolicyType
+ LoadInfo::InternalContentPolicyType()
+diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h
+--- a/netwerk/base/LoadInfo.h
++++ b/netwerk/base/LoadInfo.h
+@@ -110,16 +110,17 @@ private:
+            uint64_t aInnerWindowID,
+            uint64_t aOuterWindowID,
+            uint64_t aParentOuterWindowID,
+            uint64_t aTopOuterWindowID,
+            uint64_t aFrameOuterWindowID,
+            bool aEnforceSecurity,
+            bool aInitialSecurityCheckDone,
+            bool aIsThirdPartyRequest,
++           bool aIsDocshellReload,
+            const OriginAttributes& aOriginAttributes,
+            RedirectHistoryArray& aRedirectChainIncludingInternalRedirects,
+            RedirectHistoryArray& aRedirectChain,
+            nsTArray<nsCOMPtr<nsIPrincipal>>&& aAncestorPrincipals,
+            const nsTArray<uint64_t>& aAncestorOuterWindowIDs,
+            const nsTArray<nsCString>& aUnsafeHeaders,
+            bool aForcePreflight,
+            bool aIsPreflight,
+@@ -171,16 +172,17 @@ private:
+   uint64_t                         mInnerWindowID;
+   uint64_t                         mOuterWindowID;
+   uint64_t                         mParentOuterWindowID;
+   uint64_t                         mTopOuterWindowID;
+   uint64_t                         mFrameOuterWindowID;
+   bool                             mEnforceSecurity;
+   bool                             mInitialSecurityCheckDone;
+   bool                             mIsThirdPartyContext;
++  bool                             mIsDocshellReload;
+   OriginAttributes                 mOriginAttributes;
+   RedirectHistoryArray             mRedirectChainIncludingInternalRedirects;
+   RedirectHistoryArray             mRedirectChain;
+   nsTArray<nsCOMPtr<nsIPrincipal>> mAncestorPrincipals;
+   nsTArray<uint64_t>               mAncestorOuterWindowIDs;
+   nsTArray<nsCString>              mCorsUnsafeHeaders;
+   bool                             mForcePreflight;
+   bool                             mIsPreflight;
+diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl
+--- a/netwerk/base/nsILoadInfo.idl
++++ b/netwerk/base/nsILoadInfo.idl
+@@ -474,16 +474,25 @@ interface nsILoadInfo : nsISupports
+   [infallible] readonly attribute boolean dontFollowRedirects;
+ 
+   /**
+    * Returns true if SEC_LOAD_ERROR_PAGE is set.
+    */
+   [infallible] readonly attribute boolean loadErrorPage;
+ 
+   /**
++   * Returns true if this is a non-subresource request that was triggered
++   * by docshell with the LOAD_CMD_RELOAD flag set.  Note, this is more
++   * specific than looking at the load flags which indicate whether to
++   * bypass the http cache.  The load flags can be set for other reasons,
++   * so they can't be used to infer this value.
++   */
++  [infallible] attribute boolean isDocshellReload;
++
++  /**
+    * The external contentPolicyType of the channel, used for security checks
+    * like Mixed Content Blocking and Content Security Policy.
+    *
+    * Specifically, content policy types with _INTERNAL_ in their name will
+    * never get returned from this attribute.
+    */
+   readonly attribute nsContentPolicyType externalContentPolicyType;
+ 
+diff --git a/netwerk/ipc/NeckoChannelParams.ipdlh b/netwerk/ipc/NeckoChannelParams.ipdlh
+--- a/netwerk/ipc/NeckoChannelParams.ipdlh
++++ b/netwerk/ipc/NeckoChannelParams.ipdlh
+@@ -52,16 +52,17 @@ struct LoadInfoArgs
+   uint64_t                    innerWindowID;
+   uint64_t                    outerWindowID;
+   uint64_t                    parentOuterWindowID;
+   uint64_t                    topOuterWindowID;
+   uint64_t                    frameOuterWindowID;
+   bool                        enforceSecurity;
+   bool                        initialSecurityCheckDone;
+   bool                        isInThirdPartyContext;
++  bool                        isDocshellReload;
+   OriginAttributes            originAttributes;
+   RedirectHistoryEntryInfo[]  redirectChainIncludingInternalRedirects;
+   RedirectHistoryEntryInfo[]  redirectChain;
+ 
+   /**
+    * Ancestor data for use with the WebRequest API.
+    * See nsILoadInfo.idl for details.
+    */

+ 542 - 0
mozilla-release/patches/1231211-02-60a1.patch

@@ -0,0 +1,542 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1516721932 18000
+# Node ID 3539077ab9a7869cd92c52beabf95ea029ec6072
+# Parent  1acb9fa2bb1ab1c8e71c727fba8d1e80e403c51d
+Bug 1231211 P2 Pass the controller ServiceWorkerDescriptor on the channel LoadInfo and back in PHttpChannel's OnStartRequest message. r=valentin
+
+diff --git a/dom/workers/IPCServiceWorkerDescriptor.ipdlh b/dom/workers/IPCServiceWorkerDescriptor.ipdlh
+--- a/dom/workers/IPCServiceWorkerDescriptor.ipdlh
++++ b/dom/workers/IPCServiceWorkerDescriptor.ipdlh
+@@ -15,10 +15,16 @@ namespace dom {
+ struct IPCServiceWorkerDescriptor
+ {
+   uint64_t id;
+   PrincipalInfo principalInfo;
+   nsCString scope;
+   ServiceWorkerState state;
+ };
+ 
++union OptionalIPCServiceWorkerDescriptor
++{
++  IPCServiceWorkerDescriptor;
++  void_t;
++};
++
+ } // namespace dom
+ } // namespace mozilla
+diff --git a/ipc/glue/BackgroundUtils.cpp b/ipc/glue/BackgroundUtils.cpp
+--- a/ipc/glue/BackgroundUtils.cpp
++++ b/ipc/glue/BackgroundUtils.cpp
+@@ -26,16 +26,18 @@
+ #include "URIUtils.h"
+ 
+ namespace mozilla {
+ namespace net {
+ class OptionalLoadInfoArgs;
+ }
+ 
+ using mozilla::BasePrincipal;
++using mozilla::Maybe;
++using mozilla::dom::ServiceWorkerDescriptor;
+ using namespace mozilla::net;
+ 
+ namespace ipc {
+ 
+ already_AddRefed<nsIPrincipal>
+ PrincipalInfoToPrincipal(const PrincipalInfo& aPrincipalInfo,
+                          nsresult* aOptionalResult)
+ {
+@@ -361,16 +363,22 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoa
+ 
+   nsTArray<PrincipalInfo> ancestorPrincipals;
+   ancestorPrincipals.SetCapacity(aLoadInfo->AncestorPrincipals().Length());
+   for (const auto& principal : aLoadInfo->AncestorPrincipals()) {
+     rv = PrincipalToPrincipalInfo(principal, ancestorPrincipals.AppendElement());
+     NS_ENSURE_SUCCESS(rv, rv);
+   }
+ 
++  OptionalIPCServiceWorkerDescriptor ipcController = mozilla::void_t();
++  const Maybe<ServiceWorkerDescriptor>& controller = aLoadInfo->GetController();
++  if (controller.isSome()) {
++    ipcController = controller.ref().ToIPC();
++  }
++
+   *aOptionalLoadInfoArgs =
+     LoadInfoArgs(
+       loadingPrincipalInfo,
+       triggeringPrincipalInfo,
+       principalToInheritInfo,
+       sandboxedLoadingPrincipalInfo,
+       optionalResultPrincipalURI,
+       aLoadInfo->GetSecurityFlags(),
+@@ -390,16 +398,17 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoa
+       aLoadInfo->GetInitialSecurityCheckDone(),
+       aLoadInfo->GetIsInThirdPartyContext(),
+       aLoadInfo->GetIsDocshellReload(),
+       aLoadInfo->GetOriginAttributes(),
+       redirectChainIncludingInternalRedirects,
+       redirectChain,
+       ancestorPrincipals,
+       aLoadInfo->AncestorOuterWindowIDs(),
++      ipcController,
+       aLoadInfo->CorsUnsafeHeaders(),
+       aLoadInfo->GetForcePreflight(),
+       aLoadInfo->GetIsPreflight(),
+       aLoadInfo->GetLoadTriggeredFromExternal(),
+       aLoadInfo->GetServiceWorkerTaintingSynthesized()
+       );
+ 
+   return NS_OK;
+@@ -469,22 +478,29 @@ LoadInfoArgsToLoadInfo(const OptionalLoa
+   ancestorPrincipals.SetCapacity(loadInfoArgs.ancestorPrincipals().Length());
+   for (const PrincipalInfo& principalInfo : loadInfoArgs.ancestorPrincipals()) {
+     nsCOMPtr<nsIPrincipal> ancestorPrincipal =
+       PrincipalInfoToPrincipal(principalInfo, &rv);
+     NS_ENSURE_SUCCESS(rv, rv);
+     ancestorPrincipals.AppendElement(ancestorPrincipal.forget());
+   }
+ 
++  Maybe<ServiceWorkerDescriptor> controller;
++  if (loadInfoArgs.controller().type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) {
++    controller.emplace(ServiceWorkerDescriptor(
++      loadInfoArgs.controller().get_IPCServiceWorkerDescriptor()));
++  }
++
+   nsCOMPtr<nsILoadInfo> loadInfo =
+     new mozilla::LoadInfo(loadingPrincipal,
+                           triggeringPrincipal,
+                           principalToInherit,
+                           sandboxedLoadingPrincipal,
+                           resultPrincipalURI,
++                          controller,
+                           loadInfoArgs.securityFlags(),
+                           loadInfoArgs.contentPolicyType(),
+                           static_cast<LoadTainting>(loadInfoArgs.tainting()),
+                           loadInfoArgs.upgradeInsecureRequests(),
+                           loadInfoArgs.verifySignedContent(),
+                           loadInfoArgs.enforceSRI(),
+                           loadInfoArgs.forceAllowDataURI(),
+                           loadInfoArgs.forceInheritPrincipalDropped(),
+diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp
+--- a/netwerk/base/LoadInfo.cpp
++++ b/netwerk/base/LoadInfo.cpp
+@@ -344,16 +344,17 @@ LoadInfo::LoadInfo(const LoadInfo& rhs)
+ {
+ }
+ 
+ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
+                    nsIPrincipal* aTriggeringPrincipal,
+                    nsIPrincipal* aPrincipalToInherit,
+                    nsIPrincipal* aSandboxedLoadingPrincipal,
+                    nsIURI* aResultPrincipalURI,
++                   const Maybe<ServiceWorkerDescriptor>& aController,
+                    nsSecurityFlags aSecurityFlags,
+                    nsContentPolicyType aContentPolicyType,
+                    LoadTainting aTainting,
+                    bool aUpgradeInsecureRequests,
+                    bool aVerifySignedContent,
+                    bool aEnforceSRI,
+                    bool aForceAllowDataURI,
+                    bool aForceInheritPrincipalDropped,
+@@ -375,16 +376,17 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadin
+                    bool aForcePreflight,
+                    bool aIsPreflight,
+                    bool aLoadTriggeredFromExternal,
+                    bool aServiceWorkerTaintingSynthesized)
+   : mLoadingPrincipal(aLoadingPrincipal)
+   , mTriggeringPrincipal(aTriggeringPrincipal)
+   , mPrincipalToInherit(aPrincipalToInherit)
+   , mResultPrincipalURI(aResultPrincipalURI)
++  , mController(aController)
+   , mSecurityFlags(aSecurityFlags)
+   , mInternalContentPolicyType(aContentPolicyType)
+   , mTainting(aTainting)
+   , mUpgradeInsecureRequests(aUpgradeInsecureRequests)
+   , mVerifySignedContent(aVerifySignedContent)
+   , mEnforceSRI(aEnforceSRI)
+   , mForceAllowDataURI(aForceAllowDataURI)
+   , mForceInheritPrincipalDropped(aForceInheritPrincipalDropped)
+diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h
+--- a/netwerk/base/LoadInfo.h
++++ b/netwerk/base/LoadInfo.h
+@@ -94,16 +94,17 @@ private:
+   // HttpChannelParent and FTPChannelParent declared as friends undeneath.
+   // In e10s we can not serialize nsINode, hence we store the innerWindowID.
+   // Please note that aRedirectChain uses swapElements.
+   LoadInfo(nsIPrincipal* aLoadingPrincipal,
+            nsIPrincipal* aTriggeringPrincipal,
+            nsIPrincipal* aPrincipalToInherit,
+            nsIPrincipal* aSandboxedLoadingPrincipal,
+            nsIURI* aResultPrincipalURI,
++           const Maybe<mozilla::dom::ServiceWorkerDescriptor>& aController,
+            nsSecurityFlags aSecurityFlags,
+            nsContentPolicyType aContentPolicyType,
+            LoadTainting aTainting,
+            bool aUpgradeInsecureRequests,
+            bool aVerifySignedContent,
+            bool aEnforceSRI,
+            bool aForceAllowDataURI,
+            bool aForceInheritPrincipalDropped,
+diff --git a/netwerk/ipc/NeckoChannelParams.ipdlh b/netwerk/ipc/NeckoChannelParams.ipdlh
+--- a/netwerk/ipc/NeckoChannelParams.ipdlh
++++ b/netwerk/ipc/NeckoChannelParams.ipdlh
+@@ -5,16 +5,17 @@
+  * 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 protocol PHttpChannel;
+ include protocol PFTPChannel;
+ include protocol PChildToParentStream;
+ include BlobTypes;
+ include URIParams;
++include IPCServiceWorkerDescriptor;
+ include IPCStream;
+ include PBackgroundSharedTypes;
+ 
+ using mozilla::OriginAttributes from "mozilla/ipc/BackgroundUtils.h";
+ using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
+ using RequestHeaderTuples from "mozilla/net/PHttpChannelParams.h";
+ using struct nsHttpAtom from "nsHttp.h";
+ using class nsHttpResponseHead from "nsHttpResponseHead.h";
+@@ -64,16 +65,23 @@ struct LoadInfoArgs
+ 
+   /**
+    * Ancestor data for use with the WebRequest API.
+    * See nsILoadInfo.idl for details.
+    */
+   PrincipalInfo[]             ancestorPrincipals;
+   uint64_t[]                  ancestorOuterWindowIDs;
+ 
++  /**
++   * Subresource loads may have a controller set based on their owning
++   * window/worker client.  We must send this across IPC to support
++   * performing interception in the parent.
++   */
++  OptionalIPCServiceWorkerDescriptor controller;
++
+   nsCString[]                 corsUnsafeHeaders;
+   bool                        forcePreflight;
+   bool                        isPreflight;
+   bool                        loadTriggeredFromExternal;
+   bool                        serviceWorkerTaintingSynthesized;
+ };
+ 
+ /**
+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
+@@ -429,17 +429,18 @@ class StartRequestEvent : public NeckoTa
+                     const int32_t& aCacheFetchCount,
+                     const uint32_t& aCacheExpirationTime,
+                     const nsCString& aCachedCharset,
+                     const nsCString& aSecurityInfoSerialization,
+                     const NetAddr& aSelfAddr,
+                     const NetAddr& aPeerAddr,
+                     const uint32_t& aCacheKey,
+                     const nsCString& altDataType,
+-                    const int64_t& altDataLen)
++                    const int64_t& altDataLen,
++                    Maybe<ServiceWorkerDescriptor>&& aController)
+   : NeckoTargetChannelEvent<HttpChannelChild>(aChild)
+   , mChannelStatus(aChannelStatus)
+   , mResponseHead(aResponseHead)
+   , mRequestHeaders(aRequestHeaders)
+   , mUseResponseHead(aUseResponseHead)
+   , mIsFromCache(aIsFromCache)
+   , mCacheEntryAvailable(aCacheEntryAvailable)
+   , mCacheEntryId(aCacheEntryId)
+@@ -447,27 +448,29 @@ class StartRequestEvent : public NeckoTa
+   , mCacheExpirationTime(aCacheExpirationTime)
+   , mCachedCharset(aCachedCharset)
+   , mSecurityInfoSerialization(aSecurityInfoSerialization)
+   , mSelfAddr(aSelfAddr)
+   , mPeerAddr(aPeerAddr)
+   , mCacheKey(aCacheKey)
+   , mAltDataType(altDataType)
+   , mAltDataLen(altDataLen)
++  , mController(Move(aController))
+   {}
+ 
+   void Run() override
+   {
+     LOG(("StartRequestEvent [this=%p]\n", mChild));
+     mChild->OnStartRequest(mChannelStatus, mResponseHead, mUseResponseHead,
+                            mRequestHeaders, mIsFromCache, mCacheEntryAvailable,
+                            mCacheEntryId, mCacheFetchCount,
+                            mCacheExpirationTime, mCachedCharset,
+                            mSecurityInfoSerialization, mSelfAddr, mPeerAddr,
+-                           mCacheKey, mAltDataType, mAltDataLen);
++                           mCacheKey, mAltDataType, mAltDataLen,
++                           mController);
+   }
+ 
+  private:
+   nsresult mChannelStatus;
+   nsHttpResponseHead mResponseHead;
+   nsHttpHeaderArray mRequestHeaders;
+   bool mUseResponseHead;
+   bool mIsFromCache;
+@@ -477,16 +480,17 @@ class StartRequestEvent : public NeckoTa
+   uint32_t mCacheExpirationTime;
+   nsCString mCachedCharset;
+   nsCString mSecurityInfoSerialization;
+   NetAddr mSelfAddr;
+   NetAddr mPeerAddr;
+   uint32_t mCacheKey;
+   nsCString mAltDataType;
+   int64_t mAltDataLen;
++  Maybe<ServiceWorkerDescriptor> mController;
+ };
+ 
+ mozilla::ipc::IPCResult
+ HttpChannelChild::RecvOnStartRequest(const nsresult& channelStatus,
+                                      const nsHttpResponseHead& responseHead,
+                                      const bool& useResponseHead,
+                                      const nsHttpHeaderArray& requestHeaders,
+                                      const bool& isFromCache,
+@@ -496,37 +500,44 @@ HttpChannelChild::RecvOnStartRequest(con
+                                      const uint32_t& cacheExpirationTime,
+                                      const nsCString& cachedCharset,
+                                      const nsCString& securityInfoSerialization,
+                                      const NetAddr& selfAddr,
+                                      const NetAddr& peerAddr,
+                                      const int16_t& redirectCount,
+                                      const uint32_t& cacheKey,
+                                      const nsCString& altDataType,
+-                                     const int64_t& altDataLen)
++                                     const int64_t& altDataLen,
++                                     const OptionalIPCServiceWorkerDescriptor& aController)
+ {
+   LOG(("HttpChannelChild::RecvOnStartRequest [this=%p]\n", this));
+   // mFlushedForDiversion and mDivertingToParent should NEVER be set at this
+   // stage, as they are set in the listener's OnStartRequest.
+   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
+     "mFlushedForDiversion should be unset before OnStartRequest!");
+   MOZ_RELEASE_ASSERT(!mDivertingToParent,
+     "mDivertingToParent should be unset before OnStartRequest!");
+ 
+ 
+   mRedirectCount = redirectCount;
++  Maybe<ServiceWorkerDescriptor> controller;
++  if (aController.type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) {
++    controller.emplace(ServiceWorkerDescriptor(
++      aController.get_IPCServiceWorkerDescriptor()));
++  }
+ 
+   mEventQ->RunOrEnqueue(new StartRequestEvent(this, channelStatus, responseHead,
+                                               useResponseHead, requestHeaders,
+                                               isFromCache, cacheEntryAvailable,
+                                               cacheEntryId, cacheFetchCount,
+                                               cacheExpirationTime, cachedCharset,
+                                               securityInfoSerialization,
+                                               selfAddr, peerAddr, cacheKey,
+-                                              altDataType, altDataLen));
++                                              altDataType, altDataLen,
++                                              Move(controller)));
+ 
+   {
+     // Child's mEventQ is to control the execution order of the IPC messages
+     // from both main thread IPDL and PBackground IPDL.
+     // To guarantee the ordering, PBackground IPC messages that are sent after
+     // OnStartRequest will be throttled until OnStartRequest hits the Child's
+     // mEventQ.
+     MutexAutoLock lock(mBgChildMutex);
+@@ -556,17 +567,18 @@ HttpChannelChild::OnStartRequest(const n
+                                  const int32_t& cacheFetchCount,
+                                  const uint32_t& cacheExpirationTime,
+                                  const nsCString& cachedCharset,
+                                  const nsCString& securityInfoSerialization,
+                                  const NetAddr& selfAddr,
+                                  const NetAddr& peerAddr,
+                                  const uint32_t& cacheKey,
+                                  const nsCString& altDataType,
+-                                 const int64_t& altDataLen)
++                                 const int64_t& altDataLen,
++                                 const Maybe<ServiceWorkerDescriptor>& aController)
+ {
+   LOG(("HttpChannelChild::OnStartRequest [this=%p]\n", this));
+ 
+   // mFlushedForDiversion and mDivertingToParent should NEVER be set at this
+   // stage, as they are set in the listener's OnStartRequest.
+   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
+     "mFlushedForDiversion should be unset before OnStartRequest!");
+   MOZ_RELEASE_ASSERT(!mDivertingToParent,
+@@ -591,16 +603,36 @@ HttpChannelChild::OnStartRequest(const n
+   mCacheExpirationTime = cacheExpirationTime;
+   mCachedCharset = cachedCharset;
+   mSelfAddr = selfAddr;
+   mPeerAddr = peerAddr;
+ 
+   mAvailableCachedAltDataType = altDataType;
+   mAltDataLength = altDataLen;
+ 
++  const Maybe<ServiceWorkerDescriptor>& prevController =
++    mLoadInfo->GetController();
++
++  // If we got a service worker controller from the parent, then note
++  // it on the LoadInfo.  This may indicate that a non-subresource request
++  // was intercepted and the resulting window/worker should be controlled.
++  if (aController.isSome() && prevController.isNothing()) {
++    mLoadInfo->SetController(aController.ref());
++  }
++
++  // If we did not set a controller, then verify it was either because:
++  //  1. Neither the parent or child know about a controlling service worker.
++  //  2. The parent and child both have the same controlling service worker.
++  else {
++    MOZ_DIAGNOSTIC_ASSERT((prevController.isNothing() && aController.isNothing()) ||
++                          (prevController.ref().Id() == aController.ref().Id() &&
++                           prevController.ref().Scope() == aController.ref().Scope() &&
++                           prevController.ref().PrincipalInfo() == aController.ref().PrincipalInfo()));
++  }
++
+   mAfterOnStartRequestBegun = true;
+ 
+   AutoEventEnqueuer ensureSerialDispatch(mEventQ);
+ 
+   nsresult rv;
+   nsCOMPtr<nsISupportsPRUint32> container =
+     do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv);
+   if (NS_FAILED(rv)) {
+diff --git a/netwerk/protocol/http/HttpChannelChild.h b/netwerk/protocol/http/HttpChannelChild.h
+--- a/netwerk/protocol/http/HttpChannelChild.h
++++ b/netwerk/protocol/http/HttpChannelChild.h
+@@ -136,17 +136,18 @@ protected:
+                                              const uint32_t& cacheExpirationTime,
+                                              const nsCString& cachedCharset,
+                                              const nsCString& securityInfoSerialization,
+                                              const NetAddr& selfAddr,
+                                              const NetAddr& peerAddr,
+                                              const int16_t& redirectCount,
+                                              const uint32_t& cacheKey,
+                                              const nsCString& altDataType,
+-                                             const int64_t& altDataLen) override;
++                                             const int64_t& altDataLen,
++                                             const OptionalIPCServiceWorkerDescriptor& aController) override;
+   mozilla::ipc::IPCResult RecvFailedAsyncOpen(const nsresult& status) override;
+   mozilla::ipc::IPCResult RecvRedirect1Begin(const uint32_t& registrarId,
+                                              const URIParams& newURI,
+                                              const uint32_t& redirectFlags,
+                                              const nsHttpResponseHead& responseHead,
+                                              const nsCString& securityInfoSerialization,
+                                              const uint64_t& channelId,
+                                              const NetAddr& oldPeerAddr) override;
+@@ -402,17 +403,18 @@ private:
+                       const int32_t& cacheFetchCount,
+                       const uint32_t& cacheExpirationTime,
+                       const nsCString& cachedCharset,
+                       const nsCString& securityInfoSerialization,
+                       const NetAddr& selfAddr,
+                       const NetAddr& peerAddr,
+                       const uint32_t& cacheKey,
+                       const nsCString& altDataType,
+-                      const int64_t& altDataLen);
++                      const int64_t& altDataLen,
++                      const Maybe<mozilla::dom::ServiceWorkerDescriptor>& aController);
+   void MaybeDivertOnData(const nsCString& data,
+                          const uint64_t& offset,
+                          const uint32_t& count);
+   void OnTransportAndData(const nsresult& channelStatus,
+                           const nsresult& status,
+                           const uint64_t& offset,
+                           const uint32_t& count,
+                           const nsCString& data);
+diff --git a/netwerk/protocol/http/HttpChannelParent.cpp b/netwerk/protocol/http/HttpChannelParent.cpp
+--- a/netwerk/protocol/http/HttpChannelParent.cpp
++++ b/netwerk/protocol/http/HttpChannelParent.cpp
+@@ -1518,16 +1518,33 @@ HttpChannelParent::OnStartRequest(nsIReq
+   nsCString secInfoSerialization;
+   UpdateAndSerializeSecurityInfo(secInfoSerialization);
+ 
+   uint8_t redirectCount = 0;
+   chan->GetRedirectCount(&redirectCount);
+ 
+   int64_t altDataLen = chan->GetAltDataLength();
+ 
++  // Maybe pass back the ServiceWorkerDescriptor controller for this channel.
++  // For subresource loads the controller is already known when the channel
++  // is first open and comes down to us via the LoadInfo.  For non-subresource
++  // loads, however, the controller is selected based on the URL by the
++  // ServiceWorkerManager.  In these cases we need to communicate the controller
++  // back to the child process so the resulting window/worker can set its
++  // navigator.serviceWorker.controller correctly immediately.
++  OptionalIPCServiceWorkerDescriptor ipcController = void_t();
++  nsCOMPtr<nsILoadInfo> loadInfo;
++  Unused << chan->GetLoadInfo(getter_AddRefs(loadInfo));
++  if (loadInfo) {
++    const Maybe<ServiceWorkerDescriptor>& controller = loadInfo->GetController();
++    if (controller.isSome()) {
++      ipcController = controller.ref().ToIPC();
++    }
++  }
++
+   // !!! We need to lock headers and please don't forget to unlock them !!!
+   requestHead->Enter();
+   nsresult rv = NS_OK;
+   if (mIPCClosed ||
+       !SendOnStartRequest(channelStatus,
+                           responseHead ? *responseHead : nsHttpResponseHead(),
+                           !!responseHead,
+                           requestHead->Headers(),
+@@ -1535,17 +1552,18 @@ HttpChannelParent::OnStartRequest(nsIReq
+                           mCacheEntry ? true : false,
+                           cacheEntryId,
+                           fetchCount, expirationTime,
+                           cachedCharset, secInfoSerialization,
+                           chan->GetSelfAddr(), chan->GetPeerAddr(),
+                           redirectCount,
+                           cacheKeyValue,
+                           altDataType,
+-                          altDataLen))
++                          altDataLen,
++                          ipcController))
+   {
+     rv = NS_ERROR_UNEXPECTED;
+   }
+   requestHead->Exit();
+ 
+   // OnStartRequest is sent to content process successfully.
+   // Notify PHttpBackgroundChannelChild that all following IPC mesasges
+   // should be run after OnStartRequest is handled.
+diff --git a/netwerk/protocol/http/PHttpChannel.ipdl b/netwerk/protocol/http/PHttpChannel.ipdl
+--- a/netwerk/protocol/http/PHttpChannel.ipdl
++++ b/netwerk/protocol/http/PHttpChannel.ipdl
+@@ -6,16 +6,17 @@
+  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+ 
+ include protocol PNecko;
+ include protocol PStreamFilter;
+ include InputStreamParams;
+ include URIParams;
+ include PBackgroundSharedTypes;
+ include NeckoChannelParams;
++include IPCServiceWorkerDescriptor;
+ 
+ include "mozilla/net/NeckoMessageUtils.h";
+ 
+ using class nsHttpHeaderArray from "nsHttpHeaderArray.h";
+ using mozilla::net::NetAddr from "mozilla/net/DNS.h";
+ using struct mozilla::net::ResourceTimingStruct from "mozilla/net/TimingStruct.h";
+ 
+ namespace mozilla {
+@@ -103,17 +104,18 @@ child:
+                        uint32_t            cacheExpirationTime,
+                        nsCString           cachedCharset,
+                        nsCString           securityInfoSerialization,
+                        NetAddr             selfAddr,
+                        NetAddr             peerAddr,
+                        int16_t             redirectCount,
+                        uint32_t            cacheKey,
+                        nsCString           altDataType,
+-                       int64_t             altDataLength);
++                       int64_t             altDataLength,
++                       OptionalIPCServiceWorkerDescriptor controller);
+ 
+   // Used to cancel child channel if we hit errors during creating and
+   // AsyncOpen of nsHttpChannel on the parent.
+   async FailedAsyncOpen(nsresult status);
+ 
+   // Called to initiate content channel redirect, starts talking to sinks
+   // on the content process and reports result via Redirect2Verify above
+   async Redirect1Begin(uint32_t           registrarId,

+ 266 - 0
mozilla-release/patches/1231211-03-60a1.patch

@@ -0,0 +1,266 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1516721932 18000
+# Node ID eb8adf8c64ece64246b53958fb84cf5b3176d6e7
+# Parent  ec28c4718b809166d666501b18d3b173a72e32a3
+Bug 1231211 P3 Serialize LoadInfo's mClientInfo, mReservedClientInfo, and mReservedClientInfo members across IPC. r=valentin
+
+diff --git a/dom/clients/manager/ClientIPCTypes.ipdlh b/dom/clients/manager/ClientIPCTypes.ipdlh
+--- a/dom/clients/manager/ClientIPCTypes.ipdlh
++++ b/dom/clients/manager/ClientIPCTypes.ipdlh
+@@ -29,16 +29,22 @@ struct IPCClientInfo
+   nsID id;
+   ClientType type;
+   PrincipalInfo principalInfo;
+   TimeStamp creationTime;
+   nsCString url;
+   FrameType frameType;
+ };
+ 
++union OptionalIPCClientInfo
++{
++  IPCClientInfo;
++  void_t;
++};
++
+ struct IPCClientWindowState
+ {
+   VisibilityState visibilityState;
+   TimeStamp lastFocusTime;
+   StorageAccess storageAccess;
+   bool focused;
+ };
+ 
+diff --git a/ipc/glue/BackgroundUtils.cpp b/ipc/glue/BackgroundUtils.cpp
+--- a/ipc/glue/BackgroundUtils.cpp
++++ b/ipc/glue/BackgroundUtils.cpp
+@@ -363,16 +363,34 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoa
+ 
+   nsTArray<PrincipalInfo> ancestorPrincipals;
+   ancestorPrincipals.SetCapacity(aLoadInfo->AncestorPrincipals().Length());
+   for (const auto& principal : aLoadInfo->AncestorPrincipals()) {
+     rv = PrincipalToPrincipalInfo(principal, ancestorPrincipals.AppendElement());
+     NS_ENSURE_SUCCESS(rv, rv);
+   }
+ 
++  OptionalIPCClientInfo ipcClientInfo = mozilla::void_t();
++  const Maybe<ClientInfo>& clientInfo = aLoadInfo->GetClientInfo();
++  if (clientInfo.isSome()) {
++    ipcClientInfo = clientInfo.ref().ToIPC();
++  }
++
++  OptionalIPCClientInfo ipcReservedClientInfo = mozilla::void_t();
++  const Maybe<ClientInfo>& reservedClientInfo = aLoadInfo->GetReservedClientInfo();
++  if (reservedClientInfo.isSome()) {
++    ipcReservedClientInfo = reservedClientInfo.ref().ToIPC();
++  }
++
++  OptionalIPCClientInfo ipcInitialClientInfo = mozilla::void_t();
++  const Maybe<ClientInfo>& initialClientInfo = aLoadInfo->GetInitialClientInfo();
++  if (initialClientInfo.isSome()) {
++    ipcInitialClientInfo = initialClientInfo.ref().ToIPC();
++  }
++
+   OptionalIPCServiceWorkerDescriptor ipcController = mozilla::void_t();
+   const Maybe<ServiceWorkerDescriptor>& controller = aLoadInfo->GetController();
+   if (controller.isSome()) {
+     ipcController = controller.ref().ToIPC();
+   }
+ 
+   *aOptionalLoadInfoArgs =
+     LoadInfoArgs(
+@@ -398,16 +416,19 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoa
+       aLoadInfo->GetInitialSecurityCheckDone(),
+       aLoadInfo->GetIsInThirdPartyContext(),
+       aLoadInfo->GetIsDocshellReload(),
+       aLoadInfo->GetOriginAttributes(),
+       redirectChainIncludingInternalRedirects,
+       redirectChain,
+       ancestorPrincipals,
+       aLoadInfo->AncestorOuterWindowIDs(),
++      ipcClientInfo,
++      ipcReservedClientInfo,
++      ipcInitialClientInfo,
+       ipcController,
+       aLoadInfo->CorsUnsafeHeaders(),
+       aLoadInfo->GetForcePreflight(),
+       aLoadInfo->GetIsPreflight(),
+       aLoadInfo->GetLoadTriggeredFromExternal(),
+       aLoadInfo->GetServiceWorkerTaintingSynthesized()
+       );
+ 
+@@ -478,28 +499,54 @@ LoadInfoArgsToLoadInfo(const OptionalLoa
+   ancestorPrincipals.SetCapacity(loadInfoArgs.ancestorPrincipals().Length());
+   for (const PrincipalInfo& principalInfo : loadInfoArgs.ancestorPrincipals()) {
+     nsCOMPtr<nsIPrincipal> ancestorPrincipal =
+       PrincipalInfoToPrincipal(principalInfo, &rv);
+     NS_ENSURE_SUCCESS(rv, rv);
+     ancestorPrincipals.AppendElement(ancestorPrincipal.forget());
+   }
+ 
++  Maybe<ClientInfo> clientInfo;
++  if (loadInfoArgs.clientInfo().type() != OptionalIPCClientInfo::Tvoid_t) {
++    clientInfo.emplace(ClientInfo(loadInfoArgs.clientInfo().get_IPCClientInfo()));
++  }
++
++  Maybe<ClientInfo> reservedClientInfo;
++  if (loadInfoArgs.reservedClientInfo().type() != OptionalIPCClientInfo::Tvoid_t) {
++    reservedClientInfo.emplace(
++      ClientInfo(loadInfoArgs.reservedClientInfo().get_IPCClientInfo()));
++  }
++
++  Maybe<ClientInfo> initialClientInfo;
++  if (loadInfoArgs.initialClientInfo().type() != OptionalIPCClientInfo::Tvoid_t) {
++    initialClientInfo.emplace(
++      ClientInfo(loadInfoArgs.initialClientInfo().get_IPCClientInfo()));
++  }
++
++  // 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<ServiceWorkerDescriptor> controller;
+   if (loadInfoArgs.controller().type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) {
+     controller.emplace(ServiceWorkerDescriptor(
+       loadInfoArgs.controller().get_IPCServiceWorkerDescriptor()));
+   }
+ 
+   nsCOMPtr<nsILoadInfo> loadInfo =
+     new mozilla::LoadInfo(loadingPrincipal,
+                           triggeringPrincipal,
+                           principalToInherit,
+                           sandboxedLoadingPrincipal,
+                           resultPrincipalURI,
++                          clientInfo,
++                          reservedClientInfo,
++                          initialClientInfo,
+                           controller,
+                           loadInfoArgs.securityFlags(),
+                           loadInfoArgs.contentPolicyType(),
+                           static_cast<LoadTainting>(loadInfoArgs.tainting()),
+                           loadInfoArgs.upgradeInsecureRequests(),
+                           loadInfoArgs.verifySignedContent(),
+                           loadInfoArgs.enforceSRI(),
+                           loadInfoArgs.forceAllowDataURI(),
+diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp
+--- a/netwerk/base/LoadInfo.cpp
++++ b/netwerk/base/LoadInfo.cpp
+@@ -344,16 +344,19 @@ LoadInfo::LoadInfo(const LoadInfo& rhs)
+ {
+ }
+ 
+ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
+                    nsIPrincipal* aTriggeringPrincipal,
+                    nsIPrincipal* aPrincipalToInherit,
+                    nsIPrincipal* aSandboxedLoadingPrincipal,
+                    nsIURI* aResultPrincipalURI,
++                   const Maybe<ClientInfo>& aClientInfo,
++                   const Maybe<ClientInfo>& aReservedClientInfo,
++                   const Maybe<ClientInfo>& aInitialClientInfo,
+                    const Maybe<ServiceWorkerDescriptor>& aController,
+                    nsSecurityFlags aSecurityFlags,
+                    nsContentPolicyType aContentPolicyType,
+                    LoadTainting aTainting,
+                    bool aUpgradeInsecureRequests,
+                    bool aVerifySignedContent,
+                    bool aEnforceSRI,
+                    bool aForceAllowDataURI,
+@@ -376,16 +379,19 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadin
+                    bool aForcePreflight,
+                    bool aIsPreflight,
+                    bool aLoadTriggeredFromExternal,
+                    bool aServiceWorkerTaintingSynthesized)
+   : mLoadingPrincipal(aLoadingPrincipal)
+   , mTriggeringPrincipal(aTriggeringPrincipal)
+   , mPrincipalToInherit(aPrincipalToInherit)
+   , mResultPrincipalURI(aResultPrincipalURI)
++  , mClientInfo(aClientInfo)
++  , mReservedClientInfo(aReservedClientInfo)
++  , mInitialClientInfo(aInitialClientInfo)
+   , mController(aController)
+   , mSecurityFlags(aSecurityFlags)
+   , mInternalContentPolicyType(aContentPolicyType)
+   , mTainting(aTainting)
+   , mUpgradeInsecureRequests(aUpgradeInsecureRequests)
+   , mVerifySignedContent(aVerifySignedContent)
+   , mEnforceSRI(aEnforceSRI)
+   , mForceAllowDataURI(aForceAllowDataURI)
+diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h
+--- a/netwerk/base/LoadInfo.h
++++ b/netwerk/base/LoadInfo.h
+@@ -94,16 +94,19 @@ private:
+   // HttpChannelParent and FTPChannelParent declared as friends undeneath.
+   // In e10s we can not serialize nsINode, hence we store the innerWindowID.
+   // Please note that aRedirectChain uses swapElements.
+   LoadInfo(nsIPrincipal* aLoadingPrincipal,
+            nsIPrincipal* aTriggeringPrincipal,
+            nsIPrincipal* aPrincipalToInherit,
+            nsIPrincipal* aSandboxedLoadingPrincipal,
+            nsIURI* aResultPrincipalURI,
++           const Maybe<mozilla::dom::ClientInfo>& aClientInfo,
++           const Maybe<mozilla::dom::ClientInfo>& aReservedClientInfo,
++           const Maybe<mozilla::dom::ClientInfo>& aInitialClientInfo,
+            const Maybe<mozilla::dom::ServiceWorkerDescriptor>& aController,
+            nsSecurityFlags aSecurityFlags,
+            nsContentPolicyType aContentPolicyType,
+            LoadTainting aTainting,
+            bool aUpgradeInsecureRequests,
+            bool aVerifySignedContent,
+            bool aEnforceSRI,
+            bool aForceAllowDataURI,
+diff --git a/netwerk/ipc/NeckoChannelParams.ipdlh b/netwerk/ipc/NeckoChannelParams.ipdlh
+--- a/netwerk/ipc/NeckoChannelParams.ipdlh
++++ b/netwerk/ipc/NeckoChannelParams.ipdlh
+@@ -4,16 +4,17 @@
+ /* 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 protocol PHttpChannel;
+ include protocol PFTPChannel;
+ include protocol PChildToParentStream;
+ include BlobTypes;
++include ClientIPCTypes;
+ include URIParams;
+ include IPCServiceWorkerDescriptor;
+ include IPCStream;
+ include PBackgroundSharedTypes;
+ 
+ using mozilla::OriginAttributes from "mozilla/ipc/BackgroundUtils.h";
+ using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
+ using RequestHeaderTuples from "mozilla/net/PHttpChannelParams.h";
+@@ -66,16 +67,32 @@ struct LoadInfoArgs
+   /**
+    * Ancestor data for use with the WebRequest API.
+    * See nsILoadInfo.idl for details.
+    */
+   PrincipalInfo[]             ancestorPrincipals;
+   uint64_t[]                  ancestorOuterWindowIDs;
+ 
+   /**
++   * ClientInfo structure representing the window or worker that triggered
++   * this network request.  May be void_t if its a system internal request.
++   */
++  OptionalIPCClientInfo       clientInfo;
++
++  /**
++   * Non-subresource requests will result in the creation of a window or
++   * worker client.  The reserved and initial ClientInfo values represent
++   * this resulting client.  An initial ClientInfo represents an initial
++   * about:blank window that will be re-used while a reserved ClientInfo
++   * represents a to-be-newly-created window/worker.
++   */
++  OptionalIPCClientInfo       reservedClientInfo;
++  OptionalIPCClientInfo       initialClientInfo;
++
++  /**
+    * Subresource loads may have a controller set based on their owning
+    * window/worker client.  We must send this across IPC to support
+    * performing interception in the parent.
+    */
+   OptionalIPCServiceWorkerDescriptor controller;
+ 
+   nsCString[]                 corsUnsafeHeaders;
+   bool                        forcePreflight;

+ 32 - 0
mozilla-release/patches/1231211-04-60a1.patch

@@ -0,0 +1,32 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1516721932 18000
+# Node ID 7f17473a7b416e433e3dc6a9271eecb925d0a4de
+# Parent  b90fec88ac78b7d4591106d9d875d0f7eaf7a891
+Bug 1231211 P4 Set isReload on LoadInfo in docshell. r=asuth
+
+diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
+--- a/docshell/base/nsDocShell.cpp
++++ b/docshell/base/nsDocShell.cpp
+@@ -10634,16 +10634,21 @@ nsDocShell::DoURILoad(nsIURI* aURI,
+     attrs.SetFirstPartyDomain(isTopLevelDoc, aURI);
+   }
+ 
+   rv = loadInfo->SetOriginAttributes(attrs);
+   if (NS_WARN_IF(NS_FAILED(rv))) {
+     return rv;
+   }
+ 
++  // Document loads should set the reload flag on the channel so that it
++  // can be exposed on the service worker FetchEvent.
++  rv = loadInfo->SetIsDocshellReload(mLoadType & LOAD_CMD_RELOAD);
++  NS_ENSURE_SUCCESS(rv, rv);
++
+   if (!isSrcdoc) {
+     rv = NS_NewChannelInternal(getter_AddRefs(channel),
+                                aURI,
+                                loadInfo,
+                                nullptr,   // loadGroup
+                                static_cast<nsIInterfaceRequestor*>(this),
+                                loadFlags);
+ 

+ 63 - 0
mozilla-release/patches/1231211-05-60a1.patch

@@ -0,0 +1,63 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1516721932 18000
+# Node ID 53679221bad1678764fa785db4f20e3e0642557a
+# Parent  9841d0bf456f1a7f8b326ea57f4dd4dafde6904c
+Bug 1231211 P5 Add nsContentUtils::IsNonSubresourceInternalPolicyType() method. r=asuth
+
+diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
+--- a/dom/base/nsContentUtils.cpp
++++ b/dom/base/nsContentUtils.cpp
+@@ -9046,18 +9046,28 @@ nsContentUtils::IsNonSubresourceRequest(
+     return true;
+   }
+ 
+   nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
+   if (!loadInfo) {
+     return false;
+   }
+   nsContentPolicyType type = loadInfo->InternalContentPolicyType();
+-  return type == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
+-         type == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;
++  return IsNonSubresourceInternalPolicyType(type);
++}
++
++// static
++bool
++nsContentUtils::IsNonSubresourceInternalPolicyType(nsContentPolicyType aType)
++{
++  return aType == nsIContentPolicy::TYPE_DOCUMENT ||
++         aType == nsIContentPolicy::TYPE_INTERNAL_IFRAME ||
++         aType == nsIContentPolicy::TYPE_INTERNAL_FRAME ||
++         aType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
++         aType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;
+ }
+ 
+ // static, public
+ nsContentUtils::StorageAccess
+ nsContentUtils::StorageAllowedForWindow(nsPIDOMWindowInner* aWindow)
+ {
+   MOZ_ASSERT(aWindow->IsInnerWindow());
+ 
+diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h
+--- a/dom/base/nsContentUtils.h
++++ b/dom/base/nsContentUtils.h
+@@ -2948,16 +2948,18 @@ public:
+    *
+    * @param aHeader the response's Referrer-Policy header to parse
+    * @return referrer policy from the response header.
+    */
+   static mozilla::net::ReferrerPolicy GetReferrerPolicyFromHeader(const nsAString& aHeader);
+ 
+   static bool IsNonSubresourceRequest(nsIChannel* aChannel);
+ 
++  static bool IsNonSubresourceInternalPolicyType(nsContentPolicyType aType);
++
+   // The order of these entries matters, as we use std::min for total ordering
+   // of permissions. Private Browsing is considered to be more limiting
+   // then session scoping
+   enum class StorageAccess {
+     // Don't allow access to the storage
+     eDeny = 0,
+     // Allow access to the storage, but only if it is secure to do so in a
+     // private browsing context.

+ 36 - 0
mozilla-release/patches/1231211-06-60a1.patch

@@ -0,0 +1,36 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1516721932 18000
+# Node ID e3a30f0dc5039a46b507294c58bab681db275db5
+# Parent  5df7e7d92d32a9ce9866166970fad30000c8f7ec
+Bug 1231211 P6 Automatically set the controller on the LoadInfo for subresource requests. r=asuth
+
+diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp
+--- a/netwerk/base/LoadInfo.cpp
++++ b/netwerk/base/LoadInfo.cpp
+@@ -111,16 +111,25 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadin
+   }
+ 
+   if (aLoadingContext) {
+     // Ensure that all network requests for a window client have the ClientInfo
+     // properly set.
+     // TODO: The ClientInfo is not set properly for worker initiated requests yet.
+     mClientInfo = aLoadingContext->OwnerDoc()->GetClientInfo();
+ 
++    // For subresource loads set the service worker based on the calling
++    // context's controller.
++    // TODO: The controller is not set properly for all requests initiated from a
++    //       worker context.  Some workers will not have an nsINode loading context
++    //       here.
++    if (!nsContentUtils::IsNonSubresourceInternalPolicyType(mInternalContentPolicyType)) {
++      mController = aLoadingContext->OwnerDoc()->GetController();
++    }
++
+     nsCOMPtr<nsPIDOMWindowOuter> contextOuter = aLoadingContext->OwnerDoc()->GetWindow();
+     if (contextOuter) {
+       ComputeIsThirdPartyContext(contextOuter);
+       mOuterWindowID = contextOuter->WindowID();
+       nsCOMPtr<nsPIDOMWindowOuter> parent = contextOuter->GetScriptableParent();
+       mParentOuterWindowID = parent ? parent->WindowID() : mOuterWindowID;
+       mTopOuterWindowID = FindTopOuterWindowID(contextOuter);
+     }

+ 112 - 0
mozilla-release/patches/1231211-07-60a1.patch

@@ -0,0 +1,112 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1516721933 18000
+# Node ID 93b38b36a962e141c4a3ac12b425ef23a09e2769
+# Parent  408d9d4066169096838496cdce51706702fd5a24
+Bug 1231211 P7 Pass the nsIChannel to ShouldPrepareForIntercept(). r=asuth
+
+diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
+--- a/docshell/base/nsDocShell.cpp
++++ b/docshell/base/nsDocShell.cpp
+@@ -14240,26 +14240,26 @@ nsDocShell::MaybeNotifyKeywordSearchLoad
+         obsSvc->NotifyObservers(searchEngine, "keyword-search", aKeyword.get());
+       }
+     }
+   }
+ #endif
+ }
+ 
+ NS_IMETHODIMP
+-nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, bool aIsNonSubresourceRequest,
++nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, nsIChannel* aChannel,
+                                       bool* aShouldIntercept)
+ {
+   *aShouldIntercept = false;
+ 
+   // For subresource requests we base our decision solely on the client's
+   // controller value.  Any settings that would have blocked service worker
+   // access should have been set before the initial navigation created the
+   // window.
+-  if (!aIsNonSubresourceRequest) {
++  if (!nsContentUtils::IsNonSubresourceRequest(aChannel)) {
+     nsCOMPtr<nsIDocument> doc = GetDocument();
+     if (!doc) {
+       return NS_ERROR_NOT_AVAILABLE;
+     }
+ 
+     ErrorResult rv;
+     *aShouldIntercept = doc->GetController().isSome();
+     if (NS_WARN_IF(rv.Failed())) {
+diff --git a/netwerk/base/nsINetworkInterceptController.idl b/netwerk/base/nsINetworkInterceptController.idl
+--- a/netwerk/base/nsINetworkInterceptController.idl
++++ b/netwerk/base/nsINetworkInterceptController.idl
+@@ -203,20 +203,22 @@ interface nsIInterceptedChannel : nsISup
+ 
+ [scriptable, uuid(70d2b4fe-a552-48cd-8d93-1d8437a56b53)]
+ interface nsINetworkInterceptController : nsISupports
+ {
+     /**
+      * Returns true if a channel should avoid initiating any network
+      * requests until specifically instructed to do so.
+      *
+-     * @param aURI the URI being requested by a channel
+-     * @param aIsNavigate True if the request is for a navigation, false for a fetch.
++     * @param aURI The URI to be loaded.  Note, this may differ from
++     *             the channel's current URL in some cases.
++     * @param aChannel The channel that may be intercepted.  It will
++     *                 be in the state prior to calling OnStartRequest().
+      */
+-    bool shouldPrepareForIntercept(in nsIURI aURI, in bool aIsNonSubresourceRequest);
++    bool shouldPrepareForIntercept(in nsIURI aURI, in nsIChannel aChannel);
+ 
+     /**
+      * Notification when a given intercepted channel is prepared to accept a synthesized
+      * response via the provided stream.
+      *
+      * @param aChannel the controlling interface for a channel that has been intercepted
+      */
+     void channelIntercepted(in nsIInterceptedChannel aChannel);
+diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp
+--- a/netwerk/protocol/http/HttpBaseChannel.cpp
++++ b/netwerk/protocol/http/HttpBaseChannel.cpp
+@@ -3088,17 +3088,17 @@ HttpBaseChannel::ShouldIntercept(nsIURI*
+   // Note, HSTS upgrade redirects are often treated the same as internal
+   // redirects.  In this case, however, we intentionally allow interception
+   // of HSTS upgrade redirects.  This matches the expected spec behavior and
+   // does not run the risk of infinite loops as described above.
+   bool internalRedirect = mLastRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL;
+ 
+   if (controller && mLoadInfo && !BypassServiceWorker() && !internalRedirect) {
+     nsresult rv = controller->ShouldPrepareForIntercept(aURI ? aURI : mURI.get(),
+-                                                        nsContentUtils::IsNonSubresourceRequest(this),
++                                                        this,
+                                                         &shouldIntercept);
+     if (NS_FAILED(rv)) {
+       return false;
+     }
+   }
+   return shouldIntercept;
+ }
+ 
+diff --git a/netwerk/protocol/http/HttpChannelParentListener.cpp b/netwerk/protocol/http/HttpChannelParentListener.cpp
+--- a/netwerk/protocol/http/HttpChannelParentListener.cpp
++++ b/netwerk/protocol/http/HttpChannelParentListener.cpp
+@@ -272,17 +272,17 @@ HttpChannelParentListener::OnRedirectRes
+ }
+ 
+ //-----------------------------------------------------------------------------
+ // HttpChannelParentListener::nsINetworkInterceptController
+ //-----------------------------------------------------------------------------
+ 
+ NS_IMETHODIMP
+ HttpChannelParentListener::ShouldPrepareForIntercept(nsIURI* aURI,
+-                                                     bool aIsNonSubresourceRequest,
++                                                     nsIChannel* aChannel,
+                                                      bool* aShouldIntercept)
+ {
+   *aShouldIntercept = mShouldIntercept;
+   return NS_OK;
+ }
+ 
+ class HeaderVisitor final : public nsIHttpHeaderVisitor
+ {

+ 57 - 0
mozilla-release/patches/1231211-08-60a1.patch

@@ -0,0 +1,57 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1516721933 18000
+# Node ID c384b60e2a0da234680aa9995892ab3ec4287d68
+# Parent  c58b6ae1f78fcefe1ebc44aaa300b85ddb07c6a6
+Bug 1231211 P8 Make nsDocShell::ShouldPrepareForIntercept() only depend on channel data. r=asuth
+
+diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
+--- a/docshell/base/nsDocShell.cpp
++++ b/docshell/base/nsDocShell.cpp
+@@ -14224,37 +14224,34 @@ nsDocShell::MaybeNotifyKeywordSearchLoad
+ }
+ 
+ NS_IMETHODIMP
+ nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, nsIChannel* aChannel,
+                                       bool* aShouldIntercept)
+ {
+   *aShouldIntercept = false;
+ 
++  nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
++  if (!loadInfo) {
++    return NS_OK;
++  }
++
+   // For subresource requests we base our decision solely on the client's
+   // controller value.  Any settings that would have blocked service worker
+   // access should have been set before the initial navigation created the
+   // window.
+   if (!nsContentUtils::IsNonSubresourceRequest(aChannel)) {
+-    nsCOMPtr<nsIDocument> doc = GetDocument();
+-    if (!doc) {
+-      return NS_ERROR_NOT_AVAILABLE;
+-    }
+-
+-    ErrorResult rv;
+-    *aShouldIntercept = doc->GetController().isSome();
+-    if (NS_WARN_IF(rv.Failed())) {
+-      return rv.StealNSResult();
+-    }
+-
++    const Maybe<ServiceWorkerDescriptor>& controller = loadInfo->GetController();
++    *aShouldIntercept = controller.isSome();
+     return NS_OK;
+   }
+ 
+   nsCOMPtr<nsIPrincipal> principal =
+-    BasePrincipal::CreateCodebasePrincipal(aURI, mOriginAttributes);
++    BasePrincipal::CreateCodebasePrincipal(aURI,
++                                           loadInfo->GetOriginAttributes());
+ 
+   // For navigations, first check to see if we are allowed to control a
+   // window with the given URL.
+   if (!ServiceWorkerAllowedToControlWindow(principal, aURI)) {
+     return NS_OK;
+   }
+ 
+   RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();

+ 421 - 0
mozilla-release/patches/1231211-09-60a1.patch

@@ -0,0 +1,421 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1516721933 18000
+# Node ID 1d3c7f0f0559f8c849800ba245443db75cf7cff0
+# Parent  c14649d3b3195b6c7ad003cb6202bee96ae0d6c3
+Bug 1231211 P9 Move logic out of nsDocShell::ChannelControlled() and into ServiceWorkerManager::DispatchFetchEvent(). r=asuth
+
+diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
+--- a/docshell/base/nsDocShell.cpp
++++ b/docshell/base/nsDocShell.cpp
+@@ -14269,36 +14269,20 @@ NS_IMETHODIMP
+ nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel)
+ {
+   RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
+   if (!swm) {
+     aChannel->CancelInterception(NS_ERROR_INTERCEPTION_FAILED);
+     return NS_OK;
+   }
+ 
+-  nsCOMPtr<nsIChannel> channel;
+-  nsresult rv = aChannel->GetChannel(getter_AddRefs(channel));
+-  NS_ENSURE_SUCCESS(rv, rv);
+-
+-  nsCOMPtr<nsIDocument> doc;
+-
+-  bool isSubresourceLoad = !nsContentUtils::IsNonSubresourceRequest(channel);
+-  if (isSubresourceLoad) {
+-    doc = GetDocument();
+-    if (!doc) {
+-      return NS_ERROR_NOT_AVAILABLE;
+-    }
+-  }
+-
+-  bool isReload = mLoadType & LOAD_CMD_RELOAD;
+-
+   ErrorResult error;
+-  swm->DispatchFetchEvent(mOriginAttributes, doc, aChannel, isReload,
+-                          isSubresourceLoad, error);
++  swm->DispatchFetchEvent(aChannel, error);
+   if (NS_WARN_IF(error.Failed())) {
++    aChannel->CancelInterception(NS_ERROR_INTERCEPTION_FAILED);
+     return error.StealNSResult();
+   }
+ 
+   return NS_OK;
+ }
+ 
+ bool
+ nsDocShell::InFrameSwap()
+diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerManager.cpp
+--- a/dom/workers/ServiceWorkerManager.cpp
++++ b/dom/workers/ServiceWorkerManager.cpp
+@@ -1988,16 +1988,35 @@ ServiceWorkerManager::PrincipalToScopeKe
+   nsresult rv = aPrincipal->GetOrigin(aKey);
+   if (NS_WARN_IF(NS_FAILED(rv))) {
+     return rv;
+   }
+ 
+   return NS_OK;
+ }
+ 
++/* static */ nsresult
++ServiceWorkerManager::PrincipalInfoToScopeKey(const PrincipalInfo& aPrincipalInfo,
++                                              nsACString& aKey)
++{
++  if (aPrincipalInfo.type() != PrincipalInfo::TContentPrincipalInfo) {
++    return NS_ERROR_FAILURE;
++  }
++
++  auto content = aPrincipalInfo.get_ContentPrincipalInfo();
++
++  nsAutoCString suffix;
++  content.attrs().CreateSuffix(suffix);
++
++  aKey = content.originNoSuffix();
++  aKey.Append(suffix);
++
++  return NS_OK;
++}
++
+ /* static */ void
+ ServiceWorkerManager::AddScopeAndRegistration(const nsACString& aScope,
+                                               ServiceWorkerRegistrationInfo* aInfo)
+ {
+   MOZ_ASSERT(aInfo);
+   MOZ_ASSERT(aInfo->mPrincipal);
+ 
+   RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
+@@ -2433,141 +2452,144 @@ public:
+ 
+     return NS_OK;
+   }
+ };
+ 
+ } // anonymous namespace
+ 
+ void
+-ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttributes,
+-                                         nsIDocument* aDoc,
+-                                         nsIInterceptedChannel* aChannel,
+-                                         bool aIsReload,
+-                                         bool aIsSubresourceLoad,
++ServiceWorkerManager::DispatchFetchEvent(nsIInterceptedChannel* aChannel,
+                                          ErrorResult& aRv)
+ {
+   MOZ_ASSERT(aChannel);
+   AssertIsOnMainThread();
+ 
+-  RefPtr<ServiceWorkerInfo> serviceWorker;
++  nsCOMPtr<nsIChannel> internalChannel;
++  aRv = aChannel->GetChannel(getter_AddRefs(internalChannel));
++  if (NS_WARN_IF(aRv.Failed())) {
++    return;
++  }
++
+   nsCOMPtr<nsILoadGroup> loadGroup;
+-
+-  if (aIsSubresourceLoad) {
+-    MOZ_ASSERT(aDoc);
+-
+-    serviceWorker = GetActiveWorkerInfoForDocument(aDoc);
+-    if (!serviceWorker) {
++  aRv = internalChannel->GetLoadGroup(getter_AddRefs(loadGroup));
++  if (NS_WARN_IF(aRv.Failed())) {
++    return;
++  }
++
++  nsCOMPtr<nsILoadInfo> loadInfo = internalChannel->GetLoadInfo();
++  if (NS_WARN_IF(!loadInfo)) {
++    aRv.Throw(NS_ERROR_UNEXPECTED);
++    return;
++  }
++
++  RefPtr<ServiceWorkerInfo> serviceWorker;
++
++  if (!nsContentUtils::IsNonSubresourceRequest(internalChannel)) {
++    const Maybe<ServiceWorkerDescriptor>& controller = loadInfo->GetController();
++    if (NS_WARN_IF(controller.isNothing())) {
+       aRv.Throw(NS_ERROR_FAILURE);
+       return;
+     }
+ 
+-    loadGroup = aDoc->GetDocumentLoadGroup();
+-  } else {
+-    nsCOMPtr<nsIChannel> internalChannel;
+-    aRv = aChannel->GetChannel(getter_AddRefs(internalChannel));
+-    if (NS_WARN_IF(aRv.Failed())) {
++    RefPtr<ServiceWorkerRegistrationInfo> registration =
++      GetRegistration(controller.ref().PrincipalInfo(), controller.ref().Scope());
++    if (NS_WARN_IF(!registration)) {
++      aRv.Throw(NS_ERROR_FAILURE);
+       return;
+     }
+ 
+-    internalChannel->GetLoadGroup(getter_AddRefs(loadGroup));
+-
++    serviceWorker = registration->GetActive();
++    if (NS_WARN_IF(!serviceWorker) ||
++        NS_WARN_IF(serviceWorker->Descriptor().Id() != controller.ref().Id())) {
++      aRv.Throw(NS_ERROR_FAILURE);
++      return;
++    }
++  } else {
+     nsCOMPtr<nsIURI> uri;
+     aRv = aChannel->GetSecureUpgradedChannelURI(getter_AddRefs(uri));
+     if (NS_WARN_IF(aRv.Failed())) {
+       return;
+     }
+ 
+     // non-subresource request means the URI contains the principal
+     nsCOMPtr<nsIPrincipal> principal =
+-      BasePrincipal::CreateCodebasePrincipal(uri, aOriginAttributes);
++      BasePrincipal::CreateCodebasePrincipal(uri,
++                                             loadInfo->GetOriginAttributes());
+ 
+     RefPtr<ServiceWorkerRegistrationInfo> registration =
+       GetServiceWorkerRegistrationInfo(principal, uri);
+-    if (!registration) {
+-      NS_WARNING("No registration found when dispatching the fetch event");
++    if (NS_WARN_IF(!registration)) {
+       aRv.Throw(NS_ERROR_FAILURE);
+       return;
+     }
+ 
+     // While we only enter this method if IsAvailable() previously saw
+     // an active worker, it is possible for that worker to be removed
+     // before we get to this point.  Therefore we must handle a nullptr
+     // active worker here.
+     serviceWorker = registration->GetActive();
+-    if (!serviceWorker) {
++    if (NS_WARN_IF(!serviceWorker)) {
+       aRv.Throw(NS_ERROR_FAILURE);
+       return;
+     }
+ 
+     // If there is a reserved client it should be marked as controlled before
+     // the FetchEvent is dispatched.
+-    nsCOMPtr<nsILoadInfo> loadInfo = internalChannel->GetLoadInfo();
+-    if (loadInfo) {
+-      Maybe<ClientInfo> clientInfo = loadInfo->GetReservedClientInfo();
+-
+-      // Also override the initial about:blank controller since the real
+-      // network load may be intercepted by a different service worker.  If
+-      // the intial about:blank has a controller here its simply been
+-      // inherited from its parent.
+-      if (clientInfo.isNothing()) {
+-        clientInfo = loadInfo->GetInitialClientInfo();
+-
+-        // TODO: We need to handle the case where the initial about:blank is
+-        //       controlled, but the final document load is not.  Right now
+-        //       the spec does not really say what to do.  There currently
+-        //       is no way for the controller to be cleared from a client in
+-        //       the spec or our implementation.  We may want to force a
+-        //       new inner window to be created instead of reusing the
+-        //       initial about:blank global.  See bug 1419620 and the spec
+-        //       issue here: https://github.com/w3c/ServiceWorker/issues/1232
+-      }
+-
+-      if (clientInfo.isSome()) {
+-        // First, attempt to mark the reserved client controlled directly.  This
+-        // will update the controlled status in the ClientManagerService in the
+-        // parent.  It will also eventually propagate back to the ClientSource.
+-        StartControllingClient(clientInfo.ref(), registration);
+-      }
+-
+-      // But we also note the reserved state on the LoadInfo.  This allows the
+-      // ClientSource to be updated immediately after the nsIChannel starts.
+-      // This is necessary to have the correct controller in place for immediate
+-      // follow-on requests.
+-      loadInfo->SetController(serviceWorker->Descriptor());
++    Maybe<ClientInfo> clientInfo = loadInfo->GetReservedClientInfo();
++
++    // Also override the initial about:blank controller since the real
++    // network load may be intercepted by a different service worker.  If
++    // the intial about:blank has a controller here its simply been
++    // inherited from its parent.
++    if (clientInfo.isNothing()) {
++      clientInfo = loadInfo->GetInitialClientInfo();
++
++      // TODO: We need to handle the case where the initial about:blank is
++      //       controlled, but the final document load is not.  Right now
++      //       the spec does not really say what to do.  There currently
++      //       is no way for the controller to be cleared from a client in
++      //       the spec or our implementation.  We may want to force a
++      //       new inner window to be created instead of reusing the
++      //       initial about:blank global.  See bug 1419620 and the spec
++      //       issue here: https://github.com/w3c/ServiceWorker/issues/1232
+     }
+-  }
+-
+-  if (NS_WARN_IF(aRv.Failed())) {
+-    return;
++
++    if (clientInfo.isSome()) {
++      // First, attempt to mark the reserved client controlled directly.  This
++      // will update the controlled status in the ClientManagerService in the
++      // parent.  It will also eventually propagate back to the ClientSource.
++      StartControllingClient(clientInfo.ref(), registration);
++    }
++
++    // But we also note the reserved state on the LoadInfo.  This allows the
++    // ClientSource to be updated immediately after the nsIChannel starts.
++    // This is necessary to have the correct controller in place for immediate
++    // follow-on requests.
++    loadInfo->SetController(serviceWorker->Descriptor());
+   }
+ 
+   MOZ_DIAGNOSTIC_ASSERT(serviceWorker);
+ 
+   nsCOMPtr<nsIRunnable> continueRunnable =
+     new ContinueDispatchFetchEventRunnable(serviceWorker->WorkerPrivate(),
+-                                           aChannel, loadGroup, aIsReload);
++                                           aChannel, loadGroup,
++                                           loadInfo->GetIsDocshellReload());
+ 
+   // When this service worker was registered, we also sent down the permissions
+   // for the runnable. They should have arrived by now, but we still need to
+   // wait for them if they have not.
+   nsCOMPtr<nsIRunnable> permissionsRunnable = NS_NewRunnableFunction(
+     "dom::workers::ServiceWorkerManager::DispatchFetchEvent", [=]() {
+       nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
+       MOZ_ALWAYS_SUCCEEDS(permMgr->WhenPermissionsAvailable(serviceWorker->Principal(),
+                                                             continueRunnable));
+     });
+ 
+-  nsCOMPtr<nsIChannel> innerChannel;
+-  aRv = aChannel->GetChannel(getter_AddRefs(innerChannel));
+-  if (NS_WARN_IF(aRv.Failed())) {
+-    return;
+-  }
+-
+-  nsCOMPtr<nsIUploadChannel2> uploadChannel = do_QueryInterface(innerChannel);
++  nsCOMPtr<nsIUploadChannel2> uploadChannel = do_QueryInterface(internalChannel);
+ 
+   // If there is no upload stream, then continue immediately
+   if (!uploadChannel) {
+     MOZ_ALWAYS_SUCCEEDS(permissionsRunnable->Run());
+     return;
+   }
+   // Otherwise, ensure the upload stream can be cloned directly.  This may
+   // require some async copying, so provide a callback.
+@@ -3087,16 +3109,29 @@ ServiceWorkerManager::GetRegistration(ns
+   nsresult rv = PrincipalToScopeKey(aPrincipal, scopeKey);
+   if (NS_WARN_IF(NS_FAILED(rv))) {
+     return nullptr;
+   }
+ 
+   return GetRegistration(scopeKey, aScope);
+ }
+ 
++already_AddRefed<ServiceWorkerRegistrationInfo>
++ServiceWorkerManager::GetRegistration(const PrincipalInfo& aPrincipalInfo,
++                                      const nsACString& aScope) const
++{
++  nsAutoCString scopeKey;
++  nsresult rv = PrincipalInfoToScopeKey(aPrincipalInfo, scopeKey);
++  if (NS_WARN_IF(NS_FAILED(rv))) {
++    return nullptr;
++  }
++
++  return GetRegistration(scopeKey, aScope);
++}
++
+ NS_IMETHODIMP
+ ServiceWorkerManager::GetRegistrationByPrincipal(nsIPrincipal* aPrincipal,
+                                                  const nsAString& aScope,
+                                                  nsIServiceWorkerRegistrationInfo** aInfo)
+ {
+   MOZ_ASSERT(aPrincipal);
+   MOZ_ASSERT(aInfo);
+ 
+diff --git a/dom/workers/ServiceWorkerManager.h b/dom/workers/ServiceWorkerManager.h
+--- a/dom/workers/ServiceWorkerManager.h
++++ b/dom/workers/ServiceWorkerManager.h
+@@ -35,16 +35,20 @@
+ #include "nsTObserverArray.h"
+ 
+ class nsIConsoleReportCollector;
+ 
+ namespace mozilla {
+ 
+ class OriginAttributes;
+ 
++namespace ipc {
++class PrincipalInfo;
++} // namespace ipc
++
+ namespace dom {
+ 
+ class ServiceWorkerRegistrar;
+ class ServiceWorkerRegistrationListener;
+ 
+ namespace workers {
+ 
+ class ServiceWorkerInfo;
+@@ -137,22 +141,17 @@ public:
+   // semantics that ensure this method returns true until the worker is known to
+   // have shut down in order to allow the caller to induce a crash for security
+   // reasons without having to worry about shutdown races with the worker.
+   bool
+   MayHaveActiveServiceWorkerInstance(ContentParent* aContent,
+                                      nsIPrincipal* aPrincipal);
+ 
+   void
+-  DispatchFetchEvent(const OriginAttributes& aOriginAttributes,
+-                     nsIDocument* aDoc,
+-                     nsIInterceptedChannel* aChannel,
+-                     bool aIsReload,
+-                     bool aIsSubresourceLoad,
+-                     ErrorResult& aRv);
++  DispatchFetchEvent(nsIInterceptedChannel* aChannel, ErrorResult& aRv);
+ 
+   void
+   Update(nsIPrincipal* aPrincipal,
+          const nsACString& aScope,
+          ServiceWorkerUpdateFinishCallback* aCallback);
+ 
+   void
+   UpdateInternal(nsIPrincipal* aPrincipal,
+@@ -184,16 +183,20 @@ public:
+ 
+   void
+   RemoveAll();
+ 
+   already_AddRefed<ServiceWorkerRegistrationInfo>
+   GetRegistration(nsIPrincipal* aPrincipal, const nsACString& aScope) const;
+ 
+   already_AddRefed<ServiceWorkerRegistrationInfo>
++  GetRegistration(const mozilla::ipc::PrincipalInfo& aPrincipal,
++                  const nsACString& aScope) const;
++
++  already_AddRefed<ServiceWorkerRegistrationInfo>
+   CreateNewRegistration(const nsCString& aScope,
+                         nsIPrincipal* aPrincipal,
+                         ServiceWorkerUpdateViaCache aUpdateViaCache);
+ 
+   void
+   RemoveRegistration(ServiceWorkerRegistrationInfo* aRegistration);
+ 
+   void StoreRegistration(nsIPrincipal* aPrincipal,
+@@ -392,16 +395,20 @@ private:
+                                    nsIURI* aURI);
+ 
+   // This method generates a key using appId and isInElementBrowser from the
+   // principal. We don't use the origin because it can change during the
+   // loading.
+   static nsresult
+   PrincipalToScopeKey(nsIPrincipal* aPrincipal, nsACString& aKey);
+ 
++  static nsresult
++  PrincipalInfoToScopeKey(const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
++                          nsACString& aKey);
++
+   static void
+   AddScopeAndRegistration(const nsACString& aScope,
+                           ServiceWorkerRegistrationInfo* aRegistation);
+ 
+   static bool
+   FindScopeForPath(const nsACString& aScopeKey,
+                    const nsACString& aPath,
+                    RegistrationDataPerPrincipal** aData, nsACString& aMatch);

+ 296 - 0
mozilla-release/patches/1231211-10-60a1.patch

@@ -0,0 +1,296 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1516721933 18000
+# Node ID 0c329c76fc13f6ef193b1ca067333984bcad4638
+# Parent  b4574e2e60c85026b073f4b7f9a3a0cbd8acdcdf
+Bug 1231211 P10 Move nsDocShell logic into separate ServiceWorkerInterceptController. r=asuth
+
+diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
+--- a/docshell/base/nsDocShell.cpp
++++ b/docshell/base/nsDocShell.cpp
+@@ -41,16 +41,17 @@
+ #include "mozilla/dom/DocGroup.h"
+ #include "mozilla/dom/Element.h"
+ #include "mozilla/dom/HTMLAnchorElement.h"
+ #include "mozilla/dom/PerformanceNavigation.h"
+ #include "mozilla/dom/PermissionMessageUtils.h"
+ #include "mozilla/dom/ProfileTimelineMarkerBinding.h"
+ #include "mozilla/dom/ScreenOrientation.h"
+ #include "mozilla/dom/ScriptSettings.h"
++#include "mozilla/dom/ServiceWorkerInterceptController.h"
+ #include "mozilla/dom/TabChild.h"
+ #include "mozilla/dom/TabGroup.h"
+ #include "mozilla/dom/ToJSValue.h"
+ 
+ #include "mozilla/dom/workers/ServiceWorkerManager.h"
+ 
+ #include "mozilla/net/ReferrerPolicy.h"
+ 
+@@ -458,16 +459,18 @@ nsDocShell::Init()
+   NS_ENSURE_SUCCESS(rv, rv);
+ 
+   NS_ASSERTION(mLoadGroup, "Something went wrong!");
+ 
+   mContentListener = new nsDSURIContentListener(this);
+   rv = mContentListener->Init();
+   NS_ENSURE_SUCCESS(rv, rv);
+ 
++  mInterceptController = new ServiceWorkerInterceptController();
++
+   // We want to hold a strong ref to the loadgroup, so it better hold a weak
+   // ref to us...  use an InterfaceRequestorProxy to do this.
+   nsCOMPtr<nsIInterfaceRequestor> proxy =
+     new InterfaceRequestorProxy(static_cast<nsIInterfaceRequestor*>(this));
+   mLoadGroup->SetNotificationCallbacks(proxy);
+ 
+   rv = nsDocLoader::AddDocLoaderAsChildOfRoot(this);
+   NS_ENSURE_SUCCESS(rv, rv);
+@@ -14222,71 +14225,24 @@ nsDocShell::MaybeNotifyKeywordSearchLoad
+   }
+ #endif
+ }
+ 
+ NS_IMETHODIMP
+ nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, nsIChannel* aChannel,
+                                       bool* aShouldIntercept)
+ {
+-  *aShouldIntercept = false;
+-
+-  nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
+-  if (!loadInfo) {
+-    return NS_OK;
+-  }
+-
+-  // For subresource requests we base our decision solely on the client's
+-  // controller value.  Any settings that would have blocked service worker
+-  // access should have been set before the initial navigation created the
+-  // window.
+-  if (!nsContentUtils::IsNonSubresourceRequest(aChannel)) {
+-    const Maybe<ServiceWorkerDescriptor>& controller = loadInfo->GetController();
+-    *aShouldIntercept = controller.isSome();
+-    return NS_OK;
+-  }
+-
+-  nsCOMPtr<nsIPrincipal> principal =
+-    BasePrincipal::CreateCodebasePrincipal(aURI,
+-                                           loadInfo->GetOriginAttributes());
+-
+-  // For navigations, first check to see if we are allowed to control a
+-  // window with the given URL.
+-  if (!ServiceWorkerAllowedToControlWindow(principal, aURI)) {
+-    return NS_OK;
+-  }
+-
+-  RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
+-  if (!swm) {
+-    return NS_OK;
+-  }
+-
+-  // We're allowed to control a window, so check with the ServiceWorkerManager
+-  // for a matching service worker.
+-  *aShouldIntercept = swm->IsAvailable(principal, aURI);
+-  return NS_OK;
++  return mInterceptController->ShouldPrepareForIntercept(aURI, aChannel,
++                                                         aShouldIntercept);
+ }
+ 
+ NS_IMETHODIMP
+ nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel)
+ {
+-  RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
+-  if (!swm) {
+-    aChannel->CancelInterception(NS_ERROR_INTERCEPTION_FAILED);
+-    return NS_OK;
+-  }
+-
+-  ErrorResult error;
+-  swm->DispatchFetchEvent(aChannel, error);
+-  if (NS_WARN_IF(error.Failed())) {
+-    aChannel->CancelInterception(NS_ERROR_INTERCEPTION_FAILED);
+-    return error.StealNSResult();
+-  }
+-
+-  return NS_OK;
++  return mInterceptController->ChannelIntercepted(aChannel);
+ }
+ 
+ bool
+ nsDocShell::InFrameSwap()
+ {
+   RefPtr<nsDocShell> shell = this;
+   do {
+     if (shell->mInFrameSwap) {
+diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
+--- a/docshell/base/nsDocShell.h
++++ b/docshell/base/nsDocShell.h
+@@ -904,16 +904,17 @@ private: // data members
+   nsCString mOriginalUriString;
+   nsWeakPtr mOnePermittedSandboxedNavigator;
+   nsWeakPtr mOpener;
+   nsTObserverArray<nsWeakPtr> mPrivacyObservers;
+   nsTObserverArray<nsWeakPtr> mReflowObservers;
+   nsTObserverArray<nsWeakPtr> mScrollObservers;
+   mozilla::OriginAttributes mOriginAttributes;
+   mozilla::UniquePtr<mozilla::dom::ClientSource> mInitialClientSource;
++  nsCOMPtr<nsINetworkInterceptController> mInterceptController;
+   RefPtr<nsDOMNavigationTiming> mTiming;
+   RefPtr<nsDSURIContentListener> mContentListener;
+   RefPtr<nsGlobalWindow> mScriptGlobal;
+   nsCOMPtr<nsIPrincipal> mParentCharsetPrincipal;
+   nsCOMPtr<nsIMutableArray> mRefreshURIList;
+   nsCOMPtr<nsIMutableArray> mSavedRefreshURIList;
+   nsCOMPtr<nsIDOMStorageManager> mSessionStorageManager;
+   nsCOMPtr<nsIContentViewer> mContentViewer;
+diff --git a/dom/workers/ServiceWorkerInterceptController.cpp b/dom/workers/ServiceWorkerInterceptController.cpp
+new file mode 100644
+--- /dev/null
++++ b/dom/workers/ServiceWorkerInterceptController.cpp
+@@ -0,0 +1,76 @@
++/* -*- 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 "ServiceWorkerInterceptController.h"
++
++#include "mozilla/BasePrincipal.h"
++#include "nsContentUtils.h"
++#include "nsIChannel.h"
++#include "ServiceWorkerManager.h"
++
++namespace mozilla {
++namespace dom {
++
++NS_IMPL_ISUPPORTS(ServiceWorkerInterceptController, nsINetworkInterceptController)
++
++NS_IMETHODIMP
++ServiceWorkerInterceptController::ShouldPrepareForIntercept(nsIURI* aURI,
++                                                            nsIChannel* aChannel,
++                                                            bool* aShouldIntercept)
++{
++  *aShouldIntercept = false;
++
++  nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
++  if (!loadInfo) {
++    return NS_OK;
++  }
++
++  // For subresource requests we base our decision solely on the client's
++  // controller value.  Any settings that would have blocked service worker
++  // access should have been set before the initial navigation created the
++  // window.
++  if (!nsContentUtils::IsNonSubresourceRequest(aChannel)) {
++    const Maybe<ServiceWorkerDescriptor>& controller = loadInfo->GetController();
++    *aShouldIntercept = controller.isSome();
++    return NS_OK;
++  }
++
++  nsCOMPtr<nsIPrincipal> principal =
++    BasePrincipal::CreateCodebasePrincipal(aURI,
++                                           loadInfo->GetOriginAttributes());
++
++  RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
++  if (!swm) {
++    return NS_OK;
++  }
++
++  // We're allowed to control a window, so check with the ServiceWorkerManager
++  // for a matching service worker.
++  *aShouldIntercept = swm->IsAvailable(principal, aURI);
++  return NS_OK;
++}
++
++NS_IMETHODIMP
++ServiceWorkerInterceptController::ChannelIntercepted(nsIInterceptedChannel* aChannel)
++{
++  RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
++  if (!swm) {
++    aChannel->CancelInterception(NS_ERROR_INTERCEPTION_FAILED);
++    return NS_OK;
++  }
++
++  ErrorResult error;
++  swm->DispatchFetchEvent(aChannel, error);
++  if (NS_WARN_IF(error.Failed())) {
++    aChannel->CancelInterception(NS_ERROR_INTERCEPTION_FAILED);
++    return error.StealNSResult();
++  }
++
++  return NS_OK;
++}
++
++} // namespace dom
++} // namespace mozilla
+diff --git a/dom/workers/ServiceWorkerInterceptController.h b/dom/workers/ServiceWorkerInterceptController.h
+new file mode 100644
+--- /dev/null
++++ b/dom/workers/ServiceWorkerInterceptController.h
+@@ -0,0 +1,28 @@
++/* -*- 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/. */
++
++#ifndef mozilla_dom_serviceworkerinterceptcontroller_h
++#define mozilla_dom_serviceworkerinterceptcontroller_h
++
++#include "nsINetworkInterceptController.h"
++
++namespace mozilla {
++namespace dom {
++
++class ServiceWorkerInterceptController final : public nsINetworkInterceptController
++{
++  ~ServiceWorkerInterceptController() = default;
++
++public:
++  NS_DECL_ISUPPORTS
++  NS_DECL_NSINETWORKINTERCEPTCONTROLLER
++};
++
++} // namespace dom
++} // namespace mozilla
++
++#endif // mozilla_dom_serviceworkerinterceptcontroller_h
++
+diff --git a/dom/workers/moz.build b/dom/workers/moz.build
+--- a/dom/workers/moz.build
++++ b/dom/workers/moz.build
+@@ -9,16 +9,17 @@ with Files("**"):
+ 
+ # Public stuff.
+ EXPORTS.mozilla.dom += [
+     'FileReaderSync.h',
+     'ServiceWorkerCommon.h',
+     'ServiceWorkerContainer.h',
+     'ServiceWorkerDescriptor.h',
+     'ServiceWorkerEvents.h',
++    'ServiceWorkerInterceptController.h',
+     'ServiceWorkerIPCUtils.h',
+     'ServiceWorkerRegistrar.h',
+     'ServiceWorkerRegistration.h',
+     'WorkerLocation.h',
+     'WorkerNavigator.h',
+     'WorkerPrivate.h',
+     'WorkerRunnable.h',
+     'WorkerScope.h',
+@@ -55,16 +56,17 @@ UNIFIED_SOURCES += [
+     'RegisterBindings.cpp',
+     'RuntimeService.cpp',
+     'ScriptLoader.cpp',
+     'ServiceWorker.cpp',
+     'ServiceWorkerContainer.cpp',
+     'ServiceWorkerDescriptor.cpp',
+     'ServiceWorkerEvents.cpp',
+     'ServiceWorkerInfo.cpp',
++    'ServiceWorkerInterceptController.cpp',
+     'ServiceWorkerJob.cpp',
+     'ServiceWorkerJobQueue.cpp',
+     'ServiceWorkerManager.cpp',
+     'ServiceWorkerManagerChild.cpp',
+     'ServiceWorkerManagerParent.cpp',
+     'ServiceWorkerManagerService.cpp',
+     'ServiceWorkerPrivate.cpp',
+     'ServiceWorkerRegisterJob.cpp',

+ 253 - 0
mozilla-release/patches/1231211-11-60a1.patch

@@ -0,0 +1,253 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1516721933 18000
+# Node ID af8c5b7bf7961f4324412b5aeafef68e018328cc
+# Parent  175c6d456b3086ab317660dc94538a6892c30548
+Bug 1231211 P11 Add a StorageAllowedForChannel() and use it in ServiceWorkerInterceptController. r=asuth
+
+diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
+--- a/dom/base/nsContentUtils.cpp
++++ b/dom/base/nsContentUtils.cpp
+@@ -9068,54 +9068,75 @@ nsContentUtils::IsNonSubresourceInternal
+ // static, public
+ nsContentUtils::StorageAccess
+ nsContentUtils::StorageAllowedForWindow(nsPIDOMWindowInner* aWindow)
+ {
+   MOZ_ASSERT(aWindow->IsInnerWindow());
+ 
+   if (nsIDocument* document = aWindow->GetExtantDoc()) {
+     nsCOMPtr<nsIPrincipal> principal = document->NodePrincipal();
+-    return InternalStorageAllowedForPrincipal(principal, aWindow, nullptr);
++    return InternalStorageAllowedForPrincipal(principal, aWindow, nullptr,
++                                              nullptr);
+   }
+ 
+   return StorageAccess::eDeny;
+ }
+ 
+ // static, public
+ nsContentUtils::StorageAccess
+ nsContentUtils::StorageAllowedForDocument(nsIDocument* aDoc)
+ {
+   MOZ_ASSERT(aDoc);
+ 
+   if (nsPIDOMWindowInner* inner = aDoc->GetInnerWindow()) {
+     nsCOMPtr<nsIPrincipal> principal = aDoc->NodePrincipal();
+-    return InternalStorageAllowedForPrincipal(principal, inner, nullptr);
++    return InternalStorageAllowedForPrincipal(principal, inner, nullptr,
++                                              nullptr);
+   }
+ 
+   return StorageAccess::eDeny;
+ }
+ 
+ // static, public
+ nsContentUtils::StorageAccess
+ nsContentUtils::StorageAllowedForNewWindow(nsIPrincipal* aPrincipal,
+                                            nsIURI* aURI,
+                                            nsPIDOMWindowInner* aParent)
+ {
+   MOZ_ASSERT(aPrincipal);
+   MOZ_ASSERT(aURI);
+   // parent may be nullptr
+ 
+-  return InternalStorageAllowedForPrincipal(aPrincipal, aParent, aURI);
++  return InternalStorageAllowedForPrincipal(aPrincipal, aParent, aURI, nullptr);
++}
++
++// static, public
++nsContentUtils::StorageAccess
++nsContentUtils::StorageAllowedForChannel(nsIChannel* aChannel)
++{
++  MOZ_DIAGNOSTIC_ASSERT(sSecurityManager);
++  MOZ_DIAGNOSTIC_ASSERT(aChannel);
++
++  nsCOMPtr<nsIPrincipal> principal;
++  Unused << sSecurityManager->GetChannelResultPrincipal(aChannel,
++                                                        getter_AddRefs(principal));
++  NS_ENSURE_TRUE(principal, nsContentUtils::StorageAccess::eDeny);
++
++  nsContentUtils::StorageAccess result =
++    InternalStorageAllowedForPrincipal(principal, nullptr, nullptr, aChannel);
++
++  return result;
+ }
+ 
+ // static, public
+ nsContentUtils::StorageAccess
+ nsContentUtils::StorageAllowedForPrincipal(nsIPrincipal* aPrincipal)
+ {
+-  return InternalStorageAllowedForPrincipal(aPrincipal, nullptr, nullptr);
++  return InternalStorageAllowedForPrincipal(aPrincipal, nullptr, nullptr,
++                                            nullptr);
+ }
+ 
+ // static, private
+ void
+ nsContentUtils::GetCookieBehaviorForPrincipal(nsIPrincipal* aPrincipal,
+                                               uint32_t* aLifetimePolicy,
+                                               uint32_t* aBehavior)
+ {
+@@ -9165,17 +9186,18 @@ nsContentUtils::GetCookieBehaviorForPrin
+       break;
+   }
+ }
+ 
+ // static, private
+ nsContentUtils::StorageAccess
+ nsContentUtils::InternalStorageAllowedForPrincipal(nsIPrincipal* aPrincipal,
+                                                    nsPIDOMWindowInner* aWindow,
+-                                                   nsIURI* aURI)
++                                                   nsIURI* aURI,
++                                                   nsIChannel* aChannel)
+ {
+   MOZ_ASSERT(aPrincipal);
+   MOZ_ASSERT(!aWindow || aWindow->IsInnerWindow());
+ 
+   StorageAccess access = StorageAccess::eAllow;
+ 
+   // We don't allow storage on the null principal, in general. Even if the
+   // calling context is chrome.
+@@ -9243,26 +9265,50 @@ nsContentUtils::InternalStorageAllowedFo
+     }
+   }
+ 
+   // We don't want to prompt for every attempt to access permissions.
+   if (behavior == nsICookieService::BEHAVIOR_REJECT) {
+     return StorageAccess::eDeny;
+   }
+ 
+-  // In the absense of a window, we assume that we are first-party.
+-  if (aWindow && (behavior == nsICookieService::BEHAVIOR_REJECT_FOREIGN ||
+-                  behavior == nsICookieService::BEHAVIOR_LIMIT_FOREIGN)) {
+-    nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
+-      do_GetService(THIRDPARTYUTIL_CONTRACTID);
+-    MOZ_ASSERT(thirdPartyUtil);
+-
+-    bool thirdPartyWindow = false;
+-    if (NS_SUCCEEDED(thirdPartyUtil->IsThirdPartyWindow(
+-          aWindow->GetOuterWindow(), aURI, &thirdPartyWindow)) && thirdPartyWindow) {
++  if (behavior == nsICookieService::BEHAVIOR_REJECT_FOREIGN ||
++      behavior == nsICookieService::BEHAVIOR_LIMIT_FOREIGN) {
++
++    // In the absence of a window or channel, we assume that we are first-party.
++    bool thirdParty = false;
++
++    MOZ_ASSERT(!aWindow || !aChannel,
++               "A window and channel should not both be provided.");
++
++    if (aWindow) {
++      nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
++        do_GetService(THIRDPARTYUTIL_CONTRACTID);
++      MOZ_ASSERT(thirdPartyUtil);
++
++      Unused << thirdPartyUtil->IsThirdPartyWindow(aWindow->GetOuterWindow(),
++                                                   aURI,
++                                                   &thirdParty);
++    }
++
++    if (aChannel) {
++      nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
++        do_GetService(THIRDPARTYUTIL_CONTRACTID);
++      MOZ_ASSERT(thirdPartyUtil);
++
++      // Note, we must call IsThirdPartyChannel() here and not just try to
++      // use nsILoadInfo.isThirdPartyContext.  That nsILoadInfo property only
++      // indicates if the parent loading window is third party or not.  We
++      // want to check the channel URI against the loading principal as well.
++      Unused << thirdPartyUtil->IsThirdPartyChannel(aChannel,
++                                                    nullptr,
++                                                    &thirdParty);
++    }
++
++    if (thirdParty) {
+       // XXX For non-cookie forms of storage, we handle BEHAVIOR_LIMIT_FOREIGN by
+       // simply rejecting the request to use the storage. In the future, if we
+       // change the meaning of BEHAVIOR_LIMIT_FOREIGN to be one which makes sense
+       // for non-cookie storage types, this may change.
+ 
+       return StorageAccess::eDeny;
+     }
+   }
+diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h
+--- a/dom/base/nsContentUtils.h
++++ b/dom/base/nsContentUtils.h
+@@ -2997,16 +2997,23 @@ public:
+    * Checks if storage should be allowed for a new window with the given
+    * principal, load URI, and parent.
+    */
+   static StorageAccess StorageAllowedForNewWindow(nsIPrincipal* aPrincipal,
+                                                   nsIURI* aURI,
+                                                   nsPIDOMWindowInner* aParent);
+ 
+   /*
++   * Checks if storage should be allowed for the given channel.  The check will
++   * be based on the channel result principal and, depending on preferences and
++   * permissions, mozIThirdPartyUtil.isThirdPartyChannel().
++   */
++  static StorageAccess StorageAllowedForChannel(nsIChannel* aChannel);
++
++  /*
+    * Checks if storage for the given principal is permitted by the user's
+    * preferences. The caller is assumed to not be a third-party iframe.
+    * (if that is possible, the caller should use StorageAllowedForWindow)
+    */
+   static StorageAccess StorageAllowedForPrincipal(nsIPrincipal* aPrincipal);
+ 
+   /*
+    * Serializes a HTML nsINode into its markup representation.
+@@ -3365,24 +3372,27 @@ private:
+                                             uint32_t* aLifetimePolicy,
+                                             uint32_t* aBehavior);
+ 
+   /*
+    * Checks if storage for a given principal is permitted by the user's
+    * preferences. If aWindow is non-null, its principal must be passed as
+    * aPrincipal, and the third-party iframe and sandboxing status of the window
+    * are also checked.  If aURI is non-null, then it is used as the comparison
+-   * against aWindow to determine if this is a third-party load.
++   * against aWindow to determine if this is a third-party load.  We also
++   * allow a channel instead of the window reference when determining 3rd party
++   * status.
+    *
+    * Used in the implementation of StorageAllowedForWindow and
+    * StorageAllowedForPrincipal.
+    */
+   static StorageAccess InternalStorageAllowedForPrincipal(nsIPrincipal* aPrincipal,
+                                                           nsPIDOMWindowInner* aWindow,
+-                                                          nsIURI* aURI);
++                                                          nsIURI* aURI,
++                                                          nsIChannel* aChannel);
+ 
+   static nsINode* GetCommonAncestorHelper(nsINode* aNode1, nsINode* aNode2);
+   static nsIContent* GetCommonFlattenedTreeAncestorHelper(nsIContent* aContent1,
+                                                           nsIContent* aContent2);
+ 
+   static nsIXPConnect *sXPConnect;
+ 
+   static nsIScriptSecurityManager *sSecurityManager;
+diff --git a/dom/workers/ServiceWorkerInterceptController.cpp b/dom/workers/ServiceWorkerInterceptController.cpp
+--- a/dom/workers/ServiceWorkerInterceptController.cpp
++++ b/dom/workers/ServiceWorkerInterceptController.cpp
+@@ -33,16 +33,21 @@ ServiceWorkerInterceptController::Should
+   // access should have been set before the initial navigation created the
+   // window.
+   if (!nsContentUtils::IsNonSubresourceRequest(aChannel)) {
+     const Maybe<ServiceWorkerDescriptor>& controller = loadInfo->GetController();
+     *aShouldIntercept = controller.isSome();
+     return NS_OK;
+   }
+ 
++  if (nsContentUtils::StorageAllowedForChannel(aChannel) !=
++      nsContentUtils::StorageAccess::eAllow) {
++    return NS_OK;
++  }
++
+   nsCOMPtr<nsIPrincipal> principal =
+     BasePrincipal::CreateCodebasePrincipal(aURI,
+                                            loadInfo->GetOriginAttributes());
+ 
+   RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
+   if (!swm) {
+     return NS_OK;
+   }

+ 1025 - 0
mozilla-release/patches/1231211-12-60a1.patch

@@ -0,0 +1,1025 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1516721934 18000
+# Node ID 60a29396c52fcd556f9f0ebf52f11811cf7f912d
+# Parent  d52014b80c4fb4223102e555f5e9e58cfca3147d
+Bug 1231211 P12 Allow the ClientInfo and ServiceWorkerDescriptor to be passed to NS_NewChannel() for principal based loads. r=valentin
+
+diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp
+--- a/netwerk/base/LoadInfo.cpp
++++ b/netwerk/base/LoadInfo.cpp
+@@ -41,22 +41,26 @@ FindTopOuterWindowID(nsPIDOMWindowOuter*
+   }
+   return outer->WindowID();
+ }
+ 
+ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
+                    nsIPrincipal* aTriggeringPrincipal,
+                    nsINode* aLoadingContext,
+                    nsSecurityFlags aSecurityFlags,
+-                   nsContentPolicyType aContentPolicyType)
++                   nsContentPolicyType aContentPolicyType,
++                   const Maybe<mozilla::dom::ClientInfo>& aLoadingClientInfo,
++                   const Maybe<mozilla::dom::ServiceWorkerDescriptor>& aController)
+   : mLoadingPrincipal(aLoadingContext ?
+                         aLoadingContext->NodePrincipal() : aLoadingPrincipal)
+   , mTriggeringPrincipal(aTriggeringPrincipal ?
+                            aTriggeringPrincipal : mLoadingPrincipal.get())
+   , mPrincipalToInherit(nullptr)
++  , mClientInfo(aLoadingClientInfo)
++  , mController(aController)
+   , mLoadingContext(do_GetWeakReference(aLoadingContext))
+   , mContextForTopLevelLoad(nullptr)
+   , mSecurityFlags(aSecurityFlags)
+   , mInternalContentPolicyType(aContentPolicyType)
+   , mTainting(LoadTainting::Basic)
+   , mUpgradeInsecureRequests(false)
+   , mVerifySignedContent(false)
+   , mEnforceSRI(false)
+@@ -87,16 +91,21 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadin
+   skipContentTypeCheck = Preferences::GetBool("network.loadinfo.skip_type_assertion");
+ #endif
+ 
+   // This constructor shouldn't be used for TYPE_DOCUMENT loads that don't
+   // have a loadingPrincipal
+   MOZ_ASSERT(skipContentTypeCheck || mLoadingPrincipal ||
+              mInternalContentPolicyType != nsIContentPolicy::TYPE_DOCUMENT);
+ 
++  // We should only get an explicit controller for subresource requests.
++  MOZ_DIAGNOSTIC_ASSERT(
++    aController.isNothing() ||
++    !nsContentUtils::IsNonSubresourceInternalPolicyType(mInternalContentPolicyType));
++
+   // TODO(bug 1259873): Above, we initialize mIsThirdPartyContext to false meaning
+   // that consumers of LoadInfo that don't pass a context or pass a context from
+   // which we can't find a window will default to assuming that they're 1st
+   // party. It would be nice if we could default "safe" and assume that we are
+   // 3rd party until proven otherwise.
+ 
+   // if consumers pass both, aLoadingContext and aLoadingPrincipal
+   // then the loadingPrincipal must be the same as the node's principal
+@@ -107,26 +116,28 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadin
+   if (mSecurityFlags & nsILoadInfo::SEC_SANDBOXED) {
+     mForceInheritPrincipalDropped =
+       (mSecurityFlags & nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL);
+     mSecurityFlags &= ~nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
+   }
+ 
+   if (aLoadingContext) {
+     // Ensure that all network requests for a window client have the ClientInfo
+-    // properly set.
+-    // TODO: The ClientInfo is not set properly for worker initiated requests yet.
+-    mClientInfo = aLoadingContext->OwnerDoc()->GetClientInfo();
++    // properly set.  Workers must currently pass the loading ClientInfo explicitly.
++    // We allow main thread requests to explicitly pass the value as well.
++    if (mClientInfo.isNothing()) {
++      mClientInfo = aLoadingContext->OwnerDoc()->GetClientInfo();
++    }
+ 
+     // For subresource loads set the service worker based on the calling
+-    // context's controller.
+-    // TODO: The controller is not set properly for all requests initiated from a
+-    //       worker context.  Some workers will not have an nsINode loading context
+-    //       here.
+-    if (!nsContentUtils::IsNonSubresourceInternalPolicyType(mInternalContentPolicyType)) {
++    // context's controller.  Workers must currently pass the controller in
++    // explicitly.  We allow main thread requests to explicitly pass the value
++    // as well, but otherwise extract from the loading context here.
++    if (mController.isNothing() &&
++        !nsContentUtils::IsNonSubresourceInternalPolicyType(mInternalContentPolicyType)) {
+       mController = aLoadingContext->OwnerDoc()->GetController();
+     }
+ 
+     nsCOMPtr<nsPIDOMWindowOuter> contextOuter = aLoadingContext->OwnerDoc()->GetWindow();
+     if (contextOuter) {
+       ComputeIsThirdPartyContext(contextOuter);
+       mOuterWindowID = contextOuter->WindowID();
+       nsCOMPtr<nsPIDOMWindowOuter> parent = contextOuter->GetScriptableParent();
+diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h
+--- a/netwerk/base/LoadInfo.h
++++ b/netwerk/base/LoadInfo.h
+@@ -51,17 +51,21 @@ public:
+   NS_DECL_ISUPPORTS
+   NS_DECL_NSILOADINFO
+ 
+   // aLoadingPrincipal MUST NOT BE NULL.
+   LoadInfo(nsIPrincipal* aLoadingPrincipal,
+            nsIPrincipal* aTriggeringPrincipal,
+            nsINode* aLoadingContext,
+            nsSecurityFlags aSecurityFlags,
+-           nsContentPolicyType aContentPolicyType);
++           nsContentPolicyType aContentPolicyType,
++           const Maybe<mozilla::dom::ClientInfo>& aLoadingClientInfo
++              = Maybe<mozilla::dom::ClientInfo>(),
++           const Maybe<mozilla::dom::ServiceWorkerDescriptor>& aController
++              = Maybe<mozilla::dom::ServiceWorkerDescriptor>());
+ 
+   // Constructor used for TYPE_DOCUMENT loads which have a different
+   // loadingContext than other loads. This ContextForTopLevelLoad is
+   // only used for content policy checks.
+   LoadInfo(nsPIDOMWindowOuter* aOuterWindow,
+            nsIPrincipal* aTriggeringPrincipal,
+            nsISupports* aContextForTopLevelLoad,
+            nsSecurityFlags aSecurityFlags);
+diff --git a/netwerk/base/nsIIOService.idl b/netwerk/base/nsIIOService.idl
+--- a/netwerk/base/nsIIOService.idl
++++ b/netwerk/base/nsIIOService.idl
+@@ -8,16 +8,30 @@
+ interface nsIProtocolHandler;
+ interface nsIChannel;
+ interface nsIURI;
+ interface nsIFile;
+ interface nsIDOMNode;
+ interface nsIPrincipal;
+ interface nsILoadInfo;
+ 
++%{C++
++#include "mozilla/Maybe.h"
++
++namespace mozilla {
++namespace dom {
++class ClientInfo;
++class ServiceWorkerDescriptor;
++} // namespace dom
++} // namespace mozilla
++%}
++
++[ref] native const_MaybeClientInfoRef(const mozilla::Maybe<mozilla::dom::ClientInfo>);
++[ref] native const_MaybeServiceWorkerDescriptorRef(const mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor>);
++
+ /**
+  * nsIIOService provides a set of network utility functions.  This interface
+  * duplicates many of the nsIProtocolHandler methods in a protocol handler
+  * independent way (e.g., NewURI inspects the scheme in order to delegate
+  * creation of the new URI to the appropriate protocol handler).  nsIIOService
+  * also provides a set of URL parsing utility functions.  These are provided
+  * as a convenience to the programmer and in some cases to improve performance
+  * by eliminating intermediate data structures and interfaces.
+@@ -88,16 +102,27 @@ interface nsIIOService : nsISupports
+      */
+     nsIChannel newChannelFromURI2(in nsIURI aURI,
+                                   in nsIDOMNode aLoadingNode,
+                                   in nsIPrincipal aLoadingPrincipal,
+                                   in nsIPrincipal aTriggeringPrincipal,
+                                   in unsigned long aSecurityFlags,
+                                   in unsigned long aContentPolicyType);
+ 
++    [noscript, nostdcall, notxpcom]
++    nsresult NewChannelFromURIWithClientAndController(in nsIURI aURI,
++                                                      in nsIDOMNode aLoadingNode,
++                                                      in nsIPrincipal aLoadingPrincipal,
++                                                      in nsIPrincipal aTriggeringPrincipal,
++                                                      in const_MaybeClientInfoRef aLoadingClientInfo,
++                                                      in const_MaybeServiceWorkerDescriptorRef aController,
++                                                      in unsigned long aSecurityFlags,
++                                                      in unsigned long aContentPolicyType,
++                                                      out nsIChannel aResult);
++
+     /**
+      * Equivalent to newChannelFromURI2(aURI, aLoadingNode, ...)
+      */
+     nsIChannel newChannelFromURIWithLoadInfo(in nsIURI aURI,
+                                              in nsILoadInfo aLoadInfo);
+ 
+     /**
+      * Equivalent to newChannelFromURI2(newURI(...))
+diff --git a/netwerk/base/nsIOService.cpp b/netwerk/base/nsIOService.cpp
+--- a/netwerk/base/nsIOService.cpp
++++ b/netwerk/base/nsIOService.cpp
+@@ -47,27 +47,33 @@
+ #include "nsThreadUtils.h"
+ #include "mozilla/LoadInfo.h"
+ #include "mozilla/net/NeckoCommon.h"
+ #include "mozilla/Services.h"
+ #include "mozilla/net/DNS.h"
+ #include "mozilla/ipc/URIUtils.h"
+ #include "mozilla/net/NeckoChild.h"
+ #include "mozilla/net/NeckoParent.h"
++#include "mozilla/dom/ClientInfo.h"
+ #include "mozilla/dom/ContentParent.h"
++#include "mozilla/dom/ServiceWorkerDescriptor.h"
+ #include "mozilla/net/CaptivePortalService.h"
+ #include "mozilla/Unused.h"
+ #include "ReferrerPolicy.h"
+ #include "nsContentSecurityManager.h"
+ #include "nsContentUtils.h"
+ #include "xpcpublic.h"
+ 
+ namespace mozilla {
+ namespace net {
+ 
++using mozilla::Maybe;
++using mozilla::dom::ClientInfo;
++using mozilla::dom::ServiceWorkerDescriptor;
++
+ #define PORT_PREF_PREFIX           "network.security.ports."
+ #define PORT_PREF(x)               PORT_PREF_PREFIX x
+ #define MANAGE_OFFLINE_STATUS_PREF "network.manage-offline-status"
+ #define OFFLINE_MIRRORS_CONNECTIVITY "network.offline-mirrors-connectivity"
+ 
+ // Nb: these have been misnomers since bug 715770 removed the buffer cache.
+ // "network.segment.count" and "network.segment.size" would be better names,
+ // but the old names are still used to preserve backward compatibility.
+@@ -745,16 +751,39 @@ nsIOService::NewChannelFromURI2(nsIURI* 
+                                             0,       // aProxyFlags
+                                             aLoadingNode,
+                                             aLoadingPrincipal,
+                                             aTriggeringPrincipal,
+                                             aSecurityFlags,
+                                             aContentPolicyType,
+                                             result);
+ }
++nsresult
++nsIOService::NewChannelFromURIWithClientAndController(nsIURI* aURI,
++                                                      nsIDOMNode* aLoadingNode,
++                                                      nsIPrincipal* aLoadingPrincipal,
++                                                      nsIPrincipal* aTriggeringPrincipal,
++                                                      const Maybe<ClientInfo>& aLoadingClientInfo,
++                                                      const Maybe<ServiceWorkerDescriptor>& aController,
++                                                      uint32_t aSecurityFlags,
++                                                      uint32_t aContentPolicyType,
++                                                      nsIChannel** aResult)
++{
++    return NewChannelFromURIWithProxyFlagsInternal(aURI,
++                                                   nullptr, // aProxyURI
++                                                   0,       // aProxyFlags
++                                                   aLoadingNode,
++                                                   aLoadingPrincipal,
++                                                   aTriggeringPrincipal,
++                                                   aLoadingClientInfo,
++                                                   aController,
++                                                   aSecurityFlags,
++                                                   aContentPolicyType,
++                                                   aResult);
++}
+ 
+ /*  ***** DEPRECATED *****
+  * please use NewChannelFromURI2 providing the right arguments for:
+  *        * aLoadingNode
+  *        * aLoadingPrincipal
+  *        * aTriggeringPrincipal
+  *        * aSecurityFlags
+  *        * aContentPolicyType
+@@ -793,16 +822,62 @@ nsIOService::NewChannelFromURIWithLoadIn
+ {
+   return NewChannelFromURIWithProxyFlagsInternal(aURI,
+                                                  nullptr, // aProxyURI
+                                                  0,       // aProxyFlags
+                                                  aLoadInfo,
+                                                  result);
+ }
+ 
++
++nsresult
++nsIOService::NewChannelFromURIWithProxyFlagsInternal(nsIURI* aURI,
++                                                     nsIURI* aProxyURI,
++                                                     uint32_t aProxyFlags,
++                                                     nsIDOMNode* aLoadingNode,
++                                                     nsIPrincipal* aLoadingPrincipal,
++                                                     nsIPrincipal* aTriggeringPrincipal,
++                                                     const Maybe<ClientInfo>& aLoadingClientInfo,
++                                                     const Maybe<ServiceWorkerDescriptor>& aController,
++                                                     uint32_t aSecurityFlags,
++                                                     uint32_t aContentPolicyType,
++                                                     nsIChannel** result)
++{
++    // Ideally all callers of NewChannelFromURIWithProxyFlagsInternal provide
++    // the necessary arguments to create a loadinfo.
++    //
++    // Note, historically this could be called with nullptr aLoadingNode,
++    // aLoadingPrincipal, and aTriggeringPrincipal from addons using
++    // newChannelFromURIWithProxyFlags().  This code tried to accomodate
++    // by not creating a LoadInfo in such cases.  Now that both the legacy
++    // addons and that API are gone we could possibly require always creating a
++    // LoadInfo here.  See bug 1432205.
++    nsCOMPtr<nsILoadInfo> loadInfo;
++
++    // TYPE_DOCUMENT loads don't require a loadingNode or principal, but other
++    // types do.
++    if (aLoadingNode || aLoadingPrincipal ||
++        aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) {
++      nsCOMPtr<nsINode> loadingNode(do_QueryInterface(aLoadingNode));
++      loadInfo = new LoadInfo(aLoadingPrincipal,
++                              aTriggeringPrincipal,
++                              loadingNode,
++                              aSecurityFlags,
++                              aContentPolicyType,
++                              aLoadingClientInfo,
++                              aController);
++    }
++    NS_ASSERTION(loadInfo, "Please pass security info when creating a channel");
++    return NewChannelFromURIWithProxyFlagsInternal(aURI,
++                                                   aProxyURI,
++                                                   aProxyFlags,
++                                                   loadInfo,
++                                                   result);
++}
++
+ nsresult
+ nsIOService::NewChannelFromURIWithProxyFlagsInternal(nsIURI* aURI,
+                                                      nsIURI* aProxyURI,
+                                                      uint32_t aProxyFlags,
+                                                      nsILoadInfo* aLoadInfo,
+                                                      nsIChannel** result)
+ {
+     nsresult rv;
+@@ -918,46 +993,26 @@ nsIOService::NewChannelFromURIWithProxyF
+                                               uint32_t aProxyFlags,
+                                               nsIDOMNode* aLoadingNode,
+                                               nsIPrincipal* aLoadingPrincipal,
+                                               nsIPrincipal* aTriggeringPrincipal,
+                                               uint32_t aSecurityFlags,
+                                               uint32_t aContentPolicyType,
+                                               nsIChannel** result)
+ {
+-    // Ideally all callers of NewChannelFromURIWithProxyFlags2 provide the
+-    // necessary arguments to create a loadinfo. Keep in mind that addons
+-    // might still call NewChannelFromURIWithProxyFlags() which forwards
+-    // its calls to NewChannelFromURIWithProxyFlags2 using *null* values
+-    // as the arguments for aLoadingNode, aLoadingPrincipal, and also
+-    // aTriggeringPrincipal.
+-    // We do not want to break those addons, hence we only create a Loadinfo
+-    // if 'aLoadingNode' or 'aLoadingPrincipal' are provided. Note, that
+-    // either aLoadingNode or aLoadingPrincipal is required to succesfully
+-    // create a LoadInfo object.
+-    // Except in the case of top level TYPE_DOCUMENT loads, where the
+-    // loadingNode and loadingPrincipal are allowed to have null values.
+-    nsCOMPtr<nsILoadInfo> loadInfo;
+-
+-    // TYPE_DOCUMENT loads don't require a loadingNode or principal, but other
+-    // types do.
+-    if (aLoadingNode || aLoadingPrincipal ||
+-        aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) {
+-      nsCOMPtr<nsINode> loadingNode(do_QueryInterface(aLoadingNode));
+-      loadInfo = new LoadInfo(aLoadingPrincipal,
+-                              aTriggeringPrincipal,
+-                              loadingNode,
+-                              aSecurityFlags,
+-                              aContentPolicyType);
+-    }
+-    NS_ASSERTION(loadInfo, "Please pass security info when creating a channel");
+     return NewChannelFromURIWithProxyFlagsInternal(aURI,
+                                                    aProxyURI,
+                                                    aProxyFlags,
+-                                                   loadInfo,
++                                                   aLoadingNode,
++                                                   aLoadingPrincipal,
++                                                   aTriggeringPrincipal,
++                                                   Maybe<ClientInfo>(),
++                                                   Maybe<ServiceWorkerDescriptor>(),
++                                                   aSecurityFlags,
++                                                   aContentPolicyType,
+                                                    result);
+ }
+ 
+ /*  ***** DEPRECATED *****
+  * please use NewChannelFromURIWithProxyFlags2 providing the right arguments for:
+  *        * aLoadingNode
+  *        * aLoadingPrincipal
+  *        * aTriggeringPrincipal
+diff --git a/netwerk/base/nsIOService.h b/netwerk/base/nsIOService.h
+--- a/netwerk/base/nsIOService.h
++++ b/netwerk/base/nsIOService.h
+@@ -138,16 +138,28 @@ private:
+     nsresult InitializeNetworkLinkService();
+     nsresult InitializeProtocolProxyService();
+ 
+     // consolidated helper function
+     void LookupProxyInfo(nsIURI *aURI, nsIURI *aProxyURI, uint32_t aProxyFlags,
+                          nsCString *aScheme, nsIProxyInfo **outPI);
+ 
+     nsresult NewChannelFromURIWithProxyFlagsInternal(nsIURI* aURI,
++                                                    nsIURI* aProxyURI,
++                                                    uint32_t aProxyFlags,
++                                                    nsIDOMNode* aLoadingNode,
++                                                    nsIPrincipal* aLoadingPrincipal,
++                                                    nsIPrincipal* aTriggeringPrincipal,
++                                                    const mozilla::Maybe<mozilla::dom::ClientInfo>& aLoadingClientInfo,
++                                                    const mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor>& aController,
++                                                    uint32_t aSecurityFlags,
++                                                    uint32_t aContentPolicyType,
++                                                    nsIChannel** result);
++
++    nsresult NewChannelFromURIWithProxyFlagsInternal(nsIURI* aURI,
+                                                      nsIURI* aProxyURI,
+                                                      uint32_t aProxyFlags,
+                                                      nsILoadInfo* aLoadInfo,
+                                                      nsIChannel** result);
+ 
+     nsresult SpeculativeConnectInternal(nsIURI *aURI,
+                                         nsIPrincipal *aPrincipal,
+                                         nsIInterfaceRequestor *aCallbacks,
+diff --git a/netwerk/base/nsNetUtil.cpp b/netwerk/base/nsNetUtil.cpp
+--- a/netwerk/base/nsNetUtil.cpp
++++ b/netwerk/base/nsNetUtil.cpp
+@@ -76,16 +76,18 @@
+ #include "nsIRedirectHistoryEntry.h"
+ #include "nsICertBlocklist.h"
+ #include "nsICertOverrideService.h"
+ 
+ #include <limits>
+ 
+ using namespace mozilla;
+ using namespace mozilla::net;
++using mozilla::dom::ClientInfo;
++using mozilla::dom::ServiceWorkerDescriptor;
+ 
+ #define DEFAULT_RP 3
+ #define DEFAULT_PRIVATE_RP 2
+ 
+ static uint32_t sDefaultRp = DEFAULT_RP;
+ static uint32_t defaultPrivateRp = DEFAULT_PRIVATE_RP;
+ 
+ already_AddRefed<nsIIOService>
+@@ -205,66 +207,157 @@ NS_NewChannelInternal(nsIChannel        
+     rv = channel->SetLoadFlags(aLoadFlags);
+     NS_ENSURE_SUCCESS(rv, rv);
+   }
+ 
+   channel.forget(outChannel);
+   return NS_OK;
+ }
+ 
++namespace {
++
++void
++AssertLoadingPrincipalAndClientInfoMatch(nsIPrincipal* aLoadingPrincipal,
++                                         const ClientInfo& aLoadingClientInfo,
++                                         nsContentPolicyType aType)
++{
++#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
++  // Verify that the provided loading ClientInfo matches the loading
++  // principal.  Unfortunately we can't just use nsIPrincipal::Equals() here
++  // because of some corner cases:
++  //
++  //  1. Worker debugger scripts want to use a system loading principal for
++  //     worker scripts with a content principal.  We exempt these from this
++  //     check.
++  //  2. Null principals currently require exact object identity for
++  //     nsIPrincipal::Equals() to return true.  This doesn't work here because
++  //     ClientInfo::GetPrincipal() uses PrincipalInfoToPrincipal() to allocate
++  //     a new object.  To work around this we compare the principal origin
++  //     string itself.  If bug 1431771 is fixed then we could switch to
++  //     Equals().
++
++  // Allow worker debugger to load with a system principal.
++  if (aLoadingPrincipal->GetIsSystemPrincipal() &&
++      (aType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
++       aType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER ||
++       aType == nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER ||
++       aType == nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS)) {
++    return;
++  }
++
++  // Perform a fast comparison for most principal checks.
++  nsCOMPtr<nsIPrincipal> clientPrincipal(aLoadingClientInfo.GetPrincipal());
++  if (aLoadingPrincipal->Equals(clientPrincipal)) {
++    return;
++  }
++
++  // Fall back to a slower origin equality test to support null principals.
++  nsAutoCString loadingOrigin;
++  MOZ_ALWAYS_SUCCEEDS(aLoadingPrincipal->GetOrigin(loadingOrigin));
++
++  nsAutoCString clientOrigin;
++  MOZ_ALWAYS_SUCCEEDS(clientPrincipal->GetOrigin(clientOrigin));
++
++  MOZ_DIAGNOSTIC_ASSERT(loadingOrigin == clientOrigin);
++#endif
++}
++
++}
++
+ nsresult
+ NS_NewChannel(nsIChannel           **outChannel,
+               nsIURI                *aUri,
+               nsIPrincipal          *aLoadingPrincipal,
+               nsSecurityFlags        aSecurityFlags,
+               nsContentPolicyType    aContentPolicyType,
+               nsILoadGroup          *aLoadGroup /* = nullptr */,
+               nsIInterfaceRequestor *aCallbacks /* = nullptr */,
+               nsLoadFlags            aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
+               nsIIOService          *aIoService /* = nullptr */)
+ {
+   return NS_NewChannelInternal(outChannel,
+                                aUri,
+                                nullptr, // aLoadingNode,
+                                aLoadingPrincipal,
+                                nullptr, // aTriggeringPrincipal
++                               Maybe<ClientInfo>(),
++                               Maybe<ServiceWorkerDescriptor>(),
++                               aSecurityFlags,
++                               aContentPolicyType,
++                               aLoadGroup,
++                               aCallbacks,
++                               aLoadFlags,
++                               aIoService);
++}
++
++nsresult
++NS_NewChannel(nsIChannel           **outChannel,
++              nsIURI                *aUri,
++              nsIPrincipal          *aLoadingPrincipal,
++              const ClientInfo      &aLoadingClientInfo,
++              const Maybe<ServiceWorkerDescriptor>& aController,
++              nsSecurityFlags        aSecurityFlags,
++              nsContentPolicyType    aContentPolicyType,
++              nsILoadGroup          *aLoadGroup /* = nullptr */,
++              nsIInterfaceRequestor *aCallbacks /* = nullptr */,
++              nsLoadFlags            aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
++              nsIIOService          *aIoService /* = nullptr */)
++{
++  AssertLoadingPrincipalAndClientInfoMatch(aLoadingPrincipal,
++                                           aLoadingClientInfo,
++                                           aContentPolicyType);
++
++  Maybe<ClientInfo> loadingClientInfo;
++  loadingClientInfo.emplace(aLoadingClientInfo);
++
++  return NS_NewChannelInternal(outChannel,
++                               aUri,
++                               nullptr, // aLoadingNode,
++                               aLoadingPrincipal,
++                               nullptr, // aTriggeringPrincipal
++                               loadingClientInfo,
++                               aController,
+                                aSecurityFlags,
+                                aContentPolicyType,
+                                aLoadGroup,
+                                aCallbacks,
+                                aLoadFlags,
+                                aIoService);
+ }
+ 
+ nsresult
+ NS_NewChannelInternal(nsIChannel           **outChannel,
+                       nsIURI                *aUri,
+                       nsINode               *aLoadingNode,
+                       nsIPrincipal          *aLoadingPrincipal,
+                       nsIPrincipal          *aTriggeringPrincipal,
++                      const Maybe<ClientInfo>& aLoadingClientInfo,
++                      const Maybe<ServiceWorkerDescriptor>& aController,
+                       nsSecurityFlags        aSecurityFlags,
+                       nsContentPolicyType    aContentPolicyType,
+                       nsILoadGroup          *aLoadGroup /* = nullptr */,
+                       nsIInterfaceRequestor *aCallbacks /* = nullptr */,
+                       nsLoadFlags            aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
+                       nsIIOService          *aIoService /* = nullptr */)
+ {
+   NS_ENSURE_ARG_POINTER(outChannel);
+ 
+   nsCOMPtr<nsIIOService> grip;
+   nsresult rv = net_EnsureIOService(&aIoService, grip);
+   NS_ENSURE_SUCCESS(rv, rv);
+ 
+   nsCOMPtr<nsIChannel> channel;
+-  rv = aIoService->NewChannelFromURI2(
++  rv = aIoService->NewChannelFromURIWithClientAndController(
+          aUri,
+          aLoadingNode ?
+            aLoadingNode->AsDOMNode() : nullptr,
+          aLoadingPrincipal,
+          aTriggeringPrincipal,
++         aLoadingClientInfo,
++         aController,
+          aSecurityFlags,
+          aContentPolicyType,
+          getter_AddRefs(channel));
+   if (NS_FAILED(rv)) {
+     return rv;
+   }
+ 
+   if (aLoadGroup) {
+@@ -309,26 +402,28 @@ NS_NewChannelWithTriggeringPrincipal(nsI
+ {
+   MOZ_ASSERT(aLoadingNode);
+   NS_ASSERTION(aTriggeringPrincipal, "Can not create channel without a triggering Principal!");
+   return NS_NewChannelInternal(outChannel,
+                                aUri,
+                                aLoadingNode,
+                                aLoadingNode->NodePrincipal(),
+                                aTriggeringPrincipal,
++                               Maybe<ClientInfo>(),
++                               Maybe<ServiceWorkerDescriptor>(),
+                                aSecurityFlags,
+                                aContentPolicyType,
+                                aLoadGroup,
+                                aCallbacks,
+                                aLoadFlags,
+                                aIoService);
+ }
+ 
+ // See NS_NewChannelInternal for usage and argument description
+-nsresult /*NS_NewChannelWithPrincipalAndTriggeringPrincipal */
++nsresult
+ NS_NewChannelWithTriggeringPrincipal(nsIChannel           **outChannel,
+                                      nsIURI                *aUri,
+                                      nsIPrincipal          *aLoadingPrincipal,
+                                      nsIPrincipal          *aTriggeringPrincipal,
+                                      nsSecurityFlags        aSecurityFlags,
+                                      nsContentPolicyType    aContentPolicyType,
+                                      nsILoadGroup          *aLoadGroup /* = nullptr */,
+                                      nsIInterfaceRequestor *aCallbacks /* = nullptr */,
+@@ -336,41 +431,82 @@ NS_NewChannelWithTriggeringPrincipal(nsI
+                                      nsIIOService          *aIoService /* = nullptr */)
+ {
+   NS_ASSERTION(aLoadingPrincipal, "Can not create channel without a loading Principal!");
+   return NS_NewChannelInternal(outChannel,
+                                aUri,
+                                nullptr, // aLoadingNode
+                                aLoadingPrincipal,
+                                aTriggeringPrincipal,
++                               Maybe<ClientInfo>(),
++                               Maybe<ServiceWorkerDescriptor>(),
+                                aSecurityFlags,
+                                aContentPolicyType,
+                                aLoadGroup,
+                                aCallbacks,
+                                aLoadFlags,
+                                aIoService);
+ }
+ 
+-nsresult /* NS_NewChannelNode */
++// See NS_NewChannelInternal for usage and argument description
++nsresult
++NS_NewChannelWithTriggeringPrincipal(nsIChannel           **outChannel,
++                                     nsIURI                *aUri,
++                                     nsIPrincipal          *aLoadingPrincipal,
++                                     nsIPrincipal          *aTriggeringPrincipal,
++                                     const ClientInfo      &aLoadingClientInfo,
++                                     const Maybe<ServiceWorkerDescriptor>& aController,
++                                     nsSecurityFlags        aSecurityFlags,
++                                     nsContentPolicyType    aContentPolicyType,
++                                     nsILoadGroup          *aLoadGroup /* = nullptr */,
++                                     nsIInterfaceRequestor *aCallbacks /* = nullptr */,
++                                     nsLoadFlags            aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
++                                     nsIIOService          *aIoService /* = nullptr */)
++{
++  AssertLoadingPrincipalAndClientInfoMatch(aLoadingPrincipal,
++                                           aLoadingClientInfo,
++                                           aContentPolicyType);
++
++  Maybe<ClientInfo> loadingClientInfo;
++  loadingClientInfo.emplace(aLoadingClientInfo);
++
++  return NS_NewChannelInternal(outChannel,
++                               aUri,
++                               nullptr, // aLoadingNode
++                               aLoadingPrincipal,
++                               aTriggeringPrincipal,
++                               loadingClientInfo,
++                               aController,
++                               aSecurityFlags,
++                               aContentPolicyType,
++                               aLoadGroup,
++                               aCallbacks,
++                               aLoadFlags,
++                               aIoService);
++}
++
++nsresult
+ NS_NewChannel(nsIChannel           **outChannel,
+               nsIURI                *aUri,
+               nsINode               *aLoadingNode,
+               nsSecurityFlags        aSecurityFlags,
+               nsContentPolicyType    aContentPolicyType,
+               nsILoadGroup          *aLoadGroup /* = nullptr */,
+               nsIInterfaceRequestor *aCallbacks /* = nullptr */,
+               nsLoadFlags            aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
+               nsIIOService          *aIoService /* = nullptr */)
+ {
+   NS_ASSERTION(aLoadingNode, "Can not create channel without a loading Node!");
+   return NS_NewChannelInternal(outChannel,
+                                aUri,
+                                aLoadingNode,
+                                aLoadingNode->NodePrincipal(),
+                                nullptr, // aTriggeringPrincipal
++                               Maybe<ClientInfo>(),
++                               Maybe<ServiceWorkerDescriptor>(),
+                                aSecurityFlags,
+                                aContentPolicyType,
+                                aLoadGroup,
+                                aCallbacks,
+                                aLoadFlags,
+                                aIoService);
+ }
+ 
+@@ -890,16 +1026,18 @@ NS_NewStreamLoaderInternal(nsIStreamLoad
+                            nsIURI                  *aReferrer /* = nullptr */)
+ {
+    nsCOMPtr<nsIChannel> channel;
+    nsresult rv = NS_NewChannelInternal(getter_AddRefs(channel),
+                                        aUri,
+                                        aLoadingNode,
+                                        aLoadingPrincipal,
+                                        nullptr, // aTriggeringPrincipal
++                                       Maybe<ClientInfo>(),
++                                       Maybe<ServiceWorkerDescriptor>(),
+                                        aSecurityFlags,
+                                        aContentPolicyType,
+                                        aLoadGroup,
+                                        aCallbacks,
+                                        aLoadFlags);
+ 
+   NS_ENSURE_SUCCESS(rv, rv);
+   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
+@@ -908,17 +1046,17 @@ NS_NewStreamLoaderInternal(nsIStreamLoad
+     MOZ_ASSERT(NS_SUCCEEDED(rv));
+   }
+   rv = NS_NewStreamLoader(outStream, aObserver);
+   NS_ENSURE_SUCCESS(rv, rv);
+   return channel->AsyncOpen2(*outStream);
+ }
+ 
+ 
+-nsresult /* NS_NewStreamLoaderNode */
++nsresult
+ NS_NewStreamLoader(nsIStreamLoader        **outStream,
+                    nsIURI                  *aUri,
+                    nsIStreamLoaderObserver *aObserver,
+                    nsINode                 *aLoadingNode,
+                    nsSecurityFlags          aSecurityFlags,
+                    nsContentPolicyType      aContentPolicyType,
+                    nsILoadGroup            *aLoadGroup /* = nullptr */,
+                    nsIInterfaceRequestor   *aCallbacks /* = nullptr */,
+@@ -934,17 +1072,17 @@ NS_NewStreamLoader(nsIStreamLoader      
+                                     aSecurityFlags,
+                                     aContentPolicyType,
+                                     aLoadGroup,
+                                     aCallbacks,
+                                     aLoadFlags,
+                                     aReferrer);
+ }
+ 
+-nsresult /* NS_NewStreamLoaderPrincipal */
++nsresult
+ NS_NewStreamLoader(nsIStreamLoader        **outStream,
+                    nsIURI                  *aUri,
+                    nsIStreamLoaderObserver *aObserver,
+                    nsIPrincipal            *aLoadingPrincipal,
+                    nsSecurityFlags          aSecurityFlags,
+                    nsContentPolicyType      aContentPolicyType,
+                    nsILoadGroup            *aLoadGroup /* = nullptr */,
+                    nsIInterfaceRequestor   *aCallbacks /* = nullptr */,
+diff --git a/netwerk/base/nsNetUtil.h b/netwerk/base/nsNetUtil.h
+--- a/netwerk/base/nsNetUtil.h
++++ b/netwerk/base/nsNetUtil.h
+@@ -2,16 +2,17 @@
+ /* vim:set ts=4 sw=4 sts=4 et cin: */
+ /* 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/. */
+ 
+ #ifndef nsNetUtil_h__
+ #define nsNetUtil_h__
+ 
++#include "mozilla/Maybe.h"
+ #include "nsCOMPtr.h"
+ #include "nsIInterfaceRequestor.h"
+ #include "nsIInterfaceRequestorUtils.h"
+ #include "nsILoadGroup.h"
+ #include "nsINetUtil.h"
+ #include "nsIRequest.h"
+ #include "nsILoadInfo.h"
+ #include "nsIIOService.h"
+@@ -50,17 +51,21 @@ class nsIStreamLoaderObserver;
+ class nsIIncrementalStreamLoader;
+ class nsIIncrementalStreamLoaderObserver;
+ class nsIUnicharStreamLoader;
+ class nsIUnicharStreamLoaderObserver;
+ 
+ namespace mozilla {
+ class Encoding;
+ class OriginAttributes;
+-}
++namespace dom {
++class ClientInfo;
++class ServiceWorkerDescriptor;
++} // namespace dom
++} // namespace mozilla
+ 
+ template <class> class nsCOMPtr;
+ template <typename> struct already_AddRefed;
+ 
+ already_AddRefed<nsIIOService> do_GetIOService(nsresult *error = 0);
+ 
+ already_AddRefed<nsINetUtil> do_GetNetUtil(nsresult *error = 0);
+ 
+@@ -108,18 +113,20 @@ nsresult NS_GetSanitizedURIStringFromURI
+ * NS_NewChannelWithTriggeringPrincipal,
+ * NS_NewInputStreamChannel, NS_NewChannelInternal
+ * and it's variations:
+ *
+ * What specific API function to use:
+ * * The NS_NewChannelInternal functions should almost never be directly
+ *   called outside of necko code.
+ * * If possible, use NS_NewChannel() providing a loading *nsINode*
+-* * If no loading *nsINode* is avaialable, call NS_NewChannel() providing
+-*   a loading *nsIPrincipal*.
++* * If no loading *nsINode* is available, try calling NS_NewChannel() providing
++*   a loading *ClientInfo*.
++* * If no loading *nsINode* or *ClientInfo* are available, call NS_NewChannel()
++*   providing a loading *nsIPrincipal*.
+ * * Call NS_NewChannelWithTriggeringPrincipal if the triggeringPrincipal
+ *   is different from the loadingPrincipal.
+ * * Call NS_NewChannelInternal() providing aLoadInfo object in cases where
+ *   you already have loadInfo object, e.g in case of a channel redirect.
+ *
+ * @param aURI
+ *        nsIURI from which to make a channel
+ * @param aLoadingNode
+@@ -129,24 +136,32 @@ nsresult NS_GetSanitizedURIStringFromURI
+ * @param aContentPolicyType
+ *        These will be used as values for the nsILoadInfo object on the
+ *        created channel. For details, see nsILoadInfo in nsILoadInfo.idl
+ *
+ * Please note, if you provide both a loadingNode and a loadingPrincipal,
+ * then loadingPrincipal must be equal to loadingNode->NodePrincipal().
+ * But less error prone is to just supply a loadingNode.
+ *
++* Note, if you provide a loading ClientInfo its principal must match the
++* loading principal.  Currently you must pass both as the loading principal
++* may have additional mutable values like CSP on it.  In the future these
++* will be removed from nsIPrincipal and the API can be changed to take just
++* the loading ClientInfo.
++*
+ * Keep in mind that URIs coming from a webpage should *never* use the
+ * systemPrincipal as the loadingPrincipal.
+ */
+ nsresult NS_NewChannelInternal(nsIChannel           **outChannel,
+                                nsIURI                *aUri,
+                                nsINode               *aLoadingNode,
+                                nsIPrincipal          *aLoadingPrincipal,
+                                nsIPrincipal          *aTriggeringPrincipal,
++                               const mozilla::Maybe<mozilla::dom::ClientInfo>& aLoadingClientInfo,
++                               const mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor>& aController,
+                                nsSecurityFlags        aSecurityFlags,
+                                nsContentPolicyType    aContentPolicyType,
+                                nsILoadGroup          *aLoadGroup = nullptr,
+                                nsIInterfaceRequestor *aCallbacks = nullptr,
+                                nsLoadFlags            aLoadFlags = nsIRequest::LOAD_NORMAL,
+                                nsIIOService          *aIoService = nullptr);
+ 
+ // See NS_NewChannelInternal for usage and argument description
+@@ -166,54 +181,83 @@ NS_NewChannelWithTriggeringPrincipal(nsI
+                                      nsIPrincipal          *aTriggeringPrincipal,
+                                      nsSecurityFlags        aSecurityFlags,
+                                      nsContentPolicyType    aContentPolicyType,
+                                      nsILoadGroup          *aLoadGroup = nullptr,
+                                      nsIInterfaceRequestor *aCallbacks = nullptr,
+                                      nsLoadFlags            aLoadFlags = nsIRequest::LOAD_NORMAL,
+                                      nsIIOService          *aIoService = nullptr);
+ 
+-
+ // See NS_NewChannelInternal for usage and argument description
+-nsresult /*NS_NewChannelWithPrincipalAndTriggeringPrincipal */
++nsresult
+ NS_NewChannelWithTriggeringPrincipal(nsIChannel           **outChannel,
+                                      nsIURI                *aUri,
+                                      nsIPrincipal          *aLoadingPrincipal,
+                                      nsIPrincipal          *aTriggeringPrincipal,
+                                      nsSecurityFlags        aSecurityFlags,
+                                      nsContentPolicyType    aContentPolicyType,
+                                      nsILoadGroup          *aLoadGroup = nullptr,
+                                      nsIInterfaceRequestor *aCallbacks = nullptr,
+                                      nsLoadFlags            aLoadFlags = nsIRequest::LOAD_NORMAL,
+                                      nsIIOService          *aIoService = nullptr);
+ 
+ // See NS_NewChannelInternal for usage and argument description
+-nsresult /* NS_NewChannelNode */
++nsresult
++NS_NewChannelWithTriggeringPrincipal(nsIChannel           **outChannel,
++                                     nsIURI                *aUri,
++                                     nsIPrincipal          *aLoadingPrincipal,
++                                     nsIPrincipal          *aTriggeringPrincipal,
++                                     const mozilla::dom::ClientInfo& aLoadingClientInfo,
++                                     const mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor>& aController,
++                                     nsSecurityFlags        aSecurityFlags,
++                                     nsContentPolicyType    aContentPolicyType,
++                                     nsILoadGroup          *aLoadGroup = nullptr,
++                                     nsIInterfaceRequestor *aCallbacks = nullptr,
++                                     nsLoadFlags            aLoadFlags = nsIRequest::LOAD_NORMAL,
++                                     nsIIOService          *aIoService = nullptr);
++
++
++// See NS_NewChannelInternal for usage and argument description
++nsresult
+ NS_NewChannel(nsIChannel           **outChannel,
+               nsIURI                *aUri,
+               nsINode               *aLoadingNode,
+               nsSecurityFlags        aSecurityFlags,
+               nsContentPolicyType    aContentPolicyType,
+               nsILoadGroup          *aLoadGroup = nullptr,
+               nsIInterfaceRequestor *aCallbacks = nullptr,
+               nsLoadFlags            aLoadFlags = nsIRequest::LOAD_NORMAL,
+               nsIIOService          *aIoService = nullptr);
+ 
+ // See NS_NewChannelInternal for usage and argument description
+-nsresult /* NS_NewChannelPrincipal */
++nsresult
+ NS_NewChannel(nsIChannel           **outChannel,
+               nsIURI                *aUri,
+               nsIPrincipal          *aLoadingPrincipal,
+               nsSecurityFlags        aSecurityFlags,
+               nsContentPolicyType    aContentPolicyType,
+               nsILoadGroup          *aLoadGroup = nullptr,
+               nsIInterfaceRequestor *aCallbacks = nullptr,
+               nsLoadFlags            aLoadFlags = nsIRequest::LOAD_NORMAL,
+               nsIIOService          *aIoService = nullptr);
+ 
++// See NS_NewChannelInternal for usage and argument description
++nsresult
++NS_NewChannel(nsIChannel** outChannel,
++              nsIURI* aUri,
++              nsIPrincipal* aLoadingPrincipal,
++              const mozilla::dom::ClientInfo& aLoadingClientInfo,
++              const mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor>& aController,
++              nsSecurityFlags aSecurityFlags,
++              nsContentPolicyType aContentPolicyType,
++              nsILoadGroup* aLoadGroup = nullptr,
++              nsIInterfaceRequestor* aCallbacks = nullptr,
++              nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL,
++              nsIIOService* aIoService = nullptr);
++
+ nsresult NS_GetIsDocumentChannel(nsIChannel * aChannel, bool *aIsDocument);
+ 
+ nsresult NS_MakeAbsoluteURI(nsACString       &result,
+                             const nsACString &spec,
+                             nsIURI           *baseURI);
+ 
+ nsresult NS_MakeAbsoluteURI(char        **result,
+                             const char   *spec,
+@@ -344,29 +388,29 @@ nsresult NS_NewStreamLoaderInternal(nsIS
+                                     nsIPrincipal            *aLoadingPrincipal,
+                                     nsSecurityFlags          aSecurityFlags,
+                                     nsContentPolicyType      aContentPolicyType,
+                                     nsILoadGroup            *aLoadGroup = nullptr,
+                                     nsIInterfaceRequestor   *aCallbacks = nullptr,
+                                     nsLoadFlags              aLoadFlags = nsIRequest::LOAD_NORMAL,
+                                     nsIURI                  *aReferrer = nullptr);
+ 
+-nsresult /* NS_NewStreamLoaderNode */
++nsresult
+ NS_NewStreamLoader(nsIStreamLoader        **outStream,
+                    nsIURI                  *aUri,
+                    nsIStreamLoaderObserver *aObserver,
+                    nsINode                 *aLoadingNode,
+                    nsSecurityFlags          aSecurityFlags,
+                    nsContentPolicyType      aContentPolicyType,
+                    nsILoadGroup            *aLoadGroup = nullptr,
+                    nsIInterfaceRequestor   *aCallbacks = nullptr,
+                    nsLoadFlags              aLoadFlags = nsIRequest::LOAD_NORMAL,
+                    nsIURI                  *aReferrer = nullptr);
+ 
+-nsresult /* NS_NewStreamLoaderPrincipal */
++nsresult
+ NS_NewStreamLoader(nsIStreamLoader        **outStream,
+                    nsIURI                  *aUri,
+                    nsIStreamLoaderObserver *aObserver,
+                    nsIPrincipal            *aLoadingPrincipal,
+                    nsSecurityFlags          aSecurityFlags,
+                    nsContentPolicyType      aContentPolicyType,
+                    nsILoadGroup            *aLoadGroup = nullptr,
+                    nsIInterfaceRequestor   *aCallbacks = nullptr,
+diff --git a/uriloader/prefetch/nsPrefetchService.cpp b/uriloader/prefetch/nsPrefetchService.cpp
+--- a/uriloader/prefetch/nsPrefetchService.cpp
++++ b/uriloader/prefetch/nsPrefetchService.cpp
+@@ -3,17 +3,19 @@
+  * 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 "nsPrefetchService.h"
+ 
+ #include "mozilla/AsyncEventDispatcher.h"
+ #include "mozilla/Attributes.h"
+ #include "mozilla/CORSMode.h"
++#include "mozilla/dom/ClientInfo.h"
+ #include "mozilla/dom/HTMLLinkElement.h"
++#include "mozilla/dom/ServiceWorkerDescriptor.h"
+ #include "mozilla/Preferences.h"
+ 
+ #include "nsICacheEntry.h"
+ #include "nsIServiceManager.h"
+ #include "nsICategoryManager.h"
+ #include "nsIObserverService.h"
+ #include "nsIWebProgress.h"
+ #include "nsCURILoader.h"
+@@ -141,16 +143,18 @@ nsPrefetchNode::OpenChannel()
+         securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
+       }
+     }
+     nsresult rv = NS_NewChannelInternal(getter_AddRefs(mChannel),
+                                         mURI,
+                                         source,
+                                         source->NodePrincipal(),
+                                         nullptr,   //aTriggeringPrincipal
++                                        Maybe<ClientInfo>(),
++                                        Maybe<ServiceWorkerDescriptor>(),
+                                         securityFlags,
+                                         mPolicyType,
+                                         loadGroup, // aLoadGroup
+                                         this,      // aCallbacks
+                                         nsIRequest::LOAD_BACKGROUND |
+                                         nsICachingChannel::LOAD_ONLY_IF_MODIFIED);
+ 
+     NS_ENSURE_SUCCESS(rv, rv);

+ 334 - 0
mozilla-release/patches/1231211-13-60a1.patch

@@ -0,0 +1,334 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1516721934 18000
+# Node ID 8fc3f67ba98e4dd0ec5be63349a6c0ab6df996d8
+# Parent  20122c6e7ab5e08dff455c0d3e910c11ea52f12d
+Bug 1231211 P13 Make worker ScriptLoader pass ClientInfo and ServiceWorkerDescriptor to NS_NewChannel() where appropriate. r=asuth
+
+diff --git a/dom/workers/ScriptLoader.cpp b/dom/workers/ScriptLoader.cpp
+--- a/dom/workers/ScriptLoader.cpp
++++ b/dom/workers/ScriptLoader.cpp
+@@ -108,16 +108,18 @@ GetBaseURI(bool aIsMainScript, WorkerPri
+ nsresult
+ ChannelFromScriptURL(nsIPrincipal* principal,
+                      nsIURI* baseURI,
+                      nsIDocument* parentDoc,
+                      nsILoadGroup* loadGroup,
+                      nsIIOService* ios,
+                      nsIScriptSecurityManager* secMan,
+                      const nsAString& aScriptURL,
++                     const Maybe<ClientInfo>& aClientInfo,
++                     const Maybe<ServiceWorkerDescriptor>& aController,
+                      bool aIsMainScript,
+                      WorkerScriptType aWorkerScriptType,
+                      nsContentPolicyType aMainScriptContentPolicyType,
+                      nsLoadFlags aLoadFlags,
+                      bool aDefaultURIEncoding,
+                      nsIChannel** aChannel)
+ {
+   AssertIsOnMainThread();
+@@ -192,25 +194,39 @@ ChannelFromScriptURL(nsIPrincipal* princ
+                        aLoadFlags,
+                        ios);
+   } else {
+     // We must have a loadGroup with a load context for the principal to
+     // traverse the channel correctly.
+     MOZ_ASSERT(loadGroup);
+     MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(loadGroup, principal));
+ 
+-    rv = NS_NewChannel(getter_AddRefs(channel),
+-                       uri,
+-                       principal,
+-                       secFlags,
+-                       contentPolicyType,
+-                       loadGroup,
+-                       nullptr, // aCallbacks
+-                       aLoadFlags,
+-                       ios);
++    if (aClientInfo.isSome()) {
++      rv = NS_NewChannel(getter_AddRefs(channel),
++                         uri,
++                         principal,
++                         aClientInfo.ref(),
++                         aController,
++                         secFlags,
++                         contentPolicyType,
++                         loadGroup,
++                         nullptr, // aCallbacks
++                         aLoadFlags,
++                         ios);
++    } else {
++      rv = NS_NewChannel(getter_AddRefs(channel),
++                         uri,
++                         principal,
++                         secFlags,
++                         contentPolicyType,
++                         loadGroup,
++                         nullptr, // aCallbacks
++                         aLoadFlags,
++                         ios);
++    }
+   }
+ 
+   NS_ENSURE_SUCCESS(rv, rv);
+ 
+   if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel)) {
+     mozilla::net::ReferrerPolicy referrerPolicy = parentDoc ?
+       parentDoc->GetReferrerPolicy() : mozilla::net::RP_Unset;
+     rv = nsContentUtils::SetFetchReferrerURIWithPolicy(principal, parentDoc,
+@@ -565,33 +581,37 @@ class ScriptLoaderRunnable final : publi
+   friend class CachePromiseHandler;
+   friend class CacheScriptLoader;
+   friend class LoaderListener;
+ 
+   WorkerPrivate* mWorkerPrivate;
+   nsCOMPtr<nsIEventTarget> mSyncLoopTarget;
+   nsTArray<ScriptLoadInfo> mLoadInfos;
+   RefPtr<CacheCreator> mCacheCreator;
++  Maybe<ClientInfo> mClientInfo;
+   Maybe<ServiceWorkerDescriptor> mController;
+   bool mIsMainScript;
+   WorkerScriptType mWorkerScriptType;
+   bool mCanceled;
+   bool mCanceledMainThread;
+   ErrorResult& mRv;
+ 
+ public:
+   NS_DECL_THREADSAFE_ISUPPORTS
+ 
+   ScriptLoaderRunnable(WorkerPrivate* aWorkerPrivate,
+                        nsIEventTarget* aSyncLoopTarget,
+                        nsTArray<ScriptLoadInfo>& aLoadInfos,
++                       const Maybe<ClientInfo>& aClientInfo,
++                       const Maybe<ServiceWorkerDescriptor>& aController,
+                        bool aIsMainScript,
+                        WorkerScriptType aWorkerScriptType,
+                        ErrorResult& aRv)
+   : mWorkerPrivate(aWorkerPrivate), mSyncLoopTarget(aSyncLoopTarget),
++    mClientInfo(aClientInfo), mController(aController),
+     mIsMainScript(aIsMainScript), mWorkerScriptType(aWorkerScriptType),
+     mCanceled(false), mCanceledMainThread(false), mRv(aRv)
+   {
+     aWorkerPrivate->AssertIsOnWorkerThread();
+     MOZ_ASSERT(aSyncLoopTarget);
+     MOZ_ASSERT_IF(aIsMainScript, aLoadInfos.Length() == 1);
+ 
+     mLoadInfos.SwapElements(aLoadInfos);
+@@ -966,17 +986,19 @@ private:
+       }
+     }
+ 
+     if (!channel) {
+       // Only top level workers' main script use the document charset for the
+       // script uri encoding. Otherwise, default encoding (UTF-8) is applied.
+       bool useDefaultEncoding = !(!parentWorker && IsMainWorkerScript());
+       rv = ChannelFromScriptURL(principal, baseURI, parentDoc, loadGroup, ios,
+-                                secMan, loadInfo.mURL, IsMainWorkerScript(),
++                                secMan, loadInfo.mURL,
++                                mClientInfo, mController,
++                                IsMainWorkerScript(),
+                                 mWorkerScriptType,
+                                 mWorkerPrivate->ContentPolicyType(), loadFlags,
+                                 useDefaultEncoding,
+                                 getter_AddRefs(channel));
+       if (NS_WARN_IF(NS_FAILED(rv))) {
+         return rv;
+       }
+     }
+@@ -1826,26 +1848,28 @@ CacheScriptLoader::OnStreamComplete(nsIS
+                                    mCSPReportOnlyHeaderValue,
+                                    mReferrerPolicyHeaderValue);
+   return NS_OK;
+ }
+ 
+ class ChannelGetterRunnable final : public WorkerMainThreadRunnable
+ {
+   const nsAString& mScriptURL;
++  const ClientInfo mClientInfo;
+   WorkerLoadInfo& mLoadInfo;
+   nsresult mResult;
+ 
+ public:
+   ChannelGetterRunnable(WorkerPrivate* aParentWorker,
+                         const nsAString& aScriptURL,
+                         WorkerLoadInfo& aLoadInfo)
+     : WorkerMainThreadRunnable(aParentWorker,
+                                NS_LITERAL_CSTRING("ScriptLoader :: ChannelGetter"))
+     , mScriptURL(aScriptURL)
++    , mClientInfo(aParentWorker->GetClientInfo())
+     , mLoadInfo(aLoadInfo)
+     , mResult(NS_ERROR_FAILURE)
+   {
+     MOZ_ASSERT(aParentWorker);
+     aParentWorker->AssertIsOnWorkerThread();
+   }
+ 
+   virtual bool
+@@ -1866,22 +1890,26 @@ public:
+     nsCOMPtr<nsIURI> baseURI = mWorkerPrivate->GetBaseURI();
+     MOZ_ASSERT(baseURI);
+ 
+     // May be null.
+     nsCOMPtr<nsIDocument> parentDoc = mWorkerPrivate->GetDocument();
+ 
+     mLoadInfo.mLoadGroup = mWorkerPrivate->GetLoadGroup();
+ 
++    Maybe<ClientInfo> clientInfo;
++    clientInfo.emplace(mClientInfo);
++
+     nsCOMPtr<nsIChannel> channel;
+     mResult =
+       scriptloader::ChannelFromScriptURLMainThread(mLoadInfo.mLoadingPrincipal,
+                                                    baseURI, parentDoc,
+                                                    mLoadInfo.mLoadGroup,
+                                                    mScriptURL,
++                                                   clientInfo,
+                                                    // Nested workers are always dedicated.
+                                                    nsIContentPolicy::TYPE_INTERNAL_WORKER,
+                                                    // Nested workers use default uri encoding.
+                                                    true,
+                                                    getter_AddRefs(channel));
+     NS_ENSURE_SUCCESS(mResult, true);
+ 
+     mResult = mLoadInfo.SetPrincipalFromChannel(channel);
+@@ -2168,18 +2196,26 @@ LoadAllScripts(WorkerPrivate* aWorkerPri
+ 
+   AutoSyncLoopHolder syncLoop(aWorkerPrivate, Terminating);
+   nsCOMPtr<nsIEventTarget> syncLoopTarget = syncLoop.GetEventTarget();
+   if (!syncLoopTarget) {
+     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+     return;
+   }
+ 
++  Maybe<ClientInfo> clientInfo;
++  Maybe<ServiceWorkerDescriptor> controller;
++  if (!aIsMainScript) {
++    clientInfo.emplace(aWorkerPrivate->GetClientInfo());
++    controller = aWorkerPrivate->GetController();
++  }
++
+   RefPtr<ScriptLoaderRunnable> loader =
+     new ScriptLoaderRunnable(aWorkerPrivate, syncLoopTarget, aLoadInfos,
++                             clientInfo, controller,
+                              aIsMainScript, aWorkerScriptType, aRv);
+ 
+   NS_ASSERTION(aLoadInfos.IsEmpty(), "Should have swapped!");
+ 
+   ScriptLoaderHolder workerHolder(loader);
+ 
+   if (NS_WARN_IF(!workerHolder.HoldWorker(aWorkerPrivate, Terminating))) {
+     aRv.Throw(NS_ERROR_FAILURE);
+@@ -2202,30 +2238,32 @@ BEGIN_WORKERS_NAMESPACE
+ namespace scriptloader {
+ 
+ nsresult
+ ChannelFromScriptURLMainThread(nsIPrincipal* aPrincipal,
+                                nsIURI* aBaseURI,
+                                nsIDocument* aParentDoc,
+                                nsILoadGroup* aLoadGroup,
+                                const nsAString& aScriptURL,
++                               const Maybe<ClientInfo>& aClientInfo,
+                                nsContentPolicyType aMainScriptContentPolicyType,
+                                bool aDefaultURIEncoding,
+                                nsIChannel** aChannel)
+ {
+   AssertIsOnMainThread();
+ 
+   nsCOMPtr<nsIIOService> ios(do_GetIOService());
+ 
+   nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
+   NS_ASSERTION(secMan, "This should never be null!");
+ 
+   return ChannelFromScriptURL(aPrincipal, aBaseURI, aParentDoc, aLoadGroup,
+-                              ios, secMan, aScriptURL, true, WorkerScript,
+-                              aMainScriptContentPolicyType,
++                              ios, secMan, aScriptURL, aClientInfo,
++                              Maybe<ServiceWorkerDescriptor>(),
++                              true, WorkerScript, aMainScriptContentPolicyType,
+                               nsIRequest::LOAD_NORMAL, aDefaultURIEncoding,
+                               aChannel);
+ }
+ 
+ nsresult
+ ChannelFromScriptURLWorkerThread(JSContext* aCx,
+                                  WorkerPrivate* aParent,
+                                  const nsAString& aScriptURL,
+diff --git a/dom/workers/ScriptLoader.h b/dom/workers/ScriptLoader.h
+--- a/dom/workers/ScriptLoader.h
++++ b/dom/workers/ScriptLoader.h
+@@ -33,16 +33,17 @@ enum WorkerScriptType {
+ namespace scriptloader {
+ 
+ nsresult
+ ChannelFromScriptURLMainThread(nsIPrincipal* aPrincipal,
+                                nsIURI* aBaseURI,
+                                nsIDocument* aParentDoc,
+                                nsILoadGroup* aLoadGroup,
+                                const nsAString& aScriptURL,
++                               const Maybe<ClientInfo>& aClientInfo,
+                                nsContentPolicyType aContentPolicyType,
+                                bool aDefaultURIEncoding,
+                                nsIChannel** aChannel);
+ 
+ nsresult
+ ChannelFromScriptURLWorkerThread(JSContext* aCx,
+                                  WorkerPrivate* aParent,
+                                  const nsAString& aScriptURL,
+diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
+--- a/dom/workers/WorkerPrivate.cpp
++++ b/dom/workers/WorkerPrivate.cpp
+@@ -4827,16 +4827,17 @@ WorkerPrivate::GetLoadInfo(JSContext* aC
+         nsJSUtils::GetStaticScriptGlobal(JS::CurrentGlobalOrNull(aCx));
+       if (scriptGlobal) {
+         globalWindow = do_QueryInterface(scriptGlobal);
+         MOZ_ASSERT(globalWindow);
+       }
+     }
+ 
+     nsCOMPtr<nsIDocument> document;
++    Maybe<ClientInfo> clientInfo;
+ 
+     if (globalWindow) {
+       // Only use the current inner window, and only use it if the caller can
+       // access it.
+       if (nsPIDOMWindowOuter* outerWindow = globalWindow->GetOuterWindow()) {
+         loadInfo.mWindow = outerWindow->GetCurrentInnerWindow();
+         // TODO: fix this for SharedWorkers with multiple documents (bug 1177935)
+         loadInfo.mServiceWorkersTestingInWindow =
+@@ -4859,16 +4860,18 @@ WorkerPrivate::GetLoadInfo(JSContext* aC
+       // from the document.
+       document = loadInfo.mWindow->GetExtantDoc();
+       NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
+ 
+       loadInfo.mBaseURI = document->GetDocBaseURI();
+       loadInfo.mLoadGroup = document->GetDocumentLoadGroup();
+       NS_ENSURE_TRUE(loadInfo.mLoadGroup, NS_ERROR_FAILURE);
+ 
++      clientInfo = globalWindow->GetClientInfo();
++
+       // Use the document's NodePrincipal as loading principal if we're not being
+       // called from chrome.
+       if (!loadInfo.mLoadingPrincipal) {
+         loadInfo.mLoadingPrincipal = document->NodePrincipal();
+         NS_ENSURE_TRUE(loadInfo.mLoadingPrincipal, NS_ERROR_FAILURE);
+ 
+         // We use the document's base domain to limit the number of workers
+         // each domain can create. For sandboxed documents, we use the domain
+@@ -4974,16 +4977,17 @@ WorkerPrivate::GetLoadInfo(JSContext* aC
+ 
+     // Top level workers' main script use the document charset for the script
+     // uri encoding.
+     bool useDefaultEncoding = false;
+     rv = ChannelFromScriptURLMainThread(loadInfo.mLoadingPrincipal,
+                                         loadInfo.mBaseURI,
+                                         document, loadInfo.mLoadGroup,
+                                         aScriptURL,
++                                        clientInfo,
+                                         ContentPolicyType(aWorkerType),
+                                         useDefaultEncoding,
+                                         getter_AddRefs(loadInfo.mChannel));
+     NS_ENSURE_SUCCESS(rv, rv);
+ 
+     rv = NS_GetFinalChannelURI(loadInfo.mChannel,
+                                getter_AddRefs(loadInfo.mResolvedScriptURI));
+     NS_ENSURE_SUCCESS(rv, rv);

+ 188 - 0
mozilla-release/patches/1231211-14-60a1.patch

@@ -0,0 +1,188 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1516721934 18000
+# Node ID 8d0f00c16279ebef12fa9d7656af736d68abea56
+# Parent  e925fefeb6f1fc1b95c7a33723ef2144463a767f
+Bug 1231211 P14 Make fetch() pass worker ClientInfo and ServiceWorkerDescriptor to NS_NewChannel(). r=asuth
+
+diff --git a/dom/fetch/Fetch.cpp b/dom/fetch/Fetch.cpp
+--- a/dom/fetch/Fetch.cpp
++++ b/dom/fetch/Fetch.cpp
+@@ -378,23 +378,29 @@ private:
+   {
+     mReporter->FlushConsoleReports(mLoadGroup);
+   }
+ };
+ 
+ class MainThreadFetchRunnable : public Runnable
+ {
+   RefPtr<WorkerFetchResolver> mResolver;
++  const ClientInfo mClientInfo;
++  const Maybe<ServiceWorkerDescriptor> mController;
+   RefPtr<InternalRequest> mRequest;
+ 
+ public:
+   MainThreadFetchRunnable(WorkerFetchResolver* aResolver,
++                          const ClientInfo& aClientInfo,
++                          const Maybe<ServiceWorkerDescriptor>& aController,
+                           InternalRequest* aRequest)
+     : Runnable("dom::MainThreadFetchRunnable")
+     , mResolver(aResolver)
++    , mClientInfo(aClientInfo)
++    , mController(aController)
+     , mRequest(aRequest)
+   {
+     MOZ_ASSERT(mResolver);
+   }
+ 
+   NS_IMETHOD
+   Run() override
+   {
+@@ -420,16 +426,19 @@ public:
+       // so pass false as the last argument to FetchDriver().
+       fetch = new FetchDriver(mRequest, principal, loadGroup,
+                               workerPrivate->MainThreadEventTarget(), false);
+       nsAutoCString spec;
+       if (proxy->GetWorkerPrivate()->GetBaseURI()) {
+         proxy->GetWorkerPrivate()->GetBaseURI()->GetAsciiSpec(spec);
+       }
+       fetch->SetWorkerScript(spec);
++
++      fetch->SetClientInfo(mClientInfo);
++      fetch->SetController(mController);
+     }
+ 
+     RefPtr<AbortSignal> signal = mResolver->GetAbortSignalForMainThread();
+ 
+     // ...but release it before calling Fetch, because mResolver's callback can
+     // be called synchronously and they want the mutex, too.
+     return fetch->Fetch(signal, mResolver);
+   }
+@@ -537,17 +546,18 @@ FetchRequest(nsIGlobalObject* aGlobal, c
+       WorkerFetchResolver::Create(worker, p, signal, observer);
+     if (!resolver) {
+       NS_WARNING("Could not add WorkerFetchResolver workerHolder to worker");
+       aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
+       return nullptr;
+     }
+ 
+     RefPtr<MainThreadFetchRunnable> run =
+-      new MainThreadFetchRunnable(resolver, r);
++      new MainThreadFetchRunnable(resolver, worker->GetClientInfo(),
++                                  worker->GetController(), r);
+     worker->DispatchToMainThread(run.forget());
+   }
+ 
+   return p.forget();
+ }
+ 
+ void
+ MainThreadFetchResolver::OnResponseAvailableInternal(InternalResponse* aResponse)
+diff --git a/dom/fetch/FetchDriver.cpp b/dom/fetch/FetchDriver.cpp
+--- a/dom/fetch/FetchDriver.cpp
++++ b/dom/fetch/FetchDriver.cpp
+@@ -512,16 +512,28 @@ FetchDriver::HttpFetch(const nsACString&
+                        uri,
+                        mDocument,
+                        secFlags,
+                        mRequest->ContentPolicyType(),
+                        mLoadGroup,
+                        nullptr, /* aCallbacks */
+                        loadFlags,
+                        ios);
++  } else if (mClientInfo.isSome()) {
++    rv = NS_NewChannel(getter_AddRefs(chan),
++                       uri,
++                       mPrincipal,
++                       mClientInfo.ref(),
++                       mController,
++                       secFlags,
++                       mRequest->ContentPolicyType(),
++                       mLoadGroup,
++                       nullptr, /* aCallbacks */
++                       loadFlags,
++                       ios);
+   } else {
+     rv = NS_NewChannel(getter_AddRefs(chan),
+                        uri,
+                        mPrincipal,
+                        secFlags,
+                        mRequest->ContentPolicyType(),
+                        mLoadGroup,
+                        nullptr, /* aCallbacks */
+@@ -1328,16 +1340,30 @@ FetchDriver::GetInterface(const nsIID& a
+ void
+ FetchDriver::SetDocument(nsIDocument* aDocument)
+ {
+   // Cannot set document after Fetch() has been called.
+   MOZ_ASSERT(!mFetchCalled);
+   mDocument = aDocument;
+ }
+ 
++void
++FetchDriver::SetClientInfo(const ClientInfo& aClientInfo)
++{
++  MOZ_ASSERT(!mFetchCalled);
++  mClientInfo.emplace(aClientInfo);
++}
++
++void
++FetchDriver::SetController(const Maybe<ServiceWorkerDescriptor>& aController)
++{
++  MOZ_ASSERT(!mFetchCalled);
++  mController = aController;
++}
++
+ void FetchDriver::SetRequestHeaders(nsIHttpChannel* aChannel) const {
+   MOZ_ASSERT(aChannel);
+ 
+   // nsIHttpChannel has a set of pre-configured headers (Accept,
+   // Accept-Languages, ...) and we don't want to merge the Request's headers
+   // with them. This array is used to know if the current header has been aleady
+   // set, if yes, we ask necko to merge it with the previous one, otherwise, we
+   // don't want the merge.
+diff --git a/dom/fetch/FetchDriver.h b/dom/fetch/FetchDriver.h
+--- a/dom/fetch/FetchDriver.h
++++ b/dom/fetch/FetchDriver.h
+@@ -113,16 +113,22 @@ public:
+ 
+   nsresult Fetch(AbortSignal* aSignal,
+                  FetchDriverObserver* aObserver);
+ 
+   void
+   SetDocument(nsIDocument* aDocument);
+ 
+   void
++  SetClientInfo(const ClientInfo& aClientInfo);
++
++  void
++  SetController(const Maybe<ServiceWorkerDescriptor>& aController);
++
++  void
+   SetWorkerScript(const nsACString& aWorkerScirpt)
+   {
+     MOZ_ASSERT(!aWorkerScirpt.IsEmpty());
+     mWorkerScript = aWorkerScirpt;
+   }
+ 
+   // AbortFollower
+   void
+@@ -131,16 +137,18 @@ public:
+ private:
+   nsCOMPtr<nsIPrincipal> mPrincipal;
+   nsCOMPtr<nsILoadGroup> mLoadGroup;
+   RefPtr<InternalRequest> mRequest;
+   RefPtr<InternalResponse> mResponse;
+   nsCOMPtr<nsIOutputStream> mPipeOutputStream;
+   RefPtr<FetchDriverObserver> mObserver;
+   nsCOMPtr<nsIDocument> mDocument;
++  Maybe<ClientInfo> mClientInfo;
++  Maybe<ServiceWorkerDescriptor> mController;
+   nsCOMPtr<nsIChannel> mChannel;
+   nsAutoPtr<SRICheckDataVerifier> mSRIDataVerifier;
+   nsCOMPtr<nsIEventTarget> mMainThreadEventTarget;
+   SRIMetadata mSRIMetadata;
+   nsCString mWorkerScript;
+ 
+   // This is written once in OnStartRequest on the main thread and then
+   // written/read in OnDataAvailable() on any thread.  Necko guarantees

+ 216 - 0
mozilla-release/patches/1231211-15no16-60a1.patch

@@ -0,0 +1,216 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1516721934 18000
+# Node ID 267096d4a6e6b7ad47c7d3c19544a8c50f549af9
+# Parent  ae0a777d1821cd114fe68f07533028b123dd0d01
+Bug 1231211 P15 Make xhr pass worker ClientInfo and ServiceWorkerDescriptor to NS_NewChannel(). r=asuth
+
+diff --git a/dom/xhr/XMLHttpRequestMainThread.cpp b/dom/xhr/XMLHttpRequestMainThread.cpp
+--- a/dom/xhr/XMLHttpRequestMainThread.cpp
++++ b/dom/xhr/XMLHttpRequestMainThread.cpp
+@@ -303,16 +303,24 @@ XMLHttpRequestMainThread::InitParameters
+       return;
+     }
+   }
+ 
+   SetParameters(aAnon, aSystem);
+ }
+ 
+ void
++XMLHttpRequestMainThread::SetClientInfoAndController(const ClientInfo& aClientInfo,
++                                                     const Maybe<ServiceWorkerDescriptor>& aController)
++{
++  mClientInfo.emplace(aClientInfo);
++  mController = aController;
++}
++
++void
+ XMLHttpRequestMainThread::ResetResponse()
+ {
+   mResponseXML = nullptr;
+   mResponseBody.Truncate();
+   TruncateResponseText();
+   mResponseBlob = nullptr;
+   mBlobStorage = nullptr;
+   mResultArrayBuffer = nullptr;
+@@ -2475,16 +2483,27 @@ XMLHttpRequestMainThread::CreateChannel(
+     rv = NS_NewChannel(getter_AddRefs(mChannel),
+                        mRequestURL,
+                        responsibleDocument,
+                        secFlags,
+                        nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST,
+                        loadGroup,
+                        nullptr,   // aCallbacks
+                        loadFlags);
++  } else if (mClientInfo.isSome()) {
++    rv = NS_NewChannel(getter_AddRefs(mChannel),
++                       mRequestURL,
++                       mPrincipal,
++                       mClientInfo.ref(),
++                       mController,
++                       secFlags,
++                       nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST,
++                       loadGroup,
++                       nullptr,   // aCallbacks
++                       loadFlags);
+   } else {
+     // Otherwise use the principal.
+     rv = NS_NewChannel(getter_AddRefs(mChannel),
+                        mRequestURL,
+                        mPrincipal,
+                        secFlags,
+                        nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST,
+                        loadGroup,
+diff --git a/dom/xhr/XMLHttpRequestMainThread.h b/dom/xhr/XMLHttpRequestMainThread.h
+--- a/dom/xhr/XMLHttpRequestMainThread.h
++++ b/dom/xhr/XMLHttpRequestMainThread.h
+@@ -27,23 +27,26 @@
+ #include "nsIPrincipal.h"
+ #include "nsIScriptObjectPrincipal.h"
+ #include "nsISizeOfEventTarget.h"
+ #include "nsIXPConnect.h"
+ #include "nsIInputStream.h"
+ #include "mozilla/Assertions.h"
+ #include "mozilla/Attributes.h"
+ #include "mozilla/DOMEventTargetHelper.h"
++#include "mozilla/Maybe.h"
+ #include "mozilla/MemoryReporting.h"
+ #include "mozilla/NotNull.h"
+ #include "mozilla/dom/MutableBlobStorage.h"
+ #include "mozilla/dom/BodyExtractor.h"
++#include "mozilla/dom/ClientInfo.h"
+ #include "mozilla/dom/TypedArray.h"
+ #include "mozilla/dom/File.h"
+ #include "mozilla/dom/FormData.h"
++#include "mozilla/dom/ServiceWorkerDescriptor.h"
+ #include "mozilla/dom/URLSearchParams.h"
+ #include "mozilla/dom/XMLHttpRequest.h"
+ #include "mozilla/dom/XMLHttpRequestBinding.h"
+ #include "mozilla/dom/XMLHttpRequestEventTarget.h"
+ #include "mozilla/dom/XMLHttpRequestString.h"
+ #include "mozilla/Encoding.h"
+ 
+ #ifdef Status
+@@ -217,16 +220,19 @@ public:
+   void InitParameters(bool aAnon, bool aSystem);
+ 
+   void SetParameters(bool aAnon, bool aSystem)
+   {
+     mIsAnon = aAnon || aSystem;
+     mIsSystem = aSystem;
+   }
+ 
++  void SetClientInfoAndController(const ClientInfo& aClientInfo,
++                                  const Maybe<ServiceWorkerDescriptor>& aController);
++
+   NS_DECL_ISUPPORTS_INHERITED
+ 
+   // nsIXMLHttpRequest
+   NS_DECL_NSIXMLHTTPREQUEST
+ 
+   NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(XMLHttpRequestEventTarget::)
+ 
+   // nsIStreamListener
+@@ -683,16 +689,19 @@ protected:
+   nsCOMPtr<nsIChannelEventSink> mChannelEventSink;
+   nsCOMPtr<nsIProgressEventSink> mProgressEventSink;
+ 
+   nsIRequestObserver* mRequestObserver;
+ 
+   nsCOMPtr<nsIURI> mBaseURI;
+   nsCOMPtr<nsILoadGroup> mLoadGroup;
+ 
++  Maybe<ClientInfo> mClientInfo;
++  Maybe<ServiceWorkerDescriptor> mController;
++
+   State mState;
+ 
+   StyleBackendType mStyleBackend;
+ 
+   bool mFlagSynchronous;
+   bool mFlagAborted;
+   bool mFlagParseBody;
+   bool mFlagSyncLooping;
+diff --git a/dom/xhr/XMLHttpRequestWorker.cpp b/dom/xhr/XMLHttpRequestWorker.cpp
+--- a/dom/xhr/XMLHttpRequestWorker.cpp
++++ b/dom/xhr/XMLHttpRequestWorker.cpp
+@@ -92,16 +92,18 @@ XMLHttpRequestWorker::StateData::trace(J
+  */
+ 
+ class Proxy final : public nsIDOMEventListener
+ {
+ public:
+   // Read on multiple threads.
+   WorkerPrivate* mWorkerPrivate;
+   XMLHttpRequestWorker* mXMLHttpRequestPrivate;
++  const ClientInfo mClientInfo;
++  const Maybe<ServiceWorkerDescriptor> mController;
+ 
+   // XHR Params:
+   bool mMozAnon;
+   bool mMozSystem;
+ 
+   // Only touched on the main thread.
+   RefPtr<XMLHttpRequestMainThread> mXHR;
+   nsCOMPtr<nsIXMLHttpRequestUpload> mXHRUpload;
+@@ -127,18 +129,21 @@ public:
+ 
+   // Only touched on the main thread.
+   bool mUploadEventListenersAttached;
+   bool mMainThreadSeenLoadStart;
+   bool mInOpen;
+   bool mArrayBufferResponseWasTransferred;
+ 
+ public:
+-  Proxy(XMLHttpRequestWorker* aXHRPrivate, bool aMozAnon, bool aMozSystem)
++  Proxy(XMLHttpRequestWorker* aXHRPrivate, const ClientInfo& aClientInfo,
++        const Maybe<ServiceWorkerDescriptor>& aController, bool aMozAnon,
++        bool aMozSystem)
+   : mWorkerPrivate(nullptr), mXMLHttpRequestPrivate(aXHRPrivate),
++    mClientInfo(aClientInfo), mController(aController),
+     mMozAnon(aMozAnon), mMozSystem(aMozSystem),
+     mInnerEventStreamId(0), mInnerChannelId(0), mOutstandingSendCount(0),
+     mOuterEventStreamId(0), mOuterChannelId(0), mOpenCount(0), mLastLoaded(0),
+     mLastTotal(0), mLastUploadLoaded(0), mLastUploadTotal(0), mIsSyncXHR(false),
+     mLastLengthComputable(false), mLastUploadLengthComputable(false),
+     mSeenLoadStart(false), mSeenUploadLoadStart(false),
+     mUploadEventListenersAttached(false), mMainThreadSeenLoadStart(false),
+     mInOpen(false), mArrayBufferResponseWasTransferred(false)
+@@ -866,16 +871,17 @@ Proxy::Init()
+   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(ownerWindow);
+ 
+   mXHR = new XMLHttpRequestMainThread();
+   mXHR->Construct(mWorkerPrivate->GetPrincipal(), global,
+                   mWorkerPrivate->GetBaseURI(),
+                   mWorkerPrivate->GetLoadGroup());
+ 
+   mXHR->SetParameters(mMozAnon, mMozSystem);
++  mXHR->SetClientInfoAndController(mClientInfo, mController);
+ 
+   ErrorResult rv;
+   mXHRUpload = mXHR->GetUpload(rv);
+   if (NS_WARN_IF(rv.Failed())) {
+     mXHR = nullptr;
+     return false;
+   }
+ 
+@@ -1877,17 +1883,18 @@ XMLHttpRequestWorker::Open(const nsACStr
+ 
+   if (mProxy) {
+     MaybeDispatchPrematureAbortEvents(aRv);
+     if (aRv.Failed()) {
+       return;
+     }
+   }
+   else {
+-    mProxy = new Proxy(this, mMozAnon, mMozSystem);
++    mProxy = new Proxy(this, mWorkerPrivate->GetClientInfo(),
++                       mWorkerPrivate->GetController(), mMozAnon, mMozSystem);
+   }
+ 
+   mProxy->mOuterEventStreamId++;
+ 
+   RefPtr<OpenRunnable> runnable =
+     new OpenRunnable(mWorkerPrivate, mProxy, aMethod, aUrl, aUser, aPassword,
+                      mBackgroundRequest, mWithCredentials,
+                      mTimeout, mResponseType);

+ 56 - 0
mozilla-release/patches/1231211-17-60a1.patch

@@ -0,0 +1,56 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1516721934 18000
+# Node ID 7b0d7cffb81e9a852532ad1542c56c81c1d1adcd
+# Parent  22c472e02f6902f12414f32385fe3e7a1165cdad
+Bug 1231211 P17 Fix test_sandbox_intercept.html to not use allow-same-origin attribute. r=asuth
+
+diff --git a/dom/workers/test/serviceworkers/test_sandbox_intercept.html b/dom/workers/test/serviceworkers/test_sandbox_intercept.html
+--- a/dom/workers/test/serviceworkers/test_sandbox_intercept.html
++++ b/dom/workers/test/serviceworkers/test_sandbox_intercept.html
+@@ -7,33 +7,39 @@
+ <head>
+   <title>Bug 1142727 - Test that sandboxed iframes are not intercepted</title>
+   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ </head>
+ <body>
+ <p id="display"></p>
+ <div id="content">
+-<iframe sandbox="allow-scripts allow-same-origin"></iframe>
++<iframe id="normal-frame"></iframe>
++<iframe sandbox="allow-scripts" id="sandbox-frame"></iframe>
+ </div>
+ <pre id="test"></pre>
+ <script class="testbody" type="text/javascript">
+ 
+-  var iframe;
++  var normalFrame;
++  var sandboxFrame;
+   function runTest() {
+-    iframe = document.querySelector("iframe");
+-    iframe.src = "/tests/dom/workers/test/serviceworkers/fetch/sandbox/register.html";
++    normalFrame = document.getElementById("normal-frame");
++    sandboxFrame = document.getElementById("sandbox-frame");
++    normalFrame.src = "/tests/dom/workers/test/serviceworkers/fetch/sandbox/register.html";
+     window.onmessage = function(e) {
+       if (e.data.status == "ok") {
+         ok(e.data.result, e.data.message);
+       } else if (e.data.status == "registrationdone") {
+-        iframe.src = "/tests/dom/workers/test/serviceworkers/fetch/sandbox/index.html";
++        normalFrame.src = "about:blank";
++        sandboxFrame.src = "/tests/dom/workers/test/serviceworkers/fetch/sandbox/index.html";
+       } else if (e.data.status == "done") {
+-        iframe.src = "/tests/dom/workers/test/serviceworkers/fetch/sandbox/unregister.html";
++        sandboxFrame.src = "about:blank";
++        normalFrame.src = "/tests/dom/workers/test/serviceworkers/fetch/sandbox/unregister.html";
+       } else if (e.data.status == "unregistrationdone") {
++        normalFrame.src = "about:blank";
+         window.onmessage = null;
+         ok(true, "Test finished successfully");
+         SimpleTest.finish();
+       }
+     };
+   }
+ 
+   SimpleTest.waitForExplicitFinish();

+ 162 - 0
mozilla-release/patches/1231211-18-60a1.patch

@@ -0,0 +1,162 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1516721934 18000
+# Node ID 591601f47ee984ba4e70bb647df36327a825b0f0
+# Parent  0b11930d961f9e24540b3b097e30977c810b8fc3
+Bug 1231211 P18 Make blob URL worker scripts inherit the parent's controller. r=asuth
+
+diff --git a/dom/workers/ScriptLoader.cpp b/dom/workers/ScriptLoader.cpp
+--- a/dom/workers/ScriptLoader.cpp
++++ b/dom/workers/ScriptLoader.cpp
+@@ -24,16 +24,17 @@
+ #include "nsIURI.h"
+ 
+ #include "jsapi.h"
+ #include "jsfriendapi.h"
+ #include "nsError.h"
+ #include "nsContentPolicyUtils.h"
+ #include "nsContentUtils.h"
+ #include "nsDocShellCID.h"
++#include "nsHostObjectProtocolHandler.h"
+ #include "nsISupportsPrimitives.h"
+ #include "nsNetUtil.h"
+ #include "nsIPipe.h"
+ #include "nsIOutputStream.h"
+ #include "nsPrintfCString.h"
+ #include "nsString.h"
+ #include "nsStreamUtils.h"
+ #include "nsTArray.h"
+@@ -1257,16 +1258,28 @@ private:
+       if (parent) {
+         // XHR Params Allowed
+         mWorkerPrivate->SetXHRParamsAllowed(parent->XHRParamsAllowed());
+       }
+ 
+       if (chanLoadInfo) {
+         mController = chanLoadInfo->GetController();
+       }
++
++      // If we are loading a blob URL we must inherit the controller
++      // from the parent.  This is a bit odd as the blob URL may have
++      // been created in a different context with a different controller.
++      // For now, though, this is what the spec says.  See:
++      //
++      // https://github.com/w3c/ServiceWorker/issues/1261
++      //
++      if (IsBlobURI(mWorkerPrivate->GetBaseURI())) {
++        MOZ_DIAGNOSTIC_ASSERT(mController.isNothing());
++        mController = mWorkerPrivate->GetParentController();
++      }
+     }
+ 
+     return NS_OK;
+   }
+ 
+   void
+   DataReceivedFromCache(uint32_t aIndex, const uint8_t* aString,
+                         uint32_t aStringLen,
+diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
+--- a/dom/workers/WorkerPrivate.cpp
++++ b/dom/workers/WorkerPrivate.cpp
+@@ -1846,16 +1846,17 @@ WorkerLoadInfo::StealFrom(WorkerLoadInfo
+   mFromWindow = aOther.mFromWindow;
+   mEvalAllowed = aOther.mEvalAllowed;
+   mReportCSPViolations = aOther.mReportCSPViolations;
+   mXHRParamsAllowed = aOther.mXHRParamsAllowed;
+   mPrincipalIsSystem = aOther.mPrincipalIsSystem;
+   mStorageAllowed = aOther.mStorageAllowed;
+   mServiceWorkersTestingInWindow = aOther.mServiceWorkersTestingInWindow;
+   mOriginAttributes = aOther.mOriginAttributes;
++  mParentController = aOther.mParentController;
+ }
+ 
+ nsresult
+ WorkerLoadInfo::SetPrincipalOnMainThread(nsIPrincipal* aPrincipal,
+                                          nsILoadGroup* aLoadGroup)
+ {
+   AssertIsOnMainThread();
+   MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(aLoadGroup, aPrincipal));
+@@ -4787,16 +4788,17 @@ WorkerPrivate::GetLoadInfo(JSContext* aC
+ 
+     loadInfo.mDomain = aParent->Domain();
+     loadInfo.mFromWindow = aParent->IsFromWindow();
+     loadInfo.mWindowID = aParent->WindowID();
+     loadInfo.mStorageAllowed = aParent->IsStorageAllowed();
+     loadInfo.mOriginAttributes = aParent->GetOriginAttributes();
+     loadInfo.mServiceWorkersTestingInWindow =
+       aParent->ServiceWorkersTestingInWindow();
++    loadInfo.mParentController = aParent->GetController();
+   } else {
+     AssertIsOnMainThread();
+ 
+     // Make sure that the IndexedDatabaseManager is set up
+     Unused << NS_WARN_IF(!IndexedDatabaseManager::GetOrCreate());
+ 
+     nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
+     MOZ_ASSERT(ssm);
+@@ -4917,16 +4919,17 @@ WorkerPrivate::GetLoadInfo(JSContext* aC
+       loadInfo.mXHRParamsAllowed = perm == nsIPermissionManager::ALLOW_ACTION;
+ 
+       loadInfo.mFromWindow = true;
+       loadInfo.mWindowID = globalWindow->WindowID();
+       nsContentUtils::StorageAccess access =
+         nsContentUtils::StorageAllowedForWindow(globalWindow);
+       loadInfo.mStorageAllowed = access > nsContentUtils::StorageAccess::eDeny;
+       loadInfo.mOriginAttributes = nsContentUtils::GetOriginAttributes(document);
++      loadInfo.mParentController = globalWindow->GetController();
+     } else {
+       // Not a window
+       MOZ_ASSERT(isChrome);
+ 
+       // We're being created outside of a window. Need to figure out the script
+       // that is creating us in order for us to use relative URIs later on.
+       JS::AutoFilename fileName;
+       if (JS::DescribeScriptedCaller(aCx, &fileName)) {
+diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h
+--- a/dom/workers/WorkerPrivate.h
++++ b/dom/workers/WorkerPrivate.h
+@@ -568,16 +568,22 @@ public:
+   void
+   UpdateServiceWorkerState(ServiceWorkerState aState)
+   {
+     MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
+     MOZ_DIAGNOSTIC_ASSERT(mLoadInfo.mServiceWorkerDescriptor.isSome());
+     return mLoadInfo.mServiceWorkerDescriptor.ref().SetState(aState);
+   }
+ 
++  const Maybe<ServiceWorkerDescriptor>&
++  GetParentController() const
++  {
++    return mLoadInfo.mParentController;
++  }
++
+   const ChannelInfo&
+   GetChannelInfo() const
+   {
+     return mLoadInfo.mChannelInfo;
+   }
+ 
+   void
+   SetChannelInfo(const ChannelInfo& aChannelInfo)
+diff --git a/dom/workers/Workers.h b/dom/workers/Workers.h
+--- a/dom/workers/Workers.h
++++ b/dom/workers/Workers.h
+@@ -240,16 +240,18 @@ struct WorkerLoadInfo
+ 
+   nsAutoPtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
+   nsCString mDomain;
+   nsString mOrigin; // Derived from mPrincipal; can be used on worker thread.
+ 
+   nsString mServiceWorkerCacheName;
+   Maybe<ServiceWorkerDescriptor> mServiceWorkerDescriptor;
+ 
++  Maybe<ServiceWorkerDescriptor> mParentController;
++
+   ChannelInfo mChannelInfo;
+   nsLoadFlags mLoadFlags;
+ 
+   uint64_t mWindowID;
+ 
+   net::ReferrerPolicy mReferrerPolicy;
+   bool mFromWindow;
+   bool mEvalAllowed;

+ 64 - 0
mozilla-release/patches/1231211-19-60a1.patch

@@ -0,0 +1,64 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1516721934 18000
+# Node ID 031f9a598f746a6057bee2dda1b0787cdd7c62a1
+# Parent  be9d3760cd81ca65a9bca410240b8d4a00a26a01
+Bug 1231211 P19 Make DevToolsUtils.newChannelForURL() set the loadingNode so that the SW controller is set on the channel. r=jryans
+
+diff --git a/devtools/shared/DevToolsUtils.js b/devtools/shared/DevToolsUtils.js
+--- a/devtools/shared/DevToolsUtils.js
++++ b/devtools/shared/DevToolsUtils.js
+@@ -662,30 +662,42 @@ function newChannelForURL(url, { policy,
+     // scheme to see if it helps.
+     uri = Services.io.newURI("file://" + url);
+   }
+   let channelOptions = {
+     contentPolicyType: policy,
+     securityFlags: securityFlags,
+     uri: uri
+   };
+-  let prin = principal;
+-  if (!prin) {
+-    let oa = {};
+-    if (window) {
+-      oa = window.document.nodePrincipal.originAttributes;
+-    }
+-    prin = Services.scriptSecurityManager
+-                   .createCodebasePrincipal(uri, oa);
+-  }
+-  // contentPolicyType is required when specifying a principal
++
++  // Ensure that we have some contentPolicyType type set if one was
++  // not provided.
+   if (!channelOptions.contentPolicyType) {
+     channelOptions.contentPolicyType = Ci.nsIContentPolicy.TYPE_OTHER;
+   }
+-  channelOptions.loadingPrincipal = prin;
++
++  // If a window is provided, always use it's document as the loadingNode.
++  // This will provide the correct principal, origin attributes, service
++  // worker controller, etc.
++  if (window) {
++    channelOptions.loadingNode = window.document;
++  } else {
++    // If a window is not provided, then we must set a loading principal.
++
++    // If the caller did not provide a principal, then we use the URI
++    // to create one.  Note, it's not clear what use cases require this
++    // and it may not be correct.
++    let prin = principal;
++    if (!prin) {
++      prin = Services.scriptSecurityManager
++                     .createCodebasePrincipal(uri, {});
++    }
++
++    channelOptions.loadingPrincipal = prin;
++  }
+ 
+   try {
+     return NetUtil.newChannel(channelOptions);
+   } catch (e) {
+     // In xpcshell tests on Windows, nsExternalProtocolHandler::NewChannel()
+     // can throw NS_ERROR_UNKNOWN_PROTOCOL if the external protocol isn't
+     // supported by Windows, so we also need to handle the exception here if
+     // parsing the URL above doesn't throw.

+ 42 - 0
mozilla-release/patches/1231211-20-60a1.patch

@@ -0,0 +1,42 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1516721935 18000
+# Node ID 470a289fb31c86aa989127c3d27221305e703244
+# Parent  031f9a598f746a6057bee2dda1b0787cdd7c62a1
+Bug 1231211 P20 Don't call CancelInterception() if an error occurs in ChannelIntercepted(). r=asuth
+
+diff --git a/dom/workers/ServiceWorkerInterceptController.cpp b/dom/workers/ServiceWorkerInterceptController.cpp
+--- a/dom/workers/ServiceWorkerInterceptController.cpp
++++ b/dom/workers/ServiceWorkerInterceptController.cpp
+@@ -56,26 +56,27 @@ ServiceWorkerInterceptController::Should
+   // for a matching service worker.
+   *aShouldIntercept = swm->IsAvailable(principal, aURI);
+   return NS_OK;
+ }
+ 
+ NS_IMETHODIMP
+ ServiceWorkerInterceptController::ChannelIntercepted(nsIInterceptedChannel* aChannel)
+ {
++  // Note, do not cancel the interception here.  The caller will try to
++  // ResetInterception() on error.
++
+   RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
+   if (!swm) {
+-    aChannel->CancelInterception(NS_ERROR_INTERCEPTION_FAILED);
+-    return NS_OK;
++    return NS_ERROR_FAILURE;
+   }
+ 
+   ErrorResult error;
+   swm->DispatchFetchEvent(aChannel, error);
+   if (NS_WARN_IF(error.Failed())) {
+-    aChannel->CancelInterception(NS_ERROR_INTERCEPTION_FAILED);
+     return error.StealNSResult();
+   }
+ 
+   return NS_OK;
+ }
+ 
+ } // namespace dom
+ } // namespace mozilla
+

+ 14 - 14
mozilla-release/patches/1252998-04-61a1.patch

@@ -2,7 +2,7 @@
 # User Andrea Marchesini <amarchesini@mozilla.com>
 # Date 1524068352 -7200
 # Node ID f60bc2fa25660c571283eb63c3475aff4566f2ac
-# Parent  702f5938a2ad23b3fc9ce8cb40a18e95c20d2b61
+# Parent  8dd13dd29d68f9f3f29cc9461ec2a32245f9739e
 Bug 1252998 - StorageActivityService - part 4 - Introduce ServiceWorkerCleanUp.jsm to clean up ServiceWorker data, r=asuth
 
 diff --git a/browser/components/extensions/ext-browsingData.js b/browser/components/extensions/ext-browsingData.js
@@ -254,14 +254,14 @@ diff --git a/browser/modules/SiteDataManager.jsm b/browser/modules/SiteDataManag
 diff --git a/dom/interfaces/base/nsIServiceWorkerManager.idl b/dom/interfaces/base/nsIServiceWorkerManager.idl
 --- a/dom/interfaces/base/nsIServiceWorkerManager.idl
 +++ b/dom/interfaces/base/nsIServiceWorkerManager.idl
-@@ -168,27 +168,16 @@ interface nsIServiceWorkerManager : nsIS
-   [noscript] nsISupports GetActive(in nsPIDOMWindowInner aWindow, in DOMString aScope);
- 
-   /*
-    * Returns a ServiceWorker object representing the active worker controlling this
-    * window.
+@@ -161,27 +161,16 @@ interface nsIServiceWorkerManager : nsIS
+    * window is the window of the caller. scope is the registration's scope and must be
+    * a valid entry that window is allowed to load, otherwise this will return nullptr.
+    * These are only meant to be called from ServiceWorkerRegistration instances.
     */
-   [noscript] nsISupports GetDocumentController(in nsPIDOMWindowInner aWindow);
+   [noscript] nsISupports GetInstalling(in nsPIDOMWindowInner aWindow, in DOMString aScope);
+   [noscript] nsISupports GetWaiting(in nsPIDOMWindowInner aWindow, in DOMString aScope);
+   [noscript] nsISupports GetActive(in nsPIDOMWindowInner aWindow, in DOMString aScope);
  
 -  /*
 -   * Clears ServiceWorker registrations from memory and disk for the specified
@@ -285,7 +285,7 @@ diff --git a/dom/interfaces/base/nsIServiceWorkerManager.idl b/dom/interfaces/ba
 diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerManager.cpp
 --- a/dom/workers/ServiceWorkerManager.cpp
 +++ b/dom/workers/ServiceWorkerManager.cpp
-@@ -91,17 +91,16 @@
+@@ -94,17 +94,16 @@
  #endif
  
  using namespace mozilla;
@@ -303,7 +303,7 @@ diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerMan
                "RequestMode enumeration value should match Necko CORS mode value.");
  static_assert(nsIHttpChannelInternal::CORS_MODE_CORS == static_cast<uint32_t>(RequestMode::Cors),
                "RequestMode enumeration value should match Necko CORS mode value.");
-@@ -281,18 +280,16 @@ ServiceWorkerManager::Init(ServiceWorker
+@@ -284,18 +283,16 @@ ServiceWorkerManager::Init(ServiceWorker
      MOZ_DIAGNOSTIC_ASSERT(aRegistrar);
  
      nsTArray<ServiceWorkerRegistrationData> data;
@@ -322,7 +322,7 @@ diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerMan
    PBackgroundChild* actorChild = BackgroundChild::GetOrCreateForCurrentThread();
    if (NS_WARN_IF(!actorChild)) {
      MaybeStartShutdown();
-@@ -334,17 +331,16 @@ ServiceWorkerManager::MaybeStartShutdown
+@@ -406,17 +403,16 @@ ServiceWorkerManager::MaybeStartShutdown
      it1.UserData()->mJobQueues.Clear();
    }
  
@@ -340,7 +340,7 @@ diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerMan
      return;
    }
  
-@@ -3596,24 +3592,16 @@ ServiceWorkerManager::ForceUnregister(Re
+@@ -3264,24 +3260,16 @@ ServiceWorkerManager::ForceUnregister(Re
      entry.Data()->Cancel();
      entry.Remove();
    }
@@ -365,7 +365,7 @@ diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerMan
    for (auto it1 = mRegistrationInfos.Iter(); !it1.Done(); it1.Next()) {
      ServiceWorkerManager::RegistrationDataPerPrincipal* data = it1.UserData();
      for (auto it2 = data->mInfos.Iter(); !it2.Done(); it2.Next()) {
-@@ -3834,23 +3822,16 @@ ServiceWorkerManager::ShouldReportToWind
+@@ -3384,23 +3372,16 @@ ServiceWorkerManager::RemoveListener(nsI
    return NS_OK;
  }
  
@@ -432,7 +432,7 @@ diff --git a/testing/specialpowers/content/specialpowersAPI.js b/testing/special
  // returning "this" from indirect eval, which returns the global.
  if (!(function() { var e = eval; return e("this"); })().File) { // eslint-disable-line no-eval
      Cu.importGlobalProperties(["File"]);
-@@ -1914,21 +1915,21 @@ SpecialPowersAPI.prototype = {
+@@ -1934,21 +1935,21 @@ SpecialPowersAPI.prototype = {
        "op": "notify",
        "observerTopic": topic,
        "observerData": data

+ 60 - 0
mozilla-release/patches/1424300-1-59a1.patch

@@ -0,0 +1,60 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1513276031 18000
+# Node ID 474703f757348ff778480170c4f049dc2c629b2c
+# Parent  f3c3d028b45af37f4a6d27681556f2bc967f5505
+Bug 1424300 P1 Gracefully handle when the service worker script cache exists, but is empty. r=edenchuang
+
+diff --git a/dom/workers/ServiceWorkerScriptCache.cpp b/dom/workers/ServiceWorkerScriptCache.cpp
+--- a/dom/workers/ServiceWorkerScriptCache.cpp
++++ b/dom/workers/ServiceWorkerScriptCache.cpp
+@@ -463,33 +463,48 @@ private:
+       return;
+     }
+ 
+     // Fetch and compare the source scripts.
+     MOZ_ASSERT(mPendingCount == 0);
+ 
+     mState = WaitingForScriptOrComparisonResult;
+ 
++    // Always make sure to fetch the main script.  If the old cache has
++    // no entries or the main script entry is missing, then the loop below
++    // may not trigger it.  This should not really happen, but we handle it
++    // gracefully if it does occur.  Its possible the bad cache state is due
++    // to a crash or shutdown during an update, etc.
++    rv = FetchScript(mURL, true /* aIsMainScript */, mOldCache);
++    if (NS_WARN_IF(NS_FAILED(rv))) {
++      return;
++    }
++
+     for (uint32_t i = 0; i < len; ++i) {
+       JS::Rooted<JS::Value> val(aCx);
+       if (NS_WARN_IF(!JS_GetElement(aCx, obj, i, &val)) ||
+           NS_WARN_IF(!val.isObject())) {
+         return;
+       }
+ 
+       Request* request;
+       JS::Rooted<JSObject*> requestObj(aCx, &val.toObject());
+       if (NS_WARN_IF(NS_FAILED(UNWRAP_OBJECT(Request, &requestObj, request)))) {
+         return;
+       };
+ 
+       nsString URL;
+       request->GetUrl(URL);
+ 
+-      rv = FetchScript(URL, mURL == URL /* aIsMainScript */, mOldCache);
++      // We explicitly start the fetch for the main script above.
++      if (mURL == URL) {
++        continue;
++      }
++
++      rv = FetchScript(URL, false /* aIsMainScript */, mOldCache);
+       if (NS_WARN_IF(NS_FAILED(rv))) {
+         return;
+       }
+     }
+ 
+     guard.release();
+   }
+ 

+ 162 - 0
mozilla-release/patches/1424300-2-59a1.patch

@@ -0,0 +1,162 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1513276031 18000
+# Node ID e48d2f34e8f9f6d73214d1822091c0e551203da3
+# Parent  d4c29a2fc40b7f6e3dbfa2dcb4dc3718e7bcacb2
+Bug 1424300 P2 Store response URLs in the service worker script cache. r=edenchuang
+
+diff --git a/dom/workers/ServiceWorkerScriptCache.cpp b/dom/workers/ServiceWorkerScriptCache.cpp
+--- a/dom/workers/ServiceWorkerScriptCache.cpp
++++ b/dom/workers/ServiceWorkerScriptCache.cpp
+@@ -159,16 +159,22 @@ public:
+   }
+ 
+   bool
+   Succeeded() const
+   {
+     return NS_SUCCEEDED(mNetworkResult);
+   }
+ 
++  const nsTArray<nsCString>&
++  URLList() const
++  {
++    return mURLList;
++  }
++
+ private:
+   ~CompareNetwork()
+   {
+     AssertIsOnMainThread();
+     MOZ_ASSERT(!mCC);
+   }
+ 
+   void
+@@ -182,16 +188,17 @@ private:
+   RefPtr<ServiceWorkerRegistrationInfo> mRegistration;
+ 
+   nsCOMPtr<nsIChannel> mChannel;
+   nsString mBuffer;
+   nsString mURL;
+   ChannelInfo mChannelInfo;
+   RefPtr<InternalHeaders> mInternalHeaders;
+   UniquePtr<PrincipalInfo> mPrincipalInfo;
++  nsTArray<nsCString> mURLList;
+ 
+   nsCString mMaxScope;
+   nsLoadFlags mLoadFlags;
+ 
+   enum {
+     WaitingForInitialization,
+     WaitingForBothFinished,
+     WaitingForNetworkFinished,
+@@ -597,16 +604,17 @@ private:
+     if (NS_WARN_IF(result.Failed())) {
+       MOZ_ASSERT(!result.IsErrorWithMessage());
+       return result.StealNSResult();
+     }
+ 
+     RefPtr<InternalResponse> ir =
+       new InternalResponse(200, NS_LITERAL_CSTRING("OK"));
+     ir->SetBody(body, aCN->Buffer().Length());
++    ir->SetURLList(aCN->URLList());
+ 
+     ir->InitChannelInfo(aCN->GetChannelInfo());
+     UniquePtr<PrincipalInfo> principalInfo = aCN->TakePrincipalInfo();
+     if (principalInfo) {
+       ir->SetPrincipalInfo(Move(principalInfo));
+     }
+ 
+     IgnoredErrorResult ignored;
+@@ -682,16 +690,17 @@ CompareNetwork::Initialize(nsIPrincipal*
+ 
+   nsCOMPtr<nsIURI> uri;
+   nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL, nullptr, nullptr);
+   if (NS_WARN_IF(NS_FAILED(rv))) {
+     return rv;
+   }
+ 
+   mURL = aURL;
++  mURLList.AppendElement(NS_ConvertUTF16toUTF8(mURL));
+ 
+   nsCOMPtr<nsILoadGroup> loadGroup;
+   rv = NS_NewLoadGroup(getter_AddRefs(loadGroup), aPrincipal);
+   if (NS_WARN_IF(NS_FAILED(rv))) {
+     return rv;
+   }
+ 
+   // Update LoadFlags for propagating to ServiceWorkerInfo.
+@@ -775,17 +784,17 @@ CompareNetwork::Finish()
+   if (mState == Finished) {
+     return;
+   }
+ 
+   bool same = true;
+   nsresult rv = NS_OK;
+ 
+   // mNetworkResult is prior to mCacheResult, since it's needed for reporting
+-  // various errors to web contenet.
++  // various errors to web content.
+   if (NS_FAILED(mNetworkResult)) {
+     // An imported script could become offline, since it might no longer be
+     // needed by the new importing script. In that case, the importing script
+     // must be different, and thus, it's okay to report same script found here.
+     rv = mIsMainScript ? mNetworkResult : NS_OK;
+     same = true;
+   } else if (mCC && NS_FAILED(mCacheResult)) {
+     rv = mCacheResult;
+@@ -984,35 +993,52 @@ CompareNetwork::OnStreamComplete(nsIStre
+ 
+   // [9.2 Update]4.13, If response's cache state is not "local",
+   // set registration's last update check time to the current time
+   if (!mIsFromCache) {
+     mRegistration->RefreshLastUpdateCheckTime();
+   }
+ 
+   nsAutoCString mimeType;
+-  nsresult rv2 = httpChannel->GetContentType(mimeType);
++  rv = httpChannel->GetContentType(mimeType);
+   if (NS_WARN_IF(NS_FAILED(rv))) {
+     // We should only end up here if !mResponseHead in the channel.  If headers
+     // were received but no content type was specified, we'll be given
+     // UNKNOWN_CONTENT_TYPE "application/x-unknown-content-type" and so fall
+     // into the next case with its better error message.
+     rv = NS_ERROR_DOM_SECURITY_ERR;
+-    return rv2;
++    return rv;
+   }
+ 
+   if (!mimeType.LowerCaseEqualsLiteral("text/javascript") &&
+       !mimeType.LowerCaseEqualsLiteral("application/x-javascript") &&
+       !mimeType.LowerCaseEqualsLiteral("application/javascript")) {
+     ServiceWorkerManager::LocalizeAndReportToAllClients(
+       mRegistration->mScope, "ServiceWorkerRegisterMimeTypeError",
+       nsTArray<nsString> { NS_ConvertUTF8toUTF16(mRegistration->mScope),
+         NS_ConvertUTF8toUTF16(mimeType), mURL });
+     rv = NS_ERROR_DOM_SECURITY_ERR;
+-    return rv2;
++    return rv;
++  }
++
++  nsCOMPtr<nsIURI> channelURL;
++  rv = httpChannel->GetURI(getter_AddRefs(channelURL));
++  if (NS_WARN_IF(NS_FAILED(rv))) {
++    return rv;
++  }
++
++  nsCString channelURLSpec;
++  MOZ_ALWAYS_SUCCEEDS(channelURL->GetSpec(channelURLSpec));
++
++  // Append the final URL if its different from the original
++  // request URL.  This lets us note that a redirect occurred
++  // even though we don't track every redirect URL here.
++  MOZ_DIAGNOSTIC_ASSERT(!mURLList.IsEmpty());
++  if (channelURLSpec != mURLList[0]) {
++    mURLList.AppendElement(channelURLSpec);
+   }
+ 
+   char16_t* buffer = nullptr;
+   size_t len = 0;
+ 
+   rv = ScriptLoader::ConvertToUTF16(httpChannel, aString, aLen,
+                                     NS_LITERAL_STRING("UTF-8"), nullptr,
+                                     buffer, len);

+ 157 - 0
mozilla-release/patches/1424300-3-59a1.patch

@@ -0,0 +1,157 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1513276031 18000
+# Node ID 9e183521e2dec6ab4ece8a8a7cdbfa476c700feb
+# Parent  a2eac135896cb2ea5272dd00f07ca4e1006599a2
+Bug 1424300 P3 Add a mochitest verifying we can recover if the script cache is deleted. r=edenchuang
+
+diff --git a/dom/workers/test/serviceworkers/mochitest.ini b/dom/workers/test/serviceworkers/mochitest.ini
+--- a/dom/workers/test/serviceworkers/mochitest.ini
++++ b/dom/workers/test/serviceworkers/mochitest.ini
+@@ -226,16 +226,17 @@ support-files =
+   lazy_worker.js
+   nofetch_handler_worker.js
+   service_worker.js
+   service_worker_client.html
+   utils.js
+   bug1290951_worker_main.sjs
+   bug1290951_worker_imported.sjs
+   sw_storage_not_allow.js
++  update_worker.sjs
+ 
+ [test_bug1151916.html]
+ [test_bug1240436.html]
+ [test_bug1408734.html]
+ [test_claim.html]
+ [test_claim_oninstall.html]
+ [test_controller.html]
+ [test_cookie_fetch.html]
+@@ -339,8 +340,9 @@ tags = openwindow
+ [test_update_missing_imported_script.html]
+ [test_workerUnregister.html]
+ [test_workerUpdate.html]
+ [test_workerupdatefoundevent.html]
+ [test_xslt.html]
+ [test_async_waituntil.html]
+ [test_worker_reference_gc_timeout.html]
+ [test_nofetch_handler.html]
++[test_bad_script_cache.html]
+diff --git a/dom/workers/test/serviceworkers/test_bad_script_cache.html b/dom/workers/test/serviceworkers/test_bad_script_cache.html
+new file mode 100644
+--- /dev/null
++++ b/dom/workers/test/serviceworkers/test_bad_script_cache.html
+@@ -0,0 +1,96 @@
++<!--
++  Any copyright is dedicated to the Public Domain.
++  http://creativecommons.org/publicdomain/zero/1.0/
++-->
++<!DOCTYPE HTML>
++<html>
++<head>
++  <title>Test updating a service worker with a bad script cache.</title>
++  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
++  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
++</head>
++<body>
++<script src='utils.js'></script>
++<script class="testbody" type="text/javascript">
++
++async function deleteCaches(cacheStorage) {
++  let keyList = await cacheStorage.keys();
++  let promiseList = [];
++  keyList.forEach(key => {
++    promiseList.push(cacheStorage.delete(key));
++  });
++  return await Promise.all(keyList);
++}
++
++function waitForUpdate(reg) {
++  return new Promise(resolve => {
++    reg.addEventListener('updatefound', resolve, { once: true });
++  });
++}
++
++async function runTest() {
++  let reg;
++  try {
++    const script = 'update_worker.sjs';
++    const scope = 'bad-script-cache';
++
++    reg = await navigator.serviceWorker.register(script, { scope: scope });
++    await waitForState(reg.installing, 'activated');
++
++    // Verify the service worker script cache has the worker script stored.
++    let chromeCaches = SpecialPowers.createChromeCache('chrome', window.origin);
++    let scriptURL = new URL(script, window.location.href);
++    let response = await chromeCaches.match(scriptURL.href);
++    is(response.url, scriptURL.href, 'worker script should be stored');
++
++    // Force delete the service worker script out from under the service worker.
++    // Note: Prefs are set to kill the SW thread immediately on idle.
++    await deleteCaches(chromeCaches);
++
++    // Verify the service script cache no longer knows about the worker script.
++    response = await chromeCaches.match(scriptURL.href);
++    is(response, undefined, 'worker script should not be stored');
++
++    // Force an update and wait for it to fire an update event.
++    reg.update();
++    await waitForUpdate(reg);
++    await waitForState(reg.installing, 'activated');
++
++    // Verify that the script cache knows about the worker script again.
++    response = await chromeCaches.match(scriptURL.href);
++    is(response.url, scriptURL.href, 'worker script should be stored');
++  } catch (e) {
++    ok(false, e);
++  }
++  if (reg) {
++    await reg.unregister();
++  }
++
++  // If this test is run on windows and the process shuts down immediately after, then
++  // we may fail to remove some of the Cache API body files.  This is because the GC
++  // runs late causing Cache API to cleanup after shutdown begins.  It seems something
++  // during shutdown scans these files and conflicts with removing the file on windows.
++  //
++  // To avoid this we perform an explict GC here to ensure that Cache API can cleanup
++  // earlier.
++  await new Promise(resolve => SpecialPowers.exactGC(resolve));
++
++  SimpleTest.finish();
++}
++
++SimpleTest.waitForExplicitFinish();
++SpecialPowers.pushPrefEnv({"set": [
++  // standard prefs
++  ["dom.serviceWorkers.exemptFromPerDomainMax", true],
++  ["dom.serviceWorkers.enabled", true],
++  ["dom.serviceWorkers.testing.enabled", true],
++  ["dom.caches.enabled", true],
++
++  // immediately kill the service worker thread when idle
++  ["dom.serviceWorkers.idle_timeout", 0],
++
++]}, runTest);
++</script>
++</pre>
++</body>
++</html>
+diff --git a/dom/workers/test/serviceworkers/update_worker.sjs b/dom/workers/test/serviceworkers/update_worker.sjs
+new file mode 100644
+--- /dev/null
++++ b/dom/workers/test/serviceworkers/update_worker.sjs
+@@ -0,0 +1,13 @@
++/* 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/. */
++"use strict";
++
++function handleRequest(request, response) {
++  // This header is necessary for making this script able to be loaded.
++  response.setHeader("Content-Type", "application/javascript");
++
++  var body = '/* ' + Date.now() + ' */';
++  response.write(body);
++}
++

+ 421 - 0
mozilla-release/patches/1424571-59a1.patch

@@ -0,0 +1,421 @@
+# HG changeset patch
+# User Kyle Machulis <kyle@nonpolynomial.com>
+# Date 1512787093 28800
+# Node ID d47afd9b9df22cb39eac5a93e81691e81b2029f5
+# Parent  76526f2bae9115f29c98cf6fc6a7b8e65b0ccc45
+Bug 1424571 - Move all notification tests to dom/notification; r=baku
+
+Tests were split between dom/notification and
+dom/test/mochitest/notification. Moving them all to the same place.
+
+MozReview-Commit-ID: IP1YtIBmHcD
+
+diff --git a/.eslintignore b/.eslintignore
+--- a/.eslintignore
++++ b/.eslintignore
+@@ -235,16 +235,17 @@ dom/manifest/**
+ dom/mathml/**
+ dom/media/**
+ !dom/media/*.js*
+ dom/messagechannel/**
+ dom/network/**
+ dom/notification/Notification*.*
+ dom/notification/test/browser/**
+ dom/notification/test/unit/**
++dom/notification/test/mochitest/**
+ dom/offline/**
+ dom/payments/**
+ dom/performance/**
+ dom/permission/**
+ dom/plugins/test/mochitest/**
+ dom/plugins/test/unit/**
+ dom/power/**
+ dom/presentation/Presentation*.js
+diff --git a/dom/notification/moz.build b/dom/notification/moz.build
+--- a/dom/notification/moz.build
++++ b/dom/notification/moz.build
+@@ -32,11 +32,12 @@ FINAL_LIBRARY = 'xul'
+ LOCAL_INCLUDES += [
+     '/dom/base',
+     '/dom/ipc',
+     '/dom/workers',
+ ]
+ 
+ BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
+ XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
++MOCHITEST_MANIFESTS += ['test/mochitest/mochitest.ini']
+ 
+ if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
+     CXXFLAGS += ['-Wno-error=shadow']
+diff --git a/dom/tests/mochitest/notification/MockServices.js b/dom/notification/test/mochitest/MockServices.js
+rename from dom/tests/mochitest/notification/MockServices.js
+rename to dom/notification/test/mochitest/MockServices.js
+diff --git a/dom/tests/mochitest/notification/NotificationTest.js b/dom/notification/test/mochitest/NotificationTest.js
+rename from dom/tests/mochitest/notification/NotificationTest.js
+rename to dom/notification/test/mochitest/NotificationTest.js
+diff --git a/dom/notification/test/mochitest/mochitest.ini b/dom/notification/test/mochitest/mochitest.ini
+--- a/dom/notification/test/mochitest/mochitest.ini
++++ b/dom/notification/test/mochitest/mochitest.ini
+@@ -1,6 +1,12 @@
+ [DEFAULT]
+ 
+ support-files =
+  create_notification.html
++  MockServices.js
++  NotificationTest.js
+ 
++[test_notification_basics.html]
++[test_notification_storage.html]
++[test_bug931307.html]
++skip-if = (os == 'android') # Bug 1258975 on android.
+ [test_notification_tag.html]
+diff --git a/dom/tests/mochitest/notification/test_bug931307.html b/dom/notification/test/mochitest/test_bug931307.html
+rename from dom/tests/mochitest/notification/test_bug931307.html
+rename to dom/notification/test/mochitest/test_bug931307.html
+diff --git a/dom/tests/mochitest/notification/test_notification_basics.html b/dom/notification/test/mochitest/test_notification_basics.html
+rename from dom/tests/mochitest/notification/test_notification_basics.html
+rename to dom/notification/test/mochitest/test_notification_basics.html
+diff --git a/dom/tests/mochitest/notification/test_notification_storage.html b/dom/notification/test/mochitest/test_notification_storage.html
+rename from dom/tests/mochitest/notification/test_notification_storage.html
+rename to dom/notification/test/mochitest/test_notification_storage.html
+diff --git a/dom/tests/mochitest/notification/mochitest.ini b/dom/tests/mochitest/notification/mochitest.ini
+deleted file mode 100644
+--- a/dom/tests/mochitest/notification/mochitest.ini
++++ /dev/null
+@@ -1,10 +0,0 @@
+-[DEFAULT]
+-
+-support-files =
+-  MockServices.js
+-  NotificationTest.js
+-
+-[test_notification_basics.html]
+-[test_notification_storage.html]
+-[test_bug931307.html]
+-skip-if = (os == 'android') # Bug 1258975 on android.
+diff --git a/dom/tests/moz.build b/dom/tests/moz.build
+--- a/dom/tests/moz.build
++++ b/dom/tests/moz.build
+@@ -77,19 +77,16 @@ with Files("mochitest/general/**"):
+     BUG_COMPONENT = ("Core", "DOM")
+ 
+ with Files("mochitest/geolocation/**"):
+     BUG_COMPONENT = ("Core", "Geolocation")
+ 
+ with Files("mochitest/localstorage/**"):
+     BUG_COMPONENT = ("Core", "DOM")
+ 
+-with Files("mochitest/notification/**"):
+-    BUG_COMPONENT = ("Core", "DOM")
+-
+ with Files("mochitest/orientation/**"):
+     BUG_COMPONENT = ("Core", "DOM: Device Interfaces")
+ 
+ with Files("mochitest/orientation/*507902*"):
+     BUG_COMPONENT = ("Core", "Layout: Images")
+ 
+ with Files("mochitest/pointerlock/**"):
+     BUG_COMPONENT = ("Core", "DOM")
+@@ -161,17 +158,16 @@ MOCHITEST_MANIFESTS += [
+     'mochitest/dom-level1-core/mochitest.ini',
+     'mochitest/dom-level2-core/mochitest.ini',
+     'mochitest/dom-level2-html/mochitest.ini',
+     'mochitest/fetch/mochitest.ini',
+     'mochitest/gamepad/mochitest.ini',
+     'mochitest/general/mochitest.ini',
+     'mochitest/geolocation/mochitest.ini',
+     'mochitest/localstorage/mochitest.ini',
+-    'mochitest/notification/mochitest.ini',
+     'mochitest/orientation/mochitest.ini',
+     'mochitest/pointerlock/mochitest.ini',
+     'mochitest/script/mochitest.ini',
+     'mochitest/sessionstorage/mochitest.ini',
+     'mochitest/storageevent/mochitest.ini',
+     'mochitest/webcomponents/mochitest.ini',
+     'mochitest/whatwg/mochitest.ini',
+ ]
+diff --git a/dom/workers/test/mochitest.ini b/dom/workers/test/mochitest.ini
+--- a/dom/workers/test/mochitest.ini
++++ b/dom/workers/test/mochitest.ini
+@@ -90,18 +90,18 @@ support-files =
+   importScripts_3rdParty_worker.js
+   worker_bug1278777.js
+   worker_setTimeoutWith0.js
+   worker_bug1301094.js
+   script_createFile.js
+   worker_suspended.js
+   window_suspended.html
+   !/dom/base/test/file_bug945152.jar
+-  !/dom/tests/mochitest/notification/MockServices.js
+-  !/dom/tests/mochitest/notification/NotificationTest.js
++  !/dom/notification/test/mochitest/MockServices.js
++  !/dom/notification/test/mochitest/NotificationTest.js
+   !/dom/xhr/tests/relativeLoad_import.js
+   !/dom/xhr/tests/relativeLoad_worker.js
+   !/dom/xhr/tests/relativeLoad_worker2.js
+   !/dom/xhr/tests/subdir/relativeLoad_sub_worker.js
+   !/dom/xhr/tests/subdir/relativeLoad_sub_worker2.js
+   !/dom/xhr/tests/subdir/relativeLoad_sub_import.js
+ 
+ [test_404.html]
+diff --git a/dom/workers/test/serviceworkers/mochitest.ini b/dom/workers/test/serviceworkers/mochitest.ini
+--- a/dom/workers/test/serviceworkers/mochitest.ini
++++ b/dom/workers/test/serviceworkers/mochitest.ini
+@@ -207,18 +207,18 @@ support-files =
+   file_js_cache.html
+   file_js_cache_with_sri.html
+   file_js_cache.js
+   file_js_cache_save_after_load.html
+   file_js_cache_save_after_load.js
+   file_js_cache_syntax_error.html
+   file_js_cache_syntax_error.js
+   !/dom/security/test/cors/file_CrossSiteXHR_server.sjs
+-  !/dom/tests/mochitest/notification/MockServices.js
+-  !/dom/tests/mochitest/notification/NotificationTest.js
++  !/dom/notification/test/mochitest/MockServices.js
++  !/dom/notification/test/mochitest/NotificationTest.js
+   blocking_install_event_worker.js
+   sw_bad_mime_type.js
+   sw_bad_mime_type.js^headers^
+   error_reporting_helpers.js
+   fetch.js
+   hello.html
+   create_another_sharedWorker.html
+   sharedWorker_fetch.js
+diff --git a/dom/workers/test/serviceworkers/test_notification_constructor_error.html b/dom/workers/test/serviceworkers/test_notification_constructor_error.html
+--- a/dom/workers/test/serviceworkers/test_notification_constructor_error.html
++++ b/dom/workers/test/serviceworkers/test_notification_constructor_error.html
+@@ -2,18 +2,18 @@
+   Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/
+ -->
+ <!DOCTYPE HTML>
+ <html>
+ <head>
+   <title>Bug XXXXXXX - Check that Notification constructor throws in ServiceWorkerGlobalScope</title>
+   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+-  <script type="text/javascript" src="/tests/dom/tests/mochitest/notification/MockServices.js"></script>
+-  <script type="text/javascript" src="/tests/dom/tests/mochitest/notification/NotificationTest.js"></script>
++  <script type="text/javascript" src="/tests/dom/notification/test/mochitest/MockServices.js"></script>
++  <script type="text/javascript" src="/tests/dom/notification/test/mochitest/NotificationTest.js"></script>
+   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ </head>
+ <body>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test"></pre>
+ <script class="testbody" type="text/javascript">
+ 
+diff --git a/dom/workers/test/serviceworkers/test_notification_get.html b/dom/workers/test/serviceworkers/test_notification_get.html
+--- a/dom/workers/test/serviceworkers/test_notification_get.html
++++ b/dom/workers/test/serviceworkers/test_notification_get.html
+@@ -1,15 +1,15 @@
+ <!DOCTYPE HTML>
+ <html>
+ <head>
+   <title>ServiceWorkerRegistration.getNotifications() on main thread and worker thread.</title>
+   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+-  <script type="text/javascript" src="/tests/dom/tests/mochitest/notification/MockServices.js"></script>
+-  <script type="text/javascript" src="/tests/dom/tests/mochitest/notification/NotificationTest.js"></script>
++  <script type="text/javascript" src="/tests/dom/notification/test/mochitest/MockServices.js"></script>
++  <script type="text/javascript" src="/tests/dom/notification/test/mochitest/NotificationTest.js"></script>
+   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ </head>
+ <body>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test"></pre>
+ <script type="text/javascript">
+ 
+diff --git a/dom/workers/test/serviceworkers/test_notificationclick-otherwindow.html b/dom/workers/test/serviceworkers/test_notificationclick-otherwindow.html
+--- a/dom/workers/test/serviceworkers/test_notificationclick-otherwindow.html
++++ b/dom/workers/test/serviceworkers/test_notificationclick-otherwindow.html
+@@ -1,18 +1,18 @@
+ <!DOCTYPE HTML>
+ <html>
+ <!--
+ https://bugzilla.mozilla.org/show_bug.cgi?id=916893
+ -->
+ <head>
+   <title>Bug 1114554 - Test ServiceWorkerGlobalScope.notificationclick event.</title>
+   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+-  <script type="text/javascript" src="/tests/dom/tests/mochitest/notification/MockServices.js"></script>
+-  <script type="text/javascript" src="/tests/dom/tests/mochitest/notification/NotificationTest.js"></script>
++  <script type="text/javascript" src="/tests/dom/notification/test/mochitest/MockServices.js"></script>
++  <script type="text/javascript" src="/tests/dom/notification/test/mochitest/NotificationTest.js"></script>
+   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ </head>
+ <body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1114554">Bug 1114554</a>
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ </div>
+ <pre id="test">
+diff --git a/dom/workers/test/serviceworkers/test_notificationclick.html b/dom/workers/test/serviceworkers/test_notificationclick.html
+--- a/dom/workers/test/serviceworkers/test_notificationclick.html
++++ b/dom/workers/test/serviceworkers/test_notificationclick.html
+@@ -1,18 +1,18 @@
+ <!DOCTYPE HTML>
+ <html>
+ <!--
+ https://bugzilla.mozilla.org/show_bug.cgi?id=916893
+ -->
+ <head>
+   <title>Bug 1114554 - Test ServiceWorkerGlobalScope.notificationclick event.</title>
+   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+-  <script type="text/javascript" src="/tests/dom/tests/mochitest/notification/MockServices.js"></script>
+-  <script type="text/javascript" src="/tests/dom/tests/mochitest/notification/NotificationTest.js"></script>
++  <script type="text/javascript" src="/tests/dom/notification/test/mochitest/MockServices.js"></script>
++  <script type="text/javascript" src="/tests/dom/notification/test/mochitest/NotificationTest.js"></script>
+   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ </head>
+ <body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1114554">Bug 1114554</a>
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ </div>
+ <pre id="test">
+diff --git a/dom/workers/test/serviceworkers/test_notificationclick_focus.html b/dom/workers/test/serviceworkers/test_notificationclick_focus.html
+--- a/dom/workers/test/serviceworkers/test_notificationclick_focus.html
++++ b/dom/workers/test/serviceworkers/test_notificationclick_focus.html
+@@ -1,18 +1,18 @@
+ <!DOCTYPE HTML>
+ <html>
+ <!--
+ https://bugzilla.mozilla.org/show_bug.cgi?id=916893
+ -->
+ <head>
+   <title>Bug 1144660 - Test client.focus() permissions on notification click</title>
+   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+-  <script type="text/javascript" src="/tests/dom/tests/mochitest/notification/MockServices.js"></script>
+-  <script type="text/javascript" src="/tests/dom/tests/mochitest/notification/NotificationTest.js"></script>
++  <script type="text/javascript" src="/tests/dom/notification/test/mochitest/MockServices.js"></script>
++  <script type="text/javascript" src="/tests/dom/notification/test/mochitest/NotificationTest.js"></script>
+   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ </head>
+ <body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1114554">Bug 1114554</a>
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ </div>
+ <pre id="test">
+diff --git a/dom/workers/test/serviceworkers/test_notificationclose.html b/dom/workers/test/serviceworkers/test_notificationclose.html
+--- a/dom/workers/test/serviceworkers/test_notificationclose.html
++++ b/dom/workers/test/serviceworkers/test_notificationclose.html
+@@ -1,18 +1,18 @@
+ <!DOCTYPE HTML>
+ <html>
+ <!--
+ https://bugzilla.mozilla.org/show_bug.cgi?id=1265841
+ -->
+ <head>
+   <title>Bug 1265841 - Test ServiceWorkerGlobalScope.notificationclose event.</title>
+   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+-  <script type="text/javascript" src="/tests/dom/tests/mochitest/notification/MockServices.js"></script>
+-  <script type="text/javascript" src="/tests/dom/tests/mochitest/notification/NotificationTest.js"></script>
++  <script type="text/javascript" src="/tests/dom/notification/test/mochitest/MockServices.js"></script>
++  <script type="text/javascript" src="/tests/dom/notification/test/mochitest/NotificationTest.js"></script>
+   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ </head>
+ <body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1265841">Bug 1265841</a>
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ </div>
+ <pre id="test">
+diff --git a/dom/workers/test/serviceworkers/test_openWindow.html b/dom/workers/test/serviceworkers/test_openWindow.html
+--- a/dom/workers/test/serviceworkers/test_openWindow.html
++++ b/dom/workers/test/serviceworkers/test_openWindow.html
+@@ -1,18 +1,18 @@
+ <!DOCTYPE HTML>
+ <html>
+ <!--
+ https://bugzilla.mozilla.org/show_bug.cgi?id=1172870
+ -->
+ <head>
+   <title>Bug 1172870 - Test clients.openWindow</title>
+   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+-  <script type="text/javascript" src="/tests/dom/tests/mochitest/notification/MockServices.js"></script>
+-  <script type="text/javascript" src="/tests/dom/tests/mochitest/notification/NotificationTest.js"></script>
++  <script type="text/javascript" src="/tests/dom/notification/test/mochitest/MockServices.js"></script>
++  <script type="text/javascript" src="/tests/dom/notification/test/mochitest/NotificationTest.js"></script>
+   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ </head>
+ <body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1172870">Bug 1172870</a>
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ </div>
+ <pre id="test">
+diff --git a/dom/workers/test/test_notification.html b/dom/workers/test/test_notification.html
+--- a/dom/workers/test/test_notification.html
++++ b/dom/workers/test/test_notification.html
+@@ -1,18 +1,18 @@
+ <!DOCTYPE HTML>
+ <html>
+ <!--
+ https://bugzilla.mozilla.org/show_bug.cgi?id=916893
+ -->
+ <head>
+   <title>Bug 916893</title>
+   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+-  <script type="text/javascript" src="/tests/dom/tests/mochitest/notification/MockServices.js"></script>
+-  <script type="text/javascript" src="/tests/dom/tests/mochitest/notification/NotificationTest.js"></script>
++  <script type="text/javascript" src="/tests/dom/notification/test/mochitest/MockServices.js"></script>
++  <script type="text/javascript" src="/tests/dom/notification/test/mochitest/NotificationTest.js"></script>
+   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ </head>
+ <body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=916893">Bug 916893</a>
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ </div>
+ <pre id="test">
+diff --git a/dom/workers/test/test_notification_child.html b/dom/workers/test/test_notification_child.html
+--- a/dom/workers/test/test_notification_child.html
++++ b/dom/workers/test/test_notification_child.html
+@@ -1,18 +1,18 @@
+ <!DOCTYPE HTML>
+ <html>
+ <!--
+ https://bugzilla.mozilla.org/show_bug.cgi?id=916893
+ -->
+ <head>
+   <title>Bug 916893 - Test Notifications in child workers.</title>
+   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+-  <script type="text/javascript" src="/tests/dom/tests/mochitest/notification/MockServices.js"></script>
+-  <script type="text/javascript" src="/tests/dom/tests/mochitest/notification/NotificationTest.js"></script>
++  <script type="text/javascript" src="/tests/dom/notification/test/mochitest/MockServices.js"></script>
++  <script type="text/javascript" src="/tests/dom/notification/test/mochitest/NotificationTest.js"></script>
+   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ </head>
+ <body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=916893">Bug 916893</a>
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ </div>
+ <pre id="test">
+diff --git a/dom/workers/test/test_notification_permission.html b/dom/workers/test/test_notification_permission.html
+--- a/dom/workers/test/test_notification_permission.html
++++ b/dom/workers/test/test_notification_permission.html
+@@ -1,18 +1,18 @@
+ <!DOCTYPE HTML>
+ <html>
+ <!--
+ https://bugzilla.mozilla.org/show_bug.cgi?id=916893
+ -->
+ <head>
+   <title>Bug 916893 - Make sure error is fired on Notification if permission is denied.</title>
+   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+-  <script type="text/javascript" src="/tests/dom/tests/mochitest/notification/MockServices.js"></script>
+-  <script type="text/javascript" src="/tests/dom/tests/mochitest/notification/NotificationTest.js"></script>
++  <script type="text/javascript" src="/tests/dom/notification/test/mochitest/MockServices.js"></script>
++  <script type="text/javascript" src="/tests/dom/notification/test/mochitest/NotificationTest.js"></script>
+   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ </head>
+ <body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=916893">Bug 916893</a>
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ </div>
+ <pre id="test">

+ 61 - 0
mozilla-release/patches/1431814-1no2-60a1.patch

@@ -0,0 +1,61 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1516728888 18000
+# Node ID 28e035f10d0a01b7a3838b765c42a28459003cf2
+# Parent  4d9fbacee92621af993dd778a10d49bb6913beb6
+Bug 1431814 P1 Allow the controller to be inheritted for other local URLs like blob: and data:. r=asuth
+
+diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
+--- a/dom/base/nsGlobalWindow.cpp
++++ b/dom/base/nsGlobalWindow.cpp
+@@ -3447,36 +3447,45 @@ nsGlobalWindow::InnerSetNewDocument(JSCo
+ 
+ nsresult
+ nsGlobalWindow::EnsureClientSource()
+ {
+   MOZ_DIAGNOSTIC_ASSERT(mDoc);
+ 
+   bool newClientSource = false;
+ 
+-  // Get the load info for the document if we performed a load.  Be careful
+-  // not to look at about:blank or about:srcdoc loads, though. They will have
+-  // a channel and loadinfo, but their loadinfo will never be controlled.  This
+-  // would in turn inadvertantly trigger the logic below to clear the inherited
+-  // controller.
++  // Get the load info for the document if we performed a load.  Be careful not
++  // to look at local URLs, though. Local URLs are those that have a scheme of:
++  //  * about:
++  //  * data:
++  //  * blob:
++  // We also do an additional check here so that we only treat about:blank
++  // and about:srcdoc as local URLs.  Other internal firefox about: URLs should
++  // not be treated this way.
+   nsCOMPtr<nsILoadInfo> loadInfo;
+   nsCOMPtr<nsIChannel> channel = mDoc->GetChannel();
+   if (channel) {
+     nsCOMPtr<nsIURI> uri;
+     Unused << channel->GetURI(getter_AddRefs(uri));
+ 
+     bool ignoreLoadInfo = false;
+ 
+     // Note, this is mostly copied from NS_IsAboutBlank().  Its duplicated
+     // here so we can efficiently check about:srcdoc as well.
+     bool isAbout = false;
+     if (NS_SUCCEEDED(uri->SchemeIs("about", &isAbout)) && isAbout) {
+       nsCString spec = uri->GetSpecOrDefault();
+       ignoreLoadInfo = spec.EqualsLiteral("about:blank") ||
+                        spec.EqualsLiteral("about:srcdoc");
++    } else {
++      // Its not an about: URL, so now check for our other URL types.
++      bool isData = false;
++      bool isBlob = false;
++      ignoreLoadInfo = (NS_SUCCEEDED(uri->SchemeIs("data", &isData)) && isData) ||
++                       (NS_SUCCEEDED(uri->SchemeIs("blob", &isBlob)) && isBlob);
+     }
+ 
+     if (!ignoreLoadInfo) {
+       loadInfo = channel->GetLoadInfo();
+     }
+   }
+ 
+   // Take the initial client source from the docshell immediately.  Even if we

+ 171 - 0
mozilla-release/patches/1432640-60a1.patch

@@ -0,0 +1,171 @@
+# HG changeset patch
+# User Ben Kelly <ben@wanderview.com>
+# Date 1516832638 28800
+# Node ID bbac8c59d58c50fec337b4832ad8ab28bc507bee
+# Parent  6343777ee5014f05776112ff01e6a70c7a75ce6e
+Bug 1432640 Remove ServiceWorkerManager::GetDocumentController() and make ServiceWorkerContainer::GetController() look up the reg instead. r=asuth
+
+diff --git a/dom/interfaces/base/nsIServiceWorkerManager.idl b/dom/interfaces/base/nsIServiceWorkerManager.idl
+--- a/dom/interfaces/base/nsIServiceWorkerManager.idl
++++ b/dom/interfaces/base/nsIServiceWorkerManager.idl
+@@ -162,22 +162,16 @@ interface nsIServiceWorkerManager : nsIS
+    * a valid entry that window is allowed to load, otherwise this will return nullptr.
+    * These are only meant to be called from ServiceWorkerRegistration instances.
+    */
+   [noscript] nsISupports GetInstalling(in nsPIDOMWindowInner aWindow, in DOMString aScope);
+   [noscript] nsISupports GetWaiting(in nsPIDOMWindowInner aWindow, in DOMString aScope);
+   [noscript] nsISupports GetActive(in nsPIDOMWindowInner aWindow, in DOMString aScope);
+ 
+   /*
+-   * Returns a ServiceWorker object representing the active worker controlling this
+-   * window.
+-   */
+-  [noscript] nsISupports GetDocumentController(in nsPIDOMWindowInner aWindow);
+-
+-  /*
+    * Clears ServiceWorker registrations from memory and disk for the specified
+    * host.
+    * - All ServiceWorker instances change their state to redundant.
+    * - Existing ServiceWorker instances handling fetches will keep running.
+    * - All documents will immediately stop being controlled.
+    * - Unregister jobs will be queued for all registrations.
+    *   This eventually results in the registration being deleted from disk too.
+    */
+diff --git a/dom/workers/ServiceWorkerContainer.cpp b/dom/workers/ServiceWorkerContainer.cpp
+--- a/dom/workers/ServiceWorkerContainer.cpp
++++ b/dom/workers/ServiceWorkerContainer.cpp
+@@ -212,33 +212,51 @@ ServiceWorkerContainer::Register(const n
+   MOZ_ASSERT(ret);
+   return ret.forget();
+ }
+ 
+ already_AddRefed<workers::ServiceWorker>
+ ServiceWorkerContainer::GetController()
+ {
+   if (!mControllerWorker) {
+-    nsCOMPtr<nsIServiceWorkerManager> swm = mozilla::services::GetServiceWorkerManager();
++    // If we don't have a controller reference cached, then we need to
++    // check if we should create one.  We try to do this in a thread-agnostic
++    // way here to help support workers in the future.  There are still
++    // some main thread calls for now, though.
++
++    nsIGlobalObject* owner = GetOwnerGlobal();
++    NS_ENSURE_TRUE(owner, nullptr);
++
++    Maybe<ServiceWorkerDescriptor> controller(owner->GetController());
++    if (controller.isNothing()) {
++      return nullptr;
++    }
++
++    RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
+     if (!swm) {
+       return nullptr;
+     }
+ 
+-    // TODO: What should we do here if the ServiceWorker script fails to load?
+-    //       In theory the DOM ServiceWorker object can exist without the worker
+-    //       thread running, but it seems our design does not expect that.
+-    nsCOMPtr<nsISupports> serviceWorker;
+-    nsresult rv = swm->GetDocumentController(GetOwner(),
+-                                             getter_AddRefs(serviceWorker));
+-    if (NS_WARN_IF(NS_FAILED(rv))) {
+-      return nullptr;
+-    }
++    // This is a main thread only call.  We will need to replace it with
++    // something for worker threads.
++    RefPtr<ServiceWorkerRegistrationInfo> reg =
++      swm->GetRegistration(controller.ref().PrincipalInfo(),
++                           controller.ref().Scope());
++    NS_ENSURE_TRUE(reg, nullptr);
+ 
+-    mControllerWorker =
+-      static_cast<workers::ServiceWorker*>(serviceWorker.get());
++    ServiceWorkerInfo* info = reg->GetActive();
++    NS_ENSURE_TRUE(info, nullptr);
++
++    nsCOMPtr<nsPIDOMWindowInner> inner = do_QueryInterface(owner);
++    NS_ENSURE_TRUE(inner, nullptr);
++
++    // Right now we only know how to create ServiceWorker DOM objects on
++    // the main thread with a window.  In the future this should operate
++    // on only nsIGlobalObject somehow.
++    mControllerWorker = info->GetOrCreateInstance(inner);
+   }
+ 
+   RefPtr<workers::ServiceWorker> ref = mControllerWorker;
+   return ref.forget();
+ }
+ 
+ already_AddRefed<Promise>
+ ServiceWorkerContainer::GetRegistrations(ErrorResult& aRv)
+diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerManager.cpp
+--- a/dom/workers/ServiceWorkerManager.cpp
++++ b/dom/workers/ServiceWorkerManager.cpp
+@@ -2622,67 +2622,16 @@ ServiceWorkerManager::GetClientRegistrat
+     return NS_ERROR_NOT_AVAILABLE;
+   }
+ 
+   RefPtr<ServiceWorkerRegistrationInfo> ref = data->mRegistrationInfo;
+   ref.forget(aRegistrationInfo);
+   return NS_OK;
+ }
+ 
+-/*
+- * The .controller is for the registration associated with the document when
+- * the document was loaded.
+- */
+-NS_IMETHODIMP
+-ServiceWorkerManager::GetDocumentController(nsPIDOMWindowInner* aWindow,
+-                                            nsISupports** aServiceWorker)
+-{
+-  if (NS_WARN_IF(!aWindow)) {
+-    return NS_ERROR_DOM_INVALID_STATE_ERR;
+-  }
+-
+-  Maybe<ServiceWorkerDescriptor> controller = aWindow->GetController();
+-  if (controller.isNothing()) {
+-    return NS_ERROR_DOM_INVALID_STATE_ERR;
+-  }
+-
+-  nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
+-  if (NS_WARN_IF(!doc)) {
+-    return NS_ERROR_DOM_INVALID_STATE_ERR;
+-  }
+-
+-  nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
+-  if (NS_WARN_IF(!principal)) {
+-    return NS_ERROR_DOM_INVALID_STATE_ERR;
+-  }
+-
+-  nsAutoCString scopeKey;
+-  nsresult rv = PrincipalToScopeKey(principal, scopeKey);
+-  if (NS_WARN_IF(NS_FAILED(rv))) {
+-    return rv;
+-  }
+-
+-  RefPtr<ServiceWorkerRegistrationInfo> registration =
+-    GetRegistration(scopeKey, controller.ref().Scope());
+-  if (NS_WARN_IF(!registration)) {
+-    return NS_ERROR_DOM_INVALID_STATE_ERR;
+-  }
+-
+-  RefPtr<ServiceWorkerInfo> active = registration->GetActive();
+-  if (NS_WARN_IF(!active) ||
+-      NS_WARN_IF(active->Descriptor().Id() != controller.ref().Id())) {
+-    return NS_ERROR_DOM_INVALID_STATE_ERR;
+-  }
+-
+-  RefPtr<ServiceWorker> serviceWorker = active->GetOrCreateInstance(aWindow);
+-  serviceWorker.forget(aServiceWorker);
+-
+-  return NS_OK;
+-}
+-
+ NS_IMETHODIMP
+ ServiceWorkerManager::GetInstalling(nsPIDOMWindowInner* aWindow,
+                                     const nsAString& aScope,
+                                     nsISupports** aServiceWorker)
+ {
+   return GetServiceWorkerForScope(aWindow, aScope,
+                                   WhichServiceWorker::INSTALLING_WORKER,
+                                   aServiceWorker);

+ 3 - 3
mozilla-release/patches/1440511-01-60a1.patch

@@ -3,7 +3,7 @@
 # Date 1519335338 18000
 #      Thu Feb 22 16:35:38 2018 -0500
 # Node ID 1517d3c496813c103e193f023da36b3b2b150671
-# Parent  e6a8080de0d6739088de39a3cd8d1f23885410a2
+# Parent  1b8f809b268d12a0fda5fb7f6a179672d941d7cc
 Bug 1440511 - Part 1: Correctly namespace nsHttpResponseHead in NeckoChannelParams.ipdlh, r=froydnj
 
 MozReview-Commit-ID: DVkTwAmqmkc
@@ -11,8 +11,8 @@ MozReview-Commit-ID: DVkTwAmqmkc
 diff --git a/netwerk/ipc/NeckoChannelParams.ipdlh b/netwerk/ipc/NeckoChannelParams.ipdlh
 --- a/netwerk/ipc/NeckoChannelParams.ipdlh
 +++ b/netwerk/ipc/NeckoChannelParams.ipdlh
-@@ -12,17 +12,17 @@ include BlobTypes;
- include URIParams;
+@@ -14,17 +14,17 @@ include URIParams;
+ include IPCServiceWorkerDescriptor;
  include IPCStream;
  include PBackgroundSharedTypes;
  

+ 78 - 40
mozilla-release/patches/1465585-3-std-62a1.patch

@@ -2,7 +2,7 @@
 # User Emilio Cobos Alvarez <emilio@crisal.io>
 # Date 1527707735 -7200
 # Node ID b54db66223586b4e04f5cb926fccdacf8a176b91
-# Parent  ca3847b26a424b86d6b8023b4041f2a321d71efd
+# Parent  311f8d558c72b391fc8107abe0b888ea1a3b99ee
 Bug 1465585: Switch from mozilla::Move to std::move. r=froydnj
 
 This was done automatically replacing:
@@ -1280,7 +1280,7 @@ diff --git a/devtools/shared/heapsnapshot/tests/gtest/DevTools.h b/devtools/shar
 diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
 --- a/docshell/base/nsDocShell.cpp
 +++ b/docshell/base/nsDocShell.cpp
-@@ -2867,17 +2867,17 @@ nsDocShell::MaybeCreateInitialClientSour
+@@ -2870,17 +2870,17 @@ nsDocShell::MaybeCreateInitialClientSour
  }
  
  Maybe<ClientInfo>
@@ -1299,7 +1299,7 @@ diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
  
    if (!doc || !doc->IsInitialDocument()) {
      return Maybe<ClientInfo>();
-@@ -5065,17 +5065,17 @@ nsDocShell::Reload(uint32_t aReloadFlags
+@@ -5068,17 +5068,17 @@ nsDocShell::Reload(uint32_t aReloadFlags
      // Stack variables to ensure changes to the member variables don't affect to
      // the call.
      nsCOMPtr<nsIURI> currentURI = mCurrentURI;
@@ -1318,7 +1318,7 @@ diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
                        referrerURI,
                        referrerPolicy,
                        triggeringPrincipal,
-@@ -11174,17 +11174,17 @@ nsDocShell::DoChannelLoad(nsIChannel* aC
+@@ -11182,17 +11182,17 @@ nsDocShell::DoChannelLoad(nsIChannel* aC
  
    // Since we are loading a document we need to make sure the proper reserved
    // and initial client data is stored on the nsILoadInfo.  The
@@ -1337,7 +1337,7 @@ diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
    NS_ENSURE_SUCCESS(rv, rv);
  
    // We're about to load a new page and it may take time before necko
-@@ -12360,17 +12360,17 @@ nsDocShell::LoadHistoryEntry(nsISHEntry*
+@@ -12368,17 +12368,17 @@ nsDocShell::LoadHistoryEntry(nsISHEntry*
      return NS_ERROR_FAILURE;
    }
  
@@ -1356,7 +1356,7 @@ diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
                      referrerURI,
                      referrerPolicy,
                      triggeringPrincipal,
-@@ -14158,17 +14158,17 @@ nsDocShell::NotifyJSRunToCompletionStart
+@@ -14166,17 +14166,17 @@ nsDocShell::NotifyJSRunToCompletionStart
                                           const uint32_t aLineNumber,
                                           JS::Handle<JS::Value> aAsyncStack,
                                           const char* aAsyncCause)
@@ -1375,7 +1375,7 @@ diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
  
    mJSRunToCompletionDepth++;
  }
-@@ -14312,17 +14312,17 @@ nsDocShell::InFrameSwap()
+@@ -14254,17 +14254,17 @@ nsDocShell::InFrameSwap()
      shell = shell->GetParentDocshell();
    } while (shell);
    return false;
@@ -3426,7 +3426,7 @@ diff --git a/dom/base/nsFrameLoader.cpp b/dom/base/nsFrameLoader.cpp
 diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
 --- a/dom/base/nsGlobalWindow.cpp
 +++ b/dom/base/nsGlobalWindow.cpp
-@@ -3490,29 +3490,29 @@ nsGlobalWindow::EnsureClientSource()
+@@ -3499,29 +3499,29 @@ nsGlobalWindow::EnsureClientSource()
    // Try to get the reserved client from the LoadInfo.  A Client is
    // reserved at the start of the channel load if there is not an
    // initial about:blank document that will be reused.  It is also
@@ -3458,7 +3458,7 @@ diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
    // Verify the final ClientSource principal matches the final document
    // principal.  The ClientChannelHelper handles things like network
    // redirects, but there are other ways the document principal can change.
-@@ -4479,29 +4479,29 @@ void
+@@ -4488,29 +4488,29 @@ void
  nsPIDOMWindowInner::SyncStateFromParentWindow()
  {
    nsGlobalWindow::Cast(this)->SyncStateFromParentWindow();
@@ -3491,7 +3491,7 @@ diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
    nsGlobalWindow::Cast(this)->NoteCalledRegisterForServiceWorkerScope(aScope);
  }
  
-@@ -11949,17 +11949,17 @@ nsGlobalWindow::ShowSlowScriptDialog(con
+@@ -11958,17 +11958,17 @@ nsGlobalWindow::ShowSlowScriptDialog(con
    auto getString = [&] (const char* name,
                          nsContentUtils::PropertiesFile propFile = nsContentUtils::eDOM_PROPERTIES) {
      nsAutoString result;
@@ -3510,7 +3510,7 @@ diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
    // Get localizable strings
  
    nsAutoString title, checkboxMsg, debugButton, msg;
-@@ -12803,43 +12803,43 @@ nsGlobalWindow::CallOnChildren(Method aM
+@@ -12812,43 +12812,43 @@ nsGlobalWindow::CallOnChildren(Method aM
  Maybe<ClientInfo>
  nsGlobalWindow::GetClientInfo() const
  {
@@ -3557,7 +3557,7 @@ diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
    FORWARD_TO_INNER(FireDelayedDOMEvents, (), NS_ERROR_UNEXPECTED);
  
    if (mApplicationCache) {
-@@ -15176,19 +15176,19 @@ nsPIDOMWindow<T>::GetDocGroup() const
+@@ -15185,19 +15185,19 @@ nsPIDOMWindow<T>::GetDocGroup() const
  }
  
  nsresult
@@ -17792,7 +17792,7 @@ diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp
 diff --git a/dom/workers/ScriptLoader.cpp b/dom/workers/ScriptLoader.cpp
 --- a/dom/workers/ScriptLoader.cpp
 +++ b/dom/workers/ScriptLoader.cpp
-@@ -718,17 +718,17 @@ private:
+@@ -739,17 +739,17 @@ private:
  
      UniquePtr<PrincipalInfo> principalInfo(new PrincipalInfo());
      rv = PrincipalToPrincipalInfo(channelPrincipal, principalInfo.get());
@@ -17811,7 +17811,7 @@ diff --git a/dom/workers/ScriptLoader.cpp b/dom/workers/ScriptLoader.cpp
      mozilla::dom::RequestOrUSVString request;
  
      MOZ_ASSERT(!loadInfo.mFullURL.IsEmpty());
-@@ -991,17 +991,17 @@ private:
+@@ -1014,17 +1014,17 @@ private:
      rv = NS_NewStreamLoader(getter_AddRefs(loader), listener);
      if (NS_WARN_IF(NS_FAILED(rv))) {
        return rv;
@@ -17830,7 +17830,7 @@ diff --git a/dom/workers/ScriptLoader.cpp b/dom/workers/ScriptLoader.cpp
      }
  
      if (loadInfo.mCacheStatus != ScriptLoadInfo::ToBeCached) {
-@@ -1748,17 +1748,17 @@ CacheScriptLoader::ResolvedCallback(JSCo
+@@ -1783,17 +1783,17 @@ CacheScriptLoader::ResolvedCallback(JSCo
    const UniquePtr<PrincipalInfo>& pInfo = response->GetPrincipalInfo();
    if (pInfo) {
      mPrincipalInfo = mozilla::MakeUnique<PrincipalInfo>(*pInfo);
@@ -17849,7 +17849,7 @@ diff --git a/dom/workers/ScriptLoader.cpp b/dom/workers/ScriptLoader.cpp
    MOZ_ASSERT(!mPump);
    rv = NS_NewInputStreamPump(getter_AddRefs(mPump),
                               inputStream.forget(),
-@@ -1815,17 +1815,17 @@ CacheScriptLoader::OnStreamComplete(nsIS
+@@ -1850,17 +1850,17 @@ CacheScriptLoader::OnStreamComplete(nsIS
      return NS_OK;
    }
  
@@ -18120,11 +18120,11 @@ diff --git a/dom/workers/ServiceWorkerScriptCache.cpp b/dom/workers/ServiceWorke
      return NS_SUCCEEDED(mNetworkResult);
    }
  
-@@ -586,17 +586,17 @@ private:
- 
+@@ -609,17 +609,17 @@ private:
      RefPtr<InternalResponse> ir =
        new InternalResponse(200, NS_LITERAL_CSTRING("OK"));
      ir->SetBody(body, aCN->Buffer().Length());
+     ir->SetURLList(aCN->URLList());
  
      ir->InitChannelInfo(aCN->GetChannelInfo());
      UniquePtr<PrincipalInfo> principalInfo = aCN->TakePrincipalInfo();
@@ -18139,7 +18139,7 @@ diff --git a/dom/workers/ServiceWorkerScriptCache.cpp b/dom/workers/ServiceWorke
      RefPtr<Response> response =
        new Response(aCache->GetGlobalObject(), ir, nullptr);
  
-@@ -889,17 +889,17 @@ CompareNetwork::SetPrincipalInfo(nsIChan
+@@ -913,17 +913,17 @@ CompareNetwork::SetPrincipalInfo(nsIChan
  
    UniquePtr<PrincipalInfo> principalInfo = MakeUnique<PrincipalInfo>();
    rv = PrincipalToPrincipalInfo(channelPrincipal, principalInfo.get());
@@ -18161,7 +18161,7 @@ diff --git a/dom/workers/ServiceWorkerScriptCache.cpp b/dom/workers/ServiceWorke
 diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
 --- a/dom/workers/WorkerPrivate.cpp
 +++ b/dom/workers/WorkerPrivate.cpp
-@@ -4701,17 +4701,17 @@ WorkerPrivate::Constructor(JSContext* aC
+@@ -4702,17 +4702,17 @@ WorkerPrivate::Constructor(JSContext* aC
    // WorkerThreadPrimaryRunnable::Run for workers just before running worker
    // code), so this is never SpiderMonkey's builtin default locale.
    JS::UniqueChars defaultLocale = JS_GetDefaultLocale(aCx);
@@ -18180,7 +18180,7 @@ diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
  
    worker->EnableDebugger();
  
-@@ -5252,17 +5252,17 @@ WorkerPrivate::DispatchToMainThread(nsIR
+@@ -5259,17 +5259,17 @@ WorkerPrivate::DispatchToMainThread(nsIR
    nsCOMPtr<nsIRunnable> r = aRunnable;
    return DispatchToMainThread(r.forget(), aFlags);
  }
@@ -18199,7 +18199,7 @@ diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
    return mWorkerControlEventTarget;
  }
  
-@@ -5340,17 +5340,17 @@ WorkerPrivate::GetClientInfo() const
+@@ -5347,17 +5347,17 @@ WorkerPrivate::GetClientInfo() const
  
  const ClientState
  WorkerPrivate::GetClientState() const
@@ -18218,7 +18218,7 @@ diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
    AssertIsOnWorkerThread();
    MOZ_DIAGNOSTIC_ASSERT(mClientSource);
    return mClientSource->GetController();
-@@ -7111,17 +7111,17 @@ WorkerPrivate::GetOrCreateGlobalScope(JS
+@@ -7118,17 +7118,17 @@ WorkerPrivate::GetOrCreateGlobalScope(JS
  
      JS::Rooted<JSObject*> global(aCx);
      NS_ENSURE_TRUE(globalScope->WrapGlobalObject(aCx, &global), nullptr);
@@ -18237,7 +18237,7 @@ diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
  
      JS_FireOnNewGlobalObject(aCx, global);
    }
-@@ -7142,17 +7142,17 @@ WorkerPrivate::CreateDebuggerGlobalScope
+@@ -7149,17 +7149,17 @@ WorkerPrivate::CreateDebuggerGlobalScope
    JS::Rooted<JSObject*> global(aCx);
    NS_ENSURE_TRUE(globalScope->WrapGlobalObject(aCx, &global), nullptr);
  
@@ -18278,7 +18278,7 @@ diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h
    nsresult
    DispatchDebuggerRunnable(already_AddRefed<WorkerRunnable> aDebuggerRunnable);
  
-@@ -1176,17 +1176,17 @@ public:
+@@ -1182,17 +1182,17 @@ public:
    }
  
    JS::UniqueChars
@@ -18498,7 +18498,7 @@ diff --git a/dom/xbl/nsXBLWindowKeyHandler.cpp b/dom/xbl/nsXBLWindowKeyHandler.c
 diff --git a/dom/xhr/XMLHttpRequestMainThread.cpp b/dom/xhr/XMLHttpRequestMainThread.cpp
 --- a/dom/xhr/XMLHttpRequestMainThread.cpp
 +++ b/dom/xhr/XMLHttpRequestMainThread.cpp
-@@ -2549,17 +2549,17 @@ XMLHttpRequestMainThread::MaybeLowerChan
+@@ -2568,17 +2568,17 @@ XMLHttpRequestMainThread::MaybeLowerChan
  }
  
  nsresult
@@ -18517,7 +18517,7 @@ diff --git a/dom/xhr/XMLHttpRequestMainThread.cpp b/dom/xhr/XMLHttpRequestMainTh
    if (HasListenersFor(nsGkAtoms::onprogress) ||
        (mUpload && mUpload->HasListenersFor(nsGkAtoms::onprogress))) {
      nsLoadFlags loadFlags;
-@@ -3249,20 +3249,20 @@ XMLHttpRequestMainThread::SetTimerEventT
+@@ -3268,20 +3268,20 @@ XMLHttpRequestMainThread::SetTimerEventT
  
  nsresult
  XMLHttpRequestMainThread::DispatchToMainThread(already_AddRefed<nsIRunnable> aRunnable)
@@ -28626,7 +28626,7 @@ diff --git a/ipc/glue/BackgroundImpl.cpp b/ipc/glue/BackgroundImpl.cpp
 diff --git a/ipc/glue/BackgroundUtils.cpp b/ipc/glue/BackgroundUtils.cpp
 --- a/ipc/glue/BackgroundUtils.cpp
 +++ b/ipc/glue/BackgroundUtils.cpp
-@@ -201,17 +201,17 @@ PrincipalToPrincipalInfo(nsIPrincipal* a
+@@ -203,17 +203,17 @@ PrincipalToPrincipalInfo(nsIPrincipal* a
          return rv;
        }
        // append that spec to the whitelist
@@ -28645,12 +28645,12 @@ diff --git a/ipc/glue/BackgroundUtils.cpp b/ipc/glue/BackgroundUtils.cpp
    nsCOMPtr<nsIURI> uri;
    rv = aPrincipal->GetURI(getter_AddRefs(uri));
    if (NS_WARN_IF(NS_FAILED(rv))) {
-@@ -493,17 +493,17 @@ LoadInfoArgsToLoadInfo(const OptionalLoa
-                           loadInfoArgs.topOuterWindowID(),
+@@ -558,17 +558,17 @@ LoadInfoArgsToLoadInfo(const OptionalLoa
                            loadInfoArgs.frameOuterWindowID(),
                            loadInfoArgs.enforceSecurity(),
                            loadInfoArgs.initialSecurityCheckDone(),
                            loadInfoArgs.isInThirdPartyContext(),
+                           loadInfoArgs.isDocshellReload(),
                            loadInfoArgs.originAttributes(),
                            redirectChainIncludingInternalRedirects,
                            redirectChain,
@@ -46804,14 +46804,14 @@ diff --git a/mozglue/misc/interceptor/VMSharingPolicies.h b/mozglue/misc/interce
 diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp
 --- a/netwerk/base/LoadInfo.cpp
 +++ b/netwerk/base/LoadInfo.cpp
-@@ -388,17 +388,17 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadin
-   , mOuterWindowID(aOuterWindowID)
+@@ -421,17 +421,17 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadin
    , mParentOuterWindowID(aParentOuterWindowID)
    , mTopOuterWindowID(aTopOuterWindowID)
    , mFrameOuterWindowID(aFrameOuterWindowID)
    , mEnforceSecurity(aEnforceSecurity)
    , mInitialSecurityCheckDone(aInitialSecurityCheckDone)
    , mIsThirdPartyContext(aIsThirdPartyContext)
+   , mIsDocshellReload(aIsDocshellReload)
    , mOriginAttributes(aOriginAttributes)
 -  , mAncestorPrincipals(Move(aAncestorPrincipals))
 +  , mAncestorPrincipals(std::move(aAncestorPrincipals))
@@ -46823,7 +46823,7 @@ diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp
    , mServiceWorkerTaintingSynthesized(aServiceWorkerTaintingSynthesized)
  {
    // Only top level TYPE_DOCUMENT loads can have a null loadingPrincipal
-@@ -1137,29 +1137,29 @@ LoadInfo::GetClientInfo()
+@@ -1184,29 +1184,29 @@ LoadInfo::GetClientInfo()
  {
    return mClientInfo;
  }
@@ -47035,7 +47035,7 @@ diff --git a/netwerk/base/nsMIMEInputStream.cpp b/netwerk/base/nsMIMEInputStream
 diff --git a/netwerk/base/nsNetUtil.cpp b/netwerk/base/nsNetUtil.cpp
 --- a/netwerk/base/nsNetUtil.cpp
 +++ b/netwerk/base/nsNetUtil.cpp
-@@ -552,17 +552,17 @@ NS_NewInputStreamChannelInternal(nsIChan
+@@ -688,17 +688,17 @@ NS_NewInputStreamChannelInternal(nsIChan
  {
    nsresult rv;
    nsCOMPtr<nsIInputStreamChannel> isc =
@@ -47054,7 +47054,7 @@ diff --git a/netwerk/base/nsNetUtil.cpp b/netwerk/base/nsNetUtil.cpp
  
    if (!aContentType.IsEmpty()) {
      rv = channel->SetContentType(aContentType);
-@@ -603,17 +603,17 @@ NS_NewInputStreamChannelInternal(nsIChan
+@@ -739,17 +739,17 @@ NS_NewInputStreamChannelInternal(nsIChan
                            aTriggeringPrincipal,
                            aLoadingNode,
                            aSecurityFlags,
@@ -47073,7 +47073,7 @@ diff --git a/netwerk/base/nsNetUtil.cpp b/netwerk/base/nsNetUtil.cpp
                                            aContentCharset,
                                            loadInfo);
  }
-@@ -721,17 +721,17 @@ NS_NewInputStreamChannel(nsIChannel     
+@@ -857,17 +857,17 @@ NS_NewInputStreamChannel(nsIChannel     
  nsresult
  NS_NewInputStreamPump(nsIInputStreamPump** aResult,
                        already_AddRefed<nsIInputStream> aStream,
@@ -47092,7 +47092,7 @@ diff --git a/netwerk/base/nsNetUtil.cpp b/netwerk/base/nsNetUtil.cpp
          rv = pump->Init(stream, aSegsize, aSegcount, aCloseWhenDone,
                          aMainThreadTarget);
          if (NS_SUCCEEDED(rv)) {
-@@ -1325,17 +1325,17 @@ NS_NewLocalFileStream(nsIFileStream **re
+@@ -1463,17 +1463,17 @@ NS_NewLocalFileStream(nsIFileStream **re
      return rv;
  }
  
@@ -47111,7 +47111,7 @@ diff --git a/netwerk/base/nsNetUtil.cpp b/netwerk/base/nsNetUtil.cpp
          rv = out->Init(outputStream, aBufferSize);
          if (NS_SUCCEEDED(rv)) {
              out.forget(aResult);
-@@ -1344,17 +1344,17 @@ NS_NewBufferedOutputStream(nsIOutputStre
+@@ -1482,17 +1482,17 @@ NS_NewBufferedOutputStream(nsIOutputStre
      return rv;
  }
  
@@ -47423,7 +47423,45 @@ diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/
  NS_IMPL_ADDREF(HttpChannelChild)
  
  NS_IMETHODIMP_(MozExternalRefCountType) HttpChannelChild::Release()
-@@ -2144,17 +2144,17 @@ HttpChannelChild::ConnectParent(uint32_t
+@@ -448,17 +448,17 @@ class StartRequestEvent : public NeckoTa
+   , mCacheExpirationTime(aCacheExpirationTime)
+   , mCachedCharset(aCachedCharset)
+   , mSecurityInfoSerialization(aSecurityInfoSerialization)
+   , mSelfAddr(aSelfAddr)
+   , mPeerAddr(aPeerAddr)
+   , mCacheKey(aCacheKey)
+   , mAltDataType(altDataType)
+   , mAltDataLen(altDataLen)
+-  , mController(Move(aController))
++  , mController(std::move(aController))
+   {}
+ 
+   void Run() override
+   {
+     LOG(("StartRequestEvent [this=%p]\n", mChild));
+     mChild->OnStartRequest(mChannelStatus, mResponseHead, mUseResponseHead,
+                            mRequestHeaders, mIsFromCache, mCacheEntryAvailable,
+                            mCacheEntryId, mCacheFetchCount,
+@@ -527,17 +527,17 @@ HttpChannelChild::RecvOnStartRequest(con
+   mEventQ->RunOrEnqueue(new StartRequestEvent(this, channelStatus, responseHead,
+                                               useResponseHead, requestHeaders,
+                                               isFromCache, cacheEntryAvailable,
+                                               cacheEntryId, cacheFetchCount,
+                                               cacheExpirationTime, cachedCharset,
+                                               securityInfoSerialization,
+                                               selfAddr, peerAddr, cacheKey,
+                                               altDataType, altDataLen,
+-                                              Move(controller)));
++                                              std::move(controller)));
+ 
+   {
+     // Child's mEventQ is to control the execution order of the IPC messages
+     // from both main thread IPDL and PBackground IPDL.
+     // To guarantee the ordering, PBackground IPC messages that are sent after
+     // OnStartRequest will be throttled until OnStartRequest hits the Child's
+     // mEventQ.
+     MutexAutoLock lock(mBgChildMutex);
+@@ -2176,17 +2176,17 @@ HttpChannelChild::ConnectParent(uint32_t
  
      MOZ_RELEASE_ASSERT(gSocketTransportService);
  
@@ -47442,7 +47480,7 @@ diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/
  
      mBgChild = bgChild.forget();
    }
-@@ -3933,17 +3933,17 @@ HttpChannelChild::RecvSetPriority(const 
+@@ -3965,17 +3965,17 @@ HttpChannelChild::RecvSetPriority(const 
  {
    mPriority = aPriority;
    return IPC_OK();

+ 25 - 0
mozilla-release/patches/series

@@ -629,6 +629,7 @@ NOBUG-20170803-promisehelper-57a1.patch
 1424338-6-59a1.patch
 1424338-7-59a1.patch
 1419401-59a1.patch
+1424571-59a1.patch
 1424658-59a1.patch
 1424809-59a1.patch
 1411622-59a1.patch
@@ -652,6 +653,9 @@ NOBUG-20170803-promisehelper-57a1.patch
 1424275-59a1.patch
 1425270-59a1.patch
 1422815-59a1.patch
+1424300-1-59a1.patch
+1424300-2-59a1.patch
+1424300-3-59a1.patch
 1419083-59a1.patch
 1423158-59a1.patch
 1424949-1-59a1.patch
@@ -1125,6 +1129,26 @@ servo-19850-60a1.patch
 1425547-60a1.patch
 1429763-60a1.patch
 1432713-60a1.patch
+1231211-01-60a1.patch
+1231211-02-60a1.patch
+1231211-03-60a1.patch
+1231211-04-60a1.patch
+1231211-05-60a1.patch
+1231211-06-60a1.patch
+1231211-07-60a1.patch
+1231211-08-60a1.patch
+1231211-09-60a1.patch
+1231211-10-60a1.patch
+1231211-11-60a1.patch
+1231211-12-60a1.patch
+1231211-13-60a1.patch
+1231211-14-60a1.patch
+1231211-15no16-60a1.patch
+1231211-17-60a1.patch
+1231211-18-60a1.patch
+1231211-19-60a1.patch
+1231211-20-60a1.patch
+1431814-1no2-60a1.patch
 1429373-1-60a1.patch
 1429373-2-60a1.patch
 1429373-3-60a1.patch
@@ -1145,6 +1169,7 @@ servo-19850-60a1.patch
 1432516-2-60a1.patch
 1432516-3-60a1.patch
 1431866-60a1.patch
+1432640-60a1.patch
 1432553-60a1.patch
 1431864-60a1.patch
 1431025-60a1.patch