network_state.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
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_util.h" 11#include "chromeos/network/onc/onc_utils.h" 12#include "chromeos/network/shill_property_util.h" 13#include "third_party/cros_system_api/dbus/service_constants.h" 14 15namespace { 16 17const char kErrorUnknown[] = "Unknown"; 18 19bool ConvertListValueToStringVector(const base::ListValue& string_list, 20 std::vector<std::string>* result) { 21 for (size_t i = 0; i < string_list.GetSize(); ++i) { 22 std::string str; 23 if (!string_list.GetString(i, &str)) 24 return false; 25 result->push_back(str); 26 } 27 return true; 28} 29 30bool IsCaCertNssSet(const base::DictionaryValue& properties) { 31 std::string ca_cert_nss; 32 if (properties.GetStringWithoutPathExpansion(flimflam::kEapCaCertNssProperty, 33 &ca_cert_nss) && 34 !ca_cert_nss.empty()) { 35 return true; 36 } 37 38 const base::DictionaryValue* provider = NULL; 39 properties.GetDictionaryWithoutPathExpansion(flimflam::kProviderProperty, 40 &provider); 41 if (!provider) 42 return false; 43 if (provider->GetStringWithoutPathExpansion( 44 flimflam::kL2tpIpsecCaCertNssProperty, &ca_cert_nss) && 45 !ca_cert_nss.empty()) { 46 return true; 47 } 48 if (provider->GetStringWithoutPathExpansion( 49 flimflam::kOpenVPNCaCertNSSProperty, &ca_cert_nss) && 50 !ca_cert_nss.empty()) { 51 return true; 52 } 53 54 return false; 55} 56 57} // namespace 58 59namespace chromeos { 60 61NetworkState::NetworkState(const std::string& path) 62 : ManagedState(MANAGED_TYPE_NETWORK, path), 63 connectable_(false), 64 prefix_length_(0), 65 signal_strength_(0), 66 activate_over_non_cellular_networks_(false), 67 cellular_out_of_credits_(false), 68 has_ca_cert_nss_(false) { 69} 70 71NetworkState::~NetworkState() { 72} 73 74bool NetworkState::PropertyChanged(const std::string& key, 75 const base::Value& value) { 76 // Keep care that these properties are the same as in |GetProperties|. 77 if (ManagedStatePropertyChanged(key, value)) 78 return true; 79 if (key == flimflam::kSignalStrengthProperty) { 80 return GetIntegerValue(key, value, &signal_strength_); 81 } else if (key == flimflam::kStateProperty) { 82 return GetStringValue(key, value, &connection_state_); 83 } else if (key == flimflam::kConnectableProperty) { 84 return GetBooleanValue(key, value, &connectable_); 85 } else if (key == flimflam::kErrorProperty) { 86 if (!GetStringValue(key, value, &error_)) 87 return false; 88 // Shill uses "Unknown" to indicate an unset error state. 89 if (error_ == kErrorUnknown) 90 error_.clear(); 91 return true; 92 } else if (key == IPConfigProperty(flimflam::kAddressProperty)) { 93 return GetStringValue(key, value, &ip_address_); 94 } else if (key == IPConfigProperty(flimflam::kGatewayProperty)) { 95 return GetStringValue(key, value, &gateway_); 96 } else if (key == IPConfigProperty(flimflam::kNameServersProperty)) { 97 const base::ListValue* dns_servers; 98 if (!value.GetAsList(&dns_servers)) 99 return false; 100 dns_servers_.clear(); 101 ConvertListValueToStringVector(*dns_servers, &dns_servers_); 102 return true; 103 } else if (key == IPConfigProperty(flimflam::kPrefixlenProperty)) { 104 return GetIntegerValue(key, value, &prefix_length_); 105 } else if (key == IPConfigProperty( 106 shill::kWebProxyAutoDiscoveryUrlProperty)) { 107 std::string url_string; 108 if (!GetStringValue(key, value, &url_string)) 109 return false; 110 if (url_string.empty()) { 111 web_proxy_auto_discovery_url_ = GURL(); 112 } else { 113 GURL gurl(url_string); 114 if (!gurl.is_valid()) { 115 web_proxy_auto_discovery_url_ = gurl; 116 } else { 117 NET_LOG_ERROR("Invalid WebProxyAutoDiscoveryUrl: " + url_string, 118 path()); 119 web_proxy_auto_discovery_url_ = GURL(); 120 } 121 } 122 return true; 123 } else if (key == flimflam::kActivationStateProperty) { 124 return GetStringValue(key, value, &activation_state_); 125 } else if (key == flimflam::kRoamingStateProperty) { 126 return GetStringValue(key, value, &roaming_); 127 } else if (key == flimflam::kSecurityProperty) { 128 return GetStringValue(key, value, &security_); 129 } else if (key == flimflam::kProxyConfigProperty) { 130 std::string proxy_config_str; 131 if (!value.GetAsString(&proxy_config_str)) { 132 NET_LOG_ERROR("Failed to parse " + key, path()); 133 return false; 134 } 135 136 proxy_config_.Clear(); 137 if (proxy_config_str.empty()) 138 return true; 139 140 scoped_ptr<base::DictionaryValue> proxy_config_dict( 141 onc::ReadDictionaryFromJson(proxy_config_str)); 142 if (proxy_config_dict) { 143 // Warning: The DictionaryValue returned from 144 // ReadDictionaryFromJson/JSONParser is an optimized derived class that 145 // doesn't allow releasing ownership of nested values. A Swap in the wrong 146 // order leads to memory access errors. 147 proxy_config_.MergeDictionary(proxy_config_dict.get()); 148 } else { 149 NET_LOG_ERROR("Failed to parse " + key, path()); 150 } 151 return true; 152 } else if (key == flimflam::kUIDataProperty) { 153 scoped_ptr<NetworkUIData> new_ui_data = 154 shill_property_util::GetUIDataFromValue(value); 155 if (!new_ui_data) { 156 NET_LOG_ERROR("Failed to parse " + key, path()); 157 return false; 158 } 159 ui_data_ = *new_ui_data; 160 return true; 161 } else if (key == flimflam::kNetworkTechnologyProperty) { 162 return GetStringValue(key, value, &network_technology_); 163 } else if (key == flimflam::kDeviceProperty) { 164 return GetStringValue(key, value, &device_path_); 165 } else if (key == flimflam::kGuidProperty) { 166 return GetStringValue(key, value, &guid_); 167 } else if (key == flimflam::kProfileProperty) { 168 return GetStringValue(key, value, &profile_path_); 169 } else if (key == shill::kActivateOverNonCellularNetworkProperty) { 170 return GetBooleanValue(key, value, &activate_over_non_cellular_networks_); 171 } else if (key == shill::kOutOfCreditsProperty) { 172 return GetBooleanValue(key, value, &cellular_out_of_credits_); 173 } 174 return false; 175} 176 177bool NetworkState::InitialPropertiesReceived( 178 const base::DictionaryValue& properties) { 179 NET_LOG_DEBUG("InitialPropertiesReceived", path()); 180 bool changed = UpdateName(properties); 181 bool had_ca_cert_nss = has_ca_cert_nss_; 182 has_ca_cert_nss_ = IsCaCertNssSet(properties); 183 changed |= had_ca_cert_nss != has_ca_cert_nss_; 184 return changed; 185} 186 187void NetworkState::GetProperties(base::DictionaryValue* dictionary) const { 188 // Keep care that these properties are the same as in |PropertyChanged|. 189 dictionary->SetStringWithoutPathExpansion(flimflam::kNameProperty, name()); 190 dictionary->SetStringWithoutPathExpansion(flimflam::kTypeProperty, type()); 191 dictionary->SetIntegerWithoutPathExpansion(flimflam::kSignalStrengthProperty, 192 signal_strength_); 193 dictionary->SetStringWithoutPathExpansion(flimflam::kStateProperty, 194 connection_state_); 195 dictionary->SetBooleanWithoutPathExpansion(flimflam::kConnectableProperty, 196 connectable_); 197 198 dictionary->SetStringWithoutPathExpansion(flimflam::kErrorProperty, 199 error_); 200 201 // IPConfig properties 202 base::DictionaryValue* ipconfig_properties = new base::DictionaryValue; 203 ipconfig_properties->SetStringWithoutPathExpansion(flimflam::kAddressProperty, 204 ip_address_); 205 ipconfig_properties->SetStringWithoutPathExpansion(flimflam::kGatewayProperty, 206 gateway_); 207 base::ListValue* name_servers = new base::ListValue; 208 name_servers->AppendStrings(dns_servers_); 209 ipconfig_properties->SetWithoutPathExpansion(flimflam::kNameServersProperty, 210 name_servers); 211 ipconfig_properties->SetStringWithoutPathExpansion( 212 shill::kWebProxyAutoDiscoveryUrlProperty, 213 web_proxy_auto_discovery_url_.spec()); 214 dictionary->SetWithoutPathExpansion(shill::kIPConfigProperty, 215 ipconfig_properties); 216 217 dictionary->SetStringWithoutPathExpansion(flimflam::kActivationStateProperty, 218 activation_state_); 219 dictionary->SetStringWithoutPathExpansion(flimflam::kRoamingStateProperty, 220 roaming_); 221 dictionary->SetStringWithoutPathExpansion(flimflam::kSecurityProperty, 222 security_); 223 // Proxy config and ONC source are intentionally omitted: These properties are 224 // placed in NetworkState to transition ProxyConfigServiceImpl from 225 // NetworkLibrary to the new network stack. The networking extension API 226 // shouldn't depend on this member. Once ManagedNetworkConfigurationHandler 227 // is used instead of NetworkLibrary, we can remove them again. 228 dictionary->SetStringWithoutPathExpansion( 229 flimflam::kNetworkTechnologyProperty, 230 network_technology_); 231 dictionary->SetStringWithoutPathExpansion(flimflam::kDeviceProperty, 232 device_path_); 233 dictionary->SetStringWithoutPathExpansion(flimflam::kGuidProperty, guid_); 234 dictionary->SetStringWithoutPathExpansion(flimflam::kProfileProperty, 235 profile_path_); 236 dictionary->SetBooleanWithoutPathExpansion( 237 shill::kActivateOverNonCellularNetworkProperty, 238 activate_over_non_cellular_networks_); 239 dictionary->SetBooleanWithoutPathExpansion(shill::kOutOfCreditsProperty, 240 cellular_out_of_credits_); 241} 242 243bool NetworkState::RequiresActivation() const { 244 return (type() == flimflam::kTypeCellular && 245 activation_state() != flimflam::kActivationStateActivated && 246 activation_state() != flimflam::kActivationStateUnknown); 247} 248 249bool NetworkState::IsConnectedState() const { 250 return StateIsConnected(connection_state_); 251} 252 253bool NetworkState::IsConnectingState() const { 254 return StateIsConnecting(connection_state_); 255} 256 257bool NetworkState::IsManaged() const { 258 return ui_data_.onc_source() == onc::ONC_SOURCE_DEVICE_POLICY || 259 ui_data_.onc_source() == onc::ONC_SOURCE_USER_POLICY; 260} 261 262bool NetworkState::IsPrivate() const { 263 return !profile_path_.empty() && 264 profile_path_ != NetworkProfileHandler::kSharedProfilePath; 265} 266 267std::string NetworkState::GetDnsServersAsString() const { 268 std::string result; 269 for (size_t i = 0; i < dns_servers_.size(); ++i) { 270 if (i != 0) 271 result += ","; 272 result += dns_servers_[i]; 273 } 274 return result; 275} 276 277std::string NetworkState::GetNetmask() const { 278 return network_util::PrefixLengthToNetmask(prefix_length_); 279} 280 281bool NetworkState::UpdateName(const base::DictionaryValue& properties) { 282 std::string updated_name = 283 shill_property_util::GetNameFromProperties(path(), properties); 284 if (updated_name != name()) { 285 set_name(updated_name); 286 return true; 287 } 288 return false; 289} 290 291// static 292bool NetworkState::StateIsConnected(const std::string& connection_state) { 293 return (connection_state == flimflam::kStateReady || 294 connection_state == flimflam::kStateOnline || 295 connection_state == flimflam::kStatePortal); 296} 297 298// static 299bool NetworkState::StateIsConnecting(const std::string& connection_state) { 300 return (connection_state == flimflam::kStateAssociation || 301 connection_state == flimflam::kStateConfiguration || 302 connection_state == flimflam::kStateCarrier); 303} 304 305// static 306std::string NetworkState::IPConfigProperty(const char* key) { 307 return base::StringPrintf("%s.%s", shill::kIPConfigProperty, key); 308} 309 310} // namespace chromeos 311