xref: /aosp_15_r20/external/cronet/net/proxy_resolution/proxy_chain_util_apple.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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