Bug 1525245 - Stabilize cookiePolicy/cookiePermission for live documents - part 12 - nsICookieSettings for the channel creation, r=ckerschb,asuth,Ehsan
☠☠ backed out by ca64604d4b78 ☠ ☠
authorAndrea Marchesini <amarchesini@mozilla.com>
Thu, 07 Mar 2019 10:21:15 +0000
changeset 462867 a5a9e01116ed480d98bbeae1c77f28306aef8e9b
parent 462866 66e19a0c38dd6aa51d551c1ca4daae7de64faf6a
child 462868 6790802e2fa5399d61848e95e9a925fb45e2d9b3
push id79881
push useramarchesini@mozilla.com
push dateThu, 07 Mar 2019 10:41:26 +0000
treeherderautoland@3fd27215698f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersckerschb, asuth, Ehsan
bugs1525245
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1525245 - Stabilize cookiePolicy/cookiePermission for live documents - part 12 - nsICookieSettings for the channel creation, r=ckerschb,asuth,Ehsan Differential Revision: https://phabricator.services.mozilla.com/D21538
dom/base/EventSource.cpp
dom/base/EventSource.h
dom/base/nsSyncLoadService.cpp
dom/base/nsSyncLoadService.h
dom/fetch/Fetch.cpp
dom/fetch/FetchDriver.cpp
dom/fetch/FetchDriver.h
dom/security/nsCSPContext.cpp
dom/serviceworkers/ServiceWorkerPrivate.cpp
dom/serviceworkers/ServiceWorkerScriptCache.cpp
dom/webbrowserpersist/nsWebBrowserPersist.cpp
dom/workers/ScriptLoader.cpp
dom/workers/ScriptLoader.h
dom/workers/WorkerLoadInfo.h
dom/workers/WorkerPrivate.cpp
dom/workers/WorkerPrivate.h
dom/workers/remoteworkers/RemoteWorkerChild.cpp
dom/xbl/nsXBLService.cpp
dom/xhr/XMLHttpRequest.cpp
dom/xhr/XMLHttpRequestMainThread.cpp
dom/xhr/XMLHttpRequestMainThread.h
dom/xhr/XMLHttpRequestWorker.cpp
dom/xml/nsXMLPrettyPrinter.cpp
dom/xslt/xml/txXMLParser.cpp
dom/xslt/xslt/txMozillaStylesheetCompiler.cpp
extensions/pref/autoconfig/src/nsAutoConfig.cpp
image/imgLoader.cpp
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/loader/mozJSSubScriptLoader.cpp
layout/style/Loader.cpp
netwerk/base/LoadInfo.cpp
netwerk/base/NetworkConnectivityService.cpp
netwerk/base/Predictor.cpp
netwerk/base/nsILoadInfo.idl
netwerk/base/nsIncrementalDownload.cpp
netwerk/base/nsNetUtil.cpp
netwerk/base/nsNetUtil.h
netwerk/base/nsPACMan.cpp
netwerk/cookie/CookieSettings.cpp
netwerk/cookie/CookieSettings.h
netwerk/dns/TRR.cpp
toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.cpp
uriloader/prefetch/nsOfflineCacheUpdate.cpp
uriloader/prefetch/nsPrefetchService.cpp
widget/android/WebExecutorSupport.cpp
widget/windows/nsDataObj.cpp
--- a/dom/base/EventSource.cpp
+++ b/dom/base/EventSource.cpp
@@ -77,17 +77,18 @@ class EventSourceImpl final : public nsI
   NS_DECL_NSIOBSERVER
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_NSICHANNELEVENTSINK
   NS_DECL_NSIINTERFACEREQUESTOR
   NS_DECL_NSIEVENTTARGET_FULL
   NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
 
-  explicit EventSourceImpl(EventSource* aEventSource);
+  EventSourceImpl(EventSource* aEventSource,
+                  nsICookieSettings* aCookieSettings);
 
   enum { CONNECTING = 0U, OPEN = 1U, CLOSED = 2U };
 
   void Close();
 
   void Init(nsIPrincipal* aPrincipal, const nsAString& aURL, ErrorResult& aRv);
 
   nsresult GetBaseURI(nsIURI** aBaseURI);
@@ -286,16 +287,18 @@ class EventSourceImpl final : public nsI
   // These attributes are used for error reporting. Should only be accessed on
   // target thread
   nsString mScriptFile;
   uint32_t mScriptLine;
   uint32_t mScriptColumn;
   uint64_t mInnerWindowID;
 
  private:
+  nsCOMPtr<nsICookieSettings> mCookieSettings;
+
   // Pointer to the target thread for checking whether we are
   // on the target thread. This is intentionally a non-owning
   // pointer in order not to affect the thread destruction
   // sequence. This pointer must only be compared for equality
   // and must not be dereferenced.
   nsIThread* mTargetThread;
 
   // prevent bad usage
@@ -311,28 +314,30 @@ class EventSourceImpl final : public nsI
   }
 };
 
 NS_IMPL_ISUPPORTS(EventSourceImpl, nsIObserver, nsIStreamListener,
                   nsIRequestObserver, nsIChannelEventSink,
                   nsIInterfaceRequestor, nsISupportsWeakReference,
                   nsIEventTarget, nsIThreadRetargetableStreamListener)
 
-EventSourceImpl::EventSourceImpl(EventSource* aEventSource)
+EventSourceImpl::EventSourceImpl(EventSource* aEventSource,
+                                 nsICookieSettings* aCookieSettings)
     : mEventSource(aEventSource),
       mReconnectionTime(0),
       mStatus(PARSE_STATE_OFF),
       mMutex("EventSourceImpl::mMutex"),
       mFrozen(false),
       mGoingToDispatchAllMessages(false),
       mIsMainThread(NS_IsMainThread()),
       mIsShutDown(false),
       mScriptLine(0),
       mScriptColumn(0),
       mInnerWindowID(0),
+      mCookieSettings(aCookieSettings),
       mTargetThread(NS_GetCurrentThread()) {
   MOZ_ASSERT(mEventSource);
   if (!mIsMainThread) {
     mEventSource->mIsMainThread = false;
   }
   SetReadyState(CONNECTING);
 }
 
