Title: [107966] trunk/Source/WebCore
Revision
107966
Author
[email protected]
Date
2012-02-16 12:19:57 -0800 (Thu, 16 Feb 2012)

Log Message

NPN_GetValueForURL / NPNURLVProxy returns DIRECT when proxy configured via PAC
<http://webkit.org/b/78766> / <rdar://problem/10729283>

Reviewed by Anders Carlsson.

* platform/network/cf/ProxyServerCFNet.cpp:
(WebCore::proxyAutoConfigurationResultCallback): Stop the runloop, and then process
the results that we received.
(WebCore::processProxyServers): Processing of array of proxy configuration information
moved from addProxyServersForURL. Handling of proxy auto-configuration URLs is now handled
by calling CFNetworkExecuteProxyAutoConfigurationURL and waiting synchronously on the result
callback. Doing this synchronously is not great, but it's the best we can do without a lot
of restructuring of the code that calls this. We arbitrarily time out the execution after five
seconds to avoid permanently hanging.
(WebCore::addProxyServersForURL): Call in to our helper function.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (107965 => 107966)


--- trunk/Source/WebCore/ChangeLog	2012-02-16 20:16:46 UTC (rev 107965)
+++ trunk/Source/WebCore/ChangeLog	2012-02-16 20:19:57 UTC (rev 107966)
@@ -1,3 +1,21 @@
+2012-02-15  Mark Rowe  <[email protected]>
+
+        NPN_GetValueForURL / NPNURLVProxy returns DIRECT when proxy configured via PAC
+        <http://webkit.org/b/78766> / <rdar://problem/10729283>
+
+        Reviewed by Anders Carlsson.
+
+        * platform/network/cf/ProxyServerCFNet.cpp:
+        (WebCore::proxyAutoConfigurationResultCallback): Stop the runloop, and then process
+        the results that we received.
+        (WebCore::processProxyServers): Processing of array of proxy configuration information
+        moved from addProxyServersForURL. Handling of proxy auto-configuration URLs is now handled
+        by calling CFNetworkExecuteProxyAutoConfigurationURL and waiting synchronously on the result
+        callback. Doing this synchronously is not great, but it's the best we can do without a lot
+        of restructuring of the code that calls this. We arbitrarily time out the execution after five
+        seconds to avoid permanently hanging.
+        (WebCore::addProxyServersForURL): Call in to our helper function.
+
 2012-02-16  Abhishek Arya  <[email protected]>
 
         Fix clone() function to handle descendant classes of RenderBlock.

Modified: trunk/Source/WebCore/platform/network/cf/ProxyServerCFNet.cpp (107965 => 107966)


--- trunk/Source/WebCore/platform/network/cf/ProxyServerCFNet.cpp	2012-02-16 20:16:46 UTC (rev 107965)
+++ trunk/Source/WebCore/platform/network/cf/ProxyServerCFNet.cpp	2012-02-16 20:19:57 UTC (rev 107966)
@@ -27,7 +27,9 @@
 #include "ProxyServer.h"
 
 #include "KURL.h"
+#include "Logging.h"
 #include <wtf/RetainPtr.h>
+#include <wtf/text/CString.h>
 
 #if PLATFORM(WIN)
 #include <CFNetwork/CFNetwork.h>
