зеркало из https://github.com/mozilla/pjs.git
fixes bug 100022 "PAC: first page/homepage load fails (b/c automatic proxy configuration is slower than first HTTP request)" r=biesi a=asa
This commit is contained in:
Родитель
6e37d41b47
Коммит
5e1daa9a78
|
@ -94,6 +94,12 @@ interface nsIProtocolProxyService : nsISupports
|
|||
* the given URI should be loaded using the HTTP protocol handler, which
|
||||
* also supports nsIProxiedProtocolHandler.
|
||||
*
|
||||
* NOTE: If PAC is configured, and the PAC file has not yet been loaded,
|
||||
* then this method will return a nsIProxyInfo instance with a type of
|
||||
* "unknown" to indicate to the consumer that asyncResolve should be used
|
||||
* to wait for the PAC file to finish loading. Otherwise, the consumer
|
||||
* may choose to treat the result as type "direct" if desired.
|
||||
*
|
||||
* @see nsIProxiedProtocolHandler::newProxiedChannel
|
||||
*/
|
||||
nsIProxyInfo resolve(in nsIURI aURI, in unsigned long aFlags);
|
||||
|
|
|
@ -66,6 +66,7 @@ interface nsIProxyInfo : nsISupports
|
|||
* "socks" SOCKS v5 proxy
|
||||
* "socks4" SOCKS v4 proxy
|
||||
* "direct" no proxy
|
||||
* "unknown" unknown proxy (see nsIProtocolProxyService::resolve)
|
||||
*/
|
||||
readonly attribute ACString type;
|
||||
|
||||
|
|
|
@ -154,6 +154,7 @@ PendingPACQuery::OnLookupComplete(nsICancelable *request,
|
|||
nsPACMan::nsPACMan()
|
||||
: mLoadEvent(nsnull)
|
||||
, mShutdown(PR_FALSE)
|
||||
, mStartingToLoad(PR_FALSE)
|
||||
{
|
||||
PR_INIT_CLIST(&mPendingQ);
|
||||
}
|
||||
|
@ -180,7 +181,14 @@ nsPACMan::GetProxyForURI(nsIURI *uri, nsACString &result)
|
|||
{
|
||||
NS_ENSURE_STATE(!mShutdown);
|
||||
|
||||
if (!mPAC || IsLoading())
|
||||
if (mStartingToLoad) {
|
||||
result.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (IsLoading())
|
||||
return NS_ERROR_IN_PROGRESS;
|
||||
if (!mPAC)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
nsCAutoString spec, host;
|
||||
|
@ -284,7 +292,14 @@ nsPACMan::StartLoading()
|
|||
nsCOMPtr<nsIIOService> ios = do_GetIOService();
|
||||
if (ios) {
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
|
||||
// Calling NewChannel will result in GetProxyForURI being called, and we
|
||||
// want to make sure that it does not return NS_ERROR_IN_PROGRESS. So,
|
||||
// we set this flag to cause it to indicate a DIRECT fetch for this URI.
|
||||
mStartingToLoad = PR_TRUE;
|
||||
ios->NewChannel(mPACSpec, nsnull, nsnull, getter_AddRefs(channel));
|
||||
mStartingToLoad = PR_FALSE;
|
||||
|
||||
if (channel) {
|
||||
channel->SetLoadFlags(nsIRequest::LOAD_BYPASS_CACHE);
|
||||
channel->SetNotificationCallbacks(this);
|
||||
|
|
|
@ -91,7 +91,8 @@ public:
|
|||
* @param result
|
||||
* Holds the PAC result string upon return.
|
||||
*
|
||||
* @return NS_ERROR_NOT_AVAILABLE if the PAC file is not yet loaded.
|
||||
* @return NS_ERROR_IN_PROGRESS if the PAC file is not yet loaded.
|
||||
* @return NS_ERROR_NOT_AVAILABLE if the PAC file could not be loaded.
|
||||
*/
|
||||
nsresult GetProxyForURI(nsIURI *uri, nsACString &result);
|
||||
|
||||
|
@ -159,6 +160,7 @@ private:
|
|||
nsCOMPtr<nsIStreamLoader> mLoader;
|
||||
PLEvent *mLoadEvent;
|
||||
PRPackedBool mShutdown;
|
||||
PRPackedBool mStartingToLoad;
|
||||
};
|
||||
|
||||
#endif // nsPACMan_h__
|
||||
|
|
|
@ -577,6 +577,7 @@ static const char kProxyType_SOCKS[] = "socks";
|
|||
static const char kProxyType_SOCKS4[] = "socks4";
|
||||
static const char kProxyType_SOCKS5[] = "socks5";
|
||||
static const char kProxyType_DIRECT[] = "direct";
|
||||
static const char kProxyType_UNKNOWN[] = "unknown";
|
||||
|
||||
const char *
|
||||
nsProtocolProxyService::ExtractProxyInfo(const char *start, nsProxyInfo **result)
|
||||
|
@ -802,10 +803,18 @@ nsProtocolProxyService::Resolve(nsIURI *uri, PRUint32 flags,
|
|||
// Query the PAC file synchronously.
|
||||
nsCString pacString;
|
||||
rv = mPACMan->GetProxyForURI(uri, pacString);
|
||||
if (NS_FAILED(rv))
|
||||
NS_WARNING("failed querying PAC file; trying DIRECT");
|
||||
else
|
||||
if (NS_SUCCEEDED(rv))
|
||||
ProcessPACString(pacString, result);
|
||||
else if (rv == NS_ERROR_IN_PROGRESS) {
|
||||
// Construct a special UNKNOWN proxy entry that informs the caller
|
||||
// that the proxy info is yet to be determined.
|
||||
rv = NewProxyInfo_Internal(kProxyType_UNKNOWN, EmptyCString(), -1,
|
||||
0, 0, nsnull, result);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
else
|
||||
NS_WARNING("failed querying PAC file; trying DIRECT");
|
||||
}
|
||||
|
||||
ApplyFilters(uri, info, result);
|
||||
|
|
|
@ -745,7 +745,8 @@ nsSocketTransport::Init(const char **types, PRUint32 typeCount,
|
|||
// grab proxy type (looking for "socks" for example)
|
||||
proxyType = proxyInfo->Type();
|
||||
if (proxyType && (strcmp(proxyType, "http") == 0 ||
|
||||
strcmp(proxyType, "direct") == 0))
|
||||
strcmp(proxyType, "direct") == 0 ||
|
||||
strcmp(proxyType, "unknown") == 0))
|
||||
proxyType = nsnull;
|
||||
}
|
||||
|
||||
|
|
|
@ -308,6 +308,8 @@ nsHttpChannel::Connect(PRBool firstTime)
|
|||
ioService->GetOffline(&offline);
|
||||
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)) {
|
||||
|
@ -920,6 +922,14 @@ nsHttpChannel::ProxyFailover()
|
|||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
return ReplaceWithProxy(pi);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpChannel::ReplaceWithProxy(nsIProxyInfo *pi)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIChannel> newChannel;
|
||||
rv = gHttpHandler->NewProxiedChannel(mURI, pi, getter_AddRefs(newChannel));
|
||||
if (NS_FAILED(rv))
|
||||
|
@ -940,6 +950,21 @@ nsHttpChannel::ProxyFailover()
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpChannel::ResolveProxy()
|
||||
{
|
||||
LOG(("nsHttpChannel::ResolveProxy [this=%x]\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()
|
||||
{
|
||||
|
@ -2940,6 +2965,7 @@ NS_INTERFACE_MAP_BEGIN(nsHttpChannel)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIResumableChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsITransportEventSink)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIProtocolProxyCallback)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsHashPropertyBag)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -2975,7 +3001,9 @@ nsHttpChannel::Cancel(nsresult status)
|
|||
LOG(("nsHttpChannel::Cancel [this=%x status=%x]\n", this, status));
|
||||
mCanceled = PR_TRUE;
|
||||
mStatus = status;
|
||||
if (mTransaction)
|
||||
if (mProxyRequest)
|
||||
mProxyRequest->Cancel(status);
|
||||
else if (mTransaction)
|
||||
gHttpHandler->CancelTransaction(mTransaction, status);
|
||||
else if (mCachePump)
|
||||
mCachePump->Cancel(status);
|
||||
|
@ -3789,6 +3817,38 @@ 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.
|
||||
if (!mCanceled) {
|
||||
status = ReplaceWithProxy(pi);
|
||||
|
||||
// XXX(darin): It'd be nice if removing ourselves from the loadgroup
|
||||
// could be factored into ReplaceWithProxy somehow.
|
||||
if (mLoadGroup && NS_SUCCEEDED(status))
|
||||
mLoadGroup->RemoveRequest(this, nsnull, mStatus);
|
||||
}
|
||||
|
||||
if (NS_FAILED(status))
|
||||
AsyncAbort(status);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpChannel::nsIRequestObserver
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -75,6 +75,8 @@
|
|||
#include "nsIPrompt.h"
|
||||
#include "nsIResumableChannel.h"
|
||||
#include "nsISupportsPriority.h"
|
||||
#include "nsIProtocolProxyCallback.h"
|
||||
#include "nsICancelable.h"
|
||||
|
||||
class nsHttpResponseHead;
|
||||
class nsAHttpConnection;
|
||||
|
@ -96,6 +98,7 @@ class nsHttpChannel : public nsHashPropertyBag
|
|||
, public nsITransportEventSink
|
||||
, public nsIResumableChannel
|
||||
, public nsISupportsPriority
|
||||
, public nsIProtocolProxyCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -112,6 +115,7 @@ public:
|
|||
NS_DECL_NSITRANSPORTEVENTSINK
|
||||
NS_DECL_NSIRESUMABLECHANNEL
|
||||
NS_DECL_NSISUPPORTSPRIORITY
|
||||
NS_DECL_NSIPROTOCOLPROXYCALLBACK
|
||||
|
||||
nsHttpChannel();
|
||||
virtual ~nsHttpChannel();
|
||||
|
@ -160,9 +164,13 @@ private:
|
|||
void HandleAsyncRedirect();
|
||||
void HandleAsyncNotModified();
|
||||
nsresult PromptTempRedirect();
|
||||
nsresult ProxyFailover();
|
||||
nsresult SetupReplacementChannel(nsIURI *, nsIChannel *, PRBool preserveMethod);
|
||||
|
||||
// proxy specific methods
|
||||
nsresult ProxyFailover();
|
||||
nsresult ReplaceWithProxy(nsIProxyInfo *);
|
||||
nsresult ResolveProxy();
|
||||
|
||||
// cache specific methods
|
||||
nsresult OpenCacheEntry(PRBool offline, PRBool *delayed);
|
||||
nsresult GenerateCacheKey(nsACString &key);
|
||||
|
@ -216,6 +224,7 @@ private:
|
|||
nsCOMPtr<nsIURI> mReferrer;
|
||||
nsCOMPtr<nsISupports> mSecurityInfo;
|
||||
nsCOMPtr<nsIEventQueue> mEventQ;
|
||||
nsCOMPtr<nsICancelable> mProxyRequest;
|
||||
|
||||
nsHttpRequestHead mRequestHead;
|
||||
nsHttpResponseHead *mResponseHead;
|
||||
|
|
Загрузка…
Ссылка в новой задаче