mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
bug 769764 move proxy resolution to separate thread and remove sync api r=biesi sr=josh
This commit is contained in:
parent
ac1c6eefd9
commit
cd31dfef08
@ -366,8 +366,6 @@
|
|||||||
@BINPATH@/components/nsHelperAppDlg.js
|
@BINPATH@/components/nsHelperAppDlg.js
|
||||||
@BINPATH@/components/nsDownloadManagerUI.manifest
|
@BINPATH@/components/nsDownloadManagerUI.manifest
|
||||||
@BINPATH@/components/nsDownloadManagerUI.js
|
@BINPATH@/components/nsDownloadManagerUI.js
|
||||||
@BINPATH@/components/nsProxyAutoConfig.manifest
|
|
||||||
@BINPATH@/components/nsProxyAutoConfig.js
|
|
||||||
@BINPATH@/components/NetworkGeolocationProvider.manifest
|
@BINPATH@/components/NetworkGeolocationProvider.manifest
|
||||||
@BINPATH@/components/NetworkGeolocationProvider.js
|
@BINPATH@/components/NetworkGeolocationProvider.js
|
||||||
@BINPATH@/components/GPSDGeolocationProvider.manifest
|
@BINPATH@/components/GPSDGeolocationProvider.manifest
|
||||||
|
@ -361,8 +361,6 @@
|
|||||||
@BINPATH@/components/nsHelperAppDlg.js
|
@BINPATH@/components/nsHelperAppDlg.js
|
||||||
@BINPATH@/components/nsDownloadManagerUI.manifest
|
@BINPATH@/components/nsDownloadManagerUI.manifest
|
||||||
@BINPATH@/components/nsDownloadManagerUI.js
|
@BINPATH@/components/nsDownloadManagerUI.js
|
||||||
@BINPATH@/components/nsProxyAutoConfig.manifest
|
|
||||||
@BINPATH@/components/nsProxyAutoConfig.js
|
|
||||||
@BINPATH@/components/NetworkGeolocationProvider.manifest
|
@BINPATH@/components/NetworkGeolocationProvider.manifest
|
||||||
@BINPATH@/components/NetworkGeolocationProvider.js
|
@BINPATH@/components/NetworkGeolocationProvider.js
|
||||||
@BINPATH@/components/GPSDGeolocationProvider.manifest
|
@BINPATH@/components/GPSDGeolocationProvider.manifest
|
||||||
|
@ -87,6 +87,8 @@ components/xpcom.xpt
|
|||||||
components/xpti.dat
|
components/xpti.dat
|
||||||
components/xptitemp.dat
|
components/xptitemp.dat
|
||||||
components/nsMicrosummaryService.js
|
components/nsMicrosummaryService.js
|
||||||
|
components/nsProxyAutoConfig.manifest
|
||||||
|
components/nsProxyAutoConfig.js
|
||||||
D3DCompiler_42.dll
|
D3DCompiler_42.dll
|
||||||
d3dx9_42.dll
|
d3dx9_42.dll
|
||||||
defaults/pref/all.js
|
defaults/pref/all.js
|
||||||
@ -921,6 +923,7 @@ xpicleanup@BIN_SUFFIX@
|
|||||||
components/nsPlacesExpiration.js
|
components/nsPlacesExpiration.js
|
||||||
components/nsPrivateBrowsingService.js
|
components/nsPrivateBrowsingService.js
|
||||||
components/nsPrompter.js
|
components/nsPrompter.js
|
||||||
|
components/nsProxyAutoConfig.manifest
|
||||||
components/nsProxyAutoConfig.js
|
components/nsProxyAutoConfig.js
|
||||||
components/nsSafebrowsingApplication.js
|
components/nsSafebrowsingApplication.js
|
||||||
components/nsSearchService.js
|
components/nsSearchService.js
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
#include "nsIURL.h"
|
#include "nsIURL.h"
|
||||||
#include "nsXPIDLString.h"
|
#include "nsXPIDLString.h"
|
||||||
#include "nsReadableUtils.h"
|
#include "nsReadableUtils.h"
|
||||||
#include "nsIProtocolProxyService.h"
|
#include "nsIProtocolProxyService2.h"
|
||||||
#include "nsIStreamConverterService.h"
|
#include "nsIStreamConverterService.h"
|
||||||
#include "nsIFile.h"
|
#include "nsIFile.h"
|
||||||
#if defined(XP_MACOSX)
|
#if defined(XP_MACOSX)
|
||||||
@ -743,12 +743,17 @@ nsresult nsPluginHost::FindProxyForURL(const char* url, char* *result)
|
|||||||
|
|
||||||
nsCOMPtr<nsIURI> uriIn;
|
nsCOMPtr<nsIURI> uriIn;
|
||||||
nsCOMPtr<nsIProtocolProxyService> proxyService;
|
nsCOMPtr<nsIProtocolProxyService> proxyService;
|
||||||
|
nsCOMPtr<nsIProtocolProxyService2> proxyService2;
|
||||||
nsCOMPtr<nsIIOService> ioService;
|
nsCOMPtr<nsIIOService> ioService;
|
||||||
|
|
||||||
proxyService = do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &res);
|
proxyService = do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &res);
|
||||||
if (NS_FAILED(res) || !proxyService)
|
if (NS_FAILED(res) || !proxyService)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
proxyService2 = do_QueryInterface(proxyService, &res);
|
||||||
|
if (NS_FAILED(res) || !proxyService)
|
||||||
|
return res;
|
||||||
|
|
||||||
ioService = do_GetService(NS_IOSERVICE_CONTRACTID, &res);
|
ioService = do_GetService(NS_IOSERVICE_CONTRACTID, &res);
|
||||||
if (NS_FAILED(res) || !ioService)
|
if (NS_FAILED(res) || !ioService)
|
||||||
return res;
|
return res;
|
||||||
@ -760,7 +765,8 @@ nsresult nsPluginHost::FindProxyForURL(const char* url, char* *result)
|
|||||||
|
|
||||||
nsCOMPtr<nsIProxyInfo> pi;
|
nsCOMPtr<nsIProxyInfo> pi;
|
||||||
|
|
||||||
res = proxyService->Resolve(uriIn, 0, getter_AddRefs(pi));
|
// Remove this with bug 778201
|
||||||
|
res = proxyService2->DeprecatedBlockingResolve(uriIn, 0, getter_AddRefs(pi));
|
||||||
if (NS_FAILED(res))
|
if (NS_FAILED(res))
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
@ -275,8 +275,6 @@
|
|||||||
@BINPATH@/components/nsHelperAppDlg.js
|
@BINPATH@/components/nsHelperAppDlg.js
|
||||||
@BINPATH@/components/nsDownloadManagerUI.manifest
|
@BINPATH@/components/nsDownloadManagerUI.manifest
|
||||||
@BINPATH@/components/nsDownloadManagerUI.js
|
@BINPATH@/components/nsDownloadManagerUI.js
|
||||||
@BINPATH@/components/nsProxyAutoConfig.manifest
|
|
||||||
@BINPATH@/components/nsProxyAutoConfig.js
|
|
||||||
@BINPATH@/components/NetworkGeolocationProvider.manifest
|
@BINPATH@/components/NetworkGeolocationProvider.manifest
|
||||||
@BINPATH@/components/NetworkGeolocationProvider.js
|
@BINPATH@/components/NetworkGeolocationProvider.js
|
||||||
@BINPATH@/components/GPSDGeolocationProvider.manifest
|
@BINPATH@/components/GPSDGeolocationProvider.manifest
|
||||||
|
@ -342,8 +342,6 @@
|
|||||||
@BINPATH@/components/nsHelperAppDlg.js
|
@BINPATH@/components/nsHelperAppDlg.js
|
||||||
@BINPATH@/components/nsDownloadManagerUI.manifest
|
@BINPATH@/components/nsDownloadManagerUI.manifest
|
||||||
@BINPATH@/components/nsDownloadManagerUI.js
|
@BINPATH@/components/nsDownloadManagerUI.js
|
||||||
@BINPATH@/components/nsProxyAutoConfig.manifest
|
|
||||||
@BINPATH@/components/nsProxyAutoConfig.js
|
|
||||||
@BINPATH@/components/NetworkGeolocationProvider.manifest
|
@BINPATH@/components/NetworkGeolocationProvider.manifest
|
||||||
@BINPATH@/components/NetworkGeolocationProvider.js
|
@BINPATH@/components/NetworkGeolocationProvider.js
|
||||||
@BINPATH@/components/GPSDGeolocationProvider.manifest
|
@BINPATH@/components/GPSDGeolocationProvider.manifest
|
||||||
|
@ -66,7 +66,6 @@ XPIDLSRCS = \
|
|||||||
nsIProtocolProxyFilter.idl \
|
nsIProtocolProxyFilter.idl \
|
||||||
nsIProtocolProxyCallback.idl \
|
nsIProtocolProxyCallback.idl \
|
||||||
nsIProxiedProtocolHandler.idl \
|
nsIProxiedProtocolHandler.idl \
|
||||||
nsIProxyAutoConfig.idl \
|
|
||||||
nsIProxyInfo.idl \
|
nsIProxyInfo.idl \
|
||||||
nsITransport.idl \
|
nsITransport.idl \
|
||||||
nsISocketTransport.idl \
|
nsISocketTransport.idl \
|
||||||
|
@ -17,24 +17,10 @@ interface nsIURI;
|
|||||||
* nsIProtocolProxyService provides methods to access information about
|
* nsIProtocolProxyService provides methods to access information about
|
||||||
* various network proxies.
|
* various network proxies.
|
||||||
*/
|
*/
|
||||||
[scriptable, uuid(d7ec6237-162e-40f5-a2b4-46ccd5fa83c9)]
|
[scriptable, uuid(e77c642b-026f-41ce-9b23-f829a6e3f300)]
|
||||||
interface nsIProtocolProxyService : nsISupports
|
interface nsIProtocolProxyService : nsISupports
|
||||||
{
|
{
|
||||||
/**
|
/** Flag 1 << 0 is unused **/
|
||||||
* This flag may be passed to the resolve method to request that it fail
|
|
||||||
* instead of block the calling thread. Proxy Auto Config (PAC) may
|
|
||||||
* perform a synchronous DNS query, which may not return immediately. So,
|
|
||||||
* calling resolve without this flag may result in locking up the calling
|
|
||||||
* thread for a lengthy period of time.
|
|
||||||
*
|
|
||||||
* By passing this flag to resolve, one can failover to asyncResolve to
|
|
||||||
* avoid locking up the calling thread if a PAC query is required.
|
|
||||||
*
|
|
||||||
* When this flag is passed to resolve, resolve may throw the exception
|
|
||||||
* NS_BASE_STREAM_WOULD_BLOCK to indicate that it failed due to this flag
|
|
||||||
* being present.
|
|
||||||
*/
|
|
||||||
const unsigned long RESOLVE_NON_BLOCKING = 1 << 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When the proxy configuration is manual this flag may be passed to the
|
* When the proxy configuration is manual this flag may be passed to the
|
||||||
@ -77,44 +63,9 @@ interface nsIProtocolProxyService : nsISupports
|
|||||||
const unsigned long RESOLVE_ALWAYS_TUNNEL = (1 << 4);
|
const unsigned long RESOLVE_ALWAYS_TUNNEL = (1 << 4);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns a nsIProxyInfo instance that identifies a proxy to
|
* This method returns via callback a nsIProxyInfo instance that identifies
|
||||||
* be used for loading the given URI. Otherwise, this method returns null
|
* a proxy to be used for loading the given URI. Otherwise, this method returns
|
||||||
* indicating that a direct connection should be used.
|
* null indicating that a direct connection should be used.
|
||||||
*
|
|
||||||
* @param aURI
|
|
||||||
* The URI to test.
|
|
||||||
* @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.
|
|
||||||
*
|
|
||||||
* NOTE: If this proxy is unavailable, getFailoverForProxy may be called
|
|
||||||
* to determine the correct secondary proxy to be used.
|
|
||||||
*
|
|
||||||
* NOTE: If the protocol handler for the given URI supports
|
|
||||||
* nsIProxiedProtocolHandler, then the nsIProxyInfo instance returned from
|
|
||||||
* resolve may be passed to the newProxiedChannel method to create a
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* NOTE: If PAC is configured, and the PAC file has not yet been loaded,
|
|
||||||
* then this method will return a nsIProxyInfo instance with a type of
|
|
||||||
* "unknown" to indicate to the consumer that asyncResolve should be used
|
|
||||||
* to wait for the PAC file to finish loading. Otherwise, the consumer
|
|
||||||
* may choose to treat the result as type "direct" if desired.
|
|
||||||
*
|
|
||||||
* @see nsIProxiedProtocolHandler::newProxiedChannel
|
|
||||||
*/
|
|
||||||
nsIProxyInfo resolve(in nsIURI aURI, in unsigned long aFlags);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is an asychronous version of the resolve method. Unlike
|
|
||||||
* resolve, this method is guaranteed not to block the calling thread
|
|
||||||
* waiting for DNS queries to complete. This method is intended as a
|
|
||||||
* substitute for resolve when the result is not needed immediately.
|
|
||||||
*
|
*
|
||||||
* @param aURI
|
* @param aURI
|
||||||
* The URI to test.
|
* The URI to test.
|
||||||
@ -128,6 +79,20 @@ interface nsIProtocolProxyService : nsISupports
|
|||||||
* @return An object that can be used to cancel the asychronous operation.
|
* @return An object that can be used to cancel the asychronous operation.
|
||||||
* If canceled, the cancelation status (aReason) will be forwarded
|
* If canceled, the cancelation status (aReason) will be forwarded
|
||||||
* to the callback's onProxyAvailable method via the aStatus param.
|
* to the callback's onProxyAvailable method via the aStatus param.
|
||||||
|
*
|
||||||
|
* NOTE: If this proxy is unavailable, getFailoverForProxy may be called
|
||||||
|
* to determine the correct secondary proxy to be used.
|
||||||
|
*
|
||||||
|
* NOTE: If the protocol handler for the given URI supports
|
||||||
|
* nsIProxiedProtocolHandler, then the nsIProxyInfo instance returned from
|
||||||
|
* resolve may be passed to the newProxiedChannel method to create a
|
||||||
|
* 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 nsIURI aURI, in unsigned long aFlags,
|
nsICancelable asyncResolve(in nsIURI aURI, in unsigned long aFlags,
|
||||||
in nsIProtocolProxyCallback aCallback);
|
in nsIProtocolProxyCallback aCallback);
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
/**
|
/**
|
||||||
* An extension of nsIProtocolProxyService
|
* An extension of nsIProtocolProxyService
|
||||||
*/
|
*/
|
||||||
[scriptable, uuid(dbd9565d-29b1-437a-bff5-2fc339e2c5df)]
|
[scriptable, uuid(bed3702d-9374-4804-a20f-32baed8e2954)]
|
||||||
interface nsIProtocolProxyService2 : nsIProtocolProxyService
|
interface nsIProtocolProxyService2 : nsIProtocolProxyService
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@ -17,4 +17,13 @@ interface nsIProtocolProxyService2 : nsIProtocolProxyService
|
|||||||
* reloaded. The PAC file is loaded asynchronously.
|
* reloaded. The PAC file is loaded asynchronously.
|
||||||
*/
|
*/
|
||||||
void reloadPAC();
|
void reloadPAC();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This exists so Java(tm) can migrate to an asynchronous interface.
|
||||||
|
* Do not use this unless you are the plugin interface, and even then you
|
||||||
|
* ought to feel horribly guilty because you will create main thread jank.
|
||||||
|
*
|
||||||
|
* No documentation - it is deprecated!
|
||||||
|
**/
|
||||||
|
nsIProxyInfo deprecatedBlockingResolve(in nsIURI aURI, in unsigned long aFlags);
|
||||||
};
|
};
|
||||||
|
@ -9,12 +9,26 @@ interface nsIChannel;
|
|||||||
interface nsIURI;
|
interface nsIURI;
|
||||||
interface nsIProxyInfo;
|
interface nsIProxyInfo;
|
||||||
|
|
||||||
[scriptable, uuid(0a24fed4-1dd2-11b2-a75c-9f8b9a8f9ba7)]
|
[scriptable, uuid(2b63fe69-b0fc-48f2-a2df-adb795a4ce5c)]
|
||||||
interface nsIProxiedProtocolHandler : nsIProtocolHandler
|
interface nsIProxiedProtocolHandler : nsIProtocolHandler
|
||||||
{
|
{
|
||||||
/** Create a new channel with the given proxyInfo
|
/** Create a new channel with the given proxyInfo
|
||||||
*
|
*
|
||||||
|
* @param uri the channel uri
|
||||||
|
* @param proxyInfo any proxy information that has already been determined,
|
||||||
|
* or null if channel should later determine the proxy on its own using
|
||||||
|
* proxyResolveFlags/proxyURI
|
||||||
|
* @param proxyResolveFlags used if the proxy is later determined
|
||||||
|
* from nsIProtocolProxyService::asyncResolve
|
||||||
|
* @param proxyURI used if the proxy is later determined from
|
||||||
|
* nsIProtocolProxyService::asyncResolve with this as the proxyURI name.
|
||||||
|
* Generally this is the same as uri (or null which has the same
|
||||||
|
* effect), except in the case of websockets which wants to bootstrap
|
||||||
|
* to an http:// channel but make its proxy determination based on
|
||||||
|
* a ws:// uri.
|
||||||
*/
|
*/
|
||||||
nsIChannel newProxiedChannel(in nsIURI uri, in nsIProxyInfo proxyInfo);
|
nsIChannel newProxiedChannel(in nsIURI uri, in nsIProxyInfo proxyInfo,
|
||||||
|
in unsigned long proxyResolveFlags,
|
||||||
|
in nsIURI proxyURI);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,68 +0,0 @@
|
|||||||
/* -*- Mode: IDL; tab-width: 4; 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 "nsISupports.idl"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The nsIProxyAutoConfig interface is used for setting arbitrary proxy
|
|
||||||
* configurations based on the specified URL.
|
|
||||||
*
|
|
||||||
* Note this interface wraps (at least in the implementation) the older
|
|
||||||
* hacks of proxy auto config.
|
|
||||||
*
|
|
||||||
* - Gagan Saksena 04/23/00
|
|
||||||
*/
|
|
||||||
|
|
||||||
[scriptable, uuid(a42619df-0a1c-46fb-8154-0e9b8f8f1ea8)]
|
|
||||||
interface nsIProxyAutoConfig : nsISupports
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* This method initializes the object. This method may be called multiple
|
|
||||||
* times. If either parameter is an empty value, then the object is
|
|
||||||
* reset to its initial state.
|
|
||||||
*
|
|
||||||
* @param aPACURI
|
|
||||||
* URI used to fetch the PAC script. This is needed for properly
|
|
||||||
* constructing the JS sandbox used to evaluate the PAC script.
|
|
||||||
* @param aPACScript
|
|
||||||
* Javascript program text.
|
|
||||||
*/
|
|
||||||
void init(in ACString aPACURI, in AString aPACScript);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the proxy string for the specified URI. The proxy string is
|
|
||||||
* given by the following:
|
|
||||||
*
|
|
||||||
* result = proxy-spec *( proxy-sep proxy-spec )
|
|
||||||
* proxy-spec = direct-type | proxy-type LWS proxy-host [":" proxy-port]
|
|
||||||
* direct-type = "DIRECT"
|
|
||||||
* proxy-type = "PROXY" | "SOCKS" | "SOCKS4" | "SOCKS5"
|
|
||||||
* proxy-sep = ";" LWS
|
|
||||||
* proxy-host = hostname | ipv4-address-literal
|
|
||||||
* proxy-port = <any 16-bit unsigned integer>
|
|
||||||
* LWS = *( SP | HT )
|
|
||||||
* SP = <US-ASCII SP, space (32)>
|
|
||||||
* HT = <US-ASCII HT, horizontal-tab (9)>
|
|
||||||
*
|
|
||||||
* NOTE: direct-type and proxy-type are case insensitive
|
|
||||||
* NOTE: SOCKS implies SOCKS4
|
|
||||||
*
|
|
||||||
* Examples:
|
|
||||||
* "PROXY proxy1.foo.com:8080; PROXY proxy2.foo.com:8080; DIRECT"
|
|
||||||
* "SOCKS socksproxy"
|
|
||||||
* "DIRECT"
|
|
||||||
*
|
|
||||||
* XXX add support for IPv6 address literals.
|
|
||||||
* XXX quote whatever the official standard is for PAC.
|
|
||||||
*
|
|
||||||
* @param aTestURI
|
|
||||||
* The URI as an ASCII string to test.
|
|
||||||
* @param aTestHost
|
|
||||||
* The ASCII hostname to test.
|
|
||||||
*
|
|
||||||
* @return PAC result string as defined above.
|
|
||||||
*/
|
|
||||||
ACString getProxyForURI(in ACString aTestURI, in ACString aTestHost);
|
|
||||||
};
|
|
@ -13,17 +13,31 @@
|
|||||||
* either return the proper proxy data from the autoconfig URL specified in the system proxy,
|
* either return the proper proxy data from the autoconfig URL specified in the system proxy,
|
||||||
* or generate proxy data based on the system's manual proxy settings.
|
* or generate proxy data based on the system's manual proxy settings.
|
||||||
*/
|
*/
|
||||||
[scriptable, uuid(a9f3ae38-b769-4e0b-9317-578388e326c9)]
|
[scriptable, uuid(971591cd-277e-409a-bbf6-0a79879cd307)]
|
||||||
interface nsISystemProxySettings : nsISupports
|
interface nsISystemProxySettings : nsISupports
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Whether or not it is appropriate to execute getProxyForURI off the main thread.
|
||||||
|
* If that method can block (e.g. for WPAD as windows does) then it must be
|
||||||
|
* not mainThreadOnly to avoid creating main thread jank. The main thread only option is
|
||||||
|
* provided for implementations that do not block but use other main thread only
|
||||||
|
* functions such as dbus.
|
||||||
|
*/
|
||||||
|
readonly attribute bool mainThreadOnly;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If non-empty, use this PAC file. If empty, call getProxyForURI instead.
|
* If non-empty, use this PAC file. If empty, call getProxyForURI instead.
|
||||||
*/
|
*/
|
||||||
readonly attribute AUTF8String PACURI;
|
readonly attribute AUTF8String PACURI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See nsIProxyAutoConfig::getProxyForURI; this function behaves exactly
|
* See ProxyAutoConfig::getProxyForURI; this function behaves similarly except
|
||||||
* the same way.
|
* a more relaxed return string is allowed that includes full urls instead of just
|
||||||
|
* host:port syntax. e.g. "PROXY http://www.foo.com:8080" instead of
|
||||||
|
* "PROXY www.foo.com:8080"
|
||||||
*/
|
*/
|
||||||
AUTF8String getProxyForURI(in nsIURI aURI);
|
AUTF8String getProxyForURI(in AUTF8String testSpec,
|
||||||
|
in AUTF8String testScheme,
|
||||||
|
in AUTF8String testHost,
|
||||||
|
in int32_t testPort);
|
||||||
};
|
};
|
||||||
|
@ -851,40 +851,6 @@ NS_GetReferrerFromChannel(nsIChannel *channel,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MOZILLA_INTERNAL_API
|
|
||||||
inline nsresult
|
|
||||||
NS_ExamineForProxy(const char *scheme,
|
|
||||||
const char *host,
|
|
||||||
int32_t port,
|
|
||||||
nsIProxyInfo **proxyInfo)
|
|
||||||
{
|
|
||||||
nsresult rv;
|
|
||||||
nsCOMPtr<nsIProtocolProxyService> pps =
|
|
||||||
do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &rv);
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
|
||||||
nsAutoCString spec(scheme);
|
|
||||||
spec.Append("://");
|
|
||||||
spec.Append(host);
|
|
||||||
spec.Append(':');
|
|
||||||
spec.AppendInt(port);
|
|
||||||
// XXXXX - Under no circumstances whatsoever should any code which
|
|
||||||
// wants a uri do this. I do this here because I do not, in fact,
|
|
||||||
// actually want a uri (the dummy uris created here may not be
|
|
||||||
// syntactically valid for the specific protocol), and all we need
|
|
||||||
// is something which has a valid scheme, hostname, and a string
|
|
||||||
// to pass to PAC if needed - bbaetz
|
|
||||||
nsCOMPtr<nsIURI> uri =
|
|
||||||
do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv);
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
|
||||||
rv = uri->SetSpec(spec);
|
|
||||||
if (NS_SUCCEEDED(rv))
|
|
||||||
rv = pps->Resolve(uri, 0, proxyInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
inline nsresult
|
inline nsresult
|
||||||
NS_ParseContentType(const nsACString &rawContentType,
|
NS_ParseContentType(const nsACString &rawContentType,
|
||||||
nsCString &contentType,
|
nsCString &contentType,
|
||||||
|
@ -66,8 +66,11 @@ CPPSRCS = \
|
|||||||
RedirectChannelRegistrar.cpp \
|
RedirectChannelRegistrar.cpp \
|
||||||
nsPreloadedStream.cpp \
|
nsPreloadedStream.cpp \
|
||||||
nsStreamListenerWrapper.cpp \
|
nsStreamListenerWrapper.cpp \
|
||||||
|
ProxyAutoConfig.cpp \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
LOCAL_INCLUDES += -I$(topsrcdir)/dom/base
|
||||||
|
|
||||||
ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
|
ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
|
||||||
CPPSRCS += nsURLHelperOS2.cpp
|
CPPSRCS += nsURLHelperOS2.cpp
|
||||||
else
|
else
|
||||||
@ -97,11 +100,6 @@ ifdef MOZ_ENABLE_QTNETWORK
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
EXTRA_COMPONENTS = \
|
|
||||||
$(srcdir)/nsProxyAutoConfig.js \
|
|
||||||
$(srcdir)/nsProxyAutoConfig.manifest \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
EXTRA_JS_MODULES = \
|
EXTRA_JS_MODULES = \
|
||||||
NetUtil.jsm \
|
NetUtil.jsm \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
623
netwerk/base/src/ProxyAutoConfig.cpp
Normal file
623
netwerk/base/src/ProxyAutoConfig.cpp
Normal file
@ -0,0 +1,623 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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 "ProxyAutoConfig.h"
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "nsICancelable.h"
|
||||||
|
#include "nsIDNSListener.h"
|
||||||
|
#include "nsIDNSRecord.h"
|
||||||
|
#include "nsIDNSService.h"
|
||||||
|
#include "nsNetUtil.h"
|
||||||
|
#include "nsThreadUtils.h"
|
||||||
|
#include "nsIConsoleService.h"
|
||||||
|
#include "nsJSUtils.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace net {
|
||||||
|
|
||||||
|
// These are some global helper symbols the PAC format requires that we provide that
|
||||||
|
// are initialized as part of the global javascript context used for PAC evaluations.
|
||||||
|
// Additionally dnsResolve(host) and myIpAddress() are supplied in the same context
|
||||||
|
// but are implemented as c++ helpers. proxyAlert(msg) is similarly defined, but that
|
||||||
|
// is a gecko specific extension.
|
||||||
|
|
||||||
|
static const char *sPacUtils =
|
||||||
|
"function dnsDomainIs(host, domain) {\n"
|
||||||
|
" return (host.length >= domain.length &&\n"
|
||||||
|
" host.substring(host.length - domain.length) == domain);\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"function dnsDomainLevels(host) {\n"
|
||||||
|
" return host.split('.').length - 1;\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"function convert_addr(ipchars) {\n"
|
||||||
|
" var bytes = ipchars.split('.');\n"
|
||||||
|
" var result = ((bytes[0] & 0xff) << 24) |\n"
|
||||||
|
" ((bytes[1] & 0xff) << 16) |\n"
|
||||||
|
" ((bytes[2] & 0xff) << 8) |\n"
|
||||||
|
" (bytes[3] & 0xff);\n"
|
||||||
|
" return result;\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"function isInNet(ipaddr, pattern, maskstr) {\n"
|
||||||
|
" var test = /^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$/.exec(ipaddr);\n"
|
||||||
|
" if (test == null) {\n"
|
||||||
|
" ipaddr = dnsResolve(ipaddr);\n"
|
||||||
|
" if (ipaddr == null)\n"
|
||||||
|
" return false;\n"
|
||||||
|
" } else if (test[1] > 255 || test[2] > 255 || \n"
|
||||||
|
" test[3] > 255 || test[4] > 255) {\n"
|
||||||
|
" return false; // not an IP address\n"
|
||||||
|
" }\n"
|
||||||
|
" var host = convert_addr(ipaddr);\n"
|
||||||
|
" var pat = convert_addr(pattern);\n"
|
||||||
|
" var mask = convert_addr(maskstr);\n"
|
||||||
|
" return ((host & mask) == (pat & mask));\n"
|
||||||
|
" \n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"function isPlainHostName(host) {\n"
|
||||||
|
" return (host.search('\\\\.') == -1);\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"function isResolvable(host) {\n"
|
||||||
|
" var ip = dnsResolve(host);\n"
|
||||||
|
" return (ip != null);\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"function localHostOrDomainIs(host, hostdom) {\n"
|
||||||
|
" return (host == hostdom) ||\n"
|
||||||
|
" (hostdom.lastIndexOf(host + '.', 0) == 0);\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"function shExpMatch(url, pattern) {\n"
|
||||||
|
" pattern = pattern.replace(/\\./g, '\\\\.');\n"
|
||||||
|
" pattern = pattern.replace(/\\*/g, '.*');\n"
|
||||||
|
" pattern = pattern.replace(/\\?/g, '.');\n"
|
||||||
|
" var newRe = new RegExp('^'+pattern+'$');\n"
|
||||||
|
" return newRe.test(url);\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"var wdays = {SUN: 0, MON: 1, TUE: 2, WED: 3, THU: 4, FRI: 5, SAT: 6};\n"
|
||||||
|
"var months = {JAN: 0, FEB: 1, MAR: 2, APR: 3, MAY: 4, JUN: 5, JUL: 6, AUG: 7, SEP: 8, OCT: 9, NOV: 10, DEC: 11};\n"
|
||||||
|
""
|
||||||
|
"function weekdayRange() {\n"
|
||||||
|
" function getDay(weekday) {\n"
|
||||||
|
" if (weekday in wdays) {\n"
|
||||||
|
" return wdays[weekday];\n"
|
||||||
|
" }\n"
|
||||||
|
" return -1;\n"
|
||||||
|
" }\n"
|
||||||
|
" var date = new Date();\n"
|
||||||
|
" var argc = arguments.length;\n"
|
||||||
|
" var wday;\n"
|
||||||
|
" if (argc < 1)\n"
|
||||||
|
" return false;\n"
|
||||||
|
" if (arguments[argc - 1] == 'GMT') {\n"
|
||||||
|
" argc--;\n"
|
||||||
|
" wday = date.getUTCDay();\n"
|
||||||
|
" } else {\n"
|
||||||
|
" wday = date.getDay();\n"
|
||||||
|
" }\n"
|
||||||
|
" var wd1 = getDay(arguments[0]);\n"
|
||||||
|
" var wd2 = (argc == 2) ? getDay(arguments[1]) : wd1;\n"
|
||||||
|
" return (wd1 == -1 || wd2 == -1) ? false\n"
|
||||||
|
" : (wd1 <= wday && wday <= wd2);\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"function dateRange() {\n"
|
||||||
|
" function getMonth(name) {\n"
|
||||||
|
" if (name in months) {\n"
|
||||||
|
" return months[name];\n"
|
||||||
|
" }\n"
|
||||||
|
" return -1;\n"
|
||||||
|
" }\n"
|
||||||
|
" var date = new Date();\n"
|
||||||
|
" var argc = arguments.length;\n"
|
||||||
|
" if (argc < 1) {\n"
|
||||||
|
" return false;\n"
|
||||||
|
" }\n"
|
||||||
|
" var isGMT = (arguments[argc - 1] == 'GMT');\n"
|
||||||
|
"\n"
|
||||||
|
" if (isGMT) {\n"
|
||||||
|
" argc--;\n"
|
||||||
|
" }\n"
|
||||||
|
" // function will work even without explict handling of this case\n"
|
||||||
|
" if (argc == 1) {\n"
|
||||||
|
" var tmp = parseInt(arguments[0]);\n"
|
||||||
|
" if (isNaN(tmp)) {\n"
|
||||||
|
" return ((isGMT ? date.getUTCMonth() : date.getMonth()) ==\n"
|
||||||
|
" getMonth(arguments[0]));\n"
|
||||||
|
" } else if (tmp < 32) {\n"
|
||||||
|
" return ((isGMT ? date.getUTCDate() : date.getDate()) == tmp);\n"
|
||||||
|
" } else { \n"
|
||||||
|
" return ((isGMT ? date.getUTCFullYear() : date.getFullYear()) ==\n"
|
||||||
|
" tmp);\n"
|
||||||
|
" }\n"
|
||||||
|
" }\n"
|
||||||
|
" var year = date.getFullYear();\n"
|
||||||
|
" var date1, date2;\n"
|
||||||
|
" date1 = new Date(year, 0, 1, 0, 0, 0);\n"
|
||||||
|
" date2 = new Date(year, 11, 31, 23, 59, 59);\n"
|
||||||
|
" var adjustMonth = false;\n"
|
||||||
|
" for (var i = 0; i < (argc >> 1); i++) {\n"
|
||||||
|
" var tmp = parseInt(arguments[i]);\n"
|
||||||
|
" if (isNaN(tmp)) {\n"
|
||||||
|
" var mon = getMonth(arguments[i]);\n"
|
||||||
|
" date1.setMonth(mon);\n"
|
||||||
|
" } else if (tmp < 32) {\n"
|
||||||
|
" adjustMonth = (argc <= 2);\n"
|
||||||
|
" date1.setDate(tmp);\n"
|
||||||
|
" } else {\n"
|
||||||
|
" date1.setFullYear(tmp);\n"
|
||||||
|
" }\n"
|
||||||
|
" }\n"
|
||||||
|
" for (var i = (argc >> 1); i < argc; i++) {\n"
|
||||||
|
" var tmp = parseInt(arguments[i]);\n"
|
||||||
|
" if (isNaN(tmp)) {\n"
|
||||||
|
" var mon = getMonth(arguments[i]);\n"
|
||||||
|
" date2.setMonth(mon);\n"
|
||||||
|
" } else if (tmp < 32) {\n"
|
||||||
|
" date2.setDate(tmp);\n"
|
||||||
|
" } else {\n"
|
||||||
|
" date2.setFullYear(tmp);\n"
|
||||||
|
" }\n"
|
||||||
|
" }\n"
|
||||||
|
" if (adjustMonth) {\n"
|
||||||
|
" date1.setMonth(date.getMonth());\n"
|
||||||
|
" date2.setMonth(date.getMonth());\n"
|
||||||
|
" }\n"
|
||||||
|
" if (isGMT) {\n"
|
||||||
|
" var tmp = date;\n"
|
||||||
|
" tmp.setFullYear(date.getUTCFullYear());\n"
|
||||||
|
" tmp.setMonth(date.getUTCMonth());\n"
|
||||||
|
" tmp.setDate(date.getUTCDate());\n"
|
||||||
|
" tmp.setHours(date.getUTCHours());\n"
|
||||||
|
" tmp.setMinutes(date.getUTCMinutes());\n"
|
||||||
|
" tmp.setSeconds(date.getUTCSeconds());\n"
|
||||||
|
" date = tmp;\n"
|
||||||
|
" }\n"
|
||||||
|
" return ((date1 <= date) && (date <= date2));\n"
|
||||||
|
"}\n"
|
||||||
|
""
|
||||||
|
"function timeRange() {\n"
|
||||||
|
" var argc = arguments.length;\n"
|
||||||
|
" var date = new Date();\n"
|
||||||
|
" var isGMT= false;\n"
|
||||||
|
""
|
||||||
|
" if (argc < 1) {\n"
|
||||||
|
" return false;\n"
|
||||||
|
" }\n"
|
||||||
|
" if (arguments[argc - 1] == 'GMT') {\n"
|
||||||
|
" isGMT = true;\n"
|
||||||
|
" argc--;\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" var hour = isGMT ? date.getUTCHours() : date.getHours();\n"
|
||||||
|
" var date1, date2;\n"
|
||||||
|
" date1 = new Date();\n"
|
||||||
|
" date2 = new Date();\n"
|
||||||
|
"\n"
|
||||||
|
" if (argc == 1) {\n"
|
||||||
|
" return (hour == arguments[0]);\n"
|
||||||
|
" } else if (argc == 2) {\n"
|
||||||
|
" return ((arguments[0] <= hour) && (hour <= arguments[1]));\n"
|
||||||
|
" } else {\n"
|
||||||
|
" switch (argc) {\n"
|
||||||
|
" case 6:\n"
|
||||||
|
" date1.setSeconds(arguments[2]);\n"
|
||||||
|
" date2.setSeconds(arguments[5]);\n"
|
||||||
|
" case 4:\n"
|
||||||
|
" var middle = argc >> 1;\n"
|
||||||
|
" date1.setHours(arguments[0]);\n"
|
||||||
|
" date1.setMinutes(arguments[1]);\n"
|
||||||
|
" date2.setHours(arguments[middle]);\n"
|
||||||
|
" date2.setMinutes(arguments[middle + 1]);\n"
|
||||||
|
" if (middle == 2) {\n"
|
||||||
|
" date2.setSeconds(59);\n"
|
||||||
|
" }\n"
|
||||||
|
" break;\n"
|
||||||
|
" default:\n"
|
||||||
|
" throw 'timeRange: bad number of arguments'\n"
|
||||||
|
" }\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" if (isGMT) {\n"
|
||||||
|
" date.setFullYear(date.getUTCFullYear());\n"
|
||||||
|
" date.setMonth(date.getUTCMonth());\n"
|
||||||
|
" date.setDate(date.getUTCDate());\n"
|
||||||
|
" date.setHours(date.getUTCHours());\n"
|
||||||
|
" date.setMinutes(date.getUTCMinutes());\n"
|
||||||
|
" date.setSeconds(date.getUTCSeconds());\n"
|
||||||
|
" }\n"
|
||||||
|
" return ((date1 <= date) && (date <= date2));\n"
|
||||||
|
"}\n"
|
||||||
|
"";
|
||||||
|
|
||||||
|
// The PACResolver is used for dnsResolve()
|
||||||
|
class PACResolver MOZ_FINAL : public nsIDNSListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
|
PACResolver()
|
||||||
|
: mStatus(NS_ERROR_FAILURE)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP OnLookupComplete(nsICancelable *request,
|
||||||
|
nsIDNSRecord *record,
|
||||||
|
nsresult status)
|
||||||
|
{
|
||||||
|
mRequest = nullptr;
|
||||||
|
mStatus = status;
|
||||||
|
mResponse = record;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult mStatus;
|
||||||
|
nsCOMPtr<nsICancelable> mRequest;
|
||||||
|
nsCOMPtr<nsIDNSRecord> mResponse;
|
||||||
|
};
|
||||||
|
NS_IMPL_THREADSAFE_ISUPPORTS1(PACResolver, nsIDNSListener)
|
||||||
|
|
||||||
|
static
|
||||||
|
void PACLogToConsole(nsString &aMessage)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIConsoleService> consoleService =
|
||||||
|
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
||||||
|
if (!consoleService)
|
||||||
|
return;
|
||||||
|
|
||||||
|
consoleService->LogStringMessage(aMessage.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Javascript errors are logged to the main error console
|
||||||
|
static void
|
||||||
|
PACErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
|
||||||
|
{
|
||||||
|
nsString formattedMessage(NS_LITERAL_STRING("PAC Execution Error: "));
|
||||||
|
formattedMessage += report->ucmessage;
|
||||||
|
formattedMessage += NS_LITERAL_STRING(" [");
|
||||||
|
formattedMessage += report->uclinebuf;
|
||||||
|
formattedMessage += NS_LITERAL_STRING("]");
|
||||||
|
PACLogToConsole(formattedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
JSBool PACResolve(const nsCString &aHostName, nsCString &aDottedDecimal)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID);
|
||||||
|
nsCOMPtr<PACResolver> helper = new PACResolver();
|
||||||
|
if (!dns || NS_FAILED(dns->AsyncResolve(aHostName, 0, helper,
|
||||||
|
NS_GetCurrentThread(),
|
||||||
|
getter_AddRefs(helper->mRequest))))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Spin the event loop of the pac thread until lookup is complete.
|
||||||
|
// nsPACman is responsible for keeping a queue and only allowing
|
||||||
|
// one PAC execution at a time even when it is called re-entrantly.
|
||||||
|
while (helper->mRequest)
|
||||||
|
NS_ProcessNextEvent(NS_GetCurrentThread());
|
||||||
|
|
||||||
|
if (NS_FAILED(helper->mStatus) ||
|
||||||
|
NS_FAILED(helper->mResponse->GetNextAddrAsString(aDottedDecimal)))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// dnsResolve(host) javascript implementation
|
||||||
|
static
|
||||||
|
JSBool PACDnsResolve(JSContext *cx, unsigned int argc, jsval *vp)
|
||||||
|
{
|
||||||
|
if (NS_IsMainThread()) {
|
||||||
|
NS_WARNING("DNS Resolution From PAC on Main Thread. How did that happen?");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSString *arg1 = nullptr;
|
||||||
|
if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "S", &arg1))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
nsDependentJSString hostName;
|
||||||
|
nsCString dottedDecimal;
|
||||||
|
|
||||||
|
if (!hostName.init(cx, arg1))
|
||||||
|
return false;
|
||||||
|
if (!PACResolve(NS_ConvertUTF16toUTF8(hostName), dottedDecimal))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
JSString *dottedDecimalString = JS_NewStringCopyZ(cx, dottedDecimal.get());
|
||||||
|
JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(dottedDecimalString));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// myIpAddress() javascript implementation
|
||||||
|
static
|
||||||
|
JSBool PACMyIpAddress(JSContext *cx, unsigned int argc, jsval *vp)
|
||||||
|
{
|
||||||
|
if (NS_IsMainThread()) {
|
||||||
|
NS_WARNING("DNS Resolution From PAC on Main Thread. How did that happen?");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCString hostName;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID);
|
||||||
|
if (!dns || NS_FAILED(dns->GetMyHostName(hostName))) {
|
||||||
|
hostName.AssignLiteral("127.0.0.1");
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCString dottedDecimal;
|
||||||
|
if (!PACResolve(hostName, dottedDecimal)) {
|
||||||
|
dottedDecimal.AssignLiteral("127.0.0.1");
|
||||||
|
}
|
||||||
|
|
||||||
|
JSString *dottedDecimalString = JS_NewStringCopyZ(cx, dottedDecimal.get());
|
||||||
|
JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(dottedDecimalString));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// proxyAlert(msg) javascript implementation
|
||||||
|
static
|
||||||
|
JSBool PACProxyAlert(JSContext *cx, unsigned int argc, jsval *vp)
|
||||||
|
{
|
||||||
|
JSString *arg1 = nullptr;
|
||||||
|
if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "S", &arg1))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
nsDependentJSString message;
|
||||||
|
if (!message.init(cx, arg1))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
nsString alertMessage;
|
||||||
|
alertMessage.SetCapacity(32 + message.Length());
|
||||||
|
alertMessage += NS_LITERAL_STRING("PAC-alert: ");
|
||||||
|
alertMessage += message;
|
||||||
|
PACLogToConsole(alertMessage);
|
||||||
|
|
||||||
|
JS_SET_RVAL(cx, vp, JSVAL_VOID); /* return undefined */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSFunctionSpec PACGlobalFunctions[] = {
|
||||||
|
JS_FS("dnsResolve", PACDnsResolve, 1, 0),
|
||||||
|
JS_FS("myIpAddress", PACMyIpAddress, 0, 0),
|
||||||
|
JS_FS("proxyAlert", PACProxyAlert, 1, 0),
|
||||||
|
JS_FS_END
|
||||||
|
};
|
||||||
|
|
||||||
|
// JSRuntimeWrapper is a c++ object that manages the runtime and context
|
||||||
|
// for the JS engine used on the PAC thread. It is initialized and destroyed
|
||||||
|
// on the PAC thread.
|
||||||
|
class JSRuntimeWrapper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static JSRuntimeWrapper *Create()
|
||||||
|
{
|
||||||
|
JSRuntimeWrapper *entry = new JSRuntimeWrapper();
|
||||||
|
|
||||||
|
if (NS_FAILED(entry->Init())) {
|
||||||
|
delete entry;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSContext *Context() const
|
||||||
|
{
|
||||||
|
return mContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject *Global() const
|
||||||
|
{
|
||||||
|
return mGlobal;
|
||||||
|
}
|
||||||
|
|
||||||
|
~JSRuntimeWrapper()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_DTOR(JSRuntimeWrapper);
|
||||||
|
if (mContext) {
|
||||||
|
JS_DestroyContext(mContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mRuntime) {
|
||||||
|
JS_DestroyRuntime(mRuntime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetOK()
|
||||||
|
{
|
||||||
|
mOK = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsOK()
|
||||||
|
{
|
||||||
|
return mOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const unsigned sRuntimeHeapSize = 2 << 20;
|
||||||
|
|
||||||
|
JSRuntime *mRuntime;
|
||||||
|
JSContext *mContext;
|
||||||
|
JSObject *mGlobal;
|
||||||
|
bool mOK;
|
||||||
|
|
||||||
|
static JSClass sGlobalClass;
|
||||||
|
|
||||||
|
JSRuntimeWrapper()
|
||||||
|
: mRuntime(nullptr), mContext(nullptr), mGlobal(nullptr), mOK(false)
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR(JSRuntimeWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult Init()
|
||||||
|
{
|
||||||
|
mRuntime = JS_NewRuntime(sRuntimeHeapSize);
|
||||||
|
NS_ENSURE_TRUE(mRuntime, NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
|
mContext = JS_NewContext(mRuntime, 0);
|
||||||
|
NS_ENSURE_TRUE(mContext, NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
|
JSAutoRequest ar(mContext);
|
||||||
|
|
||||||
|
mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, nullptr);
|
||||||
|
NS_ENSURE_TRUE(mGlobal, NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
|
JS_SetGlobalObject(mContext, mGlobal);
|
||||||
|
JS_InitStandardClasses(mContext, mGlobal);
|
||||||
|
|
||||||
|
JS_SetVersion(mContext, JSVERSION_LATEST);
|
||||||
|
JS_SetErrorReporter(mContext, PACErrorReporter);
|
||||||
|
|
||||||
|
if (!JS_DefineFunctions(mContext, mGlobal, PACGlobalFunctions))
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
JSClass JSRuntimeWrapper::sGlobalClass = {
|
||||||
|
"PACResolutionThreadGlobal",
|
||||||
|
JSCLASS_GLOBAL_FLAGS,
|
||||||
|
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
|
||||||
|
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
|
||||||
|
};
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
ProxyAutoConfig::Init(const nsCString &aPACURI,
|
||||||
|
const nsCString &aPACScript)
|
||||||
|
{
|
||||||
|
mPACURI = aPACURI;
|
||||||
|
mPACScript = sPacUtils;
|
||||||
|
mPACScript.Append(aPACScript);
|
||||||
|
|
||||||
|
if (!mRunning)
|
||||||
|
return SetupJS();
|
||||||
|
|
||||||
|
mJSNeedsSetup = true;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
ProxyAutoConfig::SetupJS()
|
||||||
|
{
|
||||||
|
mJSNeedsSetup = false;
|
||||||
|
NS_ABORT_IF_FALSE(!mRunning, "JIT is running");
|
||||||
|
|
||||||
|
delete mJSRuntime;
|
||||||
|
mJSRuntime = nullptr;
|
||||||
|
|
||||||
|
if (mPACScript.IsEmpty())
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
mJSRuntime = JSRuntimeWrapper::Create();
|
||||||
|
if (!mJSRuntime)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
JSAutoRequest ar(mJSRuntime->Context());
|
||||||
|
|
||||||
|
JSScript *script = JS_CompileScript(mJSRuntime->Context(),
|
||||||
|
mJSRuntime->Global(),
|
||||||
|
mPACScript.get(), mPACScript.Length(),
|
||||||
|
mPACURI.get(), 1);
|
||||||
|
if (!JS_ExecuteScript(mJSRuntime->Context(), mJSRuntime->Global(), script, nullptr)) {
|
||||||
|
nsString alertMessage(NS_LITERAL_STRING("PAC file failed to install from "));
|
||||||
|
alertMessage += NS_ConvertUTF8toUTF16(mPACURI);
|
||||||
|
PACLogToConsole(alertMessage);
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
mJSRuntime->SetOK();
|
||||||
|
nsString alertMessage(NS_LITERAL_STRING("PAC file installed from "));
|
||||||
|
alertMessage += NS_ConvertUTF8toUTF16(mPACURI);
|
||||||
|
PACLogToConsole(alertMessage);
|
||||||
|
|
||||||
|
// we don't need these now
|
||||||
|
mPACScript.Truncate();
|
||||||
|
mPACURI.Truncate();
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
ProxyAutoConfig::GetProxyForURI(const nsCString &aTestURI,
|
||||||
|
const nsCString &aTestHost,
|
||||||
|
nsACString &result)
|
||||||
|
{
|
||||||
|
if (mJSNeedsSetup)
|
||||||
|
SetupJS();
|
||||||
|
|
||||||
|
if (!mJSRuntime || !mJSRuntime->IsOK())
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
|
||||||
|
JSContext *cx = mJSRuntime->Context();
|
||||||
|
JSAutoRequest ar(cx);
|
||||||
|
|
||||||
|
// the mRunning flag keeps a new PAC file from being installed
|
||||||
|
// while the event loop is spinning on a DNS function. Don't early return.
|
||||||
|
mRunning = true;
|
||||||
|
|
||||||
|
nsresult rv = NS_ERROR_FAILURE;
|
||||||
|
JS::RootedString uriString(cx, JS_NewStringCopyZ(cx, aTestURI.get()));
|
||||||
|
JS::RootedString hostString(cx, JS_NewStringCopyZ(cx, aTestHost.get()));
|
||||||
|
|
||||||
|
if (uriString && hostString) {
|
||||||
|
JS::RootedValue uriValue(cx, STRING_TO_JSVAL(uriString));
|
||||||
|
JS::RootedValue hostValue(cx, STRING_TO_JSVAL(hostString));
|
||||||
|
|
||||||
|
jsval argv[2] = { uriValue, hostValue };
|
||||||
|
jsval rval;
|
||||||
|
JSBool ok = JS_CallFunctionName(cx, mJSRuntime->Global(),
|
||||||
|
"FindProxyForURL", 2, argv, &rval);
|
||||||
|
|
||||||
|
if (ok && rval.isString()) {
|
||||||
|
nsDependentJSString pacString;
|
||||||
|
if (pacString.init(cx, rval.toString())) {
|
||||||
|
CopyUTF16toUTF8(pacString, result);
|
||||||
|
rv = NS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mRunning = false;
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ProxyAutoConfig::GC()
|
||||||
|
{
|
||||||
|
if (!mJSRuntime || !mJSRuntime->IsOK())
|
||||||
|
return;
|
||||||
|
|
||||||
|
JS_MaybeGC(mJSRuntime->Context());
|
||||||
|
}
|
||||||
|
|
||||||
|
ProxyAutoConfig::~ProxyAutoConfig()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_DTOR(ProxyAutoConfig);
|
||||||
|
NS_ASSERTION(!mJSRuntime,
|
||||||
|
"~ProxyAutoConfig leaking JS runtime that "
|
||||||
|
"should have been deleted on pac thread");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ProxyAutoConfig::Shutdown()
|
||||||
|
{
|
||||||
|
NS_ABORT_IF_FALSE(!NS_IsMainThread(), "wrong thread for shutdown");
|
||||||
|
|
||||||
|
if (mRunning || mShutdown)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mShutdown = true;
|
||||||
|
delete mJSRuntime;
|
||||||
|
mJSRuntime = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
|
} // namespace mozilla::net
|
89
netwerk/base/src/ProxyAutoConfig.h
Normal file
89
netwerk/base/src/ProxyAutoConfig.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#ifndef ProxyAutoConfig_h__
|
||||||
|
#define ProxyAutoConfig_h__
|
||||||
|
|
||||||
|
#include "nsString.h"
|
||||||
|
|
||||||
|
namespace mozilla { namespace net {
|
||||||
|
|
||||||
|
class JSRuntimeWrapper;
|
||||||
|
|
||||||
|
// The ProxyAutoConfig class is meant to be created and run on a
|
||||||
|
// non main thread. It synchronously resolves PAC files by blocking that
|
||||||
|
// thread and running nested event loops. GetProxyForURI is not re-entrant.
|
||||||
|
|
||||||
|
class ProxyAutoConfig {
|
||||||
|
public:
|
||||||
|
ProxyAutoConfig()
|
||||||
|
: mJSRuntime(nullptr)
|
||||||
|
, mRunning(false)
|
||||||
|
, mJSNeedsSetup(false)
|
||||||
|
, mShutdown(false)
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR(ProxyAutoConfig);
|
||||||
|
}
|
||||||
|
~ProxyAutoConfig();
|
||||||
|
|
||||||
|
nsresult Init(const nsCString &aPACURI,
|
||||||
|
const nsCString &aPACScript);
|
||||||
|
void Shutdown();
|
||||||
|
void GC();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the proxy string for the specified URI. The proxy string is
|
||||||
|
* given by the following:
|
||||||
|
*
|
||||||
|
* result = proxy-spec *( proxy-sep proxy-spec )
|
||||||
|
* proxy-spec = direct-type | proxy-type LWS proxy-host [":" proxy-port]
|
||||||
|
* direct-type = "DIRECT"
|
||||||
|
* proxy-type = "PROXY" | "SOCKS" | "SOCKS4" | "SOCKS5"
|
||||||
|
* proxy-sep = ";" LWS
|
||||||
|
* proxy-host = hostname | ipv4-address-literal
|
||||||
|
* proxy-port = <any 16-bit unsigned integer>
|
||||||
|
* LWS = *( SP | HT )
|
||||||
|
* SP = <US-ASCII SP, space (32)>
|
||||||
|
* HT = <US-ASCII HT, horizontal-tab (9)>
|
||||||
|
*
|
||||||
|
* NOTE: direct-type and proxy-type are case insensitive
|
||||||
|
* NOTE: SOCKS implies SOCKS4
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
* "PROXY proxy1.foo.com:8080; PROXY proxy2.foo.com:8080; DIRECT"
|
||||||
|
* "SOCKS socksproxy"
|
||||||
|
* "DIRECT"
|
||||||
|
*
|
||||||
|
* XXX add support for IPv6 address literals.
|
||||||
|
* XXX quote whatever the official standard is for PAC.
|
||||||
|
*
|
||||||
|
* @param aTestURI
|
||||||
|
* The URI as an ASCII string to test.
|
||||||
|
* @param aTestHost
|
||||||
|
* The ASCII hostname to test.
|
||||||
|
*
|
||||||
|
* @param result
|
||||||
|
* result string as defined above.
|
||||||
|
*/
|
||||||
|
nsresult GetProxyForURI(const nsCString &aTestURI,
|
||||||
|
const nsCString &aTestHost,
|
||||||
|
nsACString &result);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// used to compile the PAC file and setup the execution context
|
||||||
|
nsresult SetupJS();
|
||||||
|
|
||||||
|
JSRuntimeWrapper *mJSRuntime;
|
||||||
|
bool mRunning;
|
||||||
|
bool mJSNeedsSetup;
|
||||||
|
bool mShutdown;
|
||||||
|
nsCString mPACScript;
|
||||||
|
nsCString mPACURI;
|
||||||
|
};
|
||||||
|
|
||||||
|
}} // namespace mozilla::net
|
||||||
|
|
||||||
|
#endif // ProxyAutoConfig_h__
|
@ -701,7 +701,9 @@ nsBaseChannel::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
|
|||||||
|
|
||||||
SUSPEND_PUMP_FOR_SCOPE();
|
SUSPEND_PUMP_FOR_SCOPE();
|
||||||
|
|
||||||
return mListener->OnStartRequest(this, mListenerContext);
|
if (mListener) // null in case of redirect
|
||||||
|
return mListener->OnStartRequest(this, mListenerContext);
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
@ -716,7 +718,8 @@ nsBaseChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
|
|||||||
// Cause IsPending to return false.
|
// Cause IsPending to return false.
|
||||||
mPump = nullptr;
|
mPump = nullptr;
|
||||||
|
|
||||||
mListener->OnStopRequest(this, mListenerContext, mStatus);
|
if (mListener) // null in case of redirect
|
||||||
|
mListener->OnStopRequest(this, mListenerContext, mStatus);
|
||||||
mListener = nullptr;
|
mListener = nullptr;
|
||||||
mListenerContext = nullptr;
|
mListenerContext = nullptr;
|
||||||
|
|
||||||
|
@ -39,6 +39,9 @@
|
|||||||
#include "nsIConsoleService.h"
|
#include "nsIConsoleService.h"
|
||||||
#include "nsIUploadChannel2.h"
|
#include "nsIUploadChannel2.h"
|
||||||
#include "nsXULAppAPI.h"
|
#include "nsXULAppAPI.h"
|
||||||
|
#include "nsIProxiedChannel.h"
|
||||||
|
#include "nsIProtocolProxyCallback.h"
|
||||||
|
#include "nsICancelable.h"
|
||||||
|
|
||||||
#include "mozilla/FunctionTimer.h"
|
#include "mozilla/FunctionTimer.h"
|
||||||
|
|
||||||
@ -576,31 +579,6 @@ nsIOService::NewChannelFromURI(nsIURI *aURI, nsIChannel **result)
|
|||||||
return NewChannelFromURIWithProxyFlags(aURI, nullptr, 0, result);
|
return NewChannelFromURIWithProxyFlags(aURI, nullptr, 0, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
nsIOService::LookupProxyInfo(nsIURI *aURI,
|
|
||||||
nsIURI *aProxyURI,
|
|
||||||
uint32_t aProxyFlags,
|
|
||||||
nsCString *aScheme,
|
|
||||||
nsIProxyInfo **outPI)
|
|
||||||
{
|
|
||||||
nsresult rv;
|
|
||||||
nsCOMPtr<nsIProxyInfo> pi;
|
|
||||||
|
|
||||||
if (!mProxyService) {
|
|
||||||
mProxyService = do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID);
|
|
||||||
if (!mProxyService)
|
|
||||||
NS_WARNING("failed to get protocol proxy service");
|
|
||||||
}
|
|
||||||
if (mProxyService) {
|
|
||||||
rv = mProxyService->Resolve(aProxyURI ? aProxyURI : aURI, aProxyFlags,
|
|
||||||
getter_AddRefs(pi));
|
|
||||||
if (NS_FAILED(rv))
|
|
||||||
pi = nullptr;
|
|
||||||
}
|
|
||||||
pi.forget(outPI);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsIOService::NewChannelFromURIWithProxyFlags(nsIURI *aURI,
|
nsIOService::NewChannelFromURIWithProxyFlags(nsIURI *aURI,
|
||||||
nsIURI *aProxyURI,
|
nsIURI *aProxyURI,
|
||||||
@ -625,26 +603,11 @@ nsIOService::NewChannelFromURIWithProxyFlags(nsIURI *aURI,
|
|||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
// Talk to the PPS if the protocol handler allows proxying. Otherwise,
|
nsCOMPtr<nsIProxiedProtocolHandler> pph = do_QueryInterface(handler);
|
||||||
// skip this step. This allows us to lazily load the PPS at startup.
|
if (pph)
|
||||||
if (protoFlags & nsIProtocolHandler::ALLOWS_PROXY) {
|
rv = pph->NewProxiedChannel(aURI, nullptr, aProxyFlags, aProxyURI, result);
|
||||||
nsCOMPtr<nsIProxyInfo> pi;
|
else
|
||||||
LookupProxyInfo(aURI, aProxyURI, aProxyFlags, &scheme, getter_AddRefs(pi));
|
rv = handler->NewChannel(aURI, result);
|
||||||
if (pi) {
|
|
||||||
nsAutoCString type;
|
|
||||||
if (NS_SUCCEEDED(pi->GetType(type)) && type.EqualsLiteral("http")) {
|
|
||||||
// we are going to proxy this channel using an http proxy
|
|
||||||
rv = GetProtocolHandler("http", getter_AddRefs(handler));
|
|
||||||
if (NS_FAILED(rv))
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
nsCOMPtr<nsIProxiedProtocolHandler> pph = do_QueryInterface(handler);
|
|
||||||
if (pph)
|
|
||||||
return pph->NewProxiedChannel(aURI, pi, result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = handler->NewChannel(aURI, result);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
// Some extensions override the http protocol handler and provide their own
|
// Some extensions override the http protocol handler and provide their own
|
||||||
@ -1212,35 +1175,79 @@ nsIOService::ExtractCharsetFromContentType(const nsACString &aTypeHeader,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// nsISpeculativeConnect
|
// nsISpeculativeConnect
|
||||||
NS_IMETHODIMP
|
class IOServiceProxyCallback MOZ_FINAL : public nsIProtocolProxyCallback
|
||||||
nsIOService::SpeculativeConnect(nsIURI *aURI,
|
|
||||||
nsIInterfaceRequestor *aCallbacks,
|
|
||||||
nsIEventTarget *aTarget)
|
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSIPROTOCOLPROXYCALLBACK
|
||||||
|
|
||||||
|
IOServiceProxyCallback(nsIInterfaceRequestor *aCallbacks,
|
||||||
|
nsIEventTarget *aTarget,
|
||||||
|
nsIOService *aIOService)
|
||||||
|
: mCallbacks(aCallbacks)
|
||||||
|
, mTarget(aTarget)
|
||||||
|
, mIOService(aIOService)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsRefPtr<nsIInterfaceRequestor> mCallbacks;
|
||||||
|
nsRefPtr<nsIEventTarget> mTarget;
|
||||||
|
nsRefPtr<nsIOService> mIOService;
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS1(IOServiceProxyCallback, nsIProtocolProxyCallback)
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
IOServiceProxyCallback::OnProxyAvailable(nsICancelable *request, nsIURI *aURI,
|
||||||
|
nsIProxyInfo *pi, nsresult status)
|
||||||
|
{
|
||||||
|
// Checking proxy status for speculative connect
|
||||||
|
nsAutoCString type;
|
||||||
|
if (NS_SUCCEEDED(status) && pi &&
|
||||||
|
NS_SUCCEEDED(pi->GetType(type)) &&
|
||||||
|
!type.EqualsLiteral("direct")) {
|
||||||
|
// proxies dont do speculative connect
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
nsAutoCString scheme;
|
nsAutoCString scheme;
|
||||||
nsresult rv = aURI->GetScheme(scheme);
|
nsresult rv = aURI->GetScheme(scheme);
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
|
||||||
|
|
||||||
// Check for proxy information. If there is a proxy configured then a
|
|
||||||
// speculative connect should not be performed because the potential
|
|
||||||
// reward is slim with tcp peers closely located to the browser.
|
|
||||||
nsCOMPtr<nsIProxyInfo> pi;
|
|
||||||
LookupProxyInfo(aURI, nullptr, 0, &scheme, getter_AddRefs(pi));
|
|
||||||
if (pi)
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
nsCOMPtr<nsIProtocolHandler> handler;
|
nsCOMPtr<nsIProtocolHandler> handler;
|
||||||
rv = GetProtocolHandler(scheme.get(), getter_AddRefs(handler));
|
rv = mIOService->GetProtocolHandler(scheme.get(),
|
||||||
|
getter_AddRefs(handler));
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return NS_OK;
|
||||||
|
|
||||||
nsCOMPtr<nsISpeculativeConnect> speculativeHandler =
|
nsCOMPtr<nsISpeculativeConnect> speculativeHandler =
|
||||||
do_QueryInterface(handler);
|
do_QueryInterface(handler);
|
||||||
if (!speculativeHandler)
|
if (!speculativeHandler)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
return speculativeHandler->SpeculativeConnect(aURI,
|
speculativeHandler->SpeculativeConnect(aURI,
|
||||||
aCallbacks,
|
mCallbacks,
|
||||||
aTarget);
|
mTarget);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsIOService::SpeculativeConnect(nsIURI *aURI,
|
||||||
|
nsIInterfaceRequestor *aCallbacks,
|
||||||
|
nsIEventTarget *aTarget)
|
||||||
|
{
|
||||||
|
// Check for proxy information. If there is a proxy configured then a
|
||||||
|
// speculative connect should not be performed because the potential
|
||||||
|
// reward is slim with tcp peers closely located to the browser.
|
||||||
|
nsresult rv;
|
||||||
|
nsCOMPtr<nsIProtocolProxyService> pps =
|
||||||
|
do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &rv);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
nsCOMPtr<nsICancelable> cancelable;
|
||||||
|
nsRefPtr<IOServiceProxyCallback> callback =
|
||||||
|
new IOServiceProxyCallback(aCallbacks, aTarget, this);
|
||||||
|
return pps->AsyncResolve(aURI, 0, callback, getter_AddRefs(cancelable));
|
||||||
}
|
}
|
||||||
|
@ -6,21 +6,24 @@
|
|||||||
|
|
||||||
#include "nsPACMan.h"
|
#include "nsPACMan.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
#include "nsIDNSService.h"
|
|
||||||
#include "nsIDNSListener.h"
|
|
||||||
#include "nsICancelable.h"
|
|
||||||
#include "nsIAuthPrompt.h"
|
#include "nsIAuthPrompt.h"
|
||||||
#include "nsIPromptFactory.h"
|
#include "nsIPromptFactory.h"
|
||||||
#include "nsIHttpChannel.h"
|
#include "nsIHttpChannel.h"
|
||||||
#include "nsIPrefService.h"
|
#include "nsIPrefService.h"
|
||||||
#include "nsIPrefBranch.h"
|
#include "nsIPrefBranch.h"
|
||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
#include "nsAutoPtr.h"
|
|
||||||
#include "nsCRT.h"
|
#include "nsCRT.h"
|
||||||
#include "prmon.h"
|
#include "prmon.h"
|
||||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||||
|
#include "nsProxyRelease.h"
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
using namespace mozilla;
|
||||||
|
using namespace mozilla::net;
|
||||||
|
|
||||||
|
// The PAC thread does evaluations of both PAC files and
|
||||||
|
// nsISystemProxySettings because they can both block the calling thread and we
|
||||||
|
// don't want that on the main thread
|
||||||
|
|
||||||
// Check to see if the underlying request was not an error page in the case of
|
// Check to see if the underlying request was not an error page in the case of
|
||||||
// a HTTP request. For other types of channels, just return true.
|
// a HTTP request. For other types of channels, just return true.
|
||||||
@ -41,100 +44,206 @@ HttpRequestSucceeded(nsIStreamLoader *loader)
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// These objects are stored in nsPACMan::mPendingQ
|
// The ExecuteCallback runnable is triggered by
|
||||||
|
// nsPACManCallback::OnQueryComplete on the Main thread when its completion is
|
||||||
|
// discovered on the pac thread
|
||||||
|
|
||||||
class PendingPACQuery MOZ_FINAL : public PRCList,
|
class ExecuteCallback MOZ_FINAL : public nsRunnable
|
||||||
public nsIDNSListener
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NS_DECL_ISUPPORTS
|
ExecuteCallback(nsPACManCallback *aCallback,
|
||||||
NS_DECL_NSIDNSLISTENER
|
nsresult status)
|
||||||
|
: mCallback(aCallback)
|
||||||
PendingPACQuery(nsPACMan *pacMan, nsIURI *uri, nsPACManCallback *callback)
|
, mStatus(status)
|
||||||
: mPACMan(pacMan)
|
|
||||||
, mURI(uri)
|
|
||||||
, mCallback(callback)
|
|
||||||
{
|
{
|
||||||
PR_INIT_CLIST(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult Start(uint32_t flags);
|
void SetPACString(const nsCString &pacString)
|
||||||
void Complete(nsresult status, const nsCString &pacString);
|
{
|
||||||
|
mPACString = pacString;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPACURL(const nsCString &pacURL)
|
||||||
|
{
|
||||||
|
mPACURL = pacURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP Run()
|
||||||
|
{
|
||||||
|
mCallback->OnQueryComplete(mStatus, mPACString, mPACURL);
|
||||||
|
mCallback = nullptr;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsPACMan *mPACMan; // weak reference
|
|
||||||
nsCOMPtr<nsIURI> mURI;
|
|
||||||
nsRefPtr<nsPACManCallback> mCallback;
|
nsRefPtr<nsPACManCallback> mCallback;
|
||||||
nsCOMPtr<nsICancelable> mDNSRequest;
|
nsresult mStatus;
|
||||||
|
nsCString mPACString;
|
||||||
|
nsCString mPACURL;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is threadsafe because we implement nsIDNSListener
|
//-----------------------------------------------------------------------------
|
||||||
NS_IMPL_THREADSAFE_ISUPPORTS1(PendingPACQuery, nsIDNSListener)
|
|
||||||
|
|
||||||
nsresult
|
// The PAC thread must be deleted from the main thread, this class
|
||||||
PendingPACQuery::Start(uint32_t flags)
|
// acts as a proxy to do that, as the PACMan is reference counted
|
||||||
|
// and might be destroyed on either thread
|
||||||
|
|
||||||
|
class ShutdownThread MOZ_FINAL : public nsRunnable
|
||||||
{
|
{
|
||||||
if (mDNSRequest)
|
public:
|
||||||
return NS_OK; // already started
|
ShutdownThread(nsIThread *thread)
|
||||||
|
: mThread(thread)
|
||||||
nsresult rv;
|
{
|
||||||
nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID, &rv);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
NS_WARNING("unable to get the DNS service");
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsAutoCString host;
|
NS_IMETHODIMP Run()
|
||||||
rv = mURI->GetAsciiHost(host);
|
{
|
||||||
if (NS_FAILED(rv))
|
NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
|
||||||
return rv;
|
mThread->Shutdown();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
rv = dns->AsyncResolve(host, flags, this, NS_GetCurrentThread(),
|
private:
|
||||||
getter_AddRefs(mDNSRequest));
|
nsCOMPtr<nsIThread> mThread;
|
||||||
if (NS_FAILED(rv))
|
};
|
||||||
NS_WARNING("DNS AsyncResolve failed");
|
|
||||||
|
|
||||||
return rv;
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// PACLoadComplete allows the PAC thread to tell the main thread that
|
||||||
|
// the javascript PAC file has been installed (perhaps unsuccessfully)
|
||||||
|
// and that there is no reason to queue executions anymore
|
||||||
|
|
||||||
|
class PACLoadComplete MOZ_FINAL : public nsRunnable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PACLoadComplete(nsPACMan *aPACMan)
|
||||||
|
: mPACMan(aPACMan)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP Run()
|
||||||
|
{
|
||||||
|
NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
|
||||||
|
mPACMan->mLoader = nullptr;
|
||||||
|
mPACMan->PostProcessPendingQ();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsRefPtr<nsPACMan> mPACMan;
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// ExecutePACThreadAction is used to proxy actions from the main
|
||||||
|
// thread onto the PAC thread. There are 3 options: process the queue,
|
||||||
|
// cancel the queue, and setup the javascript context with a new PAC file
|
||||||
|
|
||||||
|
class ExecutePACThreadAction MOZ_FINAL : public nsRunnable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// by default we just process the queue
|
||||||
|
ExecutePACThreadAction(nsPACMan *aPACMan)
|
||||||
|
: mPACMan(aPACMan)
|
||||||
|
, mCancel(false)
|
||||||
|
, mSetupPAC(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void CancelQueue (nsresult status)
|
||||||
|
{
|
||||||
|
mCancel = true;
|
||||||
|
mCancelStatus = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetupPAC (const char *text, uint32_t datalen, nsCString &pacURI)
|
||||||
|
{
|
||||||
|
mSetupPAC = true;
|
||||||
|
mSetupPACData.Assign(text, datalen);
|
||||||
|
mSetupPACURI = pacURI;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP Run()
|
||||||
|
{
|
||||||
|
NS_ABORT_IF_FALSE(!NS_IsMainThread(), "wrong thread");
|
||||||
|
if (mCancel) {
|
||||||
|
mPACMan->CancelPendingQ(mCancelStatus);
|
||||||
|
mCancel = false;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mSetupPAC) {
|
||||||
|
mSetupPAC = false;
|
||||||
|
|
||||||
|
mPACMan->mPAC.Init(mSetupPACURI,
|
||||||
|
mSetupPACData);
|
||||||
|
|
||||||
|
nsRefPtr<PACLoadComplete> runnable = new PACLoadComplete(mPACMan);
|
||||||
|
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
mPACMan->ProcessPendingQ();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsRefPtr<nsPACMan> mPACMan;
|
||||||
|
|
||||||
|
bool mCancel;
|
||||||
|
nsresult mCancelStatus;
|
||||||
|
|
||||||
|
bool mSetupPAC;
|
||||||
|
nsCString mSetupPACData;
|
||||||
|
nsCString mSetupPACURI;
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
PendingPACQuery::PendingPACQuery(nsPACMan *pacMan, nsIURI *uri,
|
||||||
|
nsPACManCallback *callback,
|
||||||
|
bool mainThreadResponse)
|
||||||
|
: mPACMan(pacMan)
|
||||||
|
, mCallback(callback)
|
||||||
|
, mOnMainThreadOnly(mainThreadResponse)
|
||||||
|
{
|
||||||
|
uri->GetAsciiSpec(mSpec);
|
||||||
|
uri->GetAsciiHost(mHost);
|
||||||
|
uri->GetScheme(mScheme);
|
||||||
|
uri->GetPort(&mPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This may be called before or after OnLookupComplete
|
|
||||||
void
|
void
|
||||||
PendingPACQuery::Complete(nsresult status, const nsCString &pacString)
|
PendingPACQuery::Complete(nsresult status, const nsCString &pacString)
|
||||||
{
|
{
|
||||||
if (!mCallback)
|
if (!mCallback)
|
||||||
return;
|
return;
|
||||||
|
nsRefPtr<ExecuteCallback> runnable = new ExecuteCallback(mCallback, status);
|
||||||
|
runnable->SetPACString(pacString);
|
||||||
|
if (mOnMainThreadOnly)
|
||||||
|
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
|
||||||
|
else
|
||||||
|
runnable->Run();
|
||||||
|
}
|
||||||
|
|
||||||
mCallback->OnQueryComplete(status, pacString);
|
void
|
||||||
mCallback = nullptr;
|
PendingPACQuery::UseAlternatePACFile(const nsCString &pacURL)
|
||||||
|
{
|
||||||
|
if (!mCallback)
|
||||||
|
return;
|
||||||
|
|
||||||
if (mDNSRequest) {
|
nsRefPtr<ExecuteCallback> runnable = new ExecuteCallback(mCallback, NS_OK);
|
||||||
mDNSRequest->Cancel(NS_ERROR_ABORT);
|
runnable->SetPACURL(pacURL);
|
||||||
mDNSRequest = nullptr;
|
if (mOnMainThreadOnly)
|
||||||
}
|
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
|
||||||
|
else
|
||||||
|
runnable->Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
PendingPACQuery::OnLookupComplete(nsICancelable *request,
|
PendingPACQuery::Run()
|
||||||
nsIDNSRecord *record,
|
|
||||||
nsresult status)
|
|
||||||
{
|
{
|
||||||
// NOTE: we don't care about the results of this DNS query. We issued
|
NS_ABORT_IF_FALSE(!NS_IsMainThread(), "wrong thread");
|
||||||
// this DNS query just to pre-populate our DNS cache.
|
mPACMan->PostQuery(this);
|
||||||
|
|
||||||
mDNSRequest = nullptr; // break reference cycle
|
|
||||||
|
|
||||||
// If we've already completed this query then do nothing.
|
|
||||||
if (!mCallback)
|
|
||||||
return NS_OK;
|
|
||||||
|
|
||||||
// We're no longer pending, so we can remove ourselves.
|
|
||||||
PR_REMOVE_LINK(this);
|
|
||||||
|
|
||||||
nsAutoCString pacString;
|
|
||||||
status = mPACMan->GetProxyForURI(mURI, pacString);
|
|
||||||
Complete(status, pacString);
|
|
||||||
|
|
||||||
NS_RELEASE_THIS();
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,87 +252,87 @@ PendingPACQuery::OnLookupComplete(nsICancelable *request,
|
|||||||
nsPACMan::nsPACMan()
|
nsPACMan::nsPACMan()
|
||||||
: mLoadPending(false)
|
: mLoadPending(false)
|
||||||
, mShutdown(false)
|
, mShutdown(false)
|
||||||
, mScheduledReload(LL_MAXINT)
|
|
||||||
, mLoadFailureCount(0)
|
, mLoadFailureCount(0)
|
||||||
|
, mInProgress(false)
|
||||||
{
|
{
|
||||||
PR_INIT_CLIST(&mPendingQ);
|
NS_ABORT_IF_FALSE(NS_IsMainThread(), "pacman must be created on main thread");
|
||||||
}
|
}
|
||||||
|
|
||||||
nsPACMan::~nsPACMan()
|
nsPACMan::~nsPACMan()
|
||||||
{
|
{
|
||||||
|
if (mPACThread) {
|
||||||
|
if (NS_IsMainThread()) {
|
||||||
|
mPACThread->Shutdown();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nsRefPtr<ShutdownThread> runnable = new ShutdownThread(mPACThread);
|
||||||
|
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!NS_IsMainThread()) {
|
||||||
|
nsCOMPtr<nsIThread> mainThread;
|
||||||
|
NS_GetMainThread(getter_AddRefs(mainThread));
|
||||||
|
|
||||||
|
if (mPACURI) {
|
||||||
|
nsIURI *forgettable;
|
||||||
|
mPACURI.forget(&forgettable);
|
||||||
|
NS_ProxyRelease(mainThread, forgettable, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NS_ASSERTION(mLoader == nullptr, "pac man not shutdown properly");
|
NS_ASSERTION(mLoader == nullptr, "pac man not shutdown properly");
|
||||||
NS_ASSERTION(mPAC == nullptr, "pac man not shutdown properly");
|
NS_ASSERTION(mPendingQ.isEmpty(), "pac man not shutdown properly");
|
||||||
NS_ASSERTION(PR_CLIST_IS_EMPTY(&mPendingQ), "pac man not shutdown properly");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsPACMan::Shutdown()
|
nsPACMan::Shutdown()
|
||||||
{
|
{
|
||||||
|
NS_ABORT_IF_FALSE(NS_IsMainThread(), "pacman must be shutdown on main thread");
|
||||||
CancelExistingLoad();
|
CancelExistingLoad();
|
||||||
ProcessPendingQ(NS_ERROR_ABORT);
|
|
||||||
|
|
||||||
mPAC = nullptr;
|
|
||||||
mShutdown = true;
|
mShutdown = true;
|
||||||
|
PostCancelPendingQ(NS_ERROR_ABORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsPACMan::GetProxyForURI(nsIURI *uri, nsACString &result)
|
nsPACMan::AsyncGetProxyForURI(nsIURI *uri, nsPACManCallback *callback,
|
||||||
|
bool mainThreadResponse)
|
||||||
{
|
{
|
||||||
NS_ENSURE_STATE(!mShutdown);
|
NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
|
||||||
|
if (mShutdown)
|
||||||
if (IsPACURI(uri)) {
|
|
||||||
result.Truncate();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
MaybeReloadPAC();
|
|
||||||
|
|
||||||
if (IsLoading())
|
|
||||||
return NS_ERROR_IN_PROGRESS;
|
|
||||||
if (!mPAC)
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
|
||||||
nsAutoCString spec, host;
|
// Maybe Reload PAC
|
||||||
uri->GetAsciiSpec(spec);
|
if (mPACURI && !mScheduledReload.IsNull() &&
|
||||||
uri->GetAsciiHost(host);
|
TimeStamp::Now() > mScheduledReload)
|
||||||
|
LoadPACFromURI(nullptr);
|
||||||
|
|
||||||
return mPAC->GetProxyForURI(spec, host, result);
|
nsRefPtr<PendingPACQuery> query =
|
||||||
|
new PendingPACQuery(this, uri, callback, mainThreadResponse);
|
||||||
|
|
||||||
|
if (IsPACURI(uri)) {
|
||||||
|
// deal with this directly instead of queueing it
|
||||||
|
query->Complete(NS_OK, EmptyCString());
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mPACThread->Dispatch(query, nsIEventTarget::DISPATCH_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsPACMan::AsyncGetProxyForURI(nsIURI *uri, nsPACManCallback *callback)
|
nsPACMan::PostQuery(PendingPACQuery *query)
|
||||||
{
|
{
|
||||||
NS_ENSURE_STATE(!mShutdown);
|
NS_ABORT_IF_FALSE(!NS_IsMainThread(), "wrong thread");
|
||||||
|
|
||||||
MaybeReloadPAC();
|
if (mShutdown) {
|
||||||
|
query->Complete(NS_ERROR_NOT_AVAILABLE, EmptyCString());
|
||||||
PendingPACQuery *query = new PendingPACQuery(this, uri, callback);
|
|
||||||
if (!query)
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
NS_ADDREF(query);
|
|
||||||
PR_APPEND_LINK(query, &mPendingQ);
|
|
||||||
|
|
||||||
// If we're waiting for the PAC file to load, then delay starting the query.
|
|
||||||
// See OnStreamComplete. However, if this is the PAC URI then query right
|
|
||||||
// away since we know the result will be DIRECT. We could shortcut some code
|
|
||||||
// in this case by issuing the callback directly from here, but that would
|
|
||||||
// require extra code, so we just go through the usual async code path.
|
|
||||||
int isPACURI = IsPACURI(uri);
|
|
||||||
|
|
||||||
if (IsLoading() && !isPACURI)
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
nsresult rv = query->Start(isPACURI ? 0 : nsIDNSService::RESOLVE_SPECULATE);
|
|
||||||
if (rv == NS_ERROR_DNS_LOOKUP_QUEUE_FULL && !isPACURI) {
|
|
||||||
query->OnLookupComplete(NULL, NULL, NS_OK);
|
|
||||||
rv = NS_OK;
|
|
||||||
} else if (NS_FAILED(rv)) {
|
|
||||||
NS_WARNING("failed to start PAC query");
|
|
||||||
PR_REMOVE_LINK(query);
|
|
||||||
NS_RELEASE(query);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
// add a reference to the query while it is in the pending list
|
||||||
|
nsRefPtr<PendingPACQuery> addref(query);
|
||||||
|
mPendingQ.insertBack(addref.forget().get());
|
||||||
|
ProcessPendingQ();
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
@ -256,21 +365,24 @@ nsPACMan::LoadPACFromURI(nsIURI *pacURI)
|
|||||||
mLoader = loader;
|
mLoader = loader;
|
||||||
if (pacURI) {
|
if (pacURI) {
|
||||||
mPACURI = pacURI;
|
mPACURI = pacURI;
|
||||||
|
mPACURI->GetSpec(mPACURISpec);
|
||||||
mLoadFailureCount = 0; // reset
|
mLoadFailureCount = 0; // reset
|
||||||
}
|
}
|
||||||
mScheduledReload = LL_MAXINT;
|
|
||||||
mPAC = nullptr;
|
// reset to Null
|
||||||
|
mScheduledReload = TimeStamp();
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsPACMan::StartLoading()
|
nsPACMan::StartLoading()
|
||||||
{
|
{
|
||||||
|
NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
|
||||||
mLoadPending = false;
|
mLoadPending = false;
|
||||||
|
|
||||||
// CancelExistingLoad was called...
|
// CancelExistingLoad was called...
|
||||||
if (!mLoader) {
|
if (!mLoader) {
|
||||||
ProcessPendingQ(NS_ERROR_ABORT);
|
PostCancelPendingQ(NS_ERROR_ABORT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,18 +405,9 @@ nsPACMan::StartLoading()
|
|||||||
}
|
}
|
||||||
|
|
||||||
CancelExistingLoad();
|
CancelExistingLoad();
|
||||||
ProcessPendingQ(NS_ERROR_UNEXPECTED);
|
PostCancelPendingQ(NS_ERROR_UNEXPECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
nsPACMan::MaybeReloadPAC()
|
|
||||||
{
|
|
||||||
if (!mPACURI)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (PR_Now() > mScheduledReload)
|
|
||||||
LoadPACFromURI(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
nsPACMan::OnLoadFailure()
|
nsPACMan::OnLoadFailure()
|
||||||
@ -324,11 +427,11 @@ nsPACMan::OnLoadFailure()
|
|||||||
if (!interval || interval > maxInterval)
|
if (!interval || interval > maxInterval)
|
||||||
interval = maxInterval;
|
interval = maxInterval;
|
||||||
|
|
||||||
#ifdef DEBUG
|
mScheduledReload = TimeStamp::Now() + TimeDuration::FromSeconds(interval);
|
||||||
printf("PAC load failure: will retry in %d seconds\n", interval);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
mScheduledReload = PR_Now() + int64_t(interval) * PR_USEC_PER_SEC;
|
// while we wait for the retry queued members should try direct
|
||||||
|
// even if that means fast failure.
|
||||||
|
PostCancelPendingQ(NS_ERROR_NOT_AVAILABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -344,32 +447,110 @@ nsPACMan::CancelExistingLoad()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsPACMan::ProcessPendingQ(nsresult status)
|
nsPACMan::PostProcessPendingQ()
|
||||||
{
|
{
|
||||||
// Now, start any pending queries
|
NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
|
||||||
PRCList *node = PR_LIST_HEAD(&mPendingQ);
|
nsRefPtr<ExecutePACThreadAction> pending =
|
||||||
while (node != &mPendingQ) {
|
new ExecutePACThreadAction(this);
|
||||||
PendingPACQuery *query = static_cast<PendingPACQuery *>(node);
|
if (mPACThread)
|
||||||
node = PR_NEXT_LINK(node);
|
mPACThread->Dispatch(pending, nsIEventTarget::DISPATCH_NORMAL);
|
||||||
if (NS_SUCCEEDED(status)) {
|
|
||||||
// keep the query in the list (so we can complete it from Shutdown if
|
|
||||||
// necessary).
|
|
||||||
status = query->Start(nsIDNSService::RESOLVE_SPECULATE);
|
|
||||||
}
|
|
||||||
if (status == NS_ERROR_DNS_LOOKUP_QUEUE_FULL) {
|
|
||||||
query->OnLookupComplete(NULL, NULL, NS_OK);
|
|
||||||
status = NS_OK;
|
|
||||||
} else if (NS_FAILED(status)) {
|
|
||||||
// remove the query from the list
|
|
||||||
PR_REMOVE_LINK(query);
|
|
||||||
query->Complete(status, EmptyCString());
|
|
||||||
NS_RELEASE(query);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS3(nsPACMan, nsIStreamLoaderObserver, nsIInterfaceRequestor,
|
void
|
||||||
nsIChannelEventSink)
|
nsPACMan::PostCancelPendingQ(nsresult status)
|
||||||
|
{
|
||||||
|
NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
|
||||||
|
nsRefPtr<ExecutePACThreadAction> pending =
|
||||||
|
new ExecutePACThreadAction(this);
|
||||||
|
pending->CancelQueue(status);
|
||||||
|
if (mPACThread)
|
||||||
|
mPACThread->Dispatch(pending, nsIEventTarget::DISPATCH_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsPACMan::CancelPendingQ(nsresult status)
|
||||||
|
{
|
||||||
|
NS_ABORT_IF_FALSE(!NS_IsMainThread(), "wrong thread");
|
||||||
|
nsRefPtr<PendingPACQuery> query;
|
||||||
|
|
||||||
|
while (!mPendingQ.isEmpty()) {
|
||||||
|
query = dont_AddRef(mPendingQ.popLast());
|
||||||
|
query->Complete(status, EmptyCString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mShutdown)
|
||||||
|
mPAC.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsPACMan::ProcessPendingQ()
|
||||||
|
{
|
||||||
|
NS_ABORT_IF_FALSE(!NS_IsMainThread(), "wrong thread");
|
||||||
|
while (ProcessPending());
|
||||||
|
|
||||||
|
// do GC while the thread has nothing pending
|
||||||
|
mPAC.GC();
|
||||||
|
|
||||||
|
if (mShutdown)
|
||||||
|
mPAC.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns true if progress was made by shortening the queue
|
||||||
|
bool
|
||||||
|
nsPACMan::ProcessPending()
|
||||||
|
{
|
||||||
|
if (mPendingQ.isEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// queue during normal load, but if we are retrying a failed load then
|
||||||
|
// fast fail the queries
|
||||||
|
if (mInProgress || (IsLoading() && !mLoadFailureCount))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
nsRefPtr<PendingPACQuery> query(dont_AddRef(mPendingQ.popFirst()));
|
||||||
|
|
||||||
|
if (mShutdown || IsLoading()) {
|
||||||
|
query->Complete(NS_ERROR_NOT_AVAILABLE, EmptyCString());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoCString pacString;
|
||||||
|
bool completed = false;
|
||||||
|
mInProgress = true;
|
||||||
|
nsAutoCString PACURI;
|
||||||
|
|
||||||
|
// first we need to consider the system proxy changing the pac url
|
||||||
|
if (mSystemProxySettings &&
|
||||||
|
NS_SUCCEEDED(mSystemProxySettings->GetPACURI(PACURI)) &&
|
||||||
|
!PACURI.IsEmpty() &&
|
||||||
|
!PACURI.Equals(mPACURISpec)) {
|
||||||
|
query->UseAlternatePACFile(PACURI);
|
||||||
|
completed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now try the system proxy settings for this particular url if
|
||||||
|
// PAC was not specified
|
||||||
|
if (!completed && mSystemProxySettings && PACURI.IsEmpty() &&
|
||||||
|
NS_SUCCEEDED(mSystemProxySettings->
|
||||||
|
GetProxyForURI(query->mSpec, query->mScheme,
|
||||||
|
query->mHost, query->mPort,
|
||||||
|
pacString))) {
|
||||||
|
query->Complete(NS_OK, pacString);
|
||||||
|
completed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the systemproxysettings didn't complete the resolution. try via PAC
|
||||||
|
if (!completed) {
|
||||||
|
nsresult status = mPAC.GetProxyForURI(query->mSpec, query->mHost, pacString);
|
||||||
|
query->Complete(status, pacString);
|
||||||
|
}
|
||||||
|
|
||||||
|
mInProgress = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMPL_THREADSAFE_ISUPPORTS3(nsPACMan, nsIStreamLoaderObserver,
|
||||||
|
nsIInterfaceRequestor, nsIChannelEventSink)
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsPACMan::OnStreamComplete(nsIStreamLoader *loader,
|
nsPACMan::OnStreamComplete(nsIStreamLoader *loader,
|
||||||
@ -378,6 +559,7 @@ nsPACMan::OnStreamComplete(nsIStreamLoader *loader,
|
|||||||
uint32_t dataLen,
|
uint32_t dataLen,
|
||||||
const uint8_t *data)
|
const uint8_t *data)
|
||||||
{
|
{
|
||||||
|
NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
|
||||||
if (mLoader != loader) {
|
if (mLoader != loader) {
|
||||||
// If this happens, then it means that LoadPACFromURI was called more
|
// If this happens, then it means that LoadPACFromURI was called more
|
||||||
// than once before the initial call completed. In this case, status
|
// than once before the initial call completed. In this case, status
|
||||||
@ -387,8 +569,6 @@ nsPACMan::OnStreamComplete(nsIStreamLoader *loader,
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
mLoader = nullptr;
|
|
||||||
|
|
||||||
if (NS_SUCCEEDED(status) && HttpRequestSucceeded(loader)) {
|
if (NS_SUCCEEDED(status) && HttpRequestSucceeded(loader)) {
|
||||||
// Get the URI spec used to load this PAC script.
|
// Get the URI spec used to load this PAC script.
|
||||||
nsAutoCString pacURI;
|
nsAutoCString pacURI;
|
||||||
@ -404,18 +584,21 @@ nsPACMan::OnStreamComplete(nsIStreamLoader *loader,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mPAC) {
|
// We assume that the PAC text is ASCII (or ISO-Latin-1). We've had this
|
||||||
mPAC = do_CreateInstance(NS_PROXYAUTOCONFIG_CONTRACTID, &status);
|
// assumption forever, and some real-world PAC scripts actually have some
|
||||||
if (!mPAC)
|
// non-ASCII text in comment blocks (see bug 296163).
|
||||||
NS_WARNING("failed to instantiate PAC component");
|
const char *text = (const char *) data;
|
||||||
}
|
|
||||||
if (NS_SUCCEEDED(status)) {
|
// we have succeeded in loading the pac file using a bunch of interfaces that
|
||||||
// We assume that the PAC text is ASCII (or ISO-Latin-1). We've had this
|
// are main thread only, unfortunately we have to initialize the instance of
|
||||||
// assumption forever, and some real-world PAC scripts actually have some
|
// the PAC evaluator (NS_PROXYAUTOCONFIG_CONTRACTID) on the pac thread, because
|
||||||
// non-ASCII text in comment blocks (see bug 296163).
|
// that is where it will be used.
|
||||||
const char *text = (const char *) data;
|
|
||||||
status = mPAC->Init(pacURI, NS_ConvertASCIItoUTF16(text, dataLen));
|
nsRefPtr<ExecutePACThreadAction> pending =
|
||||||
}
|
new ExecutePACThreadAction(this);
|
||||||
|
pending->SetupPAC(text, dataLen, pacURI);
|
||||||
|
if (mPACThread)
|
||||||
|
mPACThread->Dispatch(pending, nsIEventTarget::DISPATCH_NORMAL);
|
||||||
|
|
||||||
// Even if the PAC file could not be parsed, we did succeed in loading the
|
// Even if the PAC file could not be parsed, we did succeed in loading the
|
||||||
// data for it.
|
// data for it.
|
||||||
@ -426,11 +609,11 @@ nsPACMan::OnStreamComplete(nsIStreamLoader *loader,
|
|||||||
OnLoadFailure();
|
OnLoadFailure();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset mPAC if necessary
|
if (NS_SUCCEEDED(status))
|
||||||
if (mPAC && NS_FAILED(status))
|
PostProcessPendingQ();
|
||||||
mPAC = nullptr;
|
else
|
||||||
|
PostCancelPendingQ(status);
|
||||||
|
|
||||||
ProcessPendingQ(status);
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -466,3 +649,26 @@ nsPACMan::AsyncOnChannelRedirect(nsIChannel *oldChannel, nsIChannel *newChannel,
|
|||||||
callback->OnRedirectVerifyCallback(NS_OK);
|
callback->OnRedirectVerifyCallback(NS_OK);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsPACMan::NamePACThread()
|
||||||
|
{
|
||||||
|
NS_ABORT_IF_FALSE(!NS_IsMainThread(), "wrong thread");
|
||||||
|
PR_SetCurrentThreadName("Proxy Resolution");
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsPACMan::Init(nsISystemProxySettings *systemProxySettings)
|
||||||
|
{
|
||||||
|
mSystemProxySettings = systemProxySettings;
|
||||||
|
|
||||||
|
nsresult rv = NS_NewThread(getter_AddRefs(mPACThread), nullptr);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &nsPACMan::NamePACThread);
|
||||||
|
// don't check return value as it is not a big deal for this to fail.
|
||||||
|
mPACThread->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
@ -10,12 +10,20 @@
|
|||||||
#include "nsIStreamLoader.h"
|
#include "nsIStreamLoader.h"
|
||||||
#include "nsIInterfaceRequestor.h"
|
#include "nsIInterfaceRequestor.h"
|
||||||
#include "nsIChannelEventSink.h"
|
#include "nsIChannelEventSink.h"
|
||||||
#include "nsIProxyAutoConfig.h"
|
#include "ProxyAutoConfig.h"
|
||||||
|
#include "nsICancelable.h"
|
||||||
|
#include "nsThreadUtils.h"
|
||||||
#include "nsIURI.h"
|
#include "nsIURI.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "prclist.h"
|
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "mozilla/LinkedList.h"
|
||||||
|
#include "nsIThread.h"
|
||||||
|
#include "nsAutoPtr.h"
|
||||||
|
#include "nsISystemProxySettings.h"
|
||||||
|
#include "mozilla/TimeStamp.h"
|
||||||
|
|
||||||
|
class nsPACMan;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class defines a callback interface used by AsyncGetProxyForURI.
|
* This class defines a callback interface used by AsyncGetProxyForURI.
|
||||||
@ -31,14 +39,45 @@ public:
|
|||||||
* @param pacString
|
* @param pacString
|
||||||
* This parameter holds the value of the PAC string. It is empty when
|
* This parameter holds the value of the PAC string. It is empty when
|
||||||
* status is a failure code.
|
* status is a failure code.
|
||||||
|
* @param newPACURL
|
||||||
|
* This parameter holds the URL of a new PAC file that should be loaded
|
||||||
|
* before the query is evaluated again. At least one of pacString and
|
||||||
|
* newPACURL should be 0 length.
|
||||||
*/
|
*/
|
||||||
virtual void OnQueryComplete(nsresult status, const nsCString &pacString) = 0;
|
virtual void OnQueryComplete(nsresult status,
|
||||||
|
const nsCString &pacString,
|
||||||
|
const nsCString &newPACURL) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PendingPACQuery MOZ_FINAL : public nsRunnable,
|
||||||
|
public mozilla::LinkedListElement<PendingPACQuery>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PendingPACQuery(nsPACMan *pacMan, nsIURI *uri,
|
||||||
|
nsPACManCallback *callback, bool mainThreadResponse);
|
||||||
|
|
||||||
|
// can be called from either thread
|
||||||
|
void Complete(nsresult status, const nsCString &pacString);
|
||||||
|
void UseAlternatePACFile(const nsCString &pacURL);
|
||||||
|
|
||||||
|
nsCString mSpec;
|
||||||
|
nsCString mScheme;
|
||||||
|
nsCString mHost;
|
||||||
|
int32_t mPort;
|
||||||
|
|
||||||
|
NS_IMETHOD Run(void); /* nsRunnable */
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsPACMan *mPACMan; // weak reference
|
||||||
|
nsRefPtr<nsPACManCallback> mCallback;
|
||||||
|
bool mOnMainThreadOnly;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class provides an abstraction layer above the PAC thread. The methods
|
* This class provides an abstraction layer above the PAC thread. The methods
|
||||||
* defined on this class are intended to be called on the main thread only.
|
* defined on this class are intended to be called on the main thread only.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class nsPACMan MOZ_FINAL : public nsIStreamLoaderObserver
|
class nsPACMan MOZ_FINAL : public nsIStreamLoaderObserver
|
||||||
, public nsIInterfaceRequestor
|
, public nsIInterfaceRequestor
|
||||||
, public nsIChannelEventSink
|
, public nsIChannelEventSink
|
||||||
@ -55,19 +94,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
/**
|
|
||||||
* This method queries a PAC result synchronously.
|
|
||||||
*
|
|
||||||
* @param uri
|
|
||||||
* The URI to query.
|
|
||||||
* @param result
|
|
||||||
* Holds the PAC result string upon return.
|
|
||||||
*
|
|
||||||
* @return NS_ERROR_IN_PROGRESS if the PAC file is not yet loaded.
|
|
||||||
* @return NS_ERROR_NOT_AVAILABLE if the PAC file could not be loaded.
|
|
||||||
*/
|
|
||||||
nsresult GetProxyForURI(nsIURI *uri, nsACString &result);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method queries a PAC result asynchronously. The callback runs on the
|
* This method queries a PAC result asynchronously. The callback runs on the
|
||||||
* calling thread. If the PAC file has not yet been loaded, then this method
|
* calling thread. If the PAC file has not yet been loaded, then this method
|
||||||
@ -78,8 +104,11 @@ public:
|
|||||||
* The URI to query.
|
* The URI to query.
|
||||||
* @param callback
|
* @param callback
|
||||||
* The callback to run once the PAC result is available.
|
* The callback to run once the PAC result is available.
|
||||||
|
* @param mustCallbackOnMainThread
|
||||||
|
* If set to false the callback can be made from the PAC thread
|
||||||
*/
|
*/
|
||||||
nsresult AsyncGetProxyForURI(nsIURI *uri, nsPACManCallback *callback);
|
nsresult AsyncGetProxyForURI(nsIURI *uri, nsPACManCallback *callback,
|
||||||
|
bool mustCallbackOnMainThread);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method may be called to reload the PAC file. While we are loading
|
* This method may be called to reload the PAC file. While we are loading
|
||||||
@ -105,11 +134,28 @@ public:
|
|||||||
return mPACURI && NS_SUCCEEDED(mPACURI->Equals(uri, &result)) && result;
|
return mPACURI && NS_SUCCEEDED(mPACURI->Equals(uri, &result)) && result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsPACURI(nsACString &spec)
|
||||||
|
{
|
||||||
|
nsAutoCString tmp;
|
||||||
|
return (mPACURI && NS_SUCCEEDED(mPACURI->GetSpec(tmp)) && tmp.Equals(spec));
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_HIDDEN_(nsresult) Init(nsISystemProxySettings *);
|
||||||
|
static nsPACMan *sInstance;
|
||||||
|
|
||||||
|
// PAC thread operations only
|
||||||
|
void ProcessPendingQ();
|
||||||
|
void CancelPendingQ(nsresult);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NS_DECL_NSISTREAMLOADEROBSERVER
|
NS_DECL_NSISTREAMLOADEROBSERVER
|
||||||
NS_DECL_NSIINTERFACEREQUESTOR
|
NS_DECL_NSIINTERFACEREQUESTOR
|
||||||
NS_DECL_NSICHANNELEVENTSINK
|
NS_DECL_NSICHANNELEVENTSINK
|
||||||
|
|
||||||
|
friend class PendingPACQuery;
|
||||||
|
friend class PACLoadComplete;
|
||||||
|
friend class ExecutePACThreadAction;
|
||||||
|
|
||||||
~nsPACMan();
|
~nsPACMan();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -117,13 +163,6 @@ private:
|
|||||||
*/
|
*/
|
||||||
void CancelExistingLoad();
|
void CancelExistingLoad();
|
||||||
|
|
||||||
/**
|
|
||||||
* Process mPendingQ. If status is a failure code, then the pending queue
|
|
||||||
* will be emptied. If status is a success code, then the pending requests
|
|
||||||
* will be processed (i.e., their Start method will be called).
|
|
||||||
*/
|
|
||||||
void ProcessPendingQ(nsresult status);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start loading the PAC file.
|
* Start loading the PAC file.
|
||||||
*/
|
*/
|
||||||
@ -139,15 +178,35 @@ private:
|
|||||||
*/
|
*/
|
||||||
void OnLoadFailure();
|
void OnLoadFailure();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PostQuery() only runs on the PAC thread and it is used to
|
||||||
|
* place a pendingPACQuery into the queue and potentially
|
||||||
|
* execute the queue if it was otherwise empty
|
||||||
|
*/
|
||||||
|
nsresult PostQuery(PendingPACQuery *query);
|
||||||
|
|
||||||
|
// PAC thread operations only
|
||||||
|
void PostProcessPendingQ();
|
||||||
|
void PostCancelPendingQ(nsresult);
|
||||||
|
bool ProcessPending();
|
||||||
|
void NamePACThread();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsCOMPtr<nsIProxyAutoConfig> mPAC;
|
mozilla::net::ProxyAutoConfig mPAC;
|
||||||
|
nsCOMPtr<nsIThread> mPACThread;
|
||||||
|
nsCOMPtr<nsISystemProxySettings> mSystemProxySettings;
|
||||||
|
|
||||||
|
mozilla::LinkedList<PendingPACQuery> mPendingQ; /* pac thread only */
|
||||||
|
|
||||||
nsCOMPtr<nsIURI> mPACURI;
|
nsCOMPtr<nsIURI> mPACURI;
|
||||||
PRCList mPendingQ;
|
nsCString mPACURISpec; // for use off main thread
|
||||||
nsCOMPtr<nsIStreamLoader> mLoader;
|
nsCOMPtr<nsIStreamLoader> mLoader;
|
||||||
bool mLoadPending;
|
bool mLoadPending;
|
||||||
bool mShutdown;
|
bool mShutdown;
|
||||||
PRTime mScheduledReload;
|
mozilla::TimeStamp mScheduledReload;
|
||||||
uint32_t mLoadFailureCount;
|
uint32_t mLoadFailureCount;
|
||||||
|
|
||||||
|
bool mInProgress;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // nsPACMan_h__
|
#endif // nsPACMan_h__
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#include "nsIClassInfoImpl.h"
|
#include "nsIClassInfoImpl.h"
|
||||||
#include "nsIServiceManager.h"
|
#include "nsIServiceManager.h"
|
||||||
#include "nsXPIDLString.h"
|
#include "nsXPIDLString.h"
|
||||||
#include "nsIProxyAutoConfig.h"
|
|
||||||
#include "nsIIOService.h"
|
#include "nsIIOService.h"
|
||||||
#include "nsIObserverService.h"
|
#include "nsIObserverService.h"
|
||||||
#include "nsIProtocolHandler.h"
|
#include "nsIProtocolHandler.h"
|
||||||
@ -29,6 +28,9 @@
|
|||||||
#include "nsCRT.h"
|
#include "nsCRT.h"
|
||||||
#include "prnetdb.h"
|
#include "prnetdb.h"
|
||||||
#include "nsPACMan.h"
|
#include "nsPACMan.h"
|
||||||
|
#include "nsProxyRelease.h"
|
||||||
|
#include "mozilla/Mutex.h"
|
||||||
|
#include "mozilla/CondVar.h"
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -72,12 +74,49 @@ public:
|
|||||||
, mDispatched(false)
|
, mDispatched(false)
|
||||||
, mResolveFlags(aResolveFlags)
|
, mResolveFlags(aResolveFlags)
|
||||||
, mPPS(pps)
|
, mPPS(pps)
|
||||||
|
, mXPComPPS(pps)
|
||||||
, mURI(uri)
|
, mURI(uri)
|
||||||
, mCallback(callback)
|
, mCallback(callback)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(mCallback, "null callback");
|
NS_ASSERTION(mCallback, "null callback");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~nsAsyncResolveRequest()
|
||||||
|
{
|
||||||
|
if (!NS_IsMainThread()) {
|
||||||
|
// these xpcom pointers might need to be proxied back to the
|
||||||
|
// main thread to delete safely, but if this request had its
|
||||||
|
// callbacks called normally they will all be null and this is a nop
|
||||||
|
|
||||||
|
nsCOMPtr<nsIThread> mainThread;
|
||||||
|
NS_GetMainThread(getter_AddRefs(mainThread));
|
||||||
|
|
||||||
|
if (mURI) {
|
||||||
|
nsIURI *forgettable;
|
||||||
|
mURI.forget(&forgettable);
|
||||||
|
NS_ProxyRelease(mainThread, forgettable, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCallback) {
|
||||||
|
nsIProtocolProxyCallback *forgettable;
|
||||||
|
mCallback.forget(&forgettable);
|
||||||
|
NS_ProxyRelease(mainThread, forgettable, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mProxyInfo) {
|
||||||
|
nsIProxyInfo *forgettable;
|
||||||
|
mProxyInfo.forget(&forgettable);
|
||||||
|
NS_ProxyRelease(mainThread, forgettable, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mXPComPPS) {
|
||||||
|
nsIProtocolProxyService *forgettable;
|
||||||
|
mXPComPPS.forget(&forgettable);
|
||||||
|
NS_ProxyRelease(mainThread, forgettable, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SetResult(nsresult status, nsIProxyInfo *pi)
|
void SetResult(nsresult status, nsIProxyInfo *pi)
|
||||||
{
|
{
|
||||||
mStatus = status;
|
mStatus = status;
|
||||||
@ -124,7 +163,9 @@ private:
|
|||||||
|
|
||||||
// Called asynchronously, so we do not need to post another PLEvent
|
// Called asynchronously, so we do not need to post another PLEvent
|
||||||
// before calling DoCallback.
|
// before calling DoCallback.
|
||||||
void OnQueryComplete(nsresult status, const nsCString &pacString)
|
void OnQueryComplete(nsresult status,
|
||||||
|
const nsCString &pacString,
|
||||||
|
const nsCString &newPACURL)
|
||||||
{
|
{
|
||||||
// If we've already called DoCallback then, nothing more to do.
|
// If we've already called DoCallback then, nothing more to do.
|
||||||
if (!mCallback)
|
if (!mCallback)
|
||||||
@ -134,6 +175,7 @@ private:
|
|||||||
if (mStatus == NS_OK) {
|
if (mStatus == NS_OK) {
|
||||||
mStatus = status;
|
mStatus = status;
|
||||||
mPACString = pacString;
|
mPACString = pacString;
|
||||||
|
mPACURL = newPACURL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// In the cancelation case, we may still have another PLEvent in
|
// In the cancelation case, we may still have another PLEvent in
|
||||||
@ -156,26 +198,59 @@ private:
|
|||||||
mPPS->ApplyFilters(mURI, info, mProxyInfo);
|
mPPS->ApplyFilters(mURI, info, mProxyInfo);
|
||||||
else
|
else
|
||||||
mProxyInfo = nullptr;
|
mProxyInfo = nullptr;
|
||||||
|
|
||||||
|
LOG(("pac thread callback %s\n", mPACString.get()));
|
||||||
|
mCallback->OnProxyAvailable(this, mURI, mProxyInfo, mStatus);
|
||||||
|
}
|
||||||
|
else if (NS_SUCCEEDED(mStatus) && !mPACURL.IsEmpty()) {
|
||||||
|
LOG(("pac thread callback indicates new pac file load\n"));
|
||||||
|
|
||||||
|
// trigger load of new pac url
|
||||||
|
nsresult rv = mPPS->ConfigureFromPAC(mPACURL, false);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
// now that the load is triggered, we can resubmit the query
|
||||||
|
nsRefPtr<nsAsyncResolveRequest> newRequest =
|
||||||
|
new nsAsyncResolveRequest(mPPS, mURI, mResolveFlags, mCallback);
|
||||||
|
rv = mPPS->mPACMan->AsyncGetProxyForURI(mURI, newRequest, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
mCallback->OnProxyAvailable(this, mURI, nullptr, rv);
|
||||||
|
|
||||||
|
// do not call onproxyavailable() in SUCCESS case - the newRequest will
|
||||||
|
// take care of that
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG(("pac thread callback did not provide information %X\n", mStatus));
|
||||||
|
mCallback->OnProxyAvailable(this, mURI, mProxyInfo, mStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
mCallback->OnProxyAvailable(this, mURI, mProxyInfo, mStatus);
|
// We are on the main thread now and don't need these any more so
|
||||||
|
// release them to avoid having to proxy them back to the main thread
|
||||||
|
// in the dtor
|
||||||
mCallback = nullptr; // in case the callback holds an owning ref to us
|
mCallback = nullptr; // in case the callback holds an owning ref to us
|
||||||
|
mPPS = nullptr;
|
||||||
|
mXPComPPS = nullptr;
|
||||||
|
mURI = nullptr;
|
||||||
|
mProxyInfo = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
nsresult mStatus;
|
nsresult mStatus;
|
||||||
nsCString mPACString;
|
nsCString mPACString;
|
||||||
|
nsCString mPACURL;
|
||||||
bool mDispatched;
|
bool mDispatched;
|
||||||
uint32_t mResolveFlags;
|
uint32_t mResolveFlags;
|
||||||
|
|
||||||
nsRefPtr<nsProtocolProxyService> mPPS;
|
nsProtocolProxyService *mPPS;
|
||||||
|
nsCOMPtr<nsIProtocolProxyService> mXPComPPS;
|
||||||
nsCOMPtr<nsIURI> mURI;
|
nsCOMPtr<nsIURI> mURI;
|
||||||
nsCOMPtr<nsIProtocolProxyCallback> mCallback;
|
nsCOMPtr<nsIProtocolProxyCallback> mCallback;
|
||||||
nsCOMPtr<nsIProxyInfo> mProxyInfo;
|
nsCOMPtr<nsIProxyInfo> mProxyInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS2(nsAsyncResolveRequest, nsICancelable, nsIRunnable)
|
NS_IMPL_THREADSAFE_ISUPPORTS2(nsAsyncResolveRequest, nsICancelable, nsIRunnable)
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -386,8 +461,12 @@ nsProtocolProxyService::PrefsChanged(nsIPrefBranch *prefBranch,
|
|||||||
mSystemProxySettings = do_GetService(NS_SYSTEMPROXYSETTINGS_CONTRACTID);
|
mSystemProxySettings = do_GetService(NS_SYSTEMPROXYSETTINGS_CONTRACTID);
|
||||||
if (!mSystemProxySettings)
|
if (!mSystemProxySettings)
|
||||||
mProxyConfig = PROXYCONFIG_DIRECT;
|
mProxyConfig = PROXYCONFIG_DIRECT;
|
||||||
|
ResetPACThread();
|
||||||
} else {
|
} else {
|
||||||
mSystemProxySettings = nullptr;
|
if (mSystemProxySettings) {
|
||||||
|
mSystemProxySettings = nullptr;
|
||||||
|
ResetPACThread();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -572,7 +651,7 @@ nsProtocolProxyService::ExtractProxyInfo(const char *start,
|
|||||||
*result = nullptr;
|
*result = nullptr;
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
|
|
||||||
// see BNF in nsIProxyAutoConfig.idl
|
// see BNF in ProxyAutoConfig.h and notes in nsISystemProxySettings.idl
|
||||||
|
|
||||||
// find end of proxy info delimiter
|
// find end of proxy info delimiter
|
||||||
const char *end = start;
|
const char *end = start;
|
||||||
@ -616,33 +695,57 @@ nsProtocolProxyService::ExtractProxyInfo(const char *start,
|
|||||||
start = sp;
|
start = sp;
|
||||||
while ((*start == ' ' || *start == '\t') && start < end)
|
while ((*start == ' ' || *start == '\t') && start < end)
|
||||||
start++;
|
start++;
|
||||||
if (start < end) {
|
|
||||||
host = start;
|
// port defaults
|
||||||
hostEnd = strchr(host, ':');
|
if (type == kProxyType_HTTP)
|
||||||
if (!hostEnd || hostEnd > end) {
|
port = 80;
|
||||||
hostEnd = end;
|
else
|
||||||
// no port, so assume default
|
port = 1080;
|
||||||
if (type == kProxyType_HTTP)
|
|
||||||
port = 80;
|
nsProxyInfo *pi = new nsProxyInfo();
|
||||||
else
|
pi->mType = type;
|
||||||
port = 1080;
|
pi->mFlags = flags;
|
||||||
|
pi->mResolveFlags = aResolveFlags;
|
||||||
|
pi->mTimeout = mFailedProxyTimeout;
|
||||||
|
|
||||||
|
// www.foo.com:8080 and http://www.foo.com:8080
|
||||||
|
nsDependentCSubstring maybeURL(start, end - start);
|
||||||
|
nsCOMPtr<nsIURI> pacURI;
|
||||||
|
|
||||||
|
nsAutoCString urlHost;
|
||||||
|
if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(pacURI), maybeURL)) &&
|
||||||
|
NS_SUCCEEDED(pacURI->GetAsciiHost(urlHost)) &&
|
||||||
|
!urlHost.IsEmpty()) {
|
||||||
|
// http://www.example.com:8080
|
||||||
|
|
||||||
|
pi->mHost = urlHost;
|
||||||
|
|
||||||
|
int32_t tPort;
|
||||||
|
if (NS_SUCCEEDED(pacURI->GetPort(&tPort)) && tPort != -1) {
|
||||||
|
port = tPort;
|
||||||
}
|
}
|
||||||
else
|
pi->mPort = port;
|
||||||
port = atoi(hostEnd + 1);
|
|
||||||
}
|
}
|
||||||
nsProxyInfo *pi = new nsProxyInfo;
|
else {
|
||||||
if (pi) {
|
// www.example.com:8080
|
||||||
pi->mType = type;
|
if (start < end) {
|
||||||
pi->mFlags = flags;
|
host = start;
|
||||||
pi->mResolveFlags = aResolveFlags;
|
hostEnd = strchr(host, ':');
|
||||||
pi->mTimeout = mFailedProxyTimeout;
|
if (!hostEnd || hostEnd > end) {
|
||||||
|
hostEnd = end;
|
||||||
|
// no port, so assume default
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
port = atoi(hostEnd + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
// YES, it is ok to specify a null proxy host.
|
// YES, it is ok to specify a null proxy host.
|
||||||
if (host) {
|
if (host) {
|
||||||
pi->mHost.Assign(host, hostEnd - host);
|
pi->mHost.Assign(host, hostEnd - host);
|
||||||
pi->mPort = port;
|
pi->mPort = port;
|
||||||
}
|
}
|
||||||
NS_ADDREF(*result = pi);
|
|
||||||
}
|
}
|
||||||
|
NS_ADDREF(*result = pi);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (*end == ';' || *end == ' ' || *end == '\t')
|
while (*end == ';' || *end == ' ' || *end == '\t')
|
||||||
@ -739,15 +842,46 @@ nsProtocolProxyService::IsProxyDisabled(nsProxyInfo *pi)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsProtocolProxyService::SetupPACThread()
|
||||||
|
{
|
||||||
|
if (mPACMan)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
mPACMan = new nsPACMan();
|
||||||
|
|
||||||
|
bool mainThreadOnly;
|
||||||
|
nsresult rv;
|
||||||
|
if (mSystemProxySettings &&
|
||||||
|
NS_SUCCEEDED(mSystemProxySettings->GetMainThreadOnly(&mainThreadOnly)) &&
|
||||||
|
!mainThreadOnly) {
|
||||||
|
rv = mPACMan->Init(mSystemProxySettings);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rv = mPACMan->Init(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
mPACMan = nullptr;
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsProtocolProxyService::ResetPACThread()
|
||||||
|
{
|
||||||
|
if (!mPACMan)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
mPACMan->Shutdown();
|
||||||
|
mPACMan = nullptr;
|
||||||
|
return SetupPACThread();
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsProtocolProxyService::ConfigureFromPAC(const nsCString &spec,
|
nsProtocolProxyService::ConfigureFromPAC(const nsCString &spec,
|
||||||
bool forceReload)
|
bool forceReload)
|
||||||
{
|
{
|
||||||
if (!mPACMan) {
|
SetupPACThread();
|
||||||
mPACMan = new nsPACMan();
|
|
||||||
if (!mPACMan)
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIURI> pacURI;
|
nsCOMPtr<nsIURI> pacURI;
|
||||||
nsresult rv = NS_NewURI(getter_AddRefs(pacURI), spec);
|
nsresult rv = NS_NewURI(getter_AddRefs(pacURI), spec);
|
||||||
@ -814,53 +948,125 @@ nsProtocolProxyService::ReloadPAC()
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// nsIProtocolProxyService
|
// When sync interface is removed this can go away too
|
||||||
NS_IMETHODIMP
|
class nsAsyncBridgeRequest MOZ_FINAL : public nsPACManCallback
|
||||||
nsProtocolProxyService::Resolve(nsIURI *uri, uint32_t flags,
|
|
||||||
nsIProxyInfo **result)
|
|
||||||
{
|
{
|
||||||
NS_ENSURE_ARG_POINTER(uri);
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
|
nsAsyncBridgeRequest()
|
||||||
|
: mMutex("nsDeprecatedCallback")
|
||||||
|
, mCondVar(mMutex, "nsDeprecatedCallback")
|
||||||
|
, mCompleted(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnQueryComplete(nsresult status,
|
||||||
|
const nsCString &pacString,
|
||||||
|
const nsCString &newPACURL)
|
||||||
|
{
|
||||||
|
MutexAutoLock lock(mMutex);
|
||||||
|
mCompleted = true;
|
||||||
|
mStatus = status;
|
||||||
|
mPACString = pacString;
|
||||||
|
mPACURL = newPACURL;
|
||||||
|
mCondVar.Notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lock() { mMutex.Lock(); }
|
||||||
|
void Unlock() { mMutex.Unlock(); }
|
||||||
|
void Wait() { mCondVar.Wait(PR_SecondsToInterval(3)); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
~nsAsyncBridgeRequest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
friend class nsProtocolProxyService;
|
||||||
|
|
||||||
|
Mutex mMutex;
|
||||||
|
CondVar mCondVar;
|
||||||
|
|
||||||
|
nsresult mStatus;
|
||||||
|
nsCString mPACString;
|
||||||
|
nsCString mPACURL;
|
||||||
|
bool mCompleted;
|
||||||
|
};
|
||||||
|
NS_IMPL_THREADSAFE_ISUPPORTS1(nsAsyncBridgeRequest, nsPACManCallback)
|
||||||
|
|
||||||
|
// nsIProtocolProxyService2
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsProtocolProxyService::DeprecatedBlockingResolve(nsIURI *aURI,
|
||||||
|
uint32_t aFlags,
|
||||||
|
nsIProxyInfo **retval)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aURI);
|
||||||
|
|
||||||
nsProtocolInfo info;
|
nsProtocolInfo info;
|
||||||
nsresult rv = GetProtocolInfo(uri, &info);
|
nsresult rv = GetProtocolInfo(aURI, &info);
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
bool usePAC;
|
nsCOMPtr<nsIProxyInfo> pi;
|
||||||
rv = Resolve_Internal(uri, info, flags, &usePAC, result);
|
bool usePACThread;
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
LOG(("Resolve_Internal returned rv(0x%08x)\n", rv));
|
// SystemProxySettings and PAC files can block the main thread
|
||||||
|
// but if neither of them are in use, we can just do the work
|
||||||
|
// right here and directly invoke the callback
|
||||||
|
|
||||||
|
rv = Resolve_Internal(aURI, info, aFlags, &usePACThread, getter_AddRefs(pi));
|
||||||
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
|
if (!usePACThread || !mPACMan) {
|
||||||
|
ApplyFilters(aURI, info, pi);
|
||||||
|
pi.forget(retval);
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usePAC && mPACMan) {
|
// Use the PAC thread to do the work, so we don't have to reimplement that
|
||||||
NS_ASSERTION(*result == nullptr, "we should not have a result yet");
|
// code, but block this thread on that completion.
|
||||||
|
nsRefPtr<nsAsyncBridgeRequest> ctx = new nsAsyncBridgeRequest();
|
||||||
|
ctx->Lock();
|
||||||
|
if (NS_SUCCEEDED(mPACMan->AsyncGetProxyForURI(aURI, ctx, false))) {
|
||||||
|
// this can really block the main thread, so cap it at 3 seconds
|
||||||
|
ctx->Wait();
|
||||||
|
}
|
||||||
|
ctx->Unlock();
|
||||||
|
if (!ctx->mCompleted)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
if (NS_FAILED(ctx->mStatus))
|
||||||
|
return ctx->mStatus;
|
||||||
|
|
||||||
// If the caller didn't want us to invoke PAC, then error out.
|
// pretty much duplicate real DoCallback logic
|
||||||
if (flags & RESOLVE_NON_BLOCKING)
|
|
||||||
return NS_BASE_STREAM_WOULD_BLOCK;
|
|
||||||
|
|
||||||
// Query the PAC file synchronously.
|
// Generate proxy info from the PAC string if appropriate
|
||||||
nsCString pacString;
|
if (!ctx->mPACString.IsEmpty()) {
|
||||||
rv = mPACMan->GetProxyForURI(uri, pacString);
|
LOG(("sync pac thread callback %s\n", ctx->mPACString.get()));
|
||||||
if (NS_SUCCEEDED(rv))
|
ProcessPACString(ctx->mPACString, 0, getter_AddRefs(pi));
|
||||||
ProcessPACString(pacString, flags, result);
|
ApplyFilters(aURI, info, pi);
|
||||||
else if (rv == NS_ERROR_IN_PROGRESS) {
|
pi.forget(retval);
|
||||||
// Construct a special UNKNOWN proxy entry that informs the caller
|
return NS_OK;
|
||||||
// that the proxy info is yet to be determined.
|
|
||||||
rv = NewProxyInfo_Internal(kProxyType_UNKNOWN, EmptyCString(), -1,
|
|
||||||
0, 0, nullptr, flags, result);
|
|
||||||
if (NS_FAILED(rv))
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
NS_WARNING("failed querying PAC file; trying DIRECT");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplyFilters(uri, info, result);
|
if (!ctx->mPACURL.IsEmpty()) {
|
||||||
|
NS_WARNING("sync pac thread callback indicates new pac file load\n");
|
||||||
|
// This is a problem and is one of the reasons this blocking interface
|
||||||
|
// is deprecated. The main loop needs to spin to make this reload happen. So
|
||||||
|
// we are going to kick off the reload and return an error - it will work
|
||||||
|
// next time. Because this sync interface is only used in the java plugin it
|
||||||
|
// is extremely likely that the pac file has already been loaded anyhow.
|
||||||
|
|
||||||
|
rv = ConfigureFromPAC(ctx->mPACURL, false);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return rv;
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*retval = nullptr;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nsIProtocolProxyService
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsProtocolProxyService::AsyncResolve(nsIURI *uri, uint32_t flags,
|
nsProtocolProxyService::AsyncResolve(nsIURI *uri, uint32_t flags,
|
||||||
nsIProtocolProxyCallback *callback,
|
nsIProtocolProxyCallback *callback,
|
||||||
@ -871,29 +1077,33 @@ nsProtocolProxyService::AsyncResolve(nsIURI *uri, uint32_t flags,
|
|||||||
|
|
||||||
nsRefPtr<nsAsyncResolveRequest> ctx =
|
nsRefPtr<nsAsyncResolveRequest> ctx =
|
||||||
new nsAsyncResolveRequest(this, uri, flags, callback);
|
new nsAsyncResolveRequest(this, uri, flags, callback);
|
||||||
if (!ctx)
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
|
|
||||||
nsProtocolInfo info;
|
nsProtocolInfo info;
|
||||||
nsresult rv = GetProtocolInfo(uri, &info);
|
nsresult rv = GetProtocolInfo(uri, &info);
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
bool usePAC;
|
|
||||||
nsCOMPtr<nsIProxyInfo> pi;
|
nsCOMPtr<nsIProxyInfo> pi;
|
||||||
rv = Resolve_Internal(uri, info, flags, &usePAC, getter_AddRefs(pi));
|
bool usePACThread;
|
||||||
|
|
||||||
|
// SystemProxySettings and PAC files can block the main thread
|
||||||
|
// but if neither of them are in use, we can just do the work
|
||||||
|
// right here and directly invoke the callback
|
||||||
|
|
||||||
|
rv = Resolve_Internal(uri, info, flags, &usePACThread, getter_AddRefs(pi));
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
if (!usePAC || !mPACMan) {
|
if (!usePACThread || !mPACMan) {
|
||||||
|
// we can do it locally
|
||||||
ApplyFilters(uri, info, pi);
|
ApplyFilters(uri, info, pi);
|
||||||
|
|
||||||
ctx->SetResult(NS_OK, pi);
|
ctx->SetResult(NS_OK, pi);
|
||||||
return ctx->DispatchCallback();
|
return ctx->DispatchCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
// else kick off a PAC query
|
// else kick off a PAC thread query
|
||||||
rv = mPACMan->AsyncGetProxyForURI(uri, ctx);
|
|
||||||
|
rv = mPACMan->AsyncGetProxyForURI(uri, ctx, true);
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
*result = ctx;
|
*result = ctx;
|
||||||
NS_ADDREF(*result);
|
NS_ADDREF(*result);
|
||||||
@ -1241,42 +1451,76 @@ nsresult
|
|||||||
nsProtocolProxyService::Resolve_Internal(nsIURI *uri,
|
nsProtocolProxyService::Resolve_Internal(nsIURI *uri,
|
||||||
const nsProtocolInfo &info,
|
const nsProtocolInfo &info,
|
||||||
uint32_t flags,
|
uint32_t flags,
|
||||||
bool *usePAC,
|
bool *usePACThread,
|
||||||
nsIProxyInfo **result)
|
nsIProxyInfo **result)
|
||||||
{
|
{
|
||||||
NS_ENSURE_ARG_POINTER(uri);
|
NS_ENSURE_ARG_POINTER(uri);
|
||||||
|
nsresult rv = SetupPACThread();
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return rv;
|
||||||
|
|
||||||
*usePAC = false;
|
*usePACThread = false;
|
||||||
*result = nullptr;
|
*result = nullptr;
|
||||||
|
|
||||||
if (!(info.flags & nsIProtocolHandler::ALLOWS_PROXY))
|
if (!(info.flags & nsIProtocolHandler::ALLOWS_PROXY))
|
||||||
return NS_OK; // Can't proxy this (filters may not override)
|
return NS_OK; // Can't proxy this (filters may not override)
|
||||||
|
|
||||||
if (mSystemProxySettings) {
|
// See bug #586908.
|
||||||
|
// Avoid endless loop if |uri| is the current PAC-URI. Returning OK
|
||||||
|
// here means that we will not use a proxy for this connection.
|
||||||
|
if (mPACMan && mPACMan->IsPACURI(uri))
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
bool mainThreadOnly;
|
||||||
|
if (mSystemProxySettings &&
|
||||||
|
mProxyConfig == PROXYCONFIG_SYSTEM &&
|
||||||
|
NS_SUCCEEDED(mSystemProxySettings->GetMainThreadOnly(&mainThreadOnly)) &&
|
||||||
|
!mainThreadOnly) {
|
||||||
|
*usePACThread = true;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mSystemProxySettings && mProxyConfig == PROXYCONFIG_SYSTEM) {
|
||||||
|
// If the system proxy setting implementation is not threadsafe (e.g
|
||||||
|
// linux gconf), we'll do it inline here. Such implementations promise
|
||||||
|
// not to block
|
||||||
|
|
||||||
nsAutoCString PACURI;
|
nsAutoCString PACURI;
|
||||||
if (NS_FAILED(mSystemProxySettings->GetPACURI(PACURI)) ||
|
nsAutoCString pacString;
|
||||||
PACURI.IsEmpty()) {
|
|
||||||
nsAutoCString proxy;
|
if (NS_SUCCEEDED(mSystemProxySettings->GetPACURI(PACURI)) &&
|
||||||
nsresult rv = mSystemProxySettings->GetProxyForURI(uri, proxy);
|
!PACURI.IsEmpty()) {
|
||||||
if (NS_SUCCEEDED(rv)) {
|
// There is a PAC URI configured. If it is unchanged, then
|
||||||
ProcessPACString(proxy, flags, result);
|
// just execute the PAC thread. If it is changed then load
|
||||||
|
// the new value
|
||||||
|
|
||||||
|
if (mPACMan && mPACMan->IsPACURI(PACURI)) {
|
||||||
|
// unchanged
|
||||||
|
*usePACThread = true;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
// no proxy, stop search
|
|
||||||
|
ConfigureFromPAC(PACURI, false);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// See bug #586908.
|
nsAutoCString spec;
|
||||||
// Avoid endless loop if |uri| is the current PAC-URI. Returning OK
|
nsAutoCString host;
|
||||||
// here means that we will not use a proxy for this connection.
|
nsAutoCString scheme;
|
||||||
if (mPACMan && mPACMan->IsPACURI(uri))
|
int32_t port = -1;
|
||||||
return NS_OK;
|
|
||||||
|
|
||||||
// Switch to new PAC file if that setting has changed. If the setting
|
uri->GetAsciiSpec(spec);
|
||||||
// hasn't changed, ConfigureFromPAC will exit early.
|
uri->GetAsciiHost(host);
|
||||||
nsresult rv = ConfigureFromPAC(PACURI, false);
|
uri->GetScheme(scheme);
|
||||||
if (NS_FAILED(rv))
|
uri->GetPort(&port);
|
||||||
return rv;
|
|
||||||
|
// now try the system proxy settings for this particular url
|
||||||
|
if (NS_SUCCEEDED(mSystemProxySettings->
|
||||||
|
GetProxyForURI(spec, scheme, host, port,
|
||||||
|
pacString))) {
|
||||||
|
ProcessPACString(pacString, 0, result);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if proxies are enabled and this host:port combo is supposed to use a
|
// if proxies are enabled and this host:port combo is supposed to use a
|
||||||
@ -1287,10 +1531,9 @@ nsProtocolProxyService::Resolve_Internal(nsIURI *uri,
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
// Proxy auto config magic...
|
// Proxy auto config magic...
|
||||||
if (mProxyConfig == PROXYCONFIG_PAC || mProxyConfig == PROXYCONFIG_WPAD ||
|
if (mProxyConfig == PROXYCONFIG_PAC || mProxyConfig == PROXYCONFIG_WPAD) {
|
||||||
mProxyConfig == PROXYCONFIG_SYSTEM) {
|
|
||||||
// Do not query PAC now.
|
// Do not query PAC now.
|
||||||
*usePAC = true;
|
*usePACThread = true;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1304,7 +1547,7 @@ nsProtocolProxyService::Resolve_Internal(nsIURI *uri,
|
|||||||
if ((flags & RESOLVE_PREFER_SOCKS_PROXY) &&
|
if ((flags & RESOLVE_PREFER_SOCKS_PROXY) &&
|
||||||
!mSOCKSProxyHost.IsEmpty() && mSOCKSProxyPort > 0) {
|
!mSOCKSProxyHost.IsEmpty() && mSOCKSProxyPort > 0) {
|
||||||
host = &mSOCKSProxyHost;
|
host = &mSOCKSProxyHost;
|
||||||
if (mSOCKSProxyVersion == 4)
|
if (mSOCKSProxyVersion == 4)
|
||||||
type = kProxyType_SOCKS4;
|
type = kProxyType_SOCKS4;
|
||||||
else
|
else
|
||||||
type = kProxyType_SOCKS;
|
type = kProxyType_SOCKS;
|
||||||
@ -1341,7 +1584,7 @@ nsProtocolProxyService::Resolve_Internal(nsIURI *uri,
|
|||||||
}
|
}
|
||||||
else if (!mSOCKSProxyHost.IsEmpty() && mSOCKSProxyPort > 0) {
|
else if (!mSOCKSProxyHost.IsEmpty() && mSOCKSProxyPort > 0) {
|
||||||
host = &mSOCKSProxyHost;
|
host = &mSOCKSProxyHost;
|
||||||
if (mSOCKSProxyVersion == 4)
|
if (mSOCKSProxyVersion == 4)
|
||||||
type = kProxyType_SOCKS4;
|
type = kProxyType_SOCKS4;
|
||||||
else
|
else
|
||||||
type = kProxyType_SOCKS;
|
type = kProxyType_SOCKS;
|
||||||
@ -1351,9 +1594,9 @@ nsProtocolProxyService::Resolve_Internal(nsIURI *uri,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type) {
|
if (type) {
|
||||||
nsresult rv = NewProxyInfo_Internal(type, *host, port, proxyFlags,
|
rv = NewProxyInfo_Internal(type, *host, port, proxyFlags,
|
||||||
PR_UINT32_MAX, nullptr, flags,
|
PR_UINT32_MAX, nullptr, flags,
|
||||||
result);
|
result);
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -1411,7 +1654,7 @@ nsProtocolProxyService::PruneProxyInfo(const nsProtocolInfo &info,
|
|||||||
|
|
||||||
// Start by removing all disallowed proxies if required:
|
// Start by removing all disallowed proxies if required:
|
||||||
if (!(info.flags & nsIProtocolHandler::ALLOWS_PROXY_HTTP)) {
|
if (!(info.flags & nsIProtocolHandler::ALLOWS_PROXY_HTTP)) {
|
||||||
nsProxyInfo *last = nullptr, *iter = head;
|
nsProxyInfo *last = nullptr, *iter = head;
|
||||||
while (iter) {
|
while (iter) {
|
||||||
if (iter->Type() == kProxyType_HTTP) {
|
if (iter->Type() == kProxyType_HTTP) {
|
||||||
// reject!
|
// reject!
|
||||||
@ -1435,7 +1678,7 @@ nsProtocolProxyService::PruneProxyInfo(const nsProtocolInfo &info,
|
|||||||
// Now, scan to see if all remaining proxies are disabled. If so, then
|
// Now, scan to see if all remaining proxies are disabled. If so, then
|
||||||
// we'll just bail and return them all. Otherwise, we'll go and prune the
|
// we'll just bail and return them all. Otherwise, we'll go and prune the
|
||||||
// disabled ones.
|
// disabled ones.
|
||||||
|
|
||||||
bool allDisabled = true;
|
bool allDisabled = true;
|
||||||
|
|
||||||
nsProxyInfo *iter;
|
nsProxyInfo *iter;
|
||||||
@ -1450,7 +1693,7 @@ nsProtocolProxyService::PruneProxyInfo(const nsProtocolInfo &info,
|
|||||||
LOG(("All proxies are disabled, so trying all again"));
|
LOG(("All proxies are disabled, so trying all again"));
|
||||||
else {
|
else {
|
||||||
// remove any disabled proxies.
|
// remove any disabled proxies.
|
||||||
nsProxyInfo *last = nullptr;
|
nsProxyInfo *last = nullptr;
|
||||||
for (iter = head; iter; ) {
|
for (iter = head; iter; ) {
|
||||||
if (IsProxyDisabled(iter)) {
|
if (IsProxyDisabled(iter)) {
|
||||||
// reject!
|
// reject!
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#include "nsIPrefBranch.h"
|
#include "nsIPrefBranch.h"
|
||||||
#include "nsIProtocolProxyService2.h"
|
#include "nsIProtocolProxyService2.h"
|
||||||
#include "nsIProtocolProxyFilter.h"
|
#include "nsIProtocolProxyFilter.h"
|
||||||
#include "nsIProxyAutoConfig.h"
|
|
||||||
#include "nsISystemProxySettings.h"
|
#include "nsISystemProxySettings.h"
|
||||||
#include "nsIProxyInfo.h"
|
#include "nsIProxyInfo.h"
|
||||||
#include "nsIObserver.h"
|
#include "nsIObserver.h"
|
||||||
@ -272,6 +271,10 @@ protected:
|
|||||||
*/
|
*/
|
||||||
NS_HIDDEN_(bool) CanUseProxy(nsIURI *uri, int32_t defaultPort);
|
NS_HIDDEN_(bool) CanUseProxy(nsIURI *uri, int32_t defaultPort);
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsresult SetupPACThread();
|
||||||
|
nsresult ResetPACThread();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// The Sun Forte compiler and others implement older versions of the
|
// The Sun Forte compiler and others implement older versions of the
|
||||||
// C++ standard's rules on access and nested classes. These structs
|
// C++ standard's rules on access and nested classes. These structs
|
||||||
|
@ -1,314 +0,0 @@
|
|||||||
/* -*- Mode: Java; tab-width: 4; c-basic-offset: 4; -*- */
|
|
||||||
/* vim:set ts=4 sw=4 sts=4 et: */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
/*
|
|
||||||
Script for Proxy Auto Config in the new world order.
|
|
||||||
- Gagan Saksena 04/24/00
|
|
||||||
*/
|
|
||||||
|
|
||||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
||||||
|
|
||||||
const kDNS_CONTRACTID = "@mozilla.org/network/dns-service;1";
|
|
||||||
|
|
||||||
const nsISupports = Components.interfaces.nsISupports;
|
|
||||||
const nsIProxyAutoConfig = Components.interfaces.nsIProxyAutoConfig;
|
|
||||||
const nsIDNSService = Components.interfaces.nsIDNSService;
|
|
||||||
|
|
||||||
var dns;
|
|
||||||
|
|
||||||
// implementor of nsIProxyAutoConfig
|
|
||||||
function nsProxyAutoConfig() {
|
|
||||||
dns = Components.classes[kDNS_CONTRACTID].getService(nsIDNSService);
|
|
||||||
};
|
|
||||||
|
|
||||||
nsProxyAutoConfig.prototype = {
|
|
||||||
classID: Components.ID("63ac8c66-1dd2-11b2-b070-84d00d3eaece"),
|
|
||||||
|
|
||||||
// sandbox in which we eval loaded autoconfig js file
|
|
||||||
_sandBox: null,
|
|
||||||
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([nsIProxyAutoConfig]),
|
|
||||||
|
|
||||||
init: function(pacURI, pacText) {
|
|
||||||
// remove PAC configuration if requested
|
|
||||||
if (pacURI == "" || pacText == "") {
|
|
||||||
this._sandBox = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// allocate a fresh Sandbox to clear global scope for new PAC script
|
|
||||||
this._sandBox = new Components.utils.Sandbox(pacURI,
|
|
||||||
{sandboxName: 'nsProxyAutoConfig'});
|
|
||||||
Components.utils.evalInSandbox(pacUtils, this._sandBox);
|
|
||||||
|
|
||||||
// add predefined functions to pac
|
|
||||||
this._sandBox.importFunction(myIpAddress);
|
|
||||||
this._sandBox.importFunction(dnsResolve);
|
|
||||||
this._sandBox.importFunction(proxyAlert, "alert");
|
|
||||||
|
|
||||||
// evaluate loaded js file
|
|
||||||
Components.utils.evalInSandbox(pacText, this._sandBox);
|
|
||||||
},
|
|
||||||
|
|
||||||
getProxyForURI: function(testURI, testHost) {
|
|
||||||
if (!("FindProxyForURL" in this._sandBox))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
// Call the original function
|
|
||||||
try {
|
|
||||||
var rval = this._sandBox.FindProxyForURL(testURI, testHost);
|
|
||||||
} catch (e) {
|
|
||||||
throw XPCSafeJSObjectWrapper(e);
|
|
||||||
}
|
|
||||||
return rval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function proxyAlert(msg) {
|
|
||||||
try {
|
|
||||||
// It would appear that the console service is threadsafe.
|
|
||||||
var cns = Components.classes["@mozilla.org/consoleservice;1"]
|
|
||||||
.getService(Components.interfaces.nsIConsoleService);
|
|
||||||
cns.logStringMessage("PAC-alert: "+msg);
|
|
||||||
} catch (e) {
|
|
||||||
dump("PAC: proxyAlert ERROR: "+e+"\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// wrapper for getting local IP address called by PAC file
|
|
||||||
function myIpAddress() {
|
|
||||||
try {
|
|
||||||
return dns.resolve(dns.myHostName, 0).getNextAddrAsString();
|
|
||||||
} catch (e) {
|
|
||||||
return '127.0.0.1';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// wrapper for resolving hostnames called by PAC file
|
|
||||||
function dnsResolve(host) {
|
|
||||||
try {
|
|
||||||
return dns.resolve(host, 0).getNextAddrAsString();
|
|
||||||
} catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NSGetFactory = XPCOMUtils.generateNSGetFactory([nsProxyAutoConfig]);
|
|
||||||
|
|
||||||
var pacUtils =
|
|
||||||
"function dnsDomainIs(host, domain) {\n" +
|
|
||||||
" return (host.length >= domain.length &&\n" +
|
|
||||||
" host.substring(host.length - domain.length) == domain);\n" +
|
|
||||||
"}\n" +
|
|
||||||
|
|
||||||
"function dnsDomainLevels(host) {\n" +
|
|
||||||
" return host.split('.').length-1;\n" +
|
|
||||||
"}\n" +
|
|
||||||
|
|
||||||
"function convert_addr(ipchars) {\n"+
|
|
||||||
" var bytes = ipchars.split('.');\n"+
|
|
||||||
" var result = ((bytes[0] & 0xff) << 24) |\n"+
|
|
||||||
" ((bytes[1] & 0xff) << 16) |\n"+
|
|
||||||
" ((bytes[2] & 0xff) << 8) |\n"+
|
|
||||||
" (bytes[3] & 0xff);\n"+
|
|
||||||
" return result;\n"+
|
|
||||||
"}\n"+
|
|
||||||
|
|
||||||
"function isInNet(ipaddr, pattern, maskstr) {\n"+
|
|
||||||
" var test = /^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$/.exec(ipaddr);\n"+
|
|
||||||
" if (test == null) {\n"+
|
|
||||||
" ipaddr = dnsResolve(ipaddr);\n"+
|
|
||||||
" if (ipaddr == null)\n"+
|
|
||||||
" return false;\n"+
|
|
||||||
" } else if (test[1] > 255 || test[2] > 255 || \n"+
|
|
||||||
" test[3] > 255 || test[4] > 255) {\n"+
|
|
||||||
" return false; // not an IP address\n"+
|
|
||||||
" }\n"+
|
|
||||||
" var host = convert_addr(ipaddr);\n"+
|
|
||||||
" var pat = convert_addr(pattern);\n"+
|
|
||||||
" var mask = convert_addr(maskstr);\n"+
|
|
||||||
" return ((host & mask) == (pat & mask));\n"+
|
|
||||||
" \n"+
|
|
||||||
"}\n"+
|
|
||||||
|
|
||||||
"function isPlainHostName(host) {\n" +
|
|
||||||
" return (host.search('\\\\.') == -1);\n" +
|
|
||||||
"}\n" +
|
|
||||||
|
|
||||||
"function isResolvable(host) {\n" +
|
|
||||||
" var ip = dnsResolve(host);\n" +
|
|
||||||
" return (ip != null);\n" +
|
|
||||||
"}\n" +
|
|
||||||
|
|
||||||
"function localHostOrDomainIs(host, hostdom) {\n" +
|
|
||||||
" return (host == hostdom) ||\n" +
|
|
||||||
" (hostdom.lastIndexOf(host + '.', 0) == 0);\n" +
|
|
||||||
"}\n" +
|
|
||||||
|
|
||||||
"function shExpMatch(url, pattern) {\n" +
|
|
||||||
" pattern = pattern.replace(/\\./g, '\\\\.');\n" +
|
|
||||||
" pattern = pattern.replace(/\\*/g, '.*');\n" +
|
|
||||||
" pattern = pattern.replace(/\\?/g, '.');\n" +
|
|
||||||
" var newRe = new RegExp('^'+pattern+'$');\n" +
|
|
||||||
" return newRe.test(url);\n" +
|
|
||||||
"}\n" +
|
|
||||||
|
|
||||||
"var wdays = {SUN: 0, MON: 1, TUE: 2, WED: 3, THU: 4, FRI: 5, SAT: 6};\n" +
|
|
||||||
|
|
||||||
"var months = {JAN: 0, FEB: 1, MAR: 2, APR: 3, MAY: 4, JUN: 5, JUL: 6, AUG: 7, SEP: 8, OCT: 9, NOV: 10, DEC: 11};\n"+
|
|
||||||
|
|
||||||
"function weekdayRange() {\n" +
|
|
||||||
" function getDay(weekday) {\n" +
|
|
||||||
" if (weekday in wdays) {\n" +
|
|
||||||
" return wdays[weekday];\n" +
|
|
||||||
" }\n" +
|
|
||||||
" return -1;\n" +
|
|
||||||
" }\n" +
|
|
||||||
" var date = new Date();\n" +
|
|
||||||
" var argc = arguments.length;\n" +
|
|
||||||
" var wday;\n" +
|
|
||||||
" if (argc < 1)\n" +
|
|
||||||
" return false;\n" +
|
|
||||||
" if (arguments[argc - 1] == 'GMT') {\n" +
|
|
||||||
" argc--;\n" +
|
|
||||||
" wday = date.getUTCDay();\n" +
|
|
||||||
" } else {\n" +
|
|
||||||
" wday = date.getDay();\n" +
|
|
||||||
" }\n" +
|
|
||||||
" var wd1 = getDay(arguments[0]);\n" +
|
|
||||||
" var wd2 = (argc == 2) ? getDay(arguments[1]) : wd1;\n" +
|
|
||||||
" return (wd1 == -1 || wd2 == -1) ? false\n" +
|
|
||||||
" : (wd1 <= wday && wday <= wd2);\n" +
|
|
||||||
"}\n" +
|
|
||||||
|
|
||||||
"function dateRange() {\n" +
|
|
||||||
" function getMonth(name) {\n" +
|
|
||||||
" if (name in months) {\n" +
|
|
||||||
" return months[name];\n" +
|
|
||||||
" }\n" +
|
|
||||||
" return -1;\n" +
|
|
||||||
" }\n" +
|
|
||||||
" var date = new Date();\n" +
|
|
||||||
" var argc = arguments.length;\n" +
|
|
||||||
" if (argc < 1) {\n" +
|
|
||||||
" return false;\n" +
|
|
||||||
" }\n" +
|
|
||||||
" var isGMT = (arguments[argc - 1] == 'GMT');\n" +
|
|
||||||
"\n" +
|
|
||||||
" if (isGMT) {\n" +
|
|
||||||
" argc--;\n" +
|
|
||||||
" }\n" +
|
|
||||||
" // function will work even without explict handling of this case\n" +
|
|
||||||
" if (argc == 1) {\n" +
|
|
||||||
" var tmp = parseInt(arguments[0]);\n" +
|
|
||||||
" if (isNaN(tmp)) {\n" +
|
|
||||||
" return ((isGMT ? date.getUTCMonth() : date.getMonth()) ==\n" +
|
|
||||||
"getMonth(arguments[0]));\n" +
|
|
||||||
" } else if (tmp < 32) {\n" +
|
|
||||||
" return ((isGMT ? date.getUTCDate() : date.getDate()) == tmp);\n" +
|
|
||||||
" } else { \n" +
|
|
||||||
" return ((isGMT ? date.getUTCFullYear() : date.getFullYear()) ==\n" +
|
|
||||||
"tmp);\n" +
|
|
||||||
" }\n" +
|
|
||||||
" }\n" +
|
|
||||||
" var year = date.getFullYear();\n" +
|
|
||||||
" var date1, date2;\n" +
|
|
||||||
" date1 = new Date(year, 0, 1, 0, 0, 0);\n" +
|
|
||||||
" date2 = new Date(year, 11, 31, 23, 59, 59);\n" +
|
|
||||||
" var adjustMonth = false;\n" +
|
|
||||||
" for (var i = 0; i < (argc >> 1); i++) {\n" +
|
|
||||||
" var tmp = parseInt(arguments[i]);\n" +
|
|
||||||
" if (isNaN(tmp)) {\n" +
|
|
||||||
" var mon = getMonth(arguments[i]);\n" +
|
|
||||||
" date1.setMonth(mon);\n" +
|
|
||||||
" } else if (tmp < 32) {\n" +
|
|
||||||
" adjustMonth = (argc <= 2);\n" +
|
|
||||||
" date1.setDate(tmp);\n" +
|
|
||||||
" } else {\n" +
|
|
||||||
" date1.setFullYear(tmp);\n" +
|
|
||||||
" }\n" +
|
|
||||||
" }\n" +
|
|
||||||
" for (var i = (argc >> 1); i < argc; i++) {\n" +
|
|
||||||
" var tmp = parseInt(arguments[i]);\n" +
|
|
||||||
" if (isNaN(tmp)) {\n" +
|
|
||||||
" var mon = getMonth(arguments[i]);\n" +
|
|
||||||
" date2.setMonth(mon);\n" +
|
|
||||||
" } else if (tmp < 32) {\n" +
|
|
||||||
" date2.setDate(tmp);\n" +
|
|
||||||
" } else {\n" +
|
|
||||||
" date2.setFullYear(tmp);\n" +
|
|
||||||
" }\n" +
|
|
||||||
" }\n" +
|
|
||||||
" if (adjustMonth) {\n" +
|
|
||||||
" date1.setMonth(date.getMonth());\n" +
|
|
||||||
" date2.setMonth(date.getMonth());\n" +
|
|
||||||
" }\n" +
|
|
||||||
" if (isGMT) {\n" +
|
|
||||||
" var tmp = date;\n" +
|
|
||||||
" tmp.setFullYear(date.getUTCFullYear());\n" +
|
|
||||||
" tmp.setMonth(date.getUTCMonth());\n" +
|
|
||||||
" tmp.setDate(date.getUTCDate());\n" +
|
|
||||||
" tmp.setHours(date.getUTCHours());\n" +
|
|
||||||
" tmp.setMinutes(date.getUTCMinutes());\n" +
|
|
||||||
" tmp.setSeconds(date.getUTCSeconds());\n" +
|
|
||||||
" date = tmp;\n" +
|
|
||||||
" }\n" +
|
|
||||||
" return ((date1 <= date) && (date <= date2));\n" +
|
|
||||||
"}\n" +
|
|
||||||
|
|
||||||
"function timeRange() {\n" +
|
|
||||||
" var argc = arguments.length;\n" +
|
|
||||||
" var date = new Date();\n" +
|
|
||||||
" var isGMT= false;\n"+
|
|
||||||
"\n" +
|
|
||||||
" if (argc < 1) {\n" +
|
|
||||||
" return false;\n" +
|
|
||||||
" }\n" +
|
|
||||||
" if (arguments[argc - 1] == 'GMT') {\n" +
|
|
||||||
" isGMT = true;\n" +
|
|
||||||
" argc--;\n" +
|
|
||||||
" }\n" +
|
|
||||||
"\n" +
|
|
||||||
" var hour = isGMT ? date.getUTCHours() : date.getHours();\n" +
|
|
||||||
" var date1, date2;\n" +
|
|
||||||
" date1 = new Date();\n" +
|
|
||||||
" date2 = new Date();\n" +
|
|
||||||
"\n" +
|
|
||||||
" if (argc == 1) {\n" +
|
|
||||||
" return (hour == arguments[0]);\n" +
|
|
||||||
" } else if (argc == 2) {\n" +
|
|
||||||
" return ((arguments[0] <= hour) && (hour <= arguments[1]));\n" +
|
|
||||||
" } else {\n" +
|
|
||||||
" switch (argc) {\n" +
|
|
||||||
" case 6:\n" +
|
|
||||||
" date1.setSeconds(arguments[2]);\n" +
|
|
||||||
" date2.setSeconds(arguments[5]);\n" +
|
|
||||||
" case 4:\n" +
|
|
||||||
" var middle = argc >> 1;\n" +
|
|
||||||
" date1.setHours(arguments[0]);\n" +
|
|
||||||
" date1.setMinutes(arguments[1]);\n" +
|
|
||||||
" date2.setHours(arguments[middle]);\n" +
|
|
||||||
" date2.setMinutes(arguments[middle + 1]);\n" +
|
|
||||||
" if (middle == 2) {\n" +
|
|
||||||
" date2.setSeconds(59);\n" +
|
|
||||||
" }\n" +
|
|
||||||
" break;\n" +
|
|
||||||
" default:\n" +
|
|
||||||
" throw 'timeRange: bad number of arguments'\n" +
|
|
||||||
" }\n" +
|
|
||||||
" }\n" +
|
|
||||||
"\n" +
|
|
||||||
" if (isGMT) {\n" +
|
|
||||||
" date.setFullYear(date.getUTCFullYear());\n" +
|
|
||||||
" date.setMonth(date.getUTCMonth());\n" +
|
|
||||||
" date.setDate(date.getUTCDate());\n" +
|
|
||||||
" date.setHours(date.getUTCHours());\n" +
|
|
||||||
" date.setMinutes(date.getUTCMinutes());\n" +
|
|
||||||
" date.setSeconds(date.getUTCSeconds());\n" +
|
|
||||||
" }\n" +
|
|
||||||
" return ((date1 <= date) && (date <= date2));\n" +
|
|
||||||
"}\n"
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
|||||||
component {63ac8c66-1dd2-11b2-b070-84d00d3eaece} nsProxyAutoConfig.js
|
|
||||||
contract @mozilla.org/network/proxy-auto-config;1 {63ac8c66-1dd2-11b2-b070-84d00d3eaece}
|
|
@ -55,6 +55,11 @@ public:
|
|||||||
return mProxyInfo;
|
return mProxyInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetProxyInfo(nsIProxyInfo *pi)
|
||||||
|
{
|
||||||
|
mProxyInfo = pi;
|
||||||
|
}
|
||||||
|
|
||||||
// Were we asked to resume a download?
|
// Were we asked to resume a download?
|
||||||
bool ResumeRequested() { return mResumeRequested; }
|
bool ResumeRequested() { return mResumeRequested; }
|
||||||
|
|
||||||
|
@ -33,6 +33,8 @@
|
|||||||
#include "nsIStringBundle.h"
|
#include "nsIStringBundle.h"
|
||||||
#include "nsAuthInformationHolder.h"
|
#include "nsAuthInformationHolder.h"
|
||||||
#include "nsICharsetConverterManager.h"
|
#include "nsICharsetConverterManager.h"
|
||||||
|
#include "nsIProtocolProxyService.h"
|
||||||
|
#include "nsICancelable.h"
|
||||||
|
|
||||||
#if defined(PR_LOGGING)
|
#if defined(PR_LOGGING)
|
||||||
extern PRLogModuleInfo* gFTPLog;
|
extern PRLogModuleInfo* gFTPLog;
|
||||||
@ -50,12 +52,13 @@ removeParamsFromPath(nsCString& path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS_INHERITED4(nsFtpState,
|
NS_IMPL_ISUPPORTS_INHERITED5(nsFtpState,
|
||||||
nsBaseContentStream,
|
nsBaseContentStream,
|
||||||
nsIInputStreamCallback,
|
nsIInputStreamCallback,
|
||||||
nsITransportEventSink,
|
nsITransportEventSink,
|
||||||
nsICacheListener,
|
nsICacheListener,
|
||||||
nsIRequestObserver)
|
nsIRequestObserver,
|
||||||
|
nsIProtocolProxyCallback)
|
||||||
|
|
||||||
nsFtpState::nsFtpState()
|
nsFtpState::nsFtpState()
|
||||||
: nsBaseContentStream(true)
|
: nsBaseContentStream(true)
|
||||||
@ -78,6 +81,7 @@ nsFtpState::nsFtpState()
|
|||||||
, mAddressChecked(false)
|
, mAddressChecked(false)
|
||||||
, mServerIsIPv6(false)
|
, mServerIsIPv6(false)
|
||||||
, mControlStatus(NS_OK)
|
, mControlStatus(NS_OK)
|
||||||
|
, mDeferredCallbackPending(false)
|
||||||
{
|
{
|
||||||
LOG_ALWAYS(("FTP:(%x) nsFtpState created", this));
|
LOG_ALWAYS(("FTP:(%x) nsFtpState created", this));
|
||||||
|
|
||||||
@ -89,6 +93,9 @@ nsFtpState::~nsFtpState()
|
|||||||
{
|
{
|
||||||
LOG_ALWAYS(("FTP:(%x) nsFtpState destroyed", this));
|
LOG_ALWAYS(("FTP:(%x) nsFtpState destroyed", this));
|
||||||
|
|
||||||
|
if (mProxyRequest)
|
||||||
|
mProxyRequest->Cancel(NS_ERROR_FAILURE);
|
||||||
|
|
||||||
// release reference to handler
|
// release reference to handler
|
||||||
nsFtpProtocolHandler *handler = gFtpHandler;
|
nsFtpProtocolHandler *handler = gFtpHandler;
|
||||||
NS_RELEASE(handler);
|
NS_RELEASE(handler);
|
||||||
@ -1759,6 +1766,19 @@ nsFtpState::Init(nsFtpChannel *channel)
|
|||||||
if (port > 0)
|
if (port > 0)
|
||||||
mPort = port;
|
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
|
||||||
|
uint32_t proxyConfigType;
|
||||||
|
nsCOMPtr<nsIProtocolProxyService> pps =
|
||||||
|
do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID);
|
||||||
|
|
||||||
|
if (pps && !mChannel->ProxyInfo() &&
|
||||||
|
NS_SUCCEEDED(pps->GetProxyConfigType(&proxyConfigType)) &&
|
||||||
|
proxyConfigType != nsIProtocolProxyService::PROXYCONFIG_DIRECT) {
|
||||||
|
pps->AsyncResolve(mChannel->URI(), 0, this,
|
||||||
|
getter_AddRefs(mProxyRequest));
|
||||||
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2155,6 +2175,67 @@ nsFtpState::CloseWithStatus(nsresult status)
|
|||||||
return nsBaseContentStream::CloseWithStatus(status);
|
return nsBaseContentStream::CloseWithStatus(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static nsresult
|
||||||
|
CreateHTTPProxiedChannel(nsIURI *uri, nsIProxyInfo *pi, nsIChannel **newChannel)
|
||||||
|
{
|
||||||
|
nsresult rv;
|
||||||
|
nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIProtocolHandler> handler;
|
||||||
|
rv = ioService->GetProtocolHandler("http", getter_AddRefs(handler));
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIProxiedProtocolHandler> pph = do_QueryInterface(handler, &rv);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
return pph->NewProxiedChannel(uri, pi, 0, nullptr, newChannel);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsFtpState::OnProxyAvailable(nsICancelable *request, nsIURI *uri,
|
||||||
|
nsIProxyInfo *pi, nsresult status)
|
||||||
|
{
|
||||||
|
mProxyRequest = nullptr;
|
||||||
|
|
||||||
|
// failed status code just implies DIRECT processing
|
||||||
|
|
||||||
|
if (NS_SUCCEEDED(status)) {
|
||||||
|
nsAutoCString type;
|
||||||
|
if (pi && NS_SUCCEEDED(pi->GetType(type)) && type.EqualsLiteral("http")) {
|
||||||
|
// Proxy the FTP url via HTTP
|
||||||
|
// This would have been easier to just return a HTTP channel directly
|
||||||
|
// from nsIIOService::NewChannelFromURI(), but the proxy type cannot
|
||||||
|
// be reliabliy determined synchronously without jank due to pac, etc..
|
||||||
|
LOG(("FTP:(%p) Configured to use a HTTP proxy channel\n", this));
|
||||||
|
|
||||||
|
nsCOMPtr<nsIChannel> newChannel;
|
||||||
|
if (NS_SUCCEEDED(CreateHTTPProxiedChannel(uri, pi,
|
||||||
|
getter_AddRefs(newChannel))) &&
|
||||||
|
NS_SUCCEEDED(mChannel->Redirect(newChannel,
|
||||||
|
nsIChannelEventSink::REDIRECT_INTERNAL,
|
||||||
|
true))) {
|
||||||
|
LOG(("FTP:(%p) Redirected to use a HTTP proxy channel\n", this));
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pi) {
|
||||||
|
// Proxy using the FTP protocol routed through a socks proxy
|
||||||
|
LOG(("FTP:(%p) Configured to use a SOCKS proxy channel\n", this));
|
||||||
|
mChannel->SetProxyInfo(pi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mDeferredCallbackPending) {
|
||||||
|
mDeferredCallbackPending = false;
|
||||||
|
OnCallbackPending();
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsFtpState::OnCallbackPending()
|
nsFtpState::OnCallbackPending()
|
||||||
{
|
{
|
||||||
@ -2163,6 +2244,11 @@ nsFtpState::OnCallbackPending()
|
|||||||
// connect to the server.
|
// connect to the server.
|
||||||
|
|
||||||
if (mState == FTP_INIT) {
|
if (mState == FTP_INIT) {
|
||||||
|
if (mProxyRequest) {
|
||||||
|
mDeferredCallbackPending = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (CheckCache()) {
|
if (CheckCache()) {
|
||||||
mState = FTP_WAIT_CACHE;
|
mState = FTP_WAIT_CACHE;
|
||||||
return;
|
return;
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
#include "nsICacheEntryDescriptor.h"
|
#include "nsICacheEntryDescriptor.h"
|
||||||
#include "nsICacheListener.h"
|
#include "nsICacheListener.h"
|
||||||
|
#include "nsIProtocolProxyCallback.h"
|
||||||
|
|
||||||
// ftp server types
|
// ftp server types
|
||||||
#define FTP_GENERIC_TYPE 0
|
#define FTP_GENERIC_TYPE 0
|
||||||
@ -77,6 +78,7 @@ typedef enum _FTP_STATE {
|
|||||||
typedef enum _FTP_ACTION {GET, PUT} FTP_ACTION;
|
typedef enum _FTP_ACTION {GET, PUT} FTP_ACTION;
|
||||||
|
|
||||||
class nsFtpChannel;
|
class nsFtpChannel;
|
||||||
|
class nsICancelable;
|
||||||
|
|
||||||
// The nsFtpState object is the content stream for the channel. It implements
|
// The nsFtpState object is the content stream for the channel. It implements
|
||||||
// nsIInputStreamCallback, so it can read data from the control connection. It
|
// nsIInputStreamCallback, so it can read data from the control connection. It
|
||||||
@ -88,13 +90,16 @@ class nsFtpState : public nsBaseContentStream,
|
|||||||
public nsITransportEventSink,
|
public nsITransportEventSink,
|
||||||
public nsICacheListener,
|
public nsICacheListener,
|
||||||
public nsIRequestObserver,
|
public nsIRequestObserver,
|
||||||
public nsFtpControlConnectionListener {
|
public nsFtpControlConnectionListener,
|
||||||
|
public nsIProtocolProxyCallback
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
NS_DECL_NSIINPUTSTREAMCALLBACK
|
NS_DECL_NSIINPUTSTREAMCALLBACK
|
||||||
NS_DECL_NSITRANSPORTEVENTSINK
|
NS_DECL_NSITRANSPORTEVENTSINK
|
||||||
NS_DECL_NSICACHELISTENER
|
NS_DECL_NSICACHELISTENER
|
||||||
NS_DECL_NSIREQUESTOBSERVER
|
NS_DECL_NSIREQUESTOBSERVER
|
||||||
|
NS_DECL_NSIPROTOCOLPROXYCALLBACK
|
||||||
|
|
||||||
// Override input stream methods:
|
// Override input stream methods:
|
||||||
NS_IMETHOD CloseWithStatus(nsresult status);
|
NS_IMETHOD CloseWithStatus(nsresult status);
|
||||||
@ -263,6 +268,9 @@ private:
|
|||||||
bool mDoomCache;
|
bool mDoomCache;
|
||||||
|
|
||||||
nsCString mSuppliedEntityID;
|
nsCString mSuppliedEntityID;
|
||||||
|
|
||||||
|
nsCOMPtr<nsICancelable> mProxyRequest;
|
||||||
|
bool mDeferredCallbackPending;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //__nsFtpState__h_
|
#endif //__nsFtpState__h_
|
||||||
|
@ -211,11 +211,13 @@ nsFtpProtocolHandler::NewURI(const nsACString &aSpec,
|
|||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsFtpProtocolHandler::NewChannel(nsIURI* url, nsIChannel* *result)
|
nsFtpProtocolHandler::NewChannel(nsIURI* url, nsIChannel* *result)
|
||||||
{
|
{
|
||||||
return NewProxiedChannel(url, nullptr, result);
|
return NewProxiedChannel(url, nullptr, 0, nullptr, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsFtpProtocolHandler::NewProxiedChannel(nsIURI* uri, nsIProxyInfo* proxyInfo,
|
nsFtpProtocolHandler::NewProxiedChannel(nsIURI* uri, nsIProxyInfo* proxyInfo,
|
||||||
|
uint32_t proxyResolveFlags,
|
||||||
|
nsIURI *proxyURI,
|
||||||
nsIChannel* *result)
|
nsIChannel* *result)
|
||||||
{
|
{
|
||||||
NS_ENSURE_ARG_POINTER(uri);
|
NS_ENSURE_ARG_POINTER(uri);
|
||||||
|
@ -50,6 +50,7 @@ HttpBaseChannel::HttpBaseChannel()
|
|||||||
, mAllowSpdy(true)
|
, mAllowSpdy(true)
|
||||||
, mPrivateBrowsing(false)
|
, mPrivateBrowsing(false)
|
||||||
, mSuspendCount(0)
|
, mSuspendCount(0)
|
||||||
|
, mProxyResolveFlags(0)
|
||||||
{
|
{
|
||||||
LOG(("Creating HttpBaseChannel @%x\n", this));
|
LOG(("Creating HttpBaseChannel @%x\n", this));
|
||||||
|
|
||||||
@ -74,7 +75,9 @@ HttpBaseChannel::~HttpBaseChannel()
|
|||||||
nsresult
|
nsresult
|
||||||
HttpBaseChannel::Init(nsIURI *aURI,
|
HttpBaseChannel::Init(nsIURI *aURI,
|
||||||
uint8_t aCaps,
|
uint8_t aCaps,
|
||||||
nsProxyInfo *aProxyInfo)
|
nsProxyInfo *aProxyInfo,
|
||||||
|
uint32_t aProxyResolveFlags,
|
||||||
|
nsIURI *aProxyURI)
|
||||||
{
|
{
|
||||||
LOG(("HttpBaseChannel::Init [this=%p]\n", this));
|
LOG(("HttpBaseChannel::Init [this=%p]\n", this));
|
||||||
|
|
||||||
@ -87,6 +90,8 @@ HttpBaseChannel::Init(nsIURI *aURI,
|
|||||||
mOriginalURI = aURI;
|
mOriginalURI = aURI;
|
||||||
mDocumentURI = nullptr;
|
mDocumentURI = nullptr;
|
||||||
mCaps = aCaps;
|
mCaps = aCaps;
|
||||||
|
mProxyResolveFlags = aProxyResolveFlags;
|
||||||
|
mProxyURI = aProxyURI;
|
||||||
|
|
||||||
// Construct connection info object
|
// Construct connection info object
|
||||||
nsAutoCString host;
|
nsAutoCString host;
|
||||||
@ -112,11 +117,6 @@ HttpBaseChannel::Init(nsIURI *aURI,
|
|||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
LOG(("uri=%s\n", mSpec.get()));
|
LOG(("uri=%s\n", mSpec.get()));
|
||||||
|
|
||||||
mConnectionInfo = new nsHttpConnectionInfo(host, port,
|
|
||||||
aProxyInfo, usingSSL);
|
|
||||||
if (!mConnectionInfo)
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
|
|
||||||
// Set default request method
|
// Set default request method
|
||||||
mRequestHead.SetMethod(nsHttp::Get);
|
mRequestHead.SetMethod(nsHttp::Get);
|
||||||
|
|
||||||
@ -128,8 +128,13 @@ HttpBaseChannel::Init(nsIURI *aURI,
|
|||||||
rv = mRequestHead.SetHeader(nsHttp::Host, hostLine);
|
rv = mRequestHead.SetHeader(nsHttp::Host, hostLine);
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
rv = gHttpHandler->
|
rv = gHttpHandler->AddStandardRequestHeaders(&mRequestHead.Headers());
|
||||||
AddStandardRequestHeaders(&mRequestHead.Headers(), aCaps);
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
nsAutoCString type;
|
||||||
|
if (aProxyInfo && NS_SUCCEEDED(aProxyInfo->GetType(type)) &&
|
||||||
|
!type.EqualsLiteral("unknown"))
|
||||||
|
mProxyInfo = aProxyInfo;
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -1522,7 +1527,9 @@ HttpBaseChannel::SetupReplacementChannel(nsIURI *newURI,
|
|||||||
// set, then allow the flag to apply to the redirected channel as well.
|
// set, then allow the flag to apply to the redirected channel as well.
|
||||||
// since we force set INHIBIT_PERSISTENT_CACHING on all HTTPS channels,
|
// since we force set INHIBIT_PERSISTENT_CACHING on all HTTPS channels,
|
||||||
// we only need to check if the original channel was using SSL.
|
// we only need to check if the original channel was using SSL.
|
||||||
if (mConnectionInfo->UsingSSL())
|
bool usingSSL = false;
|
||||||
|
nsresult rv = mURI->SchemeIs("https", &usingSSL);
|
||||||
|
if (NS_SUCCEEDED(rv) && usingSSL)
|
||||||
newLoadFlags &= ~INHIBIT_PERSISTENT_CACHING;
|
newLoadFlags &= ~INHIBIT_PERSISTENT_CACHING;
|
||||||
|
|
||||||
// Do not pass along LOAD_CHECK_OFFLINE_CACHE
|
// Do not pass along LOAD_CHECK_OFFLINE_CACHE
|
||||||
|
@ -60,7 +60,9 @@ public:
|
|||||||
HttpBaseChannel();
|
HttpBaseChannel();
|
||||||
virtual ~HttpBaseChannel();
|
virtual ~HttpBaseChannel();
|
||||||
|
|
||||||
virtual nsresult Init(nsIURI *aURI, uint8_t aCaps, nsProxyInfo *aProxyInfo);
|
virtual nsresult Init(nsIURI *aURI, uint8_t aCaps, nsProxyInfo *aProxyInfo,
|
||||||
|
uint32_t aProxyResolveFlags,
|
||||||
|
nsIURI *aProxyURI);
|
||||||
|
|
||||||
// nsIRequest
|
// nsIRequest
|
||||||
NS_IMETHOD GetName(nsACString& aName);
|
NS_IMETHOD GetName(nsACString& aName);
|
||||||
@ -224,6 +226,7 @@ protected:
|
|||||||
nsCOMPtr<nsIInputStream> mUploadStream;
|
nsCOMPtr<nsIInputStream> mUploadStream;
|
||||||
nsAutoPtr<nsHttpResponseHead> mResponseHead;
|
nsAutoPtr<nsHttpResponseHead> mResponseHead;
|
||||||
nsRefPtr<nsHttpConnectionInfo> mConnectionInfo;
|
nsRefPtr<nsHttpConnectionInfo> mConnectionInfo;
|
||||||
|
nsCOMPtr<nsIProxyInfo> mProxyInfo;
|
||||||
|
|
||||||
nsCString mSpec; // ASCII encoded URL spec
|
nsCString mSpec; // ASCII encoded URL spec
|
||||||
nsCString mContentTypeHint;
|
nsCString mContentTypeHint;
|
||||||
@ -269,6 +272,9 @@ protected:
|
|||||||
uint32_t mSuspendCount;
|
uint32_t mSuspendCount;
|
||||||
|
|
||||||
nsAutoPtr<nsTArray<nsCString> > mRedirectedCachekeys;
|
nsAutoPtr<nsTArray<nsCString> > mRedirectedCachekeys;
|
||||||
|
|
||||||
|
uint32_t mProxyResolveFlags;
|
||||||
|
nsCOMPtr<nsIURI> mProxyURI;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Share some code while working around C++'s absurd inability to handle casting
|
// Share some code while working around C++'s absurd inability to handle casting
|
||||||
|
@ -333,21 +333,17 @@ nsHttpChannel::~nsHttpChannel()
|
|||||||
nsresult
|
nsresult
|
||||||
nsHttpChannel::Init(nsIURI *uri,
|
nsHttpChannel::Init(nsIURI *uri,
|
||||||
uint8_t caps,
|
uint8_t caps,
|
||||||
nsProxyInfo *proxyInfo)
|
nsProxyInfo *proxyInfo,
|
||||||
|
uint32_t proxyResolveFlags,
|
||||||
|
nsIURI *proxyURI)
|
||||||
{
|
{
|
||||||
nsresult rv = HttpBaseChannel::Init(uri, caps, proxyInfo);
|
nsresult rv = HttpBaseChannel::Init(uri, caps, proxyInfo,
|
||||||
|
proxyResolveFlags, proxyURI);
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
LOG(("nsHttpChannel::Init [this=%p]\n", this));
|
LOG(("nsHttpChannel::Init [this=%p]\n", this));
|
||||||
|
|
||||||
mAuthProvider =
|
|
||||||
do_CreateInstance("@mozilla.org/network/http-channel-auth-provider;1",
|
|
||||||
&rv);
|
|
||||||
if (NS_FAILED(rv))
|
|
||||||
return rv;
|
|
||||||
rv = mAuthProvider->Init(this);
|
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -407,13 +403,6 @@ nsHttpChannel::Connect()
|
|||||||
// Consider opening a TCP connection right away
|
// Consider opening a TCP connection right away
|
||||||
SpeculativeConnect();
|
SpeculativeConnect();
|
||||||
|
|
||||||
// are we offline?
|
|
||||||
bool offline = gIOService->IsOffline();
|
|
||||||
if (offline)
|
|
||||||
mLoadFlags |= LOAD_ONLY_FROM_CACHE;
|
|
||||||
else if (PL_strcmp(mConnectionInfo->ProxyType(), "unknown") == 0)
|
|
||||||
return ResolveProxy(); // Lazily resolve proxy info
|
|
||||||
|
|
||||||
// Don't allow resuming when cache must be used
|
// Don't allow resuming when cache must be used
|
||||||
if (mResuming && (mLoadFlags & LOAD_ONLY_FROM_CACHE)) {
|
if (mResuming && (mLoadFlags & LOAD_ONLY_FROM_CACHE)) {
|
||||||
LOG(("Resuming from cache is not supported yet"));
|
LOG(("Resuming from cache is not supported yet"));
|
||||||
@ -1532,54 +1521,6 @@ nsHttpChannel::ProxyFailover()
|
|||||||
return AsyncDoReplaceWithProxy(pi);
|
return AsyncDoReplaceWithProxy(pi);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
nsHttpChannel::HandleAsyncReplaceWithProxy()
|
|
||||||
{
|
|
||||||
NS_PRECONDITION(!mCallOnResume, "How did that happen?");
|
|
||||||
|
|
||||||
if (mSuspendCount) {
|
|
||||||
LOG(("Waiting until resume to do async proxy replacement [this=%p]\n",
|
|
||||||
this));
|
|
||||||
mCallOnResume = &nsHttpChannel::HandleAsyncReplaceWithProxy;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult status = mStatus;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIProxyInfo> pi;
|
|
||||||
pi.swap(mTargetProxyInfo);
|
|
||||||
if (!mCanceled) {
|
|
||||||
PushRedirectAsyncFunc(&nsHttpChannel::ContinueHandleAsyncReplaceWithProxy);
|
|
||||||
status = AsyncDoReplaceWithProxy(pi);
|
|
||||||
if (NS_SUCCEEDED(status))
|
|
||||||
return;
|
|
||||||
PopRedirectAsyncFunc(&nsHttpChannel::ContinueHandleAsyncReplaceWithProxy);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NS_FAILED(status)) {
|
|
||||||
ContinueHandleAsyncReplaceWithProxy(status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsHttpChannel::ContinueHandleAsyncReplaceWithProxy(nsresult status)
|
|
||||||
{
|
|
||||||
if (mLoadGroup && NS_SUCCEEDED(status)) {
|
|
||||||
mLoadGroup->RemoveRequest(this, nullptr, mStatus);
|
|
||||||
}
|
|
||||||
else if (NS_FAILED(status)) {
|
|
||||||
AsyncAbort(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return NS_OK here, even it seems to be breaking the async function stack
|
|
||||||
// contract (i.e. passing the result code to a function bellow).
|
|
||||||
// ContinueHandleAsyncReplaceWithProxy will always be at the bottom of the
|
|
||||||
// stack. If we would return the failure code, the async function stack
|
|
||||||
// logic would cancel the channel synchronously, which is undesired after
|
|
||||||
// invoking AsyncAbort above.
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
nsHttpChannel::HandleAsyncRedirectChannelToHttps()
|
nsHttpChannel::HandleAsyncRedirectChannelToHttps()
|
||||||
{
|
{
|
||||||
@ -1724,7 +1665,8 @@ nsHttpChannel::AsyncDoReplaceWithProxy(nsIProxyInfo* pi)
|
|||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
nsCOMPtr<nsIChannel> newChannel;
|
nsCOMPtr<nsIChannel> newChannel;
|
||||||
rv = gHttpHandler->NewProxiedChannel(mURI, pi, getter_AddRefs(newChannel));
|
rv = gHttpHandler->NewProxiedChannel(mURI, pi, mProxyResolveFlags,
|
||||||
|
mProxyURI, getter_AddRefs(newChannel));
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
@ -1795,11 +1737,16 @@ nsHttpChannel::ResolveProxy()
|
|||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
uint32_t resolveFlags = 0;
|
// Check if we are configured to directly connect. This will save us
|
||||||
if (mConnectionInfo->ProxyInfo())
|
// a round trip through the event dispatch system
|
||||||
mConnectionInfo->ProxyInfo()->GetResolveFlags(&resolveFlags);
|
uint32_t proxyConfigType;
|
||||||
|
if (NS_SUCCEEDED(pps->GetProxyConfigType(&proxyConfigType)) &&
|
||||||
|
proxyConfigType == nsIProtocolProxyService::PROXYCONFIG_DIRECT) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
return pps->AsyncResolve(mURI, resolveFlags, this, getter_AddRefs(mProxyRequest));
|
return pps->AsyncResolve(mProxyURI ? mProxyURI : mURI, mProxyResolveFlags,
|
||||||
|
this, getter_AddRefs(mProxyRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -4357,7 +4304,102 @@ nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context)
|
|||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
if (!(mConnectionInfo && mConnectionInfo->UsingHttpProxy())) {
|
// Remember the cookie header that was set, if any
|
||||||
|
const char *cookieHeader = mRequestHead.PeekHeader(nsHttp::Cookie);
|
||||||
|
if (cookieHeader) {
|
||||||
|
mUserSetCookieHeader = cookieHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddCookiesToRequest();
|
||||||
|
|
||||||
|
// notify "http-on-modify-request" observers
|
||||||
|
gHttpHandler->OnModifyRequest(this);
|
||||||
|
|
||||||
|
mIsPending = true;
|
||||||
|
mWasOpened = true;
|
||||||
|
|
||||||
|
mListener = listener;
|
||||||
|
mListenerContext = context;
|
||||||
|
|
||||||
|
// add ourselves to the load group. from this point forward, we'll report
|
||||||
|
// all failures asynchronously.
|
||||||
|
if (mLoadGroup)
|
||||||
|
mLoadGroup->AddRequest(this, nullptr);
|
||||||
|
|
||||||
|
// Collect mAsyncOpenTime after we have called all observers like
|
||||||
|
// "http-on-modify-request" and load group observers that may set
|
||||||
|
// mTimingEnabled flag.
|
||||||
|
if (mTimingEnabled)
|
||||||
|
mAsyncOpenTime = mozilla::TimeStamp::Now();
|
||||||
|
|
||||||
|
// are we offline?
|
||||||
|
bool offline = gIOService->IsOffline();
|
||||||
|
if (offline)
|
||||||
|
mLoadFlags |= LOAD_ONLY_FROM_CACHE;
|
||||||
|
|
||||||
|
// the only time we would already know the proxy information at this
|
||||||
|
// point would be if we were proxying a non-http protocol like ftp
|
||||||
|
if (!mProxyInfo && NS_SUCCEEDED(ResolveProxy()))
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
return BeginConnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsHttpChannel::BeginConnect()
|
||||||
|
{
|
||||||
|
LOG(("nsHttpChannel::BeginConnect [this=%p]\n", this));
|
||||||
|
nsresult rv;
|
||||||
|
|
||||||
|
// Construct connection info object
|
||||||
|
nsAutoCString host;
|
||||||
|
int32_t port = -1;
|
||||||
|
bool usingSSL = false;
|
||||||
|
|
||||||
|
rv = mURI->SchemeIs("https", &usingSSL);
|
||||||
|
if (NS_SUCCEEDED(rv))
|
||||||
|
rv = mURI->GetAsciiHost(host);
|
||||||
|
if (NS_SUCCEEDED(rv))
|
||||||
|
rv = mURI->GetPort(&port);
|
||||||
|
if (NS_SUCCEEDED(rv))
|
||||||
|
rv = mURI->GetAsciiSpec(mSpec);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
// Reject the URL if it doesn't specify a host
|
||||||
|
if (host.IsEmpty())
|
||||||
|
return NS_ERROR_MALFORMED_URI;
|
||||||
|
LOG(("host=%s port=%d\n", host.get(), port));
|
||||||
|
LOG(("uri=%s\n", mSpec.get()));
|
||||||
|
|
||||||
|
nsCOMPtr<nsProxyInfo> proxyInfo;
|
||||||
|
if (mProxyInfo)
|
||||||
|
proxyInfo = do_QueryInterface(mProxyInfo);
|
||||||
|
|
||||||
|
mConnectionInfo = new nsHttpConnectionInfo(host, port, proxyInfo, usingSSL);
|
||||||
|
|
||||||
|
mAuthProvider =
|
||||||
|
do_CreateInstance("@mozilla.org/network/http-channel-auth-provider;1",
|
||||||
|
&rv);
|
||||||
|
if (NS_SUCCEEDED(rv))
|
||||||
|
rv = mAuthProvider->Init(this);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
// check to see if authorization headers should be included
|
||||||
|
mAuthProvider->AddAuthorizationHeaders();
|
||||||
|
|
||||||
|
// when proxying only use the pipeline bit if ProxyPipelining() allows it.
|
||||||
|
if (!mConnectionInfo->UsingConnect() && mConnectionInfo->UsingHttpProxy()) {
|
||||||
|
mCaps &= ~NS_HTTP_ALLOW_PIPELINING;
|
||||||
|
if (gHttpHandler->ProxyPipelining())
|
||||||
|
mCaps |= NS_HTTP_ALLOW_PIPELINING;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this somehow fails we can go on without it
|
||||||
|
gHttpHandler->AddConnectionHeader(&mRequestHead.Headers(), mCaps);
|
||||||
|
|
||||||
|
if (!mConnectionInfo->UsingHttpProxy()) {
|
||||||
// Start a DNS lookup very early in case the real open is queued the DNS can
|
// Start a DNS lookup very early in case the real open is queued the DNS can
|
||||||
// happen in parallel. Do not do so in the presence of an HTTP proxy as
|
// happen in parallel. Do not do so in the presence of an HTTP proxy as
|
||||||
// all lookups other than for the proxy itself are done by the proxy.
|
// all lookups other than for the proxy itself are done by the proxy.
|
||||||
@ -4373,20 +4415,6 @@ nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context)
|
|||||||
mDNSPrefetch->PrefetchHigh();
|
mDNSPrefetch->PrefetchHigh();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remember the cookie header that was set, if any
|
|
||||||
const char *cookieHeader = mRequestHead.PeekHeader(nsHttp::Cookie);
|
|
||||||
if (cookieHeader) {
|
|
||||||
mUserSetCookieHeader = cookieHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
AddCookiesToRequest();
|
|
||||||
|
|
||||||
// check to see if authorization headers should be included
|
|
||||||
mAuthProvider->AddAuthorizationHeaders();
|
|
||||||
|
|
||||||
// notify "http-on-modify-request" observers
|
|
||||||
gHttpHandler->OnModifyRequest(this);
|
|
||||||
|
|
||||||
// Adjust mCaps according to our request headers:
|
// Adjust mCaps according to our request headers:
|
||||||
// - If "Connection: close" is set as a request header, then do not bother
|
// - If "Connection: close" is set as a request header, then do not bother
|
||||||
// trying to establish a keep-alive connection.
|
// trying to establish a keep-alive connection.
|
||||||
@ -4400,23 +4428,6 @@ nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context)
|
|||||||
// Force-Reload should reset the persistent connection pool for this host
|
// Force-Reload should reset the persistent connection pool for this host
|
||||||
if (mLoadFlags & LOAD_FRESH_CONNECTION)
|
if (mLoadFlags & LOAD_FRESH_CONNECTION)
|
||||||
mCaps |= NS_HTTP_CLEAR_KEEPALIVES;
|
mCaps |= NS_HTTP_CLEAR_KEEPALIVES;
|
||||||
|
|
||||||
mIsPending = true;
|
|
||||||
mWasOpened = true;
|
|
||||||
|
|
||||||
mListener = listener;
|
|
||||||
mListenerContext = context;
|
|
||||||
|
|
||||||
// add ourselves to the load group. from this point forward, we'll report
|
|
||||||
// all failures asynchronously.
|
|
||||||
if (mLoadGroup)
|
|
||||||
mLoadGroup->AddRequest(this, nullptr);
|
|
||||||
|
|
||||||
// Collect mAsyncOpenTime after we have called all obsrevers like
|
|
||||||
// "http-on-modify-request" and load group observers that may set
|
|
||||||
// mTimingEnabled flag.
|
|
||||||
if (mTimingEnabled)
|
|
||||||
mAsyncOpenTime = mozilla::TimeStamp::Now();
|
|
||||||
|
|
||||||
// We may have been cancelled already, either by on-modify-request
|
// We may have been cancelled already, either by on-modify-request
|
||||||
// listeners or by load group observers; in that case, we should
|
// listeners or by load group observers; in that case, we should
|
||||||
@ -4431,14 +4442,10 @@ nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context)
|
|||||||
AsyncAbort(rv);
|
AsyncAbort(rv);
|
||||||
} else if (mLoadFlags & LOAD_CLASSIFY_URI) {
|
} else if (mLoadFlags & LOAD_CLASSIFY_URI) {
|
||||||
nsRefPtr<nsChannelClassifier> classifier = new nsChannelClassifier();
|
nsRefPtr<nsChannelClassifier> classifier = new nsChannelClassifier();
|
||||||
if (!classifier) {
|
|
||||||
Cancel(NS_ERROR_OUT_OF_MEMORY);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = classifier->Start(this);
|
rv = classifier->Start(this);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
Cancel(rv);
|
Cancel(rv);
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4486,18 +4493,33 @@ NS_IMETHODIMP
|
|||||||
nsHttpChannel::OnProxyAvailable(nsICancelable *request, nsIURI *uri,
|
nsHttpChannel::OnProxyAvailable(nsICancelable *request, nsIURI *uri,
|
||||||
nsIProxyInfo *pi, nsresult status)
|
nsIProxyInfo *pi, nsresult status)
|
||||||
{
|
{
|
||||||
|
LOG(("nsHttpChannel::OnProxyAvailable [this=%p pi=%p status=%x mStatus=%x]\n",
|
||||||
|
this, pi, status, mStatus));
|
||||||
mProxyRequest = nullptr;
|
mProxyRequest = nullptr;
|
||||||
|
|
||||||
|
nsresult rv;
|
||||||
|
|
||||||
// If status is a failure code, then it means that we failed to resolve
|
// If status is a failure code, then it means that we failed to resolve
|
||||||
// proxy info. That is a non-fatal error assuming it wasn't because the
|
// proxy info. That is a non-fatal error assuming it wasn't because the
|
||||||
// request was canceled. We just failover to DIRECT when proxy resolution
|
// request was canceled. We just failover to DIRECT when proxy resolution
|
||||||
// fails (failure can mean that the PAC URL could not be loaded).
|
// fails (failure can mean that the PAC URL could not be loaded).
|
||||||
|
|
||||||
// Need to replace this channel with a new one. It would be complex to try
|
if (NS_SUCCEEDED(status))
|
||||||
// to change the value of mConnectionInfo since so much of our state may
|
mProxyInfo = pi;
|
||||||
// depend on its state.
|
|
||||||
mTargetProxyInfo = pi;
|
if (!gHttpHandler->Active()) {
|
||||||
HandleAsyncReplaceWithProxy();
|
LOG(("nsHttpChannel::OnProxyAvailable [this=%p] "
|
||||||
|
"Handler no longer active.\n", this));
|
||||||
|
rv = NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rv = BeginConnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
Cancel(rv);
|
||||||
|
DoNotifyListener();
|
||||||
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +95,9 @@ public:
|
|||||||
nsHttpChannel();
|
nsHttpChannel();
|
||||||
virtual ~nsHttpChannel();
|
virtual ~nsHttpChannel();
|
||||||
|
|
||||||
virtual nsresult Init(nsIURI *aURI, uint8_t aCaps, nsProxyInfo *aProxyInfo);
|
virtual nsresult Init(nsIURI *aURI, uint8_t aCaps, nsProxyInfo *aProxyInfo,
|
||||||
|
uint32_t aProxyResolveFlags,
|
||||||
|
nsIURI *aProxyURI);
|
||||||
|
|
||||||
// Methods HttpBaseChannel didn't implement for us or that we override.
|
// Methods HttpBaseChannel didn't implement for us or that we override.
|
||||||
//
|
//
|
||||||
@ -150,6 +152,7 @@ private:
|
|||||||
typedef nsresult (nsHttpChannel::*nsContinueRedirectionFunc)(nsresult result);
|
typedef nsresult (nsHttpChannel::*nsContinueRedirectionFunc)(nsresult result);
|
||||||
|
|
||||||
bool RequestIsConditional();
|
bool RequestIsConditional();
|
||||||
|
nsresult BeginConnect();
|
||||||
nsresult Connect();
|
nsresult Connect();
|
||||||
nsresult ContinueConnect();
|
nsresult ContinueConnect();
|
||||||
void SpeculativeConnect();
|
void SpeculativeConnect();
|
||||||
@ -186,8 +189,6 @@ private:
|
|||||||
nsresult ProxyFailover();
|
nsresult ProxyFailover();
|
||||||
nsresult AsyncDoReplaceWithProxy(nsIProxyInfo *);
|
nsresult AsyncDoReplaceWithProxy(nsIProxyInfo *);
|
||||||
nsresult ContinueDoReplaceWithProxy(nsresult);
|
nsresult ContinueDoReplaceWithProxy(nsresult);
|
||||||
void HandleAsyncReplaceWithProxy();
|
|
||||||
nsresult ContinueHandleAsyncReplaceWithProxy(nsresult);
|
|
||||||
nsresult ResolveProxy();
|
nsresult ResolveProxy();
|
||||||
|
|
||||||
// cache specific methods
|
// cache specific methods
|
||||||
@ -303,9 +304,6 @@ private:
|
|||||||
// auth specific data
|
// auth specific data
|
||||||
nsCOMPtr<nsIHttpChannelAuthProvider> mAuthProvider;
|
nsCOMPtr<nsIHttpChannelAuthProvider> mAuthProvider;
|
||||||
|
|
||||||
// Proxy info to replace with
|
|
||||||
nsCOMPtr<nsIProxyInfo> mTargetProxyInfo;
|
|
||||||
|
|
||||||
// If the channel is associated with a cache, and the URI matched
|
// If the channel is associated with a cache, and the URI matched
|
||||||
// a fallback namespace, this will hold the key for the fallback
|
// a fallback namespace, this will hold the key for the fallback
|
||||||
// cache entry.
|
// cache entry.
|
||||||
|
@ -131,9 +131,9 @@ nsHttpHandler::nsHttpHandler()
|
|||||||
, mHttpVersion(NS_HTTP_VERSION_1_1)
|
, mHttpVersion(NS_HTTP_VERSION_1_1)
|
||||||
, mProxyHttpVersion(NS_HTTP_VERSION_1_1)
|
, mProxyHttpVersion(NS_HTTP_VERSION_1_1)
|
||||||
, mCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
|
, mCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
|
||||||
, mProxyCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
|
|
||||||
, mReferrerLevel(0xff) // by default we always send a referrer
|
, mReferrerLevel(0xff) // by default we always send a referrer
|
||||||
, mFastFallbackToIPv4(false)
|
, mFastFallbackToIPv4(false)
|
||||||
|
, mProxyPipelining(true)
|
||||||
, mIdleTimeout(PR_SecondsToInterval(10))
|
, mIdleTimeout(PR_SecondsToInterval(10))
|
||||||
, mSpdyTimeout(PR_SecondsToInterval(180))
|
, mSpdyTimeout(PR_SecondsToInterval(180))
|
||||||
, mMaxRequestAttempts(10)
|
, mMaxRequestAttempts(10)
|
||||||
@ -167,6 +167,7 @@ nsHttpHandler::nsHttpHandler()
|
|||||||
, mDoNotTrackEnabled(false)
|
, mDoNotTrackEnabled(false)
|
||||||
, mTelemetryEnabled(false)
|
, mTelemetryEnabled(false)
|
||||||
, mAllowExperiments(true)
|
, mAllowExperiments(true)
|
||||||
|
, mHandlerActive(false)
|
||||||
, mEnableSpdy(false)
|
, mEnableSpdy(false)
|
||||||
, mSpdyV2(true)
|
, mSpdyV2(true)
|
||||||
, mSpdyV3(true)
|
, mSpdyV3(true)
|
||||||
@ -264,6 +265,7 @@ nsHttpHandler::Init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
mSessionStartTime = NowInSeconds();
|
mSessionStartTime = NowInSeconds();
|
||||||
|
mHandlerActive = true;
|
||||||
|
|
||||||
rv = mAuthCache.Init();
|
rv = mAuthCache.Init();
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
@ -331,8 +333,7 @@ nsHttpHandler::InitConnectionMgr()
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request,
|
nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request)
|
||||||
uint8_t caps)
|
|
||||||
{
|
{
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
@ -356,6 +357,20 @@ nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request,
|
|||||||
rv = request->SetHeader(nsHttp::Accept_Encoding, mAcceptEncodings);
|
rv = request->SetHeader(nsHttp::Accept_Encoding, mAcceptEncodings);
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
// Add the "Do-Not-Track" header
|
||||||
|
if (mDoNotTrackEnabled) {
|
||||||
|
rv = request->SetHeader(nsHttp::DoNotTrack,
|
||||||
|
NS_LITERAL_CSTRING("1"));
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsHttpHandler::AddConnectionHeader(nsHttpHeaderArray *request,
|
||||||
|
uint8_t caps)
|
||||||
|
{
|
||||||
// RFC2616 section 19.6.2 states that the "Connection: keep-alive"
|
// RFC2616 section 19.6.2 states that the "Connection: keep-alive"
|
||||||
// and "Keep-alive" request headers should not be sent by HTTP/1.1
|
// and "Keep-alive" request headers should not be sent by HTTP/1.1
|
||||||
// user-agents. But this is not a problem in practice, and the
|
// user-agents. But this is not a problem in practice, and the
|
||||||
@ -369,13 +384,6 @@ nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request,
|
|||||||
connectionType = &keepAlive;
|
connectionType = &keepAlive;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the "Do-Not-Track" header
|
|
||||||
if (mDoNotTrackEnabled) {
|
|
||||||
rv = request->SetHeader(nsHttp::DoNotTrack,
|
|
||||||
NS_LITERAL_CSTRING("1"));
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
return request->SetHeader(nsHttp::Connection, *connectionType);
|
return request->SetHeader(nsHttp::Connection, *connectionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -943,12 +951,8 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
|
|||||||
|
|
||||||
if (PREF_CHANGED(HTTP_PREF("proxy.pipelining"))) {
|
if (PREF_CHANGED(HTTP_PREF("proxy.pipelining"))) {
|
||||||
rv = prefs->GetBoolPref(HTTP_PREF("proxy.pipelining"), &cVar);
|
rv = prefs->GetBoolPref(HTTP_PREF("proxy.pipelining"), &cVar);
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv))
|
||||||
if (cVar)
|
mProxyPipelining = cVar;
|
||||||
mProxyCapabilities |= NS_HTTP_ALLOW_PIPELINING;
|
|
||||||
else
|
|
||||||
mProxyCapabilities &= ~NS_HTTP_ALLOW_PIPELINING;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PREF_CHANGED(HTTP_PREF("qos"))) {
|
if (PREF_CHANGED(HTTP_PREF("qos"))) {
|
||||||
@ -1375,7 +1379,7 @@ nsHttpHandler::NewChannel(nsIURI *uri, nsIChannel **result)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewProxiedChannel(uri, nullptr, result);
|
return NewProxiedChannel(uri, nullptr, 0, nullptr, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
@ -1393,6 +1397,8 @@ nsHttpHandler::AllowPort(int32_t port, const char *scheme, bool *_retval)
|
|||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsHttpHandler::NewProxiedChannel(nsIURI *uri,
|
nsHttpHandler::NewProxiedChannel(nsIURI *uri,
|
||||||
nsIProxyInfo* givenProxyInfo,
|
nsIProxyInfo* givenProxyInfo,
|
||||||
|
uint32_t proxyResolveFlags,
|
||||||
|
nsIURI *proxyURI,
|
||||||
nsIChannel **result)
|
nsIChannel **result)
|
||||||
{
|
{
|
||||||
nsRefPtr<HttpBaseChannel> httpChannel;
|
nsRefPtr<HttpBaseChannel> httpChannel;
|
||||||
@ -1417,13 +1423,7 @@ nsHttpHandler::NewProxiedChannel(nsIURI *uri,
|
|||||||
httpChannel = new nsHttpChannel();
|
httpChannel = new nsHttpChannel();
|
||||||
}
|
}
|
||||||
|
|
||||||
// select proxy caps if using a non-transparent proxy. SSL tunneling
|
uint8_t caps = mCapabilities;
|
||||||
// should not use proxy settings.
|
|
||||||
int8_t caps;
|
|
||||||
if (proxyInfo && !nsCRT::strcmp(proxyInfo->Type(), "http") && !https)
|
|
||||||
caps = mProxyCapabilities;
|
|
||||||
else
|
|
||||||
caps = mCapabilities;
|
|
||||||
|
|
||||||
if (https) {
|
if (https) {
|
||||||
// enable pipelining over SSL if requested
|
// enable pipelining over SSL if requested
|
||||||
@ -1436,7 +1436,7 @@ nsHttpHandler::NewProxiedChannel(nsIURI *uri,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = httpChannel->Init(uri, caps, proxyInfo);
|
rv = httpChannel->Init(uri, caps, proxyInfo, proxyResolveFlags, proxyURI);
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
@ -1509,6 +1509,8 @@ nsHttpHandler::Observe(nsISupports *subject,
|
|||||||
else if (strcmp(topic, "profile-change-net-teardown") == 0 ||
|
else if (strcmp(topic, "profile-change-net-teardown") == 0 ||
|
||||||
strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
|
strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
|
||||||
|
|
||||||
|
mHandlerActive = false;
|
||||||
|
|
||||||
// clear cache of all authentication credentials.
|
// clear cache of all authentication credentials.
|
||||||
mAuthCache.ClearAll();
|
mAuthCache.ClearAll();
|
||||||
|
|
||||||
|
@ -58,8 +58,9 @@ public:
|
|||||||
virtual ~nsHttpHandler();
|
virtual ~nsHttpHandler();
|
||||||
|
|
||||||
nsresult Init();
|
nsresult Init();
|
||||||
nsresult AddStandardRequestHeaders(nsHttpHeaderArray *,
|
nsresult AddStandardRequestHeaders(nsHttpHeaderArray *);
|
||||||
uint8_t capabilities);
|
nsresult AddConnectionHeader(nsHttpHeaderArray *,
|
||||||
|
uint8_t capabilities);
|
||||||
bool IsAcceptableEncoding(const char *encoding);
|
bool IsAcceptableEncoding(const char *encoding);
|
||||||
|
|
||||||
const nsAFlatCString &UserAgent();
|
const nsAFlatCString &UserAgent();
|
||||||
@ -78,6 +79,7 @@ public:
|
|||||||
uint8_t GetQoSBits() { return mQoSBits; }
|
uint8_t GetQoSBits() { return mQoSBits; }
|
||||||
uint16_t GetIdleSynTimeout() { return mIdleSynTimeout; }
|
uint16_t GetIdleSynTimeout() { return mIdleSynTimeout; }
|
||||||
bool FastFallbackToIPv4() { return mFastFallbackToIPv4; }
|
bool FastFallbackToIPv4() { return mFastFallbackToIPv4; }
|
||||||
|
bool ProxyPipelining() { return mProxyPipelining; }
|
||||||
uint32_t MaxSocketCount();
|
uint32_t MaxSocketCount();
|
||||||
bool EnforceAssocReq() { return mEnforceAssocReq; }
|
bool EnforceAssocReq() { return mEnforceAssocReq; }
|
||||||
|
|
||||||
@ -233,6 +235,9 @@ public:
|
|||||||
|
|
||||||
mozilla::net::SpdyInformation *SpdyInfo() { return &mSpdyInfo; }
|
mozilla::net::SpdyInformation *SpdyInfo() { return &mSpdyInfo; }
|
||||||
|
|
||||||
|
// returns true in between Init and Shutdown states
|
||||||
|
bool Active() { return mHandlerActive; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -273,11 +278,10 @@ private:
|
|||||||
uint8_t mHttpVersion;
|
uint8_t mHttpVersion;
|
||||||
uint8_t mProxyHttpVersion;
|
uint8_t mProxyHttpVersion;
|
||||||
uint8_t mCapabilities;
|
uint8_t mCapabilities;
|
||||||
uint8_t mProxyCapabilities;
|
|
||||||
uint8_t mReferrerLevel;
|
uint8_t mReferrerLevel;
|
||||||
|
|
||||||
bool mFastFallbackToIPv4;
|
bool mFastFallbackToIPv4;
|
||||||
|
bool mProxyPipelining;
|
||||||
PRIntervalTime mIdleTimeout;
|
PRIntervalTime mIdleTimeout;
|
||||||
PRIntervalTime mSpdyTimeout;
|
PRIntervalTime mSpdyTimeout;
|
||||||
|
|
||||||
@ -356,6 +360,9 @@ private:
|
|||||||
// The value of network.allow-experiments
|
// The value of network.allow-experiments
|
||||||
bool mAllowExperiments;
|
bool mAllowExperiments;
|
||||||
|
|
||||||
|
// true in between init and shutdown states
|
||||||
|
bool mHandlerActive;
|
||||||
|
|
||||||
// Try to use SPDY features instead of HTTP/1.1 over SSL
|
// Try to use SPDY features instead of HTTP/1.1 over SSL
|
||||||
mozilla::net::SpdyInformation mSpdyInfo;
|
mozilla::net::SpdyInformation mSpdyInfo;
|
||||||
bool mEnableSpdy;
|
bool mEnableSpdy;
|
||||||
|
@ -6,10 +6,21 @@
|
|||||||
|
|
||||||
// This testcase exercises the Protocol Proxy Service
|
// This testcase exercises the Protocol Proxy Service
|
||||||
|
|
||||||
|
// These are the major sub tests:
|
||||||
|
// run_filter_test();
|
||||||
|
// run_filter_test2()
|
||||||
|
// run_filter_test3()
|
||||||
|
// run_pref_test();
|
||||||
|
// run_pac_test();
|
||||||
|
// run_pac_cancel_test();
|
||||||
|
// run_proxy_host_filters_test();
|
||||||
|
|
||||||
var ios = Components.classes["@mozilla.org/network/io-service;1"]
|
var ios = Components.classes["@mozilla.org/network/io-service;1"]
|
||||||
.getService(Components.interfaces.nsIIOService);
|
.getService(Components.interfaces.nsIIOService);
|
||||||
var pps = Components.classes["@mozilla.org/network/protocol-proxy-service;1"]
|
var pps = Components.classes["@mozilla.org/network/protocol-proxy-service;1"]
|
||||||
.getService();
|
.getService();
|
||||||
|
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
|
||||||
|
.getService(Components.interfaces.nsIPrefBranch);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test nsIProtocolHandler that allows proxying, but doesn't allow HTTP
|
* Test nsIProtocolHandler that allows proxying, but doesn't allow HTTP
|
||||||
@ -143,61 +154,109 @@ function run_filter_test() {
|
|||||||
var uri = ios.newURI("http://www.mozilla.org/", null, null);
|
var uri = ios.newURI("http://www.mozilla.org/", null, null);
|
||||||
|
|
||||||
// Verify initial state
|
// Verify initial state
|
||||||
|
var cb = new resolveCallback();
|
||||||
|
cb.nextFunction = filter_test0_1;
|
||||||
|
var req = pps.asyncResolve(uri, 0, cb);
|
||||||
|
}
|
||||||
|
|
||||||
var pi = pps.resolve(uri, 0);
|
var filter01;
|
||||||
|
var filter02;
|
||||||
|
|
||||||
|
function filter_test0_1(pi) {
|
||||||
do_check_eq(pi, null);
|
do_check_eq(pi, null);
|
||||||
|
|
||||||
// Push a filter and verify the results
|
// Push a filter and verify the results
|
||||||
|
|
||||||
var filter1 = new BasicFilter();
|
filter01 = new BasicFilter();
|
||||||
var filter2 = new BasicFilter();
|
filter02 = new BasicFilter();
|
||||||
pps.registerFilter(filter1, 10);
|
pps.registerFilter(filter01, 10);
|
||||||
pps.registerFilter(filter2, 20);
|
pps.registerFilter(filter02, 20);
|
||||||
|
|
||||||
pi = pps.resolve(uri, 0);
|
var cb = new resolveCallback();
|
||||||
|
cb.nextFunction = filter_test0_2;
|
||||||
|
var uri = ios.newURI("http://www.mozilla.org/", null, null);
|
||||||
|
var req = pps.asyncResolve(uri, 0, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
function filter_test0_2(pi)
|
||||||
|
{
|
||||||
check_proxy(pi, "http", "localhost", 8080, 0, 10, true);
|
check_proxy(pi, "http", "localhost", 8080, 0, 10, true);
|
||||||
check_proxy(pi.failoverProxy, "direct", "", -1, 0, 0, false);
|
check_proxy(pi.failoverProxy, "direct", "", -1, 0, 0, false);
|
||||||
|
|
||||||
pps.unregisterFilter(filter2);
|
pps.unregisterFilter(filter02);
|
||||||
pi = pps.resolve(uri, 0);
|
|
||||||
|
var cb = new resolveCallback();
|
||||||
|
cb.nextFunction = filter_test0_3;
|
||||||
|
var uri = ios.newURI("http://www.mozilla.org/", null, null);
|
||||||
|
var req = pps.asyncResolve(uri, 0, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
function filter_test0_3(pi)
|
||||||
|
{
|
||||||
check_proxy(pi, "http", "localhost", 8080, 0, 10, true);
|
check_proxy(pi, "http", "localhost", 8080, 0, 10, true);
|
||||||
check_proxy(pi.failoverProxy, "direct", "", -1, 0, 0, false);
|
check_proxy(pi.failoverProxy, "direct", "", -1, 0, 0, false);
|
||||||
|
|
||||||
// Remove filter and verify that we return to the initial state
|
// Remove filter and verify that we return to the initial state
|
||||||
|
|
||||||
pps.unregisterFilter(filter1);
|
pps.unregisterFilter(filter01);
|
||||||
pi = pps.resolve(uri, 0);
|
|
||||||
do_check_eq(pi, null);
|
var cb = new resolveCallback();
|
||||||
|
cb.nextFunction = filter_test0_4;
|
||||||
|
var uri = ios.newURI("http://www.mozilla.org/", null, null);
|
||||||
|
var req = pps.asyncResolve(uri, 0, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
function run_filter_test2() {
|
function filter_test0_4(pi)
|
||||||
var uri = ios.newURI("http://www.mozilla.org/", null, null);
|
{
|
||||||
|
|
||||||
// Verify initial state
|
|
||||||
|
|
||||||
var pi = pps.resolve(uri, 0);
|
|
||||||
do_check_eq(pi, null);
|
do_check_eq(pi, null);
|
||||||
|
run_filter_test2();
|
||||||
|
}
|
||||||
|
|
||||||
|
var filter11;
|
||||||
|
var filter12;
|
||||||
|
|
||||||
|
function run_filter_test2() {
|
||||||
// Push a filter and verify the results
|
// Push a filter and verify the results
|
||||||
|
|
||||||
var filter1 = new TestFilter("http", "foo", 8080, 0, 10);
|
filter11 = new TestFilter("http", "foo", 8080, 0, 10);
|
||||||
var filter2 = new TestFilter("http", "bar", 8090, 0, 10);
|
filter12 = new TestFilter("http", "bar", 8090, 0, 10);
|
||||||
pps.registerFilter(filter1, 20);
|
pps.registerFilter(filter11, 20);
|
||||||
pps.registerFilter(filter2, 10);
|
pps.registerFilter(filter12, 10);
|
||||||
|
|
||||||
pi = pps.resolve(uri, 0);
|
var cb = new resolveCallback();
|
||||||
|
cb.nextFunction = filter_test1_1;
|
||||||
|
var uri = ios.newURI("http://www.mozilla.org/", null, null);
|
||||||
|
var req = pps.asyncResolve(uri, 0, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
function filter_test1_1(pi) {
|
||||||
check_proxy(pi, "http", "bar", 8090, 0, 10, true);
|
check_proxy(pi, "http", "bar", 8090, 0, 10, true);
|
||||||
check_proxy(pi.failoverProxy, "http", "foo", 8080, 0, 10, false);
|
check_proxy(pi.failoverProxy, "http", "foo", 8080, 0, 10, false);
|
||||||
|
|
||||||
pps.unregisterFilter(filter2);
|
pps.unregisterFilter(filter12);
|
||||||
pi = pps.resolve(uri, 0);
|
|
||||||
|
var cb = new resolveCallback();
|
||||||
|
cb.nextFunction = filter_test1_2;
|
||||||
|
var uri = ios.newURI("http://www.mozilla.org/", null, null);
|
||||||
|
var req = pps.asyncResolve(uri, 0, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
function filter_test1_2(pi) {
|
||||||
check_proxy(pi, "http", "foo", 8080, 0, 10, false);
|
check_proxy(pi, "http", "foo", 8080, 0, 10, false);
|
||||||
|
|
||||||
// Remove filter and verify that we return to the initial state
|
// Remove filter and verify that we return to the initial state
|
||||||
|
|
||||||
pps.unregisterFilter(filter1);
|
pps.unregisterFilter(filter11);
|
||||||
pi = pps.resolve(uri, 0);
|
|
||||||
|
var cb = new resolveCallback();
|
||||||
|
cb.nextFunction = filter_test1_3;
|
||||||
|
var uri = ios.newURI("http://www.mozilla.org/", null, null);
|
||||||
|
var req = pps.asyncResolve(uri, 0, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
function filter_test1_3(pi) {
|
||||||
do_check_eq(pi, null);
|
do_check_eq(pi, null);
|
||||||
|
run_filter_test3();
|
||||||
}
|
}
|
||||||
|
|
||||||
var filter_3_1;
|
var filter_3_1;
|
||||||
@ -213,42 +272,56 @@ function run_filter_test3() {
|
|||||||
var cb = new resolveCallback();
|
var cb = new resolveCallback();
|
||||||
cb.nextFunction = filter_test3_1;
|
cb.nextFunction = filter_test3_1;
|
||||||
var req = pps.asyncResolve(uri, 0, cb);
|
var req = pps.asyncResolve(uri, 0, cb);
|
||||||
do_test_pending();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function filter_test3_1(pi) {
|
function filter_test3_1(pi) {
|
||||||
check_proxy(pi, "http", "foo", 8080, 0, 10, false);
|
check_proxy(pi, "http", "foo", 8080, 0, 10, false);
|
||||||
pps.unregisterFilter(filter_3_1);
|
pps.unregisterFilter(filter_3_1);
|
||||||
run_test_continued_3();
|
run_pref_test();
|
||||||
do_test_finished();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function run_pref_test() {
|
function run_pref_test() {
|
||||||
var uri = ios.newURI("http://www.mozilla.org/", null, null);
|
var uri = ios.newURI("http://www.mozilla.org/", null, null);
|
||||||
|
|
||||||
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
|
|
||||||
.getService(Components.interfaces.nsIPrefBranch);
|
|
||||||
|
|
||||||
// Verify 'direct' setting
|
// Verify 'direct' setting
|
||||||
|
|
||||||
prefs.setIntPref("network.proxy.type", 0);
|
prefs.setIntPref("network.proxy.type", 0);
|
||||||
|
|
||||||
var pi = pps.resolve(uri, 0);
|
var cb = new resolveCallback();
|
||||||
|
cb.nextFunction = pref_test1_1;
|
||||||
|
var req = pps.asyncResolve(uri, 0, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
function pref_test1_1(pi)
|
||||||
|
{
|
||||||
do_check_eq(pi, null);
|
do_check_eq(pi, null);
|
||||||
|
|
||||||
// Verify 'manual' setting
|
// Verify 'manual' setting
|
||||||
|
|
||||||
prefs.setIntPref("network.proxy.type", 1);
|
prefs.setIntPref("network.proxy.type", 1);
|
||||||
|
|
||||||
|
var cb = new resolveCallback();
|
||||||
|
cb.nextFunction = pref_test1_2;
|
||||||
|
var uri = ios.newURI("http://www.mozilla.org/", null, null);
|
||||||
|
var req = pps.asyncResolve(uri, 0, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
function pref_test1_2(pi)
|
||||||
|
{
|
||||||
// nothing yet configured
|
// nothing yet configured
|
||||||
pi = pps.resolve(uri, 0);
|
|
||||||
do_check_eq(pi, null);
|
do_check_eq(pi, null);
|
||||||
|
|
||||||
// try HTTP configuration
|
// try HTTP configuration
|
||||||
prefs.setCharPref("network.proxy.http", "foopy");
|
prefs.setCharPref("network.proxy.http", "foopy");
|
||||||
prefs.setIntPref("network.proxy.http_port", 8080);
|
prefs.setIntPref("network.proxy.http_port", 8080);
|
||||||
|
|
||||||
pi = pps.resolve(uri, 0);
|
var cb = new resolveCallback();
|
||||||
|
cb.nextFunction = pref_test1_3;
|
||||||
|
var uri = ios.newURI("http://www.mozilla.org/", null, null);
|
||||||
|
var req = pps.asyncResolve(uri, 0, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
function pref_test1_3(pi)
|
||||||
|
{
|
||||||
check_proxy(pi, "http", "foopy", 8080, 0, -1, false);
|
check_proxy(pi, "http", "foopy", 8080, 0, -1, false);
|
||||||
|
|
||||||
prefs.setCharPref("network.proxy.http", "");
|
prefs.setCharPref("network.proxy.http", "");
|
||||||
@ -258,15 +331,33 @@ function run_pref_test() {
|
|||||||
prefs.setCharPref("network.proxy.socks", "barbar");
|
prefs.setCharPref("network.proxy.socks", "barbar");
|
||||||
prefs.setIntPref("network.proxy.socks_port", 1203);
|
prefs.setIntPref("network.proxy.socks_port", 1203);
|
||||||
|
|
||||||
pi = pps.resolve(uri, 0);
|
var cb = new resolveCallback();
|
||||||
|
cb.nextFunction = pref_test1_4;
|
||||||
|
var uri = ios.newURI("http://www.mozilla.org/", null, null);
|
||||||
|
var req = pps.asyncResolve(uri, 0, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
function pref_test1_4(pi)
|
||||||
|
{
|
||||||
check_proxy(pi, "socks", "barbar", 1203, 0, -1, false);
|
check_proxy(pi, "socks", "barbar", 1203, 0, -1, false);
|
||||||
|
run_pac_test();
|
||||||
}
|
}
|
||||||
|
|
||||||
function run_protocol_handler_test() {
|
function run_protocol_handler_test() {
|
||||||
var uri = ios.newURI("moz-test:foopy", null, null);
|
var uri = ios.newURI("moz-test:foopy", null, null);
|
||||||
|
|
||||||
var pi = pps.resolve(uri, 0);
|
var cb = new resolveCallback();
|
||||||
|
cb.nextFunction = protocol_handler_test_1;
|
||||||
|
var req = pps.asyncResolve(uri, 0, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
function protocol_handler_test_1(pi)
|
||||||
|
{
|
||||||
do_check_eq(pi, null);
|
do_check_eq(pi, null);
|
||||||
|
prefs.setCharPref("network.proxy.autoconfig_url", "");
|
||||||
|
prefs.setIntPref("network.proxy.type", 0);
|
||||||
|
|
||||||
|
run_pac_cancel_test();
|
||||||
}
|
}
|
||||||
|
|
||||||
function TestResolveCallback() {
|
function TestResolveCallback() {
|
||||||
@ -292,21 +383,7 @@ TestResolveCallback.prototype = {
|
|||||||
check_proxy(pi, "http", "foopy", 8080, 0, -1, true);
|
check_proxy(pi, "http", "foopy", 8080, 0, -1, true);
|
||||||
check_proxy(pi.failoverProxy, "direct", "", -1, -1, -1, false);
|
check_proxy(pi.failoverProxy, "direct", "", -1, -1, -1, false);
|
||||||
|
|
||||||
// verify direct query now that we know the PAC file is loaded
|
|
||||||
pi = pps.resolve(ios.newURI("http://bazbat.com/", null, null), 0);
|
|
||||||
do_check_neq(pi, null);
|
|
||||||
check_proxy(pi, "http", "foopy", 8080, 0, -1, true);
|
|
||||||
check_proxy(pi.failoverProxy, "direct", "", -1, -1, -1, false);
|
|
||||||
|
|
||||||
run_protocol_handler_test();
|
run_protocol_handler_test();
|
||||||
|
|
||||||
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
|
|
||||||
.getService(Components.interfaces.nsIPrefBranch);
|
|
||||||
prefs.setCharPref("network.proxy.autoconfig_url", "");
|
|
||||||
prefs.setIntPref("network.proxy.type", 0);
|
|
||||||
|
|
||||||
run_test_continued();
|
|
||||||
do_test_finished();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -317,31 +394,12 @@ function run_pac_test() {
|
|||||||
'}';
|
'}';
|
||||||
var uri = ios.newURI("http://www.mozilla.org/", null, null);
|
var uri = ios.newURI("http://www.mozilla.org/", null, null);
|
||||||
|
|
||||||
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
|
|
||||||
.getService(Components.interfaces.nsIPrefBranch);
|
|
||||||
|
|
||||||
// Configure PAC
|
// Configure PAC
|
||||||
|
|
||||||
prefs.setIntPref("network.proxy.type", 2);
|
prefs.setIntPref("network.proxy.type", 2);
|
||||||
prefs.setCharPref("network.proxy.autoconfig_url", pac);
|
prefs.setCharPref("network.proxy.autoconfig_url", pac);
|
||||||
|
|
||||||
// Test it out (we expect an "unknown" result since the PAC load is async)
|
|
||||||
var pi = pps.resolve(uri, 0);
|
|
||||||
do_check_neq(pi, null);
|
|
||||||
do_check_eq(pi.type, "unknown");
|
|
||||||
|
|
||||||
// We expect the NON_BLOCKING flag to trigger an exception here since
|
|
||||||
// we have configured the PPS to use PAC.
|
|
||||||
var hit_exception = false;
|
|
||||||
try {
|
|
||||||
pps.resolve(uri, pps.RESOLVE_NON_BLOCKING);
|
|
||||||
} catch (e) {
|
|
||||||
hit_exception = true;
|
|
||||||
}
|
|
||||||
do_check_eq(hit_exception, true);
|
|
||||||
|
|
||||||
var req = pps.asyncResolve(uri, 0, new TestResolveCallback());
|
var req = pps.asyncResolve(uri, 0, new TestResolveCallback());
|
||||||
do_test_pending();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function TestResolveCancelationCallback() {
|
function TestResolveCancelationCallback() {
|
||||||
@ -364,13 +422,10 @@ TestResolveCancelationCallback.prototype = {
|
|||||||
do_check_eq(status, Components.results.NS_ERROR_ABORT);
|
do_check_eq(status, Components.results.NS_ERROR_ABORT);
|
||||||
do_check_eq(pi, null);
|
do_check_eq(pi, null);
|
||||||
|
|
||||||
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
|
|
||||||
.getService(Components.interfaces.nsIPrefBranch);
|
|
||||||
prefs.setCharPref("network.proxy.autoconfig_url", "");
|
prefs.setCharPref("network.proxy.autoconfig_url", "");
|
||||||
prefs.setIntPref("network.proxy.type", 0);
|
prefs.setIntPref("network.proxy.type", 0);
|
||||||
|
|
||||||
run_test_continued_2();
|
run_proxy_host_filters_test();
|
||||||
do_test_finished();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -382,42 +437,70 @@ function run_pac_cancel_test() {
|
|||||||
'function FindProxyForURL(url, host) {' +
|
'function FindProxyForURL(url, host) {' +
|
||||||
' return "PROXY foopy:8080; DIRECT";' +
|
' return "PROXY foopy:8080; DIRECT";' +
|
||||||
'}';
|
'}';
|
||||||
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
|
|
||||||
.getService(Components.interfaces.nsIPrefBranch);
|
|
||||||
prefs.setIntPref("network.proxy.type", 2);
|
prefs.setIntPref("network.proxy.type", 2);
|
||||||
prefs.setCharPref("network.proxy.autoconfig_url", pac);
|
prefs.setCharPref("network.proxy.autoconfig_url", pac);
|
||||||
|
|
||||||
var req = pps.asyncResolve(uri, 0, new TestResolveCancelationCallback());
|
var req = pps.asyncResolve(uri, 0, new TestResolveCancelationCallback());
|
||||||
req.cancel(Components.results.NS_ERROR_ABORT);
|
req.cancel(Components.results.NS_ERROR_ABORT);
|
||||||
do_test_pending();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function check_host_filters(hostList, bShouldBeFiltered) {
|
var hostList;
|
||||||
|
var hostIDX;
|
||||||
|
var bShouldBeFiltered;
|
||||||
|
var hostNextFX;
|
||||||
|
|
||||||
|
function check_host_filters(hl, shouldBe, nextFX) {
|
||||||
|
hostList = hl;
|
||||||
|
hostIDX = 0;
|
||||||
|
bShouldBeFiltered = shouldBe;
|
||||||
|
hostNextFX = nextFX;
|
||||||
|
|
||||||
|
if (hostList.length > hostIDX)
|
||||||
|
check_host_filter(hostIDX);
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_host_filters_cb()
|
||||||
|
{
|
||||||
|
hostIDX++;
|
||||||
|
if (hostList.length > hostIDX)
|
||||||
|
check_host_filter(hostIDX);
|
||||||
|
else
|
||||||
|
hostNextFX();
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_host_filter(i) {
|
||||||
var uri;
|
var uri;
|
||||||
var proxy;
|
dump("*** uri=" + hostList[i] + " bShouldBeFiltered=" + bShouldBeFiltered + "\n");
|
||||||
for (var i=0; i<hostList.length; i++) {
|
uri = ios.newURI(hostList[i], null, null);
|
||||||
dump("*** uri=" + hostList[i] + " bShouldBeFiltered=" + bShouldBeFiltered + "\n");
|
|
||||||
uri = ios.newURI(hostList, null, null);
|
var cb = new resolveCallback();
|
||||||
proxy = pps.resolve(uri, 0);
|
cb.nextFunction = host_filter_cb;
|
||||||
if (bShouldBeFiltered) {
|
var req = pps.asyncResolve(uri, 0, cb);
|
||||||
do_check_eq(proxy, null);
|
}
|
||||||
} else {
|
|
||||||
do_check_neq(proxy, null);
|
function host_filter_cb(proxy)
|
||||||
// Just to be sure, let's check that the proxy is correct
|
{
|
||||||
// - this should match the proxy setup in the calling function
|
if (bShouldBeFiltered) {
|
||||||
check_proxy(proxy, "http", "foopy", 8080, 0, -1, false);
|
do_check_eq(proxy, null);
|
||||||
}
|
} else {
|
||||||
|
do_check_neq(proxy, null);
|
||||||
|
// Just to be sure, let's check that the proxy is correct
|
||||||
|
// - this should match the proxy setup in the calling function
|
||||||
|
check_proxy(proxy, "http", "foopy", 8080, 0, -1, false);
|
||||||
}
|
}
|
||||||
|
check_host_filters_cb();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Verify that hists in the host filter list are not proxied
|
// Verify that hists in the host filter list are not proxied
|
||||||
// refers to "network.proxy.no_proxies_on"
|
// refers to "network.proxy.no_proxies_on"
|
||||||
|
|
||||||
|
var uriStrUseProxyList;
|
||||||
|
var uriStrUseProxyList;
|
||||||
|
var hostFilterList;
|
||||||
|
|
||||||
function run_proxy_host_filters_test() {
|
function run_proxy_host_filters_test() {
|
||||||
// Get prefs object from DOM
|
// Get prefs object from DOM
|
||||||
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
|
|
||||||
.getService(Components.interfaces.nsIPrefBranch);
|
|
||||||
// Setup a basic HTTP proxy configuration
|
// Setup a basic HTTP proxy configuration
|
||||||
// - pps.resolve() needs this to return proxy info for non-filtered hosts
|
// - pps.resolve() needs this to return proxy info for non-filtered hosts
|
||||||
prefs.setIntPref("network.proxy.type", 1);
|
prefs.setIntPref("network.proxy.type", 1);
|
||||||
@ -425,39 +508,51 @@ function run_proxy_host_filters_test() {
|
|||||||
prefs.setIntPref("network.proxy.http_port", 8080);
|
prefs.setIntPref("network.proxy.http_port", 8080);
|
||||||
|
|
||||||
// Setup host filter list string for "no_proxies_on"
|
// Setup host filter list string for "no_proxies_on"
|
||||||
var hostFilterList = "www.mozilla.org, www.google.com, www.apple.com, "
|
hostFilterList = "www.mozilla.org, www.google.com, www.apple.com, "
|
||||||
+ ".domain, .domain2.org"
|
+ ".domain, .domain2.org"
|
||||||
prefs.setCharPref("network.proxy.no_proxies_on", hostFilterList);
|
prefs.setCharPref("network.proxy.no_proxies_on", hostFilterList);
|
||||||
do_check_eq(prefs.getCharPref("network.proxy.no_proxies_on"), hostFilterList);
|
do_check_eq(prefs.getCharPref("network.proxy.no_proxies_on"), hostFilterList);
|
||||||
|
|
||||||
var rv;
|
var rv;
|
||||||
// Check the hosts that should be filtered out
|
// Check the hosts that should be filtered out
|
||||||
var uriStrFilterList = [ "http://www.mozilla.org/",
|
uriStrFilterList = [ "http://www.mozilla.org/",
|
||||||
"http://www.google.com/",
|
"http://www.google.com/",
|
||||||
"http://www.apple.com/",
|
"http://www.apple.com/",
|
||||||
"http://somehost.domain/",
|
"http://somehost.domain/",
|
||||||
"http://someotherhost.domain/",
|
"http://someotherhost.domain/",
|
||||||
"http://somehost.domain2.org/",
|
"http://somehost.domain2.org/",
|
||||||
"http://somehost.subdomain.domain2.org/" ];
|
"http://somehost.subdomain.domain2.org/" ];
|
||||||
check_host_filters(uriStrFilterList, true);
|
check_host_filters(uriStrFilterList, true, host_filters_1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function host_filters_1()
|
||||||
|
{
|
||||||
// Check the hosts that should be proxied
|
// Check the hosts that should be proxied
|
||||||
var uriStrUseProxyList = [ "http://www.mozilla.com/",
|
uriStrUseProxyList = [ "http://www.mozilla.com/",
|
||||||
"http://mail.google.com/",
|
"http://mail.google.com/",
|
||||||
"http://somehost.domain.co.uk/",
|
"http://somehost.domain.co.uk/",
|
||||||
"http://somelocalhost/" ];
|
"http://somelocalhost/" ];
|
||||||
check_host_filters(uriStrUseProxyList, false);
|
check_host_filters(uriStrUseProxyList, false, host_filters_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function host_filters_2()
|
||||||
|
{
|
||||||
// Set no_proxies_on to include local hosts
|
// Set no_proxies_on to include local hosts
|
||||||
prefs.setCharPref("network.proxy.no_proxies_on", hostFilterList + ", <local>");
|
prefs.setCharPref("network.proxy.no_proxies_on", hostFilterList + ", <local>");
|
||||||
do_check_eq(prefs.getCharPref("network.proxy.no_proxies_on"),
|
do_check_eq(prefs.getCharPref("network.proxy.no_proxies_on"),
|
||||||
hostFilterList + ", <local>");
|
hostFilterList + ", <local>");
|
||||||
|
|
||||||
// Amend lists - move local domain to filtered list
|
// Amend lists - move local domain to filtered list
|
||||||
uriStrFilterList.push(uriStrUseProxyList.pop());
|
uriStrFilterList.push(uriStrUseProxyList.pop());
|
||||||
check_host_filters(uriStrFilterList, true);
|
check_host_filters(uriStrFilterList, true, host_filters_3);
|
||||||
check_host_filters(uriStrUseProxyList, false);
|
}
|
||||||
|
|
||||||
|
function host_filters_3()
|
||||||
|
{
|
||||||
|
check_host_filters(uriStrUseProxyList, false, host_filters_4);
|
||||||
|
}
|
||||||
|
|
||||||
|
function host_filters_4()
|
||||||
|
{
|
||||||
// Cleanup
|
// Cleanup
|
||||||
prefs.setCharPref("network.proxy.no_proxies_on", "");
|
prefs.setCharPref("network.proxy.no_proxies_on", "");
|
||||||
do_check_eq(prefs.getCharPref("network.proxy.no_proxies_on"), "");
|
do_check_eq(prefs.getCharPref("network.proxy.no_proxies_on"), "");
|
||||||
@ -465,24 +560,44 @@ function run_proxy_host_filters_test() {
|
|||||||
do_test_finished();
|
do_test_finished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function run_deprecated_sync_test()
|
||||||
|
{
|
||||||
|
var uri = ios.newURI("http://www.mozilla.org/", null, null);
|
||||||
|
|
||||||
|
pps.QueryInterface(Components.interfaces.nsIProtocolProxyService2);
|
||||||
|
|
||||||
|
// Verify initial state
|
||||||
|
var pi = pps.deprecatedBlockingResolve(uri, 0);
|
||||||
|
do_check_eq(pi, null);
|
||||||
|
|
||||||
|
// Push a filter and verify the results
|
||||||
|
var filter1 = new BasicFilter();
|
||||||
|
var filter2 = new BasicFilter();
|
||||||
|
pps.registerFilter(filter1, 10);
|
||||||
|
pps.registerFilter(filter2, 20);
|
||||||
|
|
||||||
|
pi = pps.deprecatedBlockingResolve(uri, 0);
|
||||||
|
check_proxy(pi, "http", "localhost", 8080, 0, 10, true);
|
||||||
|
check_proxy(pi.failoverProxy, "direct", "", -1, 0, 0, false);
|
||||||
|
|
||||||
|
pps.unregisterFilter(filter2);
|
||||||
|
pi = pps.deprecatedBlockingResolve(uri, 0);
|
||||||
|
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(filter1);
|
||||||
|
pi = pps.deprecatedBlockingResolve(uri, 0);
|
||||||
|
do_check_eq(pi, null);
|
||||||
|
}
|
||||||
|
|
||||||
function run_test() {
|
function run_test() {
|
||||||
register_test_protocol_handler();
|
register_test_protocol_handler();
|
||||||
|
|
||||||
|
// any synchronous tests
|
||||||
|
run_deprecated_sync_test();
|
||||||
|
|
||||||
|
// start of asynchronous test chain
|
||||||
run_filter_test();
|
run_filter_test();
|
||||||
run_filter_test2();
|
do_test_pending();
|
||||||
run_pref_test();
|
|
||||||
run_pac_test();
|
|
||||||
// additional tests may be added to run_test_continued
|
|
||||||
}
|
|
||||||
|
|
||||||
function run_test_continued() {
|
|
||||||
run_pac_cancel_test();
|
|
||||||
// additional tests may be added to run_test_continued_3
|
|
||||||
}
|
|
||||||
|
|
||||||
function run_test_continued_2() {
|
|
||||||
run_filter_test3();
|
|
||||||
}
|
|
||||||
|
|
||||||
function run_test_continued_3() {
|
|
||||||
run_proxy_host_filters_test();
|
|
||||||
}
|
}
|
||||||
|
@ -33,24 +33,11 @@ function run_test()
|
|||||||
httpServer.registerPathHandler("/content", contentHandler);
|
httpServer.registerPathHandler("/content", contentHandler);
|
||||||
httpServer.start(4444);
|
httpServer.start(4444);
|
||||||
|
|
||||||
|
// we want to cancel the failover proxy engage, so, do not allow
|
||||||
|
// redirects from now.
|
||||||
|
|
||||||
var nc = new ChannelEventSink();
|
var nc = new ChannelEventSink();
|
||||||
var on_modify_request_count = 0;
|
nc._flags = ES_ABORT_REDIRECT;
|
||||||
|
|
||||||
modifyrequestobserver = {observe: function() {
|
|
||||||
// We get 2 on-modify-request notifications:
|
|
||||||
// 1. when proxy service resolves the proxy settings from PAC function
|
|
||||||
// 2. when we try to fail over the first proxy (moving to the second one)
|
|
||||||
//
|
|
||||||
// In the second case we want to cancel the proxy engage, so, do not allow
|
|
||||||
// redirects from now.
|
|
||||||
|
|
||||||
if (++on_modify_request_count == 2)
|
|
||||||
nc._flags = ES_ABORT_REDIRECT;
|
|
||||||
}}
|
|
||||||
|
|
||||||
var os = Cc["@mozilla.org/observer-service;1"].
|
|
||||||
getService(Ci.nsIObserverService);
|
|
||||||
os.addObserver(modifyrequestobserver, "http-on-modify-request", false);
|
|
||||||
|
|
||||||
var prefserv = Cc["@mozilla.org/preferences-service;1"].
|
var prefserv = Cc["@mozilla.org/preferences-service;1"].
|
||||||
getService(Ci.nsIPrefService);
|
getService(Ci.nsIPrefService);
|
||||||
|
@ -41,8 +41,16 @@ function run_test()
|
|||||||
"function FindProxyForURL(url, host) {return 'PROXY localhost:4444';}"
|
"function FindProxyForURL(url, host) {return 'PROXY localhost:4444';}"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// this test assumed that a AsyncOnChannelRedirect query is made for
|
||||||
|
// each proxy failover or on the inital proxy only when PAC mode is used.
|
||||||
|
// Neither of those are documented anywhere that I can find and the latter
|
||||||
|
// hasn't been a useful property because it is PAC dependent and the type
|
||||||
|
// is generally unknown and OS driven. 769764 changed that to remove the
|
||||||
|
// internal redirect used to setup the initial proxy/channel as that isn't
|
||||||
|
// a redirect in any sense.
|
||||||
|
|
||||||
var chan = make_channel("http://localhost:4444/content");
|
var chan = make_channel("http://localhost:4444/content");
|
||||||
chan.notificationCallbacks = new ChannelEventSink(ES_ABORT_REDIRECT);
|
|
||||||
chan.asyncOpen(new ChannelListener(finish_test, null, CL_EXPECT_FAILURE), null);
|
chan.asyncOpen(new ChannelListener(finish_test, null, CL_EXPECT_FAILURE), null);
|
||||||
|
chan.cancel(Cr.NS_BINDING_ABORTED);
|
||||||
do_test_pending();
|
do_test_pending();
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,33 @@
|
|||||||
testNum = 1;
|
testNum = 1;
|
||||||
|
|
||||||
var login, login2;
|
var login, login2;
|
||||||
function init() {
|
|
||||||
|
var resolveCallback = {
|
||||||
|
|
||||||
|
QueryInterface : function (iid) {
|
||||||
|
const interfaces = [Ci.nsIProtocolProxyCallback, Ci.nsISupports];
|
||||||
|
|
||||||
|
if (!interfaces.some( function(v) { return iid.equals(v) } ))
|
||||||
|
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
onProxyAvailable : function (req, uri, pi, status) {
|
||||||
|
init2(SpecialPowers.wrap(pi).host, SpecialPowers.wrap(pi).port);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function init1() {
|
||||||
var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
|
var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
|
||||||
var pps = Cc["@mozilla.org/network/protocol-proxy-service;1"].getService();
|
var pps = Cc["@mozilla.org/network/protocol-proxy-service;1"].getService();
|
||||||
|
|
||||||
var uri = ios.newURI("http://example.com", null, null);
|
var uri = ios.newURI("http://example.com", null, null);
|
||||||
var pi = pps.resolve(uri, 0);
|
pps.asyncResolve(uri, 0, resolveCallback);
|
||||||
var mozproxy = "moz-proxy://" + pi.host + ":" + pi.port;
|
}
|
||||||
|
|
||||||
|
function init2(proxyHost, proxyPort) {
|
||||||
|
|
||||||
|
var mozproxy = "moz-proxy://" + proxyHost + ":" + proxyPort;
|
||||||
|
|
||||||
var pwmgr = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
|
var pwmgr = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
|
||||||
login = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
|
login = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
|
||||||
@ -96,7 +116,7 @@
|
|||||||
var pendingTests = [{expectedDialogs: 2, test: testNonAnonymousCredentials},
|
var pendingTests = [{expectedDialogs: 2, test: testNonAnonymousCredentials},
|
||||||
{expectedDialogs: 1, test: testAnonymousCredentials},
|
{expectedDialogs: 1, test: testAnonymousCredentials},
|
||||||
{expectedDialogs: 0, test: testAnonymousNoAuth}];
|
{expectedDialogs: 0, test: testAnonymousNoAuth}];
|
||||||
init();
|
init1();
|
||||||
runNextTest();
|
runNextTest();
|
||||||
|
|
||||||
function handleDialog(doc, testNum)
|
function handleDialog(doc, testNum)
|
||||||
|
@ -23,19 +23,16 @@ Login Manager test: username/password prompts
|
|||||||
var pwmgr, ioService
|
var pwmgr, ioService
|
||||||
var tmplogin, login1, login2A, login2B, login2C, login2D, login2E, login3A, login3B, login4, proxyLogin;
|
var tmplogin, login1, login2A, login2B, login2C, login2D, login2E, login3A, login3B, login4, proxyLogin;
|
||||||
var mozproxy, proxiedHost = "http://mochi.test:8888";
|
var mozproxy, proxiedHost = "http://mochi.test:8888";
|
||||||
|
var testNum = 1;
|
||||||
|
|
||||||
function initLogins() {
|
function initLogins(pi) {
|
||||||
pwmgr = Cc["@mozilla.org/login-manager;1"].
|
pwmgr = Cc["@mozilla.org/login-manager;1"].
|
||||||
getService(Ci.nsILoginManager);
|
getService(Ci.nsILoginManager);
|
||||||
ioService = Cc["@mozilla.org/network/io-service;1"].
|
ioService = Cc["@mozilla.org/network/io-service;1"].
|
||||||
getService(Ci.nsIIOService);
|
getService(Ci.nsIIOService);
|
||||||
|
|
||||||
// Figure out what our proxy is set to -- can't just hardcode this, because
|
mozproxy = "moz-proxy://" + SpecialPowers.wrap(pi).host + ":" +
|
||||||
// mobile platforms don't use localhost.
|
SpecialPowers.wrap(pi).port;
|
||||||
var pps = Cc["@mozilla.org/network/protocol-proxy-service;1"].getService();
|
|
||||||
var uri = ioService.newURI(proxiedHost, null, null);
|
|
||||||
var pi = pps.resolve(uri, 0);
|
|
||||||
mozproxy = "moz-proxy://" + pi.host + ":" + pi.port;
|
|
||||||
|
|
||||||
tmpLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].
|
tmpLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].
|
||||||
createInstance(Ci.nsILoginInfo);
|
createInstance(Ci.nsILoginInfo);
|
||||||
@ -124,6 +121,35 @@ ok(true, "whee, done!");
|
|||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var resolveCallback = {
|
||||||
|
QueryInterface : function (iid) {
|
||||||
|
const interfaces = [Ci.nsIProtocolProxyCallback, Ci.nsISupports];
|
||||||
|
|
||||||
|
if (!interfaces.some( function(v) { return iid.equals(v) } ))
|
||||||
|
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
onProxyAvailable : function (req, uri, pi, status) {
|
||||||
|
initLogins(pi);
|
||||||
|
doTests();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function startup() {
|
||||||
|
//need to allow for arbitrary network servers defined in PAC instead of a hardcoded moz-proxy.
|
||||||
|
var ios = SpecialPowers.wrap(Components)
|
||||||
|
.classes["@mozilla.org/network/io-service;1"]
|
||||||
|
.getService(Components.interfaces.nsIIOService);
|
||||||
|
|
||||||
|
var pps = SpecialPowers.wrap(Components)
|
||||||
|
.classes["@mozilla.org/network/protocol-proxy-service;1"]
|
||||||
|
.getService();
|
||||||
|
|
||||||
|
var uri = ios.newURI("http://example.com", null, null);
|
||||||
|
pps.asyncResolve(uri, 0, resolveCallback);
|
||||||
|
}
|
||||||
|
|
||||||
function addNotificationCallback(cb)
|
function addNotificationCallback(cb)
|
||||||
{
|
{
|
||||||
storageObserver.notificationCallbacks.push(cb);
|
storageObserver.notificationCallbacks.push(cb);
|
||||||
@ -569,8 +595,9 @@ dumpNotifications();
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initLogins();
|
startup();
|
||||||
|
|
||||||
|
function doTests() {
|
||||||
var authinfo = {
|
var authinfo = {
|
||||||
username : "",
|
username : "",
|
||||||
password : "",
|
password : "",
|
||||||
@ -624,7 +651,7 @@ var popupNotifications = getPopupNotifications(window.top);
|
|||||||
ok(popupNotifications, "Got popupNotifications");
|
ok(popupNotifications, "Got popupNotifications");
|
||||||
|
|
||||||
// ===== test 1 =====
|
// ===== test 1 =====
|
||||||
var testNum = 1;
|
testNum = 1;
|
||||||
startCallbackTimer();
|
startCallbackTimer();
|
||||||
isOk = prompter1.prompt(dialogTitle(), dialogText, "http://example.com",
|
isOk = prompter1.prompt(dialogTitle(), dialogText, "http://example.com",
|
||||||
Ci.nsIAuthPrompt.SAVE_PASSWORD_NEVER, "abc", result);
|
Ci.nsIAuthPrompt.SAVE_PASSWORD_NEVER, "abc", result);
|
||||||
@ -1136,6 +1163,7 @@ iframe.src = "authenticate.sjs?user=mochiuser1&pass=mochipass1";
|
|||||||
|
|
||||||
// ...remaining tests are driven by handleLoad()...
|
// ...remaining tests are driven by handleLoad()...
|
||||||
SimpleTest.waitForExplicitFinish();
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</pre>
|
</pre>
|
||||||
</body>
|
</body>
|
||||||
|
@ -69,7 +69,7 @@
|
|||||||
|
|
||||||
var pwmgr, logins = [];
|
var pwmgr, logins = [];
|
||||||
|
|
||||||
function initLogins() {
|
function initLogins(pi) {
|
||||||
pwmgr = SpecialPowers.wrap(Components)
|
pwmgr = SpecialPowers.wrap(Components)
|
||||||
.classes["@mozilla.org/login-manager;1"]
|
.classes["@mozilla.org/login-manager;1"]
|
||||||
.getService(Ci.nsILoginManager);
|
.getService(Ci.nsILoginManager);
|
||||||
@ -83,18 +83,9 @@
|
|||||||
logins.push(login);
|
logins.push(login);
|
||||||
}
|
}
|
||||||
|
|
||||||
//need to allow for arbitrary network servers defined in PAC instead of a hardcoded moz-proxy.
|
var mozproxy = "moz-proxy://" +
|
||||||
var ios = SpecialPowers.wrap(Components)
|
SpecialPowers.wrap(pi).host + ":" +
|
||||||
.classes["@mozilla.org/network/io-service;1"]
|
SpecialPowers.wrap(pi).port;
|
||||||
.getService(Components.interfaces.nsIIOService);
|
|
||||||
|
|
||||||
var pps = SpecialPowers.wrap(Components)
|
|
||||||
.classes["@mozilla.org/network/protocol-proxy-service;1"]
|
|
||||||
.getService();
|
|
||||||
|
|
||||||
var uri = ios.newURI("http://example.com", null, null);
|
|
||||||
var pi = pps.resolve(uri, 0);
|
|
||||||
var mozproxy = "moz-proxy://" + pi.host + ":" + pi.port;
|
|
||||||
|
|
||||||
addLogin(mozproxy, "proxy_realm",
|
addLogin(mozproxy, "proxy_realm",
|
||||||
"proxy_user", "proxy_pass");
|
"proxy_user", "proxy_pass");
|
||||||
@ -134,6 +125,34 @@
|
|||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var resolveCallback = {
|
||||||
|
QueryInterface : function (iid) {
|
||||||
|
const interfaces = [Ci.nsIProtocolProxyCallback, Ci.nsISupports];
|
||||||
|
|
||||||
|
if (!interfaces.some( function(v) { return iid.equals(v) } ))
|
||||||
|
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
onProxyAvailable : function (req, uri, pi, status) {
|
||||||
|
initLogins(pi);
|
||||||
|
doTest(testNum);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function startup() {
|
||||||
|
//need to allow for arbitrary network servers defined in PAC instead of a hardcoded moz-proxy.
|
||||||
|
var ios = SpecialPowers.wrap(Components)
|
||||||
|
.classes["@mozilla.org/network/io-service;1"]
|
||||||
|
.getService(Components.interfaces.nsIIOService);
|
||||||
|
|
||||||
|
var pps = SpecialPowers.wrap(Components)
|
||||||
|
.classes["@mozilla.org/network/protocol-proxy-service;1"]
|
||||||
|
.getService();
|
||||||
|
|
||||||
|
var uri = ios.newURI("http://example.com", null, null);
|
||||||
|
pps.asyncResolve(uri, 0, resolveCallback);
|
||||||
|
}
|
||||||
|
|
||||||
// --------------- Test loop spin ----------------
|
// --------------- Test loop spin ----------------
|
||||||
var testNum = 1;
|
var testNum = 1;
|
||||||
@ -148,8 +167,7 @@
|
|||||||
iframe2a.onload = onFrameLoad;
|
iframe2a.onload = onFrameLoad;
|
||||||
iframe2b.onload = onFrameLoad;
|
iframe2b.onload = onFrameLoad;
|
||||||
|
|
||||||
initLogins();
|
startup();
|
||||||
doTest(testNum);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var expectedLoads;
|
var expectedLoads;
|
||||||
|
@ -34,7 +34,7 @@ public:
|
|||||||
nsresult GetAutoconfigURL(nsAutoCString& aResult) const;
|
nsresult GetAutoconfigURL(nsAutoCString& aResult) const;
|
||||||
|
|
||||||
// Find the SystemConfiguration proxy & port for a given URI
|
// Find the SystemConfiguration proxy & port for a given URI
|
||||||
nsresult FindSCProxyPort(nsIURI* aURI, nsACString& aResultHost, int32_t& aResultPort, bool& aResultSocksProxy);
|
nsresult FindSCProxyPort(const nsACString &aScheme, nsACString& aResultHost, int32_t& aResultPort, bool& aResultSocksProxy);
|
||||||
|
|
||||||
// is host:port on the proxy exception list?
|
// is host:port on the proxy exception list?
|
||||||
bool IsInExceptionList(const nsACString& aHost) const;
|
bool IsInExceptionList(const nsACString& aHost) const;
|
||||||
@ -58,7 +58,14 @@ private:
|
|||||||
static const SchemeMapping gSchemeMappingList[];
|
static const SchemeMapping gSchemeMappingList[];
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS1(nsOSXSystemProxySettings, nsISystemProxySettings)
|
NS_IMPL_THREADSAFE_ISUPPORTS1(nsOSXSystemProxySettings, nsISystemProxySettings)
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsOSXSystemProxySettings::GetMainThreadOnly(bool *aMainThreadOnly)
|
||||||
|
{
|
||||||
|
*aMainThreadOnly = false;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// Mapping of URI schemes to SystemConfiguration keys
|
// Mapping of URI schemes to SystemConfiguration keys
|
||||||
const nsOSXSystemProxySettings::SchemeMapping nsOSXSystemProxySettings::gSchemeMappingList[] = {
|
const nsOSXSystemProxySettings::SchemeMapping nsOSXSystemProxySettings::gSchemeMappingList[] = {
|
||||||
@ -156,7 +163,7 @@ nsOSXSystemProxySettings::ProxyHasChanged()
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsOSXSystemProxySettings::FindSCProxyPort(nsIURI* aURI, nsACString& aResultHost, int32_t& aResultPort, bool& aResultSocksProxy)
|
nsOSXSystemProxySettings::FindSCProxyPort(const nsACString &aScheme, nsACString& aResultHost, int32_t& aResultPort, bool& aResultSocksProxy)
|
||||||
{
|
{
|
||||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||||
|
|
||||||
@ -164,8 +171,8 @@ nsOSXSystemProxySettings::FindSCProxyPort(nsIURI* aURI, nsACString& aResultHost,
|
|||||||
|
|
||||||
for (const SchemeMapping* keys = gSchemeMappingList; keys->mScheme != NULL; ++keys) {
|
for (const SchemeMapping* keys = gSchemeMappingList; keys->mScheme != NULL; ++keys) {
|
||||||
// Check for matching scheme (when appropriate)
|
// Check for matching scheme (when appropriate)
|
||||||
bool res;
|
if (strcasecmp(keys->mScheme, PromiseFlatCString(aScheme).get()) &&
|
||||||
if ((NS_FAILED(aURI->SchemeIs(keys->mScheme, &res)) || !res) && !keys->mIsSocksProxy)
|
!keys->mIsSocksProxy)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Check the proxy is enabled
|
// Check the proxy is enabled
|
||||||
@ -303,20 +310,20 @@ nsOSXSystemProxySettings::GetPACURI(nsACString& aResult)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsOSXSystemProxySettings::GetProxyForURI(nsIURI* aURI, nsACString& aResult)
|
nsOSXSystemProxySettings::GetProxyForURI(const nsACString & aSpec,
|
||||||
|
const nsACString & aScheme,
|
||||||
|
const nsACString & aHost,
|
||||||
|
const int32_t aPort,
|
||||||
|
nsACString & aResult)
|
||||||
{
|
{
|
||||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||||
|
|
||||||
nsAutoCString host;
|
|
||||||
nsresult rv = aURI->GetHost(host);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
int32_t proxyPort;
|
int32_t proxyPort;
|
||||||
nsAutoCString proxyHost;
|
nsAutoCString proxyHost;
|
||||||
bool proxySocks;
|
bool proxySocks;
|
||||||
rv = FindSCProxyPort(aURI, proxyHost, proxyPort, proxySocks);
|
nsresult rv = FindSCProxyPort(aScheme, proxyHost, proxyPort, proxySocks);
|
||||||
|
|
||||||
if (NS_FAILED(rv) || IsInExceptionList(host)) {
|
if (NS_FAILED(rv) || IsInExceptionList(aHost)) {
|
||||||
aResult.AssignLiteral("DIRECT");
|
aResult.AssignLiteral("DIRECT");
|
||||||
} else if (proxySocks) {
|
} else if (proxySocks) {
|
||||||
aResult.Assign(NS_LITERAL_CSTRING("SOCKS ") + proxyHost + nsPrintfCString(":%d", proxyPort));
|
aResult.Assign(NS_LITERAL_CSTRING("SOCKS ") + proxyHost + nsPrintfCString(":%d", proxyPort));
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#include "nsISystemProxySettings.h"
|
#include "nsISystemProxySettings.h"
|
||||||
#include "mozilla/ModuleUtils.h"
|
#include "mozilla/ModuleUtils.h"
|
||||||
#include "nsIServiceManager.h"
|
#include "nsIServiceManager.h"
|
||||||
#include "nsIIOService.h"
|
|
||||||
#include "nsIURI.h"
|
#include "nsIURI.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
@ -34,7 +33,14 @@ private:
|
|||||||
pxProxyFactory *mProxyFactory;
|
pxProxyFactory *mProxyFactory;
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS1(nsUnixSystemProxySettings, nsISystemProxySettings)
|
NS_IMPL_THREADSAFE_ISUPPORTS1(nsUnixSystemProxySettings, nsISystemProxySettings)
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsUnixSystemProxySettings::GetMainThreadOnly(bool *aMainThreadOnly)
|
||||||
|
{
|
||||||
|
*aMainThreadOnly = false;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsUnixSystemProxySettings::Init()
|
nsUnixSystemProxySettings::Init()
|
||||||
@ -51,7 +57,11 @@ nsUnixSystemProxySettings::GetPACURI(nsACString& aResult)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsUnixSystemProxySettings::GetProxyForURI(nsIURI* aURI, nsACString& aResult)
|
nsUnixSystemProxySettings::GetProxyForURI(const nsACString & aSpec,
|
||||||
|
const nsACString & aScheme,
|
||||||
|
const nsACString & aHost,
|
||||||
|
const int32_t aPort,
|
||||||
|
nsACString & aResult)
|
||||||
{
|
{
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
@ -60,15 +70,9 @@ nsUnixSystemProxySettings::GetProxyForURI(nsIURI* aURI, nsACString& aResult)
|
|||||||
}
|
}
|
||||||
NS_ENSURE_TRUE(mProxyFactory, NS_ERROR_NOT_AVAILABLE);
|
NS_ENSURE_TRUE(mProxyFactory, NS_ERROR_NOT_AVAILABLE);
|
||||||
|
|
||||||
nsCOMPtr<nsIIOService> ios = do_GetIOService(&rv);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
nsAutoCString spec;
|
|
||||||
rv = aURI->GetSpec(spec);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
char **proxyArray = nullptr;
|
char **proxyArray = nullptr;
|
||||||
proxyArray = px_proxy_factory_get_proxies(mProxyFactory, (char*)(spec.get()));
|
proxyArray = px_proxy_factory_get_proxies(mProxyFactory,
|
||||||
|
PromiseFlatCString(aSpec).get());
|
||||||
NS_ENSURE_TRUE(proxyArray, NS_ERROR_NOT_AVAILABLE);
|
NS_ENSURE_TRUE(proxyArray, NS_ERROR_NOT_AVAILABLE);
|
||||||
|
|
||||||
// Translate libproxy's output to PAC string as expected
|
// Translate libproxy's output to PAC string as expected
|
||||||
@ -78,45 +82,34 @@ nsUnixSystemProxySettings::GetProxyForURI(nsIURI* aURI, nsACString& aResult)
|
|||||||
// direct://
|
// direct://
|
||||||
//
|
//
|
||||||
// PAC format: "PROXY proxy1.foo.com:8080; PROXY proxy2.foo.com:8080; DIRECT"
|
// PAC format: "PROXY proxy1.foo.com:8080; PROXY proxy2.foo.com:8080; DIRECT"
|
||||||
|
// but nsISystemProxySettings allows "PROXY http://proxy.foo.com:8080" as well.
|
||||||
|
|
||||||
int c = 0;
|
int c = 0;
|
||||||
while (proxyArray[c] != NULL) {
|
while (proxyArray[c] != NULL) {
|
||||||
if (!aResult.IsEmpty()) {
|
if (!aResult.IsEmpty()) {
|
||||||
aResult.AppendLiteral("; ");
|
aResult.AppendLiteral("; ");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isScheme = false;
|
// figure out the scheme, and we can't use nsIIOService::NewURI because
|
||||||
nsXPIDLCString schemeString;
|
// this is not the main thread.
|
||||||
nsXPIDLCString hostPortString;
|
char *colon = strchr (proxyArray[c], ':');
|
||||||
nsCOMPtr<nsIURI> proxyURI;
|
uint32_t schemelen = colon ? colon - proxyArray[c] : 0;
|
||||||
|
if (schemelen < 1) {
|
||||||
rv = ios->NewURI(nsDependentCString(proxyArray[c]),
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
getter_AddRefs(proxyURI));
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
c++;
|
c++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
proxyURI->GetScheme(schemeString);
|
if (schemelen == 6 && !strncasecmp(proxyArray[c], "direct", 6)) {
|
||||||
if (NS_SUCCEEDED(proxyURI->SchemeIs("http", &isScheme)) && isScheme) {
|
aResult.AppendLiteral("DIRECT");
|
||||||
schemeString.AssignLiteral("proxy");
|
|
||||||
}
|
}
|
||||||
aResult.Append(schemeString);
|
else {
|
||||||
if (NS_SUCCEEDED(proxyURI->SchemeIs("direct", &isScheme)) && !isScheme) {
|
aResult.AppendLiteral("PROXY ");
|
||||||
// Add the proxy URI only if it's not DIRECT
|
aResult.Append(proxyArray[c]);
|
||||||
proxyURI->GetHostPort(hostPortString);
|
|
||||||
aResult.AppendLiteral(" ");
|
|
||||||
aResult.Append(hostPortString);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("returned PAC proxy string: %s\n", PromiseFlatCString(aResult).get());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PR_Free(proxyArray);
|
PR_Free(proxyArray);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "nsIGSettingsService.h"
|
#include "nsIGSettingsService.h"
|
||||||
#include "nsInterfaceHashtable.h"
|
#include "nsInterfaceHashtable.h"
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "nsIURI.h"
|
||||||
|
|
||||||
class nsUnixSystemProxySettings MOZ_FINAL : public nsISystemProxySettings {
|
class nsUnixSystemProxySettings MOZ_FINAL : public nsISystemProxySettings {
|
||||||
public:
|
public:
|
||||||
@ -43,6 +44,14 @@ private:
|
|||||||
|
|
||||||
NS_IMPL_ISUPPORTS1(nsUnixSystemProxySettings, nsISystemProxySettings)
|
NS_IMPL_ISUPPORTS1(nsUnixSystemProxySettings, nsISystemProxySettings)
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsUnixSystemProxySettings::GetMainThreadOnly(bool *aMainThreadOnly)
|
||||||
|
{
|
||||||
|
// dbus prevents us from being threadsafe, but this routine should not block anyhow
|
||||||
|
*aMainThreadOnly = true;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsUnixSystemProxySettings::Init()
|
nsUnixSystemProxySettings::Init()
|
||||||
{
|
{
|
||||||
@ -151,8 +160,10 @@ static void SetProxyResult(const char* aType, const nsACString& aHost,
|
|||||||
aResult.AppendASCII(aType);
|
aResult.AppendASCII(aType);
|
||||||
aResult.Append(' ');
|
aResult.Append(' ');
|
||||||
aResult.Append(aHost);
|
aResult.Append(aHost);
|
||||||
aResult.Append(':');
|
if (aPort > 0) {
|
||||||
aResult.Append(nsPrintfCString("%d", aPort));
|
aResult.Append(':');
|
||||||
|
aResult.Append(nsPrintfCString("%d", aPort));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static nsresult
|
static nsresult
|
||||||
@ -481,29 +492,21 @@ nsUnixSystemProxySettings::GetProxyFromGSettings(const nsACString& aScheme,
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsUnixSystemProxySettings::GetProxyForURI(nsIURI* aURI, nsACString& aResult)
|
nsUnixSystemProxySettings::GetProxyForURI(const nsACString & aSpec,
|
||||||
|
const nsACString & aScheme,
|
||||||
|
const nsACString & aHost,
|
||||||
|
const int32_t aPort,
|
||||||
|
nsACString & aResult)
|
||||||
{
|
{
|
||||||
nsAutoCString scheme;
|
|
||||||
nsresult rv = aURI->GetScheme(scheme);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
nsAutoCString host;
|
|
||||||
rv = aURI->GetHost(host);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
int32_t port;
|
|
||||||
rv = aURI->GetPort(&port);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
if (mProxySettings) {
|
if (mProxySettings) {
|
||||||
rv = GetProxyFromGSettings(scheme, host, port, aResult);
|
nsresult rv = GetProxyFromGSettings(aScheme, aHost, aPort, aResult);
|
||||||
if (rv == NS_OK)
|
if (NS_SUCCEEDED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
if (mGConf)
|
if (mGConf)
|
||||||
return GetProxyFromGConf(scheme, host, port, aResult);
|
return GetProxyFromGConf(aScheme, aHost, aPort, aResult);
|
||||||
|
|
||||||
return GetProxyFromEnvironment(scheme, host, port, aResult);
|
return GetProxyFromEnvironment(aScheme, aHost, aPort, aResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NS_UNIXSYSTEMPROXYSERVICE_CID /* 0fa3158c-d5a7-43de-9181-a285e74cf1d4 */\
|
#define NS_UNIXSYSTEMPROXYSERVICE_CID /* 0fa3158c-d5a7-43de-9181-a285e74cf1d4 */\
|
||||||
|
@ -32,7 +32,15 @@ private:
|
|||||||
bool PatternMatch(const nsACString& aHost, const nsACString& aOverride);
|
bool PatternMatch(const nsACString& aHost, const nsACString& aOverride);
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS1(nsWindowsSystemProxySettings, nsISystemProxySettings)
|
NS_IMPL_THREADSAFE_ISUPPORTS1(nsWindowsSystemProxySettings, nsISystemProxySettings)
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsWindowsSystemProxySettings::GetMainThreadOnly(bool *aMainThreadOnly)
|
||||||
|
{
|
||||||
|
*aMainThreadOnly = false;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsWindowsSystemProxySettings::Init()
|
nsWindowsSystemProxySettings::Init()
|
||||||
@ -40,33 +48,12 @@ nsWindowsSystemProxySettings::Init()
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetProxyResult(const char* aType, const nsACString& aHost,
|
|
||||||
int32_t aPort, nsACString& aResult)
|
|
||||||
{
|
|
||||||
aResult.AssignASCII(aType);
|
|
||||||
aResult.Append(' ');
|
|
||||||
aResult.Append(aHost);
|
|
||||||
aResult.Append(':');
|
|
||||||
aResult.Append(nsPrintfCString("%d", aPort));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void SetProxyResult(const char* aType, const nsACString& aHostPort,
|
static void SetProxyResult(const char* aType, const nsACString& aHostPort,
|
||||||
nsACString& aResult)
|
nsACString& aResult)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIURI> uri;
|
aResult.AssignASCII(aType);
|
||||||
nsAutoCString host;
|
aResult.Append(' ');
|
||||||
int32_t port;
|
aResult.Append(aHostPort);
|
||||||
|
|
||||||
// Try parsing it as a URI.
|
|
||||||
if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), aHostPort)) &&
|
|
||||||
NS_SUCCEEDED(uri->GetHost(host)) && !host.IsEmpty() &&
|
|
||||||
NS_SUCCEEDED(uri->GetPort(&port))) {
|
|
||||||
SetProxyResult(aType, host, port, aResult);
|
|
||||||
} else {
|
|
||||||
aResult.AssignASCII(aType);
|
|
||||||
aResult.Append(' ');
|
|
||||||
aResult.Append(aHostPort);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetProxyResultDirect(nsACString& aResult)
|
static void SetProxyResultDirect(nsACString& aResult)
|
||||||
@ -222,7 +209,11 @@ nsWindowsSystemProxySettings::GetPACURI(nsACString& aResult)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsWindowsSystemProxySettings::GetProxyForURI(nsIURI* aURI, nsACString& aResult)
|
nsWindowsSystemProxySettings::GetProxyForURI(const nsACString & aSpec,
|
||||||
|
const nsACString & aScheme,
|
||||||
|
const nsACString & aHost,
|
||||||
|
const int32_t aPort,
|
||||||
|
nsACString & aResult)
|
||||||
{
|
{
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
@ -234,15 +225,7 @@ nsWindowsSystemProxySettings::GetProxyForURI(nsIURI* aURI, nsACString& aResult)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsAutoCString scheme;
|
if (MatchOverride(aHost)) {
|
||||||
rv = aURI->GetScheme(scheme);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
nsAutoCString host;
|
|
||||||
rv = aURI->GetHost(host);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
if (MatchOverride(host)) {
|
|
||||||
SetProxyResultDirect(aResult);
|
SetProxyResultDirect(aResult);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -250,7 +233,7 @@ nsWindowsSystemProxySettings::GetProxyForURI(nsIURI* aURI, nsACString& aResult)
|
|||||||
NS_ConvertUTF16toUTF8 cbuf(buf);
|
NS_ConvertUTF16toUTF8 cbuf(buf);
|
||||||
|
|
||||||
nsAutoCString prefix;
|
nsAutoCString prefix;
|
||||||
ToLowerCase(scheme, prefix);
|
ToLowerCase(aScheme, prefix);
|
||||||
|
|
||||||
prefix.Append('=');
|
prefix.Append('=');
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user