Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chromeos / network / network_state.cc
blob93c12e41a29256afaf2d163dd058c5f7059ed4ad
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 dictionary->SetStringWithoutPathExpansion(shill::kStateProperty,
235 connection_state());
238 // VPN properties.
239 if (NetworkTypePattern::VPN().MatchesType(type())) {
240 // Shill sends VPN provider properties in a nested dictionary. |dictionary|
241 // must replicate that nested structure.
242 scoped_ptr<base::DictionaryValue> provider_property(
243 new base::DictionaryValue);
244 provider_property->SetStringWithoutPathExpansion(shill::kTypeProperty,
245 vpn_provider_type_);
246 if (vpn_provider_type_ == shill::kProviderThirdPartyVpn) {
247 provider_property->SetStringWithoutPathExpansion(
248 shill::kHostProperty, third_party_vpn_provider_extension_id_);
250 dictionary->SetWithoutPathExpansion(shill::kProviderProperty,
251 provider_property.release());
254 // Wireless properties
255 if (!NetworkTypePattern::Wireless().MatchesType(type()))
256 return;
258 if (visible()) {
259 dictionary->SetBooleanWithoutPathExpansion(shill::kConnectableProperty,
260 connectable());
261 dictionary->SetIntegerWithoutPathExpansion(shill::kSignalStrengthProperty,
262 signal_strength());
265 // Wifi properties
266 if (NetworkTypePattern::WiFi().MatchesType(type())) {
267 dictionary->SetStringWithoutPathExpansion(shill::kEapMethodProperty,
268 eap_method());
271 // Mobile properties
272 if (NetworkTypePattern::Mobile().MatchesType(type())) {
273 dictionary->SetStringWithoutPathExpansion(shill::kNetworkTechnologyProperty,
274 network_technology());
275 dictionary->SetStringWithoutPathExpansion(shill::kActivationStateProperty,
276 activation_state());
277 dictionary->SetStringWithoutPathExpansion(shill::kRoamingStateProperty,
278 roaming());
279 dictionary->SetBooleanWithoutPathExpansion(shill::kOutOfCreditsProperty,
280 cellular_out_of_credits());
284 void NetworkState::IPConfigPropertiesChanged(
285 const base::DictionaryValue& properties) {
286 for (base::DictionaryValue::Iterator iter(properties); !iter.IsAtEnd();
287 iter.Advance()) {
288 std::string key = iter.key();
289 const base::Value& value = iter.value();
291 if (key == shill::kAddressProperty) {
292 GetStringValue(key, value, &ip_address_);
293 } else if (key == shill::kGatewayProperty) {
294 GetStringValue(key, value, &gateway_);
295 } else if (key == shill::kNameServersProperty) {
296 const base::ListValue* dns_servers;
297 if (value.GetAsList(&dns_servers)) {
298 dns_servers_.clear();
299 ConvertListValueToStringVector(*dns_servers, &dns_servers_);
301 } else if (key == shill::kPrefixlenProperty) {
302 GetIntegerValue(key, value, &prefix_length_);
303 } else if (key == shill::kWebProxyAutoDiscoveryUrlProperty) {
304 std::string url_string;
305 if (GetStringValue(key, value, &url_string)) {
306 if (url_string.empty()) {
307 web_proxy_auto_discovery_url_ = GURL();
308 } else {
309 GURL gurl(url_string);
310 if (gurl.is_valid()) {
311 web_proxy_auto_discovery_url_ = gurl;
312 } else {
313 NET_LOG(ERROR) << "Invalid WebProxyAutoDiscoveryUrl: " << path()
314 << ": " << url_string;
315 web_proxy_auto_discovery_url_ = GURL();
323 bool NetworkState::RequiresActivation() const {
324 return (type() == shill::kTypeCellular &&
325 activation_state() != shill::kActivationStateActivated &&
326 activation_state() != shill::kActivationStateUnknown);
329 std::string NetworkState::connection_state() const {
330 if (!visible())
331 return shill::kStateDisconnect;
332 return connection_state_;
335 bool NetworkState::IsConnectedState() const {
336 return visible() && StateIsConnected(connection_state_);
339 bool NetworkState::IsConnectingState() const {
340 return visible() && StateIsConnecting(connection_state_);
343 bool NetworkState::IsInProfile() const {
344 // kTypeEthernetEap is always saved. We need this check because it does
345 // not show up in the visible list, but its properties may not be available
346 // when it first shows up in ServiceCompleteList. See crbug.com/355117.
347 return !profile_path_.empty() || type() == shill::kTypeEthernetEap;
350 bool NetworkState::IsPrivate() const {
351 return !profile_path_.empty() &&
352 profile_path_ != NetworkProfileHandler::GetSharedProfilePath();
355 std::string NetworkState::GetHexSsid() const {
356 return base::HexEncode(vector_as_array(&raw_ssid()), raw_ssid().size());
359 std::string NetworkState::GetDnsServersAsString() const {
360 std::string result;
361 for (size_t i = 0; i < dns_servers_.size(); ++i) {
362 if (i != 0)
363 result += ",";
364 result += dns_servers_[i];
366 return result;
369 std::string NetworkState::GetNetmask() const {
370 return network_util::PrefixLengthToNetmask(prefix_length_);
373 std::string NetworkState::GetSpecifier() const {
374 if (!update_received()) {
375 NET_LOG(ERROR) << "GetSpecifier called before update: " << path();
376 return std::string();
378 if (type() == shill::kTypeWifi)
379 return name() + "_" + security_class_;
380 if (!name().empty())
381 return name();
382 return type(); // For unnamed networks such as ethernet.
385 void NetworkState::SetGuid(const std::string& guid) {
386 guid_ = guid;
389 bool NetworkState::UpdateName(const base::DictionaryValue& properties) {
390 std::string updated_name =
391 shill_property_util::GetNameFromProperties(path(), properties);
392 if (updated_name != name()) {
393 set_name(updated_name);
394 return true;
396 return false;
399 std::string NetworkState::GetErrorState() const {
400 if (ErrorIsValid(error()))
401 return error();
402 return last_error();
405 // static
406 bool NetworkState::StateIsConnected(const std::string& connection_state) {
407 return (connection_state == shill::kStateReady ||
408 connection_state == shill::kStateOnline ||
409 connection_state == shill::kStatePortal);
412 // static
413 bool NetworkState::StateIsConnecting(const std::string& connection_state) {
414 return (connection_state == shill::kStateAssociation ||
415 connection_state == shill::kStateConfiguration ||
416 connection_state == shill::kStateCarrier);
419 // static
420 bool NetworkState::NetworkStateIsCaptivePortal(
421 const base::DictionaryValue& shill_properties) {
422 return IsCaptivePortalState(shill_properties, false /* log */);
425 // static
426 bool NetworkState::ErrorIsValid(const std::string& error) {
427 // Shill uses "Unknown" to indicate an unset or cleared error state.
428 return !error.empty() && error != kErrorUnknown;
431 } // namespace chromeos