зеркало из https://github.com/mozilla/gecko-dev.git
Backout 3182f9d08c2d (bug 347307), 2a30593cca79 (bug 507578), b87b27f5a417 (bug 769764) for m-oth permaorange in browser_463205.js
This commit is contained in:
Родитель
127870c935
Коммит
483772a3a4
|
@ -366,6 +366,8 @@
|
|||
@BINPATH@/components/nsHelperAppDlg.js
|
||||
@BINPATH@/components/nsDownloadManagerUI.manifest
|
||||
@BINPATH@/components/nsDownloadManagerUI.js
|
||||
@BINPATH@/components/nsProxyAutoConfig.manifest
|
||||
@BINPATH@/components/nsProxyAutoConfig.js
|
||||
@BINPATH@/components/NetworkGeolocationProvider.manifest
|
||||
@BINPATH@/components/NetworkGeolocationProvider.js
|
||||
@BINPATH@/components/GPSDGeolocationProvider.manifest
|
||||
|
|
|
@ -361,6 +361,8 @@
|
|||
@BINPATH@/components/nsHelperAppDlg.js
|
||||
@BINPATH@/components/nsDownloadManagerUI.manifest
|
||||
@BINPATH@/components/nsDownloadManagerUI.js
|
||||
@BINPATH@/components/nsProxyAutoConfig.manifest
|
||||
@BINPATH@/components/nsProxyAutoConfig.js
|
||||
@BINPATH@/components/NetworkGeolocationProvider.manifest
|
||||
@BINPATH@/components/NetworkGeolocationProvider.js
|
||||
@BINPATH@/components/GPSDGeolocationProvider.manifest
|
||||
|
|
|
@ -87,8 +87,6 @@ components/xpcom.xpt
|
|||
components/xpti.dat
|
||||
components/xptitemp.dat
|
||||
components/nsMicrosummaryService.js
|
||||
components/nsProxyAutoConfig.manifest
|
||||
components/nsProxyAutoConfig.js
|
||||
D3DCompiler_42.dll
|
||||
d3dx9_42.dll
|
||||
defaults/pref/all.js
|
||||
|
@ -923,7 +921,6 @@ xpicleanup@BIN_SUFFIX@
|
|||
components/nsPlacesExpiration.js
|
||||
components/nsPrivateBrowsingService.js
|
||||
components/nsPrompter.js
|
||||
components/nsProxyAutoConfig.manifest
|
||||
components/nsProxyAutoConfig.js
|
||||
components/nsSafebrowsingApplication.js
|
||||
components/nsSearchService.js
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include "nsIURL.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsIProtocolProxyService2.h"
|
||||
#include "nsIProtocolProxyService.h"
|
||||
#include "nsIStreamConverterService.h"
|
||||
#include "nsIFile.h"
|
||||
#if defined(XP_MACOSX)
|
||||
|
@ -743,17 +743,12 @@ nsresult nsPluginHost::FindProxyForURL(const char* url, char* *result)
|
|||
|
||||
nsCOMPtr<nsIURI> uriIn;
|
||||
nsCOMPtr<nsIProtocolProxyService> proxyService;
|
||||
nsCOMPtr<nsIProtocolProxyService2> proxyService2;
|
||||
nsCOMPtr<nsIIOService> ioService;
|
||||
|
||||
proxyService = do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &res);
|
||||
if (NS_FAILED(res) || !proxyService)
|
||||
return res;
|
||||
|
||||
proxyService2 = do_QueryInterface(proxyService, &res);
|
||||
if (NS_FAILED(res) || !proxyService)
|
||||
return res;
|
||||
|
||||
ioService = do_GetService(NS_IOSERVICE_CONTRACTID, &res);
|
||||
if (NS_FAILED(res) || !ioService)
|
||||
return res;
|
||||
|
@ -765,8 +760,7 @@ nsresult nsPluginHost::FindProxyForURL(const char* url, char* *result)
|
|||
|
||||
nsCOMPtr<nsIProxyInfo> pi;
|
||||
|
||||
// Remove this with bug 778201
|
||||
res = proxyService2->DeprecatedBlockingResolve(uriIn, 0, getter_AddRefs(pi));
|
||||
res = proxyService->Resolve(uriIn, 0, getter_AddRefs(pi));
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
|
||||
|
|
|
@ -275,6 +275,8 @@
|
|||
@BINPATH@/components/nsHelperAppDlg.js
|
||||
@BINPATH@/components/nsDownloadManagerUI.manifest
|
||||
@BINPATH@/components/nsDownloadManagerUI.js
|
||||
@BINPATH@/components/nsProxyAutoConfig.manifest
|
||||
@BINPATH@/components/nsProxyAutoConfig.js
|
||||
@BINPATH@/components/NetworkGeolocationProvider.manifest
|
||||
@BINPATH@/components/NetworkGeolocationProvider.js
|
||||
@BINPATH@/components/GPSDGeolocationProvider.manifest
|
||||
|
|
|
@ -342,6 +342,8 @@
|
|||
@BINPATH@/components/nsHelperAppDlg.js
|
||||
@BINPATH@/components/nsDownloadManagerUI.manifest
|
||||
@BINPATH@/components/nsDownloadManagerUI.js
|
||||
@BINPATH@/components/nsProxyAutoConfig.manifest
|
||||
@BINPATH@/components/nsProxyAutoConfig.js
|
||||
@BINPATH@/components/NetworkGeolocationProvider.manifest
|
||||
@BINPATH@/components/NetworkGeolocationProvider.js
|
||||
@BINPATH@/components/GPSDGeolocationProvider.manifest
|
||||
|
|
|
@ -1122,9 +1122,6 @@ pref("network.dns.ipv4OnlyDomains", "");
|
|||
// This preference can be used to turn off IPv6 name lookups. See bug 68796.
|
||||
pref("network.dns.disableIPv6", false);
|
||||
|
||||
// This preference can be used to turn off DNS prefetch.
|
||||
pref("network.dns.disablePrefetch", false);
|
||||
|
||||
// This preference controls whether or not URLs with UTF-8 characters are
|
||||
// escaped. Set this preference to TRUE for strict RFC2396 conformance.
|
||||
pref("network.standard-url.escape-utf8", true);
|
||||
|
|
|
@ -66,6 +66,7 @@ XPIDLSRCS = \
|
|||
nsIProtocolProxyFilter.idl \
|
||||
nsIProtocolProxyCallback.idl \
|
||||
nsIProxiedProtocolHandler.idl \
|
||||
nsIProxyAutoConfig.idl \
|
||||
nsIProxyInfo.idl \
|
||||
nsITransport.idl \
|
||||
nsISocketTransport.idl \
|
||||
|
|
|
@ -17,10 +17,24 @@ interface nsIURI;
|
|||
* nsIProtocolProxyService provides methods to access information about
|
||||
* various network proxies.
|
||||
*/
|
||||
[scriptable, uuid(e77c642b-026f-41ce-9b23-f829a6e3f300)]
|
||||
[scriptable, uuid(d7ec6237-162e-40f5-a2b4-46ccd5fa83c9)]
|
||||
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
|
||||
|
@ -63,9 +77,9 @@ interface nsIProtocolProxyService : nsISupports
|
|||
const unsigned long RESOLVE_ALWAYS_TUNNEL = (1 << 4);
|
||||
|
||||
/**
|
||||
* This method returns via callback a nsIProxyInfo instance that identifies
|
||||
* a proxy to be used for loading the given URI. Otherwise, this method returns
|
||||
* null indicating that a direct connection should be used.
|
||||
* This method returns a nsIProxyInfo instance that identifies a proxy to
|
||||
* be used for loading the given URI. Otherwise, this method returns null
|
||||
* indicating that a direct connection should be used.
|
||||
*
|
||||
* @param aURI
|
||||
* The URI to test.
|
||||
|
@ -73,12 +87,6 @@ interface nsIProtocolProxyService : nsISupports
|
|||
* A bit-wise combination of the RESOLVE_ flags defined above. Pass
|
||||
* 0 to specify the default behavior. Any additional bits that do
|
||||
* not correspond to a RESOLVE_ flag are reserved for future use.
|
||||
* @param aCallback
|
||||
* The object to be notified when the result is available.
|
||||
*
|
||||
* @return An object that can be used to cancel the asychronous operation.
|
||||
* If canceled, the cancelation status (aReason) will be forwarded
|
||||
* 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.
|
||||
|
@ -92,8 +100,35 @@ interface nsIProtocolProxyService : nsISupports
|
|||
* 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
|
||||
* 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.
|
||||
* @param aCallback
|
||||
* The object to be notified when the result is available.
|
||||
*
|
||||
* @return An object that can be used to cancel the asychronous operation.
|
||||
* If canceled, the cancelation status (aReason) will be forwarded
|
||||
* to the callback's onProxyAvailable method via the aStatus param.
|
||||
*/
|
||||
nsICancelable asyncResolve(in nsIURI aURI, in unsigned long aFlags,
|
||||
in nsIProtocolProxyCallback aCallback);
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
/**
|
||||
* An extension of nsIProtocolProxyService
|
||||
*/
|
||||
[scriptable, uuid(bed3702d-9374-4804-a20f-32baed8e2954)]
|
||||
[scriptable, uuid(dbd9565d-29b1-437a-bff5-2fc339e2c5df)]
|
||||
interface nsIProtocolProxyService2 : nsIProtocolProxyService
|
||||
{
|
||||
/**
|
||||
|
@ -17,13 +17,4 @@ interface nsIProtocolProxyService2 : nsIProtocolProxyService
|
|||
* reloaded. The PAC file is loaded asynchronously.
|
||||
*/
|
||||
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,26 +9,12 @@ interface nsIChannel;
|
|||
interface nsIURI;
|
||||
interface nsIProxyInfo;
|
||||
|
||||
[scriptable, uuid(2b63fe69-b0fc-48f2-a2df-adb795a4ce5c)]
|
||||
[scriptable, uuid(0a24fed4-1dd2-11b2-a75c-9f8b9a8f9ba7)]
|
||||
interface nsIProxiedProtocolHandler : nsIProtocolHandler
|
||||
{
|
||||
/** 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,
|
||||
in unsigned long proxyResolveFlags,
|
||||
in nsIURI proxyURI);
|
||||
nsIChannel newProxiedChannel(in nsIURI uri, in nsIProxyInfo proxyInfo);
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/* -*- 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,31 +13,17 @@
|
|||
* 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.
|
||||
*/
|
||||
[scriptable, uuid(971591cd-277e-409a-bbf6-0a79879cd307)]
|
||||
[scriptable, uuid(a9f3ae38-b769-4e0b-9317-578388e326c9)]
|
||||
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.
|
||||
*/
|
||||
readonly attribute AUTF8String PACURI;
|
||||
|
||||
/**
|
||||
* See ProxyAutoConfig::getProxyForURI; this function behaves similarly except
|
||||
* 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"
|
||||
* See nsIProxyAutoConfig::getProxyForURI; this function behaves exactly
|
||||
* the same way.
|
||||
*/
|
||||
AUTF8String getProxyForURI(in AUTF8String testSpec,
|
||||
in AUTF8String testScheme,
|
||||
in AUTF8String testHost,
|
||||
in int32_t testPort);
|
||||
AUTF8String getProxyForURI(in nsIURI aURI);
|
||||
};
|
||||
|
|
|
@ -851,6 +851,40 @@ NS_GetReferrerFromChannel(nsIChannel *channel,
|
|||
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
|
||||
NS_ParseContentType(const nsACString &rawContentType,
|
||||
nsCString &contentType,
|
||||
|
|
|
@ -66,11 +66,8 @@ CPPSRCS = \
|
|||
RedirectChannelRegistrar.cpp \
|
||||
nsPreloadedStream.cpp \
|
||||
nsStreamListenerWrapper.cpp \
|
||||
ProxyAutoConfig.cpp \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/dom/base
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
|
||||
CPPSRCS += nsURLHelperOS2.cpp
|
||||
else
|
||||
|
@ -100,6 +97,11 @@ ifdef MOZ_ENABLE_QTNETWORK
|
|||
endif
|
||||
endif
|
||||
|
||||
EXTRA_COMPONENTS = \
|
||||
$(srcdir)/nsProxyAutoConfig.js \
|
||||
$(srcdir)/nsProxyAutoConfig.manifest \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
NetUtil.jsm \
|
||||
$(NULL)
|
||||
|
|
|
@ -1,790 +0,0 @@
|
|||
/* -*- 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 "nsICancelable.h"
|
||||
#include "nsIDNSListener.h"
|
||||
#include "nsIDNSRecord.h"
|
||||
#include "nsIDNSService.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "prnetdb.h"
|
||||
#include "nsITimer.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"
|
||||
"";
|
||||
|
||||
// sRunning is defined for the helper functions only while the
|
||||
// Javascript engine is running and the PAC object cannot be deleted
|
||||
// or reset.
|
||||
static ProxyAutoConfig *sRunning = nullptr;
|
||||
|
||||
// The PACResolver is used for dnsResolve()
|
||||
class PACResolver MOZ_FINAL : public nsIDNSListener
|
||||
, public nsITimerCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
PACResolver()
|
||||
: mStatus(NS_ERROR_FAILURE)
|
||||
{
|
||||
}
|
||||
|
||||
// nsIDNSListener
|
||||
NS_IMETHODIMP OnLookupComplete(nsICancelable *request,
|
||||
nsIDNSRecord *record,
|
||||
nsresult status)
|
||||
{
|
||||
if (mTimer) {
|
||||
mTimer->Cancel();
|
||||
mTimer = nullptr;
|
||||
}
|
||||
|
||||
mRequest = nullptr;
|
||||
mStatus = status;
|
||||
mResponse = record;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsITimerCallback
|
||||
NS_IMETHODIMP Notify(nsITimer *timer)
|
||||
{
|
||||
if (mRequest)
|
||||
mRequest->Cancel(NS_ERROR_NET_TIMEOUT);
|
||||
mTimer = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult mStatus;
|
||||
nsCOMPtr<nsICancelable> mRequest;
|
||||
nsCOMPtr<nsIDNSRecord> mResponse;
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
};
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(PACResolver, nsIDNSListener, nsITimerCallback)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// timeout of 0 means the normal necko timeout strategy, otherwise the dns request
|
||||
// will be canceled after aTimeout milliseconds
|
||||
static
|
||||
JSBool PACResolve(const nsCString &aHostName, PRNetAddr *aNetAddr,
|
||||
unsigned int aTimeout)
|
||||
{
|
||||
if (!sRunning) {
|
||||
NS_WARNING("PACResolve without a running ProxyAutoConfig object");
|
||||
return false;
|
||||
}
|
||||
|
||||
return sRunning->ResolveAddress(aHostName, aNetAddr, aTimeout);
|
||||
}
|
||||
|
||||
bool
|
||||
ProxyAutoConfig::ResolveAddress(const nsCString &aHostName,
|
||||
PRNetAddr *aNetAddr,
|
||||
unsigned int aTimeout)
|
||||
{
|
||||
nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID);
|
||||
if (!dns)
|
||||
return false;
|
||||
|
||||
nsRefPtr<PACResolver> helper = new PACResolver();
|
||||
|
||||
if (NS_FAILED(dns->AsyncResolve(aHostName, 0, helper,
|
||||
NS_GetCurrentThread(),
|
||||
getter_AddRefs(helper->mRequest))))
|
||||
return false;
|
||||
|
||||
if (aTimeout && helper->mRequest) {
|
||||
if (!mTimer)
|
||||
mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
|
||||
if (mTimer) {
|
||||
mTimer->InitWithCallback(helper, aTimeout, nsITimer::TYPE_ONE_SHOT);
|
||||
helper->mTimer = mTimer;
|
||||
}
|
||||
}
|
||||
|
||||
// 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->GetNextAddr(0, aNetAddr)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool PACResolveToString(const nsCString &aHostName,
|
||||
nsCString &aDottedDecimal,
|
||||
unsigned int aTimeout)
|
||||
{
|
||||
PRNetAddr netAddr;
|
||||
if (!PACResolve(aHostName, &netAddr, aTimeout))
|
||||
return false;
|
||||
|
||||
char dottedDecimal[128];
|
||||
if (PR_NetAddrToString(&netAddr, dottedDecimal, sizeof(dottedDecimal)) != PR_SUCCESS)
|
||||
return false;
|
||||
|
||||
aDottedDecimal.Assign(dottedDecimal);
|
||||
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;
|
||||
nsAutoCString dottedDecimal;
|
||||
|
||||
if (!hostName.init(cx, arg1))
|
||||
return false;
|
||||
if (!PACResolveToString(NS_ConvertUTF16toUTF8(hostName), dottedDecimal, 0))
|
||||
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;
|
||||
}
|
||||
|
||||
if (!sRunning) {
|
||||
NS_WARNING("PAC myIPAddress without a running ProxyAutoConfig object");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return sRunning->MyIPAddress(vp);
|
||||
}
|
||||
|
||||
// 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 (!sRunning)
|
||||
return SetupJS();
|
||||
|
||||
mJSNeedsSetup = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ProxyAutoConfig::SetupJS()
|
||||
{
|
||||
mJSNeedsSetup = false;
|
||||
NS_ABORT_IF_FALSE(!sRunning, "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 sRunning flag keeps a new PAC file from being installed
|
||||
// while the event loop is spinning on a DNS function. Don't early return.
|
||||
sRunning = this;
|
||||
mRunningHost = aTestHost;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mRunningHost.Truncate();
|
||||
sRunning = nullptr;
|
||||
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 (sRunning || mShutdown)
|
||||
return;
|
||||
|
||||
mShutdown = true;
|
||||
delete mJSRuntime;
|
||||
mJSRuntime = nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
ProxyAutoConfig::SrcAddress(const PRNetAddr *remoteAddress, nsCString &localAddress)
|
||||
{
|
||||
PRFileDesc *fd;
|
||||
fd = PR_OpenUDPSocket(remoteAddress->raw.family);
|
||||
if (!fd)
|
||||
return false;
|
||||
|
||||
if (PR_Connect(fd, remoteAddress, 0) != PR_SUCCESS) {
|
||||
PR_Close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
PRNetAddr localName;
|
||||
if (PR_GetSockName(fd, &localName) != PR_SUCCESS) {
|
||||
PR_Close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
PR_Close(fd);
|
||||
|
||||
char dottedDecimal[128];
|
||||
if (PR_NetAddrToString(&localName, dottedDecimal, sizeof(dottedDecimal)) != PR_SUCCESS)
|
||||
return false;
|
||||
|
||||
localAddress.Assign(dottedDecimal);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// hostName is run through a dns lookup and then a udp socket is connected
|
||||
// to the result. If that all works, the local IP address of the socket is
|
||||
// returned to the javascript caller and true is returned from this function.
|
||||
// otherwise false is returned.
|
||||
bool
|
||||
ProxyAutoConfig::MyIPAddressTryHost(const nsCString &hostName,
|
||||
unsigned int timeout,
|
||||
jsval *vp)
|
||||
{
|
||||
PRNetAddr remoteAddress;
|
||||
nsAutoCString localDottedDecimal;
|
||||
JSContext *cx = mJSRuntime->Context();
|
||||
|
||||
if (PACResolve(hostName, &remoteAddress, timeout) &&
|
||||
SrcAddress(&remoteAddress, localDottedDecimal)) {
|
||||
JSString *dottedDecimalString =
|
||||
JS_NewStringCopyZ(cx, localDottedDecimal.get());
|
||||
JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(dottedDecimalString));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ProxyAutoConfig::MyIPAddress(jsval *vp)
|
||||
{
|
||||
nsAutoCString remoteDottedDecimal;
|
||||
nsAutoCString localDottedDecimal;
|
||||
JSContext *cx = mJSRuntime->Context();
|
||||
|
||||
// first, lookup the local address of a socket connected
|
||||
// to the host of uri being resolved by the pac file. This is
|
||||
// v6 safe.. but is the last step like that
|
||||
if (MyIPAddressTryHost(mRunningHost, kTimeout, vp))
|
||||
return true;
|
||||
|
||||
// next, look for a route to a public internet address that doesn't need DNS.
|
||||
// This is the google anycast dns address, but it doesn't matter if it
|
||||
// remains operable (as we don't contact it) as long as the address stays
|
||||
// in commonly routed IP address space.
|
||||
remoteDottedDecimal.AssignLiteral("8.8.8.8");
|
||||
if (MyIPAddressTryHost(remoteDottedDecimal, 0, vp))
|
||||
return true;
|
||||
|
||||
// next, use the old algorithm based on the local hostname
|
||||
nsAutoCString hostName;
|
||||
nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID);
|
||||
if (dns && NS_SUCCEEDED(dns->GetMyHostName(hostName)) &&
|
||||
PACResolveToString(hostName, localDottedDecimal, kTimeout)) {
|
||||
JSString *dottedDecimalString =
|
||||
JS_NewStringCopyZ(cx, localDottedDecimal.get());
|
||||
JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(dottedDecimalString));
|
||||
return true;
|
||||
}
|
||||
|
||||
// next try a couple RFC 1918 variants.. maybe there is a
|
||||
// local route
|
||||
remoteDottedDecimal.AssignLiteral("192.168.0.1");
|
||||
if (MyIPAddressTryHost(remoteDottedDecimal, 0, vp))
|
||||
return true;
|
||||
|
||||
// more RFC 1918
|
||||
remoteDottedDecimal.AssignLiteral("10.0.0.1");
|
||||
if (MyIPAddressTryHost(remoteDottedDecimal, 0, vp))
|
||||
return true;
|
||||
|
||||
// who knows? let's fallback to localhost
|
||||
localDottedDecimal.AssignLiteral("127.0.0.1");
|
||||
JSString *dottedDecimalString =
|
||||
JS_NewStringCopyZ(cx, localDottedDecimal.get());
|
||||
JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(dottedDecimalString));
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace mozilla::net
|
|
@ -1,102 +0,0 @@
|
|||
/* -*- 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"
|
||||
#include "jsapi.h"
|
||||
#include "prio.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsAutoPtr.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)
|
||||
, mJSNeedsSetup(false)
|
||||
, mShutdown(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(ProxyAutoConfig);
|
||||
}
|
||||
~ProxyAutoConfig();
|
||||
|
||||
nsresult Init(const nsCString &aPACURI,
|
||||
const nsCString &aPACScript);
|
||||
void Shutdown();
|
||||
void GC();
|
||||
bool MyIPAddress(jsval *vp);
|
||||
bool ResolveAddress(const nsCString &aHostName,
|
||||
PRNetAddr *aNetAddr, unsigned int aTimeout);
|
||||
|
||||
/**
|
||||
* 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:
|
||||
const static unsigned int kTimeout = 1000; // ms to allow for myipaddress dns queries
|
||||
|
||||
// used to compile the PAC file and setup the execution context
|
||||
nsresult SetupJS();
|
||||
|
||||
bool SrcAddress(const PRNetAddr *remoteAddress, nsCString &localAddress);
|
||||
bool MyIPAddressTryHost(const nsCString &hostName, unsigned int timeout,
|
||||
jsval *vp);
|
||||
|
||||
JSRuntimeWrapper *mJSRuntime;
|
||||
bool mJSNeedsSetup;
|
||||
bool mShutdown;
|
||||
nsCString mPACScript;
|
||||
nsCString mPACURI;
|
||||
nsCString mRunningHost;
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
};
|
||||
|
||||
}} // namespace mozilla::net
|
||||
|
||||
#endif // ProxyAutoConfig_h__
|
|
@ -701,9 +701,7 @@ nsBaseChannel::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
|
|||
|
||||
SUSPEND_PUMP_FOR_SCOPE();
|
||||
|
||||
if (mListener) // null in case of redirect
|
||||
return mListener->OnStartRequest(this, mListenerContext);
|
||||
return NS_OK;
|
||||
return mListener->OnStartRequest(this, mListenerContext);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -718,8 +716,7 @@ nsBaseChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
|
|||
// Cause IsPending to return false.
|
||||
mPump = nullptr;
|
||||
|
||||
if (mListener) // null in case of redirect
|
||||
mListener->OnStopRequest(this, mListenerContext, mStatus);
|
||||
mListener->OnStopRequest(this, mListenerContext, mStatus);
|
||||
mListener = nullptr;
|
||||
mListenerContext = nullptr;
|
||||
|
||||
|
|
|
@ -39,9 +39,6 @@
|
|||
#include "nsIConsoleService.h"
|
||||
#include "nsIUploadChannel2.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "nsIProxiedChannel.h"
|
||||
#include "nsIProtocolProxyCallback.h"
|
||||
#include "nsICancelable.h"
|
||||
|
||||
#include "mozilla/FunctionTimer.h"
|
||||
|
||||
|
@ -579,6 +576,31 @@ nsIOService::NewChannelFromURI(nsIURI *aURI, nsIChannel **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
|
||||
nsIOService::NewChannelFromURIWithProxyFlags(nsIURI *aURI,
|
||||
nsIURI *aProxyURI,
|
||||
|
@ -603,11 +625,26 @@ nsIOService::NewChannelFromURIWithProxyFlags(nsIURI *aURI,
|
|||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIProxiedProtocolHandler> pph = do_QueryInterface(handler);
|
||||
if (pph)
|
||||
rv = pph->NewProxiedChannel(aURI, nullptr, aProxyFlags, aProxyURI, result);
|
||||
else
|
||||
rv = handler->NewChannel(aURI, result);
|
||||
// Talk to the PPS if the protocol handler allows proxying. Otherwise,
|
||||
// skip this step. This allows us to lazily load the PPS at startup.
|
||||
if (protoFlags & nsIProtocolHandler::ALLOWS_PROXY) {
|
||||
nsCOMPtr<nsIProxyInfo> pi;
|
||||
LookupProxyInfo(aURI, aProxyURI, aProxyFlags, &scheme, getter_AddRefs(pi));
|
||||
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);
|
||||
|
||||
// Some extensions override the http protocol handler and provide their own
|
||||
|
@ -1175,79 +1212,35 @@ nsIOService::ExtractCharsetFromContentType(const nsACString &aTypeHeader,
|
|||
}
|
||||
|
||||
// nsISpeculativeConnect
|
||||
class IOServiceProxyCallback MOZ_FINAL : public nsIProtocolProxyCallback
|
||||
{
|
||||
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)
|
||||
nsIOService::SpeculativeConnect(nsIURI *aURI,
|
||||
nsIInterfaceRequestor *aCallbacks,
|
||||
nsIEventTarget *aTarget)
|
||||
{
|
||||
// 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;
|
||||
nsresult rv = aURI->GetScheme(scheme);
|
||||
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;
|
||||
|
||||
nsCOMPtr<nsIProtocolHandler> handler;
|
||||
rv = mIOService->GetProtocolHandler(scheme.get(),
|
||||
getter_AddRefs(handler));
|
||||
rv = GetProtocolHandler(scheme.get(), getter_AddRefs(handler));
|
||||
if (NS_FAILED(rv))
|
||||
return NS_OK;
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsISpeculativeConnect> speculativeHandler =
|
||||
do_QueryInterface(handler);
|
||||
if (!speculativeHandler)
|
||||
return NS_OK;
|
||||
|
||||
speculativeHandler->SpeculativeConnect(aURI,
|
||||
mCallbacks,
|
||||
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));
|
||||
return speculativeHandler->SpeculativeConnect(aURI,
|
||||
aCallbacks,
|
||||
aTarget);
|
||||
}
|
||||
|
|
|
@ -6,24 +6,21 @@
|
|||
|
||||
#include "nsPACMan.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIDNSService.h"
|
||||
#include "nsIDNSListener.h"
|
||||
#include "nsICancelable.h"
|
||||
#include "nsIAuthPrompt.h"
|
||||
#include "nsIPromptFactory.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCRT.h"
|
||||
#include "prmon.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
|
||||
// a HTTP request. For other types of channels, just return true.
|
||||
|
@ -44,206 +41,100 @@ HttpRequestSucceeded(nsIStreamLoader *loader)
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// The ExecuteCallback runnable is triggered by
|
||||
// nsPACManCallback::OnQueryComplete on the Main thread when its completion is
|
||||
// discovered on the pac thread
|
||||
// These objects are stored in nsPACMan::mPendingQ
|
||||
|
||||
class ExecuteCallback MOZ_FINAL : public nsRunnable
|
||||
class PendingPACQuery MOZ_FINAL : public PRCList,
|
||||
public nsIDNSListener
|
||||
{
|
||||
public:
|
||||
ExecuteCallback(nsPACManCallback *aCallback,
|
||||
nsresult status)
|
||||
: mCallback(aCallback)
|
||||
, mStatus(status)
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDNSLISTENER
|
||||
|
||||
PendingPACQuery(nsPACMan *pacMan, nsIURI *uri, nsPACManCallback *callback)
|
||||
: mPACMan(pacMan)
|
||||
, mURI(uri)
|
||||
, mCallback(callback)
|
||||
{
|
||||
PR_INIT_CLIST(this);
|
||||
}
|
||||
|
||||
void SetPACString(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;
|
||||
}
|
||||
nsresult Start(uint32_t flags);
|
||||
void Complete(nsresult status, const nsCString &pacString);
|
||||
|
||||
private:
|
||||
nsPACMan *mPACMan; // weak reference
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsRefPtr<nsPACManCallback> mCallback;
|
||||
nsresult mStatus;
|
||||
nsCString mPACString;
|
||||
nsCString mPACURL;
|
||||
nsCOMPtr<nsICancelable> mDNSRequest;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// This is threadsafe because we implement nsIDNSListener
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(PendingPACQuery, nsIDNSListener)
|
||||
|
||||
// The PAC thread must be deleted from the main thread, this class
|
||||
// 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
|
||||
nsresult
|
||||
PendingPACQuery::Start(uint32_t flags)
|
||||
{
|
||||
public:
|
||||
ShutdownThread(nsIThread *thread)
|
||||
: mThread(thread)
|
||||
{
|
||||
if (mDNSRequest)
|
||||
return NS_OK; // already started
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP Run()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
|
||||
mThread->Shutdown();
|
||||
return NS_OK;
|
||||
}
|
||||
nsAutoCString host;
|
||||
rv = mURI->GetAsciiHost(host);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
};
|
||||
rv = dns->AsyncResolve(host, flags, this, NS_GetCurrentThread(),
|
||||
getter_AddRefs(mDNSRequest));
|
||||
if (NS_FAILED(rv))
|
||||
NS_WARNING("DNS AsyncResolve failed");
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// 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);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// This may be called before or after OnLookupComplete
|
||||
void
|
||||
PendingPACQuery::Complete(nsresult status, const nsCString &pacString)
|
||||
{
|
||||
if (!mCallback)
|
||||
return;
|
||||
nsRefPtr<ExecuteCallback> runnable = new ExecuteCallback(mCallback, status);
|
||||
runnable->SetPACString(pacString);
|
||||
if (mOnMainThreadOnly)
|
||||
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
|
||||
else
|
||||
runnable->Run();
|
||||
}
|
||||
|
||||
void
|
||||
PendingPACQuery::UseAlternatePACFile(const nsCString &pacURL)
|
||||
{
|
||||
if (!mCallback)
|
||||
return;
|
||||
mCallback->OnQueryComplete(status, pacString);
|
||||
mCallback = nullptr;
|
||||
|
||||
nsRefPtr<ExecuteCallback> runnable = new ExecuteCallback(mCallback, NS_OK);
|
||||
runnable->SetPACURL(pacURL);
|
||||
if (mOnMainThreadOnly)
|
||||
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
|
||||
else
|
||||
runnable->Run();
|
||||
if (mDNSRequest) {
|
||||
mDNSRequest->Cancel(NS_ERROR_ABORT);
|
||||
mDNSRequest = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PendingPACQuery::Run()
|
||||
PendingPACQuery::OnLookupComplete(nsICancelable *request,
|
||||
nsIDNSRecord *record,
|
||||
nsresult status)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(!NS_IsMainThread(), "wrong thread");
|
||||
mPACMan->PostQuery(this);
|
||||
// NOTE: we don't care about the results of this DNS query. We issued
|
||||
// this DNS query just to pre-populate our DNS cache.
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -252,87 +143,87 @@ PendingPACQuery::Run()
|
|||
nsPACMan::nsPACMan()
|
||||
: mLoadPending(false)
|
||||
, mShutdown(false)
|
||||
, mScheduledReload(LL_MAXINT)
|
||||
, mLoadFailureCount(0)
|
||||
, mInProgress(false)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(NS_IsMainThread(), "pacman must be created on main thread");
|
||||
PR_INIT_CLIST(&mPendingQ);
|
||||
}
|
||||
|
||||
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(mPendingQ.isEmpty(), "pac man not shutdown properly");
|
||||
NS_ASSERTION(mPAC == nullptr, "pac man not shutdown properly");
|
||||
NS_ASSERTION(PR_CLIST_IS_EMPTY(&mPendingQ), "pac man not shutdown properly");
|
||||
}
|
||||
|
||||
void
|
||||
nsPACMan::Shutdown()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(NS_IsMainThread(), "pacman must be shutdown on main thread");
|
||||
CancelExistingLoad();
|
||||
ProcessPendingQ(NS_ERROR_ABORT);
|
||||
|
||||
mPAC = nullptr;
|
||||
mShutdown = true;
|
||||
PostCancelPendingQ(NS_ERROR_ABORT);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPACMan::AsyncGetProxyForURI(nsIURI *uri, nsPACManCallback *callback,
|
||||
bool mainThreadResponse)
|
||||
nsPACMan::GetProxyForURI(nsIURI *uri, nsACString &result)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
|
||||
if (mShutdown)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
// Maybe Reload PAC
|
||||
if (mPACURI && !mScheduledReload.IsNull() &&
|
||||
TimeStamp::Now() > mScheduledReload)
|
||||
LoadPACFromURI(nullptr);
|
||||
|
||||
nsRefPtr<PendingPACQuery> query =
|
||||
new PendingPACQuery(this, uri, callback, mainThreadResponse);
|
||||
NS_ENSURE_STATE(!mShutdown);
|
||||
|
||||
if (IsPACURI(uri)) {
|
||||
// deal with this directly instead of queueing it
|
||||
query->Complete(NS_OK, EmptyCString());
|
||||
result.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return mPACThread->Dispatch(query, nsIEventTarget::DISPATCH_NORMAL);
|
||||
MaybeReloadPAC();
|
||||
|
||||
if (IsLoading())
|
||||
return NS_ERROR_IN_PROGRESS;
|
||||
if (!mPAC)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
nsAutoCString spec, host;
|
||||
uri->GetAsciiSpec(spec);
|
||||
uri->GetAsciiHost(host);
|
||||
|
||||
return mPAC->GetProxyForURI(spec, host, result);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPACMan::PostQuery(PendingPACQuery *query)
|
||||
nsPACMan::AsyncGetProxyForURI(nsIURI *uri, nsPACManCallback *callback)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(!NS_IsMainThread(), "wrong thread");
|
||||
NS_ENSURE_STATE(!mShutdown);
|
||||
|
||||
if (mShutdown) {
|
||||
query->Complete(NS_ERROR_NOT_AVAILABLE, EmptyCString());
|
||||
MaybeReloadPAC();
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// 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;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -365,24 +256,21 @@ nsPACMan::LoadPACFromURI(nsIURI *pacURI)
|
|||
mLoader = loader;
|
||||
if (pacURI) {
|
||||
mPACURI = pacURI;
|
||||
mPACURI->GetSpec(mPACURISpec);
|
||||
mLoadFailureCount = 0; // reset
|
||||
}
|
||||
|
||||
// reset to Null
|
||||
mScheduledReload = TimeStamp();
|
||||
mScheduledReload = LL_MAXINT;
|
||||
mPAC = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsPACMan::StartLoading()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
|
||||
mLoadPending = false;
|
||||
|
||||
// CancelExistingLoad was called...
|
||||
if (!mLoader) {
|
||||
PostCancelPendingQ(NS_ERROR_ABORT);
|
||||
ProcessPendingQ(NS_ERROR_ABORT);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -405,9 +293,18 @@ nsPACMan::StartLoading()
|
|||
}
|
||||
|
||||
CancelExistingLoad();
|
||||
PostCancelPendingQ(NS_ERROR_UNEXPECTED);
|
||||
ProcessPendingQ(NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
|
||||
void
|
||||
nsPACMan::MaybeReloadPAC()
|
||||
{
|
||||
if (!mPACURI)
|
||||
return;
|
||||
|
||||
if (PR_Now() > mScheduledReload)
|
||||
LoadPACFromURI(nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
nsPACMan::OnLoadFailure()
|
||||
|
@ -427,11 +324,11 @@ nsPACMan::OnLoadFailure()
|
|||
if (!interval || interval > maxInterval)
|
||||
interval = maxInterval;
|
||||
|
||||
mScheduledReload = TimeStamp::Now() + TimeDuration::FromSeconds(interval);
|
||||
#ifdef DEBUG
|
||||
printf("PAC load failure: will retry in %d seconds\n", interval);
|
||||
#endif
|
||||
|
||||
// while we wait for the retry queued members should try direct
|
||||
// even if that means fast failure.
|
||||
PostCancelPendingQ(NS_ERROR_NOT_AVAILABLE);
|
||||
mScheduledReload = PR_Now() + int64_t(interval) * PR_USEC_PER_SEC;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -447,110 +344,32 @@ nsPACMan::CancelExistingLoad()
|
|||
}
|
||||
|
||||
void
|
||||
nsPACMan::PostProcessPendingQ()
|
||||
nsPACMan::ProcessPendingQ(nsresult status)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
|
||||
nsRefPtr<ExecutePACThreadAction> pending =
|
||||
new ExecutePACThreadAction(this);
|
||||
if (mPACThread)
|
||||
mPACThread->Dispatch(pending, nsIEventTarget::DISPATCH_NORMAL);
|
||||
// Now, start any pending queries
|
||||
PRCList *node = PR_LIST_HEAD(&mPendingQ);
|
||||
while (node != &mPendingQ) {
|
||||
PendingPACQuery *query = static_cast<PendingPACQuery *>(node);
|
||||
node = PR_NEXT_LINK(node);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
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_IMPL_ISUPPORTS3(nsPACMan, nsIStreamLoaderObserver, nsIInterfaceRequestor,
|
||||
nsIChannelEventSink)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPACMan::OnStreamComplete(nsIStreamLoader *loader,
|
||||
|
@ -559,7 +378,6 @@ nsPACMan::OnStreamComplete(nsIStreamLoader *loader,
|
|||
uint32_t dataLen,
|
||||
const uint8_t *data)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
|
||||
if (mLoader != loader) {
|
||||
// If this happens, then it means that LoadPACFromURI was called more
|
||||
// than once before the initial call completed. In this case, status
|
||||
|
@ -569,6 +387,8 @@ nsPACMan::OnStreamComplete(nsIStreamLoader *loader,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
mLoader = nullptr;
|
||||
|
||||
if (NS_SUCCEEDED(status) && HttpRequestSucceeded(loader)) {
|
||||
// Get the URI spec used to load this PAC script.
|
||||
nsAutoCString pacURI;
|
||||
|
@ -584,21 +404,18 @@ nsPACMan::OnStreamComplete(nsIStreamLoader *loader,
|
|||
}
|
||||
}
|
||||
|
||||
// We assume that the PAC text is ASCII (or ISO-Latin-1). We've had this
|
||||
// assumption forever, and some real-world PAC scripts actually have some
|
||||
// non-ASCII text in comment blocks (see bug 296163).
|
||||
const char *text = (const char *) data;
|
||||
|
||||
// we have succeeded in loading the pac file using a bunch of interfaces that
|
||||
// are main thread only, unfortunately we have to initialize the instance of
|
||||
// the PAC evaluator (NS_PROXYAUTOCONFIG_CONTRACTID) on the pac thread, because
|
||||
// that is where it will be used.
|
||||
|
||||
nsRefPtr<ExecutePACThreadAction> pending =
|
||||
new ExecutePACThreadAction(this);
|
||||
pending->SetupPAC(text, dataLen, pacURI);
|
||||
if (mPACThread)
|
||||
mPACThread->Dispatch(pending, nsIEventTarget::DISPATCH_NORMAL);
|
||||
if (!mPAC) {
|
||||
mPAC = do_CreateInstance(NS_PROXYAUTOCONFIG_CONTRACTID, &status);
|
||||
if (!mPAC)
|
||||
NS_WARNING("failed to instantiate PAC component");
|
||||
}
|
||||
if (NS_SUCCEEDED(status)) {
|
||||
// We assume that the PAC text is ASCII (or ISO-Latin-1). We've had this
|
||||
// assumption forever, and some real-world PAC scripts actually have some
|
||||
// non-ASCII text in comment blocks (see bug 296163).
|
||||
const char *text = (const char *) data;
|
||||
status = mPAC->Init(pacURI, NS_ConvertASCIItoUTF16(text, dataLen));
|
||||
}
|
||||
|
||||
// Even if the PAC file could not be parsed, we did succeed in loading the
|
||||
// data for it.
|
||||
|
@ -609,11 +426,11 @@ nsPACMan::OnStreamComplete(nsIStreamLoader *loader,
|
|||
OnLoadFailure();
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(status))
|
||||
PostProcessPendingQ();
|
||||
else
|
||||
PostCancelPendingQ(status);
|
||||
// Reset mPAC if necessary
|
||||
if (mPAC && NS_FAILED(status))
|
||||
mPAC = nullptr;
|
||||
|
||||
ProcessPendingQ(status);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -649,26 +466,3 @@ nsPACMan::AsyncOnChannelRedirect(nsIChannel *oldChannel, nsIChannel *newChannel,
|
|||
callback->OnRedirectVerifyCallback(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,20 +10,12 @@
|
|||
#include "nsIStreamLoader.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
#include "ProxyAutoConfig.h"
|
||||
#include "nsICancelable.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIProxyAutoConfig.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "prclist.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.
|
||||
|
@ -39,45 +31,14 @@ public:
|
|||
* @param pacString
|
||||
* This parameter holds the value of the PAC string. It is empty when
|
||||
* 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,
|
||||
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;
|
||||
virtual void OnQueryComplete(nsresult status, const nsCString &pacString) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
class nsPACMan MOZ_FINAL : public nsIStreamLoaderObserver
|
||||
, public nsIInterfaceRequestor
|
||||
, public nsIChannelEventSink
|
||||
|
@ -94,6 +55,19 @@ public:
|
|||
*/
|
||||
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
|
||||
* calling thread. If the PAC file has not yet been loaded, then this method
|
||||
|
@ -104,11 +78,8 @@ public:
|
|||
* The URI to query.
|
||||
* @param callback
|
||||
* 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,
|
||||
bool mustCallbackOnMainThread);
|
||||
nsresult AsyncGetProxyForURI(nsIURI *uri, nsPACManCallback *callback);
|
||||
|
||||
/**
|
||||
* This method may be called to reload the PAC file. While we are loading
|
||||
|
@ -134,28 +105,11 @@ public:
|
|||
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:
|
||||
NS_DECL_NSISTREAMLOADEROBSERVER
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSICHANNELEVENTSINK
|
||||
|
||||
friend class PendingPACQuery;
|
||||
friend class PACLoadComplete;
|
||||
friend class ExecutePACThreadAction;
|
||||
|
||||
~nsPACMan();
|
||||
|
||||
/**
|
||||
|
@ -163,6 +117,13 @@ private:
|
|||
*/
|
||||
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.
|
||||
*/
|
||||
|
@ -178,35 +139,15 @@ private:
|
|||
*/
|
||||
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:
|
||||
mozilla::net::ProxyAutoConfig mPAC;
|
||||
nsCOMPtr<nsIThread> mPACThread;
|
||||
nsCOMPtr<nsISystemProxySettings> mSystemProxySettings;
|
||||
|
||||
mozilla::LinkedList<PendingPACQuery> mPendingQ; /* pac thread only */
|
||||
|
||||
nsCOMPtr<nsIProxyAutoConfig> mPAC;
|
||||
nsCOMPtr<nsIURI> mPACURI;
|
||||
nsCString mPACURISpec; // for use off main thread
|
||||
PRCList mPendingQ;
|
||||
nsCOMPtr<nsIStreamLoader> mLoader;
|
||||
bool mLoadPending;
|
||||
bool mShutdown;
|
||||
mozilla::TimeStamp mScheduledReload;
|
||||
PRTime mScheduledReload;
|
||||
uint32_t mLoadFailureCount;
|
||||
|
||||
bool mInProgress;
|
||||
};
|
||||
|
||||
#endif // nsPACMan_h__
|
||||
|
|
|
@ -12,13 +12,13 @@
|
|||
#include "nsIClassInfoImpl.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsIProxyAutoConfig.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIProtocolHandler.h"
|
||||
#include "nsIProtocolProxyCallback.h"
|
||||
#include "nsICancelable.h"
|
||||
#include "nsIDNSService.h"
|
||||
#include "nsPIDNSService.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsReadableUtils.h"
|
||||
|
@ -29,9 +29,6 @@
|
|||
#include "nsCRT.h"
|
||||
#include "prnetdb.h"
|
||||
#include "nsPACMan.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/CondVar.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
@ -75,49 +72,12 @@ public:
|
|||
, mDispatched(false)
|
||||
, mResolveFlags(aResolveFlags)
|
||||
, mPPS(pps)
|
||||
, mXPComPPS(pps)
|
||||
, mURI(uri)
|
||||
, mCallback(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)
|
||||
{
|
||||
mStatus = status;
|
||||
|
@ -164,9 +124,7 @@ private:
|
|||
|
||||
// Called asynchronously, so we do not need to post another PLEvent
|
||||
// before calling DoCallback.
|
||||
void OnQueryComplete(nsresult status,
|
||||
const nsCString &pacString,
|
||||
const nsCString &newPACURL)
|
||||
void OnQueryComplete(nsresult status, const nsCString &pacString)
|
||||
{
|
||||
// If we've already called DoCallback then, nothing more to do.
|
||||
if (!mCallback)
|
||||
|
@ -176,7 +134,6 @@ private:
|
|||
if (mStatus == NS_OK) {
|
||||
mStatus = status;
|
||||
mPACString = pacString;
|
||||
mPACURL = newPACURL;
|
||||
}
|
||||
|
||||
// In the cancelation case, we may still have another PLEvent in
|
||||
|
@ -199,63 +156,26 @@ private:
|
|||
mPPS->ApplyFilters(mURI, info, mProxyInfo);
|
||||
else
|
||||
mProxyInfo = nullptr;
|
||||
|
||||
LOG(("pac thread callback %s\n", mPACString.get()));
|
||||
if (NS_SUCCEEDED(mStatus))
|
||||
mPPS->MaybeDisableDNSPrefetch(mProxyInfo);
|
||||
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));
|
||||
if (NS_SUCCEEDED(mStatus))
|
||||
mPPS->MaybeDisableDNSPrefetch(mProxyInfo);
|
||||
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->OnProxyAvailable(this, mURI, mProxyInfo, mStatus);
|
||||
mCallback = nullptr; // in case the callback holds an owning ref to us
|
||||
mPPS = nullptr;
|
||||
mXPComPPS = nullptr;
|
||||
mURI = nullptr;
|
||||
mProxyInfo = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
nsresult mStatus;
|
||||
nsCString mPACString;
|
||||
nsCString mPACURL;
|
||||
bool mDispatched;
|
||||
uint32_t mResolveFlags;
|
||||
|
||||
nsProtocolProxyService *mPPS;
|
||||
nsCOMPtr<nsIProtocolProxyService> mXPComPPS;
|
||||
nsRefPtr<nsProtocolProxyService> mPPS;
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCOMPtr<nsIProtocolProxyCallback> mCallback;
|
||||
nsCOMPtr<nsIProxyInfo> mProxyInfo;
|
||||
};
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(nsAsyncResolveRequest, nsICancelable, nsIRunnable)
|
||||
NS_IMPL_ISUPPORTS2(nsAsyncResolveRequest, nsICancelable, nsIRunnable)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
@ -466,12 +386,8 @@ nsProtocolProxyService::PrefsChanged(nsIPrefBranch *prefBranch,
|
|||
mSystemProxySettings = do_GetService(NS_SYSTEMPROXYSETTINGS_CONTRACTID);
|
||||
if (!mSystemProxySettings)
|
||||
mProxyConfig = PROXYCONFIG_DIRECT;
|
||||
ResetPACThread();
|
||||
} else {
|
||||
if (mSystemProxySettings) {
|
||||
mSystemProxySettings = nullptr;
|
||||
ResetPACThread();
|
||||
}
|
||||
mSystemProxySettings = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -656,7 +572,7 @@ nsProtocolProxyService::ExtractProxyInfo(const char *start,
|
|||
*result = nullptr;
|
||||
uint32_t flags = 0;
|
||||
|
||||
// see BNF in ProxyAutoConfig.h and notes in nsISystemProxySettings.idl
|
||||
// see BNF in nsIProxyAutoConfig.idl
|
||||
|
||||
// find end of proxy info delimiter
|
||||
const char *end = start;
|
||||
|
@ -700,57 +616,33 @@ nsProtocolProxyService::ExtractProxyInfo(const char *start,
|
|||
start = sp;
|
||||
while ((*start == ' ' || *start == '\t') && start < end)
|
||||
start++;
|
||||
|
||||
// port defaults
|
||||
if (type == kProxyType_HTTP)
|
||||
port = 80;
|
||||
else
|
||||
port = 1080;
|
||||
|
||||
nsProxyInfo *pi = new nsProxyInfo();
|
||||
pi->mType = type;
|
||||
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;
|
||||
if (start < end) {
|
||||
host = start;
|
||||
hostEnd = strchr(host, ':');
|
||||
if (!hostEnd || hostEnd > end) {
|
||||
hostEnd = end;
|
||||
// no port, so assume default
|
||||
if (type == kProxyType_HTTP)
|
||||
port = 80;
|
||||
else
|
||||
port = 1080;
|
||||
}
|
||||
pi->mPort = port;
|
||||
else
|
||||
port = atoi(hostEnd + 1);
|
||||
}
|
||||
else {
|
||||
// www.example.com:8080
|
||||
if (start < end) {
|
||||
host = start;
|
||||
hostEnd = strchr(host, ':');
|
||||
if (!hostEnd || hostEnd > end) {
|
||||
hostEnd = end;
|
||||
// no port, so assume default
|
||||
}
|
||||
else {
|
||||
port = atoi(hostEnd + 1);
|
||||
}
|
||||
}
|
||||
nsProxyInfo *pi = new nsProxyInfo;
|
||||
if (pi) {
|
||||
pi->mType = type;
|
||||
pi->mFlags = flags;
|
||||
pi->mResolveFlags = aResolveFlags;
|
||||
pi->mTimeout = mFailedProxyTimeout;
|
||||
// YES, it is ok to specify a null proxy host.
|
||||
if (host) {
|
||||
pi->mHost.Assign(host, hostEnd - host);
|
||||
pi->mPort = port;
|
||||
}
|
||||
NS_ADDREF(*result = pi);
|
||||
}
|
||||
NS_ADDREF(*result = pi);
|
||||
}
|
||||
|
||||
while (*end == ';' || *end == ' ' || *end == '\t')
|
||||
|
@ -847,46 +739,15 @@ nsProtocolProxyService::IsProxyDisabled(nsProxyInfo *pi)
|
|||
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
|
||||
nsProtocolProxyService::ConfigureFromPAC(const nsCString &spec,
|
||||
bool forceReload)
|
||||
{
|
||||
SetupPACThread();
|
||||
if (!mPACMan) {
|
||||
mPACMan = new nsPACMan();
|
||||
if (!mPACMan)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> pacURI;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(pacURI), spec);
|
||||
|
@ -953,125 +814,53 @@ nsProtocolProxyService::ReloadPAC()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// When sync interface is removed this can go away too
|
||||
class nsAsyncBridgeRequest MOZ_FINAL : public nsPACManCallback
|
||||
{
|
||||
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
|
||||
// nsIProtocolProxyService
|
||||
NS_IMETHODIMP
|
||||
nsProtocolProxyService::DeprecatedBlockingResolve(nsIURI *aURI,
|
||||
uint32_t aFlags,
|
||||
nsIProxyInfo **retval)
|
||||
nsProtocolProxyService::Resolve(nsIURI *uri, uint32_t flags,
|
||||
nsIProxyInfo **result)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aURI);
|
||||
NS_ENSURE_ARG_POINTER(uri);
|
||||
|
||||
nsProtocolInfo info;
|
||||
nsresult rv = GetProtocolInfo(aURI, &info);
|
||||
nsresult rv = GetProtocolInfo(uri, &info);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIProxyInfo> 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(aURI, info, aFlags, &usePACThread, getter_AddRefs(pi));
|
||||
if (NS_FAILED(rv))
|
||||
bool usePAC;
|
||||
rv = Resolve_Internal(uri, info, flags, &usePAC, result);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("Resolve_Internal returned rv(0x%08x)\n", rv));
|
||||
return rv;
|
||||
|
||||
if (!usePACThread || !mPACMan) {
|
||||
ApplyFilters(aURI, info, pi);
|
||||
pi.forget(retval);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Use the PAC thread to do the work, so we don't have to reimplement that
|
||||
// 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 (usePAC && mPACMan) {
|
||||
NS_ASSERTION(*result == nullptr, "we should not have a result yet");
|
||||
|
||||
// pretty much duplicate real DoCallback logic
|
||||
// If the caller didn't want us to invoke PAC, then error out.
|
||||
if (flags & RESOLVE_NON_BLOCKING)
|
||||
return NS_BASE_STREAM_WOULD_BLOCK;
|
||||
|
||||
// Generate proxy info from the PAC string if appropriate
|
||||
if (!ctx->mPACString.IsEmpty()) {
|
||||
LOG(("sync pac thread callback %s\n", ctx->mPACString.get()));
|
||||
ProcessPACString(ctx->mPACString, 0, getter_AddRefs(pi));
|
||||
ApplyFilters(aURI, info, pi);
|
||||
pi.forget(retval);
|
||||
return NS_OK;
|
||||
// Query the PAC file synchronously.
|
||||
nsCString pacString;
|
||||
rv = mPACMan->GetProxyForURI(uri, pacString);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
ProcessPACString(pacString, flags, result);
|
||||
else if (rv == NS_ERROR_IN_PROGRESS) {
|
||||
// Construct a special UNKNOWN proxy entry that informs the caller
|
||||
// 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");
|
||||
}
|
||||
|
||||
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;
|
||||
ApplyFilters(uri, info, result);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIProtocolProxyService
|
||||
NS_IMETHODIMP
|
||||
nsProtocolProxyService::AsyncResolve(nsIURI *uri, uint32_t flags,
|
||||
nsIProtocolProxyCallback *callback,
|
||||
|
@ -1082,33 +871,29 @@ nsProtocolProxyService::AsyncResolve(nsIURI *uri, uint32_t flags,
|
|||
|
||||
nsRefPtr<nsAsyncResolveRequest> ctx =
|
||||
new nsAsyncResolveRequest(this, uri, flags, callback);
|
||||
if (!ctx)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsProtocolInfo info;
|
||||
nsresult rv = GetProtocolInfo(uri, &info);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
bool usePAC;
|
||||
nsCOMPtr<nsIProxyInfo> 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));
|
||||
rv = Resolve_Internal(uri, info, flags, &usePAC, getter_AddRefs(pi));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (!usePACThread || !mPACMan) {
|
||||
// we can do it locally
|
||||
if (!usePAC || !mPACMan) {
|
||||
ApplyFilters(uri, info, pi);
|
||||
|
||||
ctx->SetResult(NS_OK, pi);
|
||||
return ctx->DispatchCallback();
|
||||
}
|
||||
|
||||
// else kick off a PAC thread query
|
||||
|
||||
rv = mPACMan->AsyncGetProxyForURI(uri, ctx, true);
|
||||
// else kick off a PAC query
|
||||
rv = mPACMan->AsyncGetProxyForURI(uri, ctx);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
*result = ctx;
|
||||
NS_ADDREF(*result);
|
||||
|
@ -1456,76 +1241,42 @@ nsresult
|
|||
nsProtocolProxyService::Resolve_Internal(nsIURI *uri,
|
||||
const nsProtocolInfo &info,
|
||||
uint32_t flags,
|
||||
bool *usePACThread,
|
||||
bool *usePAC,
|
||||
nsIProxyInfo **result)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(uri);
|
||||
nsresult rv = SetupPACThread();
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
*usePACThread = false;
|
||||
*usePAC = false;
|
||||
*result = nullptr;
|
||||
|
||||
if (!(info.flags & nsIProtocolHandler::ALLOWS_PROXY))
|
||||
return NS_OK; // Can't proxy this (filters may not override)
|
||||
|
||||
// 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
|
||||
|
||||
if (mSystemProxySettings) {
|
||||
nsAutoCString PACURI;
|
||||
nsAutoCString pacString;
|
||||
|
||||
if (NS_SUCCEEDED(mSystemProxySettings->GetPACURI(PACURI)) &&
|
||||
!PACURI.IsEmpty()) {
|
||||
// There is a PAC URI configured. If it is unchanged, then
|
||||
// just execute the PAC thread. If it is changed then load
|
||||
// the new value
|
||||
|
||||
if (mPACMan && mPACMan->IsPACURI(PACURI)) {
|
||||
// unchanged
|
||||
*usePACThread = true;
|
||||
if (NS_FAILED(mSystemProxySettings->GetPACURI(PACURI)) ||
|
||||
PACURI.IsEmpty()) {
|
||||
nsAutoCString proxy;
|
||||
nsresult rv = mSystemProxySettings->GetProxyForURI(uri, proxy);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
ProcessPACString(proxy, flags, result);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ConfigureFromPAC(PACURI, false);
|
||||
// no proxy, stop search
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoCString spec;
|
||||
nsAutoCString host;
|
||||
nsAutoCString scheme;
|
||||
int32_t port = -1;
|
||||
|
||||
uri->GetAsciiSpec(spec);
|
||||
uri->GetAsciiHost(host);
|
||||
uri->GetScheme(scheme);
|
||||
uri->GetPort(&port);
|
||||
|
||||
// now try the system proxy settings for this particular url
|
||||
if (NS_SUCCEEDED(mSystemProxySettings->
|
||||
GetProxyForURI(spec, scheme, host, port,
|
||||
pacString))) {
|
||||
ProcessPACString(pacString, 0, result);
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Switch to new PAC file if that setting has changed. If the setting
|
||||
// hasn't changed, ConfigureFromPAC will exit early.
|
||||
nsresult rv = ConfigureFromPAC(PACURI, false);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
||||
// if proxies are enabled and this host:port combo is supposed to use a
|
||||
|
@ -1536,9 +1287,10 @@ nsProtocolProxyService::Resolve_Internal(nsIURI *uri,
|
|||
return NS_OK;
|
||||
|
||||
// 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.
|
||||
*usePACThread = true;
|
||||
*usePAC = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1552,7 +1304,7 @@ nsProtocolProxyService::Resolve_Internal(nsIURI *uri,
|
|||
if ((flags & RESOLVE_PREFER_SOCKS_PROXY) &&
|
||||
!mSOCKSProxyHost.IsEmpty() && mSOCKSProxyPort > 0) {
|
||||
host = &mSOCKSProxyHost;
|
||||
if (mSOCKSProxyVersion == 4)
|
||||
if (mSOCKSProxyVersion == 4)
|
||||
type = kProxyType_SOCKS4;
|
||||
else
|
||||
type = kProxyType_SOCKS;
|
||||
|
@ -1589,7 +1341,7 @@ nsProtocolProxyService::Resolve_Internal(nsIURI *uri,
|
|||
}
|
||||
else if (!mSOCKSProxyHost.IsEmpty() && mSOCKSProxyPort > 0) {
|
||||
host = &mSOCKSProxyHost;
|
||||
if (mSOCKSProxyVersion == 4)
|
||||
if (mSOCKSProxyVersion == 4)
|
||||
type = kProxyType_SOCKS4;
|
||||
else
|
||||
type = kProxyType_SOCKS;
|
||||
|
@ -1599,9 +1351,9 @@ nsProtocolProxyService::Resolve_Internal(nsIURI *uri,
|
|||
}
|
||||
|
||||
if (type) {
|
||||
rv = NewProxyInfo_Internal(type, *host, port, proxyFlags,
|
||||
PR_UINT32_MAX, nullptr, flags,
|
||||
result);
|
||||
nsresult rv = NewProxyInfo_Internal(type, *host, port, proxyFlags,
|
||||
PR_UINT32_MAX, nullptr, flags,
|
||||
result);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
@ -1609,30 +1361,6 @@ nsProtocolProxyService::Resolve_Internal(nsIURI *uri,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsProtocolProxyService::MaybeDisableDNSPrefetch(nsIProxyInfo *aProxy)
|
||||
{
|
||||
// Disable Prefetch in the DNS service if a proxy is in use.
|
||||
if (!aProxy)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsProxyInfo> pi = do_QueryInterface(aProxy);
|
||||
if (!pi ||
|
||||
!pi->mType ||
|
||||
pi->mType == kProxyType_DIRECT)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID);
|
||||
if (!dns)
|
||||
return;
|
||||
nsCOMPtr<nsPIDNSService> pdns = do_QueryInterface(dns);
|
||||
if (!pdns)
|
||||
return;
|
||||
|
||||
// We lose the prefetch optimization for the life of the dns service.
|
||||
pdns->SetPrefetchEnabled(false);
|
||||
}
|
||||
|
||||
void
|
||||
nsProtocolProxyService::ApplyFilters(nsIURI *uri, const nsProtocolInfo &info,
|
||||
nsIProxyInfo **list)
|
||||
|
@ -1683,7 +1411,7 @@ nsProtocolProxyService::PruneProxyInfo(const nsProtocolInfo &info,
|
|||
|
||||
// Start by removing all disallowed proxies if required:
|
||||
if (!(info.flags & nsIProtocolHandler::ALLOWS_PROXY_HTTP)) {
|
||||
nsProxyInfo *last = nullptr, *iter = head;
|
||||
nsProxyInfo *last = nullptr, *iter = head;
|
||||
while (iter) {
|
||||
if (iter->Type() == kProxyType_HTTP) {
|
||||
// reject!
|
||||
|
@ -1707,7 +1435,7 @@ nsProtocolProxyService::PruneProxyInfo(const nsProtocolInfo &info,
|
|||
// 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
|
||||
// disabled ones.
|
||||
|
||||
|
||||
bool allDisabled = true;
|
||||
|
||||
nsProxyInfo *iter;
|
||||
|
@ -1722,7 +1450,7 @@ nsProtocolProxyService::PruneProxyInfo(const nsProtocolInfo &info,
|
|||
LOG(("All proxies are disabled, so trying all again"));
|
||||
else {
|
||||
// remove any disabled proxies.
|
||||
nsProxyInfo *last = nullptr;
|
||||
nsProxyInfo *last = nullptr;
|
||||
for (iter = head; iter; ) {
|
||||
if (IsProxyDisabled(iter)) {
|
||||
// reject!
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "nsIPrefBranch.h"
|
||||
#include "nsIProtocolProxyService2.h"
|
||||
#include "nsIProtocolProxyFilter.h"
|
||||
#include "nsIProxyAutoConfig.h"
|
||||
#include "nsISystemProxySettings.h"
|
||||
#include "nsIProxyInfo.h"
|
||||
#include "nsIObserver.h"
|
||||
|
@ -271,18 +272,6 @@ protected:
|
|||
*/
|
||||
NS_HIDDEN_(bool) CanUseProxy(nsIURI *uri, int32_t defaultPort);
|
||||
|
||||
/**
|
||||
* Disable Prefetch in the DNS service if a proxy is in use.
|
||||
*
|
||||
* @param aProxy
|
||||
* The proxy information
|
||||
*/
|
||||
NS_HIDDEN_(void) MaybeDisableDNSPrefetch(nsIProxyInfo *aProxy);
|
||||
|
||||
private:
|
||||
nsresult SetupPACThread();
|
||||
nsresult ResetPACThread();
|
||||
|
||||
public:
|
||||
// The Sun Forte compiler and others implement older versions of the
|
||||
// C++ standard's rules on access and nested classes. These structs
|
||||
|
|
|
@ -0,0 +1,314 @@
|
|||
/* -*- 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"
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
component {63ac8c66-1dd2-11b2-b070-84d00d3eaece} nsProxyAutoConfig.js
|
||||
contract @mozilla.org/network/proxy-auto-config;1 {63ac8c66-1dd2-11b2-b070-84d00d3eaece}
|
|
@ -482,20 +482,6 @@ nsDNSService::Shutdown()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSService::GetPrefetchEnabled(bool *outVal)
|
||||
{
|
||||
*outVal = !mDisablePrefetch;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSService::SetPrefetchEnabled(bool inVal)
|
||||
{
|
||||
mDisablePrefetch = !inVal;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class DNSListenerProxy MOZ_FINAL : public nsIDNSListener
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
* This is a private interface used by the internals of the networking library.
|
||||
* It will never be frozen. Do not use it in external code.
|
||||
*/
|
||||
[scriptable, uuid(6b16fb1f-5709-4c94-a89f-a22be873c54d)]
|
||||
[scriptable, uuid(a26c5b45-7707-4412-bbc1-2462b890848d)]
|
||||
interface nsPIDNSService : nsIDNSService
|
||||
{
|
||||
/**
|
||||
|
@ -26,9 +26,4 @@ interface nsPIDNSService : nsIDNSService
|
|||
* this method.
|
||||
*/
|
||||
void shutdown();
|
||||
|
||||
/**
|
||||
* Whether or not DNS prefetching (aka RESOLVE_SPECULATE) is enabled
|
||||
*/
|
||||
attribute boolean prefetchEnabled;
|
||||
};
|
||||
|
|
|
@ -55,11 +55,6 @@ public:
|
|||
return mProxyInfo;
|
||||
}
|
||||
|
||||
void SetProxyInfo(nsIProxyInfo *pi)
|
||||
{
|
||||
mProxyInfo = pi;
|
||||
}
|
||||
|
||||
// Were we asked to resume a download?
|
||||
bool ResumeRequested() { return mResumeRequested; }
|
||||
|
||||
|
|
|
@ -33,8 +33,6 @@
|
|||
#include "nsIStringBundle.h"
|
||||
#include "nsAuthInformationHolder.h"
|
||||
#include "nsICharsetConverterManager.h"
|
||||
#include "nsIProtocolProxyService.h"
|
||||
#include "nsICancelable.h"
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
extern PRLogModuleInfo* gFTPLog;
|
||||
|
@ -52,13 +50,12 @@ removeParamsFromPath(nsCString& path)
|
|||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED5(nsFtpState,
|
||||
NS_IMPL_ISUPPORTS_INHERITED4(nsFtpState,
|
||||
nsBaseContentStream,
|
||||
nsIInputStreamCallback,
|
||||
nsITransportEventSink,
|
||||
nsICacheListener,
|
||||
nsIRequestObserver,
|
||||
nsIProtocolProxyCallback)
|
||||
nsIRequestObserver)
|
||||
|
||||
nsFtpState::nsFtpState()
|
||||
: nsBaseContentStream(true)
|
||||
|
@ -81,7 +78,6 @@ nsFtpState::nsFtpState()
|
|||
, mAddressChecked(false)
|
||||
, mServerIsIPv6(false)
|
||||
, mControlStatus(NS_OK)
|
||||
, mDeferredCallbackPending(false)
|
||||
{
|
||||
LOG_ALWAYS(("FTP:(%x) nsFtpState created", this));
|
||||
|
||||
|
@ -93,9 +89,6 @@ nsFtpState::~nsFtpState()
|
|||
{
|
||||
LOG_ALWAYS(("FTP:(%x) nsFtpState destroyed", this));
|
||||
|
||||
if (mProxyRequest)
|
||||
mProxyRequest->Cancel(NS_ERROR_FAILURE);
|
||||
|
||||
// release reference to handler
|
||||
nsFtpProtocolHandler *handler = gFtpHandler;
|
||||
NS_RELEASE(handler);
|
||||
|
@ -1766,19 +1759,6 @@ nsFtpState::Init(nsFtpChannel *channel)
|
|||
if (port > 0)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -2175,67 +2155,6 @@ nsFtpState::CloseWithStatus(nsresult 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
|
||||
nsFtpState::OnCallbackPending()
|
||||
{
|
||||
|
@ -2244,11 +2163,6 @@ nsFtpState::OnCallbackPending()
|
|||
// connect to the server.
|
||||
|
||||
if (mState == FTP_INIT) {
|
||||
if (mProxyRequest) {
|
||||
mDeferredCallbackPending = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (CheckCache()) {
|
||||
mState = FTP_WAIT_CACHE;
|
||||
return;
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
|
||||
#include "nsICacheEntryDescriptor.h"
|
||||
#include "nsICacheListener.h"
|
||||
#include "nsIProtocolProxyCallback.h"
|
||||
|
||||
// ftp server types
|
||||
#define FTP_GENERIC_TYPE 0
|
||||
|
@ -78,7 +77,6 @@ typedef enum _FTP_STATE {
|
|||
typedef enum _FTP_ACTION {GET, PUT} FTP_ACTION;
|
||||
|
||||
class nsFtpChannel;
|
||||
class nsICancelable;
|
||||
|
||||
// The nsFtpState object is the content stream for the channel. It implements
|
||||
// nsIInputStreamCallback, so it can read data from the control connection. It
|
||||
|
@ -90,16 +88,13 @@ class nsFtpState : public nsBaseContentStream,
|
|||
public nsITransportEventSink,
|
||||
public nsICacheListener,
|
||||
public nsIRequestObserver,
|
||||
public nsFtpControlConnectionListener,
|
||||
public nsIProtocolProxyCallback
|
||||
{
|
||||
public nsFtpControlConnectionListener {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIINPUTSTREAMCALLBACK
|
||||
NS_DECL_NSITRANSPORTEVENTSINK
|
||||
NS_DECL_NSICACHELISTENER
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSIPROTOCOLPROXYCALLBACK
|
||||
|
||||
// Override input stream methods:
|
||||
NS_IMETHOD CloseWithStatus(nsresult status);
|
||||
|
@ -268,9 +263,6 @@ private:
|
|||
bool mDoomCache;
|
||||
|
||||
nsCString mSuppliedEntityID;
|
||||
|
||||
nsCOMPtr<nsICancelable> mProxyRequest;
|
||||
bool mDeferredCallbackPending;
|
||||
};
|
||||
|
||||
#endif //__nsFtpState__h_
|
||||
|
|
|
@ -211,13 +211,11 @@ nsFtpProtocolHandler::NewURI(const nsACString &aSpec,
|
|||
NS_IMETHODIMP
|
||||
nsFtpProtocolHandler::NewChannel(nsIURI* url, nsIChannel* *result)
|
||||
{
|
||||
return NewProxiedChannel(url, nullptr, 0, nullptr, result);
|
||||
return NewProxiedChannel(url, nullptr, result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFtpProtocolHandler::NewProxiedChannel(nsIURI* uri, nsIProxyInfo* proxyInfo,
|
||||
uint32_t proxyResolveFlags,
|
||||
nsIURI *proxyURI,
|
||||
nsIChannel* *result)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(uri);
|
||||
|
|
|
@ -50,7 +50,6 @@ HttpBaseChannel::HttpBaseChannel()
|
|||
, mAllowSpdy(true)
|
||||
, mPrivateBrowsing(false)
|
||||
, mSuspendCount(0)
|
||||
, mProxyResolveFlags(0)
|
||||
{
|
||||
LOG(("Creating HttpBaseChannel @%x\n", this));
|
||||
|
||||
|
@ -75,9 +74,7 @@ HttpBaseChannel::~HttpBaseChannel()
|
|||
nsresult
|
||||
HttpBaseChannel::Init(nsIURI *aURI,
|
||||
uint8_t aCaps,
|
||||
nsProxyInfo *aProxyInfo,
|
||||
uint32_t aProxyResolveFlags,
|
||||
nsIURI *aProxyURI)
|
||||
nsProxyInfo *aProxyInfo)
|
||||
{
|
||||
LOG(("HttpBaseChannel::Init [this=%p]\n", this));
|
||||
|
||||
|
@ -90,8 +87,6 @@ HttpBaseChannel::Init(nsIURI *aURI,
|
|||
mOriginalURI = aURI;
|
||||
mDocumentURI = nullptr;
|
||||
mCaps = aCaps;
|
||||
mProxyResolveFlags = aProxyResolveFlags;
|
||||
mProxyURI = aProxyURI;
|
||||
|
||||
// Construct connection info object
|
||||
nsAutoCString host;
|
||||
|
@ -117,6 +112,11 @@ HttpBaseChannel::Init(nsIURI *aURI,
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
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
|
||||
mRequestHead.SetMethod(nsHttp::Get);
|
||||
|
||||
|
@ -128,13 +128,8 @@ HttpBaseChannel::Init(nsIURI *aURI,
|
|||
rv = mRequestHead.SetHeader(nsHttp::Host, hostLine);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = gHttpHandler->AddStandardRequestHeaders(&mRequestHead.Headers());
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsAutoCString type;
|
||||
if (aProxyInfo && NS_SUCCEEDED(aProxyInfo->GetType(type)) &&
|
||||
!type.EqualsLiteral("unknown"))
|
||||
mProxyInfo = aProxyInfo;
|
||||
rv = gHttpHandler->
|
||||
AddStandardRequestHeaders(&mRequestHead.Headers(), aCaps);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -1527,9 +1522,7 @@ HttpBaseChannel::SetupReplacementChannel(nsIURI *newURI,
|
|||
// set, then allow the flag to apply to the redirected channel as well.
|
||||
// since we force set INHIBIT_PERSISTENT_CACHING on all HTTPS channels,
|
||||
// we only need to check if the original channel was using SSL.
|
||||
bool usingSSL = false;
|
||||
nsresult rv = mURI->SchemeIs("https", &usingSSL);
|
||||
if (NS_SUCCEEDED(rv) && usingSSL)
|
||||
if (mConnectionInfo->UsingSSL())
|
||||
newLoadFlags &= ~INHIBIT_PERSISTENT_CACHING;
|
||||
|
||||
// Do not pass along LOAD_CHECK_OFFLINE_CACHE
|
||||
|
|
|
@ -60,9 +60,7 @@ public:
|
|||
HttpBaseChannel();
|
||||
virtual ~HttpBaseChannel();
|
||||
|
||||
virtual nsresult Init(nsIURI *aURI, uint8_t aCaps, nsProxyInfo *aProxyInfo,
|
||||
uint32_t aProxyResolveFlags,
|
||||
nsIURI *aProxyURI);
|
||||
virtual nsresult Init(nsIURI *aURI, uint8_t aCaps, nsProxyInfo *aProxyInfo);
|
||||
|
||||
// nsIRequest
|
||||
NS_IMETHOD GetName(nsACString& aName);
|
||||
|
@ -226,7 +224,6 @@ protected:
|
|||
nsCOMPtr<nsIInputStream> mUploadStream;
|
||||
nsAutoPtr<nsHttpResponseHead> mResponseHead;
|
||||
nsRefPtr<nsHttpConnectionInfo> mConnectionInfo;
|
||||
nsCOMPtr<nsIProxyInfo> mProxyInfo;
|
||||
|
||||
nsCString mSpec; // ASCII encoded URL spec
|
||||
nsCString mContentTypeHint;
|
||||
|
@ -272,9 +269,6 @@ protected:
|
|||
uint32_t mSuspendCount;
|
||||
|
||||
nsAutoPtr<nsTArray<nsCString> > mRedirectedCachekeys;
|
||||
|
||||
uint32_t mProxyResolveFlags;
|
||||
nsCOMPtr<nsIURI> mProxyURI;
|
||||
};
|
||||
|
||||
// Share some code while working around C++'s absurd inability to handle casting
|
||||
|
|
|
@ -333,17 +333,21 @@ nsHttpChannel::~nsHttpChannel()
|
|||
nsresult
|
||||
nsHttpChannel::Init(nsIURI *uri,
|
||||
uint8_t caps,
|
||||
nsProxyInfo *proxyInfo,
|
||||
uint32_t proxyResolveFlags,
|
||||
nsIURI *proxyURI)
|
||||
nsProxyInfo *proxyInfo)
|
||||
{
|
||||
nsresult rv = HttpBaseChannel::Init(uri, caps, proxyInfo,
|
||||
proxyResolveFlags, proxyURI);
|
||||
nsresult rv = HttpBaseChannel::Init(uri, caps, proxyInfo);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
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;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -403,6 +407,13 @@ nsHttpChannel::Connect()
|
|||
// Consider opening a TCP connection right away
|
||||
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
|
||||
if (mResuming && (mLoadFlags & LOAD_ONLY_FROM_CACHE)) {
|
||||
LOG(("Resuming from cache is not supported yet"));
|
||||
|
@ -1521,6 +1532,54 @@ nsHttpChannel::ProxyFailover()
|
|||
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
|
||||
nsHttpChannel::HandleAsyncRedirectChannelToHttps()
|
||||
{
|
||||
|
@ -1665,8 +1724,7 @@ nsHttpChannel::AsyncDoReplaceWithProxy(nsIProxyInfo* pi)
|
|||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIChannel> newChannel;
|
||||
rv = gHttpHandler->NewProxiedChannel(mURI, pi, mProxyResolveFlags,
|
||||
mProxyURI, getter_AddRefs(newChannel));
|
||||
rv = gHttpHandler->NewProxiedChannel(mURI, pi, getter_AddRefs(newChannel));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
|
@ -1737,16 +1795,11 @@ nsHttpChannel::ResolveProxy()
|
|||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Check if we are configured to directly connect. This will save us
|
||||
// a round trip through the event dispatch system
|
||||
uint32_t proxyConfigType;
|
||||
if (NS_SUCCEEDED(pps->GetProxyConfigType(&proxyConfigType)) &&
|
||||
proxyConfigType == nsIProtocolProxyService::PROXYCONFIG_DIRECT) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
uint32_t resolveFlags = 0;
|
||||
if (mConnectionInfo->ProxyInfo())
|
||||
mConnectionInfo->ProxyInfo()->GetResolveFlags(&resolveFlags);
|
||||
|
||||
return pps->AsyncResolve(mProxyURI ? mProxyURI : mURI, mProxyResolveFlags,
|
||||
this, getter_AddRefs(mProxyRequest));
|
||||
return pps->AsyncResolve(mURI, resolveFlags, this, getter_AddRefs(mProxyRequest));
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -4304,102 +4357,7 @@ nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context)
|
|||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// 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()) {
|
||||
if (!(mConnectionInfo && mConnectionInfo->UsingHttpProxy())) {
|
||||
// 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
|
||||
// all lookups other than for the proxy itself are done by the proxy.
|
||||
|
@ -4415,6 +4373,20 @@ nsHttpChannel::BeginConnect()
|
|||
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:
|
||||
// - If "Connection: close" is set as a request header, then do not bother
|
||||
// trying to establish a keep-alive connection.
|
||||
|
@ -4428,6 +4400,23 @@ nsHttpChannel::BeginConnect()
|
|||
// Force-Reload should reset the persistent connection pool for this host
|
||||
if (mLoadFlags & LOAD_FRESH_CONNECTION)
|
||||
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
|
||||
// listeners or by load group observers; in that case, we should
|
||||
|
@ -4442,10 +4431,14 @@ nsHttpChannel::BeginConnect()
|
|||
AsyncAbort(rv);
|
||||
} else if (mLoadFlags & LOAD_CLASSIFY_URI) {
|
||||
nsRefPtr<nsChannelClassifier> classifier = new nsChannelClassifier();
|
||||
if (!classifier) {
|
||||
Cancel(NS_ERROR_OUT_OF_MEMORY);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = classifier->Start(this);
|
||||
if (NS_FAILED(rv)) {
|
||||
Cancel(rv);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4493,33 +4486,18 @@ NS_IMETHODIMP
|
|||
nsHttpChannel::OnProxyAvailable(nsICancelable *request, nsIURI *uri,
|
||||
nsIProxyInfo *pi, nsresult status)
|
||||
{
|
||||
LOG(("nsHttpChannel::OnProxyAvailable [this=%p pi=%p status=%x mStatus=%x]\n",
|
||||
this, pi, status, mStatus));
|
||||
mProxyRequest = nullptr;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// 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
|
||||
// request was canceled. We just failover to DIRECT when proxy resolution
|
||||
// fails (failure can mean that the PAC URL could not be loaded).
|
||||
|
||||
if (NS_SUCCEEDED(status))
|
||||
mProxyInfo = pi;
|
||||
|
||||
if (!gHttpHandler->Active()) {
|
||||
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();
|
||||
}
|
||||
// Need to replace this channel with a new one. It would be complex to try
|
||||
// to change the value of mConnectionInfo since so much of our state may
|
||||
// depend on its state.
|
||||
mTargetProxyInfo = pi;
|
||||
HandleAsyncReplaceWithProxy();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -95,9 +95,7 @@ public:
|
|||
nsHttpChannel();
|
||||
virtual ~nsHttpChannel();
|
||||
|
||||
virtual nsresult Init(nsIURI *aURI, uint8_t aCaps, nsProxyInfo *aProxyInfo,
|
||||
uint32_t aProxyResolveFlags,
|
||||
nsIURI *aProxyURI);
|
||||
virtual nsresult Init(nsIURI *aURI, uint8_t aCaps, nsProxyInfo *aProxyInfo);
|
||||
|
||||
// Methods HttpBaseChannel didn't implement for us or that we override.
|
||||
//
|
||||
|
@ -152,7 +150,6 @@ private:
|
|||
typedef nsresult (nsHttpChannel::*nsContinueRedirectionFunc)(nsresult result);
|
||||
|
||||
bool RequestIsConditional();
|
||||
nsresult BeginConnect();
|
||||
nsresult Connect();
|
||||
nsresult ContinueConnect();
|
||||
void SpeculativeConnect();
|
||||
|
@ -189,6 +186,8 @@ private:
|
|||
nsresult ProxyFailover();
|
||||
nsresult AsyncDoReplaceWithProxy(nsIProxyInfo *);
|
||||
nsresult ContinueDoReplaceWithProxy(nsresult);
|
||||
void HandleAsyncReplaceWithProxy();
|
||||
nsresult ContinueHandleAsyncReplaceWithProxy(nsresult);
|
||||
nsresult ResolveProxy();
|
||||
|
||||
// cache specific methods
|
||||
|
@ -304,6 +303,9 @@ private:
|
|||
// auth specific data
|
||||
nsCOMPtr<nsIHttpChannelAuthProvider> mAuthProvider;
|
||||
|
||||
// Proxy info to replace with
|
||||
nsCOMPtr<nsIProxyInfo> mTargetProxyInfo;
|
||||
|
||||
// If the channel is associated with a cache, and the URI matched
|
||||
// a fallback namespace, this will hold the key for the fallback
|
||||
// cache entry.
|
||||
|
|
|
@ -131,9 +131,9 @@ nsHttpHandler::nsHttpHandler()
|
|||
, mHttpVersion(NS_HTTP_VERSION_1_1)
|
||||
, mProxyHttpVersion(NS_HTTP_VERSION_1_1)
|
||||
, mCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
|
||||
, mProxyCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
|
||||
, mReferrerLevel(0xff) // by default we always send a referrer
|
||||
, mFastFallbackToIPv4(false)
|
||||
, mProxyPipelining(true)
|
||||
, mIdleTimeout(PR_SecondsToInterval(10))
|
||||
, mSpdyTimeout(PR_SecondsToInterval(180))
|
||||
, mMaxRequestAttempts(10)
|
||||
|
@ -167,7 +167,6 @@ nsHttpHandler::nsHttpHandler()
|
|||
, mDoNotTrackEnabled(false)
|
||||
, mTelemetryEnabled(false)
|
||||
, mAllowExperiments(true)
|
||||
, mHandlerActive(false)
|
||||
, mEnableSpdy(false)
|
||||
, mSpdyV2(true)
|
||||
, mSpdyV3(true)
|
||||
|
@ -265,7 +264,6 @@ nsHttpHandler::Init()
|
|||
}
|
||||
|
||||
mSessionStartTime = NowInSeconds();
|
||||
mHandlerActive = true;
|
||||
|
||||
rv = mAuthCache.Init();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
@ -333,7 +331,8 @@ nsHttpHandler::InitConnectionMgr()
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request)
|
||||
nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request,
|
||||
uint8_t caps)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
|
@ -357,20 +356,6 @@ nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request)
|
|||
rv = request->SetHeader(nsHttp::Accept_Encoding, mAcceptEncodings);
|
||||
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"
|
||||
// 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
|
||||
|
@ -384,6 +369,13 @@ nsHttpHandler::AddConnectionHeader(nsHttpHeaderArray *request,
|
|||
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);
|
||||
}
|
||||
|
||||
|
@ -951,8 +943,12 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
|
|||
|
||||
if (PREF_CHANGED(HTTP_PREF("proxy.pipelining"))) {
|
||||
rv = prefs->GetBoolPref(HTTP_PREF("proxy.pipelining"), &cVar);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
mProxyPipelining = cVar;
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (cVar)
|
||||
mProxyCapabilities |= NS_HTTP_ALLOW_PIPELINING;
|
||||
else
|
||||
mProxyCapabilities &= ~NS_HTTP_ALLOW_PIPELINING;
|
||||
}
|
||||
}
|
||||
|
||||
if (PREF_CHANGED(HTTP_PREF("qos"))) {
|
||||
|
@ -1379,7 +1375,7 @@ nsHttpHandler::NewChannel(nsIURI *uri, nsIChannel **result)
|
|||
}
|
||||
}
|
||||
|
||||
return NewProxiedChannel(uri, nullptr, 0, nullptr, result);
|
||||
return NewProxiedChannel(uri, nullptr, result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1397,8 +1393,6 @@ nsHttpHandler::AllowPort(int32_t port, const char *scheme, bool *_retval)
|
|||
NS_IMETHODIMP
|
||||
nsHttpHandler::NewProxiedChannel(nsIURI *uri,
|
||||
nsIProxyInfo* givenProxyInfo,
|
||||
uint32_t proxyResolveFlags,
|
||||
nsIURI *proxyURI,
|
||||
nsIChannel **result)
|
||||
{
|
||||
nsRefPtr<HttpBaseChannel> httpChannel;
|
||||
|
@ -1423,7 +1417,13 @@ nsHttpHandler::NewProxiedChannel(nsIURI *uri,
|
|||
httpChannel = new nsHttpChannel();
|
||||
}
|
||||
|
||||
uint8_t caps = mCapabilities;
|
||||
// select proxy caps if using a non-transparent proxy. SSL tunneling
|
||||
// should not use proxy settings.
|
||||
int8_t caps;
|
||||
if (proxyInfo && !nsCRT::strcmp(proxyInfo->Type(), "http") && !https)
|
||||
caps = mProxyCapabilities;
|
||||
else
|
||||
caps = mCapabilities;
|
||||
|
||||
if (https) {
|
||||
// enable pipelining over SSL if requested
|
||||
|
@ -1436,7 +1436,7 @@ nsHttpHandler::NewProxiedChannel(nsIURI *uri,
|
|||
}
|
||||
}
|
||||
|
||||
rv = httpChannel->Init(uri, caps, proxyInfo, proxyResolveFlags, proxyURI);
|
||||
rv = httpChannel->Init(uri, caps, proxyInfo);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
|
@ -1509,8 +1509,6 @@ nsHttpHandler::Observe(nsISupports *subject,
|
|||
else if (strcmp(topic, "profile-change-net-teardown") == 0 ||
|
||||
strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
|
||||
|
||||
mHandlerActive = false;
|
||||
|
||||
// clear cache of all authentication credentials.
|
||||
mAuthCache.ClearAll();
|
||||
|
||||
|
|
|
@ -58,9 +58,8 @@ public:
|
|||
virtual ~nsHttpHandler();
|
||||
|
||||
nsresult Init();
|
||||
nsresult AddStandardRequestHeaders(nsHttpHeaderArray *);
|
||||
nsresult AddConnectionHeader(nsHttpHeaderArray *,
|
||||
uint8_t capabilities);
|
||||
nsresult AddStandardRequestHeaders(nsHttpHeaderArray *,
|
||||
uint8_t capabilities);
|
||||
bool IsAcceptableEncoding(const char *encoding);
|
||||
|
||||
const nsAFlatCString &UserAgent();
|
||||
|
@ -79,7 +78,6 @@ public:
|
|||
uint8_t GetQoSBits() { return mQoSBits; }
|
||||
uint16_t GetIdleSynTimeout() { return mIdleSynTimeout; }
|
||||
bool FastFallbackToIPv4() { return mFastFallbackToIPv4; }
|
||||
bool ProxyPipelining() { return mProxyPipelining; }
|
||||
uint32_t MaxSocketCount();
|
||||
bool EnforceAssocReq() { return mEnforceAssocReq; }
|
||||
|
||||
|
@ -235,9 +233,6 @@ public:
|
|||
|
||||
mozilla::net::SpdyInformation *SpdyInfo() { return &mSpdyInfo; }
|
||||
|
||||
// returns true in between Init and Shutdown states
|
||||
bool Active() { return mHandlerActive; }
|
||||
|
||||
private:
|
||||
|
||||
//
|
||||
|
@ -278,10 +273,11 @@ private:
|
|||
uint8_t mHttpVersion;
|
||||
uint8_t mProxyHttpVersion;
|
||||
uint8_t mCapabilities;
|
||||
uint8_t mProxyCapabilities;
|
||||
uint8_t mReferrerLevel;
|
||||
|
||||
bool mFastFallbackToIPv4;
|
||||
bool mProxyPipelining;
|
||||
|
||||
PRIntervalTime mIdleTimeout;
|
||||
PRIntervalTime mSpdyTimeout;
|
||||
|
||||
|
@ -360,9 +356,6 @@ private:
|
|||
// The value of network.allow-experiments
|
||||
bool mAllowExperiments;
|
||||
|
||||
// true in between init and shutdown states
|
||||
bool mHandlerActive;
|
||||
|
||||
// Try to use SPDY features instead of HTTP/1.1 over SSL
|
||||
mozilla::net::SpdyInformation mSpdyInfo;
|
||||
bool mEnableSpdy;
|
||||
|
|
|
@ -6,22 +6,10 @@
|
|||
|
||||
// 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();
|
||||
// run_myipaddress_test();
|
||||
|
||||
var ios = Components.classes["@mozilla.org/network/io-service;1"]
|
||||
.getService(Components.interfaces.nsIIOService);
|
||||
var pps = Components.classes["@mozilla.org/network/protocol-proxy-service;1"]
|
||||
.getService();
|
||||
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch);
|
||||
|
||||
/**
|
||||
* Test nsIProtocolHandler that allows proxying, but doesn't allow HTTP
|
||||
|
@ -155,109 +143,61 @@ function run_filter_test() {
|
|||
var uri = ios.newURI("http://www.mozilla.org/", null, null);
|
||||
|
||||
// Verify initial state
|
||||
var cb = new resolveCallback();
|
||||
cb.nextFunction = filter_test0_1;
|
||||
var req = pps.asyncResolve(uri, 0, cb);
|
||||
}
|
||||
|
||||
var filter01;
|
||||
var filter02;
|
||||
|
||||
function filter_test0_1(pi) {
|
||||
var pi = pps.resolve(uri, 0);
|
||||
do_check_eq(pi, null);
|
||||
|
||||
// Push a filter and verify the results
|
||||
|
||||
filter01 = new BasicFilter();
|
||||
filter02 = new BasicFilter();
|
||||
pps.registerFilter(filter01, 10);
|
||||
pps.registerFilter(filter02, 20);
|
||||
var filter1 = new BasicFilter();
|
||||
var filter2 = new BasicFilter();
|
||||
pps.registerFilter(filter1, 10);
|
||||
pps.registerFilter(filter2, 20);
|
||||
|
||||
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)
|
||||
{
|
||||
pi = pps.resolve(uri, 0);
|
||||
check_proxy(pi, "http", "localhost", 8080, 0, 10, true);
|
||||
check_proxy(pi.failoverProxy, "direct", "", -1, 0, 0, false);
|
||||
|
||||
pps.unregisterFilter(filter02);
|
||||
|
||||
var cb = new resolveCallback();
|
||||
cb.nextFunction = filter_test0_3;
|
||||
var uri = ios.newURI("http://www.mozilla.org/", null, null);
|
||||
var req = pps.asyncResolve(uri, 0, cb);
|
||||
}
|
||||
|
||||
function filter_test0_3(pi)
|
||||
{
|
||||
pps.unregisterFilter(filter2);
|
||||
pi = pps.resolve(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(filter01);
|
||||
|
||||
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 filter_test0_4(pi)
|
||||
{
|
||||
pps.unregisterFilter(filter1);
|
||||
pi = pps.resolve(uri, 0);
|
||||
do_check_eq(pi, null);
|
||||
run_filter_test2();
|
||||
}
|
||||
|
||||
var filter11;
|
||||
var filter12;
|
||||
|
||||
function run_filter_test2() {
|
||||
var uri = ios.newURI("http://www.mozilla.org/", null, null);
|
||||
|
||||
// Verify initial state
|
||||
|
||||
var pi = pps.resolve(uri, 0);
|
||||
do_check_eq(pi, null);
|
||||
|
||||
// Push a filter and verify the results
|
||||
|
||||
filter11 = new TestFilter("http", "foo", 8080, 0, 10);
|
||||
filter12 = new TestFilter("http", "bar", 8090, 0, 10);
|
||||
pps.registerFilter(filter11, 20);
|
||||
pps.registerFilter(filter12, 10);
|
||||
var filter1 = new TestFilter("http", "foo", 8080, 0, 10);
|
||||
var filter2 = new TestFilter("http", "bar", 8090, 0, 10);
|
||||
pps.registerFilter(filter1, 20);
|
||||
pps.registerFilter(filter2, 10);
|
||||
|
||||
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) {
|
||||
pi = pps.resolve(uri, 0);
|
||||
check_proxy(pi, "http", "bar", 8090, 0, 10, true);
|
||||
check_proxy(pi.failoverProxy, "http", "foo", 8080, 0, 10, false);
|
||||
|
||||
pps.unregisterFilter(filter12);
|
||||
|
||||
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) {
|
||||
pps.unregisterFilter(filter2);
|
||||
pi = pps.resolve(uri, 0);
|
||||
check_proxy(pi, "http", "foo", 8080, 0, 10, false);
|
||||
|
||||
// Remove filter and verify that we return to the initial state
|
||||
|
||||
pps.unregisterFilter(filter11);
|
||||
|
||||
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) {
|
||||
pps.unregisterFilter(filter1);
|
||||
pi = pps.resolve(uri, 0);
|
||||
do_check_eq(pi, null);
|
||||
run_filter_test3();
|
||||
}
|
||||
|
||||
var filter_3_1;
|
||||
|
@ -273,56 +213,42 @@ function run_filter_test3() {
|
|||
var cb = new resolveCallback();
|
||||
cb.nextFunction = filter_test3_1;
|
||||
var req = pps.asyncResolve(uri, 0, cb);
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function filter_test3_1(pi) {
|
||||
check_proxy(pi, "http", "foo", 8080, 0, 10, false);
|
||||
pps.unregisterFilter(filter_3_1);
|
||||
run_pref_test();
|
||||
run_test_continued_3();
|
||||
do_test_finished();
|
||||
}
|
||||
|
||||
function run_pref_test() {
|
||||
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
|
||||
|
||||
prefs.setIntPref("network.proxy.type", 0);
|
||||
|
||||
var cb = new resolveCallback();
|
||||
cb.nextFunction = pref_test1_1;
|
||||
var req = pps.asyncResolve(uri, 0, cb);
|
||||
}
|
||||
|
||||
function pref_test1_1(pi)
|
||||
{
|
||||
var pi = pps.resolve(uri, 0);
|
||||
do_check_eq(pi, null);
|
||||
|
||||
// Verify 'manual' setting
|
||||
|
||||
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
|
||||
pi = pps.resolve(uri, 0);
|
||||
do_check_eq(pi, null);
|
||||
|
||||
// try HTTP configuration
|
||||
prefs.setCharPref("network.proxy.http", "foopy");
|
||||
prefs.setIntPref("network.proxy.http_port", 8080);
|
||||
|
||||
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)
|
||||
{
|
||||
pi = pps.resolve(uri, 0);
|
||||
check_proxy(pi, "http", "foopy", 8080, 0, -1, false);
|
||||
|
||||
prefs.setCharPref("network.proxy.http", "");
|
||||
|
@ -332,33 +258,15 @@ function pref_test1_3(pi)
|
|||
prefs.setCharPref("network.proxy.socks", "barbar");
|
||||
prefs.setIntPref("network.proxy.socks_port", 1203);
|
||||
|
||||
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)
|
||||
{
|
||||
pi = pps.resolve(uri, 0);
|
||||
check_proxy(pi, "socks", "barbar", 1203, 0, -1, false);
|
||||
run_pac_test();
|
||||
}
|
||||
|
||||
function run_protocol_handler_test() {
|
||||
var uri = ios.newURI("moz-test:foopy", null, null);
|
||||
|
||||
var cb = new resolveCallback();
|
||||
cb.nextFunction = protocol_handler_test_1;
|
||||
var req = pps.asyncResolve(uri, 0, cb);
|
||||
}
|
||||
|
||||
function protocol_handler_test_1(pi)
|
||||
{
|
||||
var pi = pps.resolve(uri, 0);
|
||||
do_check_eq(pi, null);
|
||||
prefs.setCharPref("network.proxy.autoconfig_url", "");
|
||||
prefs.setIntPref("network.proxy.type", 0);
|
||||
|
||||
run_pac_cancel_test();
|
||||
}
|
||||
|
||||
function TestResolveCallback() {
|
||||
|
@ -384,7 +292,21 @@ TestResolveCallback.prototype = {
|
|||
check_proxy(pi, "http", "foopy", 8080, 0, -1, true);
|
||||
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();
|
||||
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -395,12 +317,31 @@ function run_pac_test() {
|
|||
'}';
|
||||
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
|
||||
|
||||
prefs.setIntPref("network.proxy.type", 2);
|
||||
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());
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function TestResolveCancelationCallback() {
|
||||
|
@ -423,10 +364,13 @@ TestResolveCancelationCallback.prototype = {
|
|||
do_check_eq(status, Components.results.NS_ERROR_ABORT);
|
||||
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.setIntPref("network.proxy.type", 0);
|
||||
|
||||
run_proxy_host_filters_test();
|
||||
run_test_continued_2();
|
||||
do_test_finished();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -438,70 +382,42 @@ function run_pac_cancel_test() {
|
|||
'function FindProxyForURL(url, host) {' +
|
||||
' 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.setCharPref("network.proxy.autoconfig_url", pac);
|
||||
|
||||
var req = pps.asyncResolve(uri, 0, new TestResolveCancelationCallback());
|
||||
req.cancel(Components.results.NS_ERROR_ABORT);
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
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) {
|
||||
function check_host_filters(hostList, bShouldBeFiltered) {
|
||||
var uri;
|
||||
dump("*** uri=" + hostList[i] + " bShouldBeFiltered=" + bShouldBeFiltered + "\n");
|
||||
uri = ios.newURI(hostList[i], null, null);
|
||||
|
||||
var cb = new resolveCallback();
|
||||
cb.nextFunction = host_filter_cb;
|
||||
var req = pps.asyncResolve(uri, 0, cb);
|
||||
}
|
||||
|
||||
function host_filter_cb(proxy)
|
||||
{
|
||||
if (bShouldBeFiltered) {
|
||||
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);
|
||||
var proxy;
|
||||
for (var i=0; i<hostList.length; i++) {
|
||||
dump("*** uri=" + hostList[i] + " bShouldBeFiltered=" + bShouldBeFiltered + "\n");
|
||||
uri = ios.newURI(hostList, null, null);
|
||||
proxy = pps.resolve(uri, 0);
|
||||
if (bShouldBeFiltered) {
|
||||
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
|
||||
// refers to "network.proxy.no_proxies_on"
|
||||
|
||||
var uriStrUseProxyList;
|
||||
var uriStrUseProxyList;
|
||||
var hostFilterList;
|
||||
|
||||
function run_proxy_host_filters_test() {
|
||||
// Get prefs object from DOM
|
||||
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch);
|
||||
// Setup a basic HTTP proxy configuration
|
||||
// - pps.resolve() needs this to return proxy info for non-filtered hosts
|
||||
prefs.setIntPref("network.proxy.type", 1);
|
||||
|
@ -509,135 +425,64 @@ function run_proxy_host_filters_test() {
|
|||
prefs.setIntPref("network.proxy.http_port", 8080);
|
||||
|
||||
// Setup host filter list string for "no_proxies_on"
|
||||
hostFilterList = "www.mozilla.org, www.google.com, www.apple.com, "
|
||||
var hostFilterList = "www.mozilla.org, www.google.com, www.apple.com, "
|
||||
+ ".domain, .domain2.org"
|
||||
prefs.setCharPref("network.proxy.no_proxies_on", hostFilterList);
|
||||
do_check_eq(prefs.getCharPref("network.proxy.no_proxies_on"), hostFilterList);
|
||||
|
||||
|
||||
var rv;
|
||||
// Check the hosts that should be filtered out
|
||||
uriStrFilterList = [ "http://www.mozilla.org/",
|
||||
var uriStrFilterList = [ "http://www.mozilla.org/",
|
||||
"http://www.google.com/",
|
||||
"http://www.apple.com/",
|
||||
"http://somehost.domain/",
|
||||
"http://someotherhost.domain/",
|
||||
"http://somehost.domain2.org/",
|
||||
"http://somehost.subdomain.domain2.org/" ];
|
||||
check_host_filters(uriStrFilterList, true, host_filters_1);
|
||||
}
|
||||
check_host_filters(uriStrFilterList, true);
|
||||
|
||||
function host_filters_1()
|
||||
{
|
||||
// Check the hosts that should be proxied
|
||||
uriStrUseProxyList = [ "http://www.mozilla.com/",
|
||||
var uriStrUseProxyList = [ "http://www.mozilla.com/",
|
||||
"http://mail.google.com/",
|
||||
"http://somehost.domain.co.uk/",
|
||||
"http://somelocalhost/" ];
|
||||
check_host_filters(uriStrUseProxyList, false, host_filters_2);
|
||||
}
|
||||
|
||||
function host_filters_2()
|
||||
{
|
||||
check_host_filters(uriStrUseProxyList, false);
|
||||
|
||||
// Set no_proxies_on to include local hosts
|
||||
prefs.setCharPref("network.proxy.no_proxies_on", hostFilterList + ", <local>");
|
||||
do_check_eq(prefs.getCharPref("network.proxy.no_proxies_on"),
|
||||
hostFilterList + ", <local>");
|
||||
|
||||
// Amend lists - move local domain to filtered list
|
||||
uriStrFilterList.push(uriStrUseProxyList.pop());
|
||||
check_host_filters(uriStrFilterList, true, host_filters_3);
|
||||
}
|
||||
check_host_filters(uriStrFilterList, true);
|
||||
check_host_filters(uriStrUseProxyList, false);
|
||||
|
||||
function host_filters_3()
|
||||
{
|
||||
check_host_filters(uriStrUseProxyList, false, host_filters_4);
|
||||
}
|
||||
|
||||
function host_filters_4()
|
||||
{
|
||||
// Cleanup
|
||||
prefs.setCharPref("network.proxy.no_proxies_on", "");
|
||||
do_check_eq(prefs.getCharPref("network.proxy.no_proxies_on"), "");
|
||||
|
||||
run_myipaddress_test();
|
||||
}
|
||||
|
||||
function run_myipaddress_test()
|
||||
{
|
||||
// This test makes sure myIpAddress() comes up with some valid
|
||||
// IP address other than localhost. The DUT must be configured with
|
||||
// an Internet route for this to work - though no Internet traffic
|
||||
// should be created.
|
||||
|
||||
var pac = 'data:text/plain,' +
|
||||
'function FindProxyForURL(url, host) {' +
|
||||
' return "PROXY " + myIpAddress() + ":1234";' +
|
||||
'}';
|
||||
|
||||
// no traffic to this IP is ever sent, it is just a public IP that
|
||||
// does not require DNS to determine a route.
|
||||
var uri = ios.newURI("http://192.0.43.10/", null, null);
|
||||
|
||||
prefs.setIntPref("network.proxy.type", 2);
|
||||
prefs.setCharPref("network.proxy.autoconfig_url", pac);
|
||||
|
||||
var cb = new resolveCallback();
|
||||
cb.nextFunction = myipaddress_callback;
|
||||
var req = pps.asyncResolve(uri, 0, cb);
|
||||
}
|
||||
|
||||
function myipaddress_callback(pi)
|
||||
{
|
||||
do_check_neq(pi, null);
|
||||
do_check_eq(pi.type, "http");
|
||||
do_check_eq(pi.port, 1234);
|
||||
|
||||
// make sure we didn't return localhost
|
||||
do_check_neq(pi.host, null);
|
||||
do_check_neq(pi.host, "127.0.0.1");
|
||||
do_check_neq(pi.host, "::1");
|
||||
|
||||
prefs.setIntPref("network.proxy.type", 0);
|
||||
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() {
|
||||
register_test_protocol_handler();
|
||||
|
||||
// any synchronous tests
|
||||
run_deprecated_sync_test();
|
||||
|
||||
// start of asynchronous test chain
|
||||
run_filter_test();
|
||||
do_test_pending();
|
||||
run_filter_test2();
|
||||
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,11 +33,24 @@ function run_test()
|
|||
httpServer.registerPathHandler("/content", contentHandler);
|
||||
httpServer.start(4444);
|
||||
|
||||
// we want to cancel the failover proxy engage, so, do not allow
|
||||
// redirects from now.
|
||||
|
||||
var nc = new ChannelEventSink();
|
||||
nc._flags = ES_ABORT_REDIRECT;
|
||||
var on_modify_request_count = 0;
|
||||
|
||||
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"].
|
||||
getService(Ci.nsIPrefService);
|
||||
|
|
|
@ -41,16 +41,8 @@ function run_test()
|
|||
"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");
|
||||
chan.notificationCallbacks = new ChannelEventSink(ES_ABORT_REDIRECT);
|
||||
chan.asyncOpen(new ChannelListener(finish_test, null, CL_EXPECT_FAILURE), null);
|
||||
chan.cancel(Cr.NS_BINDING_ABORTED);
|
||||
do_test_pending();
|
||||
}
|
||||
|
|
|
@ -15,33 +15,13 @@
|
|||
testNum = 1;
|
||||
|
||||
var login, login2;
|
||||
|
||||
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() {
|
||||
function init() {
|
||||
var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
|
||||
var pps = Cc["@mozilla.org/network/protocol-proxy-service;1"].getService();
|
||||
|
||||
var uri = ios.newURI("http://example.com", null, null);
|
||||
pps.asyncResolve(uri, 0, resolveCallback);
|
||||
}
|
||||
|
||||
function init2(proxyHost, proxyPort) {
|
||||
|
||||
var mozproxy = "moz-proxy://" + proxyHost + ":" + proxyPort;
|
||||
var pi = pps.resolve(uri, 0);
|
||||
var mozproxy = "moz-proxy://" + pi.host + ":" + pi.port;
|
||||
|
||||
var pwmgr = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
|
||||
login = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
|
||||
|
@ -116,7 +96,7 @@
|
|||
var pendingTests = [{expectedDialogs: 2, test: testNonAnonymousCredentials},
|
||||
{expectedDialogs: 1, test: testAnonymousCredentials},
|
||||
{expectedDialogs: 0, test: testAnonymousNoAuth}];
|
||||
init1();
|
||||
init();
|
||||
runNextTest();
|
||||
|
||||
function handleDialog(doc, testNum)
|
||||
|
|
|
@ -23,16 +23,19 @@ Login Manager test: username/password prompts
|
|||
var pwmgr, ioService
|
||||
var tmplogin, login1, login2A, login2B, login2C, login2D, login2E, login3A, login3B, login4, proxyLogin;
|
||||
var mozproxy, proxiedHost = "http://mochi.test:8888";
|
||||
var testNum = 1;
|
||||
|
||||
function initLogins(pi) {
|
||||
function initLogins() {
|
||||
pwmgr = Cc["@mozilla.org/login-manager;1"].
|
||||
getService(Ci.nsILoginManager);
|
||||
ioService = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Ci.nsIIOService);
|
||||
|
||||
mozproxy = "moz-proxy://" + SpecialPowers.wrap(pi).host + ":" +
|
||||
SpecialPowers.wrap(pi).port;
|
||||
// Figure out what our proxy is set to -- can't just hardcode this, because
|
||||
// mobile platforms don't use localhost.
|
||||
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"].
|
||||
createInstance(Ci.nsILoginInfo);
|
||||
|
@ -121,35 +124,6 @@ ok(true, "whee, done!");
|
|||
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)
|
||||
{
|
||||
storageObserver.notificationCallbacks.push(cb);
|
||||
|
@ -595,9 +569,8 @@ dumpNotifications();
|
|||
|
||||
}
|
||||
|
||||
startup();
|
||||
initLogins();
|
||||
|
||||
function doTests() {
|
||||
var authinfo = {
|
||||
username : "",
|
||||
password : "",
|
||||
|
@ -651,7 +624,7 @@ var popupNotifications = getPopupNotifications(window.top);
|
|||
ok(popupNotifications, "Got popupNotifications");
|
||||
|
||||
// ===== test 1 =====
|
||||
testNum = 1;
|
||||
var testNum = 1;
|
||||
startCallbackTimer();
|
||||
isOk = prompter1.prompt(dialogTitle(), dialogText, "http://example.com",
|
||||
Ci.nsIAuthPrompt.SAVE_PASSWORD_NEVER, "abc", result);
|
||||
|
@ -1163,7 +1136,6 @@ iframe.src = "authenticate.sjs?user=mochiuser1&pass=mochipass1";
|
|||
|
||||
// ...remaining tests are driven by handleLoad()...
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
|
||||
var pwmgr, logins = [];
|
||||
|
||||
function initLogins(pi) {
|
||||
function initLogins() {
|
||||
pwmgr = SpecialPowers.wrap(Components)
|
||||
.classes["@mozilla.org/login-manager;1"]
|
||||
.getService(Ci.nsILoginManager);
|
||||
|
@ -83,9 +83,18 @@
|
|||
logins.push(login);
|
||||
}
|
||||
|
||||
var mozproxy = "moz-proxy://" +
|
||||
SpecialPowers.wrap(pi).host + ":" +
|
||||
SpecialPowers.wrap(pi).port;
|
||||
//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);
|
||||
var pi = pps.resolve(uri, 0);
|
||||
var mozproxy = "moz-proxy://" + pi.host + ":" + pi.port;
|
||||
|
||||
addLogin(mozproxy, "proxy_realm",
|
||||
"proxy_user", "proxy_pass");
|
||||
|
@ -125,34 +134,6 @@
|
|||
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 ----------------
|
||||
var testNum = 1;
|
||||
|
@ -167,7 +148,8 @@
|
|||
iframe2a.onload = onFrameLoad;
|
||||
iframe2b.onload = onFrameLoad;
|
||||
|
||||
startup();
|
||||
initLogins();
|
||||
doTest(testNum);
|
||||
}
|
||||
|
||||
var expectedLoads;
|
||||
|
|
|
@ -34,7 +34,7 @@ public:
|
|||
nsresult GetAutoconfigURL(nsAutoCString& aResult) const;
|
||||
|
||||
// Find the SystemConfiguration proxy & port for a given URI
|
||||
nsresult FindSCProxyPort(const nsACString &aScheme, nsACString& aResultHost, int32_t& aResultPort, bool& aResultSocksProxy);
|
||||
nsresult FindSCProxyPort(nsIURI* aURI, nsACString& aResultHost, int32_t& aResultPort, bool& aResultSocksProxy);
|
||||
|
||||
// is host:port on the proxy exception list?
|
||||
bool IsInExceptionList(const nsACString& aHost) const;
|
||||
|
@ -58,14 +58,7 @@ private:
|
|||
static const SchemeMapping gSchemeMappingList[];
|
||||
};
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsOSXSystemProxySettings, nsISystemProxySettings)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsOSXSystemProxySettings::GetMainThreadOnly(bool *aMainThreadOnly)
|
||||
{
|
||||
*aMainThreadOnly = false;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMPL_ISUPPORTS1(nsOSXSystemProxySettings, nsISystemProxySettings)
|
||||
|
||||
// Mapping of URI schemes to SystemConfiguration keys
|
||||
const nsOSXSystemProxySettings::SchemeMapping nsOSXSystemProxySettings::gSchemeMappingList[] = {
|
||||
|
@ -163,7 +156,7 @@ nsOSXSystemProxySettings::ProxyHasChanged()
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsOSXSystemProxySettings::FindSCProxyPort(const nsACString &aScheme, nsACString& aResultHost, int32_t& aResultPort, bool& aResultSocksProxy)
|
||||
nsOSXSystemProxySettings::FindSCProxyPort(nsIURI* aURI, nsACString& aResultHost, int32_t& aResultPort, bool& aResultSocksProxy)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
|
@ -171,8 +164,8 @@ nsOSXSystemProxySettings::FindSCProxyPort(const nsACString &aScheme, nsACString&
|
|||
|
||||
for (const SchemeMapping* keys = gSchemeMappingList; keys->mScheme != NULL; ++keys) {
|
||||
// Check for matching scheme (when appropriate)
|
||||
if (strcasecmp(keys->mScheme, PromiseFlatCString(aScheme).get()) &&
|
||||
!keys->mIsSocksProxy)
|
||||
bool res;
|
||||
if ((NS_FAILED(aURI->SchemeIs(keys->mScheme, &res)) || !res) && !keys->mIsSocksProxy)
|
||||
continue;
|
||||
|
||||
// Check the proxy is enabled
|
||||
|
@ -310,20 +303,20 @@ nsOSXSystemProxySettings::GetPACURI(nsACString& aResult)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsOSXSystemProxySettings::GetProxyForURI(const nsACString & aSpec,
|
||||
const nsACString & aScheme,
|
||||
const nsACString & aHost,
|
||||
const int32_t aPort,
|
||||
nsACString & aResult)
|
||||
nsOSXSystemProxySettings::GetProxyForURI(nsIURI* aURI, nsACString& aResult)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
nsAutoCString host;
|
||||
nsresult rv = aURI->GetHost(host);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
int32_t proxyPort;
|
||||
nsAutoCString proxyHost;
|
||||
bool proxySocks;
|
||||
nsresult rv = FindSCProxyPort(aScheme, proxyHost, proxyPort, proxySocks);
|
||||
rv = FindSCProxyPort(aURI, proxyHost, proxyPort, proxySocks);
|
||||
|
||||
if (NS_FAILED(rv) || IsInExceptionList(aHost)) {
|
||||
if (NS_FAILED(rv) || IsInExceptionList(host)) {
|
||||
aResult.AssignLiteral("DIRECT");
|
||||
} else if (proxySocks) {
|
||||
aResult.Assign(NS_LITERAL_CSTRING("SOCKS ") + proxyHost + nsPrintfCString(":%d", proxyPort));
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "nsISystemProxySettings.h"
|
||||
#include "mozilla/ModuleUtils.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsString.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
@ -33,14 +34,7 @@ private:
|
|||
pxProxyFactory *mProxyFactory;
|
||||
};
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsUnixSystemProxySettings, nsISystemProxySettings)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUnixSystemProxySettings::GetMainThreadOnly(bool *aMainThreadOnly)
|
||||
{
|
||||
*aMainThreadOnly = false;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMPL_ISUPPORTS1(nsUnixSystemProxySettings, nsISystemProxySettings)
|
||||
|
||||
nsresult
|
||||
nsUnixSystemProxySettings::Init()
|
||||
|
@ -57,11 +51,7 @@ nsUnixSystemProxySettings::GetPACURI(nsACString& aResult)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsUnixSystemProxySettings::GetProxyForURI(const nsACString & aSpec,
|
||||
const nsACString & aScheme,
|
||||
const nsACString & aHost,
|
||||
const int32_t aPort,
|
||||
nsACString & aResult)
|
||||
nsUnixSystemProxySettings::GetProxyForURI(nsIURI* aURI, nsACString& aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
|
@ -70,9 +60,15 @@ nsUnixSystemProxySettings::GetProxyForURI(const nsACString & aSpec,
|
|||
}
|
||||
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;
|
||||
proxyArray = px_proxy_factory_get_proxies(mProxyFactory,
|
||||
PromiseFlatCString(aSpec).get());
|
||||
proxyArray = px_proxy_factory_get_proxies(mProxyFactory, (char*)(spec.get()));
|
||||
NS_ENSURE_TRUE(proxyArray, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
// Translate libproxy's output to PAC string as expected
|
||||
|
@ -82,34 +78,45 @@ nsUnixSystemProxySettings::GetProxyForURI(const nsACString & aSpec,
|
|||
// 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;
|
||||
while (proxyArray[c] != NULL) {
|
||||
if (!aResult.IsEmpty()) {
|
||||
aResult.AppendLiteral("; ");
|
||||
}
|
||||
|
||||
// figure out the scheme, and we can't use nsIIOService::NewURI because
|
||||
// this is not the main thread.
|
||||
char *colon = strchr (proxyArray[c], ':');
|
||||
uint32_t schemelen = colon ? colon - proxyArray[c] : 0;
|
||||
if (schemelen < 1) {
|
||||
bool isScheme = false;
|
||||
nsXPIDLCString schemeString;
|
||||
nsXPIDLCString hostPortString;
|
||||
nsCOMPtr<nsIURI> proxyURI;
|
||||
|
||||
rv = ios->NewURI(nsDependentCString(proxyArray[c]),
|
||||
nullptr,
|
||||
nullptr,
|
||||
getter_AddRefs(proxyURI));
|
||||
if (NS_FAILED(rv)) {
|
||||
c++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (schemelen == 6 && !strncasecmp(proxyArray[c], "direct", 6)) {
|
||||
aResult.AppendLiteral("DIRECT");
|
||||
proxyURI->GetScheme(schemeString);
|
||||
if (NS_SUCCEEDED(proxyURI->SchemeIs("http", &isScheme)) && isScheme) {
|
||||
schemeString.AssignLiteral("proxy");
|
||||
}
|
||||
else {
|
||||
aResult.AppendLiteral("PROXY ");
|
||||
aResult.Append(proxyArray[c]);
|
||||
aResult.Append(schemeString);
|
||||
if (NS_SUCCEEDED(proxyURI->SchemeIs("direct", &isScheme)) && !isScheme) {
|
||||
// Add the proxy URI only if it's not DIRECT
|
||||
proxyURI->GetHostPort(hostPortString);
|
||||
aResult.AppendLiteral(" ");
|
||||
aResult.Append(hostPortString);
|
||||
}
|
||||
|
||||
c++;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("returned PAC proxy string: %s\n", PromiseFlatCString(aResult).get());
|
||||
#endif
|
||||
|
||||
PR_Free(proxyArray);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "nsIGSettingsService.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
class nsUnixSystemProxySettings MOZ_FINAL : public nsISystemProxySettings {
|
||||
public:
|
||||
|
@ -44,14 +43,6 @@ private:
|
|||
|
||||
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
|
||||
nsUnixSystemProxySettings::Init()
|
||||
{
|
||||
|
@ -160,10 +151,8 @@ static void SetProxyResult(const char* aType, const nsACString& aHost,
|
|||
aResult.AppendASCII(aType);
|
||||
aResult.Append(' ');
|
||||
aResult.Append(aHost);
|
||||
if (aPort > 0) {
|
||||
aResult.Append(':');
|
||||
aResult.Append(nsPrintfCString("%d", aPort));
|
||||
}
|
||||
aResult.Append(':');
|
||||
aResult.Append(nsPrintfCString("%d", aPort));
|
||||
}
|
||||
|
||||
static nsresult
|
||||
|
@ -492,21 +481,29 @@ nsUnixSystemProxySettings::GetProxyFromGSettings(const nsACString& aScheme,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsUnixSystemProxySettings::GetProxyForURI(const nsACString & aSpec,
|
||||
const nsACString & aScheme,
|
||||
const nsACString & aHost,
|
||||
const int32_t aPort,
|
||||
nsACString & aResult)
|
||||
nsUnixSystemProxySettings::GetProxyForURI(nsIURI* aURI, 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) {
|
||||
nsresult rv = GetProxyFromGSettings(aScheme, aHost, aPort, aResult);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = GetProxyFromGSettings(scheme, host, port, aResult);
|
||||
if (rv == NS_OK)
|
||||
return rv;
|
||||
}
|
||||
if (mGConf)
|
||||
return GetProxyFromGConf(aScheme, aHost, aPort, aResult);
|
||||
return GetProxyFromGConf(scheme, host, port, aResult);
|
||||
|
||||
return GetProxyFromEnvironment(aScheme, aHost, aPort, aResult);
|
||||
return GetProxyFromEnvironment(scheme, host, port, aResult);
|
||||
}
|
||||
|
||||
#define NS_UNIXSYSTEMPROXYSERVICE_CID /* 0fa3158c-d5a7-43de-9181-a285e74cf1d4 */\
|
||||
|
|
|
@ -32,15 +32,7 @@ private:
|
|||
bool PatternMatch(const nsACString& aHost, const nsACString& aOverride);
|
||||
};
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsWindowsSystemProxySettings, nsISystemProxySettings)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWindowsSystemProxySettings::GetMainThreadOnly(bool *aMainThreadOnly)
|
||||
{
|
||||
*aMainThreadOnly = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsWindowsSystemProxySettings, nsISystemProxySettings)
|
||||
|
||||
nsresult
|
||||
nsWindowsSystemProxySettings::Init()
|
||||
|
@ -48,12 +40,33 @@ nsWindowsSystemProxySettings::Init()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static void SetProxyResult(const char* aType, const nsACString& aHostPort,
|
||||
nsACString& aResult)
|
||||
static void SetProxyResult(const char* aType, const nsACString& aHost,
|
||||
int32_t aPort, nsACString& aResult)
|
||||
{
|
||||
aResult.AssignASCII(aType);
|
||||
aResult.Append(' ');
|
||||
aResult.Append(aHostPort);
|
||||
aResult.Append(aHost);
|
||||
aResult.Append(':');
|
||||
aResult.Append(nsPrintfCString("%d", aPort));
|
||||
}
|
||||
|
||||
static void SetProxyResult(const char* aType, const nsACString& aHostPort,
|
||||
nsACString& aResult)
|
||||
{
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsAutoCString host;
|
||||
int32_t port;
|
||||
|
||||
// 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)
|
||||
|
@ -209,11 +222,7 @@ nsWindowsSystemProxySettings::GetPACURI(nsACString& aResult)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsWindowsSystemProxySettings::GetProxyForURI(const nsACString & aSpec,
|
||||
const nsACString & aScheme,
|
||||
const nsACString & aHost,
|
||||
const int32_t aPort,
|
||||
nsACString & aResult)
|
||||
nsWindowsSystemProxySettings::GetProxyForURI(nsIURI* aURI, nsACString& aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
uint32_t flags = 0;
|
||||
|
@ -225,7 +234,15 @@ nsWindowsSystemProxySettings::GetProxyForURI(const nsACString & aSpec,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
if (MatchOverride(aHost)) {
|
||||
nsAutoCString scheme;
|
||||
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);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -233,7 +250,7 @@ nsWindowsSystemProxySettings::GetProxyForURI(const nsACString & aSpec,
|
|||
NS_ConvertUTF16toUTF8 cbuf(buf);
|
||||
|
||||
nsAutoCString prefix;
|
||||
ToLowerCase(aScheme, prefix);
|
||||
ToLowerCase(scheme, prefix);
|
||||
|
||||
prefix.Append('=');
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче