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
authorgavin@gavinsharp.com
Thu, 17 Apr 2008 18:36:29 -0700
changeset 14443 098aaf5ccdb8cddf4606b97f82093aae2a339c2e
parent 14442 51b6c016b617023883abea1191a77b7e45f95aa5
child 14444 21f8472921e34e9ee3da82de67e210cb21cb8226
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbeltzner
bugs235853
milestone1.9pre
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
extensions/cookie/test/test_loadflags.html
netwerk/base/src/nsIOService.cpp
netwerk/base/src/nsProtocolProxyService.cpp
netwerk/protocol/http/src/nsHttpChannel.cpp
netwerk/protocol/http/src/nsHttpChannel.h
--- 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