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/test/base/interactive_test_utils.h"
7 #include "extensions/browser/app_window/native_app_window.h"
8 #include "extensions/test/extension_test_message_listener.h"
9 #include "extensions/test/result_catcher.h"
11 #if defined(OS_MACOSX) && !defined(OS_IOS)
12 #include "base/mac/mac_util.h"
17 #include "ui/aura/window.h"
18 #include "ui/aura/window_tree_host.h"
19 #include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h"
20 #include "ui/views/win/hwnd_message_handler_delegate.h"
21 #include "ui/views/win/hwnd_util.h"
24 using extensions::AppWindow
;
25 using extensions::NativeAppWindow
;
27 // Helper class that has to be created in the stack to check if the fullscreen
28 // setting of a NativeWindow has changed since the creation of the object.
29 class FullscreenChangeWaiter
{
31 explicit FullscreenChangeWaiter(NativeAppWindow
* window
)
33 initial_fullscreen_state_(window_
->IsFullscreen()) {}
36 while (initial_fullscreen_state_
== window_
->IsFullscreen())
37 content::RunAllPendingInMessageLoop();
41 NativeAppWindow
* window_
;
42 bool initial_fullscreen_state_
;
44 DISALLOW_COPY_AND_ASSIGN(FullscreenChangeWaiter
);
47 class AppWindowInteractiveTest
: public extensions::PlatformAppBrowserTest
{
49 bool RunAppWindowInteractiveTest(const char* testName
) {
50 ExtensionTestMessageListener
launched_listener("Launched", true);
51 LoadAndLaunchPlatformApp("window_api_interactive", &launched_listener
);
53 extensions::ResultCatcher catcher
;
54 launched_listener
.Reply(testName
);
56 if (!catcher
.GetNextResult()) {
57 message_
= catcher
.message();
64 bool SimulateKeyPress(ui::KeyboardCode key
) {
65 return ui_test_utils::SendKeyPressToWindowSync(
66 GetFirstAppWindow()->GetNativeWindow(),
74 // This method will wait until the application is able to ack a key event.
75 void WaitUntilKeyFocus() {
76 ExtensionTestMessageListener
key_listener("KeyReceived", false);
78 while (!key_listener
.was_satisfied()) {
79 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_Z
));
80 content::RunAllPendingInMessageLoop();
84 // This test is a method so that we can test with each frame type.
85 void TestOuterBoundsHelper(const std::string
& frame_type
);
88 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
, ESCLeavesFullscreenWindow
) {
89 // This test is flaky on MacOS 10.6 and 10.9.
90 #if defined(OS_MACOSX) && !defined(OS_IOS)
91 if (base::mac::IsOSSnowLeopard() || base::mac::IsOSMavericks())
95 ExtensionTestMessageListener
launched_listener("Launched", true);
96 LoadAndLaunchPlatformApp("leave_fullscreen", &launched_listener
);
98 // We start by making sure the window is actually focused.
99 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
100 GetFirstAppWindow()->GetNativeWindow()));
102 // When receiving the reply, the application will try to go fullscreen using
103 // the Window API but there is no synchronous way to know if that actually
104 // succeeded. Also, failure will not be notified. A failure case will only be
105 // known with a timeout.
107 FullscreenChangeWaiter
fs_changed(GetFirstAppWindow()->GetBaseWindow());
109 launched_listener
.Reply("window");
114 // Depending on the platform, going fullscreen might create an animation.
115 // We want to make sure that the ESC key we will send next is actually going
116 // to be received and the application might not receive key events during the
117 // animation so we should wait for the key focus to be back.
120 // Same idea as above but for leaving fullscreen. Fullscreen mode should be
121 // left when ESC is received.
123 FullscreenChangeWaiter
fs_changed(GetFirstAppWindow()->GetBaseWindow());
125 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_ESCAPE
));
131 #if defined(OS_MACOSX)
132 // http://crbug.com/406009
133 #define MAYBE_ESCLeavesFullscreenDOM DISABLED_ESCLeavesFullscreenDOM
135 #define MAYBE_ESCLeavesFullscreenDOM ESCLeavesFullscreenDOM
137 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
, MAYBE_ESCLeavesFullscreenDOM
) {
138 // This test is flaky on MacOS 10.6.
139 #if defined(OS_MACOSX) && !defined(OS_IOS)
140 if (base::mac::IsOSSnowLeopard())
144 ExtensionTestMessageListener
launched_listener("Launched", true);
145 LoadAndLaunchPlatformApp("leave_fullscreen", &launched_listener
);
147 // We start by making sure the window is actually focused.
148 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
149 GetFirstAppWindow()->GetNativeWindow()));
151 launched_listener
.Reply("dom");
153 // Because the DOM way to go fullscreen requires user gesture, we simulate a
154 // key event to get the window entering in fullscreen mode. The reply will
155 // make the window listen for the key event. The reply will be sent to the
156 // renderer process before the keypress and should be received in that order.
157 // When receiving the key event, the application will try to go fullscreen
158 // using the Window API but there is no synchronous way to know if that
159 // actually succeeded. Also, failure will not be notified. A failure case will
160 // only be known with a timeout.
162 FullscreenChangeWaiter
fs_changed(GetFirstAppWindow()->GetBaseWindow());
165 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_A
));
170 // Depending on the platform, going fullscreen might create an animation.
171 // We want to make sure that the ESC key we will send next is actually going
172 // to be received and the application might not receive key events during the
173 // animation so we should wait for the key focus to be back.
176 // Same idea as above but for leaving fullscreen. Fullscreen mode should be
177 // left when ESC is received.
179 FullscreenChangeWaiter
fs_changed(GetFirstAppWindow()->GetBaseWindow());
181 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_ESCAPE
));
187 #if defined(OS_MACOSX)
188 // http://crbug.com/406009
189 #define MAYBE_ESCDoesNotLeaveFullscreenWindow DISABLED_ESCDoesNotLeaveFullscreenWindow
191 #define MAYBE_ESCDoesNotLeaveFullscreenWindow ESCDoesNotLeaveFullscreenWindow
193 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
,
194 MAYBE_ESCDoesNotLeaveFullscreenWindow
) {
195 // This test is flaky on MacOS 10.6.
196 #if defined(OS_MACOSX) && !defined(OS_IOS)
197 if (base::mac::IsOSSnowLeopard())
201 ExtensionTestMessageListener
launched_listener("Launched", true);
202 LoadAndLaunchPlatformApp("prevent_leave_fullscreen", &launched_listener
);
204 // We start by making sure the window is actually focused.
205 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
206 GetFirstAppWindow()->GetNativeWindow()));
208 // When receiving the reply, the application will try to go fullscreen using
209 // the Window API but there is no synchronous way to know if that actually
210 // succeeded. Also, failure will not be notified. A failure case will only be
211 // known with a timeout.
213 FullscreenChangeWaiter
fs_changed(GetFirstAppWindow()->GetBaseWindow());
215 launched_listener
.Reply("window");
220 // Depending on the platform, going fullscreen might create an animation.
221 // We want to make sure that the ESC key we will send next is actually going
222 // to be received and the application might not receive key events during the
223 // animation so we should wait for the key focus to be back.
226 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_ESCAPE
));
228 ExtensionTestMessageListener
second_key_listener("B_KEY_RECEIVED", false);
230 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_B
));
232 ASSERT_TRUE(second_key_listener
.WaitUntilSatisfied());
234 // We assume that at that point, if we had to leave fullscreen, we should be.
235 // However, by nature, we can not guarantee that and given that we do test
236 // that nothing happens, we might end up with random-success when the feature
238 EXPECT_TRUE(GetFirstAppWindow()->GetBaseWindow()->IsFullscreen());
241 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
,
242 ESCDoesNotLeaveFullscreenDOM
) {
243 // This test is flaky on MacOS 10.6 and 10.9.
244 #if defined(OS_MACOSX) && !defined(OS_IOS)
245 if (base::mac::IsOSSnowLeopard() || base::mac::IsOSMavericks())
249 ExtensionTestMessageListener
launched_listener("Launched", true);
250 LoadAndLaunchPlatformApp("prevent_leave_fullscreen", &launched_listener
);
252 // We start by making sure the window is actually focused.
253 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
254 GetFirstAppWindow()->GetNativeWindow()));
256 launched_listener
.Reply("dom");
258 // Because the DOM way to go fullscreen requires user gesture, we simulate a
259 // key event to get the window entering in fullscreen mode. The reply will
260 // make the window listen for the key event. The reply will be sent to the
261 // renderer process before the keypress and should be received in that order.
262 // When receiving the key event, the application will try to go fullscreen
263 // using the Window API but there is no synchronous way to know if that
264 // actually succeeded. Also, failure will not be notified. A failure case will
265 // only be known with a timeout.
267 FullscreenChangeWaiter
fs_changed(GetFirstAppWindow()->GetBaseWindow());
270 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_A
));
275 // Depending on the platform, going fullscreen might create an animation.
276 // We want to make sure that the ESC key we will send next is actually going
277 // to be received and the application might not receive key events during the
278 // animation so we should wait for the key focus to be back.
281 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_ESCAPE
));
283 ExtensionTestMessageListener
second_key_listener("B_KEY_RECEIVED", false);
285 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_B
));
287 ASSERT_TRUE(second_key_listener
.WaitUntilSatisfied());
289 // We assume that at that point, if we had to leave fullscreen, we should be.
290 // However, by nature, we can not guarantee that and given that we do test
291 // that nothing happens, we might end up with random-success when the feature
293 EXPECT_TRUE(GetFirstAppWindow()->GetBaseWindow()->IsFullscreen());
296 // This test is duplicated from ESCDoesNotLeaveFullscreenWindow.
297 // It runs the same test, but uses the old permission names: 'fullscreen'
298 // and 'overrideEscFullscreen'.
299 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
,
300 ESCDoesNotLeaveFullscreenOldPermission
) {
301 // This test is flaky on MacOS 10.6 and 10.9.
302 #if defined(OS_MACOSX) && !defined(OS_IOS)
303 if (base::mac::IsOSSnowLeopard() || base::mac::IsOSMavericks())
307 ExtensionTestMessageListener
launched_listener("Launched", true);
308 LoadAndLaunchPlatformApp("prevent_leave_fullscreen_old", &launched_listener
);
310 // We start by making sure the window is actually focused.
311 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
312 GetFirstAppWindow()->GetNativeWindow()));
314 // When receiving the reply, the application will try to go fullscreen using
315 // the Window API but there is no synchronous way to know if that actually
316 // succeeded. Also, failure will not be notified. A failure case will only be
317 // known with a timeout.
319 FullscreenChangeWaiter
fs_changed(GetFirstAppWindow()->GetBaseWindow());
321 launched_listener
.Reply("window");
326 // Depending on the platform, going fullscreen might create an animation.
327 // We want to make sure that the ESC key we will send next is actually going
328 // to be received and the application might not receive key events during the
329 // animation so we should wait for the key focus to be back.
332 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_ESCAPE
));
334 ExtensionTestMessageListener
second_key_listener("B_KEY_RECEIVED", false);
336 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_B
));
338 ASSERT_TRUE(second_key_listener
.WaitUntilSatisfied());
340 // We assume that at that point, if we had to leave fullscreen, we should be.
341 // However, by nature, we can not guarantee that and given that we do test
342 // that nothing happens, we might end up with random-success when the feature
344 EXPECT_TRUE(GetFirstAppWindow()->GetBaseWindow()->IsFullscreen());
347 #if defined(OS_MACOSX) || defined(OS_WIN)
348 // http://crbug.com/404081
349 #define MAYBE_TestInnerBounds DISABLED_TestInnerBounds
351 #define MAYBE_TestInnerBounds TestInnerBounds
353 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
, MAYBE_TestInnerBounds
) {
354 ASSERT_TRUE(RunAppWindowInteractiveTest("testInnerBounds")) << message_
;
357 void AppWindowInteractiveTest::TestOuterBoundsHelper(
358 const std::string
& frame_type
) {
359 ExtensionTestMessageListener
launched_listener("Launched", true);
360 const extensions::Extension
* app
=
361 LoadAndLaunchPlatformApp("outer_bounds", &launched_listener
);
363 launched_listener
.Reply(frame_type
);
364 launched_listener
.Reset();
365 ASSERT_TRUE(launched_listener
.WaitUntilSatisfied());
367 AppWindow
* window
= GetFirstAppWindowForApp(app
->id());
368 gfx::Rect window_bounds
;
369 gfx::Size min_size
, max_size
;
372 // Get the bounds from the HWND.
373 HWND hwnd
= views::HWNDForNativeWindow(window
->GetNativeWindow());
375 ::GetWindowRect(hwnd
, &rect
);
376 window_bounds
= gfx::Rect(
377 rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
);
379 // HWNDMessageHandler calls this when responding to WM_GETMINMAXSIZE, so it's
380 // the closest to what the window will see.
381 views::HWNDMessageHandlerDelegate
* host
=
382 static_cast<views::HWNDMessageHandlerDelegate
*>(
383 static_cast<views::DesktopWindowTreeHostWin
*>(
384 aura::WindowTreeHost::GetForAcceleratedWidget(hwnd
)));
385 host
->GetMinMaxSize(&min_size
, &max_size
);
386 // Note that this does not include the the client area insets so we need to
389 host
->GetClientAreaInsets(&insets
);
390 min_size
= gfx::Size(min_size
.width() + insets
.left() + insets
.right(),
391 min_size
.height() + insets
.top() + insets
.bottom());
392 max_size
= gfx::Size(
393 max_size
.width() ? max_size
.width() + insets
.left() + insets
.right() : 0,
394 max_size
.height() ? max_size
.height() + insets
.top() + insets
.bottom()
396 #endif // defined(OS_WIN)
398 // These match the values in the outer_bounds/test.js
399 EXPECT_EQ(gfx::Rect(10, 11, 300, 301), window_bounds
);
400 EXPECT_EQ(window
->GetBaseWindow()->GetBounds(), window_bounds
);
401 EXPECT_EQ(200, min_size
.width());
402 EXPECT_EQ(201, min_size
.height());
403 EXPECT_EQ(400, max_size
.width());
404 EXPECT_EQ(401, max_size
.height());
407 // TODO(jackhou): Make this test work for other OSes.
409 #define MAYBE_TestOuterBoundsFrameChrome DISABLED_TestOuterBoundsFrameChrome
410 #define MAYBE_TestOuterBoundsFrameNone DISABLED_TestOuterBoundsFrameNone
411 #define MAYBE_TestOuterBoundsFrameColor DISABLED_TestOuterBoundsFrameColor
413 #define MAYBE_TestOuterBoundsFrameChrome TestOuterBoundsFrameChrome
414 #define MAYBE_TestOuterBoundsFrameNone TestOuterBoundsFrameNone
415 #define MAYBE_TestOuterBoundsFrameColor TestOuterBoundsFrameColor
418 // Test that the outer bounds match that of the native window.
419 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
,
420 MAYBE_TestOuterBoundsFrameChrome
) {
421 TestOuterBoundsHelper("chrome");
423 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
,
424 MAYBE_TestOuterBoundsFrameNone
) {
425 TestOuterBoundsHelper("none");
427 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
,
428 MAYBE_TestOuterBoundsFrameColor
) {
429 TestOuterBoundsHelper("color");
432 // This test does not work on Linux Aura because ShowInactive() is not
433 // implemented. See http://crbug.com/325142
434 // It also does not work on Windows because of the document being focused even
435 // though the window is not activated. See http://crbug.com/326986
436 // It also does not work on MacOS because ::ShowInactive() ends up behaving like
437 // ::Show() because of Cocoa conventions. See http://crbug.com/326987
438 // Those tests should be disabled on Linux GTK when they are enabled on the
439 // other platforms, see http://crbug.com/328829
440 #if (defined(OS_LINUX) && defined(USE_AURA)) || \
441 defined(OS_WIN) || defined(OS_MACOSX)
442 #define MAYBE_TestCreate DISABLED_TestCreate
443 #define MAYBE_TestShow DISABLED_TestShow
445 #define MAYBE_TestCreate TestCreate
446 #define MAYBE_TestShow TestShow
449 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
, MAYBE_TestCreate
) {
450 ASSERT_TRUE(RunAppWindowInteractiveTest("testCreate")) << message_
;
453 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
, MAYBE_TestShow
) {
454 ASSERT_TRUE(RunAppWindowInteractiveTest("testShow")) << message_
;
457 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest
, TestDrawAttention
) {
458 ASSERT_TRUE(RunAppWindowInteractiveTest("testDrawAttention")) << message_
;