Don't preload rarely seen large images
[chromium-blink-merge.git] / ash / display / resolution_notification_controller_unittest.cc
blob98a9172e50d0e72dd580ced3246a609fcb7cfb4e
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.
5 #include "ash/display/resolution_notification_controller.h"
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/geometry/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"
20 namespace ash {
21 namespace {
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()));
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()));
46 } // namespace
48 class ResolutionNotificationControllerTest : public ash::test::AshTestBase {
49 public:
50 ResolutionNotificationControllerTest()
51 : accept_count_(0) {
54 ~ResolutionNotificationControllerTest() override {}
56 protected:
57 void SetUp() override {
58 ash::test::AshTestBase::SetUp();
59 ResolutionNotificationController::SuppressTimerForTest();
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();
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;
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)));
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);
96 info_list.push_back(info);
98 display_manager->OnNativeDisplaysChanged(info_list);
99 RunAllPendingInMessageLoop();
102 void SetDisplayResolutionAndNotify(const gfx::Display& display,
103 const gfx::Size& new_resolution) {
104 SetDisplayResolutionAndNotifyWithResolution(
105 display, new_resolution, new_resolution);
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();
117 return base::string16();
120 static void ClickOnNotification() {
121 message_center::MessageCenter::Get()->ClickOnNotification(
122 ResolutionNotificationController::kNotificationId);
125 static void ClickOnNotificationButton(int index) {
126 message_center::MessageCenter::Get()->ClickOnNotificationButton(
127 ResolutionNotificationController::kNotificationId, index);
130 static void CloseNotification() {
131 message_center::MessageCenter::Get()->RemoveNotification(
132 ResolutionNotificationController::kNotificationId, true /* by_user */);
135 static bool IsNotificationVisible() {
136 return message_center::MessageCenter::Get()->FindVisibleNotificationById(
137 ResolutionNotificationController::kNotificationId);
140 static void TickTimer() {
141 controller()->OnTimerTick();
144 static ResolutionNotificationController* controller() {
145 return Shell::GetInstance()->resolution_notification_controller();
148 int accept_count() const {
149 return accept_count_;
152 private:
153 void OnAccepted() {
154 EXPECT_FALSE(controller()->DoesNotificationTimeout());
155 accept_count_++;
158 int accept_count_;
160 DISALLOW_COPY_AND_ASSIGN(ResolutionNotificationControllerTest);
163 // Basic behaviors and verifies it doesn't cause crashes.
164 TEST_F(ResolutionNotificationControllerTest, Basic) {
165 if (!SupportsMultipleDisplays())
166 return;
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());
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);
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);
197 TEST_F(ResolutionNotificationControllerTest, ClickMeansAccept) {
198 if (!SupportsMultipleDisplays())
199 return;
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());
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);
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);
228 TEST_F(ResolutionNotificationControllerTest, AcceptButton) {
229 if (!SupportsMultipleDisplays())
230 return;
232 ash::DisplayManager* display_manager =
233 ash::Shell::GetInstance()->display_manager();
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());
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);
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());
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);
267 TEST_F(ResolutionNotificationControllerTest, Close) {
268 if (!SupportsMultipleDisplays())
269 return;
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());
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);
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());
296 TEST_F(ResolutionNotificationControllerTest, Timeout) {
297 if (!SupportsMultipleDisplays())
298 return;
300 UpdateDisplay("300x300#300x300%59|200x200%60");
301 const gfx::Display& display = ash::Shell::GetScreen()->GetPrimaryDisplay();
302 SetDisplayResolutionAndNotify(display, gfx::Size(200, 200));
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();
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);
321 TEST_F(ResolutionNotificationControllerTest, DisplayDisconnected) {
322 if (!SupportsMultipleDisplays())
323 return;
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());
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);
346 TEST_F(ResolutionNotificationControllerTest, MultipleResolutionChange) {
347 if (!SupportsMultipleDisplays())
348 return;
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();
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);
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);
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);
385 TEST_F(ResolutionNotificationControllerTest, Fallback) {
386 if (!SupportsMultipleDisplays())
387 return;
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());
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);
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);
423 } // namespace ash