network_state.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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 "base/values.h"
9#include "chromeos/network/network_event_log.h"
10#include "chromeos/network/network_profile_handler.h"
11#include "chromeos/network/network_util.h"
12#include "chromeos/network/shill_property_util.h"
13#include "third_party/cros_system_api/dbus/service_constants.h"
14
15namespace {
16
17const char kErrorUnknown[] = "Unknown";
18
19bool ConvertListValueToStringVector(const base::ListValue& string_list,
20                                    std::vector<std::string>* result) {
21  for (size_t i = 0; i < string_list.GetSize(); ++i) {
22    std::string str;
23    if (!string_list.GetString(i, &str))
24      return false;
25    result->push_back(str);
26  }
27  return true;
28}
29
30bool IsCaCertNssSet(const base::DictionaryValue& properties) {
31  std::string ca_cert_nss;
32  if (properties.GetStringWithoutPathExpansion(shill::kEapCaCertNssProperty,
33                                               &ca_cert_nss) &&
34      !ca_cert_nss.empty()) {
35    return true;
36  }
37
38  const base::DictionaryValue* provider = NULL;
39  properties.GetDictionaryWithoutPathExpansion(shill::kProviderProperty,
40                                               &provider);
41  if (!provider)
42    return false;
43  if (provider->GetStringWithoutPathExpansion(
44          shill::kL2tpIpsecCaCertNssProperty, &ca_cert_nss) &&
45      !ca_cert_nss.empty()) {
46    return true;
47  }
48  if (provider->GetStringWithoutPathExpansion(
49          shill::kOpenVPNCaCertNSSProperty, &ca_cert_nss) &&
50      !ca_cert_nss.empty()) {
51    return true;
52  }
53
54  return false;
55}
56
57}  // namespace
58
59namespace chromeos {
60
61NetworkState::NetworkState(const std::string& path)
62    : ManagedState(MANAGED_TYPE_NETWORK, path),
63      connectable_(false),
64      prefix_length_(0),
65      signal_strength_(0),
66      activate_over_non_cellular_networks_(false),
67      cellular_out_of_credits_(false),
68      has_ca_cert_nss_(false) {
69}
70
71NetworkState::~NetworkState() {
72}
73
74bool NetworkState::PropertyChanged(const std::string& key,
75                                   const base::Value& value) {
76  // Keep care that these properties are the same as in |GetProperties|.
77  if (ManagedStatePropertyChanged(key, value))
78    return true;
79  if (key == shill::kSignalStrengthProperty) {
80    return GetIntegerValue(key, value, &signal_strength_);
81  } else if (key == shill::kStateProperty) {
82    return GetStringValue(key, value, &connection_state_);
83  } else if (key == shill::kConnectableProperty) {
84    return GetBooleanValue(key, value, &connectable_);
85  } else if (key == shill::kErrorProperty) {
86    if (!GetStringValue(key, value, &error_))
87      return false;
88    if (ErrorIsValid(error_))
89      last_error_ = error_;
90    else
91      error_.clear();
92    return true;
93  } else if (key == IPConfigProperty(shill::kAddressProperty)) {
94    return GetStringValue(key, value, &ip_address_);
95  } else if (key == IPConfigProperty(shill::kGatewayProperty)) {
96    return GetStringValue(key, value, &gateway_);
97  } else if (key == IPConfigProperty(shill::kNameServersProperty)) {
98    const base::ListValue* dns_servers;
99    if (!value.GetAsList(&dns_servers))
100      return false;
101    dns_servers_.clear();
102    ConvertListValueToStringVector(*dns_servers, &dns_servers_);
103    return true;
104  } else if (key == IPConfigProperty(shill::kPrefixlenProperty)) {
105    return GetIntegerValue(key, value, &prefix_length_);
106  } else if (key == IPConfigProperty(
107      shill::kWebProxyAutoDiscoveryUrlProperty)) {
108    std::string url_string;
109    if (!GetStringValue(key, value, &url_string))
110      return false;
111    if (url_string.empty()) {
112      web_proxy_auto_discovery_url_ = GURL();
113    } else {
114      GURL gurl(url_string);
115      if (!gurl.is_valid()) {
116        web_proxy_auto_discovery_url_ = gurl;
117      } else {
118        NET_LOG_ERROR("Invalid WebProxyAutoDiscoveryUrl: " + url_string,
119                      path());
120        web_proxy_auto_discovery_url_ = GURL();
121      }
122    }
123    return true;
124  } else if (key == shill::kActivationStateProperty) {
125    return GetStringValue(key, value, &activation_state_);
126  } else if (key == shill::kRoamingStateProperty) {
127    return GetStringValue(key, value, &roaming_);
128  } else if (key == shill::kSecurityProperty) {
129    return GetStringValue(key, value, &security_);
130  } else if (key == shill::kEapMethodProperty) {
131    return GetStringValue(key, value, &eap_method_);
132  } else if (key == shill::kUIDataProperty) {
133    scoped_ptr<NetworkUIData> new_ui_data =
134        shill_property_util::GetUIDataFromValue(value);
135    if (!new_ui_data) {
136      NET_LOG_ERROR("Failed to parse " + key, path());
137      return false;
138    }
139    ui_data_ = *new_ui_data;
140    return true;
141  } else if (key == shill::kNetworkTechnologyProperty) {
142    return GetStringValue(key, value, &network_technology_);
143  } else if (key == shill::kDeviceProperty) {
144    return GetStringValue(key, value, &device_path_);
145  } else if (key == shill::kGuidProperty) {
146    return GetStringValue(key, value, &guid_);
147  } else if (key == shill::kProfileProperty) {
148    return GetStringValue(key, value, &profile_path_);
149  } else if (key == shill::kActivateOverNonCellularNetworkProperty) {
150    return GetBooleanValue(key, value, &activate_over_non_cellular_networks_);
151  } else if (key == shill::kOutOfCreditsProperty) {
152    return GetBooleanValue(key, value, &cellular_out_of_credits_);
153  }
154  return false;
155}
156
157bool NetworkState::InitialPropertiesReceived(
158    const base::DictionaryValue& properties) {
159  NET_LOG_DEBUG("InitialPropertiesReceived", path());
160  bool changed = false;
161  if (!properties.HasKey(shill::kTypeProperty)) {
162    NET_LOG_ERROR("NetworkState has no type",
163                  shill_property_util::GetNetworkIdFromProperties(properties));
164  } else {
165    changed |= UpdateName(properties);
166  }
167  bool had_ca_cert_nss = has_ca_cert_nss_;
168  has_ca_cert_nss_ = IsCaCertNssSet(properties);
169  changed |= had_ca_cert_nss != has_ca_cert_nss_;
170  return changed;
171}
172
173void NetworkState::GetProperties(base::DictionaryValue* dictionary) const {
174  // Keep care that these properties are the same as in |PropertyChanged|.
175  dictionary->SetStringWithoutPathExpansion(shill::kNameProperty, name());
176  dictionary->SetStringWithoutPathExpansion(shill::kTypeProperty, type());
177  dictionary->SetIntegerWithoutPathExpansion(shill::kSignalStrengthProperty,
178                                             signal_strength_);
179  dictionary->SetStringWithoutPathExpansion(shill::kStateProperty,
180                                            connection_state_);
181  dictionary->SetBooleanWithoutPathExpansion(shill::kConnectableProperty,
182                                             connectable_);
183
184  dictionary->SetStringWithoutPathExpansion(shill::kErrorProperty, error_);
185
186  // IPConfig properties
187  base::DictionaryValue* ipconfig_properties = new base::DictionaryValue;
188  ipconfig_properties->SetStringWithoutPathExpansion(shill::kAddressProperty,
189                                                     ip_address_);
190  ipconfig_properties->SetStringWithoutPathExpansion(shill::kGatewayProperty,
191                                                     gateway_);
192  base::ListValue* name_servers = new base::ListValue;
193  name_servers->AppendStrings(dns_servers_);
194  ipconfig_properties->SetWithoutPathExpansion(shill::kNameServersProperty,
195                                               name_servers);
196  ipconfig_properties->SetStringWithoutPathExpansion(
197      shill::kWebProxyAutoDiscoveryUrlProperty,
198      web_proxy_auto_discovery_url_.spec());
199  dictionary->SetWithoutPathExpansion(shill::kIPConfigProperty,
200                                      ipconfig_properties);
201
202  dictionary->SetStringWithoutPathExpansion(shill::kActivationStateProperty,
203                                            activation_state_);
204  dictionary->SetStringWithoutPathExpansion(shill::kRoamingStateProperty,
205                                            roaming_);
206  dictionary->SetStringWithoutPathExpansion(shill::kSecurityProperty,
207                                            security_);
208  dictionary->SetStringWithoutPathExpansion(shill::kEapMethodProperty,
209                                            eap_method_);
210
211  // ui_data_ (contains ONC source) is intentionally omitted.
212
213  dictionary->SetStringWithoutPathExpansion(
214      shill::kNetworkTechnologyProperty,
215      network_technology_);
216  dictionary->SetStringWithoutPathExpansion(shill::kDeviceProperty,
217                                            device_path_);
218  dictionary->SetStringWithoutPathExpansion(shill::kGuidProperty, guid_);
219  dictionary->SetStringWithoutPathExpansion(shill::kProfileProperty,
220                                            profile_path_);
221  dictionary->SetBooleanWithoutPathExpansion(
222      shill::kActivateOverNonCellularNetworkProperty,
223      activate_over_non_cellular_networks_);
224  dictionary->SetBooleanWithoutPathExpansion(shill::kOutOfCreditsProperty,
225                                             cellular_out_of_credits_);
226}
227
228bool NetworkState::RequiresActivation() const {
229  return (type() == shill::kTypeCellular &&
230          activation_state() != shill::kActivationStateActivated &&
231          activation_state() != shill::kActivationStateUnknown);
232}
233
234bool NetworkState::IsConnectedState() const {
235  return StateIsConnected(connection_state_);
236}
237
238bool NetworkState::IsConnectingState() const {
239  return StateIsConnecting(connection_state_);
240}
241
242bool NetworkState::IsPrivate() const {
243  return !profile_path_.empty() &&
244      profile_path_ != NetworkProfileHandler::GetSharedProfilePath();
245}
246
247std::string NetworkState::GetDnsServersAsString() const {
248  std::string result;
249  for (size_t i = 0; i < dns_servers_.size(); ++i) {
250    if (i != 0)
251      result += ",";
252    result += dns_servers_[i];
253  }
254  return result;
255}
256
257std::string NetworkState::GetNetmask() const {
258  return network_util::PrefixLengthToNetmask(prefix_length_);
259}
260
261bool NetworkState::UpdateName(const base::DictionaryValue& properties) {
262  std::string updated_name =
263      shill_property_util::GetNameFromProperties(path(), properties);
264  if (updated_name != name()) {
265    set_name(updated_name);
266    return true;
267  }
268  return false;
269}
270
271// static
272bool NetworkState::StateIsConnected(const std::string& connection_state) {
273  return (connection_state == shill::kStateReady ||
274          connection_state == shill::kStateOnline ||
275          connection_state == shill::kStatePortal);
276}
277
278// static
279bool NetworkState::StateIsConnecting(const std::string& connection_state) {
280  return (connection_state == shill::kStateAssociation ||
281          connection_state == shill::kStateConfiguration ||
282          connection_state == shill::kStateCarrier);
283}
284
285// static
286bool NetworkState::ErrorIsValid(const std::string& error) {
287  // Shill uses "Unknown" to indicate an unset or cleared error state.
288  return !error.empty() && error != kErrorUnknown;
289}
290
291// static
292std::string NetworkState::IPConfigProperty(const char* key) {
293  return base::StringPrintf("%s.%s", shill::kIPConfigProperty, key);
294}
295
296}  // namespace chromeos
297