Backout 3182f9d08c2d (bug 347307), 2a30593cca79 (bug 507578), b87b27f5a417 (bug 769764) for m-oth permaorange in browser_463205.js
authorEd Morley <emorley@mozilla.com>
Thu, 13 Sep 2012 22:42:29 +0100
changeset 113331 e59b9b887c2586b05613a2f696e981544705a68a
parent 113330 710e45d869208cc9f410423d85d300a218661fe3
child 113332 8daf8d51c827ea0e3c7c649d9bc7abf3b55e7242
push id1708
push userakeybl@mozilla.com
push dateMon, 19 Nov 2012 21:10:21 +0000
treeherdermozilla-beta@27b14fe50103 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs347307, 507578, 769764
milestone18.0a1
backs out3182f9d08c2dc22f4234616169366a887b800cf3
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backout 3182f9d08c2d (bug 347307), 2a30593cca79 (bug 507578), b87b27f5a417 (bug 769764) for m-oth permaorange in browser_463205.js
b2g/installer/package-manifest.in
browser/installer/package-manifest.in
browser/installer/removed-files.in
dom/plugins/base/nsPluginHost.cpp
mobile/android/installer/package-manifest.in
mobile/xul/installer/package-manifest.in
modules/libpref/src/init/all.js
netwerk/base/public/Makefile.in
netwerk/base/public/nsIProtocolProxyService.idl
netwerk/base/public/nsIProtocolProxyService2.idl
netwerk/base/public/nsIProxiedProtocolHandler.idl
netwerk/base/public/nsIProxyAutoConfig.idl
netwerk/base/public/nsISystemProxySettings.idl
netwerk/base/public/nsNetUtil.h
netwerk/base/src/Makefile.in
netwerk/base/src/ProxyAutoConfig.cpp
netwerk/base/src/ProxyAutoConfig.h
netwerk/base/src/nsBaseChannel.cpp
netwerk/base/src/nsIOService.cpp
netwerk/base/src/nsPACMan.cpp
netwerk/base/src/nsPACMan.h
netwerk/base/src/nsProtocolProxyService.cpp
netwerk/base/src/nsProtocolProxyService.h
netwerk/base/src/nsProxyAutoConfig.js
netwerk/base/src/nsProxyAutoConfig.manifest
netwerk/dns/nsDNSService2.cpp
netwerk/dns/nsPIDNSService.idl
netwerk/protocol/ftp/nsFTPChannel.h
netwerk/protocol/ftp/nsFtpConnectionThread.cpp
netwerk/protocol/ftp/nsFtpConnectionThread.h
netwerk/protocol/ftp/nsFtpProtocolHandler.cpp
netwerk/protocol/http/HttpBaseChannel.cpp
netwerk/protocol/http/HttpBaseChannel.h
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/protocol/http/nsHttpChannel.h
netwerk/protocol/http/nsHttpHandler.cpp
netwerk/protocol/http/nsHttpHandler.h
netwerk/test/unit/test_protocolproxyservice.js
netwerk/test/unit/test_proxy-failover_canceled.js
netwerk/test/unit/test_proxy-replace_canceled.js
toolkit/components/passwordmgr/test/test_bug_627616.html
toolkit/components/passwordmgr/test/test_prompt.html
toolkit/components/passwordmgr/test/test_prompt_async.html
toolkit/system/osxproxy/nsOSXSystemProxySettings.mm
toolkit/system/unixproxy/nsLibProxySettings.cpp
toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
toolkit/system/windowsproxy/nsWindowsSystemProxySettings.cpp
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -361,16 +361,18 @@
 #ifdef MOZ_GTK2
 @BINPATH@/components/nsFilePicker.manifest
 @BINPATH@/components/nsFilePicker.js
 #endif
 @BINPATH@/components/nsHelperAppDlg.manifest
 @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
 @BINPATH@/components/GPSDGeolocationProvider.js
 @BINPATH@/components/nsSidebar.manifest
 @BINPATH@/components/nsSidebar.js
 @BINPATH@/components/extensions.manifest
 @BINPATH@/components/addonManager.js
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -356,16 +356,18 @@
 #ifdef MOZ_GTK2
 @BINPATH@/components/nsFilePicker.manifest
 @BINPATH@/components/nsFilePicker.js
 #endif
 @BINPATH@/components/nsHelperAppDlg.manifest
 @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
 @BINPATH@/components/GPSDGeolocationProvider.js
 @BINPATH@/components/nsSidebar.manifest
 @BINPATH@/components/nsSidebar.js
 @BINPATH@/components/extensions.manifest
 @BINPATH@/components/addonManager.js
--- a/browser/installer/removed-files.in
+++ b/browser/installer/removed-files.in
@@ -82,18 +82,16 @@ components/dom_system_b2g.xpt
 components/uconvd.dll
 components/WeaveCrypto.js
 components/WeaveCrypto.manifest
 components/xmlextras.xpt
 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
 defaults/pref/bug259708.js
 defaults/pref/bug307259.js
 defaults/pref/reporter.js
 defaults/pref/security-prefs.js
 defaults/pref/winpref.js
@@ -918,17 +916,16 @@ xpicleanup@BIN_SUFFIX@
   components/nsLoginInfo.js
   components/nsLoginManager.js
   components/nsLoginManagerPrompter.js
   components/nsPlacesAutoComplete.js
   components/nsPlacesDBFlush.js
   components/nsPlacesExpiration.js
   components/nsPrivateBrowsingService.js
   components/nsPrompter.js
-  components/nsProxyAutoConfig.manifest
   components/nsProxyAutoConfig.js
   components/nsSafebrowsingApplication.js
   components/nsSearchService.js
   components/nsSearchSuggestions.js
   components/nsSessionStartup.js
   components/nsSessionStore.js
   components/nsSetDefaultBrowser.js
   components/nsSidebar.js
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -26,17 +26,17 @@
 #include "nsIUploadChannel.h"
 #include "nsIByteRangeRequest.h"
 #include "nsIStreamListener.h"
 #include "nsIInputStream.h"
 #include "nsIOutputStream.h"
 #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)
 #include "nsILocalFileMac.h"
 #endif
 #include "nsIInputStream.h"
 #include "nsIIOService.h"
 #include "nsIURL.h"
