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 <string>
      8 
      9 #include "base/memory/scoped_ptr.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "base/prefs/pref_service.h"
     12 #include "base/strings/utf_string_conversions.h"
     13 #include "chrome/browser/notifications/notification.h"
     14 #include "chrome/common/pref_names.h"
     15 #include "chrome/test/base/testing_pref_service_syncable.h"
     16 #include "chrome/test/base/testing_profile.h"
     17 #include "components/user_prefs/pref_registry_syncable.h"
     18 #include "sync/api/sync_error_factory_mock.h"
     19 #include "testing/gtest/include/gtest/gtest.h"
     20 #include "ui/message_center/fake_message_center.h"
     21 #include "ui/message_center/notification.h"
     22 
     23 const char kChromeNowExtensionID[] = "pafkbggdmjlpgkdkcbjmhmfcdpncadgh";
     24 
     25 class MockMessageCenter : public message_center::FakeMessageCenter {
     26  public:
     27   MockMessageCenter()
     28     : add_notification_calls_(0),
     29       remove_notification_calls_(0),
     30       notifications_with_shown_as_popup_(0) {};
     31 
     32   int add_notification_calls() { return add_notification_calls_; }
     33   int remove_notification_calls() { return remove_notification_calls_; }
     34   int notifications_with_shown_as_popup() {
     35     return notifications_with_shown_as_popup_;
     36   }
     37 
     38   // message_center::FakeMessageCenter Overrides
     39   virtual bool HasNotification(const std::string& id) OVERRIDE {
     40     return last_notification.get() &&
     41         (last_notification->id() == id);
     42   }
     43 
     44   virtual void AddNotification(
     45       scoped_ptr<message_center::Notification> notification) OVERRIDE {
     46     EXPECT_FALSE(last_notification.get());
     47     last_notification.swap(notification);
     48     add_notification_calls_++;
     49     if (last_notification->shown_as_popup())
     50       notifications_with_shown_as_popup_++;
     51   }
     52 
     53   virtual void RemoveNotification(const std::string& id, bool by_user)
     54       OVERRIDE {
     55     EXPECT_TRUE(last_notification.get());
     56     last_notification.reset();
     57     remove_notification_calls_++;
     58   }
     59 
     60   void CloseCurrentNotification() {
     61     EXPECT_TRUE(last_notification.get());
     62     last_notification->delegate()->Close(true);
     63     RemoveNotification(last_notification->id(), true);
     64   }
     65 
     66  private:
     67   scoped_ptr<message_center::Notification> last_notification;
     68   int add_notification_calls_;
     69   int remove_notification_calls_;
     70   int notifications_with_shown_as_popup_;
     71 };
     72 
     73 class TestSyncProcessor : public syncer::SyncChangeProcessor {
     74   virtual syncer::SyncError ProcessSyncChanges(
     75       const tracked_objects::Location& from_here,
     76       const syncer::SyncChangeList& change_list) OVERRIDE {
     77     return syncer::SyncError();
     78   }
     79 
     80   virtual syncer::SyncDataList GetAllSyncData(
     81       syncer::ModelType type) const OVERRIDE {
     82     return syncer::SyncDataList();
     83   }
     84 };
     85 
     86 class WelcomeNotificationTest : public testing::Test {
     87  protected:
     88   WelcomeNotificationTest() {
     89     scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry(
     90         new user_prefs::PrefRegistrySyncable());
     91     WelcomeNotification::RegisterProfilePrefs(pref_registry.get());
     92   }
     93 
     94   virtual void SetUp() {
     95     message_loop_.reset(new base::MessageLoop());
     96     profile_.reset(new TestingProfile());
     97     message_center_.reset(new MockMessageCenter());
     98     welcome_notification_.reset(
     99         new WelcomeNotification(profile_.get(), message_center_.get()));
    100   }
    101 
    102   virtual void TearDown() {
    103     welcome_notification_.reset();
    104     message_center_.reset();
    105     profile_.reset();
    106     message_loop_.reset();
    107   }
    108 
    109   void StartPreferenceSyncing() {
    110     PrefServiceSyncable::FromProfile(profile())->GetSyncableService(
    111         syncer::PREFERENCES)->MergeDataAndStartSyncing(
    112             syncer::PREFERENCES,
    113             syncer::SyncDataList(),
    114             scoped_ptr<syncer::SyncChangeProcessor>(new TestSyncProcessor),
    115             scoped_ptr<syncer::SyncErrorFactory>(
    116                 new syncer::SyncErrorFactoryMock()));
    117   }
    118 
    119   void ShowChromeNowNotification() {
    120     ShowNotification(
    121         "ChromeNowNotification",
    122         message_center::NotifierId(
    123             message_center::NotifierId::APPLICATION,
    124             kChromeNowExtensionID));
    125   }
    126 
    127   void ShowRegularNotification() {
    128     ShowNotification(
    129         "RegularNotification",
    130         message_center::NotifierId(
    131             message_center::NotifierId::APPLICATION,
    132             "aaaabbbbccccddddeeeeffffggghhhhi"));
    133   }
    134 
    135   void FlushMessageLoop() {
    136     message_loop_->RunUntilIdle();
    137   }
    138 
    139   TestingProfile* profile() { return profile_.get(); }
    140   MockMessageCenter* message_center() { return message_center_.get(); }
    141 
    142  private:
    143   class TestNotificationDelegate : public NotificationDelegate {
    144    public:
    145     explicit TestNotificationDelegate(const std::string& id)
    146         : id_(id) {}
    147 
    148     // Overridden from NotificationDelegate:
    149     virtual void Display() OVERRIDE {}
    150     virtual void Error() OVERRIDE {}
    151     virtual void Close(bool by_user) OVERRIDE {}
    152     virtual void Click() OVERRIDE {}
    153     virtual void ButtonClick(int index) OVERRIDE {}
    154 
    155     virtual std::string id() const OVERRIDE { return id_; }
    156 
    157     virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE {
    158       return NULL;
    159     }
    160 
    161    private:
    162     virtual ~TestNotificationDelegate() {}
    163 
    164     const std::string id_;
    165 
    166     DISALLOW_COPY_AND_ASSIGN(TestNotificationDelegate);
    167   };
    168 
    169   void ShowNotification(
    170       std::string notification_id,
    171       const message_center::NotifierId& notifier_id) {
    172     message_center::RichNotificationData rich_notification_data;
    173     rich_notification_data.priority = 0;
    174     Notification notification(
    175         message_center::NOTIFICATION_TYPE_BASE_FORMAT,
    176         GURL("http://tests.url"),
    177         base::UTF8ToUTF16("Title"),
    178         base::UTF8ToUTF16("Body"),
    179         gfx::Image(),
    180         blink::WebTextDirectionDefault,
    181         notifier_id,
    182         base::UTF8ToUTF16("Source"),
    183         base::UTF8ToUTF16(notification_id),
    184         rich_notification_data,
    185         new TestNotificationDelegate("TestNotification"));
    186     welcome_notification_->ShowWelcomeNotificationIfNecessary(notification);
    187   }
    188 
    189   scoped_ptr<TestingProfile> profile_;
    190   scoped_ptr<MockMessageCenter> message_center_;
    191   scoped_ptr<WelcomeNotification> welcome_notification_;
    192   scoped_ptr<base::MessageLoop> message_loop_;
    193 };
    194 
    195 // Show a regular notification. Expect that WelcomeNotification will
    196 // not show a welcome notification.
    197 TEST_F(WelcomeNotificationTest, FirstRunShowRegularNotification) {
    198   StartPreferenceSyncing();
    199   EXPECT_FALSE(
    200       profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
    201   EXPECT_FALSE(
    202       profile()->GetPrefs()->GetBoolean(
    203           prefs::kWelcomeNotificationPreviouslyPoppedUp));
    204 
    205   ShowRegularNotification();
    206 
    207   EXPECT_TRUE(message_center()->add_notification_calls() == 0);
    208   EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
    209   EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
    210   EXPECT_FALSE(
    211       profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
    212   EXPECT_FALSE(
    213       profile()->GetPrefs()->GetBoolean(
    214           prefs::kWelcomeNotificationPreviouslyPoppedUp));
    215 }
    216 
    217 // Show a Chrome Now notification. Expect that WelcomeNotification will
    218 // show a welcome notification.
    219 TEST_F(WelcomeNotificationTest, FirstRunChromeNowNotification) {
    220   StartPreferenceSyncing();
    221   EXPECT_FALSE(
    222       profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
    223   EXPECT_FALSE(
    224       profile()->GetPrefs()->GetBoolean(
    225           prefs::kWelcomeNotificationPreviouslyPoppedUp));
    226 
    227   ShowChromeNowNotification();
    228 
    229   EXPECT_TRUE(message_center()->add_notification_calls() == 1);
    230   EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
    231   EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
    232   EXPECT_FALSE(
    233       profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
    234   EXPECT_TRUE(
    235       profile()->GetPrefs()->GetBoolean(
    236           prefs::kWelcomeNotificationPreviouslyPoppedUp));
    237 }
    238 
    239 // Show a Chrome Now notification that was already shown before.
    240 TEST_F(WelcomeNotificationTest, ShowWelcomeNotificationAgain) {
    241   StartPreferenceSyncing();
    242   profile()->GetPrefs()->SetBoolean(
    243       prefs::kWelcomeNotificationPreviouslyPoppedUp, true);
    244   EXPECT_FALSE(
    245       profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
    246   EXPECT_TRUE(
    247       profile()->GetPrefs()->GetBoolean(
    248           prefs::kWelcomeNotificationPreviouslyPoppedUp));
    249 
    250   ShowChromeNowNotification();
    251 
    252   EXPECT_TRUE(message_center()->add_notification_calls() == 1);
    253   EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
    254   EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 1);
    255   EXPECT_FALSE(
    256       profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
    257   EXPECT_TRUE(
    258       profile()->GetPrefs()->GetBoolean(
    259           prefs::kWelcomeNotificationPreviouslyPoppedUp));
    260 }
    261 
    262 // Don't show a welcome notification if it was previously dismissed
    263 TEST_F(WelcomeNotificationTest, WelcomeNotificationPreviouslyDismissed) {
    264   StartPreferenceSyncing();
    265   profile()->GetPrefs()->SetBoolean(prefs::kWelcomeNotificationDismissed, true);
    266   EXPECT_TRUE(
    267       profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
    268   EXPECT_FALSE(
    269       profile()->GetPrefs()->GetBoolean(
    270           prefs::kWelcomeNotificationPreviouslyPoppedUp));
    271 
    272   ShowChromeNowNotification();
    273 
    274   EXPECT_TRUE(message_center()->add_notification_calls() == 0);
    275   EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
    276   EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
    277   EXPECT_TRUE(
    278       profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
    279   EXPECT_FALSE(
    280       profile()->GetPrefs()->GetBoolean(
    281           prefs::kWelcomeNotificationPreviouslyPoppedUp));
    282 }
    283 
    284 // Show a Chrome Now notification and dismiss it.
    285 // Expect welcome toast dismissed to be true.
    286 TEST_F(WelcomeNotificationTest, DismissWelcomeNotification) {
    287   StartPreferenceSyncing();
    288   EXPECT_FALSE(
    289       profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
    290   EXPECT_FALSE(
    291       profile()->GetPrefs()->GetBoolean(
    292           prefs::kWelcomeNotificationPreviouslyPoppedUp));
    293 
    294   ShowChromeNowNotification();
    295   message_center()->CloseCurrentNotification();
    296   FlushMessageLoop();
    297 
    298   EXPECT_TRUE(message_center()->add_notification_calls() == 1);
    299   EXPECT_TRUE(message_center()->remove_notification_calls() == 1);
    300   EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
    301   EXPECT_TRUE(
    302       profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
    303   EXPECT_TRUE(
    304       profile()->GetPrefs()->GetBoolean(
    305           prefs::kWelcomeNotificationPreviouslyPoppedUp));
    306 }
    307 
    308 // Show a Chrome Now notification and dismiss it via a synced preference change.
    309 // Expect welcome toast dismissed to be true.
    310 TEST_F(WelcomeNotificationTest, SyncedDismissalWelcomeNotification) {
    311   StartPreferenceSyncing();
    312   EXPECT_FALSE(
    313       profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
    314   EXPECT_FALSE(
    315       profile()->GetPrefs()->GetBoolean(
    316           prefs::kWelcomeNotificationPreviouslyPoppedUp));
    317 
    318   ShowChromeNowNotification();
    319   profile()->GetPrefs()->SetBoolean(prefs::kWelcomeNotificationDismissed, true);
    320 
    321   EXPECT_TRUE(message_center()->add_notification_calls() == 1);
    322   EXPECT_TRUE(message_center()->remove_notification_calls() == 1);
    323   EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
    324   EXPECT_TRUE(
    325       profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
    326   EXPECT_TRUE(
    327       profile()->GetPrefs()->GetBoolean(
    328           prefs::kWelcomeNotificationPreviouslyPoppedUp));
    329 }
    330 
    331 // Simulate a delayed preference sync when the welcome notification was
    332 // previously dismissed.
    333 TEST_F(WelcomeNotificationTest, DelayedPreferenceSyncPreviouslyDismissed) {
    334   // Show a notification while the preference system is not syncing.
    335   EXPECT_FALSE(
    336       profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
    337   EXPECT_FALSE(
    338       profile()->GetPrefs()->GetBoolean(
    339           prefs::kWelcomeNotificationPreviouslyPoppedUp));
    340 
    341   ShowChromeNowNotification();
    342 
    343   EXPECT_TRUE(message_center()->add_notification_calls() == 0);
    344   EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
    345   EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
    346   EXPECT_FALSE(
    347       profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
    348   EXPECT_FALSE(
    349       profile()->GetPrefs()->GetBoolean(
    350           prefs::kWelcomeNotificationPreviouslyPoppedUp));
    351 
    352   // Now start the preference syncing with a previously dismissed welcome.
    353   profile()->GetPrefs()->SetBoolean(prefs::kWelcomeNotificationDismissed, true);
    354   EXPECT_TRUE(
    355       profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
    356   EXPECT_FALSE(
    357       profile()->GetPrefs()->GetBoolean(
    358           prefs::kWelcomeNotificationPreviouslyPoppedUp));
    359 
    360   StartPreferenceSyncing();
    361 
    362   EXPECT_TRUE(message_center()->add_notification_calls() == 0);
    363   EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
    364   EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
    365   EXPECT_TRUE(
    366       profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
    367   EXPECT_FALSE(
    368       profile()->GetPrefs()->GetBoolean(
    369           prefs::kWelcomeNotificationPreviouslyPoppedUp));
    370 }
    371 
    372 // Simulate a delayed preference sync when the welcome notification was
    373 // never shown.
    374 TEST_F(WelcomeNotificationTest, DelayedPreferenceSyncNeverShown) {
    375   // Show a notification while the preference system is not syncing.
    376   EXPECT_FALSE(
    377       profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
    378   EXPECT_FALSE(
    379       profile()->GetPrefs()->GetBoolean(
    380           prefs::kWelcomeNotificationPreviouslyPoppedUp));
    381 
    382   ShowChromeNowNotification();
    383 
    384   EXPECT_TRUE(message_center()->add_notification_calls() == 0);
    385   EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
    386   EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
    387   EXPECT_FALSE(
    388       profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
    389   EXPECT_FALSE(
    390       profile()->GetPrefs()->GetBoolean(
    391           prefs::kWelcomeNotificationPreviouslyPoppedUp));
    392 
    393   // Now start the preference syncing with the default preference values.
    394   EXPECT_FALSE(
    395       profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
    396   EXPECT_FALSE(
    397       profile()->GetPrefs()->GetBoolean(
    398           prefs::kWelcomeNotificationPreviouslyPoppedUp));
    399 
    400   StartPreferenceSyncing();
    401 
    402   EXPECT_TRUE(message_center()->add_notification_calls() == 1);
    403   EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
    404   EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
    405   EXPECT_FALSE(
    406       profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
    407   EXPECT_TRUE(
    408       profile()->GetPrefs()->GetBoolean(
    409           prefs::kWelcomeNotificationPreviouslyPoppedUp));
    410 }
    411