Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chromeos / network / network_state.cc
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.
4
5 #include "chromeos/network/network_state.h"
6
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"
15
16 namespace {
17
18 const char kErrorUnknown[] = "Unknown";
19
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) {
23     std::string str;
24     if (!string_list.GetString(i, &str))
25       return false;
26     result->push_back(str);
27   }
28   return true;
29 }
30
31 bool IsCaCertNssSet(const base::DictionaryValue& properties) {
32   std::string ca_cert_nss;
33   if (properties.GetStringWithoutPathExpansion(shill::kEapCaCertNssProperty,
34                                                &ca_cert_nss) &&
35       !ca_cert_nss.empty()) {
36     return true;
37   }
38
39   const base::DictionaryValue* provider = NULL;
40   properties.GetDictionaryWithoutPathExpansion(shill::kProviderProperty,
41                                                &provider);
42   if (!provider)
43     return false;
44   if (provider->GetStringWithoutPathExpansion(
45           shill::kL2tpIpsecCaCertNssProperty, &ca_cert_nss) &&
46       !ca_cert_nss.empty()) {
47     return true;
48   }
49   if (provider->GetStringWithoutPathExpansion(
50           shill::kOpenVPNCaCertNSSProperty, &ca_cert_nss) &&
51       !ca_cert_nss.empty()) {
52     return true;
53   }
54
55   return false;
56 }
57
58 }  // namespace
59
60 namespace chromeos {
61
62 NetworkState::NetworkState(const std::string& path)
63     : ManagedState(MANAGED_TYPE_NETWORK, path),
64       visible_(false),
65       connectable_(false),
66       prefix_length_(0),
67       signal_strength_(0),
68       cellular_out_of_credits_(false),
69       has_ca_cert_nss_(false) {
70 }
71
72 NetworkState::~NetworkState() {
73 }
74
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))
79     return true;
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_))
90       return false;
91     if (ErrorIsValid(error_))
92       last_error_ = error_;
93     else
94       error_.clear();
95     return true;
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());
120       return false;
121     }
122
123     proxy_config_.Clear();
124     if (proxy_config_str.empty())
125       return true;
126
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());
135     } else {
136       NET_LOG_ERROR("Failed to parse " + key, path());
137     }
138     return true;
139   }
140   return false;
141 }
142
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));
150     return false;
151   }
152   // Ensure that the network has a valid name.
153   changed |= UpdateName(properties);
154
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_;
159
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;
164   }
165
166   return changed;
167 }
168
169 void NetworkState::GetStateProperties(base::DictionaryValue* dictionary) const {
170   ManagedState::GetStateProperties(dictionary);
171
172   // Properties shared by all types.
173   dictionary->SetStringWithoutPathExpansion(shill::kGuidProperty, guid());
174   dictionary->SetStringWithoutPathExpansion(shill::kSecurityProperty,
175                                             security());
176
177   if (visible()) {
178     if (!error().empty())
179       dictionary->SetStringWithoutPathExpansion(shill::kErrorProperty, error());
180     dictionary->SetStringWithoutPathExpansion(shill::kStateProperty,
181                                               connection_state());
182   }
183
184   // Wireless properties
185   if (!NetworkTypePattern::Wireless().MatchesType(type()))
186     return;
187
188   if (visible()) {
189     dictionary->SetBooleanWithoutPathExpansion(shill::kConnectableProperty,
190                                                connectable());
191     dictionary->SetIntegerWithoutPathExpansion(shill::kSignalStrengthProperty,
192                                                signal_strength());
193   }
194
195   // Wifi properties
196   if (NetworkTypePattern::WiFi().MatchesType(type())) {
197     dictionary->SetStringWithoutPathExpansion(shill::kEapMethodProperty,
198                                               eap_method());
199   }
200
201   // Mobile properties
202   if (NetworkTypePattern::Mobile().MatchesType(type())) {
203     dictionary->SetStringWithoutPathExpansion(
204         shill::kNetworkTechnologyProperty,
205         network_technology());
206     dictionary->SetStringWithoutPathExpansion(shill::kActivationStateProperty,
207                                               activation_state());
208     dictionary->SetStringWithoutPathExpansion(shill::kRoamingStateProperty,
209                                               roaming());
210     dictionary->SetBooleanWithoutPathExpansion(shill::kOutOfCreditsProperty,
211                                                cellular_out_of_credits());
212   }
213 }
214
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();
221
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_);
231       }
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();
239         } else {
240           GURL gurl(url_string);
241           if (gurl.is_valid()) {
242             web_proxy_auto_discovery_url_ = gurl;
243           } else {
244             NET_LOG_ERROR("Invalid WebProxyAutoDiscoveryUrl: " + url_string,
245                           path());
246             web_proxy_auto_discovery_url_ = GURL();
247           }
248         }
249       }
250     }
251   }
252 }
253
254 bool NetworkState::RequiresActivation() const {
255   return (type() == shill::kTypeCellular &&
256           activation_state() != shill::kActivationStateActivated &&
257           activation_state() != shill::kActivationStateUnknown);
258 }
259
260 std::string NetworkState::connection_state() const {
261   if (!visible())
262     return shill::kStateDisconnect;
263   return connection_state_;
264 }
265
266 bool NetworkState::IsConnectedState() const {
267   return visible() && StateIsConnected(connection_state_);
268 }
269
270 bool NetworkState::IsConnectingState() const {
271   return visible() && StateIsConnecting(connection_state_);
272 }
273
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;
279 }
280
281 bool NetworkState::IsPrivate() const {
282   return !profile_path_.empty() &&
283       profile_path_ != NetworkProfileHandler::GetSharedProfilePath();
284 }
285
286 std::string NetworkState::GetDnsServersAsString() const {
287   std::string result;
288   for (size_t i = 0; i < dns_servers_.size(); ++i) {
289     if (i != 0)
290       result += ",";
291     result += dns_servers_[i];
292   }
293   return result;
294 }
295
296 std::string NetworkState::GetNetmask() const {
297   return network_util::PrefixLengthToNetmask(prefix_length_);
298 }
299
300 std::string NetworkState::GetSpecifier() const {
301   if (!update_received()) {
302     NET_LOG_ERROR("GetSpecifier called before update", path());
303     return std::string();
304   }
305   if (type() == shill::kTypeWifi)
306     return name() + "_" + security_;
307   if (!name().empty())
308     return name();
309   return type();  // For unnamed networks such as ethernet.
310 }
311
312 void NetworkState::SetGuid(const std::string& guid) {
313   guid_ = guid;
314 }
315
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);
321     return true;
322   }
323   return false;
324 }
325
326 // static
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);
331 }
332
333 // static
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);
338 }
339
340 // static
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;
344 }
345
346 }  // namespace chromeos