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 "chrome/browser/apps/app_browsertest_util.h"
6 #include "chrome/browser/extensions/extension_test_message_listener.h"
7 #include "chrome/test/base/interactive_test_utils.h"
8 #include "extensions/browser/app_window/native_app_window.h"
10 #if defined(OS_MACOSX) && !defined(OS_IOS)
11 #include "base/mac/mac_util.h"
16 #include "ui/aura/window.h"
17 #include "ui/aura/window_tree_host.h"
18 #include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h"
19 #include "ui/views/win/hwnd_message_handler_delegate.h"
20 #include "ui/views/win/hwnd_util.h"
23 using extensions::NativeAppWindow
;
25 // Helper class that has to be created in the stack to check if the fullscreen
26 // setting of a NativeWindow has changed since the creation of the object.
27 class FullscreenChangeWaiter
{
29 explicit FullscreenChangeWaiter(NativeAppWindow
* window
)
31 initial_fullscreen_state_(window_
->IsFullscreen()) {}
34 while (initial_fullscreen_state_
== window_
->IsFullscreen())
35 content::RunAllPendingInMessageLoop();
39 NativeAppWindow
* window_
;
40 bool initial_fullscreen_state_
;
42 DISALLOW_COPY_AND_ASSIGN(FullscreenChangeWaiter
);
45 class AppWindowInteractiveTest
: public extensions::PlatformAppBrowserTest
{
47 bool RunAppWindowInteractiveTest(const char* testName
) {
48 ExtensionTestMessageListener
launched_listener("Launched", true);
49 LoadAndLaunchPlatformApp("window_api_interactive", &launched_listener
);
51 ResultCatcher catcher
;
52 launched_listener
.Reply(testName
);
54 if (!catcher
.GetNextResult()) {
55 message_
= catcher
.message();
62 bool SimulateKeyPress(ui::KeyboardCode key
) {
63 return ui_test_utils::SendKeyPressToWindowSync(
64 GetFirstAppWindow()->GetNativeWindow(),
72 // This method will wait until the application is able to ack a key event.
73 void WaitUntilKeyFocus() {
74 ExtensionTestMessageListener
key_listener("KeyReceived", false);
76 while (!key_listener
.was_satisfied()) {
77 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_Z
));
78 content::RunAllPendingInMessageLoop();
82 // This test is a method so that we can test with each frame type.
83 void TestOuterBoundsHelper(const std::string
& frame_type
);
86 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
, ESCLeavesFullscreenWindow
) {
87 // This test is flaky on MacOS 10.6.
88 #if defined(OS_MACOSX) && !defined(OS_IOS)
89 if (base::mac::IsOSSnowLeopard())
93 ExtensionTestMessageListener
launched_listener("Launched", true);
94 LoadAndLaunchPlatformApp("leave_fullscreen", &launched_listener
);
96 // We start by making sure the window is actually focused.
97 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
98 GetFirstAppWindow()->GetNativeWindow()));
100 // When receiving the reply, the application will try to go fullscreen using
101 // the Window API but there is no synchronous way to know if that actually
102 // succeeded. Also, failure will not be notified. A failure case will only be
103 // known with a timeout.
105 FullscreenChangeWaiter
fs_changed(GetFirstAppWindow()->GetBaseWindow());
107 launched_listener
.Reply("window");
112 // Depending on the platform, going fullscreen might create an animation.
113 // We want to make sure that the ESC key we will send next is actually going
114 // to be received and the application might not receive key events during the
115 // animation so we should wait for the key focus to be back.
118 // Same idea as above but for leaving fullscreen. Fullscreen mode should be
119 // left when ESC is received.
121 FullscreenChangeWaiter
fs_changed(GetFirstAppWindow()->GetBaseWindow());
123 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_ESCAPE
));
129 #if defined(OS_MACOSX)
130 // http://crbug.com/406009
131 #define MAYBE_ESCLeavesFullscreenDOM DISABLED_ESCLeavesFullscreenDOM
133 #define MAYBE_ESCLeavesFullscreenDOM ESCLeavesFullscreenDOM
135 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
, MAYBE_ESCLeavesFullscreenDOM
) {
136 // This test is flaky on MacOS 10.6.
137 #if defined(OS_MACOSX) && !defined(OS_IOS)
138 if (base::mac::IsOSSnowLeopard())
142 ExtensionTestMessageListener
launched_listener("Launched", true);
143 LoadAndLaunchPlatformApp("leave_fullscreen", &launched_listener
);
145 // We start by making sure the window is actually focused.
146 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
147 GetFirstAppWindow()->GetNativeWindow()));
149 launched_listener
.Reply("dom");
151 // Because the DOM way to go fullscreen requires user gesture, we simulate a
152 // key event to get the window entering in fullscreen mode. The reply will
153 // make the window listen for the key event. The reply will be sent to the
154 // renderer process before the keypress and should be received in that order.
155 // When receiving the key event, the application will try to go fullscreen
156 // using the Window API but there is no synchronous way to know if that
157 // actually succeeded. Also, failure will not be notified. A failure case will
158 // only be known with a timeout.
160 FullscreenChangeWaiter
fs_changed(GetFirstAppWindow()->GetBaseWindow());
163 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_A
));
168 // Depending on the platform, going fullscreen might create an animation.
169 // We want to make sure that the ESC key we will send next is actually going
170 // to be received and the application might not receive key events during the
171 // animation so we should wait for the key focus to be back.
174 // Same idea as above but for leaving fullscreen. Fullscreen mode should be
175 // left when ESC is received.
177 FullscreenChangeWaiter
fs_changed(GetFirstAppWindow()->GetBaseWindow());
179 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_ESCAPE
));
185 #if defined(OS_MACOSX)
186 // http://crbug.com/406009
187 #define MAYBE_ESCDoesNotLeaveFullscreenWindow DISABLED_ESCDoesNotLeaveFullscreenWindow
189 #define MAYBE_ESCDoesNotLeaveFullscreenWindow ESCDoesNotLeaveFullscreenWindow
191 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
,
192 MAYBE_ESCDoesNotLeaveFullscreenWindow
) {
193 // This test is flaky on MacOS 10.6.
194 #if defined(OS_MACOSX) && !defined(OS_IOS)
195 if (base::mac::IsOSSnowLeopard())
199 ExtensionTestMessageListener
launched_listener("Launched", true);
200 LoadAndLaunchPlatformApp("prevent_leave_fullscreen", &launched_listener
);
202 // We start by making sure the window is actually focused.
203 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
204 GetFirstAppWindow()->GetNativeWindow()));
206 // When receiving the reply, the application will try to go fullscreen using
207 // the Window API but there is no synchronous way to know if that actually
208 // succeeded. Also, failure will not be notified. A failure case will only be
209 // known with a timeout.
211 FullscreenChangeWaiter
fs_changed(GetFirstAppWindow()->GetBaseWindow());
213 launched_listener
.Reply("window");
218 // Depending on the platform, going fullscreen might create an animation.
219 // We want to make sure that the ESC key we will send next is actually going
220 // to be received and the application might not receive key events during the
221 // animation so we should wait for the key focus to be back.
224 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_ESCAPE
));
226 ExtensionTestMessageListener
second_key_listener("B_KEY_RECEIVED", false);
228 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_B
));
230 ASSERT_TRUE(second_key_listener
.WaitUntilSatisfied());
232 // We assume that at that point, if we had to leave fullscreen, we should be.
233 // However, by nature, we can not guarantee that and given that we do test
234 // that nothing happens, we might end up with random-success when the feature
236 EXPECT_TRUE(GetFirstAppWindow()->GetBaseWindow()->IsFullscreen());
239 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
,
240 ESCDoesNotLeaveFullscreenDOM
) {
241 // This test is flaky on MacOS 10.6.
242 #if defined(OS_MACOSX) && !defined(OS_IOS)
243 if (base::mac::IsOSSnowLeopard())
247 ExtensionTestMessageListener
launched_listener("Launched", true);
248 LoadAndLaunchPlatformApp("prevent_leave_fullscreen", &launched_listener
);
250 // We start by making sure the window is actually focused.
251 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
252 GetFirstAppWindow()->GetNativeWindow()));
254 launched_listener
.Reply("dom");
256 // Because the DOM way to go fullscreen requires user gesture, we simulate a
257 // key event to get the window entering in fullscreen mode. The reply will
258 // make the window listen for the key event. The reply will be sent to the
259 // renderer process before the keypress and should be received in that order.
260 // When receiving the key event, the application will try to go fullscreen
261 // using the Window API but there is no synchronous way to know if that
262 // actually succeeded. Also, failure will not be notified. A failure case will
263 // only be known with a timeout.
265 FullscreenChangeWaiter
fs_changed(GetFirstAppWindow()->GetBaseWindow());
268 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_A
));
273 // Depending on the platform, going fullscreen might create an animation.
274 // We want to make sure that the ESC key we will send next is actually going
275 // to be received and the application might not receive key events during the
276 // animation so we should wait for the key focus to be back.
279 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_ESCAPE
));
281 ExtensionTestMessageListener
second_key_listener("B_KEY_RECEIVED", false);
283 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_B
));
285 ASSERT_TRUE(second_key_listener
.WaitUntilSatisfied());
287 // We assume that at that point, if we had to leave fullscreen, we should be.
288 // However, by nature, we can not guarantee that and given that we do test
289 // that nothing happens, we might end up with random-success when the feature
291 EXPECT_TRUE(GetFirstAppWindow()->GetBaseWindow()->IsFullscreen());
294 // This test is duplicated from ESCDoesNotLeaveFullscreenWindow.
295 // It runs the same test, but uses the old permission names: 'fullscreen'
296 // and 'overrideEscFullscreen'.
297 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
,
298 ESCDoesNotLeaveFullscreenOldPermission
) {
299 // This test is flaky on MacOS 10.6.
300 #if defined(OS_MACOSX) && !defined(OS_IOS)
301 if (base::mac::IsOSSnowLeopard())
305 ExtensionTestMessageListener
launched_listener("Launched", true);
306 LoadAndLaunchPlatformApp("prevent_leave_fullscreen_old", &launched_listener
);
308 // We start by making sure the window is actually focused.
309 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
310 GetFirstAppWindow()->GetNativeWindow()));
312 // When receiving the reply, the application will try to go fullscreen using
313 // the Window API but there is no synchronous way to know if that actually
314 // succeeded. Also, failure will not be notified. A failure case will only be
315 // known with a timeout.
317 FullscreenChangeWaiter
fs_changed(GetFirstAppWindow()->GetBaseWindow());
319 launched_listener
.Reply("window");
324 // Depending on the platform, going fullscreen might create an animation.
325 // We want to make sure that the ESC key we will send next is actually going
326 // to be received and the application might not receive key events during the
327 // animation so we should wait for the key focus to be back.
330 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_ESCAPE
));
332 ExtensionTestMessageListener
second_key_listener("B_KEY_RECEIVED", false);
334 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_B
));
336 ASSERT_TRUE(second_key_listener
.WaitUntilSatisfied());
338 // We assume that at that point, if we had to leave fullscreen, we should be.
339 // However, by nature, we can not guarantee that and given that we do test
340 // that nothing happens, we might end up with random-success when the feature
342 EXPECT_TRUE(GetFirstAppWindow()->GetBaseWindow()->IsFullscreen());
345 #if defined(OS_MACOSX)
346 // http://crbug.com/404081
347 #define MAYBE_TestInnerBounds DISABLED_TestInnerBounds
349 #define MAYBE_TestInnerBounds TestInnerBounds
351 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
, MAYBE_TestInnerBounds
) {
352 ASSERT_TRUE(RunAppWindowInteractiveTest("testInnerBounds")) << message_
;
355 void AppWindowInteractiveTest::TestOuterBoundsHelper(
356 const std::string
& frame_type
) {
357 ExtensionTestMessageListener
launched_listener("Launched", true);
358 const extensions::Extension
* app
=
359 LoadAndLaunchPlatformApp("outer_bounds", &launched_listener
);
361 launched_listener
.Reply(frame_type
);
362 launched_listener
.Reset();
363 ASSERT_TRUE(launched_listener
.WaitUntilSatisfied());
365 apps::AppWindow
* window
= GetFirstAppWindowForApp(app
->id());
366 gfx::Rect window_bounds
;
367 gfx::Size min_size
, max_size
;
370 // Get the bounds from the HWND.
371 HWND hwnd
= views::HWNDForNativeWindow(window
->GetNativeWindow());
373 ::GetWindowRect(hwnd
, &rect
);
374 window_bounds
= gfx::Rect(
375 rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
);
377 // HWNDMessageHandler calls this when responding to WM_GETMINMAXSIZE, so it's
378 // the closest to what the window will see.
379 views::HWNDMessageHandlerDelegate
* host
=
380 static_cast<views::HWNDMessageHandlerDelegate
*>(
381 static_cast<views::DesktopWindowTreeHostWin
*>(
382 aura::WindowTreeHost::GetForAcceleratedWidget(hwnd
)));
383 host
->GetMinMaxSize(&min_size
, &max_size
);
384 // Note that this does not include the the client area insets so we need to
387 host
->GetClientAreaInsets(&insets
);
388 min_size
= gfx::Size(min_size
.width() + insets
.left() + insets
.right(),
389 min_size
.height() + insets
.top() + insets
.bottom());
390 max_size
= gfx::Size(
391 max_size
.width() ? max_size
.width() + insets
.left() + insets
.right() : 0,
392 max_size
.height() ? max_size
.height() + insets
.top() + insets
.bottom()
394 #endif // defined(OS_WIN)
396 // These match the values in the outer_bounds/test.js
397 EXPECT_EQ(gfx::Rect(10, 11, 300, 301), window_bounds
);
398 EXPECT_EQ(window
->GetBaseWindow()->GetBounds(), window_bounds
);
399 EXPECT_EQ(200, min_size
.width());
400 EXPECT_EQ(201, min_size
.height());
401 EXPECT_EQ(400, max_size
.width());
402 EXPECT_EQ(401, max_size
.height());
405 // TODO(jackhou): Make this test work for other OSes.
407 #define MAYBE_TestOuterBoundsFrameChrome DISABLED_TestOuterBoundsFrameChrome
408 #define MAYBE_TestOuterBoundsFrameNone DISABLED_TestOuterBoundsFrameNone
409 #define MAYBE_TestOuterBoundsFrameColor DISABLED_TestOuterBoundsFrameColor
411 #define MAYBE_TestOuterBoundsFrameChrome TestOuterBoundsFrameChrome
412 #define MAYBE_TestOuterBoundsFrameNone TestOuterBoundsFrameNone
413 #define MAYBE_TestOuterBoundsFrameColor TestOuterBoundsFrameColor
416 // Test that the outer bounds match that of the native window.
417 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
,
418 MAYBE_TestOuterBoundsFrameChrome
) {
419 TestOuterBoundsHelper("chrome");
421 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
,
422 MAYBE_TestOuterBoundsFrameNone
) {
423 TestOuterBoundsHelper("none");
425 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
,
426 MAYBE_TestOuterBoundsFrameColor
) {
427 TestOuterBoundsHelper("color");
430 // This test does not work on Linux Aura because ShowInactive() is not
431 // implemented. See http://crbug.com/325142
432 // It also does not work on Windows because of the document being focused even
433 // though the window is not activated. See http://crbug.com/326986
434 // It also does not work on MacOS because ::ShowInactive() ends up behaving like
435 // ::Show() because of Cocoa conventions. See http://crbug.com/326987
436 // Those tests should be disabled on Linux GTK when they are enabled on the
437 // other platforms, see http://crbug.com/328829
438 #if (defined(OS_LINUX) && defined(USE_AURA)) || \
439 defined(OS_WIN) || defined(OS_MACOSX)
440 #define MAYBE_TestCreate DISABLED_TestCreate
441 #define MAYBE_TestShow DISABLED_TestShow
443 #define MAYBE_TestCreate TestCreate
444 #define MAYBE_TestShow TestShow
447 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
, MAYBE_TestCreate
) {
448 ASSERT_TRUE(RunAppWindowInteractiveTest("testCreate")) << message_
;
451 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
, MAYBE_TestShow
) {
452 ASSERT_TRUE(RunAppWindowInteractiveTest("testShow")) << message_
;
455 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
, TestDrawAttention
) {
456 ASSERT_TRUE(RunAppWindowInteractiveTest("testDrawAttention")) << message_
;