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/message_center_notification_manager.h"
16 #include "chrome/browser/notifications/notification.h"
17 #include "chrome/browser/notifications/notification_delegate.h"
18 #include "chrome/browser/notifications/notification_ui_manager.h"
19 #include "chrome/browser/ui/browser.h"
20 #include "chrome/test/base/in_process_browser_test.h"
21 #include "content/public/test/test_utils.h"
22 #include "ui/message_center/message_center_style.h"
23 #include "ui/message_center/message_center_tray.h"
24 #include "ui/message_center/notification_list.h"
25 #include "ui/message_center/notification_types.h"
26 #include "ui/message_center/views/message_center_bubble.h"
27 #include "ui/message_center/views/message_popup_collection.h"
28 #include "ui/views/controls/label.h"
29 #include "ui/views/layout/fill_layout.h"
30 #include "ui/views/view.h"
31 #include "ui/views/widget/widget.h"
32
33 namespace message_center {
34
35 namespace {
36
37 class WebNotificationTrayTest : public InProcessBrowserTest {
38 public:
WebNotificationTrayTest()39 WebNotificationTrayTest() {}
~WebNotificationTrayTest()40 virtual ~WebNotificationTrayTest() {}
41
CleanUpOnMainThread()42 virtual void CleanUpOnMainThread() OVERRIDE {
43 message_center::MessageCenter::Get()->RemoveAllNotifications(false);
44 }
45
46 protected:
47 class TestNotificationDelegate : public ::NotificationDelegate {
48 public:
TestNotificationDelegate(std::string id)49 explicit TestNotificationDelegate(std::string id) : id_(id) {}
Display()50 virtual void Display() OVERRIDE {}
Error()51 virtual void Error() OVERRIDE {}
Close(bool by_user)52 virtual void Close(bool by_user) OVERRIDE {}
Click()53 virtual void Click() OVERRIDE {}
id() const54 virtual std::string id() const OVERRIDE { return id_; }
GetWebContents() const55 virtual content::WebContents* GetWebContents() const OVERRIDE {
56 return NULL;
57 }
58
59 private:
~TestNotificationDelegate()60 virtual ~TestNotificationDelegate() {}
61
62 std::string id_;
63 };
64
AddNotification(const std::string & id,const std::string & replace_id)65 void AddNotification(const std::string& id, const std::string& replace_id) {
66 ::Notification notification(GURL("chrome-extension://abbccedd"),
67 GURL(),
68 base::ASCIIToUTF16("Test Web Notification"),
69 base::ASCIIToUTF16(
70 "Notification message body."),
71 blink::WebTextDirectionDefault,
72 base::string16(),
73 base::ASCIIToUTF16(replace_id),
74 new TestNotificationDelegate(id));
75
76 g_browser_process->notification_ui_manager()->Add(
77 notification, browser()->profile());
78 }
79
UpdateNotification(const std::string & replace_id,const std::string & new_id)80 void UpdateNotification(const std::string& replace_id,
81 const std::string& new_id) {
82 ::Notification notification(GURL("chrome-extension://abbccedd"),
83 GURL(""),
84 base::ASCIIToUTF16("Updated Web Notification"),
85 base::ASCIIToUTF16("Updated message body."),
86 blink::WebTextDirectionDefault,
87 base::string16(),
88 base::ASCIIToUTF16(replace_id),
89 new TestNotificationDelegate(new_id));
90
91 g_browser_process->notification_ui_manager()->Add(
92 notification, browser()->profile());
93 }
94
RemoveNotification(const std::string & id)95 void RemoveNotification(const std::string& id) {
96 g_browser_process->notification_ui_manager()->CancelById(id);
97 }
98
HasNotification(message_center::MessageCenter * message_center,const std::string & id)99 bool HasNotification(message_center::MessageCenter* message_center,
100 const std::string& id) {
101 return message_center->FindVisibleNotificationById(id) != NULL;
102 }
103
104 private:
105 DISALLOW_COPY_AND_ASSIGN(WebNotificationTrayTest);
106 };
107
108 } // namespace
109
110
111 // TODO(dewittj): More exhaustive testing.
IN_PROC_BROWSER_TEST_F(WebNotificationTrayTest,WebNotifications)112 IN_PROC_BROWSER_TEST_F(WebNotificationTrayTest, 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(HasNotification(message_center, "test_id1"));
120 EXPECT_FALSE(HasNotification(message_center, "test_id2"));
121 AddNotification("test_id2", "replace_id2");
122 AddNotification("test_id2", "replace_id2");
123 EXPECT_EQ(2u, message_center->NotificationCount());
124 EXPECT_TRUE(HasNotification(message_center, "test_id1"));
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(HasNotification(message_center, "test_id2"));
131
132 // Ensure that Removing the first notification removes it from the tray.
133 RemoveNotification("test_id1");
134 EXPECT_FALSE(HasNotification(message_center, "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(HasNotification(message_center, "test_id1"));
141 }
142
IN_PROC_BROWSER_TEST_F(WebNotificationTrayTest,WebNotificationPopupBubble)143 IN_PROC_BROWSER_TEST_F(WebNotificationTrayTest, WebNotificationPopupBubble) {
144 scoped_ptr<WebNotificationTray> tray(new WebNotificationTray(NULL));
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
165 using message_center::NotificationList;
166
167 // Flaky, see http://crbug.com/222500 .
IN_PROC_BROWSER_TEST_F(WebNotificationTrayTest,DISABLED_ManyMessageCenterNotifications)168 IN_PROC_BROWSER_TEST_F(WebNotificationTrayTest,
169 DISABLED_ManyMessageCenterNotifications) {
170 scoped_ptr<WebNotificationTray> tray(new WebNotificationTray(NULL));
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
IN_PROC_BROWSER_TEST_F(WebNotificationTrayTest,ManyPopupNotifications)190 IN_PROC_BROWSER_TEST_F(WebNotificationTrayTest, ManyPopupNotifications) {
191 scoped_ptr<WebNotificationTray> tray(new WebNotificationTray(NULL));
192 message_center::MessageCenter* message_center = tray->message_center();
193
194 // Add the max visible popup notifications +1, ensure the correct num visible.
195 size_t notifications_to_add = kMaxVisiblePopupNotifications + 1;
196 for (size_t i = 0; i < notifications_to_add; ++i) {
197 std::string id = base::StringPrintf("test_id%d", static_cast<int>(i));
198 std::string replace_id =
199 base::StringPrintf("replace_id%d", static_cast<int>(i));
200 AddNotification(id, replace_id);
201 }
202 // Hide and reshow the bubble so that it is updated immediately, not delayed.
203 tray->message_center_tray_->HidePopupBubble();
204 tray->message_center_tray_->ShowPopupBubble();
205 EXPECT_TRUE(tray->message_center_tray_->popups_visible());
206 EXPECT_EQ(notifications_to_add, message_center->NotificationCount());
207 NotificationList::PopupNotifications popups =
208 message_center->GetPopupNotifications();
209 EXPECT_EQ(kMaxVisiblePopupNotifications, popups.size());
210 }
211
IN_PROC_BROWSER_TEST_F(WebNotificationTrayTest,ManuallyCloseMessageCenter)212 IN_PROC_BROWSER_TEST_F(WebNotificationTrayTest,
213 ManuallyCloseMessageCenter) {
214 NotificationUIManager* manager = g_browser_process->notification_ui_manager();
215 MessageCenterNotificationManager* mc_manager =
216 static_cast<MessageCenterNotificationManager*>(manager);
217
218 WebNotificationTray* tray =
219 static_cast<WebNotificationTray*>(mc_manager->tray_.get());
220 ASSERT_TRUE(NULL != tray);
221
222 message_center::MessageCenter* message_center = tray->message_center();
223
224 bool shown = tray->message_center_tray_->ShowMessageCenterBubble();
225 EXPECT_TRUE(shown);
226 EXPECT_TRUE(message_center->IsMessageCenterVisible());
227
228 mc_manager->EnsureMessageCenterClosed();
229
230 EXPECT_FALSE(message_center->IsMessageCenterVisible());
231 if (NULL != tray->message_center_delegate_)
232 EXPECT_TRUE(tray->message_center_delegate_->GetWidget()->IsClosed());
233 }
234
235 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
236 #define MAYBE_StatusIconBehavior DISABLED_StatusIconBehavior
237 #else
238 #define MAYBE_StatusIconBehavior StatusIconBehavior
239 #endif
IN_PROC_BROWSER_TEST_F(WebNotificationTrayTest,MAYBE_StatusIconBehavior)240 IN_PROC_BROWSER_TEST_F(WebNotificationTrayTest, MAYBE_StatusIconBehavior) {
241 scoped_ptr<WebNotificationTray> tray(new WebNotificationTray(NULL));
242
243 EXPECT_TRUE(tray->status_icon_ == NULL);
244 tray->OnMessageCenterTrayChanged();
245 base::RunLoop().RunUntilIdle();
246 EXPECT_TRUE(tray->status_icon_ == NULL);
247 AddNotification("test_id", "replace_id");
248 base::RunLoop().RunUntilIdle();
249 EXPECT_TRUE(tray->status_icon_ != NULL);
250 RemoveNotification("test_id");
251 base::RunLoop().RunUntilIdle();
252 EXPECT_TRUE(tray->status_icon_ != NULL);
253 }
254 } // namespace message_center
255