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_ash.h"
10 #include "ash/test/ash_test_base.h"
11 #include "base/bind.h"
12 #include "ui/gfx/size.h"
13 #include "ui/message_center/message_center.h"
18 class ResolutionNotificationControllerTest : public ash::test::AshTestBase {
20 ResolutionNotificationControllerTest()
24 virtual ~ResolutionNotificationControllerTest() {}
27 virtual void SetUp() OVERRIDE {
28 ash::test::AshTestBase::SetUp();
29 ResolutionNotificationController::SuppressTimerForTest();
32 void SetDisplayResolutionAndNotify(const gfx::Display& display,
33 const gfx::Size& new_resolution) {
34 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
35 const DisplayInfo& info = display_manager->GetDisplayInfo(display.id());
36 Shell::GetInstance()->resolution_notification_controller()->
37 SetDisplayResolutionAndNotify(
41 base::Bind(&ResolutionNotificationControllerTest::OnAccepted,
42 base::Unretained(this)));
44 // OnConfigurationChanged event won't be emitted in the test environment,
45 // so invoke UpdateDisplay() to emit that event explicitly.
46 std::vector<DisplayInfo> info_list;
47 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
48 int64 id = display_manager->GetDisplayAt(i).id();
49 DisplayInfo info = display_manager->GetDisplayInfo(id);
50 if (display.id() == id) {
51 gfx::Rect bounds = info.bounds_in_native();
52 bounds.set_size(new_resolution);
53 info.SetBounds(bounds);
55 info_list.push_back(info);
57 display_manager->OnNativeDisplaysChanged(info_list);
58 RunAllPendingInMessageLoop();
61 void ClickOnNotification() {
62 message_center::MessageCenter::Get()->ClickOnNotification(
63 ResolutionNotificationController::kNotificationId);
66 void ClickOnNotificationButton(int index) {
67 message_center::MessageCenter::Get()->ClickOnNotificationButton(
68 ResolutionNotificationController::kNotificationId, index);
71 void CloseNotification() {
72 message_center::MessageCenter::Get()->RemoveNotification(
73 ResolutionNotificationController::kNotificationId, true /* by_user */);
76 bool IsNotificationVisible() {
77 return message_center::MessageCenter::Get()->HasNotification(
78 ResolutionNotificationController::kNotificationId);
82 controller()->OnTimerTick();
85 ResolutionNotificationController* controller() {
86 return Shell::GetInstance()->resolution_notification_controller();
89 int accept_count() const {
95 EXPECT_FALSE(controller()->DoesNotificationTimeout());
101 DISALLOW_COPY_AND_ASSIGN(ResolutionNotificationControllerTest);
104 // Basic behaviors and verifies it doesn't cause crashes.
105 TEST_F(ResolutionNotificationControllerTest, Basic) {
106 if (!SupportsMultipleDisplays())
109 UpdateDisplay("300x300#300x300|200x200,250x250#250x250|200x200");
110 int64 id2 = ash::ScreenAsh::GetSecondaryDisplay().id();
111 ash::internal::DisplayManager* display_manager =
112 ash::Shell::GetInstance()->display_manager();
113 ASSERT_EQ(0, accept_count());
114 EXPECT_FALSE(IsNotificationVisible());
116 // Changes the resolution and apply the result.
117 SetDisplayResolutionAndNotify(
118 ScreenAsh::GetSecondaryDisplay(), gfx::Size(200, 200));
119 EXPECT_TRUE(IsNotificationVisible());
120 EXPECT_FALSE(controller()->DoesNotificationTimeout());
121 gfx::Size resolution;
123 display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
124 EXPECT_EQ("200x200", resolution.ToString());
126 // Click the revert button, which reverts to the best resolution.
127 ClickOnNotificationButton(0);
128 RunAllPendingInMessageLoop();
129 EXPECT_FALSE(IsNotificationVisible());
130 EXPECT_EQ(0, accept_count());
132 display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
135 TEST_F(ResolutionNotificationControllerTest, ClickMeansAccept) {
136 if (!SupportsMultipleDisplays())
139 UpdateDisplay("300x300#300x300|200x200,250x250#250x250|200x200");
140 int64 id2 = ash::ScreenAsh::GetSecondaryDisplay().id();
141 ash::internal::DisplayManager* display_manager =
142 ash::Shell::GetInstance()->display_manager();
143 ASSERT_EQ(0, accept_count());
144 EXPECT_FALSE(IsNotificationVisible());
146 // Changes the resolution and apply the result.
147 SetDisplayResolutionAndNotify(
148 ScreenAsh::GetSecondaryDisplay(), gfx::Size(200, 200));
149 EXPECT_TRUE(IsNotificationVisible());
150 EXPECT_FALSE(controller()->DoesNotificationTimeout());
151 gfx::Size resolution;
153 display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
154 EXPECT_EQ("200x200", resolution.ToString());
156 // Click the revert button, which reverts the resolution.
157 ClickOnNotification();
158 RunAllPendingInMessageLoop();
159 EXPECT_FALSE(IsNotificationVisible());
160 EXPECT_EQ(1, accept_count());
162 display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
163 EXPECT_EQ("200x200", resolution.ToString());
166 TEST_F(ResolutionNotificationControllerTest, AcceptButton) {
167 if (!SupportsMultipleDisplays())
170 ash::internal::DisplayManager* display_manager =
171 ash::Shell::GetInstance()->display_manager();
173 UpdateDisplay("300x300#300x300|200x200");
174 const gfx::Display& display = ash::Shell::GetScreen()->GetPrimaryDisplay();
175 SetDisplayResolutionAndNotify(display, gfx::Size(200, 200));
176 EXPECT_TRUE(IsNotificationVisible());
178 // If there's a single display only, it will have timeout and the first button
180 EXPECT_TRUE(controller()->DoesNotificationTimeout());
181 ClickOnNotificationButton(0);
182 EXPECT_FALSE(IsNotificationVisible());
183 EXPECT_EQ(1, accept_count());
184 gfx::Size resolution;
185 EXPECT_TRUE(display_manager->GetSelectedResolutionForDisplayId(
186 display.id(), &resolution));
187 EXPECT_EQ("200x200", resolution.ToString());
189 // In that case the second button is revert.
190 UpdateDisplay("300x300#300x300|200x200");
191 SetDisplayResolutionAndNotify(display, gfx::Size(200, 200));
192 EXPECT_TRUE(IsNotificationVisible());
194 EXPECT_TRUE(controller()->DoesNotificationTimeout());
195 ClickOnNotificationButton(1);
196 EXPECT_FALSE(IsNotificationVisible());
197 EXPECT_EQ(1, accept_count());
198 EXPECT_FALSE(display_manager->GetSelectedResolutionForDisplayId(
199 display.id(), &resolution));
202 TEST_F(ResolutionNotificationControllerTest, Close) {
203 if (!SupportsMultipleDisplays())
206 UpdateDisplay("100x100,150x150#150x150|200x200");
207 int64 id2 = ash::ScreenAsh::GetSecondaryDisplay().id();
208 ash::internal::DisplayManager* display_manager =
209 ash::Shell::GetInstance()->display_manager();
210 ASSERT_EQ(0, accept_count());
211 EXPECT_FALSE(IsNotificationVisible());
213 // Changes the resolution and apply the result.
214 SetDisplayResolutionAndNotify(
215 ScreenAsh::GetSecondaryDisplay(), gfx::Size(200, 200));
216 EXPECT_TRUE(IsNotificationVisible());
217 EXPECT_FALSE(controller()->DoesNotificationTimeout());
218 gfx::Size resolution;
220 display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
221 EXPECT_EQ("200x200", resolution.ToString());
223 // Close the notification (imitates clicking [x] button). Also verifies if
224 // this does not cause a crash. See crbug.com/271784
226 RunAllPendingInMessageLoop();
227 EXPECT_FALSE(IsNotificationVisible());
228 EXPECT_EQ(1, accept_count());
231 TEST_F(ResolutionNotificationControllerTest, Timeout) {
232 if (!SupportsMultipleDisplays())
235 UpdateDisplay("300x300#300x300|200x200");
236 const gfx::Display& display = ash::Shell::GetScreen()->GetPrimaryDisplay();
237 SetDisplayResolutionAndNotify(display, gfx::Size(200, 200));
239 for (int i = 0; i < ResolutionNotificationController::kTimeoutInSec; ++i) {
240 EXPECT_TRUE(IsNotificationVisible()) << "notification is closed after "
241 << i << "-th timer tick";
243 RunAllPendingInMessageLoop();
245 EXPECT_FALSE(IsNotificationVisible());
246 EXPECT_EQ(0, accept_count());
247 gfx::Size resolution;
248 ash::internal::DisplayManager* display_manager =
249 ash::Shell::GetInstance()->display_manager();
250 EXPECT_FALSE(display_manager->GetSelectedResolutionForDisplayId(
251 display.id(), &resolution));
254 TEST_F(ResolutionNotificationControllerTest, DisplayDisconnected) {
255 if (!SupportsMultipleDisplays())
258 UpdateDisplay("300x300#300x300|200x200,200x200#250x250|200x200|100x100");
259 int64 id2 = ash::ScreenAsh::GetSecondaryDisplay().id();
260 ash::internal::DisplayManager* display_manager =
261 ash::Shell::GetInstance()->display_manager();
262 SetDisplayResolutionAndNotify(
263 ScreenAsh::GetSecondaryDisplay(), gfx::Size(100, 100));
264 ASSERT_TRUE(IsNotificationVisible());
266 // Disconnects the secondary display and verifies it doesn't cause crashes.
267 UpdateDisplay("300x300#300x300|200x200");
268 RunAllPendingInMessageLoop();
269 EXPECT_FALSE(IsNotificationVisible());
270 EXPECT_EQ(0, accept_count());
271 gfx::Size resolution;
273 display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
274 EXPECT_EQ("200x200", resolution.ToString());
277 TEST_F(ResolutionNotificationControllerTest, MultipleResolutionChange) {
278 if (!SupportsMultipleDisplays())
281 UpdateDisplay("300x300#300x300|200x200,250x250#250x250|200x200");
282 int64 id2 = ash::ScreenAsh::GetSecondaryDisplay().id();
283 ash::internal::DisplayManager* display_manager =
284 ash::Shell::GetInstance()->display_manager();
286 SetDisplayResolutionAndNotify(
287 ScreenAsh::GetSecondaryDisplay(), gfx::Size(200, 200));
288 EXPECT_TRUE(IsNotificationVisible());
289 EXPECT_FALSE(controller()->DoesNotificationTimeout());
290 gfx::Size resolution;
292 display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
293 EXPECT_EQ("200x200", resolution.ToString());
295 // Invokes SetDisplayResolutionAndNotify during the previous notification is
297 SetDisplayResolutionAndNotify(
298 ScreenAsh::GetSecondaryDisplay(), gfx::Size(250, 250));
300 display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
302 // Then, click the revert button. Although |old_resolution| for the second
303 // SetDisplayResolutionAndNotify is 200x200, it should revert to the original
305 ClickOnNotificationButton(0);
306 RunAllPendingInMessageLoop();
307 EXPECT_FALSE(IsNotificationVisible());
308 EXPECT_EQ(0, accept_count());
310 display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
313 } // namespace internal