Home | History | Annotate | Download | only in net
      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 
     27 namespace chromeos {
     28 
     29 namespace {
     30 
     31 const 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 
     48 scoped_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   const PrefService::Preference* preference =
     59       pref_service->FindPreference(pref_name);
     60   if (!preference) {
     61     // The preference may not exit in tests.
     62     return scoped_ptr<ProxyConfigDictionary>();
     63   }
     64 
     65   // User prefs are not stored in this Preference yet but only the policy.
     66   //
     67   // The policy server incorrectly configures the OpenNetworkConfiguration user
     68   // policy as Recommended. To work around that, we handle the Recommended and
     69   // the Mandatory value in the same way.
     70   // TODO(pneubeck): Remove this workaround, once the server is fixed. See
     71   // http://crbug.com/280553 .
     72   if (preference->IsDefaultValue()) {
     73     // No policy set.
     74     return scoped_ptr<ProxyConfigDictionary>();
     75   }
     76   const base::Value* onc_policy_value = preference->GetValue();
     77   DCHECK(onc_policy_value);
     78 
     79   const base::ListValue* onc_policy = NULL;
     80   onc_policy_value->GetAsList(&onc_policy);
     81   DCHECK(onc_policy);
     82 
     83   const base::DictionaryValue* network_policy =
     84       GetNetworkConfigByGUID(*onc_policy, network.guid());
     85   if (!network_policy) {
     86     // This network isn't managed by this policy.
     87     return scoped_ptr<ProxyConfigDictionary>();
     88   }
     89 
     90   const base::DictionaryValue* proxy_policy = NULL;
     91   network_policy->GetDictionaryWithoutPathExpansion(
     92       onc::network_config::kProxySettings, &proxy_policy);
     93   if (!proxy_policy) {
     94     // This policy doesn't set a proxy for this network. Nonetheless, this
     95     // disallows changes by the user.
     96     *network_is_managed = true;
     97     return scoped_ptr<ProxyConfigDictionary>();
     98   }
     99 
    100   scoped_ptr<base::DictionaryValue> proxy_dict =
    101       onc::ConvertOncProxySettingsToProxyConfig(*proxy_policy);
    102   *network_is_managed = true;
    103   return make_scoped_ptr(new ProxyConfigDictionary(proxy_dict.get()));
    104 }
    105 
    106 }  // namespace
    107 
    108 namespace proxy_config {
    109 
    110 scoped_ptr<ProxyConfigDictionary> GetProxyConfigForNetwork(
    111     const PrefService* profile_prefs,
    112     const PrefService* local_state_prefs,
    113     const NetworkState& network,
    114     onc::ONCSource* onc_source) {
    115   VLOG(2) << "GetProxyConfigForNetwork network: " << network.path()
    116           << " , guid: " << network.guid();
    117   *onc_source = onc::ONC_SOURCE_NONE;
    118   bool network_is_managed = false;
    119 
    120   scoped_ptr<ProxyConfigDictionary> proxy_config =
    121       GetProxyPolicy(profile_prefs,
    122                      prefs::kOpenNetworkConfiguration,
    123                      network,
    124                      &network_is_managed);
    125   if (network_is_managed) {
    126     VLOG(1) << "Network " << network.path() << " is managed by user policy.";
    127     *onc_source = onc::ONC_SOURCE_USER_POLICY;
    128     return proxy_config.Pass();
    129   }
    130   proxy_config = GetProxyPolicy(local_state_prefs,
    131                                 prefs::kDeviceOpenNetworkConfiguration,
    132                                 network,
    133                                 &network_is_managed);
    134   if (network_is_managed) {
    135     VLOG(1) << "Network " << network.path() << " is managed by device policy.";
    136     *onc_source = onc::ONC_SOURCE_DEVICE_POLICY;
    137     return proxy_config.Pass();
    138   }
    139 
    140   if (network.profile_path().empty())
    141     return scoped_ptr<ProxyConfigDictionary>();
    142 
    143   const NetworkProfile* profile = NetworkHandler::Get()
    144       ->network_profile_handler()->GetProfileForPath(network.profile_path());
    145   if (!profile) {
    146     LOG(WARNING) << "Unknown profile_path '" << network.profile_path() << "'.";
    147     return scoped_ptr<ProxyConfigDictionary>();
    148   }
    149   if (!profile_prefs && profile->type() == NetworkProfile::TYPE_USER) {
    150     // This case occurs, for example, if called from the proxy config tracker
    151     // created for the system request context and the signin screen. Both don't
    152     // use profile prefs and shouldn't depend on the user's not shared proxy
    153     // settings.
    154     VLOG(1)
    155         << "Don't use unshared settings for system context or signin screen.";
    156     return scoped_ptr<ProxyConfigDictionary>();
    157   }
    158 
    159   // No policy set for this network, read instead the user's (shared or
    160   // unshared) configuration.
    161   // The user's proxy setting is not stored in the Chrome preference yet. We
    162   // still rely on Shill storing it.
    163   const base::DictionaryValue& value = network.proxy_config();
    164   if (value.empty())
    165     return scoped_ptr<ProxyConfigDictionary>();
    166   return make_scoped_ptr(new ProxyConfigDictionary(&value));
    167 }
    168 
    169 void SetProxyConfigForNetwork(const ProxyConfigDictionary& proxy_config,
    170                               const NetworkState& network) {
    171   chromeos::ShillServiceClient* shill_service_client =
    172       DBusThreadManager::Get()->GetShillServiceClient();
    173 
    174   // The user's proxy setting is not stored in the Chrome preference yet. We
    175   // still rely on Shill storing it.
    176   ProxyPrefs::ProxyMode mode;
    177   if (!proxy_config.GetMode(&mode) || mode == ProxyPrefs::MODE_DIRECT) {
    178     // TODO(pneubeck): Consider removing this legacy code.  Return empty string
    179     // for direct mode for portal check to work correctly.
    180     shill_service_client->ClearProperty(
    181         dbus::ObjectPath(network.path()),
    182         flimflam::kProxyConfigProperty,
    183         base::Bind(&base::DoNothing),
    184         base::Bind(&network_handler::ShillErrorCallbackFunction,
    185                    "SetProxyConfig.ClearProperty Failed",
    186                    network.path(),
    187                    network_handler::ErrorCallback()));
    188   } else {
    189     std::string proxy_config_str;
    190     base::JSONWriter::Write(&proxy_config.GetDictionary(), &proxy_config_str);
    191     shill_service_client->SetProperty(
    192         dbus::ObjectPath(network.path()),
    193         flimflam::kProxyConfigProperty,
    194         base::StringValue(proxy_config_str),
    195         base::Bind(&base::DoNothing),
    196         base::Bind(&network_handler::ShillErrorCallbackFunction,
    197                    "SetProxyConfig.SetProperty Failed",
    198                    network.path(),
    199                    network_handler::ErrorCallback()));
    200   }
    201 
    202   if (NetworkHandler::IsInitialized()) {
    203     NetworkHandler::Get()->network_state_handler()
    204         ->RequestUpdateForNetwork(network.path());
    205   }
    206 }
    207 
    208 void RegisterPrefs(PrefRegistrySimple* registry) {
    209   registry->RegisterListPref(prefs::kDeviceOpenNetworkConfiguration);
    210 }
    211 
    212 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
    213   registry->RegisterBooleanPref(
    214       prefs::kUseSharedProxies,
    215       false,
    216       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
    217 
    218   registry->RegisterListPref(prefs::kOpenNetworkConfiguration,
    219                              user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
    220 }
    221 
    222 }  // namespace proxy_config
    223 
    224 }  // namespace chromeos
    225