@@ -738,40 +738,34 @@ nsresult nsPluginHost::FindProxyForURL(c
 {
   if (!url || !result) {
     return NS_ERROR_INVALID_ARG;
   }
   nsresult res;
 
   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;
 
   // make an nsURI from the argument url
   res = ioService->NewURI(nsDependentCString(url), nullptr, nullptr, getter_AddRefs(uriIn));
   if (NS_FAILED(res))
     return res;
 
   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;
 
   nsAutoCString host, type;
   int32_t port = -1;
 
   // These won't fail, and even if they do... we'll be ok.
   if (pi) {
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -270,16 +270,18 @@
 #ifdef MOZ_GTK2
 @BINPATH@/components/nsFilePicker.manifest
 @BINPATH@/components/nsFilePicker.js
 #endif
 @BINPATH@/components/nsHelperAppDlg.manifest
 @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
 @BINPATH@/components/GPSDGeolocationProvider.js
 @BINPATH@/components/nsSidebar.manifest
 @BINPATH@/components/nsSidebar.js
 @BINPATH@/components/extensions.manifest
 @BINPATH@/components/addonManager.js
--- a/mobile/xul/installer/package-manifest.in
+++ b/mobile/xul/installer/package-manifest.in
@@ -337,16 +337,18 @@
 #ifdef MOZ_GTK2
 @BINPATH@/components/nsFilePicker.manifest
 @BINPATH@/components/nsFilePicker.js
 #endif
 @BINPATH@/components/nsHelperAppDlg.manifest
 @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
 @BINPATH@/components/GPSDGeolocationProvider.js
 @BINPATH@/components/nsSidebar.manifest
 @BINPATH@/components/nsSidebar.js
 @BINPATH@/components/extensions.manifest
 @BINPATH@/components/addonManager.js
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -1117,19 +1117,16 @@ pref("network.IDN.blacklist_chars", "\u0
 // This preference specifies a list of domains for which DNS lookups will be
 // IPv4 only. Works around broken DNS servers which can't handle IPv6 lookups
 // and/or allows the user to disable IPv6 on a per-domain basis. See bug 68796.
 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);
 
 // This preference controls whether or not URLs are always encoded and sent as
 // UTF-8.
 pref("network.standard-url.encode-utf8", true);
 
--- a/netwerk/base/public/Makefile.in
+++ b/netwerk/base/public/Makefile.in
@@ -61,16 +61,17 @@ XPIDLSRCS	= \
 		nsIPrivateBrowsingService.idl \
 		nsIProgressEventSink.idl \
 		nsIPrompt.idl \
 		nsIProtocolProxyService.idl \
 		nsIProtocolProxyService2.idl \
 		nsIProtocolProxyFilter.idl \
 		nsIProtocolProxyCallback.idl \
 		nsIProxiedProtocolHandler.idl \
+		nsIProxyAutoConfig.idl \
 		nsIProxyInfo.idl \
 		nsITransport.idl \
 		nsISocketTransport.idl \
 		nsISocketTransportService.idl \
 		nsISpeculativeConnect.idl \
 		nsIServerSocket.idl \
 		nsIResumableChannel.idl \
 		nsIRequestObserverProxy.idl \
--- a/netwerk/base/public/nsIProtocolProxyService.idl
+++ b/netwerk/base/public/nsIProtocolProxyService.idl
@@ -12,20 +12,34 @@ interface nsIProtocolProxyFilter;
 interface nsIProxyInfo;
 interface nsIChannel;
 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
      * resolve and asyncResolve methods to request to prefer the SOCKS proxy
      * to HTTP ones.
      */
     const unsigned long RESOLVE_PREFER_SOCKS_PROXY = 1 << 1;
 
@@ -58,46 +72,67 @@ interface nsIProtocolProxyService : nsIS
     /**
      * When the proxy configuration is manual this flag may be passed to the
      * resolve and asyncResolve methods to that all methods will be tunneled via
      * CONNECT through the http proxy.
      */
     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.
+     * @param aFlags
+     *        A bit-wise combination of the RESOLVE_ flags defined above.  Pass
+     *        0 to specify the default behavior.  Any additional bits that do
+     *        not correspond to a RESOLVE_ flag are reserved for future use.
+     *
+     * NOTE: If this proxy is unavailable, getFailoverForProxy may be called
+     * to determine the correct secondary proxy to be used.
+     *
+     * NOTE: If the protocol handler for the given URI supports
+     * nsIProxiedProtocolHandler, then the nsIProxyInfo instance returned from
+     * resolve may be passed to the newProxiedChannel method to create a
+     * nsIChannel to the given URI that uses the specified proxy.
+     *
+     * NOTE: However, if the nsIProxyInfo type is "http", then it means that
+     * the given URI should be loaded using the HTTP protocol handler, which
+     * also supports nsIProxiedProtocolHandler.
+     *
+     * NOTE: If PAC is configured, and the PAC file has not yet been loaded,
+     * then this method will return a nsIProxyInfo instance with a type of
+     * "unknown" to indicate to the consumer that asyncResolve should be used
+     * to wait for the PAC file to finish loading.  Otherwise, the consumer
+     * may choose to treat the result as type "direct" if desired.
+     *
+     * @see nsIProxiedProtocolHandler::newProxiedChannel 
+     */
+    nsIProxyInfo resolve(in nsIURI aURI, in unsigned long aFlags);
+
+    /**
+     * This method is an asychronous version of the resolve method.  Unlike
+     * resolve, this method is guaranteed not to block the calling thread
+     * waiting for DNS queries to complete.  This method is intended as a
+     * substitute for resolve when the result is not needed immediately.
      *
      * @param aURI
      *        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.
-     *
-     * NOTE: If this proxy is unavailable, getFailoverForProxy may be called
-     * to determine the correct secondary proxy to be used.
-     *
-     * NOTE: If the protocol handler for the given URI supports
-     * nsIProxiedProtocolHandler, then the nsIProxyInfo instance returned from
-     * resolve may be passed to the newProxiedChannel method to create a
-     * nsIChannel to the given URI that uses the specified proxy.
-     *
-     * NOTE: However, if the nsIProxyInfo type is "http", then it means that
-     * the given URI should be loaded using the HTTP protocol handler, which
-     * also supports nsIProxiedProtocolHandler.
-     *
-     * @see nsIProxiedProtocolHandler::newProxiedChannel 
      */
     nsICancelable asyncResolve(in nsIURI aURI, in unsigned long aFlags,
                                in nsIProtocolProxyCallback aCallback);
 
     /**
      * This method may be called to construct a nsIProxyInfo instance from
      * the given parameters.  This method may be useful in conjunction with
      * nsISocketTransportService::createTransport for creating, for example,
--- a/netwerk/base/public/nsIProtocolProxyService2.idl
+++ b/netwerk/base/public/nsIProtocolProxyService2.idl
@@ -4,26 +4,17 @@
  * 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 "nsIProtocolProxyService.idl"
 
 /**
  * An extension of nsIProtocolProxyService
  */
-[scriptable, uuid(bed3702d-9374-4804-a20f-32baed8e2954)]
+[scriptable, uuid(dbd9565d-29b1-437a-bff5-2fc339e2c5df)]
 interface nsIProtocolProxyService2 : nsIProtocolProxyService
 {
   /**
    * Call this method to cause the PAC file (if any is configured) to be
    * 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);
 };
--- a/netwerk/base/public/nsIProxiedProtocolHandler.idl
+++ b/netwerk/base/public/nsIProxiedProtocolHandler.idl
@@ -4,31 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIProtocolHandler.idl"
 
 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);
 };
 
new file mode 100644
--- /dev/null
+++ b/netwerk/base/public/nsIProxyAutoConfig.idl
@@ -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);
+};
--- a/netwerk/base/public/nsISystemProxySettings.idl
+++ b/netwerk/base/public/nsISystemProxySettings.idl
@@ -8,36 +8,22 @@
 
 /** 
  * This interface allows the proxy code to use platform-specific proxy
  * settings when the proxy preference is set to "automatic discovery". This service
  * acts like a PAC parser to netwerk, but it will actually read the system settings and
  * 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);
 };
--- a/netwerk/base/public/nsNetUtil.h
+++ b/netwerk/base/public/nsNetUtil.h
@@ -846,16 +846,50 @@ NS_GetReferrerFromChannel(nsIChannel *ch
         rv = chan->GetReferrer(referrer);
         if (NS_FAILED(rv))
           *referrer = nullptr;
       }
     }
     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,
                     nsCString        &contentCharset)
 {
     // contentCharset is left untouched if not present in rawContentType
     nsresult rv;
     nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
--- a/netwerk/base/src/Makefile.in
+++ b/netwerk/base/src/Makefile.in
@@ -61,21 +61,18 @@ CPPSRCS		= \
 		nsNetAddr.cpp \
 		nsNetStrings.cpp \
 		nsBase64Encoder.cpp \
 		nsSerializationHelper.cpp \
 		nsDNSPrefetch.cpp \
 		RedirectChannelRegistrar.cpp \
 		nsPreloadedStream.cpp \
 		nsStreamListenerWrapper.cpp \
-		ProxyAutoConfig.cpp \
 		$(NULL)
 
-LOCAL_INCLUDES	+= -I$(topsrcdir)/dom/base
-
 ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
 	CPPSRCS += nsURLHelperOS2.cpp
 else
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 	CPPSRCS += nsURLHelperWin.cpp
 	CPPSRCS += nsNativeConnectionHelper.cpp
 	CPPSRCS += nsAutodialWin.cpp
 else
@@ -95,16 +92,21 @@ ifdef MOZ_ENABLE_LIBCONIC
 endif
 ifdef MOZ_ENABLE_QTNETWORK
 	CPPSRCS += nsAutodialQt.cpp
 	LOCAL_INCLUDES += -I$(srcdir)/../../system/qt
 	OS_INCLUDES += $(MOZ_QT_CFLAGS)
 endif
 endif
 
+EXTRA_COMPONENTS = \
+		$(srcdir)/nsProxyAutoConfig.js \
+		$(srcdir)/nsProxyAutoConfig.manifest \
+		$(NULL)
+
 EXTRA_JS_MODULES = \
 		NetUtil.jsm \
 		$(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a
 # static lib.
 FORCE_STATIC_LIB = 1
 
deleted file mode 100644
--- a/netwerk/base/src/ProxyAutoConfig.cpp
+++ /dev/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
deleted file mode 100644
--- a/netwerk/base/src/ProxyAutoConfig.h
+++ /dev/null
@@ -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__
--- a/netwerk/base/src/nsBaseChannel.cpp
+++ b/netwerk/base/src/nsBaseChannel.cpp
@@ -696,35 +696,32 @@ nsBaseChannel::OnStartRequest(nsIRequest
 
   // Now, the general type sniffers. Skip this if we have none.
   if ((mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS) &&
       gIOService->GetContentSniffers().Count() != 0)
     mPump->PeekStream(CallTypeSniffers, static_cast<nsIChannel*>(this));
 
   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
 nsBaseChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
                              nsresult status)
 {
   // If both mStatus and status are failure codes, we keep mStatus as-is since
   // that is consistent with our GetStatus and Cancel methods.
   if (NS_SUCCEEDED(mStatus))
     mStatus = status;
 
   // 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;
 
   // No need to suspend pump in this scope since we will not be receiving
   // any more events from it.
 
   if (mLoadGroup)
     mLoadGroup->RemoveRequest(this, nullptr, mStatus);
--- a/netwerk/base/src/nsIOService.cpp
+++ b/netwerk/base/src/nsIOService.cpp
@@ -34,19 +34,16 @@
 #include "nsSimpleNestedURI.h"
 #include "nsNetUtil.h"
 #include "nsThreadUtils.h"
 #include "nsIPermissionManager.h"
 #include "nsTArray.h"
 #include "nsIConsoleService.h"
 #include "nsIUploadChannel2.h"
 #include "nsXULAppAPI.h"
-#include "nsIProxiedChannel.h"
-#include "nsIProtocolProxyCallback.h"
-#include "nsICancelable.h"
 
 #include "mozilla/FunctionTimer.h"
 
 #if defined(XP_WIN) || defined(MOZ_PLATFORM_MAEMO)
 #include "nsNativeConnectionHelper.h"
 #endif
 
 #define PORT_PREF_PREFIX           "network.security.ports."
@@ -574,16 +571,41 @@ nsIOService::NewFileURI(nsIFile *file, n
 }
 
 NS_IMETHODIMP
 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,
                                              uint32_t aProxyFlags,
                                              nsIChannel **result)
 {
     nsresult rv;
     NS_ENSURE_ARG_POINTER(aURI);
@@ -598,21 +620,36 @@ nsIOService::NewChannelFromURIWithProxyF
     if (NS_FAILED(rv))
         return rv;
 
     uint32_t protoFlags;
     rv = handler->GetProtocolFlags(&protoFlags);
     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
     // implementation. The channels returned from that implementation doesn't
     // seem to always implement the nsIUploadChannel2 interface, presumably
     // because it's a new interface.
     // Eventually we should remove this and simply require that http channels
     // implement the new interface.
@@ -1170,84 +1207,40 @@ nsIOService::ExtractCharsetFromContentTy
                          aCharsetStart, aCharsetEnd);
     if (*aHadCharset && *aCharsetStart == *aCharsetEnd) {
         *aHadCharset = false;
     }
     return NS_OK;
 }
 
 // nsISpeculativeConnect
-class IOServiceProxyCallback MOZ_FINAL : public nsIProtocolProxyCallback
+NS_IMETHODIMP
+nsIOService::SpeculativeConnect(nsIURI *aURI,
+                                nsIInterfaceRequestor *aCallbacks,
+                                nsIEventTarget *aTarget)
 {
-public:
-    NS_DECL_ISUPPORTS
-    NS_DECL_NSIPROTOCOLPROXYCALLBACK
-
-    IOServiceProxyCallback(nsIInterfaceRequestor *aCallbacks,
-                           nsIEventTarget *aTarget,
-                           nsIOService *aIOService)
-        : mCallbacks(aCallbacks)
-        , mTarget(aTarget)
-        , mIOService(aIOService)
-    { }
-
-private:
-    nsRefPtr<nsIInterfaceRequestor> mCallbacks;
-    nsRefPtr<nsIEventTarget>        mTarget;
-    nsRefPtr<nsIOService>           mIOService;
-};
-
-NS_IMPL_ISUPPORTS1(IOServiceProxyCallback, nsIProtocolProxyCallback)
-
-NS_IMETHODIMP
-IOServiceProxyCallback::OnProxyAvailable(nsICancelable *request, nsIURI *aURI,
-                                         nsIProxyInfo *pi, nsresult status)
-{
-    // Checking proxy status for speculative connect
-    nsAutoCString type;
-    if (NS_SUCCEEDED(status) && pi &&
-        NS_SUCCEEDED(pi->GetType(type)) &&
-        !type.EqualsLiteral("direct")) {
-        // proxies dont do speculative connect
-        return NS_OK;
-    }
-
     nsAutoCString scheme;
     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;
+    return speculativeHandler->SpeculativeConnect(aURI,
+                                                  aCallbacks,
+                                                  aTarget);
 }
-
-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));
-}
--- a/netwerk/base/src/nsPACMan.cpp
+++ b/netwerk/base/src/nsPACMan.cpp
@@ -1,34 +1,31 @@
 /* -*- 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 "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.
 static bool
 HttpRequestSucceeded(nsIStreamLoader *loader)
 {
   nsCOMPtr<nsIRequest> request;
   loader->GetRequest(getter_AddRefs(request));
@@ -39,305 +36,199 @@ HttpRequestSucceeded(nsIStreamLoader *lo
   if (httpChannel)
     httpChannel->GetRequestSucceeded(&result);
 
   return result;
 }
 
 //-----------------------------------------------------------------------------
 
-// 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)
-  {
-  }
-
-  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;
-  }
-
-private:
-  nsRefPtr<nsPACManCallback> mCallback;
-  nsresult                   mStatus;
-  nsCString                  mPACString;
-  nsCString                  mPACURL;
-};
-
-//-----------------------------------------------------------------------------
+  NS_DECL_ISUPPORTS
+  NS_DECL_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
-{
-public:
-  ShutdownThread(nsIThread *thread)
-    : mThread(thread)
-  {
-  }
-
-  NS_IMETHODIMP Run()
+  PendingPACQuery(nsPACMan *pacMan, nsIURI *uri, nsPACManCallback *callback)
+    : mPACMan(pacMan)
+    , mURI(uri)
+    , mCallback(callback)
   {
-    NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
-    mThread->Shutdown();
-    return NS_OK;
-  }
-
-private:
-  nsCOMPtr<nsIThread> mThread;
-};
-
-//-----------------------------------------------------------------------------
-
-// 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)
-  {
+    PR_INIT_CLIST(this);
   }
 
-  NS_IMETHODIMP Run()
-  {
-    NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
-    mPACMan->mLoader = nullptr;
-    mPACMan->PostProcessPendingQ();
-    return NS_OK;
-  }
+  nsresult Start(uint32_t flags);
+  void     Complete(nsresult status, const nsCString &pacString);
 
 private:
-    nsRefPtr<nsPACMan> mPACMan;
+  nsPACMan                  *mPACMan;  // weak reference
+  nsCOMPtr<nsIURI>           mURI;
+  nsRefPtr<nsPACManCallback> mCallback;
+  nsCOMPtr<nsICancelable>    mDNSRequest;
 };
 
-//-----------------------------------------------------------------------------
+// This is threadsafe because we implement nsIDNSListener
+NS_IMPL_THREADSAFE_ISUPPORTS1(PendingPACQuery, nsIDNSListener)
 
-// 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
+nsresult
+PendingPACQuery::Start(uint32_t flags)
 {
-public:
-  // by default we just process the queue
-  ExecutePACThreadAction(nsPACMan *aPACMan)
-    : mPACMan(aPACMan)
-    , mCancel(false)
-    , mSetupPAC(false)
-  { }
+  if (mDNSRequest)
+    return NS_OK;  // already started
 
-  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;
+  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");
-    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;
-  }
+  nsAutoCString host;
+  rv = mURI->GetAsciiHost(host);
+  if (NS_FAILED(rv))
+    return rv;
 
-private:
-  nsRefPtr<nsPACMan> mPACMan;
-
-  bool      mCancel;
-  nsresult  mCancelStatus;
-
-  bool                 mSetupPAC;
-  nsCString            mSetupPACData;
-  nsCString            mSetupPACURI;
-};
+  rv = dns->AsyncResolve(host, flags, this, NS_GetCurrentThread(),
+                         getter_AddRefs(mDNSRequest));
+  if (NS_FAILED(rv))
+    NS_WARNING("DNS AsyncResolve failed");
 
-//-----------------------------------------------------------------------------
-
-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();
-}
+
+  mCallback->OnQueryComplete(status, pacString);
+  mCallback = nullptr;
 
-void
-PendingPACQuery::UseAlternatePACFile(const nsCString &pacURL)
-{
-  if (!mCallback)
-    return;
-
-  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;
 }
 
 //-----------------------------------------------------------------------------
 
 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::GetProxyForURI(nsIURI *uri, nsACString &result)
+{
+  NS_ENSURE_STATE(!mShutdown);
+
+  if (IsPACURI(uri)) {
+    result.Truncate();
+    return NS_OK;
+  }
+
+  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::AsyncGetProxyForURI(nsIURI *uri, nsPACManCallback *callback,
-                              bool mainThreadResponse)
+nsPACMan::AsyncGetProxyForURI(nsIURI *uri, nsPACManCallback *callback)
 {
-  NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
-  if (mShutdown)
-    return NS_ERROR_NOT_AVAILABLE;
+  NS_ENSURE_STATE(!mShutdown);
+
+  MaybeReloadPAC();
+
+  PendingPACQuery *query = new PendingPACQuery(this, uri, callback);
+  if (!query)
+    return NS_ERROR_OUT_OF_MEMORY;
+  NS_ADDREF(query);
+  PR_APPEND_LINK(query, &mPendingQ);
 
-  // Maybe Reload PAC
-  if (mPACURI && !mScheduledReload.IsNull() &&
-      TimeStamp::Now() > mScheduledReload)
-    LoadPACFromURI(nullptr);
+  // 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);
 
-  nsRefPtr<PendingPACQuery> query =
-    new PendingPACQuery(this, uri, callback, mainThreadResponse);
+  if (IsLoading() && !isPACURI)
+    return NS_OK;
 
-  if (IsPACURI(uri)) {
-    // deal with this directly instead of queueing it
-    query->Complete(NS_OK, EmptyCString());
-    return NS_OK;
+  nsresult rv = query->Start(isPACURI ? 0 : nsIDNSService::RESOLVE_SPECULATE);
+  if (rv == NS_ERROR_DNS_LOOKUP_QUEUE_FULL && !isPACURI) {
+    query->OnLookupComplete(NULL, NULL, NS_OK);
+    rv = NS_OK;
+  } else if (NS_FAILED(rv)) {
+    NS_WARNING("failed to start PAC query");
+    PR_REMOVE_LINK(query);
+    NS_RELEASE(query);
   }
 
-  return mPACThread->Dispatch(query, nsIEventTarget::DISPATCH_NORMAL);
-}
-
-nsresult
-nsPACMan::PostQuery(PendingPACQuery *query)
-{
-  NS_ABORT_IF_FALSE(!NS_IsMainThread(), "wrong thread");
-
-  if (mShutdown) {
-    query->Complete(NS_ERROR_NOT_AVAILABLE, EmptyCString());
-    return NS_OK;
-  }
-
-  // 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
 nsPACMan::LoadPACFromURI(nsIURI *pacURI)
 {
   NS_ENSURE_STATE(!mShutdown);
   NS_ENSURE_ARG(pacURI || mPACURI);
 
@@ -360,34 +251,31 @@ nsPACMan::LoadPACFromURI(nsIURI *pacURI)
     mLoadPending = true;
   }
 
   CancelExistingLoad();
 
   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;
   }
 
   if (NS_SUCCEEDED(mLoader->Init(this))) {
     // Always hit the origin server when loading PAC.
     nsCOMPtr<nsIIOService> ios = do_GetIOService();
     if (ios) {
       nsCOMPtr<nsIChannel> channel;
@@ -400,19 +288,28 @@ nsPACMan::StartLoading()
         channel->SetNotificationCallbacks(this);
         if (NS_SUCCEEDED(channel->AsyncOpen(mLoader, nullptr)))
           return;
       }
     }
   }
 
   CancelExistingLoad();
-  PostCancelPendingQ(NS_ERROR_UNEXPECTED);
+  ProcessPendingQ(NS_ERROR_UNEXPECTED);
 }
 
+void
+nsPACMan::MaybeReloadPAC()
+{
+  if (!mPACURI)
+    return;
+
+  if (PR_Now() > mScheduledReload)
+    LoadPACFromURI(nullptr);
+}
 
 void
 nsPACMan::OnLoadFailure()
 {
   int32_t minInterval = 5;    // 5 seconds
   int32_t maxInterval = 300;  // 5 minutes
 
   nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
@@ -422,203 +319,123 @@ nsPACMan::OnLoadFailure()
     prefs->GetIntPref("network.proxy.autoconfig_retry_interval_max",
                       &maxInterval);
   }
 
   int32_t interval = minInterval << mLoadFailureCount++;  // seconds
   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
 nsPACMan::CancelExistingLoad()
 {
   if (mLoader) {
     nsCOMPtr<nsIRequest> request;
     mLoader->GetRequest(getter_AddRefs(request));
     if (request)
       request->Cancel(NS_ERROR_ABORT);
     mLoader = nullptr;
   }
 }
 
 void
-nsPACMan::PostProcessPendingQ()
-{
-  NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
-  nsRefPtr<ExecutePACThreadAction> pending =
-    new ExecutePACThreadAction(this);
-  if (mPACThread)
-    mPACThread->Dispatch(pending, nsIEventTarget::DISPATCH_NORMAL);
-}
-
-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)
+nsPACMan::ProcessPendingQ(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());
+  // 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);
+    }
   }
-
-  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,
                            nsISupports *context,
                            nsresult status,
                            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
     // should be NS_ERROR_ABORT, and if so, then we know that we can and
     // should delay any processing.
     if (status == NS_ERROR_ABORT)
       return NS_OK;
   }
 
+  mLoader = nullptr;
+
   if (NS_SUCCEEDED(status) && HttpRequestSucceeded(loader)) {
     // Get the URI spec used to load this PAC script.
     nsAutoCString pacURI;
     {
       nsCOMPtr<nsIRequest> request;
       loader->GetRequest(getter_AddRefs(request));
       nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
       if (channel) {
         nsCOMPtr<nsIURI> uri;
         channel->GetURI(getter_AddRefs(uri));
         if (uri)
           uri->GetAsciiSpec(pacURI);
       }
     }
 
-    // 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.
     mLoadFailureCount = 0;
   } else {
     // We were unable to load the PAC file (presumably because of a network
     // failure).  Try again a little later.
     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;
 }
 
 NS_IMETHODIMP
 nsPACMan::GetInterface(const nsIID &iid, void **result)
 {
   // In case loading the PAC file requires authentication.
   if (iid.Equals(NS_GET_IID(nsIAuthPrompt))) {
@@ -644,31 +461,8 @@ nsPACMan::AsyncOnChannelRedirect(nsIChan
 {
   nsresult rv = NS_OK;
   if (NS_FAILED((rv = newChannel->GetURI(getter_AddRefs(mPACURI)))))
       return rv;
 
   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;
-}
--- a/netwerk/base/src/nsPACMan.h
+++ b/netwerk/base/src/nsPACMan.h
@@ -5,84 +5,45 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsPACMan_h__
 #define nsPACMan_h__
 
 #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.
  */
 class NS_NO_VTABLE nsPACManCallback : public nsISupports
 {
 public:
   /**
    * This method is invoked on the same thread that called AsyncGetProxyForURI.
    *
    * @param status
    *        This parameter indicates whether or not the PAC query succeeded.
    * @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
 {
 public:
   NS_DECL_ISUPPORTS
 
   nsPACMan();
@@ -90,30 +51,40 @@ public:
   /**
    * This method may be called to shutdown the PAC manager.  Any async queries
    * that have not yet completed will either finish normally or be canceled by
    * the time this method returns.
    */
   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
    * will queue up the request, and complete it once the PAC file has been
    * loaded.
    * 
    * @param uri
    *        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
    * the PAC file, any asynchronous PAC queries will be queued up to be
    * processed once the PAC file finishes loading.
    *
    * @param pacURI
    *        The nsIURI of the PAC file to load.  If this parameter is null,
@@ -129,84 +100,54 @@ public:
   /**
    * Returns true if the given URI matches the URI of our PAC file.
    */
   bool IsPACURI(nsIURI *uri) {
     bool result;
     return mPACURI && NS_SUCCEEDED(mPACURI->Equals(uri, &result)) && result;
   }
 
-  bool IsPACURI(nsACString &spec)
-  {
-    nsAutoCString tmp;
-    return (mPACURI && NS_SUCCEEDED(mPACURI->GetSpec(tmp)) && tmp.Equals(spec));
-  }
-
-  NS_HIDDEN_(nsresult) Init(nsISystemProxySettings *);
-  static nsPACMan *sInstance;
-
-  // PAC thread operations only
-  void ProcessPendingQ();
-  void CancelPendingQ(nsresult);
-
 private:
   NS_DECL_NSISTREAMLOADEROBSERVER
   NS_DECL_NSIINTERFACEREQUESTOR
   NS_DECL_NSICHANNELEVENTSINK
 
-  friend class PendingPACQuery;
-  friend class PACLoadComplete;
-  friend class ExecutePACThreadAction;
-
   ~nsPACMan();
 
   /**
    * Cancel any existing load if any.
    */
   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.
    */
   void StartLoading();
 
   /**
    * Reload the PAC file if there is reason to.
    */
   void MaybeReloadPAC();
 
   /**
    * Called when we fail to load the PAC file.
    */
   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__
--- a/netwerk/base/src/nsProtocolProxyService.cpp
+++ b/netwerk/base/src/nsProtocolProxyService.cpp
@@ -7,36 +7,33 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/Util.h"
 
 #include "nsProtocolProxyService.h"
 #include "nsProxyInfo.h"
 #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"
 #include "nsThreadUtils.h"
 #include "nsString.h"
 #include "nsNetUtil.h"
 #include "nsNetCID.h"
 #include "nsCRT.h"
 #include "prnetdb.h"
 #include "nsPACMan.h"
-#include "nsProxyRelease.h"
-#include "mozilla/Mutex.h"
-#include "mozilla/CondVar.h"
 
 //----------------------------------------------------------------------------
 
 using namespace mozilla;
 
 #include "prlog.h"
 #if defined(PR_LOGGING)
 static PRLogModuleInfo *sLog = PR_NewLogModule("proxy");
@@ -70,59 +67,22 @@ public:
 
     nsAsyncResolveRequest(nsProtocolProxyService *pps, nsIURI *uri,
                           uint32_t aResolveFlags,
                           nsIProtocolProxyCallback *callback)
         : mStatus(NS_OK)
         , 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;
         mProxyInfo = pi;
     }
 
     NS_IMETHOD Run()
     {
@@ -159,29 +119,26 @@ public:
         mCallback = nullptr;  // break possible reference cycle
         return rv;
     }
 
 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)
             return;
 
         // Provided we haven't been canceled...
         if (mStatus == NS_OK) {
             mStatus = status;
             mPACString = pacString;
-            mPACURL = newPACURL;
         }
 
         // In the cancelation case, we may still have another PLEvent in
         // the queue that wants to call DoCallback.  No need to wait for
         // it, just run the callback now.
         DoCallback();
     }
 
@@ -194,73 +151,36 @@ private:
 
             // Now apply proxy filters
             nsProtocolInfo info;
             mStatus = mPPS->GetProtocolInfo(mURI, &info);
             if (NS_SUCCEEDED(mStatus))
                 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)
 
 //----------------------------------------------------------------------------
 
 #define IS_ASCII_SPACE(_c) ((_c) == ' ' || (_c) == '\t')
 
 //
 // apply mask to address (zeros out excluded bits).
 //
@@ -461,22 +381,18 @@ nsProtocolProxyService::PrefsChanged(nsI
             mProxyConfig = type;
             reloadPAC = true;
         }
 
         if (mProxyConfig == PROXYCONFIG_SYSTEM) {
             mSystemProxySettings = do_GetService(NS_SYSTEMPROXYSETTINGS_CONTRACTID);
             if (!mSystemProxySettings)
                 mProxyConfig = PROXYCONFIG_DIRECT;
-            ResetPACThread();
         } else {
-            if (mSystemProxySettings) {
-                mSystemProxySettings = nullptr;
-                ResetPACThread();
-            }
+            mSystemProxySettings = nullptr;
         }
     }
 
     if (!pref || !strcmp(pref, PROXY_PREF("http")))
         proxy_GetStringPref(prefBranch, PROXY_PREF("http"), mHTTPProxyHost);
 
     if (!pref || !strcmp(pref, PROXY_PREF("http_port")))
         proxy_GetIntPref(prefBranch, PROXY_PREF("http_port"), mHTTPProxyPort);
