- add sources.
[platform/framework/web/crosswalk.git] / src / ash / system / tray / system_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/tray/system_tray.h"
6
7 #include <vector>
8
9 #include "ash/root_window_controller.h"
10 #include "ash/shelf/shelf_layout_manager.h"
11 #include "ash/shelf/shelf_widget.h"
12 #include "ash/shell.h"
13 #include "ash/system/status_area_widget.h"
14 #include "ash/system/tray/system_tray_item.h"
15 #include "ash/test/ash_test_base.h"
16 #include "ash/wm/window_util.h"
17 #include "base/run_loop.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "ui/aura/test/event_generator.h"
20 #include "ui/aura/window.h"
21 #include "ui/views/controls/label.h"
22 #include "ui/views/layout/fill_layout.h"
23 #include "ui/views/view.h"
24 #include "ui/views/widget/widget.h"
25
26 #if defined(OS_WIN)
27 #include "base/win/windows_version.h"
28 #endif
29
30 namespace ash {
31 namespace test {
32
33 namespace {
34
35 SystemTray* GetSystemTray() {
36   return Shell::GetPrimaryRootWindowController()->shelf()->
37       status_area_widget()->system_tray();
38 }
39
40 // Trivial item implementation that tracks its views for testing.
41 class TestItem : public SystemTrayItem {
42  public:
43   TestItem() : SystemTrayItem(GetSystemTray()), tray_view_(NULL) {}
44
45   virtual views::View* CreateTrayView(user::LoginStatus status) OVERRIDE {
46     tray_view_ = new views::View;
47     // Add a label so it has non-zero width.
48     tray_view_->SetLayoutManager(new views::FillLayout);
49     tray_view_->AddChildView(new views::Label(UTF8ToUTF16("Tray")));
50     return tray_view_;
51   }
52
53   virtual views::View* CreateDefaultView(user::LoginStatus status) OVERRIDE {
54     default_view_ = new views::View;
55     default_view_->SetLayoutManager(new views::FillLayout);
56     default_view_->AddChildView(new views::Label(UTF8ToUTF16("Default")));
57     return default_view_;
58   }
59
60   virtual views::View* CreateDetailedView(user::LoginStatus status) OVERRIDE {
61     detailed_view_ = new views::View;
62     detailed_view_->SetLayoutManager(new views::FillLayout);
63     detailed_view_->AddChildView(new views::Label(UTF8ToUTF16("Detailed")));
64     return detailed_view_;
65   }
66
67   virtual views::View* CreateNotificationView(
68       user::LoginStatus status) OVERRIDE {
69     notification_view_ = new views::View;
70     return notification_view_;
71   }
72
73   virtual void DestroyTrayView() OVERRIDE {
74     tray_view_ = NULL;
75   }
76
77   virtual void DestroyDefaultView() OVERRIDE {
78     default_view_ = NULL;
79   }
80
81   virtual void DestroyDetailedView() OVERRIDE {
82     detailed_view_ = NULL;
83   }
84
85   virtual void DestroyNotificationView() OVERRIDE {
86     notification_view_ = NULL;
87   }
88
89   virtual void UpdateAfterLoginStatusChange(
90       user::LoginStatus status) OVERRIDE {
91   }
92
93   views::View* tray_view() const { return tray_view_; }
94   views::View* default_view() const { return default_view_; }
95   views::View* detailed_view() const { return detailed_view_; }
96   views::View* notification_view() const { return notification_view_; }
97
98  private:
99   views::View* tray_view_;
100   views::View* default_view_;
101   views::View* detailed_view_;
102   views::View* notification_view_;
103 };
104
105 // Trivial item implementation that returns NULL from tray/default/detailed
106 // view creation methods.
107 class TestNoViewItem : public SystemTrayItem {
108  public:
109   TestNoViewItem() : SystemTrayItem(GetSystemTray()) {}
110
111   virtual views::View* CreateTrayView(user::LoginStatus status) OVERRIDE {
112     return NULL;
113   }
114
115   virtual views::View* CreateDefaultView(user::LoginStatus status) OVERRIDE {
116     return NULL;
117   }
118
119   virtual views::View* CreateDetailedView(user::LoginStatus status) OVERRIDE {
120     return NULL;
121   }
122
123   virtual views::View* CreateNotificationView(
124       user::LoginStatus status) OVERRIDE {
125     return NULL;
126   }
127
128   virtual void DestroyTrayView() OVERRIDE {}
129   virtual void DestroyDefaultView() OVERRIDE {}
130   virtual void DestroyDetailedView() OVERRIDE {}
131   virtual void DestroyNotificationView() OVERRIDE {}
132   virtual void UpdateAfterLoginStatusChange(
133       user::LoginStatus status) OVERRIDE {
134   }
135 };
136
137 }  // namespace
138
139 typedef AshTestBase SystemTrayTest;
140
141 TEST_F(SystemTrayTest, SystemTrayDefaultView) {
142   SystemTray* tray = GetSystemTray();
143   ASSERT_TRUE(tray->GetWidget());
144
145   tray->ShowDefaultView(BUBBLE_CREATE_NEW);
146
147   // Ensure that closing the bubble destroys it.
148   ASSERT_TRUE(tray->CloseSystemBubble());
149   RunAllPendingInMessageLoop();
150   ASSERT_FALSE(tray->CloseSystemBubble());
151 }
152
153 // Opening and closing the bubble should change the coloring of the tray.
154 TEST_F(SystemTrayTest, SystemTrayColoring) {
155   SystemTray* tray = GetSystemTray();
156   ASSERT_TRUE(tray->GetWidget());
157   // At the beginning the tray coloring is not active.
158   ASSERT_FALSE(tray->draw_background_as_active());
159
160   // Showing the system bubble should show the background as active.
161   tray->ShowDefaultView(BUBBLE_CREATE_NEW);
162   ASSERT_TRUE(tray->draw_background_as_active());
163
164   // Closing the system menu should change the coloring back to normal.
165   ASSERT_TRUE(tray->CloseSystemBubble());
166   RunAllPendingInMessageLoop();
167   ASSERT_FALSE(tray->draw_background_as_active());
168 }
169
170 // Closing the system bubble through an alignment change should change the
171 // system tray coloring back to normal.
172 TEST_F(SystemTrayTest, SystemTrayColoringAfterAlignmentChange) {
173   SystemTray* tray = GetSystemTray();
174   ASSERT_TRUE(tray->GetWidget());
175   internal::ShelfLayoutManager* manager =
176       Shell::GetPrimaryRootWindowController()->shelf()->shelf_layout_manager();
177   manager->SetAlignment(SHELF_ALIGNMENT_BOTTOM);
178   // At the beginning the tray coloring is not active.
179   ASSERT_FALSE(tray->draw_background_as_active());
180
181   // Showing the system bubble should show the background as active.
182   tray->ShowDefaultView(BUBBLE_CREATE_NEW);
183   ASSERT_TRUE(tray->draw_background_as_active());
184
185   // Changing the alignment should close the system bubble and change the
186   // background color.
187   manager->SetAlignment(SHELF_ALIGNMENT_LEFT);
188   ASSERT_FALSE(tray->draw_background_as_active());
189   RunAllPendingInMessageLoop();
190   // The bubble should already be closed by now.
191   ASSERT_FALSE(tray->CloseSystemBubble());
192 }
193
194 TEST_F(SystemTrayTest, SystemTrayTestItems) {
195   SystemTray* tray = GetSystemTray();
196   ASSERT_TRUE(tray->GetWidget());
197
198   TestItem* test_item = new TestItem;
199   TestItem* detailed_item = new TestItem;
200   tray->AddTrayItem(test_item);
201   tray->AddTrayItem(detailed_item);
202
203   // Check items have been added
204   const std::vector<SystemTrayItem*>& items = tray->GetTrayItems();
205   ASSERT_TRUE(
206       std::find(items.begin(), items.end(), test_item) != items.end());
207   ASSERT_TRUE(
208       std::find(items.begin(), items.end(), detailed_item) != items.end());
209
210   // Ensure the tray views are created.
211   ASSERT_TRUE(test_item->tray_view() != NULL);
212   ASSERT_TRUE(detailed_item->tray_view() != NULL);
213
214   // Ensure a default views are created.
215   tray->ShowDefaultView(BUBBLE_CREATE_NEW);
216   ASSERT_TRUE(test_item->default_view() != NULL);
217   ASSERT_TRUE(detailed_item->default_view() != NULL);
218
219   // Show the detailed view, ensure it's created and the default view destroyed.
220   tray->ShowDetailedView(detailed_item, 0, false, BUBBLE_CREATE_NEW);
221   RunAllPendingInMessageLoop();
222   ASSERT_TRUE(test_item->default_view() == NULL);
223   ASSERT_TRUE(detailed_item->detailed_view() != NULL);
224
225   // Show the default view, ensure it's created and the detailed view destroyed.
226   tray->ShowDefaultView(BUBBLE_CREATE_NEW);
227   RunAllPendingInMessageLoop();
228   ASSERT_TRUE(test_item->default_view() != NULL);
229   ASSERT_TRUE(detailed_item->detailed_view() == NULL);
230 }
231
232 TEST_F(SystemTrayTest, SystemTrayNoViewItems) {
233   SystemTray* tray = GetSystemTray();
234   ASSERT_TRUE(tray->GetWidget());
235
236   // Verify that no crashes occur on items lacking some views.
237   TestNoViewItem* no_view_item = new TestNoViewItem;
238   tray->AddTrayItem(no_view_item);
239   tray->ShowDefaultView(BUBBLE_CREATE_NEW);
240   tray->ShowDetailedView(no_view_item, 0, false, BUBBLE_USE_EXISTING);
241   RunAllPendingInMessageLoop();
242 }
243
244 TEST_F(SystemTrayTest, TrayWidgetAutoResizes) {
245   SystemTray* tray = GetSystemTray();
246   ASSERT_TRUE(tray->GetWidget());
247
248   // Add an initial tray item so that the tray gets laid out correctly.
249   TestItem* initial_item = new TestItem;
250   tray->AddTrayItem(initial_item);
251
252   gfx::Size initial_size = tray->GetWidget()->GetWindowBoundsInScreen().size();
253
254   TestItem* new_item = new TestItem;
255   tray->AddTrayItem(new_item);
256
257   gfx::Size new_size = tray->GetWidget()->GetWindowBoundsInScreen().size();
258
259   // Adding the new item should change the size of the tray.
260   EXPECT_NE(initial_size.ToString(), new_size.ToString());
261
262   // Hiding the tray view of the new item should also change the size of the
263   // tray.
264   new_item->tray_view()->SetVisible(false);
265   EXPECT_EQ(initial_size.ToString(),
266             tray->GetWidget()->GetWindowBoundsInScreen().size().ToString());
267
268   new_item->tray_view()->SetVisible(true);
269   EXPECT_EQ(new_size.ToString(),
270             tray->GetWidget()->GetWindowBoundsInScreen().size().ToString());
271 }
272
273 TEST_F(SystemTrayTest, SystemTrayNotifications) {
274   SystemTray* tray = GetSystemTray();
275   ASSERT_TRUE(tray->GetWidget());
276
277   TestItem* test_item = new TestItem;
278   TestItem* detailed_item = new TestItem;
279   tray->AddTrayItem(test_item);
280   tray->AddTrayItem(detailed_item);
281
282   // Ensure the tray views are created.
283   ASSERT_TRUE(test_item->tray_view() != NULL);
284   ASSERT_TRUE(detailed_item->tray_view() != NULL);
285
286   // Ensure a notification view is created.
287   tray->ShowNotificationView(test_item);
288   ASSERT_TRUE(test_item->notification_view() != NULL);
289
290   // Show the default view, notification view should remain.
291   tray->ShowDefaultView(BUBBLE_CREATE_NEW);
292   RunAllPendingInMessageLoop();
293   ASSERT_TRUE(test_item->notification_view() != NULL);
294
295   // Show the detailed view, ensure the notificaiton view remains.
296   tray->ShowDetailedView(detailed_item, 0, false, BUBBLE_CREATE_NEW);
297   RunAllPendingInMessageLoop();
298   ASSERT_TRUE(detailed_item->detailed_view() != NULL);
299   ASSERT_TRUE(test_item->notification_view() != NULL);
300
301   // Hide the detailed view, ensure the notification view still exists.
302   ASSERT_TRUE(tray->CloseSystemBubble());
303   RunAllPendingInMessageLoop();
304   ASSERT_TRUE(detailed_item->detailed_view() == NULL);
305   ASSERT_TRUE(test_item->notification_view() != NULL);
306 }
307
308 TEST_F(SystemTrayTest, BubbleCreationTypesTest) {
309   SystemTray* tray = GetSystemTray();
310   ASSERT_TRUE(tray->GetWidget());
311
312   TestItem* test_item = new TestItem;
313   tray->AddTrayItem(test_item);
314
315   // Ensure the tray views are created.
316   ASSERT_TRUE(test_item->tray_view() != NULL);
317
318   // Show the default view, ensure the notification view is destroyed.
319   tray->ShowDefaultView(BUBBLE_CREATE_NEW);
320   RunAllPendingInMessageLoop();
321
322   views::Widget* widget = test_item->default_view()->GetWidget();
323   gfx::Rect bubble_bounds = widget->GetWindowBoundsInScreen();
324
325   tray->ShowDetailedView(test_item, 0, true, BUBBLE_USE_EXISTING);
326   RunAllPendingInMessageLoop();
327
328   EXPECT_FALSE(test_item->default_view());
329
330   EXPECT_EQ(bubble_bounds.ToString(), test_item->detailed_view()->GetWidget()->
331       GetWindowBoundsInScreen().ToString());
332   EXPECT_EQ(widget, test_item->detailed_view()->GetWidget());
333
334   tray->ShowDefaultView(BUBBLE_USE_EXISTING);
335   RunAllPendingInMessageLoop();
336
337   EXPECT_EQ(bubble_bounds.ToString(), test_item->default_view()->GetWidget()->
338       GetWindowBoundsInScreen().ToString());
339   EXPECT_EQ(widget, test_item->default_view()->GetWidget());
340 }
341
342 // Tests that the tray is laid out properly and is fully contained within
343 // the shelf.
344 TEST_F(SystemTrayTest, TrayBoundsInWidget) {
345   internal::ShelfLayoutManager* manager =
346       Shell::GetPrimaryRootWindowController()->shelf()->shelf_layout_manager();
347   internal::StatusAreaWidget* widget =
348       Shell::GetPrimaryRootWindowController()->shelf()->status_area_widget();
349   SystemTray* tray = widget->system_tray();
350
351   // Test in bottom alignment.
352   manager->SetAlignment(SHELF_ALIGNMENT_BOTTOM);
353   gfx::Rect window_bounds = widget->GetWindowBoundsInScreen();
354   gfx::Rect tray_bounds = tray->GetBoundsInScreen();
355   EXPECT_TRUE(window_bounds.bottom() >= tray_bounds.bottom());
356   EXPECT_TRUE(window_bounds.right() >= tray_bounds.right());
357   EXPECT_TRUE(window_bounds.x() >= tray_bounds.x());
358   EXPECT_TRUE(window_bounds.y() >= tray_bounds.y());
359
360   // Test in the left alignment.
361   manager->SetAlignment(SHELF_ALIGNMENT_LEFT);
362   window_bounds = widget->GetWindowBoundsInScreen();
363   tray_bounds = tray->GetBoundsInScreen();
364   EXPECT_TRUE(window_bounds.bottom() >= tray_bounds.bottom());
365   EXPECT_TRUE(window_bounds.right() >= tray_bounds.right());
366   EXPECT_TRUE(window_bounds.x() >= tray_bounds.x());
367   EXPECT_TRUE(window_bounds.y() >= tray_bounds.y());
368
369   // Test in the right alignment.
370   manager->SetAlignment(SHELF_ALIGNMENT_LEFT);
371   window_bounds = widget->GetWindowBoundsInScreen();
372   tray_bounds = tray->GetBoundsInScreen();
373   EXPECT_TRUE(window_bounds.bottom() >= tray_bounds.bottom());
374   EXPECT_TRUE(window_bounds.right() >= tray_bounds.right());
375   EXPECT_TRUE(window_bounds.x() >= tray_bounds.x());
376   EXPECT_TRUE(window_bounds.y() >= tray_bounds.y());
377 }
378
379 TEST_F(SystemTrayTest, PersistentBubble) {
380   SystemTray* tray = GetSystemTray();
381   ASSERT_TRUE(tray->GetWidget());
382
383   TestItem* test_item = new TestItem;
384   tray->AddTrayItem(test_item);
385
386   scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
387
388   // Tests for usual default view.
389   // Activating window.
390   tray->ShowDefaultView(BUBBLE_CREATE_NEW);
391   ASSERT_TRUE(tray->HasSystemBubble());
392   wm::ActivateWindow(window.get());
393   base::RunLoop().RunUntilIdle();
394   ASSERT_FALSE(tray->HasSystemBubble());
395
396   tray->ShowDefaultView(BUBBLE_CREATE_NEW);
397   ASSERT_TRUE(tray->HasSystemBubble());
398   {
399     aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
400                                          gfx::Point(5, 5));
401     generator.ClickLeftButton();
402     ASSERT_FALSE(tray->HasSystemBubble());
403   }
404
405   // Same tests for persistent default view.
406   tray->ShowPersistentDefaultView();
407   ASSERT_TRUE(tray->HasSystemBubble());
408   wm::ActivateWindow(window.get());
409   base::RunLoop().RunUntilIdle();
410   ASSERT_TRUE(tray->HasSystemBubble());
411
412   {
413     aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
414                                          gfx::Point(5, 5));
415     generator.ClickLeftButton();
416     ASSERT_TRUE(tray->HasSystemBubble());
417   }
418 }
419
420 }  // namespace test
421 }  // namespace ash