• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
MockMessageCenter()27   MockMessageCenter()
28     : add_notification_calls_(0),
29       remove_notification_calls_(0),
30       notifications_with_shown_as_popup_(0) {};
31 
add_notification_calls()32   int add_notification_calls() { return add_notification_calls_; }
remove_notification_calls()33   int remove_notification_calls() { return remove_notification_calls_; }
notifications_with_shown_as_popup()34   int notifications_with_shown_as_popup() {
35     return notifications_with_shown_as_popup_;
36   }
37 
38   // message_center::FakeMessageCenter Overrides
HasNotification(const std::string & id)39   virtual bool HasNotification(const std::string& id) OVERRIDE {
40     return last_notification.get() &&
41         (last_notification->id() == id);
42   }
43 
AddNotification(scoped_ptr<message_center::Notification> notification)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 
RemoveNotification(const std::string & id,bool by_user)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 
CloseCurrentNotification()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 {
ProcessSyncChanges(const tracked_objects::Location & from_here,const syncer::SyncChangeList & change_list)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 
GetAllSyncData(syncer::ModelType type) const80   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:
WelcomeNotificationTest()88   WelcomeNotificationTest() {
89     scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry(
90         new user_prefs::PrefRegistrySyncable());
91     WelcomeNotification::RegisterProfilePrefs(pref_registry.get());
92   }
93 
SetUp()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 
TearDown()102   virtual void TearDown() {
103     welcome_notification_.reset();
104     message_center_.reset();
105     profile_.reset();
106     message_loop_.reset();
107   }
108 
StartPreferenceSyncing()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 
ShowChromeNowNotification()119   void ShowChromeNowNotification() {
120     ShowNotification(
121         "ChromeNowNotification",
122         message_center::NotifierId(
123             message_center::NotifierId::APPLICATION,
124             kChromeNowExtensionID));
125   }
126 
ShowRegularNotification()127   void ShowRegularNotification() {
128     ShowNotification(
129         "RegularNotification",
130         message_center::NotifierId(
131             message_center::NotifierId::APPLICATION,
132             "aaaabbbbccccddddeeeeffffggghhhhi"));
133   }
134 
FlushMessageLoop()135   void FlushMessageLoop() {
136     message_loop_->RunUntilIdle();
137   }
138 
profile()139   TestingProfile* profile() { return profile_.get(); }
message_center()140   MockMessageCenter* message_center() { return message_center_.get(); }
141 
142  private:
143   class TestNotificationDelegate : public NotificationDelegate {
144    public:
TestNotificationDelegate(const std::string & id)145     explicit TestNotificationDelegate(const std::string& id)
146         : id_(id) {}
147 
148     // Overridden from NotificationDelegate:
Display()149     virtual void Display() OVERRIDE {}
Error()150     virtual void Error() OVERRIDE {}
Close(bool by_user)151     virtual void Close(bool by_user) OVERRIDE {}
Click()152     virtual void Click() OVERRIDE {}
ButtonClick(int index)153     virtual void ButtonClick(int index) OVERRIDE {}
154 
id() const155     virtual std::string id() const OVERRIDE { return id_; }
156 
GetRenderViewHost() const157     virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE {
158       return NULL;
159     }
160 
161    private:
~TestNotificationDelegate()162     virtual ~TestNotificationDelegate() {}
163 
164     const std::string id_;
165 
166     DISALLOW_COPY_AND_ASSIGN(TestNotificationDelegate);
167   };
168 
ShowNotification(std::string notification_id,const message_center::NotifierId & notifier_id)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.
TEST_F(WelcomeNotificationTest,FirstRunShowRegularNotification)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.
TEST_F(WelcomeNotificationTest,FirstRunChromeNowNotification)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.
TEST_F(WelcomeNotificationTest,ShowWelcomeNotificationAgain)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
TEST_F(WelcomeNotificationTest,WelcomeNotificationPreviouslyDismissed)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.
TEST_F(WelcomeNotificationTest,DismissWelcomeNotification)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.
TEST_F(WelcomeNotificationTest,SyncedDismissalWelcomeNotification)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.
TEST_F(WelcomeNotificationTest,DelayedPreferenceSyncPreviouslyDismissed)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.
TEST_F(WelcomeNotificationTest,DelayedPreferenceSyncNeverShown)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