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; CFIndex numProxies = CFArrayGetCount(proxiesForURL.get()); for (CFIndex i = 0; i < numProxies; ++i) { CFDictionaryRef proxyDictionary = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(proxiesForURL.get(), i)); ProxyServer::Type type = ProxyServer::Direct; CFStringRef typeString = static_cast<CFStringRef>(CFDictionaryGetValue(proxyDictionary, kCFProxyTypeKey)); if (CFEqual(typeString, kCFProxyTypeAutoConfigurationURL)) { // FIXME: Handle PAC URLs. 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)) type = ProxyServer::HTTPS; else if (CFEqual(typeString, kCFProxyTypeSOCKS)) type = ProxyServer::SOCKS; else { // We don't know how to handle this type. continue; } CFStringRef host = static_cast<CFStringRef>(CFDictionaryGetValue(proxyDictionary, kCFProxyHostNameKey)); CFNumberRef port = static_cast<CFNumberRef>(CFDictionaryGetValue(proxyDictionary, kCFProxyPortNumberKey)); SInt32 portValue; CFNumberGetValue(port, kCFNumberSInt32Type, &portValue); proxyServers.append(ProxyServer(type, host, portValue)); } }
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(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)) { 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)) type = ProxyServer::HTTPS; else if (CFEqual(typeString, kCFProxyTypeSOCKS)) type = ProxyServer::SOCKS; else { // We don't know how to handle this type. continue; } CFStringRef host = static_cast<CFStringRef>(CFDictionaryGetValue(proxyDictionary, kCFProxyHostNameKey)); CFNumberRef port = static_cast<CFNumberRef>(CFDictionaryGetValue(proxyDictionary, kCFProxyPortNumberKey)); SInt32 portValue; CFNumberGetValue(port, kCFNumberSInt32Type, &portValue); proxyServers.append(ProxyServer(type, host, portValue)); } }