network_state.cc revision 116680a4aac90f2aa7413d9095a592090648e557
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 "chromeos/network/network_state.h" 6 7#include "base/strings/stringprintf.h" 8#include "chromeos/network/network_event_log.h" 9#include "chromeos/network/network_profile_handler.h" 10#include "chromeos/network/network_type_pattern.h" 11#include "chromeos/network/network_util.h" 12#include "chromeos/network/onc/onc_utils.h" 13#include "chromeos/network/shill_property_util.h" 14#include "third_party/cros_system_api/dbus/service_constants.h" 15 16namespace { 17 18const char kErrorUnknown[] = "Unknown"; 19 20bool ConvertListValueToStringVector(const base::ListValue& string_list, 21 std::vector<std::string>* result) { 22 for (size_t i = 0; i < string_list.GetSize(); ++i) { 23 std::string str; 24 if (!string_list.GetString(i, &str)) 25 return false; 26 result->push_back(str); 27 } 28 return true; 29} 30 31bool IsCaCertNssSet(const base::DictionaryValue& properties) { 32 std::string ca_cert_nss; 33 if (properties.GetStringWithoutPathExpansion(shill::kEapCaCertNssProperty, 34 &ca_cert_nss) && 35 !ca_cert_nss.empty()) { 36 return true; 37 } 38 39 const base::DictionaryValue* provider = NULL; 40 properties.GetDictionaryWithoutPathExpansion(shill::kProviderProperty, 41 &provider); 42 if (!provider) 43 return false; 44 if (provider->GetStringWithoutPathExpansion( 45 shill::kL2tpIpsecCaCertNssProperty, &ca_cert_nss) && 46 !ca_cert_nss.empty()) { 47 return true; 48 } 49 if (provider->GetStringWithoutPathExpansion( 50 shill::kOpenVPNCaCertNSSProperty, &ca_cert_nss) && 51 !ca_cert_nss.empty()) { 52 return true; 53 } 54 55 return false; 56} 57 58} // namespace 59 60namespace chromeos { 61 62NetworkState::NetworkState(const std::string& path) 63 : ManagedState(MANAGED_TYPE_NETWORK, path), 64 visible_(false), 65 connectable_(false), 66 prefix_length_(0), 67 signal_strength_(0), 68 activate_over_non_cellular_networks_(false), 69 cellular_out_of_credits_(false), 70 has_ca_cert_nss_(false) { 71} 72 73NetworkState::~NetworkState() { 74} 75 76bool NetworkState::PropertyChanged(const std::string& key, 77 const base::Value& value) { 78 // Keep care that these properties are the same as in |GetProperties|. 79 if (ManagedStatePropertyChanged(key, value)) 80 return true; 81 if (key == shill::kSignalStrengthProperty) { 82 return GetIntegerValue(key, value, &signal_strength_); 83 } else if (key == shill::kStateProperty) { 84 return GetStringValue(key, value, &connection_state_); 85 } else if (key == shill::kVisibleProperty) { 86 return GetBooleanValue(key, value, &visible_); 87 } else if (key == shill::kConnectableProperty) { 88 return GetBooleanValue(key, value, &connectable_); 89 } else if (key == shill::kErrorProperty) { 90 if (!GetStringValue(key, value, &error_)) 91 return false; 92 if (ErrorIsValid(error_)) 93 last_error_ = error_; 94 else 95 error_.clear(); 96 return true; 97 } else if (key == shill::kActivationStateProperty) { 98 return GetStringValue(key, value, &activation_state_); 99 } else if (key == shill::kRoamingStateProperty) { 100 return GetStringValue(key, value, &roaming_); 101 } else if (key == shill::kSecurityProperty) { 102 return GetStringValue(key, value, &security_); 103 } else if (key == shill::kEapMethodProperty) { 104 return GetStringValue(key, value, &eap_method_); 105 } else if (key == shill::kNetworkTechnologyProperty) { 106 return GetStringValue(key, value, &network_technology_); 107 } else if (key == shill::kDeviceProperty) { 108 return GetStringValue(key, value, &device_path_); 109 } else if (key == shill::kGuidProperty) { 110 return GetStringValue(key, value, &guid_); 111 } else if (key == shill::kProfileProperty) { 112 return GetStringValue(key, value, &profile_path_); 113 } else if (key == shill::kActivateOverNonCellularNetworkProperty) { 114 return GetBooleanValue(key, value, &activate_over_non_cellular_networks_); 115 } else if (key == shill::kOutOfCreditsProperty) { 116 return GetBooleanValue(key, value, &cellular_out_of_credits_); 117 } else if (key == shill::kProxyConfigProperty) { 118 std::string proxy_config_str; 119 if (!value.GetAsString(&proxy_config_str)) { 120 NET_LOG_ERROR("Failed to parse " + key, path()); 121 return false; 122 } 123 124 proxy_config_.Clear(); 125 if (proxy_config_str.empty()) 126 return true; 127 128 scoped_ptr<base::DictionaryValue> proxy_config_dict( 129 onc::ReadDictionaryFromJson(proxy_config_str)); 130 if (proxy_config_dict) { 131 // Warning: The DictionaryValue returned from 132 // ReadDictionaryFromJson/JSONParser is an optimized derived class that 133 // doesn't allow releasing ownership of nested values. A Swap in the wrong 134 // order leads to memory access errors. 135 proxy_config_.MergeDictionary(proxy_config_dict.get()); 136 } else { 137 NET_LOG_ERROR("Failed to parse " + key, path()); 138 } 139 return true; 140 } 141 return false; 142} 143 144bool NetworkState::InitialPropertiesReceived( 145 const base::DictionaryValue& properties) { 146 NET_LOG_DEBUG("InitialPropertiesReceived", path()); 147 bool changed = false; 148 if (!properties.HasKey(shill::kTypeProperty)) { 149 NET_LOG_ERROR("NetworkState has no type", 150 shill_property_util::GetNetworkIdFromProperties(properties)); 151 return false; 152 } 153 // Ensure that the network has a valid name. 154 changed |= UpdateName(properties); 155 156 // Set the has_ca_cert_nss_ property. 157 bool had_ca_cert_nss = has_ca_cert_nss_; 158 has_ca_cert_nss_ = IsCaCertNssSet(properties); 159 changed |= had_ca_cert_nss != has_ca_cert_nss_; 160 161 // By convention, all visible WiFi networks have a SignalStrength > 0. 162 if (visible() && type() == shill::kTypeWifi) { 163 if (signal_strength_ <= 0) 164 signal_strength_ = 1; 165 } 166 167 return changed; 168} 169 170void NetworkState::GetStateProperties(base::DictionaryValue* dictionary) const { 171 ManagedState::GetStateProperties(dictionary); 172 173 // Properties shared by all types. 174 dictionary->SetStringWithoutPathExpansion(shill::kGuidProperty, guid()); 175 dictionary->SetStringWithoutPathExpansion(shill::kSecurityProperty, 176 security()); 177 178 if (visible()) { 179 if (!error().empty()) 180 dictionary->SetStringWithoutPathExpansion(shill::kErrorProperty, error()); 181 dictionary->SetStringWithoutPathExpansion(shill::kStateProperty, 182 connection_state()); 183 } 184 185 // Wireless properties 186 if (!NetworkTypePattern::Wireless().MatchesType(type())) 187 return; 188 189 if (visible()) { 190 dictionary->SetBooleanWithoutPathExpansion(shill::kConnectableProperty, 191 connectable()); 192 dictionary->SetIntegerWithoutPathExpansion(shill::kSignalStrengthProperty, 193 signal_strength()); 194 } 195 196 // Wifi properties 197 if (NetworkTypePattern::WiFi().MatchesType(type())) { 198 dictionary->SetStringWithoutPathExpansion(shill::kEapMethodProperty, 199 eap_method()); 200 } 201 202 // Mobile properties 203 if (NetworkTypePattern::Mobile().MatchesType(type())) { 204 dictionary->SetStringWithoutPathExpansion( 205 shill::kNetworkTechnologyProperty, 206 network_technology()); 207 dictionary->SetStringWithoutPathExpansion(shill::kActivationStateProperty, 208 activation_state()); 209 dictionary->SetStringWithoutPathExpansion(shill::kRoamingStateProperty, 210 roaming()); 211 dictionary->SetBooleanWithoutPathExpansion(shill::kOutOfCreditsProperty, 212 cellular_out_of_credits()); 213 } 214} 215 216void NetworkState::IPConfigPropertiesChanged( 217 const base::DictionaryValue& properties) { 218 for (base::DictionaryValue::Iterator iter(properties); 219 !iter.IsAtEnd(); iter.Advance()) { 220 std::string key = iter.key(); 221 const base::Value& value = iter.value(); 222 223 if (key == shill::kAddressProperty) { 224 GetStringValue(key, value, &ip_address_); 225 } else if (key == shill::kGatewayProperty) { 226 GetStringValue(key, value, &gateway_); 227 } else if (key == shill::kNameServersProperty) { 228 const base::ListValue* dns_servers; 229 if (value.GetAsList(&dns_servers)) { 230 dns_servers_.clear(); 231 ConvertListValueToStringVector(*dns_servers, &dns_servers_); 232 } 233 } else if (key == shill::kPrefixlenProperty) { 234 GetIntegerValue(key, value, &prefix_length_); 235 } else if (key == shill::kWebProxyAutoDiscoveryUrlProperty) { 236 std::string url_string; 237 if (GetStringValue(key, value, &url_string)) { 238 if (url_string.empty()) { 239 web_proxy_auto_discovery_url_ = GURL(); 240 } else { 241 GURL gurl(url_string); 242 if (gurl.is_valid()) { 243 web_proxy_auto_discovery_url_ = gurl; 244 } else { 245 NET_LOG_ERROR("Invalid WebProxyAutoDiscoveryUrl: " + url_string, 246 path()); 247 web_proxy_auto_discovery_url_ = GURL(); 248 } 249 } 250 } 251 } 252 } 253} 254 255bool NetworkState::RequiresActivation() const { 256 return (type() == shill::kTypeCellular && 257 activation_state() != shill::kActivationStateActivated && 258 activation_state() != shill::kActivationStateUnknown); 259} 260 261std::string NetworkState::connection_state() const { 262 if (!visible()) 263 return shill::kStateDisconnect; 264 return connection_state_; 265} 266 267bool NetworkState::IsConnectedState() const { 268 return visible() && StateIsConnected(connection_state_); 269} 270 271bool NetworkState::IsConnectingState() const { 272 return visible() && StateIsConnecting(connection_state_); 273} 274 275bool NetworkState::IsInProfile() const { 276 // kTypeEthernetEap is always saved. We need this check because it does 277 // not show up in the visible list, but its properties may not be available 278 // when it first shows up in ServiceCompleteList. See crbug.com/355117. 279 return !profile_path_.empty() || type() == shill::kTypeEthernetEap; 280} 281 282bool NetworkState::IsPrivate() const { 283 return !profile_path_.empty() && 284 profile_path_ != NetworkProfileHandler::GetSharedProfilePath(); 285} 286 287std::string NetworkState::GetDnsServersAsString() const { 288 std::string result; 289 for (size_t i = 0; i < dns_servers_.size(); ++i) { 290 if (i != 0) 291 result += ","; 292 result += dns_servers_[i]; 293 } 294 return result; 295} 296 297std::string NetworkState::GetNetmask() const { 298 return network_util::PrefixLengthToNetmask(prefix_length_); 299} 300 301std::string NetworkState::GetSpecifier() const { 302 if (!update_received()) { 303 NET_LOG_ERROR("GetSpecifier called before update", path()); 304 return std::string(); 305 } 306 if (type() == shill::kTypeWifi) 307 return name() + "_" + security_; 308 if (!name().empty()) 309 return name(); 310 return type(); // For unnamed networks such as ethernet. 311} 312 313void NetworkState::SetGuid(const std::string& guid) { 314 guid_ = guid; 315} 316 317bool NetworkState::UpdateName(const base::DictionaryValue& properties) { 318 std::string updated_name = 319 shill_property_util::GetNameFromProperties(path(), properties); 320 if (updated_name != name()) { 321 set_name(updated_name); 322 return true; 323 } 324 return false; 325} 326 327// static 328bool NetworkState::StateIsConnected(const std::string& connection_state) { 329 return (connection_state == shill::kStateReady || 330 connection_state == shill::kStateOnline || 331 connection_state == shill::kStatePortal); 332} 333 334// static 335bool NetworkState::StateIsConnecting(const std::string& connection_state) { 336 return (connection_state == shill::kStateAssociation || 337 connection_state == shill::kStateConfiguration || 338 connection_state == shill::kStateCarrier); 339} 340 341// static 342bool NetworkState::ErrorIsValid(const std::string& error) { 343 // Shill uses "Unknown" to indicate an unset or cleared error state. 344 return !error.empty() && error != kErrorUnknown; 345} 346 347} // namespace chromeos 348