Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ash / display / resolution_notification_controller_unittest.cc
1 // Copyright 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 "ash/display/resolution_notification_controller.h"
6
7 #include "ash/display/display_manager.h"
8 #include "ash/screen_util.h"
9 #include "ash/shell.h"
10 #include "ash/test/ash_test_base.h"
11 #include "base/bind.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "grit/ash_strings.h"
14 #include "ui/base/l10n/l10n_util.h"
15 #include "ui/gfx/size.h"
16 #include "ui/message_center/message_center.h"
17 #include "ui/message_center/notification.h"
18 #include "ui/message_center/notification_list.h"
19
20 namespace ash {
21 namespace {
22
23 base::string16 ExpectedNotificationMessage(int64 display_id,
24                                            const gfx::Size& new_resolution) {
25   return l10n_util::GetStringFUTF16(
26       IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED,
27       base::UTF8ToUTF16(
28           Shell::GetInstance()->display_manager()->GetDisplayNameForId(
29               display_id)),
30       base::UTF8ToUTF16(new_resolution.ToString()));
31 }
32
33 base::string16 ExpectedFallbackNotificationMessage(
34     int64 display_id,
35     const gfx::Size& specified_resolution,
36     const gfx::Size& fallback_resolution) {
37   return l10n_util::GetStringFUTF16(
38       IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED_TO_UNSUPPORTED,
39       base::UTF8ToUTF16(
40           Shell::GetInstance()->display_manager()->GetDisplayNameForId(
41               display_id)),
42       base::UTF8ToUTF16(specified_resolution.ToString()),
43       base::UTF8ToUTF16(fallback_resolution.ToString()));
44 }
45
46 }  // namespace
47
48 class ResolutionNotificationControllerTest : public ash::test::AshTestBase {
49  public:
50   ResolutionNotificationControllerTest()
51       : accept_count_(0) {
52   }
53
54   virtual ~ResolutionNotificationControllerTest() {}
55
56  protected:
57   virtual void SetUp() override {
58     ash::test::AshTestBase::SetUp();
59     ResolutionNotificationController::SuppressTimerForTest();
60   }
61
62   void SetDisplayResolutionAndNotifyWithResolution(
63       const gfx::Display& display,
64       const gfx::Size& new_resolution,
65       const gfx::Size& actual_new_resolution) {
66     DisplayManager* display_manager = Shell::GetInstance()->display_manager();
67
68     const DisplayInfo& info = display_manager->GetDisplayInfo(display.id());
69     DisplayMode old_mode(info.size_in_pixel(),
70                          60 /* refresh_rate */,
71                          false /* interlaced */,
72                          false /* native */);
73     DisplayMode new_mode = old_mode;
74     new_mode.size = new_resolution;
75
76     if (display_manager->SetDisplayMode(display.id(), new_mode)) {
77       controller()->PrepareNotification(
78           display.id(),
79           old_mode,
80           new_mode,
81           base::Bind(&ResolutionNotificationControllerTest::OnAccepted,
82                      base::Unretained(this)));
83     }
84
85     // OnConfigurationChanged event won't be emitted in the test environment,
86     // so invoke UpdateDisplay() to emit that event explicitly.
87     std::vector<DisplayInfo> info_list;
88     for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
89       int64 id = display_manager->GetDisplayAt(i).id();
90       DisplayInfo info = display_manager->GetDisplayInfo(id);
91       if (display.id() == id) {
92         gfx::Rect bounds = info.bounds_in_native();
93         bounds.set_size(actual_new_resolution);
94         info.SetBounds(bounds);
95       }
96       info_list.push_back(info);
97     }
98     display_manager->OnNativeDisplaysChanged(info_list);
99     RunAllPendingInMessageLoop();
100   }
101
102   void SetDisplayResolutionAndNotify(const gfx::Display& display,
103                                      const gfx::Size& new_resolution) {
104     SetDisplayResolutionAndNotifyWithResolution(
105         display, new_resolution, new_resolution);
106   }
107
108   static base::string16 GetNotificationMessage() {
109     const message_center::NotificationList::Notifications& notifications =
110         message_center::MessageCenter::Get()->GetVisibleNotifications();
111     for (message_center::NotificationList::Notifications::const_iterator iter =
112              notifications.begin(); iter != notifications.end(); ++iter) {
113       if ((*iter)->id() == ResolutionNotificationController::kNotificationId)
114         return (*iter)->title();
115     }
116
117     return base::string16();
118   }
119
120   static void ClickOnNotification() {
121     message_center::MessageCenter::Get()->ClickOnNotification(
122         ResolutionNotificationController::kNotificationId);
123   }
124
125   static void ClickOnNotificationButton(int index) {
126     message_center::MessageCenter::Get()->ClickOnNotificationButton(
127         ResolutionNotificationController::kNotificationId, index);
128   }
129
130   static void CloseNotification() {
131     message_center::MessageCenter::Get()->RemoveNotification(
132         ResolutionNotificationController::kNotificationId, true /* by_user */);
133   }
134
135   static bool IsNotificationVisible() {
136     return message_center::MessageCenter::Get()->FindVisibleNotificationById(
137         ResolutionNotificationController::kNotificationId);
138   }
139
140   static void TickTimer() {
141     controller()->OnTimerTick();
142   }
143
144   static ResolutionNotificationController* controller() {
145     return Shell::GetInstance()->resolution_notification_controller();
146   }
147
148   int accept_count() const {
149     return accept_count_;
150   }
151
152  private:
153   void OnAccepted() {
154     EXPECT_FALSE(controller()->DoesNotificationTimeout());
155     accept_count_++;
156   }
157
158   int accept_count_;
159
160   DISALLOW_COPY_AND_ASSIGN(ResolutionNotificationControllerTest);
161 };
162
163 // Basic behaviors and verifies it doesn't cause crashes.
164 TEST_F(ResolutionNotificationControllerTest, Basic) {
165   if (!SupportsMultipleDisplays())
166     return;
167
168   UpdateDisplay("300x300#300x300%57|200x200%58,250x250#250x250%59|200x200%60");
169   int64 id2 = ash::ScreenUtil::GetSecondaryDisplay().id();
170   ash::DisplayManager* display_manager =
171       ash::Shell::GetInstance()->display_manager();
172   ASSERT_EQ(0, accept_count());
173   EXPECT_FALSE(IsNotificationVisible());
174
175   // Changes the resolution and apply the result.
176   SetDisplayResolutionAndNotify(
177       ScreenUtil::GetSecondaryDisplay(), gfx::Size(200, 200));
178   EXPECT_TRUE(IsNotificationVisible());
179   EXPECT_FALSE(controller()->DoesNotificationTimeout());
180   EXPECT_EQ(ExpectedNotificationMessage(id2, gfx::Size(200, 200)),
181             GetNotificationMessage());
182   DisplayMode mode;
183   EXPECT_TRUE(display_manager->GetSelectedModeForDisplayId(id2, &mode));
184   EXPECT_EQ("200x200", mode.size.ToString());
185   EXPECT_EQ(60.0, mode.refresh_rate);
186
187   // Click the revert button, which reverts to the best resolution.
188   ClickOnNotificationButton(0);
189   RunAllPendingInMessageLoop();
190   EXPECT_FALSE(IsNotificationVisible());
191   EXPECT_EQ(0, accept_count());
192   EXPECT_TRUE(display_manager->GetSelectedModeForDisplayId(id2, &mode));
193   EXPECT_EQ("250x250", mode.size.ToString());
194   EXPECT_EQ(59.0, mode.refresh_rate);
195 }
196
197 TEST_F(ResolutionNotificationControllerTest, ClickMeansAccept) {
198   if (!SupportsMultipleDisplays())
199     return;
200
201   UpdateDisplay("300x300#300x300%57|200x200%58,250x250#250x250%59|200x200%60");
202   int64 id2 = ash::ScreenUtil::GetSecondaryDisplay().id();
203   ash::DisplayManager* display_manager =
204       ash::Shell::GetInstance()->display_manager();
205   ASSERT_EQ(0, accept_count());
206   EXPECT_FALSE(IsNotificationVisible());
207
208   // Changes the resolution and apply the result.
209   SetDisplayResolutionAndNotify(
210       ScreenUtil::GetSecondaryDisplay(), gfx::Size(200, 200));
211   EXPECT_TRUE(IsNotificationVisible());
212   EXPECT_FALSE(controller()->DoesNotificationTimeout());
213   DisplayMode mode;
214   EXPECT_TRUE(display_manager->GetSelectedModeForDisplayId(id2, &mode));
215   EXPECT_EQ("200x200", mode.size.ToString());
216   EXPECT_EQ(60.0, mode.refresh_rate);
217
218   // Click the revert button, which reverts the resolution.
219   ClickOnNotification();
220   RunAllPendingInMessageLoop();
221   EXPECT_FALSE(IsNotificationVisible());
222   EXPECT_EQ(1, accept_count());
223   EXPECT_TRUE(display_manager->GetSelectedModeForDisplayId(id2, &mode));
224   EXPECT_EQ("200x200", mode.size.ToString());
225   EXPECT_EQ(60.0, mode.refresh_rate);
226 }
227
228 TEST_F(ResolutionNotificationControllerTest, AcceptButton) {
229   if (!SupportsMultipleDisplays())
230     return;
231
232   ash::DisplayManager* display_manager =
233       ash::Shell::GetInstance()->display_manager();
234
235   UpdateDisplay("300x300#300x300%59|200x200%60");
236   const gfx::Display& display = ash::Shell::GetScreen()->GetPrimaryDisplay();
237   SetDisplayResolutionAndNotify(display, gfx::Size(200, 200));
238   EXPECT_TRUE(IsNotificationVisible());
239
240   // If there's a single display only, it will have timeout and the first button
241   // becomes accept.
242   EXPECT_TRUE(controller()->DoesNotificationTimeout());
243   ClickOnNotificationButton(0);
244   EXPECT_FALSE(IsNotificationVisible());
245   EXPECT_EQ(1, accept_count());
246   DisplayMode mode;
247   EXPECT_TRUE(
248       display_manager->GetSelectedModeForDisplayId(display.id(), &mode));
249   EXPECT_EQ("200x200", mode.size.ToString());
250   EXPECT_EQ(60.0f, mode.refresh_rate);
251
252   // In that case the second button is revert.
253   UpdateDisplay("300x300#300x300%59|200x200%60");
254   SetDisplayResolutionAndNotify(display, gfx::Size(200, 200));
255   EXPECT_TRUE(IsNotificationVisible());
256
257   EXPECT_TRUE(controller()->DoesNotificationTimeout());
258   ClickOnNotificationButton(1);
259   EXPECT_FALSE(IsNotificationVisible());
260   EXPECT_EQ(1, accept_count());
261   EXPECT_TRUE(
262       display_manager->GetSelectedModeForDisplayId(display.id(), &mode));
263   EXPECT_EQ("300x300", mode.size.ToString());
264   EXPECT_EQ(59.0f, mode.refresh_rate);
265 }
266
267 TEST_F(ResolutionNotificationControllerTest, Close) {
268   if (!SupportsMultipleDisplays())
269     return;
270
271   UpdateDisplay("100x100,150x150#150x150%59|200x200%60");
272   int64 id2 = ash::ScreenUtil::GetSecondaryDisplay().id();
273   ash::DisplayManager* display_manager =
274       ash::Shell::GetInstance()->display_manager();
275   ASSERT_EQ(0, accept_count());
276   EXPECT_FALSE(IsNotificationVisible());
277
278   // Changes the resolution and apply the result.
279   SetDisplayResolutionAndNotify(
280       ScreenUtil::GetSecondaryDisplay(), gfx::Size(200, 200));
281   EXPECT_TRUE(IsNotificationVisible());
282   EXPECT_FALSE(controller()->DoesNotificationTimeout());
283   DisplayMode mode;
284   EXPECT_TRUE(display_manager->GetSelectedModeForDisplayId(id2, &mode));
285   EXPECT_EQ("200x200", mode.size.ToString());
286   EXPECT_EQ(60.0f, mode.refresh_rate);
287
288   // Close the notification (imitates clicking [x] button). Also verifies if
289   // this does not cause a crash.  See crbug.com/271784
290   CloseNotification();
291   RunAllPendingInMessageLoop();
292   EXPECT_FALSE(IsNotificationVisible());
293   EXPECT_EQ(1, accept_count());
294 }
295
296 TEST_F(ResolutionNotificationControllerTest, Timeout) {
297   if (!SupportsMultipleDisplays())
298     return;
299
300   UpdateDisplay("300x300#300x300%59|200x200%60");
301   const gfx::Display& display = ash::Shell::GetScreen()->GetPrimaryDisplay();
302   SetDisplayResolutionAndNotify(display, gfx::Size(200, 200));
303
304   for (int i = 0; i < ResolutionNotificationController::kTimeoutInSec; ++i) {
305     EXPECT_TRUE(IsNotificationVisible()) << "notification is closed after "
306                                          << i << "-th timer tick";
307     TickTimer();
308     RunAllPendingInMessageLoop();
309   }
310   EXPECT_FALSE(IsNotificationVisible());
311   EXPECT_EQ(0, accept_count());
312   ash::DisplayManager* display_manager =
313       ash::Shell::GetInstance()->display_manager();
314   DisplayMode mode;
315   EXPECT_TRUE(
316       display_manager->GetSelectedModeForDisplayId(display.id(), &mode));
317   EXPECT_EQ("300x300", mode.size.ToString());
318   EXPECT_EQ(59.0f, mode.refresh_rate);
319 }
320
321 TEST_F(ResolutionNotificationControllerTest, DisplayDisconnected) {
322   if (!SupportsMultipleDisplays())
323     return;
324
325   UpdateDisplay("300x300#300x300%56|200x200%57,"
326                 "200x200#250x250%58|200x200%59|100x100%60");
327   int64 id2 = ash::ScreenUtil::GetSecondaryDisplay().id();
328   ash::DisplayManager* display_manager =
329       ash::Shell::GetInstance()->display_manager();
330   SetDisplayResolutionAndNotify(
331       ScreenUtil::GetSecondaryDisplay(), gfx::Size(100, 100));
332   ASSERT_TRUE(IsNotificationVisible());
333
334   // Disconnects the secondary display and verifies it doesn't cause crashes.
335   UpdateDisplay("300x300#300x300%56|200x200%57");
336   RunAllPendingInMessageLoop();
337   EXPECT_FALSE(IsNotificationVisible());
338   EXPECT_EQ(0, accept_count());
339   DisplayMode mode;
340   EXPECT_TRUE(display_manager->GetSelectedModeForDisplayId(id2, &mode));
341   gfx::Size resolution;
342   EXPECT_EQ("200x200", mode.size.ToString());
343   EXPECT_EQ(59.0f, mode.refresh_rate);
344 }
345
346 TEST_F(ResolutionNotificationControllerTest, MultipleResolutionChange) {
347   if (!SupportsMultipleDisplays())
348     return;
349
350   UpdateDisplay("300x300#300x300%56|200x200%57,"
351                 "250x250#250x250%58|200x200%59");
352   int64 id2 = ash::ScreenUtil::GetSecondaryDisplay().id();
353   ash::DisplayManager* display_manager =
354       ash::Shell::GetInstance()->display_manager();
355
356   SetDisplayResolutionAndNotify(
357       ScreenUtil::GetSecondaryDisplay(), gfx::Size(200, 200));
358   EXPECT_TRUE(IsNotificationVisible());
359   EXPECT_FALSE(controller()->DoesNotificationTimeout());
360   DisplayMode mode;
361   EXPECT_TRUE(display_manager->GetSelectedModeForDisplayId(id2, &mode));
362   EXPECT_EQ("200x200", mode.size.ToString());
363   EXPECT_EQ(59.0f, mode.refresh_rate);
364
365   // Invokes SetDisplayResolutionAndNotify during the previous notification is
366   // visible.
367   SetDisplayResolutionAndNotify(
368       ScreenUtil::GetSecondaryDisplay(), gfx::Size(250, 250));
369   EXPECT_TRUE(display_manager->GetSelectedModeForDisplayId(id2, &mode));
370   EXPECT_EQ("250x250", mode.size.ToString());
371   EXPECT_EQ(58.0f, mode.refresh_rate);
372
373   // Then, click the revert button. Although |old_resolution| for the second
374   // SetDisplayResolutionAndNotify is 200x200, it should revert to the original
375   // size 250x250.
376   ClickOnNotificationButton(0);
377   RunAllPendingInMessageLoop();
378   EXPECT_FALSE(IsNotificationVisible());
379   EXPECT_EQ(0, accept_count());
380   EXPECT_TRUE(display_manager->GetSelectedModeForDisplayId(id2, &mode));
381   EXPECT_EQ("250x250", mode.size.ToString());
382   EXPECT_EQ(58.0f, mode.refresh_rate);
383 }
384
385 TEST_F(ResolutionNotificationControllerTest, Fallback) {
386   if (!SupportsMultipleDisplays())
387     return;
388
389   UpdateDisplay("300x300#300x300%56|200x200%57,"
390                 "250x250#250x250%58|220x220%59|200x200%60");
391   int64 id2 = ash::ScreenUtil::GetSecondaryDisplay().id();
392   ash::DisplayManager* display_manager =
393       ash::Shell::GetInstance()->display_manager();
394   ASSERT_EQ(0, accept_count());
395   EXPECT_FALSE(IsNotificationVisible());
396
397   // Changes the resolution and apply the result.
398   SetDisplayResolutionAndNotifyWithResolution(
399       ScreenUtil::GetSecondaryDisplay(),
400       gfx::Size(220, 220),
401       gfx::Size(200, 200));
402   EXPECT_TRUE(IsNotificationVisible());
403   EXPECT_FALSE(controller()->DoesNotificationTimeout());
404   EXPECT_EQ(
405       ExpectedFallbackNotificationMessage(
406           id2, gfx::Size(220, 220), gfx::Size(200, 200)),
407       GetNotificationMessage());
408   DisplayMode mode;
409   EXPECT_TRUE(display_manager->GetSelectedModeForDisplayId(id2, &mode));
410   EXPECT_EQ("200x200", mode.size.ToString());
411   EXPECT_EQ(60.0f, mode.refresh_rate);
412
413   // Click the revert button, which reverts to the best resolution.
414   ClickOnNotificationButton(0);
415   RunAllPendingInMessageLoop();
416   EXPECT_FALSE(IsNotificationVisible());
417   EXPECT_EQ(0, accept_count());
418   EXPECT_TRUE(display_manager->GetSelectedModeForDisplayId(id2, &mode));
419   EXPECT_EQ("250x250", mode.size.ToString());
420   EXPECT_EQ(58.0f, mode.refresh_rate);
421 }
422
423 }  // namespace ash