Bug 472529, websockets (netwerk patch), r=smaug+biesi
authorwfernandom2004@gmail.com
Thu, 17 Jun 2010 21:33:42 +0300
changeset 43832 64a60466f0d4a16a2a2e9bf826514f8bd2d8a8c3
parent 43831 fb11e27cda712fbe63d0028a15a471533502303a
child 43833 bcd52abd2495fb9b9a0dc2008d130e2fcd6f5ccb
push idunknown
push userunknown
push dateunknown
reviewerssmaug
bugs472529
milestone1.9.3a6pre
Bug 472529, websockets (netwerk patch), r=smaug+biesi
extensions/auth/nsHttpNegotiateAuth.cpp
netwerk/base/public/nsIProtocolProxyService.idl
netwerk/base/src/nsProtocolProxyService.cpp
netwerk/base/src/nsProtocolProxyService.h
netwerk/build/nsNetCID.h
netwerk/build/nsNetModule.cpp
netwerk/dns/nsDNSService2.cpp
netwerk/protocol/http/Makefile.in
netwerk/protocol/http/nsHttpBasicAuth.cpp
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/protocol/http/nsHttpChannel.h
netwerk/protocol/http/nsHttpChannelAuthProvider.cpp
netwerk/protocol/http/nsHttpChannelAuthProvider.h
netwerk/protocol/http/nsHttpDigestAuth.cpp
netwerk/protocol/http/nsHttpDigestAuth.h
netwerk/protocol/http/nsHttpNTLMAuth.cpp
netwerk/protocol/http/nsIHttpAuthenticableChannel.idl
netwerk/protocol/http/nsIHttpAuthenticator.idl
netwerk/protocol/http/nsIHttpChannelAuthProvider.idl
--- a/extensions/auth/nsHttpNegotiateAuth.cpp
+++ b/extensions/auth/nsHttpNegotiateAuth.cpp
@@ -49,17 +49,17 @@
 //
 
 #include <string.h>
 #include <stdlib.h>
 
 #include "nsAuth.h"
 #include "nsHttpNegotiateAuth.h"
 
-#include "nsIHttpChannel.h"
+#include "nsIHttpAuthenticableChannel.h"
 #include "nsIProxiedChannel.h"
 #include "nsIAuthModule.h"
 #include "nsIServiceManager.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsIProxyInfo.h"
 #include "nsIURI.h"
 #include "nsCOMPtr.h"
@@ -102,51 +102,47 @@ nsHttpNegotiateAuth::GetAuthFlags(PRUint
 //
 // Always set *identityInvalid == FALSE here.  This 
 // will prevent the browser from popping up the authentication
 // prompt window.  Because GSSAPI does not have an API
 // for fetching initial credentials (ex: A Kerberos TGT),
 // there is no correct way to get the users credentials.
 // 
 NS_IMETHODIMP
-nsHttpNegotiateAuth::ChallengeReceived(nsIHttpChannel *httpChannel,
+nsHttpNegotiateAuth::ChallengeReceived(nsIHttpAuthenticableChannel *authChannel,
                                        const char *challenge,
                                        PRBool isProxyAuth,
                                        nsISupports **sessionState,
                                        nsISupports **continuationState,
                                        PRBool *identityInvalid)
 {
     nsIAuthModule *module = (nsIAuthModule *) *continuationState;
 
     *identityInvalid = PR_FALSE;
     if (module)
         return NS_OK;
 
     nsresult rv;
 
     nsCOMPtr<nsIURI> uri;
-    rv = httpChannel->GetURI(getter_AddRefs(uri));
+    rv = authChannel->GetURI(getter_AddRefs(uri));
     if (NS_FAILED(rv))
         return rv;
 
     PRUint32 req_flags = nsIAuthModule::REQ_DEFAULT;
     nsCAutoString service;
 
     if (isProxyAuth) {
         if (!TestBoolPref(kNegotiateAuthAllowProxies)) {
             LOG(("nsHttpNegotiateAuth::ChallengeReceived proxy auth blocked\n"));
             return NS_ERROR_ABORT;
         }
 
-        nsCOMPtr<nsIProxiedChannel> proxied =
-                do_QueryInterface(httpChannel);
-        NS_ENSURE_STATE(proxied);
-
         nsCOMPtr<nsIProxyInfo> proxyInfo;
-        proxied->GetProxyInfo(getter_AddRefs(proxyInfo));
+        authChannel->GetProxyInfo(getter_AddRefs(proxyInfo));
         NS_ENSURE_STATE(proxyInfo);
 
         proxyInfo->GetHost(service);
     }
     else {
         PRBool allowed = TestPref(uri, kNegotiateAuthTrustedURIs);
         if (!allowed) {
             LOG(("nsHttpNegotiateAuth::ChallengeReceived URI blocked\n"));
@@ -208,17 +204,17 @@ NS_IMPL_ISUPPORTS1(nsHttpNegotiateAuth, 
    
 //
 // GenerateCredentials
 //
 // This routine is responsible for creating the correct authentication
 // blob to pass to the server that requested "Negotiate" authentication.
 //
 NS_IMETHODIMP
-nsHttpNegotiateAuth::GenerateCredentials(nsIHttpChannel *httpChannel,
+nsHttpNegotiateAuth::GenerateCredentials(nsIHttpAuthenticableChannel *authChannel,
                                          const char *challenge,
                                          PRBool isProxyAuth,
                                          const PRUnichar *domain,
                                          const PRUnichar *username,
                                          const PRUnichar *password,
                                          nsISupports **sessionState,
                                          nsISupports **continuationState,
                                          PRUint32 *flags,
--- a/netwerk/base/public/nsIProtocolProxyService.idl
+++ b/netwerk/base/public/nsIProtocolProxyService.idl
@@ -47,17 +47,17 @@ interface nsIChannel;
 interface nsIURI;
 
 /**
  * nsIProtocolProxyService provides methods to access information about
  * various network proxies.
  *
  * @status UNDER_REVIEW
  */
-[scriptable, uuid(e38ab577-786e-4a7f-936b-7ae4c7d877b2)]
+[scriptable, uuid(d7ec6237-162e-40f5-a2b4-46ccd5fa83c9)]
 interface nsIProtocolProxyService : nsISupports
 {
     /**
      * 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.
@@ -67,16 +67,49 @@ interface nsIProtocolProxyService : nsIS
      *
      * 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;
+
+    /**
+     * When the proxy configuration is manual this flag may be passed to the
+     * resolve and asyncResolve methods to request to not analyze the uri's
+     * scheme specific proxy. When this flag is set the main HTTP proxy is the
+     * preferred one.
+     *
+     * NOTE: if RESOLVE_PREFER_SOCKS_PROXY is set then the SOCKS proxy is
+     *       the preferred one.
+     *
+     * NOTE: if RESOLVE_PREFER_HTTPS_PROXY is set then the HTTPS proxy
+     *       is the preferred one.
+     */
+    const unsigned long RESOLVE_IGNORE_URI_SCHEME = 1 << 2;
+
+    /**
+     * When the proxy configuration is manual this flag may be passed to the
+     * resolve and asyncResolve methods to request to prefer the HTTPS proxy
+     * to the others HTTP ones.
+     *
+     * NOTE: RESOLVE_PREFER_SOCKS_PROXY takes precedence over this flag.
+     *
+     * NOTE: This flag implies RESOLVE_IGNORE_URI_SCHEME.
+     */
+    const unsigned long RESOLVE_PREFER_HTTPS_PROXY =
+        (1 << 3) | RESOLVE_IGNORE_URI_SCHEME;
+
+    /**
      * 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
@@ -223,9 +256,24 @@ interface nsIProtocolProxyService : nsIS
     /**
      * This method may be used to unregister a proxy filter instance.  All
      * filters will be automatically unregistered at XPCOM shutdown.
      *
      * @param aFilter
      *        The nsIProtocolProxyFilter instance to be unregistered.
      */
     void unregisterFilter(in nsIProtocolProxyFilter aFilter);
+
+     /**
+      * These values correspond to the possible integer values for the
+      * network.proxy.type preference.
+      */ 
+     const unsigned long PROXYCONFIG_DIRECT   = 0;
+     const unsigned long PROXYCONFIG_MANUAL   = 1;
+     const unsigned long PROXYCONFIG_PAC      = 2;
+     const unsigned long PROXYCONFIG_WPAD     = 4;
+     const unsigned long PROXYCONFIG_SYSTEM   = 5;
+
+     /**
+      * This attribute specifies the current type of proxy configuration.
+      */
+     readonly attribute unsigned long proxyConfigType;
 };
--- a/netwerk/base/src/nsProtocolProxyService.cpp
+++ b/netwerk/base/src/nsProtocolProxyService.cpp
@@ -281,29 +281,32 @@ proxy_GetBoolPref(nsIPrefBranch *aPrefBr
     if (NS_FAILED(rv)) 
         aResult = PR_FALSE;
     else
         aResult = temp;
 }
 
 //----------------------------------------------------------------------------
 
+static const PRInt32 PROXYCONFIG_DIRECT4X = 3;
+static const PRInt32 PROXYCONFIG_COUNT = 6;
+
 NS_IMPL_ADDREF(nsProtocolProxyService)
 NS_IMPL_RELEASE(nsProtocolProxyService)
 NS_IMPL_QUERY_INTERFACE3_CI(nsProtocolProxyService,
                             nsIProtocolProxyService,
                             nsIProtocolProxyService2,
                             nsIObserver)
 NS_IMPL_CI_INTERFACE_GETTER2(nsProtocolProxyService,
                              nsIProtocolProxyService,
                              nsIProtocolProxyService2)
 
 nsProtocolProxyService::nsProtocolProxyService()
     : mFilters(nsnull)
-    , mProxyConfig(eProxyConfig_Direct)
+    , mProxyConfig(PROXYCONFIG_DIRECT)
     , mHTTPProxyPort(-1)
     , mFTPProxyPort(-1)
     , mHTTPSProxyPort(-1)
     , mSOCKSProxyPort(-1)
     , mSOCKSProxyVersion(4)
     , mSOCKSProxyRemoteDNS(PR_FALSE)
     , mPACMan(nsnull)
     , mSessionStart(PR_Now())
@@ -381,36 +384,36 @@ nsProtocolProxyService::PrefsChanged(nsI
     PRBool reloadPAC = PR_FALSE;
     nsXPIDLCString tempString;
 
     if (!pref || !strcmp(pref, PROXY_PREF("type"))) {
         PRInt32 type = -1;
         rv = prefBranch->GetIntPref(PROXY_PREF("type"), &type);
         if (NS_SUCCEEDED(rv)) {
             // bug 115720 - for ns4.x backwards compatability
-            if (type == eProxyConfig_Direct4x) {
-                type = eProxyConfig_Direct;
+            if (type == PROXYCONFIG_DIRECT4X) {
+                type = PROXYCONFIG_DIRECT;
                 // Reset the type so that the dialog looks correct, and we
                 // don't have to handle this case everywhere else
                 // I'm paranoid about a loop of some sort - only do this
                 // if we're enumerating all prefs, and ignore any error
                 if (!pref)
                     prefBranch->SetIntPref(PROXY_PREF("type"), type);
-            } else if (type >= eProxyConfig_Last) {
+            } else if (type >= PROXYCONFIG_COUNT) {
                 LOG(("unknown proxy type: %lu; assuming direct\n", type));
-                type = eProxyConfig_Direct;
+                type = PROXYCONFIG_DIRECT;
             }
-            mProxyConfig = static_cast<ProxyConfig>(type);
+            mProxyConfig = type;
             reloadPAC = PR_TRUE;
         }
 
-        if (mProxyConfig == eProxyConfig_System) {
+        if (mProxyConfig == PROXYCONFIG_SYSTEM) {
             mSystemProxySettings = do_GetService(NS_SYSTEMPROXYSETTINGS_CONTRACTID);
             if (!mSystemProxySettings)
-                mProxyConfig = eProxyConfig_Direct;
+                mProxyConfig = PROXYCONFIG_DIRECT;
         } else {
             mSystemProxySettings = nsnull;
         }
     }
 
     if (!pref || !strcmp(pref, PROXY_PREF("http")))
         proxy_GetStringPref(prefBranch, PROXY_PREF("http"), mHTTPProxyHost);
 
@@ -457,33 +460,33 @@ nsProtocolProxyService::PrefsChanged(nsI
         rv = prefBranch->GetCharPref(PROXY_PREF("no_proxies_on"),
                                      getter_Copies(tempString));
         if (NS_SUCCEEDED(rv))
             LoadHostFilters(tempString.get());
     }
 
     // We're done if not using something that could give us a PAC URL
     // (PAC, WPAD or System)
-    if (mProxyConfig != eProxyConfig_PAC && mProxyConfig != eProxyConfig_WPAD &&
-        mProxyConfig != eProxyConfig_System)
+    if (mProxyConfig != PROXYCONFIG_PAC && mProxyConfig != PROXYCONFIG_WPAD &&
+        mProxyConfig != PROXYCONFIG_SYSTEM)
         return;
 
     // OK, we need to reload the PAC file if:
     //  1) network.proxy.type changed, or
     //  2) network.proxy.autoconfig_url changed and PAC is configured
 
     if (!pref || !strcmp(pref, PROXY_PREF("autoconfig_url")))
         reloadPAC = PR_TRUE;
 
     if (reloadPAC) {
         tempString.Truncate();
-        if (mProxyConfig == eProxyConfig_PAC) {
+        if (mProxyConfig == PROXYCONFIG_PAC) {
             prefBranch->GetCharPref(PROXY_PREF("autoconfig_url"),
                                     getter_Copies(tempString));
-        } else if (mProxyConfig == eProxyConfig_WPAD) {
+        } else if (mProxyConfig == PROXYCONFIG_WPAD) {
             // We diverge from the WPAD spec here in that we don't walk the
             // hosts's FQDN, stripping components until we hit a TLD.  Doing so
             // is dangerous in the face of an incomplete list of TLDs, and TLDs
             // get added over time.  We could consider doing only a single
             // substitution of the first component, if that proves to help
             // compatibility.
             tempString.AssignLiteral(WPAD_URL);
         } else if (mSystemProxySettings) {
@@ -809,19 +812,19 @@ nsProtocolProxyService::ReloadPAC()
         return NS_OK;
 
     PRInt32 type;
     nsresult rv = prefs->GetIntPref(PROXY_PREF("type"), &type);
     if (NS_FAILED(rv))
         return NS_OK;
 
     nsXPIDLCString pacSpec;
-    if (type == eProxyConfig_PAC)
+    if (type == PROXYCONFIG_PAC)
         prefs->GetCharPref(PROXY_PREF("autoconfig_url"), getter_Copies(pacSpec));
-    else if (type == eProxyConfig_WPAD)
+    else if (type == PROXYCONFIG_WPAD)
         pacSpec.AssignLiteral(WPAD_URL);
 
     if (!pacSpec.IsEmpty())
         ConfigureFromPAC(pacSpec, PR_TRUE);
     return NS_OK;
 }
 
 // nsIProtocolProxyService
@@ -830,17 +833,17 @@ nsProtocolProxyService::Resolve(nsIURI *
                                 nsIProxyInfo **result)
 {
     nsProtocolInfo info;
     nsresult rv = GetProtocolInfo(uri, &info);
     if (NS_FAILED(rv))
         return rv;
 
     PRBool usePAC;
-    rv = Resolve_Internal(uri, info, &usePAC, result);
+    rv = Resolve_Internal(uri, info, flags, &usePAC, result);
     if (NS_FAILED(rv))
         return rv;
 
     if (usePAC && mPACMan) {
         NS_ASSERTION(*result == nsnull, "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)
@@ -879,17 +882,17 @@ nsProtocolProxyService::AsyncResolve(nsI
 
     nsProtocolInfo info;
     nsresult rv = GetProtocolInfo(uri, &info);
     if (NS_FAILED(rv))
         return rv;
 
     PRBool usePAC;
     nsCOMPtr<nsIProxyInfo> pi;
-    rv = Resolve_Internal(uri, info, &usePAC, getter_AddRefs(pi));
+    rv = Resolve_Internal(uri, info, flags, &usePAC, getter_AddRefs(pi));
     if (NS_FAILED(rv))
         return rv;
 
     if (!usePAC || !mPACMan) {
         ApplyFilters(uri, info, pi);
 
         ctx->SetResult(NS_OK, pi);
         return ctx->DispatchCallback();
@@ -941,18 +944,18 @@ nsProtocolProxyService::NewProxyInfo(con
 NS_IMETHODIMP
 nsProtocolProxyService::GetFailoverForProxy(nsIProxyInfo  *aProxy,
                                             nsIURI        *aURI,
                                             nsresult       aStatus,
                                             nsIProxyInfo **aResult)
 {
     // We only support failover when a PAC file is configured, either
     // directly or via system settings
-    if (mProxyConfig != eProxyConfig_PAC && mProxyConfig != eProxyConfig_WPAD &&
-        mProxyConfig != eProxyConfig_System)
+    if (mProxyConfig != PROXYCONFIG_PAC && mProxyConfig != PROXYCONFIG_WPAD &&
+        mProxyConfig != PROXYCONFIG_SYSTEM)
         return NS_ERROR_NOT_AVAILABLE;
 
     // Verify that |aProxy| is one of our nsProxyInfo objects.
     nsCOMPtr<nsProxyInfo> pi = do_QueryInterface(aProxy);
     NS_ENSURE_ARG(pi);
     // OK, the QI checked out.  We can proceed.
 
     // Remember that this proxy is down.
@@ -1028,16 +1031,24 @@ nsProtocolProxyService::UnregisterFilter
             return NS_OK;
         }
         last = iter;
     }
 
     // No need to throw an exception in this case.
     return NS_OK;
 }
+
+NS_IMETHODIMP
+nsProtocolProxyService::GetProxyConfigType(PRUint32* aProxyConfigType)
+{
+  *aProxyConfigType = mProxyConfig;
+  return NS_OK;
+}
+
 void
 nsProtocolProxyService::LoadHostFilters(const char *filters)
 {
     // check to see the owners flag? /!?/ TODO
     if (mHostFiltersArray.Length() > 0) {
         mHostFiltersArray.Clear();
     }
 
@@ -1215,16 +1226,17 @@ nsProtocolProxyService::NewProxyInfo_Int
 
     NS_ADDREF(*aResult = proxyInfo);
     return NS_OK;
 }
 
 nsresult
 nsProtocolProxyService::Resolve_Internal(nsIURI *uri,
                                          const nsProtocolInfo &info,
+                                         PRUint32 flags,
                                          PRBool *usePAC,
                                          nsIProxyInfo **result)
 {
     NS_ENSURE_ARG_POINTER(uri);
 
     *usePAC = PR_FALSE;
     *result = nsnull;
 
@@ -1249,49 +1261,69 @@ nsProtocolProxyService::Resolve_Internal
         // hasn't changed, ConfigureFromPAC will exit early.
         nsresult rv = ConfigureFromPAC(PACURI, PR_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 == eProxyConfig_Direct ||
-        (mProxyConfig == eProxyConfig_Manual &&
+    if (mProxyConfig == PROXYCONFIG_DIRECT ||
+        (mProxyConfig == PROXYCONFIG_MANUAL &&
          !CanUseProxy(uri, info.defaultPort)))
         return NS_OK;
 
     // Proxy auto config magic...
-    if (mProxyConfig == eProxyConfig_PAC || mProxyConfig == eProxyConfig_WPAD ||
-        mProxyConfig == eProxyConfig_System) {
+    if (mProxyConfig == PROXYCONFIG_PAC || mProxyConfig == PROXYCONFIG_WPAD ||
+        mProxyConfig == PROXYCONFIG_SYSTEM) {
         // Do not query PAC now.
         *usePAC = PR_TRUE;
         return NS_OK;
     }
 
     // proxy info values
     const char *type = nsnull;
     const nsACString *host = nsnull;
     PRInt32 port = -1;
 
     PRUint32 proxyFlags = 0;
 
-    if (!mHTTPProxyHost.IsEmpty() && mHTTPProxyPort > 0 &&
-        info.scheme.EqualsLiteral("http")) {
+    if ((flags & RESOLVE_PREFER_SOCKS_PROXY) &&
+        !mSOCKSProxyHost.IsEmpty() && mSOCKSProxyPort > 0) {
+      host = &mSOCKSProxyHost;
+      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) &&
+             !mHTTPSProxyHost.IsEmpty() && mHTTPSProxyPort > 0) {
+        host = &mHTTPSProxyHost;
+        type = kProxyType_HTTP;
+        port = mHTTPSProxyPort;
+    }
+    else if (!mHTTPProxyHost.IsEmpty() && mHTTPProxyPort > 0 &&
+             ((flags & RESOLVE_IGNORE_URI_SCHEME) ||
+              info.scheme.EqualsLiteral("http"))) {
         host = &mHTTPProxyHost;
         type = kProxyType_HTTP;
         port = mHTTPProxyPort;
     }
     else if (!mHTTPSProxyHost.IsEmpty() && mHTTPSProxyPort > 0 &&
+             !(flags & RESOLVE_IGNORE_URI_SCHEME) &&
              info.scheme.EqualsLiteral("https")) {
         host = &mHTTPSProxyHost;
         type = kProxyType_HTTP;
         port = mHTTPSProxyPort;
     }
     else if (!mFTPProxyHost.IsEmpty() && mFTPProxyPort > 0 &&
+             !(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) 
--- a/netwerk/base/src/nsProtocolProxyService.h
+++ b/netwerk/base/src/nsProtocolProxyService.h
@@ -215,24 +215,27 @@ protected:
      * It performs all of the built-in processing, and reports back to the
      * caller with either the proxy info result or a flag to instruct the
      * caller to use PAC instead.
      *
      * @param uri
      *        The URI to test.
      * @param info
      *        Information about the URI's protocol.
+     * @param flags
+     *        The flags passed to either the resolve or the asyncResolve method.
      * @param usePAC
      *        If this flag is set upon return, then PAC should be queried to
      *        resolve the proxy info.
      * @param result
      *        The resulting proxy info or null.
      */
     NS_HIDDEN_(nsresult) Resolve_Internal(nsIURI *uri,
                                           const nsProtocolInfo &info,
+                                          PRUint32 flags,
                                           PRBool *usePAC, 
                                           nsIProxyInfo **result);
 
     /**
      * This method applies the registered filters to the given proxy info
      * list, and returns a possibly modified list.
      *
      * @param uri
@@ -301,27 +304,16 @@ public:
         PRIPv6Addr addr; // possibly IPv4-mapped address
     };
 
     struct HostInfoName {
         char    *host;
         PRUint32 host_len;
     };
 
-    // These values correspond to the integer network.proxy.type preference
-    enum ProxyConfig {
-        eProxyConfig_Direct,
-        eProxyConfig_Manual,
-        eProxyConfig_PAC,
-        eProxyConfig_Direct4x,
-        eProxyConfig_WPAD,
-        eProxyConfig_System, // use system proxy settings if available, otherwise DIRECT
-        eProxyConfig_Last
-    };
-
 protected:
 
     // simplified array of filters defined by this struct
     struct HostInfo {
         PRBool  is_ipaddr;
         PRInt32 port;
         union {
             HostInfoIP   ip;
@@ -352,17 +344,17 @@ protected:
 
     // Holds an array of HostInfo objects
     nsTArray<nsAutoPtr<HostInfo> > mHostFiltersArray;
 
     // Points to the start of a sorted by position, singly linked list
     // of FilterLink objects.
     FilterLink                  *mFilters;
 
-    ProxyConfig                  mProxyConfig;
+    PRUint32                     mProxyConfig;
 
     nsCString                    mHTTPProxyHost;
     PRInt32                      mHTTPProxyPort;
 
     nsCString                    mFTPProxyHost;
     PRInt32                      mFTPProxyPort;
 
     nsCString                    mHTTPSProxyHost;
--- a/netwerk/build/nsNetCID.h
+++ b/netwerk/build/nsNetCID.h
@@ -551,16 +551,28 @@
 #define NS_HTTPAUTHMANAGER_CID \
 { /* 36b63ef3-e0fa-4c49-9fd4-e065e85568f4 */         \
     0x36b63ef3,                                      \
     0xe0fa,                                          \
     0x4c49,                                          \
     {0x9f, 0xd4, 0xe0, 0x65, 0xe8, 0x55, 0x68, 0xf4} \
 }
 
+#define NS_HTTPCHANNELAUTHPROVIDER_CLASSNAME \
+    "nsHttpChannelAuthProvider"
+#define NS_HTTPCHANNELAUTHPROVIDER_CONTRACTID \
+    "@mozilla.org/network/http-channel-auth-provider;1"
+#define NS_HTTPCHANNELAUTHPROVIDER_CID \
+{ /* 02f5a8d8-4ef3-48b1-b527-8a643056abbd */         \
+    0x02f5a8d8,                                      \
+    0x4ef3,                                          \
+    0x48b1,                                          \
+    {0xb5, 0x27, 0x8a, 0x64, 0x30, 0x56, 0xab, 0xbd} \
+}
+
 #define NS_HTTPACTIVITYDISTRIBUTOR_CLASSNAME \
     "nsHttpActivityDistributor"
 #define NS_HTTPACTIVITYDISTRIBUTOR_CONTRACTID \
     "@mozilla.org/network/http-activity-distributor;1"
 #define NS_HTTPACTIVITYDISTRIBUTOR_CID \
 { /* 15629ada-a41c-4a09-961f-6553cd60b1a2 */         \
     0x15629ada,                                      \
     0xa41c,                                          \
--- a/netwerk/build/nsNetModule.cpp
+++ b/netwerk/build/nsNetModule.cpp
@@ -223,26 +223,28 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsFt
 #endif
 
 #ifdef NECKO_PROTOCOL_http
 // http/https
 #include "nsHttpHandler.h"
 #undef LOG
 #undef LOG_ENABLED
 #include "nsHttpAuthManager.h"
+#include "nsHttpChannelAuthProvider.h"
 #include "nsHttpBasicAuth.h"
 #include "nsHttpDigestAuth.h"
 #include "nsHttpNTLMAuth.h"
 #include "nsHttpActivityDistributor.h"
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsHttpNTLMAuth)
 #undef LOG
 #undef LOG_ENABLED
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsHttpHandler, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsHttpsHandler, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsHttpAuthManager, Init)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsHttpChannelAuthProvider)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsHttpActivityDistributor, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsHttpBasicAuth)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsHttpDigestAuth)
 #endif // !NECKO_PROTOCOL_http
 
 #ifdef NECKO_PROTOCOL_res
 // resource
 #include "nsResProtocolHandler.h"
@@ -971,16 +973,21 @@ static const nsModuleComponentInfo gNetM
       NS_HTTP_AUTHENTICATOR_CONTRACTID_PREFIX "ntlm",
       nsHttpNTLMAuthConstructor },
 
     { NS_HTTPAUTHMANAGER_CLASSNAME,
       NS_HTTPAUTHMANAGER_CID,
       NS_HTTPAUTHMANAGER_CONTRACTID,
       nsHttpAuthManagerConstructor },
 
+   { NS_HTTPCHANNELAUTHPROVIDER_CLASSNAME,
+     NS_HTTPCHANNELAUTHPROVIDER_CID,
+     NS_HTTPCHANNELAUTHPROVIDER_CONTRACTID,
+     nsHttpChannelAuthProviderConstructor },
+
    { NS_HTTPACTIVITYDISTRIBUTOR_CLASSNAME,
      NS_HTTPACTIVITYDISTRIBUTOR_CID,
      NS_HTTPACTIVITYDISTRIBUTOR_CONTRACTID,
      nsHttpActivityDistributorConstructor },
 #endif // !NECKO_PROTOCOL_http
       
 #ifdef NECKO_PROTOCOL_ftp
     // from netwerk/protocol/ftp:
--- a/netwerk/dns/nsDNSService2.cpp
+++ b/netwerk/dns/nsDNSService2.cpp
@@ -46,17 +46,17 @@
 #include "nsIServiceManager.h"
 #include "nsReadableUtils.h"
 #include "nsString.h"
 #include "nsAutoLock.h"
 #include "nsAutoPtr.h"
 #include "nsNetCID.h"
 #include "nsNetError.h"
 #include "nsDNSPrefetch.h"
-#include "nsProtocolProxyService.h"
+#include "nsIProtocolProxyService.h"
 #include "prsystem.h"
 #include "prnetdb.h"
 #include "prmon.h"
 #include "prio.h"
 #include "plstr.h"
 
 #include "mozilla/FunctionTimer.h"
 
@@ -328,17 +328,17 @@ nsDNSService::Init()
     PRBool firstTime = (mLock == nsnull);
 
     // prefs
     PRUint32 maxCacheEntries  = 400;
     PRUint32 maxCacheLifetime = 3; // minutes
     PRBool   enableIDN        = PR_TRUE;
     PRBool   disableIPv6      = PR_FALSE;
     PRBool   disablePrefetch  = PR_FALSE;
-    int      proxyType        = nsProtocolProxyService::eProxyConfig_Direct;
+    int      proxyType        = nsIProtocolProxyService::PROXYCONFIG_DIRECT;
     
     nsAdoptingCString ipv4OnlyDomains;
 
     // read prefs
     nsCOMPtr<nsIPrefBranch2> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
     if (prefs) {
         PRInt32 val;
         if (NS_SUCCEEDED(prefs->GetIntPref(kPrefDnsCacheEntries, &val)))
@@ -390,17 +390,17 @@ nsDNSService::Init()
         // now, set all of our member variables while holding the lock
         nsAutoLock lock(mLock);
         mResolver = res;
         mIDN = idn;
         mIPv4OnlyDomains = ipv4OnlyDomains; // exchanges buffer ownership
         mDisableIPv6 = disableIPv6;
 
         // Disable prefetching either by explicit preference or if a manual proxy is configured 
-        mDisablePrefetch = disablePrefetch || (proxyType == nsProtocolProxyService::eProxyConfig_Manual);
+        mDisablePrefetch = disablePrefetch || (proxyType == nsIProtocolProxyService::PROXYCONFIG_MANUAL);
     }
     
     nsDNSPrefetch::Initialize(this);
     return rv;
 }
 
 NS_IMETHODIMP
 nsDNSService::Shutdown()
--- a/netwerk/protocol/http/Makefile.in
+++ b/netwerk/protocol/http/Makefile.in
@@ -58,16 +58,18 @@ SDK_XPIDLSRCS = \
 
 XPIDLSRCS = \
   nsIHttpActivityObserver.idl \
   nsIHttpAuthManager.idl \
   nsIHttpAuthenticator.idl \
   nsIHttpChannelInternal.idl \
   nsIHttpEventSink.idl \
   nsIHttpProtocolHandler.idl \
+  nsIHttpChannelAuthProvider.idl \
+  nsIHttpAuthenticableChannel.idl \
   $(NULL)
 
 CPPSRCS = \
   nsHttp.cpp \
   nsHttpHeaderArray.cpp \
   nsHttpConnectionInfo.cpp \
   nsHttpConnection.cpp \
   nsHttpConnectionMgr.cpp \
@@ -79,16 +81,17 @@ CPPSRCS = \
   nsHttpBasicAuth.cpp \
   nsHttpDigestAuth.cpp \
   nsHttpNTLMAuth.cpp \
   nsHttpTransaction.cpp \
   nsHttpHandler.cpp \
   nsHttpChannel.cpp \
   nsHttpPipeline.cpp \
   nsHttpActivityDistributor.cpp \
+  nsHttpChannelAuthProvider.cpp \
   $(NULL)
 
 LOCAL_INCLUDES = \
   -I$(srcdir)/../../base/src \
   -I$(topsrcdir)/xpcom/ds \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/netwerk/protocol/http/nsHttpBasicAuth.cpp
+++ b/netwerk/protocol/http/nsHttpBasicAuth.cpp
@@ -65,31 +65,31 @@ nsHttpBasicAuth::~nsHttpBasicAuth()
 
 NS_IMPL_ISUPPORTS1(nsHttpBasicAuth, nsIHttpAuthenticator)
 
 //-----------------------------------------------------------------------------
 // nsHttpBasicAuth::nsIHttpAuthenticator
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
-nsHttpBasicAuth::ChallengeReceived(nsIHttpChannel *httpChannel,
+nsHttpBasicAuth::ChallengeReceived(nsIHttpAuthenticableChannel *authChannel,
                                    const char *challenge,
                                    PRBool isProxyAuth,
                                    nsISupports **sessionState,
                                    nsISupports **continuationState,
                                    PRBool *identityInvalid)
 {
     // if challenged, then the username:password that was sent must
     // have been wrong.
     *identityInvalid = PR_TRUE;
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHttpBasicAuth::GenerateCredentials(nsIHttpChannel *httpChannel,
+nsHttpBasicAuth::GenerateCredentials(nsIHttpAuthenticableChannel *authChannel,
                                      const char *challenge,
                                      PRBool isProxyAuth,
                                      const PRUnichar *domain,
                                      const PRUnichar *user,
                                      const PRUnichar *password,
                                      nsISupports **sessionState,
                                      nsISupports **continuationState,
                                      PRUint32 *aFlags,
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -45,22 +45,19 @@
 
 #include "nsHttpChannel.h"
 #include "nsHttpTransaction.h"
 #include "nsHttpConnection.h"
 #include "nsHttpHandler.h"
 #include "nsHttpAuthCache.h"
 #include "nsHttpResponseHead.h"
 #include "nsHttp.h"
-#include "nsIHttpAuthenticator.h"
 #include "nsIApplicationCacheService.h"
 #include "nsIApplicationCacheContainer.h"
 #include "nsIAuthInformation.h"
-#include "nsIAuthPrompt2.h"
-#include "nsIAuthPromptProvider.h"
 #include "nsIStringBundle.h"
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIURL.h"
 #include "nsIIDNService.h"
 #include "nsIStreamListenerTee.h"
 #include "nsISeekableStream.h"
 #include "nsMimeTypes.h"
@@ -75,17 +72,16 @@
 #include "nsEscape.h"
 #include "nsICookieService.h"
 #include "nsIResumableChannel.h"
 #include "nsInt64.h"
 #include "nsIVariant.h"
 #include "nsChannelProperties.h"
 #include "nsStreamUtils.h"
 #include "nsIOService.h"
-#include "nsAuthInformationHolder.h"
 #include "nsICacheService.h"
 #include "nsDNSPrefetch.h"
 #include "nsChannelClassifier.h"
 
 // True if the local cache should be bypassed when processing a request.
 #define BYPASS_LOCAL_CACHE(loadFlags) \
         (loadFlags & (nsIRequest::LOAD_BYPASS_CACHE | \
                       nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE))
@@ -104,37 +100,31 @@ nsHttpChannel::nsHttpChannel()
     , mStatus(NS_OK)
     , mLogicalOffset(0)
     , mCaps(0)
     , mPriority(PRIORITY_NORMAL)
     , mCachedResponseHead(nsnull)
     , mCacheAccess(0)
     , mPostID(0)
     , mRequestTime(0)
-    , mProxyAuthContinuationState(nsnull)
-    , mAuthContinuationState(nsnull)
     , mStartPos(LL_MAXUINT)
     , mPendingAsyncCallOnResume(nsnull)
     , mSuspendCount(0)
     , mRedirectionLimit(gHttpHandler->RedirectionLimit())
     , mIsPending(PR_FALSE)
     , mWasOpened(PR_FALSE)
     , mApplyConversion(PR_TRUE)
     , mAllowPipelining(PR_TRUE)
     , mCachedContentIsValid(PR_FALSE)
     , mCachedContentIsPartial(PR_FALSE)
     , mResponseHeadersModified(PR_FALSE)
     , mCanceled(PR_FALSE)
     , mTransactionReplaced(PR_FALSE)
     , mUploadStreamHasHeaders(PR_FALSE)
     , mAuthRetryPending(PR_FALSE)
-    , mProxyAuth(PR_FALSE)
-    , mTriedProxyAuth(PR_FALSE)
-    , mTriedHostAuth(PR_FALSE)
-    , mSuppressDefensiveAuth(PR_FALSE)
     , mResuming(PR_FALSE)
     , mInitedCacheEntry(PR_FALSE)
     , mCacheForOfflineUse(PR_FALSE)
     , mCachingOpportunistically(PR_FALSE)
     , mFallbackChannel(PR_FALSE)
     , mInheritApplicationCache(PR_TRUE)
     , mChooseApplicationCache(PR_FALSE)
     , mLoadedFromApplicationCache(PR_FALSE)
@@ -148,22 +138,24 @@ nsHttpChannel::nsHttpChannel()
     nsHttpHandler *handler = gHttpHandler;
     NS_ADDREF(handler);
 }
 
 nsHttpChannel::~nsHttpChannel()
 {
     LOG(("Destroying nsHttpChannel [this=%p]\n", this));
 
+    if (mAuthProvider) {
+        mAuthProvider->Disconnect(NS_ERROR_ABORT);
+        mAuthProvider = nsnull;
+    }
+    
     NS_IF_RELEASE(mConnectionInfo);
     NS_IF_RELEASE(mTransaction);
 
-    NS_IF_RELEASE(mProxyAuthContinuationState);
-    NS_IF_RELEASE(mAuthContinuationState);
-
     delete mResponseHead;
     delete mCachedResponseHead;
 
     // release our reference to the handler
     nsHttpHandler *handler = gHttpHandler;
     NS_RELEASE(handler);
 }
 
@@ -231,17 +223,26 @@ nsHttpChannel::Init(nsIURI *uri,
 
     rv = mRequestHead.SetHeader(nsHttp::Host, hostLine);
     if (NS_FAILED(rv)) return rv;
 
     rv = gHttpHandler->
         AddStandardRequestHeaders(&mRequestHead.Headers(), caps,
                                   !mConnectionInfo->UsingSSL() &&
                                   mConnectionInfo->UsingHttpProxy());
-
+    if (NS_FAILED(rv)) return rv;
+
+    mAuthProvider =
+        do_CreateInstance("@mozilla.org/network/http-channel-auth-provider;1",
+                          &rv);
+    if (NS_FAILED(rv)) return rv;
+
+    rv = mAuthProvider->Init(this);
+    if (NS_FAILED(rv)) return rv;
+    
     return rv;
 }
 
 //-----------------------------------------------------------------------------
 // nsHttpChannel <private>
 //-----------------------------------------------------------------------------
 
 nsresult
@@ -343,17 +344,17 @@ nsHttpChannel::Connect(PRBool firstTime)
             // validated before we can reuse it.  since we are not allowed
             // to hit the net, there's nothing more to do.  the document
             // is effectively not in the cache.
             return NS_ERROR_DOCUMENT_NOT_CACHED;
         }
     }
 
     // check to see if authorization headers should be included
-    AddAuthorizationHeaders();
+    mAuthProvider->AddAuthorizationHeaders();
 
     if (mLoadFlags & LOAD_NO_NETWORK_IO) {
         return NS_ERROR_DOCUMENT_NOT_CACHED;
     }
 
     // hit the net...
     rv = SetupTransaction();
     if (NS_FAILED(rv)) return rv;
@@ -963,26 +964,26 @@ nsHttpChannel::ProcessResponse()
     gHttpHandler->OnExamineResponse(this);
 
     // set cookies, if any exist; done after OnExamineResponse to allow those
     // observers to modify the cookie response headers
     SetCookie(mResponseHead->PeekHeader(nsHttp::Set_Cookie));
 
     // handle unused username and password in url (see bug 232567)
     if (httpStatus != 401 && httpStatus != 407) {
-        CheckForSuperfluousAuth();
+        if (!mAuthRetryPending)
+            mAuthProvider->CheckForSuperfluousAuth();
         if (mCanceled)
             return CallOnStartRequest();
 
-        if (mAuthContinuationState) {
-            // reset the current continuation state because our last
-            // authentication attempt has been completed successfully
-            NS_RELEASE(mAuthContinuationState);
-            LOG(("  continuation state has been reset"));
-        }
+        // reset the authentication's current continuation state because our
+        // last authentication attempt has been completed successfully
+        mAuthProvider->Disconnect(NS_ERROR_ABORT);
+        mAuthProvider = nsnull;
+        LOG(("  continuation state has been reset"));
     }
 
     // handle different server response categories.  Note that we handle
     // caching or not caching of error pages in
     // nsHttpResponseHead::MustValidate; if you change this switch, update that
     // one
     switch (httpStatus) {
     case 200:
@@ -1039,24 +1040,41 @@ nsHttpChannel::ProcessResponse()
         rv = ProcessNotModified();
         if (NS_FAILED(rv)) {
             LOG(("ProcessNotModified failed [rv=%x]\n", rv));
             rv = ProcessNormal();
         }
         break;
     case 401:
     case 407:
-        rv = ProcessAuthentication(httpStatus);
-        if (NS_FAILED(rv)) {
+        rv = mAuthProvider->ProcessAuthentication(
+            httpStatus, mConnectionInfo->UsingSSL() &&
+                        mTransaction->SSLConnectFailed());
+        if (rv == NS_ERROR_IN_PROGRESS)  {
+            // authentication prompt has been invoked and result
+            // is expected asynchronously
+            mAuthRetryPending = PR_TRUE;
+            // suspend the transaction pump to stop receiving the
+            // unauthenticated content data. We will throw that data
+            // away when user provides credentials or resume the pump
+            // when user refuses to authenticate.
+            LOG(("Suspending the transaction, asynchronously prompting for credentials"));
+            mTransactionPump->Suspend();
+            rv = NS_OK;
+        }
+        else if (NS_FAILED(rv)) {
             LOG(("ProcessAuthentication failed [rv=%x]\n", rv));
             if (mTransaction->SSLConnectFailed())
                 return ProcessFailedSSLConnect(httpStatus);
-            CheckForSuperfluousAuth();
+            if (!mAuthRetryPending)
+                mAuthProvider->CheckForSuperfluousAuth();
             rv = ProcessNormal();
         }
+        else
+            mAuthRetryPending = PR_TRUE; // see DoAuthRetry
         break;
     default:
         rv = ProcessNormal();
         MaybeInvalidateCacheEntryForSubsequentGet();
         break;
     }
 
     return rv;
@@ -3025,1102 +3043,52 @@ nsHttpChannel::ProcessRedirection(PRUint
     mProgressSink = nsnull;
     return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // nsHttpChannel <auth>
 //-----------------------------------------------------------------------------
 
-// buf contains "domain\user"
-static void
-ParseUserDomain(PRUnichar *buf,
-                const PRUnichar **user,
-                const PRUnichar **domain)
-{
-    PRUnichar *p = buf;
-    while (*p && *p != '\\') ++p;
-    if (!*p)
-        return;
-    *p = '\0';
-    *domain = buf;
-    *user = p + 1;
-}
-
-// helper function for setting identity from raw user:pass
-static void
-SetIdent(nsHttpAuthIdentity &ident,
-         PRUint32 authFlags,
-         PRUnichar *userBuf,
-         PRUnichar *passBuf)
-{
-    const PRUnichar *user = userBuf;
-    const PRUnichar *domain = nsnull;
-
-    if (authFlags & nsIHttpAuthenticator::IDENTITY_INCLUDES_DOMAIN)
-        ParseUserDomain(userBuf, &user, &domain);
-
-    ident.Set(domain, user, passBuf);
-}
-
-// helper function for getting an auth prompt from an interface requestor
-static void
-GetAuthPrompt(nsIInterfaceRequestor *ifreq, PRBool proxyAuth,
-              nsIAuthPrompt2 **result)
-{
-    if (!ifreq)
-        return;
-
-    PRUint32 promptReason;
-    if (proxyAuth)
-        promptReason = nsIAuthPromptProvider::PROMPT_PROXY;
-    else 
-        promptReason = nsIAuthPromptProvider::PROMPT_NORMAL;
-
-    nsCOMPtr<nsIAuthPromptProvider> promptProvider = do_GetInterface(ifreq);
-    if (promptProvider)
-        promptProvider->GetAuthPrompt(promptReason,
-                                      NS_GET_IID(nsIAuthPrompt2),
-                                      reinterpret_cast<void**>(result));
-    else
-        NS_QueryAuthPrompt2(ifreq, result);
-}
-
-// generate credentials for the given challenge, and update the auth cache.
-nsresult
-nsHttpChannel::GenCredsAndSetEntry(nsIHttpAuthenticator *auth,
-                                   PRBool proxyAuth,
-                                   const char *scheme,
-                                   const char *host,
-                                   PRInt32 port,
-                                   const char *directory,
-                                   const char *realm,
-                                   const char *challenge,
-                                   const nsHttpAuthIdentity &ident,
-                                   nsCOMPtr<nsISupports> &sessionState,
-                                   char **result)
-{
-    nsresult rv;
-    PRUint32 authFlags;
-
-    rv = auth->GetAuthFlags(&authFlags);
-    if (NS_FAILED(rv)) return rv;
-
-    nsISupports *ss = sessionState;
-
-    // set informations that depend on whether
-    // we're authenticating against a proxy
-    // or a webserver
-    nsISupports **continuationState;
-
-    if (proxyAuth) {
-        continuationState = &mProxyAuthContinuationState;
-    } else {
-        continuationState = &mAuthContinuationState;
-    }
-
-    PRUint32 generateFlags;
-    rv = auth->GenerateCredentials(this,
-                                   challenge,
-                                   proxyAuth,
-                                   ident.Domain(),
-                                   ident.User(),
-                                   ident.Password(),
-                                   &ss,
-                                   &*continuationState,
-                                   &generateFlags,
-                                   result);
-
-    sessionState.swap(ss);
-    if (NS_FAILED(rv)) return rv;
-
-    // don't log this in release build since it could contain sensitive info.
-#ifdef DEBUG 
-    LOG(("generated creds: %s\n", *result));
-#endif
-
-    // find out if this authenticator allows reuse of credentials and/or
-    // challenge.
-    PRBool saveCreds =
-        0 != (authFlags & nsIHttpAuthenticator::REUSABLE_CREDENTIALS);
-    PRBool saveChallenge =
-        0 != (authFlags & nsIHttpAuthenticator::REUSABLE_CHALLENGE);
-
-    PRBool saveIdentity =
-        0 == (generateFlags & nsIHttpAuthenticator::USING_INTERNAL_IDENTITY);
-
-    // this getter never fails
-    nsHttpAuthCache *authCache = gHttpHandler->AuthCache();
-
-    // create a cache entry.  we do this even though we don't yet know that
-    // these credentials are valid b/c we need to avoid prompting the user
-    // more than once in case the credentials are valid.
-    //
-    // if the credentials are not reusable, then we don't bother sticking
-    // them in the auth cache.
-    rv = authCache->SetAuthEntry(scheme, host, port, directory, realm,
-                                 saveCreds ? *result : nsnull,
-                                 saveChallenge ? challenge : nsnull,
-                                 saveIdentity ? &ident : nsnull,
-                                 sessionState);
-    return rv;
-}
-
-nsresult
-nsHttpChannel::ProcessAuthentication(PRUint32 httpStatus)
+NS_IMETHODIMP nsHttpChannel::OnAuthAvailable()
 {
-    LOG(("nsHttpChannel::ProcessAuthentication [this=%p code=%u]\n",
-        this, httpStatus));
-
-    if (mLoadFlags & LOAD_ANONYMOUS) {
-      return NS_ERROR_NOT_AVAILABLE;
-    }
-
-    const char *challenges;
-    mProxyAuth = (httpStatus == 407);
-
-    nsresult rv = PrepareForAuthentication(mProxyAuth);
-    if (NS_FAILED(rv))
-        return rv;
-
-    if (mProxyAuth) {
-        // only allow a proxy challenge if we have a proxy server configured.
-        // otherwise, we could inadvertantly expose the user's proxy
-        // credentials to an origin server.  We could attempt to proceed as
-        // if we had received a 401 from the server, but why risk flirting
-        // with trouble?  IE similarly rejects 407s when a proxy server is
-        // not configured, so there's no reason not to do the same.
-        if (!mConnectionInfo->UsingHttpProxy()) {
-            LOG(("rejecting 407 when proxy server not configured!\n"));
-            return NS_ERROR_UNEXPECTED;
-        }
-        if (mConnectionInfo->UsingSSL() && !mTransaction->SSLConnectFailed()) {
-            // we need to verify that this challenge came from the proxy
-            // server itself, and not some server on the other side of the
-            // SSL tunnel.
-            LOG(("rejecting 407 from origin server!\n"));
-            return NS_ERROR_UNEXPECTED;
-        }
-        challenges = mResponseHead->PeekHeader(nsHttp::Proxy_Authenticate);
-    }
-    else
-        challenges = mResponseHead->PeekHeader(nsHttp::WWW_Authenticate);
-    NS_ENSURE_TRUE(challenges, NS_ERROR_UNEXPECTED);
-
-    nsCAutoString creds;
-    rv = GetCredentials(challenges, mProxyAuth, creds);
-    if (rv == NS_ERROR_IN_PROGRESS)  {
-        // authentication prompt has been invoked and result
-        // is expected asynchronously
-        mAuthRetryPending = PR_TRUE;
-        // suspend the transaction pump to stop receiving the
-        // unauthenticated content data. We will throw that data
-        // away when user provides credentials or resume the pump
-        // when user refuses to authenticate.
-        LOG(("Suspending the transaction, asynchronously prompting for credentials"));
-        mTransactionPump->Suspend();
-        return NS_OK;
-    }
-    else if (NS_FAILED(rv))
-        LOG(("unable to authenticate\n"));
-    else {
-        // set the authentication credentials
-        if (mProxyAuth)
-            mRequestHead.SetHeader(nsHttp::Proxy_Authorization, creds);
-        else
-            mRequestHead.SetHeader(nsHttp::Authorization, creds);
-
-        mAuthRetryPending = PR_TRUE; // see DoAuthRetry
-    }
-    return rv;
-}
-
-nsresult
-nsHttpChannel::PrepareForAuthentication(PRBool proxyAuth)
-{
-    LOG(("nsHttpChannel::PrepareForAuthentication [this=%p]\n", this));
-
-    if (!proxyAuth) {
-        // reset the current proxy continuation state because our last
-        // authentication attempt was completed successfully.
-        NS_IF_RELEASE(mProxyAuthContinuationState);
-        LOG(("  proxy continuation state has been reset"));
-    }
-
-    if (!mConnectionInfo->UsingHttpProxy() || mProxyAuthType.IsEmpty())
-        return NS_OK;
-
-    // We need to remove any Proxy_Authorization header left over from a
-    // non-request based authentication handshake (e.g., for NTLM auth).
-
-    nsCAutoString contractId;
-    contractId.Assign(NS_HTTP_AUTHENTICATOR_CONTRACTID_PREFIX);
-    contractId.Append(mProxyAuthType);
-
-    nsresult rv;
-    nsCOMPtr<nsIHttpAuthenticator> precedingAuth =
-        do_GetService(contractId.get(), &rv);
-    if (NS_FAILED(rv))
-        return rv;
-
-    PRUint32 precedingAuthFlags;
-    rv = precedingAuth->GetAuthFlags(&precedingAuthFlags);
-    if (NS_FAILED(rv))
-        return rv;
-
-    if (!(precedingAuthFlags & nsIHttpAuthenticator::REQUEST_BASED)) {
-        const char *challenges =
-                mResponseHead->PeekHeader(nsHttp::Proxy_Authenticate);
-        if (!challenges) {
-            // delete the proxy authorization header because we weren't
-            // asked to authenticate
-            mRequestHead.ClearHeader(nsHttp::Proxy_Authorization);
-            LOG(("  cleared proxy authorization header"));
-        }
-    }
-
-    return NS_OK;
-}
-
-nsresult
-nsHttpChannel::GetCredentials(const char *challenges,
-                              PRBool proxyAuth,
-                              nsAFlatCString &creds)
-{
-    nsCOMPtr<nsIHttpAuthenticator> auth;
-    nsCAutoString challenge;
-
-    nsCString authType; // force heap allocation to enable string sharing since
-                        // we'll be assigning this value into mAuthType.
-
-    // set informations that depend on whether we're authenticating against a
-    // proxy or a webserver
-    nsISupports **currentContinuationState;
-    nsCString *currentAuthType;
-
-    if (proxyAuth) {
-        currentContinuationState = &mProxyAuthContinuationState;
-        currentAuthType = &mProxyAuthType;
-    } else {
-        currentContinuationState = &mAuthContinuationState;
-        currentAuthType = &mAuthType;
-    }
-
-    nsresult rv = NS_ERROR_NOT_AVAILABLE;
-    PRBool gotCreds = PR_FALSE;
-    
-    // figure out which challenge we can handle and which authenticator to use.
-    for (const char *eol = challenges - 1; eol; ) {
-        const char *p = eol + 1;
-
-        // get the challenge string (LF separated -- see nsHttpHeaderArray)
-        if ((eol = strchr(p, '\n')) != nsnull)
-            challenge.Assign(p, eol - p);
-        else
-            challenge.Assign(p);
-
-        rv = GetAuthenticator(challenge.get(), authType, getter_AddRefs(auth));
-        if (NS_SUCCEEDED(rv)) {
-            //
-            // if we've already selected an auth type from a previous challenge
-            // received while processing this channel, then skip others until
-            // we find a challenge corresponding to the previously tried auth
-            // type.
-            //
-            if (!currentAuthType->IsEmpty() && authType != *currentAuthType)
-                continue;
-
-            //
-            // we allow the routines to run all the way through before we
-            // decide if they are valid.
-            //
-            // we don't worry about the auth cache being altered because that
-            // would have been the last step, and if the error is from updating
-            // the authcache it wasn't really altered anyway. -CTN 
-            //
-            // at this point the code is really only useful for client side
-            // errors (it will not automatically fail over to do a different
-            // auth type if the server keeps rejecting what is being sent, even
-            // if a particular auth method only knows 1 thing, like a
-            // non-identity based authentication method)
-            //
-            rv = GetCredentialsForChallenge(challenge.get(), authType.get(),
-                                            proxyAuth, auth, creds);
-            if (NS_SUCCEEDED(rv)) {
-                gotCreds = PR_TRUE;
-                *currentAuthType = authType;
-
-                break;
-            }
-            else if (rv == NS_ERROR_IN_PROGRESS) {
-                // authentication prompt has been invoked and result is
-                // expected asynchronously, save current challenge being
-                // processed and all remaining challenges to use later in
-                // OnAuthAvailable and now immediately return
-                mCurrentChallenge = challenge;
-                mRemainingChallenges = eol ? eol+1 : nsnull;
-                return rv;
-            }
-
-            // reset the auth type and continuation state
-            NS_IF_RELEASE(*currentContinuationState);
-            currentAuthType->Truncate();
-        }
-    }
-
-    if (!gotCreds && !currentAuthType->IsEmpty()) {
-        // looks like we never found the auth type we were looking for.
-        // reset the auth type and continuation state, and try again.
-        currentAuthType->Truncate();
-        NS_IF_RELEASE(*currentContinuationState);
-
-        rv = GetCredentials(challenges, proxyAuth, creds);
-    }
-
-    return rv;
-}
-
-nsresult
-nsHttpChannel::GetAuthorizationMembers(PRBool proxyAuth,
-                                       nsCSubstring& scheme,
-                                       const char*& host,
-                                       PRInt32& port,
-                                       nsCSubstring& path,
-                                       nsHttpAuthIdentity*& ident,
-                                       nsISupports**& continuationState)
-{
-    if (proxyAuth) {
-        NS_ASSERTION (mConnectionInfo->UsingHttpProxy(), "proxyAuth is true, but no HTTP proxy is configured!");
-
-        host = mConnectionInfo->ProxyHost();
-        port = mConnectionInfo->ProxyPort();
-        ident = &mProxyIdent;
-        scheme.AssignLiteral("http");
-
-        continuationState = &mProxyAuthContinuationState;
-    }
-    else {
-        host = mConnectionInfo->Host();
-        port = mConnectionInfo->Port();
-        ident = &mIdent;
-
-        nsresult rv;
-        rv = GetCurrentPath(path);
-        if (NS_FAILED(rv)) return rv;
-
-        rv = mURI->GetScheme(scheme);
-        if (NS_FAILED(rv)) return rv;
-
-        continuationState = &mAuthContinuationState;
-    }
-
+    LOG(("nsHttpChannel::OnAuthAvailable [this=%p]", this));
+
+    // setting mAuthRetryPending flag and resuming the transaction
+    // triggers process of throwing away the unauthenticated data already
+    // coming from the network
+    mAuthRetryPending = PR_TRUE;
+    LOG(("Resuming the transaction, we got credentials from user"));
+    mTransactionPump->Resume();
+  
     return NS_OK;
 }
 
-nsresult
-nsHttpChannel::GetCredentialsForChallenge(const char *challenge,
-                                          const char *authType,
-                                          PRBool proxyAuth,
-                                          nsIHttpAuthenticator *auth,
-                                          nsAFlatCString &creds)
-{
-    LOG(("nsHttpChannel::GetCredentialsForChallenge [this=%p proxyAuth=%d challenges=%s]\n",
-        this, proxyAuth, challenge));
-
-    // this getter never fails
-    nsHttpAuthCache *authCache = gHttpHandler->AuthCache();
-
-    PRUint32 authFlags;
-    nsresult rv = auth->GetAuthFlags(&authFlags);
-    if (NS_FAILED(rv)) return rv;
-
-    nsCAutoString realm;
-    ParseRealm(challenge, realm);
-
-    // if no realm, then use the auth type as the realm.  ToUpperCase so the
-    // ficticious realm stands out a bit more.
-    // XXX this will cause some single signon misses!
-    // XXX this was meant to be used with NTLM, which supplies no realm.
-    /*
-    if (realm.IsEmpty()) {
-        realm = authType;
-        ToUpperCase(realm);
-    }
-    */
-
-    // set informations that depend on whether
-    // we're authenticating against a proxy
-    // or a webserver
-    const char *host;
-    PRInt32 port;
-    nsHttpAuthIdentity *ident;
-    nsCAutoString path, scheme;
-    PRBool identFromURI = PR_FALSE;
-    nsISupports **continuationState;
-
-    rv = GetAuthorizationMembers(proxyAuth, scheme, host, port, path, ident, continuationState);
-    if (NS_FAILED(rv)) return rv;
-
-    if (!proxyAuth) {
-        // if this is the first challenge, then try using the identity
-        // specified in the URL.
-        if (mIdent.IsEmpty()) {
-            GetIdentityFromURI(authFlags, mIdent);
-            identFromURI = !mIdent.IsEmpty();
-        }
-    }
-
-    //
-    // if we already tried some credentials for this transaction, then
-    // we need to possibly clear them from the cache, unless the credentials
-    // in the cache have changed, in which case we'd want to give them a
-    // try instead.
-    //
-    nsHttpAuthEntry *entry = nsnull;
-    authCache->GetAuthEntryForDomain(scheme.get(), host, port, realm.get(), &entry);
-
-    // hold reference to the auth session state (in case we clear our
-    // reference to the entry).
-    nsCOMPtr<nsISupports> sessionStateGrip;
-    if (entry)
-        sessionStateGrip = entry->mMetaData;
-
-    // for digest auth, maybe our cached nonce value simply timed out...
-    PRBool identityInvalid;
-    nsISupports *sessionState = sessionStateGrip;
-    rv = auth->ChallengeReceived(this,
-                                 challenge,
-                                 proxyAuth,
-                                 &sessionState,
-                                 &*continuationState,
-                                 &identityInvalid);
-    sessionStateGrip.swap(sessionState);
-    if (NS_FAILED(rv)) return rv;
-
-    LOG(("  identity invalid = %d\n", identityInvalid));
-
-    if (identityInvalid) {
-        if (entry) {
-            if (ident->Equals(entry->Identity())) {
-                LOG(("  clearing bad auth cache entry\n"));
-                // ok, we've already tried this user identity, so clear the
-                // corresponding entry from the auth cache.
-                authCache->ClearAuthEntry(scheme.get(), host, port, realm.get());
-                entry = nsnull;
-                ident->Clear();
-            }
-            else if (!identFromURI || nsCRT::strcmp(ident->User(), entry->Identity().User()) == 0) {
-                LOG(("  taking identity from auth cache\n"));
-                // the password from the auth cache is more likely to be
-                // correct than the one in the URL.  at least, we know that it
-                // works with the given username.  it is possible for a server
-                // to distinguish logons based on the supplied password alone,
-                // but that would be quite unusual... and i don't think we need
-                // to worry about such unorthodox cases.
-                ident->Set(entry->Identity());
-                identFromURI = PR_FALSE;
-                if (entry->Creds()[0] != '\0') {
-                    LOG(("    using cached credentials!\n"));
-                    creds.Assign(entry->Creds());
-                    return entry->AddPath(path.get());
-                }
-            }
-        }
-        else if (!identFromURI) {
-            // hmm... identity invalid, but no auth entry!  the realm probably
-            // changed (see bug 201986).
-            ident->Clear();
-        }
-
-        if (!entry && ident->IsEmpty()) {
-            PRUint32 level = nsIAuthPrompt2::LEVEL_NONE;
-            if (scheme.EqualsLiteral("https"))
-                level = nsIAuthPrompt2::LEVEL_SECURE;
-            else if (authFlags & nsIHttpAuthenticator::IDENTITY_ENCRYPTED)
-                level = nsIAuthPrompt2::LEVEL_PW_ENCRYPTED;
-
-            // at this point we are forced to interact with the user to get
-            // their username and password for this domain.
-            rv = PromptForIdentity(level, proxyAuth, realm.get(), 
-                                   authType, authFlags, *ident);
-            if (NS_FAILED(rv)) return rv;
-            identFromURI = PR_FALSE;
-        }
-    }
-
-    if (identFromURI) {
-        // Warn the user before automatically using the identity from the URL
-        // to automatically log them into a site (see bug 232567).
-        if (!ConfirmAuth(NS_LITERAL_STRING("AutomaticAuth"), PR_FALSE)) {
-            // calling cancel here sets our mStatus and aborts the HTTP
-            // transaction, which prevents OnDataAvailable events.
-            Cancel(NS_ERROR_ABORT);
-            // this return code alone is not equivalent to Cancel, since
-            // it only instructs our caller that authentication failed.
-            // without an explicit call to Cancel, our caller would just
-            // load the page that accompanies the HTTP auth challenge.
-            return NS_ERROR_ABORT;
-        }
-    }
-
-    //
-    // get credentials for the given user:pass
-    //
-    // always store the credentials we're trying now so that they will be used
-    // on subsequent links.  This will potentially remove good credentials from
-    // the cache.  This is ok as we don't want to use cached credentials if the
-    // user specified something on the URI or in another manner.  This is so
-    // that we don't transparently authenticate as someone they're not
-    // expecting to authenticate as.
-    //
-    nsXPIDLCString result;
-    rv = GenCredsAndSetEntry(auth, proxyAuth, scheme.get(), host, port, path.get(),
-                             realm.get(), challenge, *ident, sessionStateGrip,
-                             getter_Copies(result));
-    if (NS_SUCCEEDED(rv))
-        creds = result;
-    return rv;
-}
-
-nsresult
-nsHttpChannel::GetAuthenticator(const char *challenge,
-                                nsCString &authType,
-                                nsIHttpAuthenticator **auth)
-{
-    LOG(("nsHttpChannel::GetAuthenticator [this=%p]\n", this));
-
-    GetAuthType(challenge, authType);
- 
-    // normalize to lowercase
-    ToLowerCase(authType);
-
-    nsCAutoString contractid;
-    contractid.Assign(NS_HTTP_AUTHENTICATOR_CONTRACTID_PREFIX);
-    contractid.Append(authType);
-
-    return CallGetService(contractid.get(), auth);
-}
-
-void
-nsHttpChannel::GetIdentityFromURI(PRUint32 authFlags, nsHttpAuthIdentity &ident)
-{
-    LOG(("nsHttpChannel::GetIdentityFromURI [this=%p]\n", this));
-
-    nsAutoString userBuf;
-    nsAutoString passBuf;
-
-    // XXX i18n
-    nsCAutoString buf;
-    mURI->GetUsername(buf);
-    if (!buf.IsEmpty()) {
-        NS_UnescapeURL(buf);
-        CopyASCIItoUTF16(buf, userBuf);
-        mURI->GetPassword(buf);
-        if (!buf.IsEmpty()) {
-            NS_UnescapeURL(buf);
-            CopyASCIItoUTF16(buf, passBuf);
-        }
-    }
-
-    if (!userBuf.IsEmpty())
-        SetIdent(ident, authFlags, (PRUnichar *) userBuf.get(), (PRUnichar *) passBuf.get());
-}
-
-void
-nsHttpChannel::ParseRealm(const char *challenge, nsACString &realm)
-{
-    //
-    // From RFC2617 section 1.2, the realm value is defined as such:
-    //
-    //    realm       = "realm" "=" realm-value
-    //    realm-value = quoted-string
-    //
-    // but, we'll accept anything after the the "=" up to the first space, or
-    // end-of-line, if the string is not quoted.
-    //
-    const char *p = PL_strcasestr(challenge, "realm=");
-    if (p) {
-        PRBool has_quote = PR_FALSE;
-        p += 6;
-        if (*p == '"') {
-            has_quote = PR_TRUE;
-            p++;
-        }
-
-        const char *end = p;
-        while (*end && has_quote) {
-           // Loop through all the string characters to find the closing
-           // quote, ignoring escaped quotes.
-            if (*end == '"' && end[-1] != '\\')
-                break;
-            ++end;
-        }
-
-        if (!has_quote)
-            end = strchr(p, ' '); 
-        if (end)
-            realm.Assign(p, end - p);
-        else
-            realm.Assign(p);
-    }
-}
-
-
-class nsHTTPAuthInformation : public nsAuthInformationHolder {
-public:
-    nsHTTPAuthInformation(PRUint32 aFlags, const nsString& aRealm,
-                          const nsCString& aAuthType)
-        : nsAuthInformationHolder(aFlags, aRealm, aAuthType) {}
-
-    void SetToHttpAuthIdentity(PRUint32 authFlags, nsHttpAuthIdentity& identity);
-};
-
-void
-nsHTTPAuthInformation::SetToHttpAuthIdentity(PRUint32 authFlags, nsHttpAuthIdentity& identity)
-{
-    identity.Set(Domain().get(), User().get(), Password().get());
-}
-
-nsresult
-nsHttpChannel::PromptForIdentity(PRUint32    level,
-                                 PRBool      proxyAuth,
-                                 const char *realm,
-                                 const char *authType,
-                                 PRUint32 authFlags,
-                                 nsHttpAuthIdentity &ident)
-{
-    LOG(("nsHttpChannel::PromptForIdentity [this=%p]\n", this));
-
-    nsCOMPtr<nsIAuthPrompt2> authPrompt;
-    GetAuthPrompt(mCallbacks, proxyAuth, getter_AddRefs(authPrompt));
-    if (!authPrompt && mLoadGroup) {
-        nsCOMPtr<nsIInterfaceRequestor> cbs;
-        mLoadGroup->GetNotificationCallbacks(getter_AddRefs(cbs));
-        GetAuthPrompt(cbs, proxyAuth, getter_AddRefs(authPrompt));
-    }
-    if (!authPrompt)
-        return NS_ERROR_NO_INTERFACE;
-
-    // XXX i18n: need to support non-ASCII realm strings (see bug 41489)
-    NS_ConvertASCIItoUTF16 realmU(realm);
-
-    nsresult rv;
-
-    // prompt the user...
-    PRUint32 promptFlags = 0;
-    if (proxyAuth)
-    {
-        promptFlags |= nsIAuthInformation::AUTH_PROXY;
-        if (mTriedProxyAuth)
-            promptFlags |= nsIAuthInformation::PREVIOUS_FAILED;
-        mTriedProxyAuth = PR_TRUE;
-    }
-    else {
-        promptFlags |= nsIAuthInformation::AUTH_HOST;
-        if (mTriedHostAuth)
-            promptFlags |= nsIAuthInformation::PREVIOUS_FAILED;
-        mTriedHostAuth = PR_TRUE;
-    }
-
-    if (authFlags & nsIHttpAuthenticator::IDENTITY_INCLUDES_DOMAIN)
-        promptFlags |= nsIAuthInformation::NEED_DOMAIN;
-
-    nsRefPtr<nsHTTPAuthInformation> holder =
-        new nsHTTPAuthInformation(promptFlags, realmU,
-                                  nsDependentCString(authType));
-    if (!holder)
-        return NS_ERROR_OUT_OF_MEMORY;
-
-    rv = authPrompt->AsyncPromptAuth(this, this, nsnull, level, holder,
-                     getter_AddRefs(mAsyncPromptAuthCancelable));
-
-    if (NS_SUCCEEDED(rv)) {
-        // indicate using this error code that authentication prompt
-        // result is expected asynchronously
-        rv = NS_ERROR_IN_PROGRESS;
-    }
-    else {
-        // Fall back to synchronous prompt
-        PRBool retval = PR_FALSE;
-        rv = authPrompt->PromptAuth(this, level, holder, &retval);
-        if (NS_FAILED(rv))
-            return rv;
-
-        if (!retval)
-            rv = NS_ERROR_ABORT;
-        else
-            holder->SetToHttpAuthIdentity(authFlags, ident);
-    }
-
-    // remember that we successfully showed the user an auth dialog
-    if (!proxyAuth)
-        mSuppressDefensiveAuth = PR_TRUE;
-
-    return rv;
-}
-
-NS_IMETHODIMP nsHttpChannel::OnAuthAvailable(nsISupports *aContext,
-                                             nsIAuthInformation *aAuthInfo)
-{
-    LOG(("nsHttpChannel::OnAuthAvailable [this=%p]", this));
-    mAsyncPromptAuthCancelable = nsnull;
-
-    nsresult rv;
-
-    const char *host;
-    PRInt32 port;
-    nsHttpAuthIdentity *ident;
-    nsCAutoString path, scheme;
-    nsISupports **continuationState;
-    rv = GetAuthorizationMembers(mProxyAuth, scheme, host, port, path, ident, continuationState);
-    if (NS_FAILED(rv))
-        OnAuthCancelled(aContext, PR_FALSE);
-
-    nsCAutoString realm;
-    ParseRealm(mCurrentChallenge.get(), realm);
-
-    nsHttpAuthCache *authCache = gHttpHandler->AuthCache();
-    nsHttpAuthEntry *entry = nsnull;
-    authCache->GetAuthEntryForDomain(scheme.get(), host, port, realm.get(), &entry);
-
-    nsCOMPtr<nsISupports> sessionStateGrip;
-    if (entry)
-        sessionStateGrip = entry->mMetaData;
-
-    nsAuthInformationHolder* holder =
-            static_cast<nsAuthInformationHolder*>(aAuthInfo);
-    ident->Set(holder->Domain().get(),
-               holder->User().get(),
-               holder->Password().get());
-
-    nsCAutoString unused;
-    nsCOMPtr<nsIHttpAuthenticator> auth;
-    rv = GetAuthenticator(mCurrentChallenge.get(), unused, getter_AddRefs(auth));
-    if (NS_FAILED(rv)) {
-        NS_ASSERTION(PR_FALSE, "GetAuthenticator failed");
-        OnAuthCancelled(aContext, PR_TRUE);
-        return NS_OK;
-    }
-
-    nsXPIDLCString creds;
-    rv = GenCredsAndSetEntry(auth, mProxyAuth,
-                             scheme.get(), host, port, path.get(),
-                             realm.get(), mCurrentChallenge.get(), *ident, sessionStateGrip,
-                             getter_Copies(creds));
-
-    mCurrentChallenge.Truncate();
-    if (NS_FAILED(rv)) {
-        OnAuthCancelled(aContext, PR_TRUE);
-        return NS_OK;
-    }
-
-    return ContinueOnAuthAvailable(creds);
-}
-
-NS_IMETHODIMP nsHttpChannel::OnAuthCancelled(nsISupports *aContext, 
-                                             PRBool userCancel)
+NS_IMETHODIMP nsHttpChannel::OnAuthCancelled(PRBool userCancel)
 {
     LOG(("nsHttpChannel::OnAuthCancelled [this=%p]", this));
-    mAsyncPromptAuthCancelable = nsnull;
+
     if (userCancel) {
-        if (!mRemainingChallenges.IsEmpty()) {
-            // there are still some challenges to process, do so
-            nsresult rv;
-
-            nsCAutoString creds;
-            rv = GetCredentials(mRemainingChallenges.get(), mProxyAuth, creds);
-            if (NS_SUCCEEDED(rv)) {
-                // GetCredentials loaded the credentials from the cache or
-                // some other way in a synchronous manner, process those
-                // credentials now
-                mRemainingChallenges.Truncate();
-                return ContinueOnAuthAvailable(creds);
-            }
-            else if (rv == NS_ERROR_IN_PROGRESS) {
-                // GetCredentials successfully queued another authprompt for
-                // a challenge from the list, we are now waiting for the user
-                // to provide the credentials
-                return NS_OK;
-            }
-
-            // otherwise, we failed...
-        }
-
-        mRemainingChallenges.Truncate();
-
         // ensure call of OnStartRequest of the current listener here,
         // it would not be called otherwise at all
         nsresult rv = CallOnStartRequest();
 
         // drop mAuthRetryPending flag and resume the transaction
         // this resumes load of the unauthenticated content data
         mAuthRetryPending = PR_FALSE;
         LOG(("Resuming the transaction, user cancelled the auth dialog"));
         mTransactionPump->Resume();
 
         if (NS_FAILED(rv))
             mTransactionPump->Cancel(rv);
     }
-
-    return NS_OK;
-}
-
-nsresult
-nsHttpChannel::ContinueOnAuthAvailable(const nsCSubstring& creds)
-{
-    if (mProxyAuth)
-        mRequestHead.SetHeader(nsHttp::Proxy_Authorization, creds);
-    else
-        mRequestHead.SetHeader(nsHttp::Authorization, creds);
-
-    // drop our remaining list of challenges.  We don't need them, because we
-    // have now authenticated against a challenge and will be sending that
-    // information to the server (or proxy).  If it doesn't accept our
-    // authentication it'll respond with failure and resend the challenge list
-    mRemainingChallenges.Truncate();
-
-    // setting mAuthRetryPending flag and resuming the transaction
-    // triggers process of throwing away the unauthenticated data already
-    // coming from the network
-    mAuthRetryPending = PR_TRUE;
-    LOG(("Resuming the transaction, we got credentials from user"));
-    mTransactionPump->Resume();
-
+    
     return NS_OK;
 }
 
-PRBool
-nsHttpChannel::ConfirmAuth(const nsString &bundleKey, PRBool doYesNoPrompt)
-{
-    // skip prompting the user if
-    //   1) we've already prompted the user
-    //   2) we're not a toplevel channel
-    //   3) the userpass length is less than the "phishy" threshold
-
-    if (mSuppressDefensiveAuth || !(mLoadFlags & LOAD_INITIAL_DOCUMENT_URI))
-        return PR_TRUE;
-
-    nsresult rv;
-    nsCAutoString userPass;
-    rv = mURI->GetUserPass(userPass);
-    if (NS_FAILED(rv) || (userPass.Length() < gHttpHandler->PhishyUserPassLength()))
-        return PR_TRUE;
-
-    // we try to confirm by prompting the user.  if we cannot do so, then
-    // assume the user said ok.  this is done to keep things working in
-    // embedded builds, where the string bundle might not be present, etc.
-
-    nsCOMPtr<nsIStringBundleService> bundleService =
-            do_GetService(NS_STRINGBUNDLE_CONTRACTID);
-    if (!bundleService)
-        return PR_TRUE;
-
-    nsCOMPtr<nsIStringBundle> bundle;
-    bundleService->CreateBundle(NECKO_MSGS_URL, getter_AddRefs(bundle));
-    if (!bundle)
-        return PR_TRUE;
-
-    nsCAutoString host;
-    rv = mURI->GetHost(host);
-    if (NS_FAILED(rv))
-        return PR_TRUE;
-
-    nsCAutoString user;
-    rv = mURI->GetUsername(user);
-    if (NS_FAILED(rv))
-        return PR_TRUE;
-
-    NS_ConvertUTF8toUTF16 ucsHost(host), ucsUser(user);
-    const PRUnichar *strs[2] = { ucsHost.get(), ucsUser.get() };
-
-    nsXPIDLString msg;
-    bundle->FormatStringFromName(bundleKey.get(), strs, 2, getter_Copies(msg));
-    if (!msg)
-        return PR_TRUE;
-    
-    nsCOMPtr<nsIPrompt> prompt;
-    GetCallback(prompt);
-    if (!prompt)
-        return PR_TRUE;
-
-    // do not prompt again
-    mSuppressDefensiveAuth = PR_TRUE;
-
-    PRBool confirmed;
-    if (doYesNoPrompt) {
-        PRInt32 choice;
-        PRBool checkState;
-        rv = prompt->ConfirmEx(nsnull, msg,
-                               nsIPrompt::BUTTON_POS_1_DEFAULT +
-                               nsIPrompt::STD_YES_NO_BUTTONS,
-                               nsnull, nsnull, nsnull, nsnull, &checkState, &choice);
-        if (NS_FAILED(rv))
-            return PR_TRUE;
-
-        confirmed = choice == 0;
-    }
-    else {
-        rv = prompt->Confirm(nsnull, msg, &confirmed);
-        if (NS_FAILED(rv))
-            return PR_TRUE;
-    }
-
-    return confirmed;
-}
-
-void
-nsHttpChannel::CheckForSuperfluousAuth()
-{
-    // we've been called because it has been determined that this channel is
-    // getting loaded without taking the userpass from the URL.  if the URL
-    // contained a userpass, then (provided some other conditions are true),
-    // we'll give the user an opportunity to abort the channel as this might be
-    // an attempt to spoof a different site (see bug 232567).
-    if (!mAuthRetryPending) {
-        // ask user...
-        if (!ConfirmAuth(NS_LITERAL_STRING("SuperfluousAuth"), PR_TRUE)) {
-            // calling cancel here sets our mStatus and aborts the HTTP
-            // transaction, which prevents OnDataAvailable events.
-            Cancel(NS_ERROR_ABORT);
-        }
-    }
-}
-
-void
-nsHttpChannel::SetAuthorizationHeader(nsHttpAuthCache *authCache,
-                                      nsHttpAtom header,
-                                      const char *scheme,
-                                      const char *host,
-                                      PRInt32 port,
-                                      const char *path,
-                                      nsHttpAuthIdentity &ident)
-{
-    nsHttpAuthEntry *entry = nsnull;
-    nsresult rv;
-
-    // set informations that depend on whether
-    // we're authenticating against a proxy
-    // or a webserver
-    nsISupports **continuationState;
-
-    if (header == nsHttp::Proxy_Authorization) {
-        continuationState = &mProxyAuthContinuationState;
-    } else {
-        continuationState = &mAuthContinuationState;
-    }
-
-    rv = authCache->GetAuthEntryForPath(scheme, host, port, path, &entry);
-    if (NS_SUCCEEDED(rv)) {
-        // if we are trying to add a header for origin server auth and if the
-        // URL contains an explicit username, then try the given username first.
-        // we only want to do this, however, if we know the URL requires auth
-        // based on the presence of an auth cache entry for this URL (which is
-        // true since we are here).  but, if the username from the URL matches
-        // the username from the cache, then we should prefer the password
-        // stored in the cache since that is most likely to be valid.
-        if (header == nsHttp::Authorization && entry->Domain()[0] == '\0') {
-            GetIdentityFromURI(0, ident);
-            // if the usernames match, then clear the ident so we will pick
-            // up the one from the auth cache instead.
-            if (nsCRT::strcmp(ident.User(), entry->User()) == 0)
-                ident.Clear();
-        }
-        PRBool identFromURI;
-        if (ident.IsEmpty()) {
-            ident.Set(entry->Identity());
-            identFromURI = PR_FALSE;
-        }
-        else
-            identFromURI = PR_TRUE;
-
-        nsXPIDLCString temp;
-        const char *creds     = entry->Creds();
-        const char *challenge = entry->Challenge();
-        // we can only send a preemptive Authorization header if we have either
-        // stored credentials or a stored challenge from which to derive
-        // credentials.  if the identity is from the URI, then we cannot use
-        // the stored credentials.
-        if ((!creds[0] || identFromURI) && challenge[0]) {
-            nsCOMPtr<nsIHttpAuthenticator> auth;
-            nsCAutoString unused;
-            rv = GetAuthenticator(challenge, unused, getter_AddRefs(auth));
-            if (NS_SUCCEEDED(rv)) {
-                PRBool proxyAuth = (header == nsHttp::Proxy_Authorization);
-                rv = GenCredsAndSetEntry(auth, proxyAuth, scheme, host, port, path,
-                                         entry->Realm(), challenge, ident,
-                                         entry->mMetaData, getter_Copies(temp));
-                if (NS_SUCCEEDED(rv))
-                    creds = temp.get();
-
-                // make sure the continuation state is null since we do not
-                // support mixing preemptive and 'multirequest' authentication.
-                NS_IF_RELEASE(*continuationState);
-            }
-        }
-        if (creds[0]) {
-            LOG(("   adding \"%s\" request header\n", header.get()));
-            mRequestHead.SetHeader(header, nsDependentCString(creds));
-
-            // suppress defensive auth prompting for this channel since we know
-            // that we already prompted at least once this session.  we only do
-            // this for non-proxy auth since the URL's userpass is not used for
-            // proxy auth.
-            if (header == nsHttp::Authorization)
-                mSuppressDefensiveAuth = PR_TRUE;
-        }
-        else
-            ident.Clear(); // don't remember the identity
-    }
-}
-
-void
-nsHttpChannel::AddAuthorizationHeaders()
-{
-    LOG(("nsHttpChannel::AddAuthorizationHeaders? [this=%p]\n", this));
-
-    if (mLoadFlags & LOAD_ANONYMOUS) {
-      return;
-    }
-
-    // this getter never fails
-    nsHttpAuthCache *authCache = gHttpHandler->AuthCache();
-
-    // check if proxy credentials should be sent
-    const char *proxyHost = mConnectionInfo->ProxyHost();
-    if (proxyHost && mConnectionInfo->UsingHttpProxy())
-        SetAuthorizationHeader(authCache, nsHttp::Proxy_Authorization,
-                               "http", proxyHost, mConnectionInfo->ProxyPort(),
-                               nsnull, // proxy has no path
-                               mProxyIdent);
-
-    // check if server credentials should be sent
-    nsCAutoString path, scheme;
-    if (NS_SUCCEEDED(GetCurrentPath(path)) &&
-        NS_SUCCEEDED(mURI->GetScheme(scheme))) {
-        SetAuthorizationHeader(authCache, nsHttp::Authorization,
-                               scheme.get(),
-                               mConnectionInfo->Host(),
-                               mConnectionInfo->Port(),
-                               path.get(),
-                               mIdent);
-    }
-}
-
-nsresult
-nsHttpChannel::GetCurrentPath(nsACString &path)
-{
-    nsresult rv;
-    nsCOMPtr<nsIURL> url = do_QueryInterface(mURI);
-    if (url)
-        rv = url->GetDirectory(path);
-    else
-        rv = mURI->GetPath(path);
-    return rv;
-}
-
 //-----------------------------------------------------------------------------
 // nsHttpChannel::nsISupports
 //-----------------------------------------------------------------------------
 
 NS_IMPL_ADDREF_INHERITED(nsHttpChannel, nsHashPropertyBag)
 NS_IMPL_RELEASE_INHERITED(nsHttpChannel, nsHashPropertyBag)
 
 NS_INTERFACE_MAP_BEGIN(nsHttpChannel)
@@ -4135,20 +3103,20 @@ NS_INTERFACE_MAP_BEGIN(nsHttpChannel)
     NS_INTERFACE_MAP_ENTRY(nsICacheListener)
     NS_INTERFACE_MAP_ENTRY(nsIEncodedChannel)
     NS_INTERFACE_MAP_ENTRY(nsIHttpChannelInternal)
     NS_INTERFACE_MAP_ENTRY(nsIResumableChannel)
     NS_INTERFACE_MAP_ENTRY(nsITransportEventSink)
     NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
     NS_INTERFACE_MAP_ENTRY(nsIProtocolProxyCallback)
     NS_INTERFACE_MAP_ENTRY(nsIProxiedChannel)
+    NS_INTERFACE_MAP_ENTRY(nsIHttpAuthenticableChannel)
     NS_INTERFACE_MAP_ENTRY(nsITraceableChannel)
     NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheContainer)
     NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheChannel)
-    NS_INTERFACE_MAP_ENTRY(nsIAuthPromptCallback)
 NS_INTERFACE_MAP_END_INHERITING(nsHashPropertyBag)
 
 //-----------------------------------------------------------------------------
 // nsHttpChannel::nsIRequest
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsHttpChannel::GetName(nsACString &aName)
@@ -4186,18 +3154,18 @@ nsHttpChannel::Cancel(nsresult status)
     if (mProxyRequest)
         mProxyRequest->Cancel(status);
     if (mTransaction)
         gHttpHandler->CancelTransaction(mTransaction, status);
     if (mTransactionPump)
         mTransactionPump->Cancel(status);
     if (mCachePump)
         mCachePump->Cancel(status);
-    if (mAsyncPromptAuthCancelable)
-        mAsyncPromptAuthCancelable->Cancel(status);
+    if (mAuthProvider)
+        mAuthProvider->Cancel(status);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHttpChannel::Suspend()
 {
     NS_ENSURE_TRUE(mIsPending, NS_ERROR_NOT_AVAILABLE);
     
@@ -5153,16 +4121,71 @@ nsHttpChannel::GetProxyInfo(nsIProxyInfo
     else {
         *result = mConnectionInfo->ProxyInfo();
         NS_IF_ADDREF(*result);
     }
     return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
+// nsHttpChannel::nsIHttpAuthenticableChannel
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+nsHttpChannel::GetIsSSL(PRBool *aIsSSL)
+{
+    *aIsSSL = mConnectionInfo->UsingSSL();
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsHttpChannel::GetProxyMethodIsConnect(PRBool *aProxyMethodIsConnect)
+{
+    *aProxyMethodIsConnect =
+        (mConnectionInfo->UsingHttpProxy() && mConnectionInfo->UsingSSL());
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsHttpChannel::GetServerResponseHeader(nsACString &value)
+{
+    if (!mResponseHead)
+        return NS_ERROR_NOT_AVAILABLE;
+    return mResponseHead->GetHeader(nsHttp::Server, value);
+}
+
+NS_IMETHODIMP
+nsHttpChannel::GetProxyChallenges(nsACString &value)
+{
+    if (!mResponseHead)
+        return NS_ERROR_UNEXPECTED;
+    return mResponseHead->GetHeader(nsHttp::Proxy_Authenticate, value);
+}
+
+NS_IMETHODIMP
+nsHttpChannel::GetWWWChallenges(nsACString &value)
+{
+    if (!mResponseHead)
+        return NS_ERROR_UNEXPECTED;
+    return mResponseHead->GetHeader(nsHttp::WWW_Authenticate, value);
+}
+
+NS_IMETHODIMP
+nsHttpChannel::SetProxyCredentials(const nsACString &value)
+{
+    return mRequestHead.SetHeader(nsHttp::Proxy_Authorization, value);
+}
+
+NS_IMETHODIMP
+nsHttpChannel::SetWWWCredentials(const nsACString &value)
+{
+    return mRequestHead.SetHeader(nsHttp::Authorization, value);
+}
+
+//-----------------------------------------------------------------------------
 // nsHttpChannel::nsIRequestObserver
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsHttpChannel::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
 {
     if (!(mCanceled || NS_FAILED(mStatus))) {
         // capture the request's status, so our consumers will know ASAP of any
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -38,17 +38,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsHttpChannel_h__
 #define nsHttpChannel_h__
 
 #include "nsHttpTransaction.h"
 #include "nsHttpRequestHead.h"
-#include "nsHttpAuthCache.h"
 #include "nsHashPropertyBag.h"
 #include "nsInputStreamPump.h"
 #include "nsThreadUtils.h"
 #include "nsString.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsInt64.h"
 
@@ -78,23 +77,22 @@
 #include "nsIStringEnumerator.h"
 #include "nsIOutputStream.h"
 #include "nsIAsyncInputStream.h"
 #include "nsIPrompt.h"
 #include "nsIResumableChannel.h"
 #include "nsISupportsPriority.h"
 #include "nsIProtocolProxyCallback.h"
 #include "nsICancelable.h"
-#include "nsIProxiedChannel.h"
+#include "nsIHttpAuthenticableChannel.h"
 #include "nsITraceableChannel.h"
-#include "nsIAuthPromptCallback.h"
+#include "nsIHttpChannelAuthProvider.h"
 
 class nsHttpResponseHead;
 class nsAHttpConnection;
-class nsIHttpAuthenticator;
 class nsProxyInfo;
 
 //-----------------------------------------------------------------------------
 // nsHttpChannel
 //-----------------------------------------------------------------------------
 
 class nsHttpChannel : public nsHashPropertyBag
                     , public nsIHttpChannel
@@ -104,20 +102,19 @@ class nsHttpChannel : public nsHashPrope
                     , public nsIUploadChannel
                     , public nsIUploadChannel2
                     , public nsICacheListener
                     , public nsIEncodedChannel
                     , public nsITransportEventSink
                     , public nsIResumableChannel
                     , public nsISupportsPriority
                     , public nsIProtocolProxyCallback
-                    , public nsIProxiedChannel
+                    , public nsIHttpAuthenticableChannel
                     , public nsITraceableChannel
                     , public nsIApplicationCacheChannel
-                    , public nsIAuthPromptCallback
 {
 public:
     NS_DECL_ISUPPORTS_INHERITED
     NS_DECL_NSIREQUEST
     NS_DECL_NSICHANNEL
     NS_DECL_NSIHTTPCHANNEL
     NS_DECL_NSIREQUESTOBSERVER
     NS_DECL_NSISTREAMLISTENER
@@ -130,17 +127,29 @@ public:
     NS_DECL_NSITRANSPORTEVENTSINK
     NS_DECL_NSIRESUMABLECHANNEL
     NS_DECL_NSISUPPORTSPRIORITY
     NS_DECL_NSIPROTOCOLPROXYCALLBACK
     NS_DECL_NSIPROXIEDCHANNEL
     NS_DECL_NSITRACEABLECHANNEL
     NS_DECL_NSIAPPLICATIONCACHECONTAINER
     NS_DECL_NSIAPPLICATIONCACHECHANNEL
-    NS_DECL_NSIAUTHPROMPTCALLBACK
+
+    // nsIHttpAuthenticableChannel. We can't use
+    // NS_DECL_NSIHTTPAUTHENTICABLECHANNEL because it duplicates cancel() and
+    // others.
+    NS_IMETHOD GetIsSSL(PRBool *aIsSSL);
+    NS_IMETHOD GetProxyMethodIsConnect(PRBool *aProxyMethodIsConnect);
+    NS_IMETHOD GetServerResponseHeader(nsACString & aServerResponseHeader);
+    NS_IMETHOD GetProxyChallenges(nsACString & aChallenges);
+    NS_IMETHOD GetWWWChallenges(nsACString & aChallenges);
+    NS_IMETHOD SetProxyCredentials(const nsACString & aCredentials);
+    NS_IMETHOD SetWWWCredentials(const nsACString & aCredentials);
+    NS_IMETHOD OnAuthAvailable();
+    NS_IMETHOD OnAuthCancelled(PRBool userCancel);
 
     nsHttpChannel();
     virtual ~nsHttpChannel();
 
     nsresult Init(nsIURI *uri,
                   PRUint8 capabilities,
                   nsProxyInfo* proxyInfo);
 
@@ -175,17 +184,16 @@ private:
     nsresult ApplyContentConversions();
     nsresult CallOnStartRequest();
     nsresult ProcessResponse();
     nsresult ProcessNormal();
     nsresult ProcessNotModified();
     nsresult ProcessRedirection(PRUint32 httpStatus);
     PRBool   ShouldSSLProxyResponseContinue(PRUint32 httpStatus);
     nsresult ProcessFailedSSLConnect(PRUint32 httpStatus);
-    nsresult ProcessAuthentication(PRUint32 httpStatus);
     nsresult ProcessFallback(PRBool *fallingBack);
     PRBool   ResponseWouldVary();
 
     // redirection specific methods
     void     HandleAsyncRedirect();
     void     HandleAsyncNotModified();
     void     HandleAsyncFallback();
     nsresult PromptTempRedirect();
@@ -221,51 +229,18 @@ private:
     // Handle the bogus Content-Encoding Apache sometimes sends
     void ClearBogusContentEncodingIfNeeded();
 
     // byte range request specific methods
     nsresult SetupByteRangeRequest(PRUint32 partialLen);
     nsresult ProcessPartialContent();
     nsresult OnDoneReadingPartialCacheEntry(PRBool *streamDone);
 
-    // auth specific methods
-    nsresult PrepareForAuthentication(PRBool proxyAuth);
-    nsresult GenCredsAndSetEntry(nsIHttpAuthenticator *, PRBool proxyAuth, const char *scheme, const char *host, PRInt32 port, const char *dir, const char *realm, const char *challenge, const nsHttpAuthIdentity &ident, nsCOMPtr<nsISupports> &session, char **result);
-    nsresult GetAuthenticator(const char *challenge, nsCString &scheme, nsIHttpAuthenticator **auth); 
-    void     ParseRealm(const char *challenge, nsACString &realm);
-    void     GetIdentityFromURI(PRUint32 authFlags, nsHttpAuthIdentity&);
-    /**
-     * Following three methods return NS_ERROR_IN_PROGRESS when
-     * nsIAuthPrompt2.asyncPromptAuth method is called. This result indicates
-     * the user's decision will be gathered in a callback and is not an actual
-     * error.
-     */
-    nsresult GetCredentials(const char *challenges, PRBool proxyAuth, nsAFlatCString &creds);
-    nsresult GetCredentialsForChallenge(const char *challenge, const char *scheme,  PRBool proxyAuth, nsIHttpAuthenticator *auth, nsAFlatCString &creds);
-    nsresult PromptForIdentity(PRUint32 level, PRBool proxyAuth, const char *realm, const char *authType, PRUint32 authFlags, nsHttpAuthIdentity &);
-
-    PRBool   ConfirmAuth(const nsString &bundleKey, PRBool doYesNoPrompt);
-    void     CheckForSuperfluousAuth();
-    void     SetAuthorizationHeader(nsHttpAuthCache *, nsHttpAtom header, const char *scheme, const char *host, PRInt32 port, const char *path, nsHttpAuthIdentity &ident);
-    void     AddAuthorizationHeaders();
-    nsresult GetCurrentPath(nsACString &);
-    /**
-     * Return all information needed to build authorization information,
-     * all paramters except proxyAuth are out parameters. proxyAuth specifies
-     * with what authorization we work (WWW or proxy).
-     */
-    nsresult GetAuthorizationMembers(PRBool proxyAuth, nsCSubstring& scheme, const char*& host, PRInt32& port, nsCSubstring& path, nsHttpAuthIdentity*& ident, nsISupports**& continuationState);
     nsresult DoAuthRetry(nsAHttpConnection *);
     PRBool   MustValidateBasedOnQueryUrl();
-    /**
-     * Method called to resume suspended transaction after we got credentials
-     * from the user. Called from OnAuthAvailable callback or OnAuthCancelled
-     * when credentials for next challenge were obtained synchronously.
-     */
-    nsresult ContinueOnAuthAvailable(const nsCSubstring& creds);
 
 private:
     nsCOMPtr<nsIURI>                  mOriginalURI;
     nsCOMPtr<nsIURI>                  mURI;
     nsCOMPtr<nsIURI>                  mDocumentURI;
     nsCOMPtr<nsIStreamListener>       mListener;
     nsCOMPtr<nsISupports>             mListenerContext;
     nsCOMPtr<nsILoadGroup>            mLoadGroup;
@@ -306,35 +281,17 @@ private:
 
     nsCOMPtr<nsICacheEntryDescriptor> mOfflineCacheEntry;
     nsCacheAccessMode                 mOfflineCacheAccess;
     nsCString                         mOfflineCacheClientID;
 
     nsCOMPtr<nsIApplicationCache>     mApplicationCache;
 
     // auth specific data
-    nsISupports                      *mProxyAuthContinuationState;
-    nsCString                         mProxyAuthType;
-    nsISupports                      *mAuthContinuationState;
-    nsCString                         mAuthType;
-    nsHttpAuthIdentity                mIdent;
-    nsHttpAuthIdentity                mProxyIdent;
-
-    // Reference to the prompt wating in prompt queue. The channel is
-    // responsible to call its cancel method when user in any way cancels
-    // this request.
-    nsCOMPtr<nsICancelable>           mAsyncPromptAuthCancelable;
-    // Saved in GetCredentials when prompt is asynchronous, the first challenge
-    // we obtained from the server with 401/407 response, will be processed in
-    // OnAuthAvailable callback.
-    nsCString                         mCurrentChallenge;
-    // Saved in GetCredentials when prompt is asynchronous, remaning challenges
-    // we have to process when user cancels the auth dialog for the current
-    // challenge.
-    nsCString                         mRemainingChallenges;
+    nsCOMPtr<nsIHttpChannelAuthProvider> mAuthProvider;
 
     // Resumable channel specific data
     nsCString                         mEntityID;
     PRUint64                          mStartPos;
 
     // Function pointer that can be set to indicate that we got suspended while
     // waiting on an AsyncCall.  When we get resumed we should AsyncCall this
     // function.
@@ -362,22 +319,16 @@ private:
     PRUint32                          mAllowPipelining          : 1;
     PRUint32                          mCachedContentIsValid     : 1;
     PRUint32                          mCachedContentIsPartial   : 1;
     PRUint32                          mResponseHeadersModified  : 1;
     PRUint32                          mCanceled                 : 1;
     PRUint32                          mTransactionReplaced      : 1;
     PRUint32                          mUploadStreamHasHeaders   : 1;
     PRUint32                          mAuthRetryPending         : 1;
-    // True when we need to authenticate to proxy, i.e. when we get 407
-    // response. Used in OnAuthAvailable and OnAuthCancelled callbacks.
-    PRUint32                          mProxyAuth                : 1;
-    PRUint32                          mTriedProxyAuth           : 1;
-    PRUint32                          mTriedHostAuth            : 1;
-    PRUint32                          mSuppressDefensiveAuth    : 1;
     PRUint32                          mResuming                 : 1;
     PRUint32                          mInitedCacheEntry         : 1;
     PRUint32                          mCacheForOfflineUse       : 1;
     // True if mCacheForOfflineUse was set because we were caching
     // opportunistically.
     PRUint32                          mCachingOpportunistically : 1;
     // True if we are loading a fallback cache entry from the
     // application cache.
copy from netwerk/protocol/http/nsHttpChannel.cpp
copy to netwerk/protocol/http/nsHttpChannelAuthProvider.cpp
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp
@@ -23,3018 +23,267 @@
  * Contributor(s):
  *   Darin Fisher <darin@meer.net> (original author)
  *   Christian Biesinger <cbiesinger@web.de>
  *   Google Inc.
  *   Jan Wrobel <wrobel@blues.ath.cx>
  *   Jan Odvarko <odvarko@gmail.com>
  *   Dave Camp <dcamp@mozilla.com>
  *   Honza Bambas <honzab@firemni.cz>
+ *   Wellington Fernando de Macedo <wfernandom2004@gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-#include "nsHttpChannel.h"
-#include "nsHttpTransaction.h"
-#include "nsHttpConnection.h"
+#include "nsHttpChannelAuthProvider.h"
+#include "nsNetUtil.h"
 #include "nsHttpHandler.h"
-#include "nsHttpAuthCache.h"
-#include "nsHttpResponseHead.h"
-#include "nsHttp.h"
 #include "nsIHttpAuthenticator.h"
-#include "nsIApplicationCacheService.h"
-#include "nsIApplicationCacheContainer.h"
-#include "nsIAuthInformation.h"
 #include "nsIAuthPrompt2.h"
 #include "nsIAuthPromptProvider.h"
-#include "nsIStringBundle.h"
-#include "nsXPCOM.h"
-#include "nsISupportsPrimitives.h"
-#include "nsIURL.h"
-#include "nsIIDNService.h"
-#include "nsIStreamListenerTee.h"
-#include "nsISeekableStream.h"
-#include "nsMimeTypes.h"
-#include "nsNetUtil.h"
-#include "nsString.h"
-#include "nsPrintfCString.h"
-#include "nsReadableUtils.h"
-#include "nsUnicharUtils.h"
-#include "nsAutoPtr.h"
-#include "plstr.h"
-#include "prprf.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsIInterfaceRequestorUtils.h"
 #include "nsEscape.h"
-#include "nsICookieService.h"
-#include "nsIResumableChannel.h"
-#include "nsInt64.h"
-#include "nsIVariant.h"
-#include "nsChannelProperties.h"
-#include "nsStreamUtils.h"
-#include "nsIOService.h"
 #include "nsAuthInformationHolder.h"
-#include "nsICacheService.h"
-#include "nsDNSPrefetch.h"
-#include "nsChannelClassifier.h"
-
-// True if the local cache should be bypassed when processing a request.
-#define BYPASS_LOCAL_CACHE(loadFlags) \
-        (loadFlags & (nsIRequest::LOAD_BYPASS_CACHE | \
-                      nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE))
-
-static NS_DEFINE_CID(kStreamListenerTeeCID, NS_STREAMLISTENERTEE_CID);
+#include "nsIStringBundle.h"
+#include "nsIPrompt.h"
 
-//-----------------------------------------------------------------------------
-// nsHttpChannel <public>
-//-----------------------------------------------------------------------------
-
-nsHttpChannel::nsHttpChannel()
-    : mResponseHead(nsnull)
-    , mTransaction(nsnull)
-    , mConnectionInfo(nsnull)
-    , mLoadFlags(LOAD_NORMAL)
-    , mStatus(NS_OK)
-    , mLogicalOffset(0)
-    , mCaps(0)
-    , mPriority(PRIORITY_NORMAL)
-    , mCachedResponseHead(nsnull)
-    , mCacheAccess(0)
-    , mPostID(0)
-    , mRequestTime(0)
+nsHttpChannelAuthProvider::nsHttpChannelAuthProvider()
+    : mAuthChannel(nsnull)
     , mProxyAuthContinuationState(nsnull)
     , mAuthContinuationState(nsnull)
-    , mStartPos(LL_MAXUINT)
-    , mPendingAsyncCallOnResume(nsnull)
-    , mSuspendCount(0)
-    , mRedirectionLimit(gHttpHandler->RedirectionLimit())
-    , mIsPending(PR_FALSE)
-    , mWasOpened(PR_FALSE)
-    , mApplyConversion(PR_TRUE)
-    , mAllowPipelining(PR_TRUE)
-    , mCachedContentIsValid(PR_FALSE)
-    , mCachedContentIsPartial(PR_FALSE)
-    , mResponseHeadersModified(PR_FALSE)
-    , mCanceled(PR_FALSE)
-    , mTransactionReplaced(PR_FALSE)
-    , mUploadStreamHasHeaders(PR_FALSE)
-    , mAuthRetryPending(PR_FALSE)
     , mProxyAuth(PR_FALSE)
     , mTriedProxyAuth(PR_FALSE)
     , mTriedHostAuth(PR_FALSE)
     , mSuppressDefensiveAuth(PR_FALSE)
-    , mResuming(PR_FALSE)
-    , mInitedCacheEntry(PR_FALSE)
-    , mCacheForOfflineUse(PR_FALSE)
-    , mCachingOpportunistically(PR_FALSE)
-    , mFallbackChannel(PR_FALSE)
-    , mInheritApplicationCache(PR_TRUE)
-    , mChooseApplicationCache(PR_FALSE)
-    , mLoadedFromApplicationCache(PR_FALSE)
-    , mTracingEnabled(PR_TRUE)
-    , mForceAllowThirdPartyCookie(PR_FALSE)
-    , mCustomConditionalRequest(PR_FALSE)
 {
-    LOG(("Creating nsHttpChannel [this=%p]\n", this));
-
     // grab a reference to the handler to ensure that it doesn't go away.
     nsHttpHandler *handler = gHttpHandler;
     NS_ADDREF(handler);
 }
 
-nsHttpChannel::~nsHttpChannel()
+nsHttpChannelAuthProvider::~nsHttpChannelAuthProvider()
 {
-    LOG(("Destroying nsHttpChannel [this=%p]\n", this));
-
-    NS_IF_RELEASE(mConnectionInfo);
-    NS_IF_RELEASE(mTransaction);
-
-    NS_IF_RELEASE(mProxyAuthContinuationState);
-    NS_IF_RELEASE(mAuthContinuationState);
-
-    delete mResponseHead;
-    delete mCachedResponseHead;
+    NS_ASSERTION(!mAuthChannel, "Disconnect wasn't called");
 
     // release our reference to the handler
     nsHttpHandler *handler = gHttpHandler;
     NS_RELEASE(handler);
 }
 
-nsresult
-nsHttpChannel::Init(nsIURI *uri,
-                    PRUint8 caps,
-                    nsProxyInfo *proxyInfo)
+NS_IMETHODIMP
+nsHttpChannelAuthProvider::Init(nsIHttpAuthenticableChannel *channel)
 {
-    LOG(("nsHttpChannel::Init [this=%p]\n", this));
-
-    NS_PRECONDITION(uri, "null uri");
-
-    nsresult rv = nsHashPropertyBag::Init();
-    if (NS_FAILED(rv))
-        return rv;
+    NS_ASSERTION(channel, "channel expected!");
 
-    mURI = uri;
-    mOriginalURI = uri;
-    mDocumentURI = nsnull;
-    mCaps = caps;
+    mAuthChannel = channel;
 
-    //
-    // Construct connection info object
-    //
-    nsCAutoString host;
-    PRInt32 port = -1;
-    PRBool usingSSL = PR_FALSE;
-    
-    rv = mURI->SchemeIs("https", &usingSSL);
+    nsresult rv = mAuthChannel->GetURI(getter_AddRefs(mURI));
     if (NS_FAILED(rv)) return rv;
 
-    rv = mURI->GetAsciiHost(host);
+    mAuthChannel->GetIsSSL(&mUsingSSL);
+    if (NS_FAILED(rv)) return rv;
+
+    rv = mURI->GetAsciiHost(mHost);
     if (NS_FAILED(rv)) return rv;
 
     // reject the URL if it doesn't specify a host
-    if (host.IsEmpty())
+    if (mHost.IsEmpty())
         return NS_ERROR_MALFORMED_URI;
 
-    rv = mURI->GetPort(&port);
-    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,
-                                               proxyInfo, usingSSL);
-    if (!mConnectionInfo)
-        return NS_ERROR_OUT_OF_MEMORY;
-    NS_ADDREF(mConnectionInfo);
-
-    // Set default request method
-    mRequestHead.SetMethod(nsHttp::Get);
-
-    //
-    // Set request headers
-    //
-    nsCAutoString 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(), caps,
-                                  !mConnectionInfo->UsingSSL() &&
-                                  mConnectionInfo->UsingHttpProxy());
-
-    return rv;
-}
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel <private>
-//-----------------------------------------------------------------------------
-
-nsresult
-nsHttpChannel::AsyncCall(nsAsyncCallback funcPtr,
-                         nsRunnableMethod<nsHttpChannel> **retval)
-{
-    nsresult rv;
-
-    nsRefPtr<nsRunnableMethod<nsHttpChannel> > event =
-        NS_NewRunnableMethod(this, funcPtr);
-    rv = NS_DispatchToCurrentThread(event);
-    if (NS_SUCCEEDED(rv) && retval) {
-        *retval = event;
-    }
-
-    return rv;
-}
-
-nsresult
-nsHttpChannel::Connect(PRBool firstTime)
-{
-    nsresult rv;
-
-    LOG(("nsHttpChannel::Connect [this=%p]\n", this));
-
-    // ensure that we are using a valid hostname
-    if (!net_IsValidHostName(nsDependentCString(mConnectionInfo->Host())))
-        return NS_ERROR_UNKNOWN_HOST;
-
-    // true when called from AsyncOpen
-    if (firstTime) {
-        PRBool delayed = PR_FALSE;
-
-        // are we offline?
-        PRBool 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;
-        }
-
-        // open a cache entry for this channel...
-        rv = OpenCacheEntry(offline, &delayed);
-
-        if (NS_FAILED(rv)) {
-            LOG(("OpenCacheEntry failed [rv=%x]\n", rv));
-            // if this channel is only allowed to pull from the cache, then
-            // we must fail if we were unable to open a cache entry.
-            if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
-                // If we have a fallback URI (and we're not already
-                // falling back), process the fallback asynchronously.
-                if (!mFallbackChannel && !mFallbackKey.IsEmpty()) {
-                    return AsyncCall(&nsHttpChannel::HandleAsyncFallback);
-                }
-                return NS_ERROR_DOCUMENT_NOT_CACHED;
-            }
-            // otherwise, let's just proceed without using the cache.
-        }
-
-        // if cacheForOfflineUse has been set, open up an offline cache
-        // entry to update
-        if (mCacheForOfflineUse) {
-            rv = OpenOfflineCacheEntryForWriting();
-            if (NS_FAILED(rv)) return rv;
-        }
-
-        if (NS_SUCCEEDED(rv) && delayed)
-            return NS_OK;
-    }
-
-    // we may or may not have a cache entry at this point
-    if (mCacheEntry) {
-        // inspect the cache entry to determine whether or not we need to go
-        // out to net to validate it.  this call sets mCachedContentIsValid
-        // and may set request headers as required for cache validation.
-        rv = CheckCache();
-        if (NS_FAILED(rv))
-            NS_WARNING("cache check failed");
-
-        // read straight from the cache if possible...
-        if (mCachedContentIsValid) {
-            nsRunnableMethod<nsHttpChannel> *event = nsnull;
-            if (!mCachedContentIsPartial) {
-                AsyncCall(&nsHttpChannel::AsyncOnExamineCachedResponse, &event);
-            }
-            rv = ReadFromCache();
-            if (NS_FAILED(rv) && event) {
-                event->Revoke();
-            }
-            return rv;
-        }
-        else if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
-            // the cache contains the requested resource, but it must be 
-            // validated before we can reuse it.  since we are not allowed
-            // to hit the net, there's nothing more to do.  the document
-            // is effectively not in the cache.
-            return NS_ERROR_DOCUMENT_NOT_CACHED;
-        }
-    }
-
-    // check to see if authorization headers should be included
-    AddAuthorizationHeaders();
-
-    if (mLoadFlags & LOAD_NO_NETWORK_IO) {
-        return NS_ERROR_DOCUMENT_NOT_CACHED;
-    }
-
-    // hit the net...
-    rv = SetupTransaction();
-    if (NS_FAILED(rv)) return rv;
-
-    rv = gHttpHandler->InitiateTransaction(mTransaction, mPriority);
+    rv = mURI->GetPort(&mPort);
     if (NS_FAILED(rv)) return rv;
 
-    return mTransactionPump->AsyncRead(this, nsnull);
-}
-
-// called when Connect fails
-nsresult
-nsHttpChannel::AsyncAbort(nsresult status)
-{
-    LOG(("nsHttpChannel::AsyncAbort [this=%p status=%x]\n", this, status));
-
-    mStatus = status;
-    mIsPending = PR_FALSE;
-
-    nsresult rv = AsyncCall(&nsHttpChannel::HandleAsyncNotifyListener);
-    // And if that fails?  Callers ignore our return value anyway....
-    
-    // finally remove ourselves from the load group.
-    if (mLoadGroup)
-        mLoadGroup->RemoveRequest(this, nsnull, status);
-
-    return rv;
-}
-
-void
-nsHttpChannel::HandleAsyncNotifyListener()
-{
-    NS_PRECONDITION(!mPendingAsyncCallOnResume, "How did that happen?");
-    
-    if (mSuspendCount) {
-        LOG(("Waiting until resume to do async notification [this=%p]\n",
-             this));
-        mPendingAsyncCallOnResume = &nsHttpChannel::HandleAsyncNotifyListener;
-        return;
-    }
-
-    DoNotifyListener();
-}
-
-void
-nsHttpChannel::DoNotifyListener()
-{
-    if (mListener) {
-        mListener->OnStartRequest(this, mListenerContext);
-        mListener->OnStopRequest(this, mListenerContext, mStatus);
-        mListener = 0;
-        mListenerContext = 0;
-    }
-    // We have to make sure to drop the reference to the callbacks too
-    mCallbacks = nsnull;
-    mProgressSink = nsnull;
-}
-
-void
-nsHttpChannel::HandleAsyncRedirect()
-{
-    NS_PRECONDITION(!mPendingAsyncCallOnResume, "How did that happen?");
-    
-    if (mSuspendCount) {
-        LOG(("Waiting until resume to do async redirect [this=%p]\n", this));
-        mPendingAsyncCallOnResume = &nsHttpChannel::HandleAsyncRedirect;
-        return;
-    }
-
-    nsresult rv = NS_OK;
-
-    LOG(("nsHttpChannel::HandleAsyncRedirect [this=%p]\n", this));
-
-    // since this event is handled asynchronously, it is possible that this
-    // channel could have been canceled, in which case there would be no point
-    // in processing the redirect.
-    if (NS_SUCCEEDED(mStatus)) {
-        rv = ProcessRedirection(mResponseHead->Status());
-        if (NS_FAILED(rv)) {
-            // If ProcessRedirection fails, then we have to send out the
-            // OnStart/OnStop notifications.
-            LOG(("ProcessRedirection failed [rv=%x]\n", rv));
-            mStatus = rv;
-            DoNotifyListener();
-        }
-    }
-
-    // close the cache entry.  Blow it away if we couldn't process the redirect
-    // for some reason (the cache entry might be corrupt).
-    if (mCacheEntry) {
-        if (NS_FAILED(rv))
-            mCacheEntry->Doom();
-        CloseCacheEntry(PR_FALSE);
-    }
-
-    mIsPending = PR_FALSE;
-
-    if (mLoadGroup)
-        mLoadGroup->RemoveRequest(this, nsnull, mStatus);
-}
-
-void
-nsHttpChannel::HandleAsyncNotModified()
-{
-    NS_PRECONDITION(!mPendingAsyncCallOnResume, "How did that happen?");
-    
-    if (mSuspendCount) {
-        LOG(("Waiting until resume to do async not-modified [this=%p]\n",
-             this));
-        mPendingAsyncCallOnResume = &nsHttpChannel::HandleAsyncNotModified;
-        return;
-    }
-    
-    LOG(("nsHttpChannel::HandleAsyncNotModified [this=%p]\n", this));
-
-    DoNotifyListener();
-
-    CloseCacheEntry(PR_TRUE);
-
-    mIsPending = PR_FALSE;
-
-    if (mLoadGroup)
-        mLoadGroup->RemoveRequest(this, nsnull, mStatus);
-}
-
-void
-nsHttpChannel::HandleAsyncFallback()
-{
-    NS_PRECONDITION(!mPendingAsyncCallOnResume, "How did that happen?");
-
-    if (mSuspendCount) {
-        LOG(("Waiting until resume to do async fallback [this=%p]\n", this));
-        mPendingAsyncCallOnResume = &nsHttpChannel::HandleAsyncFallback;
-        return;
-    }
-
-    nsresult rv = NS_OK;
-
-    LOG(("nsHttpChannel::HandleAsyncFallback [this=%p]\n", this));
-
-    // since this event is handled asynchronously, it is possible that this
-    // channel could have been canceled, in which case there would be no point
-    // in processing the fallback.
-    if (!mCanceled) {
-        PRBool fallingBack;
-        rv = ProcessFallback(&fallingBack);
-        if (NS_FAILED(rv) || !fallingBack) {
-            // If ProcessFallback fails, then we have to send out the
-            // OnStart/OnStop notifications.
-            LOG(("ProcessFallback failed [rv=%x, %d]\n", rv, fallingBack));
-            mStatus = NS_FAILED(rv) ? rv : NS_ERROR_DOCUMENT_NOT_CACHED;
-            DoNotifyListener();
-        }
-    }
-
-    mIsPending = PR_FALSE;
-
-    if (mLoadGroup)
-        mLoadGroup->RemoveRequest(this, nsnull, mStatus);
-}
-
-nsresult
-nsHttpChannel::SetupTransaction()
-{
-    LOG(("nsHttpChannel::SetupTransaction [this=%p]\n", this));
-
-    NS_ENSURE_TRUE(!mTransaction, NS_ERROR_ALREADY_INITIALIZED);
-
-    nsresult rv;
-
-    if (mCaps & NS_HTTP_ALLOW_PIPELINING) {
-        //
-        // disable pipelining if:
-        //   (1) pipelining has been explicitly disabled
-        //   (2) request corresponds to a top-level document load (link click)
-        //   (3) request method is non-idempotent
-        //
-        // XXX does the toplevel document check really belong here?  or, should
-        //     we push it out entirely to necko consumers?
-        //
-        if (!mAllowPipelining || (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) ||
-            !(mRequestHead.Method() == nsHttp::Get ||
-              mRequestHead.Method() == nsHttp::Head ||
-              mRequestHead.Method() == nsHttp::Propfind ||
-              mRequestHead.Method() == nsHttp::Proppatch)) {
-            LOG(("  pipelining disallowed\n"));
-            mCaps &= ~NS_HTTP_ALLOW_PIPELINING;
-        }
-    }
-
-    // use the URI path if not proxying (transparent proxying such as SSL proxy
-    // does not count here). also, figure out what version we should be speaking.
-    nsCAutoString buf, path;
-    nsCString* requestURI;
-    if (mConnectionInfo->UsingSSL() || !mConnectionInfo->UsingHttpProxy()) {
-        rv = mURI->GetPath(path);
-        if (NS_FAILED(rv)) return rv;
-        // path may contain UTF-8 characters, so ensure that they're escaped.
-        if (NS_EscapeURL(path.get(), path.Length(), esc_OnlyNonASCII, buf))
-            requestURI = &buf;
-        else
-            requestURI = &path;
-        mRequestHead.SetVersion(gHttpHandler->HttpVersion());
-    }
-    else {
-        rv = mURI->GetUserPass(buf);
-        if (NS_FAILED(rv)) return rv;
-        if (!buf.IsEmpty() && ((strncmp(mSpec.get(), "http:", 5) == 0) ||
-                                strncmp(mSpec.get(), "https:", 6) == 0)) {
-            nsCOMPtr<nsIURI> tempURI;
-            rv = mURI->Clone(getter_AddRefs(tempURI));
-            if (NS_FAILED(rv)) return rv;
-            rv = tempURI->SetUserPass(EmptyCString());
-            if (NS_FAILED(rv)) return rv;
-            rv = tempURI->GetAsciiSpec(path);
-            if (NS_FAILED(rv)) return rv;
-            requestURI = &path;
-        }
-        else
-            requestURI = &mSpec;
-        mRequestHead.SetVersion(gHttpHandler->ProxyHttpVersion());
-    }
-
-    // trim off the #ref portion if any...
-    PRInt32 ref = requestURI->FindChar('#');
-    if (ref != kNotFound)
-        requestURI->SetLength(ref);
-
-    mRequestHead.SetRequestURI(*requestURI);
-
-    // set the request time for cache expiration calculations
-    mRequestTime = NowInSeconds();
-
-    // if doing a reload, force end-to-end
-    if (mLoadFlags & LOAD_BYPASS_CACHE) {
-        // We need to send 'Pragma:no-cache' to inhibit proxy caching even if
-        // no proxy is configured since we might be talking with a transparent
-        // proxy, i.e. one that operates at the network level.  See bug #14772.
-        mRequestHead.SetHeader(nsHttp::Pragma, NS_LITERAL_CSTRING("no-cache"), PR_TRUE);
-        // If we're configured to speak HTTP/1.1 then also send 'Cache-control:
-        // no-cache'
-        if (mRequestHead.Version() >= NS_HTTP_VERSION_1_1)
-            mRequestHead.SetHeader(nsHttp::Cache_Control, NS_LITERAL_CSTRING("no-cache"), PR_TRUE);
-    }
-    else if ((mLoadFlags & VALIDATE_ALWAYS) && (mCacheAccess & nsICache::ACCESS_READ)) {
-        // We need to send 'Cache-Control: max-age=0' to force each cache along
-        // the path to the origin server to revalidate its own entry, if any,
-        // with the next cache or server.  See bug #84847.
-        //
-        // If we're configured to speak HTTP/1.0 then just send 'Pragma: no-cache'
-        if (mRequestHead.Version() >= NS_HTTP_VERSION_1_1)
-            mRequestHead.SetHeader(nsHttp::Cache_Control, NS_LITERAL_CSTRING("max-age=0"), PR_TRUE);
-        else
-            mRequestHead.SetHeader(nsHttp::Pragma, NS_LITERAL_CSTRING("no-cache"), PR_TRUE);
-    }
-
-    if (mResuming) {
-        char byteRange[32];
-        PR_snprintf(byteRange, sizeof(byteRange), "bytes=%llu-", mStartPos);
-        mRequestHead.SetHeader(nsHttp::Range, nsDependentCString(byteRange));
-
-        if (!mEntityID.IsEmpty()) {
-            // Also, we want an error if this resource changed in the meantime
-            // Format of the entity id is: escaped_etag/size/lastmod
-            nsCString::const_iterator start, end, slash;
-            mEntityID.BeginReading(start);
-            mEntityID.EndReading(end);
-            mEntityID.BeginReading(slash);
-
-            if (FindCharInReadable('/', slash, end)) {
-                nsCAutoString ifMatch;
-                mRequestHead.SetHeader(nsHttp::If_Match,
-                        NS_UnescapeURL(Substring(start, slash), 0, ifMatch));
-
-                ++slash; // Incrementing, so that searching for '/' won't find
-                         // the same slash again
-            }
-
-            if (FindCharInReadable('/', slash, end)) {
-                mRequestHead.SetHeader(nsHttp::If_Unmodified_Since,
-                        Substring(++slash, end));
-            }
-        }
-    }
-
-    // create wrapper for this channel's notification callbacks
-    nsCOMPtr<nsIInterfaceRequestor> callbacks;
-    NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
-                                           getter_AddRefs(callbacks));
-    if (!callbacks)
-        return NS_ERROR_OUT_OF_MEMORY;
-
-    // create the transaction object
-    mTransaction = new nsHttpTransaction();
-    if (!mTransaction)
-        return NS_ERROR_OUT_OF_MEMORY;
-    NS_ADDREF(mTransaction);
-
-    // See bug #466080. Transfer LOAD_ANONYMOUS flag to socket-layer.
-    if (mLoadFlags & LOAD_ANONYMOUS)
-        mCaps |= NS_HTTP_LOAD_ANONYMOUS;
-
-    mConnectionInfo->SetAnonymous((mLoadFlags & LOAD_ANONYMOUS) != 0);
-
-    nsCOMPtr<nsIAsyncInputStream> responseStream;
-    rv = mTransaction->Init(mCaps, mConnectionInfo, &mRequestHead,
-                            mUploadStream, mUploadStreamHasHeaders,
-                            NS_GetCurrentThread(), callbacks, this,
-                            getter_AddRefs(responseStream));
-    if (NS_FAILED(rv)) {
-        NS_RELEASE(mTransaction);
-        return rv;
-    }
-
-    rv = nsInputStreamPump::Create(getter_AddRefs(mTransactionPump),
-                                   responseStream);
-    return rv;
-}
-
-void
-nsHttpChannel::AddCookiesToRequest()
-{
-    if (mLoadFlags & LOAD_ANONYMOUS) {
-      return;
-    }
-
-    nsXPIDLCString cookie;
-
-    nsICookieService *cs = gHttpHandler->GetCookieService();
-    if (cs)
-        cs->GetCookieStringFromHttp(mURI,
-                                    mDocumentURI ? mDocumentURI : mOriginalURI,
-                                    this,
-                                    getter_Copies(cookie));
-    if (cookie.IsEmpty())
-        cookie = mUserSetCookieHeader;
-    else if (!mUserSetCookieHeader.IsEmpty())
-        cookie.Append(NS_LITERAL_CSTRING("; ") + mUserSetCookieHeader);
-
-    // overwrite any existing cookie headers.  be sure to clear any
-    // existing cookies if we have no cookies to set or if the cookie
-    // service is unavailable.
-    mRequestHead.SetHeader(nsHttp::Cookie, cookie, PR_FALSE);
-}
-
-nsresult
-nsHttpChannel::ApplyContentConversions()
-{
-    if (!mResponseHead)
-        return NS_OK;
-
-    LOG(("nsHttpChannel::ApplyContentConversions [this=%p]\n", this));
-
-    if (!mApplyConversion) {
-        LOG(("not applying conversion per mApplyConversion\n"));
-        return NS_OK;
-    }
-
-    const char *val = mResponseHead->PeekHeader(nsHttp::Content_Encoding);
-    if (gHttpHandler->IsAcceptableEncoding(val)) {
-        nsCOMPtr<nsIStreamConverterService> serv;
-        nsresult rv = gHttpHandler->
-                GetStreamConverterService(getter_AddRefs(serv));
-        // we won't fail to load the page just because we couldn't load the
-        // stream converter service.. carry on..
-        if (NS_SUCCEEDED(rv)) {
-            nsCOMPtr<nsIStreamListener> converter;
-            nsCAutoString from(val);
-            ToLowerCase(from);
-            rv = serv->AsyncConvertData(from.get(),
-                                        "uncompressed",
-                                        mListener,
-                                        mListenerContext,
-                                        getter_AddRefs(converter));
-            if (NS_SUCCEEDED(rv)) {
-                LOG(("converter installed from \'%s\' to \'uncompressed\'\n", val));
-                mListener = converter;
-            }
-        }
-    } else if (val != nsnull) {
-        LOG(("Unknown content encoding '%s', ignoring\n", val));
-    }
-
     return NS_OK;
 }
 
-// NOTE: This function duplicates code from nsBaseChannel. This will go away
-// once HTTP uses nsBaseChannel (part of bug 312760)
-static void
-CallTypeSniffers(void *aClosure, const PRUint8 *aData, PRUint32 aCount)
+NS_IMETHODIMP
+nsHttpChannelAuthProvider::ProcessAuthentication(PRUint32 httpStatus,
+                                                 PRBool   SSLConnectFailed)
 {
-  nsIChannel *chan = static_cast<nsIChannel*>(aClosure);
-
-  const nsCOMArray<nsIContentSniffer>& sniffers =
-    gIOService->GetContentSniffers();
-  PRUint32 length = sniffers.Count();
-  for (PRUint32 i = 0; i < length; ++i) {
-    nsCAutoString newType;
-    nsresult rv =
-      sniffers[i]->GetMIMETypeFromContent(chan, aData, aCount, newType);
-    if (NS_SUCCEEDED(rv) && !newType.IsEmpty()) {
-      chan->SetContentType(newType);
-      break;
-    }
-  }
-}
-
-nsresult
-nsHttpChannel::CallOnStartRequest()
-{
-    mTracingEnabled = PR_FALSE;
+    LOG(("nsHttpChannelAuthProvider::ProcessAuthentication "
+         "[this=%p channel=%p code=%u SSLConnectFailed=%d]\n",
+         this, mAuthChannel, httpStatus, SSLConnectFailed));
 
-    if (mResponseHead && mResponseHead->ContentType().IsEmpty()) {
-        if (!mContentTypeHint.IsEmpty())
-            mResponseHead->SetContentType(mContentTypeHint);
-        else {
-            // Uh-oh.  We had better find out what type we are!
-
-            // XXX This does not work with content-encodings...  but
-            // neither does applying the conversion from the URILoader
+    NS_ASSERTION(mAuthChannel, "Channel not initialized");
 
-            nsCOMPtr<nsIStreamConverterService> serv;
-            nsresult rv = gHttpHandler->
-                GetStreamConverterService(getter_AddRefs(serv));
-            // If we failed, we just fall through to the "normal" case
-            if (NS_SUCCEEDED(rv)) {
-                nsCOMPtr<nsIStreamListener> converter;
-                rv = serv->AsyncConvertData(UNKNOWN_CONTENT_TYPE,
-                                            "*/*",
-                                            mListener,
-                                            mListenerContext,
-                                            getter_AddRefs(converter));
-                if (NS_SUCCEEDED(rv)) {
-                    mListener = converter;
-                }
-            }
-        }
+    nsCOMPtr<nsIProxyInfo> proxyInfo;
+    nsresult rv = mAuthChannel->GetProxyInfo(getter_AddRefs(proxyInfo));
+    if (NS_FAILED(rv)) return rv;
+    if (proxyInfo) {
+        mProxyInfo = do_QueryInterface(proxyInfo);
+        if (!mProxyInfo) return NS_ERROR_NO_INTERFACE;
     }
 
-    if (mResponseHead && mResponseHead->ContentCharset().IsEmpty())
-        mResponseHead->SetContentCharset(mContentCharsetHint);
-
-    if (mResponseHead)
-        SetPropertyAsInt64(NS_CHANNEL_PROP_CONTENT_LENGTH,
-                           mResponseHead->ContentLength());
-
-    // Allow consumers to override our content type
-    if ((mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS) &&
-        gIOService->GetContentSniffers().Count() != 0) {
-        // NOTE: We can have both a txn pump and a cache pump when the cache
-        // content is partial. In that case, we need to read from the cache,
-        // because that's the one that has the initial contents. If that fails
-        // then give the transaction pump a shot.
-
-        nsIChannel* thisChannel = static_cast<nsIChannel*>(this);
-
-        PRBool typeSniffersCalled = PR_FALSE;
-        if (mCachePump) {
-          typeSniffersCalled =
-            NS_SUCCEEDED(mCachePump->PeekStream(CallTypeSniffers, thisChannel));
-        }
-        
-        if (!typeSniffersCalled && mTransactionPump) {
-          mTransactionPump->PeekStream(CallTypeSniffers, thisChannel);
-        }
-    }
-
-    LOG(("  calling mListener->OnStartRequest\n"));
-    nsresult rv = mListener->OnStartRequest(this, mListenerContext);
-    if (NS_FAILED(rv)) return rv;
-
-    // install stream converter if required
-    rv = ApplyContentConversions();
+    PRUint32 loadFlags;
+    rv = mAuthChannel->GetLoadFlags(&loadFlags);
     if (NS_FAILED(rv)) return rv;
 
-    if (!mCanceled) {
-        // create offline cache entry if offline caching was requested
-        if (mCacheForOfflineUse) {
-            PRBool shouldCacheForOfflineUse;
-            rv = ShouldUpdateOfflineCacheEntry(&shouldCacheForOfflineUse);
-            if (NS_FAILED(rv)) return rv;
-            
-            if (shouldCacheForOfflineUse) {
-                LOG(("writing to the offline cache"));
-                rv = InitOfflineCacheEntry();
-                if (NS_FAILED(rv)) return rv;
-                
-                if (mOfflineCacheEntry) {
-                  rv = InstallOfflineCacheListener();
-                  if (NS_FAILED(rv)) return rv;
-                }
-            } else {
-                LOG(("offline cache is up to date, not updating"));
-                CloseOfflineCacheEntry();
-            }
-        }
+    if (loadFlags & nsIRequest::LOAD_ANONYMOUS) {
+        return NS_ERROR_NOT_AVAILABLE;
     }
 
-    return NS_OK;
-}
+    nsCAutoString challenges;
+    mProxyAuth = (httpStatus == 407);
 
-nsresult
-nsHttpChannel::ProcessFailedSSLConnect(PRUint32 httpStatus)
-{
-    // Failure to set up SSL proxy tunnel means one of the following:
-    // 1) Proxy wants authorization, or forbids.
-    // 2) DNS at proxy couldn't resolve target URL.
-    // 3) Proxy connection to target failed or timed out.
-    // 4) Eve noticed our proxy CONNECT, and is replying with malicious HTML.
-    // 
-    // Our current architecture will parse response content with the
-    // permission of the target URL!  Given #4, we must avoid rendering the
-    // body of the reply, and instead give the user a (hopefully helpful) 
-    // boilerplate error page, based on just the HTTP status of the reply.
+    rv = PrepareForAuthentication(mProxyAuth);
+    if (NS_FAILED(rv))
+        return rv;
 
-    NS_ABORT_IF_FALSE(mConnectionInfo->UsingSSL(),
-                      "SSL connect failed but not using SSL?");
-    nsresult rv;
-    switch (httpStatus) 
-    {
-    case 300: case 301: case 302: case 303: case 307:
-        // Bad redirect: not top-level, or it's a POST, bad/missing Location,
-        // or ProcessRedirect() failed for some other reason.  Legal
-        // redirects that fail because site not available, etc., are handled
-        // elsewhere, in the regular codepath.
-        rv = NS_ERROR_CONNECTION_REFUSED;
-        break;
-    case 403: // HTTP/1.1: "Forbidden"
-    case 407: // ProcessAuthentication() failed
-    case 501: // HTTP/1.1: "Not Implemented"
-        // user sees boilerplate Mozilla "Proxy Refused Connection" page.
-        rv = NS_ERROR_PROXY_CONNECTION_REFUSED; 
-        break;
-    // Squid sends 404 if DNS fails (regular 404 from target is tunneled)
-    case 404: // HTTP/1.1: "Not Found"
-    // RFC 2616: "some deployed proxies are known to return 400 or 500 when
-    // DNS lookups time out."  (Squid uses 500 if it runs out of sockets: so
-    // we have a conflict here).
-    case 400: // HTTP/1.1 "Bad Request"
-    case 500: // HTTP/1.1: "Internal Server Error"
-        /* User sees: "Address Not Found: Firefox can't find the server at
-         * www.foo.com."
-         */
-        rv = NS_ERROR_UNKNOWN_HOST; 
-        break;
-    case 502: // HTTP/1.1: "Bad Gateway" (invalid resp from target server)
-    // Squid returns 503 if target request fails for anything but DNS.
-    case 503: // HTTP/1.1: "Service Unavailable"
-        /* User sees: "Failed to Connect:
-         *  Firefox can't establish a connection to the server at
-         *  www.foo.com.  Though the site seems valid, the browser
-         *  was unable to establish a connection."
-         */
-        rv = NS_ERROR_CONNECTION_REFUSED;
-        break;
-    // RFC 2616 uses 504 for both DNS and target timeout, so not clear what to
-    // do here: picking target timeout, as DNS covered by 400/404/500
-    case 504: // HTTP/1.1: "Gateway Timeout" 
-        // user sees: "Network Timeout: The server at www.foo.com
-        //              is taking too long to respond."
-        rv = NS_ERROR_NET_TIMEOUT;
-        break;
-    // Confused proxy server or malicious response
-    default:
-        rv = NS_ERROR_PROXY_CONNECTION_REFUSED; 
-        break;
+    if (mProxyAuth) {
+        // only allow a proxy challenge if we have a proxy server configured.
+        // otherwise, we could inadvertantly expose the user's proxy
+        // credentials to an origin server.  We could attempt to proceed as
+        // if we had received a 401 from the server, but why risk flirting
+        // with trouble?  IE similarly rejects 407s when a proxy server is
+        // not configured, so there's no reason not to do the same.
+        if (!UsingHttpProxy()) {
+            LOG(("rejecting 407 when proxy server not configured!\n"));
+            return NS_ERROR_UNEXPECTED;
+        }
+        if (UsingSSL() && !SSLConnectFailed) {
+            // we need to verify that this challenge came from the proxy
+            // server itself, and not some server on the other side of the
+            // SSL tunnel.
+            LOG(("rejecting 407 from origin server!\n"));
+            return NS_ERROR_UNEXPECTED;
+        }
+        rv = mAuthChannel->GetProxyChallenges(challenges);
     }
-    LOG(("Cancelling failed SSL proxy connection [this=%p httpStatus=%u]\n",
-         this, httpStatus)); 
-    Cancel(rv);
-    CallOnStartRequest();
+    else
+        rv = mAuthChannel->GetWWWChallenges(challenges);
+    if (NS_FAILED(rv)) return rv;
+
+    nsCAutoString creds;
+    rv = GetCredentials(challenges.get(), mProxyAuth, creds);
+    if (rv == NS_ERROR_IN_PROGRESS)
+        return rv;
+    if (NS_FAILED(rv))
+        LOG(("unable to authenticate\n"));
+    else {
+        // set the authentication credentials
+        if (mProxyAuth)
+            rv = mAuthChannel->SetProxyCredentials(creds);
+        else
+            rv = mAuthChannel->SetWWWCredentials(creds);
+    }
     return rv;
 }
 
-PRBool
-nsHttpChannel::ShouldSSLProxyResponseContinue(PRUint32 httpStatus)
+NS_IMETHODIMP
+nsHttpChannelAuthProvider::AddAuthorizationHeaders()
 {
-    // When SSL connect has failed, allow proxy reply to continue only if it's
-    // an auth request, or a redirect of a non-POST top-level document load.
-    switch (httpStatus) {
-    case 407:
-        return PR_TRUE;
-    case 300: case 301: case 302: case 303: case 307:
-      {
-        return ( (mLoadFlags & nsIChannel::LOAD_DOCUMENT_URI) &&
-                 mURI == mDocumentURI &&
-                 mRequestHead.Method() != nsHttp::Post);
-      }
-    }
-    return PR_FALSE;
-}
-
-nsresult
-nsHttpChannel::ProcessResponse()
-{
-    nsresult rv;
-    PRUint32 httpStatus = mResponseHead->Status();
+    LOG(("nsHttpChannelAuthProvider::AddAuthorizationHeaders? "
+         "[this=%p channel=%p]\n", this, mAuthChannel));
 
-    LOG(("nsHttpChannel::ProcessResponse [this=%p httpStatus=%u]\n",
-        this, httpStatus));
-
-    if (mTransaction->SSLConnectFailed() &&
-        !ShouldSSLProxyResponseContinue(httpStatus))
-        return ProcessFailedSSLConnect(httpStatus);
-
-    // notify "http-on-examine-response" observers
-    gHttpHandler->OnExamineResponse(this);
+    NS_ASSERTION(mAuthChannel, "Channel not initialized");
 
-    // set cookies, if any exist; done after OnExamineResponse to allow those
-    // observers to modify the cookie response headers
-    SetCookie(mResponseHead->PeekHeader(nsHttp::Set_Cookie));
-
-    // handle unused username and password in url (see bug 232567)
-    if (httpStatus != 401 && httpStatus != 407) {
-        CheckForSuperfluousAuth();
-        if (mCanceled)
-            return CallOnStartRequest();
-
-        if (mAuthContinuationState) {
-            // reset the current continuation state because our last
-            // authentication attempt has been completed successfully
-            NS_RELEASE(mAuthContinuationState);
-            LOG(("  continuation state has been reset"));
-        }
+    nsCOMPtr<nsIProxyInfo> proxyInfo;
+    nsresult rv = mAuthChannel->GetProxyInfo(getter_AddRefs(proxyInfo));
+    if (NS_FAILED(rv)) return rv;
+    if (proxyInfo) {
+        mProxyInfo = do_QueryInterface(proxyInfo);
+        if (!mProxyInfo) return NS_ERROR_NO_INTERFACE;
     }
 
-    // handle different server response categories.  Note that we handle
-    // caching or not caching of error pages in
-    // nsHttpResponseHead::MustValidate; if you change this switch, update that
-    // one
-    switch (httpStatus) {
-    case 200:
-    case 203:
-        // Per RFC 2616, 14.35.2, "A server MAY ignore the Range header".
-        // So if a server does that and sends 200 instead of 206 that we
-        // expect, notify our caller.
-        // However, if we wanted to start from the beginning, let it go through
-        if (mResuming && mStartPos != 0) {
-            LOG(("Server ignored our Range header, cancelling [this=%p]\n", this));
-            Cancel(NS_ERROR_NOT_RESUMABLE);
-            rv = CallOnStartRequest();
-            break;
-        }
-        // these can normally be cached
-        rv = ProcessNormal();
-        MaybeInvalidateCacheEntryForSubsequentGet();
-        break;
-    case 206:
-        if (mCachedContentIsPartial) // an internal byte range request...
-            rv = ProcessPartialContent();
-        else
-            rv = ProcessNormal();
-        break;
-    case 300:
-    case 301:
-    case 302:
-    case 307:
-    case 303:
-#if 0
-    case 305: // disabled as a security measure (see bug 187996).
-#endif
-        // don't store the response body for redirects
-        MaybeInvalidateCacheEntryForSubsequentGet();
-        rv = ProcessRedirection(httpStatus);
-        if (NS_SUCCEEDED(rv)) {
-            InitCacheEntry();
-            CloseCacheEntry(PR_FALSE);
+    PRUint32 loadFlags;
+    rv = mAuthChannel->GetLoadFlags(&loadFlags);
+    if (NS_FAILED(rv)) return rv;
 
-            if (mCacheForOfflineUse) {
-                // Store response in the offline cache
-                InitOfflineCacheEntry();
-                CloseOfflineCacheEntry();
-            }
-        }    
-        else {
-            LOG(("ProcessRedirection failed [rv=%x]\n", rv));
-            if (mTransaction->SSLConnectFailed())
-                return ProcessFailedSSLConnect(httpStatus);
-            rv = ProcessNormal();
-        }
-        break;
-    case 304:
-        rv = ProcessNotModified();
-        if (NS_FAILED(rv)) {
-            LOG(("ProcessNotModified failed [rv=%x]\n", rv));
-            rv = ProcessNormal();
-        }
-        break;
-    case 401:
-    case 407:
-        rv = ProcessAuthentication(httpStatus);
-        if (NS_FAILED(rv)) {
-            LOG(("ProcessAuthentication failed [rv=%x]\n", rv));
-            if (mTransaction->SSLConnectFailed())
-                return ProcessFailedSSLConnect(httpStatus);
-            CheckForSuperfluousAuth();
-            rv = ProcessNormal();
-        }
-        break;
-    default:
-        rv = ProcessNormal();
-        MaybeInvalidateCacheEntryForSubsequentGet();
-        break;
+    if (loadFlags & nsIRequest::LOAD_ANONYMOUS) {
+        return NS_OK;
     }
 
-    return rv;
-}
-
-nsresult
-nsHttpChannel::ProcessNormal()
-{
-    nsresult rv;
-
-    LOG(("nsHttpChannel::ProcessNormal [this=%p]\n", this));
+    // this getter never fails
+    nsHttpAuthCache *authCache = gHttpHandler->AuthCache();
 
-    PRBool succeeded;
-    rv = GetRequestSucceeded(&succeeded);
-    if (NS_SUCCEEDED(rv) && !succeeded) {
-        PRBool fallingBack;
-        rv = ProcessFallback(&fallingBack);
-        if (NS_FAILED(rv)) {
-            DoNotifyListener();
-            return rv;
-        }
-
-        if (fallingBack) {
-            // Do not continue with normal processing, fallback is in
-            // progress now.
-            return NS_OK;
-        }
-    }
-
-    // if we're here, then any byte-range requests failed to result in a partial
-    // response.  we must clear this flag to prevent BufferPartialContent from
-    // being called inside our OnDataAvailable (see bug 136678).
-    mCachedContentIsPartial = PR_FALSE;
-
-    ClearBogusContentEncodingIfNeeded();
+    // check if proxy credentials should be sent
+    const char *proxyHost = ProxyHost();
+    if (proxyHost && UsingHttpProxy())
+        SetAuthorizationHeader(authCache, nsHttp::Proxy_Authorization,
+                               "http", proxyHost, ProxyPort(),
+                               nsnull, // proxy has no path
+                               mProxyIdent);
 
-    // this must be called before firing OnStartRequest, since http clients,
-    // such as imagelib, expect our cache entry to already have the correct
-    // expiration time (bug 87710).
-    if (mCacheEntry) {
-        rv = InitCacheEntry();
-        if (NS_FAILED(rv))
-            CloseCacheEntry(PR_TRUE);
-    }
-
-    // Check that the server sent us what we were asking for
-    if (mResuming) {
-        // Create an entity id from the response
-        nsCAutoString id;
-        rv = GetEntityID(id);
-        if (NS_FAILED(rv)) {
-            // If creating an entity id is not possible -> error
-            Cancel(NS_ERROR_NOT_RESUMABLE);
-        }
-        else if (mResponseHead->Status() != 206 &&
-                 mResponseHead->Status() != 200) {
-            // Probably 404 Not Found, 412 Precondition Failed or
-            // 416 Invalid Range -> error
-            LOG(("Unexpected response status while resuming, aborting [this=%p]\n",
-                 this));
-            Cancel(NS_ERROR_ENTITY_CHANGED);
-        }
-        // If we were passed an entity id, verify it's equal to the server's
-        else if (!mEntityID.IsEmpty()) {
-            if (!mEntityID.Equals(id)) {
-                LOG(("Entity mismatch, expected '%s', got '%s', aborting [this=%p]",
-                     mEntityID.get(), id.get(), this));
-                Cancel(NS_ERROR_ENTITY_CHANGED);
-            }
-        }
-    }
-
-    rv = CallOnStartRequest();
-    if (NS_FAILED(rv)) return rv;
-
-    // install cache listener if we still have a cache entry open
-    if (mCacheEntry && (mCacheAccess & nsICache::ACCESS_WRITE)) {
-        rv = InstallCacheListener();
-        if (NS_FAILED(rv)) return rv;
+    // check if server credentials should be sent
+    nsCAutoString path, scheme;
+    if (NS_SUCCEEDED(GetCurrentPath(path)) &&
+        NS_SUCCEEDED(mURI->GetScheme(scheme))) {
+        SetAuthorizationHeader(authCache, nsHttp::Authorization,
+                               scheme.get(),
+                               Host(),
+                               Port(),
+                               path.get(),
+                               mIdent);
     }
 
     return NS_OK;
 }
 
-nsresult
-nsHttpChannel::PromptTempRedirect()
-{
-    if (!gHttpHandler->PromptTempRedirect()) {
-        return NS_OK;
-    }
-    nsresult rv;
-    nsCOMPtr<nsIStringBundleService> bundleService =
-            do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
-    if (NS_FAILED(rv)) return rv;
-
-    nsCOMPtr<nsIStringBundle> stringBundle;
-    rv = bundleService->CreateBundle(NECKO_MSGS_URL, getter_AddRefs(stringBundle));
-    if (NS_FAILED(rv)) return rv;
-
-    nsXPIDLString messageString;
-    rv = stringBundle->GetStringFromName(NS_LITERAL_STRING("RepostFormData").get(), getter_Copies(messageString));
-    // GetStringFromName can return NS_OK and NULL messageString.
-    if (NS_SUCCEEDED(rv) && messageString) {
-        PRBool repost = PR_FALSE;
-
-        nsCOMPtr<nsIPrompt> prompt;
-        GetCallback(prompt);
-        if (!prompt)
-            return NS_ERROR_NO_INTERFACE;
-
-        prompt->Confirm(nsnull, messageString, &repost);
-        if (!repost)
-            return NS_ERROR_FAILURE;
-    }
-
-    return rv;
-}
-
-nsresult
-nsHttpChannel::ProxyFailover()
-{
-    LOG(("nsHttpChannel::ProxyFailover [this=%p]\n", this));
-
-    nsresult rv;
-
-    nsCOMPtr<nsIProtocolProxyService> pps =
-            do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &rv);
-    if (NS_FAILED(rv))
-        return rv;
-
-    nsCOMPtr<nsIProxyInfo> pi;
-    rv = pps->GetFailoverForProxy(mConnectionInfo->ProxyInfo(), mURI, mStatus,
-                                  getter_AddRefs(pi));
-    if (NS_FAILED(rv))
-        return rv;
-
-    // XXXbz so where does this codepath remove us from the loadgroup,
-    // exactly?
-    return DoReplaceWithProxy(pi);
-}
-
-void
-nsHttpChannel::HandleAsyncReplaceWithProxy()
-{
-    NS_PRECONDITION(!mPendingAsyncCallOnResume, "How did that happen?");
-
-    if (mSuspendCount) {
-        LOG(("Waiting until resume to do async proxy replacement [this=%p]\n",
-             this));
-        mPendingAsyncCallOnResume =
-            &nsHttpChannel::HandleAsyncReplaceWithProxy;
-        return;
-    }
-
-    nsresult status = mStatus;
-    
-    nsCOMPtr<nsIProxyInfo> pi;
-    pi.swap(mTargetProxyInfo);
-    if (!mCanceled) {
-        status = DoReplaceWithProxy(pi);
-        if (mLoadGroup && NS_SUCCEEDED(status)) {
-            mLoadGroup->RemoveRequest(this, nsnull, mStatus);
-        }
-    }
-
-    if (NS_FAILED(status)) {
-        AsyncAbort(status);
-    }
-}
-
-nsresult
-nsHttpChannel::DoReplaceWithProxy(nsIProxyInfo* pi)
-{
-    LOG(("nsHttpChannel::DoReplaceWithProxy [this=%p pi=%p]", this, pi));
-    nsresult rv;
-
-    nsCOMPtr<nsIChannel> newChannel;
-    rv = gHttpHandler->NewProxiedChannel(mURI, pi, getter_AddRefs(newChannel));
-    if (NS_FAILED(rv))
-        return rv;
-
-    rv = SetupReplacementChannel(mURI, newChannel, PR_TRUE);
-    if (NS_FAILED(rv))
-        return rv;
-
-    // Inform consumers about this fake redirect
-    PRUint32 flags = nsIChannelEventSink::REDIRECT_INTERNAL;
-    rv = gHttpHandler->OnChannelRedirect(this, newChannel, flags);
-    if (NS_FAILED(rv))
-        return rv;
-
-    // Make sure to do this _after_ calling OnChannelRedirect
-    newChannel->SetOriginalURI(mOriginalURI);
-
-    // open new channel
-    rv = newChannel->AsyncOpen(mListener, mListenerContext);
-    if (NS_FAILED(rv))
-        return rv;
-
-    mStatus = NS_BINDING_REDIRECTED;
-
-    // disconnect from the old listeners...
-    mListener = nsnull;
-    mListenerContext = nsnull;
-
-    // ...and the old callbacks
-    mCallbacks = nsnull;
-    mProgressSink = nsnull;
-
-    return rv;
-}
-
-nsresult
-nsHttpChannel::ResolveProxy()
-{
-    LOG(("nsHttpChannel::ResolveProxy [this=%p]\n", this));
-
-    nsresult rv;
-
-    nsCOMPtr<nsIProtocolProxyService> pps =
-            do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &rv);
-    if (NS_FAILED(rv))
-        return rv;
-
-    return pps->AsyncResolve(mURI, 0, this, getter_AddRefs(mProxyRequest));
-}
-
-PRBool
-nsHttpChannel::ResponseWouldVary()
+NS_IMETHODIMP
+nsHttpChannelAuthProvider::CheckForSuperfluousAuth()
 {
-    PRBool result = PR_FALSE;
-    nsCAutoString buf, metaKey;
-    mCachedResponseHead->GetHeader(nsHttp::Vary, buf);
-    if (!buf.IsEmpty()) {
-        NS_NAMED_LITERAL_CSTRING(prefix, "request-");
-
-        // enumerate the elements of the Vary header...
-        char *val = buf.BeginWriting(); // going to munge buf
-        char *token = nsCRT::strtok(val, NS_HTTP_HEADER_SEPS, &val);
-        while (token) {
-            //
-            // if "*", then assume response would vary.  technically speaking,
-            // "Vary: header, *" is not permitted, but we allow it anyways.
-            //
-            // if the response depends on the value of the "Cookie" header, then
-            // bail since we do not store cookies in the cache.  this is done
-            // for the following reasons:
-            //
-            //   1- cookies can be very large in size
-            //
-            //   2- cookies may contain sensitive information.  (for parity with
-            //      out policy of not storing Set-cookie headers in the cache
-            //      meta data, we likewise do not want to store cookie headers
-            //      here.)
-            //
-            // this implementation is obviously not fully standards compliant, but
-            // it is perhaps most prudent given the above issues.
-            //
-            if ((*token == '*') || (PL_strcasecmp(token, "cookie") == 0)) {
-                result = PR_TRUE;
-                break;
-            }
-            else {
-                // build cache meta data key...
-                metaKey = prefix + nsDependentCString(token);
-
-                // check the last value of the given request header to see if it has
-                // since changed.  if so, then indeed the cached response is invalid.
-                nsXPIDLCString lastVal;
-                mCacheEntry->GetMetaDataElement(metaKey.get(), getter_Copies(lastVal));
-                if (lastVal) {
-                    nsHttpAtom atom = nsHttp::ResolveAtom(token);
-                    const char *newVal = mRequestHead.PeekHeader(atom);
-                    if (newVal && (strcmp(newVal, lastVal) != 0)) {
-                        result = PR_TRUE; // yes, response would vary
-                        break;
-                    }
-                }
-                
-                // next token...
-                token = nsCRT::strtok(val, NS_HTTP_HEADER_SEPS, &val);
-            }
-        }
-    }
-    return result;
-}
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel <byte-range>
-//-----------------------------------------------------------------------------
-
-nsresult
-nsHttpChannel::SetupByteRangeRequest(PRUint32 partialLen)
-{
-    // cached content has been found to be partial, add necessary request
-    // headers to complete cache entry.
-
-    // use strongest validator available...
-    const char *val = mCachedResponseHead->PeekHeader(nsHttp::ETag);
-    if (!val)
-        val = mCachedResponseHead->PeekHeader(nsHttp::Last_Modified);
-    if (!val) {
-        // if we hit this code it means mCachedResponseHead->IsResumable() is
-        // either broken or not being called.
-        NS_NOTREACHED("no cache validator");
-        return NS_ERROR_FAILURE;
-    }
-
-    char buf[32];
-    PR_snprintf(buf, sizeof(buf), "bytes=%u-", partialLen);
-
-    mRequestHead.SetHeader(nsHttp::Range, nsDependentCString(buf));
-    mRequestHead.SetHeader(nsHttp::If_Range, nsDependentCString(val));
-
-    return NS_OK;
-}
-
-nsresult
-nsHttpChannel::ProcessPartialContent()
-{
-    // ok, we've just received a 206
-    //
-    // we need to stream whatever data is in the cache out first, and then
-    // pick up whatever data is on the wire, writing it into the cache.
-
-    LOG(("nsHttpChannel::ProcessPartialContent [this=%p]\n", this)); 
-
-    NS_ENSURE_TRUE(mCachedResponseHead, NS_ERROR_NOT_INITIALIZED);
-    NS_ENSURE_TRUE(mCacheEntry, NS_ERROR_NOT_INITIALIZED);
-
-    // Make sure to clear bogus content-encodings before looking at the header
-    ClearBogusContentEncodingIfNeeded();
-    
-    // Check if the content-encoding we now got is different from the one we
-    // got before
-    if (PL_strcasecmp(mResponseHead->PeekHeader(nsHttp::Content_Encoding),
-                      mCachedResponseHead->PeekHeader(nsHttp::Content_Encoding))
-                      != 0) {
-        Cancel(NS_ERROR_INVALID_CONTENT_ENCODING);
-        return CallOnStartRequest();
-    }
-
-
-    // suspend the current transaction
-    nsresult rv = mTransactionPump->Suspend();
-    if (NS_FAILED(rv)) return rv;
-
-    // merge any new headers with the cached response headers
-    rv = mCachedResponseHead->UpdateHeaders(mResponseHead->Headers());
-    if (NS_FAILED(rv)) return rv;
-
-    // update the cached response head
-    nsCAutoString head;
-    mCachedResponseHead->Flatten(head, PR_TRUE);
-    rv = mCacheEntry->SetMetaDataElement("response-head", head.get());
-    if (NS_FAILED(rv)) return rv;
-
-    // make the cached response be the current response
-    delete mResponseHead;
-    mResponseHead = mCachedResponseHead;
-    mCachedResponseHead = 0;
-
-    rv = UpdateExpirationTime();
-    if (NS_FAILED(rv)) return rv;
-
-    // notify observers interested in looking at a response that has been
-    // merged with any cached headers (http-on-examine-merged-response).
-    gHttpHandler->OnExamineMergedResponse(this);
-
-    // the cached content is valid, although incomplete.
-    mCachedContentIsValid = PR_TRUE;
-    return ReadFromCache();
-}
-
-nsresult
-nsHttpChannel::OnDoneReadingPartialCacheEntry(PRBool *streamDone)
-{
-    nsresult rv;
-
-    LOG(("nsHttpChannel::OnDoneReadingPartialCacheEntry [this=%p]", this));
-
-    // by default, assume we would have streamed all data or failed...
-    *streamDone = PR_TRUE;
-
-    // setup cache listener to append to cache entry
-    PRUint32 size;
-    rv = mCacheEntry->GetDataSize(&size);
-    if (NS_FAILED(rv)) return rv;
-
-    rv = InstallCacheListener(size);
-    if (NS_FAILED(rv)) return rv;
-
-    // need to track the logical offset of the data being sent to our listener
-    mLogicalOffset = size;
-
-    // we're now completing the cached content, so we can clear this flag.
-    // this puts us in the state of a regular download.
-    mCachedContentIsPartial = PR_FALSE;
-
-    // resume the transaction if it exists, otherwise the pipe contained the
-    // remaining part of the document and we've now streamed all of the data.
-    if (mTransactionPump) {
-        rv = mTransactionPump->Resume();
-        if (NS_SUCCEEDED(rv))
-            *streamDone = PR_FALSE;
-    }
-    else
-        NS_NOTREACHED("no transaction");
-    return rv;
-}
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel <cache>
-//-----------------------------------------------------------------------------
-
-nsresult
-nsHttpChannel::ProcessNotModified()
-{
-    nsresult rv;
-
-    LOG(("nsHttpChannel::ProcessNotModified [this=%p]\n", this)); 
-
-    if (mCustomConditionalRequest) {
-        LOG(("Bypassing ProcessNotModified due to custom conditional headers")); 
-        return NS_ERROR_FAILURE;
-    }
-
-    NS_ENSURE_TRUE(mCachedResponseHead, NS_ERROR_NOT_INITIALIZED);
-    NS_ENSURE_TRUE(mCacheEntry, NS_ERROR_NOT_INITIALIZED);
-
-    // merge any new headers with the cached response headers
-    rv = mCachedResponseHead->UpdateHeaders(mResponseHead->Headers());
-    if (NS_FAILED(rv)) return rv;
-
-    // update the cached response head
-    nsCAutoString head;
-    mCachedResponseHead->Flatten(head, PR_TRUE);
-    rv = mCacheEntry->SetMetaDataElement("response-head", head.get());
-    if (NS_FAILED(rv)) return rv;
-
-    // make the cached response be the current response
-    delete mResponseHead;
-    mResponseHead = mCachedResponseHead;
-    mCachedResponseHead = 0;
-
-    rv = UpdateExpirationTime();
-    if (NS_FAILED(rv)) return rv;
-
-    // notify observers interested in looking at a reponse that has been
-    // merged with any cached headers
-    gHttpHandler->OnExamineMergedResponse(this);
-
-    mCachedContentIsValid = PR_TRUE;
-    rv = ReadFromCache();
-    if (NS_FAILED(rv)) return rv;
+    LOG(("nsHttpChannelAuthProvider::CheckForSuperfluousAuth? "
+         "[this=%p channel=%p]\n", this, mAuthChannel));
 
-    mTransactionReplaced = PR_TRUE;
-    return NS_OK;
-}
-
-nsresult
-nsHttpChannel::ProcessFallback(PRBool *fallingBack)
-{
-    LOG(("nsHttpChannel::ProcessFallback [this=%p]\n", this));
-    nsresult rv;
-
-    *fallingBack = PR_FALSE;
-
-    // At this point a load has failed (either due to network problems
-    // or an error returned on the server).  Perform an application
-    // cache fallback if we have a URI to fall back to.
-    if (!mApplicationCache || mFallbackKey.IsEmpty() || mFallbackChannel) {
-        LOG(("  choosing not to fallback [%p,%s,%d]",
-             mApplicationCache.get(), mFallbackKey.get(), mFallbackChannel));
-        return NS_OK;
-    }
-
-    // Make sure the fallback entry hasn't been marked as a foreign
-    // entry.
-    PRUint32 fallbackEntryType;
-    rv = mApplicationCache->GetTypes(mFallbackKey, &fallbackEntryType);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    if (fallbackEntryType & nsIApplicationCache::ITEM_FOREIGN) {
-        // This cache points to a fallback that refers to a different
-        // manifest.  Refuse to fall back.
-        return NS_OK;
-    }
-
-    NS_ASSERTION(fallbackEntryType & nsIApplicationCache::ITEM_FALLBACK,
-                 "Fallback entry not marked correctly!");
-
-    // Kill any opportunistic cache entry, and disable opportunistic
-    // caching for the fallback.
-    if (mOfflineCacheEntry) {
-        mOfflineCacheEntry->Doom();
-        mOfflineCacheEntry = 0;
-        mOfflineCacheAccess = 0;
-    }
-
-    mCacheForOfflineUse = PR_FALSE;
-    mCachingOpportunistically = PR_FALSE;
-    mOfflineCacheClientID.Truncate();
-    mOfflineCacheEntry = 0;
-    mOfflineCacheAccess = 0;
-
-    // Close the current cache entry.
-    if (mCacheEntry)
-        CloseCacheEntry(PR_TRUE);
-
-    // Create a new channel to load the fallback entry.
-    nsRefPtr<nsIChannel> newChannel;
-    rv = gHttpHandler->NewChannel(mURI, getter_AddRefs(newChannel));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = SetupReplacementChannel(mURI, newChannel, PR_TRUE);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    // Make sure the new channel loads from the fallback key.
-    nsCOMPtr<nsIHttpChannelInternal> httpInternal =
-        do_QueryInterface(newChannel, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = httpInternal->SetupFallbackChannel(mFallbackKey.get());
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    // ... and fallbacks should only load from the cache.
-    PRUint32 newLoadFlags = mLoadFlags | LOAD_REPLACE | LOAD_ONLY_FROM_CACHE;
-    rv = newChannel->SetLoadFlags(newLoadFlags);
-
-    // Inform consumers about this fake redirect
-    PRUint32 redirectFlags = nsIChannelEventSink::REDIRECT_INTERNAL;
-    rv = gHttpHandler->OnChannelRedirect(this, newChannel, redirectFlags);
-    if (NS_FAILED(rv))
-        return rv;
-
-    // Make sure to do this _after_ calling OnChannelRedirect
-    newChannel->SetOriginalURI(mOriginalURI);
-    
-    rv = newChannel->AsyncOpen(mListener, mListenerContext);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    // close down this channel
-    Cancel(NS_BINDING_REDIRECTED);
-
-    // disconnect from our listener
-    mListener = 0;
-    mListenerContext = 0;
-    // and from our callbacks
-    mCallbacks = nsnull;
-    mProgressSink = nsnull;
-
-    *fallingBack = PR_TRUE;
-
-    return NS_OK;
-}
-
-// Determines if a request is a byte range request for a subrange,
-// i.e. is a byte range request, but not a 0- byte range request.
-static PRBool
-IsSubRangeRequest(nsHttpRequestHead &aRequestHead)
-{
-    if (!aRequestHead.PeekHeader(nsHttp::Range))
-        return PR_FALSE;
-    nsCAutoString byteRange;
-    aRequestHead.GetHeader(nsHttp::Range, byteRange);
-    return !byteRange.EqualsLiteral("bytes=0-");
-}
-
-nsresult
-nsHttpChannel::OpenCacheEntry(PRBool offline, PRBool *delayed)
-{
-    nsresult rv;
-
-    *delayed = PR_FALSE;
-    mLoadedFromApplicationCache = PR_FALSE;
-
-    LOG(("nsHttpChannel::OpenCacheEntry [this=%p]", this));
-
-    // make sure we're not abusing this function
-    NS_PRECONDITION(!mCacheEntry, "cache entry already open");
-
-    nsCAutoString cacheKey;
-
-    if (mRequestHead.Method() == nsHttp::Post) {
-        // If the post id is already set then this is an attempt to replay
-        // a post transaction via the cache.  Otherwise, we need a unique
-        // post id for this transaction.
-        if (mPostID == 0)
-            mPostID = gHttpHandler->GenerateUniqueID();
-    }
-    else if ((mRequestHead.Method() != nsHttp::Get) &&
-             (mRequestHead.Method() != nsHttp::Head)) {
-        // don't use the cache for other types of requests
-        return NS_OK;
-    }
-
-    if (mResuming) {
-        // We don't support caching for requests initiated
-        // via nsIResumableChannel.
-        return NS_OK;
-    }
-
-    // Don't cache byte range requests which are subranges, only cache 0-
-    // byte range requests.
-    if (IsSubRangeRequest(mRequestHead))
-        return NS_OK;
-
-    GenerateCacheKey(mPostID, cacheKey);
-
-    // Get a cache session with appropriate storage policy
-    nsCacheStoragePolicy storagePolicy = DetermineStoragePolicy();
-
-    // Set the desired cache access mode accordingly...
-    nsCacheAccessMode accessRequested;
-    if (offline || (mLoadFlags & INHIBIT_CACHING)) {
-        // If we have been asked to bypass the cache and not write to the
-        // cache, then don't use the cache at all.  Unless we're actually
-        // offline, which takes precedence over BYPASS_LOCAL_CACHE.
-        if (BYPASS_LOCAL_CACHE(mLoadFlags) && !offline)
-            return NS_ERROR_NOT_AVAILABLE;
-        accessRequested = nsICache::ACCESS_READ;
-    }
-    else if (BYPASS_LOCAL_CACHE(mLoadFlags))
-        accessRequested = nsICache::ACCESS_WRITE; // replace cache entry
-    else
-        accessRequested = nsICache::ACCESS_READ_WRITE; // normal browsing
-
-    if (!mApplicationCache && mInheritApplicationCache) {
-        // Pick up an application cache from the notification
-        // callbacks if available
-        nsCOMPtr<nsIApplicationCacheContainer> appCacheContainer;
-        GetCallback(appCacheContainer);
-
-        if (appCacheContainer) {
-            appCacheContainer->GetApplicationCache(getter_AddRefs(mApplicationCache));
-        }
-    }
-
-    if (!mApplicationCache &&
-        (mChooseApplicationCache || (mLoadFlags & LOAD_CHECK_OFFLINE_CACHE))) {
-        // We're supposed to load from an application cache, but
-        // one was not supplied by the load group.  Ask the
-        // application cache service to choose one for us.
-        nsCOMPtr<nsIApplicationCacheService> appCacheService =
-            do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID);
-        if (appCacheService) {
-            nsresult rv = appCacheService->ChooseApplicationCache
-                (cacheKey, getter_AddRefs(mApplicationCache));
-            NS_ENSURE_SUCCESS(rv, rv);
-        }
-    }
-
-    nsCOMPtr<nsICacheSession> session;
-
-    // Will be set to true if we've found the right session, but need
-    // to open the cache entry asynchronously.
-    PRBool waitingForValidation = PR_FALSE;
-
-    // If we have an application cache, we check it first.
-    if (mApplicationCache) {
-        nsCAutoString appCacheClientID;
-        mApplicationCache->GetClientID(appCacheClientID);
-
-        nsCOMPtr<nsICacheService> serv =
-            do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        rv = serv->CreateSession(appCacheClientID.get(),
-                                 nsICache::STORE_OFFLINE,
-                                 nsICache::STREAM_BASED,
-                                 getter_AddRefs(session));
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        // we'll try to synchronously open the cache entry... however,
-        // it may be in use and not yet validated, in which case we'll
-        // try asynchronously opening the cache entry.
-        //
-        // We open with ACCESS_READ only, because we don't want to
-        // overwrite the offline cache entry non-atomically.
-        // ACCESS_READ will prevent us from writing to the offline
-        // cache as a normal cache entry.
-        rv = session->OpenCacheEntry(cacheKey,
-                                     nsICache::ACCESS_READ, PR_FALSE,
-                                     getter_AddRefs(mCacheEntry));
-        if (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION) {
-            accessRequested = nsICache::ACCESS_READ;
-            waitingForValidation = PR_TRUE;
-            rv = NS_OK;
-        }
-
-        if (NS_FAILED(rv) && !mCacheForOfflineUse && !mFallbackChannel) {
-            // Check for namespace match.
-            nsCOMPtr<nsIApplicationCacheNamespace> namespaceEntry;
-            rv = mApplicationCache->GetMatchingNamespace
-                (cacheKey, getter_AddRefs(namespaceEntry));
-            NS_ENSURE_SUCCESS(rv, rv);
-
-            PRUint32 namespaceType = 0;
-            if (!namespaceEntry ||
-                NS_FAILED(namespaceEntry->GetItemType(&namespaceType)) ||
-                (namespaceType &
-                 (nsIApplicationCacheNamespace::NAMESPACE_FALLBACK |
-                  nsIApplicationCacheNamespace::NAMESPACE_OPPORTUNISTIC |
-                  nsIApplicationCacheNamespace::NAMESPACE_BYPASS)) == 0) {
-                // When loading from an application cache, only items
-                // on the whitelist or matching a
-                // fallback/opportunistic namespace should hit the
-                // network...
-                mLoadFlags |= LOAD_ONLY_FROM_CACHE;
-
-                // ... and if there were an application cache entry,
-                // we would have found it earlier.
-                return NS_ERROR_CACHE_KEY_NOT_FOUND;
-            }
-
-            if (namespaceType &
-                nsIApplicationCacheNamespace::NAMESPACE_FALLBACK) {
-                rv = namespaceEntry->GetData(mFallbackKey);
-                NS_ENSURE_SUCCESS(rv, rv);
-            }
-
-            if ((namespaceType &
-                 nsIApplicationCacheNamespace::NAMESPACE_OPPORTUNISTIC) &&
-                mLoadFlags & LOAD_DOCUMENT_URI) {
-                // Document loads for items in an opportunistic namespace
-                // should be placed in the offline cache.
-                nsCString clientID;
-                mApplicationCache->GetClientID(clientID);
-
-                mCacheForOfflineUse = !clientID.IsEmpty();
-                SetOfflineCacheClientID(clientID);
-                mCachingOpportunistically = PR_TRUE;
-            }
-        }
-        else if (NS_SUCCEEDED(rv)) {
-            // We successfully opened an offline cache session and the entry,
-            // now indiciate we load from the offline cache.
-            mLoadedFromApplicationCache = PR_TRUE;
-        }
-    }
-
-    if (!mCacheEntry && !waitingForValidation) {
-        rv = gHttpHandler->GetCacheSession(storagePolicy,
-                                           getter_AddRefs(session));
-        if (NS_FAILED(rv)) return rv;
-
-        rv = session->OpenCacheEntry(cacheKey, accessRequested, PR_FALSE,
-                                     getter_AddRefs(mCacheEntry));
-        if (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION) {
-            waitingForValidation = PR_TRUE;
-            rv = NS_OK;
-        }
-        if (NS_FAILED(rv)) return rv;
-    }
-
-    if (waitingForValidation) {
-        // access to the cache entry has been denied (because the
-        // cache entry is probably in use by another channel).
-        if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY) {
-            LOG(("bypassing local cache since it is busy\n"));
-            return NS_ERROR_NOT_AVAILABLE;
-        }
-        rv = session->AsyncOpenCacheEntry(cacheKey, accessRequested, this);
-        if (NS_FAILED(rv)) return rv;
-        // we'll have to wait for the cache entry
-        *delayed = PR_TRUE;
-    }
-    else if (NS_SUCCEEDED(rv)) {
-        mCacheEntry->GetAccessGranted(&mCacheAccess);
-        LOG(("nsHttpChannel::OpenCacheEntry [this=%p grantedAccess=%d]", this, mCacheAccess));
-    }
-    return rv;
-}
-
-
-nsresult
-nsHttpChannel::OpenOfflineCacheEntryForWriting()
-{
-    nsresult rv;
-
-    LOG(("nsHttpChannel::OpenOfflineCacheEntryForWriting [this=%p]", this));
-
-    // make sure we're not abusing this function
-    NS_PRECONDITION(!mOfflineCacheEntry, "cache entry already open");
-
-    PRBool offline = gIOService->IsOffline();
-    if (offline) {
-        // only put things in the offline cache while online
-        return NS_OK;
-    }
-
-    if (mRequestHead.Method() != nsHttp::Get) {
-        // only cache complete documents offline
-        return NS_OK;
-    }
-
-    // Don't cache byte range requests which are subranges, only cache 0-
-    // byte range requests.
-    if (IsSubRangeRequest(mRequestHead))
-        return NS_OK;
-
-    nsCAutoString cacheKey;
-    GenerateCacheKey(mPostID, cacheKey);
-
-    NS_ENSURE_TRUE(!mOfflineCacheClientID.IsEmpty(),
-                   NS_ERROR_NOT_AVAILABLE);
-
-    nsCOMPtr<nsICacheSession> session;
-    nsCOMPtr<nsICacheService> serv =
-        do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
-    if (NS_FAILED(rv)) return rv;
-
-    rv = serv->CreateSession(mOfflineCacheClientID.get(),
-                             nsICache::STORE_OFFLINE,
-                             nsICache::STREAM_BASED,
-                             getter_AddRefs(session));
-    if (NS_FAILED(rv)) return rv;
-
-    rv = session->OpenCacheEntry(cacheKey, nsICache::ACCESS_READ_WRITE,
-                                 PR_FALSE, getter_AddRefs(mOfflineCacheEntry));
-
-    if (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION) {
-        // access to the cache entry has been denied (because the cache entry
-        // is probably in use by another channel).  Either the cache is being
-        // read from (we're offline) or it's being updated elsewhere.
-        return NS_OK;
-    }
+    NS_ASSERTION(mAuthChannel, "Channel not initialized");
 
-    if (NS_SUCCEEDED(rv)) {
-        mOfflineCacheEntry->GetAccessGranted(&mOfflineCacheAccess);
-        LOG(("got offline cache entry [access=%x]\n", mOfflineCacheAccess));
-    }
-
-    return rv;
-}
-
-nsresult
-nsHttpChannel::GenerateCacheKey(PRUint32 postID, nsACString &cacheKey)
-{
-    cacheKey.Truncate();
-
-    if (mLoadFlags & LOAD_ANONYMOUS) {
-      cacheKey.AssignLiteral("anon&");
-    }
-
-    if (postID) {
-        char buf[32];
-        PR_snprintf(buf, sizeof(buf), "id=%x&", postID);
-        cacheKey.Append(buf);
-    }
-
-    if (!cacheKey.IsEmpty()) {
-      cacheKey.AppendLiteral("uri=");
-    }
-
-    // Strip any trailing #ref from the URL before using it as the key
-    const char *spec = mFallbackChannel ? mFallbackKey.get() : mSpec.get();
-    const char *p = strchr(spec, '#');
-    if (p)
-        cacheKey.Append(spec, p - spec);
-    else
-        cacheKey.Append(spec);
-    return NS_OK;
-}
-
-// UpdateExpirationTime is called when a new response comes in from the server.
-// It updates the stored response-time and sets the expiration time on the
-// cache entry.  
-//
-// From section 13.2.4 of RFC2616, we compute expiration time as follows:
-//
-//    timeRemaining = freshnessLifetime - currentAge
-//    expirationTime = now + timeRemaining
-// 
-nsresult
-nsHttpChannel::UpdateExpirationTime()
-{
-    NS_ENSURE_TRUE(mResponseHead, NS_ERROR_FAILURE);
-
-    nsresult rv;
-
-    PRUint32 expirationTime = 0;
-    if (!mResponseHead->MustValidate()) {
-        PRUint32 freshnessLifetime = 0;
-
-        rv = mResponseHead->ComputeFreshnessLifetime(&freshnessLifetime);
-        if (NS_FAILED(rv)) return rv;
-
-        if (freshnessLifetime > 0) {
-            PRUint32 now = NowInSeconds(), currentAge = 0;
-
-            rv = mResponseHead->ComputeCurrentAge(now, mRequestTime, &currentAge); 
-            if (NS_FAILED(rv)) return rv;
-
-            LOG(("freshnessLifetime = %u, currentAge = %u\n",
-                freshnessLifetime, currentAge));
-
-            if (freshnessLifetime > currentAge) {
-                PRUint32 timeRemaining = freshnessLifetime - currentAge;
-                // be careful... now + timeRemaining may overflow
-                if (now + timeRemaining < now)
-                    expirationTime = PRUint32(-1);
-                else
-                    expirationTime = now + timeRemaining;
-            }
-            else
-                expirationTime = now;
-        }
-    }
-
-    rv = mCacheEntry->SetExpirationTime(expirationTime);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    if (mOfflineCacheEntry) {
-        rv = mOfflineCacheEntry->SetExpirationTime(expirationTime);
-        NS_ENSURE_SUCCESS(rv, rv);
-    }
-
-    return NS_OK;
-}
-
-// CheckCache is called from Connect after a cache entry has been opened for
-// this URL but before going out to net.  It's purpose is to set or clear the 
-// mCachedContentIsValid flag, and to configure an If-Modified-Since request
-// if validation is required.
-nsresult
-nsHttpChannel::CheckCache()
-{
-    nsresult rv = NS_OK;
-
-    LOG(("nsHTTPChannel::CheckCache enter [this=%p entry=%p access=%d]",
-        this, mCacheEntry.get(), mCacheAccess));
-    
-    // Be pessimistic: assume the cache entry has no useful data.
-    mCachedContentIsValid = PR_FALSE;
-
-    // Don't proceed unless we have opened a cache entry for reading.
-    if (!mCacheEntry || !(mCacheAccess & nsICache::ACCESS_READ))
-        return NS_OK;
-
-    nsXPIDLCString buf;
-
-    // Get the method that was used to generate the cached response
-    rv = mCacheEntry->GetMetaDataElement("request-method", getter_Copies(buf));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    nsHttpAtom method = nsHttp::ResolveAtom(buf);
-    if (method == nsHttp::Head) {
-        // The cached response does not contain an entity.  We can only reuse
-        // the response if the current request is also HEAD.
-        if (mRequestHead.Method() != nsHttp::Head)
-            return NS_OK;
-    }
-    buf.Adopt(0);
-
-    // We'll need this value in later computations...
-    PRUint32 lastModifiedTime;
-    rv = mCacheEntry->GetLastModified(&lastModifiedTime);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    // Determine if this is the first time that this cache entry
-    // has been accessed during this session.
-    PRBool fromPreviousSession =
-            (gHttpHandler->SessionStartTime() > lastModifiedTime);
-
-    // Get the cached HTTP response headers
-    rv = mCacheEntry->GetMetaDataElement("response-head", getter_Copies(buf));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    // Parse the cached HTTP response headers
-    NS_ASSERTION(!mCachedResponseHead, "memory leak detected");
-    mCachedResponseHead = new nsHttpResponseHead();
-    if (!mCachedResponseHead)
-        return NS_ERROR_OUT_OF_MEMORY;
-    rv = mCachedResponseHead->Parse((char *) buf.get());
-    NS_ENSURE_SUCCESS(rv, rv);
-    buf.Adopt(0);
-
-    // Don't bother to validate items that are read-only,
-    // unless they are read-only because of INHIBIT_CACHING or because
-    // we're updating the offline cache.
-    // Don't bother to validate if this is a fallback entry.
-    if (!mCacheForOfflineUse &&
-        (mLoadedFromApplicationCache ||
-         (mCacheAccess == nsICache::ACCESS_READ &&
-          !(mLoadFlags & INHIBIT_CACHING)) ||
-         mFallbackChannel)) {
-        mCachedContentIsValid = PR_TRUE;
-        return NS_OK;
-    }
-
-    PRUint16 isCachedRedirect = mCachedResponseHead->Status()/100 == 3;
-
-    if (method != nsHttp::Head && !isCachedRedirect) {
-        // If the cached content-length is set and it does not match the data
-        // size of the cached content, then the cached response is partial...
-        // either we need to issue a byte range request or we need to refetch
-        // the entire document.
-        nsInt64 contentLength = mCachedResponseHead->ContentLength();
-        if (contentLength != nsInt64(-1)) {
-            PRUint32 size;
-            rv = mCacheEntry->GetDataSize(&size);
-            NS_ENSURE_SUCCESS(rv, rv);
-
-            if (nsInt64(size) != contentLength) {
-                LOG(("Cached data size does not match the Content-Length header "
-                     "[content-length=%lld size=%u]\n", PRInt64(contentLength), size));
-                if ((nsInt64(size) < contentLength) && mCachedResponseHead->IsResumable()) {
-                    // looks like a partial entry.
-                    rv = SetupByteRangeRequest(size);
-                    NS_ENSURE_SUCCESS(rv, rv);
-                    mCachedContentIsPartial = PR_TRUE;
-                }
-                return NS_OK;
-            }
-        }
-    }
-
-    PRBool doValidation = PR_FALSE;
-    PRBool canAddImsHeader = PR_TRUE;
-
-    mCustomConditionalRequest = 
-        mRequestHead.PeekHeader(nsHttp::If_Modified_Since) ||
-        mRequestHead.PeekHeader(nsHttp::If_None_Match) ||
-        mRequestHead.PeekHeader(nsHttp::If_Unmodified_Since) ||
-        mRequestHead.PeekHeader(nsHttp::If_Match) ||
-        mRequestHead.PeekHeader(nsHttp::If_Range);
-
-    // If the LOAD_FROM_CACHE flag is set, any cached data can simply be used.
-    if (mLoadFlags & LOAD_FROM_CACHE) {
-        LOG(("NOT validating based on LOAD_FROM_CACHE load flag\n"));
-        doValidation = PR_FALSE;
-    }
-    // If the VALIDATE_ALWAYS flag is set, any cached data won't be used until
-    // it's revalidated with the server.
-    else if (mLoadFlags & VALIDATE_ALWAYS) {
-        LOG(("Validating based on VALIDATE_ALWAYS load flag\n"));
-        doValidation = PR_TRUE;
-    }
-    // Even if the VALIDATE_NEVER flag is set, there are still some cases in
-    // which we must validate the cached response with the server.
-    else if (mLoadFlags & VALIDATE_NEVER) {
-        LOG(("VALIDATE_NEVER set\n"));
-        // if no-store or if no-cache and ssl, validate cached response (see
-        // bug 112564 for an explanation of this logic)
-        if (mCachedResponseHead->NoStore() ||
-           (mCachedResponseHead->NoCache() && mConnectionInfo->UsingSSL())) {
-            LOG(("Validating based on (no-store || (no-cache && ssl)) logic\n"));
-            doValidation = PR_TRUE;
-        }
-        else {
-            LOG(("NOT validating based on VALIDATE_NEVER load flag\n"));
-            doValidation = PR_FALSE;
-        }
-    }
-    // check if validation is strictly required...
-    else if (mCachedResponseHead->MustValidate()) {
-        LOG(("Validating based on MustValidate() returning TRUE\n"));
-        doValidation = PR_TRUE;
-    }
-
-    else if (ResponseWouldVary()) {
-        LOG(("Validating based on Vary headers returning TRUE\n"));
-        canAddImsHeader = PR_FALSE;
-        doValidation = PR_TRUE;
-    }
-    
-    else if (MustValidateBasedOnQueryUrl()) {
-        LOG(("Validating based on RFC 2616 section 13.9 "
-             "(query-url w/o explicit expiration-time)\n"));
-        doValidation = PR_TRUE;
-    }
-    // Check if the cache entry has expired...
-    else {
-        PRUint32 time = 0; // a temporary variable for storing time values...
-
-        rv = mCacheEntry->GetExpirationTime(&time);
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        if (NowInSeconds() <= time)
-            doValidation = PR_FALSE;
-        else if (mCachedResponseHead->MustValidateIfExpired())
-            doValidation = PR_TRUE;
-        else if (mLoadFlags & VALIDATE_ONCE_PER_SESSION) {
-            // If the cached response does not include expiration infor-
-            // mation, then we must validate the response, despite whether
-            // or not this is the first access this session.  This behavior
-            // is consistent with existing browsers and is generally expected
-            // by web authors.
-            rv = mCachedResponseHead->ComputeFreshnessLifetime(&time);
-            NS_ENSURE_SUCCESS(rv, rv);
-
-            if (time == 0)
-                doValidation = PR_TRUE;
-            else
-                doValidation = fromPreviousSession;
-        }
-        else
-            doValidation = PR_TRUE;
-
-        LOG(("%salidating based on expiration time\n", doValidation ? "V" : "Not v"));
-    }
-
-    if (!doValidation && mRequestHead.PeekHeader(nsHttp::If_Match) &&
-        (method == nsHttp::Get || method == nsHttp::Head)) {
-        const char *requestedETag, *cachedETag;
-        cachedETag = mCachedResponseHead->PeekHeader(nsHttp::ETag);
-        requestedETag = mRequestHead.PeekHeader(nsHttp::If_Match);
-        if (cachedETag && (!strncmp(cachedETag, "W/", 2) ||
-            strcmp(requestedETag, cachedETag))) {
-            // User has defined If-Match header, if the cached entry is not 
-            // matching the provided header value or the cached ETag is weak,
-            // force validation.
-            doValidation = PR_TRUE;
-        }
-    }
-
-    if (!doValidation) {
-        //
-        // Check the authorization headers used to generate the cache entry.
-        // We must validate the cache entry if:
-        //
-        // 1) the cache entry was generated prior to this session w/
-        //    credentials (see bug 103402).
-        // 2) the cache entry was generated w/o credentials, but would now
-        //    require credentials (see bug 96705).
-        //
-        // NOTE: this does not apply to proxy authentication.
-        //
-        mCacheEntry->GetMetaDataElement("auth", getter_Copies(buf));
-        doValidation =
-            (fromPreviousSession && !buf.IsEmpty()) ||
-            (buf.IsEmpty() && mRequestHead.PeekHeader(nsHttp::Authorization));
-    }
-
-    if (!doValidation) {
-        // Sites redirect back to the original URI after setting a session/tracking
-        // cookie. In such cases, force revalidation so that we hit the net and do not
-        // cycle thru cached responses.
-        if (isCachedRedirect && mRequestHead.PeekHeader(nsHttp::Cookie))
-            doValidation = PR_TRUE;
-    }
-
-    mCachedContentIsValid = !doValidation;
-
-    if (doValidation) {
-        //
-        // now, we are definitely going to issue a HTTP request to the server.
-        // make it conditional if possible.
-        //
-        // do not attempt to validate no-store content, since servers will not
-        // expect it to be cached.  (we only keep it in our cache for the
-        // purposes of back/forward, etc.)
-        //
-        // the request method MUST be either GET or HEAD (see bug 175641).
-        //
-        // do not override conditional headers when consumer has defined its own
-        if (!mCachedResponseHead->NoStore() &&
-            (mRequestHead.Method() == nsHttp::Get ||
-             mRequestHead.Method() == nsHttp::Head) &&
-             !mCustomConditionalRequest) {
-            const char *val;
-            // Add If-Modified-Since header if a Last-Modified was given
-            // and we are allowed to do this (see bugs 510359 and 269303)
-            if (canAddImsHeader) {
-                val = mCachedResponseHead->PeekHeader(nsHttp::Last_Modified);
-                if (val)
-                    mRequestHead.SetHeader(nsHttp::If_Modified_Since,
-                                           nsDependentCString(val));
-            }
-            // Add If-None-Match header if an ETag was given in the response
-            val = mCachedResponseHead->PeekHeader(nsHttp::ETag);
-            if (val)
-                mRequestHead.SetHeader(nsHttp::If_None_Match,
-                                       nsDependentCString(val));
-        }
-    }
-
-    LOG(("nsHTTPChannel::CheckCache exit [this=%p doValidation=%d]\n", this, doValidation));
-    return NS_OK;
-}
-
-PRBool
-nsHttpChannel::MustValidateBasedOnQueryUrl()
-{
-    // RFC 2616, section 13.9 states that GET-requests with a query-url
-    // MUST NOT be treated as fresh unless the server explicitly provides
-    // an expiration-time in the response. See bug #468594
-    // Section 13.2.1 (6th paragraph) defines "explicit expiration time"
-    if (mRequestHead.Method() == nsHttp::Get)
-    {
-        nsCAutoString query;
-        nsCOMPtr<nsIURL> url = do_QueryInterface(mURI);
-        nsresult rv = url->GetQuery(query);
-        if (NS_SUCCEEDED(rv) && !query.IsEmpty()) {
-            PRUint32 tmp; // we don't need the value, just whether it's set
-            rv = mCachedResponseHead->GetExpiresValue(&tmp);
-            if (NS_FAILED(rv)) {
-                rv = mCachedResponseHead->GetMaxAgeValue(&tmp);
-                if (NS_FAILED(rv)) {
-                    return PR_TRUE;
-                }
-            }
-        }
-    }
-    return PR_FALSE;
-}
-
-
-nsresult
-nsHttpChannel::ShouldUpdateOfflineCacheEntry(PRBool *shouldCacheForOfflineUse)
-{
-    *shouldCacheForOfflineUse = PR_FALSE;
-
-    if (!mOfflineCacheEntry) {
-        return NS_OK;
-    }
-
-    // if we're updating the cache entry, update the offline cache entry too
-    if (mCacheEntry && (mCacheAccess & nsICache::ACCESS_WRITE)) {
-        *shouldCacheForOfflineUse = PR_TRUE;
-        return NS_OK;
-    }
-
-    // if there's nothing in the offline cache, add it
-    if (mOfflineCacheEntry && (mOfflineCacheAccess == nsICache::ACCESS_WRITE)) {
-        *shouldCacheForOfflineUse = PR_TRUE;
-        return NS_OK;
-    }
-
-    // if the document is newer than the offline entry, update it
-    PRUint32 docLastModifiedTime;
-    nsresult rv = mResponseHead->GetLastModifiedValue(&docLastModifiedTime);
-    if (NS_FAILED(rv)) {
-        *shouldCacheForOfflineUse = PR_TRUE;
-        return NS_OK;
-    }
-
-    PRUint32 offlineLastModifiedTime;
-    rv = mOfflineCacheEntry->GetLastModified(&offlineLastModifiedTime);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    if (docLastModifiedTime > offlineLastModifiedTime) {
-        *shouldCacheForOfflineUse = PR_TRUE;
-        return NS_OK;
-    }
-
-    return NS_OK;
-}
-
-// If the data in the cache hasn't expired, then there's no need to
-// talk with the server, not even to do an if-modified-since.  This
-// method creates a stream from the cache, synthesizing all the various
-// channel-related events.
-nsresult
-nsHttpChannel::ReadFromCache()
-{
-    nsresult rv;
-
-    NS_ENSURE_TRUE(mCacheEntry, NS_ERROR_FAILURE);
-    NS_ENSURE_TRUE(mCachedContentIsValid, NS_ERROR_FAILURE);
-
-    LOG(("nsHttpChannel::ReadFromCache [this=%p] "
-         "Using cached copy of: %s\n", this, mSpec.get()));
-
-    if (mCachedResponseHead) {
-        NS_ASSERTION(!mResponseHead, "memory leak");
-        mResponseHead = mCachedResponseHead;
-        mCachedResponseHead = 0;
-    }
-
-    // if we don't already have security info, try to get it from the cache 
-    // entry. there are two cases to consider here: 1) we are just reading
-    // from the cache, or 2) this may be due to a 304 not modified response,
-    // in which case we could have security info from a socket transport.
-    if (!mSecurityInfo)
-        mCacheEntry->GetSecurityInfo(getter_AddRefs(mSecurityInfo));
-
-    if ((mCacheAccess & nsICache::ACCESS_WRITE) && !mCachedContentIsPartial) {
-        // We have write access to the cache, but we don't need to go to the
-        // server to validate at this time, so just mark the cache entry as
-        // valid in order to allow others access to this cache entry.
-        mCacheEntry->MarkValid();
-    }
-
-    // if this is a cached redirect, we must process the redirect asynchronously
-    // since AsyncOpen may not have returned yet.  Make sure there is a Location
-    // header, otherwise we'll have to treat this like a normal 200 response.
-    if (mResponseHead && (mResponseHead->Status() / 100 == 3) 
-                      && (mResponseHead->PeekHeader(nsHttp::Location)))
-        return AsyncCall(&nsHttpChannel::HandleAsyncRedirect);
-
-    // have we been configured to skip reading from the cache?
-    if ((mLoadFlags & LOAD_ONLY_IF_MODIFIED) && !mCachedContentIsPartial) {
-        // if offline caching has been requested and the offline cache needs
-        // updating, complete the call even if the main cache entry is
-        // up-to-date
-        PRBool shouldUpdateOffline;
-        if (!mCacheForOfflineUse ||
-            NS_FAILED(ShouldUpdateOfflineCacheEntry(&shouldUpdateOffline)) ||
-            !shouldUpdateOffline) {
-
-            LOG(("skipping read from cache based on LOAD_ONLY_IF_MODIFIED "
-                 "load flag\n"));
-            return AsyncCall(&nsHttpChannel::HandleAsyncNotModified);
-        }
-    }
-
-    // open input stream for reading...
-    nsCOMPtr<nsIInputStream> stream;
-    rv = mCacheEntry->OpenInputStream(0, getter_AddRefs(stream));
-    if (NS_FAILED(rv)) return rv;
-
-    rv = nsInputStreamPump::Create(getter_AddRefs(mCachePump),
-                                   stream, nsInt64(-1), nsInt64(-1), 0, 0,
-                                   PR_TRUE);
-    if (NS_FAILED(rv)) return rv;
-
-    return mCachePump->AsyncRead(this, mListenerContext);
-}
-
-void
-nsHttpChannel::CloseCacheEntry(PRBool doomOnFailure)
-{
-    if (!mCacheEntry)
-        return;
-
-    LOG(("nsHttpChannel::CloseCacheEntry [this=%p] mStatus=%x mCacheAccess=%x",
-         this, mStatus, mCacheAccess));
-
-    // If we have begun to create or replace a cache entry, and that cache
-    // entry is not complete and not resumable, then it needs to be doomed.
-    // Otherwise, CheckCache will make the mistake of thinking that the
-    // partial cache entry is complete.
-
-    PRBool doom = PR_FALSE;
-    if (mInitedCacheEntry) {
-        NS_ASSERTION(mResponseHead, "oops");
-        if (NS_FAILED(mStatus) && doomOnFailure &&
-            (mCacheAccess & nsICache::ACCESS_WRITE) &&
-            !mResponseHead->IsResumable())
-            doom = PR_TRUE;
-    }
-    else if (mCacheAccess == nsICache::ACCESS_WRITE)
-        doom = PR_TRUE;
-
-    if (doom) {
-        LOG(("  dooming cache entry!!"));
-        mCacheEntry->Doom();
-    }
-
-    if (mCachedResponseHead) {
-        delete mCachedResponseHead;
-        mCachedResponseHead = 0;
-    }
-
-    mCachePump = 0;
-    mCacheEntry = 0;
-    mCacheAccess = 0;
-    mInitedCacheEntry = PR_FALSE;
-}
-
-
-void
-nsHttpChannel::CloseOfflineCacheEntry()
-{
-    if (!mOfflineCacheEntry)
-        return;
-
-    LOG(("nsHttpChannel::CloseOfflineCacheEntry [this=%p]", this));
-
-    if (NS_FAILED(mStatus)) {
-        mOfflineCacheEntry->Doom();
-    }
-    else {
-        PRBool succeeded;
-        if (NS_SUCCEEDED(GetRequestSucceeded(&succeeded)) && !succeeded)
-            mOfflineCacheEntry->Doom();
-    }
-
-    mOfflineCacheEntry = 0;
-    mOfflineCacheAccess = 0;
-
-    if (mCachingOpportunistically) {
-        nsCOMPtr<nsIApplicationCacheService> appCacheService =
-            do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID);
-        if (appCacheService) {
-            nsCAutoString cacheKey;
-            GenerateCacheKey(mPostID, cacheKey);
-            appCacheService->CacheOpportunistically(mApplicationCache,
-                                                    cacheKey);
-        }
-    }
-}
-
-
-// Initialize the cache entry for writing.
-//  - finalize storage policy
-//  - store security info
-//  - update expiration time
-//  - store headers and other meta data
-nsresult
-nsHttpChannel::InitCacheEntry()
-{
-    nsresult rv;
-
-    NS_ENSURE_TRUE(mCacheEntry, NS_ERROR_UNEXPECTED);
-    // if only reading, nothing to be done here.
-    if (mCacheAccess == nsICache::ACCESS_READ)
-        return NS_OK;
-
-    // Don't cache the response again if already cached...
-    if (mCachedContentIsValid)
-        return NS_OK;
-
-    LOG(("nsHttpChannel::InitCacheEntry [this=%p entry=%p]\n",
-        this, mCacheEntry.get()));
-
-    // The no-store directive within the 'Cache-Control:' header indicates
-    // that we must not store the response in a persistent cache.
-    if (mResponseHead->NoStore())
-        mLoadFlags |= INHIBIT_PERSISTENT_CACHING;
-
-    // Only cache SSL content on disk if the pref is set
-    if (!gHttpHandler->IsPersistentHttpsCachingEnabled() &&
-        mConnectionInfo->UsingSSL())
-        mLoadFlags |= INHIBIT_PERSISTENT_CACHING;
-
-    if (mLoadFlags & INHIBIT_PERSISTENT_CACHING) {
-        rv = mCacheEntry->SetStoragePolicy(nsICache::STORE_IN_MEMORY);
-        if (NS_FAILED(rv)) return rv;
-    }
-
-    // Set the expiration time for this cache entry
-    rv = UpdateExpirationTime();
-    if (NS_FAILED(rv)) return rv;
-
-    rv = AddCacheEntryHeaders(mCacheEntry);
-    if (NS_FAILED(rv)) return rv;
-
-    mInitedCacheEntry = PR_TRUE;
-    return NS_OK;
-}
-
-
-nsresult
-nsHttpChannel::InitOfflineCacheEntry()
-{
-    // This function can be called even when we fail to connect (bug 551990)
-
-    if (!mOfflineCacheEntry) {
-        return NS_OK;
-    }
-
-    if (mResponseHead && mResponseHead->NoStore()) {
-        CloseOfflineCacheEntry();
-
-        return NS_OK;
-    }
-
-    // This entry's expiration time should match the main entry's expiration
-    // time.  UpdateExpirationTime() will keep it in sync once the offline
-    // cache entry has been created.
-    if (mCacheEntry) {
-        PRUint32 expirationTime;
-        nsresult rv = mCacheEntry->GetExpirationTime(&expirationTime);
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        mOfflineCacheEntry->SetExpirationTime(expirationTime);
-    }
-
-    return AddCacheEntryHeaders(mOfflineCacheEntry);
-}
-
-
-nsresult
-nsHttpChannel::AddCacheEntryHeaders(nsICacheEntryDescriptor *entry)
-{
-    nsresult rv;
-
-    // Store secure data in memory only
-    if (mSecurityInfo)
-        entry->SetSecurityInfo(mSecurityInfo);
-
-    // Store the HTTP request method with the cache entry so we can distinguish
-    // for example GET and HEAD responses.
-    rv = entry->SetMetaDataElement("request-method",
-                                   mRequestHead.Method().get());
-    if (NS_FAILED(rv)) return rv;
-
-    // Store the HTTP authorization scheme used if any...
-    rv = StoreAuthorizationMetaData(entry);
-    if (NS_FAILED(rv)) return rv;
-
-    // Iterate over the headers listed in the Vary response header, and
-    // store the value of the corresponding request header so we can verify
-    // that it has not varied when we try to re-use the cached response at
-    // a later time.  Take care not to store "Cookie" headers though.  We
-    // take care of "Vary: cookie" in ResponseWouldVary.
-    //
-    // NOTE: if "Vary: accept, cookie", then we will store the "accept" header
-    // in the cache.  we could try to avoid needlessly storing the "accept"
-    // header in this case, but it doesn't seem worth the extra code to perform
-    // the check.
-    {
-        nsCAutoString buf, metaKey;
-        mResponseHead->GetHeader(nsHttp::Vary, buf);
-        if (!buf.IsEmpty()) {
-            NS_NAMED_LITERAL_CSTRING(prefix, "request-");
-           
-            char *val = buf.BeginWriting(); // going to munge buf
-            char *token = nsCRT::strtok(val, NS_HTTP_HEADER_SEPS, &val);
-            while (token) {
-                if ((*token != '*') && (PL_strcasecmp(token, "cookie") != 0)) {
-                    nsHttpAtom atom = nsHttp::ResolveAtom(token);
-                    const char *requestVal = mRequestHead.PeekHeader(atom);
-                    if (requestVal) {
-                        // build cache meta data key and set meta data element...
-                        metaKey = prefix + nsDependentCString(token);
-                        entry->SetMetaDataElement(metaKey.get(), requestVal);
-                    }
-                }
-                token = nsCRT::strtok(val, NS_HTTP_HEADER_SEPS, &val);
-            }
-        }
-    }
-
-
-    // Store the received HTTP head with the cache entry as an element of
-    // the meta data.
-    nsCAutoString head;
-    mResponseHead->Flatten(head, PR_TRUE);
-    rv = entry->SetMetaDataElement("response-head", head.get());
-
-    return rv;
-}
-
-inline void
-GetAuthType(const char *challenge, nsCString &authType)
-{
-    const char *p;
-
-    // get the challenge type
-    if ((p = strchr(challenge, ' ')) != nsnull)
-        authType.Assign(challenge, p - challenge);
-    else
-        authType.Assign(challenge);
-}
-
-nsresult
-nsHttpChannel::StoreAuthorizationMetaData(nsICacheEntryDescriptor *entry)
-{
-    // Not applicable to proxy authorization...
-    const char *val = mRequestHead.PeekHeader(nsHttp::Authorization);
-    if (!val)
-        return NS_OK;
-
-    // eg. [Basic realm="wally world"]
-    nsCAutoString buf;
-    GetAuthType(val, buf);
-    return entry->SetMetaDataElement("auth", buf.get());
-}
-
-// Finalize the cache entry
-//  - may need to rewrite response headers if any headers changed
-//  - may need to recalculate the expiration time if any headers changed
-//  - called only for freshly written cache entries
-nsresult
-nsHttpChannel::FinalizeCacheEntry()
-{
-    LOG(("nsHttpChannel::FinalizeCacheEntry [this=%p]\n", this));
-
-    if (mResponseHead && mResponseHeadersModified) {
-        // Set the expiration time for this cache entry
-        nsresult rv = UpdateExpirationTime();
-        if (NS_FAILED(rv)) return rv;
+    // we've been called because it has been determined that this channel is
+    // getting loaded without taking the userpass from the URL.  if the URL
+    // contained a userpass, then (provided some other conditions are true),
+    // we'll give the user an opportunity to abort the channel as this might be
+    // an attempt to spoof a different site (see bug 232567).
+    if (!ConfirmAuth(NS_LITERAL_STRING("SuperfluousAuth"), PR_TRUE)) {
+        // calling cancel here sets our mStatus and aborts the HTTP
+        // transaction, which prevents OnDataAvailable events.
+        mAuthChannel->Cancel(NS_ERROR_ABORT);
+        return NS_ERROR_ABORT;
     }
     return NS_OK;
 }
 
-// Open an output stream to the cache entry and insert a listener tee into
-// the chain of response listeners.
-nsresult
-nsHttpChannel::InstallCacheListener(PRUint32 offset)
+NS_IMETHODIMP
+nsHttpChannelAuthProvider::Cancel(nsresult status)
 {
-    nsresult rv;
-
-    LOG(("Preparing to write data into the cache [uri=%s]\n", mSpec.get()));
-
-    NS_ASSERTION(mCacheEntry, "no cache entry");
-    NS_ASSERTION(mListener, "no listener");
-
-    nsCOMPtr<nsIOutputStream> out;
-    rv = mCacheEntry->OpenOutputStream(offset, getter_AddRefs(out));
-    if (NS_FAILED(rv)) return rv;
-
-    // XXX disk cache does not support overlapped i/o yet
-#if 0
-    // Mark entry valid inorder to allow simultaneous reading...
-    rv = mCacheEntry->MarkValid();
-    if (NS_FAILED(rv)) return rv;
-#endif
-
-    nsCOMPtr<nsIStreamListenerTee> tee =
-        do_CreateInstance(kStreamListenerTeeCID, &rv);
-    if (NS_FAILED(rv)) return rv;
-
-    nsCacheStoragePolicy policy;
-    rv = mCacheEntry->GetStoragePolicy(&policy);
+    NS_ASSERTION(mAuthChannel, "Channel not initialized");
 
-    if (!gHttpHandler->mCacheWriteThread ||
-         NS_FAILED(rv) ||
-         policy == nsICache::STORE_ON_DISK_AS_FILE) {
-        LOG(("nsHttpChannel::InstallCacheListener sync tee %p\n", tee.get()));
-        rv = tee->Init(mListener, out, nsnull);
-    } else {
-        LOG(("nsHttpChannel::InstallCacheListener async tee %p\n",
-                tee.get()));
-        rv = tee->InitAsync(mListener, gHttpHandler->mCacheWriteThread, out, nsnull);
+    if (mAsyncPromptAuthCancelable) {
+        mAsyncPromptAuthCancelable->Cancel(status);
+        mAsyncPromptAuthCancelable = nsnull;
     }
-   
-    if (NS_FAILED(rv)) return rv;
-    mListener = tee;
-    return NS_OK;
-}
-
-nsresult
-nsHttpChannel::InstallOfflineCacheListener()
-{
-    nsresult rv;
-
-    LOG(("Preparing to write data into the offline cache [uri=%s]\n",
-         mSpec.get()));
-
-    NS_ASSERTION(mOfflineCacheEntry, "no offline cache entry");
-    NS_ASSERTION(mListener, "no listener");
-
-    nsCOMPtr<nsIOutputStream> out;
-    rv = mOfflineCacheEntry->OpenOutputStream(0, getter_AddRefs(out));
-    if (NS_FAILED(rv)) return rv;
-
-    nsCOMPtr<nsIStreamListenerTee> tee =
-        do_CreateInstance(kStreamListenerTeeCID, &rv);
-    if (NS_FAILED(rv)) return rv;
-
-    rv = tee->Init(mListener, out, nsnull);
-    if (NS_FAILED(rv)) return rv;
-
-    mListener = tee;
-
     return NS_OK;
 }
 
-void
-nsHttpChannel::ClearBogusContentEncodingIfNeeded()
-{
-    // For .gz files, apache sends both a Content-Type: application/x-gzip
-    // as well as Content-Encoding: gzip, which is completely wrong.  In
-    // this case, we choose to ignore the rogue Content-Encoding header. We
-    // must do this early on so as to prevent it from being seen up stream.
-    // The same problem exists for Content-Encoding: compress in default
-    // Apache installs.
-    if (mResponseHead->HasHeaderValue(nsHttp::Content_Encoding, "gzip") && (
-        mResponseHead->ContentType().EqualsLiteral(APPLICATION_GZIP) ||
-        mResponseHead->ContentType().EqualsLiteral(APPLICATION_GZIP2) ||
-        mResponseHead->ContentType().EqualsLiteral(APPLICATION_GZIP3))) {
-        // clear the Content-Encoding header
-        mResponseHead->ClearHeader(nsHttp::Content_Encoding);
-    }
-    else if (mResponseHead->HasHeaderValue(nsHttp::Content_Encoding, "compress") && (
-             mResponseHead->ContentType().EqualsLiteral(APPLICATION_COMPRESS) ||
-             mResponseHead->ContentType().EqualsLiteral(APPLICATION_COMPRESS2))) {
-        // clear the Content-Encoding header
-        mResponseHead->ClearHeader(nsHttp::Content_Encoding);
-    }
-}
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel <redirect>
-//-----------------------------------------------------------------------------
-
-static PLDHashOperator
-CopyProperties(const nsAString& aKey, nsIVariant *aData, void *aClosure)
+NS_IMETHODIMP
+nsHttpChannelAuthProvider::Disconnect(nsresult status)
 {
-    nsIWritablePropertyBag* bag = static_cast<nsIWritablePropertyBag*>
-                                             (aClosure);
-    bag->SetProperty(aKey, aData);
-    return PL_DHASH_NEXT;
-}
-
-nsresult
-nsHttpChannel::SetupReplacementChannel(nsIURI       *newURI, 
-                                       nsIChannel   *newChannel,
-                                       PRBool        preserveMethod)
-{
-    LOG(("nsHttpChannel::SetupReplacementChannel "
-         "[this=%p newChannel=%p preserveMethod=%d]",
-         this, newChannel, preserveMethod));
-    PRUint32 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.
-    if (mConnectionInfo->UsingSSL())
-        newLoadFlags &= ~INHIBIT_PERSISTENT_CACHING;
-
-    // Do not pass along LOAD_CHECK_OFFLINE_CACHE
-    newLoadFlags &= ~LOAD_CHECK_OFFLINE_CACHE;
-
-    newChannel->SetLoadGroup(mLoadGroup); 
-    newChannel->SetNotificationCallbacks(mCallbacks);
-    newChannel->SetLoadFlags(newLoadFlags);
-
-    nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel);
-    if (!httpChannel)
-        return NS_OK; // no other options to set
-
-    if (preserveMethod) {
-        nsCOMPtr<nsIUploadChannel> uploadChannel =
-            do_QueryInterface(httpChannel);
-        nsCOMPtr<nsIUploadChannel2> uploadChannel2 =
-            do_QueryInterface(httpChannel);
-        if (mUploadStream && (uploadChannel2 || uploadChannel)) {
-            // rewind upload stream
-            nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mUploadStream);
-            if (seekable)
-                seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
+    mAuthChannel = nsnull;
 
-            // replicate original call to SetUploadStream...
-            if (uploadChannel2) {
-                const char *ctype = mRequestHead.PeekHeader(nsHttp::Content_Type);
-                if (!ctype)
-                    ctype = "";
-                const char *clen  = mRequestHead.PeekHeader(nsHttp::Content_Length);
-                PRInt64 len = clen ? nsCRT::atoll(clen) : -1;
-                uploadChannel2->ExplicitSetUploadStream(
-                        mUploadStream,
-                        nsDependentCString(ctype),
-                        len,
-                        nsDependentCString(mRequestHead.Method()),
-                        mUploadStreamHasHeaders);
-            }
-            else {
-                if (mUploadStreamHasHeaders)
-                    uploadChannel->SetUploadStream(mUploadStream, EmptyCString(),
-                                                   -1);
-                else {
-                    const char *ctype =
-                        mRequestHead.PeekHeader(nsHttp::Content_Type);
-                    const char *clen =
-                        mRequestHead.PeekHeader(nsHttp::Content_Length);
-                    if (!ctype) {
-                        ctype = "application/octet-stream";
-                    }
-                    if (clen) {
-                        uploadChannel->SetUploadStream(mUploadStream,
-                                                       nsDependentCString(ctype),
-                                                       atoi(clen));
-                    }
-                }
-            }
-        }
-        // since preserveMethod is true, we need to ensure that the appropriate 
-        // request method gets set on the channel, regardless of whether or not 
-        // we set the upload stream above. This means SetRequestMethod() will
-        // be called twice if ExplicitSetUploadStream() gets called above.
-
-        httpChannel->SetRequestMethod(nsDependentCString(mRequestHead.Method()));
-    }
-    // convey the referrer if one was used for this channel to the next one
-    if (mReferrer)
-        httpChannel->SetReferrer(mReferrer);
-    // convey the mAllowPipelining flag
-    httpChannel->SetAllowPipelining(mAllowPipelining);
-    // convey the new redirection limit
-    httpChannel->SetRedirectionLimit(mRedirectionLimit - 1);
-
-    nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(newChannel);
-    if (httpInternal) {
-        // convey the mForceAllowThirdPartyCookie flag
-        httpInternal->SetForceAllowThirdPartyCookie(mForceAllowThirdPartyCookie);
-
-        // update the DocumentURI indicator since we are being redirected.
-        // if this was a top-level document channel, then the new channel
-        // should have its mDocumentURI point to newURI; otherwise, we
-        // just need to pass along our mDocumentURI to the new channel.
-        if (newURI && (mURI == mDocumentURI))
-            httpInternal->SetDocumentURI(newURI);
-        else
-            httpInternal->SetDocumentURI(mDocumentURI);
-    } 
-    
-    // convey the mApplyConversion flag (bug 91862)
-    nsCOMPtr<nsIEncodedChannel> encodedChannel = do_QueryInterface(httpChannel);
-    if (encodedChannel)
-        encodedChannel->SetApplyConversion(mApplyConversion);
-
-    // transfer the resume information
-    if (mResuming) {
-        nsCOMPtr<nsIResumableChannel> resumableChannel(do_QueryInterface(newChannel));
-        if (!resumableChannel) {
-            NS_WARNING("Got asked to resume, but redirected to non-resumable channel!");
-            return NS_ERROR_NOT_RESUMABLE;
-        }
-        resumableChannel->ResumeAt(mStartPos, mEntityID);
+    if (mAsyncPromptAuthCancelable) {
+        mAsyncPromptAuthCancelable->Cancel(status);
+        mAsyncPromptAuthCancelable = nsnull;
     }
 
-    // transfer application cache information
-    nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
-        do_QueryInterface(newChannel);
-    if (appCacheChannel) {
-        appCacheChannel->SetApplicationCache(mApplicationCache);
-        appCacheChannel->SetInheritApplicationCache(mInheritApplicationCache);
-        // We purposely avoid transfering mChooseApplicationCache.
-    }
-
-    // transfer any properties
-    nsCOMPtr<nsIWritablePropertyBag> bag(do_QueryInterface(newChannel));
-    if (bag)
-        mPropertyHash.EnumerateRead(CopyProperties, bag.get());
+    NS_IF_RELEASE(mProxyAuthContinuationState);
+    NS_IF_RELEASE(mAuthContinuationState);
 
     return NS_OK;
 }
 
-nsresult
-nsHttpChannel::ProcessRedirection(PRUint32 redirectType)
-{
-    LOG(("nsHttpChannel::ProcessRedirection [this=%p type=%u]\n",
-        this, redirectType));
-
-    const char *location = mResponseHead->PeekHeader(nsHttp::Location);
-
-    // if a location header was not given, then we can't perform the redirect,
-    // so just carry on as though this were a normal response.
-    if (!location)
-        return NS_ERROR_FAILURE;
-
-    // make sure non-ASCII characters in the location header are escaped.
-    nsCAutoString locationBuf;
-    if (NS_EscapeURL(location, -1, esc_OnlyNonASCII, locationBuf))
-        location = locationBuf.get();
-
-    if (mRedirectionLimit == 0) {
-        LOG(("redirection limit reached!\n"));
-        // this error code is fatal, and should be conveyed to our listener.
-        Cancel(NS_ERROR_REDIRECT_LOOP);
-        return NS_ERROR_REDIRECT_LOOP;
-    }
-
-    LOG(("redirecting to: %s [redirection-limit=%u]\n",
-        location, PRUint32(mRedirectionLimit)));
-
-    nsresult rv;
-    nsCOMPtr<nsIChannel> newChannel;
-    nsCOMPtr<nsIURI> newURI;
-
-    // create a new URI using the location header and the current URL
-    // as a base...
-    nsCOMPtr<nsIIOService> ioService;
-    rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
-    if (NS_FAILED(rv)) return rv;
-
-    // the new uri should inherit the origin charset of the current uri
-    nsCAutoString originCharset;
-    rv = mURI->GetOriginCharset(originCharset);
-    if (NS_FAILED(rv))
-        originCharset.Truncate();
-
-    rv = ioService->NewURI(nsDependentCString(location), originCharset.get(), mURI,
-                           getter_AddRefs(newURI));
-    if (NS_FAILED(rv)) return rv;
-
-    if (mApplicationCache) {
-        // if we are redirected to a different origin check if there is a fallback
-        // cache entry to fall back to. we don't care about file strict 
-        // checking, at least mURI is not a file URI.
-        if (!NS_SecurityCompareURIs(mURI, newURI, PR_FALSE)) {
-            PRBool fallingBack;
-            rv = ProcessFallback(&fallingBack);
-            if (NS_SUCCEEDED(rv) && fallingBack) {
-                // do not continue with redirect processing, fallback is in
-                // progress now.
-                return NS_OK;
-            }
-        }
-    }
-
-    // Kill the current cache entry if we are redirecting
-    // back to ourself.
-    PRBool redirectingBackToSameURI = PR_FALSE;
-    if (mCacheEntry && (mCacheAccess & nsICache::ACCESS_WRITE) &&
-        NS_SUCCEEDED(mURI->Equals(newURI, &redirectingBackToSameURI)) &&
-        redirectingBackToSameURI)
-            mCacheEntry->Doom();
-
-    // move the reference of the old location to the new one if the new
-    // one has none.
-    nsCOMPtr<nsIURL> newURL = do_QueryInterface(newURI);
-    if (newURL) {
-        nsCAutoString ref;
-        rv = newURL->GetRef(ref);
-        if (NS_SUCCEEDED(rv) && ref.IsEmpty()) {
-            nsCOMPtr<nsIURL> baseURL(do_QueryInterface(mURI));
-            if (baseURL) {
-                baseURL->GetRef(ref);
-                if (!ref.IsEmpty())
-                    newURL->SetRef(ref);
-            }
-        }
-    }
-
-    // if we need to re-send POST data then be sure to ask the user first.
-    PRBool preserveMethod = (redirectType == 307);
-    if (preserveMethod && mUploadStream) {
-        rv = PromptTempRedirect();
-        if (NS_FAILED(rv)) return rv;
-    }
-
-    rv = ioService->NewChannelFromURI(newURI, getter_AddRefs(newChannel));
-    if (NS_FAILED(rv)) return rv;
-
-    rv = SetupReplacementChannel(newURI, newChannel, preserveMethod);
-    if (NS_FAILED(rv)) return rv;
-
-    PRUint32 redirectFlags;
-    if (redirectType == 301) // Moved Permanently
-        redirectFlags = nsIChannelEventSink::REDIRECT_PERMANENT;
-    else
-        redirectFlags = nsIChannelEventSink::REDIRECT_TEMPORARY;
-
-    // verify that this is a legal redirect
-    rv = gHttpHandler->OnChannelRedirect(this, newChannel, redirectFlags);
-    if (NS_FAILED(rv))
-        return rv;
-
-    // Make sure to do this _after_ calling OnChannelRedirect
-    newChannel->SetOriginalURI(mOriginalURI);    
-
-    // And now, the deprecated way
-    nsCOMPtr<nsIHttpEventSink> httpEventSink;
-    GetCallback(httpEventSink);
-    if (httpEventSink) {
-        // NOTE: nsIHttpEventSink is only used for compatibility with pre-1.8
-        // versions.
-        rv = httpEventSink->OnRedirect(this, newChannel);
-        if (NS_FAILED(rv)) return rv;
-    }
-    // XXX we used to talk directly with the script security manager, but that
-    // should really be handled by the event sink implementation.
-
-    // begin loading the new channel
-    rv = newChannel->AsyncOpen(mListener, mListenerContext);
-    if (NS_FAILED(rv)) return rv;
-
-    // close down this channel
-    Cancel(NS_BINDING_REDIRECTED);
-    
-    // disconnect from our listener
-    mListener = 0;
-    mListenerContext = 0;
-    // and from our callbacks
-    mCallbacks = nsnull;
-    mProgressSink = nsnull;
-    return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel <auth>
-//-----------------------------------------------------------------------------
-
 // buf contains "domain\user"
 static void
 ParseUserDomain(PRUnichar *buf,
                 const PRUnichar **user,
                 const PRUnichar **domain)
 {
     PRUnichar *p = buf;
     while (*p && *p != '\\') ++p;
@@ -3067,41 +316,41 @@ GetAuthPrompt(nsIInterfaceRequestor *ifr
               nsIAuthPrompt2 **result)
 {
     if (!ifreq)
         return;
 
     PRUint32 promptReason;
     if (proxyAuth)
         promptReason = nsIAuthPromptProvider::PROMPT_PROXY;
-    else 
+    else
         promptReason = nsIAuthPromptProvider::PROMPT_NORMAL;
 
     nsCOMPtr<nsIAuthPromptProvider> promptProvider = do_GetInterface(ifreq);
     if (promptProvider)
         promptProvider->GetAuthPrompt(promptReason,
                                       NS_GET_IID(nsIAuthPrompt2),
                                       reinterpret_cast<void**>(result));
     else
         NS_QueryAuthPrompt2(ifreq, result);
 }
 
 // generate credentials for the given challenge, and update the auth cache.
 nsresult
-nsHttpChannel::GenCredsAndSetEntry(nsIHttpAuthenticator *auth,
-                                   PRBool proxyAuth,
-                                   const char *scheme,
-                                   const char *host,
-                                   PRInt32 port,
-                                   const char *directory,
-                                   const char *realm,
-                                   const char *challenge,
-                                   const nsHttpAuthIdentity &ident,
-                                   nsCOMPtr<nsISupports> &sessionState,
-                                   char **result)
+nsHttpChannelAuthProvider::GenCredsAndSetEntry(nsIHttpAuthenticator *auth,
+                                               PRBool                proxyAuth,
+                                               const char           *scheme,
+                                               const char           *host,
+                                               PRInt32               port,
+                                               const char           *directory,
+                                               const char           *realm,
+                                               const char           *challenge,
+                                               const nsHttpAuthIdentity &ident,
+                                               nsCOMPtr<nsISupports>    &sessionState,
+                                               char                    **result)
 {
     nsresult rv;
     PRUint32 authFlags;
 
     rv = auth->GetAuthFlags(&authFlags);
     if (NS_FAILED(rv)) return rv;
 
     nsISupports *ss = sessionState;
@@ -3113,32 +362,32 @@ nsHttpChannel::GenCredsAndSetEntry(nsIHt
 
     if (proxyAuth) {
         continuationState = &mProxyAuthContinuationState;
     } else {
         continuationState = &mAuthContinuationState;
     }
 
     PRUint32 generateFlags;
-    rv = auth->GenerateCredentials(this,
+    rv = auth->GenerateCredentials(mAuthChannel,
                                    challenge,
                                    proxyAuth,
                                    ident.Domain(),
                                    ident.User(),
                                    ident.Password(),
                                    &ss,
                                    &*continuationState,
                                    &generateFlags,
                                    result);
 
     sessionState.swap(ss);
     if (NS_FAILED(rv)) return rv;
 
     // don't log this in release build since it could contain sensitive info.
-#ifdef DEBUG 
+#ifdef DEBUG
     LOG(("generated creds: %s\n", *result));
 #endif
 
     // find out if this authenticator allows reuse of credentials and/or
     // challenge.
     PRBool saveCreds =
         0 != (authFlags & nsIHttpAuthenticator::REUSABLE_CREDENTIALS);
     PRBool saveChallenge =
@@ -3160,97 +409,29 @@ nsHttpChannel::GenCredsAndSetEntry(nsIHt
                                  saveCreds ? *result : nsnull,
                                  saveChallenge ? challenge : nsnull,
                                  saveIdentity ? &ident : nsnull,
                                  sessionState);
     return rv;
 }
 
 nsresult
-nsHttpChannel::ProcessAuthentication(PRUint32 httpStatus)
+nsHttpChannelAuthProvider::PrepareForAuthentication(PRBool proxyAuth)
 {
-    LOG(("nsHttpChannel::ProcessAuthentication [this=%p code=%u]\n",
-        this, httpStatus));
-
-    if (mLoadFlags & LOAD_ANONYMOUS) {
-      return NS_ERROR_NOT_AVAILABLE;
-    }
-
-    const char *challenges;
-    mProxyAuth = (httpStatus == 407);
-
-    nsresult rv = PrepareForAuthentication(mProxyAuth);
-    if (NS_FAILED(rv))
-        return rv;
-
-    if (mProxyAuth) {
-        // only allow a proxy challenge if we have a proxy server configured.
-        // otherwise, we could inadvertantly expose the user's proxy
-        // credentials to an origin server.  We could attempt to proceed as
-        // if we had received a 401 from the server, but why risk flirting
-        // with trouble?  IE similarly rejects 407s when a proxy server is
-        // not configured, so there's no reason not to do the same.
-        if (!mConnectionInfo->UsingHttpProxy()) {
-            LOG(("rejecting 407 when proxy server not configured!\n"));
-            return NS_ERROR_UNEXPECTED;
-        }
-        if (mConnectionInfo->UsingSSL() && !mTransaction->SSLConnectFailed()) {
-            // we need to verify that this challenge came from the proxy
-            // server itself, and not some server on the other side of the
-            // SSL tunnel.
-            LOG(("rejecting 407 from origin server!\n"));
-            return NS_ERROR_UNEXPECTED;
-        }
-        challenges = mResponseHead->PeekHeader(nsHttp::Proxy_Authenticate);
-    }
-    else
-        challenges = mResponseHead->PeekHeader(nsHttp::WWW_Authenticate);
-    NS_ENSURE_TRUE(challenges, NS_ERROR_UNEXPECTED);
-
-    nsCAutoString creds;
-    rv = GetCredentials(challenges, mProxyAuth, creds);
-    if (rv == NS_ERROR_IN_PROGRESS)  {
-        // authentication prompt has been invoked and result
-        // is expected asynchronously
-        mAuthRetryPending = PR_TRUE;
-        // suspend the transaction pump to stop receiving the
-        // unauthenticated content data. We will throw that data
-        // away when user provides credentials or resume the pump
-        // when user refuses to authenticate.
-        LOG(("Suspending the transaction, asynchronously prompting for credentials"));
-        mTransactionPump->Suspend();
-        return NS_OK;
-    }
-    else if (NS_FAILED(rv))
-        LOG(("unable to authenticate\n"));
-    else {
-        // set the authentication credentials
-        if (mProxyAuth)
-            mRequestHead.SetHeader(nsHttp::Proxy_Authorization, creds);
-        else
-            mRequestHead.SetHeader(nsHttp::Authorization, creds);
-
-        mAuthRetryPending = PR_TRUE; // see DoAuthRetry
-    }
-    return rv;
-}
-
-nsresult
-nsHttpChannel::PrepareForAuthentication(PRBool proxyAuth)
-{
-    LOG(("nsHttpChannel::PrepareForAuthentication [this=%p]\n", this));
+    LOG(("nsHttpChannelAuthProvider::PrepareForAuthentication "
+         "[this=%p channel=%p]\n", this, mAuthChannel));
 
     if (!proxyAuth) {
         // reset the current proxy continuation state because our last
         // authentication attempt was completed successfully.
         NS_IF_RELEASE(mProxyAuthContinuationState);
         LOG(("  proxy continuation state has been reset"));
     }
 
-    if (!mConnectionInfo->UsingHttpProxy() || mProxyAuthType.IsEmpty())
+    if (!UsingHttpProxy() || mProxyAuthType.IsEmpty())
         return NS_OK;
 
     // We need to remove any Proxy_Authorization header left over from a
     // non-request based authentication handshake (e.g., for NTLM auth).
 
     nsCAutoString contractId;
     contractId.Assign(NS_HTTP_AUTHENTICATOR_CONTRACTID_PREFIX);
     contractId.Append(mProxyAuthType);
@@ -3262,33 +443,34 @@ nsHttpChannel::PrepareForAuthentication(
         return rv;
 
     PRUint32 precedingAuthFlags;
     rv = precedingAuth->GetAuthFlags(&precedingAuthFlags);
     if (NS_FAILED(rv))
         return rv;
 
     if (!(precedingAuthFlags & nsIHttpAuthenticator::REQUEST_BASED)) {
-        const char *challenges =
-                mResponseHead->PeekHeader(nsHttp::Proxy_Authenticate);
-        if (!challenges) {
+        nsCAutoString challenges;
+        rv = mAuthChannel->GetProxyChallenges(challenges);
+        if (NS_FAILED(rv)) {
             // delete the proxy authorization header because we weren't
             // asked to authenticate
-            mRequestHead.ClearHeader(nsHttp::Proxy_Authorization);
+            rv = mAuthChannel->SetProxyCredentials(EmptyCString());
+            if (NS_FAILED(rv)) return rv;
             LOG(("  cleared proxy authorization header"));
         }
     }
 
     return NS_OK;
 }
 
 nsresult
-nsHttpChannel::GetCredentials(const char *challenges,
-                              PRBool proxyAuth,
-                              nsAFlatCString &creds)
+nsHttpChannelAuthProvider::GetCredentials(const char     *challenges,
+                                          PRBool          proxyAuth,
+                                          nsAFlatCString &creds)
 {
     nsCOMPtr<nsIHttpAuthenticator> auth;
     nsCAutoString challenge;
 
     nsCString authType; // force heap allocation to enable string sharing since
                         // we'll be assigning this value into mAuthType.
 
     // set informations that depend on whether we're authenticating against a
@@ -3301,17 +483,17 @@ nsHttpChannel::GetCredentials(const char
         currentAuthType = &mProxyAuthType;
     } else {
         currentContinuationState = &mAuthContinuationState;
         currentAuthType = &mAuthType;
     }
 
     nsresult rv = NS_ERROR_NOT_AVAILABLE;
     PRBool gotCreds = PR_FALSE;
-    
+
     // figure out which challenge we can handle and which authenticator to use.
     for (const char *eol = challenges - 1; eol; ) {
         const char *p = eol + 1;
 
         // get the challenge string (LF separated -- see nsHttpHeaderArray)
         if ((eol = strchr(p, '\n')) != nsnull)
             challenge.Assign(p, eol - p);
         else
@@ -3329,17 +511,17 @@ nsHttpChannel::GetCredentials(const char
                 continue;
 
             //
             // we allow the routines to run all the way through before we
             // decide if they are valid.
             //
             // we don't worry about the auth cache being altered because that
             // would have been the last step, and if the error is from updating
-            // the authcache it wasn't really altered anyway. -CTN 
+            // the authcache it wasn't really altered anyway. -CTN
             //
             // at this point the code is really only useful for client side
             // errors (it will not automatically fail over to do a different
             // auth type if the server keeps rejecting what is being sent, even
             // if a particular auth method only knows 1 thing, like a
             // non-identity based authentication method)
             //
             rv = GetCredentialsForChallenge(challenge.get(), authType.get(),
@@ -3374,61 +556,63 @@ nsHttpChannel::GetCredentials(const char
 
         rv = GetCredentials(challenges, proxyAuth, creds);
     }
 
     return rv;
 }
 
 nsresult
-nsHttpChannel::GetAuthorizationMembers(PRBool proxyAuth,
-                                       nsCSubstring& scheme,
-                                       const char*& host,
-                                       PRInt32& port,
-                                       nsCSubstring& path,
-                                       nsHttpAuthIdentity*& ident,
-                                       nsISupports**& continuationState)
+nsHttpChannelAuthProvider::GetAuthorizationMembers(PRBool               proxyAuth,
+                                                   nsCSubstring&        scheme,
+                                                   const char*&         host,
+                                                   PRInt32&             port,
+                                                   nsCSubstring&        path,
+                                                   nsHttpAuthIdentity*& ident,
+                                                   nsISupports**&       continuationState)
 {
     if (proxyAuth) {
-        NS_ASSERTION (mConnectionInfo->UsingHttpProxy(), "proxyAuth is true, but no HTTP proxy is configured!");
+        NS_ASSERTION (UsingHttpProxy(),
+                      "proxyAuth is true, but no HTTP proxy is configured!");
 
-        host = mConnectionInfo->ProxyHost();
-        port = mConnectionInfo->ProxyPort();
+        host = ProxyHost();
+        port = ProxyPort();
         ident = &mProxyIdent;
         scheme.AssignLiteral("http");
 
         continuationState = &mProxyAuthContinuationState;
     }
     else {
-        host = mConnectionInfo->Host();
-        port = mConnectionInfo->Port();
+        host = Host();
+        port = Port();
         ident = &mIdent;
 
         nsresult rv;
         rv = GetCurrentPath(path);
         if (NS_FAILED(rv)) return rv;
 
         rv = mURI->GetScheme(scheme);
         if (NS_FAILED(rv)) return rv;
 
         continuationState = &mAuthContinuationState;
     }
 
     return NS_OK;
 }
 
 nsresult
-nsHttpChannel::GetCredentialsForChallenge(const char *challenge,
-                                          const char *authType,
-                                          PRBool proxyAuth,
-                                          nsIHttpAuthenticator *auth,
-                                          nsAFlatCString &creds)
+nsHttpChannelAuthProvider::GetCredentialsForChallenge(const char *challenge,
+                                                      const char *authType,
+                                                      PRBool      proxyAuth,
+                                                      nsIHttpAuthenticator *auth,
+                                                      nsAFlatCString     &creds)
 {
-    LOG(("nsHttpChannel::GetCredentialsForChallenge [this=%p proxyAuth=%d challenges=%s]\n",
-        this, proxyAuth, challenge));
+    LOG(("nsHttpChannelAuthProvider::GetCredentialsForChallenge "
+         "[this=%p channel=%p proxyAuth=%d challenges=%s]\n",
+        this, mAuthChannel, proxyAuth, challenge));
 
     // this getter never fails
     nsHttpAuthCache *authCache = gHttpHandler->AuthCache();
 
     PRUint32 authFlags;
     nsresult rv = auth->GetAuthFlags(&authFlags);
     if (NS_FAILED(rv)) return rv;
 
@@ -3451,17 +635,18 @@ nsHttpChannel::GetCredentialsForChalleng
     // or a webserver
     const char *host;
     PRInt32 port;
     nsHttpAuthIdentity *ident;
     nsCAutoString path, scheme;
     PRBool identFromURI = PR_FALSE;
     nsISupports **continuationState;
 
-    rv = GetAuthorizationMembers(proxyAuth, scheme, host, port, path, ident, continuationState);
+    rv = GetAuthorizationMembers(proxyAuth, scheme, host, port,
+                                 path, ident, continuationState);
     if (NS_FAILED(rv)) return rv;
 
     if (!proxyAuth) {
         // if this is the first challenge, then try using the identity
         // specified in the URL.
         if (mIdent.IsEmpty()) {
             GetIdentityFromURI(authFlags, mIdent);
             identFromURI = !mIdent.IsEmpty();
@@ -3470,49 +655,53 @@ nsHttpChannel::GetCredentialsForChalleng
 
     //
     // if we already tried some credentials for this transaction, then
     // we need to possibly clear them from the cache, unless the credentials
     // in the cache have changed, in which case we'd want to give them a
     // try instead.
     //
     nsHttpAuthEntry *entry = nsnull;
-    authCache->GetAuthEntryForDomain(scheme.get(), host, port, realm.get(), &entry);
+    authCache->GetAuthEntryForDomain(scheme.get(), host, port,
+                                     realm.get(), &entry);
 
     // hold reference to the auth session state (in case we clear our
     // reference to the entry).
     nsCOMPtr<nsISupports> sessionStateGrip;
     if (entry)
         sessionStateGrip = entry->mMetaData;
 
     // for digest auth, maybe our cached nonce value simply timed out...
     PRBool identityInvalid;
     nsISupports *sessionState = sessionStateGrip;
-    rv = auth->ChallengeReceived(this,
+    rv = auth->ChallengeReceived(mAuthChannel,
                                  challenge,
                                  proxyAuth,
                                  &sessionState,
                                  &*continuationState,
                                  &identityInvalid);
     sessionStateGrip.swap(sessionState);
     if (NS_FAILED(rv)) return rv;
 
     LOG(("  identity invalid = %d\n", identityInvalid));
 
     if (identityInvalid) {
         if (entry) {
             if (ident->Equals(entry->Identity())) {
                 LOG(("  clearing bad auth cache entry\n"));
                 // ok, we've already tried this user identity, so clear the
                 // corresponding entry from the auth cache.
-                authCache->ClearAuthEntry(scheme.get(), host, port, realm.get());
+                authCache->ClearAuthEntry(scheme.get(), host,
+                                          port, realm.get());
                 entry = nsnull;
                 ident->Clear();
             }
-            else if (!identFromURI || nsCRT::strcmp(ident->User(), entry->Identity().User()) == 0) {
+            else if (!identFromURI ||
+                     nsCRT::strcmp(ident->User(),
+                                   entry->Identity().User()) == 0) {
                 LOG(("  taking identity from auth cache\n"));
                 // the password from the auth cache is more likely to be
                 // correct than the one in the URL.  at least, we know that it
                 // works with the given username.  it is possible for a server
                 // to distinguish logons based on the supplied password alone,
                 // but that would be quite unusual... and i don't think we need
                 // to worry about such unorthodox cases.
                 ident->Set(entry->Identity());
@@ -3527,37 +716,37 @@ nsHttpChannel::GetCredentialsForChalleng
         else if (!identFromURI) {
             // hmm... identity invalid, but no auth entry!  the realm probably
             // changed (see bug 201986).
             ident->Clear();
         }
 
         if (!entry && ident->IsEmpty()) {
             PRUint32 level = nsIAuthPrompt2::LEVEL_NONE;
-            if (scheme.EqualsLiteral("https"))
+            if (mUsingSSL)
                 level = nsIAuthPrompt2::LEVEL_SECURE;
             else if (authFlags & nsIHttpAuthenticator::IDENTITY_ENCRYPTED)
                 level = nsIAuthPrompt2::LEVEL_PW_ENCRYPTED;
 
             // at this point we are forced to interact with the user to get
             // their username and password for this domain.
-            rv = PromptForIdentity(level, proxyAuth, realm.get(), 
+            rv = PromptForIdentity(level, proxyAuth, realm.get(),
                                    authType, authFlags, *ident);
             if (NS_FAILED(rv)) return rv;
             identFromURI = PR_FALSE;
         }
     }
 
     if (identFromURI) {
         // Warn the user before automatically using the identity from the URL
         // to automatically log them into a site (see bug 232567).
         if (!ConfirmAuth(NS_LITERAL_STRING("AutomaticAuth"), PR_FALSE)) {
             // calling cancel here sets our mStatus and aborts the HTTP
             // transaction, which prevents OnDataAvailable events.
-            Cancel(NS_ERROR_ABORT);
+            mAuthChannel->Cancel(NS_ERROR_ABORT);
             // this return code alone is not equivalent to Cancel, since
             // it only instructs our caller that authentication failed.
             // without an explicit call to Cancel, our caller would just
             // load the page that accompanies the HTTP auth challenge.
             return NS_ERROR_ABORT;
         }
     }
 
@@ -3567,47 +756,62 @@ nsHttpChannel::GetCredentialsForChalleng
     // always store the credentials we're trying now so that they will be used
     // on subsequent links.  This will potentially remove good credentials from
     // the cache.  This is ok as we don't want to use cached credentials if the
     // user specified something on the URI or in another manner.  This is so
     // that we don't transparently authenticate as someone they're not
     // expecting to authenticate as.
     //
     nsXPIDLCString result;
-    rv = GenCredsAndSetEntry(auth, proxyAuth, scheme.get(), host, port, path.get(),
-                             realm.get(), challenge, *ident, sessionStateGrip,
-                             getter_Copies(result));
+    rv = GenCredsAndSetEntry(auth, proxyAuth, scheme.get(), host, port,
+                             path.get(), realm.get(), challenge, *ident,
+                             sessionStateGrip, getter_Copies(result));
     if (NS_SUCCEEDED(rv))
         creds = result;
     return rv;
 }
 
+inline void
+GetAuthType(const char *challenge, nsCString &authType)
+{
+    const char *p;
+
+    // get the challenge type
+    if ((p = strchr(challenge, ' ')) != nsnull)
+        authType.Assign(challenge, p - challenge);
+    else
+        authType.Assign(challenge);
+}
+
 nsresult
-nsHttpChannel::GetAuthenticator(const char *challenge,
-                                nsCString &authType,
-                                nsIHttpAuthenticator **auth)
+nsHttpChannelAuthProvider::GetAuthenticator(const char            *challenge,
+                                            nsCString             &authType,
+                                            nsIHttpAuthenticator **auth)
 {
-    LOG(("nsHttpChannel::GetAuthenticator [this=%p]\n", this));
+    LOG(("nsHttpChannelAuthProvider::GetAuthenticator [this=%p channel=%p]\n",
+        this, mAuthChannel));
 
     GetAuthType(challenge, authType);
- 
+
     // normalize to lowercase
     ToLowerCase(authType);
 
     nsCAutoString contractid;
     contractid.Assign(NS_HTTP_AUTHENTICATOR_CONTRACTID_PREFIX);
     contractid.Append(authType);
 
     return CallGetService(contractid.get(), auth);
 }
 
 void
-nsHttpChannel::GetIdentityFromURI(PRUint32 authFlags, nsHttpAuthIdentity &ident)
+nsHttpChannelAuthProvider::GetIdentityFromURI(PRUint32            authFlags,
+                                              nsHttpAuthIdentity &ident)
 {
-    LOG(("nsHttpChannel::GetIdentityFromURI [this=%p]\n", this));
+    LOG(("nsHttpChannelAuthProvider::GetIdentityFromURI [this=%p channel=%p]\n",
+        this, mAuthChannel));
 
     nsAutoString userBuf;
     nsAutoString passBuf;
 
     // XXX i18n
     nsCAutoString buf;
     mURI->GetUsername(buf);
     if (!buf.IsEmpty()) {
@@ -3615,22 +819,25 @@ nsHttpChannel::GetIdentityFromURI(PRUint
         CopyASCIItoUTF16(buf, userBuf);
         mURI->GetPassword(buf);
         if (!buf.IsEmpty()) {
             NS_UnescapeURL(buf);
             CopyASCIItoUTF16(buf, passBuf);
         }
     }
 
-    if (!userBuf.IsEmpty())
-        SetIdent(ident, authFlags, (PRUnichar *) userBuf.get(), (PRUnichar *) passBuf.get());
+    if (!userBuf.IsEmpty()) {
+        SetIdent(ident, authFlags, (PRUnichar *) userBuf.get(),
+                 (PRUnichar *) passBuf.get());
+    }
 }
 
 void
-nsHttpChannel::ParseRealm(const char *challenge, nsACString &realm)
+nsHttpChannelAuthProvider::ParseRealm(const char *challenge,
+                                      nsACString &realm)
 {
     //
     // From RFC2617 section 1.2, the realm value is defined as such:
     //
     //    realm       = "realm" "=" realm-value
     //    realm-value = quoted-string
     //
     // but, we'll accept anything after the the "=" up to the first space, or
@@ -3650,65 +857,76 @@ nsHttpChannel::ParseRealm(const char *ch
            // Loop through all the string characters to find the closing
            // quote, ignoring escaped quotes.
             if (*end == '"' && end[-1] != '\\')
                 break;
             ++end;
         }
 
         if (!has_quote)
-            end = strchr(p, ' '); 
+            end = strchr(p, ' ');
         if (end)
             realm.Assign(p, end - p);
         else
             realm.Assign(p);
     }
 }
 
 
 class nsHTTPAuthInformation : public nsAuthInformationHolder {
 public:
     nsHTTPAuthInformation(PRUint32 aFlags, const nsString& aRealm,
                           const nsCString& aAuthType)
         : nsAuthInformationHolder(aFlags, aRealm, aAuthType) {}
 
-    void SetToHttpAuthIdentity(PRUint32 authFlags, nsHttpAuthIdentity& identity);
+    void SetToHttpAuthIdentity(PRUint32 authFlags,
+                               nsHttpAuthIdentity& identity);
 };
 
 void
-nsHTTPAuthInformation::SetToHttpAuthIdentity(PRUint32 authFlags, nsHttpAuthIdentity& identity)
+nsHTTPAuthInformation::SetToHttpAuthIdentity(PRUint32 authFlags,
+                                             nsHttpAuthIdentity& identity)
 {
     identity.Set(Domain().get(), User().get(), Password().get());
 }
 
 nsresult
-nsHttpChannel::PromptForIdentity(PRUint32    level,
-                                 PRBool      proxyAuth,
-                                 const char *realm,
-                                 const char *authType,
-                                 PRUint32 authFlags,
-                                 nsHttpAuthIdentity &ident)
+nsHttpChannelAuthProvider::PromptForIdentity(PRUint32            level,
+                                             PRBool              proxyAuth,
+                                             const char         *realm,
+                                             const char         *authType,
+                                             PRUint32            authFlags,
+                                             nsHttpAuthIdentity &ident)
 {
-    LOG(("nsHttpChannel::PromptForIdentity [this=%p]\n", this));
+    LOG(("nsHttpChannelAuthProvider::PromptForIdentity [this=%p channel=%p]\n",
+        this, mAuthChannel));
+
+    nsresult rv;
+
+    nsCOMPtr<nsIInterfaceRequestor> callbacks;
+    rv = mAuthChannel->GetNotificationCallbacks(getter_AddRefs(callbacks));
+    if (NS_FAILED(rv)) return rv;
+
+    nsCOMPtr<nsILoadGroup> loadGroup;
+    rv = mAuthChannel->GetLoadGroup(getter_AddRefs(loadGroup));
+    if (NS_FAILED(rv)) return rv;
 
     nsCOMPtr<nsIAuthPrompt2> authPrompt;
-    GetAuthPrompt(mCallbacks, proxyAuth, getter_AddRefs(authPrompt));
-    if (!authPrompt && mLoadGroup) {
+    GetAuthPrompt(callbacks, proxyAuth, getter_AddRefs(authPrompt));
+    if (!authPrompt && loadGroup) {
         nsCOMPtr<nsIInterfaceRequestor> cbs;
-        mLoadGroup->GetNotificationCallbacks(getter_AddRefs(cbs));
+        loadGroup->GetNotificationCallbacks(getter_AddRefs(cbs));
         GetAuthPrompt(cbs, proxyAuth, getter_AddRefs(authPrompt));
     }
     if (!authPrompt)
         return NS_ERROR_NO_INTERFACE;
 
     // XXX i18n: need to support non-ASCII realm strings (see bug 41489)
     NS_ConvertASCIItoUTF16 realmU(realm);
 
-    nsresult rv;
-
     // prompt the user...
     PRUint32 promptFlags = 0;
     if (proxyAuth)
     {
         promptFlags |= nsIAuthInformation::AUTH_PROXY;
         if (mTriedProxyAuth)
             promptFlags |= nsIAuthInformation::PREVIOUS_FAILED;
         mTriedProxyAuth = PR_TRUE;
@@ -3724,107 +942,123 @@ nsHttpChannel::PromptForIdentity(PRUint3
         promptFlags |= nsIAuthInformation::NEED_DOMAIN;
 
     nsRefPtr<nsHTTPAuthInformation> holder =
         new nsHTTPAuthInformation(promptFlags, realmU,
                                   nsDependentCString(authType));
     if (!holder)
         return NS_ERROR_OUT_OF_MEMORY;
 
-    rv = authPrompt->AsyncPromptAuth(this, this, nsnull, level, holder,
-                     getter_AddRefs(mAsyncPromptAuthCancelable));
+    nsCOMPtr<nsIChannel> channel(do_QueryInterface(mAuthChannel, &rv));
+    if (NS_FAILED(rv)) return rv;
+
+    rv =
+        authPrompt->AsyncPromptAuth(channel, this, nsnull, level, holder,
+                                    getter_AddRefs(mAsyncPromptAuthCancelable));
 
     if (NS_SUCCEEDED(rv)) {
         // indicate using this error code that authentication prompt
         // result is expected asynchronously
         rv = NS_ERROR_IN_PROGRESS;
     }
     else {
         // Fall back to synchronous prompt
         PRBool retval = PR_FALSE;
-        rv = authPrompt->PromptAuth(this, level, holder, &retval);
+        rv = authPrompt->PromptAuth(channel, level, holder, &retval);
         if (NS_FAILED(rv))
             return rv;
 
         if (!retval)
             rv = NS_ERROR_ABORT;
         else
             holder->SetToHttpAuthIdentity(authFlags, ident);
     }
 
     // remember that we successfully showed the user an auth dialog
     if (!proxyAuth)
         mSuppressDefensiveAuth = PR_TRUE;
 
     return rv;
 }
 
-NS_IMETHODIMP nsHttpChannel::OnAuthAvailable(nsISupports *aContext,
-                                             nsIAuthInformation *aAuthInfo)
+NS_IMETHODIMP nsHttpChannelAuthProvider::OnAuthAvailable(nsISupports *aContext,
+                                                         nsIAuthInformation *aAuthInfo)
 {
-    LOG(("nsHttpChannel::OnAuthAvailable [this=%p]", this));
+    LOG(("nsHttpChannelAuthProvider::OnAuthAvailable [this=%p channel=%p]",
+        this, mAuthChannel));
+
     mAsyncPromptAuthCancelable = nsnull;
+    if (!mAuthChannel)
+        return NS_OK;
 
     nsresult rv;
 
     const char *host;
     PRInt32 port;
     nsHttpAuthIdentity *ident;
     nsCAutoString path, scheme;
     nsISupports **continuationState;
-    rv = GetAuthorizationMembers(mProxyAuth, scheme, host, port, path, ident, continuationState);
+    rv = GetAuthorizationMembers(mProxyAuth, scheme, host, port,
+                                 path, ident, continuationState);
     if (NS_FAILED(rv))
         OnAuthCancelled(aContext, PR_FALSE);
 
     nsCAutoString realm;
     ParseRealm(mCurrentChallenge.get(), realm);
 
     nsHttpAuthCache *authCache = gHttpHandler->AuthCache();
     nsHttpAuthEntry *entry = nsnull;
-    authCache->GetAuthEntryForDomain(scheme.get(), host, port, realm.get(), &entry);
+    authCache->GetAuthEntryForDomain(scheme.get(), host, port,
+                                     realm.get(), &entry);
 
     nsCOMPtr<nsISupports> sessionStateGrip;
     if (entry)
         sessionStateGrip = entry->mMetaData;
 
     nsAuthInformationHolder* holder =
             static_cast<nsAuthInformationHolder*>(aAuthInfo);
     ident->Set(holder->Domain().get(),
                holder->User().get(),
                holder->Password().get());
 
     nsCAutoString unused;
     nsCOMPtr<nsIHttpAuthenticator> auth;
-    rv = GetAuthenticator(mCurrentChallenge.get(), unused, getter_AddRefs(auth));
+    rv = GetAuthenticator(mCurrentChallenge.get(), unused,
+                          getter_AddRefs(auth));
     if (NS_FAILED(rv)) {
         NS_ASSERTION(PR_FALSE, "GetAuthenticator failed");
         OnAuthCancelled(aContext, PR_TRUE);
         return NS_OK;
     }
 
     nsXPIDLCString creds;
     rv = GenCredsAndSetEntry(auth, mProxyAuth,
                              scheme.get(), host, port, path.get(),
-                             realm.get(), mCurrentChallenge.get(), *ident, sessionStateGrip,
-                             getter_Copies(creds));
+                             realm.get(), mCurrentChallenge.get(), *ident,
+                             sessionStateGrip, getter_Copies(creds));
 
     mCurrentChallenge.Truncate();
     if (NS_FAILED(rv)) {
         OnAuthCancelled(aContext, PR_TRUE);
         return NS_OK;
     }
 
     return ContinueOnAuthAvailable(creds);
 }
 
-NS_IMETHODIMP nsHttpChannel::OnAuthCancelled(nsISupports *aContext, 
-                                             PRBool userCancel)
+NS_IMETHODIMP nsHttpChannelAuthProvider::OnAuthCancelled(nsISupports *aContext,
+                                                         PRBool      userCancel)
 {
-    LOG(("nsHttpChannel::OnAuthCancelled [this=%p]", this));
+    LOG(("nsHttpChannelAuthProvider::OnAuthCancelled [this=%p channel=%p]",
+        this, mAuthChannel));
+
     mAsyncPromptAuthCancelable = nsnull;
+    if (!mAuthChannel)
+        return NS_OK;
+
     if (userCancel) {
         if (!mRemainingChallenges.IsEmpty()) {
             // there are still some challenges to process, do so
             nsresult rv;
 
             nsCAutoString creds;
             rv = GetCredentials(mRemainingChallenges.get(), mProxyAuth, creds);
             if (NS_SUCCEEDED(rv)) {
@@ -3840,73 +1074,65 @@ NS_IMETHODIMP nsHttpChannel::OnAuthCance
                 // to provide the credentials
                 return NS_OK;
             }
 
             // otherwise, we failed...
         }
 
         mRemainingChallenges.Truncate();
-
-        // ensure call of OnStartRequest of the current listener here,
-        // it would not be called otherwise at all
-        nsresult rv = CallOnStartRequest();
+    }
 
-        // drop mAuthRetryPending flag and resume the transaction
-        // this resumes load of the unauthenticated content data
-        mAuthRetryPending = PR_FALSE;
-        LOG(("Resuming the transaction, user cancelled the auth dialog"));
-        mTransactionPump->Resume();
-
-        if (NS_FAILED(rv))
-            mTransactionPump->Cancel(rv);
-    }
+    mAuthChannel->OnAuthCancelled(userCancel);
 
     return NS_OK;
 }
 
 nsresult
-nsHttpChannel::ContinueOnAuthAvailable(const nsCSubstring& creds)
+nsHttpChannelAuthProvider::ContinueOnAuthAvailable(const nsCSubstring& creds)
 {
+    nsresult rv;
     if (mProxyAuth)
-        mRequestHead.SetHeader(nsHttp::Proxy_Authorization, creds);
+        rv = mAuthChannel->SetProxyCredentials(creds);
     else
-        mRequestHead.SetHeader(nsHttp::Authorization, creds);
+        rv = mAuthChannel->SetWWWCredentials(creds);
+    if (NS_FAILED(rv)) return rv;
 
     // drop our remaining list of challenges.  We don't need them, because we
     // have now authenticated against a challenge and will be sending that
     // information to the server (or proxy).  If it doesn't accept our
     // authentication it'll respond with failure and resend the challenge list
     mRemainingChallenges.Truncate();
 
-    // setting mAuthRetryPending flag and resuming the transaction
-    // triggers process of throwing away the unauthenticated data already
-    // coming from the network
-    mAuthRetryPending = PR_TRUE;
-    LOG(("Resuming the transaction, we got credentials from user"));
-    mTransactionPump->Resume();
+    mAuthChannel->OnAuthAvailable();
 
     return NS_OK;
 }
 
 PRBool
-nsHttpChannel::ConfirmAuth(const nsString &bundleKey, PRBool doYesNoPrompt)
+nsHttpChannelAuthProvider::ConfirmAuth(const nsString &bundleKey,
+                                       PRBool          doYesNoPrompt)
 {
     // skip prompting the user if
     //   1) we've already prompted the user
     //   2) we're not a toplevel channel
     //   3) the userpass length is less than the "phishy" threshold
 
-    if (mSuppressDefensiveAuth || !(mLoadFlags & LOAD_INITIAL_DOCUMENT_URI))
+    PRUint32 loadFlags;
+    nsresult rv = mAuthChannel->GetLoadFlags(&loadFlags);
+    if (NS_FAILED(rv)) return rv;
+
+    if (mSuppressDefensiveAuth ||
+        !(loadFlags & nsIChannel::LOAD_INITIAL_DOCUMENT_URI))
         return PR_TRUE;
 
-    nsresult rv;
     nsCAutoString userPass;
     rv = mURI->GetUserPass(userPass);
-    if (NS_FAILED(rv) || (userPass.Length() < gHttpHandler->PhishyUserPassLength()))
+    if (NS_FAILED(rv) ||
+        (userPass.Length() < gHttpHandler->PhishyUserPassLength()))
         return PR_TRUE;
 
     // we try to confirm by prompting the user.  if we cannot do so, then
     // assume the user said ok.  this is done to keep things working in
     // embedded builds, where the string bundle might not be present, etc.
 
     nsCOMPtr<nsIStringBundleService> bundleService =
             do_GetService(NS_STRINGBUNDLE_CONTRACTID);
@@ -3930,73 +1156,65 @@ nsHttpChannel::ConfirmAuth(const nsStrin
 
     NS_ConvertUTF8toUTF16 ucsHost(host), ucsUser(user);
     const PRUnichar *strs[2] = { ucsHost.get(), ucsUser.get() };
 
     nsXPIDLString msg;
     bundle->FormatStringFromName(bundleKey.get(), strs, 2, getter_Copies(msg));
     if (!msg)
         return PR_TRUE;
-    
+
+    nsCOMPtr<nsIInterfaceRequestor> callbacks;
+    rv = mAuthChannel->GetNotificationCallbacks(getter_AddRefs(callbacks));
+    if (NS_FAILED(rv)) return rv;
+
+    nsCOMPtr<nsILoadGroup> loadGroup;
+    rv = mAuthChannel->GetLoadGroup(getter_AddRefs(loadGroup));
+    if (NS_FAILED(rv)) return rv;
+
     nsCOMPtr<nsIPrompt> prompt;
-    GetCallback(prompt);
+    NS_QueryNotificationCallbacks(callbacks, loadGroup, NS_GET_IID(nsIPrompt),
+                                  getter_AddRefs(prompt));
     if (!prompt)
         return PR_TRUE;
 
     // do not prompt again
     mSuppressDefensiveAuth = PR_TRUE;
 
     PRBool confirmed;
     if (doYesNoPrompt) {
         PRInt32 choice;
         PRBool checkState;
         rv = prompt->ConfirmEx(nsnull, msg,
                                nsIPrompt::BUTTON_POS_1_DEFAULT +
                                nsIPrompt::STD_YES_NO_BUTTONS,
-                               nsnull, nsnull, nsnull, nsnull, &checkState, &choice);
+                               nsnull, nsnull, nsnull, nsnull,
+                               &checkState, &choice);
         if (NS_FAILED(rv))
             return PR_TRUE;
 
         confirmed = choice == 0;
     }
     else {
         rv = prompt->Confirm(nsnull, msg, &confirmed);
         if (NS_FAILED(rv))
             return PR_TRUE;
     }
 
     return confirmed;
 }
 
 void
-nsHttpChannel::CheckForSuperfluousAuth()
-{
-    // we've been called because it has been determined that this channel is
-    // getting loaded without taking the userpass from the URL.  if the URL
-    // contained a userpass, then (provided some other conditions are true),
-    // we'll give the user an opportunity to abort the channel as this might be
-    // an attempt to spoof a different site (see bug 232567).
-    if (!mAuthRetryPending) {
-        // ask user...
-        if (!ConfirmAuth(NS_LITERAL_STRING("SuperfluousAuth"), PR_TRUE)) {
-            // calling cancel here sets our mStatus and aborts the HTTP
-            // transaction, which prevents OnDataAvailable events.
-            Cancel(NS_ERROR_ABORT);
-        }
-    }
-}
-
-void
-nsHttpChannel::SetAuthorizationHeader(nsHttpAuthCache *authCache,
-                                      nsHttpAtom header,
-                                      const char *scheme,
-                                      const char *host,
-                                      PRInt32 port,
-                                      const char *path,
-                                      nsHttpAuthIdentity &ident)
+nsHttpChannelAuthProvider::SetAuthorizationHeader(nsHttpAuthCache    *authCache,
+                                                  nsHttpAtom          header,
+                                                  const char         *scheme,
+                                                  const char         *host,
+                                                  PRInt32             port,
+                                                  const char         *path,
+                                                  nsHttpAuthIdentity &ident)
 {
     nsHttpAuthEntry *entry = nsnull;
     nsresult rv;
 
     // set informations that depend on whether
     // we're authenticating against a proxy
     // or a webserver
     nsISupports **continuationState;
@@ -4039,2112 +1257,52 @@ nsHttpChannel::SetAuthorizationHeader(ns
         // credentials.  if the identity is from the URI, then we cannot use
         // the stored credentials.
         if ((!creds[0] || identFromURI) && challenge[0]) {
             nsCOMPtr<nsIHttpAuthenticator> auth;
             nsCAutoString unused;
             rv = GetAuthenticator(challenge, unused, getter_AddRefs(auth));
             if (NS_SUCCEEDED(rv)) {
                 PRBool proxyAuth = (header == nsHttp::Proxy_Authorization);
-                rv = GenCredsAndSetEntry(auth, proxyAuth, scheme, host, port, path,
-                                         entry->Realm(), challenge, ident,
+                rv = GenCredsAndSetEntry(auth, proxyAuth, scheme, host, port,
+                                         path, entry->Realm(), challenge, ident,
                                          entry->mMetaData, getter_Copies(temp));
                 if (NS_SUCCEEDED(rv))
                     creds = temp.get();
 
                 // make sure the continuation state is null since we do not
                 // support mixing preemptive and 'multirequest' authentication.
                 NS_IF_RELEASE(*continuationState);
             }
         }
         if (creds[0]) {
             LOG(("   adding \"%s\" request header\n", header.get()));
-            mRequestHead.SetHeader(header, nsDependentCString(creds));
+            if (header == nsHttp::Proxy_Authorization)
+                mAuthChannel->SetProxyCredentials(nsDependentCString(creds));
+            else
+                mAuthChannel->SetWWWCredentials(nsDependentCString(creds));
 
             // suppress defensive auth prompting for this channel since we know
             // that we already prompted at least once this session.  we only do
             // this for non-proxy auth since the URL's userpass is not used for
             // proxy auth.
             if (header == nsHttp::Authorization)
                 mSuppressDefensiveAuth = PR_TRUE;
         }
         else
             ident.Clear(); // don't remember the identity
     }
 }
 
-void
-nsHttpChannel::AddAuthorizationHeaders()
-{
-    LOG(("nsHttpChannel::AddAuthorizationHeaders? [this=%p]\n", this));
-
-    if (mLoadFlags & LOAD_ANONYMOUS) {
-      return;
-    }
-
-    // this getter never fails
-    nsHttpAuthCache *authCache = gHttpHandler->AuthCache();
-
-    // check if proxy credentials should be sent
-    const char *proxyHost = mConnectionInfo->ProxyHost();
-    if (proxyHost && mConnectionInfo->UsingHttpProxy())
-        SetAuthorizationHeader(authCache, nsHttp::Proxy_Authorization,
-                               "http", proxyHost, mConnectionInfo->ProxyPort(),
-                               nsnull, // proxy has no path
-                               mProxyIdent);
-
-    // check if server credentials should be sent
-    nsCAutoString path, scheme;
-    if (NS_SUCCEEDED(GetCurrentPath(path)) &&
-        NS_SUCCEEDED(mURI->GetScheme(scheme))) {
-        SetAuthorizationHeader(authCache, nsHttp::Authorization,
-                               scheme.get(),
-                               mConnectionInfo->Host(),
-                               mConnectionInfo->Port(),
-                               path.get(),
-                               mIdent);
-    }
-}
-
 nsresult
-nsHttpChannel::GetCurrentPath(nsACString &path)
+nsHttpChannelAuthProvider::GetCurrentPath(nsACString &path)
 {
     nsresult rv;
     nsCOMPtr<nsIURL> url = do_QueryInterface(mURI);
     if (url)
         rv = url->GetDirectory(path);
     else
         rv = mURI->GetPath(path);
     return rv;
 }
 
-//-----------------------------------------------------------------------------
-// nsHttpChannel::nsISupports
-//-----------------------------------------------------------------------------
-
-NS_IMPL_ADDREF_INHERITED(nsHttpChannel, nsHashPropertyBag)
-NS_IMPL_RELEASE_INHERITED(nsHttpChannel, nsHashPropertyBag)
-
-NS_INTERFACE_MAP_BEGIN(nsHttpChannel)
-    NS_INTERFACE_MAP_ENTRY(nsIRequest)
-    NS_INTERFACE_MAP_ENTRY(nsIChannel)
-    NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
-    NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
-    NS_INTERFACE_MAP_ENTRY(nsIHttpChannel)
-    NS_INTERFACE_MAP_ENTRY(nsICachingChannel)
-    NS_INTERFACE_MAP_ENTRY(nsIUploadChannel)
-    NS_INTERFACE_MAP_ENTRY(nsIUploadChannel2)
-    NS_INTERFACE_MAP_ENTRY(nsICacheListener)
-    NS_INTERFACE_MAP_ENTRY(nsIEncodedChannel)
-    NS_INTERFACE_MAP_ENTRY(nsIHttpChannelInternal)
-    NS_INTERFACE_MAP_ENTRY(nsIResumableChannel)
-    NS_INTERFACE_MAP_ENTRY(nsITransportEventSink)
-    NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
-    NS_INTERFACE_MAP_ENTRY(nsIProtocolProxyCallback)
-    NS_INTERFACE_MAP_ENTRY(nsIProxiedChannel)
-    NS_INTERFACE_MAP_ENTRY(nsITraceableChannel)
-    NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheContainer)
-    NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheChannel)
-    NS_INTERFACE_MAP_ENTRY(nsIAuthPromptCallback)
-NS_INTERFACE_MAP_END_INHERITING(nsHashPropertyBag)
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel::nsIRequest
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsHttpChannel::GetName(nsACString &aName)
-{
-    aName = mSpec;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::IsPending(PRBool *value)
-{
-    NS_ENSURE_ARG_POINTER(value);
-    *value = mIsPending;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetStatus(nsresult *aStatus)
-{
-    NS_ENSURE_ARG_POINTER(aStatus);
-    *aStatus = mStatus;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::Cancel(nsresult status)
-{
-    LOG(("nsHttpChannel::Cancel [this=%p status=%x]\n", this, status));
-    if (mCanceled) {
-        LOG(("  ignoring; already canceled\n"));
-        return NS_OK;
-    }
-    mCanceled = PR_TRUE;
-    mStatus = status;
-    if (mProxyRequest)
-        mProxyRequest->Cancel(status);
-    if (mTransaction)
-        gHttpHandler->CancelTransaction(mTransaction, status);
-    if (mTransactionPump)
-        mTransactionPump->Cancel(status);
-    if (mCachePump)
-        mCachePump->Cancel(status);
-    if (mAsyncPromptAuthCancelable)
-        mAsyncPromptAuthCancelable->Cancel(status);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::Suspend()
-{
-    NS_ENSURE_TRUE(mIsPending, NS_ERROR_NOT_AVAILABLE);
-    
-    LOG(("nsHttpChannel::Suspend [this=%p]\n", this));
-
-    ++mSuspendCount;
-
-    if (mTransactionPump)
-        return mTransactionPump->Suspend();
-    if (mCachePump)
-        return mCachePump->Suspend();
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::Resume()
-{
-    NS_ENSURE_TRUE(mSuspendCount > 0, NS_ERROR_UNEXPECTED);
-    
-    LOG(("nsHttpChannel::Resume [this=%p]\n", this));
-        
-    if (--mSuspendCount == 0 && mPendingAsyncCallOnResume) {
-        nsresult rv = AsyncCall(mPendingAsyncCallOnResume);
-        mPendingAsyncCallOnResume = nsnull;
-        NS_ENSURE_SUCCESS(rv, rv);
-    }
-
-    if (mTransactionPump)
-        return mTransactionPump->Resume();
-    if (mCachePump)
-        return mCachePump->Resume();
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetLoadGroup(nsILoadGroup **aLoadGroup)
-{
-    NS_ENSURE_ARG_POINTER(aLoadGroup);
-    *aLoadGroup = mLoadGroup;
-    NS_IF_ADDREF(*aLoadGroup);
-    return NS_OK;
-}
-NS_IMETHODIMP
-nsHttpChannel::SetLoadGroup(nsILoadGroup *aLoadGroup)
-{
-    mLoadGroup = aLoadGroup;
-    mProgressSink = nsnull;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
-{
-    NS_ENSURE_ARG_POINTER(aLoadFlags);
-    *aLoadFlags = mLoadFlags;
-    return NS_OK;
-}
-NS_IMETHODIMP
-nsHttpChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
-{
-    mLoadFlags = aLoadFlags;
-    return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel::nsIChannel
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsHttpChannel::GetOriginalURI(nsIURI **originalURI)
-{
-    NS_ENSURE_ARG_POINTER(originalURI);
-    *originalURI = mOriginalURI;
-    NS_ADDREF(*originalURI);
-    return NS_OK;
-}
-NS_IMETHODIMP
-nsHttpChannel::SetOriginalURI(nsIURI *originalURI)
-{
-    NS_ENSURE_ARG_POINTER(originalURI);
-    mOriginalURI = originalURI;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetURI(nsIURI **URI)
-{
-    NS_ENSURE_ARG_POINTER(URI);
-    *URI = mURI;
-    NS_IF_ADDREF(*URI);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetOwner(nsISupports **owner)
-{
-    NS_ENSURE_ARG_POINTER(owner);
-    *owner = mOwner;
-    NS_IF_ADDREF(*owner);
-    return NS_OK;
-}
-NS_IMETHODIMP
-nsHttpChannel::SetOwner(nsISupports *owner)
-{
-    mOwner = owner;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetNotificationCallbacks(nsIInterfaceRequestor **callbacks)
-{
-    NS_IF_ADDREF(*callbacks = mCallbacks);
-    return NS_OK;
-}
-NS_IMETHODIMP
-nsHttpChannel::SetNotificationCallbacks(nsIInterfaceRequestor *callbacks)
-{
-    mCallbacks = callbacks;
-    mProgressSink = nsnull;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetSecurityInfo(nsISupports **securityInfo)
-{
-    NS_ENSURE_ARG_POINTER(securityInfo);
-    *securityInfo = mSecurityInfo;
-    NS_IF_ADDREF(*securityInfo);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetContentType(nsACString &value)
-{
-    if (!mResponseHead) {
-        // We got no data, we got no headers, we got nothing
-        value.Truncate();
-        return NS_ERROR_NOT_AVAILABLE;
-    }
-
-    if (!mResponseHead->ContentType().IsEmpty()) {
-        value = mResponseHead->ContentType();
-        return NS_OK;
-    }
-
-    
-    value.AssignLiteral(UNKNOWN_CONTENT_TYPE);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetContentType(const nsACString &value)
-{
-    if (mListener || mWasOpened) {
-        if (!mResponseHead)
-            return NS_ERROR_NOT_AVAILABLE;
-
-        nsCAutoString contentTypeBuf, charsetBuf;
-        PRBool hadCharset;
-        net_ParseContentType(value, contentTypeBuf, charsetBuf, &hadCharset);
-
-        mResponseHead->SetContentType(contentTypeBuf);
-
-        // take care not to stomp on an existing charset
-        if (hadCharset)
-            mResponseHead->SetContentCharset(charsetBuf);
-    } else {
-        // We are being given a content-type hint.
-        PRBool dummy;
-        net_ParseContentType(value, mContentTypeHint, mContentCharsetHint,
-                             &dummy);
-    }
-    
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetContentCharset(nsACString &value)
-{
-    if (!mResponseHead)
-        return NS_ERROR_NOT_AVAILABLE;
-
-    value = mResponseHead->ContentCharset();
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetContentCharset(const nsACString &value)
-{
-    if (mListener) {
-        if (!mResponseHead)
-            return NS_ERROR_NOT_AVAILABLE;
-
-        mResponseHead->SetContentCharset(value);
-    } else {
-        // Charset hint
-        mContentCharsetHint = value;
-    }
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetContentLength(PRInt32 *value)
-{
-    NS_ENSURE_ARG_POINTER(value);
-
-    if (!mResponseHead)
-        return NS_ERROR_NOT_AVAILABLE;
-
-    // XXX truncates to 32 bit
-    LL_L2I(*value, mResponseHead->ContentLength());
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetContentLength(PRInt32 value)
-{
-    NS_NOTYETIMPLEMENTED("nsHttpChannel::SetContentLength");
-    return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::Open(nsIInputStream **_retval)
-{
-    NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_IN_PROGRESS);
-    return NS_ImplementChannelOpen(this, _retval);
-}
-
-NS_IMETHODIMP
-nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context)
-{
-    LOG(("nsHttpChannel::AsyncOpen [this=%p]\n", this));
-
-    NS_ENSURE_ARG_POINTER(listener);
-    NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
-    NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
-
-    nsresult rv;
-
-    rv = NS_CheckPortSafety(mURI);
-    if (NS_FAILED(rv))
-        return rv;
-
-    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.
-        nsRefPtr<nsDNSPrefetch> prefetch = new nsDNSPrefetch(mURI);
-        if (prefetch) {
-            prefetch->PrefetchHigh();
-        }
-    }
-    
-    // Remember the cookie header that was set, if any
-    const char *cookieHeader = mRequestHead.PeekHeader(nsHttp::Cookie);
-    if (cookieHeader)
-        mUserSetCookieHeader = cookieHeader;
-
-    // fetch cookies, and add them to the request header
-    AddCookiesToRequest();
-
-    // 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;
-
-    mIsPending = PR_TRUE;
-    mWasOpened = PR_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, nsnull);
-
-    // 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(PR_TRUE);
-        AsyncAbort(rv);
-    }
-
-    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 NS_OK;
-}
-//-----------------------------------------------------------------------------
-// nsHttpChannel::nsIHttpChannel
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsHttpChannel::GetRequestMethod(nsACString &method)
-{
-    method = mRequestHead.Method();
-    return NS_OK;
-}
-NS_IMETHODIMP
-nsHttpChannel::SetRequestMethod(const nsACString &method)
-{
-    NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
-
-    const nsCString &flatMethod = PromiseFlatCString(method);
-
-    // Method names are restricted to valid HTTP tokens.
-    if (!nsHttp::IsValidToken(flatMethod))
-        return NS_ERROR_INVALID_ARG;
-
-    nsHttpAtom atom = nsHttp::ResolveAtom(flatMethod.get());
-    if (!atom)
-        return NS_ERROR_FAILURE;
-
-    mRequestHead.SetMethod(atom);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetReferrer(nsIURI **referrer)
-{
-    NS_ENSURE_ARG_POINTER(referrer);
-    *referrer = mReferrer;
-    NS_IF_ADDREF(*referrer);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetReferrer(nsIURI *referrer)
-{
-    NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
-
-    // clear existing referrer, if any
-    mReferrer = nsnull;
-    mRequestHead.ClearHeader(nsHttp::Referer);
-
-    if (!referrer)
-        return NS_OK;
-
-    // check referrer blocking pref
-    PRUint32 referrerLevel;
-    if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI)
-        referrerLevel = 1; // user action
-    else
-        referrerLevel = 2; // inline content
-    if (gHttpHandler->ReferrerLevel() < referrerLevel)
-        return NS_OK;
-
-    nsCOMPtr<nsIURI> referrerGrip;
-    nsresult rv;
-    PRBool match;
-
-    //
-    // Strip off "wyciwyg://123/" from wyciwyg referrers.
-    //
-    // XXX this really belongs elsewhere since wyciwyg URLs aren't part of necko.
-    //     perhaps some sort of generic nsINestedURI could be used.  then, if an URI
-    //     fails the whitelist test, then we could check for an inner URI and try
-    //     that instead.  though, that might be too automatic.
-    // 
-    rv = referrer->SchemeIs("wyciwyg", &match);
-    if (NS_FAILED(rv)) return rv;
-    if (match) {
-        nsCAutoString path;
-        rv = referrer->GetPath(path);
-        if (NS_FAILED(rv)) return rv;
-
-        PRUint32 pathLength = path.Length();
-        if (pathLength <= 2) return NS_ERROR_FAILURE;
-
-        // Path is of the form "//123/http://foo/bar", with a variable number of digits.
-        // To figure out where the "real" URL starts, search path for a '/', starting at 
-        // the third character.
-        PRInt32 slashIndex = path.FindChar('/', 2);
-        if (slashIndex == kNotFound) return NS_ERROR_FAILURE;
-
-        // Get the charset of the original URI so we can pass it to our fixed up URI.
-        nsCAutoString charset;
-        referrer->GetOriginCharset(charset);
-
-        // Replace |referrer| with a URI without wyciwyg://123/.
-        rv = NS_NewURI(getter_AddRefs(referrerGrip),
-                       Substring(path, slashIndex + 1, pathLength - slashIndex - 1),
-                       charset.get());
-        if (NS_FAILED(rv)) return rv;
-
-        referrer = referrerGrip.get();
-    }
-
-    //
-    // block referrer if not on our white list...
-    //
-    static const char *const referrerWhiteList[] = {
-        "http",
-        "https",
-        "ftp",
-        nsnull
-    };
-    match = PR_FALSE;
-    const char *const *scheme = referrerWhiteList;
-    for (; *scheme && !match; ++scheme) {
-        rv = referrer->SchemeIs(*scheme, &match);
-        if (NS_FAILED(rv)) return rv;
-    }
-    if (!match)
-        return NS_OK; // kick out....
-
-    //
-    // Handle secure referrals.
-    //
-    // Support referrals from a secure server if this is a secure site
-    // and (optionally) if the host names are the same.
-    //
-    rv = referrer->SchemeIs("https", &match);
-    if (NS_FAILED(rv)) return rv;
-    if (match) {
-        rv = mURI->SchemeIs("https", &match);
-        if (NS_FAILED(rv)) return rv;
-        if (!match)
-            return NS_OK;
-
-        if (!gHttpHandler->SendSecureXSiteReferrer()) {
-            nsCAutoString referrerHost;
-            nsCAutoString host;
-
-            rv = referrer->GetAsciiHost(referrerHost);
-            if (NS_FAILED(rv)) return rv;
-
-            rv = mURI->GetAsciiHost(host);
-            if (NS_FAILED(rv)) return rv;
-
-            // GetAsciiHost returns lowercase hostname.
-            if (!referrerHost.Equals(host))
-                return NS_OK;
-        }
-    }
-
-    nsCOMPtr<nsIURI> clone;
-    //
-    // we need to clone the referrer, so we can:
-    //  (1) modify it
-    //  (2) keep a reference to it after returning from this function
-    //
-    rv = referrer->Clone(getter_AddRefs(clone));
-    if (NS_FAILED(rv)) return rv;
-
-    // strip away any userpass; we don't want to be giving out passwords ;-)
-    clone->SetUserPass(EmptyCString());
-
-    // strip away any fragment per RFC 2616 section 14.36
-    nsCOMPtr<nsIURL> url = do_QueryInterface(clone);
-    if (url)
-        url->SetRef(EmptyCString());
-
-    nsCAutoString spec;
-    rv = clone->GetAsciiSpec(spec);
-    if (NS_FAILED(rv)) return rv;
-
-    // finally, remember the referrer URI and set the Referer header.
-    mReferrer = clone;
-    mRequestHead.SetHeader(nsHttp::Referer, spec);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetRequestHeader(const nsACString &header, nsACString &value)
-{
-    // XXX might be better to search the header list directly instead of
-    // hitting the http atom hash table.
-
-    nsHttpAtom atom = nsHttp::ResolveAtom(header);
-    if (!atom)
-        return NS_ERROR_NOT_AVAILABLE;
-
-    return mRequestHead.GetHeader(atom, value);
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetRequestHeader(const nsACString &header,
-                                const nsACString &value,
-                                PRBool merge)
-{
-    NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
-
-    const nsCString &flatHeader = PromiseFlatCString(header);
-    const nsCString &flatValue  = PromiseFlatCString(value);
-
-    LOG(("nsHttpChannel::SetRequestHeader [this=%p header=\"%s\" value=\"%s\" merge=%u]\n",
-        this, flatHeader.get(), flatValue.get(), merge));
-
-    // Header names are restricted to valid HTTP tokens.
-    if (!nsHttp::IsValidToken(flatHeader))
-        return NS_ERROR_INVALID_ARG;
-    
-    // Header values MUST NOT contain line-breaks.  RFC 2616 technically
-    // permits CTL characters, including CR and LF, in header values provided
-    // they are quoted.  However, this can lead to problems if servers do not
-    // interpret quoted strings properly.  Disallowing CR and LF here seems
-    // reasonable and keeps things simple.  We also disallow a null byte.
-    if (flatValue.FindCharInSet("\r\n") != kNotFound ||
-        flatValue.Length() != strlen(flatValue.get()))
-        return NS_ERROR_INVALID_ARG;
-
-    nsHttpAtom atom = nsHttp::ResolveAtom(flatHeader.get());
-    if (!atom) {
-        NS_WARNING("failed to resolve atom");
-        return NS_ERROR_NOT_AVAILABLE;
-    }
-
-    return mRequestHead.SetHeader(atom, flatValue, merge);
-}
-
-NS_IMETHODIMP
-nsHttpChannel::VisitRequestHeaders(nsIHttpHeaderVisitor *visitor)
-{
-    return mRequestHead.Headers().VisitHeaders(visitor);
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetUploadStream(nsIInputStream **stream)
-{
-    NS_ENSURE_ARG_POINTER(stream);
-    *stream = mUploadStream;
-    NS_IF_ADDREF(*stream);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetUploadStream(nsIInputStream *stream,
-                               const nsACString &contentType,
-                               PRInt32 contentLength)
-{
-    // NOTE: for backwards compatibility and for compatibility with old style
-    // plugins, |stream| may include headers, specifically Content-Type and
-    // Content-Length headers.  in this case, |contentType| and |contentLength|
-    // would be unspecified.  this is traditionally the case of a POST request,
-    // and so we select POST as the request method if contentType and
-    // contentLength are unspecified.
-    
-    if (stream) {
-        if (!contentType.IsEmpty()) {
-            if (contentLength < 0) {
-                stream->Available((PRUint32 *) &contentLength);
-                if (contentLength < 0) {
-                    NS_ERROR("unable to determine content length");
-                    return NS_ERROR_FAILURE;
-                }
-            }
-            mRequestHead.SetHeader(nsHttp::Content_Length,
-                                   nsPrintfCString("%d", contentLength));
-            mRequestHead.SetHeader(nsHttp::Content_Type, contentType);
-            mUploadStreamHasHeaders = PR_FALSE;
-            mRequestHead.SetMethod(nsHttp::Put); // PUT request
-        }
-        else {
-            mUploadStreamHasHeaders = PR_TRUE;
-            mRequestHead.SetMethod(nsHttp::Post); // POST request
-        }
-    }
-    else {
-        mUploadStreamHasHeaders = PR_FALSE;
-        mRequestHead.SetMethod(nsHttp::Get); // revert to GET request
-    }
-    mUploadStream = stream;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::ExplicitSetUploadStream(nsIInputStream *aStream,
-                                       const nsACString &aContentType,
-                                       PRInt64 aContentLength,
-                                       const nsACString &aMethod,
-                                       PRBool aStreamHasHeaders)
-{
-    // Ensure stream is set and method is valid 
-    NS_ENSURE_TRUE(aStream, NS_ERROR_FAILURE);
-
-    if (aContentLength < 0 && !aStreamHasHeaders) {
-        PRUint32 streamLength;
-        aStream->Available(&streamLength);
-        aContentLength = streamLength;
-        if (aContentLength < 0) {
-            NS_ERROR("unable to determine content length");
-            return NS_ERROR_FAILURE;
-        }
-    }
-
-    nsresult rv = SetRequestMethod(aMethod);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    if (!aStreamHasHeaders) {
-        mRequestHead.SetHeader(nsHttp::Content_Length,
-                               nsPrintfCString("%lld", aContentLength));
-        mRequestHead.SetHeader(nsHttp::Content_Type, aContentType);
-    }
-
-    mUploadStreamHasHeaders = aStreamHasHeaders;
-    mUploadStream = aStream;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetResponseStatus(PRUint32 *value)
-{
-    NS_ENSURE_ARG_POINTER(value);
-    if (!mResponseHead)
-        return NS_ERROR_NOT_AVAILABLE;
-    *value = mResponseHead->Status();
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetResponseStatusText(nsACString &value)
-{
-    if (!mResponseHead)
-        return NS_ERROR_NOT_AVAILABLE;
-    value = mResponseHead->StatusText();
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetRequestSucceeded(PRBool *value)
-{
-    NS_PRECONDITION(value, "Don't ever pass a null arg to this function");
-    if (!mResponseHead)
-        return NS_ERROR_NOT_AVAILABLE;
-    PRUint32 status = mResponseHead->Status();
-    *value = (status / 100 == 2);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetResponseHeader(const nsACString &header, nsACString &value)
-{
-    if (!mResponseHead)
-        return NS_ERROR_NOT_AVAILABLE;
-    nsHttpAtom atom = nsHttp::ResolveAtom(header);
-    if (!atom)
-        return NS_ERROR_NOT_AVAILABLE;
-    return mResponseHead->GetHeader(atom, value);
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetResponseHeader(const nsACString &header,
-                                 const nsACString &value,
-                                 PRBool merge)
-{
-    LOG(("nsHttpChannel::SetResponseHeader [this=%p header=\"%s\" value=\"%s\" merge=%u]\n",
-        this, PromiseFlatCString(header).get(), PromiseFlatCString(value).get(), merge));
-
-    if (!mResponseHead)
-        return NS_ERROR_NOT_AVAILABLE;
-    nsHttpAtom atom = nsHttp::ResolveAtom(header);
-    if (!atom)
-        return NS_ERROR_NOT_AVAILABLE;
-
-    // these response headers must not be changed 
-    if (atom == nsHttp::Content_Type ||
-        atom == nsHttp::Content_Length ||
-        atom == nsHttp::Content_Encoding ||
-        atom == nsHttp::Trailer ||
-        atom == nsHttp::Transfer_Encoding)
-        return NS_ERROR_ILLEGAL_VALUE;
-
-    mResponseHeadersModified = PR_TRUE;
-
-    return mResponseHead->SetHeader(atom, value, merge);
-}
-
-NS_IMETHODIMP
-nsHttpChannel::VisitResponseHeaders(nsIHttpHeaderVisitor *visitor)
-{
-    if (!mResponseHead)
-        return NS_ERROR_NOT_AVAILABLE;
-    return mResponseHead->Headers().VisitHeaders(visitor);
-}
-
-NS_IMETHODIMP
-nsHttpChannel::IsNoStoreResponse(PRBool *value)
-{
-    if (!mResponseHead)
-        return NS_ERROR_NOT_AVAILABLE;
-    *value = mResponseHead->NoStore();
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::IsNoCacheResponse(PRBool *value)
-{
-    if (!mResponseHead)
-        return NS_ERROR_NOT_AVAILABLE;
-    *value = mResponseHead->NoCache();
-    if (!*value)
-        *value = mResponseHead->ExpiresInPast();
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetApplyConversion(PRBool *value)
-{
-    NS_ENSURE_ARG_POINTER(value);
-    *value = mApplyConversion;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetApplyConversion(PRBool value)
-{
-    LOG(("nsHttpChannel::SetApplyConversion [this=%p value=%d]\n", this, value));
-    mApplyConversion = value;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetAllowPipelining(PRBool *value)
-{
-    NS_ENSURE_ARG_POINTER(value);
-    *value = mAllowPipelining;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetAllowPipelining(PRBool value)
-{
-    if (mIsPending)
-        return NS_ERROR_FAILURE;
-    mAllowPipelining = value;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetRedirectionLimit(PRUint32 *value)
-{
-    NS_ENSURE_ARG_POINTER(value);
-    *value = PRUint32(mRedirectionLimit);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetRedirectionLimit(PRUint32 value)
-{
-    mRedirectionLimit = PR_MIN(value, 0xff);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetContentEncodings(nsIUTF8StringEnumerator** aEncodings)
-{
-    NS_PRECONDITION(aEncodings, "Null out param");
-    if (!mResponseHead) {
-        *aEncodings = nsnull;
-        return NS_OK;
-    }
-    
-    const char *encoding = mResponseHead->PeekHeader(nsHttp::Content_Encoding);
-    if (!encoding) {
-        *aEncodings = nsnull;
-        return NS_OK;
-    }
-    nsContentEncodings* enumerator = new nsContentEncodings(this, encoding);
-    if (!enumerator)
-        return NS_ERROR_OUT_OF_MEMORY;
-
-    NS_ADDREF(*aEncodings = enumerator);
-    return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel::nsIHttpChannelInternal
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsHttpChannel::GetDocumentURI(nsIURI **aDocumentURI)
-{
-    NS_ENSURE_ARG_POINTER(aDocumentURI);
-    *aDocumentURI = mDocumentURI;
-    NS_IF_ADDREF(*aDocumentURI);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetDocumentURI(nsIURI *aDocumentURI)
-{
-    mDocumentURI = aDocumentURI;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetForceAllowThirdPartyCookie(PRBool *aForceAllowThirdPartyCookie)
-{
-    *aForceAllowThirdPartyCookie = mForceAllowThirdPartyCookie;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetForceAllowThirdPartyCookie(PRBool aForceAllowThirdPartyCookie)
-{
-    mForceAllowThirdPartyCookie = aForceAllowThirdPartyCookie;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetRequestVersion(PRUint32 *major, PRUint32 *minor)
-{
-  int version = mRequestHead.Version();
-
-  if (major) { *major = version / 10; }
-  if (minor) { *minor = version % 10; }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetResponseVersion(PRUint32 *major, PRUint32 *minor)
-{
-  if (!mResponseHead)
-  {
-    *major = *minor = 0;                   // we should at least be kind about it
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  int version = mResponseHead->Version();
-
-  if (major) { *major = version / 10; }
-  if (minor) { *minor = version % 10; }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetCookie(const char *aCookieHeader)
-{
-    if (mLoadFlags & LOAD_ANONYMOUS) {
-      return NS_OK;
-    }
-
-    // empty header isn't an error
-    if (!(aCookieHeader && *aCookieHeader))
-        return NS_OK;
-
-    nsICookieService *cs = gHttpHandler->GetCookieService();
-    NS_ENSURE_TRUE(cs, NS_ERROR_FAILURE);
-
-    nsCOMPtr<nsIPrompt> prompt;
-    GetCallback(prompt);
-
-    return cs->SetCookieStringFromHttp(mURI,
-                                       mDocumentURI ? mDocumentURI : mOriginalURI,
-                                       prompt,
-                                       aCookieHeader,
-                                       mResponseHead->PeekHeader(nsHttp::Date),
-                                       this);
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetupFallbackChannel(const char *aFallbackKey)
-{
-    LOG(("nsHttpChannel::SetupFallbackChannel [this=%p, key=%s]",
-         this, aFallbackKey));
-    mFallbackChannel = PR_TRUE;
-    mFallbackKey = aFallbackKey;
-
-    return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel::nsISupportsPriority
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsHttpChannel::GetPriority(PRInt32 *value)
-{
-    *value = mPriority;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetPriority(PRInt32 value)
-{
-    PRInt16 newValue = NS_CLAMP(value, PR_INT16_MIN, PR_INT16_MAX);
-    if (mPriority == newValue)
-        return NS_OK;
-    mPriority = newValue;
-    if (mTransaction)
-        gHttpHandler->RescheduleTransaction(mTransaction, mPriority);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::AdjustPriority(PRInt32 delta)
-{
-    return SetPriority(mPriority + delta);
-}
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel::nsIProtocolProxyCallback
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsHttpChannel::OnProxyAvailable(nsICancelable *request, nsIURI *uri,
-                                nsIProxyInfo *pi, nsresult status)
-{
-    mProxyRequest = nsnull;
-
-    // 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).
-    
-    // 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
-nsHttpChannel::GetProxyInfo(nsIProxyInfo **result)
-{
-    if (!mConnectionInfo)
-        *result = nsnull;
-    else {
-        *result = mConnectionInfo->ProxyInfo();
-        NS_IF_ADDREF(*result);
-    }
-    return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel::nsIRequestObserver
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsHttpChannel::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
-{
-    if (!(mCanceled || NS_FAILED(mStatus))) {
-        // capture the request's status, so our consumers will know ASAP of any
-        // connection failures, etc - bug 93581
-        request->GetStatus(&mStatus);
-    }
-
-    LOG(("nsHttpChannel::OnStartRequest [this=%p request=%p status=%x]\n",
-        this, request, mStatus));
-
-    // Make sure things are what we expect them to be...
-    NS_ASSERTION(request == mCachePump || request == mTransactionPump,
-                 "Unexpected request");
-    NS_ASSERTION(!(mTransactionPump && mCachePump) || mCachedContentIsPartial,
-                 "If we have both pumps, the cache content must be partial");
-
-    if (!mSecurityInfo && !mCachePump && mTransaction) {
-        // grab the security info from the connection object; the transaction
-        // is guaranteed to own a reference to the connection.
-        mSecurityInfo = mTransaction->SecurityInfo();
-    }
-
-    // don't enter this block if we're reading from the cache...
-    if (NS_SUCCEEDED(mStatus) && !mCachePump && mTransaction) {
-        NS_ASSERTION(mResponseHead == nsnull, "leaking mResponseHead");
-
-        // all of the response headers have been acquired, so we can take ownership
-        // of them from the transaction.
-        mResponseHead = mTransaction->TakeResponseHead();
-        // the response head may be null if the transaction was cancelled.  in
-        // which case we just need to call OnStartRequest/OnStopRequest.
-        if (mResponseHead)
-            return ProcessResponse();
-
-        NS_WARNING("No response head in OnStartRequest");
-    }
-
-    // avoid crashing if mListener happens to be null...
-    if (!mListener) {
-        NS_NOTREACHED("mListener is null");
-        return NS_OK;
-    }
-
-    // on proxy errors, try to failover
-    if (mConnectionInfo->ProxyInfo() &&
-           (mStatus == NS_ERROR_PROXY_CONNECTION_REFUSED ||
-            mStatus == NS_ERROR_UNKNOWN_PROXY_HOST ||
-            mStatus == NS_ERROR_NET_TIMEOUT)) {
-        if (NS_SUCCEEDED(ProxyFailover()))
-            return NS_OK;
-    }
-
-    // on other request errors, try to fall back
-    PRBool fallingBack;
-    if (NS_FAILED(mStatus) &&
-        NS_SUCCEEDED(ProcessFallback(&fallingBack)) &&
-        fallingBack) {
-
-        return NS_OK;
-    }
-
-    return CallOnStartRequest();
-}
-
-NS_IMETHODIMP
-nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult status)
-{
-    LOG(("nsHttpChannel::OnStopRequest [this=%p request=%p status=%x]\n",
-        this, request, status));
-
-    // honor the cancelation status even if the underlying transaction completed.
-    if (mCanceled || NS_FAILED(mStatus))
-        status = mStatus;
-
-    if (mCachedContentIsPartial) {
-        if (NS_SUCCEEDED(status)) {
-            // mTransactionPump should be suspended
-            NS_ASSERTION(request != mTransactionPump,
-                "byte-range transaction finished prematurely");
-
-            if (request == mCachePump) {
-                PRBool streamDone;
-                status = OnDoneReadingPartialCacheEntry(&streamDone);
-                if (NS_SUCCEEDED(status) && !streamDone)
-                    return status;
-                // otherwise, fall through and fire OnStopRequest...
-            }
-            else
-                NS_NOTREACHED("unexpected request");
-        }
-        // Do not to leave the transaction in a suspended state in error cases.
-        if (NS_FAILED(status) && mTransaction)
-            gHttpHandler->CancelTransaction(mTransaction, status); 
-    }
-
-    if (mTransaction) {
-        // determine if we should call DoAuthRetry
-        PRBool authRetry = mAuthRetryPending && NS_SUCCEEDED(status);
-
-        //
-        // grab reference to connection in case we need to retry an
-        // authentication request over it.  this applies to connection based
-        // authentication schemes only.  for request based schemes, conn is not
-        // needed, so it may be null.
-        // 
-        // this code relies on the code in nsHttpTransaction::Close, which
-        // tests for NS_HTTP_STICKY_CONNECTION to determine whether or not to
-        // keep the connection around after the transaction is finished.
-        //
-        nsRefPtr<nsAHttpConnection> conn;
-        if (authRetry && (mCaps & NS_HTTP_STICKY_CONNECTION)) {
-            conn = mTransaction->Connection();
-            // This is so far a workaround to fix leak when reusing unpersistent
-            // connection for authentication retry. See bug 459620 comment 4
-            // for details.
-            if (conn && !conn->IsPersistent())
-                conn = nsnull;
-        }
-
-        // at this point, we're done with the transaction
-        NS_RELEASE(mTransaction);
-        mTransactionPump = 0;
-
-        // handle auth retry...
-        if (authRetry) {
-            mAuthRetryPending = PR_FALSE;
-            status = DoAuthRetry(conn);
-            if (NS_SUCCEEDED(status))
-                return NS_OK;
-        }
-
-        // If DoAuthRetry failed, or if we have been cancelled since showing
-        // the auth. dialog, then we need to send OnStartRequest now
-        if (authRetry || (mAuthRetryPending && NS_FAILED(status))) {
-            NS_ASSERTION(NS_FAILED(status), "should have a failure code here");
-            // NOTE: since we have a failure status, we can ignore the return
-            // value from onStartRequest.
-            mListener->OnStartRequest(this, mListenerContext);
-        }
-
-        // if this transaction has been replaced, then bail.
-        if (mTransactionReplaced)
-            return NS_OK;
-    }
-
-    mIsPending = PR_FALSE;
-    mStatus = status;
-
-    // perform any final cache operations before we close the cache entry.
-    if (mCacheEntry && (mCacheAccess & nsICache::ACCESS_WRITE))
-        FinalizeCacheEntry();
-    
-    if (mListener) {
-        LOG(("  calling OnStopRequest\n"));
-        mListener->OnStopRequest(this, mListenerContext, status);
-        mListener = 0;
-        mListenerContext = 0;
-    }
-
-    if (mCacheEntry)
-        CloseCacheEntry(PR_TRUE);
-
-    if (mOfflineCacheEntry)
-        CloseOfflineCacheEntry();
-
-    if (mLoadGroup)
-        mLoadGroup->RemoveRequest(this, nsnull, status);
-
-    mCallbacks = nsnull;
-    mProgressSink = nsnull;
-    
-    return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel::nsIStreamListener
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsHttpChannel::OnDataAvailable(nsIRequest *request, nsISupports *ctxt,
-                               nsIInputStream *input,
-                               PRUint32 offset, PRUint32 count)
-{
-    LOG(("nsHttpChannel::OnDataAvailable [this=%p request=%p offset=%u count=%u]\n",
-        this, request, offset, count));
-
-    // don't send out OnDataAvailable notifications if we've been canceled.
-    if (mCanceled)
-        return mStatus;
-
-    NS_ASSERTION(mResponseHead, "No response head in ODA!!");
-
-    NS_ASSERTION(!(mCachedContentIsPartial && (request == mTransactionPump)),
-            "transaction pump not suspended");
-
-    if (mAuthRetryPending || (request == mTransactionPump && mTransactionReplaced)) {
-        PRUint32 n;
-        return input->ReadSegments(NS_DiscardSegment, nsnull, count, &n);
-    }
-
-    if (mListener) {
-        //
-        // synthesize transport progress event.  we do this here since we want
-        // to delay OnProgress events until we start streaming data.  this is
-        // crucially important since it impacts the lock icon (see bug 240053).
-        //
-        nsresult transportStatus;
-        if (request == mCachePump)
-            transportStatus = nsITransport::STATUS_READING;
-        else
-            transportStatus = nsISocketTransport::STATUS_RECEIVING_FROM;
-
-        // mResponseHead may reference new or cached headers, but either way it
-        // holds our best estimate of the total content length.  Even in the case
-        // of a byte range request, the content length stored in the cached
-        // response headers is what we want to use here.
-
-        PRUint64 progressMax(PRUint64(mResponseHead->ContentLength()));
-        PRUint64 progress = mLogicalOffset + PRUint64(count);
-        NS_ASSERTION(progress <= progressMax, "unexpected progress values");
-
-        OnTransportStatus(nsnull, transportStatus, progress, progressMax);
-
-        //
-        // we have to manually keep the logical offset of the stream up-to-date.
-        // we cannot depend solely on the offset provided, since we may have 
-        // already streamed some data from another source (see, for example,
-        // OnDoneReadingPartialCacheEntry).
-        //
-        nsresult rv =  mListener->OnDataAvailable(this,
-                                                  mListenerContext,
-                                                  input,
-                                                  mLogicalOffset,
-                                                  count);
-        if (NS_SUCCEEDED(rv))
-            mLogicalOffset = progress;
-        return rv;
-    }
-
-    return NS_ERROR_ABORT;
-}
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel::nsITransportEventSink
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsHttpChannel::OnTransportStatus(nsITransport *trans, nsresult status,
-                                 PRUint64 progress, PRUint64 progressMax)
-{
-    // cache the progress sink so we don't have to query for it each time.
-    if (!mProgressSink)
-        GetCallback(mProgressSink);
-
-    // block socket status event after Cancel or OnStopRequest has been called.
-    if (mProgressSink && NS_SUCCEEDED(mStatus) && mIsPending && !(mLoadFlags & LOAD_BACKGROUND)) {
-        LOG(("sending status notification [this=%p status=%x progress=%llu/%llu]\n",
-            this, status, progress, progressMax));
-
-        nsCAutoString host;
-        mURI->GetHost(host);
-        mProgressSink->OnStatus(this, nsnull, status,
-                                NS_ConvertUTF8toUTF16(host).get());
-
-        if (progress > 0) {
-            NS_ASSERTION(progress <= progressMax, "unexpected progress values");
-            mProgressSink->OnProgress(this, nsnull, progress, progressMax);
-        }
-    }
-#ifdef DEBUG
-    else
-        LOG(("skipping status notification [this=%p sink=%p pending=%u background=%x]\n",
-            this, mProgressSink.get(), mIsPending, (mLoadFlags & LOAD_BACKGROUND)));
-#endif
-
-    return NS_OK;
-} 
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel::nsICachingChannel
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsHttpChannel::GetCacheToken(nsISupports **token)
-{
-    NS_ENSURE_ARG_POINTER(token);
-    if (!mCacheEntry)
-        return NS_ERROR_NOT_AVAILABLE;
-    return CallQueryInterface(mCacheEntry, token);
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetCacheToken(nsISupports *token)
-{
-    return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetOfflineCacheToken(nsISupports **token)
-{
-    NS_ENSURE_ARG_POINTER(token);
-    if (!mOfflineCacheEntry)
-        return NS_ERROR_NOT_AVAILABLE;
-    return CallQueryInterface(mOfflineCacheEntry, token);
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetOfflineCacheToken(nsISupports *token)
-{
-    return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-class nsHttpChannelCacheKey : public nsISupportsPRUint32,
-                              public nsISupportsCString
-{
-    NS_DECL_ISUPPORTS
-
-    NS_DECL_NSISUPPORTSPRIMITIVE
-    NS_FORWARD_NSISUPPORTSPRUINT32(mSupportsPRUint32->)
-    
-    // Both interfaces declares toString method with the same signature.
-    // Thus we have to delegate only to nsISupportsPRUint32 implementation.
-    NS_SCRIPTABLE NS_IMETHOD GetData(nsACString & aData) 
-    { 
-        return mSupportsCString->GetData(aData);
-    }
-    NS_SCRIPTABLE NS_IMETHOD SetData(const nsACString & aData)
-    { 
-        return mSupportsCString->SetData(aData);
-    }
-    
-public:
-    nsresult SetData(PRUint32 aPostID, const nsACString& aKey);
-
-protected:
-    nsCOMPtr<nsISupportsPRUint32> mSupportsPRUint32;
-    nsCOMPtr<nsISupportsCString> mSupportsCString;
-};
-
-NS_IMPL_ADDREF(nsHttpChannelCacheKey)
-NS_IMPL_RELEASE(nsHttpChannelCacheKey)
-NS_INTERFACE_TABLE_HEAD(nsHttpChannelCacheKey)
-NS_INTERFACE_TABLE_BEGIN
-NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(nsHttpChannelCacheKey,
-                                   nsISupports, nsISupportsPRUint32)
-NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(nsHttpChannelCacheKey,
-                                   nsISupportsPrimitive, nsISupportsPRUint32)
-NS_INTERFACE_TABLE_ENTRY(nsHttpChannelCacheKey,
-                         nsISupportsPRUint32)
-NS_INTERFACE_TABLE_ENTRY(nsHttpChannelCacheKey,
-                         nsISupportsCString)
-NS_INTERFACE_TABLE_END
-NS_INTERFACE_TABLE_TAIL
-
-NS_IMETHODIMP nsHttpChannelCacheKey::GetType(PRUint16 *aType)
-{
-    NS_ENSURE_ARG_POINTER(aType);
-
-    *aType = TYPE_PRUINT32;
-    return NS_OK;
-}
-
-nsresult nsHttpChannelCacheKey::SetData(PRUint32 aPostID,
-                                        const nsACString& aKey)
-{
-    nsresult rv;
-
-    mSupportsCString = 
-        do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, &rv);
-    if (NS_FAILED(rv)) return rv;
-
-    mSupportsCString->SetData(aKey);
-    if (NS_FAILED(rv)) return rv;
-
-    mSupportsPRUint32 = 
-        do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv);
-    if (NS_FAILED(rv)) return rv;
-
-    mSupportsPRUint32->SetData(aPostID);
-    if (NS_FAILED(rv)) return rv;
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetCacheKey(nsISupports **key)
-{
-    nsresult rv;
-    NS_ENSURE_ARG_POINTER(key);
-
-    LOG(("nsHttpChannel::GetCacheKey [this=%p]\n", this));
-
-    *key = nsnull;
-
-    nsRefPtr<nsHttpChannelCacheKey> container =
-        new nsHttpChannelCacheKey();
-
-    if (!container)
-        return NS_ERROR_OUT_OF_MEMORY;
-
-    nsCAutoString cacheKey;
-    rv = GenerateCacheKey(mPostID, cacheKey);
-    if (NS_FAILED(rv)) return rv;
-
-    rv = container->SetData(mPostID, cacheKey);
-    if (NS_FAILED(rv)) return rv;
-
-    return CallQueryInterface(container.get(), key);
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetCacheKey(nsISupports *key)
-{
-    nsresult rv;
-
-    LOG(("nsHttpChannel::SetCacheKey [this=%p key=%p]\n", this, key));
-
-    // can only set the cache key if a load is not in progress
-    NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
-
-    if (!key)
-        mPostID = 0;
-    else {
-        // extract the post id
-        nsCOMPtr<nsISupportsPRUint32> container = do_QueryInterface(key, &rv);
-        if (NS_FAILED(rv)) return rv;
-
-        rv = container->GetData(&mPostID);
-        if (NS_FAILED(rv)) return rv;
-    }
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetCacheAsFile(PRBool *value)
-{
-    NS_ENSURE_ARG_POINTER(value);
-    if (!mCacheEntry)
-        return NS_ERROR_NOT_AVAILABLE;
-    nsCacheStoragePolicy storagePolicy;
-    mCacheEntry->GetStoragePolicy(&storagePolicy);
-    *value = (storagePolicy == nsICache::STORE_ON_DISK_AS_FILE);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetCacheAsFile(PRBool value)
-{
-    if (!mCacheEntry || mLoadFlags & INHIBIT_PERSISTENT_CACHING)
-        return NS_ERROR_NOT_AVAILABLE;
-    nsCacheStoragePolicy policy;
-    if (value)
-        policy = nsICache::STORE_ON_DISK_AS_FILE;
-    else
-        policy = nsICache::STORE_ANYWHERE;
-    return mCacheEntry->SetStoragePolicy(policy);
-}
-
-
-NS_IMETHODIMP
-nsHttpChannel::GetCacheForOfflineUse(PRBool *value)
-{
-    *value = mCacheForOfflineUse;
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetCacheForOfflineUse(PRBool value)
-{
-    mCacheForOfflineUse = value;
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetOfflineCacheClientID(nsACString &value)
-{
-    value = mOfflineCacheClientID;
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetOfflineCacheClientID(const nsACString &value)
-{
-    mOfflineCacheClientID = value;
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetCacheFile(nsIFile **cacheFile)
-{
-    if (!mCacheEntry)
-        return NS_ERROR_NOT_AVAILABLE;
-    return mCacheEntry->GetFile(cacheFile);
-}
-
-NS_IMETHODIMP
-nsHttpChannel::IsFromCache(PRBool *value)
-{
-    if (!mIsPending)
-        return NS_ERROR_NOT_AVAILABLE;
-
-    // return false if reading a partial cache entry; the data isn't entirely
-    // from the cache!
-
-    *value = (mCachePump || (mLoadFlags & LOAD_ONLY_IF_MODIFIED)) &&
-              mCachedContentIsValid && !mCachedContentIsPartial;
-
-    return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel::nsIResumableChannel
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsHttpChannel::ResumeAt(PRUint64 aStartPos,
-                        const nsACString& aEntityID)
-{
-    LOG(("nsHttpChannel::ResumeAt [this=%p startPos=%llu id='%s']\n",
-         this, aStartPos, PromiseFlatCString(aEntityID).get()));
-    mEntityID = aEntityID;
-    mStartPos = aStartPos;
-    mResuming = PR_TRUE;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetEntityID(nsACString& aEntityID)
-{
-    // Don't return an entity ID for Non-GET requests which require
-    // additional data
-    if (mRequestHead.Method() != nsHttp::Get) {
-        return NS_ERROR_NOT_RESUMABLE;
-    }
-
-    // Don't return an entity if the server sent the following header:
-    // Accept-Ranges: none
-    // Not sending the Accept-Ranges header means we can still try
-    // sending range requests.
-    const char* acceptRanges =
-        mResponseHead->PeekHeader(nsHttp::Accept_Ranges);
-    if (acceptRanges &&
-        !nsHttp::FindToken(acceptRanges, "bytes", HTTP_HEADER_VALUE_SEPS)) {
-        return NS_ERROR_NOT_RESUMABLE;
-    }
-
-    PRUint64 size = LL_MAXUINT;
-    nsCAutoString etag, lastmod;
-    if (mResponseHead) {
-        size = mResponseHead->TotalEntitySize();
-        const char* cLastMod = mResponseHead->PeekHeader(nsHttp::Last_Modified);
-        if (cLastMod)
-            lastmod = cLastMod;
-        const char* cEtag = mResponseHead->PeekHeader(nsHttp::ETag);
-        if (cEtag)
-            etag = cEtag;
-    }
-    nsCString entityID;
-    NS_EscapeURL(etag.BeginReading(), etag.Length(), esc_AlwaysCopy |
-            esc_FileBaseName | esc_Forced, entityID);
-    entityID.Append('/');
-    entityID.AppendInt(PRInt64(size));
-    entityID.Append('/');
-    entityID.Append(lastmod);
-    // NOTE: Appending lastmod as the last part avoids having to escape it
-
-    aEntityID = entityID;
-
-    return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel::nsICacheListener
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsHttpChannel::OnCacheEntryAvailable(nsICacheEntryDescriptor *entry,
-                                     nsCacheAccessMode access,
-                                     nsresult status)
-{
-    LOG(("nsHttpChannel::OnCacheEntryAvailable [this=%p entry=%p "
-         "access=%x status=%x]\n", this, entry, access, status));
-
-    // if the channel's already fired onStopRequest, then we should ignore
-    // this event.
-    if (!mIsPending)
-        return NS_OK;
-
-    // otherwise, we have to handle this event.
-    if (NS_SUCCEEDED(status)) {
-        mCacheEntry = entry;
-        mCacheAccess = access;
-    }
-
-    nsresult rv;
-
-    if (mCanceled && NS_FAILED(mStatus)) {
-        LOG(("channel was canceled [this=%p status=%x]\n", this, mStatus));
-        rv = mStatus;
-    }
-    else if ((mLoadFlags & LOAD_ONLY_FROM_CACHE) && NS_FAILED(status))
-        // if this channel is only allowed to pull from the cache, then
-        // we must fail if we were unable to open a cache entry.
-        rv = NS_ERROR_DOCUMENT_NOT_CACHED;
-    else
-        // advance to the next state...
-        rv = Connect(PR_FALSE);
-
-    // a failure from Connect means that we have to abort the channel.
-    if (NS_FAILED(rv)) {
-        CloseCacheEntry(PR_TRUE);
-        AsyncAbort(rv);
-    }
-
-    return NS_OK;
-}
-
-nsresult
-nsHttpChannel::DoAuthRetry(nsAHttpConnection *conn)
-{
-    LOG(("nsHttpChannel::DoAuthRetry [this=%p]\n", this));
-
-    NS_ASSERTION(!mTransaction, "should not have a transaction");
-    nsresult rv;
-
-    // toggle mIsPending to allow nsIObserver implementations to modify
-    // the request headers (bug 95044).
-    mIsPending = PR_FALSE;
-
-    // fetch cookies, and add them to the request header.
-    // the server response could have included cookies that must be sent with
-    // this authentication attempt (bug 84794).
-    AddCookiesToRequest();
-
-    // notify "http-on-modify-request" observers
-    gHttpHandler->OnModifyRequest(this);
-
-    mIsPending = PR_TRUE;
-
-    // get rid of the old response headers
-    delete mResponseHead;
-    mResponseHead = nsnull;
-
-    // set sticky connection flag and disable pipelining.
-    mCaps |=  NS_HTTP_STICKY_CONNECTION;
-    mCaps &= ~NS_HTTP_ALLOW_PIPELINING;
-   
-    // and create a new one...
-    rv = SetupTransaction();
-    if (NS_FAILED(rv)) return rv;
-
-    // transfer ownership of connection to transaction
-    if (conn)
-        mTransaction->SetConnection(conn);
-
-    // rewind the upload stream
-    if (mUploadStream) {
-        nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mUploadStream);
-        if (seekable)
-            seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
-    }
-
-    rv = gHttpHandler->InitiateTransaction(mTransaction, mPriority);
-    if (NS_FAILED(rv)) return rv;
-
-    return mTransactionPump->AsyncRead(this, nsnull);
-}
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel::nsIApplicationCacheChannel
-//-----------------------------------------------------------------------------
-NS_IMETHODIMP
-nsHttpChannel::GetApplicationCache(nsIApplicationCache **out)
-{
-    NS_IF_ADDREF(*out = mApplicationCache);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetApplicationCache(nsIApplicationCache *appCache)
-{
-    NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
-
-    mApplicationCache = appCache;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetLoadedFromApplicationCache(PRBool *aLoadedFromApplicationCache)
-{
-    *aLoadedFromApplicationCache = mLoadedFromApplicationCache;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetInheritApplicationCache(PRBool *aInherit)
-{
-    *aInherit = mInheritApplicationCache;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetInheritApplicationCache(PRBool aInherit)
-{
-    NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
-
-    mInheritApplicationCache = aInherit;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetChooseApplicationCache(PRBool *aChoose)
-{
-    *aChoose = mChooseApplicationCache;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetChooseApplicationCache(PRBool aChoose)
-{
-    NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
-
-    mChooseApplicationCache = aChoose;
-    return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel::nsContentEncodings <public>
-//-----------------------------------------------------------------------------
-
-nsHttpChannel::nsContentEncodings::nsContentEncodings(nsIHttpChannel* aChannel,
-                                                          const char* aEncodingHeader) :
-    mEncodingHeader(aEncodingHeader), mChannel(aChannel), mReady(PR_FALSE)
-{
-    mCurEnd = aEncodingHeader + strlen(aEncodingHeader);
-    mCurStart = mCurEnd;
-}
-    
-nsHttpChannel::nsContentEncodings::~nsContentEncodings()
-{
-}
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel::nsContentEncodings::nsISimpleEnumerator
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsHttpChannel::nsContentEncodings::HasMore(PRBool* aMoreEncodings)
-{
-    if (mReady) {
-        *aMoreEncodings = PR_TRUE;
-        return NS_OK;
-    }
-    
-    nsresult rv = PrepareForNext();
-    *aMoreEncodings = NS_SUCCEEDED(rv);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::nsContentEncodings::GetNext(nsACString& aNextEncoding)
-{
-    aNextEncoding.Truncate();
-    if (!mReady) {
-        nsresult rv = PrepareForNext();
-        if (NS_FAILED(rv)) {
-            return NS_ERROR_FAILURE;
-        }
-    }
-
-    const nsACString & encoding = Substring(mCurStart, mCurEnd);
-
-    nsACString::const_iterator start, end;
-    encoding.BeginReading(start);
-    encoding.EndReading(end);
-
-    PRBool haveType = PR_FALSE;
-    if (CaseInsensitiveFindInReadable(NS_LITERAL_CSTRING("gzip"),
-                                      start,
-                                      end)) {
-        aNextEncoding.AssignLiteral(APPLICATION_GZIP);
-        haveType = PR_TRUE;
-    }
-
-    if (!haveType) {
-        encoding.BeginReading(start);
-        if (CaseInsensitiveFindInReadable(NS_LITERAL_CSTRING("compress"),
-                                          start,
-                                          end)) {
-            aNextEncoding.AssignLiteral(APPLICATION_COMPRESS);
-                                           
-            haveType = PR_TRUE;
-        }
-    }
-    
-    if (! haveType) {
-        encoding.BeginReading(start);
-        if (CaseInsensitiveFindInReadable(NS_LITERAL_CSTRING("deflate"),
-                                          start,
-                                          end)) {
-            aNextEncoding.AssignLiteral(APPLICATION_ZIP);
-            haveType = PR_TRUE;
-        }
-    }
-
-    // Prepare to fetch the next encoding
-    mCurEnd = mCurStart;
-    mReady = PR_FALSE;
-    
-    if (haveType)
-        return NS_OK;
-
-    NS_WARNING("Unknown encoding type");
-    return NS_ERROR_FAILURE;
-}
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel::nsContentEncodings::nsISupports
-//-----------------------------------------------------------------------------
-
-NS_IMPL_ISUPPORTS1(nsHttpChannel::nsContentEncodings, nsIUTF8StringEnumerator)
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel::nsContentEncodings <private>
-//-----------------------------------------------------------------------------
-
-nsresult
-nsHttpChannel::nsContentEncodings::PrepareForNext(void)
-{
-    NS_PRECONDITION(mCurStart == mCurEnd, "Indeterminate state");
-    
-    // At this point both mCurStart and mCurEnd point to somewhere
-    // past the end of the next thing we want to return
-    
-    while (mCurEnd != mEncodingHeader) {
-        --mCurEnd;
-        if (*mCurEnd != ',' && !nsCRT::IsAsciiSpace(*mCurEnd))
-            break;
-    }
-    if (mCurEnd == mEncodingHeader)
-        return NS_ERROR_NOT_AVAILABLE; // no more encodings
-    ++mCurEnd;
-        
-    // At this point mCurEnd points to the first char _after_ the
-    // header we want.  Furthermore, mCurEnd - 1 != mEncodingHeader
-    
-    mCurStart = mCurEnd - 1;
-    while (mCurStart != mEncodingHeader &&
-           *mCurStart != ',' && !nsCRT::IsAsciiSpace(*mCurStart))
-        --mCurStart;
-    if (*mCurStart == ',' || nsCRT::IsAsciiSpace(*mCurStart))
-        ++mCurStart; // we stopped because of a weird char, so move up one
-        
-    // At this point mCurStart and mCurEnd bracket the encoding string
-    // we want.  Check that it's not "identity"
-    if (Substring(mCurStart, mCurEnd).Equals("identity",
-                                             nsCaseInsensitiveCStringComparator())) {
-        mCurEnd = mCurStart;
-        return PrepareForNext();
-    }
-        
-    mReady = PR_TRUE;
-    return NS_OK;
-}
-
-//-----------------------------------------------------------------------------
-// nsStreamListenerWrapper <private>
-//-----------------------------------------------------------------------------
-
-// Wrapper class to make replacement of nsHttpChannel's listener
-// from JavaScript possible. It is workaround for bug 433711.
-class nsStreamListenerWrapper : public nsIStreamListener
-{
-public:
-    nsStreamListenerWrapper(nsIStreamListener *listener);
-
-    NS_DECL_ISUPPORTS
-    NS_FORWARD_NSIREQUESTOBSERVER(mListener->)
-    NS_FORWARD_NSISTREAMLISTENER(mListener->)
-
-private:
-    ~nsStreamListenerWrapper() {}
-    nsCOMPtr<nsIStreamListener> mListener;
-};
-
-nsStreamListenerWrapper::nsStreamListenerWrapper(nsIStreamListener *listener)
-    : mListener(listener) 
-{
-    NS_ASSERTION(mListener, "no stream listener specified");
-}
-
-NS_IMPL_ISUPPORTS2(nsStreamListenerWrapper,
-                   nsIStreamListener,
-                   nsIRequestObserver)
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel::nsITraceableChannel
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-nsHttpChannel::SetNewListener(nsIStreamListener *aListener, nsIStreamListener **_retval)
-{
-    if (!mTracingEnabled)
-        return NS_ERROR_FAILURE;
-
-    NS_ENSURE_ARG_POINTER(aListener);
-
-    nsCOMPtr<nsIStreamListener> wrapper = 
-        new nsStreamListenerWrapper(mListener);
-
-    if (!wrapper)
-        return NS_ERROR_OUT_OF_MEMORY;
-
-    wrapper.forget(_retval);
-    mListener = aListener;
-    return NS_OK;
-}
-
-void
-nsHttpChannel::MaybeInvalidateCacheEntryForSubsequentGet()
-{
-    // See RFC 2616 section 5.1.1. These are considered valid
-    // methods which DO NOT invalidate cache-entries for the
-    // referred resource. POST, PUT and DELETE as well as any
-    // other method not listed here will potentially invalidate
-    // any cached copy of the resource
-    if (mRequestHead.Method() == nsHttp::Options ||
-       mRequestHead.Method() == nsHttp::Get ||
-       mRequestHead.Method() == nsHttp::Head ||
-       mRequestHead.Method() == nsHttp::Trace ||
-       mRequestHead.Method() == nsHttp::Connect)
-        return;
-        
-    // NOTE:
-    // Following comments 24,32 and 33 in bug #327765, we only care about
-    // the cache in the protocol-handler.
-    // The logic below deviates from the original logic in OpenCacheEntry on
-    // one point by using only READ_ONLY access-policy. I think this is safe.
-    LOG(("MaybeInvalidateCacheEntryForSubsequentGet [this=%p]\n", this));
-
-    nsCAutoString tmpCacheKey;
-    // passing 0 in first param gives the cache-key for a GET to my resource
-    GenerateCacheKey(0, tmpCacheKey);
-
-    // Now, find the session holding the cache-entry
-    nsCOMPtr<nsICacheSession> session;
-    nsCacheStoragePolicy storagePolicy = DetermineStoragePolicy();
-
-    nsresult rv;
-    rv = gHttpHandler->GetCacheSession(storagePolicy,
-                                       getter_AddRefs(session));
-
-    if (NS_FAILED(rv)) return;
-
-    // Finally, find the actual cache-entry
-    nsCOMPtr<nsICacheEntryDescriptor> tmpCacheEntry;
-    rv = session->OpenCacheEntry(tmpCacheKey, nsICache::ACCESS_READ,
-                                 PR_FALSE,
-                                 getter_AddRefs(tmpCacheEntry));
-    
-    // If entry was found, set its expiration-time = 0
-    if(NS_SUCCEEDED(rv)) {
-       tmpCacheEntry->SetExpirationTime(0);
-    }
-}
-
-nsCacheStoragePolicy
-nsHttpChannel::DetermineStoragePolicy()
-{
-    nsCacheStoragePolicy policy = nsICache::STORE_ANYWHERE;
-    if (mLoadFlags & INHIBIT_PERSISTENT_CACHING)
-        policy = nsICache::STORE_IN_MEMORY;
-
-    return policy;
-}
-
-void
-nsHttpChannel::AsyncOnExamineCachedResponse()
-{
-    gHttpHandler->OnExamineCachedResponse(this);
-}
+NS_IMPL_ISUPPORTS3(nsHttpChannelAuthProvider, nsICancelable,
+                   nsIHttpChannelAuthProvider, nsIAuthPromptCallback)
copy from netwerk/protocol/http/nsHttpChannel.h
copy to netwerk/protocol/http/nsHttpChannelAuthProvider.h
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannelAuthProvider.h
@@ -18,304 +18,131 @@
  * The Initial Developer of the Original Code is
  * Netscape Communications.
  * Portions created by the Initial Developer are Copyright (C) 2001
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Darin Fisher <darin@netscape.com> (original author)
  *   Christian Biesinger <cbiesinger@web.de>
+ *   Wellington Fernando de Macedo <wfernandom2004@gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-#ifndef nsHttpChannel_h__
-#define nsHttpChannel_h__
+#ifndef nsHttpChannelAuthProvider_h__
+#define nsHttpChannelAuthProvider_h__
 
-#include "nsHttpTransaction.h"
-#include "nsHttpRequestHead.h"
-#include "nsHttpAuthCache.h"
-#include "nsHashPropertyBag.h"
-#include "nsInputStreamPump.h"
-#include "nsThreadUtils.h"
+#include "nsIHttpChannelAuthProvider.h"
+#include "nsIAuthPromptCallback.h"
 #include "nsString.h"
-#include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
-#include "nsInt64.h"
-
-#include "nsIHttpChannel.h"
-#include "nsIHttpChannelInternal.h"
-#include "nsIHttpHeaderVisitor.h"
-#include "nsIHttpEventSink.h"
-#include "nsIChannelEventSink.h"
-#include "nsIStreamListener.h"
-#include "nsIIOService.h"
+#include "nsIHttpAuthenticableChannel.h"
 #include "nsIURI.h"
-#include "nsILoadGroup.h"
-#include "nsIInterfaceRequestor.h"
-#include "nsIInterfaceRequestorUtils.h"
-#include "nsIInputStream.h"
-#include "nsIProgressEventSink.h"
-#include "nsICachingChannel.h"
-#include "nsICacheSession.h"
-#include "nsICacheEntryDescriptor.h"
-#include "nsICacheListener.h"
-#include "nsIApplicationCache.h"
-#include "nsIApplicationCacheChannel.h"
-#include "nsIEncodedChannel.h"
-#include "nsITransport.h"
-#include "nsIUploadChannel.h"
-#include "nsIUploadChannel2.h"
-#include "nsIStringEnumerator.h"
-#include "nsIOutputStream.h"
-#include "nsIAsyncInputStream.h"
-#include "nsIPrompt.h"
-#include "nsIResumableChannel.h"
-#include "nsISupportsPriority.h"
-#include "nsIProtocolProxyCallback.h"
-#include "nsICancelable.h"
-#include "nsIProxiedChannel.h"
-#include "nsITraceableChannel.h"
-#include "nsIAuthPromptCallback.h"
+#include "nsHttpAuthCache.h"
+#include "nsProxyInfo.h"
 
-class nsHttpResponseHead;
-class nsAHttpConnection;
 class nsIHttpAuthenticator;
-class nsProxyInfo;
-
-//-----------------------------------------------------------------------------
-// nsHttpChannel
-//-----------------------------------------------------------------------------
 
-class nsHttpChannel : public nsHashPropertyBag
-                    , public nsIHttpChannel
-                    , public nsIHttpChannelInternal
-                    , public nsIStreamListener
-                    , public nsICachingChannel
-                    , public nsIUploadChannel
-                    , public nsIUploadChannel2
-                    , public nsICacheListener
-                    , public nsIEncodedChannel
-                    , public nsITransportEventSink
-                    , public nsIResumableChannel
-                    , public nsISupportsPriority
-                    , public nsIProtocolProxyCallback
-                    , public nsIProxiedChannel
-                    , public nsITraceableChannel
-                    , public nsIApplicationCacheChannel
-                    , public nsIAuthPromptCallback
+class nsHttpChannelAuthProvider : public nsIHttpChannelAuthProvider
+                                , public nsIAuthPromptCallback
 {
 public:
-    NS_DECL_ISUPPORTS_INHERITED
-    NS_DECL_NSIREQUEST
-    NS_DECL_NSICHANNEL
-    NS_DECL_NSIHTTPCHANNEL
-    NS_DECL_NSIREQUESTOBSERVER
-    NS_DECL_NSISTREAMLISTENER
-    NS_DECL_NSICACHINGCHANNEL
-    NS_DECL_NSIUPLOADCHANNEL
-    NS_DECL_NSIUPLOADCHANNEL2
-    NS_DECL_NSICACHELISTENER
-    NS_DECL_NSIENCODEDCHANNEL
-    NS_DECL_NSIHTTPCHANNELINTERNAL
-    NS_DECL_NSITRANSPORTEVENTSINK
-    NS_DECL_NSIRESUMABLECHANNEL
-    NS_DECL_NSISUPPORTSPRIORITY
-    NS_DECL_NSIPROTOCOLPROXYCALLBACK
-    NS_DECL_NSIPROXIEDCHANNEL
-    NS_DECL_NSITRACEABLECHANNEL
-    NS_DECL_NSIAPPLICATIONCACHECONTAINER
-    NS_DECL_NSIAPPLICATIONCACHECHANNEL
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSICANCELABLE
+    NS_DECL_NSIHTTPCHANNELAUTHPROVIDER
     NS_DECL_NSIAUTHPROMPTCALLBACK
 
-    nsHttpChannel();
-    virtual ~nsHttpChannel();
-
-    nsresult Init(nsIURI *uri,
-                  PRUint8 capabilities,
-                  nsProxyInfo* proxyInfo);
-
-public: /* internal; workaround lame compilers */ 
-    typedef void (nsHttpChannel:: *nsAsyncCallback)(void);
+    nsHttpChannelAuthProvider();
+    virtual ~nsHttpChannelAuthProvider();
 
 private:
-
-    // Helper function to simplify getting notification callbacks.
-    template <class T>
-    void GetCallback(nsCOMPtr<T> &aResult)
-    {
-        NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
-                                      NS_GET_TEMPLATE_IID(T),
-                                      getter_AddRefs(aResult));
-    }
-
-    // AsyncCall may be used to call a member function asynchronously.
-    // retval isn't refcounted and is set only when event was successfully
-    // posted, the event is returned for the purpose of cancelling when needed
-    nsresult AsyncCall(nsAsyncCallback funcPtr,
-                       nsRunnableMethod<nsHttpChannel> **retval = nsnull);
+    const char *ProxyHost() const
+    { return mProxyInfo ? mProxyInfo->Host().get() : nsnull; }
 
-    PRBool   RequestIsConditional();
-    nsresult Connect(PRBool firstTime = PR_TRUE);
-    nsresult AsyncAbort(nsresult status);
-    // Send OnStartRequest/OnStopRequest to our listener, if any.
-    void     HandleAsyncNotifyListener();
-    void     DoNotifyListener();
-    nsresult SetupTransaction();
-    void     AddCookiesToRequest();
-    nsresult ApplyContentConversions();
-    nsresult CallOnStartRequest();
-    nsresult ProcessResponse();
-    nsresult ProcessNormal();
-    nsresult ProcessNotModified();
-    nsresult ProcessRedirection(PRUint32 httpStatus);
-    PRBool   ShouldSSLProxyResponseContinue(PRUint32 httpStatus);
-    nsresult ProcessFailedSSLConnect(PRUint32 httpStatus);
-    nsresult ProcessAuthentication(PRUint32 httpStatus);
-    nsresult ProcessFallback(PRBool *fallingBack);
-    PRBool   ResponseWouldVary();
+    PRInt32     ProxyPort() const
+    { return mProxyInfo ? mProxyInfo->Port() : -1; }
+
+    const char *Host() const      { return mHost.get(); }
+    PRInt32     Port() const      { return mPort; }
+    PRBool      UsingSSL() const  { return mUsingSSL; }
 
-    // redirection specific methods
-    void     HandleAsyncRedirect();
-    void     HandleAsyncNotModified();
-    void     HandleAsyncFallback();
-    nsresult PromptTempRedirect();
-    nsresult SetupReplacementChannel(nsIURI *, nsIChannel *, PRBool preserveMethod);
-
-    // proxy specific methods
-    nsresult ProxyFailover();
-    nsresult DoReplaceWithProxy(nsIProxyInfo *);
-    void HandleAsyncReplaceWithProxy();
-    nsresult ResolveProxy();
+    PRBool      UsingHttpProxy() const
+    { return !!(mProxyInfo && !nsCRT::strcmp(mProxyInfo->Type(), "http")); }
 
-    // cache specific methods
-    nsresult OpenCacheEntry(PRBool offline, PRBool *delayed);
-    nsresult OpenOfflineCacheEntryForWriting();
-    nsresult GenerateCacheKey(PRUint32 postID, nsACString &key);
-    nsresult UpdateExpirationTime();
-    nsresult CheckCache();
-    nsresult ShouldUpdateOfflineCacheEntry(PRBool *shouldCacheForOfflineUse);
-    nsresult ReadFromCache();
-    void     CloseCacheEntry(PRBool doomOnFailure);
-    void     CloseOfflineCacheEntry();
-    nsresult InitCacheEntry();
-    nsresult InitOfflineCacheEntry();
-    nsresult AddCacheEntryHeaders(nsICacheEntryDescriptor *entry);
-    nsresult StoreAuthorizationMetaData(nsICacheEntryDescriptor *entry);
-    nsresult FinalizeCacheEntry();
-    nsresult InstallCacheListener(PRUint32 offset = 0);
-    nsresult InstallOfflineCacheListener();
-    void     MaybeInvalidateCacheEntryForSubsequentGet();
-    nsCacheStoragePolicy DetermineStoragePolicy();
-    void     AsyncOnExamineCachedResponse();
-
-    // Handle the bogus Content-Encoding Apache sometimes sends
-    void ClearBogusContentEncodingIfNeeded();
-
-    // byte range request specific methods
-    nsresult SetupByteRangeRequest(PRUint32 partialLen);
-    nsresult ProcessPartialContent();
-    nsresult OnDoneReadingPartialCacheEntry(PRBool *streamDone);
-
-    // auth specific methods
     nsresult PrepareForAuthentication(PRBool proxyAuth);
-    nsresult GenCredsAndSetEntry(nsIHttpAuthenticator *, PRBool proxyAuth, const char *scheme, const char *host, PRInt32 port, const char *dir, const char *realm, const char *challenge, const nsHttpAuthIdentity &ident, nsCOMPtr<nsISupports> &session, char **result);
-    nsresult GetAuthenticator(const char *challenge, nsCString &scheme, nsIHttpAuthenticator **auth); 
+    nsresult GenCredsAndSetEntry(nsIHttpAuthenticator *, PRBool proxyAuth,
+                                 const char *scheme, const char *host,
+                                 PRInt32 port, const char *dir,
+                                 const char *realm, const char *challenge,
+                                 const nsHttpAuthIdentity &ident,
+                                 nsCOMPtr<nsISupports> &session, char **result);
+    nsresult GetAuthenticator(const char *challenge, nsCString &scheme,
+                              nsIHttpAuthenticator **auth);
     void     ParseRealm(const char *challenge, nsACString &realm);
     void     GetIdentityFromURI(PRUint32 authFlags, nsHttpAuthIdentity&);
     /**
      * Following three methods return NS_ERROR_IN_PROGRESS when
      * nsIAuthPrompt2.asyncPromptAuth method is called. This result indicates
      * the user's decision will be gathered in a callback and is not an actual
      * error.
      */
-    nsresult GetCredentials(const char *challenges, PRBool proxyAuth, nsAFlatCString &creds);
-    nsresult GetCredentialsForChallenge(const char *challenge, const char *scheme,  PRBool proxyAuth, nsIHttpAuthenticator *auth, nsAFlatCString &creds);
-    nsresult PromptForIdentity(PRUint32 level, PRBool proxyAuth, const char *realm, const char *authType, PRUint32 authFlags, nsHttpAuthIdentity &);
+    nsresult GetCredentials(const char *challenges, PRBool proxyAuth,
+                            nsAFlatCString &creds);
+    nsresult GetCredentialsForChallenge(const char *challenge,
+                                        const char *scheme,  PRBool proxyAuth,
+                                        nsIHttpAuthenticator *auth,
+                                        nsAFlatCString &creds);
+    nsresult PromptForIdentity(PRUint32 level, PRBool proxyAuth,
+                               const char *realm, const char *authType,
+                               PRUint32 authFlags, nsHttpAuthIdentity &);
 
     PRBool   ConfirmAuth(const nsString &bundleKey, PRBool doYesNoPrompt);
-    void     CheckForSuperfluousAuth();
-    void     SetAuthorizationHeader(nsHttpAuthCache *, nsHttpAtom header, const char *scheme, const char *host, PRInt32 port, const char *path, nsHttpAuthIdentity &ident);
-    void     AddAuthorizationHeaders();
+    void     SetAuthorizationHeader(nsHttpAuthCache *, nsHttpAtom header,
+                                    const char *scheme, const char *host,
+                                    PRInt32 port, const char *path,
+                                    nsHttpAuthIdentity &ident);
     nsresult GetCurrentPath(nsACString &);
     /**
      * Return all information needed to build authorization information,
-     * all paramters except proxyAuth are out parameters. proxyAuth specifies
+     * all parameters except proxyAuth are out parameters. proxyAuth specifies
      * with what authorization we work (WWW or proxy).
      */
-    nsresult GetAuthorizationMembers(PRBool proxyAuth, nsCSubstring& scheme, const char*& host, PRInt32& port, nsCSubstring& path, nsHttpAuthIdentity*& ident, nsISupports**& continuationState);
-    nsresult DoAuthRetry(nsAHttpConnection *);
-    PRBool   MustValidateBasedOnQueryUrl();
+    nsresult GetAuthorizationMembers(PRBool proxyAuth, nsCSubstring& scheme,
+                                     const char*& host, PRInt32& port,
+                                     nsCSubstring& path,
+                                     nsHttpAuthIdentity*& ident,
+                                     nsISupports**& continuationState);
     /**
      * Method called to resume suspended transaction after we got credentials
      * from the user. Called from OnAuthAvailable callback or OnAuthCancelled
      * when credentials for next challenge were obtained synchronously.
      */
     nsresult ContinueOnAuthAvailable(const nsCSubstring& creds);
 
 private:
-    nsCOMPtr<nsIURI>                  mOriginalURI;
-    nsCOMPtr<nsIURI>                  mURI;
-    nsCOMPtr<nsIURI>                  mDocumentURI;
-    nsCOMPtr<nsIStreamListener>       mListener;
-    nsCOMPtr<nsISupports>             mListenerContext;
-    nsCOMPtr<nsILoadGroup>            mLoadGroup;
-    nsCOMPtr<nsISupports>             mOwner;
-    nsCOMPtr<nsIInterfaceRequestor>   mCallbacks;
-    nsCOMPtr<nsIProgressEventSink>    mProgressSink;
-    nsCOMPtr<nsIInputStream>          mUploadStream;
-    nsCOMPtr<nsIURI>                  mReferrer;
-    nsCOMPtr<nsISupports>             mSecurityInfo;
-    nsCOMPtr<nsICancelable>           mProxyRequest;
-
-    nsHttpRequestHead                 mRequestHead;
-    nsHttpResponseHead               *mResponseHead;
-
-    nsRefPtr<nsInputStreamPump>       mTransactionPump;
-    nsHttpTransaction                *mTransaction;     // hard ref
-    nsHttpConnectionInfo             *mConnectionInfo;  // hard ref
-
-    nsCString                         mSpec; // ASCII encoded URL spec
+    nsIHttpAuthenticableChannel      *mAuthChannel;  // weak ref
 
-    PRUint32                          mLoadFlags;
-    PRUint32                          mStatus;
-    PRUint64                          mLogicalOffset;
-    PRUint8                           mCaps;
-    PRInt16                           mPriority;
-
-    nsCString                         mContentTypeHint;
-    nsCString                         mContentCharsetHint;
-    nsCString                         mUserSetCookieHeader;
+    nsCOMPtr<nsIURI>                  mURI;
+    nsCOMPtr<nsProxyInfo>             mProxyInfo;
+    nsCString                         mHost;
+    PRInt32                           mPort;
+    PRBool                            mUsingSSL;
 
-    // cache specific data
-    nsCOMPtr<nsICacheEntryDescriptor> mCacheEntry;
-    nsRefPtr<nsInputStreamPump>       mCachePump;
-    nsHttpResponseHead               *mCachedResponseHead;
-    nsCacheAccessMode                 mCacheAccess;
-    PRUint32                          mPostID;
-    PRUint32                          mRequestTime;
-
-    nsCOMPtr<nsICacheEntryDescriptor> mOfflineCacheEntry;
-    nsCacheAccessMode                 mOfflineCacheAccess;
-    nsCString                         mOfflineCacheClientID;
-
-    nsCOMPtr<nsIApplicationCache>     mApplicationCache;
-
-    // auth specific data
     nsISupports                      *mProxyAuthContinuationState;
     nsCString                         mProxyAuthType;
     nsISupports                      *mAuthContinuationState;
     nsCString                         mAuthType;
     nsHttpAuthIdentity                mIdent;
     nsHttpAuthIdentity                mProxyIdent;
 
     // Reference to the prompt wating in prompt queue. The channel is
@@ -326,95 +153,17 @@ private:
     // we obtained from the server with 401/407 response, will be processed in
     // OnAuthAvailable callback.
     nsCString                         mCurrentChallenge;
     // Saved in GetCredentials when prompt is asynchronous, remaning challenges
     // we have to process when user cancels the auth dialog for the current
     // challenge.
     nsCString                         mRemainingChallenges;
 
-    // Resumable channel specific data
-    nsCString                         mEntityID;
-    PRUint64                          mStartPos;
-
-    // Function pointer that can be set to indicate that we got suspended while
-    // waiting on an AsyncCall.  When we get resumed we should AsyncCall this
-    // function.
-    nsAsyncCallback                   mPendingAsyncCallOnResume;
-
-    // Proxy info to replace with
-    nsCOMPtr<nsIProxyInfo>            mTargetProxyInfo;
-
-    // Suspend counter.  This is used if someone tries to suspend/resume us
-    // before we have either a cache pump or a transaction pump.
-    PRUint32                          mSuspendCount;
-
-    // redirection specific data.
-    PRUint8                           mRedirectionLimit;
-
-    // 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;
-
-    // state flags
-    PRUint32                          mIsPending                : 1;
-    PRUint32                          mWasOpened                : 1;
-    PRUint32                          mApplyConversion          : 1;
-    PRUint32                          mAllowPipelining          : 1;
-    PRUint32                          mCachedContentIsValid     : 1;
-    PRUint32                          mCachedContentIsPartial   : 1;
-    PRUint32                          mResponseHeadersModified  : 1;
-    PRUint32                          mCanceled                 : 1;
-    PRUint32                          mTransactionReplaced      : 1;
-    PRUint32                          mUploadStreamHasHeaders   : 1;
-    PRUint32                          mAuthRetryPending         : 1;
     // True when we need to authenticate to proxy, i.e. when we get 407
     // response. Used in OnAuthAvailable and OnAuthCancelled callbacks.
     PRUint32                          mProxyAuth                : 1;
     PRUint32                          mTriedProxyAuth           : 1;
     PRUint32                          mTriedHostAuth            : 1;
     PRUint32                          mSuppressDefensiveAuth    : 1;
-    PRUint32                          mResuming                 : 1;
-    PRUint32                          mInitedCacheEntry         : 1;
-    PRUint32                          mCacheForOfflineUse       : 1;
-    // True if mCacheForOfflineUse was set because we were caching
-    // opportunistically.
-    PRUint32                          mCachingOpportunistically : 1;
-    // True if we are loading a fallback cache entry from the
-    // application cache.
-    PRUint32                          mFallbackChannel          : 1;
-    PRUint32                          mInheritApplicationCache  : 1;
-    PRUint32                          mChooseApplicationCache   : 1;
-    PRUint32                          mLoadedFromApplicationCache : 1;
-    PRUint32                          mTracingEnabled           : 1;
-    PRUint32                          mForceAllowThirdPartyCookie : 1;
-    // True if consumer added its own If-None-Match or If-Modified-Since
-    // headers. In such a case we must not override them in the cache code
-    // and also we want to pass possible 304 code response through.
-    PRUint32                          mCustomConditionalRequest : 1;
-
-    class nsContentEncodings : public nsIUTF8StringEnumerator
-    {
-    public:
-        NS_DECL_ISUPPORTS
-        NS_DECL_NSIUTF8STRINGENUMERATOR
-
-        nsContentEncodings(nsIHttpChannel* aChannel, const char* aEncodingHeader);
-        virtual ~nsContentEncodings();
-        
-    private:
-        nsresult PrepareForNext(void);
-        
-        // We do not own the buffer.  The channel owns it.
-        const char* mEncodingHeader;
-        const char* mCurStart;  // points to start of current header
-        const char* mCurEnd;  // points to end of current header
-        
-        // Hold a ref to our channel so that it can't go away and take the
-        // header with it.
-        nsCOMPtr<nsIHttpChannel> mChannel;
-        
-        PRPackedBool mReady;
-    };
 };
 
-#endif // nsHttpChannel_h__
+#endif // nsHttpChannelAuthProvider_h__
--- a/netwerk/protocol/http/nsHttpDigestAuth.cpp
+++ b/netwerk/protocol/http/nsHttpDigestAuth.cpp
@@ -37,17 +37,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include <stdlib.h>
 #include "nsHttp.h"
 #include "nsHttpDigestAuth.h"
-#include "nsIHttpChannel.h"
+#include "nsIHttpAuthenticableChannel.h"
 #include "nsIServiceManager.h"
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIURI.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "nsEscape.h"
 #include "nsNetCID.h"
@@ -104,49 +104,45 @@ nsHttpDigestAuth::MD5Hash(const char *bu
 
   NS_ENSURE_STATE(hashString.Length() == sizeof(mHashBuf));
   memcpy(mHashBuf, hashString.get(), hashString.Length());
 
   return rv;
 }
 
 nsresult
-nsHttpDigestAuth::GetMethodAndPath(nsIHttpChannel *httpChannel,
-                                   PRBool          isProxyAuth,
-                                   nsCString      &httpMethod,
-                                   nsCString      &path)
+nsHttpDigestAuth::GetMethodAndPath(nsIHttpAuthenticableChannel *authChannel,
+                                   PRBool                       isProxyAuth,
+                                   nsCString                   &httpMethod,
+                                   nsCString                   &path)
 {
   nsresult rv;
   nsCOMPtr<nsIURI> uri;
-  rv = httpChannel->GetURI(getter_AddRefs(uri));
+  rv = authChannel->GetURI(getter_AddRefs(uri));
   if (NS_SUCCEEDED(rv)) {
-    PRBool isSecure;
-    rv = uri->SchemeIs("https", &isSecure);
+    PRBool proxyMethodIsConnect;
+    rv = authChannel->GetProxyMethodIsConnect(&proxyMethodIsConnect);
     if (NS_SUCCEEDED(rv)) {
-      //
-      // if we are being called in response to a 407, and if the protocol
-      // is HTTPS, then we are really using a CONNECT method.
-      //
-      if (isSecure && isProxyAuth) {
+      if (proxyMethodIsConnect && isProxyAuth) {
         httpMethod.AssignLiteral("CONNECT");
         //
         // generate hostname:port string. (unfortunately uri->GetHostPort
         // leaves out the port if it matches the default value, so we can't
         // just call it.)
         //
         PRInt32 port;
         rv  = uri->GetAsciiHost(path);
         rv |= uri->GetPort(&port);
         if (NS_SUCCEEDED(rv)) {
           path.Append(':');
           path.AppendInt(port < 0 ? NS_HTTPS_DEFAULT_PORT : port);
         }
       }
       else { 
-        rv  = httpChannel->GetRequestMethod(httpMethod);
+        rv  = authChannel->GetRequestMethod(httpMethod);
         rv |= uri->GetPath(path);
         if (NS_SUCCEEDED(rv)) {
           //
           // strip any fragment identifier from the URL path.
           //
           PRInt32 ref = path.RFindChar('#');
           if (ref != kNotFound)
             path.Truncate(ref);
@@ -166,17 +162,17 @@ nsHttpDigestAuth::GetMethodAndPath(nsIHt
   return rv;
 }
 
 //-----------------------------------------------------------------------------
 // nsHttpDigestAuth::nsIHttpAuthenticator
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
-nsHttpDigestAuth::ChallengeReceived(nsIHttpChannel *httpChannel,
+nsHttpDigestAuth::ChallengeReceived(nsIHttpAuthenticableChannel *authChannel,
                                     const char *challenge,
                                     PRBool isProxyAuth,
                                     nsISupports **sessionState,
                                     nsISupports **continuationState,
                                     PRBool *result)
 {
   nsCAutoString realm, domain, nonce, opaque;
   PRBool stale;
@@ -192,17 +188,17 @@ nsHttpDigestAuth::ChallengeReceived(nsIH
   *result = !stale;
 
   // clear any existing nonce_count since we have a new challenge.
   NS_IF_RELEASE(*sessionState);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHttpDigestAuth::GenerateCredentials(nsIHttpChannel *httpChannel,
+nsHttpDigestAuth::GenerateCredentials(nsIHttpAuthenticableChannel *authChannel,
                                       const char *challenge,
                                       PRBool isProxyAuth,
                                       const PRUnichar *userdomain,
                                       const PRUnichar *username,
                                       const PRUnichar *password,
                                       nsISupports **sessionState,
                                       nsISupports **continuationState,
                                       PRUint32 *aFlags,
@@ -217,26 +213,26 @@ nsHttpDigestAuth::GenerateCredentials(ns
 
   PRBool isDigestAuth = !PL_strncasecmp(challenge, "digest ", 7);
   NS_ENSURE_TRUE(isDigestAuth, NS_ERROR_UNEXPECTED);
 
   // IIS implementation requires extra quotes
   PRBool requireExtraQuotes = PR_FALSE;
   {
     nsCAutoString serverVal;
-    httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Server"), serverVal);
+    authChannel->GetServerResponseHeader(serverVal);
     if (!serverVal.IsEmpty()) {
       requireExtraQuotes = !PL_strncasecmp(serverVal.get(), "Microsoft-IIS", 13);
     }
   }
 
   nsresult rv;
   nsCAutoString httpMethod;
   nsCAutoString path;
-  rv = GetMethodAndPath(httpChannel, isProxyAuth, httpMethod, path);
+  rv = GetMethodAndPath(authChannel, isProxyAuth, httpMethod, path);
   if (NS_FAILED(rv)) return rv;
 
   nsCAutoString realm, domain, nonce, opaque;
   PRBool stale;
   PRUint16 algorithm, qop;
 
   rv = ParseChallenge(challenge, realm, domain, nonce, opaque,
                       &stale, &algorithm, &qop);
--- a/netwerk/protocol/http/nsHttpDigestAuth.h
+++ b/netwerk/protocol/http/nsHttpDigestAuth.h
@@ -102,17 +102,18 @@ class nsHttpDigestAuth : public nsIHttpA
                             nsACString & opaque,
                             PRBool * stale,
                             PRUint16 * algorithm,
                             PRUint16 * qop);
 
     // result is in mHashBuf
     nsresult MD5Hash(const char *buf, PRUint32 len);
 
-    nsresult GetMethodAndPath(nsIHttpChannel *, PRBool, nsCString &, nsCString &);
+    nsresult GetMethodAndPath(nsIHttpAuthenticableChannel *,
+                              PRBool, nsCString &, nsCString &);
 
     // append the quoted version of value to aHeaderLine
     nsresult AppendQuotedString(const nsACString & value,
                                 nsACString & aHeaderLine);
 
   protected:
     nsCOMPtr<nsICryptoHash>        mVerifier;
     char                           mHashBuf[DIGEST_LENGTH];
--- a/netwerk/protocol/http/nsHttpNTLMAuth.cpp
+++ b/netwerk/protocol/http/nsHttpNTLMAuth.cpp
@@ -45,17 +45,17 @@
 #include "nsCOMPtr.h"
 #include "plbase64.h"
 
 //-----------------------------------------------------------------------------
 
 #include "nsIPrefBranch.h"
 #include "nsIPrefService.h"
 #include "nsIServiceManager.h"
-#include "nsIHttpChannel.h"
+#include "nsIHttpAuthenticableChannel.h"
 #include "nsIURI.h"
 
 static const char kAllowProxies[] = "network.automatic-ntlm-auth.allow-proxies";
 static const char kTrustedURIs[]  = "network.automatic-ntlm-auth.trusted-uris";
 static const char kForceGeneric[] = "network.auth.force-generic-ntlm";
 
 // XXX MatchesBaseURI and TestPref are duplicated in nsHttpNegotiateAuth.cpp,
 // but since that file lives in a separate library we cannot directly share it.
@@ -184,17 +184,18 @@ ForceGenericNTLM()
         flag = PR_FALSE;
 
     LOG(("Force use of generic ntlm auth module: %d\n", flag));
     return flag;
 }
 
 // Check to see if we should use default credentials for this host or proxy.
 static PRBool
-CanUseDefaultCredentials(nsIHttpChannel *channel, PRBool isProxyAuth)
+CanUseDefaultCredentials(nsIHttpAuthenticableChannel *channel,
+                         PRBool isProxyAuth)
 {
     nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
     if (!prefs)
         return PR_FALSE;
 
     if (isProxyAuth) {
         PRBool val;
         if (NS_FAILED(prefs->GetBoolPref(kAllowProxies, &val)))
@@ -219,17 +220,17 @@ public:
 };
 NS_IMPL_ISUPPORTS0(nsNTLMSessionState)
 
 //-----------------------------------------------------------------------------
 
 NS_IMPL_ISUPPORTS1(nsHttpNTLMAuth, nsIHttpAuthenticator)
 
 NS_IMETHODIMP
-nsHttpNTLMAuth::ChallengeReceived(nsIHttpChannel *channel,
+nsHttpNTLMAuth::ChallengeReceived(nsIHttpAuthenticableChannel *channel,
                                   const char     *challenge,
                                   PRBool          isProxyAuth,
                                   nsISupports   **sessionState,
                                   nsISupports   **continuationState,
                                   PRBool         *identityInvalid)
 {
     LOG(("nsHttpNTLMAuth::ChallengeReceived [ss=%p cs=%p]\n",
          *sessionState, *continuationState));
@@ -311,17 +312,17 @@ nsHttpNTLMAuth::ChallengeReceived(nsIHtt
         // A non-null continuation state implies that we failed to authenticate.
         // Blow away the old authentication state, and use the new one.
         module.swap(*continuationState);
     }
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHttpNTLMAuth::GenerateCredentials(nsIHttpChannel  *httpChannel,
+nsHttpNTLMAuth::GenerateCredentials(nsIHttpAuthenticableChannel *authChannel,
                                     const char      *challenge,
                                     PRBool           isProxyAuth,
                                     const PRUnichar *domain,
                                     const PRUnichar *user,
                                     const PRUnichar *pass,
                                     nsISupports    **sessionState,
                                     nsISupports    **continuationState,
                                     PRUint32       *aFlags,
@@ -346,17 +347,17 @@ nsHttpNTLMAuth::GenerateCredentials(nsIH
 
     void *inBuf, *outBuf;
     PRUint32 inBufLen, outBufLen;
 
     // initial challenge
     if (PL_strcasecmp(challenge, "NTLM") == 0) {
         // NTLM service name format is 'HTTP@host' for both http and https
         nsCOMPtr<nsIURI> uri;
-        rv = httpChannel->GetURI(getter_AddRefs(uri));
+        rv = authChannel->GetURI(getter_AddRefs(uri));
         if (NS_FAILED(rv))
             return rv;
         nsCAutoString serviceName, host;
         rv = uri->GetAsciiHost(host);
         if (NS_FAILED(rv))
             return rv;
         serviceName.AppendLiteral("HTTP@");
         serviceName.Append(host);
new file mode 100644
--- /dev/null
+++ b/netwerk/protocol/http/nsIHttpAuthenticableChannel.idl
@@ -0,0 +1,141 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is
+ * Wellington Fernando de Macedo.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *    Wellington Fernando de Macedo <wfernandom2004@gmail.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIProxiedChannel.idl"
+#include "nsIChannel.idl"
+
+interface nsILoadGroup;
+interface nsIURI;
+interface nsIInterfaceRequestor;
+
+[scriptable, uuid(701093ac-5c7f-429c-99e3-423b041fccb4)]
+interface nsIHttpAuthenticableChannel : nsIProxiedChannel
+{
+    /**
+     * If the channel being authenticated is using SSL.
+     */
+    readonly attribute boolean isSSL;
+    
+    /**
+     * Returns if the proxy HTTP method used is CONNECT. If no proxy is being
+     * used it must return PR_FALSE.
+     */
+    readonly attribute boolean proxyMethodIsConnect;
+
+    /**
+     * Cancels the current request. See nsIRequest.
+     */
+    void cancel(in nsresult aStatus);
+
+    /**
+     * The load flags of this request. See nsIRequest.
+     */
+    readonly attribute nsLoadFlags loadFlags;
+
+    /**
+     * The URI corresponding to the channel. See nsIChannel.
+     */
+    readonly attribute nsIURI URI;
+
+    /**
+     * The load group of this request. It is here for querying its
+     * notificationCallbacks. See nsIRequest.
+     */
+    readonly attribute nsILoadGroup loadGroup;
+
+    /**
+     * The notification callbacks for the channel. See nsIChannel.
+     */
+    readonly attribute nsIInterfaceRequestor notificationCallbacks;
+
+    /**
+     * The HTTP request method. See nsIHttpChannel.
+     */
+    readonly attribute ACString requestMethod;
+
+    /**
+     * The "Server" response header.
+     * Return NS_ERROR_NOT_AVAILABLE if not available.
+     */
+    readonly attribute ACString serverResponseHeader;
+
+    /**
+     * The Proxy-Authenticate response header.
+     */
+    readonly attribute ACString proxyChallenges;
+
+    /**
+     * The WWW-Authenticate response header.
+     */
+    readonly attribute ACString WWWChallenges;
+
+    /**
+     * Sets the Proxy-Authorization request header. An empty string 
+     * will clear it.
+     */
+    void setProxyCredentials(in ACString credentials);
+
+    /**
+     * Sets the Authorization request header. An empty string
+     * will clear it.
+     */
+    void setWWWCredentials(in ACString credentials);
+
+    /**
+     * Called when authentication information is ready and has been set on this
+     * object using setWWWCredentials/setProxyCredentials. Implementations can
+     * continue with the request and send the given information to the server.
+     *
+     * It is called asynchronously from
+     * nsIHttpChannelAuthProvider::processAuthentication if that method returns
+     * NS_ERROR_IN_PROGRESS.
+     *
+     * @note  Any exceptions thrown from this method should be ignored.
+     */
+    void onAuthAvailable();
+
+    /**
+     * Notifies that the prompt was cancelled. It is called asynchronously
+     * from nsIHttpChannelAuthProvider::processAuthentication if that method
+     * returns NS_ERROR_IN_PROGRESS.
+     *
+     * @param userCancel
+     *        If the user was cancelled has cancelled the authentication prompt.
+     */
+    void onAuthCancelled(in boolean userCancel);
+};
--- a/netwerk/protocol/http/nsIHttpAuthenticator.idl
+++ b/netwerk/protocol/http/nsIHttpAuthenticator.idl
@@ -33,30 +33,30 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 
-interface nsIHttpChannel;
+interface nsIHttpAuthenticableChannel;
 
 /**
  * nsIHttpAuthenticator
  *
  * Interface designed to allow for pluggable HTTP authentication modules.
  * Implementations are registered under the ContractID:
  *
  *   "@mozilla.org/network/http-authenticator;1?scheme=<auth-scheme>"  
  *
  * where <auth-scheme> is the lower-cased value of the authentication scheme
  * found in the server challenge per the rules of RFC 2617.
  */
-[scriptable, uuid(36402c9d-c280-4860-b4b0-2e7eb35b0aaf)]
+[scriptable, uuid(16784db0-fcb1-4352-b0c9-6a3a67e3cf79)]
 interface nsIHttpAuthenticator : nsISupports
 {
     /**
      * Upon receipt of a server challenge, this function is called to determine
      * whether or not the current user identity has been rejected.  If true,
      * then the user will be prompted by the channel to enter (or revise) their
      * identity.  Following this, generateCredentials will be called.
      *
@@ -73,22 +73,22 @@ interface nsIHttpAuthenticator : nsISupp
      * @param aSessionState
      *        see description below for generateCredentials.
      * @param aContinuationState
      *        see description below for generateCredentials.
      * @param aInvalidateIdentity
      *        return value indicating whether or not to prompt the user for a
      *        revised identity.
      */
-    void challengeReceived(in nsIHttpChannel aChannel,
-                           in string         aChallenge,
-                           in boolean        aProxyAuth,
-                           inout nsISupports aSessionState,
-                           inout nsISupports aContinuationState,
-                           out boolean       aInvalidatesIdentity);
+    void challengeReceived(in    nsIHttpAuthenticableChannel aChannel,
+                           in    string       aChallenge,
+                           in    boolean      aProxyAuth,
+                           inout nsISupports  aSessionState,
+                           inout nsISupports  aContinuationState,
+                           out   boolean      aInvalidatesIdentity);
 
     /**
      * Called to generate the authentication credentials for a particular
      * server/proxy challenge.  This is the value that will be sent back
      * to the server via an Authorization/Proxy-Authorization header.
      *
      * This function may be called using a cached challenge provided the
      * authenticator sets the REUSABLE_CHALLENGE flag.
@@ -116,25 +116,25 @@ interface nsIHttpAuthenticator : nsISupp
      * @param aContinuationState
      *        state held by the channel between consecutive calls to
      *        generateCredentials, assuming multiple calls are required
      *        to authenticate.  this state is held for at most the lifetime of
      *        the channel.
      * @param aFlags
      *        authenticator may return one of the generate flags bellow.
      */
-    string generateCredentials(in nsIHttpChannel aChannel,
-                               in string         aChallenge,
-                               in boolean        aProxyAuth,
-                               in wstring        aDomain,
-                               in wstring        aUser,
-                               in wstring        aPassword,
-                               inout nsISupports aSessionState,
-                               inout nsISupports aContinuationState,
-                               out unsigned long aFlags);
+    string generateCredentials(in    nsIHttpAuthenticableChannel aChannel,
+                               in    string         aChallenge,
+                               in    boolean        aProxyAuth,
+                               in    wstring        aDomain,
+                               in    wstring        aUser,
+                               in    wstring        aPassword,
+                               inout nsISupports    aSessionState,
+                               inout nsISupports    aContinuationState,
+                               out   unsigned long  aFlags);
 
     /**
      * Generate flags
      */
 
     /**
      * Indicates that the authenticator has used an out-of-band or internal 
      * source of identity and tells the consumer that it must not cache 
new file mode 100644
--- /dev/null
+++ b/netwerk/protocol/http/nsIHttpChannelAuthProvider.idl
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
</