network_state_notifier.cc revision 424c4d7b64af9d0d8fd9624f381f469654d5e3d2
1// Copyright (c) 2012 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_state_notifier.h" 6 7#include "ash/shell.h" 8#include "ash/system/chromeos/network/network_connect.h" 9#include "ash/system/system_notifier.h" 10#include "ash/system/tray/system_tray_delegate.h" 11#include "base/strings/string16.h" 12#include "base/strings/string_util.h" 13#include "base/strings/utf_string_conversions.h" 14#include "chromeos/network/network_configuration_handler.h" 15#include "chromeos/network/network_connection_handler.h" 16#include "chromeos/network/network_event_log.h" 17#include "chromeos/network/network_state.h" 18#include "chromeos/network/network_state_handler.h" 19#include "grit/ash_resources.h" 20#include "grit/ash_strings.h" 21#include "third_party/cros_system_api/dbus/service_constants.h" 22#include "ui/base/l10n/l10n_util.h" 23#include "ui/base/resource/resource_bundle.h" 24#include "ui/message_center/message_center.h" 25#include "ui/message_center/notification.h" 26 27using chromeos::NetworkConnectionHandler; 28using chromeos::NetworkHandler; 29using chromeos::NetworkState; 30using chromeos::NetworkStateHandler; 31 32namespace { 33 34const char kNetworkOutOfCreditsNotificationId[] = 35 "chrome://settings/internet/out-of-credits"; 36 37const int kMinTimeBetweenOutOfCreditsNotifySeconds = 10 * 60; 38 39// Error messages based on |error_name|, not network_state->error(). 40string16 GetConnectErrorString(const std::string& error_name) { 41 if (error_name == NetworkConnectionHandler::kErrorNotFound) 42 return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_CONNECT_FAILED); 43 if (error_name == NetworkConnectionHandler::kErrorConfigureFailed) 44 return l10n_util::GetStringUTF16( 45 IDS_CHROMEOS_NETWORK_ERROR_CONFIGURE_FAILED); 46 if (error_name == NetworkConnectionHandler::kErrorActivateFailed) 47 return l10n_util::GetStringUTF16( 48 IDS_CHROMEOS_NETWORK_ERROR_ACTIVATION_FAILED); 49 return string16(); 50} 51 52void ShowErrorNotification(const std::string& notification_id, 53 const std::string& network_type, 54 const base::string16& title, 55 const base::string16& message, 56 const base::Closure& callback) { 57 int icon_id = (network_type == flimflam::kTypeCellular) ? 58 IDR_AURA_UBER_TRAY_CELLULAR_NETWORK_FAILED : 59 IDR_AURA_UBER_TRAY_NETWORK_FAILED; 60 const gfx::Image& icon = 61 ui::ResourceBundle::GetSharedInstance().GetImageNamed(icon_id); 62 message_center::MessageCenter::Get()->AddNotification( 63 message_center::Notification::CreateSystemNotification( 64 notification_id, 65 title, 66 message, 67 icon, 68 ash::NOTIFIER_NETWORK_ERROR, 69 callback)); 70} 71 72void ConfigureNetwork(const std::string& service_path) { 73 ash::Shell::GetInstance()->system_tray_delegate()->ConfigureNetwork( 74 service_path); 75} 76 77} // namespace 78 79namespace ash { 80 81NetworkStateNotifier::NetworkStateNotifier() 82 : did_show_out_of_credits_(false), 83 weak_ptr_factory_(this) { 84 if (!NetworkHandler::IsInitialized()) 85 return; 86 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler(); 87 handler->AddObserver(this, FROM_HERE); 88 UpdateDefaultNetwork(handler->DefaultNetwork()); 89} 90 91NetworkStateNotifier::~NetworkStateNotifier() { 92 if (!NetworkHandler::IsInitialized()) 93 return; 94 NetworkHandler::Get()->network_state_handler()->RemoveObserver( 95 this, FROM_HERE); 96} 97 98void NetworkStateNotifier::DefaultNetworkChanged(const NetworkState* network) { 99 if (!UpdateDefaultNetwork(network)) 100 return; 101 // If the default network changes to another network, allow the out of 102 // credits notification to be shown again. A delay prevents the notification 103 // from being shown too frequently (see below). 104 if (network) 105 did_show_out_of_credits_ = false; 106} 107 108void NetworkStateNotifier::NetworkPropertiesUpdated( 109 const NetworkState* network) { 110 if (network->type() != flimflam::kTypeCellular) 111 return; 112 UpdateCellularOutOfCredits(network); 113 UpdateCellularActivating(network); 114} 115 116bool NetworkStateNotifier::UpdateDefaultNetwork(const NetworkState* network) { 117 std::string default_network_path; 118 if (network) 119 default_network_path = network->path(); 120 if (default_network_path != last_default_network_) { 121 last_default_network_ = default_network_path; 122 return true; 123 } 124 return false; 125} 126 127void NetworkStateNotifier::UpdateCellularOutOfCredits( 128 const NetworkState* cellular) { 129 // Only display a notification if we are out of credits and have not already 130 // shown a notification (or have since connected to another network type). 131 if (!cellular->cellular_out_of_credits() || did_show_out_of_credits_) 132 return; 133 134 // Only display a notification if not connected, connecting, or waiting to 135 // connect to another network. 136 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler(); 137 const NetworkState* default_network = handler->DefaultNetwork(); 138 if (default_network && default_network != cellular) 139 return; 140 if (handler->ConnectingNetworkByType( 141 NetworkStateHandler::kMatchTypeNonVirtual) || 142 NetworkHandler::Get()->network_connection_handler() 143 ->HasPendingConnectRequest()) 144 return; 145 146 did_show_out_of_credits_ = true; 147 base::TimeDelta dtime = base::Time::Now() - out_of_credits_notify_time_; 148 if (dtime.InSeconds() > kMinTimeBetweenOutOfCreditsNotifySeconds) { 149 out_of_credits_notify_time_ = base::Time::Now(); 150 string16 error_msg = l10n_util::GetStringFUTF16( 151 IDS_NETWORK_OUT_OF_CREDITS_BODY, 152 UTF8ToUTF16(cellular->name())); 153 ShowErrorNotification( 154 kNetworkOutOfCreditsNotificationId, 155 cellular->type(), 156 l10n_util::GetStringUTF16(IDS_NETWORK_OUT_OF_CREDITS_TITLE), 157 error_msg, 158 base::Bind(&ConfigureNetwork, cellular->path())); 159 } 160} 161 162void NetworkStateNotifier::UpdateCellularActivating( 163 const NetworkState* cellular) { 164 // Keep track of any activating cellular network. 165 std::string activation_state = cellular->activation_state(); 166 if (activation_state == flimflam::kActivationStateActivating) { 167 cellular_activating_.insert(cellular->path()); 168 return; 169 } 170 // Only display a notification if this network was activating and is now 171 // activated. 172 if (!cellular_activating_.count(cellular->path()) || 173 activation_state != flimflam::kActivationStateActivated) 174 return; 175 176 cellular_activating_.erase(cellular->path()); 177 int icon_id; 178 if (cellular->network_technology() == flimflam::kNetworkTechnologyLte) 179 icon_id = IDR_AURA_UBER_TRAY_NOTIFICATION_LTE; 180 else 181 icon_id = IDR_AURA_UBER_TRAY_NOTIFICATION_3G; 182 const gfx::Image& icon = 183 ui::ResourceBundle::GetSharedInstance().GetImageNamed(icon_id); 184 message_center::MessageCenter::Get()->AddNotification( 185 message_center::Notification::CreateSystemNotification( 186 ash::network_connect::kNetworkActivateNotificationId, 187 l10n_util::GetStringUTF16(IDS_NETWORK_CELLULAR_ACTIVATED_TITLE), 188 l10n_util::GetStringFUTF16(IDS_NETWORK_CELLULAR_ACTIVATED, 189 UTF8ToUTF16((cellular->name()))), 190 icon, 191 NOTIFIER_NETWORK, 192 base::Bind(&ash::network_connect::ShowNetworkSettings, 193 cellular->path()))); 194} 195 196void NetworkStateNotifier::ShowNetworkConnectError( 197 const std::string& error_name, 198 const std::string& service_path) { 199 if (service_path.empty()) { 200 base::DictionaryValue shill_properties; 201 ShowConnectErrorNotification(error_name, service_path, shill_properties); 202 return; 203 } 204 // Get the up-to-date properties for the network and display the error. 205 NetworkHandler::Get()->network_configuration_handler()->GetProperties( 206 service_path, 207 base::Bind(&NetworkStateNotifier::ConnectErrorPropertiesSucceeded, 208 weak_ptr_factory_.GetWeakPtr(), error_name), 209 base::Bind(&NetworkStateNotifier::ConnectErrorPropertiesFailed, 210 weak_ptr_factory_.GetWeakPtr(), error_name, service_path)); 211} 212 213void NetworkStateNotifier::ConnectErrorPropertiesSucceeded( 214 const std::string& error_name, 215 const std::string& service_path, 216 const base::DictionaryValue& shill_properties) { 217 ShowConnectErrorNotification(error_name, service_path, shill_properties); 218} 219 220void NetworkStateNotifier::ConnectErrorPropertiesFailed( 221 const std::string& error_name, 222 const std::string& service_path, 223 const std::string& shill_error_name, 224 scoped_ptr<base::DictionaryValue> shill_error_data) { 225 base::DictionaryValue shill_properties; 226 ShowConnectErrorNotification(error_name, service_path, shill_properties); 227} 228 229void NetworkStateNotifier::ShowConnectErrorNotification( 230 const std::string& error_name, 231 const std::string& service_path, 232 const base::DictionaryValue& shill_properties) { 233 string16 error = GetConnectErrorString(error_name); 234 if (error.empty()) { 235 std::string network_error; 236 shill_properties.GetStringWithoutPathExpansion( 237 flimflam::kErrorProperty, &network_error); 238 error = network_connect::ErrorString(network_error); 239 if (error.empty()) 240 error = l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_UNKNOWN); 241 } 242 NET_LOG_ERROR("Connect error notification: " + UTF16ToUTF8(error), 243 service_path); 244 245 std::string network_name = 246 NetworkState::GetNameFromProperties(service_path, shill_properties); 247 std::string network_error_details; 248 shill_properties.GetStringWithoutPathExpansion( 249 shill::kErrorDetailsProperty, &network_error_details); 250 251 string16 error_msg; 252 if (!network_error_details.empty()) { 253 // network_name should't be empty if network_error_details is set. 254 error_msg = l10n_util::GetStringFUTF16( 255 IDS_NETWORK_CONNECTION_ERROR_MESSAGE_WITH_SERVER_MESSAGE, 256 UTF8ToUTF16(network_name), error, 257 UTF8ToUTF16(network_error_details)); 258 } else if (network_name.empty()) { 259 error_msg = l10n_util::GetStringFUTF16( 260 IDS_NETWORK_CONNECTION_ERROR_MESSAGE_NO_NAME, error); 261 } else { 262 error_msg = l10n_util::GetStringFUTF16( 263 IDS_NETWORK_CONNECTION_ERROR_MESSAGE, 264 UTF8ToUTF16(network_name), error); 265 } 266 267 std::string network_type; 268 shill_properties.GetStringWithoutPathExpansion( 269 flimflam::kTypeProperty, &network_type); 270 271 ShowErrorNotification( 272 network_connect::kNetworkConnectNotificationId, 273 network_type, 274 l10n_util::GetStringUTF16(IDS_NETWORK_CONNECTION_ERROR_TITLE), 275 error_msg, 276 base::Bind(&network_connect::ShowNetworkSettings, service_path)); 277} 278 279} // namespace ash 280