Revert 168224 - Update V8 to version 3.15.4.
[chromium-blink-merge.git] / chrome / browser / chromeos / network_message_observer.cc
blob5501d76729ae53d3bab8c24d6a8af394acab932f
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.
5 #include "chrome/browser/chromeos/network_message_observer.h"
7 #include "ash/shell.h"
8 #include "ash/shell_delegate.h"
9 #include "ash/system/chromeos/network/network_observer.h"
10 #include "ash/system/tray/system_tray.h"
11 #include "ash/system/tray/system_tray_notifier.h"
12 #include "base/bind.h"
13 #include "base/callback.h"
14 #include "base/stl_util.h"
15 #include "base/string_number_conversions.h"
16 #include "base/utf_string_conversions.h"
17 #include "chrome/browser/chromeos/cros/cros_library.h"
18 #include "chrome/browser/chromeos/cros/network_library.h"
19 #include "chrome/browser/chromeos/notifications/balloon_view_host_chromeos.h"
20 #include "chrome/browser/prefs/pref_service.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/profiles/profile_manager.h"
23 #include "chrome/browser/ui/browser.h"
24 #include "chrome/browser/ui/browser_finder.h"
25 #include "chrome/browser/ui/host_desktop.h"
26 #include "chrome/browser/ui/singleton_tabs.h"
27 #include "chrome/common/pref_names.h"
28 #include "chrome/common/time_format.h"
29 #include "grit/generated_resources.h"
30 #include "ui/base/l10n/l10n_util.h"
32 namespace {
34 // Returns prefs::kShowPlanNotifications in the profile of the last active
35 // browser. If there is no active browser, returns true.
36 bool ShouldShowMobilePlanNotifications() {
37 Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord();
38 PrefService* prefs = profile->GetPrefs();
39 return prefs->GetBoolean(prefs::kShowPlanNotifications);
42 } // namespace
44 namespace chromeos {
46 class NetworkMessageNotification : public ash::NetworkTrayDelegate {
47 public:
48 NetworkMessageNotification(Profile* profile,
49 ash::NetworkObserver::MessageType error_type)
50 : error_type_(error_type) {
51 switch (error_type) {
52 case ash::NetworkObserver::ERROR_CONNECT_FAILED:
53 title_ = l10n_util::GetStringUTF16(IDS_NETWORK_CONNECTION_ERROR_TITLE);
54 break;
55 case ash::NetworkObserver::MESSAGE_DATA_LOW:
56 title_ = l10n_util::GetStringUTF16(IDS_NETWORK_LOW_DATA_TITLE);
57 break;
58 case ash::NetworkObserver::MESSAGE_DATA_NONE:
59 title_ = l10n_util::GetStringUTF16(IDS_NETWORK_OUT_OF_DATA_TITLE);
60 break;
61 case ash::NetworkObserver::MESSAGE_DATA_PROMO:
62 NOTREACHED();
63 break;
67 // Overridden from ash::NetworkTrayDelegate:
68 virtual void NotificationLinkClicked(size_t index) OVERRIDE {
69 base::ListValue empty_value;
70 if (!callback_.is_null())
71 callback_.Run(&empty_value);
74 void Hide() {
75 ash::Shell::GetInstance()->system_tray_notifier()->
76 NotifyClearNetworkMessage(error_type_);
79 void SetTitle(const string16& title) {
80 title_ = title;
83 void Show(const string16& message,
84 const string16& link_text,
85 const BalloonViewHost::MessageCallback& callback,
86 bool urgent, bool sticky) {
87 callback_ = callback;
88 std::vector<string16> links;
89 links.push_back(link_text);
90 ash::Shell::GetInstance()->system_tray_notifier()->NotifySetNetworkMessage(
91 this, error_type_, title_, message, links);
94 void ShowAlways(const string16& message,
95 const string16& link_text,
96 const BalloonViewHost::MessageCallback& callback,
97 bool urgent, bool sticky) {
98 Show(message, link_text, callback, urgent, sticky);
101 private:
102 string16 title_;
103 ash::NetworkObserver::MessageType error_type_;
104 BalloonViewHost::MessageCallback callback_;
107 NetworkMessageObserver::NetworkMessageObserver(Profile* profile) {
108 notification_connection_error_.reset(
109 new NetworkMessageNotification(
110 profile, ash::NetworkObserver::ERROR_CONNECT_FAILED));
111 notification_low_data_.reset(
112 new NetworkMessageNotification(
113 profile,
114 ash::NetworkObserver::MESSAGE_DATA_LOW));
115 notification_no_data_.reset(
116 new NetworkMessageNotification(
117 profile,
118 ash::NetworkObserver::MESSAGE_DATA_NONE));
119 NetworkLibrary* netlib = CrosLibrary::Get()->GetNetworkLibrary();
120 OnNetworkManagerChanged(netlib);
121 // Note that this gets added as a NetworkManagerObserver,
122 // CellularDataPlanObserver, and UserActionObserver in
123 // startup_browser_creator.cc
126 NetworkMessageObserver::~NetworkMessageObserver() {
127 NetworkLibrary* netlib = CrosLibrary::Get()->GetNetworkLibrary();
128 netlib->RemoveNetworkManagerObserver(this);
129 netlib->RemoveCellularDataPlanObserver(this);
130 netlib->RemoveUserActionObserver(this);
131 notification_connection_error_->Hide();
132 notification_low_data_->Hide();
133 notification_no_data_->Hide();
136 // static
137 bool NetworkMessageObserver::IsApplicableBackupPlan(
138 const CellularDataPlan* plan, const CellularDataPlan* other_plan) {
139 // By applicable plan, we mean that the other plan has data AND the timeframe
140 // will apply: (unlimited OR used bytes < max bytes) AND
141 // ((start time - 1 sec) <= end time of currently active plan).
142 // In other words, there is data available and there is no gap of more than a
143 // second in time between the old plan and the new plan.
144 bool has_data = other_plan->plan_type == CELLULAR_DATA_PLAN_UNLIMITED ||
145 other_plan->remaining_data() > 0;
146 bool will_apply =
147 (other_plan->plan_start_time - plan->plan_end_time).InSeconds() <= 1;
148 return has_data && will_apply;
151 void NetworkMessageObserver::OpenMobileSetupPage(
152 const std::string& service_path, const ListValue* args) {
153 ash::Shell::GetInstance()->delegate()->OpenMobileSetup(service_path);
156 void NetworkMessageObserver::OpenMoreInfoPage(const ListValue* args) {
157 Browser* browser = browser::FindOrCreateTabbedBrowser(
158 ProfileManager::GetDefaultProfileOrOffTheRecord(),
159 chrome::HOST_DESKTOP_TYPE_ASH);
160 chromeos::NetworkLibrary* lib =
161 chromeos::CrosLibrary::Get()->GetNetworkLibrary();
162 const chromeos::CellularNetwork* cellular = lib->cellular_network();
163 if (!cellular)
164 return;
165 chrome::ShowSingletonTab(browser, GURL(cellular->payment_url()));
168 void NetworkMessageObserver::InitNewPlan(const CellularDataPlan* plan) {
169 notification_low_data_->Hide();
170 notification_no_data_->Hide();
171 if (plan->plan_type == CELLULAR_DATA_PLAN_UNLIMITED) {
172 notification_no_data_->SetTitle(
173 l10n_util::GetStringFUTF16(IDS_NETWORK_DATA_EXPIRED_TITLE,
174 ASCIIToUTF16(plan->plan_name)));
175 notification_low_data_->SetTitle(
176 l10n_util::GetStringFUTF16(IDS_NETWORK_NEARING_EXPIRATION_TITLE,
177 ASCIIToUTF16(plan->plan_name)));
178 } else {
179 notification_no_data_->SetTitle(
180 l10n_util::GetStringFUTF16(IDS_NETWORK_OUT_OF_DATA_TITLE,
181 ASCIIToUTF16(plan->plan_name)));
182 notification_low_data_->SetTitle(
183 l10n_util::GetStringFUTF16(IDS_NETWORK_LOW_DATA_TITLE,
184 ASCIIToUTF16(plan->plan_name)));
188 void NetworkMessageObserver::ShowNeedsPlanNotification(
189 const CellularNetwork* cellular) {
190 notification_no_data_->SetTitle(
191 l10n_util::GetStringFUTF16(IDS_NETWORK_NO_DATA_PLAN_TITLE,
192 UTF8ToUTF16(cellular->name())));
193 notification_no_data_->Show(
194 l10n_util::GetStringFUTF16(
195 IDS_NETWORK_NO_DATA_PLAN_MESSAGE,
196 UTF8ToUTF16(cellular->name())),
197 l10n_util::GetStringUTF16(IDS_NETWORK_PURCHASE_MORE_MESSAGE),
198 base::Bind(&NetworkMessageObserver::OpenMobileSetupPage,
199 AsWeakPtr(),
200 cellular->service_path()),
201 false, false);
204 void NetworkMessageObserver::ShowNoDataNotification(
205 const CellularNetwork* cellular,
206 CellularDataPlanType plan_type) {
207 notification_low_data_->Hide(); // Hide previous low data notification.
208 string16 message = plan_type == CELLULAR_DATA_PLAN_UNLIMITED ?
209 TimeFormat::TimeRemaining(base::TimeDelta()) :
210 l10n_util::GetStringFUTF16(IDS_NETWORK_DATA_REMAINING_MESSAGE,
211 ASCIIToUTF16("0"));
212 notification_no_data_->Show(message,
213 l10n_util::GetStringUTF16(IDS_NETWORK_PURCHASE_MORE_MESSAGE),
214 base::Bind(&NetworkMessageObserver::OpenMobileSetupPage,
215 AsWeakPtr(),
216 cellular->service_path()),
217 false, false);
220 void NetworkMessageObserver::ShowLowDataNotification(
221 const CellularDataPlan* plan) {
222 string16 message;
223 if (plan->plan_type == CELLULAR_DATA_PLAN_UNLIMITED) {
224 message = plan->GetPlanExpiration();
225 } else {
226 int64 remaining_mbytes = plan->remaining_data() / (1024 * 1024);
227 message = l10n_util::GetStringFUTF16(IDS_NETWORK_DATA_REMAINING_MESSAGE,
228 UTF8ToUTF16(base::Int64ToString(remaining_mbytes)));
230 notification_low_data_->Show(message,
231 l10n_util::GetStringUTF16(IDS_NETWORK_MORE_INFO_MESSAGE),
232 base::Bind(&NetworkMessageObserver::OpenMoreInfoPage, AsWeakPtr()),
233 false, false);
236 void NetworkMessageObserver::OnNetworkManagerChanged(NetworkLibrary* cros) {
237 const Network* new_failed_network = NULL;
238 // Check to see if we have any newly failed networks.
239 for (WifiNetworkVector::const_iterator it = cros->wifi_networks().begin();
240 it != cros->wifi_networks().end(); it++) {
241 const WifiNetwork* net = *it;
242 if (net->notify_failure()) {
243 new_failed_network = net;
244 break; // There should only be one failed network.
248 if (!new_failed_network) {
249 for (WimaxNetworkVector::const_iterator it = cros->wimax_networks().begin();
250 it != cros->wimax_networks().end(); ++it) {
251 const WimaxNetwork* net = *it;
252 if (net->notify_failure()) {
253 new_failed_network = net;
254 break; // There should only be one failed network.
259 if (!new_failed_network) {
260 for (CellularNetworkVector::const_iterator it =
261 cros->cellular_networks().begin();
262 it != cros->cellular_networks().end(); it++) {
263 const CellularNetwork* net = *it;
264 if (net->notify_failure()) {
265 new_failed_network = net;
266 break; // There should only be one failed network.
271 if (!new_failed_network) {
272 for (VirtualNetworkVector::const_iterator it =
273 cros->virtual_networks().begin();
274 it != cros->virtual_networks().end(); it++) {
275 const VirtualNetwork* net = *it;
276 if (net->notify_failure()) {
277 new_failed_network = net;
278 break; // There should only be one failed network.
283 // Show connection error notification if necessary.
284 if (new_failed_network) {
285 VLOG(1) << "Failed Network: " << new_failed_network->service_path();
286 notification_connection_error_->ShowAlways(
287 l10n_util::GetStringFUTF16(
288 IDS_NETWORK_CONNECTION_ERROR_MESSAGE_WITH_DETAILS,
289 UTF8ToUTF16(new_failed_network->name()),
290 UTF8ToUTF16(new_failed_network->GetErrorString())),
291 string16(), BalloonViewHost::MessageCallback(), false, false);
295 void NetworkMessageObserver::OnCellularDataPlanChanged(NetworkLibrary* cros) {
296 if (!ShouldShowMobilePlanNotifications())
297 return;
298 const CellularNetwork* cellular = cros->cellular_network();
299 if (!cellular || !cellular->SupportsDataPlan())
300 return;
302 const CellularDataPlanVector* plans =
303 cros->GetDataPlans(cellular->service_path());
304 // If no plans available, check to see if we need a new plan.
305 if (!plans || plans->empty()) {
306 // If previously, we had low data, we know that a plan was near expiring.
307 // In that case, because the plan disappeared, we assume that it expired.
308 if (cellular_data_left_ == CellularNetwork::DATA_LOW) {
309 ShowNoDataNotification(cellular, cellular_data_plan_type_);
310 } else if (cellular->needs_new_plan()) {
311 ShowNeedsPlanNotification(cellular);
313 SaveLastCellularInfo(cellular, NULL);
314 return;
317 CellularDataPlanVector::const_iterator iter = plans->begin();
318 const CellularDataPlan* current_plan = *iter;
320 // If current plan is not the last plan (there is another backup plan),
321 // then we do not show notifications for this plan.
322 // For example, if there is another data plan available when this runs out.
323 for (++iter; iter != plans->end(); ++iter) {
324 if (IsApplicableBackupPlan(current_plan, *iter)) {
325 SaveLastCellularInfo(cellular, current_plan);
326 return;
330 // If connected cellular network changed, or data plan is different, then
331 // it's a new network. Then hide all previous notifications.
332 bool new_plan = cellular->service_path() != cellular_service_path_ ||
333 current_plan->GetUniqueIdentifier() != cellular_data_plan_unique_id_;
335 if (new_plan) {
336 InitNewPlan(current_plan);
339 if (cellular->data_left() == CellularNetwork::DATA_NONE) {
340 ShowNoDataNotification(cellular, current_plan->plan_type);
341 } else if (cellular->data_left() == CellularNetwork::DATA_VERY_LOW) {
342 // Only show low data notification if we transition to very low data
343 // and we are on the same plan. This is so that users don't get a
344 // notification whenever they connect to a low data 3g network.
345 if (!new_plan && (cellular_data_left_ != CellularNetwork::DATA_VERY_LOW))
346 ShowLowDataNotification(current_plan);
349 SaveLastCellularInfo(cellular, current_plan);
352 void NetworkMessageObserver::OnConnectionInitiated(NetworkLibrary* cros,
353 const Network* network) {
354 // If user initiated any network connection, we hide the error notification.
355 notification_connection_error_->Hide();
358 void NetworkMessageObserver::SaveLastCellularInfo(
359 const CellularNetwork* cellular, const CellularDataPlan* plan) {
360 DCHECK(cellular);
361 cellular_service_path_ = cellular->service_path();
362 cellular_data_left_ = cellular->data_left();
363 if (plan) {
364 cellular_data_plan_unique_id_ = plan->GetUniqueIdentifier();
365 cellular_data_plan_type_ = plan->plan_type;
366 } else {
367 cellular_data_plan_unique_id_ = std::string();
368 cellular_data_plan_type_ = CELLULAR_DATA_PLAN_UNKNOWN;
372 } // namespace chromeos