// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/ui_proxy_config.h"
#include "base/logging.h"
#include "base/values.h"
#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
#include "chrome/browser/prefs/proxy_config_dictionary.h"
#include "net/proxy/proxy_config.h"
namespace chromeos {
UIProxyConfig::UIProxyConfig()
: mode(MODE_DIRECT),
state(ProxyPrefs::CONFIG_UNSET),
user_modifiable(true) {
}
UIProxyConfig::~UIProxyConfig() {
}
void UIProxyConfig::SetPacUrl(const GURL& pac_url) {
mode = UIProxyConfig::MODE_PAC_SCRIPT;
automatic_proxy.pac_url = pac_url;
}
void UIProxyConfig::SetSingleProxy(const net::ProxyServer& server) {
mode = UIProxyConfig::MODE_SINGLE_PROXY;
single_proxy.server = server;
}
void UIProxyConfig::SetProxyForScheme(const std::string& scheme,
const net::ProxyServer& server) {
ManualProxy* proxy = MapSchemeToProxy(scheme);
if (!proxy) {
NOTREACHED() << "Cannot set proxy: invalid scheme [" << scheme << "]";
return;
}
mode = UIProxyConfig::MODE_PROXY_PER_SCHEME;
proxy->server = server;
}
void UIProxyConfig::SetBypassRules(const net::ProxyBypassRules& rules) {
if (mode != UIProxyConfig::MODE_SINGLE_PROXY &&
mode != UIProxyConfig::MODE_PROXY_PER_SCHEME) {
NOTREACHED() << "Cannot set bypass rules for proxy mode [" << mode << "]";
return;
}
bypass_rules = rules;
}
bool UIProxyConfig::FromNetProxyConfig(const net::ProxyConfig& net_config) {
*this = UIProxyConfig(); // Reset to default.
const net::ProxyConfig::ProxyRules& rules = net_config.proxy_rules();
switch (rules.type) {
case net::ProxyConfig::ProxyRules::TYPE_NO_RULES:
if (!net_config.HasAutomaticSettings()) {
mode = UIProxyConfig::MODE_DIRECT;
} else if (net_config.auto_detect()) {
mode = UIProxyConfig::MODE_AUTO_DETECT;
} else if (net_config.has_pac_url()) {
mode = UIProxyConfig::MODE_PAC_SCRIPT;
automatic_proxy.pac_url = net_config.pac_url();
} else {
return false;
}
return true;
case net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY:
if (rules.single_proxies.IsEmpty())
return false;
mode = MODE_SINGLE_PROXY;
single_proxy.server = rules.single_proxies.Get();
bypass_rules = rules.bypass_rules;
return true;
case net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME:
// Make sure we have valid server for at least one of the protocols.
if (rules.proxies_for_http.IsEmpty() &&
rules.proxies_for_https.IsEmpty() &&
rules.proxies_for_ftp.IsEmpty() &&
rules.fallback_proxies.IsEmpty()) {
return false;
}
mode = MODE_PROXY_PER_SCHEME;
if (!rules.proxies_for_http.IsEmpty())
http_proxy.server = rules.proxies_for_http.Get();
if (!rules.proxies_for_https.IsEmpty())
https_proxy.server = rules.proxies_for_https.Get();
if (!rules.proxies_for_ftp.IsEmpty())
ftp_proxy.server = rules.proxies_for_ftp.Get();
if (!rules.fallback_proxies.IsEmpty())
socks_proxy.server = rules.fallback_proxies.Get();
bypass_rules = rules.bypass_rules;
return true;
default:
NOTREACHED() << "Unrecognized proxy config mode";
break;
}
return false;
}
base::DictionaryValue* UIProxyConfig::ToPrefProxyConfig() const {
switch (mode) {
case MODE_DIRECT: {
return ProxyConfigDictionary::CreateDirect();
}
case MODE_AUTO_DETECT: {
return ProxyConfigDictionary::CreateAutoDetect();
}
case MODE_PAC_SCRIPT: {
return ProxyConfigDictionary::CreatePacScript(
automatic_proxy.pac_url.spec(), false);
}
case MODE_SINGLE_PROXY: {
std::string spec;
if (single_proxy.server.is_valid())
spec = single_proxy.server.ToURI();
return ProxyConfigDictionary::CreateFixedServers(
spec, bypass_rules.ToString());
}
case MODE_PROXY_PER_SCHEME: {
std::string spec;
EncodeAndAppendProxyServer("http", http_proxy.server, &spec);
EncodeAndAppendProxyServer("https", https_proxy.server, &spec);
EncodeAndAppendProxyServer("ftp", ftp_proxy.server, &spec);
EncodeAndAppendProxyServer("socks", socks_proxy.server, &spec);
return ProxyConfigDictionary::CreateFixedServers(
spec, bypass_rules.ToString());
}
default:
break;
}
NOTREACHED() << "Unrecognized proxy config mode for preference";
return NULL;
}
UIProxyConfig::ManualProxy* UIProxyConfig::MapSchemeToProxy(
const std::string& scheme) {
if (scheme == "http")
return &http_proxy;
if (scheme == "https")
return &https_proxy;
if (scheme == "ftp")
return &ftp_proxy;
if (scheme == "socks")
return &socks_proxy;
NOTREACHED() << "Invalid scheme: " << scheme;
return NULL;
}
// static
void UIProxyConfig::EncodeAndAppendProxyServer(const std::string& url_scheme,
const net::ProxyServer& server,
std::string* spec) {
if (!server.is_valid())
return;
if (!spec->empty())
*spec += ';';
if (!url_scheme.empty()) {
*spec += url_scheme;
*spec += "=";
}
*spec += server.ToURI();
}
} // namespace chromeos