ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / chromeos / network / network_state.cc
blobbd53eae5d141dd190c160e18d13a9109b7993f55
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/stl_util.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/stringprintf.h"
10 #include "chromeos/network/network_profile_handler.h"
11 #include "chromeos/network/network_type_pattern.h"
12 #include "chromeos/network/network_util.h"
13 #include "chromeos/network/onc/onc_utils.h"
14 #include "chromeos/network/shill_property_util.h"
15 #include "components/device_event_log/device_event_log.h"
16 #include "third_party/cros_system_api/dbus/service_constants.h"
18 namespace {
20 const char kErrorUnknown[] = "Unknown";
22 bool ConvertListValueToStringVector(const base::ListValue& string_list,
23 std::vector<std::string>* result) {
24 for (size_t i = 0; i < string_list.GetSize(); ++i) {
25 std::string str;
26 if (!string_list.GetString(i, &str))
27 return false;
28 result->push_back(str);
30 return true;
33 bool IsCaptivePortalState(const base::DictionaryValue& properties, bool log) {
34 std::string state;
35 properties.GetStringWithoutPathExpansion(shill::kStateProperty, &state);
36 if (state != shill::kStatePortal)
37 return false;
38 std::string portal_detection_phase, portal_detection_status;
39 if (!properties.GetStringWithoutPathExpansion(
40 shill::kPortalDetectionFailedPhaseProperty,
41 &portal_detection_phase) ||
42 !properties.GetStringWithoutPathExpansion(
43 shill::kPortalDetectionFailedStatusProperty,
44 &portal_detection_status)) {
45 // If Shill (or a stub) has not set PortalDetectionFailedStatus
46 // or PortalDetectionFailedPhase, assume we are in captive portal state.
47 return true;
50 // Shill reports the phase in which it determined that the device is behind a
51 // captive portal. We only want to rely only on incorrect content being
52 // returned and ignore other reasons.
53 bool is_captive_portal =
54 portal_detection_phase == shill::kPortalDetectionPhaseContent &&
55 portal_detection_status == shill::kPortalDetectionStatusFailure;
57 if (log) {
58 std::string name;
59 properties.GetStringWithoutPathExpansion(shill::kNameProperty, &name);
60 if (name.empty())
61 properties.GetStringWithoutPathExpansion(shill::kSSIDProperty, &name);
62 if (!is_captive_portal) {
63 NET_LOG(EVENT) << "State is 'portal' but not in captive portal state:"
64 << " name=" << name << " phase=" << portal_detection_phase
65 << " status=" << portal_detection_status;
66 } else {
67 NET_LOG(EVENT) << "Network is in captive portal state: " << name;
71 return is_captive_portal;
74 } // namespace
76 namespace chromeos {
78 NetworkState::NetworkState(const std::string& path)
79 : ManagedState(MANAGED_TYPE_NETWORK, path),
80 visible_(false),
81 prefix_length_(0),
82 connectable_(false),
83 is_captive_portal_(false),
84 signal_strength_(0),
85 cellular_out_of_credits_(false) {
88 NetworkState::~NetworkState() {
91 bool NetworkState::PropertyChanged(const std::string& key,
92 const base::Value& value) {
93 // Keep care that these properties are the same as in |GetProperties|.
94 if (ManagedStatePropertyChanged(key, value))
95 return true;
96 if (key == shill::kSignalStrengthProperty) {
97 return GetIntegerValue(key, value, &signal_strength_);
98 } else if (key == shill::kStateProperty) {
99 return GetStringValue(key, value, &connection_state_);
100 } else if (key == shill::kVisibleProperty) {
101 return GetBooleanValue(key, value, &visible_);
102 } else if (key == shill::kConnectableProperty) {
103 return GetBooleanValue(key, value, &connectable_);
104 } else if (key == shill::kErrorProperty) {
105 if (!GetStringValue(key, value, &error_))
106 return false;
107 if (ErrorIsValid(error_))
108 last_error_ = error_;
109 else
110 error_.clear();
111 return true;
112 } else if (key == shill::kActivationTypeProperty) {
113 return GetStringValue(key, value, &activation_type_);
114 } else if (key == shill::kActivationStateProperty) {
115 return GetStringValue(key, value, &activation_state_);
116 } else if (key == shill::kRoamingStateProperty) {
117 return GetStringValue(key, value, &roaming_);
118 } else if (key == shill::kPaymentPortalProperty) {
119 const base::DictionaryValue* olp;
120 if (!value.GetAsDictionary(&olp))
121 return false;
122 return olp->GetStringWithoutPathExpansion(shill::kPaymentPortalURL,
123 &payment_url_);
124 } else if (key == shill::kSecurityClassProperty) {
125 return GetStringValue(key, value, &security_class_);
126 } else if (key == shill::kEapMethodProperty) {
127 return GetStringValue(key, value, &eap_method_);
128 } else if (key == shill::kNetworkTechnologyProperty) {
129 return GetStringValue(key, value, &network_technology_);
130 } else if (key == shill::kDeviceProperty) {
131 return GetStringValue(key, value, &device_path_);
132 } else if (key == shill::kGuidProperty) {
133 return GetStringValue(key, value, &guid_);
134 } else if (key == shill::kProfileProperty) {
135 return GetStringValue(key, value, &profile_path_);
136 } else if (key == shill::kWifiHexSsid) {
137 std::string ssid_hex;
138 if (!GetStringValue(key, value, &ssid_hex)) {
139 return false;
141 raw_ssid_.clear();
142 return base::HexStringToBytes(ssid_hex, &raw_ssid_);
143 } else if (key == shill::kOutOfCreditsProperty) {
144 return GetBooleanValue(key, value, &cellular_out_of_credits_);
145 } else if (key == shill::kProxyConfigProperty) {
146 std::string proxy_config_str;
147 if (!value.GetAsString(&proxy_config_str)) {
148 NET_LOG(ERROR) << "Failed to parse " << path() << "." << key;
149 return false;
152 proxy_config_.Clear();
153 if (proxy_config_str.empty())
154 return true;
156 scoped_ptr<base::DictionaryValue> proxy_config_dict(
157 onc::ReadDictionaryFromJson(proxy_config_str));
158 if (proxy_config_dict) {
159 // Warning: The DictionaryValue returned from
160 // ReadDictionaryFromJson/JSONParser is an optimized derived class that
161 // doesn't allow releasing ownership of nested values. A Swap in the wrong
162 // order leads to memory access errors.
163 proxy_config_.MergeDictionary(proxy_config_dict.get());
164 } else {
165 NET_LOG(ERROR) << "Failed to parse " << path() << "." << key;
167 return true;
169 return false;
172 bool NetworkState::InitialPropertiesReceived(
173 const base::DictionaryValue& properties) {
174 NET_LOG(EVENT) << "InitialPropertiesReceived: " << path() << ": " << name()
175 << " State: " << connection_state_ << " Visible: " << visible_;
176 if (!properties.HasKey(shill::kTypeProperty)) {
177 NET_LOG(ERROR) << "NetworkState has no type: "
178 << shill_property_util::GetNetworkIdFromProperties(
179 properties);
180 return false;
183 // By convention, all visible WiFi and WiMAX networks have a
184 // SignalStrength > 0.
185 if ((type() == shill::kTypeWifi || type() == shill::kTypeWimax) &&
186 visible() && signal_strength_ <= 0) {
187 signal_strength_ = 1;
190 // Any change to connection state will trigger a complete property update,
191 // so we update is_captive_portal_ here.
192 is_captive_portal_ = IsCaptivePortalState(properties, true /* log */);
194 // Ensure that the network has a valid name.
195 return UpdateName(properties);
198 void NetworkState::GetStateProperties(base::DictionaryValue* dictionary) const {
199 ManagedState::GetStateProperties(dictionary);
201 // Properties shared by all types.
202 dictionary->SetStringWithoutPathExpansion(shill::kGuidProperty, guid());
203 dictionary->SetStringWithoutPathExpansion(shill::kSecurityClassProperty,
204 security_class());
205 dictionary->SetStringWithoutPathExpansion(shill::kProfileProperty,
206 profile_path());
208 if (visible()) {
209 if (!error().empty())
210 dictionary->SetStringWithoutPathExpansion(shill::kErrorProperty, error());
211 dictionary->SetStringWithoutPathExpansion(shill::kStateProperty,
212 connection_state());
215 // Wireless properties
216 if (!NetworkTypePattern::Wireless().MatchesType(type()))
217 return;
219 if (visible()) {
220 dictionary->SetBooleanWithoutPathExpansion(shill::kConnectableProperty,
221 connectable());
222 dictionary->SetIntegerWithoutPathExpansion(shill::kSignalStrengthProperty,
223 signal_strength());
226 // Wifi properties
227 if (NetworkTypePattern::WiFi().MatchesType(type())) {
228 dictionary->SetStringWithoutPathExpansion(shill::kEapMethodProperty,
229 eap_method());
232 // Mobile properties
233 if (NetworkTypePattern::Mobile().MatchesType(type())) {
234 dictionary->SetStringWithoutPathExpansion(shill::kNetworkTechnologyProperty,
235 network_technology());
236 dictionary->SetStringWithoutPathExpansion(shill::kActivationStateProperty,
237 activation_state());
238 dictionary->SetStringWithoutPathExpansion(shill::kRoamingStateProperty,
239 roaming());
240 dictionary->SetBooleanWithoutPathExpansion(shill::kOutOfCreditsProperty,
241 cellular_out_of_credits());
245 void NetworkState::IPConfigPropertiesChanged(
246 const base::DictionaryValue& properties) {
247 for (base::DictionaryValue::Iterator iter(properties); !iter.IsAtEnd();
248 iter.Advance()) {
249 std::string key = iter.key();
250 const base::Value& value = iter.value();
252 if (key == shill::kAddressProperty) {
253 GetStringValue(key, value, &ip_address_);
254 } else if (key == shill::kGatewayProperty) {
255 GetStringValue(key, value, &gateway_);
256 } else if (key == shill::kNameServersProperty) {
257 const base::ListValue* dns_servers;
258 if (value.GetAsList(&dns_servers)) {
259 dns_servers_.clear();
260 ConvertListValueToStringVector(*dns_servers, &dns_servers_);
262 } else if (key == shill::kPrefixlenProperty) {
263 GetIntegerValue(key, value, &prefix_length_);
264 } else if (key == shill::kWebProxyAutoDiscoveryUrlProperty) {
265 std::string url_string;
266 if (GetStringValue(key, value, &url_string)) {
267 if (url_string.empty()) {
268 web_proxy_auto_discovery_url_ = GURL();
269 } else {
270 GURL gurl(url_string);
271 if (gurl.is_valid()) {
272 web_proxy_auto_discovery_url_ = gurl;
273 } else {
274 NET_LOG(ERROR) << "Invalid WebProxyAutoDiscoveryUrl: " << path()
275 << ": " << url_string;
276 web_proxy_auto_discovery_url_ = GURL();
284 bool NetworkState::RequiresActivation() const {
285 return (type() == shill::kTypeCellular &&
286 activation_state() != shill::kActivationStateActivated &&
287 activation_state() != shill::kActivationStateUnknown);
290 std::string NetworkState::connection_state() const {
291 if (!visible())
292 return shill::kStateDisconnect;
293 return connection_state_;
296 bool NetworkState::IsConnectedState() const {
297 return visible() && StateIsConnected(connection_state_);
300 bool NetworkState::IsConnectingState() const {
301 return visible() && StateIsConnecting(connection_state_);
304 bool NetworkState::IsInProfile() const {
305 // kTypeEthernetEap is always saved. We need this check because it does
306 // not show up in the visible list, but its properties may not be available
307 // when it first shows up in ServiceCompleteList. See crbug.com/355117.
308 return !profile_path_.empty() || type() == shill::kTypeEthernetEap;
311 bool NetworkState::IsPrivate() const {
312 return !profile_path_.empty() &&
313 profile_path_ != NetworkProfileHandler::GetSharedProfilePath();
316 std::string NetworkState::GetHexSsid() const {
317 return base::HexEncode(vector_as_array(&raw_ssid()), raw_ssid().size());
320 std::string NetworkState::GetDnsServersAsString() const {
321 std::string result;
322 for (size_t i = 0; i < dns_servers_.size(); ++i) {
323 if (i != 0)
324 result += ",";
325 result += dns_servers_[i];
327 return result;
330 std::string NetworkState::GetNetmask() const {
331 return network_util::PrefixLengthToNetmask(prefix_length_);
334 std::string NetworkState::GetSpecifier() const {
335 if (!update_received()) {
336 NET_LOG(ERROR) << "GetSpecifier called before update: " << path();
337 return std::string();
339 if (type() == shill::kTypeWifi)
340 return name() + "_" + security_class_;
341 if (!name().empty())
342 return name();
343 return type(); // For unnamed networks such as ethernet.
346 void NetworkState::SetGuid(const std::string& guid) {
347 guid_ = guid;
350 bool NetworkState::UpdateName(const base::DictionaryValue& properties) {
351 std::string updated_name =
352 shill_property_util::GetNameFromProperties(path(), properties);
353 if (updated_name != name()) {
354 set_name(updated_name);
355 return true;
357 return false;
360 // static
361 bool NetworkState::StateIsConnected(const std::string& connection_state) {
362 return (connection_state == shill::kStateReady ||
363 connection_state == shill::kStateOnline ||
364 connection_state == shill::kStatePortal);
367 // static
368 bool NetworkState::StateIsConnecting(const std::string& connection_state) {
369 return (connection_state == shill::kStateAssociation ||
370 connection_state == shill::kStateConfiguration ||
371 connection_state == shill::kStateCarrier);
374 // static
375 bool NetworkState::NetworkStateIsCaptivePortal(
376 const base::DictionaryValue& shill_properties) {
377 return IsCaptivePortalState(shill_properties, false /* log */);
380 // static
381 bool NetworkState::ErrorIsValid(const std::string& error) {
382 // Shill uses "Unknown" to indicate an unset or cleared error state.
383 return !error.empty() && error != kErrorUnknown;
386 } // namespace chromeos