Bug 1125372 - use nsISupports as first param of asyncResolve instead of switching wholesale from nsIURI to nsIChannel, for improved add-on compat, r=mcmanus
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Tue, 27 Jan 2015 21:30:49 +0000
changeset 239540 feea863c5f247b463547b356a991d707503099de
parent 239539 577212601d5c10f0316e304d8705f975ec3992cc
child 239541 3b544c5bb1a84c739bb6a677efb7a93789b4bff4
push id500
push userjoshua.m.grant@gmail.com
push dateThu, 29 Jan 2015 01:48:36 +0000
reviewersmcmanus
bugs1125372
milestone38.0a1
Bug 1125372 - use nsISupports as first param of asyncResolve instead of switching wholesale from nsIURI to nsIChannel, for improved add-on compat, r=mcmanus
netwerk/base/nsIProtocolProxyService.idl
netwerk/base/nsIProtocolProxyService2.idl
netwerk/base/nsProtocolProxyService.cpp
netwerk/protocol/ftp/nsFtpConnectionThread.cpp
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/test/unit/test_protocolproxyservice.js
--- a/netwerk/base/nsIProtocolProxyService.idl
+++ b/netwerk/base/nsIProtocolProxyService.idl
@@ -13,17 +13,17 @@ interface nsIProtocolProxyChannelFilter;
 interface nsIProxyInfo;
 interface nsIChannel;
 interface nsIURI;
 
 /**
  * nsIProtocolProxyService provides methods to access information about
  * various network proxies.
  */
