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/status/data_promo_notification.h"
7 #include "ash/system/system_notifier.h"
8 #include "base/command_line.h"
9 #include "base/prefs/pref_registry_simple.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/chromeos/login/helper.h"
14 #include "chrome/browser/chromeos/mobile_config.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/profiles/profile_manager.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/browser_list.h"
19 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
20 #include "chrome/browser/ui/singleton_tabs.h"
21 #include "chrome/common/extensions/extension_constants.h"
22 #include "chrome/common/pref_names.h"
23 #include "chrome/grit/generated_resources.h"
24 #include "chromeos/chromeos_switches.h"
25 #include "chromeos/login/login_state.h"
26 #include "chromeos/network/device_state.h"
27 #include "chromeos/network/network_connection_handler.h"
28 #include "chromeos/network/network_event_log.h"
29 #include "chromeos/network/network_state.h"
30 #include "chromeos/network/network_state_handler.h"
31 #include "content/public/browser/user_metrics.h"
32 #include "extensions/browser/extension_registry.h"
33 #include "grit/ui_chromeos_resources.h"
34 #include "third_party/cros_system_api/dbus/service_constants.h"
35 #include "ui/base/l10n/l10n_util.h"
36 #include "ui/base/resource/resource_bundle.h"
37 #include "ui/chromeos/network/network_connect.h"
38 #include "ui/chromeos/network/network_state_notifier.h"
39 #include "ui/message_center/message_center.h"
40 #include "ui/message_center/notification.h"
41 #include "ui/views/view.h"
42 #include "ui/views/widget/widget.h"
48 const char kDataPromoNotificationId
[] = "chrome://settings/internet/data_promo";
49 const char kDataSaverNotificationId
[] = "chrome://settings/internet/data_saver";
50 const char kDataSaverExtensionUrl
[] =
51 "https://chrome.google.com/webstore/detail/"
52 "pfmgfdlgomnbgkofeojodiodmgpgmkac?utm_source=chromeos-datasaver-prompt";
54 const int kNotificationCountPrefDefault
= -1;
55 const int kTimesToShowDataSaverPrompt
= 2;
57 bool GetBooleanPref(const char* pref_name
) {
58 Profile
* profile
= ProfileManager::GetPrimaryUserProfile();
59 PrefService
* prefs
= profile
->GetPrefs();
60 return prefs
->GetBoolean(pref_name
);
63 int GetIntegerLocalPref(const char* pref_name
) {
64 PrefService
* prefs
= g_browser_process
->local_state();
65 return prefs
->GetInteger(pref_name
);
68 void SetBooleanPref(const char* pref_name
, bool value
) {
69 Profile
* profile
= ProfileManager::GetPrimaryUserProfile();
70 PrefService
* prefs
= profile
->GetPrefs();
71 prefs
->SetBoolean(pref_name
, value
);
74 void SetIntegerLocalPref(const char* pref_name
, int value
) {
75 PrefService
* prefs
= g_browser_process
->local_state();
76 prefs
->SetInteger(pref_name
, value
);
79 // Returns prefs::kShow3gPromoNotification or false if no active browser.
80 bool ShouldShow3gPromoNotification() {
81 return GetBooleanPref(prefs::kShow3gPromoNotification
);
84 void SetShow3gPromoNotification(bool value
) {
85 SetBooleanPref(prefs::kShow3gPromoNotification
, value
);
88 // Returns prefs::kCarrierDealPromoShown which is number of times
89 // carrier deal notification has been shown to users on this machine.
90 int GetCarrierDealPromoShown() {
91 return GetIntegerLocalPref(prefs::kCarrierDealPromoShown
);
94 void SetCarrierDealPromoShown(int value
) {
95 SetIntegerLocalPref(prefs::kCarrierDealPromoShown
, value
);
98 // Returns number of times the Data Saver prompt has been displayed.
99 int GetDataSaverPromptsShown() {
100 return ProfileManager::GetActiveUserProfile()->GetPrefs()->GetInteger(
101 prefs::kDataSaverPromptsShown
);
104 // Updates number of times the Data Saver prompt has been displayed.
105 void SetDataSaverPromptsShown(int times_shown
) {
106 ProfileManager::GetActiveUserProfile()->GetPrefs()->SetInteger(
107 prefs::kDataSaverPromptsShown
, times_shown
);
110 // kDisableDataSaverPrompt takes precedence over any kEnableDataSaverPrompt
111 // value. If neither flag is set, the Data Saver prompt is enabled by default.
112 bool DataSaverSwitchEnabled() {
113 return !base::CommandLine::ForCurrentProcess()->HasSwitch(
114 chromeos::switches::kDisableDataSaverPrompt
);
117 // Is command line switch set for Data Saver demo mode, where we show the prompt
118 // after any change in network properties?
119 bool DataSaverSwitchDemoMode() {
120 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
121 chromeos::switches::kDisableDataSaverPrompt
))
124 const std::string value
=
125 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
126 chromeos::switches::kEnableDataSaverPrompt
);
127 return value
== chromeos::switches::kDataSaverPromptDemoMode
;
130 const chromeos::MobileConfig::Carrier
* GetCarrier(
131 const NetworkState
* cellular
) {
132 const DeviceState
* device
= NetworkHandler::Get()->network_state_handler()->
133 GetDeviceState(cellular
->device_path());
134 std::string carrier_id
= device
? device
->home_provider_id() : "";
135 if (carrier_id
.empty()) {
136 NET_LOG_ERROR("Empty carrier ID for cellular network",
137 device
? device
->path(): "No device");
141 chromeos::MobileConfig
* config
= chromeos::MobileConfig::GetInstance();
142 if (!config
->IsReady())
145 return config
->GetCarrier(carrier_id
);
148 const chromeos::MobileConfig::CarrierDeal
* GetCarrierDeal(
149 const chromeos::MobileConfig::Carrier
* carrier
) {
150 const chromeos::MobileConfig::CarrierDeal
* deal
= carrier
->GetDefaultDeal();
152 // Check deal for validity.
153 int carrier_deal_promo_pref
= GetCarrierDealPromoShown();
154 if (carrier_deal_promo_pref
>= deal
->notification_count())
156 const std::string locale
= g_browser_process
->GetApplicationLocale();
157 std::string deal_text
= deal
->GetLocalizedString(locale
,
158 "notification_text");
159 NET_LOG_DEBUG("Carrier Deal Found", deal_text
);
160 if (deal_text
.empty())
166 void NotificationClicked(const std::string
& service_path
,
167 const std::string
& info_url
) {
168 if (!info_url
.empty()) {
169 chrome::ScopedTabbedBrowserDisplayer
displayer(
170 ProfileManager::GetPrimaryUserProfile(), chrome::HOST_DESKTOP_TYPE_ASH
);
171 chrome::ShowSingletonTab(displayer
.browser(), GURL(info_url
));
172 if (info_url
== kDataSaverExtensionUrl
)
173 content::RecordAction(base::UserMetricsAction("DataSaverPrompt_Clicked"));
175 ui::NetworkConnect::Get()->ShowNetworkSettingsForPath(service_path
);
181 ////////////////////////////////////////////////////////////////////////////////
182 // DataPromoNotification
184 DataPromoNotification::DataPromoNotification()
185 : notifications_shown_(false),
186 weak_ptr_factory_(this) {
187 NetworkHandler::Get()->network_state_handler()->AddObserver(this, FROM_HERE
);
190 DataPromoNotification::~DataPromoNotification() {
191 if (NetworkHandler::IsInitialized()) {
192 NetworkHandler::Get()->network_state_handler()->RemoveObserver(
197 void DataPromoNotification::RegisterPrefs(PrefRegistrySimple
* registry
) {
198 // Carrier deal notification shown count defaults to 0.
199 registry
->RegisterIntegerPref(prefs::kCarrierDealPromoShown
, 0);
202 void DataPromoNotification::NetworkPropertiesUpdated(
203 const NetworkState
* network
) {
205 (network
->type() != shill::kTypeCellular
&& !DataSaverSwitchDemoMode()))
207 ShowOptionalMobileDataPromoNotification();
210 void DataPromoNotification::DefaultNetworkChanged(const NetworkState
* network
) {
211 // Call NetworkPropertiesUpdated in case the Cellular network became the
213 NetworkPropertiesUpdated(network
);
216 void DataPromoNotification::ShowOptionalMobileDataPromoNotification() {
217 // Do not show notifications to unauthenticated users, or when requesting a
218 // network connection, or if there's no default_network.
219 if (!LoginState::Get()->IsUserAuthenticated())
221 const NetworkState
* default_network
=
222 NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
223 if (!default_network
)
225 if (NetworkHandler::Get()->network_connection_handler()->
226 HasPendingConnectRequest())
229 if (!DataSaverSwitchDemoMode() &&
230 (notifications_shown_
|| default_network
->type() != shill::kTypeCellular
))
233 notifications_shown_
= true;
234 bool data_saver_prompt_shown
= ShowDataSaverNotification();
236 // Display a one-time notification on first use of Mobile Data connection, or
237 // if there is a carrier deal defined show that even if user has already seen
238 // generic promo. Show deal regardless of |data_saver_prompt_shown|.
239 int carrier_deal_promo_pref
= kNotificationCountPrefDefault
;
240 const MobileConfig::CarrierDeal
* deal
= NULL
;
241 const MobileConfig::Carrier
* carrier
= GetCarrier(default_network
);
243 deal
= GetCarrierDeal(carrier
);
245 base::string16 message
=
246 l10n_util::GetStringUTF16(IDS_3G_NOTIFICATION_MESSAGE
);
247 std::string info_url
;
249 carrier_deal_promo_pref
= GetCarrierDealPromoShown();
250 const std::string locale
= g_browser_process
->GetApplicationLocale();
251 std::string deal_text
=
252 deal
->GetLocalizedString(locale
, "notification_text");
253 message
= base::UTF8ToUTF16(deal_text
+ "\n\n") + message
;
254 info_url
= deal
->info_url();
255 if (info_url
.empty() && carrier
)
256 info_url
= carrier
->top_up_url();
257 } else if (data_saver_prompt_shown
|| !ShouldShow3gPromoNotification()) {
262 if (default_network
->network_technology() == shill::kNetworkTechnologyLte
)
263 icon_id
= IDR_AURA_UBER_TRAY_NOTIFICATION_LTE
;
265 icon_id
= IDR_AURA_UBER_TRAY_NOTIFICATION_3G
;
266 const gfx::Image
& icon
=
267 ui::ResourceBundle::GetSharedInstance().GetImageNamed(icon_id
);
269 message_center::MessageCenter::Get()->AddNotification(
270 message_center::Notification::CreateSystemNotification(
271 kDataPromoNotificationId
, base::string16() /* title */, message
, icon
,
272 ui::NetworkStateNotifier::kNotifierNetwork
,
273 base::Bind(&NotificationClicked
, default_network
->path(), info_url
)));
275 SetShow3gPromoNotification(false);
276 if (carrier_deal_promo_pref
!= kNotificationCountPrefDefault
)
277 SetCarrierDealPromoShown(carrier_deal_promo_pref
+ 1);
280 bool DataPromoNotification::ShowDataSaverNotification() {
281 if (!DataSaverSwitchEnabled())
284 if (message_center::MessageCenter::Get()->FindVisibleNotificationById(
285 kDataSaverNotificationId
)) // already showing.
288 int times_shown
= GetDataSaverPromptsShown();
289 if (!DataSaverSwitchDemoMode() && times_shown
>= kTimesToShowDataSaverPrompt
)
292 if (extensions::ExtensionRegistry::Get(ProfileManager::GetActiveUserProfile())
293 ->GetExtensionById(extension_misc::kDataSaverExtensionId
,
294 extensions::ExtensionRegistry::EVERYTHING
)) {
295 // If extension is installed, disable future prompts.
296 SetDataSaverPromptsShown(kTimesToShowDataSaverPrompt
);
300 base::string16 title
= l10n_util::GetStringUTF16(IDS_3G_DATASAVER_TITLE
);
301 base::string16 message
= l10n_util::GetStringUTF16(IDS_3G_DATASAVER_MESSAGE
);
302 const gfx::Image
& icon
=
303 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
304 IDR_AURA_UBER_TRAY_NOTIFICATION_DATASAVER
);
306 message_center::MessageCenter::Get()->AddNotification(
307 message_center::Notification::CreateSystemNotification(
308 kDataSaverNotificationId
, title
, message
, icon
,
309 ui::NetworkStateNotifier::kNotifierNetwork
,
310 base::Bind(&NotificationClicked
, "", kDataSaverExtensionUrl
)));
311 content::RecordAction(base::UserMetricsAction("DataSaverPrompt_Shown"));
313 if (DataSaverSwitchDemoMode()) {
314 SetDataSaverPromptsShown(0); // demo mode resets times shown counts.
315 SetShow3gPromoNotification(true);
317 SetDataSaverPromptsShown(times_shown
+ 1);
323 } // namespace chromeos