Check USB device path access when prompting users to select a device.
[chromium-blink-merge.git] / chrome / browser / ui / exclusive_access / flash_fullscreen_interactive_browsertest.cc
blobef37aa5c9d3803167ca1f90fe40d134f50a7efe3
1 // Copyright 2014 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 "base/bind.h"
6 #include "base/bind_helpers.h"
7 #include "base/macros.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/time/time.h"
10 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
12 #include "chrome/browser/ui/tabs/tab_strip_model.h"
13 #include "chrome/test/base/interactive_test_utils.h"
14 #include "chrome/test/ppapi/ppapi_test.h"
15 #include "content/public/browser/render_widget_host.h"
16 #include "content/public/browser/render_widget_host_view.h"
17 #include "content/public/browser/web_contents.h"
18 #include "content/public/test/test_utils.h"
19 #include "third_party/skia/include/core/SkColor.h"
21 namespace {
23 #if defined(OS_MACOSX)
24 const bool kIsMacUI = true;
25 #else
26 const bool kIsMacUI = false;
27 #endif
29 // Runs the current MessageLoop until |condition| is true or timeout.
30 bool RunLoopUntil(const base::Callback<bool()>& condition) {
31 const base::TimeTicks start_time = base::TimeTicks::Now();
32 while (!condition.Run()) {
33 const base::TimeTicks current_time = base::TimeTicks::Now();
34 if (current_time - start_time > base::TimeDelta::FromSeconds(10)) {
35 ADD_FAILURE() << "Condition not met within ten seconds.";
36 return false;
39 base::MessageLoop::current()->PostDelayedTask(
40 FROM_HERE,
41 base::MessageLoop::QuitClosure(),
42 base::TimeDelta::FromMilliseconds(20));
43 content::RunMessageLoop();
45 return true;
48 } // namespace
50 // A BrowserTest that opens a test page that launches a simulated fullscreen
51 // Flash plugin. The plugin responds to mouse clicks and key presses by
52 // changing color. Once launched, the browser UI can be tested to confirm the
53 // desired interactive behaviors.
54 class FlashFullscreenInteractiveBrowserTest : public OutOfProcessPPAPITest {
55 public:
56 FlashFullscreenInteractiveBrowserTest() {}
57 ~FlashFullscreenInteractiveBrowserTest() override {}
59 protected:
60 content::WebContents* GetActiveWebContents() const {
61 return browser()->tab_strip_model()->GetActiveWebContents();
64 // A simple way to convince libcontent and the browser UI that a tab is being
65 // screen captured. During tab capture, Flash fullscreen remains embedded
66 // within the tab content area of a non-fullscreened browser window.
67 void StartFakingTabCapture() {
68 GetActiveWebContents()->IncrementCapturerCount(gfx::Size(360, 240));
71 bool LaunchFlashFullscreen() {
72 // This navigates to a page that runs the simulated fullscreen Flash
73 // plugin. It will block until the plugin has completed an attempt to enter
74 // Flash fullscreen mode.
75 OutOfProcessPPAPITest::RunTest("FlashFullscreenForBrowserUI");
77 if (::testing::Test::HasFailure()) {
78 ADD_FAILURE() << ("Failed to launch simulated fullscreen Flash plugin. "
79 "Interactive UI testing cannot proceed.");
80 return false;
83 EXPECT_TRUE(ObserveTabIsInFullscreen(true));
85 return !::testing::Test::HasFailure();
88 void UseAcceleratorToOpenNewTab() {
89 content::WebContents* const old_tab_contents = GetActiveWebContents();
90 EXPECT_TRUE(ui_test_utils::SendKeyPressSync(
91 browser(), ui::VKEY_T, !kIsMacUI, false, false, kIsMacUI));
92 EXPECT_TRUE(RunLoopUntil(base::Bind(
93 &FlashFullscreenInteractiveBrowserTest::IsObservingActiveWebContents,
94 base::Unretained(this),
95 old_tab_contents,
96 false)));
99 void UseAcceleratorToSwitchToTab(int tab_index) {
100 content::WebContents* const old_tab_contents = GetActiveWebContents();
101 const ui::KeyboardCode key_code =
102 static_cast<ui::KeyboardCode>(ui::VKEY_1 + tab_index);
103 EXPECT_TRUE(ui_test_utils::SendKeyPressSync(
104 browser(), key_code, !kIsMacUI, false, false, kIsMacUI));
105 EXPECT_TRUE(RunLoopUntil(base::Bind(
106 &FlashFullscreenInteractiveBrowserTest::IsObservingActiveWebContents,
107 base::Unretained(this),
108 old_tab_contents,
109 false)));
112 void PressEscape() {
113 EXPECT_TRUE(ui_test_utils::SendKeyPressSync(
114 browser(), ui::VKEY_ESCAPE, false, false, false, false));
117 void PressSpacebar() {
118 EXPECT_TRUE(ui_test_utils::SendKeyPressSync(
119 browser(), ui::VKEY_SPACE, false, false, false, false));
122 void SpamSpacebar() {
123 for (int i = 0; i < 11; ++i)
124 PressSpacebar();
127 void ClickOnTabContainer() {
128 ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER);
131 void ClickOnOmnibox() {
132 ui_test_utils::ClickOnView(browser(), VIEW_ID_OMNIBOX);
135 bool ObserveTabIsInFullscreen(bool expected_in_fullscreen) const {
136 if (!RunLoopUntil(base::Bind(
137 &FlashFullscreenInteractiveBrowserTest::IsObservingTabInFullscreen,
138 base::Unretained(this),
139 GetActiveWebContents(),
140 expected_in_fullscreen)))
141 return false;
143 if (expected_in_fullscreen) {
144 if (!GetActiveWebContents()->GetFullscreenRenderWidgetHostView()) {
145 ADD_FAILURE()
146 << "WebContents should have a fullscreen RenderWidgetHostView.";
147 return false;
149 EXPECT_EQ(GetActiveWebContents()->GetCapturerCount() > 0,
150 !browser()
151 ->exclusive_access_manager()
152 ->fullscreen_controller()
153 ->IsWindowFullscreenForTabOrPending());
156 return true;
159 bool ObserveFlashHasFocus(content::WebContents* contents,
160 bool expected_to_have_focus) const {
161 if (!RunLoopUntil(base::Bind(
162 &FlashFullscreenInteractiveBrowserTest::IsObservingFlashHasFocus,
163 base::Unretained(this),
164 contents,
165 expected_to_have_focus)))
166 return false;
168 if (expected_to_have_focus) {
169 content::RenderWidgetHostView* const web_page_view =
170 contents->GetRenderWidgetHostView();
171 EXPECT_FALSE(web_page_view && web_page_view->HasFocus())
172 << "Both RenderWidgetHostViews cannot have focus at the same time.";
174 if (contents == GetActiveWebContents())
175 EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(),
176 VIEW_ID_TAB_CONTAINER));
179 return true;
182 bool ObserveFlashFillColor(SkColor expected_color) const {
183 return RunLoopUntil(base::Bind(
184 &FlashFullscreenInteractiveBrowserTest::IsObservingFlashFillColor,
185 base::Unretained(this),
186 expected_color));
189 private:
190 bool IsObservingTabInFullscreen(content::WebContents* contents,
191 bool expected_in_fullscreen) const {
192 return expected_in_fullscreen ==
193 browser()
194 ->exclusive_access_manager()
195 ->fullscreen_controller()
196 ->IsFullscreenForTabOrPending(contents);
199 bool IsObservingFlashHasFocus(content::WebContents* contents,
200 bool expected_to_have_focus) const {
201 content::RenderWidgetHostView* const flash_fs_view =
202 contents->GetFullscreenRenderWidgetHostView();
203 const bool flash_has_focus = flash_fs_view && flash_fs_view->HasFocus();
204 return flash_has_focus == expected_to_have_focus;
207 bool IsObservingActiveWebContents(content::WebContents* contents,
208 bool expected_active_contents) const {
209 return (contents == GetActiveWebContents()) == expected_active_contents;
212 bool IsObservingFlashFillColor(SkColor expected_color) const {
213 content::RenderWidgetHostView* const flash_fs_view =
214 GetActiveWebContents()->GetFullscreenRenderWidgetHostView();
215 content::RenderWidgetHost* const flash_fs_host =
216 flash_fs_view ? flash_fs_view->GetRenderWidgetHost() : nullptr;
217 if (!flash_fs_host) {
218 ADD_FAILURE() << "Flash fullscreen RenderWidgetHost is gone.";
219 return false;
222 // When a widget is first shown, it can take some time before it is ready
223 // for copying from its backing store. This is a transient condition, and
224 // so it is not being treated as a test failure.
225 if (!flash_fs_host->CanCopyFromBackingStore())
226 return false;
228 // Copy and examine the upper-left pixel of the widget and compare it to the
229 // |expected_color|.
230 bool is_expected_color = false;
231 flash_fs_host->CopyFromBackingStore(
232 gfx::Rect(0, 0, 1, 1),
233 gfx::Size(1, 1),
234 base::Bind(
235 &FlashFullscreenInteractiveBrowserTest::CheckBitmapForFillColor,
236 expected_color,
237 &is_expected_color,
238 base::MessageLoop::QuitClosure()),
239 kN32_SkColorType);
240 content::RunMessageLoop();
242 return is_expected_color;
245 static void CheckBitmapForFillColor(SkColor expected_color,
246 bool* is_expected_color,
247 const base::Closure& done_cb,
248 const SkBitmap& bitmap,
249 content::ReadbackResponse response) {
250 if (response == content::READBACK_SUCCESS) {
251 SkAutoLockPixels lock_pixels(bitmap);
252 if (bitmap.width() > 0 && bitmap.height() > 0)
253 *is_expected_color = (bitmap.getColor(0, 0) == expected_color);
255 done_cb.Run();
258 DISALLOW_COPY_AND_ASSIGN(FlashFullscreenInteractiveBrowserTest);
261 // Tests that launching and exiting fullscreen-within-tab works.
262 IN_PROC_BROWSER_TEST_F(FlashFullscreenInteractiveBrowserTest,
263 FullscreenWithinTab_EscapeKeyExitsFullscreen) {
264 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
265 StartFakingTabCapture();
266 ASSERT_TRUE(LaunchFlashFullscreen());
267 content::WebContents* const first_tab_contents = GetActiveWebContents();
268 EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, true));
269 PressEscape();
270 EXPECT_TRUE(ObserveTabIsInFullscreen(false));
273 // This tests that browser UI focus behavior is correct when switching between
274 // tabs; particularly, that that focus between the omnibox and tab contents is
275 // stored/restored correctly. Mouse and keyboard events are used to confirm
276 // that the widget the UI thinks is focused is the one that responds to these
277 // input events.
279 // Flaky, see http://crbug.com/444476
280 IN_PROC_BROWSER_TEST_F(FlashFullscreenInteractiveBrowserTest,
281 DISABLED_FullscreenWithinTab_FocusWhenSwitchingTabs) {
282 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
283 StartFakingTabCapture();
284 ASSERT_TRUE(LaunchFlashFullscreen());
286 // Upon entering fullscreen, the Flash widget should have focus and be filled
287 // with green.
288 content::WebContents* const first_tab_contents = GetActiveWebContents();
289 EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, true));
290 ASSERT_TRUE(ObserveFlashFillColor(SK_ColorGREEN));
292 // Pressing the spacebar on the keyboard should change the fill color to red
293 // to indicate the plugin truly does have the keyboard focus. Clicking on the
294 // view should change the fill color to blue.
295 PressSpacebar();
296 ASSERT_TRUE(ObserveFlashFillColor(SK_ColorRED));
297 ClickOnTabContainer();
298 ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE));
300 // Launch a new tab. The Flash widget should have lost focus.
301 UseAcceleratorToOpenNewTab();
302 content::WebContents* const second_tab_contents = GetActiveWebContents();
303 ASSERT_NE(first_tab_contents, second_tab_contents);
304 EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, false));
305 ClickOnOmnibox();
306 EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, false));
307 SpamSpacebar();
309 // Switch back to first tab. The plugin should not have responded to the key
310 // presses above (while the omnibox was focused), and should regain focus only
311 // now. Poke it with key and mouse events to confirm.
312 UseAcceleratorToSwitchToTab(0);
313 EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, true));
314 ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE));
315 PressSpacebar();
316 ASSERT_TRUE(ObserveFlashFillColor(SK_ColorRED));
317 ClickOnTabContainer();
318 ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE));
320 // Click on the omnibox while still in the first tab, and the Flash widget
321 // should lose focus. Key presses should not affect the color of the Flash
322 // widget.
323 ClickOnOmnibox();
324 EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, false));
325 ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE));
326 SpamSpacebar();
327 ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE));
329 // Switch to the second tab, click on the web page content, and then go back
330 // to the first tab. Focus should have been restored to the omnibox when
331 // going back to the first tab, and so key presses should not change the color
332 // of the Flash widget.
333 UseAcceleratorToSwitchToTab(1);
334 EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, false));
335 ClickOnTabContainer();
336 EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, false));
337 UseAcceleratorToSwitchToTab(0);
338 EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, false));
339 ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE));
340 SpamSpacebar();
341 ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE));
343 // Clicking on the Flash widget should give it focus again.
344 ClickOnTabContainer();
345 EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, true));
346 ASSERT_TRUE(ObserveFlashFillColor(SK_ColorRED));
347 PressSpacebar();
348 ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE));
350 // Test that the Escape key is handled as an exit fullscreen command while the
351 // Flash widget has the focus.
352 EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, true));
353 PressEscape();
354 EXPECT_TRUE(ObserveTabIsInFullscreen(false));