1// Copyright (c) 2010 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/importer/firefox_proxy_settings.h"
6
7#include "base/file_path.h"
8#include "base/string_tokenizer.h"
9#include "base/string_util.h"
10#include "base/values.h"
11#include "chrome/browser/importer/firefox_importer_utils.h"
12#include "net/proxy/proxy_config.h"
13
14namespace {
15
16const char* const kNetworkProxyTypeKey = "network.proxy.type";
17const char* const kHTTPProxyKey = "network.proxy.http";
18const char* const kHTTPProxyPortKey = "network.proxy.http_port";
19const char* const kSSLProxyKey = "network.proxy.ssl";
20const char* const kSSLProxyPortKey = "network.proxy.ssl_port";
21const char* const kFTPProxyKey = "network.proxy.ftp";
22const char* const kFTPProxyPortKey = "network.proxy.ftp_port";
23const char* const kGopherProxyKey = "network.proxy.gopher";
24const char* const kGopherProxyPortKey = "network.proxy.gopher_port";
25const char* const kSOCKSHostKey = "network.proxy.socks";
26const char* const kSOCKSHostPortKey = "network.proxy.socks_port";
27const char* const kSOCKSVersionKey = "network.proxy.socks_version";
28const char* const kAutoconfigURL = "network.proxy.autoconfig_url";
29const char* const kNoProxyListKey = "network.proxy.no_proxies_on";
30const char* const kPrefFileName = "prefs.js";
31
32FirefoxProxySettings::ProxyConfig IntToProxyConfig(int type) {
33  switch (type) {
34    case 1:
35      return FirefoxProxySettings::MANUAL;
36    case 2:
37      return FirefoxProxySettings::AUTO_FROM_URL;
38    case 4:
39      return FirefoxProxySettings::AUTO_DETECT;
40    case 5:
41      return FirefoxProxySettings::SYSTEM;
42    default:
43      LOG(ERROR) << "Unknown Firefox proxy config type: " << type;
44      return FirefoxProxySettings::NO_PROXY;
45  }
46}
47
48FirefoxProxySettings::SOCKSVersion IntToSOCKSVersion(int type) {
49  switch (type) {
50    case 4:
51      return FirefoxProxySettings::V4;
52    case 5:
53      return FirefoxProxySettings::V5;
54    default:
55      LOG(ERROR) << "Unknown Firefox proxy config type: " << type;
56      return FirefoxProxySettings::UNKNONW;
57  }
58}
59
60}  // namespace
61
62FirefoxProxySettings::FirefoxProxySettings() {
63  Reset();
64}
65
66FirefoxProxySettings::~FirefoxProxySettings() {
67}
68
69void FirefoxProxySettings::Reset() {
70  config_type_ = NO_PROXY;
71  http_proxy_.clear();
72  http_proxy_port_ = 0;
73  ssl_proxy_.clear();
74  ssl_proxy_port_ = 0;
75  ftp_proxy_.clear();
76  ftp_proxy_port_ = 0;
77  gopher_proxy_.clear();
78  gopher_proxy_port_ = 0;
79  socks_host_.clear();
80  socks_port_ = 0;
81  socks_version_ = UNKNONW;
82  proxy_bypass_list_.clear();
83  autoconfig_url_.clear();
84}
85
86// static
87bool FirefoxProxySettings::GetSettings(FirefoxProxySettings* settings) {
88  DCHECK(settings);
89  settings->Reset();
90
91  FilePath profile_path = GetFirefoxProfilePath();
92  if (profile_path.empty())
93    return false;
94  FilePath pref_file = profile_path.AppendASCII(kPrefFileName);
95  return GetSettingsFromFile(pref_file, settings);
96}
97
98bool FirefoxProxySettings::ToProxyConfig(net::ProxyConfig* config) {
99  switch (config_type()) {
100    case NO_PROXY:
101      *config = net::ProxyConfig::CreateDirect();
102      return true;
103    case AUTO_DETECT:
104      *config = net::ProxyConfig::CreateAutoDetect();
105      return true;
106    case AUTO_FROM_URL:
107      *config = net::ProxyConfig::CreateFromCustomPacURL(
108          GURL(autoconfig_url()));
109      return true;
110    case SYSTEM:
111      // Can't convert this directly to a ProxyConfig.
112      return false;
113    case MANUAL:
114      // Handled outside of the switch (since it is a lot of code.)
115      break;
116    default:
117      NOTREACHED();
118      return false;
119  }
120
121  // The rest of this funciton is for handling the MANUAL case.
122  DCHECK_EQ(MANUAL, config_type());
123
124  *config = net::ProxyConfig();
125  config->proxy_rules().type =
126      net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME;
127
128  if (!http_proxy().empty()) {
129    config->proxy_rules().proxy_for_http = net::ProxyServer(
130        net::ProxyServer::SCHEME_HTTP,
131        net::HostPortPair(http_proxy(), http_proxy_port()));
132  }
133
134  if (!ftp_proxy().empty()) {
135    config->proxy_rules().proxy_for_ftp = net::ProxyServer(
136        net::ProxyServer::SCHEME_HTTP,
137        net::HostPortPair(ftp_proxy(), ftp_proxy_port()));
138  }
139
140  if (!ssl_proxy().empty()) {
141    config->proxy_rules().proxy_for_https = net::ProxyServer(
142        net::ProxyServer::SCHEME_HTTP,
143        net::HostPortPair(ssl_proxy(), ssl_proxy_port()));
144  }
145
146  if (!socks_host().empty()) {
147    net::ProxyServer::Scheme proxy_scheme = V5 == socks_version() ?
148        net::ProxyServer::SCHEME_SOCKS5 : net::ProxyServer::SCHEME_SOCKS4;
149
150    config->proxy_rules().fallback_proxy = net::ProxyServer(
151        proxy_scheme,
152        net::HostPortPair(socks_host(), socks_port()));
153  }
154
155  config->proxy_rules().bypass_rules.ParseFromStringUsingSuffixMatching(
156      JoinString(proxy_bypass_list_, ';'));
157
158  return true;
159}
160
161// static
162bool FirefoxProxySettings::GetSettingsFromFile(const FilePath& pref_file,
163                                               FirefoxProxySettings* settings) {
164  DictionaryValue dictionary;
165  if (!ParsePrefFile(pref_file, &dictionary))
166    return false;
167
168  int proxy_type = 0;
169  if (!dictionary.GetInteger(kNetworkProxyTypeKey, &proxy_type))
170    return true;  // No type means no proxy.
171
172  settings->config_type_ = IntToProxyConfig(proxy_type);
173  if (settings->config_type_ == AUTO_FROM_URL) {
174    if (!dictionary.GetStringASCII(kAutoconfigURL,
175                                   &(settings->autoconfig_url_))) {
176      LOG(ERROR) << "Failed to retrieve Firefox proxy autoconfig URL";
177    }
178    return true;
179  }
180
181  if (settings->config_type_ == MANUAL) {
182    if (!dictionary.GetStringASCII(kHTTPProxyKey, &(settings->http_proxy_)))
183      LOG(ERROR) << "Failed to retrieve Firefox proxy HTTP host";
184    if (!dictionary.GetInteger(kHTTPProxyPortKey,
185                               &(settings->http_proxy_port_))) {
186      LOG(ERROR) << "Failed to retrieve Firefox proxy HTTP port";
187    }
188    if (!dictionary.GetStringASCII(kSSLProxyKey, &(settings->ssl_proxy_)))
189      LOG(ERROR) << "Failed to retrieve Firefox proxy SSL host";
190    if (!dictionary.GetInteger(kSSLProxyPortKey, &(settings->ssl_proxy_port_)))
191      LOG(ERROR) << "Failed to retrieve Firefox proxy SSL port";
192    if (!dictionary.GetStringASCII(kFTPProxyKey, &(settings->ftp_proxy_)))
193      LOG(ERROR) << "Failed to retrieve Firefox proxy FTP host";
194    if (!dictionary.GetInteger(kFTPProxyPortKey, &(settings->ftp_proxy_port_)))
195      LOG(ERROR) << "Failed to retrieve Firefox proxy SSL port";
196    if (!dictionary.GetStringASCII(kGopherProxyKey, &(settings->gopher_proxy_)))
197      LOG(ERROR) << "Failed to retrieve Firefox proxy gopher host";
198    if (!dictionary.GetInteger(kGopherProxyPortKey,
199                               &(settings->gopher_proxy_port_))) {
200      LOG(ERROR) << "Failed to retrieve Firefox proxy gopher port";
201    }
202    if (!dictionary.GetStringASCII(kSOCKSHostKey, &(settings->socks_host_)))
203      LOG(ERROR) << "Failed to retrieve Firefox SOCKS host";
204    if (!dictionary.GetInteger(kSOCKSHostPortKey, &(settings->socks_port_)))
205      LOG(ERROR) << "Failed to retrieve Firefox SOCKS port";
206    int socks_version;
207    if (dictionary.GetInteger(kSOCKSVersionKey, &socks_version))
208      settings->socks_version_ = IntToSOCKSVersion(socks_version);
209
210    std::string proxy_bypass;
211    if (dictionary.GetStringASCII(kNoProxyListKey, &proxy_bypass) &&
212        !proxy_bypass.empty()) {
213      StringTokenizer string_tok(proxy_bypass, ",");
214      while (string_tok.GetNext()) {
215        std::string token = string_tok.token();
216        TrimWhitespaceASCII(token, TRIM_ALL, &token);
217        if (!token.empty())
218          settings->proxy_bypass_list_.push_back(token);
219      }
220    }
221  }
222  return true;
223}
224