1 // Copyright 2023 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/proxy_resolution/proxy_chain_util_apple.h"
6
7 #include <CFNetwork/CFProxySupport.h>
8 #include <CoreFoundation/CoreFoundation.h>
9
10 #include <string>
11
12 #include "base/apple/foundation_util.h"
13 #include "base/apple/scoped_cftyperef.h"
14 #include "base/logging.h"
15 #include "base/strings/sys_string_conversions.h"
16 #include "net/base/host_port_pair.h"
17 #include "net/base/proxy_chain.h"
18 #include "net/base/proxy_server.h"
19
20 namespace net {
21
22 namespace {
23
24 // Utility function to map a CFProxyType to a ProxyServer::Scheme.
25 // If the type is unknown, returns ProxyServer::SCHEME_INVALID.
GetProxyServerScheme(CFStringRef proxy_type)26 ProxyServer::Scheme GetProxyServerScheme(CFStringRef proxy_type) {
27 if (CFEqual(proxy_type, kCFProxyTypeHTTP)) {
28 return ProxyServer::SCHEME_HTTP;
29 }
30 if (CFEqual(proxy_type, kCFProxyTypeHTTPS)) {
31 // The "HTTPS" on the Mac side here means "proxy applies to https://" URLs;
32 // the proxy itself is still expected to be an HTTP proxy.
33 return ProxyServer::SCHEME_HTTP;
34 }
35 if (CFEqual(proxy_type, kCFProxyTypeSOCKS)) {
36 // We can't tell whether this was v4 or v5. We will assume it is
37 // v5 since that is the only version macOS X supports.
38 return ProxyServer::SCHEME_SOCKS5;
39 }
40 return ProxyServer::SCHEME_INVALID;
41 }
42
43 } // namespace
44
ProxyDictionaryToProxyChain(CFStringRef proxy_type,CFDictionaryRef dict,CFStringRef host_key,CFStringRef port_key)45 ProxyChain ProxyDictionaryToProxyChain(CFStringRef proxy_type,
46 CFDictionaryRef dict,
47 CFStringRef host_key,
48 CFStringRef port_key) {
49 ProxyServer::Scheme scheme = GetProxyServerScheme(proxy_type);
50 if (CFEqual(proxy_type, kCFProxyTypeNone)) {
51 return ProxyChain::Direct();
52 }
53
54 if (scheme == ProxyServer::SCHEME_INVALID) {
55 // No hostname port to extract; we are done.
56 return ProxyChain(scheme, HostPortPair());
57 }
58
59 CFStringRef host_ref =
60 base::apple::GetValueFromDictionary<CFStringRef>(dict, host_key);
61 if (!host_ref) {
62 LOG(WARNING) << "Could not find expected key "
63 << base::SysCFStringRefToUTF8(host_key)
64 << " in the proxy dictionary";
65 return ProxyChain(); // Invalid.
66 }
67 std::string host = base::SysCFStringRefToUTF8(host_ref);
68
69 CFNumberRef port_ref =
70 base::apple::GetValueFromDictionary<CFNumberRef>(dict, port_key);
71 int port;
72 if (port_ref) {
73 CFNumberGetValue(port_ref, kCFNumberIntType, &port);
74 } else {
75 port = ProxyServer::GetDefaultPortForScheme(scheme);
76 }
77
78 return ProxyChain::FromSchemeHostAndPort(scheme, host, port);
79 }
80
81 } // namespace net
82