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"
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"
23 const char kChromeNowExtensionID[] = "pafkbggdmjlpgkdkcbjmhmfcdpncadgh";
25 class MockMessageCenter : public message_center::FakeMessageCenter {
28 : add_notification_calls_(0),
29 remove_notification_calls_(0),
30 notifications_with_shown_as_popup_(0) {};
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_;
38 // message_center::FakeMessageCenter Overrides
39 virtual bool HasNotification(const std::string& id) OVERRIDE {
40 return last_notification.get() && (last_notification->id() == id);
43 virtual void AddNotification(
44 scoped_ptr<message_center::Notification> notification) OVERRIDE {
45 EXPECT_FALSE(last_notification.get());
46 last_notification.swap(notification);
47 add_notification_calls_++;
48 if (last_notification->shown_as_popup())
49 notifications_with_shown_as_popup_++;
52 virtual void RemoveNotification(const std::string& id,
53 bool by_user) OVERRIDE {
54 EXPECT_TRUE(last_notification.get());
55 last_notification.reset();
56 remove_notification_calls_++;
59 void CloseCurrentNotification() {
60 EXPECT_TRUE(last_notification.get());
61 last_notification->delegate()->Close(true);
62 RemoveNotification(last_notification->id(), true);
66 scoped_ptr<message_center::Notification> last_notification;
67 int add_notification_calls_;
68 int remove_notification_calls_;
69 int notifications_with_shown_as_popup_;
72 class TestSyncProcessor : public syncer::SyncChangeProcessor {
73 virtual syncer::SyncError ProcessSyncChanges(
74 const tracked_objects::Location& from_here,
75 const syncer::SyncChangeList& change_list) OVERRIDE {
76 return syncer::SyncError();
79 virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type)
81 return syncer::SyncDataList();
85 class ExtensionWelcomeNotificationTest : public testing::Test {
87 ExtensionWelcomeNotificationTest() {
88 scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry(
89 new user_prefs::PrefRegistrySyncable());
90 ExtensionWelcomeNotification::RegisterProfilePrefs(pref_registry.get());
93 virtual void SetUp() {
94 message_loop_.reset(new base::MessageLoop());
95 profile_.reset(new TestingProfile());
96 message_center_.reset(new MockMessageCenter());
97 welcome_notification_.reset(new ExtensionWelcomeNotification(
98 kChromeNowExtensionID, profile_.get(), message_center_.get()));
101 virtual void TearDown() {
102 welcome_notification_.reset();
103 message_center_.reset();
105 message_loop_.reset();
108 void StartPreferenceSyncing() {
109 PrefServiceSyncable::FromProfile(profile())
110 ->GetSyncableService(syncer::PREFERENCES)
111 ->MergeDataAndStartSyncing(
113 syncer::SyncDataList(),
114 scoped_ptr<syncer::SyncChangeProcessor>(new TestSyncProcessor),
115 scoped_ptr<syncer::SyncErrorFactory>(
116 new syncer::SyncErrorFactoryMock()));
119 void ShowChromeNowNotification() {
121 "ChromeNowNotification",
122 message_center::NotifierId(message_center::NotifierId::APPLICATION,
123 kChromeNowExtensionID));
126 void ShowRegularNotification() {
128 "RegularNotification",
129 message_center::NotifierId(message_center::NotifierId::APPLICATION,
130 "aaaabbbbccccddddeeeeffffggghhhhi"));
133 void FlushMessageLoop() { message_loop_->RunUntilIdle(); }
135 TestingProfile* profile() { return profile_.get(); }
136 MockMessageCenter* message_center() { return message_center_.get(); }
139 class TestNotificationDelegate : public NotificationDelegate {
141 explicit TestNotificationDelegate(const std::string& id) : id_(id) {}
143 // Overridden from NotificationDelegate:
144 virtual void Display() OVERRIDE {}
145 virtual void Error() OVERRIDE {}
146 virtual void Close(bool by_user) OVERRIDE {}
147 virtual void Click() OVERRIDE {}
148 virtual void ButtonClick(int index) OVERRIDE {}
150 virtual std::string id() const OVERRIDE { return id_; }
152 virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE {
157 virtual ~TestNotificationDelegate() {}
159 const std::string id_;
161 DISALLOW_COPY_AND_ASSIGN(TestNotificationDelegate);
164 void ShowNotification(std::string notification_id,
165 const message_center::NotifierId& notifier_id) {
166 message_center::RichNotificationData rich_notification_data;
167 rich_notification_data.priority = 0;
168 Notification notification(message_center::NOTIFICATION_TYPE_BASE_FORMAT,
169 GURL("http://tests.url"),
170 base::UTF8ToUTF16("Title"),
171 base::UTF8ToUTF16("Body"),
173 blink::WebTextDirectionDefault,
175 base::UTF8ToUTF16("Source"),
176 base::UTF8ToUTF16(notification_id),
177 rich_notification_data,
178 new TestNotificationDelegate("TestNotification"));
179 welcome_notification_->ShowWelcomeNotificationIfNecessary(notification);
182 scoped_ptr<TestingProfile> profile_;
183 scoped_ptr<MockMessageCenter> message_center_;
184 scoped_ptr<ExtensionWelcomeNotification> welcome_notification_;
185 scoped_ptr<base::MessageLoop> message_loop_;
188 // Show a regular notification. Expect that WelcomeNotification will
189 // not show a welcome notification.
190 TEST_F(ExtensionWelcomeNotificationTest, FirstRunShowRegularNotification) {
191 StartPreferenceSyncing();
193 profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
194 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
195 prefs::kWelcomeNotificationPreviouslyPoppedUp));
197 ShowRegularNotification();
199 EXPECT_TRUE(message_center()->add_notification_calls() == 0);
200 EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
201 EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
203 profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
204 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
205 prefs::kWelcomeNotificationPreviouslyPoppedUp));
208 // Show a Chrome Now notification. Expect that WelcomeNotification will
209 // show a welcome notification.
210 TEST_F(ExtensionWelcomeNotificationTest, FirstRunChromeNowNotification) {
211 StartPreferenceSyncing();
213 profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
214 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
215 prefs::kWelcomeNotificationPreviouslyPoppedUp));
217 ShowChromeNowNotification();
219 EXPECT_TRUE(message_center()->add_notification_calls() == 1);
220 EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
221 EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
223 profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
224 EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
225 prefs::kWelcomeNotificationPreviouslyPoppedUp));
228 // Show a Chrome Now notification that was already shown before.
229 TEST_F(ExtensionWelcomeNotificationTest, ShowWelcomeNotificationAgain) {
230 StartPreferenceSyncing();
231 profile()->GetPrefs()->SetBoolean(
232 prefs::kWelcomeNotificationPreviouslyPoppedUp, true);
234 profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
235 EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
236 prefs::kWelcomeNotificationPreviouslyPoppedUp));
238 ShowChromeNowNotification();
240 EXPECT_TRUE(message_center()->add_notification_calls() == 1);
241 EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
242 EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 1);
244 profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
245 EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
246 prefs::kWelcomeNotificationPreviouslyPoppedUp));
249 // Don't show a welcome notification if it was previously dismissed
250 TEST_F(ExtensionWelcomeNotificationTest,
251 WelcomeNotificationPreviouslyDismissed) {
252 StartPreferenceSyncing();
253 profile()->GetPrefs()->SetBoolean(prefs::kWelcomeNotificationDismissed, true);
255 profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
256 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
257 prefs::kWelcomeNotificationPreviouslyPoppedUp));
259 ShowChromeNowNotification();
261 EXPECT_TRUE(message_center()->add_notification_calls() == 0);
262 EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
263 EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
265 profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
266 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
267 prefs::kWelcomeNotificationPreviouslyPoppedUp));
270 // Show a Chrome Now notification and dismiss it.
271 // Expect welcome toast dismissed to be true.
272 TEST_F(ExtensionWelcomeNotificationTest, DismissWelcomeNotification) {
273 StartPreferenceSyncing();
275 profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
276 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
277 prefs::kWelcomeNotificationPreviouslyPoppedUp));
279 ShowChromeNowNotification();
280 message_center()->CloseCurrentNotification();
283 EXPECT_TRUE(message_center()->add_notification_calls() == 1);
284 EXPECT_TRUE(message_center()->remove_notification_calls() == 1);
285 EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
287 profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
288 EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
289 prefs::kWelcomeNotificationPreviouslyPoppedUp));
292 // Show a Chrome Now notification and dismiss it via a synced preference change.
293 // Expect welcome toast dismissed to be true.
294 TEST_F(ExtensionWelcomeNotificationTest, SyncedDismissalWelcomeNotification) {
295 StartPreferenceSyncing();
297 profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
298 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
299 prefs::kWelcomeNotificationPreviouslyPoppedUp));
301 ShowChromeNowNotification();
302 profile()->GetPrefs()->SetBoolean(prefs::kWelcomeNotificationDismissed, true);
304 EXPECT_TRUE(message_center()->add_notification_calls() == 1);
305 EXPECT_TRUE(message_center()->remove_notification_calls() == 1);
306 EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
308 profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
309 EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
310 prefs::kWelcomeNotificationPreviouslyPoppedUp));
313 // Simulate a delayed preference sync when the welcome notification was
314 // previously dismissed.
315 TEST_F(ExtensionWelcomeNotificationTest,
316 DelayedPreferenceSyncPreviouslyDismissed) {
317 // Show a notification while the preference system is not syncing.
319 profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
320 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
321 prefs::kWelcomeNotificationPreviouslyPoppedUp));
323 ShowChromeNowNotification();
325 EXPECT_TRUE(message_center()->add_notification_calls() == 0);
326 EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
327 EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
329 profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
330 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
331 prefs::kWelcomeNotificationPreviouslyPoppedUp));
333 // Now start the preference syncing with a previously dismissed welcome.
334 profile()->GetPrefs()->SetBoolean(prefs::kWelcomeNotificationDismissed, true);
336 profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
337 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
338 prefs::kWelcomeNotificationPreviouslyPoppedUp));
340 StartPreferenceSyncing();
342 EXPECT_TRUE(message_center()->add_notification_calls() == 0);
343 EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
344 EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
346 profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
347 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
348 prefs::kWelcomeNotificationPreviouslyPoppedUp));
351 // Simulate a delayed preference sync when the welcome notification was
353 TEST_F(ExtensionWelcomeNotificationTest, DelayedPreferenceSyncNeverShown) {
354 // Show a notification while the preference system is not syncing.
356 profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
357 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
358 prefs::kWelcomeNotificationPreviouslyPoppedUp));
360 ShowChromeNowNotification();
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);
366 profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
367 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
368 prefs::kWelcomeNotificationPreviouslyPoppedUp));
370 // Now start the preference syncing with the default preference values.
372 profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
373 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
374 prefs::kWelcomeNotificationPreviouslyPoppedUp));
376 StartPreferenceSyncing();
378 EXPECT_TRUE(message_center()->add_notification_calls() == 1);
379 EXPECT_TRUE(message_center()->remove_notification_calls() == 0);
380 EXPECT_TRUE(message_center()->notifications_with_shown_as_popup() == 0);
382 profile()->GetPrefs()->GetBoolean(prefs::kWelcomeNotificationDismissed));
383 EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
384 prefs::kWelcomeNotificationPreviouslyPoppedUp));