普通文本  |  170行  |  5.34 KB

// 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