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/ui/views/message_center/web_notification_tray.h"
6
7#include <set>
8
9#include "ash/root_window_controller.h"
10#include "ash/system/status_area_widget.h"
11#include "ash/system/tray/system_tray_item.h"
12#include "base/strings/stringprintf.h"
13#include "base/strings/utf_string_conversions.h"
14#include "chrome/browser/browser_process.h"
15#include "chrome/browser/notifications/notification.h"
16#include "chrome/browser/notifications/notification_delegate.h"
17#include "chrome/browser/notifications/notification_ui_manager.h"
18#include "chrome/browser/ui/browser.h"
19#include "chrome/test/base/in_process_browser_test.h"
20#include "content/public/test/test_utils.h"
21#include "ui/message_center/message_center_style.h"
22#include "ui/message_center/message_center_tray.h"
23#include "ui/message_center/notification_list.h"
24#include "ui/message_center/notification_types.h"
25#include "ui/message_center/views/message_center_bubble.h"
26#include "ui/message_center/views/message_popup_collection.h"
27#include "ui/views/controls/label.h"
28#include "ui/views/layout/fill_layout.h"
29#include "ui/views/view.h"
30#include "ui/views/widget/widget.h"
31
32namespace message_center {
33
34namespace {
35
36class WebNotificationTrayTest : public InProcessBrowserTest {
37 public:
38  WebNotificationTrayTest() {}
39  virtual ~WebNotificationTrayTest() {}
40
41  virtual void CleanUpOnMainThread() OVERRIDE {
42    message_center::MessageCenter::Get()->RemoveAllNotifications(false);
43  }
44
45 protected:
46  class TestNotificationDelegate : public ::NotificationDelegate {
47   public:
48    explicit TestNotificationDelegate(std::string id) : id_(id) {}
49    virtual void Display() OVERRIDE {}
50    virtual void Error() OVERRIDE {}
51    virtual void Close(bool by_user) OVERRIDE {}
52    virtual void Click() OVERRIDE {}
53    virtual std::string id() const OVERRIDE { return id_; }
54    virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE {
55      return NULL;
56    }
57
58   private:
59    virtual ~TestNotificationDelegate() {}
60
61    std::string id_;
62  };
63
64  void AddNotification(const std::string& id, const std::string& replace_id) {
65    ::Notification notification(GURL("chrome-extension://abbccedd"),
66                                GURL(),
67                                ASCIIToUTF16("Test Web Notification"),
68                                ASCIIToUTF16("Notification message body."),
69                                blink::WebTextDirectionDefault,
70                                base::string16(),
71                                ASCIIToUTF16(replace_id),
72                                new TestNotificationDelegate(id));
73
74    g_browser_process->notification_ui_manager()->Add(
75     notification, browser()->profile());
76  }
77
78  void UpdateNotification(const std::string& replace_id,
79                          const std::string& new_id) {
80    ::Notification notification(GURL("chrome-extension://abbccedd"),
81                                GURL(""),
82                                ASCIIToUTF16("Updated Web Notification"),
83                                ASCIIToUTF16("Updated message body."),
84                                blink::WebTextDirectionDefault,
85                                base::string16(),
86                                ASCIIToUTF16(replace_id),
87                                new TestNotificationDelegate(new_id));
88
89    g_browser_process->notification_ui_manager()->Add(
90     notification, browser()->profile());
91  }
92
93  void RemoveNotification(const std::string& id) {
94    g_browser_process->notification_ui_manager()->CancelById(id);
95  }
96
97 private:
98  DISALLOW_COPY_AND_ASSIGN(WebNotificationTrayTest);
99};
100
101}  // namespace
102
103
104#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)
105// TODO(erg): linux_aura bringup: http://crbug.com/163931
106#define MAYBE_WebNotifications DISABLED_WebNotifications
107#else
108#define MAYBE_WebNotifications WebNotifications
109#endif
110
111// TODO(dewittj): More exhaustive testing.
112IN_PROC_BROWSER_TEST_F(WebNotificationTrayTest, MAYBE_WebNotifications) {
113  message_center::MessageCenter* message_center =
114      message_center::MessageCenter::Get();
115
116  // Add a notification.
117  AddNotification("test_id1", "replace_id1");
118  EXPECT_EQ(1u, message_center->NotificationCount());
119  EXPECT_TRUE(message_center->HasNotification("test_id1"));
120  EXPECT_FALSE(message_center->HasNotification("test_id2"));
121  AddNotification("test_id2", "replace_id2");
122  AddNotification("test_id2", "replace_id2");
123  EXPECT_EQ(2u, message_center->NotificationCount());
124  EXPECT_TRUE(message_center->HasNotification("test_id2"));
125
126  // Ensure that updating a notification does not affect the count.
127  UpdateNotification("replace_id2", "test_id3");
128  UpdateNotification("replace_id2", "test_id3");
129  EXPECT_EQ(2u, message_center->NotificationCount());
130  EXPECT_FALSE(message_center->HasNotification("test_id2"));
131
132  // Ensure that Removing the first notification removes it from the tray.
133  RemoveNotification("test_id1");
134  EXPECT_FALSE(message_center->HasNotification("test_id1"));
135  EXPECT_EQ(1u, message_center->NotificationCount());
136
137  // Remove the remaining notification.
138  RemoveNotification("test_id3");
139  EXPECT_EQ(0u, message_center->NotificationCount());
140  EXPECT_FALSE(message_center->HasNotification("test_id3"));
141}
142
143IN_PROC_BROWSER_TEST_F(WebNotificationTrayTest, WebNotificationPopupBubble) {
144  scoped_ptr<WebNotificationTray> tray(new WebNotificationTray());
145  tray->message_center();
146
147  // Adding a notification should show the popup bubble.
148  AddNotification("test_id1", "replace_id1");
149  EXPECT_TRUE(tray->message_center_tray_->popups_visible());
150
151  // Updating a notification should not hide the popup bubble.
152  AddNotification("test_id2", "replace_id2");
153  UpdateNotification("replace_id2", "test_id3");
154  EXPECT_TRUE(tray->message_center_tray_->popups_visible());
155
156  // Removing the first notification should not hide the popup bubble.
157  RemoveNotification("test_id1");
158  EXPECT_TRUE(tray->message_center_tray_->popups_visible());
159
160  // Removing the visible notification should hide the popup bubble.
161  RemoveNotification("test_id3");
162  EXPECT_FALSE(tray->message_center_tray_->popups_visible());
163}
164
165using message_center::NotificationList;
166
167// Flaky, see http://crbug.com/222500 .
168IN_PROC_BROWSER_TEST_F(WebNotificationTrayTest,
169                       DISABLED_ManyMessageCenterNotifications) {
170  scoped_ptr<WebNotificationTray> tray(new WebNotificationTray());
171  message_center::MessageCenter* message_center = tray->message_center();
172
173  // Add the max visible notifications +1, ensure the correct visible number.
174  size_t notifications_to_add = kMaxVisibleMessageCenterNotifications + 1;
175  for (size_t i = 0; i < notifications_to_add; ++i) {
176    std::string id = base::StringPrintf("test_id%d", static_cast<int>(i));
177    std::string replace_id =
178        base::StringPrintf("replace_id%d", static_cast<int>(i));
179    AddNotification(id, replace_id);
180  }
181  bool shown = tray->message_center_tray_->ShowMessageCenterBubble();
182  EXPECT_TRUE(shown);
183  content::RunAllPendingInMessageLoop();
184  EXPECT_TRUE(tray->message_center_delegate_ != NULL);
185  EXPECT_EQ(notifications_to_add, message_center->NotificationCount());
186  EXPECT_EQ(kMaxVisibleMessageCenterNotifications,
187            tray->message_center_delegate_->NumMessageViewsForTest());
188}
189
190#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)
191// TODO(erg): linux_aura bringup: http://crbug.com/163931
192#define MAYBE_ManyPopupNotifications DISABLED_ManyPopupNotifications
193#else
194#define MAYBE_ManyPopupNotifications ManyPopupNotifications
195#endif
196
197IN_PROC_BROWSER_TEST_F(WebNotificationTrayTest, MAYBE_ManyPopupNotifications) {
198  scoped_ptr<WebNotificationTray> tray(new WebNotificationTray());
199  message_center::MessageCenter* message_center = tray->message_center();
200
201  // Add the max visible popup notifications +1, ensure the correct num visible.
202  size_t notifications_to_add = kMaxVisiblePopupNotifications + 1;
203  for (size_t i = 0; i < notifications_to_add; ++i) {
204    std::string id = base::StringPrintf("test_id%d", static_cast<int>(i));
205    std::string replace_id =
206        base::StringPrintf("replace_id%d", static_cast<int>(i));
207    AddNotification(id, replace_id);
208  }
209  // Hide and reshow the bubble so that it is updated immediately, not delayed.
210  tray->message_center_tray_->HidePopupBubble();
211  tray->message_center_tray_->ShowPopupBubble();
212  EXPECT_TRUE(tray->message_center_tray_->popups_visible());
213  EXPECT_EQ(notifications_to_add, message_center->NotificationCount());
214  NotificationList::PopupNotifications popups =
215      message_center->GetPopupNotifications();
216  EXPECT_EQ(kMaxVisiblePopupNotifications, popups.size());
217}
218
219}  // namespace message_center
220