@@ -651,17 +567,17 @@ static const char kProxyType_UNKNOWN[] =
 const char *
 nsProtocolProxyService::ExtractProxyInfo(const char *start,
                                          uint32_t aResolveFlags,
                                          nsProxyInfo **result)
 {
     *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;
     while (*end && *end != ';') ++end;
 
     // find end of proxy type delimiter
     const char *sp = start;
     while (sp < end && *sp != ' ' && *sp != '\t') ++sp;
@@ -695,67 +611,43 @@ nsProtocolProxyService::ExtractProxyInfo
         // support it.
         if (type == kProxyType_SOCKS || mSOCKSProxyRemoteDNS)
             flags |= nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST;
 
         // extract host:port
         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')
         ++end;
     return end;
 }
 
 void
@@ -843,55 +735,24 @@ nsProtocolProxyService::IsProxyDisabled(
         mFailedProxies.Remove(key);
         return false;
     }
 
     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);
     if (NS_FAILED(rv))
         return rv;
 
     if (mPACMan->IsPACURI(pacURI) && !forceReload)
         return NS_OK;
@@ -948,172 +809,96 @@ nsProtocolProxyService::ReloadPAC()
     else if (type == PROXYCONFIG_WPAD)
         pacSpec.AssignLiteral(WPAD_URL);
 
     if (!pacSpec.IsEmpty())
         ConfigureFromPAC(pacSpec, true);
     return NS_OK;
 }
 
