13345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/proxy/proxy_config.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/logging.h"
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_tokenizer.h"
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h"
103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/values.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/proxy/proxy_info.h"
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net {
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricknamespace {
163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// If |proxy| is valid, sets it in |dict| under the key |name|.
183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid AddProxyToValue(const char* name,
193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                     const ProxyServer& proxy,
203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                     DictionaryValue* dict) {
213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (proxy.is_valid())
223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    dict->SetString(name, proxy.ToURI());
233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}  // namespace
263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
273345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickProxyConfig::ProxyRules::ProxyRules()
283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : reverse_bypass(false),
293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      type(TYPE_NO_RULES) {
303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
323345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickProxyConfig::ProxyRules::~ProxyRules() {
333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ProxyConfig::ProxyRules::Apply(const GURL& url, ProxyInfo* result) {
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (empty()) {
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    result->UseDirect();
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool bypass_proxy = bypass_rules.Matches(url);
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (reverse_bypass)
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bypass_proxy = !bypass_proxy;
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (bypass_proxy) {
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    result->UseDirect();
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (type) {
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case ProxyRules::TYPE_SINGLE_PROXY: {
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      result->UseProxyServer(single_proxy);
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case ProxyRules::TYPE_PROXY_PER_SCHEME: {
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const ProxyServer* entry = MapUrlSchemeToProxy(url.scheme());
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (entry) {
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        result->UseProxyServer(*entry);
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // We failed to find a matching proxy server for the current URL
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // scheme. Default to direct.
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        result->UseDirect();
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default: {
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      result->UseDirect();
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED();
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ProxyConfig::ProxyRules::ParseFromString(const std::string& proxy_rules) {
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Reset.
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  type = TYPE_NO_RULES;
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  single_proxy = ProxyServer();
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  proxy_for_http = ProxyServer();
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  proxy_for_https = ProxyServer();
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  proxy_for_ftp = ProxyServer();
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  fallback_proxy = ProxyServer();
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  StringTokenizer proxy_server_list(proxy_rules, ";");
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  while (proxy_server_list.GetNext()) {
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    StringTokenizer proxy_server_for_scheme(
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        proxy_server_list.token_begin(), proxy_server_list.token_end(), "=");
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    while (proxy_server_for_scheme.GetNext()) {
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      std::string url_scheme = proxy_server_for_scheme.token();
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // If we fail to get the proxy server here, it means that
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // this is a regular proxy server configuration, i.e. proxies
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // are not configured per protocol.
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (!proxy_server_for_scheme.GetNext()) {
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (type == TYPE_PROXY_PER_SCHEME)
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          continue;  // Unexpected.
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        single_proxy = ProxyServer::FromURI(url_scheme,
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                            ProxyServer::SCHEME_HTTP);
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        type = TYPE_SINGLE_PROXY;
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return;
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Trim whitespace off the url scheme.
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      TrimWhitespaceASCII(url_scheme, TRIM_ALL, &url_scheme);
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Add it to the per-scheme mappings (if supported scheme).
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      type = TYPE_PROXY_PER_SCHEME;
1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ProxyServer* entry = MapUrlSchemeToProxyNoFallback(url_scheme);
1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ProxyServer::Scheme default_scheme = ProxyServer::SCHEME_HTTP;
1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // socks=XXX is inconsistent with the other formats, since "socks"
1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // is not a URL scheme. Rather this means "for everything else, send
1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // it to the SOCKS proxy server XXX".
1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (url_scheme == "socks") {
1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        DCHECK(!entry);
1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        entry = &fallback_proxy;
1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        default_scheme = ProxyServer::SCHEME_SOCKS4;
1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (entry) {
1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        *entry = ProxyServer::FromURI(proxy_server_for_scheme.token(),
1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                      default_scheme);
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst ProxyServer* ProxyConfig::ProxyRules::MapUrlSchemeToProxy(
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const std::string& url_scheme) const {
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const ProxyServer* proxy_server =
1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const_cast<ProxyRules*>(this)->MapUrlSchemeToProxyNoFallback(url_scheme);
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (proxy_server && proxy_server->is_valid())
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return proxy_server;
1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (fallback_proxy.is_valid())
1343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return &fallback_proxy;
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return NULL;  // No mapping for this scheme. Use direct.
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
13872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool ProxyConfig::ProxyRules::Equals(const ProxyRules& other) const {
13972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return type == other.type &&
14072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen         single_proxy == other.single_proxy &&
14172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen         proxy_for_http == other.proxy_for_http &&
14272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen         proxy_for_https == other.proxy_for_https &&
14372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen         proxy_for_ftp == other.proxy_for_ftp &&
14472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen         fallback_proxy == other.fallback_proxy &&
14572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen         bypass_rules.Equals(other.bypass_rules) &&
14672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen         reverse_bypass == other.reverse_bypass;
14772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
14872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickProxyServer* ProxyConfig::ProxyRules::MapUrlSchemeToProxyNoFallback(
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const std::string& scheme) {
1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_EQ(TYPE_PROXY_PER_SCHEME, type);
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (scheme == "http")
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return &proxy_for_http;
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (scheme == "https")
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return &proxy_for_https;
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (scheme == "ftp")
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return &proxy_for_ftp;
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return NULL;  // No mapping for this scheme.
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochProxyConfig::ProxyConfig() : auto_detect_(false), id_(INVALID_ID) {
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1643345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickProxyConfig::ProxyConfig(const ProxyConfig& config)
1653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : auto_detect_(config.auto_detect_),
1663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      pac_url_(config.pac_url_),
1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      proxy_rules_(config.proxy_rules_),
1683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      id_(config.id_) {
1693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1713345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickProxyConfig::~ProxyConfig() {
1723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1743345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickProxyConfig& ProxyConfig::operator=(const ProxyConfig& config) {
1753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  auto_detect_ = config.auto_detect_;
1763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  pac_url_ = config.pac_url_;
1773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  proxy_rules_ = config.proxy_rules_;
1783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  id_ = config.id_;
1793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return *this;
1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ProxyConfig::Equals(const ProxyConfig& other) const {
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The two configs can have different IDs.  We are just interested in if they
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // have the same settings.
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return auto_detect_ == other.auto_detect_ &&
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         pac_url_ == other.pac_url_ &&
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         proxy_rules_.Equals(other.proxy_rules());
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool ProxyConfig::HasAutomaticSettings() const {
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return auto_detect_ || has_pac_url();
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid ProxyConfig::ClearAutomaticSettings() {
1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  auto_detect_ = false;
1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  pac_url_ = GURL();
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickValue* ProxyConfig::ToValue() const {
2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DictionaryValue* dict = new DictionaryValue();
2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Output the automatic settings.
2033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (auto_detect_)
2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    dict->SetBoolean("auto_detect", auto_detect_);
2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (has_pac_url())
2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    dict->SetString("pac_url", pac_url_.possibly_invalid_spec());
2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Output the manual settings.
2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (proxy_rules_.type != ProxyRules::TYPE_NO_RULES) {
2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    switch (proxy_rules_.type) {
2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      case ProxyRules::TYPE_SINGLE_PROXY:
2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        AddProxyToValue("single_proxy", proxy_rules_.single_proxy, dict);
2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        break;
2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      case ProxyRules::TYPE_PROXY_PER_SCHEME: {
2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        DictionaryValue* dict2 = new DictionaryValue();
2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        AddProxyToValue("http", proxy_rules_.proxy_for_http, dict2);
2173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        AddProxyToValue("https", proxy_rules_.proxy_for_https, dict2);
2183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        AddProxyToValue("ftp", proxy_rules_.proxy_for_ftp, dict2);
2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        AddProxyToValue("fallback", proxy_rules_.fallback_proxy, dict2);
2203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        dict->Set("proxy_per_scheme", dict2);
2213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        break;
2223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
2233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      default:
2243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        NOTREACHED();
2253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Output the bypass rules.
2283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const ProxyBypassRules& bypass = proxy_rules_.bypass_rules;
2293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (!bypass.rules().empty()) {
2303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (proxy_rules_.reverse_bypass)
2313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        dict->SetBoolean("reverse_bypass", true);
232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ListValue* list = new ListValue();
2343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      for (ProxyBypassRules::RuleList::const_iterator it =
2363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              bypass.rules().begin();
2373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick           it != bypass.rules().end(); ++it) {
2383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        list->Append(Value::CreateStringValue((*it)->ToString()));
2393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      dict->Set("bypass_list", list);
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return dict;
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}  // namespace net
2493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
250