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 <string>
6
7#include "base/command_line.h"
8#include "base/message_loop/message_loop.h"
9#include "base/strings/string_number_conversions.h"
10#include "base/strings/string_util.h"
11#include "base/strings/utf_string_conversions.h"
12#include "chrome/browser/browser_process.h"
13#include "chrome/browser/chrome_notification_types.h"
14#include "chrome/browser/notifications/message_center_notification_manager.h"
15#include "chrome/browser/notifications/notification.h"
16#include "chrome/browser/notifications/notification_ui_manager.h"
17#include "chrome/browser/profiles/profile.h"
18#include "chrome/browser/ui/browser.h"
19#include "chrome/test/base/in_process_browser_test.h"
20#include "chrome/test/base/test_switches.h"
21#include "content/public/browser/notification_details.h"
22#include "content/public/browser/notification_observer.h"
23#include "content/public/browser/notification_source.h"
24#include "ui/message_center/message_center.h"
25#include "ui/message_center/message_center_switches.h"
26#include "ui/message_center/message_center_types.h"
27#include "ui/message_center/message_center_util.h"
28
29class TestAddObserver : public message_center::MessageCenterObserver {
30 public:
31  explicit TestAddObserver(message_center::MessageCenter* message_center)
32      : message_center_(message_center) {
33    message_center_->AddObserver(this);
34  }
35
36  virtual ~TestAddObserver() { message_center_->RemoveObserver(this); }
37
38  virtual void OnNotificationAdded(const std::string& id) OVERRIDE {
39    if (log_ != "")
40      log_ += "_";
41    log_ += "add-" + id;
42  }
43
44  virtual void OnNotificationUpdated(const std::string& id) OVERRIDE {
45    if (log_ != "")
46      log_ += "_";
47    log_ += "update-" + id;
48  }
49
50  const std::string log() const { return log_; }
51  void reset_log() { log_ = ""; }
52
53 private:
54  std::string log_;
55  message_center::MessageCenter* message_center_;
56};
57
58class MessageCenterNotificationsTest : public InProcessBrowserTest {
59 public:
60  MessageCenterNotificationsTest() {}
61
62  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
63    // This switch enables the new piping of Notifications through Message
64    // Center.
65    command_line->AppendSwitch(
66      message_center::switches::kEnableRichNotifications);
67  }
68
69  MessageCenterNotificationManager* manager() {
70    return static_cast<MessageCenterNotificationManager*>(
71        g_browser_process->notification_ui_manager());
72  }
73
74  message_center::MessageCenter* message_center() {
75    return g_browser_process->message_center();
76  }
77
78  Profile* profile() { return browser()->profile(); }
79
80  class TestDelegate : public NotificationDelegate {
81   public:
82    explicit TestDelegate(const std::string& id) : id_(id) {}
83
84    virtual void Display() OVERRIDE { log_ += "Display_"; }
85    virtual void Error() OVERRIDE { log_ += "Error_"; }
86    virtual void Close(bool by_user) OVERRIDE {
87      log_ += "Close_";
88      log_ += ( by_user ? "by_user_" : "programmatically_");
89    }
90    virtual void Click() OVERRIDE { log_ += "Click_"; }
91    virtual void ButtonClick(int button_index) OVERRIDE {
92      log_ += "ButtonClick_";
93      log_ += base::IntToString(button_index) + "_";
94    }
95    virtual std::string id() const OVERRIDE { return id_; }
96    virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE {
97      return NULL;
98    }
99
100    const std::string& log() { return log_; }
101
102   private:
103    virtual ~TestDelegate() {}
104    std::string id_;
105    std::string log_;
106
107    DISALLOW_COPY_AND_ASSIGN(TestDelegate);
108  };
109
110  Notification CreateTestNotification(const std::string& id,
111                                      TestDelegate** delegate = NULL) {
112    TestDelegate* new_delegate = new TestDelegate(id);
113    if (delegate) {
114      *delegate = new_delegate;
115      new_delegate->AddRef();
116    }
117
118    return Notification(GURL("chrome-test://testing/"),
119                        GURL(),
120                        ASCIIToUTF16("title"),
121                        ASCIIToUTF16("message"),
122                        blink::WebTextDirectionDefault,
123                        UTF8ToUTF16("chrome-test://testing/"),
124                        UTF8ToUTF16("REPLACE-ME"),
125                        new_delegate);
126  }
127
128  Notification CreateRichTestNotification(const std::string& id,
129                                          TestDelegate** delegate = NULL) {
130    TestDelegate* new_delegate = new TestDelegate(id);
131    if (delegate) {
132      *delegate = new_delegate;
133      new_delegate->AddRef();
134    }
135
136    message_center::RichNotificationData data;
137
138    return Notification(message_center::NOTIFICATION_TYPE_BASE_FORMAT,
139                        GURL("chrome-test://testing/"),
140                        ASCIIToUTF16("title"),
141                        ASCIIToUTF16("message"),
142                        gfx::Image(),
143                        blink::WebTextDirectionDefault,
144                        message_center::NotifierId(
145                            message_center::NotifierId::APPLICATION,
146                            "extension_id"),
147                        UTF8ToUTF16("chrome-test://testing/"),
148                        UTF8ToUTF16("REPLACE-ME"),
149                        data,
150                        new_delegate);
151  }
152};
153
154// TODO(rsesek): Implement Message Center on Mac and get these tests passing
155// for real. http://crbug.com/179904
156#if !defined(OS_MACOSX)
157
158IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest, RetrieveBaseParts) {
159  // Make sure comamnd-line switch has an effect.
160  EXPECT_EQ(NotificationUIManager::DelegatesToMessageCenter(),
161            message_center::IsRichNotificationEnabled());
162  EXPECT_TRUE(manager());
163  EXPECT_TRUE(message_center());
164}
165
166// MessaceCenter-specific test.
167#if defined(RUN_MESSAGE_CENTER_TESTS)
168#define MAYBE_BasicAddCancel BasicAddCancel
169#else
170#define MAYBE_BasicAddCancel DISABLED_BasicAddCancel
171#endif
172
173IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest, MAYBE_BasicAddCancel) {
174#if defined(OS_WIN) && defined(USE_ASH)
175  // Disable this test in Metro+Ash for now (http://crbug.com/262796).
176  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
177    return;
178#endif
179
180  EXPECT_TRUE(NotificationUIManager::DelegatesToMessageCenter());
181  manager()->Add(CreateTestNotification("hey"), profile());
182  EXPECT_EQ(1u, message_center()->NotificationCount());
183  manager()->CancelById("hey");
184  EXPECT_EQ(0u, message_center()->NotificationCount());
185}
186
187// MessaceCenter-specific test.
188#if defined(RUN_MESSAGE_CENTER_TESTS)
189#define MAYBE_BasicDelegate BasicDelegate
190#else
191#define MAYBE_BasicDelegate DISABLED_BasicDelegate
192#endif
193
194IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest, MAYBE_BasicDelegate) {
195#if defined(OS_WIN) && defined(USE_ASH)
196  // Disable this test in Metro+Ash for now (http://crbug.com/262796).
197  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
198    return;
199#endif
200
201  EXPECT_TRUE(NotificationUIManager::DelegatesToMessageCenter());
202  TestDelegate* delegate;
203  manager()->Add(CreateTestNotification("hey", &delegate), profile());
204  // Verify that delegate accumulated correct log of events.
205  EXPECT_EQ("Display_", delegate->log());
206  manager()->CancelById("hey");
207  // Verify that delegate accumulated correct log of events.
208  EXPECT_EQ("Display_Close_programmatically_", delegate->log());
209  delegate->Release();
210}
211
212// MessaceCenter-specific test.
213#if defined(RUN_MESSAGE_CENTER_TESTS)
214#define MAYBE_ButtonClickedDelegate ButtonClickedDelegate
215#else
216#define MAYBE_ButtonClickedDelegate DISABLED_ButtonClickedDelegate
217#endif
218
219IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest,
220                       MAYBE_ButtonClickedDelegate) {
221#if defined(OS_WIN) && defined(USE_ASH)
222  // Disable this test in Metro+Ash for now (http://crbug.com/262796).
223  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
224    return;
225#endif
226
227  EXPECT_TRUE(NotificationUIManager::DelegatesToMessageCenter());
228  TestDelegate* delegate;
229  manager()->Add(CreateTestNotification("n", &delegate), profile());
230  message_center()->ClickOnNotificationButton("n", 1);
231  // Verify that delegate accumulated correct log of events.
232  EXPECT_EQ("Display_ButtonClick_1_", delegate->log());
233  delegate->Release();
234}
235
236// MessaceCenter-specific test.
237#if defined(RUN_MESSAGE_CENTER_TESTS)
238#define MAYBE_UpdateExistingNotification UpdateExistingNotification
239#else
240#define MAYBE_UpdateExistingNotification DISABLED_UpdateExistingNotification
241#endif
242
243IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest,
244                       MAYBE_UpdateExistingNotification) {
245#if defined(OS_WIN) && defined(USE_ASH)
246  // Disable this test in Metro+Ash for now (http://crbug.com/262796).
247  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
248    return;
249#endif
250
251  EXPECT_TRUE(NotificationUIManager::DelegatesToMessageCenter());
252  TestDelegate* delegate;
253  manager()->Add(CreateTestNotification("n", &delegate), profile());
254  TestDelegate* delegate2;
255  manager()->Add(CreateRichTestNotification("n", &delegate2), profile());
256
257  manager()->CancelById("n");
258  EXPECT_EQ("Display_", delegate->log());
259  EXPECT_EQ("Close_programmatically_", delegate2->log());
260
261  delegate->Release();
262  delegate2->Release();
263}
264
265// MessaceCenter-specific test.
266#if defined(RUN_MESSAGE_CENTER_TESTS)
267#define MAYBE_QueueWhenCenterVisible QueueWhenCenterVisible
268#else
269#define MAYBE_QueueWhenCenterVisible DISABLED_QueueWhenCenterVisible
270#endif
271
272IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest,
273                       MAYBE_QueueWhenCenterVisible) {
274#if defined(OS_WIN) && defined(USE_ASH)
275  // Disable this test in Metro+Ash for now (http://crbug.com/262796).
276  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
277    return;
278#endif
279
280  EXPECT_TRUE(NotificationUIManager::DelegatesToMessageCenter());
281  TestAddObserver observer(message_center());
282
283  TestDelegate* delegate;
284  TestDelegate* delegate2;
285
286  manager()->Add(CreateTestNotification("n", &delegate), profile());
287  message_center()->SetVisibility(message_center::VISIBILITY_MESSAGE_CENTER);
288  manager()->Add(CreateTestNotification("n2", &delegate2), profile());
289
290  // 'update-n' should happen since SetVisibility updates is_read status of n.
291  // TODO(mukai): fix event handling to happen update-n just once.
292  EXPECT_EQ("add-n_update-n_update-n", observer.log());
293
294  message_center()->SetVisibility(message_center::VISIBILITY_TRANSIENT);
295
296  EXPECT_EQ("add-n_update-n_update-n_add-n2", observer.log());
297
298  delegate->Release();
299  delegate2->Release();
300}
301
302// MessaceCenter-specific test.
303#if defined(RUN_MESSAGE_CENTER_TESTS)
304#define MAYBE_UpdateNonProgressNotificationWhenCenterVisible \
305    UpdateNonProgressNotificationWhenCenterVisible
306#else
307#define MAYBE_UpdateNonProgressNotificationWhenCenterVisible \
308    DISABLED_UpdateNonProgressNotificationWhenCenterVisible
309#endif
310
311IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest,
312                       MAYBE_UpdateNonProgressNotificationWhenCenterVisible) {
313#if defined(OS_WIN) && defined(USE_ASH)
314  // Disable this test in Metro+Ash for now (http://crbug.com/262796).
315  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
316    return;
317#endif
318
319  EXPECT_TRUE(NotificationUIManager::DelegatesToMessageCenter());
320  TestAddObserver observer(message_center());
321
322  TestDelegate* delegate;
323
324  // Add a non-progress notification and update it while the message center
325  // is visible.
326  Notification notification = CreateTestNotification("n", &delegate);
327  manager()->Add(notification, profile());
328  message_center()->ClickOnNotification("n");
329  message_center()->SetVisibility(message_center::VISIBILITY_MESSAGE_CENTER);
330  observer.reset_log();
331  notification.set_title(ASCIIToUTF16("title2"));
332  manager()->Update(notification, profile());
333
334  // Expect that the notification update is not done.
335  EXPECT_EQ("", observer.log());
336
337  message_center()->SetVisibility(message_center::VISIBILITY_TRANSIENT);
338  EXPECT_EQ("update-n", observer.log());
339
340  delegate->Release();
341}
342
343// MessaceCenter-specific test.
344#if defined(RUN_MESSAGE_CENTER_TESTS)
345#define MAYBE_UpdateNonProgressToProgressNotificationWhenCenterVisible \
346    UpdateNonProgressToProgressNotificationWhenCenterVisible
347#else
348#define MAYBE_UpdateNonProgressToProgressNotificationWhenCenterVisible \
349    DISABLED_UpdateNonProgressToProgressNotificationWhenCenterVisible
350#endif
351
352IN_PROC_BROWSER_TEST_F(
353    MessageCenterNotificationsTest,
354    MAYBE_UpdateNonProgressToProgressNotificationWhenCenterVisible) {
355#if defined(OS_WIN) && defined(USE_ASH)
356  // Disable this test in Metro+Ash for now (http://crbug.com/262796).
357  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
358    return;
359#endif
360
361  EXPECT_TRUE(NotificationUIManager::DelegatesToMessageCenter());
362  TestAddObserver observer(message_center());
363
364  TestDelegate* delegate;
365
366  // Add a non-progress notification and change the type to progress while the
367  // message center is visible.
368  Notification notification = CreateTestNotification("n", &delegate);
369  manager()->Add(notification, profile());
370  message_center()->ClickOnNotification("n");
371  message_center()->SetVisibility(message_center::VISIBILITY_MESSAGE_CENTER);
372  observer.reset_log();
373  notification.set_type(message_center::NOTIFICATION_TYPE_PROGRESS);
374  manager()->Update(notification, profile());
375
376  // Expect that the notification update is not done.
377  EXPECT_EQ("", observer.log());
378
379  message_center()->SetVisibility(message_center::VISIBILITY_TRANSIENT);
380  EXPECT_EQ("update-n", observer.log());
381
382  delegate->Release();
383}
384
385// MessaceCenter-specific test.
386#if defined(RUN_MESSAGE_CENTER_TESTS)
387#define MAYBE_UpdateProgressNotificationWhenCenterVisible \
388    UpdateProgressNotificationWhenCenterVisible
389#else
390#define MAYBE_UpdateProgressNotificationWhenCenterVisible \
391    DISABLED_UpdateProgressNotificationWhenCenterVisible
392#endif
393
394IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest,
395                       MAYBE_UpdateProgressNotificationWhenCenterVisible) {
396#if defined(OS_WIN) && defined(USE_ASH)
397  // Disable this test in Metro+Ash for now (http://crbug.com/262796).
398  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
399    return;
400#endif
401
402  EXPECT_TRUE(NotificationUIManager::DelegatesToMessageCenter());
403  TestAddObserver observer(message_center());
404
405  TestDelegate* delegate;
406
407  // Add a progress notification and update it while the message center
408  // is visible.
409  Notification notification = CreateTestNotification("n", &delegate);
410  notification.set_type(message_center::NOTIFICATION_TYPE_PROGRESS);
411  manager()->Add(notification, profile());
412  message_center()->ClickOnNotification("n");
413  message_center()->SetVisibility(message_center::VISIBILITY_MESSAGE_CENTER);
414  observer.reset_log();
415  notification.set_progress(50);
416  manager()->Update(notification, profile());
417
418  // Expect that the progress notification update is performed.
419  EXPECT_EQ("update-n", observer.log());
420
421  delegate->Release();
422}
423
424#if !defined(OS_CHROMEOS) && defined(RUN_MESSAGE_CENTER_TESTS)
425#define MAYBE_HideWhenFullscreenEnabled HideWhenFullscreenEnabled
426#else
427#define MAYBE_HideWhenFullscreenEnabled DISABLED_HideWhenFullscreenEnabled
428#endif
429
430IN_PROC_BROWSER_TEST_F(MessageCenterNotificationsTest,
431                       MAYBE_HideWhenFullscreenEnabled) {
432  EXPECT_TRUE(NotificationUIManager::DelegatesToMessageCenter());
433
434  TestDelegate* delegate;
435  manager()->Add(CreateTestNotification("n", &delegate), profile());
436
437  EXPECT_EQ("Display_", delegate->log());
438  EXPECT_TRUE(message_center()->HasPopupNotifications());
439  bool is_fullscreen = true;
440  // Cast so that Observe() is public.
441  content::NotificationObserver* observer =
442      static_cast<content::NotificationObserver*>(manager());
443  observer->Observe(chrome::NOTIFICATION_FULLSCREEN_CHANGED,
444                    content::Source<Profile>(profile()),
445                    content::Details<bool>(&is_fullscreen));
446  EXPECT_FALSE(message_center()->HasPopupNotifications());
447}
448
449#endif  // !defined(OS_MACOSX)
450