Bug 235853: Defer proxy resolution for HTTP and HTTPS PAC to avoid blocking main thread during DNS resolution, and fix HTTP channel code to properly forward cache-related properties to new proxied channels, patch by shaver@mozilla.org, r+sr=biesi, a=beltzner
--- a/extensions/cookie/test/test_loadflags.html
+++ b/extensions/cookie/test/test_loadflags.html
@@ -1,16 +1,16 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Cross domain access to properties</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
-<body onload="setupTest('http://example.org/tests/extensions/cookie/test/file_loadflags_inner.html', 'example.org', 5, 1, 2)">
+<body onload="setupTest('http://example.org/tests/extensions/cookie/test/file_loadflags_inner.html', 'example.org', 5, 1, 4)">
<p id="display"></p>
<pre id="test">
<script class="testbody" type="text/javascript" src="file_testloadflags.js">
</script>
</pre>
</body>
</html>
--- a/netwerk/base/src/nsIOService.cpp
+++ b/netwerk/base/src/nsIOService.cpp
@@ -545,17 +545,27 @@ nsIOService::NewChannelFromURI(nsIURI *a
if (protoFlags & nsIProtocolHandler::ALLOWS_PROXY) {
nsCOMPtr<nsIProxyInfo> pi;
if (!mProxyService) {
mProxyService = do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID);
if (!mProxyService)
NS_WARNING("failed to get protocol proxy service");
}
if (mProxyService) {
- rv = mProxyService->Resolve(aURI, 0, getter_AddRefs(pi));
+ PRUint32 flags = 0;
+ if (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https"))
+ flags = nsIProtocolProxyService::RESOLVE_NON_BLOCKING;
+ rv = mProxyService->Resolve(aURI, flags, getter_AddRefs(pi));
+ if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
+ // Use an UNKNOWN proxy to defer resolution and avoid blocking.
+ rv = mProxyService->NewProxyInfo(NS_LITERAL_CSTRING("unknown"),
+ NS_LITERAL_CSTRING(""),
+ -1, 0, 0, nsnull,
+ getter_AddRefs(pi));
+ }
if (NS_FAILED(rv))
pi = nsnull;
}
if (pi) {
nsCAutoString type;
if (NS_SUCCEEDED(pi->GetType(type)) && type.EqualsLiteral("http")) {
// we are going to proxy this channel using an http proxy
rv = GetProtocolHandler("http", getter_AddRefs(handler));
--- a/netwerk/base/src/nsProtocolProxyService.cpp
+++ b/netwerk/base/src/nsProtocolProxyService.cpp
@@ -918,17 +918,18 @@ nsProtocolProxyService::NewProxyInfo(con
PRUint32 aFailoverTimeout,
nsIProxyInfo *aFailoverProxy,
nsIProxyInfo **aResult)
{
static const char *types[] = {
kProxyType_HTTP,
kProxyType_SOCKS,
kProxyType_SOCKS4,
- kProxyType_DIRECT
+ kProxyType_DIRECT,
+ kProxyType_UNKNOWN
};
// resolve type; this allows us to avoid copying the type string into each
// proxy info instance. we just reference the string literals directly :)
const char *type = nsnull;
for (PRUint32 i=0; i<NS_ARRAY_LENGTH(types); ++i) {
if (aType.LowerCaseEqualsASCII(types[i])) {
type = types[i];
--- a/netwerk/protocol/http/src/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/src/nsHttpChannel.cpp
@@ -1055,17 +1055,17 @@ nsHttpChannel::DoReplaceWithProxy(nsIPro
{
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);
+ rv = SetupReplacementChannel(mURI, newChannel, PR_TRUE, 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;
@@ -2244,17 +2244,18 @@ CopyProperties(const nsAString& aKey, ns
(aClosure);
bag->SetProperty(aKey, aData);
return PL_DHASH_NEXT;
}
nsresult
nsHttpChannel::SetupReplacementChannel(nsIURI *newURI,
nsIChannel *newChannel,
- PRBool preserveMethod)
+ PRBool preserveMethod,
+ PRBool transferCacheInfo)
{
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.
@@ -2329,16 +2330,36 @@ nsHttpChannel::SetupReplacementChannel(n
resumableChannel->ResumeAt(mStartPos, mEntityID);
}
// transfer any properties
nsCOMPtr<nsIWritablePropertyBag> bag(do_QueryInterface(newChannel));
if (bag)
mPropertyHash.EnumerateRead(CopyProperties, bag.get());
+ // Transfer the cache info to the new channel, if needed.
+ if (transferCacheInfo) {
+ nsCOMPtr<nsICachingChannel> cachingChannel = do_QueryInterface(newChannel);
+ if (cachingChannel) {
+ // cacheKey is just mPostID wrapped in an nsISupportsPRUint32,
+ // we don't need to transfer it if it's 0.
+ if (mPostID) {
+ nsCOMPtr<nsISupports> cacheKey;
+ GetCacheKey(getter_AddRefs(cacheKey));
+ if (cacheKey) {
+ cachingChannel->SetCacheKey(cacheKey);
+ }
+ }
+
+ // cacheClientID, cacheForOfflineUse
+ cachingChannel->SetOfflineCacheClientID(mOfflineCacheClientID);
+ cachingChannel->SetCacheForOfflineUse(mCacheForOfflineUse);
+ }
+ }
+
return NS_OK;
}
nsresult
nsHttpChannel::ProcessRedirection(PRUint32 redirectType)
{
LOG(("nsHttpChannel::ProcessRedirection [this=%x type=%u]\n",
this, redirectType));
@@ -2414,17 +2435,17 @@ nsHttpChannel::ProcessRedirection(PRUint
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);
+ rv = SetupReplacementChannel(newURI, newChannel, preserveMethod, PR_FALSE);
if (NS_FAILED(rv)) return rv;
PRUint32 redirectFlags;
if (redirectType == 301) // Moved Permanently
redirectFlags = nsIChannelEventSink::REDIRECT_PERMANENT;
else
redirectFlags = nsIChannelEventSink::REDIRECT_TEMPORARY;
--- a/netwerk/protocol/http/src/nsHttpChannel.h
+++ b/netwerk/protocol/http/src/nsHttpChannel.h
@@ -162,17 +162,17 @@ private:
nsresult ProcessRedirection(PRUint32 httpStatus);
nsresult ProcessAuthentication(PRUint32 httpStatus);
PRBool ResponseWouldVary();
// redirection specific methods
void HandleAsyncRedirect();
void HandleAsyncNotModified();
nsresult PromptTempRedirect();
- nsresult SetupReplacementChannel(nsIURI *, nsIChannel *, PRBool preserveMethod);
+ nsresult SetupReplacementChannel(nsIURI *, nsIChannel *, PRBool preserveMethod, PRBool transferCacheInfo);
// proxy specific methods
nsresult ProxyFailover();
nsresult DoReplaceWithProxy(nsIProxyInfo *);
void HandleAsyncReplaceWithProxy();
nsresult ResolveProxy();
// cache specific methods