<http://webkit.org/b/91015> Remove BUILDING_ON / TARGETING macros in favor of system...
[WebKit-https.git] / Source / WebCore / platform / network / cf / ProxyServerCFNet.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "ProxyServer.h"
28
29 #include "KURL.h"
30 #include "Logging.h"
31 #include <wtf/RetainPtr.h>
32 #include <wtf/text/CString.h>
33
34 #if PLATFORM(WIN)
35 #include <CFNetwork/CFNetwork.h>
36 #endif
37
38 namespace WebCore {
39
40 #if !PLATFORM(MAC) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
41
42 static void processProxyServers(Vector<ProxyServer>& proxyServers, CFArrayRef proxies, CFURLRef url);
43
44 static void proxyAutoConfigurationResultCallback(void *context, CFArrayRef proxies, CFErrorRef error)
45 {
46     // We only expect a single result callback per invocation. Stop our runloop to unblock our caller.
47     CFRunLoopStop(CFRunLoopGetCurrent());
48
49     Vector<ProxyServer>* proxyServers = (Vector<ProxyServer>*)context;
50     if (!proxies) {
51         ASSERT(error);
52         RetainPtr<CFStringRef> errorDescriptionCF(AdoptCF, CFErrorCopyDescription(error));
53         String errorDescription(errorDescriptionCF.get());
54         LOG(Network, "Failed to process proxy auto-configuration file with error: %s", errorDescription.utf8().data());
55         return;
56     }
57
58     processProxyServers(*proxyServers, proxies, 0);
59 }
60
61 static void processProxyServers(Vector<ProxyServer>& proxyServers, CFArrayRef proxies, CFURLRef url)
62 {
63     CFIndex numProxies = CFArrayGetCount(proxies);
64     for (CFIndex i = 0; i < numProxies; ++i) {
65         CFDictionaryRef proxyDictionary = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(proxies, i));
66
67         ProxyServer::Type type = ProxyServer::Direct;
68         CFStringRef typeString = static_cast<CFStringRef>(CFDictionaryGetValue(proxyDictionary, kCFProxyTypeKey));
69
70         if (!url) {
71             // If we have no URL then we're processing an auto-configuration response.
72             // It isn't sensible to receive another auto-configured proxy in such a response.
73             ASSERT(!CFEqual(typeString, kCFProxyTypeAutoConfigurationURL));
74         }
75
76         if (CFEqual(typeString, kCFProxyTypeAutoConfigurationURL)) {
77             if (!url)
78                 continue;
79
80             // FIXME: We should restructure to allow this to happen asynchronously.
81             CFURLRef scriptURL = static_cast<CFURLRef>(CFDictionaryGetValue(proxyDictionary, kCFProxyAutoConfigurationURLKey));
82             if (!scriptURL || CFGetTypeID(scriptURL) != CFURLGetTypeID())
83                 continue;
84
85             CFStreamClientContext context = { 0, (void*)&proxyServers, 0, 0, 0 };
86             RetainPtr<CFRunLoopSourceRef> runLoopSource(AdoptCF, CFNetworkExecuteProxyAutoConfigurationURL(scriptURL, url, proxyAutoConfigurationResultCallback, &context));
87
88             CFStringRef privateRunLoopMode = CFSTR("com.apple.WebKit.ProxyAutoConfiguration");
89             CFTimeInterval timeout = 5;
90             CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource.get(), privateRunLoopMode);
91             CFRunLoopRunInMode(privateRunLoopMode, timeout, 0);
92             CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runLoopSource.get(), privateRunLoopMode);
93             CFRunLoopSourceInvalidate(runLoopSource.get());
94
95             // The proxyAutoConfigurationResultCallback has added any relevant ProxyServers to proxyServers.
96             continue;
97         }
98
99         if (CFEqual(typeString, kCFProxyTypeNone)) {
100             proxyServers.append(ProxyServer(ProxyServer::Direct, String(), -1));
101             continue;
102         }
103
104         if (CFEqual(typeString, kCFProxyTypeHTTP))
105             type = ProxyServer::HTTP;
106         else if (CFEqual(typeString, kCFProxyTypeHTTPS))
107             type = ProxyServer::HTTPS;
108         else if (CFEqual(typeString, kCFProxyTypeSOCKS))
109             type = ProxyServer::SOCKS;
110         else {
111             // We don't know how to handle this type.
112             continue;
113         }
114
115         CFStringRef host = static_cast<CFStringRef>(CFDictionaryGetValue(proxyDictionary, kCFProxyHostNameKey));
116         CFNumberRef port = static_cast<CFNumberRef>(CFDictionaryGetValue(proxyDictionary, kCFProxyPortNumberKey));
117         SInt32 portValue;
118         CFNumberGetValue(port, kCFNumberSInt32Type, &portValue);
119
120         proxyServers.append(ProxyServer(type, host, portValue));
121     }
122 }
123
124 static void addProxyServersForURL(Vector<ProxyServer>& proxyServers, const KURL& url)
125 {
126     RetainPtr<CFDictionaryRef> proxySettings(AdoptCF, CFNetworkCopySystemProxySettings());
127     if (!proxySettings)
128         return;
129
130     RetainPtr<CFURLRef> cfURL(AdoptCF, url.createCFURL());
131     RetainPtr<CFArrayRef> proxiesForURL(AdoptCF, CFNetworkCopyProxiesForURL(cfURL.get(), proxySettings.get()));
132     if (!proxiesForURL)
133         return;
134
135     processProxyServers(proxyServers, proxiesForURL.get(), cfURL.get());
136 }
137
138 Vector<ProxyServer> proxyServersForURL(const KURL& url, const NetworkingContext*)
139 {
140     Vector<ProxyServer> proxyServers;
141     
142     addProxyServersForURL(proxyServers, url);
143     return proxyServers;
144     
145 }
146 #else
147 Vector<ProxyServer> proxyServersForURL(const KURL&, const NetworkingContext*)
148 {
149     // FIXME: Implement.
150     return Vector<ProxyServer>();
151 }
152 #endif
153
154 } // namespace WebCore