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::kPaymentPortalProperty
) {
103 const base::DictionaryValue
* olp
;
104 if (!value
.GetAsDictionary(&olp
))
106 return olp
->GetStringWithoutPathExpansion(shill::kPaymentPortalURL
,
108 } else if (key
== shill::kSecurityProperty
) {
109 return GetStringValue(key
, value
, &security_
);
110 } else if (key
== shill::kEapMethodProperty
) {
111 return GetStringValue(key
, value
, &eap_method_
);
112 } else if (key
== shill::kNetworkTechnologyProperty
) {
113 return GetStringValue(key
, value
, &network_technology_
);
114 } else if (key
== shill::kDeviceProperty
) {
115 return GetStringValue(key
, value
, &device_path_
);
116 } else if (key
== shill::kGuidProperty
) {
117 return GetStringValue(key
, value
, &guid_
);
118 } else if (key
== shill::kProfileProperty
) {
119 return GetStringValue(key
, value
, &profile_path_
);
120 } else if (key
== shill::kOutOfCreditsProperty
) {
121 return GetBooleanValue(key
, value
, &cellular_out_of_credits_
);
122 } else if (key
== shill::kProxyConfigProperty
) {
123 std::string proxy_config_str
;
124 if (!value
.GetAsString(&proxy_config_str
)) {
125 NET_LOG_ERROR("Failed to parse " + key
, path());
129 proxy_config_
.Clear();
130 if (proxy_config_str
.empty())
133 scoped_ptr
<base::DictionaryValue
> proxy_config_dict(
134 onc::ReadDictionaryFromJson(proxy_config_str
));
135 if (proxy_config_dict
) {
136 // Warning: The DictionaryValue returned from
137 // ReadDictionaryFromJson/JSONParser is an optimized derived class that
138 // doesn't allow releasing ownership of nested values. A Swap in the wrong
139 // order leads to memory access errors.
140 proxy_config_
.MergeDictionary(proxy_config_dict
.get());
142 NET_LOG_ERROR("Failed to parse " + key
, path());
149 bool NetworkState::InitialPropertiesReceived(
150 const base::DictionaryValue
& properties
) {
151 NET_LOG_DEBUG("InitialPropertiesReceived", path());
152 bool changed
= false;
153 if (!properties
.HasKey(shill::kTypeProperty
)) {
154 NET_LOG_ERROR("NetworkState has no type",
155 shill_property_util::GetNetworkIdFromProperties(properties
));
158 // Ensure that the network has a valid name.
159 changed
|= UpdateName(properties
);
161 // Set the has_ca_cert_nss_ property.
162 bool had_ca_cert_nss
= has_ca_cert_nss_
;
163 has_ca_cert_nss_
= IsCaCertNssSet(properties
);
164 changed
|= had_ca_cert_nss
!= has_ca_cert_nss_
;
166 // By convention, all visible WiFi and WiMAX networks have a
167 // SignalStrength > 0.
168 if ((type() == shill::kTypeWifi
|| type() == shill::kTypeWimax
) &&
169 visible() && signal_strength_
<= 0) {
170 signal_strength_
= 1;
176 void NetworkState::GetStateProperties(base::DictionaryValue
* dictionary
) const {
177 ManagedState::GetStateProperties(dictionary
);
179 // Properties shared by all types.
180 dictionary
->SetStringWithoutPathExpansion(shill::kGuidProperty
, guid());
181 dictionary
->SetStringWithoutPathExpansion(shill::kSecurityProperty
,
185 if (!error().empty())
186 dictionary
->SetStringWithoutPathExpansion(shill::kErrorProperty
, error());
187 dictionary
->SetStringWithoutPathExpansion(shill::kStateProperty
,
191 // Wireless properties
192 if (!NetworkTypePattern::Wireless().MatchesType(type()))
196 dictionary
->SetBooleanWithoutPathExpansion(shill::kConnectableProperty
,
198 dictionary
->SetIntegerWithoutPathExpansion(shill::kSignalStrengthProperty
,
203 if (NetworkTypePattern::WiFi().MatchesType(type())) {
204 dictionary
->SetStringWithoutPathExpansion(shill::kEapMethodProperty
,
209 if (NetworkTypePattern::Mobile().MatchesType(type())) {
210 dictionary
->SetStringWithoutPathExpansion(
211 shill::kNetworkTechnologyProperty
,
212 network_technology());
213 dictionary
->SetStringWithoutPathExpansion(shill::kActivationStateProperty
,
215 dictionary
->SetStringWithoutPathExpansion(shill::kRoamingStateProperty
,
217 dictionary
->SetBooleanWithoutPathExpansion(shill::kOutOfCreditsProperty
,
218 cellular_out_of_credits());
222 void NetworkState::IPConfigPropertiesChanged(
223 const base::DictionaryValue
& properties
) {
224 for (base::DictionaryValue::Iterator
iter(properties
);
225 !iter
.IsAtEnd(); iter
.Advance()) {
226 std::string key
= iter
.key();
227 const base::Value
& value
= iter
.value();
229 if (key
== shill::kAddressProperty
) {
230 GetStringValue(key
, value
, &ip_address_
);
231 } else if (key
== shill::kGatewayProperty
) {
232 GetStringValue(key
, value
, &gateway_
);
233 } else if (key
== shill::kNameServersProperty
) {
234 const base::ListValue
* dns_servers
;
235 if (value
.GetAsList(&dns_servers
)) {
236 dns_servers_
.clear();
237 ConvertListValueToStringVector(*dns_servers
, &dns_servers_
);
239 } else if (key
== shill::kPrefixlenProperty
) {
240 GetIntegerValue(key
, value
, &prefix_length_
);
241 } else if (key
== shill::kWebProxyAutoDiscoveryUrlProperty
) {
242 std::string url_string
;
243 if (GetStringValue(key
, value
, &url_string
)) {
244 if (url_string
.empty()) {
245 web_proxy_auto_discovery_url_
= GURL();
247 GURL
gurl(url_string
);
248 if (gurl
.is_valid()) {
249 web_proxy_auto_discovery_url_
= gurl
;
251 NET_LOG_ERROR("Invalid WebProxyAutoDiscoveryUrl: " + url_string
,
253 web_proxy_auto_discovery_url_
= GURL();
261 bool NetworkState::RequiresActivation() const {
262 return (type() == shill::kTypeCellular
&&
263 activation_state() != shill::kActivationStateActivated
&&
264 activation_state() != shill::kActivationStateUnknown
);
267 std::string
NetworkState::connection_state() const {
269 return shill::kStateDisconnect
;
270 return connection_state_
;
273 bool NetworkState::IsConnectedState() const {
274 return visible() && StateIsConnected(connection_state_
);
277 bool NetworkState::IsConnectingState() const {
278 return visible() && StateIsConnecting(connection_state_
);
281 bool NetworkState::IsInProfile() const {
282 // kTypeEthernetEap is always saved. We need this check because it does
283 // not show up in the visible list, but its properties may not be available
284 // when it first shows up in ServiceCompleteList. See crbug.com/355117.
285 return !profile_path_
.empty() || type() == shill::kTypeEthernetEap
;
288 bool NetworkState::IsPrivate() const {
289 return !profile_path_
.empty() &&
290 profile_path_
!= NetworkProfileHandler::GetSharedProfilePath();
293 std::string
NetworkState::GetDnsServersAsString() const {
295 for (size_t i
= 0; i
< dns_servers_
.size(); ++i
) {
298 result
+= dns_servers_
[i
];
303 std::string
NetworkState::GetNetmask() const {
304 return network_util::PrefixLengthToNetmask(prefix_length_
);
307 std::string
NetworkState::GetSpecifier() const {
308 if (!update_received()) {
309 NET_LOG_ERROR("GetSpecifier called before update", path());
310 return std::string();
312 if (type() == shill::kTypeWifi
)
313 return name() + "_" + security_
;
316 return type(); // For unnamed networks such as ethernet.
319 void NetworkState::SetGuid(const std::string
& guid
) {
323 bool NetworkState::UpdateName(const base::DictionaryValue
& properties
) {
324 std::string updated_name
=
325 shill_property_util::GetNameFromProperties(path(), properties
);
326 if (updated_name
!= name()) {
327 set_name(updated_name
);
334 bool NetworkState::StateIsConnected(const std::string
& connection_state
) {
335 return (connection_state
== shill::kStateReady
||
336 connection_state
== shill::kStateOnline
||
337 connection_state
== shill::kStatePortal
);
341 bool NetworkState::StateIsConnecting(const std::string
& connection_state
) {
342 return (connection_state
== shill::kStateAssociation
||
343 connection_state
== shill::kStateConfiguration
||
344 connection_state
== shill::kStateCarrier
);
348 bool NetworkState::ErrorIsValid(const std::string
& error
) {
349 // Shill uses "Unknown" to indicate an unset or cleared error state.
350 return !error
.empty() && error
!= kErrorUnknown
;
353 } // namespace chromeos