-// When sync interface is removed this can go away too
-class nsAsyncBridgeRequest MOZ_FINAL  : public nsPACManCallback
+// nsIProtocolProxyService
+NS_IMETHODIMP
+nsProtocolProxyService::Resolve(nsIURI *uri, uint32_t flags,
+                                nsIProxyInfo **result)
 {
-    NS_DECL_ISUPPORTS
-
-     nsAsyncBridgeRequest()
-        : mMutex("nsDeprecatedCallback")
-        , mCondVar(mMutex, "nsDeprecatedCallback")
-        , mCompleted(false)
-    {
-    }
-
-    void OnQueryComplete(nsresult status,
-                         const nsCString &pacString,
-                         const nsCString &newPACURL)
-    {
-        MutexAutoLock lock(mMutex);
-        mCompleted = true;
-        mStatus = status;
-        mPACString = pacString;
-        mPACURL = newPACURL;
-        mCondVar.Notify();
-    }
-
-    void Lock()   { mMutex.Lock(); }
-    void Unlock() { mMutex.Unlock(); }
-    void Wait()   { mCondVar.Wait(PR_SecondsToInterval(3)); }
-
-private:
-    ~nsAsyncBridgeRequest()
-    {
-    }
-
-    friend class nsProtocolProxyService;
-
-    Mutex    mMutex;
-    CondVar  mCondVar;
-
-    nsresult  mStatus;
-    nsCString mPACString;
-    nsCString mPACURL;
-    bool      mCompleted;
-};
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsAsyncBridgeRequest, nsPACManCallback)
-
-// nsIProtocolProxyService2
-NS_IMETHODIMP
-nsProtocolProxyService::DeprecatedBlockingResolve(nsIURI *aURI,
-                                                  uint32_t aFlags,
-                                                  nsIProxyInfo **retval)
-{
-    NS_ENSURE_ARG_POINTER(aURI);
+    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");
+
+        // If the caller didn't want us to invoke PAC, then error out.
+        if (flags & RESOLVE_NON_BLOCKING)
+            return NS_BASE_STREAM_WOULD_BLOCK;
 
-    // pretty much duplicate real DoCallback logic
-
-    // 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,
                                      nsICancelable **result)
 {
     NS_ENSURE_ARG_POINTER(uri);
     NS_ENSURE_ARG_POINTER(callback);
 
     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);
     }
     return rv;
 }
 
 NS_IMETHODIMP
@@ -1451,113 +1236,80 @@ nsProtocolProxyService::NewProxyInfo_Int
     NS_ADDREF(*aResult = proxyInfo);
     return NS_OK;
 }
 
 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;
+        // 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;
 
-        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);
-            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
     // proxy, check for a proxy.
     if (mProxyConfig == PROXYCONFIG_DIRECT ||
         (mProxyConfig == PROXYCONFIG_MANUAL &&
          !CanUseProxy(uri, info.defaultPort)))
         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;
     }
 
     // proxy info values
     const char *type = nullptr;
     const nsACString *host = nullptr;
     int32_t port = -1;
 
     uint32_t proxyFlags = 0;
 
     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;
       port = mSOCKSProxyPort;
       if (mSOCKSProxyRemoteDNS)
           proxyFlags |= nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST;
     }
     else if ((flags & RESOLVE_PREFER_HTTPS_PROXY) &&
@@ -1584,61 +1336,37 @@ nsProtocolProxyService::Resolve_Internal
              !(flags & RESOLVE_IGNORE_URI_SCHEME) &&
              info.scheme.EqualsLiteral("ftp")) {
         host = &mFTPProxyHost;
         type = kProxyType_HTTP;
         port = mFTPProxyPort;
     }
     else if (!mSOCKSProxyHost.IsEmpty() && mSOCKSProxyPort > 0) {
         host = &mSOCKSProxyHost;
-        if (mSOCKSProxyVersion == 4)
+        if (mSOCKSProxyVersion == 4) 
             type = kProxyType_SOCKS4;
         else
             type = kProxyType_SOCKS;
         port = mSOCKSProxyPort;
         if (mSOCKSProxyRemoteDNS)
             proxyFlags |= nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST;
     }
 
     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;
     }
 
     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)
 {
     if (!(info.flags & nsIProtocolHandler::ALLOWS_PROXY))
         return;
 
     // We prune the proxy list prior to invoking each filter.  This may be
     // somewhat inefficient, but it seems like a good idea since we want each
@@ -1678,17 +1406,17 @@ nsProtocolProxyService::PruneProxyInfo(c
     //   - If all proxies are disabled, return the full list
     //   - Otherwise, remove the disabled proxies.
     //
     // Pruning of disallowed proxies works like this:
     //   - If the protocol handler disallows the proxy, then we disallow it.
 
     // 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!
                 if (last)
                     last->mNext = iter->mNext;
                 else
                     head = iter->mNext;
                 nsProxyInfo *next = iter->mNext;
@@ -1702,32 +1430,32 @@ nsProtocolProxyService::PruneProxyInfo(c
         }
         if (!head)
             return;
     }
 
     // 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;
     for (iter = head; iter; iter = iter->mNext) {
         if (!IsProxyDisabled(iter)) {
             allDisabled = false;
             break;
         }
     }
 
     if (allDisabled)
         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!
                 nsProxyInfo *reject = iter;
 
                 iter = iter->mNext;
                 if (last)
                     last->mNext = iter;
--- a/netwerk/base/src/nsProtocolProxyService.h
+++ b/netwerk/base/src/nsProtocolProxyService.h
@@ -8,16 +8,17 @@
 
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsTArray.h"
 #include "nsIPrefBranch.h"
 #include "nsIProtocolProxyService2.h"
 #include "nsIProtocolProxyFilter.h"
+#include "nsIProxyAutoConfig.h"
 #include "nsISystemProxySettings.h"
 #include "nsIProxyInfo.h"
 #include "nsIObserver.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "nsPACMan.h"
 #include "prtime.h"
 #include "prmem.h"
@@ -266,28 +267,16 @@ protected:
      *        The URI to test.
      * @param defaultPort
      *        The default port for the given URI.
      *
      * @return True if the URI can use the specified proxy.
      */
     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
     // need to be public in order to deal with those compilers.
 
     struct HostInfoIP {
         uint16_t   family;
         uint16_t   mask_len;
new file mode 100644
--- /dev/null
+++ b/netwerk/base/src/nsProxyAutoConfig.js
@@ -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"
+
new file mode 100644
--- /dev/null
+++ b/netwerk/base/src/nsProxyAutoConfig.manifest
@@ -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}
--- a/netwerk/dns/nsDNSService2.cpp
+++ b/netwerk/dns/nsDNSService2.cpp
@@ -477,30 +477,16 @@ nsDNSService::Shutdown()
         res = mResolver;
         mResolver = nullptr;
     }
     if (res)
         res->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
 {
 public:
   DNSListenerProxy(nsIDNSListener* aListener, nsIEventTarget* aTargetThread)
     : mListener(aListener)
     , mTargetThread(aTargetThread)
--- a/netwerk/dns/nsPIDNSService.idl
+++ b/netwerk/dns/nsPIDNSService.idl
@@ -5,30 +5,25 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIDNSService.idl"
 
 /**
  * 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
 {
     /**
      * called to initialize the DNS service.
      */
     void init();
 
     /**
      * called to shutdown the DNS service.  any pending asynchronous
      * requests will be canceled, and the local cache of DNS records
      * will be cleared.  NOTE: the operating system may still have
      * its own cache of DNS records, which would be unaffected by
      * this method.
      */
     void shutdown();
-
-    /**
-     * Whether or not DNS prefetching (aka RESOLVE_SPECULATE) is enabled
-     */
-    attribute boolean prefetchEnabled;
 };
--- a/netwerk/protocol/ftp/nsFTPChannel.h
+++ b/netwerk/protocol/ftp/nsFTPChannel.h
@@ -50,21 +50,16 @@ public:
     {
         SetURI(uri);
     }
 
     nsIProxyInfo *ProxyInfo() {
         return mProxyInfo;
     }
 
