summaryrefslogtreecommitdiff
path: root/chromium/ash/system/chromeos/network/network_connect.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ash/system/chromeos/network/network_connect.cc')
-rw-r--r--chromium/ash/system/chromeos/network/network_connect.cc579
1 files changed, 579 insertions, 0 deletions
diff --git a/chromium/ash/system/chromeos/network/network_connect.cc b/chromium/ash/system/chromeos/network/network_connect.cc
new file mode 100644
index 00000000000..d8f524aea43
--- /dev/null
+++ b/chromium/ash/system/chromeos/network/network_connect.cc
@@ -0,0 +1,579 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/system/chromeos/network/network_connect.h"
+
+#include "ash/session_state_delegate.h"
+#include "ash/shell.h"
+#include "ash/system/chromeos/network/network_state_notifier.h"
+#include "ash/system/system_notifier.h"
+#include "ash/system/tray/system_tray_delegate.h"
+#include "ash/system/tray/system_tray_notifier.h"
+#include "base/bind.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "chromeos/login/login_state.h"
+#include "chromeos/network/device_state.h"
+#include "chromeos/network/network_activation_handler.h"
+#include "chromeos/network/network_configuration_handler.h"
+#include "chromeos/network/network_connection_handler.h"
+#include "chromeos/network/network_event_log.h"
+#include "chromeos/network/network_handler_callbacks.h"
+#include "chromeos/network/network_profile.h"
+#include "chromeos/network/network_profile_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
+#include "chromeos/network/shill_property_util.h"
+#include "grit/ash_resources.h"
+#include "grit/ash_strings.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/message_center/message_center.h"
+#include "ui/message_center/notification.h"
+
+using chromeos::DeviceState;
+using chromeos::NetworkConfigurationHandler;
+using chromeos::NetworkConnectionHandler;
+using chromeos::NetworkHandler;
+using chromeos::NetworkProfile;
+using chromeos::NetworkProfileHandler;
+using chromeos::NetworkState;
+using chromeos::NetworkStateHandler;
+using chromeos::NetworkTypePattern;
+
+namespace ash {
+
+namespace {
+
+// TODO(stevenjb): This should be in service_constants.h
+const char kErrorInProgress[] = "org.chromium.flimflam.Error.InProgress";
+
+// Returns true for carriers that can be activated through Shill instead of
+// through a WebUI dialog.
+bool IsDirectActivatedCarrier(const std::string& carrier) {
+ if (carrier == shill::kCarrierSprint)
+ return true;
+ return false;
+}
+
+void ShowErrorNotification(const std::string& error_name,
+ const std::string& shill_error,
+ const std::string& service_path) {
+ Shell::GetInstance()->system_tray_notifier()->network_state_notifier()->
+ ShowNetworkConnectError(error_name, shill_error, service_path);
+}
+
+void HandleUnconfiguredNetwork(const std::string& service_path,
+ gfx::NativeWindow parent_window) {
+ const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
+ GetNetworkState(service_path);
+ if (!network) {
+ NET_LOG_ERROR("Configuring unknown network", service_path);
+ return;
+ }
+
+ if (network->type() == shill::kTypeWifi) {
+ // Only show the config view for secure networks, otherwise do nothing.
+ if (network->security() != shill::kSecurityNone) {
+ ash::Shell::GetInstance()->system_tray_delegate()->
+ ShowNetworkConfigure(service_path, parent_window);
+ }
+ return;
+ }
+
+ if (network->type() == shill::kTypeWimax ||
+ network->type() == shill::kTypeVPN) {
+ ash::Shell::GetInstance()->system_tray_delegate()->
+ ShowNetworkConfigure(service_path, parent_window);
+ return;
+ }
+
+ if (network->type() == shill::kTypeCellular) {
+ if (network->RequiresActivation()) {
+ ash::network_connect::ActivateCellular(service_path);
+ return;
+ }
+ if (network->cellular_out_of_credits()) {
+ ash::network_connect::ShowMobileSetup(service_path);
+ return;
+ }
+ // No special configure or setup for |network|, show the settings UI.
+ if (chromeos::LoginState::Get()->IsUserLoggedIn()) {
+ ash::Shell::GetInstance()->system_tray_delegate()->
+ ShowNetworkSettings(service_path);
+ }
+ return;
+ }
+ NOTREACHED();
+}
+
+void OnConnectFailed(const std::string& service_path,
+ gfx::NativeWindow parent_window,
+ const std::string& error_name,
+ scoped_ptr<base::DictionaryValue> error_data) {
+ NET_LOG_ERROR("Connect Failed: " + error_name, service_path);
+
+ if (!ash::Shell::HasInstance())
+ return;
+
+ // If a new connect attempt canceled this connect, no need to notify the user.
+ if (error_name == NetworkConnectionHandler::kErrorConnectCanceled)
+ return;
+
+ if (error_name == shill::kErrorBadPassphrase ||
+ error_name == NetworkConnectionHandler::kErrorPassphraseRequired ||
+ error_name == NetworkConnectionHandler::kErrorConfigurationRequired ||
+ error_name == NetworkConnectionHandler::kErrorAuthenticationRequired) {
+ HandleUnconfiguredNetwork(service_path, parent_window);
+ return;
+ }
+
+ if (error_name == NetworkConnectionHandler::kErrorCertificateRequired) {
+ if (!ash::Shell::GetInstance()->system_tray_delegate()->EnrollNetwork(
+ service_path, parent_window)) {
+ HandleUnconfiguredNetwork(service_path, parent_window);
+ }
+ return;
+ }
+
+ if (error_name == NetworkConnectionHandler::kErrorActivationRequired) {
+ network_connect::ActivateCellular(service_path);
+ return;
+ }
+
+ if (error_name == NetworkConnectionHandler::kErrorConnected ||
+ error_name == NetworkConnectionHandler::kErrorConnecting) {
+ network_connect::ShowNetworkSettings(service_path);
+ return;
+ }
+
+ // ConnectFailed or unknown error; show a notification.
+ std::string shill_error;
+ error_data.get()->GetString(
+ chromeos::network_handler::kErrorDetail, &shill_error);
+ ShowErrorNotification(error_name, shill_error, service_path);
+
+ // Only show a configure dialog if there was a ConnectFailed error and the
+ // screen is not locked.
+ if (error_name != shill::kErrorConnectFailed ||
+ Shell::GetInstance()->session_state_delegate()->IsScreenLocked())
+ return;
+
+ // If Shill reports an InProgress error, don't try to configure the network.
+ std::string dbus_error_name;
+ error_data.get()->GetString(
+ chromeos::network_handler::kDbusErrorName, &dbus_error_name);
+ if (dbus_error_name == kErrorInProgress)
+ return;
+
+ HandleUnconfiguredNetwork(service_path, parent_window);
+}
+
+void OnConnectSucceeded(const std::string& service_path) {
+ NET_LOG_USER("Connect Succeeded", service_path);
+ if (!ash::Shell::HasInstance())
+ return;
+ message_center::MessageCenter::Get()->RemoveNotification(
+ network_connect::kNetworkConnectNotificationId, false /* not by user */);
+}
+
+// If |check_error_state| is true, error state for the network is checked,
+// otherwise any current error state is ignored (e.g. for recently configured
+// networks or repeat connect attempts). |parent_window| will be used to parent
+// any configuration UI on failure and may be NULL (in which case the default
+// window will be used).
+void CallConnectToNetwork(const std::string& service_path,
+ bool check_error_state,
+ gfx::NativeWindow parent_window) {
+ if (!ash::Shell::HasInstance())
+ return;
+ message_center::MessageCenter::Get()->RemoveNotification(
+ network_connect::kNetworkConnectNotificationId, false /* not by user */);
+
+ NetworkHandler::Get()->network_connection_handler()->ConnectToNetwork(
+ service_path,
+ base::Bind(&OnConnectSucceeded, service_path),
+ base::Bind(&OnConnectFailed, service_path, parent_window),
+ check_error_state);
+}
+
+void OnActivateFailed(const std::string& service_path,
+ const std::string& error_name,
+ scoped_ptr<base::DictionaryValue> error_data) {
+ NET_LOG_ERROR("Unable to activate network", service_path);
+ ShowErrorNotification(
+ network_connect::kErrorActivateFailed, "", service_path);
+}
+
+void OnActivateSucceeded(const std::string& service_path) {
+ NET_LOG_USER("Activation Succeeded", service_path);
+}
+
+void OnConfigureFailed(const std::string& error_name,
+ scoped_ptr<base::DictionaryValue> error_data) {
+ NET_LOG_ERROR("Unable to configure network", "");
+ ShowErrorNotification(
+ NetworkConnectionHandler::kErrorConfigureFailed, "", "");
+}
+
+void OnConfigureSucceeded(const std::string& service_path) {
+ NET_LOG_USER("Configure Succeeded", service_path);
+ // After configuring a network, ignore any (possibly stale) error state.
+ const bool check_error_state = false;
+ const gfx::NativeWindow parent_window = NULL;
+ CallConnectToNetwork(service_path, check_error_state, parent_window);
+}
+
+void SetPropertiesFailed(const std::string& desc,
+ const std::string& service_path,
+ const std::string& config_error_name,
+ scoped_ptr<base::DictionaryValue> error_data) {
+ NET_LOG_ERROR(desc + ": Failed: " + config_error_name, service_path);
+ ShowErrorNotification(
+ NetworkConnectionHandler::kErrorConfigureFailed, "", service_path);
+}
+
+void SetPropertiesToClear(base::DictionaryValue* properties_to_set,
+ std::vector<std::string>* properties_to_clear) {
+ // Move empty string properties to properties_to_clear.
+ for (base::DictionaryValue::Iterator iter(*properties_to_set);
+ !iter.IsAtEnd(); iter.Advance()) {
+ std::string value_str;
+ if (iter.value().GetAsString(&value_str) && value_str.empty())
+ properties_to_clear->push_back(iter.key());
+ }
+ // Remove cleared properties from properties_to_set.
+ for (std::vector<std::string>::iterator iter = properties_to_clear->begin();
+ iter != properties_to_clear->end(); ++iter) {
+ properties_to_set->RemoveWithoutPathExpansion(*iter, NULL);
+ }
+}
+
+void ClearPropertiesAndConnect(
+ const std::string& service_path,
+ const std::vector<std::string>& properties_to_clear) {
+ NET_LOG_USER("ClearPropertiesAndConnect", service_path);
+ // After configuring a network, ignore any (possibly stale) error state.
+ const bool check_error_state = false;
+ const gfx::NativeWindow parent_window = NULL;
+ NetworkHandler::Get()->network_configuration_handler()->ClearProperties(
+ service_path,
+ properties_to_clear,
+ base::Bind(&CallConnectToNetwork,
+ service_path, check_error_state,
+ parent_window),
+ base::Bind(&SetPropertiesFailed, "ClearProperties", service_path));
+}
+
+// Returns false if !shared and no valid profile is available, which will
+// trigger an error and abort.
+bool GetNetworkProfilePath(bool shared, std::string* profile_path) {
+ if (shared) {
+ *profile_path = NetworkProfileHandler::kSharedProfilePath;
+ return true;
+ }
+
+ if (!chromeos::LoginState::Get()->IsUserAuthenticated()) {
+ NET_LOG_ERROR("User profile specified before login", "");
+ return false;
+ }
+
+ const NetworkProfile* profile =
+ NetworkHandler::Get()->network_profile_handler()->
+ GetDefaultUserProfile();
+ if (!profile) {
+ NET_LOG_ERROR("No user profile for unshared network configuration", "");
+ return false;
+ }
+
+ *profile_path = profile->path;
+ return true;
+}
+
+void ConfigureSetProfileSucceeded(
+ const std::string& service_path,
+ scoped_ptr<base::DictionaryValue> properties_to_set) {
+ std::vector<std::string> properties_to_clear;
+ SetPropertiesToClear(properties_to_set.get(), &properties_to_clear);
+ NetworkHandler::Get()->network_configuration_handler()->SetProperties(
+ service_path,
+ *properties_to_set,
+ base::Bind(&ClearPropertiesAndConnect,
+ service_path,
+ properties_to_clear),
+ base::Bind(&SetPropertiesFailed, "SetProperties", service_path));
+}
+
+const NetworkState* GetNetworkState(const std::string& service_path) {
+ return NetworkHandler::Get()->network_state_handler()->
+ GetNetworkState(service_path);
+}
+
+} // namespace
+
+namespace network_connect {
+
+const char kNetworkConnectNotificationId[] =
+ "chrome://settings/internet/connect";
+const char kNetworkActivateNotificationId[] =
+ "chrome://settings/internet/activate";
+
+const char kErrorActivateFailed[] = "activate-failed";
+
+void ConnectToNetwork(const std::string& service_path,
+ gfx::NativeWindow parent_window) {
+ NET_LOG_USER("ConnectToNetwork", service_path);
+ const NetworkState* network = GetNetworkState(service_path);
+ if (network && !network->error().empty()) {
+ NET_LOG_USER("Configure: " + network->error(), service_path);
+ // If the network is in an error state, show the configuration UI directly
+ // to avoid a spurious notification.
+ HandleUnconfiguredNetwork(service_path, parent_window);
+ return;
+ }
+ const bool check_error_state = true;
+ CallConnectToNetwork(service_path, check_error_state, parent_window);
+}
+
+void SetTechnologyEnabled(const NetworkTypePattern& technology,
+ bool enabled_state) {
+ std::string log_string =
+ base::StringPrintf("technology %s, target state: %s",
+ technology.ToDebugString().c_str(),
+ (enabled_state ? "ENABLED" : "DISABLED"));
+ NET_LOG_USER("SetTechnologyEnabled", log_string);
+ NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
+ bool enabled = handler->IsTechnologyEnabled(technology);
+ if (enabled_state == enabled) {
+ NET_LOG_USER("Technology already in target state.", log_string);
+ return;
+ }
+ if (enabled) {
+ // User requested to disable the technology.
+ handler->SetTechnologyEnabled(
+ technology, false, chromeos::network_handler::ErrorCallback());
+ return;
+ }
+ // If we're dealing with a mobile network, then handle SIM lock here.
+ // SIM locking only applies to cellular, so the code below won't execute
+ // if |technology| has been explicitly set to WiMAX.
+ if (technology.MatchesPattern(NetworkTypePattern::Mobile())) {
+ const DeviceState* mobile = handler->GetDeviceStateByType(technology);
+ if (!mobile) {
+ NET_LOG_ERROR("SetTechnologyEnabled with no device", log_string);
+ return;
+ }
+ // The following only applies to cellular.
+ if (mobile->type() == shill::kTypeCellular) {
+ if (mobile->IsSimAbsent()) {
+ // If this is true, then we have a cellular device with no SIM inserted.
+ // TODO(armansito): Chrome should display a notification here, prompting
+ // the user to insert a SIM card and restart the device to enable
+ // cellular. See crbug.com/125171.
+ NET_LOG_USER("Cannot enable cellular device without SIM.", log_string);
+ return;
+ }
+ if (!mobile->sim_lock_type().empty()) {
+ // A SIM has been inserted, but it is locked. Let the user unlock it
+ // via the dialog.
+ ash::Shell::GetInstance()->system_tray_delegate()->
+ ShowMobileSimDialog();
+ return;
+ }
+ }
+ }
+ handler->SetTechnologyEnabled(
+ technology, true, chromeos::network_handler::ErrorCallback());
+}
+
+void ActivateCellular(const std::string& service_path) {
+ NET_LOG_USER("ActivateCellular", service_path);
+ const NetworkState* cellular = GetNetworkState(service_path);
+ if (!cellular || cellular->type() != shill::kTypeCellular) {
+ NET_LOG_ERROR("ActivateCellular with no Service", service_path);
+ return;
+ }
+ const DeviceState* cellular_device =
+ NetworkHandler::Get()->network_state_handler()->
+ GetDeviceState(cellular->device_path());
+ if (!cellular_device) {
+ NET_LOG_ERROR("ActivateCellular with no Device", service_path);
+ return;
+ }
+ if (!IsDirectActivatedCarrier(cellular_device->carrier())) {
+ // For non direct activation, show the mobile setup dialog which can be
+ // used to activate the network.
+ ShowMobileSetup(service_path);
+ return;
+ }
+ if (cellular->activation_state() == shill::kActivationStateActivated) {
+ NET_LOG_ERROR("ActivateCellular for activated service", service_path);
+ return;
+ }
+
+ NetworkHandler::Get()->network_activation_handler()->Activate(
+ service_path,
+ "", // carrier
+ base::Bind(&OnActivateSucceeded, service_path),
+ base::Bind(&OnActivateFailed, service_path));
+}
+
+void ShowMobileSetup(const std::string& service_path) {
+ NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
+ const NetworkState* cellular = handler->GetNetworkState(service_path);
+ if (!cellular || cellular->type() != shill::kTypeCellular) {
+ NET_LOG_ERROR("ShowMobileSetup without Cellular network", service_path);
+ return;
+ }
+ if (cellular->activation_state() != shill::kActivationStateActivated &&
+ cellular->activate_over_non_cellular_networks() &&
+ !handler->DefaultNetwork()) {
+ message_center::MessageCenter::Get()->AddNotification(
+ message_center::Notification::CreateSystemNotification(
+ kNetworkActivateNotificationId,
+ l10n_util::GetStringUTF16(IDS_NETWORK_ACTIVATION_ERROR_TITLE),
+ l10n_util::GetStringFUTF16(IDS_NETWORK_ACTIVATION_NEEDS_CONNECTION,
+ UTF8ToUTF16(cellular->name())),
+ ui::ResourceBundle::GetSharedInstance().GetImageNamed(
+ IDR_AURA_UBER_TRAY_CELLULAR_NETWORK_FAILED),
+ ash::system_notifier::kNotifierNetwork,
+ base::Bind(&ash::network_connect::ShowNetworkSettings,
+ service_path)));
+ return;
+ }
+ ash::Shell::GetInstance()->system_tray_delegate()->ShowMobileSetupDialog(
+ service_path);
+}
+
+void ConfigureNetworkAndConnect(const std::string& service_path,
+ const base::DictionaryValue& properties,
+ bool shared) {
+ NET_LOG_USER("ConfigureNetworkAndConnect", service_path);
+
+ scoped_ptr<base::DictionaryValue> properties_to_set(properties.DeepCopy());
+
+ std::string profile_path;
+ if (!GetNetworkProfilePath(shared, &profile_path)) {
+ ShowErrorNotification(
+ NetworkConnectionHandler::kErrorConfigureFailed, "", service_path);
+ return;
+ }
+ NetworkHandler::Get()->network_configuration_handler()->SetNetworkProfile(
+ service_path, profile_path,
+ base::Bind(&ConfigureSetProfileSucceeded,
+ service_path, base::Passed(&properties_to_set)),
+ base::Bind(&SetPropertiesFailed,
+ "SetProfile: " + profile_path, service_path));
+}
+
+void CreateConfigurationAndConnect(base::DictionaryValue* properties,
+ bool shared) {
+ NET_LOG_USER("CreateConfigurationAndConnect", "");
+ std::string profile_path;
+ if (!GetNetworkProfilePath(shared, &profile_path)) {
+ ShowErrorNotification(
+ NetworkConnectionHandler::kErrorConfigureFailed, "", "");
+ return;
+ }
+ properties->SetStringWithoutPathExpansion(
+ shill::kProfileProperty, profile_path);
+ NetworkHandler::Get()->network_configuration_handler()->CreateConfiguration(
+ *properties,
+ base::Bind(&OnConfigureSucceeded),
+ base::Bind(&OnConfigureFailed));
+}
+
+string16 ErrorString(const std::string& error,
+ const std::string& service_path) {
+ if (error.empty())
+ return string16();
+ if (error == shill::kErrorOutOfRange)
+ return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_OUT_OF_RANGE);
+ if (error == shill::kErrorPinMissing)
+ return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_PIN_MISSING);
+ if (error == shill::kErrorDhcpFailed)
+ return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_DHCP_FAILED);
+ if (error == shill::kErrorConnectFailed)
+ return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_CONNECT_FAILED);
+ if (error == shill::kErrorBadPassphrase)
+ return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_BAD_PASSPHRASE);
+ if (error == shill::kErrorBadWEPKey)
+ return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_BAD_WEPKEY);
+ if (error == shill::kErrorActivationFailed) {
+ return l10n_util::GetStringUTF16(
+ IDS_CHROMEOS_NETWORK_ERROR_ACTIVATION_FAILED);
+ }
+ if (error == shill::kErrorNeedEvdo)
+ return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_NEED_EVDO);
+ if (error == shill::kErrorNeedHomeNetwork) {
+ return l10n_util::GetStringUTF16(
+ IDS_CHROMEOS_NETWORK_ERROR_NEED_HOME_NETWORK);
+ }
+ if (error == shill::kErrorOtaspFailed)
+ return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_OTASP_FAILED);
+ if (error == shill::kErrorAaaFailed)
+ return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_AAA_FAILED);
+ if (error == shill::kErrorInternal)
+ return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_INTERNAL);
+ if (error == shill::kErrorDNSLookupFailed) {
+ return l10n_util::GetStringUTF16(
+ IDS_CHROMEOS_NETWORK_ERROR_DNS_LOOKUP_FAILED);
+ }
+ if (error == shill::kErrorHTTPGetFailed) {
+ return l10n_util::GetStringUTF16(
+ IDS_CHROMEOS_NETWORK_ERROR_HTTP_GET_FAILED);
+ }
+ if (error == shill::kErrorIpsecPskAuthFailed) {
+ return l10n_util::GetStringUTF16(
+ IDS_CHROMEOS_NETWORK_ERROR_IPSEC_PSK_AUTH_FAILED);
+ }
+ if (error == shill::kErrorIpsecCertAuthFailed) {
+ return l10n_util::GetStringUTF16(
+ IDS_CHROMEOS_NETWORK_ERROR_CERT_AUTH_FAILED);
+ }
+ if (error == shill::kErrorEapAuthenticationFailed) {
+ const NetworkState* network = GetNetworkState(service_path);
+ // TLS always requires a client certificate, so show a cert auth
+ // failed message for TLS. Other EAP methods do not generally require
+ // a client certicate.
+ if (network && network->eap_method() == shill::kEapMethodTLS) {
+ return l10n_util::GetStringUTF16(
+ IDS_CHROMEOS_NETWORK_ERROR_CERT_AUTH_FAILED);
+ } else {
+ return l10n_util::GetStringUTF16(
+ IDS_CHROMEOS_NETWORK_ERROR_EAP_AUTH_FAILED);
+ }
+ }
+ if (error == shill::kErrorEapLocalTlsFailed) {
+ return l10n_util::GetStringUTF16(
+ IDS_CHROMEOS_NETWORK_ERROR_EAP_LOCAL_TLS_FAILED);
+ }
+ if (error == shill::kErrorEapRemoteTlsFailed) {
+ return l10n_util::GetStringUTF16(
+ IDS_CHROMEOS_NETWORK_ERROR_EAP_REMOTE_TLS_FAILED);
+ }
+ if (error == shill::kErrorPppAuthFailed) {
+ return l10n_util::GetStringUTF16(
+ IDS_CHROMEOS_NETWORK_ERROR_PPP_AUTH_FAILED);
+ }
+
+ if (StringToLowerASCII(error) ==
+ StringToLowerASCII(std::string(shill::kUnknownString))) {
+ return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_UNKNOWN);
+ }
+ return l10n_util::GetStringFUTF16(IDS_NETWORK_UNRECOGNIZED_ERROR,
+ UTF8ToUTF16(error));
+}
+
+void ShowNetworkSettings(const std::string& service_path) {
+ if (!ash::Shell::HasInstance())
+ return;
+ ash::Shell::GetInstance()->system_tray_delegate()->ShowNetworkSettings(
+ service_path);
+}
+
+} // network_connect
+} // ash