[Session restore] Rename group name Enabled to Restore.
[chromium-blink-merge.git] / chromeos / network / network_state.cc
blobf4ad9599cfa98a0dbaf20eaffe4ca1304873c6e4
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/memory/scoped_ptr.h"
8 #include "base/stl_util.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/stringprintf.h"
11 #include "chromeos/network/network_profile_handler.h"
12 #include "chromeos/network/network_type_pattern.h"
13 #include "chromeos/network/network_util.h"
14 #include "chromeos/network/onc/onc_utils.h"
15 #include "chromeos/network/shill_property_util.h"
16 #include "components/device_event_log/device_event_log.h"
17 #include "third_party/cros_system_api/dbus/service_constants.h"
19 namespace {
21 const char kErrorUnknown[] = "Unknown";
23 bool ConvertListValueToStringVector(const base::ListValue& string_list,
24 std::vector<std::string>* result) {
25 for (size_t i = 0; i < string_list.GetSize(); ++i) {
26 std::string str;
27 if (!string_list.GetString(i, &str))
28 return false;
29 result->push_back(str);
31 return true;
34 bool IsCaptivePortalState(const base::DictionaryValue& properties, bool log) {
35 std::string state;
36 properties.GetStringWithoutPathExpansion(shill::kStateProperty, &state);
37 if (state != shill::kStatePortal)
38 return false;
39 std::string portal_detection_phase, portal_detection_status;
40 if (!properties.GetStringWithoutPathExpansion(
41 shill::kPortalDetectionFailedPhaseProperty,
42 &portal_detection_phase) ||
43 !properties.GetStringWithoutPathExpansion(
44 shill::kPortalDetectionFailedStatusProperty,
45 &portal_detection_status)) {
46 // If Shill (or a stub) has not set PortalDetectionFailedStatus
47 // or PortalDetectionFailedPhase, assume we are in captive portal state.
48 return true;
51 // Shill reports the phase in which it determined that the device is behind a
52 // captive portal. We only want to rely only on incorrect content being
53 // returned and ignore other reasons.
54 bool is_captive_portal =
55 portal_detection_phase == shill::kPortalDetectionPhaseContent &&
56 portal_detection_status == shill::kPortalDetectionStatusFailure;
58 if (log) {
59 std::string name;
60 properties.GetStringWithoutPathExpansion(shill::kNameProperty, &name);
61 if (name.empty())
62 properties.GetStringWithoutPathExpansion(shill::kSSIDProperty, &name);
63 if (!is_captive_portal) {
64 NET_LOG(EVENT) << "State is 'portal' but not in captive portal state:"
65 << " name=" << name << " phase=" << portal_detection_phase
66 << " status=" << portal_detection_status;
67 } else {
68 NET_LOG(EVENT) << "Network is in captive portal state: " << name;
72 return is_captive_portal;
75 } // namespace
77 namespace chromeos {
79 NetworkState::NetworkState(const std::string& path)
80 : ManagedState(MANAGED_TYPE_NETWORK, path),
81 visible_(false),
82 prefix_length_(0),
83 connectable_(false),
84 is_captive_portal_(false),
85 signal_strength_(0),
86 cellular_out_of_credits_(false) {
89 NetworkState::~NetworkState() {
92 bool NetworkState::PropertyChanged(const std::string& key,
93 const base::Value& value) {
94 // Keep care that these properties are the same as in |GetProperties|.
95 if (ManagedStatePropertyChanged(key, value))
96 return true;
97 if (key == shill::kSignalStrengthProperty) {
98 return GetIntegerValue(key, value, &signal_strength_);
99 } else if (key == shill::kStateProperty) {
100 return GetStringValue(key, value, &connection_state_);
101 } else if (key == shill::kVisibleProperty) {
102 return GetBooleanValue(key, value, &visible_);
103 } else if (key == shill::kConnectableProperty) {
104 return GetBooleanValue(key, value, &connectable_);
105 } else if (key == shill::kErrorProperty) {
106 if (!GetStringValue(key, value, &error_))
107 return false;
108 if (ErrorIsValid(error_))
109 last_error_ = error_;
110 else
111 error_.clear();
112 return true;
113 } else if (key == shill::kActivationTypeProperty) {
114 return GetStringValue(key, value, &activation_type_);
115 } else if (key == shill::kActivationStateProperty) {
116 return GetStringValue(key, value, &activation_state_);
117 } else if (key == shill::kRoamingStateProperty) {
118 return GetStringValue(key, value, &roaming_);
119 } else if (key == shill::kPaymentPortalProperty) {
120 const base::DictionaryValue* olp;
121 if (!value.GetAsDictionary(&olp))
122 return false;
123 return olp->GetStringWithoutPathExpansion(shill::kPaymentPortalURL,
124 &payment_url_);
125 } else if (key == shill::kSecurityClassProperty) {
126 return GetStringValue(key, value, &security_class_);
127 } else if (key == shill::kEapMethodProperty) {
128 return GetStringValue(key, value, &eap_method_);
129 } else if (key == shill::kNetworkTechnologyProperty) {
130 return GetStringValue(key, value, &network_technology_);
131 } else if (key == shill::kDeviceProperty) {
132 return GetStringValue(key, value, &device_path_);
133 } else if (key == shill::kGuidProperty) {
134 return GetStringValue(key, value, &guid_);
135 } else if (key == shill::kProfileProperty) {
136 return GetStringValue(key, value, &profile_path_);
137 } else if (key == shill::kWifiHexSsid) {
138 std::string ssid_hex;
139 if (!GetStringValue(key, value, &ssid_hex)) {
140 return false;
142 raw_ssid_.clear();
143 return base::HexStringToBytes(ssid_hex, &raw_ssid_);
144 } else if (key == shill::kOutOfCreditsProperty) {
145 return GetBooleanValue(key, value, &cellular_out_of_credits_);
146 } else if (key == shill::kProxyConfigProperty) {
147 std::string proxy_config_str;
148 if (!value.GetAsString(&proxy_config_str)) {
149 NET_LOG(ERROR) << "Failed to parse " << path() << "." << key;
150 return false;
153 proxy_config_.Clear();
154 if (proxy_config_str.empty())
155 return true;
157 scoped_ptr<base::DictionaryValue> proxy_config_dict(
158 onc::ReadDictionaryFromJson(proxy_config_str));
159 if (proxy_config_dict) {
160 // Warning: The DictionaryValue returned from
161 // ReadDictionaryFromJson/JSONParser is an optimized derived class that
162 // doesn't allow releasing ownership of nested values. A Swap in the wrong
163 // order leads to memory access errors.
164 proxy_config_.MergeDictionary(proxy_config_dict.get());
165 } else {
166 NET_LOG(ERROR) << "Failed to parse " << path() << "." << key;
168 return true;
169 } else if (key == shill::kProviderProperty) {
170 std::string vpn_provider_type;
171 const base::DictionaryValue* dict;
172 if (!value.GetAsDictionary(&dict) ||
173 !dict->GetStringWithoutPathExpansion(shill::kTypeProperty,
174 &vpn_provider_type)) {
175 NET_LOG(ERROR) << "Failed to parse " << path() << "." << key;
176 return false;
179 if (vpn_provider_type == shill::kProviderThirdPartyVpn) {
180 // If the network uses a third-party VPN provider, copy over the
181 // provider's extension ID, which is held in |shill::kHostProperty|.
182 if (!dict->GetStringWithoutPathExpansion(
183 shill::kHostProperty, &third_party_vpn_provider_extension_id_)) {
184 NET_LOG(ERROR) << "Failed to parse " << path() << "." << key;
185 return false;
187 } else {
188 third_party_vpn_provider_extension_id_.clear();
191 vpn_provider_type_ = vpn_provider_type;
192 return true;
194 return false;
197 bool NetworkState::InitialPropertiesReceived(
198 const base::DictionaryValue& properties) {
199 NET_LOG(EVENT) << "InitialPropertiesReceived: " << path() << ": " << name()
200 << " State: " << connection_state_ << " Visible: " << visible_;
201 if (!properties.HasKey(shill::kTypeProperty)) {
202 NET_LOG(ERROR) << "NetworkState has no type: "
203 << shill_property_util::GetNetworkIdFromProperties(
204 properties);
205 return false;
208 // By convention, all visible WiFi and WiMAX networks have a
209 // SignalStrength > 0.
210 if ((type() == shill::kTypeWifi || type() == shill::kTypeWimax) &&
211 visible() && signal_strength_ <= 0) {
212 signal_strength_ = 1;
215 // Any change to connection state will trigger a complete property update,
216 // so we update is_captive_portal_ here.
217 is_captive_portal_ = IsCaptivePortalState(properties, true /* log */);
219 // Ensure that the network has a valid name.
220 return UpdateName(properties);
223 void NetworkState::GetStateProperties(base::DictionaryValue* dictionary) const {
224 ManagedState::GetStateProperties(dictionary);
226 // Properties shared by all types.
227 dictionary->SetStringWithoutPathExpansion(shill::kGuidProperty, guid());
228 dictionary->SetStringWithoutPathExpansion(shill::kSecurityClassProperty,
229 security_class());
230 dictionary->SetStringWithoutPathExpansion(shill::kProfileProperty,
231 profile_path());
233 if (visible()) {
234 if (!error().empty())
235 dictionary->SetStringWithoutPathExpansion(shill::kErrorProperty, error());
236 dictionary->SetStringWithoutPathExpansion(shill::kStateProperty,
237 connection_state());
240 // VPN properties.
241 if (NetworkTypePattern::VPN().MatchesType(type())) {
242 // Shill sends VPN provider properties in a nested dictionary. |dictionary|
243 // must replicate that nested structure.
244 scoped_ptr<base::DictionaryValue> provider_property(
245 new base::DictionaryValue);
246 provider_property->SetStringWithoutPathExpansion(shill::kTypeProperty,
247 vpn_provider_type_);
248 if (vpn_provider_type_ == shill::kProviderThirdPartyVpn) {
249 provider_property->SetStringWithoutPathExpansion(
250 shill::kHostProperty, third_party_vpn_provider_extension_id_);
252 dictionary->SetWithoutPathExpansion(shill::kProviderProperty,
253 provider_property.release());
256 // Wireless properties
257 if (!NetworkTypePattern::Wireless().MatchesType(type()))
258 return;
260 if (visible()) {
261 dictionary->SetBooleanWithoutPathExpansion(shill::kConnectableProperty,
262 connectable());
263 dictionary->SetIntegerWithoutPathExpansion(shill::kSignalStrengthProperty,
264 signal_strength());
267 // Wifi properties
268 if (NetworkTypePattern::WiFi().MatchesType(type())) {
269 dictionary->SetStringWithoutPathExpansion(shill::kEapMethodProperty,
270 eap_method());
273 // Mobile properties
274 if (NetworkTypePattern::Mobile().MatchesType(type())) {
275 dictionary->SetStringWithoutPathExpansion(shill::kNetworkTechnologyProperty,
276 network_technology());
277 dictionary->SetStringWithoutPathExpansion(shill::kActivationStateProperty,
278 activation_state());
279 dictionary->SetStringWithoutPathExpansion(shill::kRoamingStateProperty,
280 roaming());
281 dictionary->SetBooleanWithoutPathExpansion(shill::kOutOfCreditsProperty,
282 cellular_out_of_credits());
286 void NetworkState::IPConfigPropertiesChanged(
287 const base::DictionaryValue& properties) {
288 for (base::DictionaryValue::Iterator iter(properties); !iter.IsAtEnd();
289 iter.Advance()) {
290 std::string key = iter.key();
291 const base::Value& value = iter.value();
293 if (key == shill::kAddressProperty) {
294 GetStringValue(key, value, &ip_address_);
295 } else if (key == shill::kGatewayProperty) {
296 GetStringValue(key, value, &gateway_);
297 } else if (key == shill::kNameServersProperty) {
298 const base::ListValue* dns_servers;
299 if (value.GetAsList(&dns_servers)) {
300 dns_servers_.clear();
301 ConvertListValueToStringVector(*dns_servers, &dns_servers_);
303 } else if (key == shill::kPrefixlenProperty) {
304 GetIntegerValue(key, value, &prefix_length_);
305 } else if (key == shill::kWebProxyAutoDiscoveryUrlProperty) {
306 std::string url_string;
307 if (GetStringValue(key, value, &url_string)) {
308 if (url_string.empty()) {
309 web_proxy_auto_discovery_url_ = GURL();
310 } else {
311 GURL gurl(url_string);
312 if (gurl.is_valid()) {
313 web_proxy_auto_discovery_url_ = gurl;
314 } else {
315 NET_LOG(ERROR) << "Invalid WebProxyAutoDiscoveryUrl: " << path()
316 << ": " << url_string;
317 web_proxy_auto_discovery_url_ = GURL();
325 bool NetworkState::RequiresActivation() const {
326 return (type() == shill::kTypeCellular &&
327 activation_state() != shill::kActivationStateActivated &&
328 activation_state() != shill::kActivationStateUnknown);
331 std::string NetworkState::connection_state() const {
332 if (!visible())
333 return shill::kStateDisconnect;
334 return connection_state_;
337 bool NetworkState::IsConnectedState() const {
338 return visible() && StateIsConnected(connection_state_);
341 bool NetworkState::IsConnectingState() const {
342 return visible() && StateIsConnecting(connection_state_);
345 bool NetworkState::IsInProfile() const {
346 // kTypeEthernetEap is always saved. We need this check because it does
347 // not show up in the visible list, but its properties may not be available
348 // when it first shows up in ServiceCompleteList. See crbug.com/355117.
349 return !profile_path_.empty() || type() == shill::kTypeEthernetEap;
352 bool NetworkState::IsPrivate() const {
353 return !profile_path_.empty() &&
354 profile_path_ != NetworkProfileHandler::GetSharedProfilePath();
357 std::string NetworkState::GetHexSsid() const {
358 return base::HexEncode(vector_as_array(&raw_ssid()), raw_ssid().size());
361 std::string NetworkState::GetDnsServersAsString() const {
362 std::string result;
363 for (size_t i = 0; i < dns_servers_.size(); ++i) {
364 if (i != 0)
365 result += ",";
366 result += dns_servers_[i];
368 return result;
371 std::string NetworkState::GetNetmask() const {
372 return network_util::PrefixLengthToNetmask(prefix_length_);
375 std::string NetworkState::GetSpecifier() const {
376 if (!update_received()) {
377 NET_LOG(ERROR) << "GetSpecifier called before update: " << path();
378 return std::string();
380 if (type() == shill::kTypeWifi)
381 return name() + "_" + security_class_;
382 if (!name().empty())
383 return name();
384 return type(); // For unnamed networks such as ethernet.
387 void NetworkState::SetGuid(const std::string& guid) {
388 guid_ = guid;
391 bool NetworkState::UpdateName(const base::DictionaryValue& properties) {
392 std::string updated_name =
393 shill_property_util::GetNameFromProperties(path(), properties);
394 if (updated_name != name()) {
395 set_name(updated_name);
396 return true;
398 return false;
401 // static
402 bool NetworkState::StateIsConnected(const std::string& connection_state) {
403 return (connection_state == shill::kStateReady ||
404 connection_state == shill::kStateOnline ||
405 connection_state == shill::kStatePortal);
408 // static
409 bool NetworkState::StateIsConnecting(const std::string& connection_state) {
410 return (connection_state == shill::kStateAssociation ||
411 connection_state == shill::kStateConfiguration ||
412 connection_state == shill::kStateCarrier);
415 // static
416 bool NetworkState::NetworkStateIsCaptivePortal(
417 const base::DictionaryValue& shill_properties) {
418 return IsCaptivePortalState(shill_properties, false /* log */);
421 // static
422 bool NetworkState::ErrorIsValid(const std::string& error) {
423 // Shill uses "Unknown" to indicate an unset or cleared error state.
424 return !error.empty() && error != kErrorUnknown;
427 } // namespace chromeos