• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 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 <map>
6 #include <string>
7 
8 #include "base/command_line.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/chrome_notification_types.h"
15 #include "chrome/browser/notifications/message_center_notification_manager.h"
16 #include "chrome/browser/notifications/notification.h"
17 #include "chrome/browser/notifications/notification_ui_manager.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/ui/browser.h"
20 #include "chrome/test/base/in_process_browser_test.h"
21 #include "chrome/test/base/test_switches.h"
22 #include "content/public/browser/notification_details.h"
23 #include "content/public/browser/notification_observer.h"
24 #include "content/public/browser/notification_source.h"
25 #include "ui/message_center/message_center.h"
26 #include "ui/message_center/message_center_types.h"
27 
28 class TestAddObserver : public message_center::MessageCenterObserver {
29  public:
TestAddObserver(message_center::MessageCenter * message_center)30   explicit TestAddObserver(message_center::MessageCenter* message_center)
31       : message_center_(message_center) {
32     message_center_->AddObserver(this);
33   }
34 
~TestAddObserver()35   virtual ~TestAddObserver() { message_center_->RemoveObserver(this); }
36 
OnNotificationAdded(const std::string & id)37   virtual void OnNotificationAdded(const std::string& id) OVERRIDE {
38     std::string log = logs_[id];
39     if (log != "")
40       log += "_";
41     logs_[id] = log + "add-" + id;
42   }
43 
OnNotificationUpdated(const std::string & id)44   virtual void OnNotificationUpdated(const std::string& id) OVERRIDE {
45     std::string log = logs_[id];
46     if (log != "")
47       log += "_";
48     logs_[id] = log + "update-" + id;
49   }
50 
log(const std::string & id)51   const std::string log(const std::string& id) { return logs_[id]; }
reset_logs()52   void reset_logs() { logs_.clear(); }
53 
54  private:
55   std::map<std::string, std::string> logs_;
56   message_center::MessageCenter* message_center_;
57 };
58 
59 class MessageCenterNotificationsTest : public InProcessBrowserTest {
60  public:
MessageCenterNotificationsTest()61   MessageCenterNotificationsTest() {}
62 
manager()63   MessageCenterNotificationManager* manager() {
64     return static_cast<MessageCenterNotificationManager*>(
65         g_browser_process->notification_ui_manager());
66   }
67 
message_center()68   message_center::MessageCenter* message_center() {
69     return g_browser_process->message_center();
70   }
71 
profile()72   Profile* profile() { return browser()->profile(); }
73 
74   class TestDelegate : public NotificationDelegate {
75    public:
TestDelegate(const std::string & id)76     explicit TestDelegate(const std::string& id) : id_(id) {}
77 
Display()78     virtual void Display() OVERRIDE { log_ += "Display_"; }
Error()79     virtual void Error() OVERRIDE { log_ += "Error_"; }
Close(bool by_user)80     virtual void Close(bool by_user) OVERRIDE {
81       log_ += "Close_";
82       log_ += ( by_user ? "by_user_" : "programmatically_");
83     }
Click()84     virtual void Click() OVERRIDE { log_ += "Click_"; }
ButtonClick(int button_index)85     virtual void ButtonClick(int button_index) OVERRIDE {
86       log_ += "ButtonClick_";
87       log_ += base::IntToString(button_index) + "_";
88     }
id() const89     virtual std::string id() const OVERRIDE { return id_; }
GetWebContents() const90     virtual content::WebContents* GetWebContents() const OVERRIDE {
91       return NULL;
92     }
93 
log()94     const std::string& log() { return log_; }
95 
96    private:
~TestDelegate()97     virtual ~TestDelegate() {}
98     std::string id_;
99     std::string log_;
100 
101     DISALLOW_COPY_AND_ASSIGN(TestDelegate);
102   };
103 
CreateTestNotification(const std::string & id,TestDelegate ** delegate=NULL)104   Notification CreateTestNotification(const std::string& id,
105                                       TestDelegate** delegate = NULL) {
106     TestDelegate* new_delegate = new TestDelegate(id);
107     if (delegate) {
108       *delegate = new_delegate;
109       new_delegate->AddRef();
110     }
111 
112     return Notification(GURL("chrome-test://testing/"),
113                         GURL(),
114                         base::ASCIIToUTF16("title"),
115                         base::ASCIIToUTF16("message"),
116                         blink::WebTextDirectionDefault,
117                         base::UTF8ToUTF16("chrome-test://testing/"),
118                         base::UTF8ToUTF16("REPLACE-ME"),
119                         new_delegate);
120   }
121 
CreateRichTestNotification(const std::string & id,TestDelegate ** delegate=NULL)122   Notification CreateRichTestNotification(const std::string& id,
123                                           TestDelegate** delegate = NULL) {
124     TestDelegate* new_delegate = new TestDelegate(id);
125     if (delegate) {
126       *delegate = new_delegate;
127       new_delegate->AddRef();
128     }
129 
130     message_center::RichNotificationData data;
131 
132     return Notification(message_center::NOTIFICATION_TYPE_BASE_FORMAT,
133                         GURL("chrome-test://testing/"),
134                         base::ASCIIToUTF16("title"),
135                         base::ASCIIToUTF16("message"),
136                         gfx::Image(),
137                         blink::WebTextDirectionDefault,
138                         message_center::NotifierId(
139                             message_center::NotifierId::APPLICATION,
140                             "extension_id"),
141                         base::UTF8ToUTF16("chrome-test://testing/"),
142                         base::UTF8ToUTF16("REPLACE-ME"),
143                         data,
144                         new_delegate);
145   }
146 };
147 
148 // TODO(rsesek): Implement Message Center on Mac and get these tests passing
149 // for real. http://crbug.com/179904
150 #if !defined(OS_MACOSX)
151 
IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest,RetrieveBaseParts)152 IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest, RetrieveBaseParts) {
153   EXPECT_TRUE(manager());
154   EXPECT_TRUE(message_center());
155 }
156 
IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest,BasicAddCancel)157 IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest, BasicAddCancel) {
158 #if defined(OS_WIN) && defined(USE_ASH)
159   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
160   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
161     return;
162 #endif
163 
164   // Someone may create system notifications like "you're in multi-profile
165   // mode..." or something which may change the expectation.
166   // TODO(mukai): move this to SetUpOnMainThread() after fixing the side-effect
167   // of canceling animation which prevents some Displayed() event.
168   manager()->CancelAll();
169   manager()->Add(CreateTestNotification("hey"), profile());
170   EXPECT_EQ(1u, message_center()->NotificationCount());
171   manager()->CancelById("hey");
172   EXPECT_EQ(0u, message_center()->NotificationCount());
173 }
174 
IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest,BasicDelegate)175 IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest, BasicDelegate) {
176 #if defined(OS_WIN) && defined(USE_ASH)
177   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
178   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
179     return;
180 #endif
181 
182   TestDelegate* delegate;
183   manager()->Add(CreateTestNotification("hey", &delegate), profile());
184   // Verify that delegate accumulated correct log of events.
185   EXPECT_EQ("Display_", delegate->log());
186   manager()->CancelById("hey");
187   // Verify that delegate accumulated correct log of events.
188   EXPECT_EQ("Display_Close_programmatically_", delegate->log());
189   delegate->Release();
190 }
191 
IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest,ButtonClickedDelegate)192 IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest, ButtonClickedDelegate) {
193 #if defined(OS_WIN) && defined(USE_ASH)
194   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
195   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
196     return;
197 #endif
198 
199   TestDelegate* delegate;
200   manager()->Add(CreateTestNotification("n", &delegate), profile());
201   message_center()->ClickOnNotificationButton("n", 1);
202   // Verify that delegate accumulated correct log of events.
203   EXPECT_EQ("Display_ButtonClick_1_", delegate->log());
204   delegate->Release();
205 }
206 
IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest,UpdateExistingNotification)207 IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest,
208                        UpdateExistingNotification) {
209 #if defined(OS_WIN) && defined(USE_ASH)
210   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
211   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
212     return;
213 #endif
214 
215   TestDelegate* delegate;
216   manager()->Add(CreateTestNotification("n", &delegate), profile());
217   TestDelegate* delegate2;
218   manager()->Add(CreateRichTestNotification("n", &delegate2), profile());
219 
220   manager()->CancelById("n");
221   EXPECT_EQ("Display_", delegate->log());
222   EXPECT_EQ("Close_programmatically_", delegate2->log());
223 
224   delegate->Release();
225   delegate2->Release();
226 }
227 
IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest,QueueWhenCenterVisible)228 IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest, QueueWhenCenterVisible) {
229 #if defined(OS_WIN) && defined(USE_ASH)
230   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
231   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
232     return;
233 #endif
234 
235   TestAddObserver observer(message_center());
236 
237   TestDelegate* delegate;
238   TestDelegate* delegate2;
239 
240   manager()->Add(CreateTestNotification("n", &delegate), profile());
241   message_center()->SetVisibility(message_center::VISIBILITY_MESSAGE_CENTER);
242   manager()->Add(CreateTestNotification("n2", &delegate2), profile());
243 
244   // 'update-n' should happen since SetVisibility updates is_read status of n.
245   // TODO(mukai): fix event handling to happen update-n just once.
246   EXPECT_EQ("add-n_update-n_update-n", observer.log("n"));
247 
248   message_center()->SetVisibility(message_center::VISIBILITY_TRANSIENT);
249 
250   EXPECT_EQ("add-n2", observer.log("n2"));
251 
252   delegate->Release();
253   delegate2->Release();
254 }
255 
IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest,UpdateNonProgressNotificationWhenCenterVisible)256 IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest,
257                        UpdateNonProgressNotificationWhenCenterVisible) {
258 #if defined(OS_WIN) && defined(USE_ASH)
259   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
260   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
261     return;
262 #endif
263 
264   TestAddObserver observer(message_center());
265 
266   TestDelegate* delegate;
267 
268   // Add a non-progress notification and update it while the message center
269   // is visible.
270   Notification notification = CreateTestNotification("n", &delegate);
271   manager()->Add(notification, profile());
272   message_center()->ClickOnNotification("n");
273   message_center()->SetVisibility(message_center::VISIBILITY_MESSAGE_CENTER);
274   observer.reset_logs();
275   notification.set_title(base::ASCIIToUTF16("title2"));
276   manager()->Update(notification, profile());
277 
278   // Expect that the notification update is not done.
279   EXPECT_EQ("", observer.log("n"));
280 
281   message_center()->SetVisibility(message_center::VISIBILITY_TRANSIENT);
282   EXPECT_EQ("update-n", observer.log("n"));
283 
284   delegate->Release();
285 }
286 
IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest,UpdateNonProgressToProgressNotificationWhenCenterVisible)287 IN_PROC_BROWSER_TEST_F(
288     MessageCenterNotificationsTest,
289     UpdateNonProgressToProgressNotificationWhenCenterVisible) {
290 #if defined(OS_WIN) && defined(USE_ASH)
291   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
292   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
293     return;
294 #endif
295 
296   TestAddObserver observer(message_center());
297 
298   TestDelegate* delegate;
299 
300   // Add a non-progress notification and change the type to progress while the
301   // message center is visible.
302   Notification notification = CreateTestNotification("n", &delegate);
303   manager()->Add(notification, profile());
304   message_center()->ClickOnNotification("n");
305   message_center()->SetVisibility(message_center::VISIBILITY_MESSAGE_CENTER);
306   observer.reset_logs();
307   notification.set_type(message_center::NOTIFICATION_TYPE_PROGRESS);
308   manager()->Update(notification, profile());
309 
310   // Expect that the notification update is not done.
311   EXPECT_EQ("", observer.log("n"));
312 
313   message_center()->SetVisibility(message_center::VISIBILITY_TRANSIENT);
314   EXPECT_EQ("update-n", observer.log("n"));
315 
316   delegate->Release();
317 }
318 
IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest,UpdateProgressNotificationWhenCenterVisible)319 IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest,
320                        UpdateProgressNotificationWhenCenterVisible) {
321 #if defined(OS_WIN) && defined(USE_ASH)
322   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
323   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
324     return;
325 #endif
326 
327   TestAddObserver observer(message_center());
328 
329   TestDelegate* delegate;
330 
331   // Add a progress notification and update it while the message center
332   // is visible.
333   Notification notification = CreateTestNotification("n", &delegate);
334   notification.set_type(message_center::NOTIFICATION_TYPE_PROGRESS);
335   manager()->Add(notification, profile());
336   message_center()->ClickOnNotification("n");
337   message_center()->SetVisibility(message_center::VISIBILITY_MESSAGE_CENTER);
338   observer.reset_logs();
339   notification.set_progress(50);
340   manager()->Update(notification, profile());
341 
342   // Expect that the progress notification update is performed.
343   EXPECT_EQ("update-n", observer.log("n"));
344 
345   delegate->Release();
346 }
347 
348 #if !defined(OS_CHROMEOS)
349 #define MAYBE_HideWhenFullscreenEnabled HideWhenFullscreenEnabled
350 #else
351 #define MAYBE_HideWhenFullscreenEnabled DISABLED_HideWhenFullscreenEnabled
352 #endif
353 
IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest,MAYBE_HideWhenFullscreenEnabled)354 IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest,
355                        MAYBE_HideWhenFullscreenEnabled) {
356   TestDelegate* delegate;
357   manager()->Add(CreateTestNotification("n", &delegate), profile());
358 
359   EXPECT_EQ("Display_", delegate->log());
360   EXPECT_TRUE(message_center()->HasPopupNotifications());
361   bool is_fullscreen = true;
362   // Cast so that Observe() is public.
363   content::NotificationObserver* observer =
364       static_cast<content::NotificationObserver*>(manager());
365   observer->Observe(chrome::NOTIFICATION_FULLSCREEN_CHANGED,
366                     content::Source<Profile>(profile()),
367                     content::Details<bool>(&is_fullscreen));
368   EXPECT_FALSE(message_center()->HasPopupNotifications());
369 }
370 
371 #endif  // !defined(OS_MACOSX)
372