data_promo_notification.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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 "chrome/browser/chromeos/status/data_promo_notification.h"
6
7#include "ash/shell.h"
8#include "ash/shell_window_ids.h"
9#include "ash/system/chromeos/network/network_observer.h"
10#include "ash/system/tray/system_tray.h"
11#include "base/utf_string_conversions.h"
12#include "chrome/browser/browser_process.h"
13#include "chrome/browser/chromeos/cros/cros_library.h"
14#include "chrome/browser/chromeos/cros/network_library.h"
15#include "chrome/browser/chromeos/login/helper.h"
16#include "chrome/browser/chromeos/login/user_manager.h"
17#include "chrome/browser/chromeos/mobile_config.h"
18#include "chrome/browser/prefs/pref_service.h"
19#include "chrome/browser/profiles/profile.h"
20#include "chrome/browser/profiles/profile_manager.h"
21#include "chrome/browser/ui/browser.h"
22#include "chrome/browser/ui/browser_list.h"
23#include "chrome/common/pref_names.h"
24#include "grit/generated_resources.h"
25#include "grit/theme_resources.h"
26#include "ui/base/l10n/l10n_util.h"
27#include "ui/base/resource/resource_bundle.h"
28#include "ui/views/view.h"
29#include "ui/views/widget/widget.h"
30
31namespace {
32
33// Time in milliseconds to delay showing of promo
34// notification when Chrome window is not on screen.
35const int kPromoShowDelayMs = 10000;
36
37const int kNotificationCountPrefDefault = -1;
38
39bool GetBooleanPref(const char* pref_name) {
40  Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord();
41  PrefService* prefs = profile->GetPrefs();
42  return prefs->GetBoolean(pref_name);
43}
44
45int GetIntegerLocalPref(const char* pref_name) {
46  PrefService* prefs = g_browser_process->local_state();
47  return prefs->GetInteger(pref_name);
48}
49
50void SetBooleanPref(const char* pref_name, bool value) {
51  Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord();
52  PrefService* prefs = profile->GetPrefs();
53  prefs->SetBoolean(pref_name, value);
54}
55
56void SetIntegerLocalPref(const char* pref_name, int value) {
57  PrefService* prefs = g_browser_process->local_state();
58  prefs->SetInteger(pref_name, value);
59}
60
61// Returns prefs::kShow3gPromoNotification or false
62// if there's no active browser.
63bool ShouldShow3gPromoNotification() {
64  return GetBooleanPref(prefs::kShow3gPromoNotification);
65}
66
67void SetShow3gPromoNotification(bool value) {
68  SetBooleanPref(prefs::kShow3gPromoNotification, value);
69}
70
71// Returns prefs::kCarrierDealPromoShown which is number of times
72// carrier deal notification has been shown to users on this machine.
73int GetCarrierDealPromoShown() {
74  return GetIntegerLocalPref(prefs::kCarrierDealPromoShown);
75}
76
77void SetCarrierDealPromoShown(int value) {
78  SetIntegerLocalPref(prefs::kCarrierDealPromoShown, value);
79}
80
81const chromeos::MobileConfig::Carrier* GetCarrier(
82    chromeos::NetworkLibrary* cros) {
83  std::string carrier_id = cros->GetCellularHomeCarrierId();
84  if (carrier_id.empty()) {
85    LOG(ERROR) << "Empty carrier ID with a cellular connected.";
86    return NULL;
87  }
88
89  chromeos::MobileConfig* config = chromeos::MobileConfig::GetInstance();
90  if (!config->IsReady())
91    return NULL;
92
93  return config->GetCarrier(carrier_id);
94}
95
96const chromeos::MobileConfig::CarrierDeal* GetCarrierDeal(
97    const chromeos::MobileConfig::Carrier* carrier) {
98  const chromeos::MobileConfig::CarrierDeal* deal = carrier->GetDefaultDeal();
99  if (deal) {
100    // Check deal for validity.
101    int carrier_deal_promo_pref = GetCarrierDealPromoShown();
102    if (carrier_deal_promo_pref >= deal->notification_count())
103      return NULL;
104    const std::string locale = g_browser_process->GetApplicationLocale();
105    std::string deal_text = deal->GetLocalizedString(locale,
106                                                     "notification_text");
107    if (deal_text.empty())
108      return NULL;
109  }
110  return deal;
111}
112
113}  // namespace
114
115namespace chromeos {
116
117////////////////////////////////////////////////////////////////////////////////
118// DataPromoNotification
119
120DataPromoNotification::DataPromoNotification()
121    : check_for_promo_(true),
122      ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
123}
124
125DataPromoNotification::~DataPromoNotification() {
126  CloseNotification();
127}
128
129void DataPromoNotification::RegisterPrefs(PrefService* local_state) {
130  // Carrier deal notification shown count defaults to 0.
131  local_state->RegisterIntegerPref(prefs::kCarrierDealPromoShown, 0);
132}
133
134void DataPromoNotification::ShowOptionalMobileDataPromoNotification(
135    NetworkLibrary* cros,
136    views::View* host,
137    ash::NetworkTrayDelegate* listener) {
138  // Display one-time notification for non-Guest users on first use
139  // of Mobile Data connection or if there's a carrier deal defined
140  // show that even if user has already seen generic promo.
141  if (UserManager::Get()->IsUserLoggedIn() &&
142      !UserManager::Get()->IsLoggedInAsGuest() &&
143      check_for_promo_ &&
144      cros->cellular_connected() && !cros->ethernet_connected() &&
145      !cros->wifi_connected() && !cros->wimax_connected()) {
146    std::string deal_text;
147    int carrier_deal_promo_pref = kNotificationCountPrefDefault;
148    const MobileConfig::CarrierDeal* deal = NULL;
149    const MobileConfig::Carrier* carrier = GetCarrier(cros);
150    if (carrier)
151      deal = GetCarrierDeal(carrier);
152    deal_info_url_.clear();
153    deal_topup_url_.clear();
154    if (deal) {
155      carrier_deal_promo_pref = GetCarrierDealPromoShown();
156      const std::string locale = g_browser_process->GetApplicationLocale();
157      deal_text = deal->GetLocalizedString(locale, "notification_text");
158      deal_info_url_ = deal->info_url();
159      deal_topup_url_ = carrier->top_up_url();
160    } else if (!ShouldShow3gPromoNotification()) {
161      check_for_promo_ = false;
162      return;
163    }
164
165    gfx::Rect button_bounds = host->GetBoundsInScreen();
166    // StatusArea button Y position is usually -1, fix it so that
167    // Contains() method for screen bounds works correctly.
168    button_bounds.set_y(button_bounds.y() + 1);
169    gfx::Rect screen_bounds(chromeos::CalculateScreenBounds(gfx::Size()));
170
171    // Chrome window is initialized in visible state off screen and then is
172    // moved into visible screen area. Make sure that we're on screen
173    // so that bubble is shown correctly.
174    if (!screen_bounds.Contains(button_bounds)) {
175      // If we're not on screen yet, delay notification display.
176      // It may be shown earlier, on next NetworkLibrary callback processing.
177      if (!weak_ptr_factory_.HasWeakPtrs()) {
178        MessageLoop::current()->PostDelayedTask(FROM_HERE,
179            base::Bind(
180                &DataPromoNotification::ShowOptionalMobileDataPromoNotification,
181                weak_ptr_factory_.GetWeakPtr(),
182                cros,
183                host,
184                listener),
185            base::TimeDelta::FromMilliseconds(kPromoShowDelayMs));
186      }
187      return;
188    }
189
190    string16 message = l10n_util::GetStringUTF16(IDS_3G_NOTIFICATION_MESSAGE);
191    if (!deal_text.empty())
192      message = UTF8ToUTF16(deal_text + "\n\n") + message;
193
194    // Use deal URL if it's defined or general "Network Settings" URL.
195    int link_message_id;
196    if (deal_topup_url_.empty())
197      link_message_id = IDS_OFFLINE_NETWORK_SETTINGS;
198    else
199      link_message_id = IDS_STATUSBAR_NETWORK_VIEW_ACCOUNT;
200
201    std::vector<string16> links;
202    links.push_back(l10n_util::GetStringUTF16(link_message_id));
203    if (!deal_info_url_.empty())
204      links.push_back(l10n_util::GetStringUTF16(IDS_LEARN_MORE));
205    if (ash::Shell::GetInstance()->system_tray()->network_observer()) {
206      ash::Shell::GetInstance()->system_tray()->network_observer()->
207          SetNetworkMessage(listener, ash::NetworkObserver::MESSAGE_DATA_PROMO,
208              string16(), message, links);
209    }
210
211    check_for_promo_ = false;
212    SetShow3gPromoNotification(false);
213    if (carrier_deal_promo_pref != kNotificationCountPrefDefault)
214      SetCarrierDealPromoShown(carrier_deal_promo_pref + 1);
215  }
216}
217
218void DataPromoNotification::CloseNotification() {
219  if (ash::Shell::GetInstance()->status_area_widget() &&
220      ash::Shell::GetInstance()->system_tray()->network_observer()) {
221    ash::Shell::GetInstance()->system_tray()->network_observer()->
222        ClearNetworkMessage(ash::NetworkObserver::MESSAGE_DATA_PROMO);
223  }
224}
225
226}  // namespace chromeos
227