proxy_config_handler.cc revision ca12bfac764ba476d6cd062bf1dde12cc64c3f40
1// Copyright (c) 2013 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/proxy_config_handler.h"
6
7#include "base/bind.h"
8#include "base/json/json_writer.h"
9#include "base/logging.h"
10#include "base/prefs/pref_registry_simple.h"
11#include "base/prefs/pref_service.h"
12#include "base/values.h"
13#include "chrome/browser/chromeos/net/onc_utils.h"
14#include "chrome/browser/prefs/proxy_config_dictionary.h"
15#include "chrome/common/pref_names.h"
16#include "chromeos/dbus/dbus_thread_manager.h"
17#include "chromeos/dbus/shill_service_client.h"
18#include "chromeos/network/network_handler_callbacks.h"
19#include "chromeos/network/network_profile.h"
20#include "chromeos/network/network_profile_handler.h"
21#include "chromeos/network/network_state.h"
22#include "chromeos/network/network_state_handler.h"
23#include "components/user_prefs/pref_registry_syncable.h"
24#include "dbus/object_path.h"
25#include "third_party/cros_system_api/dbus/service_constants.h"
26
27namespace chromeos {
28
29namespace {
30
31const base::DictionaryValue* GetNetworkConfigByGUID(
32    const base::ListValue& network_configs,
33    const std::string& guid) {
34  for (base::ListValue::const_iterator it = network_configs.begin();
35       it != network_configs.end();
36       ++it) {
37    const base::DictionaryValue* network = NULL;
38    (*it)->GetAsDictionary(&network);
39    std::string current_guid;
40    network->GetStringWithoutPathExpansion(onc::network_config::kGUID,
41                                           &current_guid);
42    if (current_guid == guid)
43      return network;
44  }
45  return NULL;
46}
47
48scoped_ptr<ProxyConfigDictionary> GetProxyPolicy(
49    const PrefService* pref_service,
50    const char* pref_name,
51    const NetworkState& network,
52    bool* network_is_managed) {
53  *network_is_managed = false;
54
55  if (!pref_service || network.guid().empty())
56    return scoped_ptr<ProxyConfigDictionary>();
57
58  if (!pref_service->IsManagedPreference(pref_name)) {
59    // No policy set.
60    return scoped_ptr<ProxyConfigDictionary>();
61  }
62
63  const base::ListValue* onc_policy = pref_service->GetList(pref_name);
64  if (!onc_policy) {
65    LOG(ERROR) << "Pref " << pref_name << " is managed, but no value is set.";
66    return scoped_ptr<ProxyConfigDictionary>();
67  }
68
69  const base::DictionaryValue* network_policy =
70      GetNetworkConfigByGUID(*onc_policy, network.guid());
71  if (!network_policy) {
72    // This network isn't managed by this policy.
73    return scoped_ptr<ProxyConfigDictionary>();
74  }
75
76  const base::DictionaryValue* proxy_policy = NULL;
77  network_policy->GetDictionaryWithoutPathExpansion(
78      onc::network_config::kProxySettings, &proxy_policy);
79  if (!proxy_policy) {
80    // This policy doesn't set a proxy for this network. Nonetheless, this
81    // disallows changes by the user.
82    *network_is_managed = true;
83    return scoped_ptr<ProxyConfigDictionary>();
84  }
85
86  scoped_ptr<base::DictionaryValue> proxy_dict =
87      onc::ConvertOncProxySettingsToProxyConfig(*proxy_policy);
88  *network_is_managed = true;
89  return make_scoped_ptr(new ProxyConfigDictionary(proxy_dict.get()));
90}
91
92}  // namespace
93
94namespace proxy_config {
95
96scoped_ptr<ProxyConfigDictionary> GetProxyConfigForNetwork(
97    const PrefService* profile_prefs,
98    const PrefService* local_state_prefs,
99    const NetworkState& network,
100    onc::ONCSource* onc_source) {
101  VLOG(2) << "GetProxyConfigForNetwork network: " << network.path()
102          << " , guid: " << network.guid();
103  *onc_source = onc::ONC_SOURCE_NONE;
104  bool network_is_managed = false;
105
106  scoped_ptr<ProxyConfigDictionary> proxy_config =
107      GetProxyPolicy(profile_prefs,
108                     prefs::kOpenNetworkConfiguration,
109                     network,
110                     &network_is_managed);
111  if (network_is_managed) {
112    VLOG(1) << "Network " << network.path() << " is managed by user policy.";
113    *onc_source = onc::ONC_SOURCE_USER_POLICY;
114    return proxy_config.Pass();
115  }
116  proxy_config = GetProxyPolicy(local_state_prefs,
117                                prefs::kDeviceOpenNetworkConfiguration,
118                                network,
119                                &network_is_managed);
120  if (network_is_managed) {
121    VLOG(1) << "Network " << network.path() << " is managed by device policy.";
122    *onc_source = onc::ONC_SOURCE_DEVICE_POLICY;
123    return proxy_config.Pass();
124  }
125
126  if (network.profile_path().empty())
127    return scoped_ptr<ProxyConfigDictionary>();
128
129  const NetworkProfile* profile = NetworkHandler::Get()
130      ->network_profile_handler()->GetProfileForPath(network.profile_path());
131  if (!profile) {
132    LOG(WARNING) << "Unknown profile_path '" << network.profile_path() << "'.";
133    return scoped_ptr<ProxyConfigDictionary>();
134  }
135  if (!profile_prefs && profile->type() == NetworkProfile::TYPE_USER) {
136    // This case occurs, for example, if called from the proxy config tracker
137    // created for the system request context and the signin screen. Both don't
138    // use profile prefs and shouldn't depend on the user's not shared proxy
139    // settings.
140    VLOG(1)
141        << "Don't use unshared settings for system context or signin screen.";
142    return scoped_ptr<ProxyConfigDictionary>();
143  }
144
145  // No policy set for this network, read instead the user's (shared or
146  // unshared) configuration.
147  const base::DictionaryValue& value = network.proxy_config();
148  if (value.empty())
149    return scoped_ptr<ProxyConfigDictionary>();
150  return make_scoped_ptr(new ProxyConfigDictionary(&value));
151}
152
153void SetProxyConfigForNetwork(const ProxyConfigDictionary& proxy_config,
154                              const NetworkState& network) {
155  chromeos::ShillServiceClient* shill_service_client =
156      DBusThreadManager::Get()->GetShillServiceClient();
157
158  ProxyPrefs::ProxyMode mode;
159  if (!proxy_config.GetMode(&mode) || mode == ProxyPrefs::MODE_DIRECT) {
160    // TODO(pneubeck): Consider removing this legacy code.  Return empty string
161    // for direct mode for portal check to work correctly.
162    shill_service_client->ClearProperty(
163        dbus::ObjectPath(network.path()),
164        flimflam::kProxyConfigProperty,
165        base::Bind(&base::DoNothing),
166        base::Bind(&network_handler::ShillErrorCallbackFunction,
167                   "SetProxyConfig.ClearProperty Failed",
168                   network.path(),
169                   network_handler::ErrorCallback()));
170  } else {
171    std::string proxy_config_str;
172    base::JSONWriter::Write(&proxy_config.GetDictionary(), &proxy_config_str);
173    shill_service_client->SetProperty(
174        dbus::ObjectPath(network.path()),
175        flimflam::kProxyConfigProperty,
176        base::StringValue(proxy_config_str),
177        base::Bind(&base::DoNothing),
178        base::Bind(&network_handler::ShillErrorCallbackFunction,
179                   "SetProxyConfig.SetProperty Failed",
180                   network.path(),
181                   network_handler::ErrorCallback()));
182  }
183
184  if (NetworkHandler::IsInitialized()) {
185    NetworkHandler::Get()->network_state_handler()
186        ->RequestUpdateForNetwork(network.path());
187  }
188}
189
190void RegisterPrefs(PrefRegistrySimple* registry) {
191  registry->RegisterListPref(prefs::kDeviceOpenNetworkConfiguration);
192}
193
194void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
195  registry->RegisterBooleanPref(
196      prefs::kUseSharedProxies,
197      false,
198      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
199
200  registry->RegisterListPref(prefs::kOpenNetworkConfiguration,
201                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
202}
203
204}  // namespace proxy_config
205
206}  // namespace chromeos
207