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.
5 #include "chromeos/network/network_state.h"
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"
18 const char kErrorUnknown[] = "Unknown";
20 bool ConvertListValueToStringVector(const base::ListValue& string_list,
21 std::vector<std::string>* result) {
22 for (size_t i = 0; i < string_list.GetSize(); ++i) {
24 if (!string_list.GetString(i, &str))
26 result->push_back(str);
31 bool IsCaCertNssSet(const base::DictionaryValue& properties) {
32 std::string ca_cert_nss;
33 if (properties.GetStringWithoutPathExpansion(shill::kEapCaCertNssProperty,
35 !ca_cert_nss.empty()) {
39 const base::DictionaryValue* provider = NULL;
40 properties.GetDictionaryWithoutPathExpansion(shill::kProviderProperty,
44 if (provider->GetStringWithoutPathExpansion(
45 shill::kL2tpIpsecCaCertNssProperty, &ca_cert_nss) &&
46 !ca_cert_nss.empty()) {
49 if (provider->GetStringWithoutPathExpansion(
50 shill::kOpenVPNCaCertNSSProperty, &ca_cert_nss) &&
51 !ca_cert_nss.empty()) {
62 NetworkState::NetworkState(const std::string& path)
63 : ManagedState(MANAGED_TYPE_NETWORK, path),
68 cellular_out_of_credits_(false),
69 has_ca_cert_nss_(false) {
72 NetworkState::~NetworkState() {
75 bool NetworkState::PropertyChanged(const std::string& key,
76 const base::Value& value) {
77 // Keep care that these properties are the same as in |GetProperties|.
78 if (ManagedStatePropertyChanged(key, value))
80 if (key == shill::kSignalStrengthProperty) {
81 return GetIntegerValue(key, value, &signal_strength_);
82 } else if (key == shill::kStateProperty) {
83 return GetStringValue(key, value, &connection_state_);
84 } else if (key == shill::kVisibleProperty) {
85 return GetBooleanValue(key, value, &visible_);
86 } else if (key == shill::kConnectableProperty) {
87 return GetBooleanValue(key, value, &connectable_);
88 } else if (key == shill::kErrorProperty) {
89 if (!GetStringValue(key, value, &error_))
91 if (ErrorIsValid(error_))
96 } else if (key == shill::kActivationTypeProperty) {
97 return GetStringValue(key, value, &activation_type_);
98 } else if (key == shill::kActivationStateProperty) {
99 return GetStringValue(key, value, &activation_state_);
100 } else if (key == shill::kRoamingStateProperty) {
101 return GetStringValue(key, value, &roaming_);
102 } else if (key == shill::kSecurityProperty) {
103 return GetStringValue(key, value, &security_);
104 } else if (key == shill::kEapMethodProperty) {
105 return GetStringValue(key, value, &eap_method_);
106 } else if (key == shill::kNetworkTechnologyProperty) {
107 return GetStringValue(key, value, &network_technology_);
108 } else if (key == shill::kDeviceProperty) {
109 return GetStringValue(key, value, &device_path_);
110 } else if (key == shill::kGuidProperty) {
111 return GetStringValue(key, value, &guid_);
112 } else if (key == shill::kProfileProperty) {
113 return GetStringValue(key, value, &profile_path_);
114 } else if (key == shill::kOutOfCreditsProperty) {
115 return GetBooleanValue(key, value, &cellular_out_of_credits_);
116 } else if (key == shill::kProxyConfigProperty) {
117 std::string proxy_config_str;
118 if (!value.GetAsString(&proxy_config_str)) {
119 NET_LOG_ERROR("Failed to parse " + key, path());
123 proxy_config_.Clear();
124 if (proxy_config_str.empty())
127 scoped_ptr<base::DictionaryValue> proxy_config_dict(
128 onc::ReadDictionaryFromJson(proxy_config_str));
129 if (proxy_config_dict) {
130 // Warning: The DictionaryValue returned from
131 // ReadDictionaryFromJson/JSONParser is an optimized derived class that
132 // doesn't allow releasing ownership of nested values. A Swap in the wrong
133 // order leads to memory access errors.
134 proxy_config_.MergeDictionary(proxy_config_dict.get());
136 NET_LOG_ERROR("Failed to parse " + key, path());
143 bool NetworkState::InitialPropertiesReceived(
144 const base::DictionaryValue& properties) {
145 NET_LOG_DEBUG("InitialPropertiesReceived", path());
146 bool changed = false;
147 if (!properties.HasKey(shill::kTypeProperty)) {
148 NET_LOG_ERROR("NetworkState has no type",
149 shill_property_util::GetNetworkIdFromProperties(properties));
152 // Ensure that the network has a valid name.
153 changed |= UpdateName(properties);
155 // Set the has_ca_cert_nss_ property.
156 bool had_ca_cert_nss = has_ca_cert_nss_;
157 has_ca_cert_nss_ = IsCaCertNssSet(properties);
158 changed |= had_ca_cert_nss != has_ca_cert_nss_;
160 // By convention, all visible WiFi networks have a SignalStrength > 0.
161 if (visible() && type() == shill::kTypeWifi) {
162 if (signal_strength_ <= 0)
163 signal_strength_ = 1;
169 void NetworkState::GetStateProperties(base::DictionaryValue* dictionary) const {
170 ManagedState::GetStateProperties(dictionary);
172 // Properties shared by all types.
173 dictionary->SetStringWithoutPathExpansion(shill::kGuidProperty, guid());
174 dictionary->SetStringWithoutPathExpansion(shill::kSecurityProperty,
178 if (!error().empty())
179 dictionary->SetStringWithoutPathExpansion(shill::kErrorProperty, error());
180 dictionary->SetStringWithoutPathExpansion(shill::kStateProperty,
184 // Wireless properties
185 if (!NetworkTypePattern::Wireless().MatchesType(type()))
189 dictionary->SetBooleanWithoutPathExpansion(shill::kConnectableProperty,
191 dictionary->SetIntegerWithoutPathExpansion(shill::kSignalStrengthProperty,
196 if (NetworkTypePattern::WiFi().MatchesType(type())) {
197 dictionary->SetStringWithoutPathExpansion(shill::kEapMethodProperty,
202 if (NetworkTypePattern::Mobile().MatchesType(type())) {
203 dictionary->SetStringWithoutPathExpansion(
204 shill::kNetworkTechnologyProperty,
205 network_technology());
206 dictionary->SetStringWithoutPathExpansion(shill::kActivationStateProperty,
208 dictionary->SetStringWithoutPathExpansion(shill::kRoamingStateProperty,
210 dictionary->SetBooleanWithoutPathExpansion(shill::kOutOfCreditsProperty,
211 cellular_out_of_credits());
215 void NetworkState::IPConfigPropertiesChanged(
216 const base::DictionaryValue& properties) {
217 for (base::DictionaryValue::Iterator iter(properties);
218 !iter.IsAtEnd(); iter.Advance()) {
219 std::string key = iter.key();
220 const base::Value& value = iter.value();
222 if (key == shill::kAddressProperty) {
223 GetStringValue(key, value, &ip_address_);
224 } else if (key == shill::kGatewayProperty) {
225 GetStringValue(key, value, &gateway_);
226 } else if (key == shill::kNameServersProperty) {
227 const base::ListValue* dns_servers;
228 if (value.GetAsList(&dns_servers)) {
229 dns_servers_.clear();
230 ConvertListValueToStringVector(*dns_servers, &dns_servers_);
232 } else if (key == shill::kPrefixlenProperty) {
233 GetIntegerValue(key, value, &prefix_length_);
234 } else if (key == shill::kWebProxyAutoDiscoveryUrlProperty) {
235 std::string url_string;
236 if (GetStringValue(key, value, &url_string)) {
237 if (url_string.empty()) {
238 web_proxy_auto_discovery_url_ = GURL();
240 GURL gurl(url_string);
241 if (gurl.is_valid()) {
242 web_proxy_auto_discovery_url_ = gurl;
244 NET_LOG_ERROR("Invalid WebProxyAutoDiscoveryUrl: " + url_string,
246 web_proxy_auto_discovery_url_ = GURL();
254 bool NetworkState::RequiresActivation() const {
255 return (type() == shill::kTypeCellular &&
256 activation_state() != shill::kActivationStateActivated &&
257 activation_state() != shill::kActivationStateUnknown);
260 std::string NetworkState::connection_state() const {
262 return shill::kStateDisconnect;
263 return connection_state_;
266 bool NetworkState::IsConnectedState() const {
267 return visible() && StateIsConnected(connection_state_);
270 bool NetworkState::IsConnectingState() const {
271 return visible() && StateIsConnecting(connection_state_);
274 bool NetworkState::IsInProfile() const {
275 // kTypeEthernetEap is always saved. We need this check because it does
276 // not show up in the visible list, but its properties may not be available
277 // when it first shows up in ServiceCompleteList. See crbug.com/355117.
278 return !profile_path_.empty() || type() == shill::kTypeEthernetEap;
281 bool NetworkState::IsPrivate() const {
282 return !profile_path_.empty() &&
283 profile_path_ != NetworkProfileHandler::GetSharedProfilePath();
286 std::string NetworkState::GetDnsServersAsString() const {
288 for (size_t i = 0; i < dns_servers_.size(); ++i) {
291 result += dns_servers_[i];
296 std::string NetworkState::GetNetmask() const {
297 return network_util::PrefixLengthToNetmask(prefix_length_);
300 std::string NetworkState::GetSpecifier() const {
301 if (!update_received()) {
302 NET_LOG_ERROR("GetSpecifier called before update", path());
303 return std::string();
305 if (type() == shill::kTypeWifi)
306 return name() + "_" + security_;
309 return type(); // For unnamed networks such as ethernet.
312 void NetworkState::SetGuid(const std::string& guid) {
316 bool NetworkState::UpdateName(const base::DictionaryValue& properties) {
317 std::string updated_name =
318 shill_property_util::GetNameFromProperties(path(), properties);
319 if (updated_name != name()) {
320 set_name(updated_name);
327 bool NetworkState::StateIsConnected(const std::string& connection_state) {
328 return (connection_state == shill::kStateReady ||
329 connection_state == shill::kStateOnline ||
330 connection_state == shill::kStatePortal);
334 bool NetworkState::StateIsConnecting(const std::string& connection_state) {
335 return (connection_state == shill::kStateAssociation ||
336 connection_state == shill::kStateConfiguration ||
337 connection_state == shill::kStateCarrier);
341 bool NetworkState::ErrorIsValid(const std::string& error) {
342 // Shill uses "Unknown" to indicate an unset or cleared error state.
343 return !error.empty() && error != kErrorUnknown;
346 } // namespace chromeos