1 // Copyright (c) 2011 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 "base/memory/ref_counted.h" 6 #include "base/memory/scoped_ptr.h" 7 #include "base/message_loop.h" 8 #include "base/string16.h" 9 #include "base/string_util.h" 10 #include "base/stringprintf.h" 11 #include "base/utf_string_conversions.h" 12 #include "chrome/browser/browser_process.h" 13 #include "chrome/browser/chromeos/notifications/balloon_collection_impl.h" 14 #include "chrome/browser/chromeos/notifications/balloon_view.h" 15 #include "chrome/browser/chromeos/notifications/notification_panel.h" 16 #include "chrome/browser/chromeos/notifications/system_notification_factory.h" 17 #include "chrome/browser/notifications/notification_test_util.h" 18 #include "chrome/browser/notifications/notification_ui_manager.h" 19 #include "chrome/browser/ui/browser.h" 20 #include "chrome/test/in_process_browser_test.h" 21 #include "chrome/test/ui_test_utils.h" 22 #include "content/common/notification_service.h" 23 #include "ui/base/x/x11_util.h" 24 25 namespace { 26 27 // The name of ChromeOS's window manager. 28 const char* kChromeOsWindowManagerName = "chromeos-wm"; 29 30 } // namespace 31 32 namespace chromeos { 33 34 class NotificationTest : public InProcessBrowserTest, 35 public NotificationObserver { 36 public: 37 NotificationTest() 38 : under_chromeos_(false), 39 state_(PanelController::INITIAL), 40 expected_(PanelController::INITIAL) { 41 } 42 43 void HandleWebUIMessage(const ListValue* value) { 44 MessageLoop::current()->Quit(); 45 } 46 47 protected: 48 virtual void SetUp() { 49 // Detect if we're running under ChromeOS WindowManager. See 50 // the description for "under_chromeos_" below for why we need this. 51 std::string wm_name; 52 bool wm_name_valid = ui::GetWindowManagerName(&wm_name); 53 // NOTE: On Chrome OS the wm and Chrome are started in parallel. This 54 // means it's possible for us not to be able to get the name of the window 55 // manager. We assume that when this happens we're on Chrome OS. 56 under_chromeos_ = (!wm_name_valid || 57 wm_name == kChromeOsWindowManagerName); 58 InProcessBrowserTest::SetUp(); 59 } 60 61 BalloonCollectionImpl* GetBalloonCollectionImpl() { 62 return static_cast<BalloonCollectionImpl*>( 63 g_browser_process->notification_ui_manager()->balloon_collection()); 64 } 65 66 NotificationPanel* GetNotificationPanel() { 67 return static_cast<NotificationPanel*>( 68 GetBalloonCollectionImpl()->notification_ui()); 69 } 70 71 Notification NewMockNotification(const std::string& id) { 72 return NewMockNotification(new MockNotificationDelegate(id)); 73 } 74 75 Notification NewMockNotification(NotificationDelegate* delegate) { 76 std::string text = delegate->id(); 77 return SystemNotificationFactory::Create( 78 GURL(), ASCIIToUTF16(text.c_str()), ASCIIToUTF16(text.c_str()), 79 delegate); 80 } 81 82 void MarkStale(const char* id) { 83 GetNotificationPanel()->GetTester()->MarkStale(NewMockNotification(id)); 84 } 85 86 // Waits untilt the panel's state becomes the specified state. 87 // Does nothing if it's not running with ChromeOS Window Manager. 88 void WaitForPanelState(NotificationPanelTester* tester, 89 PanelController::State state) { 90 if (under_chromeos_ && state != state_) { 91 expected_ = state; 92 ui_test_utils::RunAllPendingInMessageLoop(); 93 } 94 } 95 96 // Busy loop to wait until the view becomes visible in the panel. 97 void WaitForVisible(BalloonViewImpl* view) { 98 WaitForResize(view); 99 NotificationPanelTester* tester = GetNotificationPanel()->GetTester(); 100 while (!tester->IsVisible(view)) { 101 ui_test_utils::RunAllPendingInMessageLoop(); 102 } 103 } 104 105 // Busy loop to wait until the webkit give some size to the notification. 106 void WaitForResize(BalloonViewImpl* view) { 107 while (view->bounds().IsEmpty()) { 108 ui_test_utils::RunAllPendingInMessageLoop(); 109 } 110 } 111 112 // NotificationObserver overrides. 113 virtual void Observe(NotificationType type, 114 const NotificationSource& source, 115 const NotificationDetails& details) { 116 ASSERT_TRUE(NotificationType::PANEL_STATE_CHANGED == type); 117 PanelController::State* state = 118 reinterpret_cast<PanelController::State*>(details.map_key()); 119 state_ = *state; 120 if (under_chromeos_ && expected_ == state_) { 121 expected_ = PanelController::INITIAL; 122 MessageLoop::current()->Quit(); 123 } 124 } 125 126 private: 127 // ChromeOS build of chrome communicates with ChromeOS's 128 // WindowManager, and behaves differently if it runs under a 129 // chromeos window manager. ChromeOS WindowManager sends 130 // EXPANDED/MINIMIED state change message when the panels's state 131 // changed (regardless of who changed it), and to avoid 132 // mis-recognizing such events as user-initiated actions, we need to 133 // wait and eat them before moving to a next step. 134 bool under_chromeos_; 135 PanelController::State state_; 136 PanelController::State expected_; 137 }; 138 139 IN_PROC_BROWSER_TEST_F(NotificationTest, TestBasic) { 140 BalloonCollectionImpl* collection = GetBalloonCollectionImpl(); 141 NotificationPanel* panel = GetNotificationPanel(); 142 NotificationPanelTester* tester = panel->GetTester(); 143 144 // Using system notification as regular notification. 145 collection->Add(NewMockNotification("1"), browser()->profile()); 146 147 EXPECT_EQ(1, tester->GetNewNotificationCount()); 148 EXPECT_EQ(1, tester->GetNotificationCount()); 149 EXPECT_EQ(0, tester->GetStickyNotificationCount()); 150 EXPECT_EQ(NotificationPanel::STICKY_AND_NEW, tester->state()); 151 152 collection->Add(NewMockNotification("2"), browser()->profile()); 153 154 EXPECT_EQ(2, tester->GetNewNotificationCount()); 155 EXPECT_EQ(2, tester->GetNotificationCount()); 156 EXPECT_EQ(NotificationPanel::STICKY_AND_NEW, tester->state()); 157 158 collection->RemoveById("1"); 159 ui_test_utils::RunAllPendingInMessageLoop(); 160 161 EXPECT_EQ(1, tester->GetNewNotificationCount()); 162 EXPECT_EQ(1, tester->GetNotificationCount()); 163 EXPECT_EQ(NotificationPanel::STICKY_AND_NEW, tester->state()); 164 165 collection->RemoveById("2"); 166 ui_test_utils::RunAllPendingInMessageLoop(); 167 EXPECT_EQ(0, tester->GetNewNotificationCount()); 168 EXPECT_EQ(0, tester->GetNotificationCount()); 169 EXPECT_EQ(NotificationPanel::CLOSED, tester->state()); 170 171 // CLOSE is asynchronous. Run the all pending tasks to finish closing 172 // task. 173 ui_test_utils::RunAllPendingInMessageLoop(); 174 } 175 176 // [CLOSED] -add->[STICKY_AND_NEW] -mouse-> [KEEP_SIZE] -remove/add-> 177 // [KEEP_SIZE] -remove-> [CLOSED] -add-> [STICKY_AND_NEW] -remove-> [CLOSED] 178 IN_PROC_BROWSER_TEST_F(NotificationTest, TestKeepSizeState) { 179 BalloonCollectionImpl* collection = GetBalloonCollectionImpl(); 180 NotificationPanel* panel = GetNotificationPanel(); 181 NotificationPanelTester* tester = panel->GetTester(); 182 183 EXPECT_EQ(NotificationPanel::CLOSED, tester->state()); 184 185 // Using system notification as regular notification. 186 collection->Add(NewMockNotification("1"), browser()->profile()); 187 collection->Add(NewMockNotification("2"), browser()->profile()); 188 189 EXPECT_EQ(NotificationPanel::STICKY_AND_NEW, tester->state()); 190 191 panel->OnMouseMotion(gfx::Point(10, 10)); 192 EXPECT_EQ(NotificationPanel::KEEP_SIZE, tester->state()); 193 194 collection->RemoveById("1"); 195 ui_test_utils::RunAllPendingInMessageLoop(); 196 EXPECT_EQ(1, tester->GetNewNotificationCount()); 197 EXPECT_EQ(1, tester->GetNotificationCount()); 198 EXPECT_EQ(NotificationPanel::KEEP_SIZE, tester->state()); 199 200 collection->Add(NewMockNotification("1"), browser()->profile()); 201 ui_test_utils::RunAllPendingInMessageLoop(); 202 EXPECT_EQ(2, tester->GetNewNotificationCount()); 203 EXPECT_EQ(2, tester->GetNotificationCount()); 204 EXPECT_EQ(NotificationPanel::KEEP_SIZE, tester->state()); 205 206 collection->RemoveById("1"); 207 ui_test_utils::RunAllPendingInMessageLoop(); 208 EXPECT_EQ(1, tester->GetNewNotificationCount()); 209 EXPECT_EQ(1, tester->GetNotificationCount()); 210 EXPECT_EQ(NotificationPanel::KEEP_SIZE, tester->state()); 211 212 collection->RemoveById("2"); 213 ui_test_utils::RunAllPendingInMessageLoop(); 214 EXPECT_EQ(0, tester->GetNotificationCount()); 215 EXPECT_EQ(NotificationPanel::CLOSED, tester->state()); 216 217 collection->Add(NewMockNotification("3"), browser()->profile()); 218 EXPECT_EQ(NotificationPanel::STICKY_AND_NEW, tester->state()); 219 collection->RemoveById("3"); 220 221 ui_test_utils::RunAllPendingInMessageLoop(); 222 EXPECT_EQ(0, tester->GetNotificationCount()); 223 EXPECT_EQ(NotificationPanel::CLOSED, tester->state()); 224 } 225 226 IN_PROC_BROWSER_TEST_F(NotificationTest, TestSystemNotification) { 227 BalloonCollectionImpl* collection = GetBalloonCollectionImpl(); 228 NotificationPanel* panel = GetNotificationPanel(); 229 scoped_refptr<MockNotificationDelegate> delegate( 230 new MockNotificationDelegate("power")); 231 NotificationPanelTester* tester = panel->GetTester(); 232 233 Notification notify = NewMockNotification(delegate.get()); 234 collection->AddSystemNotification(notify, browser()->profile(), true, false); 235 236 EXPECT_EQ(1, tester->GetNewNotificationCount()); 237 EXPECT_EQ(1, tester->GetStickyNotificationCount()); 238 239 Notification update = SystemNotificationFactory::Create( 240 GURL(), ASCIIToUTF16("Title"), ASCIIToUTF16("updated"), delegate.get()); 241 collection->UpdateNotification(update); 242 243 EXPECT_EQ(1, tester->GetStickyNotificationCount()); 244 245 Notification update_and_show = SystemNotificationFactory::Create( 246 GURL(), ASCIIToUTF16("Title"), ASCIIToUTF16("updated and shown"), 247 delegate.get()); 248 collection->UpdateAndShowNotification(update_and_show); 249 250 EXPECT_EQ(1, tester->GetStickyNotificationCount()); 251 252 // Dismiss the notification. 253 collection->RemoveById(delegate->id()); 254 ui_test_utils::RunAllPendingInMessageLoop(); 255 256 EXPECT_EQ(0, tester->GetStickyNotificationCount()); 257 EXPECT_EQ(0, tester->GetNewNotificationCount()); 258 // TODO(oshima): check content, etc.. 259 } 260 261 // [CLOSED] -add,add->[STICKY_AND_NEW] -stale-> [MINIMIZED] -remove-> 262 // [MINIMIZED] -remove-> [CLOSED] 263 IN_PROC_BROWSER_TEST_F(NotificationTest, TestStateTransition1) { 264 BalloonCollectionImpl* collection = GetBalloonCollectionImpl(); 265 NotificationPanel* panel = GetNotificationPanel(); 266 NotificationPanelTester* tester = panel->GetTester(); 267 268 tester->SetStaleTimeout(0); 269 EXPECT_EQ(NotificationPanel::CLOSED, tester->state()); 270 271 collection->Add(NewMockNotification("1"), browser()->profile()); 272 EXPECT_EQ(NotificationPanel::STICKY_AND_NEW, tester->state()); 273 274 collection->Add(NewMockNotification("2"), browser()->profile()); 275 EXPECT_EQ(NotificationPanel::STICKY_AND_NEW, tester->state()); 276 277 ui_test_utils::RunAllPendingInMessageLoop(); 278 EXPECT_EQ(NotificationPanel::MINIMIZED, tester->state()); 279 280 collection->RemoveById("2"); 281 ui_test_utils::RunAllPendingInMessageLoop(); 282 EXPECT_EQ(NotificationPanel::MINIMIZED, tester->state()); 283 284 collection->RemoveById("1"); 285 ui_test_utils::RunAllPendingInMessageLoop(); 286 EXPECT_EQ(0, tester->GetNotificationCount()); 287 EXPECT_EQ(NotificationPanel::CLOSED, tester->state()); 288 289 ui_test_utils::RunAllPendingInMessageLoop(); 290 } 291 292 // [CLOSED] -add->[STICKY_AND_NEW] -stale-> [MINIMIZED] -add-> 293 // [STICKY_AND_NEW] -stale-> [MINIMIZED] -add sys-> [STICKY_NEW] 294 // -stale-> [STICKY_NEW] -remove-> [STICKY_NEW] -remove sys-> 295 // [MINIMIZED] -remove-> [CLOSED] 296 // 297 // This test depends on the fact that the panel state change occurs 298 // quicker than stale timeout, thus the stale timeout cannot be set to 299 // 0. This test explicitly controls the stale state instead. 300 IN_PROC_BROWSER_TEST_F(NotificationTest, TestStateTransition2) { 301 // Register observer here as the registration does not work in SetUp(). 302 NotificationRegistrar registrar; 303 registrar.Add(this, 304 NotificationType::PANEL_STATE_CHANGED, 305 NotificationService::AllSources()); 306 307 BalloonCollectionImpl* collection = GetBalloonCollectionImpl(); 308 NotificationPanel* panel = GetNotificationPanel(); 309 NotificationPanelTester* tester = panel->GetTester(); 310 311 // See description above. 312 tester->SetStaleTimeout(100000); 313 314 EXPECT_EQ(NotificationPanel::CLOSED, tester->state()); 315 316 collection->Add(NewMockNotification("1"), browser()->profile()); 317 EXPECT_EQ(NotificationPanel::STICKY_AND_NEW, tester->state()); 318 ui_test_utils::RunAllPendingInMessageLoop(); 319 320 // Make the notification stale and make sure panel is minimized state. 321 MarkStale("1"); 322 ui_test_utils::RunAllPendingInMessageLoop(); 323 EXPECT_EQ(NotificationPanel::MINIMIZED, tester->state()); 324 WaitForPanelState(tester, PanelController::MINIMIZED); 325 326 // Adding new notification expands the panel. 327 collection->Add(NewMockNotification("2"), browser()->profile()); 328 EXPECT_EQ(NotificationPanel::STICKY_AND_NEW, tester->state()); 329 WaitForPanelState(tester, PanelController::EXPANDED); 330 331 // The panel must be minimzied when the new notification becomes stale. 332 MarkStale("2"); 333 ui_test_utils::RunAllPendingInMessageLoop(); 334 EXPECT_EQ(NotificationPanel::MINIMIZED, tester->state()); 335 WaitForPanelState(tester, PanelController::MINIMIZED); 336 337 // The panel must be expanded again when a new system notification is added. 338 collection->AddSystemNotification( 339 NewMockNotification("3"), browser()->profile(), true, false); 340 EXPECT_EQ(3, tester->GetNotificationCount()); 341 EXPECT_EQ(NotificationPanel::STICKY_AND_NEW, tester->state()); 342 WaitForPanelState(tester, PanelController::EXPANDED); 343 344 // Running all events nor removing non sticky should not change the state. 345 ui_test_utils::RunAllPendingInMessageLoop(); 346 EXPECT_EQ(NotificationPanel::STICKY_AND_NEW, tester->state()); 347 348 collection->RemoveById("1"); 349 ui_test_utils::RunAllPendingInMessageLoop(); 350 EXPECT_EQ(NotificationPanel::STICKY_AND_NEW, tester->state()); 351 352 // Removing the system notification should minimize the panel. 353 collection->RemoveById("3"); 354 ui_test_utils::RunAllPendingInMessageLoop(); 355 EXPECT_EQ(1, tester->GetNotificationCount()); 356 EXPECT_EQ(NotificationPanel::MINIMIZED, tester->state()); 357 WaitForPanelState(tester, PanelController::MINIMIZED); 358 359 // Removing the last notification. Should close the panel. 360 collection->RemoveById("2"); 361 ui_test_utils::RunAllPendingInMessageLoop(); 362 EXPECT_EQ(0, tester->GetNotificationCount()); 363 EXPECT_EQ(NotificationPanel::CLOSED, tester->state()); 364 365 ui_test_utils::RunAllPendingInMessageLoop(); 366 } 367 368 IN_PROC_BROWSER_TEST_F(NotificationTest, TestCleanupOnExit) { 369 NotificationRegistrar registrar; 370 registrar.Add(this, 371 NotificationType::PANEL_STATE_CHANGED, 372 NotificationService::AllSources()); 373 374 BalloonCollectionImpl* collection = GetBalloonCollectionImpl(); 375 NotificationPanel* panel = GetNotificationPanel(); 376 NotificationPanelTester* tester = panel->GetTester(); 377 378 // Don't become stale. 379 tester->SetStaleTimeout(100000); 380 381 collection->Add(NewMockNotification("1"), browser()->profile()); 382 EXPECT_EQ(NotificationPanel::STICKY_AND_NEW, tester->state()); 383 WaitForPanelState(tester, PanelController::EXPANDED); 384 // end without closing. 385 } 386 387 IN_PROC_BROWSER_TEST_F(NotificationTest, TestCloseOpen) { 388 BalloonCollectionImpl* collection = GetBalloonCollectionImpl(); 389 NotificationPanel* panel = GetNotificationPanel(); 390 NotificationPanelTester* tester = panel->GetTester(); 391 Profile* profile = browser()->profile(); 392 393 collection->Add(NewMockNotification("1"), profile); 394 collection->Add(NewMockNotification("2"), profile); 395 ui_test_utils::RunAllPendingInMessageLoop(); 396 WaitForPanelState(tester, PanelController::EXPANDED); 397 PanelController* controller = tester->GetPanelController(); 398 // close now 399 panel->ClosePanel(); 400 controller->Close(); 401 ui_test_utils::RunAllPendingInMessageLoop(); 402 EXPECT_EQ(NotificationPanel::CLOSED, tester->state()); 403 // open again 404 collection->Add(NewMockNotification("3"), profile); 405 WaitForPanelState(tester, PanelController::EXPANDED); 406 EXPECT_EQ(NotificationPanel::STICKY_AND_NEW, tester->state()); 407 408 // close again 409 controller = tester->GetPanelController(); 410 panel->ClosePanel(); 411 controller->Close(); 412 ui_test_utils::RunAllPendingInMessageLoop(); 413 EXPECT_EQ(NotificationPanel::CLOSED, tester->state()); 414 } 415 416 IN_PROC_BROWSER_TEST_F(NotificationTest, TestScrollBalloonToVisible) { 417 BalloonCollectionImpl* collection = GetBalloonCollectionImpl(); 418 NotificationPanel* panel = GetNotificationPanel(); 419 NotificationPanelTester* tester = panel->GetTester(); 420 Profile* profile = browser()->profile(); 421 422 // Create notifications enough to overflow the panel size. 423 const int create_count = 15; 424 425 // new notification is always visible 426 for (int i = 0; i < create_count; i++) { 427 { 428 SCOPED_TRACE(base::StringPrintf("new normal %d", i)); 429 std::string id = base::StringPrintf("n%d", i); 430 collection->Add(NewMockNotification(id), profile); 431 EXPECT_EQ(NotificationPanel::STICKY_AND_NEW, tester->state()); 432 BalloonViewImpl* view = 433 tester->GetBalloonView(collection, NewMockNotification(id)); 434 WaitForVisible(view); 435 } 436 { 437 SCOPED_TRACE(base::StringPrintf("new system %d", i)); 438 std::string id = base::StringPrintf("s%d", i); 439 collection->AddSystemNotification( 440 NewMockNotification(id), browser()->profile(), true, false); 441 BalloonViewImpl* view = 442 tester->GetBalloonView(collection, NewMockNotification(id)); 443 WaitForVisible(view); 444 } 445 } 446 447 // Update should not change the visibility 448 for (int i = 0; i < create_count; i++) { 449 { 450 SCOPED_TRACE(base::StringPrintf("update n%d", i)); 451 Notification notify = NewMockNotification(base::StringPrintf("n%d", i)); 452 // The last shown notification is sticky, which makes all non sticky 453 // invisible. 454 EXPECT_TRUE(collection->UpdateNotification(notify)); 455 ui_test_utils::RunAllPendingInMessageLoop(); 456 BalloonViewImpl* view = tester->GetBalloonView(collection, notify); 457 EXPECT_FALSE(tester->IsVisible(view)); 458 } 459 { 460 SCOPED_TRACE(base::StringPrintf("update s%d", i)); 461 Notification notify = NewMockNotification(base::StringPrintf("s%d", i)); 462 BalloonViewImpl* view = tester->GetBalloonView(collection, notify); 463 bool currently_visible = tester->IsVisible(view); 464 EXPECT_TRUE(collection->UpdateNotification(notify)); 465 ui_test_utils::RunAllPendingInMessageLoop(); 466 EXPECT_EQ(view, tester->GetBalloonView(collection, notify)); 467 EXPECT_EQ(currently_visible, tester->IsVisible(view)); 468 } 469 } 470 // UpdateAndShowNotification makes notification visible 471 for (int i = 0; i < create_count; i++) { 472 { 473 SCOPED_TRACE(base::StringPrintf("update and show n%d", i)); 474 Notification notify = NewMockNotification(base::StringPrintf("n%d", i)); 475 EXPECT_TRUE(collection->UpdateAndShowNotification(notify)); 476 ui_test_utils::RunAllPendingInMessageLoop(); 477 BalloonViewImpl* view = tester->GetBalloonView(collection, notify); 478 EXPECT_TRUE(tester->IsVisible(view)); 479 } 480 { 481 SCOPED_TRACE(base::StringPrintf("update and show s%d", i)); 482 Notification notify = NewMockNotification(base::StringPrintf("s%d", i)); 483 EXPECT_TRUE(collection->UpdateAndShowNotification(notify)); 484 ui_test_utils::RunAllPendingInMessageLoop(); 485 BalloonViewImpl* view = tester->GetBalloonView(collection, notify); 486 EXPECT_TRUE(tester->IsVisible(view)); 487 } 488 } 489 } 490 491 IN_PROC_BROWSER_TEST_F(NotificationTest, TestActivateDeactivate) { 492 BalloonCollectionImpl* collection = GetBalloonCollectionImpl(); 493 NotificationPanel* panel = GetNotificationPanel(); 494 NotificationPanelTester* tester = panel->GetTester(); 495 Profile* profile = browser()->profile(); 496 497 collection->Add(NewMockNotification("1"), profile); 498 collection->AddSystemNotification( 499 NewMockNotification("2"), profile, true, false); 500 ui_test_utils::RunAllPendingInMessageLoop(); 501 EXPECT_EQ(NotificationPanel::STICKY_AND_NEW, tester->state()); 502 BalloonViewImpl* view1 = 503 tester->GetBalloonView(collection, NewMockNotification("1")); 504 BalloonViewImpl* view2 = 505 tester->GetBalloonView(collection, NewMockNotification("2")); 506 // Wait until all renderers get size. 507 WaitForResize(view1); 508 WaitForResize(view2); 509 EXPECT_LT(view2->size().height(), 50) << "view size is bigger than expected"; 510 511 panel->OnMouseMotion(gfx::Point(10, 50)); 512 EXPECT_TRUE(tester->IsActive(view1)); 513 EXPECT_FALSE(tester->IsActive(view2)); 514 515 panel->OnMouseMotion(gfx::Point(10, 10)); 516 EXPECT_FALSE(tester->IsActive(view1)); 517 EXPECT_TRUE(tester->IsActive(view2)); 518 519 panel->OnMouseMotion(gfx::Point(500, 500)); 520 EXPECT_FALSE(tester->IsActive(view1)); 521 EXPECT_FALSE(tester->IsActive(view2)); 522 } 523 524 IN_PROC_BROWSER_TEST_F(NotificationTest, TestCloseDismissAllNonSticky) { 525 BalloonCollectionImpl* collection = GetBalloonCollectionImpl(); 526 NotificationPanel* panel = GetNotificationPanel(); 527 NotificationPanelTester* tester = panel->GetTester(); 528 Profile* profile = browser()->profile(); 529 530 collection->Add(NewMockNotification("1"), profile); 531 collection->AddSystemNotification( 532 NewMockNotification("2"), profile, true, false); 533 collection->Add(NewMockNotification("3"), profile); 534 535 ui_test_utils::RunAllPendingInMessageLoop(); 536 EXPECT_EQ(NotificationPanel::STICKY_AND_NEW, tester->state()); 537 EXPECT_EQ(3, tester->GetNotificationCount()); 538 EXPECT_EQ(1, tester->GetStickyNotificationCount()); 539 540 // Hide 541 panel->Hide(); 542 ui_test_utils::RunAllPendingInMessageLoop(); 543 EXPECT_EQ(1, tester->GetNotificationCount()); 544 EXPECT_EQ(1, tester->GetStickyNotificationCount()); 545 } 546 547 IN_PROC_BROWSER_TEST_F(NotificationTest, TestAddWebUIMessageCallback) { 548 BalloonCollectionImpl* collection = GetBalloonCollectionImpl(); 549 Profile* profile = browser()->profile(); 550 551 collection->AddSystemNotification( 552 NewMockNotification("1"), profile, false, false); 553 554 EXPECT_TRUE(collection->AddWebUIMessageCallback( 555 NewMockNotification("1"), 556 "test", 557 NewCallback( 558 static_cast<NotificationTest*>(this), 559 &NotificationTest::HandleWebUIMessage))); 560 561 // Adding callback for the same message twice should fail. 562 EXPECT_FALSE(collection->AddWebUIMessageCallback( 563 NewMockNotification("1"), 564 "test", 565 NewCallback( 566 static_cast<NotificationTest*>(this), 567 &NotificationTest::HandleWebUIMessage))); 568 569 // Adding callback to nonexistent notification should fail. 570 EXPECT_FALSE(collection->AddWebUIMessageCallback( 571 NewMockNotification("2"), 572 "test1", 573 NewCallback( 574 static_cast<NotificationTest*>(this), 575 &NotificationTest::HandleWebUIMessage))); 576 } 577 578 IN_PROC_BROWSER_TEST_F(NotificationTest, TestWebUIMessageCallback) { 579 BalloonCollectionImpl* collection = GetBalloonCollectionImpl(); 580 Profile* profile = browser()->profile(); 581 // A notification that sends 'test' WebUI message back to chrome. 582 const GURL content_url( 583 "data:text/html;charset=utf-8," 584 "<html><script>function send() { chrome.send('test', ['']); }</script>" 585 "<body onload='send()'></body></html>"); 586 collection->AddSystemNotification( 587 Notification(GURL(), content_url, string16(), string16(), 588 new MockNotificationDelegate("1")), 589 profile, 590 false, 591 false); 592 EXPECT_TRUE(collection->AddWebUIMessageCallback( 593 NewMockNotification("1"), 594 "test", 595 NewCallback( 596 static_cast<NotificationTest*>(this), 597 &NotificationTest::HandleWebUIMessage))); 598 MessageLoop::current()->Run(); 599 } 600 601 } // namespace chromeos 602