[ExtensionToolbarMac] Restrict action button drags to the container's bounds
[chromium-blink-merge.git] / chrome / browser / apps / app_window_interactive_uitest.cc
blob1212c206c288a42012b828fc3dd48eb2c6b4d06f
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"
13 #endif
15 #if defined(OS_WIN)
16 #include <windows.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"
22 #endif
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 {
30 public:
31 explicit FullscreenChangeWaiter(NativeAppWindow* window)
32 : window_(window),
33 initial_fullscreen_state_(window_->IsFullscreen()) {}
35 void Wait() {
36 while (initial_fullscreen_state_ == window_->IsFullscreen())
37 content::RunAllPendingInMessageLoop();
40 private:
41 NativeAppWindow* window_;
42 bool initial_fullscreen_state_;
44 DISALLOW_COPY_AND_ASSIGN(FullscreenChangeWaiter);
47 class AppWindowInteractiveTest : public extensions::PlatformAppBrowserTest {
48 public:
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();
58 return false;
61 return true;
64 bool SimulateKeyPress(ui::KeyboardCode key) {
65 return ui_test_utils::SendKeyPressToWindowSync(
66 GetFirstAppWindow()->GetNativeWindow(),
67 key,
68 false,
69 false,
70 false,
71 false);
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())
92 return;
93 #endif
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");
111 fs_changed.Wait();
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.
118 WaitUntilKeyFocus();
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));
127 fs_changed.Wait();
131 #if defined(OS_MACOSX)
132 // http://crbug.com/406009
133 #define MAYBE_ESCLeavesFullscreenDOM DISABLED_ESCLeavesFullscreenDOM
134 #else
135 #define MAYBE_ESCLeavesFullscreenDOM ESCLeavesFullscreenDOM
136 #endif
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())
141 return;
142 #endif
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());
164 WaitUntilKeyFocus();
165 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_A));
167 fs_changed.Wait();
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.
174 WaitUntilKeyFocus();
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));
183 fs_changed.Wait();
187 #if defined(OS_MACOSX)
188 // http://crbug.com/406009
189 #define MAYBE_ESCDoesNotLeaveFullscreenWindow DISABLED_ESCDoesNotLeaveFullscreenWindow
190 #else
191 #define MAYBE_ESCDoesNotLeaveFullscreenWindow ESCDoesNotLeaveFullscreenWindow
192 #endif
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())
198 return;
199 #endif
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");
217 fs_changed.Wait();
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.
224 WaitUntilKeyFocus();
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
237 // is broken.
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())
246 return;
247 #endif
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());
269 WaitUntilKeyFocus();
270 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_A));
272 fs_changed.Wait();
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.
279 WaitUntilKeyFocus();
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
292 // is broken.
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())
304 return;
305 #endif
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");
323 fs_changed.Wait();
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.
330 WaitUntilKeyFocus();
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
343 // is broken.
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
350 #else
351 #define MAYBE_TestInnerBounds TestInnerBounds
352 #endif
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;
371 #if defined(OS_WIN)
372 // Get the bounds from the HWND.
373 HWND hwnd = views::HWNDForNativeWindow(window->GetNativeWindow());
374 RECT rect;
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
387 // add them.
388 gfx::Insets insets;
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()
395 : 0);
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.
408 #if !defined(OS_WIN)
409 #define MAYBE_TestOuterBoundsFrameChrome DISABLED_TestOuterBoundsFrameChrome
410 #define MAYBE_TestOuterBoundsFrameNone DISABLED_TestOuterBoundsFrameNone
411 #define MAYBE_TestOuterBoundsFrameColor DISABLED_TestOuterBoundsFrameColor
412 #else
413 #define MAYBE_TestOuterBoundsFrameChrome TestOuterBoundsFrameChrome
414 #define MAYBE_TestOuterBoundsFrameNone TestOuterBoundsFrameNone
415 #define MAYBE_TestOuterBoundsFrameColor TestOuterBoundsFrameColor
416 #endif
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
444 #else
445 #define MAYBE_TestCreate TestCreate
446 #define MAYBE_TestShow TestShow
447 #endif
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_;