-    void SetProxyInfo(nsIProxyInfo *pi)
-    {
-        mProxyInfo = pi;
-    }
-
     // Were we asked to resume a download?
     bool ResumeRequested() { return mResumeRequested; }
 
     // Download from this byte offset
     uint64_t StartPos() { return mStartPos; }
 
     // ID of the entity to resume downloading
     const nsCString &EntityID() {
--- a/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
+++ b/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
@@ -28,18 +28,16 @@
 #include "nsIURL.h"
 #include "nsISocketTransport.h"
 #include "nsIStreamListenerTee.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsIStringBundle.h"
 #include "nsAuthInformationHolder.h"
 #include "nsICharsetConverterManager.h"
-#include "nsIProtocolProxyService.h"
-#include "nsICancelable.h"
 
 #if defined(PR_LOGGING)
 extern PRLogModuleInfo* gFTPLog;
 #endif
 #define LOG(args)         PR_LOG(gFTPLog, PR_LOG_DEBUG, args)
 #define LOG_ALWAYS(args)  PR_LOG(gFTPLog, PR_LOG_ALWAYS, args)
 
 // remove FTP parameters (starting with ";") from the path
@@ -47,23 +45,22 @@ static void
 removeParamsFromPath(nsCString& path)
 {
   int32_t index = path.FindChar(';');
   if (index >= 0) {
     path.SetLength(index);
   }
 }
 
-NS_IMPL_ISUPPORTS_INHERITED5(nsFtpState,
+NS_IMPL_ISUPPORTS_INHERITED4(nsFtpState,
                              nsBaseContentStream,
                              nsIInputStreamCallback, 
                              nsITransportEventSink,
                              nsICacheListener,
-                             nsIRequestObserver,
-                             nsIProtocolProxyCallback)
+                             nsIRequestObserver)
 
 nsFtpState::nsFtpState()
     : nsBaseContentStream(true)
     , mState(FTP_INIT)
     , mNextState(FTP_S_USER)
     , mKeepRunning(true)
     , mReceivedControlData(false)
     , mTryingCachedControl(false)
@@ -76,31 +73,27 @@ nsFtpState::nsFtpState()
     , mStorReplyReceived(false)
     , mInternalError(NS_OK)
     , mReconnectAndLoginAgain(false)
     , mCacheConnection(true)
     , mPort(21)
     , mAddressChecked(false)
     , mServerIsIPv6(false)
     , mControlStatus(NS_OK)
-    , mDeferredCallbackPending(false)
 {
     LOG_ALWAYS(("FTP:(%x) nsFtpState created", this));
 
     // make sure handler stays around
     NS_ADDREF(gFtpHandler);
 }
 
 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);
 }
 
 // nsIInputStreamCallback implementation
 NS_IMETHODIMP
 nsFtpState::OnInputStreamReady(nsIAsyncInputStream *aInStream)
@@ -1761,29 +1754,16 @@ nsFtpState::Init(nsFtpChannel *channel)
     int32_t port;
     rv = mChannel->URI()->GetPort(&port);
     if (NS_FAILED(rv))
         return rv;
 
     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;
 }
 
 void
 nsFtpState::Connect()
 {
     mState = FTP_COMMAND_CONNECT;
     mNextState = FTP_S_USER;
@@ -2170,90 +2150,24 @@ nsFtpState::CloseWithStatus(nsresult sta
     mDataStream = nullptr;
     if (mDoomCache && mCacheEntry)
         mCacheEntry->Doom();
     mCacheEntry = nullptr;
 
     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()
 {
     // If this is the first call, then see if we could use the cache.  If we
     // aren't going to read from (or write to) the cache, then just proceed to
     // connect to the server.
 
     if (mState == FTP_INIT) {
-        if (mProxyRequest) {
-            mDeferredCallbackPending = true;
-            return;
-        }
-
         if (CheckCache()) {
             mState = FTP_WAIT_CACHE;
             return;
         } 
         if (mCacheEntry && CanReadCacheEntry() && ReadCacheEntry()) {
             mState = FTP_READ_CACHE;
             return;
         }
--- a/netwerk/protocol/ftp/nsFtpConnectionThread.h
+++ b/netwerk/protocol/ftp/nsFtpConnectionThread.h
@@ -30,17 +30,16 @@
 #include "nsIPrompt.h"
 #include "nsITransport.h"
 #include "nsIProxyInfo.h"
 
 #include "nsFtpControlConnection.h"
 
 #include "nsICacheEntryDescriptor.h"
 #include "nsICacheListener.h"
-#include "nsIProtocolProxyCallback.h"
 
 // ftp server types
 #define FTP_GENERIC_TYPE     0
 #define FTP_UNIX_TYPE        1
 #define FTP_VMS_TYPE         8
 #define FTP_NT_TYPE          9
 #define FTP_OS2_TYPE         11
 
@@ -73,38 +72,34 @@ typedef enum _FTP_STATE {
     FTP_S_PASV, FTP_R_PASV,
     FTP_S_PWD,  FTP_R_PWD
 } FTP_STATE;
 
 // higher level ftp actions
 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
 // implements nsITransportEventSink so it can mix status events from both the
 // control connection and the data connection.
 
 class nsFtpState : public nsBaseContentStream,
                    public nsIInputStreamCallback,
                    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);
     NS_IMETHOD Available(uint64_t *result);
     NS_IMETHOD ReadSegments(nsWriteSegmentFun fun, void *closure,
                             uint32_t count, uint32_t *result);
 
     // nsFtpControlConnectionListener methods:
@@ -263,14 +258,11 @@ private:
     // ***** control read gvars
     nsresult                mControlStatus;
     nsCString               mControlReadCarryOverBuf;
 
     nsCOMPtr<nsICacheEntryDescriptor> mCacheEntry;
     bool                    mDoomCache;
     
     nsCString mSuppliedEntityID;
-
-    nsCOMPtr<nsICancelable>  mProxyRequest;
-    bool                     mDeferredCallbackPending;
 };
 
 #endif //__nsFtpState__h_
--- a/netwerk/protocol/ftp/nsFtpProtocolHandler.cpp
+++ b/netwerk/protocol/ftp/nsFtpProtocolHandler.cpp
@@ -206,23 +206,21 @@ nsFtpProtocolHandler::NewURI(const nsACS
     if (NS_FAILED(rv)) return rv;
 
     return CallQueryInterface(url, result);
 }
 
 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);
     nsRefPtr<nsBaseChannel> channel;
     if (IsNeckoChild())
         channel = new FTPChannelChild(uri);
     else
         channel = new nsFtpChannel(uri, proxyInfo);
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -45,17 +45,16 @@ HttpBaseChannel::HttpBaseChannel()
   , mChooseApplicationCache(false)
   , mLoadedFromApplicationCache(false)
   , mChannelIsForDownload(false)
   , mTracingEnabled(true)
   , mTimingEnabled(false)
   , mAllowSpdy(true)
   , mPrivateBrowsing(false)
   , mSuspendCount(0)
-  , mProxyResolveFlags(0)
 {
   LOG(("Creating HttpBaseChannel @%x\n", this));
 
   // grab a reference to the handler to ensure that it doesn't go away.
   NS_ADDREF(gHttpHandler);
 
   // Subfields of unions cannot be targeted in an initializer list
   mSelfAddr.raw.family = PR_AF_UNSPEC;
@@ -70,33 +69,29 @@ HttpBaseChannel::~HttpBaseChannel()
   CleanRedirectCacheChainIfNecessary();
 
   gHttpHandler->Release();
 }
 
 nsresult
 HttpBaseChannel::Init(nsIURI *aURI,
                       uint8_t aCaps,
-                      nsProxyInfo *aProxyInfo,
-                      uint32_t aProxyResolveFlags,
-                      nsIURI *aProxyURI)
+                      nsProxyInfo *aProxyInfo)
 {
   LOG(("HttpBaseChannel::Init [this=%p]\n", this));
 
   NS_PRECONDITION(aURI, "null uri");
 
   nsresult rv = nsHashPropertyBag::Init();
   if (NS_FAILED(rv)) return rv;
 
   mURI = aURI;
   mOriginalURI = aURI;
   mDocumentURI = nullptr;
   mCaps = aCaps;
-  mProxyResolveFlags = aProxyResolveFlags;
-  mProxyURI = aProxyURI;
 
   // Construct connection info object
   nsAutoCString host;
   int32_t port = -1;
   bool usingSSL = false;
 
   rv = mURI->SchemeIs("https", &usingSSL);
   if (NS_FAILED(rv)) return rv;
@@ -112,34 +107,34 @@ HttpBaseChannel::Init(nsIURI *aURI,
   if (NS_FAILED(rv)) return rv;
 
   LOG(("host=%s port=%d\n", host.get(), port));
 
   rv = mURI->GetAsciiSpec(mSpec);
   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);
 
   // Set request headers
   nsAutoCString hostLine;
   rv = nsHttpHandler::GenerateHostPort(host, port, hostLine);
   if (NS_FAILED(rv)) return rv;
 
   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;
 }
 
 //-----------------------------------------------------------------------------
 // HttpBaseChannel::nsISupports
 //-----------------------------------------------------------------------------
 
@@ -1522,19 +1517,17 @@ HttpBaseChannel::SetupReplacementChannel
      this, newChannel, preserveMethod));
   uint32_t newLoadFlags = mLoadFlags | LOAD_REPLACE;
   // if the original channel was using SSL and this channel is not using
   // SSL, then no need to inhibit persistent caching.  however, if the
   // original channel was not using SSL and has INHIBIT_PERSISTENT_CACHING
   // 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
   newLoadFlags &= ~nsICachingChannel::LOAD_CHECK_OFFLINE_CACHE;
 
   newChannel->SetLoadGroup(mLoadGroup); 
   newChannel->SetNotificationCallbacks(mCallbacks);
   newChannel->SetLoadFlags(newLoadFlags);
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -55,19 +55,17 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIUPLOADCHANNEL
   NS_DECL_NSIUPLOADCHANNEL2
   NS_DECL_NSITRACEABLECHANNEL
 
   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);
   NS_IMETHOD IsPending(bool *aIsPending);
   NS_IMETHOD GetStatus(nsresult *aStatus);
   NS_IMETHOD GetLoadGroup(nsILoadGroup **aLoadGroup);
   NS_IMETHOD SetLoadGroup(nsILoadGroup *aLoadGroup);
   NS_IMETHOD GetLoadFlags(nsLoadFlags *aLoadFlags);
@@ -221,17 +219,16 @@ protected:
   nsCOMPtr<nsIProgressEventSink>    mProgressSink;
   nsCOMPtr<nsIURI>                  mReferrer;
   nsCOMPtr<nsIApplicationCache>     mApplicationCache;
 
   nsHttpRequestHead                 mRequestHead;
   nsCOMPtr<nsIInputStream>          mUploadStream;
   nsAutoPtr<nsHttpResponseHead>     mResponseHead;
   nsRefPtr<nsHttpConnectionInfo>    mConnectionInfo;
-  nsCOMPtr<nsIProxyInfo>            mProxyInfo;
 
   nsCString                         mSpec; // ASCII encoded URL spec
   nsCString                         mContentTypeHint;
   nsCString                         mContentCharsetHint;
   nsCString                         mUserSetCookieHeader;
 
   PRNetAddr                         mSelfAddr;
   PRNetAddr                         mPeerAddr;
@@ -267,19 +264,16 @@ protected:
   uint32_t                          mTimingEnabled              : 1;
   uint32_t                          mAllowSpdy                  : 1;
   uint32_t                          mPrivateBrowsing            : 1;
 
   // Current suspension depth for this channel object
   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
 // of member functions between base/derived types.
 // - We want to store member function pointer to call at resume time, but one
 //   such function--HandleAsyncAbort--we want to share between the
 //   nsHttpChannel/HttpChannelChild.  Can't define it in base class, because
 //   then we'd have to cast member function ptr between base/derived class
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -328,27 +328,31 @@ nsHttpChannel::~nsHttpChannel()
 
     if (mAuthProvider)
         mAuthProvider->Disconnect(NS_ERROR_ABORT);
 }
 
 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;
 }
 //-----------------------------------------------------------------------------
 // nsHttpChannel <private>
 //-----------------------------------------------------------------------------
 
 nsresult
 nsHttpChannel::Connect()
