network_message_observer.cc revision 4a5e2dc747d50c653511c68ccb2cfbfb740bd5a7
1// Copyright (c) 2010 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 "chrome/browser/chromeos/network_message_observer.h" 6 7#include "app/l10n_util.h" 8#include "base/callback.h" 9#include "base/stl_util-inl.h" 10#include "base/string_number_conversions.h" 11#include "base/utf_string_conversions.h" 12#include "chrome/browser/browser_list.h" 13#include "chrome/browser/browser_window.h" 14#include "chrome/browser/chromeos/cros/cros_library.h" 15#include "chrome/browser/chromeos/cros/network_library.h" 16#include "chrome/browser/chromeos/notifications/balloon_view_host.h" 17#include "chrome/browser/chromeos/options/network_config_view.h" 18#include "chrome/browser/ui/browser.h" 19#include "chrome/browser/views/window.h" 20#include "grit/generated_resources.h" 21#include "grit/theme_resources.h" 22#include "views/window/dialog_delegate.h" 23#include "views/window/window.h" 24 25namespace chromeos { 26 27NetworkMessageObserver::NetworkMessageObserver(Profile* profile) 28 : initialized_(false), 29 notification_connection_error_(profile, "network_connection.chromeos", 30 IDR_NOTIFICATION_NETWORK_FAILED, 31 l10n_util::GetStringUTF16(IDS_NETWORK_CONNECTION_ERROR_TITLE)), 32 notification_low_data_(profile, "network_low_data.chromeos", 33 IDR_NOTIFICATION_BARS_CRITICAL, 34 l10n_util::GetStringUTF16(IDS_NETWORK_LOW_DATA_TITLE)), 35 notification_no_data_(profile, "network_no_data.chromeos", 36 IDR_NOTIFICATION_BARS_EMPTY, 37 l10n_util::GetStringUTF16(IDS_NETWORK_OUT_OF_DATA_TITLE)) { 38 NetworkLibrary* netlib = CrosLibrary::Get()->GetNetworkLibrary(); 39 OnNetworkManagerChanged(netlib); 40 // Note that this gets added as a NetworkManagerObserver and a 41 // CellularDataPlanObserver in browser_init.cc 42 initialized_ = true; 43} 44 45NetworkMessageObserver::~NetworkMessageObserver() { 46 NetworkLibrary* netlib = CrosLibrary::Get()->GetNetworkLibrary(); 47 netlib->RemoveNetworkManagerObserver(this); 48 netlib->RemoveCellularDataPlanObserver(this); 49 notification_connection_error_.Hide(); 50 notification_low_data_.Hide(); 51 notification_no_data_.Hide(); 52 STLDeleteValues(&cellular_networks_); 53 STLDeleteValues(&wifi_networks_); 54} 55 56void NetworkMessageObserver::CreateModalPopup(views::WindowDelegate* view) { 57 Browser* browser = BrowserList::GetLastActive(); 58 if (browser && browser->type() != Browser::TYPE_NORMAL) { 59 browser = BrowserList::FindBrowserWithType(browser->profile(), 60 Browser::TYPE_NORMAL, 61 true); 62 } 63 DCHECK(browser); 64 views::Window* window = browser::CreateViewsWindow( 65 browser->window()->GetNativeHandle(), gfx::Rect(), view); 66 window->SetIsAlwaysOnTop(true); 67 window->Show(); 68} 69 70void NetworkMessageObserver::OpenMobileSetupPage(const ListValue* args) { 71 Browser* browser = BrowserList::GetLastActive(); 72 if (browser) 73 browser->OpenMobilePlanTabAndActivate(); 74} 75 76void NetworkMessageObserver::OpenMoreInfoPage(const ListValue* args) { 77 Browser* browser = BrowserList::GetLastActive(); 78 if (!browser) 79 return; 80 chromeos::NetworkLibrary* lib = 81 chromeos::CrosLibrary::Get()->GetNetworkLibrary(); 82 chromeos::CellularNetwork* cellular = lib->cellular_network(); 83 if (!cellular) 84 return; 85 browser->ShowSingletonTab(GURL(cellular->payment_url()), false); 86} 87 88void NetworkMessageObserver::OnNetworkManagerChanged(NetworkLibrary* obj) { 89 const WifiNetworkVector& wifi_networks = obj->wifi_networks(); 90 const CellularNetworkVector& cellular_networks = obj->cellular_networks(); 91 92 NetworkConfigView* view = NULL; 93 std::string new_failed_network; 94 // Check to see if we have any newly failed wifi network. 95 for (WifiNetworkVector::const_iterator it = wifi_networks.begin(); 96 it < wifi_networks.end(); it++) { 97 const WifiNetwork* wifi = *it; 98 if (wifi->failed()) { 99 ServicePathWifiMap::iterator iter = 100 wifi_networks_.find(wifi->service_path()); 101 // If the network did not previously exist, then don't do anything. 102 // For example, if the user travels to a location and finds a service 103 // that has previously failed, we don't want to show a notification. 104 if (iter == wifi_networks_.end()) 105 continue; 106 107 const WifiNetwork* wifi_old = iter->second; 108 // If this network was in a failed state previously, then it's not new. 109 if (wifi_old->failed()) 110 continue; 111 112 // Display login box again for bad_passphrase and bad_wepkey errors. 113 if (wifi->error() == ERROR_BAD_PASSPHRASE || 114 wifi->error() == ERROR_BAD_WEPKEY) { 115 // The NetworkConfigView will show the appropriate error message. 116 view = new NetworkConfigView(wifi, true); 117 // There should only be one wifi network that failed to connect. 118 // If for some reason, we have more than one failure, 119 // we only display the first one. So we break here. 120 break; 121 } 122 123 // If network connection failed, display a notification. 124 // We only do this if we were trying to make a new connection. 125 // So if a previously connected network got disconnected for any reason, 126 // we don't display notification. 127 if (wifi_old->connecting()) { 128 new_failed_network = wifi->name(); 129 // Like above, there should only be one newly failed network. 130 break; 131 } 132 } 133 134 // If we find any network connecting, we hide the error notification. 135 if (wifi->connecting()) { 136 notification_connection_error_.Hide(); 137 } 138 } 139 140 // Refresh stored networks. 141 STLDeleteValues(&wifi_networks_); 142 wifi_networks_.clear(); 143 for (WifiNetworkVector::const_iterator it = wifi_networks.begin(); 144 it < wifi_networks.end(); it++) { 145 const WifiNetwork* wifi = *it; 146 wifi_networks_[wifi->service_path()] = new WifiNetwork(*wifi); 147 } 148 149 STLDeleteValues(&cellular_networks_); 150 cellular_networks_.clear(); 151 for (CellularNetworkVector::const_iterator it = cellular_networks.begin(); 152 it < cellular_networks.end(); it++) { 153 const CellularNetwork* cellular = *it; 154 cellular_networks_[cellular->service_path()] = 155 new CellularNetwork(*cellular); 156 } 157 158 // Show connection error notification if necessary. 159 if (!new_failed_network.empty()) { 160 // Hide if already shown to force show it in case user has closed it. 161 if (notification_connection_error_.visible()) 162 notification_connection_error_.Hide(); 163 notification_connection_error_.Show(l10n_util::GetStringFUTF16( 164 IDS_NETWORK_CONNECTION_ERROR_MESSAGE, 165 ASCIIToUTF16(new_failed_network)), false, false); 166 } 167 168 // Show login box if necessary. 169 if (view && initialized_) 170 CreateModalPopup(view); 171} 172 173void NetworkMessageObserver::OnCellularDataPlanChanged(NetworkLibrary* obj) { 174 const CellularNetwork* cellular = obj->cellular_network(); 175 if (!cellular) 176 return; 177 // Active plan is the first one in the list. Use empty one if none found. 178 const CellularDataPlanVector& plans = cellular->GetDataPlans(); 179 CellularDataPlan plan = plans.empty() ? CellularDataPlan() : plans[0]; 180 // If connected cellular network changed, or data plan is different, then 181 // it's a new network. Then hide all previous notifications. 182 bool new_plan = false; 183 if (cellular->service_path() != cellular_service_path_) { 184 cellular_service_path_ = cellular->service_path(); 185 new_plan = true; 186 } else if (plan.plan_name != cellular_data_plan_.plan_name || 187 plan.plan_type != cellular_data_plan_.plan_type) { 188 new_plan = true; 189 } 190 191 cellular_data_plan_ = plan; 192 193 if (new_plan) { 194 notification_low_data_.Hide(); 195 notification_no_data_.Hide(); 196 if (plans.empty() && cellular->needs_new_plan()) { 197 notification_no_data_.set_title( 198 l10n_util::GetStringFUTF16(IDS_NETWORK_NO_DATA_PLAN_TITLE, 199 UTF8ToUTF16(cellular->service_name()))); 200 notification_no_data_.Show( 201 l10n_util::GetStringFUTF16( 202 IDS_NETWORK_NO_DATA_PLAN_MESSAGE, 203 UTF8ToUTF16(cellular->service_name())), 204 l10n_util::GetStringUTF16(IDS_NETWORK_PURCHASE_MORE_MESSAGE), 205 NewCallback(this, &NetworkMessageObserver::OpenMobileSetupPage), 206 false, false); 207 return; 208 } else if (plan.plan_type == CELLULAR_DATA_PLAN_UNLIMITED) { 209 notification_no_data_.set_title( 210 l10n_util::GetStringFUTF16(IDS_NETWORK_DATA_EXPIRED_TITLE, 211 ASCIIToUTF16(plan.plan_name))); 212 notification_low_data_.set_title( 213 l10n_util::GetStringFUTF16(IDS_NETWORK_NEARING_EXPIRATION_TITLE, 214 ASCIIToUTF16(plan.plan_name))); 215 } else { 216 notification_no_data_.set_title( 217 l10n_util::GetStringFUTF16(IDS_NETWORK_OUT_OF_DATA_TITLE, 218 ASCIIToUTF16(plan.plan_name))); 219 notification_low_data_.set_title( 220 l10n_util::GetStringFUTF16(IDS_NETWORK_LOW_DATA_TITLE, 221 ASCIIToUTF16(plan.plan_name))); 222 } 223 } 224 225 if (plan.plan_type == CELLULAR_DATA_PLAN_UNKNOWN) 226 return; 227 228 if (cellular->data_left() == CellularNetwork::DATA_NONE) { 229 notification_low_data_.Hide(); 230 int message = plan.plan_type == CELLULAR_DATA_PLAN_UNLIMITED ? 231 IDS_NETWORK_MINUTES_REMAINING_MESSAGE : 232 IDS_NETWORK_DATA_REMAINING_MESSAGE; 233 notification_no_data_.Show(l10n_util::GetStringFUTF16( 234 message, ASCIIToUTF16("0")), 235 l10n_util::GetStringUTF16(IDS_NETWORK_PURCHASE_MORE_MESSAGE), 236 NewCallback(this, &NetworkMessageObserver::OpenMobileSetupPage), 237 false, false); 238 } else if (cellular->data_left() == CellularNetwork::DATA_VERY_LOW) { 239 notification_no_data_.Hide(); 240 int message = plan.plan_type == CELLULAR_DATA_PLAN_UNLIMITED ? 241 IDS_NETWORK_MINUTES_REMAINING_MESSAGE : 242 IDS_NETWORK_DATA_REMAINING_MESSAGE; 243 int64 remaining = plan.plan_type == 244 CELLULAR_DATA_PLAN_UNLIMITED ? plan.remaining_minutes() : 245 plan.remaining_mbytes(); 246 notification_low_data_.Show(l10n_util::GetStringFUTF16( 247 message, UTF8ToUTF16(base::Int64ToString(remaining))), 248 l10n_util::GetStringUTF16(IDS_NETWORK_MORE_INFO_MESSAGE), 249 NewCallback(this, &NetworkMessageObserver::OpenMoreInfoPage), 250 false, false); 251 } else { 252 // Got data, so hide notifications. 253 notification_low_data_.Hide(); 254 notification_no_data_.Hide(); 255 } 256} 257 258} // namespace chromeos 259