172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chromeos/network_message_observer.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/callback.h"
8513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/stl_util-inl.h"
9731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/string_number_conversions.h"
103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chromeos/cros/cros_library.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chromeos/cros/network_library.h"
13731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/chromeos/notifications/balloon_view_host.h"
14201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "chrome/browser/prefs/pref_service.h"
1521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h"
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_list.h"
18201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "chrome/common/pref_names.h"
19201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "chrome/common/time_format.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h"
2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
24201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochnamespace {
25201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
26201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// Returns prefs::kShowPlanNotifications in the profile of the last active
27201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// browser. If there is no active browser, returns true.
28201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool ShouldShowMobilePlanNotifications() {
29201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  Browser* browser = BrowserList::GetLastActive();
30201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!browser || !browser->profile())
31201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return true;
32201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
33201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  PrefService* prefs = browser->profile()->GetPrefs();
34201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return prefs->GetBoolean(prefs::kShowPlanNotifications);
35201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
36201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
37201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}  // namespace
38201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace chromeos {
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochNetworkMessageObserver::NetworkMessageObserver(Profile* profile)
4272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    : notification_connection_error_(profile, "network_connection.chromeos",
43731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          IDR_NOTIFICATION_NETWORK_FAILED,
44731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          l10n_util::GetStringUTF16(IDS_NETWORK_CONNECTION_ERROR_TITLE)),
45731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      notification_low_data_(profile, "network_low_data.chromeos",
46731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          IDR_NOTIFICATION_BARS_CRITICAL,
47731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          l10n_util::GetStringUTF16(IDS_NETWORK_LOW_DATA_TITLE)),
48731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      notification_no_data_(profile, "network_no_data.chromeos",
49731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          IDR_NOTIFICATION_BARS_EMPTY,
50731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          l10n_util::GetStringUTF16(IDS_NETWORK_OUT_OF_DATA_TITLE)) {
51513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  NetworkLibrary* netlib = CrosLibrary::Get()->GetNetworkLibrary();
52513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  OnNetworkManagerChanged(netlib);
53dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Note that this gets added as a NetworkManagerObserver,
54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // CellularDataPlanObserver, and UserActionObserver in browser_init.cc
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochNetworkMessageObserver::~NetworkMessageObserver() {
58513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  NetworkLibrary* netlib = CrosLibrary::Get()->GetNetworkLibrary();
59513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  netlib->RemoveNetworkManagerObserver(this);
60513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  netlib->RemoveCellularDataPlanObserver(this);
61dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  netlib->RemoveUserActionObserver(this);
62731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  notification_connection_error_.Hide();
63731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  notification_low_data_.Hide();
64731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  notification_no_data_.Hide();
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static
6872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool NetworkMessageObserver::IsApplicableBackupPlan(
6972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const CellularDataPlan* plan, const CellularDataPlan* other_plan) {
7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // By applicable plan, we mean that the other plan has data AND the timeframe
7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // will apply: (unlimited OR used bytes < max bytes) AND
7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  //   ((start time - 1 sec) <= end time of currently active plan).
7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // In other words, there is data available and there is no gap of more than a
7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // second in time between the old plan and the new plan.
7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  bool has_data = other_plan->plan_type == CELLULAR_DATA_PLAN_UNLIMITED ||
7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      other_plan->remaining_data() > 0;
7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  bool will_apply =
7872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      (other_plan->plan_start_time - plan->plan_end_time).InSeconds() <= 1;
7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return has_data && will_apply;
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
824a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid NetworkMessageObserver::OpenMobileSetupPage(const ListValue* args) {
834a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  Browser* browser = BrowserList::GetLastActive();
844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (browser)
854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    browser->OpenMobilePlanTabAndActivate();
864a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
884a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid NetworkMessageObserver::OpenMoreInfoPage(const ListValue* args) {
894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  Browser* browser = BrowserList::GetLastActive();
904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (!browser)
914a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return;
924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  chromeos::NetworkLibrary* lib =
934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      chromeos::CrosLibrary::Get()->GetNetworkLibrary();
9421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  const chromeos::CellularNetwork* cellular = lib->cellular_network();
954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (!cellular)
964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return;
97dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  browser->ShowSingletonTab(GURL(cellular->payment_url()));
98731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
99731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid NetworkMessageObserver::InitNewPlan(const CellularDataPlan* plan) {
10172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  notification_low_data_.Hide();
10272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  notification_no_data_.Hide();
10372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (plan->plan_type == CELLULAR_DATA_PLAN_UNLIMITED) {
10472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    notification_no_data_.set_title(
10572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        l10n_util::GetStringFUTF16(IDS_NETWORK_DATA_EXPIRED_TITLE,
10672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                   ASCIIToUTF16(plan->plan_name)));
10772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    notification_low_data_.set_title(
10872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        l10n_util::GetStringFUTF16(IDS_NETWORK_NEARING_EXPIRATION_TITLE,
10972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                   ASCIIToUTF16(plan->plan_name)));
11072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else {
11172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    notification_no_data_.set_title(
11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        l10n_util::GetStringFUTF16(IDS_NETWORK_OUT_OF_DATA_TITLE,
11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                   ASCIIToUTF16(plan->plan_name)));
11472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    notification_low_data_.set_title(
11572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        l10n_util::GetStringFUTF16(IDS_NETWORK_LOW_DATA_TITLE,
11672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                   ASCIIToUTF16(plan->plan_name)));
11772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
11872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
11972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid NetworkMessageObserver::ShowNeedsPlanNotification(
121dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const CellularNetwork* cellular) {
122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  notification_no_data_.set_title(
123dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      l10n_util::GetStringFUTF16(IDS_NETWORK_NO_DATA_PLAN_TITLE,
124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                 UTF8ToUTF16(cellular->name())));
125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  notification_no_data_.Show(
126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      l10n_util::GetStringFUTF16(
127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          IDS_NETWORK_NO_DATA_PLAN_MESSAGE,
128dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          UTF8ToUTF16(cellular->name())),
129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      l10n_util::GetStringUTF16(IDS_NETWORK_PURCHASE_MORE_MESSAGE),
130dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      NewCallback(this, &NetworkMessageObserver::OpenMobileSetupPage),
131dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      false, false);
132dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
13472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid NetworkMessageObserver::ShowNoDataNotification(
135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CellularDataPlanType plan_type) {
136dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  notification_low_data_.Hide();  // Hide previous low data notification.
137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  string16 message = plan_type == CELLULAR_DATA_PLAN_UNLIMITED ?
138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      TimeFormat::TimeRemaining(base::TimeDelta()) :
139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      l10n_util::GetStringFUTF16(IDS_NETWORK_DATA_REMAINING_MESSAGE,
140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                 ASCIIToUTF16("0"));
14172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  notification_no_data_.Show(message,
14272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      l10n_util::GetStringUTF16(IDS_NETWORK_PURCHASE_MORE_MESSAGE),
14372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      NewCallback(this, &NetworkMessageObserver::OpenMobileSetupPage),
14472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      false, false);
14572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
14672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
14772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid NetworkMessageObserver::ShowLowDataNotification(
14872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const CellularDataPlan* plan) {
149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  string16 message;
150dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (plan->plan_type == CELLULAR_DATA_PLAN_UNLIMITED) {
151dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    message = plan->GetPlanExpiration();
152dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else {
153dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int64 remaining_mbytes = plan->remaining_data() / (1024 * 1024);
154dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    message = l10n_util::GetStringFUTF16(IDS_NETWORK_DATA_REMAINING_MESSAGE,
155dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        UTF8ToUTF16(base::Int64ToString(remaining_mbytes)));
156dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
15772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  notification_low_data_.Show(message,
15872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      l10n_util::GetStringUTF16(IDS_NETWORK_MORE_INFO_MESSAGE),
15972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      NewCallback(this, &NetworkMessageObserver::OpenMoreInfoPage),
16072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      false, false);
16172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
16272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool NetworkMessageObserver::CheckNetworkFailed(const Network* network) {
164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (network->failed()) {
165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    NetworkStateMap::iterator iter =
166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        network_states_.find(network->service_path());
167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // If the network did not previously exist, then don't do anything.
168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // For example, if the user travels to a location and finds a service
169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // that has previously failed, we don't want to show a notification.
170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (iter == network_states_.end())
171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // If network connection failed, display a notification.
173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // We only do this if we were trying to make a new connection.
174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // So if a previously connected network got disconnected for any reason,
175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // we don't display notification.
176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ConnectionState prev_state = iter->second;
177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (Network::IsConnectingState(prev_state))
178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return true;
179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return false;
181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid NetworkMessageObserver::OnNetworkManagerChanged(NetworkLibrary* cros) {
184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const Network* new_failed_network = NULL;
185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Check to see if we have any newly failed networks.
186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (WifiNetworkVector::const_iterator it = cros->wifi_networks().begin();
187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       it != cros->wifi_networks().end(); it++) {
188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const WifiNetwork* net = *it;
189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (CheckNetworkFailed(net)) {
190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      new_failed_network = net;
191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;  // There should only be one failed network.
1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
1933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!new_failed_network) {
196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    for (CellularNetworkVector::const_iterator it =
197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen             cros->cellular_networks().begin();
198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen         it != cros->cellular_networks().end(); it++) {
199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const CellularNetwork* net = *it;
200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (CheckNetworkFailed(net)) {
201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        new_failed_network = net;
202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        break;  // There should only be one failed network.
203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
206513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!new_failed_network) {
208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    for (VirtualNetworkVector::const_iterator it =
209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen             cros->virtual_networks().begin();
210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen         it != cros->virtual_networks().end(); it++) {
211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const VirtualNetwork* net = *it;
212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (CheckNetworkFailed(net)) {
213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        new_failed_network = net;
214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        break;  // There should only be one failed network.
215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
2173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  network_states_.clear();
220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (WifiNetworkVector::const_iterator it = cros->wifi_networks().begin();
221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       it != cros->wifi_networks().end(); it++)
222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    network_states_[(*it)->service_path()] = (*it)->state();
223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (CellularNetworkVector::const_iterator it =
224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen           cros->cellular_networks().begin();
225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       it != cros->cellular_networks().end(); it++)
226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    network_states_[(*it)->service_path()] = (*it)->state();
227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (VirtualNetworkVector::const_iterator it =
228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen           cros->virtual_networks().begin();
229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       it != cros->virtual_networks().end(); it++)
230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    network_states_[(*it)->service_path()] = (*it)->state();
231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
232731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Show connection error notification if necessary.
233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (new_failed_network) {
2343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Hide if already shown to force show it in case user has closed it.
235731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (notification_connection_error_.visible())
236731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      notification_connection_error_.Hide();
237731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    notification_connection_error_.Show(l10n_util::GetStringFUTF16(
2383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        IDS_NETWORK_CONNECTION_ERROR_MESSAGE,
239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        UTF8ToUTF16(new_failed_network->name())), false, false);
2403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
243dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid NetworkMessageObserver::OnCellularDataPlanChanged(NetworkLibrary* cros) {
244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!ShouldShowMobilePlanNotifications())
245513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return;
246dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const CellularNetwork* cellular = cros->cellular_network();
247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!cellular || !cellular->SupportsDataPlan())
248201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return;
249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
250dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const CellularDataPlanVector* plans =
251dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      cros->GetDataPlans(cellular->service_path());
25272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // If no plans available, check to see if we need a new plan.
253dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!plans || plans->empty()) {
254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // If previously, we had low data, we know that a plan was near expiring.
255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // In that case, because the plan disappeared, we assume that it expired.
256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (cellular_data_left_ == CellularNetwork::DATA_LOW) {
257dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      ShowNoDataNotification(cellular_data_plan_type_);
258dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    } else if (cellular->needs_new_plan()) {
259dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      ShowNeedsPlanNotification(cellular);
26072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    SaveLastCellularInfo(cellular, NULL);
26272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return;
26372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
26472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
265dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  CellularDataPlanVector::const_iterator iter = plans->begin();
26672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const CellularDataPlan* current_plan = *iter;
26772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
26872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // If current plan is not the last plan (there is another backup plan),
26972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // then we do not show notifications for this plan.
27072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // For example, if there is another data plan available when this runs out.
271dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  for (++iter; iter != plans->end(); ++iter) {
27272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (IsApplicableBackupPlan(current_plan, *iter)) {
273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      SaveLastCellularInfo(cellular, current_plan);
2744a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      return;
275731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
276731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
277731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
27872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // If connected cellular network changed, or data plan is different, then
27972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // it's a new network. Then hide all previous notifications.
28072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  bool new_plan = cellular->service_path() != cellular_service_path_ ||
28172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      current_plan->GetUniqueIdentifier() != cellular_data_plan_unique_id_;
28272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
28372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (new_plan) {
28472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    InitNewPlan(current_plan);
28572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
286731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
287dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (cellular->data_left() == CellularNetwork::DATA_NONE) {
288dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ShowNoDataNotification(current_plan->plan_type);
289dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else if (cellular->data_left() == CellularNetwork::DATA_VERY_LOW) {
290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Only show low data notification if we transition to very low data
291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // and we are on the same plan. This is so that users don't get a
292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // notification whenever they connect to a low data 3g network.
293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!new_plan && (cellular_data_left_ != CellularNetwork::DATA_VERY_LOW))
294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ShowLowDataNotification(current_plan);
2954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
29672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SaveLastCellularInfo(cellular, current_plan);
298dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
299dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid NetworkMessageObserver::OnConnectionInitiated(NetworkLibrary* cros,
301dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                   const Network* network) {
302dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // If user initiated any network connection, we hide the error notification.
303dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  notification_connection_error_.Hide();
304731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
305731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid NetworkMessageObserver::SaveLastCellularInfo(
307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const CellularNetwork* cellular, const CellularDataPlan* plan) {
308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(cellular);
309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  cellular_service_path_ = cellular->service_path();
310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  cellular_data_left_ = cellular->data_left();
311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (plan) {
312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    cellular_data_plan_unique_id_ = plan->GetUniqueIdentifier();
313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    cellular_data_plan_type_ = plan->plan_type;
314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    cellular_data_plan_unique_id_ = std::string();
316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    cellular_data_plan_type_ = CELLULAR_DATA_PLAN_UNKNOWN;
317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace chromeos
321