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: 39 WebNotificationTrayTest() {} 40 virtual ~WebNotificationTrayTest() {} 41 42 virtual void CleanUpOnMainThread() OVERRIDE { 43 message_center::MessageCenter::Get()->RemoveAllNotifications(false); 44 } 45 46 protected: 47 class TestNotificationDelegate : public ::NotificationDelegate { 48 public: 49 explicit TestNotificationDelegate(std::string id) : id_(id) {} 50 virtual void Display() OVERRIDE {} 51 virtual void Error() OVERRIDE {} 52 virtual void Close(bool by_user) OVERRIDE {} 53 virtual void Click() OVERRIDE {} 54 virtual std::string id() const OVERRIDE { return id_; } 55 virtual content::WebContents* GetWebContents() const OVERRIDE { 56 return NULL; 57 } 58 59 private: 60 virtual ~TestNotificationDelegate() {} 61 62 std::string id_; 63 }; 64 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 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 95 void RemoveNotification(const std::string& id) { 96 g_browser_process->notification_ui_manager()->CancelById(id); 97 } 98 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. 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 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 . 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 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 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 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