1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file.
4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ash/system/chromeos/network/network_connect.h"
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ash/session_state_delegate.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ash/shell.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ash/system/chromeos/network/network_state_notifier.h"
10424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "ash/system/system_notifier.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ash/system/tray/system_tray_delegate.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ash/system/tray/system_tray_notifier.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/bind.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/strings/utf_string_conversions.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/values.h"
17ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chromeos/login/login_state.h"
18ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chromeos/network/device_state.h"
19424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "chromeos/network/network_activation_handler.h"
20ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chromeos/network/network_configuration_handler.h"
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chromeos/network/network_connection_handler.h"
22ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chromeos/network/network_event_log.h"
23ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chromeos/network/network_handler_callbacks.h"
24ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chromeos/network/network_profile.h"
25ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chromeos/network/network_profile_handler.h"
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chromeos/network/network_state.h"
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chromeos/network/network_state_handler.h"
2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chromeos/network/shill_property_util.h"
293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "grit/ash_resources.h"
307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "grit/ash_strings.h"
317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "third_party/cros_system_api/dbus/service_constants.h"
327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "ui/base/l10n/l10n_util.h"
333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "ui/message_center/message_center.h"
353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "ui/message_center/notification.h"
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
37ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochusing chromeos::DeviceState;
38ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochusing chromeos::NetworkConfigurationHandler;
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using chromeos::NetworkConnectionHandler;
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using chromeos::NetworkHandler;
41ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochusing chromeos::NetworkProfile;
42ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochusing chromeos::NetworkProfileHandler;
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using chromeos::NetworkState;
443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)using chromeos::NetworkStateHandler;
4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using chromeos::NetworkTypePattern;
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace ash {
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace {
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
51ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// TODO(stevenjb): This should be in service_constants.h
52ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochconst char kErrorInProgress[] = "org.chromium.flimflam.Error.InProgress";
53ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
54ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Returns true for carriers that can be activated through Shill instead of
55ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// through a WebUI dialog.
56ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool IsDirectActivatedCarrier(const std::string& carrier) {
57ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (carrier == shill::kCarrierSprint)
58ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return true;
59ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return false;
60ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
61ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
62d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ShowErrorNotification(const std::string& error_name,
63d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                           const std::string& shill_error,
64ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                           const std::string& service_path) {
65ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  Shell::GetInstance()->system_tray_notifier()->network_state_notifier()->
66d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      ShowNetworkConnectError(error_name, shill_error, service_path);
67ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
68ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void HandleUnconfiguredNetwork(const std::string& service_path,
704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                               gfx::NativeWindow parent_window) {
714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      GetNetworkState(service_path);
734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!network) {
744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    NET_LOG_ERROR("Configuring unknown network", service_path);
754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (network->type() == shill::kTypeWifi) {
794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Only show the config view for secure networks, otherwise do nothing.
804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (network->security() != shill::kSecurityNone) {
814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      ash::Shell::GetInstance()->system_tray_delegate()->
824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          ShowNetworkConfigure(service_path, parent_window);
834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (network->type() == shill::kTypeWimax ||
884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      network->type() == shill::kTypeVPN) {
894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ash::Shell::GetInstance()->system_tray_delegate()->
904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        ShowNetworkConfigure(service_path, parent_window);
914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (network->type() == shill::kTypeCellular) {
954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (network->RequiresActivation()) {
964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      ash::network_connect::ActivateCellular(service_path);
974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return;
984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (network->cellular_out_of_credits()) {
1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      ash::network_connect::ShowMobileSetup(service_path);
1014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return;
1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // No special configure or setup for |network|, show the settings UI.
1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (chromeos::LoginState::Get()->IsUserLoggedIn()) {
1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      ash::Shell::GetInstance()->system_tray_delegate()->
1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          ShowNetworkSettings(service_path);
1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  NOTREACHED();
1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void OnConnectFailed(const std::string& service_path,
1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                     gfx::NativeWindow parent_window,
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     const std::string& error_name,
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     scoped_ptr<base::DictionaryValue> error_data) {
117ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  NET_LOG_ERROR("Connect Failed: " + error_name, service_path);
118ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!ash::Shell::HasInstance())
1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
122ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // If a new connect attempt canceled this connect, no need to notify the user.
123ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (error_name == NetworkConnectionHandler::kErrorConnectCanceled)
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
125ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
12668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error_name == shill::kErrorBadPassphrase ||
12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      error_name == NetworkConnectionHandler::kErrorPassphraseRequired ||
128a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      error_name == NetworkConnectionHandler::kErrorConfigurationRequired ||
129a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      error_name == NetworkConnectionHandler::kErrorAuthenticationRequired) {
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    HandleUnconfiguredNetwork(service_path, parent_window);
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
133ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
134ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (error_name == NetworkConnectionHandler::kErrorCertificateRequired) {
1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (!ash::Shell::GetInstance()->system_tray_delegate()->EnrollNetwork(
1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            service_path, parent_window)) {
1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      HandleUnconfiguredNetwork(service_path, parent_window);
1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
139ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
140ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
141ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
142ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (error_name == NetworkConnectionHandler::kErrorActivationRequired) {
143ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    network_connect::ActivateCellular(service_path);
144ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
145ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
146ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error_name == NetworkConnectionHandler::kErrorConnected ||
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      error_name == NetworkConnectionHandler::kErrorConnecting) {
1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    network_connect::ShowNetworkSettings(service_path);
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
152ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
153ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // ConnectFailed or unknown error; show a notification.
154d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  std::string shill_error;
155d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  error_data.get()->GetString(
156d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      chromeos::network_handler::kErrorDetail, &shill_error);
157d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ShowErrorNotification(error_name, shill_error, service_path);
158ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Only show a configure dialog if there was a ConnectFailed error and the
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // screen is not locked.
161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (error_name != shill::kErrorConnectFailed ||
162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      Shell::GetInstance()->session_state_delegate()->IsScreenLocked())
163ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
164ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
165ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // If Shill reports an InProgress error, don't try to configure the network.
166ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::string dbus_error_name;
167ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  error_data.get()->GetString(
168ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      chromeos::network_handler::kDbusErrorName, &dbus_error_name);
169ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (dbus_error_name == kErrorInProgress)
170ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
171ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  HandleUnconfiguredNetwork(service_path, parent_window);
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void OnConnectSucceeded(const std::string& service_path) {
176ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  NET_LOG_USER("Connect Succeeded", service_path);
1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!ash::Shell::HasInstance())
1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
1793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  message_center::MessageCenter::Get()->RemoveNotification(
1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      network_connect::kNetworkConnectNotificationId, false /* not by user */);
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
183ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// If |check_error_state| is true, error state for the network is checked,
184ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// otherwise any current error state is ignored (e.g. for recently configured
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// networks or repeat connect attempts). |parent_window| will be used to parent
186ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// any configuration UI on failure and may be NULL (in which case the default
187ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// window will be used).
188ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid CallConnectToNetwork(const std::string& service_path,
189ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                          bool check_error_state,
1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                          gfx::NativeWindow parent_window) {
1913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!ash::Shell::HasInstance())
1923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
1933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  message_center::MessageCenter::Get()->RemoveNotification(
1943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      network_connect::kNetworkConnectNotificationId, false /* not by user */);
195ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
196ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  NetworkHandler::Get()->network_connection_handler()->ConnectToNetwork(
197ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      service_path,
198ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Bind(&OnConnectSucceeded, service_path),
1994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::Bind(&OnConnectFailed, service_path, parent_window),
200ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      check_error_state);
201ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
202ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
203ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid OnActivateFailed(const std::string& service_path,
20458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                      const std::string& error_name,
205ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                      scoped_ptr<base::DictionaryValue> error_data) {
206ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  NET_LOG_ERROR("Unable to activate network", service_path);
207d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ShowErrorNotification(
208d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      network_connect::kErrorActivateFailed, "", service_path);
209ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
210ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
211ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid OnActivateSucceeded(const std::string& service_path) {
212ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  NET_LOG_USER("Activation Succeeded", service_path);
213ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
214ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
215ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid OnConfigureFailed(const std::string& error_name,
216ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                       scoped_ptr<base::DictionaryValue> error_data) {
217ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  NET_LOG_ERROR("Unable to configure network", "");
218d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ShowErrorNotification(
219d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      NetworkConnectionHandler::kErrorConfigureFailed, "", "");
220ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
221ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
222ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid OnConfigureSucceeded(const std::string& service_path) {
223ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  NET_LOG_USER("Configure Succeeded", service_path);
224ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // After configuring a network, ignore any (possibly stale) error state.
225ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  const bool check_error_state = false;
2264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const gfx::NativeWindow parent_window = NULL;
2274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  CallConnectToNetwork(service_path, check_error_state, parent_window);
228ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
229ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
230ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid SetPropertiesFailed(const std::string& desc,
231ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                         const std::string& service_path,
232ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                         const std::string& config_error_name,
233ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                         scoped_ptr<base::DictionaryValue> error_data) {
234ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  NET_LOG_ERROR(desc + ": Failed: " + config_error_name, service_path);
235ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  ShowErrorNotification(
236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      NetworkConnectionHandler::kErrorConfigureFailed, "", service_path);
237ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
238ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
239ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid SetPropertiesToClear(base::DictionaryValue* properties_to_set,
240ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                          std::vector<std::string>* properties_to_clear) {
241ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Move empty string properties to properties_to_clear.
242ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (base::DictionaryValue::Iterator iter(*properties_to_set);
243ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       !iter.IsAtEnd(); iter.Advance()) {
244ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    std::string value_str;
245ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (iter.value().GetAsString(&value_str) && value_str.empty())
246ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      properties_to_clear->push_back(iter.key());
247ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
248ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Remove cleared properties from properties_to_set.
249ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (std::vector<std::string>::iterator iter = properties_to_clear->begin();
250ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       iter != properties_to_clear->end(); ++iter) {
251ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    properties_to_set->RemoveWithoutPathExpansion(*iter, NULL);
252ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
253ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
254ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
255ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ClearPropertiesAndConnect(
256ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& service_path,
257ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::vector<std::string>& properties_to_clear) {
258ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  NET_LOG_USER("ClearPropertiesAndConnect", service_path);
259ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // After configuring a network, ignore any (possibly stale) error state.
260ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  const bool check_error_state = false;
2614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const gfx::NativeWindow parent_window = NULL;
262ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  NetworkHandler::Get()->network_configuration_handler()->ClearProperties(
263ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      service_path,
264ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      properties_to_clear,
265ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Bind(&CallConnectToNetwork,
266ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 service_path, check_error_state,
2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 parent_window),
268ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Bind(&SetPropertiesFailed, "ClearProperties", service_path));
269ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
270ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
271ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Returns false if !shared and no valid profile is available, which will
272ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// trigger an error and abort.
273ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool GetNetworkProfilePath(bool shared, std::string* profile_path) {
274ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (shared) {
275ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    *profile_path = NetworkProfileHandler::kSharedProfilePath;
276ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return true;
277ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
278ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
279ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!chromeos::LoginState::Get()->IsUserAuthenticated()) {
280ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    NET_LOG_ERROR("User profile specified before login", "");
281ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return false;
282ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
283ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
284ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  const NetworkProfile* profile  =
285ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      NetworkHandler::Get()->network_profile_handler()->
286ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      GetDefaultUserProfile();
287ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!profile) {
288ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    NET_LOG_ERROR("No user profile for unshared network configuration", "");
289ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return false;
290ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
291ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
292ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  *profile_path = profile->path;
293ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return true;
294ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
295ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
296ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ConfigureSetProfileSucceeded(
297ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const std::string& service_path,
298ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    scoped_ptr<base::DictionaryValue> properties_to_set) {
299ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::vector<std::string> properties_to_clear;
300ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  SetPropertiesToClear(properties_to_set.get(), &properties_to_clear);
301ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  NetworkHandler::Get()->network_configuration_handler()->SetProperties(
302ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      service_path,
303ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      *properties_to_set,
304ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Bind(&ClearPropertiesAndConnect,
305ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 service_path,
306ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 properties_to_clear),
307ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Bind(&SetPropertiesFailed, "SetProperties", service_path));
308ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
309ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const NetworkState* GetNetworkState(const std::string& service_path) {
3114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return NetworkHandler::Get()->network_state_handler()->
3124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      GetNetworkState(service_path);
3134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace
316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace network_connect {
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const char kNetworkConnectNotificationId[] =
3203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "chrome://settings/internet/connect";
3213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const char kNetworkActivateNotificationId[] =
3223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "chrome://settings/internet/activate";
3233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
32458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const char kErrorActivateFailed[] = "activate-failed";
32558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
326ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ConnectToNetwork(const std::string& service_path,
3274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                      gfx::NativeWindow parent_window) {
3283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  NET_LOG_USER("ConnectToNetwork", service_path);
3294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const NetworkState* network = GetNetworkState(service_path);
3303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (network && !network->error().empty()) {
3313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    NET_LOG_USER("Configure: " + network->error(), service_path);
3323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // If the network is in an error state, show the configuration UI directly
3333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // to avoid a spurious notification.
3344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    HandleUnconfiguredNetwork(service_path, parent_window);
3353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
3363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
337ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  const bool check_error_state = true;
3384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  CallConnectToNetwork(service_path, check_error_state, parent_window);
339ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
340ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
34158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void SetTechnologyEnabled(const NetworkTypePattern& technology,
34258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                          bool enabled_state) {
3433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string log_string =
3443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::StringPrintf("technology %s, target state: %s",
34558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                         technology.ToDebugString().c_str(),
3463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                         (enabled_state ? "ENABLED" : "DISABLED"));
3473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  NET_LOG_USER("SetTechnologyEnabled", log_string);
3483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
3493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  bool enabled = handler->IsTechnologyEnabled(technology);
3503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (enabled_state == enabled) {
3513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    NET_LOG_USER("Technology already in target state.", log_string);
3523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
3533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (enabled) {
3553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // User requested to disable the technology.
3563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    handler->SetTechnologyEnabled(
3573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        technology, false, chromeos::network_handler::ErrorCallback());
3583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
3593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // If we're dealing with a mobile network, then handle SIM lock here.
3613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // SIM locking only applies to cellular, so the code below won't execute
3623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // if |technology| has been explicitly set to WiMAX.
36358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (technology.MatchesPattern(NetworkTypePattern::Mobile())) {
3643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const DeviceState* mobile = handler->GetDeviceStateByType(technology);
3653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (!mobile) {
3663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NET_LOG_ERROR("SetTechnologyEnabled with no device", log_string);
3673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return;
3683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
3693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // The following only applies to cellular.
37068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (mobile->type() == shill::kTypeCellular) {
3713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      if (mobile->IsSimAbsent()) {
3723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        // If this is true, then we have a cellular device with no SIM inserted.
3733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        // TODO(armansito): Chrome should display a notification here, prompting
3743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        // the user to insert a SIM card and restart the device to enable
3753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        // cellular. See crbug.com/125171.
3763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        NET_LOG_USER("Cannot enable cellular device without SIM.", log_string);
3773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        return;
3783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      }
3793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      if (!mobile->sim_lock_type().empty()) {
3803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        // A SIM has been inserted, but it is locked. Let the user unlock it
3813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        // via the dialog.
3823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        ash::Shell::GetInstance()->system_tray_delegate()->
3833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            ShowMobileSimDialog();
3843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        return;
3853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      }
3863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
3873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  handler->SetTechnologyEnabled(
3893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    technology, true, chromeos::network_handler::ErrorCallback());
3903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
392ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ActivateCellular(const std::string& service_path) {
393ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  NET_LOG_USER("ActivateCellular", service_path);
3944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const NetworkState* cellular = GetNetworkState(service_path);
39568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!cellular || cellular->type() != shill::kTypeCellular) {
3963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    NET_LOG_ERROR("ActivateCellular with no Service", service_path);
3973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
3983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
399ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  const DeviceState* cellular_device =
400ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      NetworkHandler::Get()->network_state_handler()->
4013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      GetDeviceState(cellular->device_path());
402ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!cellular_device) {
403ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    NET_LOG_ERROR("ActivateCellular with no Device", service_path);
404ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
405ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
406ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!IsDirectActivatedCarrier(cellular_device->carrier())) {
407ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // For non direct activation, show the mobile setup dialog which can be
40858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // used to activate the network.
40958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ShowMobileSetup(service_path);
410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
411ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
41268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (cellular->activation_state() == shill::kActivationStateActivated) {
413ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    NET_LOG_ERROR("ActivateCellular for activated service", service_path);
414ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
415ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
416ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
417424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  NetworkHandler::Get()->network_activation_handler()->Activate(
418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      service_path,
419ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "",  // carrier
420ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Bind(&OnActivateSucceeded, service_path),
421ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Bind(&OnActivateFailed, service_path));
422ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
423ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
4243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ShowMobileSetup(const std::string& service_path) {
4253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
4263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const NetworkState* cellular = handler->GetNetworkState(service_path);
42768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!cellular || cellular->type() != shill::kTypeCellular) {
4283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    NET_LOG_ERROR("ShowMobileSetup without Cellular network", service_path);
4293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
4303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
43168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (cellular->activation_state() != shill::kActivationStateActivated &&
4323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      cellular->activate_over_non_cellular_networks() &&
4333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      !handler->DefaultNetwork()) {
4343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    message_center::MessageCenter::Get()->AddNotification(
4353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        message_center::Notification::CreateSystemNotification(
4363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            kNetworkActivateNotificationId,
4373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            l10n_util::GetStringUTF16(IDS_NETWORK_ACTIVATION_ERROR_TITLE),
4383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            l10n_util::GetStringFUTF16(IDS_NETWORK_ACTIVATION_NEEDS_CONNECTION,
4393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                       UTF8ToUTF16(cellular->name())),
4403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            ui::ResourceBundle::GetSharedInstance().GetImageNamed(
4413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                IDR_AURA_UBER_TRAY_CELLULAR_NETWORK_FAILED),
442a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            ash::system_notifier::kNotifierNetwork,
4433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            base::Bind(&ash::network_connect::ShowNetworkSettings,
4443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                       service_path)));
4453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
4463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
4473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ash::Shell::GetInstance()->system_tray_delegate()->ShowMobileSetupDialog(
4483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      service_path);
4493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
451ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ConfigureNetworkAndConnect(const std::string& service_path,
452ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                const base::DictionaryValue& properties,
453ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                bool shared) {
454ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  NET_LOG_USER("ConfigureNetworkAndConnect", service_path);
455ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
456ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  scoped_ptr<base::DictionaryValue> properties_to_set(properties.DeepCopy());
457ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
458ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::string profile_path;
459ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!GetNetworkProfilePath(shared, &profile_path)) {
460ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    ShowErrorNotification(
461d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        NetworkConnectionHandler::kErrorConfigureFailed, "", service_path);
462ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
463ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
464ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  NetworkHandler::Get()->network_configuration_handler()->SetNetworkProfile(
465ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      service_path, profile_path,
466ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Bind(&ConfigureSetProfileSucceeded,
467ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 service_path, base::Passed(&properties_to_set)),
468ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Bind(&SetPropertiesFailed,
469ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 "SetProfile: " + profile_path, service_path));
470ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
471ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
472ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid CreateConfigurationAndConnect(base::DictionaryValue* properties,
473ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                   bool shared) {
474ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  NET_LOG_USER("CreateConfigurationAndConnect", "");
475ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::string profile_path;
476ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!GetNetworkProfilePath(shared, &profile_path)) {
477d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ShowErrorNotification(
478d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        NetworkConnectionHandler::kErrorConfigureFailed, "", "");
479ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
480ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
481ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  properties->SetStringWithoutPathExpansion(
48268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      shill::kProfileProperty, profile_path);
483ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  NetworkHandler::Get()->network_configuration_handler()->CreateConfiguration(
484ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      *properties,
485ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Bind(&OnConfigureSucceeded),
486ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Bind(&OnConfigureFailed));
487868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
488868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)string16 ErrorString(const std::string& error,
4904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                     const std::string& service_path) {
4917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error.empty())
4927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return string16();
49368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error == shill::kErrorOutOfRange)
4947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_OUT_OF_RANGE);
49568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error == shill::kErrorPinMissing)
4967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_PIN_MISSING);
49768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error == shill::kErrorDhcpFailed)
4987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_DHCP_FAILED);
49968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error == shill::kErrorConnectFailed)
5007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_CONNECT_FAILED);
50168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error == shill::kErrorBadPassphrase)
5027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_BAD_PASSPHRASE);
50368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error == shill::kErrorBadWEPKey)
5047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_BAD_WEPKEY);
50568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error == shill::kErrorActivationFailed) {
5067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return l10n_util::GetStringUTF16(
5077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        IDS_CHROMEOS_NETWORK_ERROR_ACTIVATION_FAILED);
5087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
50968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error == shill::kErrorNeedEvdo)
5107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_NEED_EVDO);
51168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error == shill::kErrorNeedHomeNetwork) {
5127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return l10n_util::GetStringUTF16(
5137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        IDS_CHROMEOS_NETWORK_ERROR_NEED_HOME_NETWORK);
5147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
51568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error == shill::kErrorOtaspFailed)
5167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_OTASP_FAILED);
51768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error == shill::kErrorAaaFailed)
5187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_AAA_FAILED);
51968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error == shill::kErrorInternal)
5207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_INTERNAL);
52168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error == shill::kErrorDNSLookupFailed) {
5227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return l10n_util::GetStringUTF16(
5237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        IDS_CHROMEOS_NETWORK_ERROR_DNS_LOOKUP_FAILED);
5247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
52568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error == shill::kErrorHTTPGetFailed) {
5267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return l10n_util::GetStringUTF16(
5277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        IDS_CHROMEOS_NETWORK_ERROR_HTTP_GET_FAILED);
5287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
52968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error == shill::kErrorIpsecPskAuthFailed) {
5307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return l10n_util::GetStringUTF16(
5317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        IDS_CHROMEOS_NETWORK_ERROR_IPSEC_PSK_AUTH_FAILED);
5327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
5334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error == shill::kErrorIpsecCertAuthFailed) {
5347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return l10n_util::GetStringUTF16(
5357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        IDS_CHROMEOS_NETWORK_ERROR_CERT_AUTH_FAILED);
5367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
5374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error == shill::kErrorEapAuthenticationFailed) {
5384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const NetworkState* network = GetNetworkState(service_path);
5394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // TLS always requires a client certificate, so show a cert auth
5404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // failed message for TLS. Other EAP methods do not generally require
5414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // a client certicate.
5424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (network && network->eap_method() == shill::kEapMethodTLS) {
5434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return l10n_util::GetStringUTF16(
5444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          IDS_CHROMEOS_NETWORK_ERROR_CERT_AUTH_FAILED);
5454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    } else {
5464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return l10n_util::GetStringUTF16(
5474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          IDS_CHROMEOS_NETWORK_ERROR_EAP_AUTH_FAILED);
5484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
5494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
5507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error == shill::kErrorEapLocalTlsFailed) {
5517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return l10n_util::GetStringUTF16(
5527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        IDS_CHROMEOS_NETWORK_ERROR_EAP_LOCAL_TLS_FAILED);
5537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
5547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error == shill::kErrorEapRemoteTlsFailed) {
5557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return l10n_util::GetStringUTF16(
5567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        IDS_CHROMEOS_NETWORK_ERROR_EAP_REMOTE_TLS_FAILED);
5577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
55868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error == shill::kErrorPppAuthFailed) {
5597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return l10n_util::GetStringUTF16(
5607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        IDS_CHROMEOS_NETWORK_ERROR_PPP_AUTH_FAILED);
5617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
5627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (StringToLowerASCII(error) ==
56468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      StringToLowerASCII(std::string(shill::kUnknownString))) {
5657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_UNKNOWN);
5667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
5677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return l10n_util::GetStringFUTF16(IDS_NETWORK_UNRECOGNIZED_ERROR,
5687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                    UTF8ToUTF16(error));
5697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
5707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ShowNetworkSettings(const std::string& service_path) {
5723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!ash::Shell::HasInstance())
5733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
5743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ash::Shell::GetInstance()->system_tray_delegate()->ShowNetworkSettings(
5753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      service_path);
5763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
578868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // network_connect
579868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // ash
580