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