onc_utils.cc revision ca12bfac764ba476d6cd062bf1dde12cc64c3f40
1// Copyright (c) 2012 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/chromeos/net/onc_utils.h"
6
7#include "base/logging.h"
8#include "base/values.h"
9#include "chrome/browser/chromeos/login/user.h"
10#include "chrome/browser/chromeos/login/user_manager.h"
11#include "chrome/browser/chromeos/ui_proxy_config.h"
12#include "chrome/browser/prefs/proxy_config_dictionary.h"
13#include "chromeos/network/onc/onc_utils.h"
14#include "net/base/host_port_pair.h"
15#include "net/proxy/proxy_bypass_rules.h"
16#include "net/proxy/proxy_server.h"
17#include "url/gurl.h"
18
19namespace chromeos {
20namespace onc {
21
22namespace {
23
24net::ProxyServer ConvertOncProxyLocationToHostPort(
25    net::ProxyServer::Scheme default_proxy_scheme,
26    const base::DictionaryValue& onc_proxy_location) {
27  std::string host;
28  onc_proxy_location.GetStringWithoutPathExpansion(onc::proxy::kHost, &host);
29  // Parse |host| according to the format [<scheme>"://"]<server>[":"<port>].
30  net::ProxyServer proxy_server =
31      net::ProxyServer::FromURI(host, default_proxy_scheme);
32  int port = 0;
33  onc_proxy_location.GetIntegerWithoutPathExpansion(onc::proxy::kPort, &port);
34
35  // Replace the port parsed from |host| by the provided |port|.
36  return net::ProxyServer(
37      proxy_server.scheme(),
38      net::HostPortPair(proxy_server.host_port_pair().host(),
39                        static_cast<uint16>(port)));
40}
41
42void AppendProxyServerForScheme(
43    const base::DictionaryValue& onc_manual,
44    const std::string& onc_scheme,
45    std::string* spec) {
46  const base::DictionaryValue* onc_proxy_location = NULL;
47  if (!onc_manual.GetDictionaryWithoutPathExpansion(onc_scheme,
48                                                    &onc_proxy_location)) {
49    return;
50  }
51
52  net::ProxyServer::Scheme default_proxy_scheme = net::ProxyServer::SCHEME_HTTP;
53  std::string url_scheme;
54  if (onc_scheme == proxy::kFtp) {
55    url_scheme = "ftp";
56  } else if (onc_scheme == proxy::kHttp) {
57    url_scheme = "http";
58  } else if (onc_scheme == proxy::kHttps) {
59    url_scheme = "https";
60  } else if (onc_scheme == proxy::kSocks) {
61    default_proxy_scheme = net::ProxyServer::SCHEME_SOCKS4;
62    url_scheme = "socks";
63  } else {
64    NOTREACHED();
65  }
66
67  net::ProxyServer proxy_server = ConvertOncProxyLocationToHostPort(
68      default_proxy_scheme, *onc_proxy_location);
69
70  UIProxyConfig::EncodeAndAppendProxyServer(url_scheme, proxy_server, spec);
71}
72
73net::ProxyBypassRules ConvertOncExcludeDomainsToBypassRules(
74    const base::ListValue& onc_exclude_domains) {
75  net::ProxyBypassRules rules;
76  for (base::ListValue::const_iterator it = onc_exclude_domains.begin();
77       it != onc_exclude_domains.end(); ++it) {
78    std::string rule;
79    (*it)->GetAsString(&rule);
80    rules.AddRuleFromString(rule);
81  }
82  return rules;
83}
84
85}  // namespace
86
87scoped_ptr<base::DictionaryValue> ConvertOncProxySettingsToProxyConfig(
88    const base::DictionaryValue& onc_proxy_settings) {
89  std::string type;
90  onc_proxy_settings.GetStringWithoutPathExpansion(proxy::kType, &type);
91  scoped_ptr<DictionaryValue> proxy_dict;
92
93  if (type == proxy::kDirect) {
94    proxy_dict.reset(ProxyConfigDictionary::CreateDirect());
95  } else if (type == proxy::kWPAD) {
96    proxy_dict.reset(ProxyConfigDictionary::CreateAutoDetect());
97  } else if (type == proxy::kPAC) {
98    std::string pac_url;
99    onc_proxy_settings.GetStringWithoutPathExpansion(proxy::kPAC, &pac_url);
100    GURL url(pac_url);
101    DCHECK(url.is_valid())
102        << "PAC field is invalid for this ProxySettings.Type";
103    proxy_dict.reset(ProxyConfigDictionary::CreatePacScript(url.spec(),
104                                                            false));
105  } else if (type == proxy::kManual) {
106    const base::DictionaryValue* manual_dict = NULL;
107    onc_proxy_settings.GetDictionaryWithoutPathExpansion(proxy::kManual,
108                                                         &manual_dict);
109    std::string manual_spec;
110    AppendProxyServerForScheme(*manual_dict, proxy::kFtp, &manual_spec);
111    AppendProxyServerForScheme(*manual_dict, proxy::kHttp, &manual_spec);
112    AppendProxyServerForScheme(*manual_dict, proxy::kSocks, &manual_spec);
113    AppendProxyServerForScheme(*manual_dict, proxy::kHttps, &manual_spec);
114
115    const base::ListValue* exclude_domains = NULL;
116    net::ProxyBypassRules bypass_rules;
117    if (onc_proxy_settings.GetListWithoutPathExpansion(proxy::kExcludeDomains,
118                                                       &exclude_domains)) {
119      bypass_rules.AssignFrom(
120          ConvertOncExcludeDomainsToBypassRules(*exclude_domains));
121    }
122    proxy_dict.reset(ProxyConfigDictionary::CreateFixedServers(
123        manual_spec, bypass_rules.ToString()));
124  } else {
125    NOTREACHED();
126  }
127  return proxy_dict.Pass();
128}
129
130namespace {
131
132// This class defines which string placeholders of ONC are replaced by which
133// user attribute.
134class UserStringSubstitution : public chromeos::onc::StringSubstitution {
135 public:
136  explicit UserStringSubstitution(const chromeos::User* user) : user_(user) {}
137  virtual ~UserStringSubstitution() {}
138
139  virtual bool GetSubstitute(const std::string& placeholder,
140                             std::string* substitute) const OVERRIDE {
141    if (placeholder == chromeos::onc::substitutes::kLoginIDField)
142      *substitute = user_->GetAccountName(false);
143    else if (placeholder == chromeos::onc::substitutes::kEmailField)
144      *substitute = user_->email();
145    else
146      return false;
147    return true;
148  }
149
150 private:
151  const chromeos::User* user_;
152
153  DISALLOW_COPY_AND_ASSIGN(UserStringSubstitution);
154};
155
156const chromeos::User* GetLoggedInUserByHash(const std::string& userhash) {
157  const chromeos::UserList& users =
158      chromeos::UserManager::Get()->GetLoggedInUsers();
159  for (chromeos::UserList::const_iterator it = users.begin(); it != users.end();
160       ++it) {
161    if ((*it)->username_hash() == userhash)
162      return *it;
163  }
164  return NULL;
165}
166
167}  // namespace
168
169void ExpandStringPlaceholdersInNetworksForUser(
170    const std::string& hashed_username,
171    base::ListValue* network_configs) {
172  const chromeos::User* user = GetLoggedInUserByHash(hashed_username);
173  DCHECK(user);
174  UserStringSubstitution substitution(user);
175  chromeos::onc::ExpandStringsInNetworks(substitution, network_configs);
176}
177
178}  // namespace onc
179}  // namespace chromeos
180