Upstream version 10.39.225.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::kPaymentPortalProperty) {
103     const base::DictionaryValue* olp;
104     if (!value.GetAsDictionary(&olp))
105       return false;
106     return olp->GetStringWithoutPathExpansion(shill::kPaymentPortalURL,
107                                               &payment_url_);
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());
126       return false;
127     }
128
129     proxy_config_.Clear();
130     if (proxy_config_str.empty())
131       return true;
132
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());
141     } else {
142       NET_LOG_ERROR("Failed to parse " + key, path());
143     }
144     return true;
145   }
146   return false;
147 }
148
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));
156     return false;
157   }
158   // Ensure that the network has a valid name.
159   changed |= UpdateName(properties);
160
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_;
165
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;
171   }
172
173   return changed;
174 }
175
176 void NetworkState::GetStateProperties(base::DictionaryValue* dictionary) const {
177   ManagedState::GetStateProperties(dictionary);
178
179   // Properties shared by all types.
180   dictionary->SetStringWithoutPathExpansion(shill::kGuidProperty, guid());
181   dictionary->SetStringWithoutPathExpansion(shill::kSecurityProperty,
182                                             security());
183
184   if (visible()) {
185     if (!error().empty())
186       dictionary->SetStringWithoutPathExpansion(shill::kErrorProperty, error());
187     dictionary->SetStringWithoutPathExpansion(shill::kStateProperty,
188                                               connection_state());
189   }
190
191   // Wireless properties
192   if (!NetworkTypePattern::Wireless().MatchesType(type()))
193     return;
194
195   if (visible()) {
196     dictionary->SetBooleanWithoutPathExpansion(shill::kConnectableProperty,
197                                                connectable());
198     dictionary->SetIntegerWithoutPathExpansion(shill::kSignalStrengthProperty,
199                                                signal_strength());
200   }
201
202   // Wifi properties
203   if (NetworkTypePattern::WiFi().MatchesType(type())) {
204     dictionary->SetStringWithoutPathExpansion(shill::kEapMethodProperty,
205                                               eap_method());
206   }
207
208   // Mobile properties
209   if (NetworkTypePattern::Mobile().MatchesType(type())) {
210     dictionary->SetStringWithoutPathExpansion(
211         shill::kNetworkTechnologyProperty,
212         network_technology());
213     dictionary->SetStringWithoutPathExpansion(shill::kActivationStateProperty,
214                                               activation_state());
215     dictionary->SetStringWithoutPathExpansion(shill::kRoamingStateProperty,
216                                               roaming());
217     dictionary->SetBooleanWithoutPathExpansion(shill::kOutOfCreditsProperty,
218                                                cellular_out_of_credits());
219   }
220 }
221
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();
228
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_);
238       }
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();
246         } else {
247           GURL gurl(url_string);
248           if (gurl.is_valid()) {
249             web_proxy_auto_discovery_url_ = gurl;
250           } else {
251             NET_LOG_ERROR("Invalid WebProxyAutoDiscoveryUrl: " + url_string,
252                           path());
253             web_proxy_auto_discovery_url_ = GURL();
254           }
255         }
256       }
257     }
258   }
259 }
260
261 bool NetworkState::RequiresActivation() const {
262   return (type() == shill::kTypeCellular &&
263           activation_state() != shill::kActivationStateActivated &&
264           activation_state() != shill::kActivationStateUnknown);
265 }
266
267 std::string NetworkState::connection_state() const {
268   if (!visible())
269     return shill::kStateDisconnect;
270   return connection_state_;
271 }
272
273 bool NetworkState::IsConnectedState() const {
274   return visible() && StateIsConnected(connection_state_);
275 }
276
277 bool NetworkState::IsConnectingState() const {
278   return visible() && StateIsConnecting(connection_state_);
279 }
280
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;
286 }
287
288 bool NetworkState::IsPrivate() const {
289   return !profile_path_.empty() &&
290       profile_path_ != NetworkProfileHandler::GetSharedProfilePath();
291 }
292
293 std::string NetworkState::GetDnsServersAsString() const {
294   std::string result;
295   for (size_t i = 0; i < dns_servers_.size(); ++i) {
296     if (i != 0)
297       result += ",";
298     result += dns_servers_[i];
299   }
300   return result;
301 }
302
303 std::string NetworkState::GetNetmask() const {
304   return network_util::PrefixLengthToNetmask(prefix_length_);
305 }
306
307 std::string NetworkState::GetSpecifier() const {
308   if (!update_received()) {
309     NET_LOG_ERROR("GetSpecifier called before update", path());
310     return std::string();
311   }
312   if (type() == shill::kTypeWifi)
313     return name() + "_" + security_;
314   if (!name().empty())
315     return name();
316   return type();  // For unnamed networks such as ethernet.
317 }
318
319 void NetworkState::SetGuid(const std::string& guid) {
320   guid_ = guid;
321 }
322
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);
328     return true;
329   }
330   return false;
331 }
332
333 // static
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);
338 }
339
340 // static
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);
345 }
346
347 // static
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;
351 }
352
353 }  // namespace chromeos