Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / net / firefox_proxy_settings.cc
1 // Copyright 2013 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 "chrome/browser/net/firefox_proxy_settings.h"
6
7 #include "base/file_util.h"
8 #include "base/files/file_path.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_tokenizer.h"
11 #include "base/strings/string_util.h"
12 #include "base/values.h"
13 #include "chrome/common/importer/firefox_importer_utils.h"
14 #include "net/proxy/proxy_config.h"
15
16 namespace {
17
18 const char* const kNetworkProxyTypeKey = "network.proxy.type";
19 const char* const kHTTPProxyKey = "network.proxy.http";
20 const char* const kHTTPProxyPortKey = "network.proxy.http_port";
21 const char* const kSSLProxyKey = "network.proxy.ssl";
22 const char* const kSSLProxyPortKey = "network.proxy.ssl_port";
23 const char* const kFTPProxyKey = "network.proxy.ftp";
24 const char* const kFTPProxyPortKey = "network.proxy.ftp_port";
25 const char* const kGopherProxyKey = "network.proxy.gopher";
26 const char* const kGopherProxyPortKey = "network.proxy.gopher_port";
27 const char* const kSOCKSHostKey = "network.proxy.socks";
28 const char* const kSOCKSHostPortKey = "network.proxy.socks_port";
29 const char* const kSOCKSVersionKey = "network.proxy.socks_version";
30 const char* const kAutoconfigURL = "network.proxy.autoconfig_url";
31 const char* const kNoProxyListKey = "network.proxy.no_proxies_on";
32 const char* const kPrefFileName = "prefs.js";
33
34 FirefoxProxySettings::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
50 FirefoxProxySettings::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
62 // 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|.
68 bool ParsePrefFile(const base::FilePath& pref_file,
69                    base::DictionaryValue* prefs) {
70   // The string that is before a pref key.
71   const std::string kUserPrefString = "user_pref(\"";
72   std::string contents;
73   if (!base::ReadFileToString(pref_file, &contents))
74     return false;
75
76   std::vector<std::string> lines;
77   Tokenize(contents, "\n", &lines);
78
79   for (std::vector<std::string>::const_iterator iter = lines.begin();
80        iter != lines.end(); ++iter) {
81     const std::string& line = *iter;
82     size_t start_key = line.find(kUserPrefString);
83     if (start_key == std::string::npos)
84       continue;  // Could be a comment or a blank line.
85     start_key += kUserPrefString.length();
86     size_t stop_key = line.find('"', start_key);
87     if (stop_key == std::string::npos) {
88       LOG(ERROR) << "Invalid key found in Firefox pref file '" <<
89           pref_file.value() << "' line is '" << line << "'.";
90       continue;
91     }
92     std::string key = line.substr(start_key, stop_key - start_key);
93     size_t start_value = line.find(',', stop_key + 1);
94     if (start_value == std::string::npos) {
95       LOG(ERROR) << "Invalid value found in Firefox pref file '" <<
96           pref_file.value() << "' line is '" << line << "'.";
97       continue;
98     }
99     size_t stop_value = line.find(");", start_value + 1);
100     if (stop_value == std::string::npos) {
101       LOG(ERROR) << "Invalid value found in Firefox pref file '" <<
102           pref_file.value() << "' line is '" << line << "'.";
103       continue;
104     }
105     std::string value = line.substr(start_value + 1,
106                                     stop_value - start_value - 1);
107     base::TrimWhitespace(value, base::TRIM_ALL, &value);
108     // Value could be a boolean.
109     bool is_value_true = LowerCaseEqualsASCII(value, "true");
110     if (is_value_true || LowerCaseEqualsASCII(value, "false")) {
111       prefs->SetBoolean(key, is_value_true);
112       continue;
113     }
114
115     // Value could be a string.
116     if (value.size() >= 2U &&
117         value[0] == '"' && value[value.size() - 1] == '"') {
118       value = value.substr(1, value.size() - 2);
119       // ValueString only accept valid UTF-8.  Simply ignore that entry if it is
120       // not UTF-8.
121       if (base::IsStringUTF8(value))
122         prefs->SetString(key, value);
123       else
124         VLOG(1) << "Non UTF8 value for key " << key << ", ignored.";
125       continue;
126     }
127
128     // Or value could be an integer.
129     int int_value = 0;
130     if (base::StringToInt(value, &int_value)) {
131       prefs->SetInteger(key, int_value);
132       continue;
133     }
134
135     LOG(ERROR) << "Invalid value found in Firefox pref file '"
136                << pref_file.value() << "' value is '" << value << "'.";
137   }
138   return true;
139 }
140
141 }  // namespace
142
143 FirefoxProxySettings::FirefoxProxySettings() {
144   Reset();
145 }
146
147 FirefoxProxySettings::~FirefoxProxySettings() {
148 }
149
150 void FirefoxProxySettings::Reset() {
151   config_type_ = NO_PROXY;
152   http_proxy_.clear();
153   http_proxy_port_ = 0;
154   ssl_proxy_.clear();
155   ssl_proxy_port_ = 0;
156   ftp_proxy_.clear();
157   ftp_proxy_port_ = 0;
158   gopher_proxy_.clear();
159   gopher_proxy_port_ = 0;
160   socks_host_.clear();
161   socks_port_ = 0;
162   socks_version_ = UNKNONW;
163   proxy_bypass_list_.clear();
164   autoconfig_url_.clear();
165 }
166
167 // static
168 bool FirefoxProxySettings::GetSettings(FirefoxProxySettings* settings) {
169   DCHECK(settings);
170   settings->Reset();
171
172   base::FilePath profile_path = GetFirefoxProfilePath();
173   if (profile_path.empty())
174     return false;
175   base::FilePath pref_file = profile_path.AppendASCII(kPrefFileName);
176   return GetSettingsFromFile(pref_file, settings);
177 }
178
179 bool FirefoxProxySettings::ToProxyConfig(net::ProxyConfig* config) {
180   switch (config_type()) {
181     case NO_PROXY:
182       *config = net::ProxyConfig::CreateDirect();
183       return true;
184     case AUTO_DETECT:
185       *config = net::ProxyConfig::CreateAutoDetect();
186       return true;
187     case AUTO_FROM_URL:
188       *config = net::ProxyConfig::CreateFromCustomPacURL(
189           GURL(autoconfig_url()));
190       return true;
191     case SYSTEM:
192       // Can't convert this directly to a ProxyConfig.
193       return false;
194     case MANUAL:
195       // Handled outside of the switch (since it is a lot of code.)
196       break;
197     default:
198       NOTREACHED();
199       return false;
200   }
201
202   // The rest of this funciton is for handling the MANUAL case.
203   DCHECK_EQ(MANUAL, config_type());
204
205   *config = net::ProxyConfig();
206   config->proxy_rules().type =
207       net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME;
208
209   if (!http_proxy().empty()) {
210     config->proxy_rules().proxies_for_http.SetSingleProxyServer(
211         net::ProxyServer(
212             net::ProxyServer::SCHEME_HTTP,
213             net::HostPortPair(http_proxy(), http_proxy_port())));
214   }
215
216   if (!ftp_proxy().empty()) {
217     config->proxy_rules().proxies_for_ftp.SetSingleProxyServer(
218         net::ProxyServer(
219             net::ProxyServer::SCHEME_HTTP,
220             net::HostPortPair(ftp_proxy(), ftp_proxy_port())));
221   }
222
223   if (!ssl_proxy().empty()) {
224     config->proxy_rules().proxies_for_https.SetSingleProxyServer(
225         net::ProxyServer(
226             net::ProxyServer::SCHEME_HTTP,
227             net::HostPortPair(ssl_proxy(), ssl_proxy_port())));
228   }
229
230   if (!socks_host().empty()) {
231     net::ProxyServer::Scheme proxy_scheme = V5 == socks_version() ?
232         net::ProxyServer::SCHEME_SOCKS5 : net::ProxyServer::SCHEME_SOCKS4;
233
234     config->proxy_rules().fallback_proxies.SetSingleProxyServer(
235         net::ProxyServer(
236             proxy_scheme,
237             net::HostPortPair(socks_host(), socks_port())));
238   }
239
240   config->proxy_rules().bypass_rules.ParseFromStringUsingSuffixMatching(
241       JoinString(proxy_bypass_list_, ';'));
242
243   return true;
244 }
245
246 // static
247 bool FirefoxProxySettings::GetSettingsFromFile(const base::FilePath& pref_file,
248                                                FirefoxProxySettings* settings) {
249   base::DictionaryValue dictionary;
250   if (!ParsePrefFile(pref_file, &dictionary))
251     return false;
252
253   int proxy_type = 0;
254   if (!dictionary.GetInteger(kNetworkProxyTypeKey, &proxy_type))
255     return true;  // No type means no proxy.
256
257   settings->config_type_ = IntToProxyConfig(proxy_type);
258   if (settings->config_type_ == AUTO_FROM_URL) {
259     if (!dictionary.GetStringASCII(kAutoconfigURL,
260                                    &(settings->autoconfig_url_))) {
261       LOG(ERROR) << "Failed to retrieve Firefox proxy autoconfig URL";
262     }
263     return true;
264   }
265
266   if (settings->config_type_ == MANUAL) {
267     if (!dictionary.GetStringASCII(kHTTPProxyKey, &(settings->http_proxy_)))
268       LOG(ERROR) << "Failed to retrieve Firefox proxy HTTP host";
269     if (!dictionary.GetInteger(kHTTPProxyPortKey,
270                                &(settings->http_proxy_port_))) {
271       LOG(ERROR) << "Failed to retrieve Firefox proxy HTTP port";
272     }
273     if (!dictionary.GetStringASCII(kSSLProxyKey, &(settings->ssl_proxy_)))
274       LOG(ERROR) << "Failed to retrieve Firefox proxy SSL host";
275     if (!dictionary.GetInteger(kSSLProxyPortKey, &(settings->ssl_proxy_port_)))
276       LOG(ERROR) << "Failed to retrieve Firefox proxy SSL port";
277     if (!dictionary.GetStringASCII(kFTPProxyKey, &(settings->ftp_proxy_)))
278       LOG(ERROR) << "Failed to retrieve Firefox proxy FTP host";
279     if (!dictionary.GetInteger(kFTPProxyPortKey, &(settings->ftp_proxy_port_)))
280       LOG(ERROR) << "Failed to retrieve Firefox proxy SSL port";
281     if (!dictionary.GetStringASCII(kGopherProxyKey, &(settings->gopher_proxy_)))
282       LOG(ERROR) << "Failed to retrieve Firefox proxy gopher host";
283     if (!dictionary.GetInteger(kGopherProxyPortKey,
284                                &(settings->gopher_proxy_port_))) {
285       LOG(ERROR) << "Failed to retrieve Firefox proxy gopher port";
286     }
287     if (!dictionary.GetStringASCII(kSOCKSHostKey, &(settings->socks_host_)))
288       LOG(ERROR) << "Failed to retrieve Firefox SOCKS host";
289     if (!dictionary.GetInteger(kSOCKSHostPortKey, &(settings->socks_port_)))
290       LOG(ERROR) << "Failed to retrieve Firefox SOCKS port";
291     int socks_version;
292     if (dictionary.GetInteger(kSOCKSVersionKey, &socks_version))
293       settings->socks_version_ = IntToSOCKSVersion(socks_version);
294
295     std::string proxy_bypass;
296     if (dictionary.GetStringASCII(kNoProxyListKey, &proxy_bypass) &&
297         !proxy_bypass.empty()) {
298       base::StringTokenizer string_tok(proxy_bypass, ",");
299       while (string_tok.GetNext()) {
300         std::string token = string_tok.token();
301         base::TrimWhitespaceASCII(token, base::TRIM_ALL, &token);
302         if (!token.empty())
303           settings->proxy_bypass_list_.push_back(token);
304       }
305     }
306   }
307   return true;
308 }