1 // Copyright 2012 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_config_service_ios.h"
6
7 #include <CFNetwork/CFProxySupport.h>
8 #include <CoreFoundation/CoreFoundation.h>
9
10 #include "base/apple/foundation_util.h"
11 #include "base/apple/scoped_cftyperef.h"
12 #include "base/functional/bind.h"
13 #include "base/functional/callback.h"
14 #include "base/strings/sys_string_conversions.h"
15 #include "net/base/proxy_chain.h"
16 #include "net/proxy_resolution/proxy_chain_util_apple.h"
17 #include "net/proxy_resolution/proxy_config_with_annotation.h"
18
19 namespace net {
20
21 namespace {
22
23 const int kPollIntervalSec = 10;
24
25 // Utility function to pull out a boolean value from a dictionary and return it,
26 // returning a default value if the key is not present.
GetBoolFromDictionary(CFDictionaryRef dict,CFStringRef key,bool default_value)27 bool GetBoolFromDictionary(CFDictionaryRef dict,
28 CFStringRef key,
29 bool default_value) {
30 CFNumberRef number =
31 base::apple::GetValueFromDictionary<CFNumberRef>(dict, key);
32 if (!number) {
33 return default_value;
34 }
35
36 int int_value;
37 if (CFNumberGetValue(number, kCFNumberIntType, &int_value)) {
38 return int_value;
39 } else {
40 return default_value;
41 }
42 }
43
GetCurrentProxyConfig(const NetworkTrafficAnnotationTag traffic_annotation,ProxyConfigWithAnnotation * config)44 void GetCurrentProxyConfig(const NetworkTrafficAnnotationTag traffic_annotation,
45 ProxyConfigWithAnnotation* config) {
46 base::apple::ScopedCFTypeRef<CFDictionaryRef> config_dict(
47 CFNetworkCopySystemProxySettings());
48 DCHECK(config_dict);
49 ProxyConfig proxy_config;
50 // Auto-detect is not supported.
51 // The kCFNetworkProxiesProxyAutoDiscoveryEnable key is not available on iOS.
52
53 // PAC file
54
55 if (GetBoolFromDictionary(config_dict.get(),
56 kCFNetworkProxiesProxyAutoConfigEnable, false)) {
57 CFStringRef pac_url_ref = base::apple::GetValueFromDictionary<CFStringRef>(
58 config_dict.get(), kCFNetworkProxiesProxyAutoConfigURLString);
59 if (pac_url_ref) {
60 proxy_config.set_pac_url(GURL(base::SysCFStringRefToUTF8(pac_url_ref)));
61 }
62 }
63
64 // Proxies (for now http).
65
66 // The following keys are not available on iOS:
67 // kCFNetworkProxiesFTPEnable
68 // kCFNetworkProxiesFTPProxy
69 // kCFNetworkProxiesFTPPort
70 // kCFNetworkProxiesHTTPSEnable
71 // kCFNetworkProxiesHTTPSProxy
72 // kCFNetworkProxiesHTTPSPort
73 // kCFNetworkProxiesSOCKSEnable
74 // kCFNetworkProxiesSOCKSProxy
75 // kCFNetworkProxiesSOCKSPort
76 if (GetBoolFromDictionary(config_dict.get(), kCFNetworkProxiesHTTPEnable,
77 false)) {
78 ProxyChain proxy_chain = ProxyDictionaryToProxyChain(
79 kCFProxyTypeHTTP, config_dict.get(), kCFNetworkProxiesHTTPProxy,
80 kCFNetworkProxiesHTTPPort);
81 if (proxy_chain.IsValid()) {
82 proxy_config.proxy_rules().type =
83 ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME;
84 proxy_config.proxy_rules().proxies_for_http.SetSingleProxyChain(
85 proxy_chain);
86 // Desktop Safari applies the HTTP proxy to http:// URLs only, but
87 // Mobile Safari applies the HTTP proxy to https:// URLs as well.
88 proxy_config.proxy_rules().proxies_for_https.SetSingleProxyChain(
89 proxy_chain);
90 }
91 }
92
93 // Proxy bypass list is not supported.
94 // The kCFNetworkProxiesExceptionsList key is not available on iOS.
95
96 // Proxy bypass boolean is not supported.
97 // The kCFNetworkProxiesExcludeSimpleHostnames key is not available on iOS.
98
99 // Source
100 proxy_config.set_from_system(true);
101 *config = ProxyConfigWithAnnotation(proxy_config, traffic_annotation);
102 }
103
104 } // namespace
105
ProxyConfigServiceIOS(const NetworkTrafficAnnotationTag & traffic_annotation)106 ProxyConfigServiceIOS::ProxyConfigServiceIOS(
107 const NetworkTrafficAnnotationTag& traffic_annotation)
108 : PollingProxyConfigService(base::Seconds(kPollIntervalSec),
109 base::BindRepeating(GetCurrentProxyConfig),
110 traffic_annotation) {}
111
112 ProxyConfigServiceIOS::~ProxyConfigServiceIOS() = default;
113
114 } // namespace net
115