1// Copyright (c) 2009 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_mac.h" 6 7#include <CoreFoundation/CoreFoundation.h> 8#include <SystemConfiguration/SystemConfiguration.h> 9 10#include "base/logging.h" 11#include "base/mac_util.h" 12#include "base/scoped_cftyperef.h" 13#include "base/sys_string_conversions.h" 14#include "net/base/net_errors.h" 15#include "net/proxy/proxy_config.h" 16#include "net/proxy/proxy_info.h" 17#include "net/proxy/proxy_server.h" 18 19namespace { 20 21// Utility function to pull out a boolean value from a dictionary and return it, 22// returning a default value if the key is not present. 23bool GetBoolFromDictionary(CFDictionaryRef dict, 24 CFStringRef key, 25 bool default_value) { 26 CFNumberRef number = (CFNumberRef)mac_util::GetValueFromDictionary( 27 dict, key, CFNumberGetTypeID()); 28 if (!number) 29 return default_value; 30 31 int int_value; 32 if (CFNumberGetValue(number, kCFNumberIntType, &int_value)) 33 return int_value; 34 else 35 return default_value; 36} 37 38} // namespace 39 40namespace net { 41 42int ProxyConfigServiceMac::GetProxyConfig(ProxyConfig* config) { 43 scoped_cftyperef<CFDictionaryRef> config_dict( 44 SCDynamicStoreCopyProxies(NULL)); 45 DCHECK(config_dict); 46 47 // auto-detect 48 49 // There appears to be no UI for this configuration option, and we're not sure 50 // if Apple's proxy code even takes it into account. But the constant is in 51 // the header file so we'll use it. 52 config->auto_detect = 53 GetBoolFromDictionary(config_dict.get(), 54 kSCPropNetProxiesProxyAutoDiscoveryEnable, 55 false); 56 57 // PAC file 58 59 if (GetBoolFromDictionary(config_dict.get(), 60 kSCPropNetProxiesProxyAutoConfigEnable, 61 false)) { 62 CFStringRef pac_url_ref = (CFStringRef)mac_util::GetValueFromDictionary( 63 config_dict.get(), 64 kSCPropNetProxiesProxyAutoConfigURLString, 65 CFStringGetTypeID()); 66 if (pac_url_ref) 67 config->pac_url = GURL(base::SysCFStringRefToUTF8(pac_url_ref)); 68 } 69 70 // proxies (for now ftp, http, https, and SOCKS) 71 72 if (GetBoolFromDictionary(config_dict.get(), 73 kSCPropNetProxiesFTPEnable, 74 false)) { 75 ProxyServer proxy_server = 76 ProxyServer::FromDictionary(ProxyServer::SCHEME_HTTP, 77 config_dict.get(), 78 kSCPropNetProxiesFTPProxy, 79 kSCPropNetProxiesFTPPort); 80 if (proxy_server.is_valid()) { 81 config->proxy_rules.type = ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; 82 config->proxy_rules.proxy_for_ftp = proxy_server; 83 } 84 } 85 if (GetBoolFromDictionary(config_dict.get(), 86 kSCPropNetProxiesHTTPEnable, 87 false)) { 88 ProxyServer proxy_server = 89 ProxyServer::FromDictionary(ProxyServer::SCHEME_HTTP, 90 config_dict.get(), 91 kSCPropNetProxiesHTTPProxy, 92 kSCPropNetProxiesHTTPPort); 93 if (proxy_server.is_valid()) { 94 config->proxy_rules.type = ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; 95 config->proxy_rules.proxy_for_http = proxy_server; 96 } 97 } 98 if (GetBoolFromDictionary(config_dict.get(), 99 kSCPropNetProxiesHTTPSEnable, 100 false)) { 101 ProxyServer proxy_server = 102 ProxyServer::FromDictionary(ProxyServer::SCHEME_HTTP, 103 config_dict.get(), 104 kSCPropNetProxiesHTTPSProxy, 105 kSCPropNetProxiesHTTPSPort); 106 if (proxy_server.is_valid()) { 107 config->proxy_rules.type = ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; 108 config->proxy_rules.proxy_for_https = proxy_server; 109 } 110 } 111 if (GetBoolFromDictionary(config_dict.get(), 112 kSCPropNetProxiesSOCKSEnable, 113 false)) { 114 ProxyServer proxy_server = 115 ProxyServer::FromDictionary(ProxyServer::SCHEME_SOCKS5, 116 config_dict.get(), 117 kSCPropNetProxiesSOCKSProxy, 118 kSCPropNetProxiesSOCKSPort); 119 if (proxy_server.is_valid()) { 120 config->proxy_rules.type = ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; 121 config->proxy_rules.socks_proxy = proxy_server; 122 } 123 } 124 125 // proxy bypass list 126 127 CFArrayRef bypass_array_ref = 128 (CFArrayRef)mac_util::GetValueFromDictionary( 129 config_dict.get(), 130 kSCPropNetProxiesExceptionsList, 131 CFArrayGetTypeID()); 132 if (bypass_array_ref) { 133 CFIndex bypass_array_count = CFArrayGetCount(bypass_array_ref); 134 for (CFIndex i = 0; i < bypass_array_count; ++i) { 135 CFStringRef bypass_item_ref = 136 (CFStringRef)CFArrayGetValueAtIndex(bypass_array_ref, i); 137 if (CFGetTypeID(bypass_item_ref) != CFStringGetTypeID()) { 138 LOG(WARNING) << "Expected value for item " << i 139 << " in the kSCPropNetProxiesExceptionsList" 140 " to be a CFStringRef but it was not"; 141 142 } else { 143 config->proxy_bypass.push_back( 144 base::SysCFStringRefToUTF8(bypass_item_ref)); 145 } 146 } 147 } 148 149 // proxy bypass boolean 150 151 config->proxy_bypass_local_names = 152 GetBoolFromDictionary(config_dict.get(), 153 kSCPropNetProxiesExcludeSimpleHostnames, 154 false); 155 156 return OK; 157} 158 159} // namespace net 160