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. 4 5 #include "ash/system/chromeos/network/network_connect.h" 6 7 #include "ash/session/session_state_delegate.h" 8 #include "ash/shell.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/utf_string_conversions.h" 16 #include "base/values.h" 17 #include "chromeos/login/login_state.h" 18 #include "chromeos/network/device_state.h" 19 #include "chromeos/network/network_activation_handler.h" 20 #include "chromeos/network/network_configuration_handler.h" 21 #include "chromeos/network/network_connection_handler.h" 22 #include "chromeos/network/network_event_log.h" 23 #include "chromeos/network/network_handler_callbacks.h" 24 #include "chromeos/network/network_profile.h" 25 #include "chromeos/network/network_profile_handler.h" 26 #include "chromeos/network/network_state.h" 27 #include "chromeos/network/network_state_handler.h" 28 #include "grit/ash_resources.h" 29 #include "grit/ash_strings.h" 30 #include "third_party/cros_system_api/dbus/service_constants.h" 31 #include "ui/base/l10n/l10n_util.h" 32 #include "ui/base/resource/resource_bundle.h" 33 #include "ui/message_center/message_center.h" 34 #include "ui/message_center/notification.h" 35 36 using chromeos::DeviceState; 37 using chromeos::NetworkConfigurationHandler; 38 using chromeos::NetworkConnectionHandler; 39 using chromeos::NetworkHandler; 40 using chromeos::NetworkProfile; 41 using chromeos::NetworkProfileHandler; 42 using chromeos::NetworkState; 43 using chromeos::NetworkStateHandler; 44 using chromeos::NetworkTypePattern; 45 46 namespace ash { 47 48 namespace { 49 50 // TODO(stevenjb): This should be in service_constants.h 51 const char kErrorInProgress[] = "org.chromium.flimflam.Error.InProgress"; 52 53 // Returns true for carriers that can be activated through Shill instead of 54 // through a WebUI dialog. 55 bool IsDirectActivatedCarrier(const std::string& carrier) { 56 if (carrier == shill::kCarrierSprint) 57 return true; 58 return false; 59 } 60 61 void ShowErrorNotification(const std::string& error_name, 62 const std::string& service_path) { 63 Shell::GetInstance()->system_tray_notifier()->network_state_notifier()-> 64 ShowNetworkConnectError(error_name, service_path); 65 } 66 67 void HandleUnconfiguredNetwork(const std::string& service_path, 68 gfx::NativeWindow parent_window) { 69 const NetworkState* network = NetworkHandler::Get()->network_state_handler()-> 70 GetNetworkState(service_path); 71 if (!network) { 72 NET_LOG_ERROR("Configuring unknown network", service_path); 73 return; 74 } 75 76 if (network->type() == shill::kTypeWifi) { 77 // Only show the config view for secure networks, otherwise do nothing. 78 if (network->security() != shill::kSecurityNone) { 79 ash::Shell::GetInstance()->system_tray_delegate()-> 80 ShowNetworkConfigure(service_path, parent_window); 81 } 82 return; 83 } 84 85 if (network->type() == shill::kTypeWimax || 86 network->type() == shill::kTypeVPN) { 87 ash::Shell::GetInstance()->system_tray_delegate()-> 88 ShowNetworkConfigure(service_path, parent_window); 89 return; 90 } 91 92 if (network->type() == shill::kTypeCellular) { 93 if (network->RequiresActivation()) { 94 ash::network_connect::ActivateCellular(service_path); 95 return; 96 } 97 if (network->cellular_out_of_credits()) { 98 ash::network_connect::ShowMobileSetup(service_path); 99 return; 100 } 101 // No special configure or setup for |network|, show the settings UI. 102 if (chromeos::LoginState::Get()->IsUserLoggedIn()) { 103 ash::Shell::GetInstance()->system_tray_delegate()-> 104 ShowNetworkSettings(service_path); 105 } 106 return; 107 } 108 NOTREACHED(); 109 } 110 111 // If |shared| is true, sets |profile_path| to the shared profile path. 112 // Otherwise sets |profile_path| to the user profile path if authenticated and 113 // available. Returns 'false' if unable to set |profile_path|. 114 bool GetNetworkProfilePath(bool shared, std::string* profile_path) { 115 if (shared) { 116 *profile_path = NetworkProfileHandler::GetSharedProfilePath(); 117 return true; 118 } 119 120 if (!chromeos::LoginState::Get()->UserHasNetworkProfile()) { 121 NET_LOG_ERROR("User profile specified before login", ""); 122 return false; 123 } 124 125 const NetworkProfile* profile = 126 NetworkHandler::Get()->network_profile_handler()-> 127 GetDefaultUserProfile(); 128 if (!profile) { 129 NET_LOG_ERROR("No user profile for unshared network configuration", ""); 130 return false; 131 } 132 133 *profile_path = profile->path; 134 return true; 135 } 136 137 void OnConnectFailed(const std::string& service_path, 138 gfx::NativeWindow parent_window, 139 const std::string& error_name, 140 scoped_ptr<base::DictionaryValue> error_data) { 141 NET_LOG_ERROR("Connect Failed: " + error_name, service_path); 142 143 if (!ash::Shell::HasInstance()) 144 return; 145 146 // If a new connect attempt canceled this connect, no need to notify the user. 147 if (error_name == NetworkConnectionHandler::kErrorConnectCanceled) 148 return; 149 150 if (error_name == shill::kErrorBadPassphrase || 151 error_name == NetworkConnectionHandler::kErrorPassphraseRequired || 152 error_name == NetworkConnectionHandler::kErrorConfigurationRequired || 153 error_name == NetworkConnectionHandler::kErrorAuthenticationRequired) { 154 HandleUnconfiguredNetwork(service_path, parent_window); 155 return; 156 } 157 158 if (error_name == NetworkConnectionHandler::kErrorCertificateRequired) { 159 if (!ash::Shell::GetInstance()->system_tray_delegate()->EnrollNetwork( 160 service_path, parent_window)) { 161 HandleUnconfiguredNetwork(service_path, parent_window); 162 } 163 return; 164 } 165 166 if (error_name == NetworkConnectionHandler::kErrorActivationRequired) { 167 network_connect::ActivateCellular(service_path); 168 return; 169 } 170 171 if (error_name == NetworkConnectionHandler::kErrorConnected || 172 error_name == NetworkConnectionHandler::kErrorConnecting) { 173 network_connect::ShowNetworkSettings(service_path); 174 return; 175 } 176 177 // ConnectFailed or unknown error; show a notification. 178 ShowErrorNotification(error_name, service_path); 179 180 // Only show a configure dialog if there was a ConnectFailed error and the 181 // screen is not locked. 182 if (error_name != shill::kErrorConnectFailed || 183 Shell::GetInstance()->session_state_delegate()->IsScreenLocked()) 184 return; 185 186 // If Shill reports an InProgress error, don't try to configure the network. 187 std::string dbus_error_name; 188 error_data.get()->GetString( 189 chromeos::network_handler::kDbusErrorName, &dbus_error_name); 190 if (dbus_error_name == kErrorInProgress) 191 return; 192 193 HandleUnconfiguredNetwork(service_path, parent_window); 194 } 195 196 void OnConnectSucceeded(const std::string& service_path) { 197 NET_LOG_USER("Connect Succeeded", service_path); 198 if (!ash::Shell::HasInstance()) 199 return; 200 message_center::MessageCenter::Get()->RemoveNotification( 201 network_connect::kNetworkConnectNotificationId, false /* not by user */); 202 } 203 204 // If |check_error_state| is true, error state for the network is checked, 205 // otherwise any current error state is ignored (e.g. for recently configured 206 // networks or repeat connect attempts). |parent_window| will be used to parent 207 // any configuration UI on failure and may be NULL (in which case the default 208 // window will be used). 209 void CallConnectToNetwork(const std::string& service_path, 210 bool check_error_state, 211 gfx::NativeWindow parent_window) { 212 if (!ash::Shell::HasInstance()) 213 return; 214 message_center::MessageCenter::Get()->RemoveNotification( 215 network_connect::kNetworkConnectNotificationId, false /* not by user */); 216 217 NetworkHandler::Get()->network_connection_handler()->ConnectToNetwork( 218 service_path, 219 base::Bind(&OnConnectSucceeded, service_path), 220 base::Bind(&OnConnectFailed, service_path, parent_window), 221 check_error_state); 222 } 223 224 void OnActivateFailed(const std::string& service_path, 225 const std::string& error_name, 226 scoped_ptr<base::DictionaryValue> error_data) { 227 NET_LOG_ERROR("Unable to activate network", service_path); 228 ShowErrorNotification(network_connect::kErrorActivateFailed, service_path); 229 } 230 231 void OnActivateSucceeded(const std::string& service_path) { 232 NET_LOG_USER("Activation Succeeded", service_path); 233 } 234 235 void OnConfigureFailed(const std::string& error_name, 236 scoped_ptr<base::DictionaryValue> error_data) { 237 NET_LOG_ERROR("Unable to configure network", ""); 238 ShowErrorNotification(NetworkConnectionHandler::kErrorConfigureFailed, ""); 239 } 240 241 void OnConfigureSucceeded(bool connect_on_configure, 242 const std::string& service_path) { 243 NET_LOG_USER("Configure Succeeded", service_path); 244 if (!connect_on_configure) 245 return; 246 // After configuring a network, ignore any (possibly stale) error state. 247 const bool check_error_state = false; 248 const gfx::NativeWindow parent_window = NULL; 249 CallConnectToNetwork(service_path, check_error_state, parent_window); 250 } 251 252 void CallCreateConfiguration(base::DictionaryValue* properties, 253 bool shared, 254 bool connect_on_configure) { 255 std::string profile_path; 256 if (!GetNetworkProfilePath(shared, &profile_path)) { 257 ShowErrorNotification(NetworkConnectionHandler::kErrorConfigureFailed, ""); 258 return; 259 } 260 properties->SetStringWithoutPathExpansion( 261 shill::kProfileProperty, profile_path); 262 NetworkHandler::Get()->network_configuration_handler()->CreateConfiguration( 263 *properties, 264 base::Bind(&OnConfigureSucceeded, connect_on_configure), 265 base::Bind(&OnConfigureFailed)); 266 } 267 268 void SetPropertiesFailed(const std::string& desc, 269 const std::string& service_path, 270 const std::string& config_error_name, 271 scoped_ptr<base::DictionaryValue> error_data) { 272 NET_LOG_ERROR(desc + ": Failed: " + config_error_name, service_path); 273 ShowErrorNotification( 274 NetworkConnectionHandler::kErrorConfigureFailed, service_path); 275 } 276 277 void SetPropertiesToClear(base::DictionaryValue* properties_to_set, 278 std::vector<std::string>* properties_to_clear) { 279 // Move empty string properties to properties_to_clear. 280 for (base::DictionaryValue::Iterator iter(*properties_to_set); 281 !iter.IsAtEnd(); iter.Advance()) { 282 std::string value_str; 283 if (iter.value().GetAsString(&value_str) && value_str.empty()) 284 properties_to_clear->push_back(iter.key()); 285 } 286 // Remove cleared properties from properties_to_set. 287 for (std::vector<std::string>::iterator iter = properties_to_clear->begin(); 288 iter != properties_to_clear->end(); ++iter) { 289 properties_to_set->RemoveWithoutPathExpansion(*iter, NULL); 290 } 291 } 292 293 void ClearPropertiesAndConnect( 294 const std::string& service_path, 295 const std::vector<std::string>& properties_to_clear) { 296 NET_LOG_USER("ClearPropertiesAndConnect", service_path); 297 // After configuring a network, ignore any (possibly stale) error state. 298 const bool check_error_state = false; 299 const gfx::NativeWindow parent_window = NULL; 300 NetworkHandler::Get()->network_configuration_handler()->ClearProperties( 301 service_path, 302 properties_to_clear, 303 base::Bind(&CallConnectToNetwork, 304 service_path, check_error_state, 305 parent_window), 306 base::Bind(&SetPropertiesFailed, "ClearProperties", service_path)); 307 } 308 309 void ConfigureSetProfileSucceeded( 310 const std::string& service_path, 311 scoped_ptr<base::DictionaryValue> properties_to_set) { 312 std::vector<std::string> properties_to_clear; 313 SetPropertiesToClear(properties_to_set.get(), &properties_to_clear); 314 NetworkHandler::Get()->network_configuration_handler()->SetProperties( 315 service_path, 316 *properties_to_set, 317 base::Bind(&ClearPropertiesAndConnect, 318 service_path, 319 properties_to_clear), 320 base::Bind(&SetPropertiesFailed, "SetProperties", service_path)); 321 } 322 323 const NetworkState* GetNetworkState(const std::string& service_path) { 324 return NetworkHandler::Get()->network_state_handler()-> 325 GetNetworkState(service_path); 326 } 327 328 } // namespace 329 330 namespace network_connect { 331 332 const char kNetworkConnectNotificationId[] = 333 "chrome://settings/internet/connect"; 334 const char kNetworkActivateNotificationId[] = 335 "chrome://settings/internet/activate"; 336 337 const char kErrorActivateFailed[] = "activate-failed"; 338 339 void ConnectToNetwork(const std::string& service_path, 340 gfx::NativeWindow parent_window) { 341 NET_LOG_USER("ConnectToNetwork", service_path); 342 const NetworkState* network = GetNetworkState(service_path); 343 if (network && !network->error().empty() && !network->security().empty()) { 344 NET_LOG_USER("Configure: " + network->error(), service_path); 345 // If the network is in an error state, show the configuration UI directly 346 // to avoid a spurious notification. 347 HandleUnconfiguredNetwork(service_path, parent_window); 348 return; 349 } 350 const bool check_error_state = true; 351 CallConnectToNetwork(service_path, check_error_state, parent_window); 352 } 353 354 void SetTechnologyEnabled(const NetworkTypePattern& technology, 355 bool enabled_state) { 356 std::string log_string = 357 base::StringPrintf("technology %s, target state: %s", 358 technology.ToDebugString().c_str(), 359 (enabled_state ? "ENABLED" : "DISABLED")); 360 NET_LOG_USER("SetTechnologyEnabled", log_string); 361 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler(); 362 bool enabled = handler->IsTechnologyEnabled(technology); 363 if (enabled_state == enabled) { 364 NET_LOG_USER("Technology already in target state.", log_string); 365 return; 366 } 367 if (enabled) { 368 // User requested to disable the technology. 369 handler->SetTechnologyEnabled( 370 technology, false, chromeos::network_handler::ErrorCallback()); 371 return; 372 } 373 // If we're dealing with a mobile network, then handle SIM lock here. 374 // SIM locking only applies to cellular, so the code below won't execute 375 // if |technology| has been explicitly set to WiMAX. 376 if (technology.MatchesPattern(NetworkTypePattern::Mobile())) { 377 const DeviceState* mobile = handler->GetDeviceStateByType(technology); 378 if (!mobile) { 379 NET_LOG_ERROR("SetTechnologyEnabled with no device", log_string); 380 return; 381 } 382 // The following only applies to cellular. 383 if (mobile->type() == shill::kTypeCellular) { 384 if (mobile->IsSimAbsent()) { 385 // If this is true, then we have a cellular device with no SIM inserted. 386 // TODO(armansito): Chrome should display a notification here, prompting 387 // the user to insert a SIM card and restart the device to enable 388 // cellular. See crbug.com/125171. 389 NET_LOG_USER("Cannot enable cellular device without SIM.", log_string); 390 return; 391 } 392 if (!mobile->sim_lock_type().empty()) { 393 // A SIM has been inserted, but it is locked. Let the user unlock it 394 // via the dialog. 395 ash::Shell::GetInstance()->system_tray_delegate()-> 396 ShowMobileSimDialog(); 397 return; 398 } 399 } 400 } 401 handler->SetTechnologyEnabled( 402 technology, true, chromeos::network_handler::ErrorCallback()); 403 } 404 405 void ActivateCellular(const std::string& service_path) { 406 NET_LOG_USER("ActivateCellular", service_path); 407 const NetworkState* cellular = GetNetworkState(service_path); 408 if (!cellular || cellular->type() != shill::kTypeCellular) { 409 NET_LOG_ERROR("ActivateCellular with no Service", service_path); 410 return; 411 } 412 const DeviceState* cellular_device = 413 NetworkHandler::Get()->network_state_handler()-> 414 GetDeviceState(cellular->device_path()); 415 if (!cellular_device) { 416 NET_LOG_ERROR("ActivateCellular with no Device", service_path); 417 return; 418 } 419 if (!IsDirectActivatedCarrier(cellular_device->carrier())) { 420 // For non direct activation, show the mobile setup dialog which can be 421 // used to activate the network. 422 ShowMobileSetup(service_path); 423 return; 424 } 425 if (cellular->activation_state() == shill::kActivationStateActivated) { 426 NET_LOG_ERROR("ActivateCellular for activated service", service_path); 427 return; 428 } 429 430 NetworkHandler::Get()->network_activation_handler()->Activate( 431 service_path, 432 "", // carrier 433 base::Bind(&OnActivateSucceeded, service_path), 434 base::Bind(&OnActivateFailed, service_path)); 435 } 436 437 void ShowMobileSetup(const std::string& service_path) { 438 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler(); 439 const NetworkState* cellular = handler->GetNetworkState(service_path); 440 if (!cellular || cellular->type() != shill::kTypeCellular) { 441 NET_LOG_ERROR("ShowMobileSetup without Cellular network", service_path); 442 return; 443 } 444 if (cellular->activation_state() != shill::kActivationStateActivated && 445 cellular->activate_over_non_cellular_networks() && 446 !handler->DefaultNetwork()) { 447 message_center::MessageCenter::Get()->AddNotification( 448 message_center::Notification::CreateSystemNotification( 449 kNetworkActivateNotificationId, 450 l10n_util::GetStringUTF16(IDS_NETWORK_ACTIVATION_ERROR_TITLE), 451 l10n_util::GetStringFUTF16(IDS_NETWORK_ACTIVATION_NEEDS_CONNECTION, 452 base::UTF8ToUTF16(cellular->name())), 453 ui::ResourceBundle::GetSharedInstance().GetImageNamed( 454 IDR_AURA_UBER_TRAY_CELLULAR_NETWORK_FAILED), 455 ash::system_notifier::kNotifierNetworkError, 456 base::Bind(&ash::network_connect::ShowNetworkSettings, 457 service_path))); 458 return; 459 } 460 ash::Shell::GetInstance()->system_tray_delegate()->ShowMobileSetupDialog( 461 service_path); 462 } 463 464 void ConfigureNetworkAndConnect(const std::string& service_path, 465 const base::DictionaryValue& properties, 466 bool shared) { 467 NET_LOG_USER("ConfigureNetworkAndConnect", service_path); 468 469 scoped_ptr<base::DictionaryValue> properties_to_set(properties.DeepCopy()); 470 471 std::string profile_path; 472 if (!GetNetworkProfilePath(shared, &profile_path)) { 473 ShowErrorNotification( 474 NetworkConnectionHandler::kErrorConfigureFailed, service_path); 475 return; 476 } 477 NetworkHandler::Get()->network_configuration_handler()->SetNetworkProfile( 478 service_path, profile_path, 479 base::Bind(&ConfigureSetProfileSucceeded, 480 service_path, base::Passed(&properties_to_set)), 481 base::Bind(&SetPropertiesFailed, 482 "SetProfile: " + profile_path, service_path)); 483 } 484 485 void CreateConfigurationAndConnect(base::DictionaryValue* properties, 486 bool shared) { 487 NET_LOG_USER("CreateConfigurationAndConnect", ""); 488 CallCreateConfiguration(properties, shared, true /* connect_on_configure */); 489 } 490 491 void CreateConfiguration(base::DictionaryValue* properties, bool shared) { 492 NET_LOG_USER("CreateConfiguration", ""); 493 CallCreateConfiguration(properties, shared, false /* connect_on_configure */); 494 } 495 496 base::string16 ErrorString(const std::string& error, 497 const std::string& service_path) { 498 if (error.empty()) 499 return base::string16(); 500 if (error == shill::kErrorOutOfRange) 501 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_OUT_OF_RANGE); 502 if (error == shill::kErrorPinMissing) 503 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_PIN_MISSING); 504 if (error == shill::kErrorDhcpFailed) 505 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_DHCP_FAILED); 506 if (error == shill::kErrorConnectFailed) 507 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_CONNECT_FAILED); 508 if (error == shill::kErrorBadPassphrase) 509 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_BAD_PASSPHRASE); 510 if (error == shill::kErrorBadWEPKey) 511 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_BAD_WEPKEY); 512 if (error == shill::kErrorActivationFailed) { 513 return l10n_util::GetStringUTF16( 514 IDS_CHROMEOS_NETWORK_ERROR_ACTIVATION_FAILED); 515 } 516 if (error == shill::kErrorNeedEvdo) 517 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_NEED_EVDO); 518 if (error == shill::kErrorNeedHomeNetwork) { 519 return l10n_util::GetStringUTF16( 520 IDS_CHROMEOS_NETWORK_ERROR_NEED_HOME_NETWORK); 521 } 522 if (error == shill::kErrorOtaspFailed) 523 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_OTASP_FAILED); 524 if (error == shill::kErrorAaaFailed) 525 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_AAA_FAILED); 526 if (error == shill::kErrorInternal) 527 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_INTERNAL); 528 if (error == shill::kErrorDNSLookupFailed) { 529 return l10n_util::GetStringUTF16( 530 IDS_CHROMEOS_NETWORK_ERROR_DNS_LOOKUP_FAILED); 531 } 532 if (error == shill::kErrorHTTPGetFailed) { 533 return l10n_util::GetStringUTF16( 534 IDS_CHROMEOS_NETWORK_ERROR_HTTP_GET_FAILED); 535 } 536 if (error == shill::kErrorIpsecPskAuthFailed) { 537 return l10n_util::GetStringUTF16( 538 IDS_CHROMEOS_NETWORK_ERROR_IPSEC_PSK_AUTH_FAILED); 539 } 540 if (error == shill::kErrorIpsecCertAuthFailed) { 541 return l10n_util::GetStringUTF16( 542 IDS_CHROMEOS_NETWORK_ERROR_CERT_AUTH_FAILED); 543 } 544 if (error == shill::kErrorEapAuthenticationFailed) { 545 const NetworkState* network = GetNetworkState(service_path); 546 // TLS always requires a client certificate, so show a cert auth 547 // failed message for TLS. Other EAP methods do not generally require 548 // a client certicate. 549 if (network && network->eap_method() == shill::kEapMethodTLS) { 550 return l10n_util::GetStringUTF16( 551 IDS_CHROMEOS_NETWORK_ERROR_CERT_AUTH_FAILED); 552 } else { 553 return l10n_util::GetStringUTF16( 554 IDS_CHROMEOS_NETWORK_ERROR_EAP_AUTH_FAILED); 555 } 556 } 557 if (error == shill::kErrorEapLocalTlsFailed) { 558 return l10n_util::GetStringUTF16( 559 IDS_CHROMEOS_NETWORK_ERROR_EAP_LOCAL_TLS_FAILED); 560 } 561 if (error == shill::kErrorEapRemoteTlsFailed) { 562 return l10n_util::GetStringUTF16( 563 IDS_CHROMEOS_NETWORK_ERROR_EAP_REMOTE_TLS_FAILED); 564 } 565 if (error == shill::kErrorPppAuthFailed) { 566 return l10n_util::GetStringUTF16( 567 IDS_CHROMEOS_NETWORK_ERROR_PPP_AUTH_FAILED); 568 } 569 570 if (StringToLowerASCII(error) == 571 StringToLowerASCII(std::string(shill::kUnknownString))) { 572 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_UNKNOWN); 573 } 574 return l10n_util::GetStringFUTF16(IDS_NETWORK_UNRECOGNIZED_ERROR, 575 base::UTF8ToUTF16(error)); 576 } 577 578 void ShowNetworkSettings(const std::string& service_path) { 579 if (!ash::Shell::HasInstance()) 580 return; 581 ash::Shell::GetInstance()->system_tray_delegate()->ShowNetworkSettings( 582 service_path); 583 } 584 585 } // network_connect 586 } // ash 587