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
15 namespace {
16
17 const char kErrorUnknown[] = "Unknown";
18
ConvertListValueToStringVector(const base::ListValue & string_list,std::vector<std::string> * result)19 bool 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
IsCaCertNssSet(const base::DictionaryValue & properties)30 bool 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
59 namespace chromeos {
60
NetworkState(const std::string & path)61 NetworkState::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
~NetworkState()71 NetworkState::~NetworkState() {
72 }
73
PropertyChanged(const std::string & key,const base::Value & value)74 bool 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 // Shill uses "Unknown" to indicate an unset error state.
89 if (error_ == kErrorUnknown)
90 error_.clear();
91 return true;
92 } else if (key == IPConfigProperty(shill::kAddressProperty)) {
93 return GetStringValue(key, value, &ip_address_);
94 } else if (key == IPConfigProperty(shill::kGatewayProperty)) {
95 return GetStringValue(key, value, &gateway_);
96 } else if (key == IPConfigProperty(shill::kNameServersProperty)) {
97 const base::ListValue* dns_servers;
98 if (!value.GetAsList(&dns_servers))
99 return false;
100 dns_servers_.clear();
101 ConvertListValueToStringVector(*dns_servers, &dns_servers_);
102 return true;
103 } else if (key == IPConfigProperty(shill::kPrefixlenProperty)) {
104 return GetIntegerValue(key, value, &prefix_length_);
105 } else if (key == IPConfigProperty(
106 shill::kWebProxyAutoDiscoveryUrlProperty)) {
107 std::string url_string;
108 if (!GetStringValue(key, value, &url_string))
109 return false;
110 if (url_string.empty()) {
111 web_proxy_auto_discovery_url_ = GURL();
112 } else {
113 GURL gurl(url_string);
114 if (!gurl.is_valid()) {
115 web_proxy_auto_discovery_url_ = gurl;
116 } else {
117 NET_LOG_ERROR("Invalid WebProxyAutoDiscoveryUrl: " + url_string,
118 path());
119 web_proxy_auto_discovery_url_ = GURL();
120 }
121 }
122 return true;
123 } else if (key == shill::kActivationStateProperty) {
124 return GetStringValue(key, value, &activation_state_);
125 } else if (key == shill::kRoamingStateProperty) {
126 return GetStringValue(key, value, &roaming_);
127 } else if (key == shill::kSecurityProperty) {
128 return GetStringValue(key, value, &security_);
129 } else if (key == shill::kEapMethodProperty) {
130 return GetStringValue(key, value, &eap_method_);
131 } else if (key == shill::kUIDataProperty) {
132 scoped_ptr<NetworkUIData> new_ui_data =
133 shill_property_util::GetUIDataFromValue(value);
134 if (!new_ui_data) {
135 NET_LOG_ERROR("Failed to parse " + key, path());
136 return false;
137 }
138 ui_data_ = *new_ui_data;
139 return true;
140 } else if (key == shill::kNetworkTechnologyProperty) {
141 return GetStringValue(key, value, &network_technology_);
142 } else if (key == shill::kDeviceProperty) {
143 return GetStringValue(key, value, &device_path_);
144 } else if (key == shill::kGuidProperty) {
145 return GetStringValue(key, value, &guid_);
146 } else if (key == shill::kProfileProperty) {
147 return GetStringValue(key, value, &profile_path_);
148 } else if (key == shill::kActivateOverNonCellularNetworkProperty) {
149 return GetBooleanValue(key, value, &activate_over_non_cellular_networks_);
150 } else if (key == shill::kOutOfCreditsProperty) {
151 return GetBooleanValue(key, value, &cellular_out_of_credits_);
152 }
153 return false;
154 }
155
InitialPropertiesReceived(const base::DictionaryValue & properties)156 bool NetworkState::InitialPropertiesReceived(
157 const base::DictionaryValue& properties) {
158 NET_LOG_DEBUG("InitialPropertiesReceived", path());
159 bool changed = UpdateName(properties);
160 bool had_ca_cert_nss = has_ca_cert_nss_;
161 has_ca_cert_nss_ = IsCaCertNssSet(properties);
162 changed |= had_ca_cert_nss != has_ca_cert_nss_;
163 return changed;
164 }
165
GetProperties(base::DictionaryValue * dictionary) const166 void NetworkState::GetProperties(base::DictionaryValue* dictionary) const {
167 // Keep care that these properties are the same as in |PropertyChanged|.
168 dictionary->SetStringWithoutPathExpansion(shill::kNameProperty, name());
169 dictionary->SetStringWithoutPathExpansion(shill::kTypeProperty, type());
170 dictionary->SetIntegerWithoutPathExpansion(shill::kSignalStrengthProperty,
171 signal_strength_);
172 dictionary->SetStringWithoutPathExpansion(shill::kStateProperty,
173 connection_state_);
174 dictionary->SetBooleanWithoutPathExpansion(shill::kConnectableProperty,
175 connectable_);
176
177 dictionary->SetStringWithoutPathExpansion(shill::kErrorProperty, error_);
178
179 // IPConfig properties
180 base::DictionaryValue* ipconfig_properties = new base::DictionaryValue;
181 ipconfig_properties->SetStringWithoutPathExpansion(shill::kAddressProperty,
182 ip_address_);
183 ipconfig_properties->SetStringWithoutPathExpansion(shill::kGatewayProperty,
184 gateway_);
185 base::ListValue* name_servers = new base::ListValue;
186 name_servers->AppendStrings(dns_servers_);
187 ipconfig_properties->SetWithoutPathExpansion(shill::kNameServersProperty,
188 name_servers);
189 ipconfig_properties->SetStringWithoutPathExpansion(
190 shill::kWebProxyAutoDiscoveryUrlProperty,
191 web_proxy_auto_discovery_url_.spec());
192 dictionary->SetWithoutPathExpansion(shill::kIPConfigProperty,
193 ipconfig_properties);
194
195 dictionary->SetStringWithoutPathExpansion(shill::kActivationStateProperty,
196 activation_state_);
197 dictionary->SetStringWithoutPathExpansion(shill::kRoamingStateProperty,
198 roaming_);
199 dictionary->SetStringWithoutPathExpansion(shill::kSecurityProperty,
200 security_);
201 dictionary->SetStringWithoutPathExpansion(shill::kEapMethodProperty,
202 eap_method_);
203 // Proxy config and ONC source are intentionally omitted: These properties are
204 // placed in NetworkState to transition ProxyConfigServiceImpl from
205 // NetworkLibrary to the new network stack. The networking extension API
206 // shouldn't depend on this member. Once ManagedNetworkConfigurationHandler
207 // is used instead of NetworkLibrary, we can remove them again.
208 dictionary->SetStringWithoutPathExpansion(
209 shill::kNetworkTechnologyProperty,
210 network_technology_);
211 dictionary->SetStringWithoutPathExpansion(shill::kDeviceProperty,
212 device_path_);
213 dictionary->SetStringWithoutPathExpansion(shill::kGuidProperty, guid_);
214 dictionary->SetStringWithoutPathExpansion(shill::kProfileProperty,
215 profile_path_);
216 dictionary->SetBooleanWithoutPathExpansion(
217 shill::kActivateOverNonCellularNetworkProperty,
218 activate_over_non_cellular_networks_);
219 dictionary->SetBooleanWithoutPathExpansion(shill::kOutOfCreditsProperty,
220 cellular_out_of_credits_);
221 }
222
RequiresActivation() const223 bool NetworkState::RequiresActivation() const {
224 return (type() == shill::kTypeCellular &&
225 activation_state() != shill::kActivationStateActivated &&
226 activation_state() != shill::kActivationStateUnknown);
227 }
228
IsConnectedState() const229 bool NetworkState::IsConnectedState() const {
230 return StateIsConnected(connection_state_);
231 }
232
IsConnectingState() const233 bool NetworkState::IsConnectingState() const {
234 return StateIsConnecting(connection_state_);
235 }
236
IsPrivate() const237 bool NetworkState::IsPrivate() const {
238 return !profile_path_.empty() &&
239 profile_path_ != NetworkProfileHandler::kSharedProfilePath;
240 }
241
GetDnsServersAsString() const242 std::string NetworkState::GetDnsServersAsString() const {
243 std::string result;
244 for (size_t i = 0; i < dns_servers_.size(); ++i) {
245 if (i != 0)
246 result += ",";
247 result += dns_servers_[i];
248 }
249 return result;
250 }
251
GetNetmask() const252 std::string NetworkState::GetNetmask() const {
253 return network_util::PrefixLengthToNetmask(prefix_length_);
254 }
255
UpdateName(const base::DictionaryValue & properties)256 bool NetworkState::UpdateName(const base::DictionaryValue& properties) {
257 std::string updated_name =
258 shill_property_util::GetNameFromProperties(path(), properties);
259 if (updated_name != name()) {
260 set_name(updated_name);
261 return true;
262 }
263 return false;
264 }
265
266 // static
StateIsConnected(const std::string & connection_state)267 bool NetworkState::StateIsConnected(const std::string& connection_state) {
268 return (connection_state == shill::kStateReady ||
269 connection_state == shill::kStateOnline ||
270 connection_state == shill::kStatePortal);
271 }
272
273 // static
StateIsConnecting(const std::string & connection_state)274 bool NetworkState::StateIsConnecting(const std::string& connection_state) {
275 return (connection_state == shill::kStateAssociation ||
276 connection_state == shill::kStateConfiguration ||
277 connection_state == shill::kStateCarrier);
278 }
279
280 // static
IPConfigProperty(const char * key)281 std::string NetworkState::IPConfigProperty(const char* key) {
282 return base::StringPrintf("%s.%s", shill::kIPConfigProperty, key);
283 }
284
285 } // namespace chromeos
286