Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / notifications / extension_welcome_notification.cc
blob335ebb8fc3c53e6363c39d1ba8a762836ec6ff7a
1 // Copyright 2014 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/notifications/extension_welcome_notification.h"
7 #include "base/guid.h"
8 #include "base/lazy_instance.h"
9 #include "base/message_loop/message_loop.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/notifications/notification.h"
14 #include "chrome/browser/prefs/pref_service_syncable.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/ui/browser_navigator.h"
17 #include "chrome/common/pref_names.h"
18 #include "chrome/common/url_constants.h"
19 #include "chrome/grit/generated_resources.h"
20 #include "components/pref_registry/pref_registry_syncable.h"
21 #include "grit/theme_resources.h"
22 #include "ui/base/l10n/l10n_util.h"
23 #include "ui/base/resource/resource_bundle.h"
24 #include "ui/message_center/message_center.h"
25 #include "ui/message_center/notification.h"
26 #include "ui/message_center/notification_delegate.h"
27 #include "ui/message_center/notification_types.h"
29 const int ExtensionWelcomeNotification::kRequestedShowTimeDays = 14;
30 const char ExtensionWelcomeNotification::kChromeNowExtensionID[] =
31 "pafkbggdmjlpgkdkcbjmhmfcdpncadgh";
33 namespace {
35 class NotificationCallbacks
36 : public message_center::NotificationDelegate {
37 public:
38 NotificationCallbacks(
39 Profile* profile,
40 const message_center::NotifierId notifier_id,
41 const std::string& welcome_notification_id,
42 ExtensionWelcomeNotification::Delegate* delegate)
43 : profile_(profile),
44 notifier_id_(notifier_id.type, notifier_id.id),
45 welcome_notification_id_(welcome_notification_id),
46 delegate_(delegate) {
49 // Overridden from NotificationDelegate:
50 void Close(bool by_user) override {
51 if (by_user) {
52 // Setting the preference here may cause the notification erasing
53 // to reenter. Posting a task avoids this issue.
54 delegate_->PostTask(
55 FROM_HERE,
56 base::Bind(&NotificationCallbacks::MarkAsDismissed, this));
60 void ButtonClick(int index) override {
61 if (index == 0) {
62 OpenNotificationLearnMoreTab();
63 } else if (index == 1) {
64 DisableNotificationProvider();
65 Close(true);
66 } else {
67 NOTREACHED();
71 private:
72 void MarkAsDismissed() {
73 profile_->GetPrefs()->SetBoolean(prefs::kWelcomeNotificationDismissedLocal,
74 true);
77 void OpenNotificationLearnMoreTab() {
78 chrome::NavigateParams params(
79 profile_,
80 GURL(chrome::kNotificationWelcomeLearnMoreURL),
81 ui::PAGE_TRANSITION_LINK);
82 params.disposition = NEW_FOREGROUND_TAB;
83 params.window_action = chrome::NavigateParams::SHOW_WINDOW;
84 chrome::Navigate(&params);
87 void DisableNotificationProvider() {
88 message_center::Notifier notifier(notifier_id_, base::string16(), true);
89 message_center::MessageCenter* message_center =
90 delegate_->GetMessageCenter();
91 message_center->DisableNotificationsByNotifier(notifier_id_);
92 message_center->RemoveNotification(welcome_notification_id_, false);
93 message_center->GetNotifierSettingsProvider()->SetNotifierEnabled(
94 notifier, false);
97 ~NotificationCallbacks() override {}
99 Profile* const profile_;
101 const message_center::NotifierId notifier_id_;
103 std::string welcome_notification_id_;
105 // Weak ref owned by ExtensionWelcomeNotification.
106 ExtensionWelcomeNotification::Delegate* const delegate_;
108 DISALLOW_COPY_AND_ASSIGN(NotificationCallbacks);
111 class DefaultDelegate : public ExtensionWelcomeNotification::Delegate {
112 public:
113 DefaultDelegate() {}
115 message_center::MessageCenter* GetMessageCenter() override {
116 return g_browser_process->message_center();
119 base::Time GetCurrentTime() override { return base::Time::Now(); }
121 void PostTask(const tracked_objects::Location& from_here,
122 const base::Closure& task) override {
123 base::MessageLoop::current()->PostTask(from_here, task);
126 private:
127 DISALLOW_COPY_AND_ASSIGN(DefaultDelegate);
130 } // namespace
132 ExtensionWelcomeNotification::ExtensionWelcomeNotification(
133 Profile* const profile,
134 ExtensionWelcomeNotification::Delegate* const delegate)
135 : notifier_id_(message_center::NotifierId::APPLICATION,
136 kChromeNowExtensionID),
137 profile_(profile),
138 delegate_(delegate) {
139 welcome_notification_dismissed_pref_.Init(
140 prefs::kWelcomeNotificationDismissed,
141 profile_->GetPrefs(),
142 base::Bind(
143 &ExtensionWelcomeNotification::OnWelcomeNotificationDismissedChanged,
144 base::Unretained(this)));
145 welcome_notification_dismissed_local_pref_.Init(
146 prefs::kWelcomeNotificationDismissedLocal,
147 profile_->GetPrefs());
150 // static
151 ExtensionWelcomeNotification* ExtensionWelcomeNotification::Create(
152 Profile* const profile) {
153 return Create(profile, new DefaultDelegate());
156 // static
157 ExtensionWelcomeNotification* ExtensionWelcomeNotification::Create(
158 Profile* const profile, Delegate* const delegate) {
159 return new ExtensionWelcomeNotification(profile, delegate);
162 ExtensionWelcomeNotification::~ExtensionWelcomeNotification() {
163 if (delayed_notification_) {
164 delayed_notification_.reset();
165 PrefServiceSyncable::FromProfile(profile_)->RemoveObserver(this);
166 } else {
167 HideWelcomeNotification();
171 void ExtensionWelcomeNotification::OnIsSyncingChanged() {
172 DCHECK(delayed_notification_);
173 PrefServiceSyncable* const pref_service_syncable =
174 PrefServiceSyncable::FromProfile(profile_);
175 if (pref_service_syncable->IsSyncing()) {
176 pref_service_syncable->RemoveObserver(this);
177 scoped_ptr<Notification> previous_notification(
178 delayed_notification_.release());
179 ShowWelcomeNotificationIfNecessary(*(previous_notification.get()));
183 void ExtensionWelcomeNotification::ShowWelcomeNotificationIfNecessary(
184 const Notification& notification) {
185 if ((notification.notifier_id() == notifier_id_) && !delayed_notification_) {
186 PrefServiceSyncable* const pref_service_syncable =
187 PrefServiceSyncable::FromProfile(profile_);
188 if (pref_service_syncable->IsSyncing()) {
189 PrefService* const pref_service = profile_->GetPrefs();
190 if (!UserHasDismissedWelcomeNotification()) {
191 const PopUpRequest pop_up_request =
192 pref_service->GetBoolean(
193 prefs::kWelcomeNotificationPreviouslyPoppedUp)
194 ? POP_UP_HIDDEN
195 : POP_UP_SHOWN;
196 if (pop_up_request == POP_UP_SHOWN) {
197 pref_service->SetBoolean(
198 prefs::kWelcomeNotificationPreviouslyPoppedUp, true);
201 if (IsWelcomeNotificationExpired()) {
202 ExpireWelcomeNotification();
203 } else {
204 ShowWelcomeNotification(
205 notification.display_source(), pop_up_request);
208 } else {
209 delayed_notification_.reset(new Notification(notification));
210 pref_service_syncable->AddObserver(this);
215 // static
216 void ExtensionWelcomeNotification::RegisterProfilePrefs(
217 user_prefs::PrefRegistrySyncable* prefs) {
218 prefs->RegisterBooleanPref(prefs::kWelcomeNotificationDismissed,
219 false,
220 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
221 prefs->RegisterBooleanPref(prefs::kWelcomeNotificationDismissedLocal,
222 false,
223 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
224 prefs->RegisterBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp,
225 false,
226 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
227 prefs->RegisterInt64Pref(prefs::kWelcomeNotificationExpirationTimestamp,
229 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
232 message_center::MessageCenter*
233 ExtensionWelcomeNotification::GetMessageCenter() const {
234 return delegate_->GetMessageCenter();
237 void ExtensionWelcomeNotification::ShowWelcomeNotification(
238 const base::string16& display_source,
239 const PopUpRequest pop_up_request) {
240 message_center::ButtonInfo learn_more(
241 l10n_util::GetStringUTF16(IDS_NOTIFICATION_WELCOME_BUTTON_LEARN_MORE));
242 learn_more.icon = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
243 IDR_NOTIFICATION_WELCOME_LEARN_MORE);
244 message_center::ButtonInfo disable(
245 l10n_util::GetStringUTF16(IDS_NOTIFIER_WELCOME_BUTTON));
246 disable.icon = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
247 IDR_NOTIFIER_BLOCK_BUTTON);
249 message_center::RichNotificationData rich_notification_data;
250 rich_notification_data.priority = 2;
251 rich_notification_data.buttons.push_back(learn_more);
252 rich_notification_data.buttons.push_back(disable);
254 if (welcome_notification_id_.empty())
255 welcome_notification_id_ = base::GenerateGUID();
257 if (!welcome_notification_id_.empty()) {
258 scoped_ptr<message_center::Notification> message_center_notification(
259 new message_center::Notification(
260 message_center::NOTIFICATION_TYPE_BASE_FORMAT,
261 welcome_notification_id_,
262 l10n_util::GetStringUTF16(IDS_NOTIFICATION_WELCOME_TITLE),
263 l10n_util::GetStringUTF16(IDS_NOTIFICATION_WELCOME_BODY),
264 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
265 IDR_NOTIFICATION_WELCOME_ICON),
266 display_source,
267 notifier_id_,
268 rich_notification_data,
269 new NotificationCallbacks(
270 profile_, notifier_id_, welcome_notification_id_,
271 delegate_.get())));
273 if (pop_up_request == POP_UP_HIDDEN)
274 message_center_notification->set_shown_as_popup(true);
276 GetMessageCenter()->AddNotification(message_center_notification.Pass());
277 StartExpirationTimer();
281 void ExtensionWelcomeNotification::HideWelcomeNotification() {
282 if (!welcome_notification_id_.empty() &&
283 GetMessageCenter()->FindVisibleNotificationById(
284 welcome_notification_id_) != NULL) {
285 GetMessageCenter()->RemoveNotification(welcome_notification_id_, false);
286 StopExpirationTimer();
290 bool ExtensionWelcomeNotification::UserHasDismissedWelcomeNotification() const {
291 // This was previously a syncable preference; now it's per-machine.
292 // Only the local pref will be written moving forward, but check for both so
293 // users won't be double-toasted.
294 bool shown_synced = profile_->GetPrefs()->GetBoolean(
295 prefs::kWelcomeNotificationDismissed);
296 bool shown_local = profile_->GetPrefs()->GetBoolean(
297 prefs::kWelcomeNotificationDismissedLocal);
298 return (shown_synced || shown_local);
301 void ExtensionWelcomeNotification::OnWelcomeNotificationDismissedChanged() {
302 if (UserHasDismissedWelcomeNotification()) {
303 HideWelcomeNotification();
307 void ExtensionWelcomeNotification::StartExpirationTimer() {
308 if (!expiration_timer_ && !IsWelcomeNotificationExpired()) {
309 base::Time expiration_timestamp = GetExpirationTimestamp();
310 if (expiration_timestamp.is_null()) {
311 SetExpirationTimestampFromNow();
312 expiration_timestamp = GetExpirationTimestamp();
313 DCHECK(!expiration_timestamp.is_null());
315 expiration_timer_.reset(
316 new base::OneShotTimer<ExtensionWelcomeNotification>());
317 expiration_timer_->Start(
318 FROM_HERE,
319 expiration_timestamp - delegate_->GetCurrentTime(),
320 this,
321 &ExtensionWelcomeNotification::ExpireWelcomeNotification);
325 void ExtensionWelcomeNotification::StopExpirationTimer() {
326 if (expiration_timer_) {
327 expiration_timer_->Stop();
328 expiration_timer_.reset();
332 void ExtensionWelcomeNotification::ExpireWelcomeNotification() {
333 DCHECK(IsWelcomeNotificationExpired());
334 profile_->GetPrefs()->SetBoolean(
335 prefs::kWelcomeNotificationDismissedLocal, true);
336 HideWelcomeNotification();
339 base::Time ExtensionWelcomeNotification::GetExpirationTimestamp() const {
340 PrefService* const pref_service = profile_->GetPrefs();
341 const int64 expiration_timestamp =
342 pref_service->GetInt64(prefs::kWelcomeNotificationExpirationTimestamp);
343 return (expiration_timestamp == 0)
344 ? base::Time()
345 : base::Time::FromInternalValue(expiration_timestamp);
348 void ExtensionWelcomeNotification::SetExpirationTimestampFromNow() {
349 PrefService* const pref_service = profile_->GetPrefs();
350 pref_service->SetInt64(
351 prefs::kWelcomeNotificationExpirationTimestamp,
352 (delegate_->GetCurrentTime() +
353 base::TimeDelta::FromDays(kRequestedShowTimeDays)).ToInternalValue());
356 bool ExtensionWelcomeNotification::IsWelcomeNotificationExpired() const {
357 const base::Time expiration_timestamp = GetExpirationTimestamp();
358 return !expiration_timestamp.is_null() &&
359 (expiration_timestamp <= delegate_->GetCurrentTime());