Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ash / system / web_notification / web_notification_tray_unittest.cc
1 // Copyright (c) 2012 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 "ash/system/web_notification/web_notification_tray.h"
6
7 #include <vector>
8
9 #include "ash/display/display_manager.h"
10 #include "ash/root_window_controller.h"
11 #include "ash/shelf/shelf_layout_manager.h"
12 #include "ash/shelf/shelf_widget.h"
13 #include "ash/shell.h"
14 #include "ash/system/status_area_widget.h"
15 #include "ash/system/tray/system_tray.h"
16 #include "ash/system/tray/system_tray_item.h"
17 #include "ash/test/ash_test_base.h"
18 #include "ash/test/status_area_widget_test_helper.h"
19 #include "ash/test/test_system_tray_delegate.h"
20 #include "ash/wm/window_state.h"
21 #include "base/strings/stringprintf.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "ui/aura/client/aura_constants.h"
24 #include "ui/aura/test/event_generator.h"
25 #include "ui/aura/window.h"
26 #include "ui/gfx/display.h"
27 #include "ui/gfx/screen.h"
28 #include "ui/message_center/message_center_style.h"
29 #include "ui/message_center/message_center_tray.h"
30 #include "ui/message_center/notification_list.h"
31 #include "ui/message_center/notification_types.h"
32 #include "ui/message_center/views/message_center_bubble.h"
33 #include "ui/message_center/views/message_popup_collection.h"
34 #include "ui/views/controls/label.h"
35 #include "ui/views/layout/fill_layout.h"
36 #include "ui/views/view.h"
37 #include "ui/views/widget/widget.h"
38
39 namespace ash {
40
41 namespace {
42
43 WebNotificationTray* GetTray() {
44   return StatusAreaWidgetTestHelper::GetStatusAreaWidget()->
45       web_notification_tray();
46 }
47
48 WebNotificationTray* GetSecondaryTray() {
49   StatusAreaWidget* status_area_widget =
50       StatusAreaWidgetTestHelper::GetSecondaryStatusAreaWidget();
51   if (status_area_widget)
52     return status_area_widget->web_notification_tray();
53   return NULL;
54 }
55
56 message_center::MessageCenter* GetMessageCenter() {
57   return GetTray()->message_center();
58 }
59
60 SystemTray* GetSystemTray() {
61   return StatusAreaWidgetTestHelper::GetStatusAreaWidget()->system_tray();
62 }
63
64 // Trivial item implementation for testing PopupAndSystemTray test case.
65 class TestItem : public SystemTrayItem {
66  public:
67   TestItem() : SystemTrayItem(GetSystemTray()) {}
68
69   virtual views::View* CreateDefaultView(user::LoginStatus status) OVERRIDE {
70     views::View* default_view = new views::View;
71     default_view->SetLayoutManager(new views::FillLayout);
72     default_view->AddChildView(new views::Label(base::UTF8ToUTF16("Default")));
73     return default_view;
74   }
75
76   virtual views::View* CreateNotificationView(
77       user::LoginStatus status) OVERRIDE {
78     return new views::View;
79   }
80
81  private:
82   DISALLOW_COPY_AND_ASSIGN(TestItem);
83 };
84
85 }  // namespace
86
87 class WebNotificationTrayTest : public test::AshTestBase {
88  public:
89   WebNotificationTrayTest() {}
90   virtual ~WebNotificationTrayTest() {}
91
92   virtual void TearDown() OVERRIDE {
93     GetMessageCenter()->RemoveAllNotifications(false);
94     test::AshTestBase::TearDown();
95   }
96
97  protected:
98   void AddNotification(const std::string& id) {
99     scoped_ptr<message_center::Notification> notification;
100     notification.reset(new message_center::Notification(
101         message_center::NOTIFICATION_TYPE_SIMPLE,
102         id,
103         base::ASCIIToUTF16("Test Web Notification"),
104         base::ASCIIToUTF16("Notification message body."),
105         gfx::Image(),
106         base::ASCIIToUTF16("www.test.org"),
107         message_center::NotifierId(),
108         message_center::RichNotificationData(),
109         NULL /* delegate */));
110     GetMessageCenter()->AddNotification(notification.Pass());
111   }
112
113   void UpdateNotification(const std::string& old_id,
114                           const std::string& new_id) {
115     scoped_ptr<message_center::Notification> notification;
116     notification.reset(new message_center::Notification(
117         message_center::NOTIFICATION_TYPE_SIMPLE,
118         new_id,
119         base::ASCIIToUTF16("Updated Web Notification"),
120         base::ASCIIToUTF16("Updated message body."),
121         gfx::Image(),
122         base::ASCIIToUTF16("www.test.org"),
123         message_center::NotifierId(),
124         message_center::RichNotificationData(),
125         NULL /* delegate */));
126     GetMessageCenter()->UpdateNotification(old_id, notification.Pass());
127   }
128
129   void RemoveNotification(const std::string& id) {
130     GetMessageCenter()->RemoveNotification(id, false);
131   }
132
133   views::Widget* GetWidget() {
134     return GetTray()->GetWidget();
135   }
136
137   gfx::Rect GetPopupWorkArea() {
138     return GetPopupWorkAreaForTray(GetTray());
139   }
140
141   gfx::Rect GetPopupWorkAreaForTray(WebNotificationTray* tray) {
142     return tray->popup_collection_->work_area_;
143   }
144
145   bool IsPopupVisible() {
146     return GetTray()->IsPopupVisible();
147   }
148
149  private:
150   DISALLOW_COPY_AND_ASSIGN(WebNotificationTrayTest);
151 };
152
153 TEST_F(WebNotificationTrayTest, WebNotifications) {
154   // TODO(mukai): move this test case to ui/message_center.
155   ASSERT_TRUE(GetWidget());
156
157   // Add a notification.
158   AddNotification("test_id1");
159   EXPECT_EQ(1u, GetMessageCenter()->NotificationCount());
160   EXPECT_TRUE(GetMessageCenter()->HasNotification("test_id1"));
161   AddNotification("test_id2");
162   AddNotification("test_id2");
163   EXPECT_EQ(2u, GetMessageCenter()->NotificationCount());
164   EXPECT_TRUE(GetMessageCenter()->HasNotification("test_id2"));
165
166   // Ensure that updating a notification does not affect the count.
167   UpdateNotification("test_id2", "test_id3");
168   UpdateNotification("test_id3", "test_id3");
169   EXPECT_EQ(2u, GetMessageCenter()->NotificationCount());
170   EXPECT_FALSE(GetMessageCenter()->HasNotification("test_id2"));
171
172   // Ensure that Removing the first notification removes it from the tray.
173   RemoveNotification("test_id1");
174   EXPECT_FALSE(GetMessageCenter()->HasNotification("test_id1"));
175   EXPECT_EQ(1u, GetMessageCenter()->NotificationCount());
176
177   // Remove the remianing notification.
178   RemoveNotification("test_id3");
179   EXPECT_EQ(0u, GetMessageCenter()->NotificationCount());
180   EXPECT_FALSE(GetMessageCenter()->HasNotification("test_id3"));
181 }
182
183 TEST_F(WebNotificationTrayTest, WebNotificationPopupBubble) {
184   // TODO(mukai): move this test case to ui/message_center.
185   ASSERT_TRUE(GetWidget());
186
187   // Adding a notification should show the popup bubble.
188   AddNotification("test_id1");
189   EXPECT_TRUE(GetTray()->IsPopupVisible());
190
191   // Updating a notification should not hide the popup bubble.
192   AddNotification("test_id2");
193   UpdateNotification("test_id2", "test_id3");
194   EXPECT_TRUE(GetTray()->IsPopupVisible());
195
196   // Removing the first notification should not hide the popup bubble.
197   RemoveNotification("test_id1");
198   EXPECT_TRUE(GetTray()->IsPopupVisible());
199
200   // Removing the visible notification should hide the popup bubble.
201   RemoveNotification("test_id3");
202   EXPECT_FALSE(GetTray()->IsPopupVisible());
203
204   // Now test that we can show multiple popups and then show the message center.
205   AddNotification("test_id4");
206   AddNotification("test_id5");
207   EXPECT_TRUE(GetTray()->IsPopupVisible());
208
209   GetTray()->message_center_tray_->ShowMessageCenterBubble();
210   GetTray()->message_center_tray_->HideMessageCenterBubble();
211
212   EXPECT_FALSE(GetTray()->IsPopupVisible());
213 }
214
215 using message_center::NotificationList;
216
217
218 // Flakily fails. http://crbug.com/229791
219 TEST_F(WebNotificationTrayTest, DISABLED_ManyMessageCenterNotifications) {
220   // Add the max visible notifications +1, ensure the correct visible number.
221   size_t notifications_to_add =
222       message_center::kMaxVisibleMessageCenterNotifications + 1;
223   for (size_t i = 0; i < notifications_to_add; ++i) {
224     std::string id = base::StringPrintf("test_id%d", static_cast<int>(i));
225     AddNotification(id);
226   }
227   bool shown = GetTray()->message_center_tray_->ShowMessageCenterBubble();
228   EXPECT_TRUE(shown);
229   RunAllPendingInMessageLoop();
230   EXPECT_TRUE(GetTray()->message_center_bubble() != NULL);
231   EXPECT_EQ(notifications_to_add,
232             GetMessageCenter()->NotificationCount());
233   EXPECT_EQ(message_center::kMaxVisibleMessageCenterNotifications,
234             GetTray()->GetMessageCenterBubbleForTest()->
235                 NumMessageViewsForTest());
236 }
237
238 // Flakily times out. http://crbug.com/229792
239 TEST_F(WebNotificationTrayTest, DISABLED_ManyPopupNotifications) {
240   // Add the max visible popup notifications +1, ensure the correct num visible.
241   size_t notifications_to_add =
242       message_center::kMaxVisiblePopupNotifications + 1;
243   for (size_t i = 0; i < notifications_to_add; ++i) {
244     std::string id = base::StringPrintf("test_id%d", static_cast<int>(i));
245     AddNotification(id);
246   }
247   GetTray()->ShowPopups();
248   EXPECT_TRUE(GetTray()->IsPopupVisible());
249   EXPECT_EQ(notifications_to_add,
250             GetMessageCenter()->NotificationCount());
251   NotificationList::PopupNotifications popups =
252       GetMessageCenter()->GetPopupNotifications();
253   EXPECT_EQ(message_center::kMaxVisiblePopupNotifications, popups.size());
254 }
255
256 #if defined(OS_CHROMEOS)
257 // Display notification is ChromeOS only.
258 #define MAYBE_PopupShownOnBothDisplays PopupShownOnBothDisplays
259 #define MAYBE_PopupAndSystemTrayMultiDisplay PopupAndSystemTrayMultiDisplay
260 #else
261 #define MAYBE_PopupShownOnBothDisplays DISABLED_PopupShownOnBothDisplays
262 #define MAYBE_PopupAndSystemTrayMultiDisplay \
263   DISABLED_PopupAndSystemTrayMultiDisplay
264 #endif
265
266 // Verifies if the notification appears on both displays when extended mode.
267 TEST_F(WebNotificationTrayTest, MAYBE_PopupShownOnBothDisplays) {
268   if (!SupportsMultipleDisplays())
269     return;
270
271   // Enables to appear the notification for display changes.
272   test::TestSystemTrayDelegate* tray_delegate =
273       static_cast<test::TestSystemTrayDelegate*>(
274           Shell::GetInstance()->system_tray_delegate());
275   tray_delegate->set_should_show_display_notification(true);
276
277   UpdateDisplay("400x400,200x200");
278   // UpdateDisplay() creates the display notifications, so popup is visible.
279   EXPECT_TRUE(GetTray()->IsPopupVisible());
280   WebNotificationTray* secondary_tray = GetSecondaryTray();
281   ASSERT_TRUE(secondary_tray);
282   EXPECT_TRUE(secondary_tray->IsPopupVisible());
283
284   // Transition to mirroring and then back to extended display, which recreates
285   // root window controller and shelf with having notifications. This code
286   // verifies it doesn't cause crash and popups are still visible. See
287   // http://crbug.com/263664
288   DisplayManager* display_manager = Shell::GetInstance()->display_manager();
289
290   display_manager->SetSecondDisplayMode(DisplayManager::MIRRORING);
291   UpdateDisplay("400x400,200x200");
292   EXPECT_TRUE(GetTray()->IsPopupVisible());
293   EXPECT_FALSE(GetSecondaryTray());
294
295   display_manager->SetSecondDisplayMode(DisplayManager::EXTENDED);
296   UpdateDisplay("400x400,200x200");
297   EXPECT_TRUE(GetTray()->IsPopupVisible());
298   secondary_tray = GetSecondaryTray();
299   ASSERT_TRUE(secondary_tray);
300   EXPECT_TRUE(secondary_tray->IsPopupVisible());
301 }
302
303 #if defined(OS_CHROMEOS)
304 // PopupAndSystemTray may fail in platforms other than ChromeOS because the
305 // RootWindow's bound can be bigger than gfx::Display's work area so that
306 // openingsystem tray doesn't affect at all the work area of popups.
307 #define MAYBE_PopupAndSystemTray PopupAndSystemTray
308 #define MAYBE_PopupAndAutoHideShelf PopupAndAutoHideShelf
309 #define MAYBE_PopupAndFullscreen PopupAndFullscreen
310 #else
311 #define MAYBE_PopupAndSystemTray DISABLED_PopupAndSystemTray
312 #define MAYBE_PopupAndAutoHideShelf DISABLED_PopupAndAutoHideShelf
313 #define MAYBE_PopupAndFullscreen DISABLED_PopupAndFullscreen
314 #endif
315
316 TEST_F(WebNotificationTrayTest, MAYBE_PopupAndSystemTray) {
317   TestItem* test_item = new TestItem;
318   GetSystemTray()->AddTrayItem(test_item);
319
320   AddNotification("test_id");
321   EXPECT_TRUE(GetTray()->IsPopupVisible());
322   gfx::Rect work_area = GetPopupWorkArea();
323
324   // System tray is created, the popup's work area should be narrowed but still
325   // visible.
326   GetSystemTray()->ShowDefaultView(BUBBLE_CREATE_NEW);
327   EXPECT_TRUE(GetTray()->IsPopupVisible());
328   gfx::Rect work_area_with_tray = GetPopupWorkArea();
329   EXPECT_GT(work_area.size().GetArea(), work_area_with_tray.size().GetArea());
330
331   // System tray notification is also created, the popup's work area is narrowed
332   // even more, but still visible.
333   GetSystemTray()->ShowNotificationView(test_item);
334   EXPECT_TRUE(GetTray()->IsPopupVisible());
335   gfx::Rect work_area_with_tray_notification = GetPopupWorkArea();
336   EXPECT_GT(work_area.size().GetArea(),
337             work_area_with_tray_notification.size().GetArea());
338   EXPECT_GT(work_area_with_tray.size().GetArea(),
339             work_area_with_tray_notification.size().GetArea());
340
341   // Close system tray, only system tray notifications.
342   GetSystemTray()->ClickedOutsideBubble();
343   EXPECT_TRUE(GetTray()->IsPopupVisible());
344   gfx::Rect work_area_with_notification = GetPopupWorkArea();
345   EXPECT_GT(work_area.size().GetArea(),
346             work_area_with_notification.size().GetArea());
347   EXPECT_LT(work_area_with_tray_notification.size().GetArea(),
348             work_area_with_notification.size().GetArea());
349
350   // Close the system tray notifications.
351   GetSystemTray()->HideNotificationView(test_item);
352   EXPECT_TRUE(GetTray()->IsPopupVisible());
353   EXPECT_EQ(work_area.ToString(), GetPopupWorkArea().ToString());
354 }
355
356 TEST_F(WebNotificationTrayTest, MAYBE_PopupAndAutoHideShelf) {
357   AddNotification("test_id");
358   EXPECT_TRUE(GetTray()->IsPopupVisible());
359   gfx::Rect work_area = GetPopupWorkArea();
360
361   // Shelf's auto-hide state won't be HIDDEN unless window exists.
362   scoped_ptr<aura::Window> window(
363       CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 3, 4)));
364   ShelfLayoutManager* shelf =
365       Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
366   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
367
368   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
369   gfx::Rect work_area_auto_hidden = GetPopupWorkArea();
370   EXPECT_LT(work_area.size().GetArea(), work_area_auto_hidden.size().GetArea());
371
372   // Close the window, which shows the shelf.
373   window.reset();
374   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
375   gfx::Rect work_area_auto_shown = GetPopupWorkArea();
376   EXPECT_EQ(work_area.ToString(), work_area_auto_shown.ToString());
377
378   // Create the system tray during auto-hide.
379   window.reset(CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 3, 4)));
380   TestItem* test_item = new TestItem;
381   GetSystemTray()->AddTrayItem(test_item);
382   GetSystemTray()->ShowDefaultView(BUBBLE_CREATE_NEW);
383
384   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
385   EXPECT_TRUE(GetTray()->IsPopupVisible());
386   gfx::Rect work_area_with_tray = GetPopupWorkArea();
387   EXPECT_GT(work_area_auto_shown.size().GetArea(),
388             work_area_with_tray.size().GetArea());
389
390   // Create tray notification.
391   GetSystemTray()->ShowNotificationView(test_item);
392   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
393   gfx::Rect work_area_with_tray_notification = GetPopupWorkArea();
394   EXPECT_GT(work_area_with_tray.size().GetArea(),
395             work_area_with_tray_notification.size().GetArea());
396
397   // Close the system tray.
398   GetSystemTray()->ClickedOutsideBubble();
399   shelf->UpdateAutoHideState();
400   RunAllPendingInMessageLoop();
401   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
402   gfx::Rect work_area_hidden_with_tray_notification = GetPopupWorkArea();
403   EXPECT_LT(work_area_with_tray_notification.size().GetArea(),
404             work_area_hidden_with_tray_notification.size().GetArea());
405   EXPECT_GT(work_area_auto_hidden.size().GetArea(),
406             work_area_hidden_with_tray_notification.size().GetArea());
407
408   // Close the window again, which shows the shelf.
409   window.reset();
410   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
411   gfx::Rect work_area_shown_with_tray_notification = GetPopupWorkArea();
412   EXPECT_GT(work_area_hidden_with_tray_notification.size().GetArea(),
413             work_area_shown_with_tray_notification.size().GetArea());
414   EXPECT_GT(work_area_auto_shown.size().GetArea(),
415             work_area_shown_with_tray_notification.size().GetArea());
416 }
417
418 TEST_F(WebNotificationTrayTest, MAYBE_PopupAndFullscreen) {
419   AddNotification("test_id");
420   EXPECT_TRUE(IsPopupVisible());
421   gfx::Rect work_area = GetPopupWorkArea();
422
423   // Checks the work area for normal auto-hidden state.
424   scoped_ptr<aura::Window> window(
425       CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 3, 4)));
426   ShelfLayoutManager* shelf =
427       Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
428   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
429   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
430   gfx::Rect work_area_auto_hidden = GetPopupWorkArea();
431   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
432
433   // Put |window| into fullscreen without forcing the shelf to hide. Currently,
434   // this is used by immersive fullscreen and forces the shelf to be auto
435   // hidden.
436   wm::GetWindowState(window.get())->set_hide_shelf_when_fullscreen(false);
437   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
438   RunAllPendingInMessageLoop();
439
440   // The work area for auto-hidden status of fullscreen is a bit larger
441   // since it doesn't even have the 3-pixel width.
442   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
443   gfx::Rect work_area_fullscreen_hidden = GetPopupWorkArea();
444   EXPECT_EQ(work_area_auto_hidden.ToString(),
445             work_area_fullscreen_hidden.ToString());
446
447   // Move the mouse cursor at the bottom, which shows the shelf.
448   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
449   gfx::Point bottom_right =
450       Shell::GetScreen()->GetPrimaryDisplay().bounds().bottom_right();
451   bottom_right.Offset(-1, -1);
452   generator.MoveMouseTo(bottom_right);
453   shelf->UpdateAutoHideStateNow();
454   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
455   EXPECT_EQ(work_area.ToString(), GetPopupWorkArea().ToString());
456
457   generator.MoveMouseTo(work_area.CenterPoint());
458   shelf->UpdateAutoHideStateNow();
459   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
460   EXPECT_EQ(work_area_auto_hidden.ToString(), GetPopupWorkArea().ToString());
461 }
462
463 TEST_F(WebNotificationTrayTest, MAYBE_PopupAndSystemTrayMultiDisplay) {
464   UpdateDisplay("800x600,600x400");
465
466   AddNotification("test_id");
467   gfx::Rect work_area = GetPopupWorkArea();
468   gfx::Rect work_area_second = GetPopupWorkAreaForTray(GetSecondaryTray());
469
470   // System tray is created on the primary display. The popups in the secondary
471   // tray aren't affected.
472   GetSystemTray()->ShowDefaultView(BUBBLE_CREATE_NEW);
473   EXPECT_GT(work_area.size().GetArea(), GetPopupWorkArea().size().GetArea());
474   EXPECT_EQ(work_area_second.ToString(),
475             GetPopupWorkAreaForTray(GetSecondaryTray()).ToString());
476 }
477
478 }  // namespace ash