5f7788bb4ae434f1f91a9c8f3eab933a5d0e8bcc
[platform/framework/web/crosswalk.git] / src / chrome / browser / notifications / extension_welcome_notification_unittest.cc
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.
4
5 #include "chrome/browser/notifications/extension_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 "base/test/test_simple_task_runner.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "chrome/browser/notifications/notification.h"
16 #include "chrome/common/pref_names.h"
17 #include "chrome/test/base/testing_pref_service_syncable.h"
18 #include "chrome/test/base/testing_profile.h"
19 #include "components/user_prefs/pref_registry_syncable.h"
20 #include "sync/api/fake_sync_change_processor.h"
21 #include "sync/api/sync_error_factory_mock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "ui/message_center/fake_message_center.h"
24 #include "ui/message_center/notification.h"
25
26 const char kChromeNowExtensionID[] = "pafkbggdmjlpgkdkcbjmhmfcdpncadgh";
27
28 class MockMessageCenter : public message_center::FakeMessageCenter {
29  public:
30   MockMessageCenter()
31       : add_notification_calls_(0),
32         remove_notification_calls_(0),
33         notifications_with_shown_as_popup_(0) {
34   }
35
36   int add_notification_calls() { return add_notification_calls_; }
37   int remove_notification_calls() { return remove_notification_calls_; }
38   int notifications_with_shown_as_popup() {
39     return notifications_with_shown_as_popup_;
40   }
41
42   // message_center::FakeMessageCenter Overrides
43   virtual bool HasNotification(const std::string& id) OVERRIDE {
44     return last_notification.get() && (last_notification->id() == id);
45   }
46
47   virtual void AddNotification(
48       scoped_ptr<message_center::Notification> notification) OVERRIDE {
49     EXPECT_FALSE(last_notification.get());
50     last_notification.swap(notification);
51     add_notification_calls_++;
52     if (last_notification->shown_as_popup())
53       notifications_with_shown_as_popup_++;
54   }
55
56   virtual void RemoveNotification(const std::string& id,
57                                   bool by_user) OVERRIDE {
58     EXPECT_TRUE(last_notification.get());
59     last_notification.reset();
60     remove_notification_calls_++;
61   }
62
63   void CloseCurrentNotification() {
64     EXPECT_TRUE(last_notification.get());
65     last_notification->delegate()->Close(true);
66     RemoveNotification(last_notification->id(), true);
67   }
68
69  private:
70   scoped_ptr<message_center::Notification> last_notification;
71   int add_notification_calls_;
72   int remove_notification_calls_;
73   int notifications_with_shown_as_popup_;
74
75   DISALLOW_COPY_AND_ASSIGN(MockMessageCenter);
76 };
77
78 class WelcomeNotificationDelegate
79     : public ExtensionWelcomeNotification::Delegate {
80 public:
81   WelcomeNotificationDelegate()
82       : start_time_(base::Time::Now()),
83         message_center_(new MockMessageCenter()) {
84   }
85
86   // ExtensionWelcomeNotification::Delegate
87   virtual message_center::MessageCenter* GetMessageCenter() OVERRIDE {
88     return message_center_.get();
89   }
90
91   virtual base::Time GetCurrentTime() OVERRIDE {
92     return start_time_ + elapsed_time_;
93   }
94
95   virtual void PostTask(
96       const tracked_objects::Location& from_here,
97       const base::Closure& task) OVERRIDE {
98     EXPECT_TRUE(pending_task_.is_null());
99     pending_task_ = task;
100   }
101
102   // WelcomeNotificationDelegate
103   MockMessageCenter* message_center() const { return message_center_.get(); }
104
105   base::Time GetStartTime() const { return start_time_; }
106
107   void SetElapsedTime(base::TimeDelta elapsed_time) {
108     elapsed_time_ = elapsed_time;
109   }
110
111   void RunPendingTask() {
112     base::Closure task_to_run = pending_task_;
113     pending_task_.Reset();
114     task_to_run.Run();
115   }
116
117  private:
118   const base::Time start_time_;
119   base::TimeDelta elapsed_time_;
120   scoped_ptr<MockMessageCenter> message_center_;
121   base::Closure pending_task_;
122
123   DISALLOW_COPY_AND_ASSIGN(WelcomeNotificationDelegate);
124 };
125
126 class ExtensionWelcomeNotificationTest : public testing::Test {
127  protected:
128   ExtensionWelcomeNotificationTest() {
129     scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry(
130         new user_prefs::PrefRegistrySyncable());
131     ExtensionWelcomeNotification::RegisterProfilePrefs(pref_registry.get());
132   }
133
134   virtual void SetUp() {
135     task_runner_ = new base::TestSimpleTaskRunner();
136     thread_task_runner_handle_.reset(
137         new base::ThreadTaskRunnerHandle(task_runner_));
138     profile_.reset(new TestingProfile());
139     delegate_ = new WelcomeNotificationDelegate();
140     welcome_notification_ = ExtensionWelcomeNotification::Create(
141         kChromeNowExtensionID, profile_.get(), delegate_);
142   }
143
144   virtual void TearDown() {
145     delegate_ = NULL;
146     welcome_notification_.reset();
147     profile_.reset();
148     thread_task_runner_handle_.reset();
149     task_runner_ = NULL;
150   }
151
152   void StartPreferenceSyncing() const {
153     PrefServiceSyncable::FromProfile(profile_.get())
154         ->GetSyncableService(syncer::PREFERENCES)
155         ->MergeDataAndStartSyncing(syncer::PREFERENCES,
156                                    syncer::SyncDataList(),
157                                    scoped_ptr<syncer::SyncChangeProcessor>(
158                                        new syncer::FakeSyncChangeProcessor),
159                                    scoped_ptr<syncer::SyncErrorFactory>(
160                                        new syncer::SyncErrorFactoryMock()));
161   }
162
163   void ShowChromeNowNotification() const {
164     ShowNotification(
165         "ChromeNowNotification",
166         message_center::NotifierId(message_center::NotifierId::APPLICATION,
167                                    kChromeNowExtensionID));
168   }
169
170   void ShowRegularNotification() const {
171     ShowNotification(
172         "RegularNotification",
173         message_center::NotifierId(message_center::NotifierId::APPLICATION,
174                                    "aaaabbbbccccddddeeeeffffggghhhhi"));
175   }
176
177   void FlushMessageLoop() { delegate_->RunPendingTask(); }
178
179   MockMessageCenter* message_center() const {
180     return delegate_->message_center();
181   }
182   base::TestSimpleTaskRunner* task_runner() const {
183     return task_runner_.get();
184   }
185   base::Time GetStartTime() const {
186     return delegate_->GetStartTime();
187   }
188   void SetElapsedTime(base::TimeDelta elapsed_time) const {
189     delegate_->SetElapsedTime(elapsed_time);
190   }
191   bool GetBooleanPref(const char* path) const {
192     return profile_->GetPrefs()->GetBoolean(path);
193   }
194   void SetBooleanPref(const char* path, bool value) const {
195     profile_->GetPrefs()->SetBoolean(path, value);
196   }
197   int64 GetInt64Pref(const char* path) const {
198     return profile_->GetPrefs()->GetInt64(path);
199   }
200   void SetInt64Pref(const char* path, int64 value) const {
201     profile_->GetPrefs()->SetInt64(path, value);
202   }
203
204  private:
205   class TestNotificationDelegate : public NotificationDelegate {
206    public:
207     explicit TestNotificationDelegate(const std::string& id) : id_(id) {}
208
209     // Overridden from NotificationDelegate:
210     virtual void Display() OVERRIDE {}
211     virtual void Error() OVERRIDE {}
212     virtual void Close(bool by_user) OVERRIDE {}
213     virtual void Click() OVERRIDE {}
214     virtual void ButtonClick(int index) OVERRIDE {}
215
216     virtual std::string id() const OVERRIDE { return id_; }
217
218     virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE {
219       return NULL;
220     }
221
222    private:
223     virtual ~TestNotificationDelegate() {}
224
225     const std::string id_;
226
227     DISALLOW_COPY_AND_ASSIGN(TestNotificationDelegate);
228   };
229
230   void ShowNotification(std::string notification_id,
231                         const message_center::NotifierId& notifier_id) const {
232     message_center::RichNotificationData rich_notification_data;
233     rich_notification_data.priority = 0;
234     Notification notification(message_center::NOTIFICATION_TYPE_BASE_FORMAT,
235                               GURL("http://tests.url"),
236                               base::UTF8ToUTF16("Title"),
237                               base::UTF8ToUTF16("Body"),
238                               gfx::Image(),
239                               blink::WebTextDirectionDefault,
240                               notifier_id,
241                               base::UTF8ToUTF16("Source"),
242                               base::UTF8ToUTF16(notification_id),
243                               rich_notification_data,
244                               new TestNotificationDelegate("TestNotification"));
245     welcome_notification_->ShowWelcomeNotificationIfNecessary(notification);
246   }
247
248   scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
249   scoped_ptr<base::ThreadTaskRunnerHandle> thread_task_runner_handle_;
250   scoped_ptr<TestingProfile> profile_;
251   // Weak Ref owned by welcome_notification_
252   WelcomeNotificationDelegate* delegate_;
253   scoped_ptr<ExtensionWelcomeNotification> welcome_notification_;
254
255   DISALLOW_COPY_AND_ASSIGN(ExtensionWelcomeNotificationTest);
256 };
257
258 // Show a regular notification. Expect that WelcomeNotification will
259 // not show a welcome notification.
260 TEST_F(ExtensionWelcomeNotificationTest, FirstRunShowRegularNotification) {
261   StartPreferenceSyncing();
262   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
263   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
264
265   ShowRegularNotification();
266
267   EXPECT_EQ(message_center()->add_notification_calls(), 0);
268   EXPECT_EQ(message_center()->remove_notification_calls(), 0);
269   EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
270   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
271   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
272 }
273
274 // Show a Chrome Now notification. Expect that WelcomeNotification will
275 // show a welcome notification.
276 TEST_F(ExtensionWelcomeNotificationTest, FirstRunChromeNowNotification) {
277   StartPreferenceSyncing();
278   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
279   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
280
281   ShowChromeNowNotification();
282
283   EXPECT_EQ(message_center()->add_notification_calls(), 1);
284   EXPECT_EQ(message_center()->remove_notification_calls(), 0);
285   EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
286   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
287   EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
288 }
289
290 // Show a Chrome Now notification that was already shown before.
291 TEST_F(ExtensionWelcomeNotificationTest, ShowWelcomeNotificationAgain) {
292   StartPreferenceSyncing();
293   SetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp, true);
294   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
295   EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
296
297   ShowChromeNowNotification();
298
299   EXPECT_EQ(message_center()->add_notification_calls(), 1);
300   EXPECT_EQ(message_center()->remove_notification_calls(), 0);
301   EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 1);
302   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
303   EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
304 }
305
306 // Don't show a welcome notification if it was previously dismissed
307 TEST_F(ExtensionWelcomeNotificationTest,
308        WelcomeNotificationPreviouslyDismissed) {
309   StartPreferenceSyncing();
310   SetBooleanPref(prefs::kWelcomeNotificationDismissed, true);
311   EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
312   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
313
314   ShowChromeNowNotification();
315
316   EXPECT_EQ(message_center()->add_notification_calls(), 0);
317   EXPECT_EQ(message_center()->remove_notification_calls(), 0);
318   EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
319   EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
320   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
321 }
322
323 // Show a Chrome Now notification and dismiss it.
324 // Expect welcome toast dismissed to be true.
325 TEST_F(ExtensionWelcomeNotificationTest, DismissWelcomeNotification) {
326   StartPreferenceSyncing();
327   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
328   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
329
330   ShowChromeNowNotification();
331   message_center()->CloseCurrentNotification();
332   FlushMessageLoop();
333
334   EXPECT_EQ(message_center()->add_notification_calls(), 1);
335   EXPECT_EQ(message_center()->remove_notification_calls(), 1);
336   EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
337   EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
338   EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
339 }
340
341 // Show a Chrome Now notification and dismiss it via a synced preference change.
342 // Expect welcome toast dismissed to be true.
343 TEST_F(ExtensionWelcomeNotificationTest, SyncedDismissalWelcomeNotification) {
344   StartPreferenceSyncing();
345   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
346   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
347
348   ShowChromeNowNotification();
349   SetBooleanPref(prefs::kWelcomeNotificationDismissed, true);
350
351   EXPECT_EQ(message_center()->add_notification_calls(), 1);
352   EXPECT_EQ(message_center()->remove_notification_calls(), 1);
353   EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
354   EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
355   EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
356 }
357
358 // Simulate a delayed preference sync when the welcome notification was
359 // previously dismissed.
360 TEST_F(ExtensionWelcomeNotificationTest,
361        DelayedPreferenceSyncPreviouslyDismissed) {
362   // Show a notification while the preference system is not syncing.
363   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
364   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
365
366   ShowChromeNowNotification();
367
368   EXPECT_EQ(message_center()->add_notification_calls(), 0);
369   EXPECT_EQ(message_center()->remove_notification_calls(), 0);
370   EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
371   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
372   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
373
374   // Now start the preference syncing with a previously dismissed welcome.
375   SetBooleanPref(prefs::kWelcomeNotificationDismissed, true);
376   EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
377   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
378
379   StartPreferenceSyncing();
380
381   EXPECT_EQ(message_center()->add_notification_calls(), 0);
382   EXPECT_EQ(message_center()->remove_notification_calls(), 0);
383   EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
384   EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
385   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
386 }
387
388 // Simulate a delayed preference sync when the welcome notification was
389 // never shown.
390 TEST_F(ExtensionWelcomeNotificationTest, DelayedPreferenceSyncNeverShown) {
391   // Show a notification while the preference system is not syncing.
392   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
393   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
394
395   ShowChromeNowNotification();
396
397   EXPECT_EQ(message_center()->add_notification_calls(), 0);
398   EXPECT_EQ(message_center()->remove_notification_calls(), 0);
399   EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
400   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
401   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
402
403   // Now start the preference syncing with the default preference values.
404   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
405   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
406
407   StartPreferenceSyncing();
408
409   EXPECT_EQ(message_center()->add_notification_calls(), 1);
410   EXPECT_EQ(message_center()->remove_notification_calls(), 0);
411   EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
412   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
413   EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
414 }
415
416 // Simulate the passage of time when the welcome notification
417 // automatically dismisses.
418 TEST_F(ExtensionWelcomeNotificationTest, TimeExpiredNotification) {
419   StartPreferenceSyncing();
420   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
421   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
422   EXPECT_EQ(GetInt64Pref(prefs::kWelcomeNotificationExpirationTimestamp), 0);
423   EXPECT_TRUE(task_runner()->GetPendingTasks().empty());
424
425   ShowChromeNowNotification();
426
427   base::TimeDelta requested_show_time =
428       base::TimeDelta::FromDays(
429           ExtensionWelcomeNotification::kRequestedShowTimeDays);
430
431   EXPECT_EQ(task_runner()->GetPendingTasks().size(), 1U);
432   EXPECT_EQ(task_runner()->NextPendingTaskDelay(), requested_show_time);
433
434   EXPECT_EQ(message_center()->add_notification_calls(), 1);
435   EXPECT_EQ(message_center()->remove_notification_calls(), 0);
436   EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
437   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
438   EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
439   EXPECT_EQ(
440       GetInt64Pref(prefs::kWelcomeNotificationExpirationTimestamp),
441       (GetStartTime() + requested_show_time).ToInternalValue());
442
443   SetElapsedTime(requested_show_time);
444   task_runner()->RunPendingTasks();
445
446   EXPECT_TRUE(task_runner()->GetPendingTasks().empty());
447   EXPECT_EQ(message_center()->add_notification_calls(), 1);
448   EXPECT_EQ(message_center()->remove_notification_calls(), 1);
449   EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
450   EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
451   EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
452   EXPECT_EQ(
453       GetInt64Pref(prefs::kWelcomeNotificationExpirationTimestamp),
454       (GetStartTime() + requested_show_time).ToInternalValue());
455 }
456
457 // Simulate the passage of time after Chrome is closed and the welcome
458 // notification expiration elapses.
459 TEST_F(ExtensionWelcomeNotificationTest, NotificationPreviouslyExpired) {
460   StartPreferenceSyncing();
461   SetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp, true);
462   SetInt64Pref(prefs::kWelcomeNotificationExpirationTimestamp, 1);
463   EXPECT_FALSE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
464   EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
465   EXPECT_EQ(GetInt64Pref(prefs::kWelcomeNotificationExpirationTimestamp), 1);
466   EXPECT_TRUE(task_runner()->GetPendingTasks().empty());
467
468   const base::TimeDelta requested_show_time =
469       base::TimeDelta::FromDays(
470           ExtensionWelcomeNotification::kRequestedShowTimeDays);
471   SetElapsedTime(requested_show_time);
472   ShowChromeNowNotification();
473
474   EXPECT_TRUE(task_runner()->GetPendingTasks().empty());
475   EXPECT_EQ(message_center()->add_notification_calls(), 0);
476   EXPECT_EQ(message_center()->remove_notification_calls(), 0);
477   EXPECT_EQ(message_center()->notifications_with_shown_as_popup(), 0);
478   EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationDismissed));
479   EXPECT_TRUE(GetBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp));
480   EXPECT_EQ(GetInt64Pref(prefs::kWelcomeNotificationExpirationTimestamp), 1);
481 }
482
483 // C++ Readability Review Change Trigger