@@ -398,16 +402,23 @@ nsHttpChannel::Connect()
 
     // ensure that we are using a valid hostname
     if (!net_IsValidHostName(nsDependentCString(mConnectionInfo->Host())))
         return NS_ERROR_UNKNOWN_HOST;
 
     // 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"));
         return NS_ERROR_DOCUMENT_NOT_CACHED;
     }
 
     if (!gHttpHandler->UseCache())
         return ContinueConnect();
@@ -1517,16 +1528,64 @@ nsHttpChannel::ProxyFailover()
         return rv;
 
     // XXXbz so where does this codepath remove us from the loadgroup,
     // exactly?
     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()
 {
     NS_PRECONDITION(!mCallOnResume, "How did that happen?");
 
     if (mSuspendCount) {
         LOG(("Waiting until resume to do async redirect to https [this=%p]\n", this));
         mCallOnResume = &nsHttpChannel::HandleAsyncRedirectChannelToHttps;
         return;
@@ -1660,18 +1719,17 @@ nsHttpChannel::ContinueAsyncRedirectChan
 
 nsresult
 nsHttpChannel::AsyncDoReplaceWithProxy(nsIProxyInfo* pi)
 {
     LOG(("nsHttpChannel::AsyncDoReplaceWithProxy [this=%p pi=%p]", this, 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;
 
     rv = SetupReplacementChannel(mURI, newChannel, true);
     if (NS_FAILED(rv))
         return rv;
 
     // Inform consumers about this fake redirect
@@ -1732,26 +1790,21 @@ nsHttpChannel::ResolveProxy()
 
     nsresult rv;
 
     nsCOMPtr<nsIProtocolProxyService> pps =
             do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &rv);
     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;
-    }
-
-    return pps->AsyncResolve(mProxyURI ? mProxyURI : mURI, mProxyResolveFlags,
-                             this, getter_AddRefs(mProxyRequest));
+    uint32_t resolveFlags = 0;
+    if (mConnectionInfo->ProxyInfo())
+        mConnectionInfo->ProxyInfo()->GetResolveFlags(&resolveFlags);
+
+    return pps->AsyncResolve(mURI, resolveFlags, this, getter_AddRefs(mProxyRequest));
 }
 
 bool
 HttpCacheQuery::ResponseWouldVary() const
 {
     AssertOnCacheThread();
 
     nsresult rv;
@@ -4299,158 +4352,98 @@ nsHttpChannel::AsyncOpen(nsIStreamListen
     NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
 
     nsresult rv;
 
     rv = NS_CheckPortSafety(mURI);
     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.
         //
         // We keep the DNS prefetch object around so that we can retrieve
         // timing information from it. There is no guarantee that we actually
         // use the DNS prefetch data for the real connection, but as we keep
         // this data around for 3 minutes by default, this should almost always
         // be correct, and even when it isn't, the timing still represents _a_
         // valid DNS lookup timing for the site, even if it is not _the_
         // timing we used.
         mDNSPrefetch = new nsDNSPrefetch(mURI, mTimingEnabled);
         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.
     if (mRequestHead.HasHeaderValue(nsHttp::Connection, "close"))
         mCaps &= ~(NS_HTTP_ALLOW_KEEPALIVE | NS_HTTP_ALLOW_PIPELINING);
     
     if ((mLoadFlags & VALIDATE_ALWAYS) || 
         (BYPASS_LOCAL_CACHE(mLoadFlags)))
         mCaps |= NS_HTTP_REFRESH_DNS;
 
     // 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
     // not send the request to the server
     if (mCanceled)
         rv = mStatus;
     else
         rv = Connect();
     if (NS_FAILED(rv)) {
         LOG(("Calling AsyncAbort [rv=%x mCanceled=%i]\n", rv, mCanceled));
         CloseCacheEntry(true);
         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;
         }
     }
 
     return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // nsHttpChannel::nsIHttpChannelInternal
@@ -4488,43 +4481,28 @@ nsHttpChannel::SetPriority(int32_t value
 //-----------------------------------------------------------------------------
 // nsHttpChannel::nsIProtocolProxyCallback
 //-----------------------------------------------------------------------------
 
 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;
 }
 
 //-----------------------------------------------------------------------------
 // nsHttpChannel::nsIProxiedChannel
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -90,19 +90,17 @@ public:
     NS_IMETHOD GetURI(nsIURI **aURI);
     NS_IMETHOD GetNotificationCallbacks(nsIInterfaceRequestor **aCallbacks);
     NS_IMETHOD GetLoadGroup(nsILoadGroup **aLoadGroup);
     NS_IMETHOD GetRequestMethod(nsACString& aMethod);
 
     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.
     //
     // nsIRequest
     NS_IMETHOD Cancel(nsresult status);
     NS_IMETHOD Suspend();
     NS_IMETHOD Resume();
     // nsIChannel
@@ -147,17 +145,16 @@ public: /* internal necko use only */
     };
 
     OfflineCacheEntryAsForeignMarker* GetOfflineCacheEntryAsForeignMarker();
 
 private:
     typedef nsresult (nsHttpChannel::*nsContinueRedirectionFunc)(nsresult result);
 
     bool     RequestIsConditional();
-    nsresult BeginConnect();
     nsresult Connect();
     nsresult ContinueConnect();
     void     SpeculativeConnect();
     nsresult SetupTransaction();
     nsresult CallOnStartRequest();
     nsresult ProcessResponse();
     nsresult ContinueProcessResponse(nsresult);
     nsresult ProcessNormal();
@@ -184,16 +181,18 @@ private:
     nsresult ContinueHandleAsyncFallback(nsresult);
     nsresult PromptTempRedirect();
     virtual nsresult SetupReplacementChannel(nsIURI *, nsIChannel *, bool preserveMethod);
 
     // proxy specific methods
     nsresult ProxyFailover();
     nsresult AsyncDoReplaceWithProxy(nsIProxyInfo *);
     nsresult ContinueDoReplaceWithProxy(nsresult);
+    void HandleAsyncReplaceWithProxy();
+    nsresult ContinueHandleAsyncReplaceWithProxy(nsresult);
     nsresult ResolveProxy();
 
     // cache specific methods
     nsresult OpenCacheEntry(bool usingSSL);
     nsresult OnOfflineCacheEntryAvailable(nsICacheEntryDescriptor *aEntry,
                                           nsCacheAccessMode aAccess,
                                           nsresult aResult);
     nsresult OpenNormalCacheEntry(bool usingSSL);
@@ -299,16 +298,19 @@ private:
     nsCOMPtr<nsICacheEntryDescriptor> mOfflineCacheEntry;
     nsCacheAccessMode                 mOfflineCacheAccess;
     uint32_t                          mOfflineCacheLastModifiedTime;
     nsCOMPtr<nsIApplicationCache>     mApplicationCacheForWrite;
 
     // 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.
     nsCString                         mFallbackKey;
 
     friend class AutoRedirectVetoNotifier;
     friend class HttpAsyncAborter<nsHttpChannel>;
     friend class HttpCacheQuery;
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -126,19 +126,19 @@ NewURI(const nsACString &aSpec,
 
 nsHttpHandler *gHttpHandler = nullptr;
 
 nsHttpHandler::nsHttpHandler()
     : mConnMgr(nullptr)
     , 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)
     , mMaxRequestDelay(10)
     , mIdleSynTimeout(250)
     , mMaxConnections(24)
     , mMaxPersistentConnectionsPerServer(2)
     , mMaxPersistentConnectionsPerProxy(4)
@@ -162,17 +162,16 @@ nsHttpHandler::nsHttpHandler()
     , mUserAgentIsDirty(true)
     , mUseCache(true)
     , mPromptTempRedirect(true)
     , mSendSecureXSiteReferrer(true)
     , mEnablePersistentHttpsCaching(false)
     , mDoNotTrackEnabled(false)
     , mTelemetryEnabled(false)
     , mAllowExperiments(true)
-    , mHandlerActive(false)
     , mEnableSpdy(false)
     , mSpdyV2(true)
     , mSpdyV3(true)
     , mCoalesceSpdy(true)
     , mUseAlternateProtocol(false)
     , mSpdySendingChunkSize(ASpdySession::kSendingChunkSize)
     , mSpdyPingThreshold(PR_SecondsToInterval(44))
     , mSpdyPingTimeout(PR_SecondsToInterval(8))
@@ -260,17 +259,16 @@ nsHttpHandler::Init()
         }
         appInfo->GetVersion(mAppVersion);
         mAppName.StripChars(" ()<>@,;:\\\"/[]?={}");
     } else {
         mAppVersion.AssignLiteral(MOZ_APP_UA_VERSION);
     }
 
     mSessionStartTime = NowInSeconds();
-    mHandlerActive = true;
 
     rv = mAuthCache.Init();
     if (NS_FAILED(rv)) return rv;
 
     rv = InitConnectionMgr();
     if (NS_FAILED(rv)) return rv;
 
     mProductSub.AssignLiteral(MOZILLA_UAVERSION);
@@ -328,17 +326,18 @@ nsHttpHandler::InitConnectionMgr()
                         mMaxPersistentConnectionsPerProxy,
                         mMaxRequestDelay,
                         mMaxPipelinedRequests,
                         mMaxOptimisticPipelinedRequests);
     return rv;
 }
 
 nsresult
-nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request)
+nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request,
+                                         uint8_t caps)
 {
     nsresult rv;
 
     // Add the "User-Agent" header
     rv = request->SetHeader(nsHttp::User_Agent, UserAgent());
     if (NS_FAILED(rv)) return rv;
 
     // MIME based content negotiation lives!
@@ -352,43 +351,36 @@ nsHttpHandler::AddStandardRequestHeaders
         rv = request->SetHeader(nsHttp::Accept_Language, mAcceptLanguages);
         if (NS_FAILED(rv)) return rv;
     }
 
     // Add the "Accept-Encoding" header
     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
     // alternative proxy-connection is worse. see 570283
 
     NS_NAMED_LITERAL_CSTRING(close, "close");
     NS_NAMED_LITERAL_CSTRING(keepAlive, "keep-alive");
 
     const nsACString *connectionType = &close;
     if (caps & NS_HTTP_ALLOW_KEEPALIVE) {
         connectionType = &keepAlive;
     }
 
