Home | History | Annotate | Download | only in notifications
      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