network_state.cc revision 010d83a9304c5a91596085d917d248abff47903a
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 == shill::kActivationStateProperty) {
94    return GetStringValue(key, value, &activation_state_);
95  } else if (key == shill::kRoamingStateProperty) {
96    return GetStringValue(key, value, &roaming_);
97  } else if (key == shill::kSecurityProperty) {
98    return GetStringValue(key, value, &security_);
99  } else if (key == shill::kEapMethodProperty) {
100    return GetStringValue(key, value, &eap_method_);
101  } else if (key == shill::kUIDataProperty) {
102    scoped_ptr<NetworkUIData> new_ui_data =
103        shill_property_util::GetUIDataFromValue(value);
104    if (!new_ui_data) {
105      NET_LOG_ERROR("Failed to parse " + key, path());
106      return false;
107    }
108    ui_data_ = *new_ui_data;
109    return true;
110  } else if (key == shill::kNetworkTechnologyProperty) {
111    return GetStringValue(key, value, &network_technology_);
112  } else if (key == shill::kDeviceProperty) {
113    return GetStringValue(key, value, &device_path_);
114  } else if (key == shill::kGuidProperty) {
115    return GetStringValue(key, value, &guid_);
116  } else if (key == shill::kProfileProperty) {
117    return GetStringValue(key, value, &profile_path_);
118  } else if (key == shill::kActivateOverNonCellularNetworkProperty) {
119    return GetBooleanValue(key, value, &activate_over_non_cellular_networks_);
120  } else if (key == shill::kOutOfCreditsProperty) {
121    return GetBooleanValue(key, value, &cellular_out_of_credits_);
122  }
123  return false;
124}
125
126bool NetworkState::InitialPropertiesReceived(
127    const base::DictionaryValue& properties) {
128  NET_LOG_DEBUG("InitialPropertiesReceived", path());
129  bool changed = false;
130  if (!properties.HasKey(shill::kTypeProperty)) {
131    NET_LOG_ERROR("NetworkState has no type",
132                  shill_property_util::GetNetworkIdFromProperties(properties));
133  } else {
134    changed |= UpdateName(properties);
135  }
136  bool had_ca_cert_nss = has_ca_cert_nss_;
137  has_ca_cert_nss_ = IsCaCertNssSet(properties);
138  changed |= had_ca_cert_nss != has_ca_cert_nss_;
139  return changed;
140}
141
142void NetworkState::GetStateProperties(base::DictionaryValue* dictionary) const {
143  ManagedState::GetStateProperties(dictionary);
144
145  // Properties shared by all types.
146  dictionary->SetStringWithoutPathExpansion(shill::kGuidProperty, guid());
147  dictionary->SetStringWithoutPathExpansion(shill::kStateProperty,
148                                            connection_state());
149  dictionary->SetStringWithoutPathExpansion(shill::kSecurityProperty,
150                                            security());
151  if (!error().empty())
152    dictionary->SetStringWithoutPathExpansion(shill::kErrorProperty, error());
153
154  if (!NetworkTypePattern::Wireless().MatchesType(type()))
155    return;
156
157  // Wireless properties
158  dictionary->SetBooleanWithoutPathExpansion(shill::kConnectableProperty,
159                                             connectable());
160  dictionary->SetIntegerWithoutPathExpansion(shill::kSignalStrengthProperty,
161                                             signal_strength());
162
163  // Wifi properties
164  if (NetworkTypePattern::WiFi().MatchesType(type())) {
165    dictionary->SetStringWithoutPathExpansion(shill::kEapMethodProperty,
166                                              eap_method());
167  }
168
169  // Mobile properties
170  if (NetworkTypePattern::Mobile().MatchesType(type())) {
171    dictionary->SetStringWithoutPathExpansion(
172        shill::kNetworkTechnologyProperty,
173        network_technology());
174    dictionary->SetStringWithoutPathExpansion(shill::kActivationStateProperty,
175                                              activation_state());
176    dictionary->SetStringWithoutPathExpansion(shill::kRoamingStateProperty,
177                                              roaming());
178    dictionary->SetBooleanWithoutPathExpansion(shill::kOutOfCreditsProperty,
179                                               cellular_out_of_credits());
180  }
181}
182
183void NetworkState::IPConfigPropertiesChanged(
184    const base::DictionaryValue& properties) {
185  for (base::DictionaryValue::Iterator iter(properties);
186       !iter.IsAtEnd(); iter.Advance()) {
187    std::string key = iter.key();
188    const base::Value& value = iter.value();
189
190    if (key == shill::kAddressProperty) {
191      GetStringValue(key, value, &ip_address_);
192    } else if (key == shill::kGatewayProperty) {
193      GetStringValue(key, value, &gateway_);
194    } else if (key == shill::kNameServersProperty) {
195      const base::ListValue* dns_servers;
196      if (value.GetAsList(&dns_servers)) {
197        dns_servers_.clear();
198        ConvertListValueToStringVector(*dns_servers, &dns_servers_);
199      }
200    } else if (key == shill::kPrefixlenProperty) {
201      GetIntegerValue(key, value, &prefix_length_);
202    } else if (key == shill::kWebProxyAutoDiscoveryUrlProperty) {
203      std::string url_string;
204      if (GetStringValue(key, value, &url_string)) {
205        if (url_string.empty()) {
206          web_proxy_auto_discovery_url_ = GURL();
207        } else {
208          GURL gurl(url_string);
209          if (gurl.is_valid()) {
210            web_proxy_auto_discovery_url_ = gurl;
211          } else {
212            NET_LOG_ERROR("Invalid WebProxyAutoDiscoveryUrl: " + url_string,
213                          path());
214            web_proxy_auto_discovery_url_ = GURL();
215          }
216        }
217      }
218    }
219  }
220}
221
222bool NetworkState::RequiresActivation() const {
223  return (type() == shill::kTypeCellular &&
224          activation_state() != shill::kActivationStateActivated &&
225          activation_state() != shill::kActivationStateUnknown);
226}
227
228bool NetworkState::IsConnectedState() const {
229  return StateIsConnected(connection_state_);
230}
231
232bool NetworkState::IsConnectingState() const {
233  return StateIsConnecting(connection_state_);
234}
235
236bool NetworkState::IsPrivate() const {
237  return !profile_path_.empty() &&
238      profile_path_ != NetworkProfileHandler::GetSharedProfilePath();
239}
240
241std::string NetworkState::GetDnsServersAsString() const {
242  std::string result;
243  for (size_t i = 0; i < dns_servers_.size(); ++i) {
244    if (i != 0)
245      result += ",";
246    result += dns_servers_[i];
247  }
248  return result;
249}
250
251std::string NetworkState::GetNetmask() const {
252  return network_util::PrefixLengthToNetmask(prefix_length_);
253}
254
255bool NetworkState::UpdateName(const base::DictionaryValue& properties) {
256  std::string updated_name =
257      shill_property_util::GetNameFromProperties(path(), properties);
258  if (updated_name != name()) {
259    set_name(updated_name);
260    return true;
261  }
262  return false;
263}
264
265// static
266bool NetworkState::StateIsConnected(const std::string& connection_state) {
267  return (connection_state == shill::kStateReady ||
268          connection_state == shill::kStateOnline ||
269          connection_state == shill::kStatePortal);
270}
271
272// static
273bool NetworkState::StateIsConnecting(const std::string& connection_state) {
274  return (connection_state == shill::kStateAssociation ||
275          connection_state == shill::kStateConfiguration ||
276          connection_state == shill::kStateCarrier);
277}
278
279// static
280bool NetworkState::ErrorIsValid(const std::string& error) {
281  // Shill uses "Unknown" to indicate an unset or cleared error state.
282  return !error.empty() && error != kErrorUnknown;
283}
284
285}  // namespace chromeos
286