+    // Add the "Do-Not-Track" header
+    if (mDoNotTrackEnabled) {
+      rv = request->SetHeader(nsHttp::DoNotTrack,
+                              NS_LITERAL_CSTRING("1"));
+      if (NS_FAILED(rv)) return rv;
+    }
+
     return request->SetHeader(nsHttp::Connection, *connectionType);
 }
 
 bool
 nsHttpHandler::IsAcceptableEncoding(const char *enc)
 {
     if (!enc)
         return false;
@@ -946,18 +938,22 @@ nsHttpHandler::PrefsChanged(nsIPrefBranc
     if (PREF_CHANGED(HTTP_PREF("pipelining.ssl"))) {
         rv = prefs->GetBoolPref(HTTP_PREF("pipelining.ssl"), &cVar);
         if (NS_SUCCEEDED(rv))
             mPipeliningOverSSL = cVar;
     }
 
     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"))) {
         rv = prefs->GetIntPref(HTTP_PREF("qos"), &val);
         if (NS_SUCCEEDED(rv))
             mQoSBits = (uint8_t) clamped(val, 0, 0xff);
     }
 
@@ -1374,17 +1370,17 @@ nsHttpHandler::NewChannel(nsIURI *uri, n
         rv = uri->SchemeIs("https", &isHttps);
         if (NS_FAILED(rv)) return rv;
         if (!isHttps) {
             NS_WARNING("Invalid URI scheme");
             return NS_ERROR_UNEXPECTED;
         }
     }
 
-    return NewProxiedChannel(uri, nullptr, 0, nullptr, result);
+    return NewProxiedChannel(uri, nullptr, result);
 }
 
 NS_IMETHODIMP
 nsHttpHandler::AllowPort(int32_t port, const char *scheme, bool *_retval)
 {
     // don't override anything.
     *_retval = false;
     return NS_OK;
@@ -1392,18 +1388,16 @@ nsHttpHandler::AllowPort(int32_t port, c
 
 //-----------------------------------------------------------------------------
 // nsHttpHandler::nsIProxiedProtocolHandler
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsHttpHandler::NewProxiedChannel(nsIURI *uri,
                                  nsIProxyInfo* givenProxyInfo,
-                                 uint32_t proxyResolveFlags,
-                                 nsIURI *proxyURI,
                                  nsIChannel **result)
 {
     nsRefPtr<HttpBaseChannel> httpChannel;
 
     LOG(("nsHttpHandler::NewProxiedChannel [proxyInfo=%p]\n",
         givenProxyInfo));
 
     nsCOMPtr<nsProxyInfo> proxyInfo;
@@ -1418,30 +1412,36 @@ nsHttpHandler::NewProxiedChannel(nsIURI 
         return rv;
 
     if (IsNeckoChild()) {
         httpChannel = new HttpChannelChild();
     } else {
         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
         if (mPipeliningOverSSL)
             caps |= NS_HTTP_ALLOW_PIPELINING;
 
         if (!IsNeckoChild()) {
             // HACK: make sure PSM gets initialized on the main thread.
             net_EnsurePSMInit();
         }
     }
 
-    rv = httpChannel->Init(uri, caps, proxyInfo, proxyResolveFlags, proxyURI);
+    rv = httpChannel->Init(uri, caps, proxyInfo);
     if (NS_FAILED(rv))
         return rv;
 
     httpChannel.forget(result);
     return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
@@ -1504,18 +1504,16 @@ nsHttpHandler::Observe(nsISupports *subj
     if (strcmp(topic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
         nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(subject);
         if (prefBranch)
             PrefsChanged(prefBranch, NS_ConvertUTF16toUTF8(data).get());
     }
     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();
 
         // ensure connection manager is shutdown
         if (mConnMgr)
             mConnMgr->Shutdown();
 
         // need to reset the session start time since cache validation may
--- a/netwerk/protocol/http/nsHttpHandler.h
+++ b/netwerk/protocol/http/nsHttpHandler.h
@@ -53,19 +53,18 @@ public:
     NS_DECL_NSIHTTPPROTOCOLHANDLER
     NS_DECL_NSIOBSERVER
     NS_DECL_NSISPECULATIVECONNECT
 
     nsHttpHandler();
     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();
 
     nsHttpVersion  HttpVersion()             { return mHttpVersion; }
     nsHttpVersion  ProxyHttpVersion()        { return mProxyHttpVersion; }
     uint8_t        ReferrerLevel()           { return mReferrerLevel; }
     bool           SendSecureXSiteReferrer() { return mSendSecureXSiteReferrer; }
@@ -74,17 +73,16 @@ public:
     PRIntervalTime SpdyTimeout()             { return mSpdyTimeout; }
     uint16_t       MaxRequestAttempts()      { return mMaxRequestAttempts; }
     const char    *DefaultSocketType()       { return mDefaultSocketType.get(); /* ok to return null */ }
     nsIIDNService *IDNConverter()            { return mIDNConverter; }
     uint32_t       PhishyUserPassLength()    { return mPhishyUserPassLength; }
     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; }
 
     bool           IsPersistentHttpsCachingEnabled() { return mEnablePersistentHttpsCaching; }
     bool           IsTelemetryEnabled() { return mTelemetryEnabled; }
     bool           AllowExperiments() { return mTelemetryEnabled && mAllowExperiments; }
 
     bool           IsSpdyEnabled() { return mEnableSpdy; }
@@ -230,19 +228,16 @@ public:
     {
         return mPipelineRescheduleTimeout;
     }
     
     PRIntervalTime GetPipelineTimeout()   { return mPipelineReadTimeout; }
 
     mozilla::net::SpdyInformation *SpdyInfo() { return &mSpdyInfo; }
 
-    // returns true in between Init and Shutdown states
-    bool Active() { return mHandlerActive; }
-
 private:
 
     //
     // Useragent/prefs helper methods
     //
     void     BuildUserAgent();
     void     InitUserAgentComponents();
     void     PrefsChanged(nsIPrefBranch *prefs, const char *pref);
@@ -273,20 +268,21 @@ private:
 
     //
     // prefs
     //
 
     uint8_t  mHttpVersion;
     uint8_t  mProxyHttpVersion;
     uint8_t  mCapabilities;
+    uint8_t  mProxyCapabilities;
     uint8_t  mReferrerLevel;
 
     bool mFastFallbackToIPv4;
-    bool mProxyPipelining;
+
     PRIntervalTime mIdleTimeout;
     PRIntervalTime mSpdyTimeout;
 
     uint16_t mMaxRequestAttempts;
     uint16_t mMaxRequestDelay;
     uint16_t mIdleSynTimeout;
 
     uint16_t mMaxConnections;
@@ -355,19 +351,16 @@ private:
     bool           mDoNotTrackEnabled;
     
     // Whether telemetry is reported or not
     bool           mTelemetryEnabled;
 
     // 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;
     bool           mSpdyV2;
     bool           mSpdyV3;
     bool           mCoalesceSpdy;
     bool           mUseAlternateProtocol;
     uint32_t       mSpdySendingChunkSize;
--- a/netwerk/test/unit/test_protocolproxyservice.js
+++ b/netwerk/test/unit/test_protocolproxyservice.js
@@ -1,32 +1,20 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 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/. */
 
 // 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
  * proxying.
  */
 function TestProtocolHandler() {
 }
 TestProtocolHandler.prototype = {
@@ -150,220 +138,140 @@ resolveCallback.prototype = {
     this.nextFunction(pi);
   }
 };
 
 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);
 
-function run_filter_test2() {
+  // 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;
 
 function run_filter_test3() {
   var uri = ios.newURI("http://www.mozilla.org/", null, null);
 
   // Push a filter and verify the results asynchronously
 
   filter_3_1 = new TestFilter("http", "foo", 8080, 0, 10);
   pps.registerFilter(filter_3_1, 20);
 
   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", "");
   prefs.setIntPref("network.proxy.http_port", 0);
 
   // try SOCKS configuration
   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() {
 }
 TestResolveCallback.prototype = {
   QueryInterface:
   function TestResolveCallback_QueryInterface(iid) {
     if (iid.equals(Components.interfaces.nsIProtocolProxyCallback) ||
@@ -379,33 +287,66 @@ TestResolveCallback.prototype = {
     do_check_neq(req, null);
     do_check_neq(uri, null);
     do_check_eq(status, 0);
     do_check_neq(pi, null);
 
     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();
   }
 };
 
 function run_pac_test() {
   var pac = 'data:text/plain,' +
             'function FindProxyForURL(url, host) {' +
             '  return "PROXY foopy:8080; DIRECT";' +
             '}';
   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() {
 }
 TestResolveCancelationCallback.prototype = {
   QueryInterface:
   function TestResolveCallback_QueryInterface(iid) {
     if (iid.equals(Components.interfaces.nsIProtocolProxyCallback) ||
@@ -418,226 +359,130 @@ TestResolveCancelationCallback.prototype
   function TestResolveCancelationCallback_onProxyAvailable(req, uri, pi, status) {
     dump("*** uri=" + uri.spec + ", status=" + status + "\n");
 
     do_check_neq(req, null);
     do_check_neq(uri, null);
     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();
   }
 };
 
 function run_pac_cancel_test() {
   var uri = ios.newURI("http://www.mozilla.org/", null, null);
 
   // Configure PAC
   var pac = 'data:text/plain,' +
             '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);
-}
-
-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);
+  do_test_pending();
 }
 
-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);
   prefs.setCharPref("network.proxy.http", "foopy");
   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();
+  run_filter_test();
+  run_filter_test2();
+  run_pref_test();
+  run_pac_test();
+  // additional tests may be added to run_test_continued
+}
 
-  // start of asynchronous test chain
-  run_filter_test();
-  do_test_pending();
+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();
+}
--- a/netwerk/test/unit/test_proxy-failover_canceled.js
+++ b/netwerk/test/unit/test_proxy-failover_canceled.js
@@ -28,21 +28,34 @@ function finish_test(request, buffer)
 }
 
 function run_test()
 {
   httpServer = new HttpServer();
   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();
+  var on_modify_request_count = 0;
 
-  var nc = new ChannelEventSink();
-  nc._flags = ES_ABORT_REDIRECT;
+  modifyrequestobserver = {observe: function() {
+    // We get 2 on-modify-request notifications:
+    // 1. when proxy service resolves the proxy settings from PAC function
+    // 2. when we try to fail over the first proxy (moving to the second one)
+    //
+    // In the second case we want to cancel the proxy engage, so, do not allow
+    // redirects from now.
+
+    if (++on_modify_request_count == 2)
+      nc._flags = ES_ABORT_REDIRECT;
+  }}
+
+  var os = Cc["@mozilla.org/observer-service;1"].
+           getService(Ci.nsIObserverService);
+  os.addObserver(modifyrequestobserver, "http-on-modify-request", false);
 
   var prefserv = Cc["@mozilla.org/preferences-service;1"].
                  getService(Ci.nsIPrefService);
   var prefs = prefserv.getBranch("network.proxy.");
   prefs.setIntPref("type", 2);
   prefs.setCharPref("autoconfig_url", "data:text/plain," +
     "function FindProxyForURL(url, host) {return 'PROXY a_non_existent_domain_x7x6c572v:80; PROXY localhost:4444';}"
   );
--- a/netwerk/test/unit/test_proxy-replace_canceled.js
+++ b/netwerk/test/unit/test_proxy-replace_canceled.js
@@ -36,21 +36,13 @@ function run_test()
   var prefserv = Cc["@mozilla.org/preferences-service;1"].
                  getService(Ci.nsIPrefService);
   var prefs = prefserv.getBranch("network.proxy.");
   prefs.setIntPref("type", 2);
   prefs.setCharPref("autoconfig_url", "data:text/plain," +
     "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();
 }
--- a/toolkit/components/passwordmgr/test/test_bug_627616.html
+++ b/toolkit/components/passwordmgr/test/test_bug_627616.html
@@ -10,43 +10,23 @@
 <script class="testbody" type="text/javascript">
     SimpleTest.waitForExplicitFinish();
 
     var Cc = SpecialPowers.wrap(Components).classes;
 
     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);
         login.init(mozproxy, null, "proxy_realm", "proxy_user", "proxy_pass", "", "");
         pwmgr.addLogin(login);
 
         login2 = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
         login2.init("http://mochi.test:8888", null, "mochirealm", "user1name", "user1pass", "", "");
@@ -111,17 +91,17 @@
         cleanup();
         SimpleTest.finish();
       }
     }
 
     var pendingTests = [{expectedDialogs: 2, test: testNonAnonymousCredentials},
                         {expectedDialogs: 1, test: testAnonymousCredentials},
                         {expectedDialogs: 0, test: testAnonymousNoAuth}];
-    init1();
+    init();
     runNextTest();
 
     function handleDialog(doc, testNum)
     {
         var dialog = doc.getElementById("commonDialog");
         dialog.acceptDialog();
         gExpectedDialogs--;
         startCallbackTimer();
--- a/toolkit/components/passwordmgr/test/test_prompt.html
+++ b/toolkit/components/passwordmgr/test/test_prompt.html
@@ -18,26 +18,29 @@ Login Manager test: username/password pr
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 /** Test for Login Manager: 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);
 
   login1  = Cc["@mozilla.org/login-manager/loginInfo;1"].
             createInstance(Ci.nsILoginInfo);
   login2A = Cc["@mozilla.org/login-manager/loginInfo;1"].
             createInstance(Ci.nsILoginInfo);
@@ -116,45 +119,16 @@ ok(true, "removing login 4...");
 ok(true, "removing proxyLogin...");
   pwmgr.removeLogin(proxyLogin);
   } catch (e) { ok(false, "finishTest FAILED: " + e); }
 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);
 }
 
 var storageObserver = {
   notificationCallbacks: [],
 
@@ -590,19 +564,18 @@ dumpNotifications();
 
     default:
         ok(false, "Uhh, unhandled switch for testNum #" + testNum);
         break;
   }
 
 }
 
-startup();
+initLogins();
 
-function doTests() {
 var authinfo = {
     username : "",
     password : "",
     domain   : "",
 
     flags : Ci.nsIAuthInformation.AUTH_HOST,
     authenticationScheme : "basic",
     realm : ""
@@ -646,17 +619,17 @@ var result = { value : null };
 var isOk;
 
 // popupNotifications (not *popup*) is a constant, per-tab container. So, we
 // only need to fetch it once.
 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);
 
 ok(isOk, "Checking dialog return value (accept)");
 ok(didDialog, "handleDialog was invoked");
 is(result.value, "xyz", "Checking prompt() returned value");
 
@@ -1158,13 +1131,12 @@ authMgr.clearAll();
 
 // ===== test 1000 =====
 testNum = 1000;
 startCallbackTimer();
 iframe.src = "authenticate.sjs?user=mochiuser1&pass=mochipass1";
 
 // ...remaining tests are driven by handleLoad()...
 SimpleTest.waitForExplicitFinish();
-}
 </script>
 </pre>
 </body>
 </html>
--- a/toolkit/components/passwordmgr/test/test_prompt_async.html
+++ b/toolkit/components/passwordmgr/test/test_prompt_async.html
@@ -64,33 +64,42 @@
                 this.windowsRegistered = 0;
             }
         }
 
         var monitor = new dialogMonitor();
 
         var pwmgr, logins = [];
 
-        function initLogins(pi) {
+        function initLogins() {
             pwmgr = SpecialPowers.wrap(Components)
                                  .classes["@mozilla.org/login-manager;1"]
                                  .getService(Ci.nsILoginManager);
 
             function addLogin(host, realm, user, pass) {
                 var login = SpecialPowers.wrap(Components)
                                          .classes["@mozilla.org/login-manager/loginInfo;1"]
                                          .createInstance(Ci.nsILoginInfo);
                 login.init(host, null, realm, user, pass, "", "");
                 pwmgr.addLogin(login);
                 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");
             addLogin(mozproxy, "proxy_realm2",
                      "proxy_user2", "proxy_pass2");
             addLogin(mozproxy, "proxy_realm3",
                      "proxy_user3", "proxy_pass3");
             addLogin(mozproxy, "proxy_realm4",
@@ -120,59 +129,32 @@
                                        .classes['@mozilla.org/network/http-auth-manager;1']
                                        .getService(Ci.nsIHttpAuthManager);
             authMgr.clearAll();
 
             monitor.shutdown();
             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;
         var iframe1;
         var iframe2a;
         var iframe2b;
         window.onload = function () {
             iframe1 = document.getElementById("iframe1");
             iframe2a = document.getElementById("iframe2a");
             iframe2b = document.getElementById("iframe2b");
             iframe1.onload = onFrameLoad;
             iframe2a.onload = onFrameLoad;
             iframe2b.onload = onFrameLoad;
 
-	    startup();
+            initLogins();
+            doTest(testNum);
         }
 
         var expectedLoads;
         var expectedDialogs;
         function onFrameLoad()
         {
             if (--expectedLoads == 0) {
                 // All pages expected to load has loaded, continue with the next test
--- a/toolkit/system/osxproxy/nsOSXSystemProxySettings.mm
+++ b/toolkit/system/osxproxy/nsOSXSystemProxySettings.mm
@@ -29,17 +29,17 @@ public:
   void ProxyHasChanged();
 
   // is there a PAC url specified in the system configuration
   bool IsAutoconfigEnabled() const;
   // retrieve the pac url
   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;
 
 private:
   ~nsOSXSystemProxySettings();
 
   SCDynamicStoreContext mContext;
@@ -53,24 +53,17 @@ private:
     CFStringRef mEnabled;
     CFStringRef mHost;
     CFStringRef mPort;
     bool mIsSocksProxy;
   };
   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[] = {
   {"http", kSCPropNetProxiesHTTPEnable, kSCPropNetProxiesHTTPProxy, kSCPropNetProxiesHTTPPort, false},
   {"https", kSCPropNetProxiesHTTPSEnable, kSCPropNetProxiesHTTPSProxy, kSCPropNetProxiesHTTPSPort, false},
   {"ftp", kSCPropNetProxiesFTPEnable, kSCPropNetProxiesFTPProxy, kSCPropNetProxiesFTPPort, false},
   {"socks", kSCPropNetProxiesSOCKSEnable, kSCPropNetProxiesSOCKSProxy, kSCPropNetProxiesSOCKSPort, true},
   {NULL, NULL, NULL, NULL, false},
@@ -158,26 +151,26 @@ nsOSXSystemProxySettings::ProxyHasChange
 
   [mProxyDict release];
   mProxyDict = (NSDictionary*)SCDynamicStoreCopyProxies(mSystemDynamicStore);
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 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;
 
   NS_ENSURE_TRUE(mProxyDict != NULL, NS_ERROR_FAILURE);
 
   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
     NSNumber* enabled = [mProxyDict objectForKey:(NSString*)keys->mEnabled];
     NS_ENSURE_TRUE(enabled == NULL || [enabled isKindOfClass:[NSNumber class]], NS_ERROR_FAILURE);
     if ([enabled intValue] == 0)
       continue;
     
@@ -305,30 +298,30 @@ nsOSXSystemProxySettings::GetPACURI(nsAC
   }
 
   return NS_ERROR_FAILURE;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
 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));
   } else {      
     aResult.Assign(NS_LITERAL_CSTRING("PROXY ") + proxyHost + nsPrintfCString(":%d", proxyPort));
   }
 
   return NS_OK;
--- a/toolkit/system/unixproxy/nsLibProxySettings.cpp
+++ b/toolkit/system/unixproxy/nsLibProxySettings.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 "nsISystemProxySettings.h"
 #include "mozilla/ModuleUtils.h"
 #include "nsIServiceManager.h"
+#include "nsIIOService.h"
 #include "nsIURI.h"
 #include "nsString.h"
 #include "nsNetUtil.h"
 #include "nsCOMPtr.h"
 #include "nspr.h"
 
 extern "C" {
 #include <proxy.h>
@@ -28,93 +29,99 @@ private:
   ~nsUnixSystemProxySettings() {
     if (mProxyFactory) 
       px_proxy_factory_free(mProxyFactory); 
   }
 
   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()
 {
   return NS_OK;
 }
 
 nsresult
 nsUnixSystemProxySettings::GetPACURI(nsACString& aResult)
 {
   // Make sure we return an empty result.
   aResult.Truncate();
   return NS_OK;
 }
 
 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;
 
   if (!mProxyFactory) {
     mProxyFactory = px_proxy_factory_new();
   }
   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
   // libproxy returns an array of proxies in the format:
   // <procotol>://[username:password@]proxy:port
   // or
   // 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;
 }
 
 #define NS_UNIXSYSTEMPROXYSERVICE_CID  /* 0fa3158c-d5a7-43de-9181-a285e74cf1d4 */\
      { 0x0fa3158c, 0xd5a7, 0x43de, \
        {0x91, 0x81, 0xa2, 0x85, 0xe7, 0x4c, 0xf1, 0xd4 } }
 
--- a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
+++ b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
@@ -13,17 +13,16 @@
 #include "prnetdb.h"
 #include "prenv.h"
 #include "nsPrintfCString.h"
 #include "nsNetUtil.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIGSettingsService.h"
 #include "nsInterfaceHashtable.h"
 #include "mozilla/Attributes.h"
-#include "nsIURI.h"
 
 class nsUnixSystemProxySettings MOZ_FINAL : public nsISystemProxySettings {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSISYSTEMPROXYSETTINGS
 
   nsUnixSystemProxySettings() {}
   nsresult Init();
@@ -39,24 +38,16 @@ private:
   nsresult SetProxyResultFromGConf(const char* aKeyBase, const char* aType, nsACString& aResult);
   nsresult GetProxyFromGConf(const nsACString& aScheme, const nsACString& aHost, int32_t aPort, nsACString& aResult);
   nsresult GetProxyFromGSettings(const nsACString& aScheme, const nsACString& aHost, int32_t aPort, nsACString& aResult);
   nsresult SetProxyResultFromGSettings(const char* aKeyBase, const char* aType, nsACString& aResult);
 };
 
 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()
 {
   mSchemeProxySettings.Init(5);
   mGConf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
   mGSettings = do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
   if (mGSettings) {
     mGSettings->GetCollectionForSchema(NS_LITERAL_CSTRING("org.gnome.system.proxy"),
@@ -155,20 +146,18 @@ IsInNoProxyList(const nsACString& aHost,
 }
 
 static void SetProxyResult(const char* aType, const nsACString& aHost,
                            int32_t aPort, nsACString& aResult)
 {
   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
 GetProxyFromEnvironment(const nsACString& aScheme,
                         const nsACString& aHost,
                         int32_t aPort,
                         nsACString& aResult)
 {
@@ -487,31 +476,39 @@ nsUnixSystemProxySettings::GetProxyFromG
   if (NS_FAILED(rv)) {
     aResult.AppendLiteral("DIRECT");
   }
   
   return NS_OK;
 }
 
 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 */\
      { 0x0fa3158c, 0xd5a7, 0x43de, \
        {0x91, 0x81, 0xa2, 0x85, 0xe7, 0x4c, 0xf1, 0xd4 } }
 
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsUnixSystemProxySettings, Init)
 NS_DEFINE_NAMED_CID(NS_UNIXSYSTEMPROXYSERVICE_CID);
--- a/toolkit/system/windowsproxy/nsWindowsSystemProxySettings.cpp
+++ b/toolkit/system/windowsproxy/nsWindowsSystemProxySettings.cpp
@@ -27,38 +27,51 @@ public:
 
 private:
     ~nsWindowsSystemProxySettings() {};
 
     bool MatchOverride(const nsACString& aHost);
     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()
 {
     return NS_OK;
 }
 
+static void SetProxyResult(const char* aType, const nsACString& aHost,
+                           int32_t aPort, nsACString& aResult)
+{
+    aResult.AssignASCII(aType);
+    aResult.Append(' ');
+    aResult.Append(aHost);
+    aResult.Append(':');
+    aResult.Append(nsPrintfCString("%d", aPort));
+}
+
 static void SetProxyResult(const char* aType, const nsACString& aHostPort,
                            nsACString& aResult)
 {
-    aResult.AssignASCII(aType);
-    aResult.Append(' ');
-    aResult.Append(aHostPort);
+    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)
 {
     // For whatever reason, a proxy is not to be used.
     aResult.AssignASCII("DIRECT");
 }
 
@@ -204,41 +217,45 @@ nsWindowsSystemProxySettings::GetPACURI(
     }
 
     if (NS_SUCCEEDED(rv))
         aResult = NS_ConvertUTF16toUTF8(buf);
     return rv;
 }
 
 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;
     nsAutoString buf;
 
     rv = ReadInternetOption(INTERNET_PER_CONN_PROXY_SERVER, flags, buf);
     if (NS_FAILED(rv) || !(flags & PROXY_TYPE_PROXY)) {
         SetProxyResultDirect(aResult);
         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;
     }
 
     NS_ConvertUTF16toUTF8 cbuf(buf);
 
     nsAutoCString prefix;
-    ToLowerCase(aScheme, prefix);
+    ToLowerCase(scheme, prefix);
 
     prefix.Append('=');
 
     nsAutoCString specificProxy;
     nsAutoCString defaultProxy;
     nsAutoCString socksProxy;
     int32_t start = 0;
     int32_t end = cbuf.Length();