@@ -966,27 +971,30 @@ nsresult EventSourceImpl::InitChannelAnd
 
   if (mEventSource->mWithCredentials) {
     securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
   }
 
   nsCOMPtr<nsIChannel> channel;
   // If we have the document, use it
   if (doc) {
+    MOZ_ASSERT(mCookieSettings == doc->CookieSettings());
+
     nsCOMPtr<nsILoadGroup> loadGroup = doc->GetDocumentLoadGroup();
     rv = NS_NewChannel(getter_AddRefs(channel), mSrc, doc, securityFlags,
                        nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE,
                        nullptr,  // aPerformanceStorage
                        loadGroup,
                        nullptr,     // aCallbacks
                        loadFlags);  // aLoadFlags
   } else {
     // otherwise use the principal
     rv = NS_NewChannel(getter_AddRefs(channel), mSrc, mPrincipal, securityFlags,
                        nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE,
+                       mCookieSettings,
                        nullptr,     // aPerformanceStorage
                        nullptr,     // loadGroup
                        nullptr,     // aCallbacks
                        loadFlags);  // aLoadFlags
   }
 
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -1772,22 +1780,24 @@ EventSourceImpl::CheckListenerChain() {
   MOZ_ASSERT(NS_IsMainThread(), "Should be on the main thread!");
   return NS_OK;
 }
 ////////////////////////////////////////////////////////////////////////////////
 // EventSource
 ////////////////////////////////////////////////////////////////////////////////
 
 EventSource::EventSource(nsPIDOMWindowInner* aOwnerWindow,
+                         nsICookieSettings* aCookieSettings,
                          bool aWithCredentials)
     : DOMEventTargetHelper(aOwnerWindow),
       mWithCredentials(aWithCredentials),
       mIsMainThread(true),
       mKeepingAlive(false) {
-  mImpl = new EventSourceImpl(this);
+  MOZ_ASSERT(aCookieSettings);
+  mImpl = new EventSourceImpl(this, aCookieSettings);
 }
 
 EventSource::~EventSource() {}
 
 nsresult EventSource::CreateAndDispatchSimpleEvent(const nsAString& aName) {
   RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
   // it doesn't bubble, and it isn't cancelable
   event->InitEvent(aName, false, false);
@@ -1801,18 +1811,34 @@ nsresult EventSource::CreateAndDispatchS
 already_AddRefed<EventSource> EventSource::Constructor(
     const GlobalObject& aGlobal, const nsAString& aURL,
     const EventSourceInit& aEventSourceInitDict, ErrorResult& aRv) {
   nsCOMPtr<nsPIDOMWindowInner> ownerWindow =
       do_QueryInterface(aGlobal.GetAsSupports());
 
   MOZ_ASSERT(!NS_IsMainThread() || ownerWindow);
 
-  RefPtr<EventSource> eventSource =
-      new EventSource(ownerWindow, aEventSourceInitDict.mWithCredentials);
+  nsCOMPtr<nsICookieSettings> cookieSettings;
+  if (ownerWindow) {
+    Document* doc = ownerWindow->GetExtantDoc();
+    if (NS_WARN_IF(!doc)) {
+      aRv.Throw(NS_ERROR_FAILURE);
+      return nullptr;
+    }
+
+    cookieSettings = doc->CookieSettings();
+  } else {
+    // Worker side.
+    WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
+    MOZ_ASSERT(workerPrivate);
+    cookieSettings = workerPrivate->CookieSettings();
+  }
+
+  RefPtr<EventSource> eventSource = new EventSource(
+      ownerWindow, cookieSettings, aEventSourceInitDict.mWithCredentials);
   RefPtr<EventSourceImpl> eventSourceImp = eventSource->mImpl;
 
   if (NS_IsMainThread()) {
     // Get principal from document and init EventSourceImpl
     nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal =
         do_QueryInterface(aGlobal.GetAsSupports());
     if (!scriptPrincipal) {
       aRv.Throw(NS_ERROR_FAILURE);
--- a/dom/base/EventSource.h
+++ b/dom/base/EventSource.h
@@ -20,16 +20,17 @@
 #include "nsIStreamListener.h"
 #include "nsIChannelEventSink.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsITimer.h"
 #include "nsIHttpChannel.h"
 #include "nsDeque.h"
 
 class nsPIDOMWindowInner;
+class nsICookieSettings;
 
 namespace mozilla {
 
 class ErrorResult;
 
 namespace dom {
 
 struct EventSourceInit;
@@ -75,17 +76,18 @@ class EventSource final : public DOMEven
 
   IMPL_EVENT_HANDLER(open)
   IMPL_EVENT_HANDLER(message)
   IMPL_EVENT_HANDLER(error)
 
   void Close();
 
  private:
-  EventSource(nsPIDOMWindowInner* aOwnerWindow, bool aWithCredentials);
+  EventSource(nsPIDOMWindowInner* aOwnerWindow,
+              nsICookieSettings* aCookieSettings, bool aWithCredentials);
   virtual ~EventSource();
   // prevent bad usage
   EventSource(const EventSource& x) = delete;
   EventSource& operator=(const EventSource& x) = delete;
 
   void AssertIsOnTargetThread() const {
     MOZ_ASSERT(NS_IsMainThread() == mIsMainThread);
   }
--- a/dom/base/nsSyncLoadService.cpp
+++ b/dom/base/nsSyncLoadService.cpp
@@ -274,23 +274,24 @@ NS_IMETHODIMP
 nsSyncLoader::GetInterface(const nsIID &aIID, void **aResult) {
   return QueryInterface(aIID, aResult);
 }
 
 /* static */
 nsresult nsSyncLoadService::LoadDocument(
     nsIURI *aURI, nsContentPolicyType aContentPolicyType,
     nsIPrincipal *aLoaderPrincipal, nsSecurityFlags aSecurityFlags,
-    nsILoadGroup *aLoadGroup, bool aForceToXML, ReferrerPolicy aReferrerPolicy,
-    Document **aResult) {
+    nsILoadGroup *aLoadGroup, nsICookieSettings *aCookieSettings,
+    bool aForceToXML, ReferrerPolicy aReferrerPolicy, Document **aResult) {
   nsCOMPtr<nsIChannel> channel;
-  nsresult rv = NS_NewChannel(getter_AddRefs(channel), aURI, aLoaderPrincipal,
-                              aSecurityFlags, aContentPolicyType,
-                              nullptr,  // PerformanceStorage
-                              aLoadGroup);
+  nsresult rv =
+      NS_NewChannel(getter_AddRefs(channel), aURI, aLoaderPrincipal,
+                    aSecurityFlags, aContentPolicyType, aCookieSettings,
+                    nullptr,  // PerformanceStorage
+                    aLoadGroup);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!aForceToXML) {
     channel->SetContentType(NS_LITERAL_CSTRING("text/xml"));
   }
 
   bool isChrome = false, isResource = false;
   // if the load needs to enforce CORS, then force the load to be async
--- a/dom/base/nsSyncLoadService.h
+++ b/dom/base/nsSyncLoadService.h
@@ -10,16 +10,17 @@
  */
 
 #ifndef nsSyncLoadService_h__
 #define nsSyncLoadService_h__
 
 #include "nscore.h"
 #include "mozilla/net/ReferrerPolicy.h"
 
+class nsICookieSettings;
 class nsIInputStream;
 class nsILoadGroup;
 class nsIStreamListener;
 class nsIURI;
 class nsIPrincipal;
 class nsIChannel;
 
 namespace mozilla {
@@ -39,23 +40,22 @@ class nsSyncLoadService {
    *                         checks and referrer header.
    * @param aSecurityFlags securityFlags to be set on the channel
    * @param aLoadGroup The loadgroup to use for loading the document.
    * @param aForceToXML Whether to parse the document as XML, regardless of
    *                    content type.
    * @param referrerPolicy Referrer policy.
    * @param aResult [out] The document loaded from the URI.
    */
-  static nsresult LoadDocument(nsIURI* aURI,
-                               nsContentPolicyType aContentPolicyType,
-                               nsIPrincipal* aLoaderPrincipal,
-                               nsSecurityFlags aSecurityFlags,
-                               nsILoadGroup* aLoadGroup, bool aForceToXML,
-                               mozilla::net::ReferrerPolicy aReferrerPolicy,
-                               mozilla::dom::Document** aResult);
+  static nsresult LoadDocument(
+      nsIURI* aURI, nsContentPolicyType aContentPolicyType,
+      nsIPrincipal* aLoaderPrincipal, nsSecurityFlags aSecurityFlags,
+      nsILoadGroup* aLoadGroup, nsICookieSettings* aCookieSettings,
+      bool aForceToXML, mozilla::net::ReferrerPolicy aReferrerPolicy,
+      mozilla::dom::Document** aResult);
 
   /**
    * Read input stream aIn in chunks and deliver synchronously to aListener.
    *
    * @param aIn The stream to be read. The ownership of this stream is taken.
    * @param aListener The listener that will receive
    *                  OnStartRequest/OnDataAvailable/OnStopRequest
    *                  notifications.
--- a/dom/fetch/Fetch.cpp
+++ b/dom/fetch/Fetch.cpp
@@ -33,16 +33,17 @@
 #include "mozilla/dom/MutableBlobStreamListener.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/PromiseWorkerProxy.h"
 #include "mozilla/dom/RemoteWorkerChild.h"
 #include "mozilla/dom/Request.h"
 #include "mozilla/dom/Response.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/URLSearchParams.h"
+#include "mozilla/net/CookieSettings.h"
 #include "mozilla/Telemetry.h"
 
 #include "BodyExtractor.h"
 #include "EmptyBody.h"
 #include "FetchObserver.h"
 #include "InternalRequest.h"
 #include "InternalResponse.h"
 
@@ -384,16 +385,17 @@ class MainThreadFetchRunnable : public R
       nsCOMPtr<nsIPrincipal> principal = workerPrivate->GetPrincipal();
       MOZ_ASSERT(principal);
       nsCOMPtr<nsILoadGroup> loadGroup = workerPrivate->GetLoadGroup();
       MOZ_ASSERT(loadGroup);
       // We don't track if a worker is spawned from a tracking script for now,
       // so pass false as the last argument to FetchDriver().
       fetch = new FetchDriver(mRequest, principal, loadGroup,
                               workerPrivate->MainThreadEventTarget(),
+                              workerPrivate->CookieSettings(),
                               workerPrivate->GetPerformanceStorage(), false);
       nsAutoCString spec;
       if (proxy->GetWorkerPrivate()->GetBaseURI()) {
         proxy->GetWorkerPrivate()->GetBaseURI()->GetAsciiSpec(spec);
       }
       fetch->SetWorkerScript(spec);
 
       fetch->SetClientInfo(mClientInfo);
@@ -457,51 +459,55 @@ already_AddRefed<Promise> FetchRequest(n
     observer = new FetchObserver(aGlobal, signalImpl);
     aInit.mObserve.Value().HandleEvent(*observer);
   }
 
   if (NS_IsMainThread()) {
     nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal);
     nsCOMPtr<Document> doc;
     nsCOMPtr<nsILoadGroup> loadGroup;
+    nsCOMPtr<nsICookieSettings> cookieSettings;
     nsIPrincipal* principal;
     bool isTrackingFetch = false;
     if (window) {
       doc = window->GetExtantDoc();
       if (!doc) {
         aRv.Throw(NS_ERROR_FAILURE);
         return nullptr;
       }
       principal = doc->NodePrincipal();
       loadGroup = doc->GetDocumentLoadGroup();
+      cookieSettings = doc->CookieSettings();
 
       nsAutoCString fileNameString;
       if (nsJSUtils::GetCallingLocation(cx, fileNameString)) {
         isTrackingFetch = doc->IsScriptTracking(fileNameString);
       }
     } else {
       principal = aGlobal->PrincipalOrNull();
       if (NS_WARN_IF(!principal)) {
         aRv.Throw(NS_ERROR_FAILURE);
         return nullptr;
       }
       nsresult rv = NS_NewLoadGroup(getter_AddRefs(loadGroup), principal);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         aRv.Throw(rv);
         return nullptr;
       }
+
+      cookieSettings = mozilla::net::CookieSettings::Create();
     }
 
     Telemetry::Accumulate(Telemetry::FETCH_IS_MAINTHREAD, 1);
 
     RefPtr<MainThreadFetchResolver> resolver = new MainThreadFetchResolver(
         p, observer, signalImpl, request->MozErrors());
     RefPtr<FetchDriver> fetch = new FetchDriver(
         r, principal, loadGroup, aGlobal->EventTargetFor(TaskCategory::Other),
-        nullptr,  // PerformanceStorage
+        cookieSettings, nullptr,  // PerformanceStorage
         isTrackingFetch);
     fetch->SetDocument(doc);
     resolver->SetLoadGroup(loadGroup);
     aRv = fetch->Fetch(signalImpl, resolver);
     if (NS_WARN_IF(aRv.Failed())) {
       return nullptr;
     }
   } else {
--- a/dom/fetch/FetchDriver.cpp
+++ b/dom/fetch/FetchDriver.cpp
@@ -318,22 +318,24 @@ AlternativeDataStreamListener::CheckList
 //-----------------------------------------------------------------------------
 
 NS_IMPL_ISUPPORTS(FetchDriver, nsIStreamListener, nsIChannelEventSink,
                   nsIInterfaceRequestor, nsIThreadRetargetableStreamListener)
 
 FetchDriver::FetchDriver(InternalRequest* aRequest, nsIPrincipal* aPrincipal,
                          nsILoadGroup* aLoadGroup,
                          nsIEventTarget* aMainThreadEventTarget,
+                         nsICookieSettings* aCookieSettings,
                          PerformanceStorage* aPerformanceStorage,
                          bool aIsTrackingFetch)
     : mPrincipal(aPrincipal),
       mLoadGroup(aLoadGroup),
       mRequest(aRequest),
       mMainThreadEventTarget(aMainThreadEventTarget),
+      mCookieSettings(aCookieSettings),
       mPerformanceStorage(aPerformanceStorage),
       mNeedToObserveOnDataAvailable(false),
       mIsTrackingFetch(aIsTrackingFetch),
       mOnStopRequestCalled(false)
 #ifdef DEBUG
       ,
       mResponseAvailableCalled(false),
       mFetchCalled(false)
@@ -504,32 +506,34 @@ nsresult FetchDriver::HttpFetch(
   // information from the InternalRequest. This is an implementation detail.
   MOZ_ASSERT(mLoadGroup);
   nsCOMPtr<nsIChannel> chan;
 
   nsLoadFlags loadFlags =
       nsIRequest::LOAD_BACKGROUND | bypassFlag | nsIChannel::LOAD_CLASSIFY_URI;
   if (mDocument) {
     MOZ_ASSERT(mDocument->NodePrincipal() == mPrincipal);
+    MOZ_ASSERT(mDocument->CookieSettings() == mCookieSettings);
     rv = NS_NewChannel(getter_AddRefs(chan), uri, mDocument, secFlags,
                        mRequest->ContentPolicyType(),
                        nullptr,             /* aPerformanceStorage */
                        mLoadGroup, nullptr, /* aCallbacks */
                        loadFlags, ios);
   } else if (mClientInfo.isSome()) {
+    rv = NS_NewChannel(getter_AddRefs(chan), uri, mPrincipal, mClientInfo.ref(),
+                       mController, secFlags, mRequest->ContentPolicyType(),
+                       mCookieSettings, mPerformanceStorage, mLoadGroup,
+                       nullptr, /* aCallbacks */
+                       loadFlags, ios);
+  } else {
     rv =
-        NS_NewChannel(getter_AddRefs(chan), uri, mPrincipal, mClientInfo.ref(),
-                      mController, secFlags, mRequest->ContentPolicyType(),
+        NS_NewChannel(getter_AddRefs(chan), uri, mPrincipal, secFlags,
+                      mRequest->ContentPolicyType(), mCookieSettings,
                       mPerformanceStorage, mLoadGroup, nullptr, /* aCallbacks */
                       loadFlags, ios);
-  } else {
-    rv = NS_NewChannel(getter_AddRefs(chan), uri, mPrincipal, secFlags,
-                       mRequest->ContentPolicyType(), mPerformanceStorage,
-                       mLoadGroup, nullptr, /* aCallbacks */
-                       loadFlags, ios);
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (mCSPEventListener) {
     nsCOMPtr<nsILoadInfo> loadInfo = chan->LoadInfo();
     rv = loadInfo->SetCspEventListener(mCSPEventListener);
     NS_ENSURE_SUCCESS(rv, rv);
   }
--- a/dom/fetch/FetchDriver.h
+++ b/dom/fetch/FetchDriver.h
@@ -16,16 +16,17 @@
 #include "mozilla/dom/AbortSignal.h"
 #include "mozilla/dom/SRIMetadata.h"
 #include "mozilla/RefPtr.h"
 
 #include "mozilla/DebugOnly.h"
 #include "mozilla/net/ReferrerPolicy.h"
 
 class nsIConsoleReportCollector;
+class nsICookieSettings;
 class nsICSPEventListener;
 class nsIEventTarget;
 class nsIOutputStream;
 class nsILoadGroup;
 class nsIPrincipal;
 
 namespace mozilla {
 namespace dom {
@@ -96,16 +97,17 @@ class FetchDriver final : public nsIStre
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_NSICHANNELEVENTSINK
   NS_DECL_NSIINTERFACEREQUESTOR
   NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
 
   FetchDriver(InternalRequest* aRequest, nsIPrincipal* aPrincipal,
               nsILoadGroup* aLoadGroup, nsIEventTarget* aMainThreadEventTarget,
+              nsICookieSettings* aCookieSettings,
               PerformanceStorage* aPerformanceStorage, bool aIsTrackingFetch);
 
   nsresult Fetch(AbortSignalImpl* aSignalImpl, FetchDriverObserver* aObserver);
 
   void SetDocument(Document* aDocument);
 
   void SetCSPEventListener(nsICSPEventListener* aCSPEventListener);
 
@@ -131,16 +133,18 @@ class FetchDriver final : public nsIStre
   RefPtr<Document> mDocument;
   nsCOMPtr<nsICSPEventListener> mCSPEventListener;
   Maybe<ClientInfo> mClientInfo;
   Maybe<ServiceWorkerDescriptor> mController;
   nsCOMPtr<nsIChannel> mChannel;
   nsAutoPtr<SRICheckDataVerifier> mSRIDataVerifier;
   nsCOMPtr<nsIEventTarget> mMainThreadEventTarget;
 
+  nsCOMPtr<nsICookieSettings> mCookieSettings;
+
   // This is set only when Fetch is used in workers.
   RefPtr<PerformanceStorage> mPerformanceStorage;
 
   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
--- a/dom/security/nsCSPContext.cpp
+++ b/dom/security/nsCSPContext.cpp
@@ -1011,16 +1011,17 @@ nsresult nsCSPContext::SendReports(
                          nullptr,  // aLoadGroup
                          nullptr,  // aCallbacks
                          loadFlags);
     } else {
       rv = NS_NewChannel(getter_AddRefs(reportChannel), reportURI,
                          mLoadingPrincipal,
                          nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                          nsIContentPolicy::TYPE_CSP_REPORT,
+                         nullptr,  // nsICookieSettings
                          nullptr,  // PerformanceStorage
                          nullptr,  // aLoadGroup
                          nullptr,  // aCallbacks
                          loadFlags);
     }
 
     if (NS_FAILED(rv)) {
       CSPCONTEXTLOG(("Could not create new channel for report URI %s",
--- a/dom/serviceworkers/ServiceWorkerPrivate.cpp
+++ b/dom/serviceworkers/ServiceWorkerPrivate.cpp
@@ -35,16 +35,17 @@
 #include "mozilla/dom/PromiseNativeHandler.h"
 #include "mozilla/dom/PushEventBinding.h"
 #include "mozilla/dom/RequestBinding.h"
 #include "mozilla/dom/WorkerDebugger.h"
 #include "mozilla/dom/WorkerRef.h"
 #include "mozilla/dom/WorkerRunnable.h"
 #include "mozilla/dom/WorkerScope.h"
 #include "mozilla/dom/ipc/StructuredCloneData.h"
+#include "mozilla/net/CookieSettings.h"
 #include "mozilla/net/NeckoChannelParams.h"
 #include "mozilla/StaticPrefs.h"
 #include "mozilla/Unused.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 namespace mozilla {
@@ -1726,16 +1727,20 @@ nsresult ServiceWorkerPrivate::SpawnWork
     return NS_ERROR_FAILURE;
   }
   info.mLoadingPrincipal = info.mPrincipal;
 
   nsContentUtils::StorageAccess access =
       nsContentUtils::StorageAllowedForServiceWorker(info.mPrincipal);
   info.mStorageAllowed =
       access > nsContentUtils::StorageAccess::ePrivateBrowsing;
+
+  info.mCookieSettings = mozilla::net::CookieSettings::Create();
+  MOZ_ASSERT(info.mCookieSettings);
+
   info.mOriginAttributes = mInfo->GetOriginAttributes();
 
   // Verify that we don't have any CSP on pristine principal.
 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
   nsCOMPtr<nsIContentSecurityPolicy> csp;
   Unused << info.mPrincipal->GetCsp(getter_AddRefs(csp));
   MOZ_DIAGNOSTIC_ASSERT(!csp);
 #endif
--- a/dom/serviceworkers/ServiceWorkerScriptCache.cpp
+++ b/dom/serviceworkers/ServiceWorkerScriptCache.cpp
@@ -11,16 +11,17 @@
 #include "mozilla/dom/cache/CacheStorage.h"
 #include "mozilla/dom/cache/Cache.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/PromiseWorkerProxy.h"
 #include "mozilla/dom/ScriptLoader.h"
 #include "mozilla/dom/WorkerCommon.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/ipc/PBackgroundSharedTypes.h"
+#include "mozilla/net/CookieSettings.h"
 #include "nsICacheInfoChannel.h"
 #include "nsIHttpChannelInternal.h"
 #include "nsIStreamLoader.h"
 #include "nsIThreadRetargetableRequest.h"
 
 #include "nsIInputStreamPump.h"
 #include "nsIPrincipal.h"
 #include "nsIScriptError.h"
@@ -652,22 +653,27 @@ nsresult CompareNetwork::Initialize(nsIP
   uint32_t secFlags = mIsMainScript
                           ? nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED
                           : nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS;
 
   nsContentPolicyType contentPolicyType =
       mIsMainScript ? nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER
                     : nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS;
 
+  // Create a new cookieSettings.
+  nsCOMPtr<nsICookieSettings> cookieSettings =
+      mozilla::net::CookieSettings::Create();
+
   // Note that because there is no "serviceworker" RequestContext type, we can
   // use the TYPE_INTERNAL_SCRIPT content policy types when loading a service
   // worker.
   rv = NS_NewChannel(getter_AddRefs(mChannel), uri, aPrincipal, secFlags,
-                     contentPolicyType, nullptr, /* aPerformanceStorage */
-                     loadGroup, nullptr /* aCallbacks */, mLoadFlags);
+                     contentPolicyType, cookieSettings,
+                     nullptr /* aPerformanceStorage */, loadGroup,
+                     nullptr /* aCallbacks */, mLoadFlags);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel);
   if (httpChannel) {
     // Spec says no redirects allowed for top-level SW scripts.
     if (mIsMainScript) {
--- a/dom/webbrowserpersist/nsWebBrowserPersist.cpp
+++ b/dom/webbrowserpersist/nsWebBrowserPersist.cpp
@@ -57,16 +57,17 @@
 
 #include "nsWebBrowserPersist.h"
 #include "WebBrowserPersistLocalDocument.h"
 
 #include "nsIContent.h"
 #include "nsIMIMEInfo.h"
 #include "mozilla/dom/HTMLInputElement.h"
 #include "mozilla/dom/HTMLSharedElement.h"
+#include "mozilla/net/CookieSettings.h"
 #include "mozilla/Printf.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 // Buffer file writes in 32kb chunks
 #define BUFFERED_OUTPUT_SIZE (1024 * 32)
 
@@ -1229,21 +1230,26 @@ nsresult nsWebBrowserPersist::SaveURIInt
 
   nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL;
   if (mPersistFlags & PERSIST_FLAGS_BYPASS_CACHE) {
     loadFlags |= nsIRequest::LOAD_BYPASS_CACHE;
   } else if (mPersistFlags & PERSIST_FLAGS_FROM_CACHE) {
     loadFlags |= nsIRequest::LOAD_FROM_CACHE;
   }
 
+  // Create a new cookieSettings for this download in order to send cookies
+  // based on the current state of the prefs/permissions.
+  nsCOMPtr<nsICookieSettings> cookieSettings =
+      mozilla::net::CookieSettings::Create();
+
   // Open a channel to the URI
   nsCOMPtr<nsIChannel> inputChannel;
   rv = NS_NewChannel(getter_AddRefs(inputChannel), aURI, aTriggeringPrincipal,
                      nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
-                     nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD,
+                     nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD, cookieSettings,
                      nullptr,  // aPerformanceStorage
                      nullptr,  // aLoadGroup
                      static_cast<nsIInterfaceRequestor *>(this), loadFlags);
 
   nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel =
       do_QueryInterface(inputChannel);
   if (pbChannel) {
     pbChannel->SetPrivate(aIsPrivate);
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -120,27 +120,25 @@ nsresult ConstructURI(const nsAString& a
   }
 
   if (NS_FAILED(rv)) {
     return NS_ERROR_DOM_SYNTAX_ERR;
   }
   return NS_OK;
 }
 
-nsresult ChannelFromScriptURL(nsIPrincipal* principal, Document* parentDoc,
-                              WorkerPrivate* aWorkerPrivate,
-                              nsILoadGroup* loadGroup, nsIIOService* ios,
-                              nsIScriptSecurityManager* secMan,
-                              nsIURI* aScriptURL,
-                              const Maybe<ClientInfo>& aClientInfo,
-                              const Maybe<ServiceWorkerDescriptor>& aController,
-                              bool aIsMainScript,
-                              WorkerScriptType aWorkerScriptType,
-                              nsContentPolicyType aMainScriptContentPolicyType,
-                              nsLoadFlags aLoadFlags, nsIChannel** aChannel) {
+nsresult ChannelFromScriptURL(
+    nsIPrincipal* principal, Document* parentDoc, WorkerPrivate* aWorkerPrivate,
+    nsILoadGroup* loadGroup, nsIIOService* ios,
+    nsIScriptSecurityManager* secMan, nsIURI* aScriptURL,
+    const Maybe<ClientInfo>& aClientInfo,
+    const Maybe<ServiceWorkerDescriptor>& aController, bool aIsMainScript,
+    WorkerScriptType aWorkerScriptType,
+    nsContentPolicyType aMainScriptContentPolicyType, nsLoadFlags aLoadFlags,
+    nsICookieSettings* aCookieSettings, nsIChannel** aChannel) {
   AssertIsOnMainThread();
 
   nsresult rv;
   nsCOMPtr<nsIURI> uri = aScriptURL;
 
   // If we have the document, use it. Unfortunately, for dedicated workers
   // 'parentDoc' ends up being the parent document, which is not the document
   // that we want to use. So make sure to avoid using 'parentDoc' in that
@@ -201,21 +199,17 @@ nsresult ChannelFromScriptURL(nsIPrincip
   //
   // Note, if we ever allow service worker scripts to be loaded from network
   // here we need to configure the channel properly.  For example, it must
   // not allow redirects.
   MOZ_DIAGNOSTIC_ASSERT(contentPolicyType !=
                         nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER);
 
   nsCOMPtr<nsIChannel> channel;
-  // If we have the document, use it. Unfortunately, for dedicated workers
-  // 'parentDoc' ends up being the parent document, which is not the document
-  // that we want to use. So make sure to avoid using 'parentDoc' in that
-  // situation.
-  if (parentDoc && parentDoc->NodePrincipal() == principal) {
+  if (parentDoc) {
     rv = NS_NewChannel(getter_AddRefs(channel), uri, parentDoc, secFlags,
                        contentPolicyType,
                        nullptr,  // aPerformanceStorage
                        loadGroup,
                        nullptr,  // aCallbacks
                        aLoadFlags, ios);
     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_SECURITY_ERR);
   } else {
@@ -229,23 +223,23 @@ nsresult ChannelFromScriptURL(nsIPrincip
     if (aWorkerPrivate && !aIsMainScript) {
       performanceStorage = aWorkerPrivate->GetPerformanceStorage();
       cspEventListener = aWorkerPrivate->CSPEventListener();
     }
 
     if (aClientInfo.isSome()) {
       rv = NS_NewChannel(getter_AddRefs(channel), uri, principal,
                          aClientInfo.ref(), aController, secFlags,
-                         contentPolicyType, performanceStorage, loadGroup,
-                         nullptr,  // aCallbacks
+                         contentPolicyType, aCookieSettings, performanceStorage,
+                         loadGroup, nullptr,  // aCallbacks
                          aLoadFlags, ios);
     } else {
       rv = NS_NewChannel(getter_AddRefs(channel), uri, principal, secFlags,
-                         contentPolicyType, performanceStorage, loadGroup,
-                         nullptr,  // aCallbacks
+                         contentPolicyType, aCookieSettings, performanceStorage,
+                         loadGroup, nullptr,  // aCallbacks
                          aLoadFlags, ios);
     }
 
     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_SECURITY_ERR);
 
     if (cspEventListener) {
       nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
       rv = loadInfo->SetCspEventListener(cspEventListener);
@@ -955,21 +949,21 @@ class ScriptLoaderRunnable final : publi
       bool useDefaultEncoding = !(!parentWorker && IsMainWorkerScript());
       nsCOMPtr<nsIURI> url;
       rv = ConstructURI(loadInfo.mURL, baseURI, parentDoc, useDefaultEncoding,
                         getter_AddRefs(url));
       if (NS_FAILED(rv)) {
         return rv;
       }
 
-      rv = ChannelFromScriptURL(principal, parentDoc, mWorkerPrivate, loadGroup,
-                                ios, secMan, url, mClientInfo, mController,
-                                IsMainWorkerScript(), mWorkerScriptType,
-                                mWorkerPrivate->ContentPolicyType(), loadFlags,
-                                getter_AddRefs(channel));
+      rv = ChannelFromScriptURL(
+          principal, parentDoc, mWorkerPrivate, loadGroup, ios, secMan, url,
+          mClientInfo, mController, IsMainWorkerScript(), mWorkerScriptType,
+          mWorkerPrivate->ContentPolicyType(), loadFlags,
+          mWorkerPrivate->CookieSettings(), getter_AddRefs(channel));
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
 
     // We need to know which index we're on in OnStreamComplete so we know
     // where to put the result.
     RefPtr<LoaderListener> listener = new LoaderListener(this, aIndex);
@@ -1824,32 +1818,34 @@ class ChannelGetterRunnable final : publ
     // Figure out our base URI.
     nsCOMPtr<nsIURI> baseURI = mWorkerPrivate->GetBaseURI();
     MOZ_ASSERT(baseURI);
 
     // May be null.
     nsCOMPtr<Document> parentDoc = mWorkerPrivate->GetDocument();
 
     mLoadInfo.mLoadGroup = mWorkerPrivate->GetLoadGroup();
+    mLoadInfo.mCookieSettings = mWorkerPrivate->CookieSettings();
 
     // Nested workers use default uri encoding.
     nsCOMPtr<nsIURI> url;
     mResult =
         ConstructURI(mScriptURL, baseURI, parentDoc, true, getter_AddRefs(url));
     NS_ENSURE_SUCCESS(mResult, true);
 
     Maybe<ClientInfo> clientInfo;
     clientInfo.emplace(mClientInfo);
 
     nsCOMPtr<nsIChannel> channel;
     mResult = workerinternals::ChannelFromScriptURLMainThread(
         mLoadInfo.mLoadingPrincipal, parentDoc, mLoadInfo.mLoadGroup, url,
         clientInfo,
         // Nested workers are always dedicated.
-        nsIContentPolicy::TYPE_INTERNAL_WORKER, getter_AddRefs(channel));
+        nsIContentPolicy::TYPE_INTERNAL_WORKER, mLoadInfo.mCookieSettings,
+        getter_AddRefs(channel));
     NS_ENSURE_SUCCESS(mResult, true);
 
     mResult = mLoadInfo.SetPrincipalFromChannel(channel);
     NS_ENSURE_SUCCESS(mResult, true);
 
     mLoadInfo.mChannel = channel.forget();
     return true;
   }
@@ -2154,28 +2150,30 @@ void LoadAllScripts(WorkerPrivate* aWork
 
 } /* anonymous namespace */
 
 namespace workerinternals {
 
 nsresult ChannelFromScriptURLMainThread(
     nsIPrincipal* aPrincipal, Document* aParentDoc, nsILoadGroup* aLoadGroup,
     nsIURI* aScriptURL, const Maybe<ClientInfo>& aClientInfo,
-    nsContentPolicyType aMainScriptContentPolicyType, nsIChannel** aChannel) {
+    nsContentPolicyType aMainScriptContentPolicyType,
+    nsICookieSettings* aCookieSettings, nsIChannel** aChannel) {
   AssertIsOnMainThread();
 
   nsCOMPtr<nsIIOService> ios(do_GetIOService());
 
   nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
   NS_ASSERTION(secMan, "This should never be null!");
 
   return ChannelFromScriptURL(
       aPrincipal, aParentDoc, nullptr, aLoadGroup, ios, secMan, aScriptURL,
       aClientInfo, Maybe<ServiceWorkerDescriptor>(), true, WorkerScript,
-      aMainScriptContentPolicyType, nsIRequest::LOAD_NORMAL, aChannel);
+      aMainScriptContentPolicyType, nsIRequest::LOAD_NORMAL, aCookieSettings,
+      aChannel);
 }
 
 nsresult ChannelFromScriptURLWorkerThread(JSContext* aCx,
                                           WorkerPrivate* aParent,
                                           const nsAString& aScriptURL,
                                           WorkerLoadInfo& aLoadInfo) {
   aParent->AssertIsOnWorkerThread();
 
--- a/dom/workers/ScriptLoader.h
+++ b/dom/workers/ScriptLoader.h
@@ -11,16 +11,17 @@
 #include "nsIContentPolicy.h"
 #include "nsStringFwd.h"
 
 class nsIPrincipal;
 class nsIURI;
 
 class nsILoadGroup;
 class nsIChannel;
+class nsICookieSettings;
 
 namespace mozilla {
 
 class ErrorResult;
 
 namespace dom {
 
 struct WorkerLoadInfo;
@@ -28,17 +29,18 @@ class WorkerPrivate;
 
 enum WorkerScriptType { WorkerScript, DebuggerScript };
 
 namespace workerinternals {
 
 nsresult ChannelFromScriptURLMainThread(
     nsIPrincipal* aPrincipal, Document* aParentDoc, nsILoadGroup* aLoadGroup,
     nsIURI* aScriptURL, const Maybe<ClientInfo>& aClientInfo,
-    nsContentPolicyType aContentPolicyType, nsIChannel** aChannel);
+    nsContentPolicyType aContentPolicyType, nsICookieSettings* aCookieSettings,
+    nsIChannel** aChannel);
 
 nsresult ChannelFromScriptURLWorkerThread(JSContext* aCx,
                                           WorkerPrivate* aParent,
                                           const nsAString& aScriptURL,
                                           WorkerLoadInfo& aLoadInfo);
 
 void ReportLoadError(ErrorResult& aRv, nsresult aLoadResult,
                      const nsAString& aScriptURL);
--- a/dom/workers/WorkerLoadInfo.h
+++ b/dom/workers/WorkerLoadInfo.h
@@ -14,16 +14,17 @@
 #include "nsIInterfaceRequestor.h"
 #include "nsILoadContext.h"
 #include "nsIRequest.h"
 #include "nsISupportsImpl.h"
 #include "nsIWeakReferenceUtils.h"
 
 class nsIChannel;
 class nsIContentSecurityPolicy;
+class nsICookieSettings;
 class nsILoadGroup;
 class nsIPrincipal;
 class nsIRunnable;
 class nsIScriptContext;
 class nsITabChild;
 class nsIURI;
 class nsPIDOMWindowInner;
 
@@ -45,16 +46,19 @@ struct WorkerLoadInfoData {
 
   // This is the principal of the global (parent worker or a window) loading
   // the worker. It can be null if we are executing a ServiceWorker, otherwise,
   // except for data: URL, it must subsumes the worker principal.
   // If we load a data: URL, mPrincipal will be a null principal.
   nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
   nsCOMPtr<nsIPrincipal> mPrincipal;
 
+  // Taken from the parent context.
+  nsCOMPtr<nsICookieSettings> mCookieSettings;
+
   nsCOMPtr<nsIScriptContext> mScriptContext;
   nsCOMPtr<nsPIDOMWindowInner> mWindow;
   nsCOMPtr<nsIContentSecurityPolicy> mCSP;
   nsCOMPtr<nsIChannel> mChannel;
   nsCOMPtr<nsILoadGroup> mLoadGroup;
 
   class InterfaceRequestor final : public nsIInterfaceRequestor {
     NS_DECL_ISUPPORTS
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -54,16 +54,17 @@
 #include "nsRFPService.h"
 #include "nsSandboxFlags.h"
 #include "nsUTF8Utils.h"
 
 #include "RuntimeService.h"
 #include "ScriptLoader.h"
 #include "mozilla/dom/ServiceWorkerEvents.h"
 #include "mozilla/dom/ServiceWorkerManager.h"
+#include "mozilla/net/CookieSettings.h"
 #include "WorkerCSPEventListener.h"
 #include "WorkerDebugger.h"
 #include "WorkerDebuggerManager.h"
 #include "WorkerError.h"
 #include "WorkerEventTarget.h"
 #include "WorkerNavigator.h"
 #include "WorkerRef.h"
 #include "WorkerRunnable.h"
@@ -2476,16 +2477,17 @@ nsresult WorkerPrivate::GetLoadInfo(JSCo
 
       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.mCookieSettings = document->CookieSettings();
       loadInfo.mOriginAttributes =
           nsContentUtils::GetOriginAttributes(document);
       loadInfo.mParentController = globalWindow->GetController();
       loadInfo.mSecureContext = loadInfo.mWindow->IsSecureContext()
                                     ? WorkerLoadInfo::eSecureContext
                                     : WorkerLoadInfo::eInsecureContext;
     } else {
       // Not a window
@@ -2521,16 +2523,19 @@ nsresult WorkerPrivate::GetLoadInfo(JSCo
         if (NS_FAILED(rv)) {
           return rv;
         }
       }
       loadInfo.mXHRParamsAllowed = true;
       loadInfo.mFromWindow = false;
       loadInfo.mWindowID = UINT64_MAX;
       loadInfo.mStorageAllowed = true;
+      loadInfo.mCookieSettings = mozilla::net::CookieSettings::Create();
+      MOZ_ASSERT(loadInfo.mCookieSettings);
+
       loadInfo.mOriginAttributes = OriginAttributes();
     }
 
     MOZ_ASSERT(loadInfo.mLoadingPrincipal);
     MOZ_ASSERT(isChrome || !loadInfo.mDomain.IsEmpty());
 
     if (!loadInfo.mLoadGroup || aLoadGroupBehavior == OverrideLoadGroup) {
       OverrideLoadInfoLoadGroup(loadInfo, loadInfo.mLoadingPrincipal);
@@ -2540,20 +2545,20 @@ nsresult WorkerPrivate::GetLoadInfo(JSCo
 
     // Top level workers' main script use the document charset for the script
     // uri encoding.
     nsCOMPtr<nsIURI> url;
     rv = nsContentUtils::NewURIWithDocumentCharset(
         getter_AddRefs(url), aScriptURL, document, loadInfo.mBaseURI);
     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_SYNTAX_ERR);
 
-    rv = ChannelFromScriptURLMainThread(loadInfo.mLoadingPrincipal, document,
-                                        loadInfo.mLoadGroup, url, clientInfo,
-                                        ContentPolicyType(aWorkerType),
-                                        getter_AddRefs(loadInfo.mChannel));
+    rv = ChannelFromScriptURLMainThread(
+        loadInfo.mLoadingPrincipal, document, loadInfo.mLoadGroup, url,
+        clientInfo, ContentPolicyType(aWorkerType), loadInfo.mCookieSettings,
+        getter_AddRefs(loadInfo.mChannel));
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = NS_GetFinalChannelURI(loadInfo.mChannel,
                                getter_AddRefs(loadInfo.mResolvedScriptURI));
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = loadInfo.SetPrincipalFromChannel(loadInfo.mChannel);
     NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -734,16 +734,22 @@ class WorkerPrivate : public RelativeTim
   }
 
   bool IsStorageAllowed() const {
     AssertIsOnWorkerThread();
     return mLoadInfo.mStorageAllowed ||
            mLoadInfo.mFirstPartyStorageAccessGranted;
   }
 
+  nsICookieSettings* CookieSettings() const {
+    // Any thread.
+    MOZ_ASSERT(mLoadInfo.mCookieSettings);
+    return mLoadInfo.mCookieSettings;
+  }
+
   const OriginAttributes& GetOriginAttributes() const {
     return mLoadInfo.mOriginAttributes;
   }
 
   // Determine if the SW testing per-window flag is set by devtools
   bool ServiceWorkersTestingInWindow() const {
     return mLoadInfo.mServiceWorkersTestingInWindow;
   }
--- a/dom/workers/remoteworkers/RemoteWorkerChild.cpp
+++ b/dom/workers/remoteworkers/RemoteWorkerChild.cpp
@@ -13,16 +13,17 @@
 #include "mozilla/dom/ServiceWorkerUtils.h"
 #include "mozilla/dom/workerinternals/ScriptLoader.h"
 #include "mozilla/dom/WorkerError.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/dom/WorkerRef.h"
 #include "mozilla/dom/WorkerRunnable.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/ipc/URIUtils.h"
+#include "mozilla/net/CookieSettings.h"
 #include "nsIConsoleReportCollector.h"
 #include "nsIPrincipal.h"
 #include "nsNetUtil.h"
 #include "nsProxyRelease.h"
 
 namespace mozilla {
 
 using namespace ipc;
@@ -265,16 +266,17 @@ nsresult RemoteWorkerChild::ExecWorkerOn
   info.mPrincipalInfo = new PrincipalInfo(aData.principalInfo());
 
   info.mDomain = aData.domain();
   info.mPrincipal = principal;
   info.mLoadingPrincipal = loadingPrincipal;
   info.mStorageAllowed = aData.isStorageAccessAllowed();
   info.mOriginAttributes =
       BasePrincipal::Cast(principal)->OriginAttributesRef();
+  info.mCookieSettings = net::CookieSettings::Create();
 
   // Default CSP permissions for now.  These will be overrided if necessary
   // based on the script CSP headers during load in ScriptLoader.
   info.mEvalAllowed = true;
   info.mReportCSPViolations = false;
   info.mSecureContext = aData.isSecureContext()
                             ? WorkerLoadInfo::eSecureContext
                             : WorkerLoadInfo::eInsecureContext;
@@ -297,17 +299,17 @@ nsresult RemoteWorkerChild::ExecWorkerOn
 
   // Top level workers' main script use the document charset for the script
   // uri encoding.
   rv = ChannelFromScriptURLMainThread(
       info.mLoadingPrincipal, nullptr /* parent document */, info.mLoadGroup,
       info.mResolvedScriptURI, clientInfo,
       aData.isSharedWorker() ? nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER
                              : nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER,
-      getter_AddRefs(info.mChannel));
+      info.mCookieSettings, getter_AddRefs(info.mChannel));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   AutoJSAPI jsapi;
   jsapi.Init();
 
   ErrorResult error;
--- a/dom/xbl/nsXBLService.cpp
+++ b/dom/xbl/nsXBLService.cpp
@@ -1042,16 +1042,17 @@ nsresult nsXBLService::FetchBindingDocum
         nsIContentPolicy::TYPE_XBL,
         nullptr,  // aPerformanceStorage
         loadGroup);
   } else {
     rv = NS_NewChannel(getter_AddRefs(channel), aDocumentURI,
                        nsContentUtils::GetSystemPrincipal(),
                        nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS,
                        nsIContentPolicy::TYPE_XBL,
+                       nullptr,  // nsICookieSettings
                        nullptr,  // PerformanceStorage
                        loadGroup);
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!aForceSyncLoad) {
     // We can be asynchronous
     nsXBLStreamListener* xblListener =
--- a/dom/xhr/XMLHttpRequest.cpp
+++ b/dom/xhr/XMLHttpRequest.cpp
@@ -2,16 +2,18 @@
 /* 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 "XMLHttpRequest.h"
 #include "XMLHttpRequestMainThread.h"
 #include "XMLHttpRequestWorker.h"
+#include "mozilla/net/CookieSettings.h"
+#include "nsGlobalWindowInner.h"
 
 namespace mozilla {
 namespace dom {
 
 /* static */
 already_AddRefed<XMLHttpRequest> XMLHttpRequest::Constructor(
     const GlobalObject& aGlobal, const MozXMLHttpRequestParameters& aParams,
     ErrorResult& aRv) {
@@ -20,18 +22,33 @@ already_AddRefed<XMLHttpRequest> XMLHttp
         do_QueryInterface(aGlobal.GetAsSupports());
     nsCOMPtr<nsIScriptObjectPrincipal> principal =
         do_QueryInterface(aGlobal.GetAsSupports());
     if (!global || !principal) {
       aRv.Throw(NS_ERROR_FAILURE);
       return nullptr;
     }
 
+    nsCOMPtr<nsICookieSettings> cookieSettings;
+    nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(global);
+    if (window) {
+      Document* document = window->GetExtantDoc();
+      if (NS_WARN_IF(!document)) {
+        aRv.Throw(NS_ERROR_FAILURE);
+        return nullptr;
+      }
+
+      cookieSettings = document->CookieSettings();
+    } else {
+      // We are here because this is a sandbox.
+      cookieSettings = net::CookieSettings::Create();
+    }
+
     RefPtr<XMLHttpRequestMainThread> req = new XMLHttpRequestMainThread();
-    req->Construct(principal->GetPrincipal(), global);
+    req->Construct(principal->GetPrincipal(), global, cookieSettings);
     req->InitParameters(aParams.mMozAnon, aParams.mMozSystem);
     return req.forget();
   }
 
   return XMLHttpRequestWorker::Construct(aGlobal, aParams, aRv);
 }
 
 }  // namespace dom
--- a/dom/xhr/XMLHttpRequestMainThread.cpp
+++ b/dom/xhr/XMLHttpRequestMainThread.cpp
@@ -2329,24 +2329,26 @@ nsresult XMLHttpRequestMainThread::Creat
                        nullptr,  // aPerformanceStorage
                        loadGroup,
                        nullptr,  // aCallbacks
                        loadFlags);
   } else if (mClientInfo.isSome()) {
     rv = NS_NewChannel(getter_AddRefs(mChannel), mRequestURL, mPrincipal,
                        mClientInfo.ref(), mController, secFlags,
                        nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST,
+                       mCookieSettings,
                        mPerformanceStorage,  // aPerformanceStorage
                        loadGroup,
                        nullptr,  // aCallbacks
                        loadFlags);
   } else {
     // Otherwise use the principal.
     rv = NS_NewChannel(getter_AddRefs(mChannel), mRequestURL, mPrincipal,
                        secFlags, nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST,
+                       mCookieSettings,
                        mPerformanceStorage,  // aPerformanceStorage
                        loadGroup,
                        nullptr,  // aCallbacks
                        loadFlags);
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (mCSPEventListener) {
--- a/dom/xhr/XMLHttpRequestMainThread.h
+++ b/dom/xhr/XMLHttpRequestMainThread.h
@@ -194,24 +194,26 @@ class XMLHttpRequestMainThread final : p
     eRedirect,
     eTerminated,
     ENUM_MAX
   };
 
   XMLHttpRequestMainThread();
 
   void Construct(nsIPrincipal* aPrincipal, nsIGlobalObject* aGlobalObject,
-                 nsIURI* aBaseURI = nullptr, nsILoadGroup* aLoadGroup = nullptr,
+                 nsICookieSettings* aCookieSettings, nsIURI* aBaseURI = nullptr,
+                 nsILoadGroup* aLoadGroup = nullptr,
                  PerformanceStorage* aPerformanceStorage = nullptr,
                  nsICSPEventListener* aCSPEventListener = nullptr) {
     MOZ_ASSERT(aPrincipal);
     mPrincipal = aPrincipal;
     BindToOwner(aGlobalObject);
     mBaseURI = aBaseURI;
     mLoadGroup = aLoadGroup;
+    mCookieSettings = aCookieSettings;
     mPerformanceStorage = aPerformanceStorage;
     mCSPEventListener = aCSPEventListener;
   }
 
   void InitParameters(bool aAnon, bool aSystem);
 
   void SetParameters(bool aAnon, bool aSystem) {
     mIsAnon = aAnon || aSystem;
@@ -489,16 +491,18 @@ class XMLHttpRequestMainThread final : p
   nsCOMPtr<nsIPrincipal> mPrincipal;
   nsCOMPtr<nsIChannel> mChannel;
   nsCString mRequestMethod;
   nsCOMPtr<nsIURI> mRequestURL;
   RefPtr<Document> mResponseXML;
 
   nsCOMPtr<nsIStreamListener> mXMLParserStreamListener;
 
+  nsCOMPtr<nsICookieSettings> mCookieSettings;
+
   RefPtr<PerformanceStorage> mPerformanceStorage;
   nsCOMPtr<nsICSPEventListener> mCSPEventListener;
 
   // used to implement getAllResponseHeaders()
   class nsHeaderVisitor : public nsIHttpHeaderVisitor {
     struct HeaderEntry final {
       nsCString mName;
       nsCString mValue;
--- a/dom/xhr/XMLHttpRequestWorker.cpp
+++ b/dom/xhr/XMLHttpRequestWorker.cpp
@@ -774,16 +774,17 @@ bool Proxy::Init() {
   if (ownerWindow && !ownerWindow->IsCurrentInnerWindow()) {
     NS_WARNING("Window has navigated, cannot create XHR here.");
     return false;
   }
 
   mXHR = new XMLHttpRequestMainThread();
   mXHR->Construct(mWorkerPrivate->GetPrincipal(),
                   ownerWindow ? ownerWindow->AsGlobal() : nullptr,
+                  mWorkerPrivate->CookieSettings(),
                   mWorkerPrivate->GetBaseURI(), mWorkerPrivate->GetLoadGroup(),
                   mWorkerPrivate->GetPerformanceStorage(),
                   mWorkerPrivate->CSPEventListener());
 
   mXHR->SetParameters(mMozAnon, mMozSystem);
   mXHR->SetClientInfoAndController(mClientInfo, mController);
 
   ErrorResult rv;
--- a/dom/xml/nsXMLPrettyPrinter.cpp
+++ b/dom/xml/nsXMLPrettyPrinter.cpp
@@ -63,18 +63,19 @@ nsresult nsXMLPrettyPrinter::PrettyPrint
   rv = NS_NewURI(
       getter_AddRefs(xslUri),
       NS_LITERAL_CSTRING("chrome://global/content/xml/XMLPrettyPrint.xsl"));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<Document> xslDocument;
   rv = nsSyncLoadService::LoadDocument(
       xslUri, nsIContentPolicy::TYPE_XSLT, nsContentUtils::GetSystemPrincipal(),
-      nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL, nullptr, true,
-      mozilla::net::RP_Unset, getter_AddRefs(xslDocument));
+      nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL, nullptr,
+      aDocument->CookieSettings(), true, mozilla::net::RP_Unset,
+      getter_AddRefs(xslDocument));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Transform the document
   RefPtr<txMozillaXSLTProcessor> transformer = new txMozillaXSLTProcessor();
   ErrorResult err;
   transformer->ImportStylesheet(*xslDocument, err);
   if (NS_WARN_IF(err.Failed())) {
     return err.StealNSResult();
--- a/dom/xslt/xml/txXMLParser.cpp
+++ b/dom/xslt/xml/txXMLParser.cpp
@@ -33,17 +33,18 @@ nsresult txParseDocumentFromURI(const ns
 
   // Raw pointer, we want the resulting txXPathNode to hold a reference to
   // the document.
   Document* theDocument = nullptr;
   nsAutoSyncOperation sync(loaderDocument);
   rv = nsSyncLoadService::LoadDocument(
       documentURI, nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST,
       loaderDocument->NodePrincipal(),
-      nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS, loadGroup, true,
+      nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS, loadGroup,
+      loaderDocument->CookieSettings(), true,
       loaderDocument->GetReferrerPolicy(), &theDocument);
 
   if (NS_FAILED(rv)) {
     aErrMsg.AppendLiteral("Document load of ");
     aErrMsg.Append(aHref);
     aErrMsg.AppendLiteral(" failed.");
     return NS_FAILED(rv) ? rv : NS_ERROR_FAILURE;
   }
--- a/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp
+++ b/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp
@@ -558,17 +558,18 @@ nsresult txSyncCompileObserver::loadURI(
   if (mProcessor) {
     source = mProcessor->GetSourceContentModel();
   }
   nsAutoSyncOperation sync(source ? source->OwnerDoc() : nullptr);
   nsCOMPtr<Document> document;
 
   rv = nsSyncLoadService::LoadDocument(
       uri, nsIContentPolicy::TYPE_XSLT, referrerPrincipal,
-      nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS, nullptr, false,
+      nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS, nullptr,
+      source ? source->OwnerDoc()->CookieSettings() : nullptr, false,
       aReferrerPolicy, getter_AddRefs(document));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = handleNode(document, aCompiler);
   if (NS_FAILED(rv)) {
     nsAutoCString spec;
     uri->GetSpec(spec);
     aCompiler->cancel(rv, nullptr, NS_ConvertUTF8toUTF16(spec).get());
--- a/extensions/pref/autoconfig/src/nsAutoConfig.cpp
+++ b/extensions/pref/autoconfig/src/nsAutoConfig.cpp
@@ -244,16 +244,17 @@ nsresult nsAutoConfig::downloadAutoConfi
   }
 
   MOZ_LOG(MCD, LogLevel::Debug, ("running MCD url %s\n", mConfigURL.get()));
   // open a channel for the url
   rv = NS_NewChannel(
       getter_AddRefs(channel), url, nsContentUtils::GetSystemPrincipal(),
       nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
       nsIContentPolicy::TYPE_OTHER,
+      nullptr,  // nsICookieSettings
       nullptr,  // PerformanceStorage
       nullptr,  // loadGroup
       nullptr,  // aCallbacks
       nsIRequest::INHIBIT_PERSISTENT_CACHING | nsIRequest::LOAD_BYPASS_CACHE);
 
   if (NS_FAILED(rv)) return rv;
 
   rv = channel->AsyncOpen(this);
--- a/image/imgLoader.cpp
+++ b/image/imgLoader.cpp
@@ -830,20 +830,21 @@ static nsresult NewImageChannel(
           aTriggeringPrincipal->OriginAttributesRef());
     }
   } else {
     // either we are loading something inside a document, in which case
     // we should always have a requestingNode, or we are loading something
     // outside a document, in which case the triggeringPrincipal and
     // triggeringPrincipal should always be the systemPrincipal.
     // However, there are exceptions: one is Notifications which create a
-    // channel in the parent prcoess in which case we can't get a
+    // channel in the parent process in which case we can't get a
     // requestingNode.
     rv = NS_NewChannel(aResult, aURI, nsContentUtils::GetSystemPrincipal(),
                        securityFlags, aPolicyType,
+                       nullptr,  // nsICookieSettings
                        nullptr,  // PerformanceStorage
                        nullptr,  // loadGroup
                        callbacks, aLoadFlags);
 
     if (NS_FAILED(rv)) {
       return rv;
     }
 
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -233,16 +233,17 @@ class MOZ_STACK_CLASS ComponentLoaderInf
     return mScriptChannel;
   }
   nsresult EnsureScriptChannel() {
     BEGIN_ENSURE(ScriptChannel, IOService, URI);
     return NS_NewChannel(getter_AddRefs(mScriptChannel), mURI,
                          nsContentUtils::GetSystemPrincipal(),
                          nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                          nsIContentPolicy::TYPE_SCRIPT,
+                         nullptr,  // nsICookieSettings
                          nullptr,  // aPerformanceStorage
                          nullptr,  // aLoadGroup
                          nullptr,  // aCallbacks
                          nsIRequest::LOAD_NORMAL, mIOService);
   }
 
   nsIURI* ResolvedURI() {
     MOZ_ASSERT(mResolvedURI);
--- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -412,16 +412,17 @@ nsresult mozJSSubScriptLoader::ReadScrip
   // We create a channel and call SetContentType, to avoid expensive MIME type
   // lookups (bug 632490).
   nsCOMPtr<nsIChannel> channel;
   nsresult rv;
   rv = NS_NewChannel(getter_AddRefs(channel), uri,
                      nsContentUtils::GetSystemPrincipal(),
                      nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                      nsIContentPolicy::TYPE_OTHER,
+                     nullptr,  // nsICookieSettings
                      nullptr,  // aPerformanceStorage
                      nullptr,  // aLoadGroup
                      nullptr,  // aCallbacks
                      nsIRequest::LOAD_NORMAL, serv);
 
   if (!NS_SUCCEEDED(rv)) {
     return rv;
   }
@@ -451,16 +452,17 @@ bool mozJSSubScriptLoader::ReadScript(ns
   // lookups (bug 632490).
   nsCOMPtr<nsIChannel> chan;
   nsCOMPtr<nsIInputStream> instream;
   nsresult rv;
   rv = NS_NewChannel(getter_AddRefs(chan), uri,
                      nsContentUtils::GetSystemPrincipal(),
                      nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                      nsIContentPolicy::TYPE_OTHER,
+                     nullptr,  // nsICookieSettings
                      nullptr,  // PerformanceStorage
                      nullptr,  // aLoadGroup
                      nullptr,  // aCallbacks
                      nsIRequest::LOAD_NORMAL, serv);
 
   if (NS_SUCCEEDED(rv)) {
     chan->SetContentType(NS_LITERAL_CSTRING("application/javascript"));
     rv = chan->Open(getter_AddRefs(instream));
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -1388,25 +1388,28 @@ nsresult Loader::LoadSheet(SheetLoadData
       return LoadSheet(existingData, eSheetNeedsParser, aIsPreload);
     }
     // All done here; once the load completes we'll be marked complete
     // automatically
     return NS_OK;
   }
 
   nsCOMPtr<nsILoadGroup> loadGroup;
+  nsCOMPtr<nsICookieSettings> cookieSettings;
   if (mDocument) {
     loadGroup = mDocument->GetDocumentLoadGroup();
     // load for a document with no loadgrup indicates that something is
     // completely bogus, let's bail out early.
     if (!loadGroup) {
       LOG_ERROR(("  Failed to query loadGroup from document"));
       SheetComplete(aLoadData, NS_ERROR_UNEXPECTED);
       return NS_ERROR_UNEXPECTED;
     }
+
+    cookieSettings = mDocument->CookieSettings();
   }
 #ifdef DEBUG
   mSyncCallback = true;
 #endif
 
   CORSMode ourCORSMode = aLoadData->mSheet->GetCORSMode();
   nsSecurityFlags securityFlags =
       ourCORSMode == CORS_NONE
@@ -1438,17 +1441,17 @@ nsresult Loader::LoadSheet(SheetLoadData
         nsIChannel::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI);
   } else {
     // either we are loading something inside a document, in which case
     // we should always have a requestingNode, or we are loading something
     // outside a document, in which case the loadingPrincipal and the
     // triggeringPrincipal should always be the systemPrincipal.
     rv = NS_NewChannel(getter_AddRefs(channel), aLoadData->mURI,
                        nsContentUtils::GetSystemPrincipal(), securityFlags,
-                       contentPolicyType,
+                       contentPolicyType, cookieSettings,
                        nullptr,  // aPerformanceStorage
                        loadGroup,
                        nullptr,  // aCallbacks
                        nsIChannel::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI);
   }
 
   if (NS_FAILED(rv)) {
 #ifdef DEBUG
--- a/netwerk/base/LoadInfo.cpp
+++ b/netwerk/base/LoadInfo.cpp
@@ -781,31 +781,56 @@ LoadInfo::GetCookiePolicy(uint32_t* aRes
                  ? nsILoadInfo::SEC_COOKIES_SAME_ORIGIN
                  : nsILoadInfo::SEC_COOKIES_INCLUDE;
   }
 
   *aResult = policy;
   return NS_OK;
 }
 
+namespace {
+
+already_AddRefed<nsICookieSettings> CreateCookieSettings(
+    nsContentPolicyType aContentPolicyType) {
+  if (StaticPrefs::network_cookieSettings_unblocked_for_testing()) {
+    return CookieSettings::Create();
+  }
+
+  // These contentPolictTypes require a real CookieSettings because favicon and
+  // save-as requests must send cookies. Anything else should not send/receive
+  // cookies.
+  if (aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON ||
+      aContentPolicyType == nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD) {
+    return CookieSettings::Create();
+  }
+
+  return CookieSettings::CreateBlockingAll();
+}
+
+}  // namespace
+
 NS_IMETHODIMP
 LoadInfo::GetCookieSettings(nsICookieSettings** aCookieSettings) {
   if (!mCookieSettings) {
-    if (StaticPrefs::network_cookieSettings_unblocked_for_testing()) {
-      mCookieSettings = CookieSettings::Create();
-    } else {
-      mCookieSettings = CookieSettings::CreateBlockingAll();
-    }
+    mCookieSettings = CreateCookieSettings(mInternalContentPolicyType);
   }
 
   nsCOMPtr<nsICookieSettings> cookieSettings = mCookieSettings;
   cookieSettings.forget(aCookieSettings);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+LoadInfo::SetCookieSettings(nsICookieSettings* aCookieSettings) {
+  MOZ_ASSERT(aCookieSettings);
+  // We allow the overwrite of CookieSettings.
+  mCookieSettings = aCookieSettings;
+  return NS_OK;
+}
+
 void LoadInfo::SetIncludeCookiesSecFlag() {
   MOZ_ASSERT((mSecurityFlags & sCookiePolicyMask) ==
              nsILoadInfo::SEC_COOKIES_DEFAULT);
   mSecurityFlags =
       (mSecurityFlags & ~sCookiePolicyMask) | nsILoadInfo::SEC_COOKIES_INCLUDE;
 }
 
 NS_IMETHODIMP
--- a/netwerk/base/NetworkConnectivityService.cpp
+++ b/netwerk/base/NetworkConnectivityService.cpp
@@ -186,16 +186,17 @@ static inline already_AddRefed<nsIChanne
   rv = NS_NewURI(getter_AddRefs(uri), url);
   NS_ENSURE_SUCCESS(rv, nullptr);
 
   nsCOMPtr<nsIChannel> channel;
   rv = NS_NewChannel(
       getter_AddRefs(channel), uri, nsContentUtils::GetSystemPrincipal(),
       nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
       nsIContentPolicy::TYPE_OTHER,
+      nullptr,  // nsICookieSettings
       nullptr,  // aPerformanceStorage
       nullptr,  // aLoadGroup
       nullptr,
       nsIRequest::LOAD_BYPASS_CACHE |    // don't read from the cache
           nsIRequest::INHIBIT_CACHING |  // don't write the response to cache
           nsIRequest::LOAD_ANONYMOUS);   // prevent privacy leaks
 
   NS_ENSURE_SUCCESS(rv, nullptr);
--- a/netwerk/base/Predictor.cpp
+++ b/netwerk/base/Predictor.cpp
@@ -1241,17 +1241,18 @@ nsresult Predictor::Prefetch(nsIURI *uri
   uri->GetAsciiSpec(strUri);
   referrer->GetAsciiSpec(strReferrer);
   PREDICTOR_LOG(("Predictor::Prefetch uri=%s referrer=%s verifier=%p",
                  strUri.get(), strReferrer.get(), verifier));
   nsCOMPtr<nsIChannel> channel;
   nsresult rv = NS_NewChannel(
       getter_AddRefs(channel), uri, nsContentUtils::GetSystemPrincipal(),
       nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
-      nsIContentPolicy::TYPE_OTHER, nullptr, /* aPerformanceStorage */
+      nsIContentPolicy::TYPE_OTHER, nullptr, /* nsICookieSettings */
+      nullptr,                               /* aPerformanceStorage */
       nullptr,                               /* aLoadGroup */
       nullptr,                               /* aCallbacks */
       nsIRequest::LOAD_BACKGROUND);
 
   if (NS_FAILED(rv)) {
     PREDICTOR_LOG(
         ("    NS_NewChannel failed rv=0x%" PRIX32, static_cast<uint32_t>(rv)));
     return rv;
--- a/netwerk/base/nsILoadInfo.idl
+++ b/netwerk/base/nsILoadInfo.idl
@@ -426,17 +426,17 @@ interface nsILoadInfo : nsISupports
    * otherwise.
    */
   [infallible] readonly attribute unsigned long cookiePolicy;
 
   /**
    * The cookie settings inherited from the top-level document's loadInfo.
    * It cannot be null.
    */
-  readonly attribute nsICookieSettings cookieSettings;
+  attribute nsICookieSettings cookieSettings;
 
   /**
    * If forceInheritPrincipal is true, the data coming from the channel should
    * inherit its principal, even when the data is loaded over http:// or another
    * protocol that would normally use a URI-based principal.
    *
    * See the documentation for principalToInherit, which describes exactly what
    * principal is inherited.
--- a/netwerk/base/nsIncrementalDownload.cpp
+++ b/netwerk/base/nsIncrementalDownload.cpp
@@ -215,16 +215,17 @@ nsresult nsIncrementalDownload::ProcessT
 
   // Fetch next chunk
 
   nsCOMPtr<nsIChannel> channel;
   nsresult rv = NS_NewChannel(getter_AddRefs(channel), mFinalURI,
                               nsContentUtils::GetSystemPrincipal(),
                               nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                               nsIContentPolicy::TYPE_OTHER,
+                              nullptr,  // nsICookieSettings
                               nullptr,  // PerformanceStorage
                               nullptr,  // loadGroup
                               this,     // aCallbacks
                               mLoadFlags);
 
   if (NS_FAILED(rv)) return rv;
 
   nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(channel, &rv);
--- a/netwerk/base/nsNetUtil.cpp
+++ b/netwerk/base/nsNetUtil.cpp
@@ -293,64 +293,68 @@ void AssertLoadingPrincipalAndClientInfo
 }
 
 }  // namespace
 
 nsresult NS_NewChannel(nsIChannel **outChannel, nsIURI *aUri,
                        nsIPrincipal *aLoadingPrincipal,
                        nsSecurityFlags aSecurityFlags,
                        nsContentPolicyType aContentPolicyType,
-                       PerformanceStorage *aPerformanceStorage /* nullptr */,
+                       nsICookieSettings *aCookieSettings /* = nullptr */,
+                       PerformanceStorage *aPerformanceStorage /* = nullptr */,
                        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, aPerformanceStorage,
-                               aLoadGroup, aCallbacks, aLoadFlags, aIoService);
+  return NS_NewChannelInternal(
+      outChannel, aUri,
+      nullptr,  // aLoadingNode,
+      aLoadingPrincipal,
+      nullptr,  // aTriggeringPrincipal
+      Maybe<ClientInfo>(), Maybe<ServiceWorkerDescriptor>(), aSecurityFlags,
+      aContentPolicyType, aCookieSettings, aPerformanceStorage, aLoadGroup,
+      aCallbacks, aLoadFlags, aIoService);
 }
 
 nsresult NS_NewChannel(nsIChannel **outChannel, nsIURI *aUri,
                        nsIPrincipal *aLoadingPrincipal,
                        const ClientInfo &aLoadingClientInfo,
                        const Maybe<ServiceWorkerDescriptor> &aController,
                        nsSecurityFlags aSecurityFlags,
                        nsContentPolicyType aContentPolicyType,
-                       PerformanceStorage *aPerformanceStorage /* nullptr */,
+                       nsICookieSettings *aCookieSettings /* = nullptr */,
+                       PerformanceStorage *aPerformanceStorage /* = nullptr */,
                        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, aPerformanceStorage,
-                               aLoadGroup, aCallbacks, aLoadFlags, aIoService);
+                               aContentPolicyType, aCookieSettings,
+                               aPerformanceStorage, 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,
-    PerformanceStorage *aPerformanceStorage /* nullptr */,
+    nsICookieSettings *aCookieSettings /* = nullptr */,
+    PerformanceStorage *aPerformanceStorage /* = nullptr */,
     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);
@@ -384,19 +388,26 @@ nsresult NS_NewChannelInternal(
   MOZ_DIAGNOSTIC_ASSERT(!(channelLoadFlags & nsIChannel::LOAD_REPLACE));
 #endif
 
   if (aLoadFlags != nsIRequest::LOAD_NORMAL) {
     rv = channel->SetLoadFlags(aLoadFlags);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  if (aPerformanceStorage) {
+  if (aPerformanceStorage || aCookieSettings) {
     nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
-    loadInfo->SetPerformanceStorage(aPerformanceStorage);
+
+    if (aPerformanceStorage) {
+      loadInfo->SetPerformanceStorage(aPerformanceStorage);
+    }
+
+    if (aCookieSettings) {
+      loadInfo->SetCookieSettings(aCookieSettings);
+    }
   }
 
   channel.forget(outChannel);
   return NS_OK;
 }
 
 nsresult /*NS_NewChannelWithNodeAndTriggeringPrincipal */
 NS_NewChannelWithTriggeringPrincipal(
@@ -410,79 +421,83 @@ NS_NewChannelWithTriggeringPrincipal(
     nsIIOService *aIoService /* = nullptr */) {
   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,
-      aPerformanceStorage, aLoadGroup, aCallbacks, aLoadFlags, aIoService);
+      aLoadingNode->OwnerDoc()->CookieSettings(), aPerformanceStorage,
+      aLoadGroup, aCallbacks, aLoadFlags, aIoService);
 }
 
 // See NS_NewChannelInternal for usage and argument description
 nsresult NS_NewChannelWithTriggeringPrincipal(
     nsIChannel **outChannel, nsIURI *aUri, nsIPrincipal *aLoadingPrincipal,
     nsIPrincipal *aTriggeringPrincipal, nsSecurityFlags aSecurityFlags,
     nsContentPolicyType aContentPolicyType,
+    nsICookieSettings *aCookieSettings /* = nullptr */,
     PerformanceStorage *aPerformanceStorage /* = nullptr */,
     nsILoadGroup *aLoadGroup /* = nullptr */,
     nsIInterfaceRequestor *aCallbacks /* = nullptr */,
     nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
     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,
-      aPerformanceStorage, aLoadGroup, aCallbacks, aLoadFlags, aIoService);
+      aCookieSettings, aPerformanceStorage, aLoadGroup, aCallbacks, aLoadFlags,
+      aIoService);
 }
 
 // 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,
+    nsICookieSettings *aCookieSettings /* = nullptr */,
     PerformanceStorage *aPerformanceStorage /* = nullptr */,
     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, aPerformanceStorage,
-                               aLoadGroup, aCallbacks, aLoadFlags, aIoService);
+  return NS_NewChannelInternal(
+      outChannel, aUri,
+      nullptr,  // aLoadingNode
+      aLoadingPrincipal, aTriggeringPrincipal, loadingClientInfo, aController,
+      aSecurityFlags, aContentPolicyType, aCookieSettings, aPerformanceStorage,
+      aLoadGroup, aCallbacks, aLoadFlags, aIoService);
 }
 
 nsresult NS_NewChannel(nsIChannel **outChannel, nsIURI *aUri,
                        nsINode *aLoadingNode, nsSecurityFlags aSecurityFlags,
                        nsContentPolicyType aContentPolicyType,
                        PerformanceStorage *aPerformanceStorage /* = nullptr */,
                        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, aPerformanceStorage, aLoadGroup, aCallbacks,
-      aLoadFlags, aIoService);
+      aContentPolicyType, aLoadingNode->OwnerDoc()->CookieSettings(),
+      aPerformanceStorage, aLoadGroup, aCallbacks, aLoadFlags, aIoService);
 }
 
 nsresult NS_GetIsDocumentChannel(nsIChannel *aChannel, bool *aIsDocument) {
   // Check if this channel is going to be used to create a document. If it has
   // LOAD_DOCUMENT_URI set it is trivially creating a document. If
   // LOAD_HTML_OBJECT_DATA is set it may or may not be used to create a
   // document, depending on its MIME type.
 
@@ -904,16 +919,17 @@ nsresult NS_NewStreamLoaderInternal(
     nsLoadFlags aLoadFlags /* = nsIRequest::LOAD_NORMAL */,
     nsIURI *aReferrer /* = nullptr */) {
   nsCOMPtr<nsIChannel> channel;
   nsresult rv = NS_NewChannelInternal(
       getter_AddRefs(channel), aUri, aLoadingNode, aLoadingPrincipal,
       nullptr,  // aTriggeringPrincipal
       Maybe<ClientInfo>(), Maybe<ServiceWorkerDescriptor>(), aSecurityFlags,
       aContentPolicyType,
+      nullptr,  // nsICookieSettings
       nullptr,  // PerformanceStorage
       aLoadGroup, aCallbacks, aLoadFlags);
 
   NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
   if (httpChannel) {
     rv = httpChannel->SetReferrer(aReferrer);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
--- a/netwerk/base/nsNetUtil.h
+++ b/netwerk/base/nsNetUtil.h
@@ -27,16 +27,17 @@
 #include "nsString.h"
 
 class nsIPrincipal;
 class nsIAsyncStreamCopier;
 class nsIAuthPrompt;
 class nsIAuthPrompt2;
 class nsIChannel;
 class nsIChannelPolicy;
+class nsICookieSettings;
 class nsIDownloadObserver;
 class nsIEventTarget;
 class nsIFileProtocolHandler;
 class nsIFileStream;
 class nsIHttpChannel;
 class nsIInputStream;
 class nsIInputStreamPump;
 class nsIInterfaceRequestor;
@@ -161,16 +162,17 @@ nsresult NS_GetSanitizedURIStringFromURI
  * 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,
+    nsICookieSettings *aCookieSettings = nullptr,
     mozilla::dom::PerformanceStorage *aPerformanceStorage = nullptr,
     nsILoadGroup *aLoadGroup = nullptr,
     nsIInterfaceRequestor *aCallbacks = nullptr,
     nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL,
     nsIIOService *aIoService = nullptr);
 
 // See NS_NewChannelInternal for usage and argument description
 nsresult NS_NewChannelInternal(
@@ -193,29 +195,31 @@ NS_NewChannelWithTriggeringPrincipal(
     nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL,
     nsIIOService *aIoService = nullptr);
 
 // See NS_NewChannelInternal for usage and argument description
 nsresult NS_NewChannelWithTriggeringPrincipal(
     nsIChannel **outChannel, nsIURI *aUri, nsIPrincipal *aLoadingPrincipal,
     nsIPrincipal *aTriggeringPrincipal, nsSecurityFlags aSecurityFlags,
     nsContentPolicyType aContentPolicyType,
+    nsICookieSettings *aCookieSettings = nullptr,
     mozilla::dom::PerformanceStorage *aPerformanceStorage = nullptr,
     nsILoadGroup *aLoadGroup = nullptr,
     nsIInterfaceRequestor *aCallbacks = nullptr,
     nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL,
     nsIIOService *aIoService = nullptr);
 
 // See NS_NewChannelInternal for usage and argument description
 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,
+    nsICookieSettings *aCookieSettings = nullptr,
     mozilla::dom::PerformanceStorage *aPerformanceStorage = nullptr,
     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(
@@ -226,28 +230,30 @@ nsresult NS_NewChannel(
     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,
     nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType,
+    nsICookieSettings *aCookieSettings = nullptr,
     mozilla::dom::PerformanceStorage *aPerformanceStorage = nullptr,
     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,
+    nsICookieSettings *aCookieSettings = nullptr,
     mozilla::dom::PerformanceStorage *aPerformanceStorage = nullptr,
     nsILoadGroup *aLoadGroup = nullptr,
     nsIInterfaceRequestor *aCallbacks = nullptr,
     nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL,
     nsIIOService *aIoService = nullptr);
 
 nsresult NS_GetIsDocumentChannel(nsIChannel *aChannel, bool *aIsDocument);
 
--- a/netwerk/base/nsPACMan.cpp
+++ b/netwerk/base/nsPACMan.cpp
@@ -632,17 +632,18 @@ void nsPACMan::ContinueLoadingAfterPACUr
       // NOTE: This results in GetProxyForURI being called
       if (pacURI) {
         nsresult rv = pacURI->GetSpec(mNormalPACURISpec);
         MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
         NS_NewChannel(getter_AddRefs(channel), pacURI,
                       nsContentUtils::GetSystemPrincipal(),
                       nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                       nsIContentPolicy::TYPE_OTHER,
-                      nullptr,  // PerformanceStorage,
+                      nullptr,  // nsICookieSettings
+                      nullptr,  // PerformanceStorage
                       nullptr,  // aLoadGroup
                       nullptr,  // aCallbacks
                       nsIRequest::LOAD_NORMAL, ios);
       } else {
         LOG(("nsPACMan::StartLoading Failed pacspec uri conversion %s\n",
              mPACURISpec.get()));
       }
 
--- a/netwerk/cookie/CookieSettings.cpp
+++ b/netwerk/cookie/CookieSettings.cpp
@@ -35,46 +35,81 @@ class PermissionComparator {
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return false;
     }
 
     return equals;
   }
 };
 
+class ReleaseCookiePermissions final : public Runnable {
+ public:
+  explicit ReleaseCookiePermissions(nsTArray<RefPtr<nsIPermission>>& aArray)
+      : Runnable("ReleaseCookiePermissions") {
+    mArray.SwapElements(aArray);
+  }
+
+  NS_IMETHOD Run() override {
+    MOZ_ASSERT(NS_IsMainThread());
+    mArray.Clear();
+    return NS_OK;
+  }
+
+ private:
+  nsTArray<RefPtr<nsIPermission>> mArray;
+};
+
 }  // namespace
 
 // static
 already_AddRefed<nsICookieSettings> CookieSettings::CreateBlockingAll() {
+  MOZ_ASSERT(NS_IsMainThread());
+
   RefPtr<CookieSettings> cookieSettings =
       new CookieSettings(nsICookieService::BEHAVIOR_REJECT, eFixed);
   return cookieSettings.forget();
 }
 
 // static
 already_AddRefed<nsICookieSettings> CookieSettings::Create() {
+  MOZ_ASSERT(NS_IsMainThread());
+
   RefPtr<CookieSettings> cookieSettings = new CookieSettings(
       StaticPrefs::network_cookie_cookieBehavior(), eProgressive);
   return cookieSettings.forget();
 }
 
 CookieSettings::CookieSettings(uint32_t aCookieBehavior, State aState)
-    : mCookieBehavior(aCookieBehavior), mState(aState) {}
+    : mCookieBehavior(aCookieBehavior), mState(aState) {
+  MOZ_ASSERT(NS_IsMainThread());
+}
 
-CookieSettings::~CookieSettings() = default;
+CookieSettings::~CookieSettings() {
+  if (!NS_IsMainThread() && !mCookiePermissions.IsEmpty()) {
+    nsCOMPtr<nsIEventTarget> systemGroupEventTarget =
+        mozilla::SystemGroup::EventTargetFor(mozilla::TaskCategory::Other);
+    MOZ_ASSERT(systemGroupEventTarget);
+
+    RefPtr<Runnable> r = new ReleaseCookiePermissions(mCookiePermissions);
+    MOZ_ASSERT(mCookiePermissions.IsEmpty());
+
+    systemGroupEventTarget->Dispatch(r.forget());
+  }
+}
 
 NS_IMETHODIMP
 CookieSettings::GetCookieBehavior(uint32_t* aCookieBehavior) {
   *aCookieBehavior = mCookieBehavior;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 CookieSettings::CookiePermission(nsIPrincipal* aPrincipal,
                                  uint32_t* aCookiePermission) {
+  MOZ_ASSERT(NS_IsMainThread());
   NS_ENSURE_ARG_POINTER(aPrincipal);
   NS_ENSURE_ARG_POINTER(aCookiePermission);
 
   *aCookiePermission = nsIPermissionManager::UNKNOWN_ACTION;
 
   nsresult rv;
 
   // Let's see if we know this permission.
@@ -113,16 +148,18 @@ CookieSettings::CookiePermission(nsIPrin
   if (permission) {
     mCookiePermissions.AppendElement(permission);
   }
 
   return NS_OK;
 }
 
 void CookieSettings::Serialize(CookieSettingsArgs& aData) {
+  MOZ_ASSERT(NS_IsMainThread());
+
   aData.isFixed() = mState == eFixed;
   aData.cookieBehavior() = mCookieBehavior;
 
   for (const RefPtr<nsIPermission>& permission : mCookiePermissions) {
     nsCOMPtr<nsIPrincipal> principal;
     nsresult rv = permission->GetPrincipal(getter_AddRefs(principal));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       continue;
@@ -142,16 +179,18 @@ void CookieSettings::Serialize(CookieSet
 
     aData.cookiePermissions().AppendElement(
         CookiePermissionData(principalInfo, cookiePermission));
   }
 }
 
 /* static */ void CookieSettings::Deserialize(
     const CookieSettingsArgs& aData, nsICookieSettings** aCookieSettings) {
+  MOZ_ASSERT(NS_IsMainThread());
+
   CookiePermissionList list;
   for (const CookiePermissionData& data : aData.cookiePermissions()) {
     nsCOMPtr<nsIPrincipal> principal =
         PrincipalInfoToPrincipal(data.principalInfo());
     if (NS_WARN_IF(!principal)) {
       continue;
     }
 
@@ -168,16 +207,17 @@ void CookieSettings::Serialize(CookieSet
       aData.cookieBehavior(), aData.isFixed() ? eFixed : eProgressive);
 
   cookieSettings->mCookiePermissions.SwapElements(list);
 
   cookieSettings.forget(aCookieSettings);
 }
 
 void CookieSettings::Merge(const CookieSettingsArgs& aData) {
+  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mCookieBehavior == aData.cookieBehavior());
 
   if (mState == eFixed) {
     return;
   }
 
   PermissionComparator comparator;
 
--- a/netwerk/cookie/CookieSettings.h
+++ b/netwerk/cookie/CookieSettings.h
@@ -19,17 +19,17 @@ class CookieSettingsArgs;
 
 /**
  * Class that provides an nsICookieSettings implementation.
  */
 class CookieSettings final : public nsICookieSettings {
  public:
   typedef nsTArray<RefPtr<nsIPermission>> CookiePermissionList;
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSICOOKIESETTINGS
 
   static already_AddRefed<nsICookieSettings> CreateBlockingAll();
 
   static already_AddRefed<nsICookieSettings> Create();
 
   void Serialize(CookieSettingsArgs& aData);
 
--- a/netwerk/dns/TRR.cpp
+++ b/netwerk/dns/TRR.cpp
@@ -231,16 +231,17 @@ nsresult TRR::SendHTTPRequest() {
     LOG(("TRR:SendHTTPRequest: NewURI failed!\n"));
     return rv;
   }
 
   rv = NS_NewChannel(
       getter_AddRefs(mChannel), dnsURI, nsContentUtils::GetSystemPrincipal(),
       nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
       nsIContentPolicy::TYPE_OTHER,
+      nullptr,  // nsICookieSettings
       nullptr,  // PerformanceStorage
       nullptr,  // aLoadGroup
       this,
       nsIRequest::LOAD_ANONYMOUS | (mPB ? nsIRequest::INHIBIT_CACHING : 0),
       ios);
   if (NS_FAILED(rv)) {
     LOG(("TRR:SendHTTPRequest: NewChannel failed!\n"));
     return rv;
--- a/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
@@ -1988,16 +1988,17 @@ nsUrlClassifierDBService::SendThreatHitR
                        nsIChannel::INHIBIT_CACHING |
                        nsIChannel::LOAD_BYPASS_CACHE;
 
   nsCOMPtr<nsIChannel> reportChannel;
   rv = NS_NewChannel(getter_AddRefs(reportChannel), reportURI,
                      nsContentUtils::GetSystemPrincipal(),
                      nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                      nsIContentPolicy::TYPE_OTHER,
+                     nullptr,  // nsICookieSettings
                      nullptr,  // aPerformanceStorage
                      nullptr,  // aLoadGroup
                      nullptr, loadFlags);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsILoadInfo> loadInfo = reportChannel->LoadInfo();
   mozilla::OriginAttributes attrs;
   attrs.mFirstPartyDomain.AssignLiteral(NECKO_SAFEBROWSING_FIRST_PARTY_DOMAIN);
--- a/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.cpp
@@ -128,16 +128,17 @@ nsresult nsUrlClassifierStreamUpdater::F
 
   nsresult rv;
   uint32_t loadFlags =
       nsIChannel::INHIBIT_CACHING | nsIChannel::LOAD_BYPASS_CACHE;
   rv = NS_NewChannel(getter_AddRefs(mChannel), aUpdateUrl,
                      nsContentUtils::GetSystemPrincipal(),
                      nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                      nsIContentPolicy::TYPE_OTHER,
+                     nullptr,  // nsICookieSettings
                      nullptr,  // aPerformanceStorage
                      nullptr,  // aLoadGroup
                      this,     // aInterfaceRequestor
                      loadFlags);
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsILoadInfo> loadInfo = mChannel->LoadInfo();
--- a/uriloader/prefetch/nsOfflineCacheUpdate.cpp
+++ b/uriloader/prefetch/nsOfflineCacheUpdate.cpp
@@ -161,16 +161,17 @@ nsresult nsManifestCheck::Begin() {
   mManifestHash = do_CreateInstance("@mozilla.org/security/hash;1", &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = mManifestHash->Init(nsICryptoHash::MD5);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = NS_NewChannel(getter_AddRefs(mChannel), mURI, mLoadingPrincipal,
                      nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
                      nsIContentPolicy::TYPE_OTHER,
+                     nullptr,  // nsICookieSettings
                      nullptr,  // PerformanceStorage
                      nullptr,  // loadGroup
                      nullptr,  // aCallbacks
                      nsIRequest::LOAD_BYPASS_CACHE);
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   // configure HTTP specific stuff
@@ -330,16 +331,17 @@ nsresult nsOfflineCacheUpdateItem::OpenC
     flags |= nsIRequest::INHIBIT_CACHING;
   }
 
   flags |= mLoadFlags;
 
   rv = NS_NewChannel(getter_AddRefs(mChannel), mURI, mLoadingPrincipal,
                      nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                      nsIContentPolicy::TYPE_OTHER,
+                     nullptr,  // nsICookieSettings
                      nullptr,  // PerformanceStorage
                      nullptr,  // aLoadGroup
                      this,     // aCallbacks
                      flags);
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
--- a/uriloader/prefetch/nsPrefetchService.cpp
+++ b/uriloader/prefetch/nsPrefetchService.cpp
@@ -122,17 +122,17 @@ nsresult nsPrefetchNode::OpenChannel() {
     if (corsMode == CORS_USE_CREDENTIALS) {
       securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
     }
   }
   nsresult rv = NS_NewChannelInternal(
       getter_AddRefs(mChannel), mURI, source, source->NodePrincipal(),
       nullptr,  // aTriggeringPrincipal
       Maybe<ClientInfo>(), Maybe<ServiceWorkerDescriptor>(), securityFlags,
-      mPolicyType,
+      mPolicyType, source->OwnerDoc()->CookieSettings(),
       nullptr,    // aPerformanceStorage
       loadGroup,  // aLoadGroup
       this,       // aCallbacks
       nsIRequest::LOAD_BACKGROUND | nsICachingChannel::LOAD_ONLY_IF_MODIFIED);
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   // configure HTTP specific stuff
--- a/widget/android/WebExecutorSupport.cpp
+++ b/widget/android/WebExecutorSupport.cpp
@@ -17,16 +17,17 @@
 #include "nsINSSErrorsService.h"
 #include "nsIUploadChannel2.h"
 
 #include "nsIDNSService.h"
 #include "nsIDNSListener.h"
 #include "nsIDNSRecord.h"
 
 #include "mozilla/net/DNS.h"  // for NetAddr
+#include "mozilla/net/CookieSettings.h"
 
 #include "nsNetUtil.h"  // for NS_NewURI, NS_NewChannel, NS_NewStreamLoader
 
 #include "InetAddress.h"  // for java::sdk::InetAddress and java::sdk::UnknownHostException
 
 namespace mozilla {
 using namespace net;
 
@@ -438,16 +439,22 @@ nsresult WebExecutorSupport::CreateStrea
                      nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                      nsIContentPolicy::TYPE_OTHER);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aFlags & java::GeckoWebExecutor::FETCH_FLAGS_ANONYMOUS) {
     channel->SetLoadFlags(nsIRequest::LOAD_ANONYMOUS);
   }
 
+  nsCOMPtr<nsICookieSettings> cookieSettings = CookieSettings::Create();
+  MOZ_ASSERT(cookieSettings);
+
+  nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
+  loadInfo->SetCookieSettings(cookieSettings);
+
   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Method
   rv = httpChannel->SetRequestMethod(aRequest->Method()->ToCString());
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Headers
--- a/widget/windows/nsDataObj.cpp
+++ b/widget/windows/nsDataObj.cpp
@@ -66,16 +66,17 @@ nsresult nsDataObj::CStream::Init(nsIURI
   // we can not create a channel without a requestingPrincipal
   if (!aRequestingPrincipal) {
     return NS_ERROR_FAILURE;
   }
   nsresult rv;
   rv = NS_NewChannel(getter_AddRefs(mChannel), pSourceURI, aRequestingPrincipal,
                      nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS,
                      aContentPolicyType,
+                     nullptr,  // nsICookieSettings
                      nullptr,  // PerformanceStorage
                      nullptr,  // loadGroup
                      nullptr,  // aCallbacks
                      nsIRequest::LOAD_FROM_CACHE);
 
   NS_ENSURE_SUCCESS(rv, rv);
   rv = mChannel->AsyncOpen(this);
   NS_ENSURE_SUCCESS(rv, rv);