Home | History | Annotate | Download | only in notifications
      1 // Copyright 2013 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/notifications/welcome_notification.h"
      6 
      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/notifications/notification.h"
     13 #include "chrome/browser/prefs/pref_service_syncable.h"
     14 #include "chrome/browser/profiles/profile.h"
     15 #include "chrome/browser/ui/browser_navigator.h"
     16 #include "chrome/common/pref_names.h"
     17 #include "chrome/common/url_constants.h"
     18 #include "components/user_prefs/pref_registry_syncable.h"
     19 #include "grit/generated_resources.h"
     20 #include "grit/theme_resources.h"
     21 #include "ui/base/l10n/l10n_util.h"
     22 #include "ui/base/resource/resource_bundle.h"
     23 #include "ui/message_center/message_center.h"
     24 #include "ui/message_center/notification.h"
     25 #include "ui/message_center/notification_delegate.h"
     26 #include "ui/message_center/notification_types.h"
     27 
     28 const char kChromeNowExtensionID[] = "pafkbggdmjlpgkdkcbjmhmfcdpncadgh";
     29 
     30 class WelcomeNotificationDelegate
     31     : public message_center::NotificationDelegate {
     32  public:
     33   WelcomeNotificationDelegate(const std::string& id, Profile* profile)
     34       : profile_(profile) {}
     35 
     36   // Overridden from NotificationDelegate:
     37   virtual void Display() OVERRIDE {}
     38   virtual void Error() OVERRIDE {}
     39 
     40   virtual void Close(bool by_user) OVERRIDE {
     41     if (by_user) {
     42       // Setting the preference here may cause the notification erasing
     43       // to reenter. Posting a task avoids this issue.
     44       base::MessageLoop::current()->PostTask(
     45           FROM_HERE,
     46           base::Bind(&WelcomeNotificationDelegate::MarkAsDismissed, this));
     47     }
     48   }
     49 
     50   virtual void Click() OVERRIDE {}
     51   virtual void ButtonClick(int index) OVERRIDE {
     52     DCHECK(index == 0);
     53     OpenNotificationLearnMoreTab();
     54   }
     55 
     56  private:
     57   void MarkAsDismissed() {
     58     profile_->GetPrefs()->
     59         SetBoolean(prefs::kWelcomeNotificationDismissed, true);
     60   }
     61 
     62   void OpenNotificationLearnMoreTab() {
     63     chrome::NavigateParams params(
     64         profile_,
     65         GURL(chrome::kNotificationWelcomeLearnMoreURL),
     66         content::PAGE_TRANSITION_LINK);
     67     params.disposition = NEW_FOREGROUND_TAB;
     68     params.window_action = chrome::NavigateParams::SHOW_WINDOW;
     69     chrome::Navigate(&params);
     70   }
     71 
     72   virtual ~WelcomeNotificationDelegate() {}
     73 
     74   Profile* const profile_;
     75 
     76   DISALLOW_COPY_AND_ASSIGN(WelcomeNotificationDelegate);
     77 };
     78 
     79 WelcomeNotification::WelcomeNotification(
     80     Profile* profile,
     81     message_center::MessageCenter* message_center)
     82     : profile_(profile),
     83       message_center_(message_center) {
     84   welcome_notification_dismissed_pref_.Init(
     85     prefs::kWelcomeNotificationDismissed,
     86     profile_->GetPrefs(),
     87     base::Bind(
     88         &WelcomeNotification::OnWelcomeNotificationDismissedChanged,
     89         base::Unretained(this)));
     90 }
     91 
     92 WelcomeNotification::~WelcomeNotification() {
     93   if (delayed_notification_) {
     94     delayed_notification_.reset();
     95     PrefServiceSyncable::FromProfile(profile_)->RemoveObserver(this);
     96   }
     97 }
     98 
     99 void WelcomeNotification::OnIsSyncingChanged() {
    100   DCHECK(delayed_notification_);
    101   PrefServiceSyncable* pref_service_syncable =
    102       PrefServiceSyncable::FromProfile(profile_);
    103   if (pref_service_syncable->IsSyncing()) {
    104     pref_service_syncable->RemoveObserver(this);
    105     scoped_ptr<Notification> previous_notification(
    106         delayed_notification_.release());
    107     ShowWelcomeNotificationIfNecessary(*(previous_notification.get()));
    108   }
    109 }
    110 
    111 void WelcomeNotification::ShowWelcomeNotificationIfNecessary(
    112     const Notification& notification) {
    113   message_center::NotifierId notifier_id = notification.notifier_id();
    114   if ((notifier_id.id == kChromeNowExtensionID) && !delayed_notification_) {
    115     PrefServiceSyncable* pref_service_syncable =
    116         PrefServiceSyncable::FromProfile(profile_);
    117     if (pref_service_syncable->IsSyncing()) {
    118       PrefService* pref_service = profile_->GetPrefs();
    119       if (!pref_service->GetBoolean(prefs::kWelcomeNotificationDismissed)) {
    120         PopUpRequest pop_up_request =
    121             pref_service->GetBoolean(
    122                 prefs::kWelcomeNotificationPreviouslyPoppedUp)
    123             ? POP_UP_HIDDEN
    124             : POP_UP_SHOWN;
    125         if (pop_up_request == POP_UP_SHOWN) {
    126           pref_service->SetBoolean(
    127               prefs::kWelcomeNotificationPreviouslyPoppedUp, true);
    128         }
    129 
    130         ShowWelcomeNotification(notifier_id,
    131                                 notification.display_source(),
    132                                 pop_up_request);
    133       }
    134     } else {
    135       delayed_notification_.reset(new Notification(notification));
    136       pref_service_syncable->AddObserver(this);
    137     }
    138   }
    139 }
    140 
    141 // Static
    142 void WelcomeNotification::RegisterProfilePrefs(
    143     user_prefs::PrefRegistrySyncable* prefs) {
    144   prefs->RegisterBooleanPref(
    145       prefs::kWelcomeNotificationDismissed,
    146       false,
    147       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
    148   prefs->RegisterBooleanPref(
    149       prefs::kWelcomeNotificationPreviouslyPoppedUp,
    150       false,
    151       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
    152 }
    153 
    154 void WelcomeNotification::ShowWelcomeNotification(
    155     const message_center::NotifierId notifier_id,
    156     const base::string16& display_source,
    157     PopUpRequest pop_up_request) {
    158   message_center::ButtonInfo learn_more(
    159       l10n_util::GetStringUTF16(IDS_NOTIFICATION_WELCOME_BUTTON_LEARN_MORE));
    160   learn_more.icon = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
    161       IDR_NOTIFICATION_WELCOME_LEARN_MORE);
    162 
    163   message_center::RichNotificationData rich_notification_data;
    164   rich_notification_data.priority = 2;
    165   rich_notification_data.buttons.push_back(learn_more);
    166 
    167   if (welcome_notification_id_.empty())
    168     welcome_notification_id_ = base::GenerateGUID();
    169 
    170   if (!welcome_notification_id_.empty()) {
    171     scoped_ptr<message_center::Notification> message_center_notification(
    172         new message_center::Notification(
    173             message_center::NOTIFICATION_TYPE_BASE_FORMAT,
    174             welcome_notification_id_,
    175             l10n_util::GetStringUTF16(IDS_NOTIFICATION_WELCOME_TITLE),
    176             l10n_util::GetStringUTF16(IDS_NOTIFICATION_WELCOME_BODY),
    177             ui::ResourceBundle::GetSharedInstance().GetImageNamed(
    178                 IDR_NOTIFICATION_WELCOME_ICON),
    179             display_source,
    180             notifier_id,
    181             rich_notification_data,
    182             new WelcomeNotificationDelegate(
    183                 welcome_notification_id_, profile_)));
    184 
    185     if (pop_up_request == POP_UP_HIDDEN)
    186       message_center_notification->set_shown_as_popup(true);
    187 
    188     message_center_->AddNotification(message_center_notification.Pass());
    189   }
    190 }
    191 
    192 void WelcomeNotification::HideWelcomeNotification() {
    193   if (!welcome_notification_id_.empty() &&
    194       message_center_->HasNotification(welcome_notification_id_)) {
    195     message_center_->RemoveNotification(welcome_notification_id_, false);
    196   }
    197 }
    198 
    199 void WelcomeNotification::OnWelcomeNotificationDismissedChanged() {
    200   const bool welcome_notification_dismissed =
    201       profile_->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed);
    202   if (welcome_notification_dismissed)
    203     HideWelcomeNotification();
    204 }
    205