@@ -36,33 +38,69 @@
 namespace WebCore {
 
 #ifndef BUILDING_ON_LEOPARD
-static void addProxyServersForURL(Vector<ProxyServer>& proxyServers, const KURL& url)
+
+static void processProxyServers(Vector<ProxyServer>& proxyServers, CFArrayRef proxies, CFURLRef url);
+
+static void proxyAutoConfigurationResultCallback(void *context, CFArrayRef proxies, CFErrorRef error)
 {
-    RetainPtr<CFDictionaryRef> proxySettings(AdoptCF, CFNetworkCopySystemProxySettings());
-    if (!proxySettings)
-        return;
+    // We only expect a single result callback per invocation. Stop our runloop to unblock our caller.
+    CFRunLoopStop(CFRunLoopGetCurrent());
 
-    RetainPtr<CFURLRef> cfURL(AdoptCF, url.createCFURL());
-    RetainPtr<CFArrayRef> proxiesForURL(AdoptCF, CFNetworkCopyProxiesForURL(cfURL.get(), proxySettings.get()));
-    if (!proxiesForURL)
+    Vector<ProxyServer>* proxyServers = (Vector<ProxyServer>*)context;
+    if (!proxies) {
+        ASSERT(error);
+        RetainPtr<CFStringRef> errorDescriptionCF(AdoptCF, CFErrorCopyDescription(error));
+        String errorDescription(errorDescriptionCF.get());
+        LOG(Network, "Failed to process proxy auto-configuration file with error: %s", errorDescription.utf8().data());
         return;
+    }
 
-    CFIndex numProxies = CFArrayGetCount(proxiesForURL.get());
+    processProxyServers(*proxyServers, proxies, 0);
+}
+
+static void processProxyServers(Vector<ProxyServer>& proxyServers, CFArrayRef proxies, CFURLRef url)
+{
+    CFIndex numProxies = CFArrayGetCount(proxies);
     for (CFIndex i = 0; i < numProxies; ++i) {
-        CFDictionaryRef proxyDictionary = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(proxiesForURL.get(), i));
+        CFDictionaryRef proxyDictionary = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(proxies, i));
 
         ProxyServer::Type type = ProxyServer::Direct;
         CFStringRef typeString = static_cast<CFStringRef>(CFDictionaryGetValue(proxyDictionary, kCFProxyTypeKey));
+
+        if (!url) {
+            // If we have no URL then we're processing an auto-configuration response.
+            // It isn't sensible to receive another auto-configured proxy in such a response.
+            ASSERT(!CFEqual(typeString, kCFProxyTypeAutoConfigurationURL));
+        }
+
         if (CFEqual(typeString, kCFProxyTypeAutoConfigurationURL)) {
-            // FIXME: Handle PAC URLs.
+            if (!url)
+                continue;
+
+            // FIXME: We should restructure to allow this to happen asynchronously.
+            CFURLRef scriptURL = static_cast<CFURLRef>(CFDictionaryGetValue(proxyDictionary, kCFProxyAutoConfigurationURLKey));
+            if (!scriptURL || CFGetTypeID(scriptURL) != CFURLGetTypeID())
+                continue;
+
+            CFStreamClientContext context = { 0, (void*)&proxyServers, 0, 0, 0 };
+            RetainPtr<CFRunLoopSourceRef> runLoopSource(AdoptCF, CFNetworkExecuteProxyAutoConfigurationURL(scriptURL, url, proxyAutoConfigurationResultCallback, &context));
+
+            CFStringRef privateRunLoopMode = CFSTR("com.apple.WebKit.ProxyAutoConfiguration");
+            CFTimeInterval timeout = 5;
+            CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource.get(), privateRunLoopMode);
+            CFRunLoopRunInMode(privateRunLoopMode, timeout, 0);
+            CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runLoopSource.get(), privateRunLoopMode);
+            CFRunLoopSourceInvalidate(runLoopSource.get());
+
+            // The proxyAutoConfigurationResultCallback has added any relevant ProxyServers to proxyServers.
             continue;
-        } 
-        
+        }
+
         if (CFEqual(typeString, kCFProxyTypeNone)) {
             proxyServers.append(ProxyServer(ProxyServer::Direct, String(), -1));
             continue;
         }
-        
+
         if (CFEqual(typeString, kCFProxyTypeHTTP))
             type = ProxyServer::HTTP;
         else if (CFEqual(typeString, kCFProxyTypeHTTPS))
@@ -83,6 +121,20 @@
     }
 }
 
+static void addProxyServersForURL(Vector<ProxyServer>& proxyServers, const KURL& url)
+{
+    RetainPtr<CFDictionaryRef> proxySettings(AdoptCF, CFNetworkCopySystemProxySettings());
+    if (!proxySettings)
+        return;
+
+    RetainPtr<CFURLRef> cfURL(AdoptCF, url.createCFURL());
+    RetainPtr<CFArrayRef> proxiesForURL(AdoptCF, CFNetworkCopyProxiesForURL(cfURL.get(), proxySettings.get()));
+    if (!proxiesForURL)
+        return;
+
+    processProxyServers(proxyServers, proxiesForURL.get(), cfURL.get());
+}
+
 Vector<ProxyServer> proxyServersForURL(const KURL& url, const NetworkingContext*)
 {
     Vector<ProxyServer> proxyServers;
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to