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
3 // found in the LICENSE file.
5 #include "ash/system/chromeos/network/network_connect.h"
7 #include "ash/session/session_state_delegate.h"
9 #include "ash/system/chromeos/network/network_state_notifier.h"
10 #include "ash/system/system_notifier.h"
11 #include "ash/system/tray/system_tray_delegate.h"
12 #include "ash/system/tray/system_tray_notifier.h"
13 #include "base/bind.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/values.h"
18 #include "chromeos/login/login_state.h"
19 #include "chromeos/network/device_state.h"
20 #include "chromeos/network/network_activation_handler.h"
21 #include "chromeos/network/network_configuration_handler.h"
22 #include "chromeos/network/network_connection_handler.h"
23 #include "chromeos/network/network_event_log.h"
24 #include "chromeos/network/network_handler_callbacks.h"
25 #include "chromeos/network/network_profile.h"
26 #include "chromeos/network/network_profile_handler.h"
27 #include "chromeos/network/network_state.h"
28 #include "chromeos/network/network_state_handler.h"
29 #include "grit/ash_resources.h"
30 #include "grit/ash_strings.h"
31 #include "third_party/cros_system_api/dbus/service_constants.h"
32 #include "ui/base/l10n/l10n_util.h"
33 #include "ui/base/resource/resource_bundle.h"
34 #include "ui/message_center/message_center.h"
35 #include "ui/message_center/notification.h"
37 using chromeos::DeviceState
;
38 using chromeos::NetworkConfigurationHandler
;
39 using chromeos::NetworkConnectionHandler
;
40 using chromeos::NetworkHandler
;
41 using chromeos::NetworkProfile
;
42 using chromeos::NetworkProfileHandler
;
43 using chromeos::NetworkState
;
44 using chromeos::NetworkStateHandler
;
45 using chromeos::NetworkTypePattern
;
51 // TODO(stevenjb): This should be in service_constants.h
52 const char kErrorInProgress
[] = "org.chromium.flimflam.Error.InProgress";
54 // Returns true for carriers that can be activated through Shill instead of
55 // through a WebUI dialog.
56 bool IsDirectActivatedCarrier(const std::string
& carrier
) {
57 if (carrier
== shill::kCarrierSprint
)
62 void ShowErrorNotification(const std::string
& error_name
,
63 const std::string
& service_path
) {
64 Shell::GetInstance()->system_tray_notifier()->network_state_notifier()->
65 ShowNetworkConnectError(error_name
, service_path
);
68 void HandleUnconfiguredNetwork(const std::string
& service_path
,
69 gfx::NativeWindow parent_window
) {
70 const NetworkState
* network
= NetworkHandler::Get()->network_state_handler()->
71 GetNetworkState(service_path
);
73 NET_LOG_ERROR("Configuring unknown network", service_path
);
77 if (network
->type() == shill::kTypeWifi
) {
78 // Only show the config view for secure networks, otherwise do nothing.
79 if (network
->security() != shill::kSecurityNone
) {
80 ash::Shell::GetInstance()->system_tray_delegate()->
81 ShowNetworkConfigure(service_path
, parent_window
);
86 if (network
->type() == shill::kTypeWimax
||
87 network
->type() == shill::kTypeVPN
) {
88 ash::Shell::GetInstance()->system_tray_delegate()->
89 ShowNetworkConfigure(service_path
, parent_window
);
93 if (network
->type() == shill::kTypeCellular
) {
94 if (network
->RequiresActivation()) {
95 ash::network_connect::ActivateCellular(service_path
);
98 if (network
->cellular_out_of_credits()) {
99 ash::network_connect::ShowMobileSetup(service_path
);
102 // No special configure or setup for |network|, show the settings UI.
103 if (chromeos::LoginState::Get()->IsUserLoggedIn()) {
104 ash::Shell::GetInstance()->system_tray_delegate()->
105 ShowNetworkSettings(service_path
);
112 // If |shared| is true, sets |profile_path| to the shared profile path.
113 // Otherwise sets |profile_path| to the user profile path if authenticated and
114 // available. Returns 'false' if unable to set |profile_path|.
115 bool GetNetworkProfilePath(bool shared
, std::string
* profile_path
) {
117 *profile_path
= NetworkProfileHandler::GetSharedProfilePath();
121 if (!chromeos::LoginState::Get()->UserHasNetworkProfile()) {
122 NET_LOG_ERROR("User profile specified before login", "");
126 const NetworkProfile
* profile
=
127 NetworkHandler::Get()->network_profile_handler()->
128 GetDefaultUserProfile();
130 NET_LOG_ERROR("No user profile for unshared network configuration", "");
134 *profile_path
= profile
->path
;
138 void OnConnectFailed(const std::string
& service_path
,
139 gfx::NativeWindow parent_window
,
140 const std::string
& error_name
,
141 scoped_ptr
<base::DictionaryValue
> error_data
) {
142 NET_LOG_ERROR("Connect Failed: " + error_name
, service_path
);
144 if (!ash::Shell::HasInstance())
147 // If a new connect attempt canceled this connect, no need to notify the user.
148 if (error_name
== NetworkConnectionHandler::kErrorConnectCanceled
)
151 if (error_name
== shill::kErrorBadPassphrase
||
152 error_name
== NetworkConnectionHandler::kErrorPassphraseRequired
||
153 error_name
== NetworkConnectionHandler::kErrorConfigurationRequired
||
154 error_name
== NetworkConnectionHandler::kErrorAuthenticationRequired
) {
155 HandleUnconfiguredNetwork(service_path
, parent_window
);
159 if (error_name
== NetworkConnectionHandler::kErrorCertificateRequired
) {
160 if (!ash::Shell::GetInstance()->system_tray_delegate()->EnrollNetwork(
161 service_path
, parent_window
)) {
162 HandleUnconfiguredNetwork(service_path
, parent_window
);
167 if (error_name
== NetworkConnectionHandler::kErrorActivationRequired
) {
168 network_connect::ActivateCellular(service_path
);
172 if (error_name
== NetworkConnectionHandler::kErrorConnected
||
173 error_name
== NetworkConnectionHandler::kErrorConnecting
) {
174 network_connect::ShowNetworkSettings(service_path
);
178 // ConnectFailed or unknown error; show a notification.
179 ShowErrorNotification(error_name
, service_path
);
181 // Only show a configure dialog if there was a ConnectFailed error and the
182 // screen is not locked.
183 if (error_name
!= shill::kErrorConnectFailed
||
184 Shell::GetInstance()->session_state_delegate()->IsScreenLocked())
187 // If Shill reports an InProgress error, don't try to configure the network.
188 std::string dbus_error_name
;
189 error_data
.get()->GetString(
190 chromeos::network_handler::kDbusErrorName
, &dbus_error_name
);
191 if (dbus_error_name
== kErrorInProgress
)
194 HandleUnconfiguredNetwork(service_path
, parent_window
);
197 void OnConnectSucceeded(const std::string
& service_path
) {
198 NET_LOG_USER("Connect Succeeded", service_path
);
199 if (!ash::Shell::HasInstance())
201 message_center::MessageCenter::Get()->RemoveNotification(
202 network_connect::kNetworkConnectNotificationId
, false /* not by user */);
205 // If |check_error_state| is true, error state for the network is checked,
206 // otherwise any current error state is ignored (e.g. for recently configured
207 // networks or repeat connect attempts). |parent_window| will be used to parent
208 // any configuration UI on failure and may be NULL (in which case the default
209 // window will be used).
210 void CallConnectToNetwork(const std::string
& service_path
,
211 bool check_error_state
,
212 gfx::NativeWindow parent_window
) {
213 if (!ash::Shell::HasInstance())
215 message_center::MessageCenter::Get()->RemoveNotification(
216 network_connect::kNetworkConnectNotificationId
, false /* not by user */);
218 NetworkHandler::Get()->network_connection_handler()->ConnectToNetwork(
220 base::Bind(&OnConnectSucceeded
, service_path
),
221 base::Bind(&OnConnectFailed
, service_path
, parent_window
),
225 void OnActivateFailed(const std::string
& service_path
,
226 const std::string
& error_name
,
227 scoped_ptr
<base::DictionaryValue
> error_data
) {
228 NET_LOG_ERROR("Unable to activate network", service_path
);
229 ShowErrorNotification(network_connect::kErrorActivateFailed
, service_path
);
232 void OnActivateSucceeded(const std::string
& service_path
) {
233 NET_LOG_USER("Activation Succeeded", service_path
);
236 void OnConfigureFailed(const std::string
& error_name
,
237 scoped_ptr
<base::DictionaryValue
> error_data
) {
238 NET_LOG_ERROR("Unable to configure network", "");
239 ShowErrorNotification(NetworkConnectionHandler::kErrorConfigureFailed
, "");
242 void OnConfigureSucceeded(bool connect_on_configure
,
243 const std::string
& service_path
) {
244 NET_LOG_USER("Configure Succeeded", service_path
);
245 if (!connect_on_configure
)
247 // After configuring a network, ignore any (possibly stale) error state.
248 const bool check_error_state
= false;
249 const gfx::NativeWindow parent_window
= NULL
;
250 CallConnectToNetwork(service_path
, check_error_state
, parent_window
);
253 void CallCreateConfiguration(base::DictionaryValue
* properties
,
255 bool connect_on_configure
) {
256 std::string profile_path
;
257 if (!GetNetworkProfilePath(shared
, &profile_path
)) {
258 ShowErrorNotification(NetworkConnectionHandler::kErrorConfigureFailed
, "");
261 properties
->SetStringWithoutPathExpansion(
262 shill::kProfileProperty
, profile_path
);
263 NetworkHandler::Get()->network_configuration_handler()->CreateConfiguration(
265 base::Bind(&OnConfigureSucceeded
, connect_on_configure
),
266 base::Bind(&OnConfigureFailed
));
269 void SetPropertiesFailed(const std::string
& desc
,
270 const std::string
& service_path
,
271 const std::string
& config_error_name
,
272 scoped_ptr
<base::DictionaryValue
> error_data
) {
273 NET_LOG_ERROR(desc
+ ": Failed: " + config_error_name
, service_path
);
274 ShowErrorNotification(
275 NetworkConnectionHandler::kErrorConfigureFailed
, service_path
);
278 void SetPropertiesToClear(base::DictionaryValue
* properties_to_set
,
279 std::vector
<std::string
>* properties_to_clear
) {
280 // Move empty string properties to properties_to_clear.
281 for (base::DictionaryValue::Iterator
iter(*properties_to_set
);
282 !iter
.IsAtEnd(); iter
.Advance()) {
283 std::string value_str
;
284 if (iter
.value().GetAsString(&value_str
) && value_str
.empty())
285 properties_to_clear
->push_back(iter
.key());
287 // Remove cleared properties from properties_to_set.
288 for (std::vector
<std::string
>::iterator iter
= properties_to_clear
->begin();
289 iter
!= properties_to_clear
->end(); ++iter
) {
290 properties_to_set
->RemoveWithoutPathExpansion(*iter
, NULL
);
294 void ClearPropertiesAndConnect(
295 const std::string
& service_path
,
296 const std::vector
<std::string
>& properties_to_clear
) {
297 NET_LOG_USER("ClearPropertiesAndConnect", service_path
);
298 // After configuring a network, ignore any (possibly stale) error state.
299 const bool check_error_state
= false;
300 const gfx::NativeWindow parent_window
= NULL
;
301 NetworkHandler::Get()->network_configuration_handler()->ClearProperties(
304 base::Bind(&CallConnectToNetwork
,
305 service_path
, check_error_state
,
307 base::Bind(&SetPropertiesFailed
, "ClearProperties", service_path
));
310 void ConfigureSetProfileSucceeded(
311 const std::string
& service_path
,
312 scoped_ptr
<base::DictionaryValue
> properties_to_set
) {
313 std::vector
<std::string
> properties_to_clear
;
314 SetPropertiesToClear(properties_to_set
.get(), &properties_to_clear
);
315 NetworkHandler::Get()->network_configuration_handler()->SetProperties(
318 base::Bind(&ClearPropertiesAndConnect
,
320 properties_to_clear
),
321 base::Bind(&SetPropertiesFailed
, "SetProperties", service_path
));
324 const NetworkState
* GetNetworkState(const std::string
& service_path
) {
325 return NetworkHandler::Get()->network_state_handler()->
326 GetNetworkState(service_path
);
331 namespace network_connect
{
333 const char kNetworkConnectNotificationId
[] =
334 "chrome://settings/internet/connect";
335 const char kNetworkActivateNotificationId
[] =
336 "chrome://settings/internet/activate";
338 const char kErrorActivateFailed
[] = "activate-failed";
340 void ConnectToNetwork(const std::string
& service_path
,
341 gfx::NativeWindow parent_window
) {
342 NET_LOG_USER("ConnectToNetwork", service_path
);
343 const NetworkState
* network
= GetNetworkState(service_path
);
345 if (!network
->error().empty() && !network
->security().empty()) {
346 NET_LOG_USER("Configure: " + network
->error(), service_path
);
347 // If the network is in an error state, show the configuration UI directly
348 // to avoid a spurious notification.
349 HandleUnconfiguredNetwork(service_path
, parent_window
);
351 } else if (network
->RequiresActivation()) {
352 ActivateCellular(service_path
);
356 const bool check_error_state
= true;
357 CallConnectToNetwork(service_path
, check_error_state
, parent_window
);
360 void SetTechnologyEnabled(const NetworkTypePattern
& technology
,
361 bool enabled_state
) {
362 std::string log_string
=
363 base::StringPrintf("technology %s, target state: %s",
364 technology
.ToDebugString().c_str(),
365 (enabled_state
? "ENABLED" : "DISABLED"));
366 NET_LOG_USER("SetTechnologyEnabled", log_string
);
367 NetworkStateHandler
* handler
= NetworkHandler::Get()->network_state_handler();
368 bool enabled
= handler
->IsTechnologyEnabled(technology
);
369 if (enabled_state
== enabled
) {
370 NET_LOG_USER("Technology already in target state.", log_string
);
374 // User requested to disable the technology.
375 handler
->SetTechnologyEnabled(
376 technology
, false, chromeos::network_handler::ErrorCallback());
379 // If we're dealing with a mobile network, then handle SIM lock here.
380 // SIM locking only applies to cellular, so the code below won't execute
381 // if |technology| has been explicitly set to WiMAX.
382 if (technology
.MatchesPattern(NetworkTypePattern::Mobile())) {
383 const DeviceState
* mobile
= handler
->GetDeviceStateByType(technology
);
385 NET_LOG_ERROR("SetTechnologyEnabled with no device", log_string
);
388 // The following only applies to cellular.
389 if (mobile
->type() == shill::kTypeCellular
) {
390 if (mobile
->IsSimAbsent()) {
391 // If this is true, then we have a cellular device with no SIM inserted.
392 // TODO(armansito): Chrome should display a notification here, prompting
393 // the user to insert a SIM card and restart the device to enable
394 // cellular. See crbug.com/125171.
395 NET_LOG_USER("Cannot enable cellular device without SIM.", log_string
);
398 if (!mobile
->sim_lock_type().empty()) {
399 // A SIM has been inserted, but it is locked. Let the user unlock it
401 ash::Shell::GetInstance()->system_tray_delegate()->
402 ShowMobileSimDialog();
407 handler
->SetTechnologyEnabled(
408 technology
, true, chromeos::network_handler::ErrorCallback());
411 void ActivateCellular(const std::string
& service_path
) {
412 NET_LOG_USER("ActivateCellular", service_path
);
413 const NetworkState
* cellular
= GetNetworkState(service_path
);
414 if (!cellular
|| cellular
->type() != shill::kTypeCellular
) {
415 NET_LOG_ERROR("ActivateCellular with no Service", service_path
);
418 const DeviceState
* cellular_device
=
419 NetworkHandler::Get()->network_state_handler()->
420 GetDeviceState(cellular
->device_path());
421 if (!cellular_device
) {
422 NET_LOG_ERROR("ActivateCellular with no Device", service_path
);
425 if (!IsDirectActivatedCarrier(cellular_device
->carrier())) {
426 // For non direct activation, show the mobile setup dialog which can be
427 // used to activate the network.
428 ShowMobileSetup(service_path
);
431 if (cellular
->activation_state() == shill::kActivationStateActivated
) {
432 NET_LOG_ERROR("ActivateCellular for activated service", service_path
);
436 NetworkHandler::Get()->network_activation_handler()->Activate(
439 base::Bind(&OnActivateSucceeded
, service_path
),
440 base::Bind(&OnActivateFailed
, service_path
));
443 void ShowMobileSetup(const std::string
& service_path
) {
444 NetworkStateHandler
* handler
= NetworkHandler::Get()->network_state_handler();
445 const NetworkState
* cellular
= handler
->GetNetworkState(service_path
);
446 if (!cellular
|| cellular
->type() != shill::kTypeCellular
) {
447 NET_LOG_ERROR("ShowMobileSetup without Cellular network", service_path
);
450 if (cellular
->activation_state() != shill::kActivationStateActivated
&&
451 cellular
->activation_type() == shill::kActivationTypeNonCellular
&&
452 !handler
->DefaultNetwork()) {
453 message_center::MessageCenter::Get()->AddNotification(
454 message_center::Notification::CreateSystemNotification(
455 kNetworkActivateNotificationId
,
456 l10n_util::GetStringUTF16(IDS_NETWORK_ACTIVATION_ERROR_TITLE
),
457 l10n_util::GetStringFUTF16(IDS_NETWORK_ACTIVATION_NEEDS_CONNECTION
,
458 base::UTF8ToUTF16(cellular
->name())),
459 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
460 IDR_AURA_UBER_TRAY_CELLULAR_NETWORK_FAILED
),
461 ash::system_notifier::kNotifierNetworkError
,
462 base::Bind(&ash::network_connect::ShowNetworkSettings
,
466 ash::Shell::GetInstance()->system_tray_delegate()->ShowMobileSetupDialog(
470 void ConfigureNetworkAndConnect(const std::string
& service_path
,
471 const base::DictionaryValue
& properties
,
473 NET_LOG_USER("ConfigureNetworkAndConnect", service_path
);
475 scoped_ptr
<base::DictionaryValue
> properties_to_set(properties
.DeepCopy());
477 std::string profile_path
;
478 if (!GetNetworkProfilePath(shared
, &profile_path
)) {
479 ShowErrorNotification(
480 NetworkConnectionHandler::kErrorConfigureFailed
, service_path
);
483 NetworkHandler::Get()->network_configuration_handler()->SetNetworkProfile(
484 service_path
, profile_path
,
485 base::Bind(&ConfigureSetProfileSucceeded
,
486 service_path
, base::Passed(&properties_to_set
)),
487 base::Bind(&SetPropertiesFailed
,
488 "SetProfile: " + profile_path
, service_path
));
491 void CreateConfigurationAndConnect(base::DictionaryValue
* properties
,
493 NET_LOG_USER("CreateConfigurationAndConnect", "");
494 CallCreateConfiguration(properties
, shared
, true /* connect_on_configure */);
497 void CreateConfiguration(base::DictionaryValue
* properties
, bool shared
) {
498 NET_LOG_USER("CreateConfiguration", "");
499 CallCreateConfiguration(properties
, shared
, false /* connect_on_configure */);
502 base::string16
ErrorString(const std::string
& error
,
503 const std::string
& service_path
) {
505 return base::string16();
506 if (error
== shill::kErrorOutOfRange
)
507 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_OUT_OF_RANGE
);
508 if (error
== shill::kErrorPinMissing
)
509 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_PIN_MISSING
);
510 if (error
== shill::kErrorDhcpFailed
)
511 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_DHCP_FAILED
);
512 if (error
== shill::kErrorConnectFailed
)
513 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_CONNECT_FAILED
);
514 if (error
== shill::kErrorBadPassphrase
)
515 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_BAD_PASSPHRASE
);
516 if (error
== shill::kErrorBadWEPKey
)
517 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_BAD_WEPKEY
);
518 if (error
== shill::kErrorActivationFailed
) {
519 return l10n_util::GetStringUTF16(
520 IDS_CHROMEOS_NETWORK_ERROR_ACTIVATION_FAILED
);
522 if (error
== shill::kErrorNeedEvdo
)
523 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_NEED_EVDO
);
524 if (error
== shill::kErrorNeedHomeNetwork
) {
525 return l10n_util::GetStringUTF16(
526 IDS_CHROMEOS_NETWORK_ERROR_NEED_HOME_NETWORK
);
528 if (error
== shill::kErrorOtaspFailed
)
529 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_OTASP_FAILED
);
530 if (error
== shill::kErrorAaaFailed
)
531 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_AAA_FAILED
);
532 if (error
== shill::kErrorInternal
)
533 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_INTERNAL
);
534 if (error
== shill::kErrorDNSLookupFailed
) {
535 return l10n_util::GetStringUTF16(
536 IDS_CHROMEOS_NETWORK_ERROR_DNS_LOOKUP_FAILED
);
538 if (error
== shill::kErrorHTTPGetFailed
) {
539 return l10n_util::GetStringUTF16(
540 IDS_CHROMEOS_NETWORK_ERROR_HTTP_GET_FAILED
);
542 if (error
== shill::kErrorIpsecPskAuthFailed
) {
543 return l10n_util::GetStringUTF16(
544 IDS_CHROMEOS_NETWORK_ERROR_IPSEC_PSK_AUTH_FAILED
);
546 if (error
== shill::kErrorIpsecCertAuthFailed
) {
547 return l10n_util::GetStringUTF16(
548 IDS_CHROMEOS_NETWORK_ERROR_CERT_AUTH_FAILED
);
550 if (error
== shill::kErrorEapAuthenticationFailed
) {
551 const NetworkState
* network
= GetNetworkState(service_path
);
552 // TLS always requires a client certificate, so show a cert auth
553 // failed message for TLS. Other EAP methods do not generally require
554 // a client certicate.
555 if (network
&& network
->eap_method() == shill::kEapMethodTLS
) {
556 return l10n_util::GetStringUTF16(
557 IDS_CHROMEOS_NETWORK_ERROR_CERT_AUTH_FAILED
);
559 return l10n_util::GetStringUTF16(
560 IDS_CHROMEOS_NETWORK_ERROR_EAP_AUTH_FAILED
);
563 if (error
== shill::kErrorEapLocalTlsFailed
) {
564 return l10n_util::GetStringUTF16(
565 IDS_CHROMEOS_NETWORK_ERROR_EAP_LOCAL_TLS_FAILED
);
567 if (error
== shill::kErrorEapRemoteTlsFailed
) {
568 return l10n_util::GetStringUTF16(
569 IDS_CHROMEOS_NETWORK_ERROR_EAP_REMOTE_TLS_FAILED
);
571 if (error
== shill::kErrorPppAuthFailed
) {
572 return l10n_util::GetStringUTF16(
573 IDS_CHROMEOS_NETWORK_ERROR_PPP_AUTH_FAILED
);
576 if (base::StringToLowerASCII(error
) ==
577 base::StringToLowerASCII(std::string(shill::kUnknownString
))) {
578 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_UNKNOWN
);
580 return l10n_util::GetStringFUTF16(IDS_NETWORK_UNRECOGNIZED_ERROR
,
581 base::UTF8ToUTF16(error
));
584 void ShowNetworkSettings(const std::string
& service_path
) {
585 if (!ash::Shell::HasInstance())
587 ash::Shell::GetInstance()->system_tray_delegate()->ShowNetworkSettings(