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.
4
5 #include "apps/ui/native_app_window.h"
6 #include "chrome/browser/apps/app_browsertest_util.h"
7 #include "chrome/browser/extensions/extension_test_message_listener.h"
8 #include "chrome/test/base/interactive_test_utils.h"
9
10 #if defined(OS_MACOSX) && !defined(OS_IOS)
11 #include "base/mac/mac_util.h"
12 #endif
13
14 using apps::NativeAppWindow;
15
16 // Helper class that has to be created in the stack to check if the fullscreen
17 // setting of a NativeWindow has changed since the creation of the object.
18 class FullscreenChangeWaiter {
19 public:
FullscreenChangeWaiter(NativeAppWindow * window)20 explicit FullscreenChangeWaiter(NativeAppWindow* window)
21 : window_(window),
22 initial_fullscreen_state_(window_->IsFullscreen()) {}
23
Wait()24 void Wait() {
25 while (initial_fullscreen_state_ == window_->IsFullscreen())
26 content::RunAllPendingInMessageLoop();
27 }
28
29 private:
30 NativeAppWindow* window_;
31 bool initial_fullscreen_state_;
32
33 DISALLOW_COPY_AND_ASSIGN(FullscreenChangeWaiter);
34 };
35
36 class AppWindowInteractiveTest : public extensions::PlatformAppBrowserTest {
37 public:
RunAppWindowInteractiveTest(const char * testName)38 bool RunAppWindowInteractiveTest(const char* testName) {
39 ExtensionTestMessageListener launched_listener("Launched", true);
40 LoadAndLaunchPlatformApp("window_api_interactive", &launched_listener);
41
42 ResultCatcher catcher;
43 launched_listener.Reply(testName);
44
45 if (!catcher.GetNextResult()) {
46 message_ = catcher.message();
47 return false;
48 }
49
50 return true;
51 }
52
SimulateKeyPress(ui::KeyboardCode key)53 bool SimulateKeyPress(ui::KeyboardCode key) {
54 return ui_test_utils::SendKeyPressToWindowSync(
55 GetFirstAppWindow()->GetNativeWindow(),
56 key,
57 false,
58 false,
59 false,
60 false);
61 }
62
63 // This method will wait until the application is able to ack a key event.
WaitUntilKeyFocus()64 void WaitUntilKeyFocus() {
65 ExtensionTestMessageListener key_listener("KeyReceived", false);
66
67 while (!key_listener.was_satisfied()) {
68 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_Z));
69 content::RunAllPendingInMessageLoop();
70 }
71 }
72 };
73
IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest,ESCLeavesFullscreenWindow)74 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest, ESCLeavesFullscreenWindow) {
75 // This test is flaky on MacOS 10.6.
76 #if defined(OS_MACOSX) && !defined(OS_IOS)
77 if (base::mac::IsOSSnowLeopard())
78 return;
79 #endif
80
81 ExtensionTestMessageListener launched_listener("Launched", true);
82 LoadAndLaunchPlatformApp("leave_fullscreen", &launched_listener);
83
84 // We start by making sure the window is actually focused.
85 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
86 GetFirstAppWindow()->GetNativeWindow()));
87
88 // When receiving the reply, the application will try to go fullscreen using
89 // the Window API but there is no synchronous way to know if that actually
90 // succeeded. Also, failure will not be notified. A failure case will only be
91 // known with a timeout.
92 {
93 FullscreenChangeWaiter fs_changed(GetFirstAppWindow()->GetBaseWindow());
94
95 launched_listener.Reply("window");
96
97 fs_changed.Wait();
98 }
99
100 // Depending on the platform, going fullscreen might create an animation.
101 // We want to make sure that the ESC key we will send next is actually going
102 // to be received and the application might not receive key events during the
103 // animation so we should wait for the key focus to be back.
104 WaitUntilKeyFocus();
105
106 // Same idea as above but for leaving fullscreen. Fullscreen mode should be
107 // left when ESC is received.
108 {
109 FullscreenChangeWaiter fs_changed(GetFirstAppWindow()->GetBaseWindow());
110
111 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_ESCAPE));
112
113 fs_changed.Wait();
114 }
115 }
116
IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest,ESCLeavesFullscreenDOM)117 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest, ESCLeavesFullscreenDOM) {
118 // This test is flaky on MacOS 10.6.
119 #if defined(OS_MACOSX) && !defined(OS_IOS)
120 if (base::mac::IsOSSnowLeopard())
121 return;
122 #endif
123
124 ExtensionTestMessageListener launched_listener("Launched", true);
125 LoadAndLaunchPlatformApp("leave_fullscreen", &launched_listener);
126
127 // We start by making sure the window is actually focused.
128 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
129 GetFirstAppWindow()->GetNativeWindow()));
130
131 launched_listener.Reply("dom");
132
133 // Because the DOM way to go fullscreen requires user gesture, we simulate a
134 // key event to get the window entering in fullscreen mode. The reply will
135 // make the window listen for the key event. The reply will be sent to the
136 // renderer process before the keypress and should be received in that order.
137 // When receiving the key event, the application will try to go fullscreen
138 // using the Window API but there is no synchronous way to know if that
139 // actually succeeded. Also, failure will not be notified. A failure case will
140 // only be known with a timeout.
141 {
142 FullscreenChangeWaiter fs_changed(GetFirstAppWindow()->GetBaseWindow());
143
144 WaitUntilKeyFocus();
145 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_A));
146
147 fs_changed.Wait();
148 }
149
150 // Depending on the platform, going fullscreen might create an animation.
151 // We want to make sure that the ESC key we will send next is actually going
152 // to be received and the application might not receive key events during the
153 // animation so we should wait for the key focus to be back.
154 WaitUntilKeyFocus();
155
156 // Same idea as above but for leaving fullscreen. Fullscreen mode should be
157 // left when ESC is received.
158 {
159 FullscreenChangeWaiter fs_changed(GetFirstAppWindow()->GetBaseWindow());
160
161 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_ESCAPE));
162
163 fs_changed.Wait();
164 }
165 }
166
IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest,ESCDoesNotLeaveFullscreenWindow)167 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest,
168 ESCDoesNotLeaveFullscreenWindow) {
169 // This test is flaky on MacOS 10.6.
170 #if defined(OS_MACOSX) && !defined(OS_IOS)
171 if (base::mac::IsOSSnowLeopard())
172 return;
173 #endif
174
175 ExtensionTestMessageListener launched_listener("Launched", true);
176 LoadAndLaunchPlatformApp("prevent_leave_fullscreen", &launched_listener);
177
178 // We start by making sure the window is actually focused.
179 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
180 GetFirstAppWindow()->GetNativeWindow()));
181
182 // When receiving the reply, the application will try to go fullscreen using
183 // the Window API but there is no synchronous way to know if that actually
184 // succeeded. Also, failure will not be notified. A failure case will only be
185 // known with a timeout.
186 {
187 FullscreenChangeWaiter fs_changed(GetFirstAppWindow()->GetBaseWindow());
188
189 launched_listener.Reply("window");
190
191 fs_changed.Wait();
192 }
193
194 // Depending on the platform, going fullscreen might create an animation.
195 // We want to make sure that the ESC key we will send next is actually going
196 // to be received and the application might not receive key events during the
197 // animation so we should wait for the key focus to be back.
198 WaitUntilKeyFocus();
199
200 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_ESCAPE));
201
202 ExtensionTestMessageListener second_key_listener("B_KEY_RECEIVED", false);
203
204 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_B));
205
206 ASSERT_TRUE(second_key_listener.WaitUntilSatisfied());
207
208 // We assume that at that point, if we had to leave fullscreen, we should be.
209 // However, by nature, we can not guarantee that and given that we do test
210 // that nothing happens, we might end up with random-success when the feature
211 // is broken.
212 EXPECT_TRUE(GetFirstAppWindow()->GetBaseWindow()->IsFullscreen());
213 }
214
IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest,ESCDoesNotLeaveFullscreenDOM)215 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest,
216 ESCDoesNotLeaveFullscreenDOM) {
217 // This test is flaky on MacOS 10.6.
218 #if defined(OS_MACOSX) && !defined(OS_IOS)
219 if (base::mac::IsOSSnowLeopard())
220 return;
221 #endif
222
223 ExtensionTestMessageListener launched_listener("Launched", true);
224 LoadAndLaunchPlatformApp("prevent_leave_fullscreen", &launched_listener);
225
226 // We start by making sure the window is actually focused.
227 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
228 GetFirstAppWindow()->GetNativeWindow()));
229
230 launched_listener.Reply("dom");
231
232 // Because the DOM way to go fullscreen requires user gesture, we simulate a
233 // key event to get the window entering in fullscreen mode. The reply will
234 // make the window listen for the key event. The reply will be sent to the
235 // renderer process before the keypress and should be received in that order.
236 // When receiving the key event, the application will try to go fullscreen
237 // using the Window API but there is no synchronous way to know if that
238 // actually succeeded. Also, failure will not be notified. A failure case will
239 // only be known with a timeout.
240 {
241 FullscreenChangeWaiter fs_changed(GetFirstAppWindow()->GetBaseWindow());
242
243 WaitUntilKeyFocus();
244 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_A));
245
246 fs_changed.Wait();
247 }
248
249 // Depending on the platform, going fullscreen might create an animation.
250 // We want to make sure that the ESC key we will send next is actually going
251 // to be received and the application might not receive key events during the
252 // animation so we should wait for the key focus to be back.
253 WaitUntilKeyFocus();
254
255 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_ESCAPE));
256
257 ExtensionTestMessageListener second_key_listener("B_KEY_RECEIVED", false);
258
259 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_B));
260
261 ASSERT_TRUE(second_key_listener.WaitUntilSatisfied());
262
263 // We assume that at that point, if we had to leave fullscreen, we should be.
264 // However, by nature, we can not guarantee that and given that we do test
265 // that nothing happens, we might end up with random-success when the feature
266 // is broken.
267 EXPECT_TRUE(GetFirstAppWindow()->GetBaseWindow()->IsFullscreen());
268 }
269
270 // This test is duplicated from ESCDoesNotLeaveFullscreenWindow.
271 // It runs the same test, but uses the old permission names: 'fullscreen'
272 // and 'overrideEscFullscreen'.
IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest,ESCDoesNotLeaveFullscreenOldPermission)273 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest,
274 ESCDoesNotLeaveFullscreenOldPermission) {
275 // This test is flaky on MacOS 10.6.
276 #if defined(OS_MACOSX) && !defined(OS_IOS)
277 if (base::mac::IsOSSnowLeopard())
278 return;
279 #endif
280
281 ExtensionTestMessageListener launched_listener("Launched", true);
282 LoadAndLaunchPlatformApp("prevent_leave_fullscreen_old", &launched_listener);
283
284 // We start by making sure the window is actually focused.
285 ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
286 GetFirstAppWindow()->GetNativeWindow()));
287
288 // When receiving the reply, the application will try to go fullscreen using
289 // the Window API but there is no synchronous way to know if that actually
290 // succeeded. Also, failure will not be notified. A failure case will only be
291 // known with a timeout.
292 {
293 FullscreenChangeWaiter fs_changed(GetFirstAppWindow()->GetBaseWindow());
294
295 launched_listener.Reply("window");
296
297 fs_changed.Wait();
298 }
299
300 // Depending on the platform, going fullscreen might create an animation.
301 // We want to make sure that the ESC key we will send next is actually going
302 // to be received and the application might not receive key events during the
303 // animation so we should wait for the key focus to be back.
304 WaitUntilKeyFocus();
305
306 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_ESCAPE));
307
308 ExtensionTestMessageListener second_key_listener("B_KEY_RECEIVED", false);
309
310 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_B));
311
312 ASSERT_TRUE(second_key_listener.WaitUntilSatisfied());
313
314 // We assume that at that point, if we had to leave fullscreen, we should be.
315 // However, by nature, we can not guarantee that and given that we do test
316 // that nothing happens, we might end up with random-success when the feature
317 // is broken.
318 EXPECT_TRUE(GetFirstAppWindow()->GetBaseWindow()->IsFullscreen());
319 }
320
321 // This test does not work on Linux Aura because ShowInactive() is not
322 // implemented. See http://crbug.com/325142
323 // It also does not work on Windows because of the document being focused even
324 // though the window is not activated. See http://crbug.com/326986
325 // It also does not work on MacOS because ::ShowInactive() ends up behaving like
326 // ::Show() because of Cocoa conventions. See http://crbug.com/326987
327 // Those tests should be disabled on Linux GTK when they are enabled on the
328 // other platforms, see http://crbug.com/328829
329 #if (defined(OS_LINUX) && defined(USE_AURA)) || \
330 defined(OS_WIN) || defined(OS_MACOSX)
331 #define MAYBE_TestCreate DISABLED_TestCreate
332 #define MAYBE_TestShow DISABLED_TestShow
333 #else
334 #define MAYBE_TestCreate TestCreate
335 #define MAYBE_TestShow TestShow
336 #endif
337
IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest,MAYBE_TestCreate)338 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest, MAYBE_TestCreate) {
339 ASSERT_TRUE(RunAppWindowInteractiveTest("testCreate")) << message_;
340 }
341
IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest,MAYBE_TestShow)342 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest, MAYBE_TestShow) {
343 ASSERT_TRUE(RunAppWindowInteractiveTest("testShow")) << message_;
344 }
345