proxy_config_handler.cc revision 3551c9c881056c480085172ff9840cab31610854
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 ¤t_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 92void NotifyNetworkStateHandler(const std::string& service_path) { 93 if (NetworkHandler::IsInitialized()) { 94 NetworkHandler::Get()->network_state_handler()->RequestUpdateForNetwork( 95 service_path); 96 } 97} 98 99} // namespace 100 101namespace proxy_config { 102 103scoped_ptr<ProxyConfigDictionary> GetProxyConfigForNetwork( 104 const PrefService* profile_prefs, 105 const PrefService* local_state_prefs, 106 const NetworkState& network, 107 onc::ONCSource* onc_source) { 108 VLOG(2) << "GetProxyConfigForNetwork network: " << network.path() 109 << " , guid: " << network.guid(); 110 *onc_source = onc::ONC_SOURCE_NONE; 111 bool network_is_managed = false; 112 113 scoped_ptr<ProxyConfigDictionary> proxy_config = 114 GetProxyPolicy(profile_prefs, 115 prefs::kOpenNetworkConfiguration, 116 network, 117 &network_is_managed); 118 if (network_is_managed) { 119 VLOG(1) << "Network " << network.path() << " is managed by user policy."; 120 *onc_source = onc::ONC_SOURCE_USER_POLICY; 121 return proxy_config.Pass(); 122 } 123 proxy_config = GetProxyPolicy(local_state_prefs, 124 prefs::kDeviceOpenNetworkConfiguration, 125 network, 126 &network_is_managed); 127 if (network_is_managed) { 128 VLOG(1) << "Network " << network.path() << " is managed by device policy."; 129 *onc_source = onc::ONC_SOURCE_DEVICE_POLICY; 130 return proxy_config.Pass(); 131 } 132 133 if (network.profile_path().empty()) 134 return scoped_ptr<ProxyConfigDictionary>(); 135 136 const NetworkProfile* profile = NetworkHandler::Get() 137 ->network_profile_handler()->GetProfileForPath(network.profile_path()); 138 if (!profile) { 139 LOG(WARNING) << "Unknown profile_path '" << network.profile_path() << "'."; 140 return scoped_ptr<ProxyConfigDictionary>(); 141 } 142 if (!profile_prefs && profile->type() == NetworkProfile::TYPE_USER) { 143 // This case occurs, for example, if called from the proxy config tracker 144 // created for the system request context and the signin screen. Both don't 145 // use profile prefs and shouldn't depend on the user's not shared proxy 146 // settings. 147 VLOG(1) 148 << "Don't use unshared settings for system context or signin screen."; 149 return scoped_ptr<ProxyConfigDictionary>(); 150 } 151 152 // No policy set for this network, read instead the user's (shared or 153 // unshared) configuration. 154 const base::DictionaryValue& value = network.proxy_config(); 155 if (value.empty()) 156 return scoped_ptr<ProxyConfigDictionary>(); 157 return make_scoped_ptr(new ProxyConfigDictionary(&value)); 158} 159 160void SetProxyConfigForNetwork(const ProxyConfigDictionary& proxy_config, 161 const NetworkState& network) { 162 chromeos::ShillServiceClient* shill_service_client = 163 DBusThreadManager::Get()->GetShillServiceClient(); 164 165 ProxyPrefs::ProxyMode mode; 166 if (!proxy_config.GetMode(&mode) || mode == ProxyPrefs::MODE_DIRECT) { 167 // Return empty string for direct mode for portal check to work correctly. 168 // TODO(pneubeck): Consider removing this legacy code. 169 shill_service_client->ClearProperty( 170 dbus::ObjectPath(network.path()), 171 flimflam::kProxyConfigProperty, 172 base::Bind(&NotifyNetworkStateHandler, network.path()), 173 base::Bind(&network_handler::ShillErrorCallbackFunction, 174 "SetProxyConfig.ClearProperty Failed", 175 network.path(), 176 network_handler::ErrorCallback())); 177 } else { 178 std::string proxy_config_str; 179 base::JSONWriter::Write(&proxy_config.GetDictionary(), &proxy_config_str); 180 shill_service_client->SetProperty( 181 dbus::ObjectPath(network.path()), 182 flimflam::kProxyConfigProperty, 183 base::StringValue(proxy_config_str), 184 base::Bind(&NotifyNetworkStateHandler, network.path()), 185 base::Bind(&network_handler::ShillErrorCallbackFunction, 186 "SetProxyConfig.SetProperty Failed", 187 network.path(), 188 network_handler::ErrorCallback())); 189 } 190} 191 192void RegisterPrefs(PrefRegistrySimple* registry) { 193 registry->RegisterListPref(prefs::kDeviceOpenNetworkConfiguration); 194} 195 196void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { 197 registry->RegisterBooleanPref( 198 prefs::kUseSharedProxies, 199 false, 200 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 201 202 registry->RegisterListPref(prefs::kOpenNetworkConfiguration, 203 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 204} 205 206} // namespace proxy_config 207 208} // namespace chromeos 209