diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index f622a81414a..1dd8e3df997 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -713,7 +713,6 @@ pref("network.ntlm.send-lm-response", false); pref("network.hosts.nntp_server", "news.mozilla.org"); pref("permissions.default.image", 1); // 1-Accept, 2-Deny, 3-dontAcceptForeign -pref("network.proxy.autoconfig_url", ""); pref("network.proxy.type", 0); pref("network.proxy.ftp", ""); pref("network.proxy.ftp_port", 0); @@ -737,6 +736,14 @@ pref("network.cookie.alwaysAcceptSessionCookies", false); pref("network.cookie.prefsMigrated", false); pref("network.cookie.lifetime.days", 90); +// The PAC file to load. Ignored unless network.proxy.type is 2. +pref("network.proxy.autoconfig_url", ""); + +// If we cannot load the PAC file, then try again (doubling from interval_min +// until we reach interval_max or the PAC file is successfully loaded). +pref("network.proxy.autoconfig_retry_interval_min", 5); // 5 seconds +pref("network.proxy.autoconfig_retry_interval_max", 300); // 5 minutes + // The following default value is for p3p medium mode. // See xpfe/components/permissions/content/cookieP3P.xul for the definitions of low/medium/hi pref("network.cookie.p3p", "ffffaaaa"); diff --git a/netwerk/base/src/nsPACMan.cpp b/netwerk/base/src/nsPACMan.cpp index c6f6aeb78e9..de8d01a0bc7 100644 --- a/netwerk/base/src/nsPACMan.cpp +++ b/netwerk/base/src/nsPACMan.cpp @@ -41,15 +41,37 @@ #include "nsIDNSService.h" #include "nsIDNSListener.h" #include "nsICancelable.h" +#include "nsIAuthPrompt.h" +#include "nsIHttpChannel.h" +#include "nsIPrefService.h" +#include "nsIPrefBranch.h" #include "nsNetUtil.h" #include "nsAutoLock.h" #include "nsAutoPtr.h" -#include "nsIAuthPrompt.h" #include "nsCRT.h" #include "prmon.h" //----------------------------------------------------------------------------- +// Check to see if the underlying request was not an error page in the case of +// a HTTP request. For other types of channels, just return true. +static PRBool +HttpRequestSucceeded(nsIStreamLoader *loader) +{ + nsCOMPtr request; + loader->GetRequest(getter_AddRefs(request)); + + PRBool result = PR_TRUE; // default to assuming success + + nsCOMPtr httpChannel = do_QueryInterface(request); + if (httpChannel) + httpChannel->GetRequestSucceeded(&result); + + return result; +} + +//----------------------------------------------------------------------------- + // These objects are stored in nsPACMan::mPendingQ class PendingPACQuery : public PRCList, public nsIDNSListener @@ -150,6 +172,8 @@ PendingPACQuery::OnLookupComplete(nsICancelable *request, nsPACMan::nsPACMan() : mLoadPending(PR_FALSE) , mShutdown(PR_FALSE) + , mScheduledReload(LL_MAXINT) + , mLoadFailureCount(0) { PR_INIT_CLIST(&mPendingQ); } @@ -181,6 +205,8 @@ nsPACMan::GetProxyForURI(nsIURI *uri, nsACString &result) return NS_OK; } + MaybeReloadPAC(); + if (IsLoading()) return NS_ERROR_IN_PROGRESS; if (!mPAC) @@ -198,6 +224,8 @@ nsPACMan::AsyncGetProxyForURI(nsIURI *uri, nsPACManCallback *callback) { NS_ENSURE_STATE(!mShutdown); + MaybeReloadPAC(); + PendingPACQuery *query = new PendingPACQuery(this, uri, callback); if (!query) return NS_ERROR_OUT_OF_MEMORY; @@ -226,6 +254,7 @@ nsresult nsPACMan::LoadPACFromURI(nsIURI *pacURI) { NS_ENSURE_STATE(!mShutdown); + NS_ENSURE_ARG(pacURI || mPACURI); nsCOMPtr loader = do_CreateInstance(NS_STREAMLOADER_CONTRACTID); @@ -249,7 +278,11 @@ nsPACMan::LoadPACFromURI(nsIURI *pacURI) CancelExistingLoad(); mLoader = loader; - mPACURI = pacURI; + if (pacURI) { + mPACURI = pacURI; + mLoadFailureCount = 0; // reset + } + mScheduledReload = LL_MAXINT; mPAC = nsnull; return NS_OK; } @@ -285,6 +318,43 @@ nsPACMan::StartLoading() ProcessPendingQ(NS_ERROR_UNEXPECTED); } +void +nsPACMan::MaybeReloadPAC() +{ + if (!mPACURI) + return; + + if (PR_Now() > mScheduledReload) { + printf("\n>>> reloading PAC <<<\n\n"); + LoadPACFromURI(nsnull); + } +} + +void +nsPACMan::OnLoadFailure() +{ + PRInt32 minInterval = 5; // 5 seconds + PRInt32 maxInterval = 300; // 5 minutes + + nsCOMPtr prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); + if (prefs) { + prefs->GetIntPref("network.proxy.autoconfig_retry_interval_min", + &minInterval); + prefs->GetIntPref("network.proxy.autoconfig_retry_interval_max", + &maxInterval); + } + + PRInt32 interval = minInterval << mLoadFailureCount++; // seconds + if (!interval || interval > maxInterval) + interval = maxInterval; + +#ifdef DEBUG + printf("PAC load failure: will retry in %d seconds\n", interval); +#endif + + mScheduledReload = PR_Now() + PRInt64(interval) * PR_USEC_PER_SEC; +} + void nsPACMan::CancelExistingLoad() { @@ -340,7 +410,7 @@ nsPACMan::OnStreamComplete(nsIStreamLoader *loader, mLoader = nsnull; - if (NS_SUCCEEDED(status)) { + if (NS_SUCCEEDED(status) && HttpRequestSucceeded(loader)) { // Get the URI spec used to load this PAC script. nsCAutoString pacURI; { @@ -367,6 +437,14 @@ nsPACMan::OnStreamComplete(nsIStreamLoader *loader, const char *text = (const char *) data; status = mPAC->Init(pacURI, NS_ConvertASCIItoUTF16(text, dataLen)); } + + // Even if the PAC file could not be parsed, we did succeed in loading the + // data for it. + mLoadFailureCount = 0; + } else { + // We were unable to load the PAC file (presumably because of a network + // failure). Try again a little later. + OnLoadFailure(); } // Reset mPAC if necessary diff --git a/netwerk/base/src/nsPACMan.h b/netwerk/base/src/nsPACMan.h index 0df01211a0c..f977cd80d77 100644 --- a/netwerk/base/src/nsPACMan.h +++ b/netwerk/base/src/nsPACMan.h @@ -118,7 +118,8 @@ public: * processed once the PAC file finishes loading. * * @param pacURI - * The nsIURI of the PAC file to load. + * The nsIURI of the PAC file to load. If this parameter is null, + * then the previous PAC URI is simply reloaded. */ nsresult LoadPACFromURI(nsIURI *pacURI); @@ -151,6 +152,16 @@ private: */ void StartLoading(); + /** + * Reload the PAC file if there is reason to. + */ + void MaybeReloadPAC(); + + /** + * Called when we fail to load the PAC file. + */ + void OnLoadFailure(); + /** * Returns true if the given URI matches the URI of our PAC file. */ @@ -166,6 +177,8 @@ private: nsCOMPtr mLoader; PRPackedBool mLoadPending; PRPackedBool mShutdown; + PRTime mScheduledReload; + PRUint32 mLoadFailureCount; }; #endif // nsPACMan_h__