Bug 1214122 - Check if addon ProtocolHandler actually provide nsHttpChannel. r=sicking,mayhemer,ba=sylvestre
authorDragana Damjanovic <dd.mozilla@gmail.com>
Fri, 16 Oct 2015 06:07:00 +0200
changeset 289606 e1261e250e85
parent 289605 4cebb6ab9288
child 289607 aac4b4aaa5f4
push id5215
push usercbook@mozilla.com
push date2015-10-22 07:52 +0000
treeherdermozilla-beta@e1261e250e85 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking, mayhemer
bugs1214122
milestone42.0
Bug 1214122 - Check if addon ProtocolHandler actually provide nsHttpChannel. r=sicking,mayhemer,ba=sylvestre
netwerk/base/nsIForcePendingChannel.idl
netwerk/base/nsIOService.cpp
netwerk/base/nsSecCheckWrapChannel.cpp
netwerk/base/nsSecCheckWrapChannel.h
--- a/netwerk/base/nsIForcePendingChannel.idl
+++ b/netwerk/base/nsIForcePendingChannel.idl
@@ -4,17 +4,17 @@
 
 #include "nsISupports.idl"
 
 /**
  * nsIForcePending interface exposes a function that enables overwriting of the normal 
  * behavior for the channel's IsPending(), forcing 'true' to be returned.
  */
 
-[scriptable, uuid(225ab092-1554-423a-9492-606f6db3b4fb)]
+[noscript, uuid(2ac3e1ca-049f-44c3-a519-f0681f51e9b1)]
 interface nsIForcePendingChannel : nsISupports
 {
 
 /**
      * forcePending(true) overrides the normal behavior for the 
      * channel's IsPending(), forcing 'true' to be returned. A call to
      * forcePending(false) reverts IsPending() back to normal behavior.
      */
--- a/netwerk/base/nsIOService.cpp
+++ b/netwerk/base/nsIOService.cpp
@@ -744,29 +744,34 @@ nsIOService::NewChannelFromURIWithProxyF
         rv = pph->NewProxiedChannel2(aURI, nullptr, aProxyFlags, aProxyURI,
                                      aLoadInfo, getter_AddRefs(channel));
         // if calling NewProxiedChannel2() fails we try to fall back to
         // creating a new proxied channel by calling NewProxiedChannel().
         if (NS_FAILED(rv)) {
             rv = pph->NewProxiedChannel(aURI, nullptr, aProxyFlags, aProxyURI,
                                         getter_AddRefs(channel));
             NS_ENSURE_SUCCESS(rv, rv);
-            // we have to wrap that channel
-            channel = new nsSecCheckWrapChannel(channel, aLoadInfo);
+
+            // The protocol handler does not implement NewProxiedChannel2, so
+            // maybe we need to wrap the channel (see comment in MaybeWrap
+            // function).
+            channel = nsSecCheckWrapChannel::MaybeWrap(channel, aLoadInfo);
         }
     }
     else {
         rv = handler->NewChannel2(aURI, aLoadInfo, getter_AddRefs(channel));
         // if calling newChannel2() fails we try to fall back to
         // creating a new channel by calling NewChannel().
         if (NS_FAILED(rv)) {
             rv = handler->NewChannel(aURI, getter_AddRefs(channel));
             NS_ENSURE_SUCCESS(rv, rv);
-            // we have to wrap that channel
-            channel = new nsSecCheckWrapChannel(channel, aLoadInfo);
+            // The protocol handler does not implement NewChannel2, so
+            // maybe we need to wrap the channel (see comment in MaybeWrap
+            // function).
+            channel = nsSecCheckWrapChannel::MaybeWrap(channel, aLoadInfo);
         }
     }
 
     // Make sure that all the individual protocolhandlers attach a loadInfo.
     if (aLoadInfo) {
       // make sure we have the same instance of loadInfo on the newly created channel
       nsCOMPtr<nsILoadInfo> loadInfo;
       channel->GetLoadInfo(getter_AddRefs(loadInfo));
--- a/netwerk/base/nsSecCheckWrapChannel.cpp
+++ b/netwerk/base/nsSecCheckWrapChannel.cpp
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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 "nsSecCheckWrapChannel.h"
-#include "nsHttpChannel.h"
+#include "nsIForcePendingChannel.h"
 #include "nsCOMPtr.h"
 
 static PRLogModuleInfo*
 GetChannelWrapperLog()
 {
   static PRLogModuleInfo* gChannelWrapperPRLog;
   if (!gChannelWrapperPRLog) {
     gChannelWrapperPRLog = PR_NewLogModule("ChannelWrapper");
@@ -79,16 +79,41 @@ nsSecCheckWrapChannel::nsSecCheckWrapCha
     nsAutoCString spec;
     if (uri) {
       uri->GetSpec(spec);
     }
     CHANNELWRAPPERLOG(("nsSecCheckWrapChannel::nsSecCheckWrapChannel [%p] (%s)",this, spec.get()));
   }
 }
 
+// static
+already_AddRefed<nsIChannel>
+nsSecCheckWrapChannel::MaybeWrap(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
+{
+  // Maybe a custom protocol handler actually returns a gecko
+  // http/ftpChannel - To check this we will check whether the channel
+  // implements a gecko non-scriptable interface e.g. nsIForcePendingChannel.
+  nsCOMPtr<nsIForcePendingChannel> isGeckoChannel = do_QueryInterface(aChannel);
+
+  nsCOMPtr<nsIChannel> channel = aChannel;
+  if (isGeckoChannel) {
+    // If it is a gecko channel (ftp or http) we do not need to wrap it.
+    channel->SetLoadInfo(aLoadInfo);
+  } else {
+    nsCOMPtr<nsIHttpChannel> httpChannel =
+      do_QueryInterface(aChannel);
+    // we can only wrap http channel.
+    if (httpChannel) {
+      // we have to wrap that channel
+      channel = new nsSecCheckWrapChannel(aChannel, aLoadInfo);
+    }
+  }
+  return channel.forget();
+}
+
 nsSecCheckWrapChannel::~nsSecCheckWrapChannel()
 {
 }
 
 //---------------------------------------------------------
 // SecWrapChannelStreamListener helper
 //---------------------------------------------------------
 
--- a/netwerk/base/nsSecCheckWrapChannel.h
+++ b/netwerk/base/nsSecCheckWrapChannel.h
@@ -83,16 +83,18 @@ class nsSecCheckWrapChannel : public nsS
 public:
   NS_IMETHOD GetLoadInfo(nsILoadInfo **aLoadInfo);
   NS_IMETHOD SetLoadInfo(nsILoadInfo *aLoadInfo);
 
   NS_IMETHOD AsyncOpen2(nsIStreamListener *aListener);
   NS_IMETHOD Open2(nsIInputStream** aStream);
 
   nsSecCheckWrapChannel(nsIChannel* aChannel, nsILoadInfo* aLoadInfo);
+  static already_AddRefed<nsIChannel> MaybeWrap(nsIChannel* aChannel,
+                                                nsILoadInfo* aLoadInfo);
 
 protected:
   virtual ~nsSecCheckWrapChannel();
 
   nsCOMPtr<nsILoadInfo> mLoadInfo;
 };
 
 #endif // nsSecCheckWrapChannel_h__