Bug 1143922 - Add AsyncOpen2 to nsIChannel and perform security checks when opening a channel - channel changes (r=mcmanus,sicking)
authorChristoph Kerschbaumer <mozilla@christophkerschbaumer.com>
Fri, 15 May 2015 13:21:20 -0700
changeset 253649 9b5a890968bbc3588901c8763954001ca04aaec1
parent 253648 6deb27dd785b2d79152a0b96730803f9a5a9c290
child 253650 accaecdd989d0a05d3d948608b7e1a7f1a97602d
push id29072
push usercbook@mozilla.com
push dateMon, 20 Jul 2015 09:36:58 +0000
treeherdermozilla-central@5df788c56ae7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmcmanus, sicking
bugs1143922
milestone42.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 1143922 - Add AsyncOpen2 to nsIChannel and perform security checks when opening a channel - channel changes (r=mcmanus,sicking)
dom/ipc/TabParent.cpp
dom/jsurl/nsJSProtocolHandler.cpp
image/decoders/icon/mac/nsIconChannelCocoa.mm
image/decoders/icon/win/nsIconChannel.cpp
modules/libjar/nsJARChannel.cpp
netwerk/base/nsBaseChannel.cpp
netwerk/base/nsIChannel.idl
netwerk/protocol/app/AppProtocolHandler.cpp
netwerk/protocol/http/HttpBaseChannel.cpp
netwerk/protocol/http/HttpBaseChannel.h
netwerk/protocol/http/HttpChannelChild.cpp
netwerk/protocol/http/HttpChannelChild.h
netwerk/protocol/http/NullHttpChannel.cpp
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/protocol/http/nsHttpChannel.h
netwerk/protocol/rtsp/RtspChannelChild.cpp
netwerk/protocol/rtsp/RtspChannelChild.h
netwerk/protocol/rtsp/RtspChannelParent.cpp
netwerk/protocol/rtsp/RtspChannelParent.h
netwerk/protocol/viewsource/nsViewSourceChannel.cpp
netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp
netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp
netwerk/streamconv/converters/nsMultiMixedConv.cpp
uriloader/exthandler/ExternalHelperAppParent.cpp
uriloader/exthandler/nsExternalProtocolHandler.cpp
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -3140,17 +3140,19 @@ public:
   NS_IMETHOD GetSecurityInfo(nsISupports**) NO_IMPL
   NS_IMETHOD GetContentType(nsACString&) NO_IMPL
   NS_IMETHOD SetContentType(const nsACString&) NO_IMPL
   NS_IMETHOD GetContentCharset(nsACString&) NO_IMPL
   NS_IMETHOD SetContentCharset(const nsACString&) NO_IMPL
   NS_IMETHOD GetContentLength(int64_t*) NO_IMPL
   NS_IMETHOD SetContentLength(int64_t) NO_IMPL
   NS_IMETHOD Open(nsIInputStream**) NO_IMPL
+  NS_IMETHOD Open2(nsIInputStream**) NO_IMPL
   NS_IMETHOD AsyncOpen(nsIStreamListener*, nsISupports*) NO_IMPL
+  NS_IMETHOD AsyncOpen2(nsIStreamListener*) NO_IMPL
   NS_IMETHOD GetContentDisposition(uint32_t*) NO_IMPL
   NS_IMETHOD SetContentDisposition(uint32_t) NO_IMPL
   NS_IMETHOD GetContentDispositionFilename(nsAString&) NO_IMPL
   NS_IMETHOD SetContentDispositionFilename(const nsAString&) NO_IMPL
   NS_IMETHOD GetContentDispositionHeader(nsACString&) NO_IMPL
   NS_IMETHOD OnAuthAvailable(nsISupports *aContext, nsIAuthInformation *aAuthInfo) override;
   NS_IMETHOD OnAuthCancelled(nsISupports *aContext, bool userCancel) override;
   NS_IMETHOD GetInterface(const nsIID & uuid, void **result) override
--- a/dom/jsurl/nsJSProtocolHandler.cpp
+++ b/dom/jsurl/nsJSProtocolHandler.cpp
@@ -45,16 +45,17 @@
 #include "nsILoadInfo.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsIWritablePropertyBag2.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsSandboxFlags.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "nsILoadInfo.h"
+#include "nsContentSecurityManager.h"
 
 #include "mozilla/ipc/URIUtils.h"
 
 using mozilla::dom::AutoEntryScript;
 
 static NS_DEFINE_CID(kJSURICID, NS_JSURI_CID);
 
 class nsJSThunk : public nsIInputStream
@@ -548,16 +549,25 @@ nsJSChannel::Open(nsIInputStream **aResu
                                            mExecutionPolicy,
                                            mOriginalInnerWindow);
     NS_ENSURE_SUCCESS(rv, rv);
 
     return mStreamChannel->Open(aResult);
 }
 
 NS_IMETHODIMP
