blob: aece777dbb84efae3ebe2e7a59812fa8d0f5f45e [file] [log] [blame]
[email protected]c8ead2762013-07-23 15:57:251// Copyright 2013 The Chromium Authors. All rights reserved.
[email protected]4200a2082010-04-27 23:19:472// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]c8ead2762013-07-23 15:57:255#include "chrome/browser/net/firefox_proxy_settings.h"
[email protected]4200a2082010-04-27 23:19:476
[email protected]c8ead2762013-07-23 15:57:257#include "base/file_util.h"
[email protected]57999812013-02-24 05:40:528#include "base/files/file_path.h"
[email protected]c8ead2762013-07-23 15:57:259#include "base/strings/string_number_conversions.h"
[email protected]f4ebe772013-02-02 00:21:3910#include "base/strings/string_tokenizer.h"
[email protected]9c7ddc92013-06-11 01:40:5711#include "base/strings/string_util.h"
[email protected]4200a2082010-04-27 23:19:4712#include "base/values.h"
[email protected]946b4ee02013-07-16 21:57:5213#include "chrome/common/importer/firefox_importer_utils.h"
[email protected]483bf122010-05-04 20:41:2414#include "net/proxy/proxy_config.h"
[email protected]4200a2082010-04-27 23:19:4715
16namespace {
17
[email protected]a65175d2010-08-17 04:00:5718const char* const kNetworkProxyTypeKey = "network.proxy.type";
[email protected]4200a2082010-04-27 23:19:4719const char* const kHTTPProxyKey = "network.proxy.http";
[email protected]a65175d2010-08-17 04:00:5720const char* const kHTTPProxyPortKey = "network.proxy.http_port";
[email protected]4200a2082010-04-27 23:19:4721const char* const kSSLProxyKey = "network.proxy.ssl";
[email protected]a65175d2010-08-17 04:00:5722const char* const kSSLProxyPortKey = "network.proxy.ssl_port";
[email protected]4200a2082010-04-27 23:19:4723const char* const kFTPProxyKey = "network.proxy.ftp";
[email protected]a65175d2010-08-17 04:00:5724const char* const kFTPProxyPortKey = "network.proxy.ftp_port";
[email protected]4200a2082010-04-27 23:19:4725const char* const kGopherProxyKey = "network.proxy.gopher";
[email protected]a65175d2010-08-17 04:00:5726const char* const kGopherProxyPortKey = "network.proxy.gopher_port";
[email protected]4200a2082010-04-27 23:19:4727const char* const kSOCKSHostKey = "network.proxy.socks";
[email protected]a65175d2010-08-17 04:00:5728const char* const kSOCKSHostPortKey = "network.proxy.socks_port";
29const char* const kSOCKSVersionKey = "network.proxy.socks_version";
[email protected]4200a2082010-04-27 23:19:4730const char* const kAutoconfigURL = "network.proxy.autoconfig_url";
31const char* const kNoProxyListKey = "network.proxy.no_proxies_on";
32const char* const kPrefFileName = "prefs.js";
33
34FirefoxProxySettings::ProxyConfig IntToProxyConfig(int type) {
35 switch (type) {
36 case 1:
37 return FirefoxProxySettings::MANUAL;
38 case 2:
39 return FirefoxProxySettings::AUTO_FROM_URL;
40 case 4:
41 return FirefoxProxySettings::AUTO_DETECT;
42 case 5:
43 return FirefoxProxySettings::SYSTEM;
44 default:
45 LOG(ERROR) << "Unknown Firefox proxy config type: " << type;
46 return FirefoxProxySettings::NO_PROXY;
47 }
48}
49
50FirefoxProxySettings::SOCKSVersion IntToSOCKSVersion(int type) {
51 switch (type) {
52 case 4:
53 return FirefoxProxySettings::V4;
54 case 5:
55 return FirefoxProxySettings::V5;
56 default:
57 LOG(ERROR) << "Unknown Firefox proxy config type: " << type;
58 return FirefoxProxySettings::UNKNONW;
59 }
60}
61
[email protected]c8ead2762013-07-23 15:57:2562// Parses the prefs found in the file |pref_file| and puts the key/value pairs
63// in |prefs|. Keys are strings, and values can be strings, booleans or
64// integers. Returns true if it succeeded, false otherwise (in which case
65// |prefs| is not filled).
66// Note: for strings, only valid UTF-8 string values are supported. If a
67// key/pair is not valid UTF-8, it is ignored and will not appear in |prefs|.
68bool ParsePrefFile(const base::FilePath& pref_file, DictionaryValue* prefs) {
69 // The string that is before a pref key.
70 const std::string kUserPrefString = "user_pref(\"";
71 std::string contents;
72 if (!file_util::ReadFileToString(pref_file, &contents))
73 return false;
74
75 std::vector<std::string> lines;
76 Tokenize(contents, "\n", &lines);
77
78 for (std::vector<std::string>::const_iterator iter = lines.begin();
79 iter != lines.end(); ++iter) {
80 const std::string& line = *iter;
81 size_t start_key = line.find(kUserPrefString);
82 if (start_key == std::string::npos)
83 continue; // Could be a comment or a blank line.
84 start_key += kUserPrefString.length();
85 size_t stop_key = line.find('"', start_key);
86 if (stop_key == std::string::npos) {
87 LOG(ERROR) << "Invalid key found in Firefox pref file '" <<
88 pref_file.value() << "' line is '" << line << "'.";
89 continue;
90 }
91 std::string key = line.substr(start_key, stop_key - start_key);
92 size_t start_value = line.find(',', stop_key + 1);
93 if (start_value == std::string::npos) {
94 LOG(ERROR) << "Invalid value found in Firefox pref file '" <<
95 pref_file.value() << "' line is '" << line << "'.";
96 continue;
97 }
98 size_t stop_value = line.find(");", start_value + 1);
99 if (stop_value == std::string::npos) {
100 LOG(ERROR) << "Invalid value found in Firefox pref file '" <<
101 pref_file.value() << "' line is '" << line << "'.";
102 continue;
103 }
104 std::string value = line.substr(start_value + 1,
105 stop_value - start_value - 1);
106 TrimWhitespace(value, TRIM_ALL, &value);
107 // Value could be a boolean.
108 bool is_value_true = LowerCaseEqualsASCII(value, "true");
109 if (is_value_true || LowerCaseEqualsASCII(value, "false")) {
110 prefs->SetBoolean(key, is_value_true);
111 continue;
112 }
113
114 // Value could be a string.
115 if (value.size() >= 2U &&
116 value[0] == '"' && value[value.size() - 1] == '"') {
117 value = value.substr(1, value.size() - 2);
118 // ValueString only accept valid UTF-8. Simply ignore that entry if it is
119 // not UTF-8.
120 if (IsStringUTF8(value))
121 prefs->SetString(key, value);
122 else
123 VLOG(1) << "Non UTF8 value for key " << key << ", ignored.";
124 continue;
125 }
126
127 // Or value could be an integer.
128 int int_value = 0;
129 if (base::StringToInt(value, &int_value)) {
130 prefs->SetInteger(key, int_value);
131 continue;
132 }
133
134 LOG(ERROR) << "Invalid value found in Firefox pref file '"
135 << pref_file.value() << "' value is '" << value << "'.";
136 }
137 return true;
138}
139
[email protected]4200a2082010-04-27 23:19:47140} // namespace
141
142FirefoxProxySettings::FirefoxProxySettings() {
143 Reset();
144}
145
146FirefoxProxySettings::~FirefoxProxySettings() {
147}
148
149void FirefoxProxySettings::Reset() {
150 config_type_ = NO_PROXY;
151 http_proxy_.clear();
152 http_proxy_port_ = 0;
153 ssl_proxy_.clear();
154 ssl_proxy_port_ = 0;
155 ftp_proxy_.clear();
156 ftp_proxy_port_ = 0;
157 gopher_proxy_.clear();
158 gopher_proxy_port_ = 0;
159 socks_host_.clear();
160 socks_port_ = 0;
161 socks_version_ = UNKNONW;
162 proxy_bypass_list_.clear();
163 autoconfig_url_.clear();
164}
165
166// static
[email protected]483bf122010-05-04 20:41:24167bool FirefoxProxySettings::GetSettings(FirefoxProxySettings* settings) {
[email protected]4200a2082010-04-27 23:19:47168 DCHECK(settings);
169 settings->Reset();
170
[email protected]650b2d52013-02-10 03:41:45171 base::FilePath profile_path = GetFirefoxProfilePath();
[email protected]4200a2082010-04-27 23:19:47172 if (profile_path.empty())
173 return false;
[email protected]650b2d52013-02-10 03:41:45174 base::FilePath pref_file = profile_path.AppendASCII(kPrefFileName);
[email protected]4200a2082010-04-27 23:19:47175 return GetSettingsFromFile(pref_file, settings);
176}
177
[email protected]483bf122010-05-04 20:41:24178bool FirefoxProxySettings::ToProxyConfig(net::ProxyConfig* config) {
179 switch (config_type()) {
180 case NO_PROXY:
181 *config = net::ProxyConfig::CreateDirect();
182 return true;
183 case AUTO_DETECT:
184 *config = net::ProxyConfig::CreateAutoDetect();
185 return true;
186 case AUTO_FROM_URL:
187 *config = net::ProxyConfig::CreateFromCustomPacURL(
188 GURL(autoconfig_url()));
189 return true;
190 case SYSTEM:
191 // Can't convert this directly to a ProxyConfig.
192 return false;
193 case MANUAL:
194 // Handled outside of the switch (since it is a lot of code.)
195 break;
196 default:
197 NOTREACHED();
198 return false;
199 }
200
201 // The rest of this funciton is for handling the MANUAL case.
202 DCHECK_EQ(MANUAL, config_type());
203
204 *config = net::ProxyConfig();
205 config->proxy_rules().type =
206 net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME;
207
208 if (!http_proxy().empty()) {
[email protected]2189e092013-03-16 18:02:02209 config->proxy_rules().proxies_for_http.SetSingleProxyServer(
210 net::ProxyServer(
211 net::ProxyServer::SCHEME_HTTP,
212 net::HostPortPair(http_proxy(), http_proxy_port())));
[email protected]483bf122010-05-04 20:41:24213 }
214
215 if (!ftp_proxy().empty()) {
[email protected]2189e092013-03-16 18:02:02216 config->proxy_rules().proxies_for_ftp.SetSingleProxyServer(
217 net::ProxyServer(
218 net::ProxyServer::SCHEME_HTTP,
219 net::HostPortPair(ftp_proxy(), ftp_proxy_port())));
[email protected]483bf122010-05-04 20:41:24220 }
221
222 if (!ssl_proxy().empty()) {
[email protected]2189e092013-03-16 18:02:02223 config->proxy_rules().proxies_for_https.SetSingleProxyServer(
224 net::ProxyServer(
225 net::ProxyServer::SCHEME_HTTP,
226 net::HostPortPair(ssl_proxy(), ssl_proxy_port())));
[email protected]483bf122010-05-04 20:41:24227 }
228
229 if (!socks_host().empty()) {
230 net::ProxyServer::Scheme proxy_scheme = V5 == socks_version() ?
231 net::ProxyServer::SCHEME_SOCKS5 : net::ProxyServer::SCHEME_SOCKS4;
232
[email protected]2189e092013-03-16 18:02:02233 config->proxy_rules().fallback_proxies.SetSingleProxyServer(
234 net::ProxyServer(
235 proxy_scheme,
236 net::HostPortPair(socks_host(), socks_port())));
[email protected]483bf122010-05-04 20:41:24237 }
238
239 config->proxy_rules().bypass_rules.ParseFromStringUsingSuffixMatching(
240 JoinString(proxy_bypass_list_, ';'));
241
242 return true;
243}
244
[email protected]4200a2082010-04-27 23:19:47245// static
[email protected]650b2d52013-02-10 03:41:45246bool FirefoxProxySettings::GetSettingsFromFile(const base::FilePath& pref_file,
[email protected]4200a2082010-04-27 23:19:47247 FirefoxProxySettings* settings) {
248 DictionaryValue dictionary;
249 if (!ParsePrefFile(pref_file, &dictionary))
250 return false;
251
252 int proxy_type = 0;
253 if (!dictionary.GetInteger(kNetworkProxyTypeKey, &proxy_type))
254 return true; // No type means no proxy.
255
256 settings->config_type_ = IntToProxyConfig(proxy_type);
257 if (settings->config_type_ == AUTO_FROM_URL) {
258 if (!dictionary.GetStringASCII(kAutoconfigURL,
259 &(settings->autoconfig_url_))) {
260 LOG(ERROR) << "Failed to retrieve Firefox proxy autoconfig URL";
261 }
[email protected]acd87532010-05-13 22:28:10262 return true;
[email protected]4200a2082010-04-27 23:19:47263 }
264
265 if (settings->config_type_ == MANUAL) {
266 if (!dictionary.GetStringASCII(kHTTPProxyKey, &(settings->http_proxy_)))
267 LOG(ERROR) << "Failed to retrieve Firefox proxy HTTP host";
268 if (!dictionary.GetInteger(kHTTPProxyPortKey,
269 &(settings->http_proxy_port_))) {
270 LOG(ERROR) << "Failed to retrieve Firefox proxy HTTP port";
271 }
272 if (!dictionary.GetStringASCII(kSSLProxyKey, &(settings->ssl_proxy_)))
273 LOG(ERROR) << "Failed to retrieve Firefox proxy SSL host";
274 if (!dictionary.GetInteger(kSSLProxyPortKey, &(settings->ssl_proxy_port_)))
275 LOG(ERROR) << "Failed to retrieve Firefox proxy SSL port";
276 if (!dictionary.GetStringASCII(kFTPProxyKey, &(settings->ftp_proxy_)))
277 LOG(ERROR) << "Failed to retrieve Firefox proxy FTP host";
278 if (!dictionary.GetInteger(kFTPProxyPortKey, &(settings->ftp_proxy_port_)))
279 LOG(ERROR) << "Failed to retrieve Firefox proxy SSL port";
280 if (!dictionary.GetStringASCII(kGopherProxyKey, &(settings->gopher_proxy_)))
281 LOG(ERROR) << "Failed to retrieve Firefox proxy gopher host";
282 if (!dictionary.GetInteger(kGopherProxyPortKey,
283 &(settings->gopher_proxy_port_))) {
284 LOG(ERROR) << "Failed to retrieve Firefox proxy gopher port";
285 }
286 if (!dictionary.GetStringASCII(kSOCKSHostKey, &(settings->socks_host_)))
287 LOG(ERROR) << "Failed to retrieve Firefox SOCKS host";
288 if (!dictionary.GetInteger(kSOCKSHostPortKey, &(settings->socks_port_)))
289 LOG(ERROR) << "Failed to retrieve Firefox SOCKS port";
290 int socks_version;
291 if (dictionary.GetInteger(kSOCKSVersionKey, &socks_version))
292 settings->socks_version_ = IntToSOCKSVersion(socks_version);
293
294 std::string proxy_bypass;
295 if (dictionary.GetStringASCII(kNoProxyListKey, &proxy_bypass) &&
296 !proxy_bypass.empty()) {
[email protected]f4ebe772013-02-02 00:21:39297 base::StringTokenizer string_tok(proxy_bypass, ",");
[email protected]4200a2082010-04-27 23:19:47298 while (string_tok.GetNext()) {
299 std::string token = string_tok.token();
300 TrimWhitespaceASCII(token, TRIM_ALL, &token);
301 if (!token.empty())
302 settings->proxy_bypass_list_.push_back(token);
303 }
304 }
305 }
306 return true;
307}