-[scriptable, uuid(ab363090-c331-489f-aabb-7fe4481795b8)]
+[scriptable, uuid(deec8e08-a246-443c-90b6-f655632d1abf)]
 interface nsIProtocolProxyService : nsISupports
 {
     /** Flag 1 << 0 is unused **/
 
     /**
      * When the proxy configuration is manual this flag may be passed to the
      * resolve and asyncResolve methods to request to prefer the SOCKS proxy
      * to HTTP ones.
@@ -63,18 +63,21 @@ interface nsIProtocolProxyService : nsIS
      */
     const unsigned long RESOLVE_ALWAYS_TUNNEL = (1 << 4);
 
     /**
      * This method returns via callback a nsIProxyInfo instance that identifies
      * a proxy to be used for the given channel.  Otherwise, this method returns
      * null indicating that a direct connection should be used.
      *
-     * @param aChannel
-     *        The channel for which a proxy is to be found.
+     * @param aChannelOrURI
+     *        The channel for which a proxy is to be found, or, if no channel is
+     *        available, a URI indicating the same. This method will return
+     *        NS_ERROR_NOINTERFACE if this argument isn't either an nsIURI or an
+     *        nsIChannel.
      * @param aFlags
      *        A bit-wise combination of the RESOLVE_ flags defined above.  Pass
      *        0 to specify the default behavior.  Any additional bits that do
      *        not correspond to a RESOLVE_ flag are reserved for future use.
      * @param aCallback
      *        The object to be notified when the result is available.
      *
      * @return An object that can be used to cancel the asychronous operation.
@@ -90,17 +93,17 @@ interface nsIProtocolProxyService : nsIS
      * nsIChannel to the given URI that uses the specified proxy.
      *
      * NOTE: However, if the nsIProxyInfo type is "http", then it means that
      * the given URI should be loaded using the HTTP protocol handler, which
      * also supports nsIProxiedProtocolHandler.
      *
      * @see nsIProxiedProtocolHandler::newProxiedChannel 
      */
-    nsICancelable asyncResolve(in nsIChannel aChannel, in unsigned long aFlags,
+    nsICancelable asyncResolve(in nsISupports aChannelOrURI, in unsigned long aFlags,
                                in nsIProtocolProxyCallback aCallback);
 
     /**
      * This method may be called to construct a nsIProxyInfo instance from
      * the given parameters.  This method may be useful in conjunction with
      * nsISocketTransportService::createTransport for creating, for example,
      * a SOCKS connection.
      *
--- a/netwerk/base/nsIProtocolProxyService2.idl
+++ b/netwerk/base/nsIProtocolProxyService2.idl
@@ -14,16 +14,17 @@ interface nsIProtocolProxyService2 : nsI
 {
   /**
    * Call this method to cause the PAC file (if any is configured) to be
    * reloaded.  The PAC file is loaded asynchronously.
    */
   void reloadPAC();
 
     /**
-     * This method is identical to asyncResolve() except it may execute the
-     * callback function immediately (i.e from the stack of asyncResolve2()) if
-     * it is immediately ready to run. The nsICancelable return value will be
-     * null in that case.
+     * This method is identical to asyncResolve() except:
+     *  - it only accepts an nsIChannel, not an nsIURI;
+     *  - it may execute the callback function immediately (i.e from the stack
+     *    of asyncResolve2()) if it is immediately ready to run.
+     *    The nsICancelable return value will be null in that case.
      */
   nsICancelable asyncResolve2(in nsIChannel aChannel, in unsigned long aFlags,
                               in nsIProtocolProxyCallback aCallback);
 };
--- a/netwerk/base/nsProtocolProxyService.cpp
+++ b/netwerk/base/nsProtocolProxyService.cpp
@@ -1266,20 +1266,37 @@ NS_IMETHODIMP
 nsProtocolProxyService::AsyncResolve2(nsIChannel *channel, uint32_t flags,
                                       nsIProtocolProxyCallback *callback,
                                       nsICancelable **result)
 {
     return AsyncResolveInternal(channel, flags, callback, result, true);
 }
 
 NS_IMETHODIMP
-nsProtocolProxyService::AsyncResolve(nsIChannel *channel, uint32_t flags,
+nsProtocolProxyService::AsyncResolve(nsISupports *channelOrURI, uint32_t flags,
                                      nsIProtocolProxyCallback *callback,
                                      nsICancelable **result)
 {
+
+    nsresult rv;
+    // Check if we got a channel:
+    nsCOMPtr<nsIChannel> channel = do_QueryInterface(channelOrURI);
+    if (!channel) {
+        nsCOMPtr<nsIURI> uri = do_QueryInterface(channelOrURI);
+        if (!uri) {
+            return NS_ERROR_NO_INTERFACE;
+        }
+
+        // make a temporary channel from the URI
+        nsCOMPtr<nsIIOService> ios(do_GetIOService(&rv));
+        if (NS_FAILED(rv)) return rv;
+        rv = ios->NewChannelFromURI(uri, getter_AddRefs(channel));
+        if (NS_FAILED(rv)) return rv;
+    }
+
     return AsyncResolveInternal(channel, flags, callback, result, false);
 }
 
 NS_IMETHODIMP
 nsProtocolProxyService::NewProxyInfo(const nsACString &aType,
                                      const nsACString &aHost,
                                      int32_t aPort,
                                      uint32_t aFlags,
--- a/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
+++ b/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
@@ -1868,17 +1868,17 @@ nsFtpState::Init(nsFtpChannel *channel)
         mPort = port;
 
     // Lookup Proxy information asynchronously if it isn't already set
     // on the channel and if we aren't configured explicitly to go directly
     nsCOMPtr<nsIProtocolProxyService> pps =
         do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID);
 
     if (pps && !mChannel->ProxyInfo()) {
-        pps->AsyncResolve(mChannel, 0, this,
+        pps->AsyncResolve(static_cast<nsIChannel*>(mChannel), 0, this,
                           getter_AddRefs(mProxyRequest));
     }
 
     return NS_OK;
 }
 
 void
 nsFtpState::Connect()
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -2034,17 +2034,17 @@ nsHttpChannel::ResolveProxy()
     // using the nsIProtocolProxyService2 allows a minor performance
     // optimization, but if an add-on has only provided the original interface
     // then it is ok to use that version.
     nsCOMPtr<nsIProtocolProxyService2> pps2 = do_QueryInterface(pps);
     if (pps2) {
         rv = pps2->AsyncResolve2(this, mProxyResolveFlags,
                                  this, getter_AddRefs(mProxyRequest));
     } else {
-        rv = pps->AsyncResolve(this, mProxyResolveFlags,
+        rv = pps->AsyncResolve(static_cast<nsIChannel*>(this), mProxyResolveFlags,
                                this, getter_AddRefs(mProxyRequest));
     }
 
     return rv;
 }
 
 bool
 nsHttpChannel::ResponseWouldVary(nsICacheEntry* entry) const
--- a/netwerk/test/unit/test_protocolproxyservice.js
+++ b/netwerk/test/unit/test_protocolproxyservice.js
@@ -237,16 +237,73 @@ function filter_test0_4(pi)
   var req = pps.asyncResolve(channel, 0, cb);
 }
 
 function filter_test0_5(pi)
 {
   pps.unregisterChannelFilter(filter03);
   check_proxy(pi, "http", "www.mozilla.org", 7777, 0, 10, true);
   check_proxy(pi.failoverProxy, "direct", "", -1, 0, 0, false);
+  run_filter_test_uri();
+}
+
+function run_filter_test_uri() {
+  var cb = new resolveCallback();
+  cb.nextFunction = filter_test_uri0_1;
+  var uri = ios.newURI("http://www.mozilla.org/", null, null);
+  pps.asyncResolve(uri, 0, cb);
+}
+
+function filter_test_uri0_1(pi) {
+  do_check_eq(pi, null);
+
+  // Push a filter and verify the results
+
+  filter01 = new BasicFilter();
+  filter02 = new BasicFilter();
+  pps.registerFilter(filter01, 10);
+  pps.registerFilter(filter02, 20);
+
+  var cb = new resolveCallback();
+  cb.nextFunction = filter_test_uri0_2;
+  var uri = ios.newURI("http://www.mozilla.org/", null, null);
+  pps.asyncResolve(uri, 0, cb);
+}
+
+function filter_test_uri0_2(pi)
+{
+  check_proxy(pi, "http", "localhost", 8080, 0, 10, true);
+  check_proxy(pi.failoverProxy, "direct", "", -1, 0, 0, false);
+
+  pps.unregisterFilter(filter02);
+
+  var cb = new resolveCallback();
+  cb.nextFunction = filter_test_uri0_3;
+  var uri = ios.newURI("http://www.mozilla.org/", null, null);
+  pps.asyncResolve(uri, 0, cb);
+}
+
+function filter_test_uri0_3(pi)
+{
+  check_proxy(pi, "http", "localhost", 8080, 0, 10, true);
+  check_proxy(pi.failoverProxy, "direct", "", -1, 0, 0, false);
+
+  // Remove filter and verify that we return to the initial state
+
+  pps.unregisterFilter(filter01);
+
+  var cb = new resolveCallback();
+  cb.nextFunction = filter_test_uri0_4;
+  var uri = ios.newURI("http://www.mozilla.org/", null, null);
+  pps.asyncResolve(uri, 0, cb);
+}
+
+function filter_test_uri0_4(pi)
+{
+  do_check_eq(pi, null);
   run_filter_test2();
 }
 
 var filter11;
 var filter12;
 
 function run_filter_test2() {
   // Push a filter and verify the results