+nsJSChannel::Open2(nsIInputStream** aStream)
+{
+    nsCOMPtr<nsIStreamListener> listener;
+    nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+    NS_ENSURE_SUCCESS(rv, rv);
+    return Open(aStream);
+}
+
+NS_IMETHODIMP
 nsJSChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
 {
     NS_ENSURE_ARG(aListener);
 
     // First make sure that we have a usable inner window; we'll want to make
     // sure that we execute against that inner and no other.
     nsIScriptGlobalObject* global = GetGlobalObject(this);
     if (!global) {
@@ -658,16 +668,25 @@ nsJSChannel::AsyncOpen(nsIStreamListener
     if (NS_FAILED(rv)) {
         loadGroup->RemoveRequest(this, nullptr, rv);
         mIsActive = false;
         CleanupStrongRefs();
     }
     return rv;
 }
 
+NS_IMETHODIMP
+nsJSChannel::AsyncOpen2(nsIStreamListener *aListener)
+{
+  nsCOMPtr<nsIStreamListener> listener = aListener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return AsyncOpen(listener, nullptr);
+}
+
 void
 nsJSChannel::EvaluateScript()
 {
     // Synchronously execute the script...
     // mIsActive is used to indicate the the request is 'busy' during the
     // the script evaluation phase.  This means that IsPending() will 
     // indicate the the request is busy while the script is executing...
 
--- a/image/decoders/icon/mac/nsIconChannelCocoa.mm
+++ b/image/decoders/icon/mac/nsIconChannelCocoa.mm
@@ -20,16 +20,17 @@
 #include "nsIOutputStream.h"
 #include "nsIMIMEService.h"
 #include "nsCExternalHandlerService.h"
 #include "nsILocalFileMac.h"
 #include "nsIFileURL.h"
 #include "nsTArray.h"
 #include "nsObjCExceptions.h"
 #include "nsProxyRelease.h"
+#include "nsContentSecurityManager.h"
 
 #include <Cocoa/Cocoa.h>
 
 // nsIconChannel methods
 nsIconChannel::nsIconChannel()
 {
 }
 
@@ -172,16 +173,25 @@ nsIconChannel::GetURI(nsIURI** aURI)
 }
 
 NS_IMETHODIMP
 nsIconChannel::Open(nsIInputStream** _retval)
 {
   return MakeInputStream(_retval, false);
 }
 
+NS_IMETHODIMP
+nsIconChannel::Open2(nsIInputStream** aStream)
+{
+  nsCOMPtr<nsIStreamListener> listener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return Open(aStream);
+}
+
 nsresult
 nsIconChannel::ExtractIconInfoFromUrl(nsIFile** aLocalFile,
                                                uint32_t* aDesiredImageSize,
                                                nsACString& aContentType,
                                                nsACString& aFileExtension)
 {
   nsresult rv = NS_OK;
   nsCOMPtr<nsIMozIconURI> iconURI (do_QueryInterface(mUrl, &rv));
@@ -231,16 +241,25 @@ nsIconChannel::AsyncOpen(nsIStreamListen
     if (mLoadGroup) {
       mLoadGroup->AddRequest(this, nullptr);
     }
   }
 
   return rv;
 }
 
+NS_IMETHODIMP
+nsIconChannel::AsyncOpen2(nsIStreamListener* aListener)
+{
+  nsCOMPtr<nsIStreamListener> listener = aListener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return AsyncOpen(listener, nullptr);
+}
+
 nsresult
 nsIconChannel::MakeInputStream(nsIInputStream** _retval,
                                         bool aNonBlocking)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   nsXPIDLCString contentType;
   nsAutoCString fileExt;
--- a/image/decoders/icon/win/nsIconChannel.cpp
+++ b/image/decoders/icon/win/nsIconChannel.cpp
@@ -21,16 +21,17 @@
 #include "nsIPipe.h"
 #include "nsNetCID.h"
 #include "nsIFile.h"
 #include "nsIFileURL.h"
 #include "nsIMIMEService.h"
 #include "nsCExternalHandlerService.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsProxyRelease.h"
+#include "nsContentSecurityManager.h"
 
 #ifdef _WIN32_WINNT
 #undef _WIN32_WINNT
 #endif
 #define _WIN32_WINNT 0x0600
 
 // we need windows.h to read out registry information...
 #include <windows.h>
@@ -193,16 +194,25 @@ nsIconChannel::GetURI(nsIURI** aURI)
 }
 
 NS_IMETHODIMP
 nsIconChannel::Open(nsIInputStream** _retval)
 {
   return MakeInputStream(_retval, false);
 }
 
+NS_IMETHODIMP
+nsIconChannel::Open2(nsIInputStream** aStream)
+{
+  nsCOMPtr<nsIStreamListener> listener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return Open(aStream);
+}
+
 nsresult
 nsIconChannel::ExtractIconInfoFromUrl(nsIFile** aLocalFile,
                         uint32_t* aDesiredImageSize, nsCString& aContentType,
                         nsCString& aFileExtension)
 {
   nsresult rv = NS_OK;
   nsCOMPtr<nsIMozIconURI> iconURI (do_QueryInterface(mUrl, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
@@ -248,16 +258,25 @@ nsIconChannel::AsyncOpen(nsIStreamListen
     // Add ourself to the load group, if available
     if (mLoadGroup) {
       mLoadGroup->AddRequest(this, nullptr);
     }
   }
   return rv;
 }
 
+NS_IMETHODIMP
+nsIconChannel::AsyncOpen2(nsIStreamListener* aListener)
+{
+  nsCOMPtr<nsIStreamListener> listener = aListener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return AsyncOpen(listener, nullptr);
+}
+
 static DWORD
 GetSpecialFolderIcon(nsIFile* aFile, int aFolder,
                                   SHFILEINFOW* aSFI, UINT aInfoFlags)
 {
   DWORD shellResult = 0;
 
   if (!aFile) {
     return shellResult;
--- a/modules/libjar/nsJARChannel.cpp
+++ b/modules/libjar/nsJARChannel.cpp
@@ -10,16 +10,17 @@
 #include "nsMimeTypes.h"
 #include "nsNetUtil.h"
 #include "nsEscape.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsIViewSourceChannel.h"
 #include "nsContentUtils.h"
 #include "nsProxyRelease.h"
+#include "nsContentSecurityManager.h"
 
 #include "nsIScriptSecurityManager.h"
 #include "nsIPrincipal.h"
 #include "nsIFileURL.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/net/RemoteOpenFileChild.h"
 #include "nsITabChild.h"
@@ -856,16 +857,25 @@ nsJARChannel::Open(nsIInputStream **stre
 
     input.forget(stream);
     mOpened = true;
     // local files are always considered safe
     mIsUnsafe = false;
     return NS_OK;
 }
 
+NS_IMETHODIMP
+nsJARChannel::Open2(nsIInputStream** aStream)
+{
+    nsCOMPtr<nsIStreamListener> listener;
+    nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+    NS_ENSURE_SUCCESS(rv, rv);
+    return Open(aStream);
+}
+
 bool
 nsJARChannel::ShouldIntercept()
 {
     LOG(("nsJARChannel::ShouldIntercept [this=%x]\n", this));
     // We only intercept app:// requests
     if (!mAppURI) {
       return false;
     }
@@ -972,16 +982,30 @@ nsJARChannel::AsyncOpen(nsIStreamListene
 
       return NS_OK;
     }
 #endif
 
     return ContinueAsyncOpen();
 }
 
+NS_IMETHODIMP
+nsJARChannel::AsyncOpen2(nsIStreamListener *aListener)
+{
+  if (!mLoadInfo) {
+    MOZ_ASSERT(mLoadInfo, "can not enforce security without loadInfo");
+    return NS_ERROR_UNEXPECTED;
+  }
+  // setting the flag on the loadInfo indicates that the underlying
+  // channel will be openend using AsyncOpen2() and hence performs
+  // the necessary security checks.
+  mLoadInfo->SetEnforceSecurity(true);
+  return AsyncOpen(aListener, nullptr);
+}
+
 nsresult
 nsJARChannel::ContinueAsyncOpen()
 {
     LOG(("nsJARChannel::ContinueAsyncOpen [this=%x]\n", this));
     nsresult rv = LookupFile(true);
     if (NS_FAILED(rv)) {
         mIsPending = false;
         mListenerContext = nullptr;
@@ -990,33 +1014,36 @@ nsJARChannel::ContinueAsyncOpen()
     }
 
     nsCOMPtr<nsIChannel> channel;
 
     if (!mJarFile) {
         // Not a local file...
         // kick off an async download of the base URI...
         nsCOMPtr<nsIStreamListener> downloader = new MemoryDownloader(this);
-        // Since we might not have a loadinfo on all channels yet
-        // we have to provide default arguments in case mLoadInfo is null;
         uint32_t loadFlags =
             mLoadFlags & ~(LOAD_DOCUMENT_URI | LOAD_CALL_CONTENT_SNIFFERS);
         rv = NS_NewChannelInternal(getter_AddRefs(channel),
                                    mJarBaseURI,
                                    mLoadInfo,
                                    mLoadGroup,
                                    mCallbacks,
                                    loadFlags);
         if (NS_FAILED(rv)) {
             mIsPending = false;
             mListenerContext = nullptr;
             mListener = nullptr;
             return rv;
         }
-        rv = channel->AsyncOpen(downloader, nullptr);
+        if (mLoadInfo && mLoadInfo->GetEnforceSecurity()) {
+            rv = channel->AsyncOpen2(downloader);
+        }
+        else {
+            rv = channel->AsyncOpen(downloader, nullptr);
+        }
     } else if (mOpeningRemote) {
         // nothing to do: already asked parent to open file.
     } else {
         rv = OpenLocalFile();
     }
 
     if (NS_FAILED(rv)) {
         mIsPending = false;
--- a/netwerk/base/nsBaseChannel.cpp
+++ b/netwerk/base/nsBaseChannel.cpp
@@ -15,16 +15,17 @@
 #include "nsIHttpEventSink.h"
 #include "nsIHttpChannel.h"
 #include "nsIChannelEventSink.h"
 #include "nsIStreamConverterService.h"
 #include "nsChannelClassifier.h"
 #include "nsAsyncRedirectVerifyHelper.h"
 #include "nsProxyRelease.h"
 #include "nsXULAppAPI.h"
+#include "nsContentSecurityManager.h"
 
 static PLDHashOperator
 CopyProperties(const nsAString &key, nsIVariant *data, void *closure)
 {
   nsIWritablePropertyBag *bag =
       static_cast<nsIWritablePropertyBag *>(closure);
 
   bag->SetProperty(key, data);
@@ -148,17 +149,24 @@ nsBaseChannel::ContinueRedirect()
   // Make sure to do this _after_ making all the OnChannelRedirect calls
   mRedirectChannel->SetOriginalURI(OriginalURI());
 
   // If we fail to open the new channel, then we want to leave this channel
   // unaffected, so we defer tearing down our channel until we have succeeded
   // with the redirect.
 
   if (mOpenRedirectChannel) {
-    nsresult rv = mRedirectChannel->AsyncOpen(mListener, mListenerContext);
+    nsresult rv = NS_OK;
+    if (mLoadInfo && mLoadInfo->GetEnforceSecurity()) {
+      MOZ_ASSERT(!mListenerContext, "mListenerContext should be null!");
+      rv = mRedirectChannel->AsyncOpen2(mListener);
+    }
+    else {
+      rv = mRedirectChannel->AsyncOpen(mListener, mListenerContext);
+    }
     NS_ENSURE_SUCCESS(rv, rv);
     // Append the initial uri of the channel to the redirectChain
     // after the channel got openend successfully.
     if (mLoadInfo) {
       nsCOMPtr<nsIPrincipal> uriPrincipal;
       nsIScriptSecurityManager *sm = nsContentUtils::GetSecurityManager();
       sm->GetChannelURIPrincipal(this, getter_AddRefs(uriPrincipal));
       mLoadInfo->AppendRedirectedPrincipal(uriPrincipal);
@@ -602,16 +610,25 @@ nsBaseChannel::Open(nsIInputStream **res
     mWasOpened = true;
     ClassifyURI();
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
+nsBaseChannel::Open2(nsIInputStream** aStream)
+{
+  nsCOMPtr<nsIStreamListener> listener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return Open(aStream);
+}
+
+NS_IMETHODIMP
 nsBaseChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt)
 {
   NS_ENSURE_TRUE(mURI, NS_ERROR_NOT_INITIALIZED);
   NS_ENSURE_TRUE(!mPump, NS_ERROR_IN_PROGRESS);
   NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
   NS_ENSURE_ARG(listener);
 
   // Ensure that this is an allowed port before proceeding.
@@ -648,16 +665,25 @@ nsBaseChannel::AsyncOpen(nsIStreamListen
   if (mLoadGroup)
     mLoadGroup->AddRequest(this, nullptr);
 
   ClassifyURI();
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsBaseChannel::AsyncOpen2(nsIStreamListener *aListener)
+{
+  nsCOMPtr<nsIStreamListener> listener = aListener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return AsyncOpen(listener, nullptr);
+}
+
 //-----------------------------------------------------------------------------
 // nsBaseChannel::nsITransportEventSink
 
 NS_IMETHODIMP
 nsBaseChannel::OnTransportStatus(nsITransport *transport, nsresult status,
                                  int64_t progress, int64_t progressMax)
 {
   // In some cases, we may wish to suppress transport-layer status events.
--- a/netwerk/base/nsIChannel.idl
+++ b/netwerk/base/nsIChannel.idl
@@ -24,17 +24,17 @@ interface nsIStreamListener;
  * by calling nsIChannel::open or nsIChannel::asyncOpen.
  *
  * After a request has been completed, the channel is still valid for accessing
  * protocol-specific results.  For example, QI'ing to nsIHttpChannel allows
  * response headers to be retrieved for the corresponding http transaction.
  *
  * This interface must be used only from the XPCOM main thread.
  */
-[scriptable, uuid(1bc48693-c45d-45f4-8ab1-46e323037fe1)]
+[scriptable, uuid(cc3bff29-324e-4704-9eeb-1b8a62c4a9dc)]
 interface nsIChannel : nsIRequest
 {
     /**
      * The original URI used to construct the channel. This is used in
      * the case of a redirect or URI "resolution" (e.g. resolving a
      * resource: URI to a file: URI) so that the original pre-redirect
      * URI can still be obtained.  This is never null.  Attempts to
      * set it to null must throw.
@@ -142,16 +142,21 @@ interface nsIChannel : nsIRequest
      * than the XPCOM main thread.
      *
      * NOTE: Implementations should throw NS_ERROR_IN_PROGRESS if the channel
      * is reopened.
      */
     nsIInputStream open();
 
     /**
+     * Performs content security check and calls open()
+     */
+    nsIInputStream open2();
+
+    /**
      * Asynchronously open this channel.  Data is fed to the specified stream
      * listener as it becomes available.  The stream listener's methods are
      * called on the thread that calls asyncOpen and are not called until
      * after asyncOpen returns.  If asyncOpen returns successfully, the
      * channel promises to call at least onStartRequest and onStopRequest.
      *
      * If the nsIRequest object passed to the stream listener's methods is not
      * this channel, an appropriate onChannelRedirect notification needs to be
@@ -174,16 +179,21 @@ interface nsIChannel : nsIRequest
      * channel is reopened.
      *
      * @param aListener the nsIStreamListener implementation
      * @param aContext an opaque parameter forwarded to aListener's methods
      * @see nsIChannelEventSink for onChannelRedirect
      */
     void asyncOpen(in nsIStreamListener aListener, in nsISupports aContext);
 
+    /**
+     * Performs content security check and calls asyncOpen().
+     */
+    void asyncOpen2(in nsIStreamListener aListener);
+
     /**************************************************************************
      * Channel specific load flags:
      *
      * Bits 23-31 are reserved for future use by this interface or one of its
      * derivatives (e.g., see nsICachingChannel).
      */
 
     /**
--- a/netwerk/protocol/app/AppProtocolHandler.cpp
+++ b/netwerk/protocol/app/AppProtocolHandler.cpp
@@ -9,16 +9,17 @@
 #include "nsJARChannel.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 #include "nsIStandardURL.h"
 #include "nsIAppsService.h"
 #include "nsILoadInfo.h"
 #include "nsXULAppAPI.h"
 #include "nsPrincipal.h"
+#include "nsContentSecurityManager.h"
 
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
 
 /**
   * This dummy channel implementation only provides enough functionality
@@ -94,16 +95,25 @@ NS_IMETHODIMP DummyChannel::Resume()
   return NS_OK;
 }
 
 NS_IMETHODIMP DummyChannel::Open(nsIInputStream**)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
+NS_IMETHODIMP
+DummyChannel::Open2(nsIInputStream** aStream)
+{
+  nsCOMPtr<nsIStreamListener> listener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return Open(aStream);
+}
+
 NS_IMETHODIMP DummyChannel::AsyncOpen(nsIStreamListener* aListener, nsISupports* aContext)
 {
   mListener = aListener;
   mListenerContext = aContext;
   mPending = true;
 
   if (mLoadGroup) {
     mLoadGroup->AddRequest(this, aContext);
@@ -111,16 +121,25 @@ NS_IMETHODIMP DummyChannel::AsyncOpen(ns
 
   if (mSuspendCount == 0) {
     NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL);
   }
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+DummyChannel::AsyncOpen2(nsIStreamListener* aListener)
+{
+  nsCOMPtr<nsIStreamListener> listener = aListener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return AsyncOpen(listener, nullptr);
+}
+
 // nsIJarChannel, needed for XHR to turn NS_ERROR_FILE_NOT_FOUND into
 // a 404 error.
 NS_IMETHODIMP DummyChannel::GetIsUnsafe(bool *aResult)
 {
   *aResult = false;
   return NS_OK;
 }
 
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -34,16 +34,17 @@
 #include "nsIScriptSecurityManager.h"
 #include "nsIObserverService.h"
 #include "nsProxyRelease.h"
 #include "nsPIDOMWindow.h"
 #include "nsPerformance.h"
 #include "nsINetworkInterceptController.h"
 #include "mozIThirdPartyUtil.h"
 #include "nsStreamUtils.h"
+#include "nsContentSecurityManager.h"
 
 #include <algorithm>
 
 namespace mozilla {
 namespace net {
 
 HttpBaseChannel::HttpBaseChannel()
   : mStartPos(UINT64_MAX)
@@ -505,16 +506,25 @@ HttpBaseChannel::SetContentLength(int64_
 
 NS_IMETHODIMP
 HttpBaseChannel::Open(nsIInputStream **aResult)
 {
   NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_IN_PROGRESS);
   return NS_ImplementChannelOpen(this, aResult);
 }
 
+NS_IMETHODIMP
+HttpBaseChannel::Open2(nsIInputStream** aStream)
+{
+  nsCOMPtr<nsIStreamListener> listener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return Open(aStream);
+}
+
 //-----------------------------------------------------------------------------
 // HttpBaseChannel::nsIUploadChannel
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 HttpBaseChannel::GetUploadStream(nsIInputStream **stream)
 {
   NS_ENSURE_ARG_POINTER(stream);
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -113,16 +113,17 @@ public:
   NS_IMETHOD GetContentDisposition(uint32_t *aContentDisposition) override;
   NS_IMETHOD SetContentDisposition(uint32_t aContentDisposition) override;
   NS_IMETHOD GetContentDispositionFilename(nsAString& aContentDispositionFilename) override;
   NS_IMETHOD SetContentDispositionFilename(const nsAString& aContentDispositionFilename) override;
   NS_IMETHOD GetContentDispositionHeader(nsACString& aContentDispositionHeader) override;
   NS_IMETHOD GetContentLength(int64_t *aContentLength) override;
   NS_IMETHOD SetContentLength(int64_t aContentLength) override;
   NS_IMETHOD Open(nsIInputStream **aResult) override;
+  NS_IMETHOD Open2(nsIInputStream **aResult) override;
 
   // nsIEncodedChannel
   NS_IMETHOD GetApplyConversion(bool *value) override;
   NS_IMETHOD SetApplyConversion(bool value) override;
   NS_IMETHOD GetContentEncodings(nsIUTF8StringEnumerator** aEncodings) override;
   NS_IMETHOD DoApplyContentConversions(nsIStreamListener *aNextListener,
                                        nsIStreamListener **aNewNextListener,
                                        nsISupports *aCtxt) override;
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -28,16 +28,17 @@
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/net/ChannelDiverterChild.h"
 #include "mozilla/net/DNS.h"
 #include "SerializedLoadContext.h"
 #include "nsInputStreamPump.h"
 #include "InterceptedChannel.h"
 #include "nsPerformance.h"
 #include "mozIThirdPartyUtil.h"
+#include "nsContentSecurityManager.h"
 
 #ifdef OS_POSIX
 #include "chrome/common/file_descriptor_set_posix.h"
 #endif
 
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
 
@@ -1551,16 +1552,25 @@ HttpChannelChild::AsyncOpen(nsIStreamLis
         new InterceptedChannelContent(this, controller, mInterceptListener);
     intercepted->NotifyController();
     return NS_OK;
   }
 
   return ContinueAsyncOpen();
 }
 
+NS_IMETHODIMP
+HttpChannelChild::AsyncOpen2(nsIStreamListener *aListener)
+{
+  nsCOMPtr<nsIStreamListener> listener = aListener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return AsyncOpen(listener, nullptr);
+}
+
 nsresult
 HttpChannelChild::ContinueAsyncOpen()
 {
   nsCString appCacheClientId;
   if (mInheritApplicationCache) {
     // Pick up an application cache from the notification
     // callbacks if available
     nsCOMPtr<nsIApplicationCacheContainer> appCacheContainer;
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -69,16 +69,18 @@ public:
   //
   // nsIRequest
   NS_IMETHOD Cancel(nsresult status) override;
   NS_IMETHOD Suspend() override;
   NS_IMETHOD Resume() override;
   // nsIChannel
   NS_IMETHOD GetSecurityInfo(nsISupports **aSecurityInfo) override;
   NS_IMETHOD AsyncOpen(nsIStreamListener *listener, nsISupports *aContext) override;
+  NS_IMETHOD AsyncOpen2(nsIStreamListener *aListener) override;
+
   // HttpBaseChannel::nsIHttpChannel
   NS_IMETHOD SetRequestHeader(const nsACString& aHeader,
                               const nsACString& aValue,
                               bool aMerge) override;
   NS_IMETHOD RedirectTo(nsIURI *newURI) override;
   // nsIHttpChannelInternal
   NS_IMETHOD SetupFallbackChannel(const char *aFallbackKey) override;
   NS_IMETHOD GetLocalAddress(nsACString& addr) override;
--- a/netwerk/protocol/http/NullHttpChannel.cpp
+++ b/netwerk/protocol/http/NullHttpChannel.cpp
@@ -1,14 +1,15 @@
 /* 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 "NullHttpChannel.h"
 #include "nsContentUtils.h"
+#include "nsContentSecurityManager.h"
 #include "nsIScriptSecurityManager.h"
 
 namespace mozilla {
 namespace net {
 
 NS_IMPL_ISUPPORTS(NullHttpChannel, nsINullChannel,
                   nsIHttpChannel, nsITimedChannel)
 
@@ -298,22 +299,40 @@ NullHttpChannel::SetContentLength(int64_
 
 NS_IMETHODIMP
 NullHttpChannel::Open(nsIInputStream * *_retval)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
+NullHttpChannel::Open2(nsIInputStream** aStream)
+{
+  nsCOMPtr<nsIStreamListener> listener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return Open(aStream);
+}
+
+NS_IMETHODIMP
 NullHttpChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
+NullHttpChannel::AsyncOpen2(nsIStreamListener *aListener)
+{
+  nsCOMPtr<nsIStreamListener> listener = aListener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return AsyncOpen(listener, nullptr);
+}
+
+NS_IMETHODIMP
 NullHttpChannel::GetContentDisposition(uint32_t *aContentDisposition)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 NullHttpChannel::SetContentDisposition(uint32_t aContentDisposition)
 {
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -47,16 +47,17 @@
 #include "GeckoProfiler.h"
 #include "nsIConsoleService.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Preferences.h"
 #include "nsISSLSocketControl.h"
 #include "sslt.h"
 #include "nsContentUtils.h"
+#include "nsContentSecurityManager.h"
 #include "nsIClassOfService.h"
 #include "nsIPermissionManager.h"
 #include "nsIPrincipal.h"
 #include "nsIScriptError.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsISSLStatus.h"
 #include "nsISSLStatusProvider.h"
 #include "nsITransportSecurityInfo.h"
@@ -1956,20 +1957,24 @@ nsHttpChannel::OpenRedirectChannel(nsres
         // versions.
         rv = httpEventSink->OnRedirect(this, mRedirectChannel);
         if (NS_FAILED(rv)) {
             return rv;
         }
     }
 
     // open new channel
-    rv = mRedirectChannel->AsyncOpen(mListener, mListenerContext);
-    if (NS_FAILED(rv)) {
-        return rv;
-    }
+    if (mLoadInfo && mLoadInfo->GetEnforceSecurity()) {
+        MOZ_ASSERT(!mListenerContext, "mListenerContext should be null!");
+        rv = mRedirectChannel->AsyncOpen2(mListener);
+    }
+    else {
+        rv = mRedirectChannel->AsyncOpen(mListener, mListenerContext);
+    }
+    NS_ENSURE_SUCCESS(rv, rv);
 
     mStatus = NS_BINDING_REDIRECTED;
 
     notifier.RedirectSucceeded();
 
     ReleaseListeners();
 
     return NS_OK;
@@ -2019,19 +2024,24 @@ nsHttpChannel::ContinueDoReplaceWithProx
         return rv;
 
     NS_PRECONDITION(mRedirectChannel, "No redirect channel?");
 
     // Make sure to do this _after_ calling OnChannelRedirect
     mRedirectChannel->SetOriginalURI(mOriginalURI);
 
     // open new channel
-    rv = mRedirectChannel->AsyncOpen(mListener, mListenerContext);
-    if (NS_FAILED(rv))
-        return rv;
+    if (mLoadInfo && mLoadInfo->GetEnforceSecurity()) {
+        MOZ_ASSERT(!mListenerContext, "mListenerContext should be null!");
+        rv = mRedirectChannel->AsyncOpen2(mListener);
+    }
+    else {
+        rv = mRedirectChannel->AsyncOpen(mListener, mListenerContext);
+    }
+    NS_ENSURE_SUCCESS(rv, rv);
 
     mStatus = NS_BINDING_REDIRECTED;
 
     notifier.RedirectSucceeded();
 
     ReleaseListeners();
 
     return rv;
@@ -2680,19 +2690,24 @@ nsHttpChannel::ContinueProcessFallback(n
     if (NS_FAILED(rv))
         return rv;
 
     NS_PRECONDITION(mRedirectChannel, "No redirect channel?");
 
     // Make sure to do this _after_ calling OnChannelRedirect
     mRedirectChannel->SetOriginalURI(mOriginalURI);
 
-    rv = mRedirectChannel->AsyncOpen(mListener, mListenerContext);
-    if (NS_FAILED(rv))
-        return rv;
+    if (mLoadInfo && mLoadInfo->GetEnforceSecurity()) {
+        MOZ_ASSERT(!mListenerContext, "mListenerContext should be null!");
+        rv = mRedirectChannel->AsyncOpen2(mListener);
+    }
+    else {
+        rv = mRedirectChannel->AsyncOpen(mListener, mListenerContext);
+    }
+    NS_ENSURE_SUCCESS(rv, rv);
 
     if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) {
         Telemetry::Accumulate(Telemetry::HTTP_OFFLINE_CACHE_DOCUMENT_LOAD,
                               true);
     }
 
     // close down this channel
     Cancel(NS_BINDING_REDIRECTED);
@@ -4628,20 +4643,24 @@ nsHttpChannel::ContinueProcessRedirectio
         rv = httpEventSink->OnRedirect(this, mRedirectChannel);
         if (NS_FAILED(rv))
             return rv;
     }
     // XXX we used to talk directly with the script security manager, but that
     // should really be handled by the event sink implementation.
 
     // begin loading the new channel
-    rv = mRedirectChannel->AsyncOpen(mListener, mListenerContext);
-
-    if (NS_FAILED(rv))
-        return rv;
+    if (mLoadInfo && mLoadInfo->GetEnforceSecurity()) {
+        MOZ_ASSERT(!mListenerContext, "mListenerContext should be null!");
+        rv = mRedirectChannel->AsyncOpen2(mListener);
+    }
+    else {
+        rv = mRedirectChannel->AsyncOpen(mListener, mListenerContext);
+    }
+    NS_ENSURE_SUCCESS(rv, rv);
 
     // close down this channel
     Cancel(NS_BINDING_REDIRECTED);
 
     notifier.RedirectSucceeded();
 
     ReleaseListeners();
 
@@ -4908,16 +4927,25 @@ nsHttpChannel::AsyncOpen(nsIStreamListen
 
     rv = BeginConnect();
     if (NS_FAILED(rv))
         ReleaseListeners();
 
     return rv;
 }
 
+NS_IMETHODIMP
+nsHttpChannel::AsyncOpen2(nsIStreamListener *aListener)
+{
+  nsCOMPtr<nsIStreamListener> listener = aListener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return AsyncOpen(listener, nullptr);
+}
+
 // BeginConnect() will not call AsyncAbort() on an error and if AsyncAbort needs
 // to be called the function calling BeginConnect will need to call AsyncAbort.
 // If BeginConnect is called from AsyncOpen, AsyncnAbort doesn't need to be
 // called. If it is called form another function (e.g. the function is called
 // from OnProxyAvailable) that function should call AsyncOpen.
 nsresult
 nsHttpChannel::BeginConnect()
 {
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -121,16 +121,17 @@ public:
     //
     // nsIRequest
     NS_IMETHOD Cancel(nsresult status) override;
     NS_IMETHOD Suspend() override;
     NS_IMETHOD Resume() override;
     // nsIChannel
     NS_IMETHOD GetSecurityInfo(nsISupports **aSecurityInfo) override;
     NS_IMETHOD AsyncOpen(nsIStreamListener *listener, nsISupports *aContext) override;
+    NS_IMETHOD AsyncOpen2(nsIStreamListener *aListener) override;
     // nsIHttpChannelInternal
     NS_IMETHOD SetupFallbackChannel(const char *aFallbackKey) override;
     // nsISupportsPriority
     NS_IMETHOD SetPriority(int32_t value) override;
     // nsIClassOfService
     NS_IMETHOD SetClassFlags(uint32_t inFlags) override;
     NS_IMETHOD AddClassFlags(uint32_t inFlags) override;
     NS_IMETHOD ClearClassFlags(uint32_t inFlags) override;
--- a/netwerk/protocol/rtsp/RtspChannelChild.cpp
+++ b/netwerk/protocol/rtsp/RtspChannelChild.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=2 ts=8 et 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 "nsContentSecurityManager.h"
 #include "RtspChannelChild.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "nsServiceManagerUtils.h"
 
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace net {
@@ -130,16 +131,25 @@ RtspChannelChild::AsyncOpen(nsIStreamLis
   mListener = aListener;
   mListenerContext = aContext;
   NS_DispatchToMainThread(
     new CallListenerOnStartRequestEvent(mListener, this, mListenerContext));
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+RtspChannelChild::AsyncOpen2(nsIStreamListener *aListener)
+{
+  nsCOMPtr<nsIStreamListener> listener = aListener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return AsyncOpen(listener, nullptr);
+}
+
 //-----------------------------------------------------------------------------
 // nsBaseChannel::nsIStreamListener::nsIRequestObserver
 //-----------------------------------------------------------------------------
 NS_IMETHODIMP
 RtspChannelChild::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
 {
   MOZ_CRASH("Should never be called");
 }
--- a/netwerk/protocol/rtsp/RtspChannelChild.h
+++ b/netwerk/protocol/rtsp/RtspChannelChild.h
@@ -37,16 +37,17 @@ public:
   NS_DECL_NSICHILDCHANNEL
 
   RtspChannelChild(nsIURI *aUri);
 
   // nsBaseChannel::nsIChannel
   NS_IMETHOD GetContentType(nsACString & aContentType) override final;
   NS_IMETHOD AsyncOpen(nsIStreamListener *listener, nsISupports *aContext)
                        override final;
+  NS_IMETHOD AsyncOpen2(nsIStreamListener *listener) override final;
 
   // nsBaseChannel::nsIStreamListener::nsIRequestObserver
   NS_IMETHOD OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
                             override final;
   NS_IMETHOD OnStopRequest(nsIRequest *aRequest,
                            nsISupports *aContext,
                            nsresult aStatusCode) override final;
 
--- a/netwerk/protocol/rtsp/RtspChannelParent.cpp
+++ b/netwerk/protocol/rtsp/RtspChannelParent.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=2 ts=8 et 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 "RtspChannelParent.h"
+#include "nsContentSecurityManager.h"
 
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace net {
 
 //-----------------------------------------------------------------------------
 // RtspChannelParent
@@ -67,16 +68,22 @@ RtspChannelParent::GetContentType(nsACSt
 }
 
 NS_IMETHODIMP
 RtspChannelParent::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
 {
   return NS_OK;
 }
 
+NS_IMETHODIMP
+RtspChannelParent::AsyncOpen2(nsIStreamListener *aListener)
+{
+  return NS_OK;
+}
+
 //-----------------------------------------------------------------------------
 // nsBaseChannel::nsIStreamListener::nsIRequestObserver
 //-----------------------------------------------------------------------------
 NS_IMETHODIMP
 RtspChannelParent::OnStartRequest(nsIRequest *aRequest,
                             nsISupports *aContext)
 {
   MOZ_CRASH("Should never be called");
--- a/netwerk/protocol/rtsp/RtspChannelParent.h
+++ b/netwerk/protocol/rtsp/RtspChannelParent.h
@@ -34,16 +34,17 @@ public:
   NS_DECL_NSIPARENTCHANNEL
 
   RtspChannelParent(nsIURI *aUri);
 
   // nsBaseChannel::nsIChannel
   NS_IMETHOD GetContentType(nsACString & aContentType) override final;
   NS_IMETHOD AsyncOpen(nsIStreamListener *listener,
                        nsISupports *aContext) override final;
+  NS_IMETHOD AsyncOpen2(nsIStreamListener *listener) override final;
 
   // nsBaseChannel::nsIStreamListener::nsIRequestObserver
   NS_IMETHOD OnStartRequest(nsIRequest *aRequest,
                             nsISupports *aContext) override final;
   NS_IMETHOD OnStopRequest(nsIRequest *aRequest,
                            nsISupports *aContext,
                            nsresult aStatusCode) override final;
 
--- a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
+++ b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsViewSourceChannel.h"
 #include "nsIIOService.h"
 #include "nsMimeTypes.h"
 #include "nsNetUtil.h"
 #include "nsContentUtils.h"
 #include "nsIHttpHeaderVisitor.h"
+#include "nsContentSecurityManager.h"
 #include "nsNullPrincipal.h"
 #include "nsServiceManagerUtils.h"
 
 NS_IMPL_ADDREF(nsViewSourceChannel)
 NS_IMPL_RELEASE(nsViewSourceChannel)
 /*
   This QI uses NS_INTERFACE_MAP_ENTRY_CONDITIONAL to check for
   non-nullness of mHttpChannel, mCachingChannel, and mUploadChannel.
@@ -219,25 +220,47 @@ nsViewSourceChannel::GetURI(nsIURI* *aUR
     return NS_NewURI(aURI, nsAutoCString(NS_LITERAL_CSTRING("view-source:")+spec), nullptr);
 }
 
 NS_IMETHODIMP
 nsViewSourceChannel::Open(nsIInputStream **_retval)
 {
     NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
 
-    nsresult rv = mChannel->Open(_retval);
+    nsresult rv = NS_OK;
+    nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
+    if (loadInfo && loadInfo->GetEnforceSecurity()) {
+        mChannel->Open2(_retval);
+    }
+    else {
+        mChannel->Open(_retval);
+    }
     if (NS_SUCCEEDED(rv)) {
         mOpened = true;
     }
-    
     return rv;
 }
 
 NS_IMETHODIMP
+nsViewSourceChannel::Open2(nsIInputStream** aStream)
+{
+    NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
+    nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
+    if(!loadInfo) {
+        MOZ_ASSERT(loadInfo, "can not enforce security without loadInfo");
+        return NS_ERROR_UNEXPECTED;
+    }
+    // setting the flag on the loadInfo indicates that the underlying
+    // channel will be openend using Open2() and hence performs
+    // the necessary security checks.
+    loadInfo->SetEnforceSecurity(true);
+    return Open(aStream);
+}
+
+NS_IMETHODIMP
 nsViewSourceChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt)
 {
     NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
 
     mListener = aListener;
 
     /*
      * We want to add ourselves to the loadgroup before opening
@@ -246,30 +269,51 @@ nsViewSourceChannel::AsyncOpen(nsIStream
      */
     
     nsCOMPtr<nsILoadGroup> loadGroup;
     mChannel->GetLoadGroup(getter_AddRefs(loadGroup));
     if (loadGroup)
         loadGroup->AddRequest(static_cast<nsIViewSourceChannel*>
                                          (this), nullptr);
     
-    nsresult rv = mChannel->AsyncOpen(this, ctxt);
+    nsresult rv = NS_OK;
+    nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
+    if (loadInfo && loadInfo->GetEnforceSecurity()) {
+        rv = mChannel->AsyncOpen2(this);
+    }
+    else {
+        rv = mChannel->AsyncOpen(this, ctxt);
+    }
 
     if (NS_FAILED(rv) && loadGroup)
         loadGroup->RemoveRequest(static_cast<nsIViewSourceChannel*>
                                             (this),
                                  nullptr, rv);
 
     if (NS_SUCCEEDED(rv)) {
         mOpened = true;
     }
     
     return rv;
 }
 
+NS_IMETHODIMP
+nsViewSourceChannel::AsyncOpen2(nsIStreamListener *aListener)
+{
+  nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
+  if(!loadInfo) {
+    MOZ_ASSERT(loadInfo, "can not enforce security without loadInfo");
+    return NS_ERROR_UNEXPECTED;
+  }
+  // setting the flag on the loadInfo indicates that the underlying
+  // channel will be openend using AsyncOpen2() and hence performs
+  // the necessary security checks.
+  loadInfo->SetEnforceSecurity(true);
+  return AsyncOpen(aListener, nullptr);
+}
 /*
  * Both the view source channel and mChannel are added to the
  * loadgroup.  There should never be more than one request in the
  * loadgroup that has LOAD_DOCUMENT_URI set.  The one that has this
  * flag set is the request whose URI is used to refetch the document,
  * so it better be the viewsource channel.
  *
  * Therefore, we need to make sure that
--- a/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp
+++ b/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp
@@ -16,16 +16,17 @@
 #include "nsNetUtil.h"
 #include "nsISerializable.h"
 #include "nsSerializationHelper.h"
 #include "nsIProgressEventSink.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "SerializedLoadContext.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "nsProxyRelease.h"
+#include "nsContentSecurityManager.h"
 
 using namespace mozilla::ipc;
 using namespace mozilla::dom;
 
 namespace mozilla {
 namespace net {
 
 NS_IMPL_ISUPPORTS(WyciwygChannelChild,
@@ -617,16 +618,25 @@ WyciwygChannelChild::SetContentLength(in
 
 /* nsIInputStream open (); */
 NS_IMETHODIMP
 WyciwygChannelChild::Open(nsIInputStream **_retval)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
+NS_IMETHODIMP
+WyciwygChannelChild::Open2(nsIInputStream** aStream)
+{
+  nsCOMPtr<nsIStreamListener> listener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return Open(aStream);
+}
+
 static mozilla::dom::TabChild*
 GetTabChild(nsIChannel* aChannel)
 {
   nsCOMPtr<nsITabChild> iTabChild;
   NS_QueryNotificationCallbacks(aChannel, iTabChild);
   return iTabChild ? static_cast<mozilla::dom::TabChild*>(iTabChild.get()) : nullptr;
 }
 
@@ -667,16 +677,25 @@ WyciwygChannelChild::AsyncOpen(nsIStream
   SendAsyncOpen(originalURI, mLoadFlags, IPC::SerializedLoadContext(this), browser);
 
   mSentAppData = true;
   mState = WCC_OPENED;
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+WyciwygChannelChild::AsyncOpen2(nsIStreamListener *aListener)
+{
+  nsCOMPtr<nsIStreamListener> listener = aListener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return AsyncOpen(listener, nullptr);
+}
+
 //-----------------------------------------------------------------------------
 // nsIWyciwygChannel
 //-----------------------------------------------------------------------------
 
 /* void writeToCacheEntry (in AString aData); */
 NS_IMETHODIMP
 WyciwygChannelChild::WriteToCacheEntry(const nsAString & aData)
 {
--- a/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp
+++ b/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp
@@ -22,16 +22,17 @@
 #include "nsIInputStream.h"
 #include "nsIInputStreamPump.h"
 #include "nsIOutputStream.h"
 #include "nsIProgressEventSink.h"
 #include "nsIURI.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/unused.h"
 #include "nsProxyRelease.h"
+#include "nsContentSecurityManager.h"
 
 typedef mozilla::net::LoadContextInfo LoadContextInfo;
 
 // Must release mChannel on the main thread
 class nsWyciwygAsyncEvent : public nsRunnable {
 public:
   explicit nsWyciwygAsyncEvent(nsWyciwygChannel *aChannel) : mChannel(aChannel) {}
 
@@ -414,16 +415,25 @@ nsWyciwygChannel::SetContentLength(int64
 
 NS_IMETHODIMP
 nsWyciwygChannel::Open(nsIInputStream ** aReturn)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
+nsWyciwygChannel::Open2(nsIInputStream** aStream)
+{
+  nsCOMPtr<nsIStreamListener> listener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return Open(aStream);
+}
+
+NS_IMETHODIMP
 nsWyciwygChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctx)
 {
   LOG(("nsWyciwygChannel::AsyncOpen [this=%p]\n", this));
   MOZ_ASSERT(mMode == NONE, "nsWyciwygChannel already open");
 
   NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
   NS_ENSURE_TRUE(mMode == NONE, NS_ERROR_IN_PROGRESS);
   NS_ENSURE_ARG_POINTER(listener);
@@ -449,16 +459,25 @@ nsWyciwygChannel::AsyncOpen(nsIStreamLis
   mListenerContext = ctx;
 
   if (mLoadGroup)
     mLoadGroup->AddRequest(this, nullptr);
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsWyciwygChannel::AsyncOpen2(nsIStreamListener *aListener)
+{
+  nsCOMPtr<nsIStreamListener> listener = aListener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return AsyncOpen(listener, nullptr);
+}
+
 //////////////////////////////////////////////////////////////////////////////
 // nsIWyciwygChannel
 //////////////////////////////////////////////////////////////////////////////
 
 nsresult
 nsWyciwygChannel::EnsureWriteCacheEntry()
 {
   MOZ_ASSERT(mMode == WRITING, "nsWyciwygChannel not open for writing");
--- a/netwerk/streamconv/converters/nsMultiMixedConv.cpp
+++ b/netwerk/streamconv/converters/nsMultiMixedConv.cpp
@@ -10,16 +10,17 @@
 #include "nsMimeTypes.h"
 #include "nsIStringStream.h"
 #include "nsCRT.h"
 #include "nsIHttpChannelInternal.h"
 #include "nsURLHelper.h"
 #include "nsIStreamConverterService.h"
 #include "nsIPackagedAppService.h"
 #include <algorithm>
+#include "nsContentSecurityManager.h"
 #include "nsHttp.h"
 
 //
 // Helper function for determining the length of data bytes up to
 // the next multipart token.  A token is usually preceded by a LF
 // or CRLF delimiter.
 // 
 static uint32_t
@@ -200,23 +201,41 @@ nsPartChannel::GetURI(nsIURI * *aURI)
 NS_IMETHODIMP
 nsPartChannel::Open(nsIInputStream **result)
 {
     // This channel cannot be opened!
     return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
+nsPartChannel::Open2(nsIInputStream** aStream)
+{
+    nsCOMPtr<nsIStreamListener> listener;
+    nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+    NS_ENSURE_SUCCESS(rv, rv);
+    return Open(aStream);
+}
+
+NS_IMETHODIMP
 nsPartChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
 {
     // This channel cannot be opened!
     return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
+nsPartChannel::AsyncOpen2(nsIStreamListener *aListener)
+{
+  nsCOMPtr<nsIStreamListener> listener = aListener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return AsyncOpen(listener, nullptr);
+}
+
+NS_IMETHODIMP
 nsPartChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
 {
     *aLoadFlags = mLoadFlags;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPartChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
--- a/uriloader/exthandler/ExternalHelperAppParent.cpp
+++ b/uriloader/exthandler/ExternalHelperAppParent.cpp
@@ -270,22 +270,34 @@ ExternalHelperAppParent::GetURI(nsIURI *
 
 NS_IMETHODIMP
 ExternalHelperAppParent::Open(nsIInputStream **aResult)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
+ExternalHelperAppParent::Open2(nsIInputStream** aStream)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
 ExternalHelperAppParent::AsyncOpen(nsIStreamListener *aListener,
                                    nsISupports *aContext)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
+NS_IMETHODIMP
+ExternalHelperAppParent::AsyncOpen2(nsIStreamListener *aListener)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
 
 NS_IMETHODIMP
 ExternalHelperAppParent::GetLoadFlags(nsLoadFlags *aLoadFlags)
 {
   *aLoadFlags = mLoadFlags;
   return NS_OK;
 }
 
--- a/uriloader/exthandler/nsExternalProtocolHandler.cpp
+++ b/uriloader/exthandler/nsExternalProtocolHandler.cpp
@@ -14,16 +14,17 @@
 #include "nsIServiceManager.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIStringBundle.h"
 #include "nsIPrefService.h"
 #include "nsIPrompt.h"
 #include "nsNetUtil.h"
+#include "nsContentSecurityManager.h"
 #include "nsExternalHelperAppService.h"
 
 // used to dispatch urls to default protocol handlers
 #include "nsCExternalHandlerService.h"
 #include "nsIExternalProtocolService.h"
 
 class nsILoadInfo;
 
@@ -170,26 +171,42 @@ finish:
   return rv;
 }
 
 NS_IMETHODIMP nsExtProtocolChannel::Open(nsIInputStream **_retval)
 {
   return OpenURL();
 }
 
+NS_IMETHODIMP nsExtProtocolChannel::Open2(nsIInputStream** aStream)
+{
+  nsCOMPtr<nsIStreamListener> listener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return Open(aStream);
+}
+
 NS_IMETHODIMP nsExtProtocolChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt)
 {
   NS_ENSURE_ARG_POINTER(listener);
   NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
 
   mWasOpened = true;
 
   return OpenURL();
 }
 
+NS_IMETHODIMP nsExtProtocolChannel::AsyncOpen2(nsIStreamListener *aListener)
+{
+  nsCOMPtr<nsIStreamListener> listener = aListener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return AsyncOpen(listener, nullptr);
+}
+
 NS_IMETHODIMP nsExtProtocolChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
 {
   *aLoadFlags = mLoadFlags;
   return NS_OK;
 }
 
 NS_IMETHODIMP nsExtProtocolChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
 {