Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Side by Side Diff: chromeos/network/network_connection_handler.cc

Issue 2861883002: [CrOS Tether] Transform NetworkConnectionHandler to an interface. (Closed)
Patch Set: stevenjb@ comments. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chromeos/network/network_connection_handler.h" 5 #include "chromeos/network/network_connection_handler.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/json/json_reader.h" 8 #include "base/json/json_reader.h"
9 #include "base/location.h" 9 #include "base/location.h"
10 #include "base/single_thread_task_runner.h" 10 #include "base/single_thread_task_runner.h"
11 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_number_conversions.h"
12 #include "base/threading/thread_task_runner_handle.h" 12 #include "base/threading/thread_task_runner_handle.h"
13 #include "base/time/time.h"
13 #include "chromeos/dbus/dbus_thread_manager.h" 14 #include "chromeos/dbus/dbus_thread_manager.h"
14 #include "chromeos/dbus/shill_manager_client.h" 15 #include "chromeos/dbus/shill_manager_client.h"
15 #include "chromeos/dbus/shill_service_client.h" 16 #include "chromeos/dbus/shill_service_client.h"
16 #include "chromeos/network/certificate_pattern.h" 17 #include "chromeos/network/certificate_pattern.h"
17 #include "chromeos/network/client_cert_resolver.h" 18 #include "chromeos/network/client_cert_resolver.h"
18 #include "chromeos/network/client_cert_util.h" 19 #include "chromeos/network/client_cert_util.h"
19 #include "chromeos/network/managed_network_configuration_handler.h" 20 #include "chromeos/network/managed_network_configuration_handler.h"
20 #include "chromeos/network/network_configuration_handler.h" 21 #include "chromeos/network/network_configuration_handler.h"
21 #include "chromeos/network/network_event_log.h" 22 #include "chromeos/network/network_event_log.h"
22 #include "chromeos/network/network_profile_handler.h" 23 #include "chromeos/network/network_profile_handler.h"
23 #include "chromeos/network/network_state.h" 24 #include "chromeos/network/network_state.h"
24 #include "chromeos/network/network_state_handler.h" 25 #include "chromeos/network/network_state_handler.h"
25 #include "chromeos/network/shill_property_util.h" 26 #include "chromeos/network/shill_property_util.h"
26 #include "dbus/object_path.h" 27 #include "dbus/object_path.h"
27 #include "net/cert/x509_certificate.h" 28 #include "net/cert/x509_certificate.h"
28 #include "third_party/cros_system_api/dbus/service_constants.h" 29 #include "third_party/cros_system_api/dbus/service_constants.h"
29 30
30 namespace chromeos { 31 namespace chromeos {
31 32
32 namespace { 33 // Static constants.
33
34 bool IsAuthenticationError(const std::string& error) {
35 return (error == shill::kErrorBadWEPKey ||
36 error == shill::kErrorPppAuthFailed ||
37 error == shill::kErrorEapLocalTlsFailed ||
38 error == shill::kErrorEapRemoteTlsFailed ||
39 error == shill::kErrorEapAuthenticationFailed);
40 }
41
42 bool VPNRequiresCredentials(const std::string& service_path,
43 const std::string& provider_type,
44 const base::DictionaryValue& provider_properties) {
45 if (provider_type == shill::kProviderOpenVpn) {
46 std::string username;
47 provider_properties.GetStringWithoutPathExpansion(
48 shill::kOpenVPNUserProperty, &username);
49 if (username.empty()) {
50 NET_LOG_EVENT("OpenVPN: No username", service_path);
51 return true;
52 }
53 bool passphrase_required = false;
54 provider_properties.GetBooleanWithoutPathExpansion(
55 shill::kPassphraseRequiredProperty, &passphrase_required);
56 if (passphrase_required) {
57 NET_LOG_EVENT("OpenVPN: Passphrase Required", service_path);
58 return true;
59 }
60 NET_LOG_EVENT("OpenVPN Is Configured", service_path);
61 } else {
62 bool passphrase_required = false;
63 provider_properties.GetBooleanWithoutPathExpansion(
64 shill::kL2tpIpsecPskRequiredProperty, &passphrase_required);
65 if (passphrase_required) {
66 NET_LOG_EVENT("VPN: PSK Required", service_path);
67 return true;
68 }
69 provider_properties.GetBooleanWithoutPathExpansion(
70 shill::kPassphraseRequiredProperty, &passphrase_required);
71 if (passphrase_required) {
72 NET_LOG_EVENT("VPN: Passphrase Required", service_path);
73 return true;
74 }
75 NET_LOG_EVENT("VPN Is Configured", service_path);
76 }
77 return false;
78 }
79
80 std::string GetDefaultUserProfilePath(const NetworkState* network) {
81 if (!NetworkHandler::IsInitialized() ||
82 (LoginState::IsInitialized() &&
83 !LoginState::Get()->UserHasNetworkProfile()) ||
84 (network && network->type() == shill::kTypeWifi &&
85 network->security_class() == shill::kSecurityNone)) {
86 return NetworkProfileHandler::GetSharedProfilePath();
87 }
88 const NetworkProfile* profile =
89 NetworkHandler::Get()->network_profile_handler()->GetDefaultUserProfile();
90 return profile ? profile->path
91 : NetworkProfileHandler::GetSharedProfilePath();
92 }
93
94 } // namespace
95
96 const char NetworkConnectionHandler::kErrorNotFound[] = "not-found"; 34 const char NetworkConnectionHandler::kErrorNotFound[] = "not-found";
97 const char NetworkConnectionHandler::kErrorConnected[] = "connected"; 35 const char NetworkConnectionHandler::kErrorConnected[] = "connected";
98 const char NetworkConnectionHandler::kErrorConnecting[] = "connecting"; 36 const char NetworkConnectionHandler::kErrorConnecting[] = "connecting";
99 const char NetworkConnectionHandler::kErrorNotConnected[] = "not-connected"; 37 const char NetworkConnectionHandler::kErrorNotConnected[] = "not-connected";
100 const char NetworkConnectionHandler::kErrorPassphraseRequired[] = 38 const char NetworkConnectionHandler::kErrorPassphraseRequired[] =
101 "passphrase-required"; 39 "passphrase-required";
102 const char NetworkConnectionHandler::kErrorBadPassphrase[] = "bad-passphrase"; 40 const char NetworkConnectionHandler::kErrorBadPassphrase[] = "bad-passphrase";
103 const char NetworkConnectionHandler::kErrorCertificateRequired[] = 41 const char NetworkConnectionHandler::kErrorCertificateRequired[] =
104 "certificate-required"; 42 "certificate-required";
105 const char NetworkConnectionHandler::kErrorConfigurationRequired[] = 43 const char NetworkConnectionHandler::kErrorConfigurationRequired[] =
(...skipping 11 matching lines...) Expand all
117 "cert-load-timeout"; 55 "cert-load-timeout";
118 const char NetworkConnectionHandler::kErrorUnmanagedNetwork[] = 56 const char NetworkConnectionHandler::kErrorUnmanagedNetwork[] =
119 "unmanaged-network"; 57 "unmanaged-network";
120 const char NetworkConnectionHandler::kErrorActivateFailed[] = "activate-failed"; 58 const char NetworkConnectionHandler::kErrorActivateFailed[] = "activate-failed";
121 const char NetworkConnectionHandler::kErrorEnabledOrDisabledWhenNotAvailable[] = 59 const char NetworkConnectionHandler::kErrorEnabledOrDisabledWhenNotAvailable[] =
122 "not-available"; 60 "not-available";
123 const char 61 const char
124 NetworkConnectionHandler::kErrorTetherConnectionAttemptWithNoDelegate[] = 62 NetworkConnectionHandler::kErrorTetherConnectionAttemptWithNoDelegate[] =
125 "tether-with-no-delegate"; 63 "tether-with-no-delegate";
126 64
127 struct NetworkConnectionHandler::ConnectRequest { 65 NetworkConnectionHandler::NetworkConnectionHandler()
128 ConnectRequest(const std::string& service_path, 66 : tether_delegate_(nullptr), weak_ptr_factory_(this) {}
129 const std::string& profile_path,
130 const base::Closure& success,
131 const network_handler::ErrorCallback& error)
132 : service_path(service_path),
133 profile_path(profile_path),
134 connect_state(CONNECT_REQUESTED),
135 success_callback(success),
136 error_callback(error) {
137 }
138 enum ConnectState {
139 CONNECT_REQUESTED = 0,
140 CONNECT_STARTED = 1,
141 CONNECT_CONNECTING = 2
142 };
143 std::string service_path;
144 std::string profile_path;
145 ConnectState connect_state;
146 base::Closure success_callback;
147 network_handler::ErrorCallback error_callback;
148 };
149 67
150 NetworkConnectionHandler::NetworkConnectionHandler() 68 NetworkConnectionHandler::~NetworkConnectionHandler() {}
151 : cert_loader_(NULL),
152 network_state_handler_(NULL),
153 configuration_handler_(NULL),
154 logged_in_(false),
155 certificates_loaded_(false),
156 tether_delegate_(nullptr) {}
157
158 NetworkConnectionHandler::~NetworkConnectionHandler() {
159 if (network_state_handler_)
160 network_state_handler_->RemoveObserver(this, FROM_HERE);
161 if (cert_loader_)
162 cert_loader_->RemoveObserver(this);
163 if (LoginState::IsInitialized())
164 LoginState::Get()->RemoveObserver(this);
165 }
166
167 void NetworkConnectionHandler::Init(
168 NetworkStateHandler* network_state_handler,
169 NetworkConfigurationHandler* network_configuration_handler,
170 ManagedNetworkConfigurationHandler* managed_network_configuration_handler) {
171 if (LoginState::IsInitialized())
172 LoginState::Get()->AddObserver(this);
173
174 if (CertLoader::IsInitialized()) {
175 cert_loader_ = CertLoader::Get();
176 cert_loader_->AddObserver(this);
177 if (cert_loader_->certificates_loaded()) {
178 NET_LOG_EVENT("Certificates Loaded", "");
179 certificates_loaded_ = true;
180 }
181 } else {
182 // TODO(tbarzic): Require a mock or stub cert_loader in tests.
183 NET_LOG_EVENT("Certificate Loader not initialized", "");
184 certificates_loaded_ = true;
185 }
186
187 if (network_state_handler) {
188 network_state_handler_ = network_state_handler;
189 network_state_handler_->AddObserver(this, FROM_HERE);
190 }
191 configuration_handler_ = network_configuration_handler;
192 managed_configuration_handler_ = managed_network_configuration_handler;
193
194 // After this point, the NetworkConnectionHandler is fully initialized (all
195 // handler references set, observers registered, ...).
196
197 if (LoginState::IsInitialized())
198 LoggedInStateChanged();
199 }
200 69
201 void NetworkConnectionHandler::AddObserver( 70 void NetworkConnectionHandler::AddObserver(
202 NetworkConnectionObserver* observer) { 71 NetworkConnectionObserver* observer) {
203 observers_.AddObserver(observer); 72 observers_.AddObserver(observer);
204 } 73 }
205 74
206 void NetworkConnectionHandler::RemoveObserver( 75 void NetworkConnectionHandler::RemoveObserver(
207 NetworkConnectionObserver* observer) { 76 NetworkConnectionObserver* observer) {
208 observers_.RemoveObserver(observer); 77 observers_.RemoveObserver(observer);
209 } 78 }
210 79
211 void NetworkConnectionHandler::LoggedInStateChanged() {
212 LoginState* login_state = LoginState::Get();
213 if (logged_in_ || !login_state->IsUserLoggedIn())
214 return;
215
216 logged_in_ = true;
217 logged_in_time_ = base::TimeTicks::Now();
218 }
219
220 void NetworkConnectionHandler::OnCertificatesLoaded(
221 const net::CertificateList& cert_list,
222 bool initial_load) {
223 certificates_loaded_ = true;
224 NET_LOG_EVENT("Certificates Loaded", "");
225 if (queued_connect_)
226 ConnectToQueuedNetwork();
227 }
228
229 void NetworkConnectionHandler::InitiateTetherNetworkConnection(
230 const std::string& tether_network_guid,
231 const base::Closure& success_callback,
232 const network_handler::ErrorCallback& error_callback) {
233 DCHECK(tether_delegate_);
234 tether_delegate_->ConnectToNetwork(
235 tether_network_guid,
236 base::Bind(&NetworkConnectionHandler::InvokeConnectSuccessCallback,
237 AsWeakPtr(), tether_network_guid, success_callback),
238 base::Bind(&NetworkConnectionHandler::InvokeConnectErrorCallback,
239 AsWeakPtr(), tether_network_guid, error_callback));
240 }
241
242 void NetworkConnectionHandler::ConnectToNetwork(
243 const std::string& service_path,
244 const base::Closure& success_callback,
245 const network_handler::ErrorCallback& error_callback,
246 bool check_error_state) {
247 NET_LOG_USER("ConnectToNetwork", service_path);
248 for (auto& observer : observers_)
249 observer.ConnectToNetworkRequested(service_path);
250
251 // Clear any existing queued connect request.
252 queued_connect_.reset();
253 if (HasConnectingNetwork(service_path)) {
254 NET_LOG_USER("Connect Request While Pending", service_path);
255 InvokeConnectErrorCallback(service_path, error_callback, kErrorConnecting);
256 return;
257 }
258
259 // Check cached network state for connected, connecting, or unactivated
260 // networks. These states will not be affected by a recent configuration.
261 // Note: NetworkState may not exist for a network that was recently
262 // configured, in which case these checks do not apply anyway.
263 const NetworkState* network =
264 network_state_handler_->GetNetworkState(service_path);
265
266 if (network) {
267 // For existing networks, perform some immediate consistency checks.
268 if (network->IsConnectedState()) {
269 InvokeConnectErrorCallback(service_path, error_callback, kErrorConnected);
270 return;
271 }
272 if (network->IsConnectingState()) {
273 InvokeConnectErrorCallback(service_path, error_callback,
274 kErrorConnecting);
275 return;
276 }
277
278 if (check_error_state) {
279 const std::string& error = network->last_error();
280 if (error == shill::kErrorBadPassphrase) {
281 InvokeConnectErrorCallback(service_path, error_callback,
282 kErrorBadPassphrase);
283 return;
284 }
285 if (IsAuthenticationError(error)) {
286 InvokeConnectErrorCallback(service_path, error_callback,
287 kErrorAuthenticationRequired);
288 return;
289 }
290 }
291
292 if (NetworkTypePattern::Tether().MatchesType(network->type())) {
293 if (tether_delegate_) {
294 const std::string& tether_network_guid = network->guid();
295 DCHECK(!tether_network_guid.empty());
296 InitiateTetherNetworkConnection(tether_network_guid, success_callback,
297 error_callback);
298 } else {
299 InvokeConnectErrorCallback(service_path, error_callback,
300 kErrorTetherConnectionAttemptWithNoDelegate);
301 }
302 return;
303 }
304 }
305
306 // If the network does not have a profile path, specify the correct default
307 // profile here and set it once connected. Otherwise leave it empty to
308 // indicate that it does not need to be set.
309 std::string profile_path;
310 if (!network || network->profile_path().empty())
311 profile_path = GetDefaultUserProfilePath(network);
312
313 // All synchronous checks passed, add |service_path| to connecting list.
314 pending_requests_.insert(std::make_pair(
315 service_path,
316 ConnectRequest(service_path, profile_path,
317 success_callback, error_callback)));
318
319 // Connect immediately to 'connectable' networks.
320 // TODO(stevenjb): Shill needs to properly set Connectable for VPN.
321 if (network && network->connectable() && network->type() != shill::kTypeVPN) {
322 if (IsNetworkProhibitedByPolicy(network->type(), network->guid(),
323 network->profile_path())) {
324 ErrorCallbackForPendingRequest(service_path, kErrorUnmanagedNetwork);
325 return;
326 }
327
328 CallShillConnect(service_path);
329 return;
330 }
331
332 // Request additional properties to check. VerifyConfiguredAndConnect will
333 // use only these properties, not cached properties, to ensure that they
334 // are up to date after any recent configuration.
335 configuration_handler_->GetShillProperties(
336 service_path,
337 base::Bind(&NetworkConnectionHandler::VerifyConfiguredAndConnect,
338 AsWeakPtr(), check_error_state),
339 base::Bind(&NetworkConnectionHandler::HandleConfigurationFailure,
340 AsWeakPtr(), service_path));
341 }
342
343 void NetworkConnectionHandler::DisconnectNetwork(
344 const std::string& service_path,
345 const base::Closure& success_callback,
346 const network_handler::ErrorCallback& error_callback) {
347 NET_LOG_USER("DisconnectNetwork", service_path);
348 for (auto& observer : observers_)
349 observer.DisconnectRequested(service_path);
350
351 const NetworkState* network =
352 network_state_handler_->GetNetworkState(service_path);
353 if (!network) {
354 NET_LOG_ERROR("Disconnect Error: Not Found", service_path);
355 network_handler::RunErrorCallback(error_callback, service_path,
356 kErrorNotFound, "");
357 return;
358 }
359 if (!network->IsConnectedState() && !network->IsConnectingState()) {
360 NET_LOG_ERROR("Disconnect Error: Not Connected", service_path);
361 network_handler::RunErrorCallback(error_callback, service_path,
362 kErrorNotConnected, "");
363 return;
364 }
365 pending_requests_.erase(service_path);
366 CallShillDisconnect(service_path, success_callback, error_callback);
367 }
368
369 bool NetworkConnectionHandler::HasConnectingNetwork(
370 const std::string& service_path) {
371 return pending_requests_.count(service_path) != 0;
372 }
373
374 bool NetworkConnectionHandler::HasPendingConnectRequest() {
375 return pending_requests_.size() > 0;
376 }
377
378 void NetworkConnectionHandler::SetTetherDelegate( 80 void NetworkConnectionHandler::SetTetherDelegate(
379 TetherDelegate* tether_delegate) { 81 TetherDelegate* tether_delegate) {
380 tether_delegate_ = tether_delegate; 82 tether_delegate_ = tether_delegate;
381 } 83 }
382 84
383 void NetworkConnectionHandler::NetworkListChanged() {
384 CheckAllPendingRequests();
385 }
386
387 void NetworkConnectionHandler::NetworkPropertiesUpdated(
388 const NetworkState* network) {
389 if (HasConnectingNetwork(network->path()))
390 CheckPendingRequest(network->path());
391 }
392
393 NetworkConnectionHandler::ConnectRequest*
394 NetworkConnectionHandler::GetPendingRequest(const std::string& service_path) {
395 std::map<std::string, ConnectRequest>::iterator iter =
396 pending_requests_.find(service_path);
397 return iter != pending_requests_.end() ? &(iter->second) : NULL;
398 }
399
400 // ConnectToNetwork implementation
401
402 void NetworkConnectionHandler::VerifyConfiguredAndConnect(
403 bool check_error_state,
404 const std::string& service_path,
405 const base::DictionaryValue& service_properties) {
406 NET_LOG_EVENT("VerifyConfiguredAndConnect", service_path);
407
408 // If 'passphrase_required' is still true, then the 'Passphrase' property
409 // has not been set to a minimum length value.
410 bool passphrase_required = false;
411 service_properties.GetBooleanWithoutPathExpansion(
412 shill::kPassphraseRequiredProperty, &passphrase_required);
413 if (passphrase_required) {
414 ErrorCallbackForPendingRequest(service_path, kErrorPassphraseRequired);
415 return;
416 }
417
418 std::string type, security_class;
419 service_properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type);
420 service_properties.GetStringWithoutPathExpansion(
421 shill::kSecurityClassProperty, &security_class);
422 bool connectable = false;
423 service_properties.GetBooleanWithoutPathExpansion(
424 shill::kConnectableProperty, &connectable);
425
426 // In case NetworkState was not available in ConnectToNetwork (e.g. it had
427 // been recently configured), we need to check Connectable again.
428 if (connectable && type != shill::kTypeVPN) {
429 // TODO(stevenjb): Shill needs to properly set Connectable for VPN.
430 CallShillConnect(service_path);
431 return;
432 }
433
434 // Get VPN provider type and host (required for configuration) and ensure
435 // that required VPN non-cert properties are set.
436 const base::DictionaryValue* provider_properties = NULL;
437 std::string vpn_provider_type, vpn_provider_host, vpn_client_cert_id;
438 if (type == shill::kTypeVPN) {
439 // VPN Provider values are read from the "Provider" dictionary, not the
440 // "Provider.Type", etc keys (which are used only to set the values).
441 if (service_properties.GetDictionaryWithoutPathExpansion(
442 shill::kProviderProperty, &provider_properties)) {
443 provider_properties->GetStringWithoutPathExpansion(
444 shill::kTypeProperty, &vpn_provider_type);
445 provider_properties->GetStringWithoutPathExpansion(
446 shill::kHostProperty, &vpn_provider_host);
447 provider_properties->GetStringWithoutPathExpansion(
448 shill::kL2tpIpsecClientCertIdProperty, &vpn_client_cert_id);
449 }
450 if (vpn_provider_type.empty() || vpn_provider_host.empty()) {
451 ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired);
452 return;
453 }
454 }
455
456 std::string guid;
457 service_properties.GetStringWithoutPathExpansion(shill::kGuidProperty, &guid);
458 std::string profile;
459 service_properties.GetStringWithoutPathExpansion(shill::kProfileProperty,
460 &profile);
461 ::onc::ONCSource onc_source = onc::ONC_SOURCE_NONE;
462 const base::DictionaryValue* policy =
463 managed_configuration_handler_->FindPolicyByGuidAndProfile(guid, profile,
464 &onc_source);
465
466 if (IsNetworkProhibitedByPolicy(type, guid, profile)) {
467 ErrorCallbackForPendingRequest(service_path, kErrorUnmanagedNetwork);
468 return;
469 }
470
471 client_cert::ClientCertConfig cert_config_from_policy;
472 if (policy) {
473 client_cert::OncToClientCertConfig(onc_source, *policy,
474 &cert_config_from_policy);
475 }
476
477 client_cert::ConfigType client_cert_type = client_cert::CONFIG_TYPE_NONE;
478 if (type == shill::kTypeVPN) {
479 if (vpn_provider_type == shill::kProviderOpenVpn) {
480 client_cert_type = client_cert::CONFIG_TYPE_OPENVPN;
481 } else {
482 // L2TP/IPSec only requires a certificate if one is specified in ONC
483 // or one was configured by the UI. Otherwise it is L2TP/IPSec with
484 // PSK and doesn't require a certificate.
485 //
486 // TODO(benchan): Modify shill to specify the authentication type via
487 // the kL2tpIpsecAuthenticationType property, so that Chrome doesn't need
488 // to deduce the authentication type based on the
489 // kL2tpIpsecClientCertIdProperty here (and also in VPNConfigView).
490 if (!vpn_client_cert_id.empty() ||
491 cert_config_from_policy.client_cert_type !=
492 onc::client_cert::kClientCertTypeNone) {
493 client_cert_type = client_cert::CONFIG_TYPE_IPSEC;
494 }
495 }
496 } else if (type == shill::kTypeWifi &&
497 security_class == shill::kSecurity8021x) {
498 client_cert_type = client_cert::CONFIG_TYPE_EAP;
499 }
500
501 base::DictionaryValue config_properties;
502 if (client_cert_type != client_cert::CONFIG_TYPE_NONE) {
503 // Note: if we get here then a certificate *may* be required, so we want
504 // to ensure that certificates have loaded successfully before attempting
505 // to connect.
506
507 // User must be logged in to connect to a network requiring a certificate.
508 if (!logged_in_ || !cert_loader_) {
509 NET_LOG_ERROR("User not logged in", "");
510 ErrorCallbackForPendingRequest(service_path, kErrorCertificateRequired);
511 return;
512 }
513 // If certificates have not been loaded yet, queue the connect request.
514 if (!certificates_loaded_) {
515 NET_LOG_EVENT("Certificates not loaded", "");
516 QueueConnectRequest(service_path);
517 return;
518 }
519
520 // Check certificate properties from policy.
521 if (cert_config_from_policy.client_cert_type ==
522 onc::client_cert::kPattern) {
523 if (!ClientCertResolver::ResolveCertificatePatternSync(
524 client_cert_type, cert_config_from_policy, &config_properties)) {
525 ErrorCallbackForPendingRequest(service_path, kErrorCertificateRequired);
526 return;
527 }
528 } else if (check_error_state &&
529 !client_cert::IsCertificateConfigured(client_cert_type,
530 service_properties)) {
531 // Network may not be configured.
532 ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired);
533 return;
534 }
535 }
536
537 if (type == shill::kTypeVPN) {
538 // VPN may require a username, and/or passphrase to be set. (Check after
539 // ensuring that any required certificates are configured).
540 DCHECK(provider_properties);
541 if (VPNRequiresCredentials(
542 service_path, vpn_provider_type, *provider_properties)) {
543 NET_LOG_USER("VPN Requires Credentials", service_path);
544 ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired);
545 return;
546 }
547
548 // If it's L2TP/IPsec PSK, there is no properties to configure, so proceed
549 // to connect.
550 if (client_cert_type == client_cert::CONFIG_TYPE_NONE) {
551 CallShillConnect(service_path);
552 return;
553 }
554 }
555
556 if (!config_properties.empty()) {
557 NET_LOG_EVENT("Configuring Network", service_path);
558 configuration_handler_->SetShillProperties(
559 service_path, config_properties,
560 NetworkConfigurationObserver::SOURCE_USER_ACTION,
561 base::Bind(&NetworkConnectionHandler::CallShillConnect, AsWeakPtr(),
562 service_path),
563 base::Bind(&NetworkConnectionHandler::HandleConfigurationFailure,
564 AsWeakPtr(), service_path));
565 return;
566 }
567
568 // Otherwise, we probably still need to configure the network since
569 // 'Connectable' is false. If |check_error_state| is true, signal an
570 // error, otherwise attempt to connect to possibly gain additional error
571 // state from Shill (or in case 'Connectable' is improperly unset).
572 if (check_error_state)
573 ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired);
574 else
575 CallShillConnect(service_path);
576 }
577
578 bool NetworkConnectionHandler::IsNetworkProhibitedByPolicy(
579 const std::string& type,
580 const std::string& guid,
581 const std::string& profile_path) {
582 if (!logged_in_)
583 return false;
584 if (type != shill::kTypeWifi)
585 return false;
586 const base::DictionaryValue* global_network_config =
587 managed_configuration_handler_->GetGlobalConfigFromPolicy(
588 std::string() /* no username hash, device policy */);
589 if (!global_network_config)
590 return false;
591 bool policy_prohibites = false;
592 if (!global_network_config->GetBooleanWithoutPathExpansion(
593 ::onc::global_network_config::kAllowOnlyPolicyNetworksToConnect,
594 &policy_prohibites) ||
595 !policy_prohibites) {
596 return false;
597 }
598 return !managed_configuration_handler_->FindPolicyByGuidAndProfile(
599 guid, profile_path, nullptr /* onc_source */);
600 }
601
602 void NetworkConnectionHandler::QueueConnectRequest(
603 const std::string& service_path) {
604 ConnectRequest* request = GetPendingRequest(service_path);
605 if (!request) {
606 NET_LOG_ERROR("No pending request to queue", service_path);
607 return;
608 }
609
610 const int kMaxCertLoadTimeSeconds = 15;
611 base::TimeDelta dtime = base::TimeTicks::Now() - logged_in_time_;
612 if (dtime > base::TimeDelta::FromSeconds(kMaxCertLoadTimeSeconds)) {
613 NET_LOG_ERROR("Certificate load timeout", service_path);
614 InvokeConnectErrorCallback(service_path, request->error_callback,
615 kErrorCertLoadTimeout);
616 return;
617 }
618
619 NET_LOG_EVENT("Connect Request Queued", service_path);
620 queued_connect_.reset(new ConnectRequest(
621 service_path, request->profile_path,
622 request->success_callback, request->error_callback));
623 pending_requests_.erase(service_path);
624
625 // Post a delayed task to check to see if certificates have loaded. If they
626 // haven't, and queued_connect_ has not been cleared (e.g. by a successful
627 // connect request), cancel the request and notify the user.
628 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
629 FROM_HERE, base::Bind(&NetworkConnectionHandler::CheckCertificatesLoaded,
630 AsWeakPtr()),
631 base::TimeDelta::FromSeconds(kMaxCertLoadTimeSeconds) - dtime);
632 }
633
634 void NetworkConnectionHandler::CheckCertificatesLoaded() {
635 if (certificates_loaded_)
636 return;
637 // If queued_connect_ has been cleared (e.g. another connect request occurred
638 // and wasn't queued), do nothing here.
639 if (!queued_connect_)
640 return;
641 // Otherwise, notify the user.
642 NET_LOG_ERROR("Certificate load timeout", queued_connect_->service_path);
643 InvokeConnectErrorCallback(queued_connect_->service_path,
644 queued_connect_->error_callback,
645 kErrorCertLoadTimeout);
646 queued_connect_.reset();
647 }
648
649 void NetworkConnectionHandler::ConnectToQueuedNetwork() {
650 DCHECK(queued_connect_);
651
652 // Make a copy of |queued_connect_| parameters, because |queued_connect_|
653 // will get reset at the beginning of |ConnectToNetwork|.
654 std::string service_path = queued_connect_->service_path;
655 base::Closure success_callback = queued_connect_->success_callback;
656 network_handler::ErrorCallback error_callback =
657 queued_connect_->error_callback;
658
659 NET_LOG_EVENT("Connecting to Queued Network", service_path);
660 ConnectToNetwork(service_path, success_callback, error_callback,
661 false /* check_error_state */);
662 }
663
664 void NetworkConnectionHandler::CallShillConnect(
665 const std::string& service_path) {
666 NET_LOG_EVENT("Sending Connect Request to Shill", service_path);
667 network_state_handler_->ClearLastErrorForNetwork(service_path);
668 DBusThreadManager::Get()->GetShillServiceClient()->Connect(
669 dbus::ObjectPath(service_path),
670 base::Bind(&NetworkConnectionHandler::HandleShillConnectSuccess,
671 AsWeakPtr(), service_path),
672 base::Bind(&NetworkConnectionHandler::HandleShillConnectFailure,
673 AsWeakPtr(), service_path));
674 }
675
676 void NetworkConnectionHandler::HandleConfigurationFailure(
677 const std::string& service_path,
678 const std::string& error_name,
679 std::unique_ptr<base::DictionaryValue> error_data) {
680 ConnectRequest* request = GetPendingRequest(service_path);
681 if (!request) {
682 NET_LOG_ERROR("HandleConfigurationFailure called with no pending request.",
683 service_path);
684 return;
685 }
686 network_handler::ErrorCallback error_callback = request->error_callback;
687 pending_requests_.erase(service_path);
688 InvokeConnectErrorCallback(service_path, error_callback,
689 kErrorConfigureFailed);
690 }
691
692 void NetworkConnectionHandler::HandleShillConnectSuccess(
693 const std::string& service_path) {
694 ConnectRequest* request = GetPendingRequest(service_path);
695 if (!request) {
696 NET_LOG_ERROR("HandleShillConnectSuccess called with no pending request.",
697 service_path);
698 return;
699 }
700 request->connect_state = ConnectRequest::CONNECT_STARTED;
701 NET_LOG_EVENT("Connect Request Acknowledged", service_path);
702 // Do not call success_callback here, wait for one of the following
703 // conditions:
704 // * State transitions to a non connecting state indicating success or failure
705 // * Network is no longer in the visible list, indicating failure
706 CheckPendingRequest(service_path);
707 }
708
709 void NetworkConnectionHandler::HandleShillConnectFailure(
710 const std::string& service_path,
711 const std::string& dbus_error_name,
712 const std::string& dbus_error_message) {
713 ConnectRequest* request = GetPendingRequest(service_path);
714 if (!request) {
715 NET_LOG_ERROR("HandleShillConnectFailure called with no pending request.",
716 service_path);
717 return;
718 }
719 network_handler::ErrorCallback error_callback = request->error_callback;
720 pending_requests_.erase(service_path);
721 std::string error;
722 if (dbus_error_name == shill::kErrorResultAlreadyConnected) {
723 error = kErrorConnected;
724 } else if (dbus_error_name == shill::kErrorResultInProgress) {
725 error = kErrorConnecting;
726 } else {
727 NET_LOG_ERROR("Connect Failure, Shill error: " + dbus_error_name,
728 service_path);
729 error = kErrorConnectFailed;
730 }
731 InvokeConnectErrorCallback(service_path, error_callback, error);
732 }
733
734 void NetworkConnectionHandler::CheckPendingRequest(
735 const std::string service_path) {
736 ConnectRequest* request = GetPendingRequest(service_path);
737 DCHECK(request);
738 if (request->connect_state == ConnectRequest::CONNECT_REQUESTED)
739 return; // Request has not started, ignore update
740 const NetworkState* network =
741 network_state_handler_->GetNetworkState(service_path);
742 if (!network)
743 return; // NetworkState may not be be updated yet.
744
745 if (network->IsConnectingState()) {
746 request->connect_state = ConnectRequest::CONNECT_CONNECTING;
747 return;
748 }
749 if (network->IsConnectedState()) {
750 if (!request->profile_path.empty()) {
751 // If a profile path was specified, set it on a successful connection.
752 configuration_handler_->SetNetworkProfile(
753 service_path,
754 request->profile_path,
755 NetworkConfigurationObserver::SOURCE_USER_ACTION,
756 base::Bind(&base::DoNothing),
757 chromeos::network_handler::ErrorCallback());
758 }
759 InvokeConnectSuccessCallback(request->service_path,
760 request->success_callback);
761 pending_requests_.erase(service_path);
762 return;
763 }
764 if (network->connection_state() == shill::kStateIdle &&
765 request->connect_state != ConnectRequest::CONNECT_CONNECTING) {
766 // Connection hasn't started yet, keep waiting.
767 return;
768 }
769
770 // Network is neither connecting or connected; an error occurred.
771 std::string error_name; // 'Canceled' or 'Failed'
772 if (network->connection_state() == shill::kStateIdle &&
773 pending_requests_.size() > 1) {
774 // Another connect request canceled this one.
775 error_name = kErrorConnectCanceled;
776 } else {
777 error_name = kErrorConnectFailed;
778 if (network->connection_state() != shill::kStateFailure) {
779 NET_LOG_ERROR("Unexpected State: " + network->connection_state(),
780 service_path);
781 }
782 }
783
784 network_handler::ErrorCallback error_callback = request->error_callback;
785 pending_requests_.erase(service_path);
786 InvokeConnectErrorCallback(service_path, error_callback, error_name);
787 }
788
789 void NetworkConnectionHandler::CheckAllPendingRequests() {
790 for (std::map<std::string, ConnectRequest>::iterator iter =
791 pending_requests_.begin(); iter != pending_requests_.end(); ++iter) {
792 CheckPendingRequest(iter->first);
793 }
794 }
795
796 // Connect callbacks
797
798 void NetworkConnectionHandler::InvokeConnectSuccessCallback( 85 void NetworkConnectionHandler::InvokeConnectSuccessCallback(
799 const std::string& service_path, 86 const std::string& service_path,
800 const base::Closure& success_callback) { 87 const base::Closure& success_callback) {
801 NET_LOG_EVENT("Connect Request Succeeded", service_path); 88 NET_LOG_EVENT("Connect Request Succeeded", service_path);
802 if (!success_callback.is_null()) 89 if (!success_callback.is_null())
803 success_callback.Run(); 90 success_callback.Run();
804 for (auto& observer : observers_) 91 for (auto& observer : observers_)
805 observer.ConnectSucceeded(service_path); 92 observer.ConnectSucceeded(service_path);
806 } 93 }
807 94
808 void NetworkConnectionHandler::ErrorCallbackForPendingRequest(
809 const std::string& service_path,
810 const std::string& error_name) {
811 ConnectRequest* request = GetPendingRequest(service_path);
812 if (!request) {
813 NET_LOG_ERROR("ErrorCallbackForPendingRequest with no pending request.",
814 service_path);
815 return;
816 }
817 // Remove the entry before invoking the callback in case it triggers a retry.
818 network_handler::ErrorCallback error_callback = request->error_callback;
819 pending_requests_.erase(service_path);
820 InvokeConnectErrorCallback(service_path, error_callback, error_name);
821 }
822
823 void NetworkConnectionHandler::InvokeConnectErrorCallback( 95 void NetworkConnectionHandler::InvokeConnectErrorCallback(
824 const std::string& service_path, 96 const std::string& service_path,
825 const network_handler::ErrorCallback& error_callback, 97 const network_handler::ErrorCallback& error_callback,
826 const std::string& error_name) { 98 const std::string& error_name) {
827 NET_LOG_ERROR("Connect Failure: " + error_name, service_path); 99 NET_LOG_ERROR("Connect Failure: " + error_name, service_path);
828 network_handler::RunErrorCallback(error_callback, service_path, error_name, 100 network_handler::RunErrorCallback(error_callback, service_path, error_name,
829 ""); 101 "");
830 for (auto& observer : observers_) 102 for (auto& observer : observers_)
831 observer.ConnectFailed(service_path, error_name); 103 observer.ConnectFailed(service_path, error_name);
832 } 104 }
833 105
834 // Disconnect 106 void NetworkConnectionHandler::InitiateTetherNetworkConnection(
835 107 const std::string& tether_network_guid,
836 void NetworkConnectionHandler::CallShillDisconnect(
837 const std::string& service_path,
838 const base::Closure& success_callback, 108 const base::Closure& success_callback,
839 const network_handler::ErrorCallback& error_callback) { 109 const network_handler::ErrorCallback& error_callback) {
840 NET_LOG_USER("Disconnect Request", service_path); 110 DCHECK(tether_delegate_);
841 DBusThreadManager::Get()->GetShillServiceClient()->Disconnect( 111 tether_delegate_->ConnectToNetwork(
842 dbus::ObjectPath(service_path), 112 tether_network_guid,
843 base::Bind(&NetworkConnectionHandler::HandleShillDisconnectSuccess, 113 base::Bind(&NetworkConnectionHandler::InvokeConnectSuccessCallback,
844 AsWeakPtr(), service_path, success_callback), 114 weak_ptr_factory_.GetWeakPtr(), tether_network_guid,
845 base::Bind(&network_handler::ShillErrorCallbackFunction, 115 success_callback),
846 kErrorDisconnectFailed, service_path, error_callback)); 116 base::Bind(&NetworkConnectionHandler::InvokeConnectErrorCallback,
117 weak_ptr_factory_.GetWeakPtr(), tether_network_guid,
118 error_callback));
847 } 119 }
848
849 void NetworkConnectionHandler::HandleShillDisconnectSuccess(
850 const std::string& service_path,
851 const base::Closure& success_callback) {
852 NET_LOG_EVENT("Disconnect Request Sent", service_path);
853 if (!success_callback.is_null())
854 success_callback.Run();
855 }
856
857 } // namespace chromeos 120 } // namespace chromeos
OLDNEW
« no previous file with comments | « chromeos/network/network_connection_handler.h ('k') | chromeos/network/network_connection_handler_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698