12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/net/onc_utils.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
73551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/bind_helpers.h"
83551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/json/json_writer.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/logging.h"
104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/prefs/pref_service.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h"
12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "chrome/browser/chromeos/login/user.h"
13ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "chrome/browser/chromeos/login/user_manager.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/ui_proxy_config.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/prefs/proxy_config_dictionary.h"
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/common/pref_names.h"
174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/network/favorite_state.h"
183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chromeos/network/managed_network_configuration_handler.h"
193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chromeos/network/network_configuration_handler.h"
203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chromeos/network/network_handler.h"
213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chromeos/network/network_profile.h"
223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chromeos/network/network_profile_handler.h"
231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chromeos/network/network_state.h"
244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/network/network_state_handler.h"
253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chromeos/network/network_ui_data.h"
263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chromeos/network/onc/onc_normalizer.h"
273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chromeos/network/onc/onc_signature.h"
283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chromeos/network/onc/onc_translator.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/network/onc/onc_utils.h"
304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/network/shill_property_util.h"
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/base/host_port_pair.h"
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/proxy/proxy_bypass_rules.h"
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/proxy/proxy_server.h"
343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h"
357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace chromeos {
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace onc {
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)net::ProxyServer ConvertOncProxyLocationToHostPort(
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    net::ProxyServer::Scheme default_proxy_scheme,
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& onc_proxy_location) {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string host;
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  onc_proxy_location.GetStringWithoutPathExpansion(::onc::proxy::kHost, &host);
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Parse |host| according to the format [<scheme>"://"]<server>[":"<port>].
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::ProxyServer proxy_server =
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net::ProxyServer::FromURI(host, default_proxy_scheme);
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int port = 0;
514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  onc_proxy_location.GetIntegerWithoutPathExpansion(::onc::proxy::kPort, &port);
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Replace the port parsed from |host| by the provided |port|.
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return net::ProxyServer(
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      proxy_server.scheme(),
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net::HostPortPair(proxy_server.host_port_pair().host(),
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        static_cast<uint16>(port)));
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppendProxyServerForScheme(
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& onc_manual,
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& onc_scheme,
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string* spec) {
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::DictionaryValue* onc_proxy_location = NULL;
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!onc_manual.GetDictionaryWithoutPathExpansion(onc_scheme,
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                    &onc_proxy_location)) {
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::ProxyServer::Scheme default_proxy_scheme = net::ProxyServer::SCHEME_HTTP;
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string url_scheme;
724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (onc_scheme == ::onc::proxy::kFtp) {
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    url_scheme = "ftp";
744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  } else if (onc_scheme == ::onc::proxy::kHttp) {
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    url_scheme = "http";
764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  } else if (onc_scheme == ::onc::proxy::kHttps) {
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    url_scheme = "https";
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  } else if (onc_scheme == ::onc::proxy::kSocks) {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default_proxy_scheme = net::ProxyServer::SCHEME_SOCKS4;
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    url_scheme = "socks";
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NOTREACHED();
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::ProxyServer proxy_server = ConvertOncProxyLocationToHostPort(
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      default_proxy_scheme, *onc_proxy_location);
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  UIProxyConfig::EncodeAndAppendProxyServer(url_scheme, proxy_server, spec);
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)net::ProxyBypassRules ConvertOncExcludeDomainsToBypassRules(
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::ListValue& onc_exclude_domains) {
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::ProxyBypassRules rules;
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (base::ListValue::const_iterator it = onc_exclude_domains.begin();
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != onc_exclude_domains.end(); ++it) {
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string rule;
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (*it)->GetAsString(&rule);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rules.AddRuleFromString(rule);
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return rules;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<base::DictionaryValue> ConvertOncProxySettingsToProxyConfig(
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue& onc_proxy_settings) {
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string type;
1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  onc_proxy_settings.GetStringWithoutPathExpansion(::onc::proxy::kType, &type);
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<DictionaryValue> proxy_dict;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (type == ::onc::proxy::kDirect) {
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    proxy_dict.reset(ProxyConfigDictionary::CreateDirect());
1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  } else if (type == ::onc::proxy::kWPAD) {
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    proxy_dict.reset(ProxyConfigDictionary::CreateAutoDetect());
1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  } else if (type == ::onc::proxy::kPAC) {
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string pac_url;
1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    onc_proxy_settings.GetStringWithoutPathExpansion(::onc::proxy::kPAC,
1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                                     &pac_url);
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GURL url(pac_url);
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(url.is_valid())
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        << "PAC field is invalid for this ProxySettings.Type";
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    proxy_dict.reset(ProxyConfigDictionary::CreatePacScript(url.spec(),
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                            false));
1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  } else if (type == ::onc::proxy::kManual) {
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::DictionaryValue* manual_dict = NULL;
1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    onc_proxy_settings.GetDictionaryWithoutPathExpansion(::onc::proxy::kManual,
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                         &manual_dict);
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string manual_spec;
1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    AppendProxyServerForScheme(*manual_dict, ::onc::proxy::kFtp, &manual_spec);
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    AppendProxyServerForScheme(*manual_dict, ::onc::proxy::kHttp, &manual_spec);
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    AppendProxyServerForScheme(*manual_dict, ::onc::proxy::kSocks,
1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                               &manual_spec);
1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    AppendProxyServerForScheme(*manual_dict, ::onc::proxy::kHttps,
1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                               &manual_spec);
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::ListValue* exclude_domains = NULL;
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    net::ProxyBypassRules bypass_rules;
1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (onc_proxy_settings.GetListWithoutPathExpansion(
1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            ::onc::proxy::kExcludeDomains, &exclude_domains)) {
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bypass_rules.AssignFrom(
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          ConvertOncExcludeDomainsToBypassRules(*exclude_domains));
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    proxy_dict.reset(ProxyConfigDictionary::CreateFixedServers(
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        manual_spec, bypass_rules.ToString()));
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NOTREACHED();
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return proxy_dict.Pass();
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
151ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace {
152ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
153ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// This class defines which string placeholders of ONC are replaced by which
154ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// user attribute.
155ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochclass UserStringSubstitution : public chromeos::onc::StringSubstitution {
156ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch public:
157ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  explicit UserStringSubstitution(const chromeos::User* user) : user_(user) {}
158ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  virtual ~UserStringSubstitution() {}
159ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
160ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  virtual bool GetSubstitute(const std::string& placeholder,
161ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                             std::string* substitute) const OVERRIDE {
1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (placeholder == ::onc::substitutes::kLoginIDField)
163ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      *substitute = user_->GetAccountName(false);
1644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    else if (placeholder == ::onc::substitutes::kEmailField)
165ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      *substitute = user_->email();
166ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    else
167ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      return false;
168ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return true;
169ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
170ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
171ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch private:
172ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const chromeos::User* user_;
173ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
174ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(UserStringSubstitution);
175ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch};
176ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
177ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}  // namespace
178ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
179ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ExpandStringPlaceholdersInNetworksForUser(
1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const chromeos::User* user,
181ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    base::ListValue* network_configs) {
182a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  if (!user) {
183a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    // In tests no user may be logged in. It's not harmful if we just don't
184a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    // expand the strings.
185a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    return;
186a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  }
187ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  UserStringSubstitution substitution(user);
188ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  chromeos::onc::ExpandStringsInNetworks(substitution, network_configs);
189ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
190ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ImportNetworksForUser(const chromeos::User* user,
1923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                           const base::ListValue& network_configs,
1933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                           std::string* error) {
1943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  error->clear();
1953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<base::ListValue> expanded_networks(network_configs.DeepCopy());
1973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ExpandStringPlaceholdersInNetworksForUser(user, expanded_networks.get());
1983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const NetworkProfile* profile =
2003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NetworkHandler::Get()->network_profile_handler()->GetProfileForUserhash(
2013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          user->username_hash());
2023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!profile) {
2033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    *error = "User profile doesn't exist.";
2043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
2053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bool ethernet_not_found = false;
2083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (base::ListValue::const_iterator it = expanded_networks->begin();
2093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)       it != expanded_networks->end();
2103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)       ++it) {
2113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const base::DictionaryValue* network = NULL;
2123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    (*it)->GetAsDictionary(&network);
2133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DCHECK(network);
2143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Remove irrelevant fields.
2163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    onc::Normalizer normalizer(true /* remove recommended fields */);
2173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<base::DictionaryValue> normalized_network =
2183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        normalizer.NormalizeObject(&onc::kNetworkConfigurationSignature,
2193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   *network);
2203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<base::DictionaryValue> shill_dict =
2223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        onc::TranslateONCObjectToShill(&onc::kNetworkConfigurationSignature,
2233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       *normalized_network);
2243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<NetworkUIData> ui_data = NetworkUIData::CreateFromONC(
2264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        ::onc::ONC_SOURCE_USER_IMPORT, *normalized_network);
2273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base::DictionaryValue ui_data_dict;
2283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    ui_data->FillDictionary(&ui_data_dict);
2293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    std::string ui_data_json;
2303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base::JSONWriter::Write(&ui_data_dict, &ui_data_json);
23168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    shill_dict->SetStringWithoutPathExpansion(shill::kUIDataProperty,
2323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              ui_data_json);
2333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
23468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    shill_dict->SetStringWithoutPathExpansion(shill::kProfileProperty,
2353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              profile->path);
2363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    std::string type;
2381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    shill_dict->GetStringWithoutPathExpansion(shill::kTypeProperty, &type);
2391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    NetworkConfigurationHandler* config_handler =
2401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        NetworkHandler::Get()->network_configuration_handler();
2411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (NetworkTypePattern::Ethernet().MatchesType(type)) {
2421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // Ethernet has to be configured using an existing Ethernet service.
2431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      const NetworkState* ethernet =
2441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          NetworkHandler::Get()->network_state_handler()->FirstNetworkByType(
2451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)              NetworkTypePattern::Ethernet());
2461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (ethernet) {
2471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        config_handler->SetProperties(ethernet->path(),
2481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                      *shill_dict,
2491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                      base::Closure(),
2501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                      network_handler::ErrorCallback());
2511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      } else {
2521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        ethernet_not_found = true;
2531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      }
2541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    } else {
2561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      config_handler->CreateConfiguration(
2571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          *shill_dict,
2581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          network_handler::StringResultCallback(),
2591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          network_handler::ErrorCallback());
2601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
2613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (ethernet_not_found)
2641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    *error = "No Ethernet available to configure.";
2653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const base::DictionaryValue* FindPolicyForActiveUser(
2683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const std::string& guid,
2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ::onc::ONCSource* onc_source) {
2703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const User* user = UserManager::Get()->GetActiveUser();
2713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string username_hash = user ? user->username_hash() : std::string();
2723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return NetworkHandler::Get()->managed_network_configuration_handler()->
2733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      FindPolicyByGUID(username_hash, guid, onc_source);
2743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)const base::DictionaryValue* GetGlobalConfigFromPolicy(bool for_active_user) {
2778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  std::string username_hash;
2788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (for_active_user) {
2798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const User* user = UserManager::Get()->GetActiveUser();
2808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (!user) {
2818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      LOG(ERROR) << "No user logged in yet.";
2828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return NULL;
2838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
2848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    username_hash = user->username_hash();
2858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
2868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return NetworkHandler::Get()->managed_network_configuration_handler()->
2878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      GetGlobalConfigFromPolicy(username_hash);
2888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
2898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool PolicyAllowsOnlyPolicyNetworksToAutoconnect(bool for_active_user) {
2918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const base::DictionaryValue* global_config =
2928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      GetGlobalConfigFromPolicy(for_active_user);
2938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!global_config)
2948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return false;  // By default, all networks are allowed to autoconnect.
2958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  bool only_policy_autoconnect = false;
2978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  global_config->GetBooleanWithoutPathExpansion(
2988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect,
2998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      &only_policy_autoconnect);
3008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return only_policy_autoconnect;
3018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
3028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace {
3044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const base::DictionaryValue* GetNetworkConfigByGUID(
3064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const base::ListValue& network_configs,
3074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const std::string& guid) {
3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (base::ListValue::const_iterator it = network_configs.begin();
3094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       it != network_configs.end(); ++it) {
3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const base::DictionaryValue* network = NULL;
3114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    (*it)->GetAsDictionary(&network);
3124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    DCHECK(network);
3134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    std::string current_guid;
3154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    network->GetStringWithoutPathExpansion(::onc::network_config::kGUID,
3164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                           &current_guid);
3174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (current_guid == guid)
3184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return network;
3194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return NULL;
3214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const base::DictionaryValue* GetNetworkConfigForEthernetWithoutEAP(
3244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const base::ListValue& network_configs) {
3254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  VLOG(2) << "Search for ethernet policy without EAP.";
3264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (base::ListValue::const_iterator it = network_configs.begin();
3274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       it != network_configs.end(); ++it) {
3284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const base::DictionaryValue* network = NULL;
3294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    (*it)->GetAsDictionary(&network);
3304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    DCHECK(network);
3314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    std::string type;
3334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    network->GetStringWithoutPathExpansion(::onc::network_config::kType, &type);
3344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (type != ::onc::network_type::kEthernet)
3354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      continue;
3364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const base::DictionaryValue* ethernet = NULL;
3384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    network->GetDictionaryWithoutPathExpansion(::onc::network_config::kEthernet,
3394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                               &ethernet);
3404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    std::string auth;
3424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ethernet->GetStringWithoutPathExpansion(::onc::ethernet::kAuthentication,
3434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                            &auth);
3444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (auth == ::onc::ethernet::kNone)
3454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return network;
3464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return NULL;
3484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const base::DictionaryValue* GetNetworkConfigForNetworkFromOnc(
3514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const base::ListValue& network_configs,
3524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const FavoriteState& favorite) {
3534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // In all cases except Ethernet, we use the GUID of |network|.
3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!favorite.Matches(NetworkTypePattern::Ethernet()))
3554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return GetNetworkConfigByGUID(network_configs, favorite.guid());
3564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Ethernet is always shared and thus cannot store a GUID per user. Thus we
3584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // search for any Ethernet policy intead of a matching GUID.
3594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // EthernetEAP service contains only the EAP parameters and stores the GUID of
3604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // the respective ONC policy. The EthernetEAP service itself is however never
3614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // in state "connected". An EthernetEAP policy must be applied, if an Ethernet
3624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // service is connected using the EAP parameters.
3634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const FavoriteState* ethernet_eap = NULL;
3644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (NetworkHandler::IsInitialized()) {
3654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ethernet_eap =
3664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        NetworkHandler::Get()->network_state_handler()->GetEAPForEthernet(
3674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            favorite.path());
3684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // The GUID associated with the EthernetEAP service refers to the ONC policy
3714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // with "Authentication: 8021X".
3724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (ethernet_eap)
3734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return GetNetworkConfigByGUID(network_configs, ethernet_eap->guid());
3744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Otherwise, EAP is not used and instead the Ethernet policy with
3764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // "Authentication: None" applies.
3774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return GetNetworkConfigForEthernetWithoutEAP(network_configs);
3784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const base::DictionaryValue* GetPolicyForNetworkFromPref(
3814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const PrefService* pref_service,
3824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const char* pref_name,
3834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const FavoriteState& favorite) {
3844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!pref_service) {
3854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    VLOG(2) << "No pref service";
3864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return NULL;
3874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const PrefService::Preference* preference =
3904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      pref_service->FindPreference(pref_name);
3914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!preference) {
3924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    VLOG(2) << "No preference " << pref_name;
3934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // The preference may not exist in tests.
3944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return NULL;
3954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // User prefs are not stored in this Preference yet but only the policy.
3984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  //
3994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // The policy server incorrectly configures the OpenNetworkConfiguration user
4004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // policy as Recommended. To work around that, we handle the Recommended and
4014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // the Mandatory value in the same way.
4024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // TODO(pneubeck): Remove this workaround, once the server is fixed. See
4034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // http://crbug.com/280553 .
4044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (preference->IsDefaultValue()) {
4054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    VLOG(2) << "Preference has no recommended or mandatory value.";
4064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // No policy set.
4074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return NULL;
4084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
4094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  VLOG(2) << "Preference with policy found.";
4104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const base::Value* onc_policy_value = preference->GetValue();
4114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(onc_policy_value);
4124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const base::ListValue* onc_policy = NULL;
4144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  onc_policy_value->GetAsList(&onc_policy);
4154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(onc_policy);
4164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return GetNetworkConfigForNetworkFromOnc(*onc_policy, favorite);
4184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
4194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace
4214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const base::DictionaryValue* GetPolicyForFavoriteNetwork(
4234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const PrefService* profile_prefs,
4244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const PrefService* local_state_prefs,
4254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const FavoriteState& favorite,
4264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ::onc::ONCSource* onc_source) {
4274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  VLOG(2) << "GetPolicyForFavoriteNetwork: " << favorite.path();
4284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  *onc_source = ::onc::ONC_SOURCE_NONE;
4294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const base::DictionaryValue* network_policy = GetPolicyForNetworkFromPref(
4314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      profile_prefs, prefs::kOpenNetworkConfiguration, favorite);
4324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (network_policy) {
4334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    VLOG(1) << "Network " << favorite.path() << " is managed by user policy.";
4344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    *onc_source = ::onc::ONC_SOURCE_USER_POLICY;
4354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return network_policy;
4364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
4374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  network_policy = GetPolicyForNetworkFromPref(
4384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      local_state_prefs, prefs::kDeviceOpenNetworkConfiguration, favorite);
4394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (network_policy) {
4404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    VLOG(1) << "Network " << favorite.path() << " is managed by device policy.";
4414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    *onc_source = ::onc::ONC_SOURCE_DEVICE_POLICY;
4424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return network_policy;
4434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
4444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  VLOG(2) << "Network " << favorite.path() << " is unmanaged.";
4454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return NULL;
4464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
4474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool HasPolicyForFavoriteNetwork(const PrefService* profile_prefs,
4494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                 const PrefService* local_state_prefs,
4504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                 const FavoriteState& network) {
4514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ::onc::ONCSource ignored_onc_source;
4524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const base::DictionaryValue* policy = onc::GetPolicyForFavoriteNetwork(
4534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      profile_prefs, local_state_prefs, network, &ignored_onc_source);
4544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return policy != NULL;
4554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
4564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace onc
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace chromeos
459