Bug 1125372 - use nsISupports as first param of asyncResolve instead of switching wholesale from nsIURI to nsIChannel, for improved add-on compat, r=mcmanus
--- 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