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 "base/values.h" 9 #include "chromeos/network/network_event_log.h" 10 #include "chromeos/network/network_profile_handler.h" 11 #include "chromeos/network/network_util.h" 12 #include "chromeos/network/shill_property_util.h" 13 #include "third_party/cros_system_api/dbus/service_constants.h" 14 15 namespace { 16 17 const char kErrorUnknown[] = "Unknown"; 18 19 bool 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 30 bool IsCaCertNssSet(const base::DictionaryValue& properties) { 31 std::string ca_cert_nss; 32 if (properties.GetStringWithoutPathExpansion(shill::kEapCaCertNssProperty, 33 &ca_cert_nss) && 34 !ca_cert_nss.empty()) { 35 return true; 36 } 37 38 const base::DictionaryValue* provider = NULL; 39 properties.GetDictionaryWithoutPathExpansion(shill::kProviderProperty, 40 &provider); 41 if (!provider) 42 return false; 43 if (provider->GetStringWithoutPathExpansion( 44 shill::kL2tpIpsecCaCertNssProperty, &ca_cert_nss) && 45 !ca_cert_nss.empty()) { 46 return true; 47 } 48 if (provider->GetStringWithoutPathExpansion( 49 shill::kOpenVPNCaCertNSSProperty, &ca_cert_nss) && 50 !ca_cert_nss.empty()) { 51 return true; 52 } 53 54 return false; 55 } 56 57 } // namespace 58 59 namespace chromeos { 60 61 NetworkState::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 71 NetworkState::~NetworkState() { 72 } 73 74 bool 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 == shill::kSignalStrengthProperty) { 80 return GetIntegerValue(key, value, &signal_strength_); 81 } else if (key == shill::kStateProperty) { 82 return GetStringValue(key, value, &connection_state_); 83 } else if (key == shill::kConnectableProperty) { 84 return GetBooleanValue(key, value, &connectable_); 85 } else if (key == shill::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(shill::kAddressProperty)) { 93 return GetStringValue(key, value, &ip_address_); 94 } else if (key == IPConfigProperty(shill::kGatewayProperty)) { 95 return GetStringValue(key, value, &gateway_); 96 } else if (key == IPConfigProperty(shill::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(shill::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 == shill::kActivationStateProperty) { 124 return GetStringValue(key, value, &activation_state_); 125 } else if (key == shill::kRoamingStateProperty) { 126 return GetStringValue(key, value, &roaming_); 127 } else if (key == shill::kSecurityProperty) { 128 return GetStringValue(key, value, &security_); 129 } else if (key == shill::kEapMethodProperty) { 130 return GetStringValue(key, value, &eap_method_); 131 } else if (key == shill::kUIDataProperty) { 132 scoped_ptr<NetworkUIData> new_ui_data = 133 shill_property_util::GetUIDataFromValue(value); 134 if (!new_ui_data) { 135 NET_LOG_ERROR("Failed to parse " + key, path()); 136 return false; 137 } 138 ui_data_ = *new_ui_data; 139 return true; 140 } else if (key == shill::kNetworkTechnologyProperty) { 141 return GetStringValue(key, value, &network_technology_); 142 } else if (key == shill::kDeviceProperty) { 143 return GetStringValue(key, value, &device_path_); 144 } else if (key == shill::kGuidProperty) { 145 return GetStringValue(key, value, &guid_); 146 } else if (key == shill::kProfileProperty) { 147 return GetStringValue(key, value, &profile_path_); 148 } else if (key == shill::kActivateOverNonCellularNetworkProperty) { 149 return GetBooleanValue(key, value, &activate_over_non_cellular_networks_); 150 } else if (key == shill::kOutOfCreditsProperty) { 151 return GetBooleanValue(key, value, &cellular_out_of_credits_); 152 } 153 return false; 154 } 155 156 bool NetworkState::InitialPropertiesReceived( 157 const base::DictionaryValue& properties) { 158 NET_LOG_DEBUG("InitialPropertiesReceived", path()); 159 bool changed = UpdateName(properties); 160 bool had_ca_cert_nss = has_ca_cert_nss_; 161 has_ca_cert_nss_ = IsCaCertNssSet(properties); 162 changed |= had_ca_cert_nss != has_ca_cert_nss_; 163 return changed; 164 } 165 166 void NetworkState::GetProperties(base::DictionaryValue* dictionary) const { 167 // Keep care that these properties are the same as in |PropertyChanged|. 168 dictionary->SetStringWithoutPathExpansion(shill::kNameProperty, name()); 169 dictionary->SetStringWithoutPathExpansion(shill::kTypeProperty, type()); 170 dictionary->SetIntegerWithoutPathExpansion(shill::kSignalStrengthProperty, 171 signal_strength_); 172 dictionary->SetStringWithoutPathExpansion(shill::kStateProperty, 173 connection_state_); 174 dictionary->SetBooleanWithoutPathExpansion(shill::kConnectableProperty, 175 connectable_); 176 177 dictionary->SetStringWithoutPathExpansion(shill::kErrorProperty, error_); 178 179 // IPConfig properties 180 base::DictionaryValue* ipconfig_properties = new base::DictionaryValue; 181 ipconfig_properties->SetStringWithoutPathExpansion(shill::kAddressProperty, 182 ip_address_); 183 ipconfig_properties->SetStringWithoutPathExpansion(shill::kGatewayProperty, 184 gateway_); 185 base::ListValue* name_servers = new base::ListValue; 186 name_servers->AppendStrings(dns_servers_); 187 ipconfig_properties->SetWithoutPathExpansion(shill::kNameServersProperty, 188 name_servers); 189 ipconfig_properties->SetStringWithoutPathExpansion( 190 shill::kWebProxyAutoDiscoveryUrlProperty, 191 web_proxy_auto_discovery_url_.spec()); 192 dictionary->SetWithoutPathExpansion(shill::kIPConfigProperty, 193 ipconfig_properties); 194 195 dictionary->SetStringWithoutPathExpansion(shill::kActivationStateProperty, 196 activation_state_); 197 dictionary->SetStringWithoutPathExpansion(shill::kRoamingStateProperty, 198 roaming_); 199 dictionary->SetStringWithoutPathExpansion(shill::kSecurityProperty, 200 security_); 201 dictionary->SetStringWithoutPathExpansion(shill::kEapMethodProperty, 202 eap_method_); 203 // Proxy config and ONC source are intentionally omitted: These properties are 204 // placed in NetworkState to transition ProxyConfigServiceImpl from 205 // NetworkLibrary to the new network stack. The networking extension API 206 // shouldn't depend on this member. Once ManagedNetworkConfigurationHandler 207 // is used instead of NetworkLibrary, we can remove them again. 208 dictionary->SetStringWithoutPathExpansion( 209 shill::kNetworkTechnologyProperty, 210 network_technology_); 211 dictionary->SetStringWithoutPathExpansion(shill::kDeviceProperty, 212 device_path_); 213 dictionary->SetStringWithoutPathExpansion(shill::kGuidProperty, guid_); 214 dictionary->SetStringWithoutPathExpansion(shill::kProfileProperty, 215 profile_path_); 216 dictionary->SetBooleanWithoutPathExpansion( 217 shill::kActivateOverNonCellularNetworkProperty, 218 activate_over_non_cellular_networks_); 219 dictionary->SetBooleanWithoutPathExpansion(shill::kOutOfCreditsProperty, 220 cellular_out_of_credits_); 221 } 222 223 bool NetworkState::RequiresActivation() const { 224 return (type() == shill::kTypeCellular && 225 activation_state() != shill::kActivationStateActivated && 226 activation_state() != shill::kActivationStateUnknown); 227 } 228 229 bool NetworkState::IsConnectedState() const { 230 return StateIsConnected(connection_state_); 231 } 232 233 bool NetworkState::IsConnectingState() const { 234 return StateIsConnecting(connection_state_); 235 } 236 237 bool NetworkState::IsPrivate() const { 238 return !profile_path_.empty() && 239 profile_path_ != NetworkProfileHandler::kSharedProfilePath; 240 } 241 242 std::string NetworkState::GetDnsServersAsString() const { 243 std::string result; 244 for (size_t i = 0; i < dns_servers_.size(); ++i) { 245 if (i != 0) 246 result += ","; 247 result += dns_servers_[i]; 248 } 249 return result; 250 } 251 252 std::string NetworkState::GetNetmask() const { 253 return network_util::PrefixLengthToNetmask(prefix_length_); 254 } 255 256 bool NetworkState::UpdateName(const base::DictionaryValue& properties) { 257 std::string updated_name = 258 shill_property_util::GetNameFromProperties(path(), properties); 259 if (updated_name != name()) { 260 set_name(updated_name); 261 return true; 262 } 263 return false; 264 } 265 266 // static 267 bool NetworkState::StateIsConnected(const std::string& connection_state) { 268 return (connection_state == shill::kStateReady || 269 connection_state == shill::kStateOnline || 270 connection_state == shill::kStatePortal); 271 } 272 273 // static 274 bool NetworkState::StateIsConnecting(const std::string& connection_state) { 275 return (connection_state == shill::kStateAssociation || 276 connection_state == shill::kStateConfiguration || 277 connection_state == shill::kStateCarrier); 278 } 279 280 // static 281 std::string NetworkState::IPConfigProperty(const char* key) { 282 return base::StringPrintf("%s.%s", shill::kIPConfigProperty, key); 283 } 284 285 } // namespace chromeos 286