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