Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(155)

Side by Side Diff: chrome/browser/site_per_process_interactive_browsertest.cc

Issue 2008873004: Reland: Add support for entering/exiting HTML fullscreen from OOPIFs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix tests on Mac Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | content/browser/frame_host/render_frame_host_impl.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/command_line.h" 5 #include "base/command_line.h"
6 #include "base/strings/string_number_conversions.h"
6 #include "chrome/browser/ui/browser.h" 7 #include "chrome/browser/ui/browser.h"
8 #include "chrome/browser/ui/browser_window.h"
9 #include "chrome/browser/ui/exclusive_access/fullscreen_controller_test.h"
7 #include "chrome/browser/ui/tabs/tab_strip_model.h" 10 #include "chrome/browser/ui/tabs/tab_strip_model.h"
8 #include "chrome/test/base/in_process_browser_test.h" 11 #include "chrome/test/base/in_process_browser_test.h"
12 #include "chrome/test/base/interactive_test_utils.h"
9 #include "chrome/test/base/ui_test_utils.h" 13 #include "chrome/test/base/ui_test_utils.h"
10 #include "content/public/browser/render_frame_host.h" 14 #include "content/public/browser/render_frame_host.h"
15 #include "content/public/browser/render_widget_host_view.h"
11 #include "content/public/browser/web_contents.h" 16 #include "content/public/browser/web_contents.h"
12 #include "content/public/test/browser_test_utils.h" 17 #include "content/public/test/browser_test_utils.h"
13 #include "content/public/test/content_browser_test_utils.h" 18 #include "content/public/test/content_browser_test_utils.h"
19 #include "content/public/test/test_navigation_observer.h"
14 #include "content/public/test/test_utils.h" 20 #include "content/public/test/test_utils.h"
15 #include "net/dns/mock_host_resolver.h" 21 #include "net/dns/mock_host_resolver.h"
16 #include "net/test/embedded_test_server/embedded_test_server.h" 22 #include "net/test/embedded_test_server/embedded_test_server.h"
23 #include "ui/display/display.h"
24 #include "ui/display/screen.h"
17 #include "url/gurl.h" 25 #include "url/gurl.h"
18 26
19 class SitePerProcessInteractiveBrowserTest : public InProcessBrowserTest { 27 class SitePerProcessInteractiveBrowserTest : public InProcessBrowserTest {
20 public: 28 public:
21 SitePerProcessInteractiveBrowserTest() {} 29 SitePerProcessInteractiveBrowserTest() {}
22 ~SitePerProcessInteractiveBrowserTest() override {} 30 ~SitePerProcessInteractiveBrowserTest() override {}
23 31
24 void SetUpCommandLine(base::CommandLine* command_line) override { 32 void SetUpCommandLine(base::CommandLine* command_line) override {
25 content::IsolateAllSitesForTesting(command_line); 33 content::IsolateAllSitesForTesting(command_line);
26 } 34 }
27 35
28 void SetUpOnMainThread() override { 36 void SetUpOnMainThread() override {
29 host_resolver()->AddRule("*", "127.0.0.1"); 37 host_resolver()->AddRule("*", "127.0.0.1");
30 38
31 // Add content/test/data for cross_site_iframe_factory.html 39 // Add content/test/data for cross_site_iframe_factory.html
32 embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data"); 40 embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
33 41
34 ASSERT_TRUE(embedded_test_server()->Start()); 42 ASSERT_TRUE(embedded_test_server()->Start());
35 } 43 }
36 44
45 gfx::Size GetScreenSize() {
46 content::WebContents* web_contents =
47 browser()->tab_strip_model()->GetActiveWebContents();
48 const display::Display display =
49 display::Screen::GetScreen()->GetDisplayNearestWindow(
50 web_contents->GetRenderWidgetHostView()->GetNativeView());
51 return display.bounds().size();
52 }
53
37 private: 54 private:
38 DISALLOW_COPY_AND_ASSIGN(SitePerProcessInteractiveBrowserTest); 55 DISALLOW_COPY_AND_ASSIGN(SitePerProcessInteractiveBrowserTest);
39 }; 56 };
40 57
41 // Check that document.hasFocus() works properly with out-of-process iframes. 58 // Check that document.hasFocus() works properly with out-of-process iframes.
42 // The test builds a page with four cross-site frames and then focuses them one 59 // The test builds a page with four cross-site frames and then focuses them one
43 // by one, checking the value of document.hasFocus() in all frames. For any 60 // by one, checking the value of document.hasFocus() in all frames. For any
44 // given focused frame, document.hasFocus() should return true for that frame 61 // given focused frame, document.hasFocus() should return true for that frame
45 // and all its ancestor frames. 62 // and all its ancestor frames.
46 IN_PROC_BROWSER_TEST_F(SitePerProcessInteractiveBrowserTest, DocumentHasFocus) { 63 IN_PROC_BROWSER_TEST_F(SitePerProcessInteractiveBrowserTest, DocumentHasFocus) {
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
225 EXPECT_EQ("\"child2-focused-input2\"", press_tab_and_wait_for_message(true)); 242 EXPECT_EQ("\"child2-focused-input2\"", press_tab_and_wait_for_message(true));
226 EXPECT_EQ(child2, web_contents->GetFocusedFrame()); 243 EXPECT_EQ(child2, web_contents->GetFocusedFrame());
227 EXPECT_EQ("\"child2-focused-input1\"", press_tab_and_wait_for_message(true)); 244 EXPECT_EQ("\"child2-focused-input1\"", press_tab_and_wait_for_message(true));
228 EXPECT_EQ("\"child1-focused-input2\"", press_tab_and_wait_for_message(true)); 245 EXPECT_EQ("\"child1-focused-input2\"", press_tab_and_wait_for_message(true));
229 EXPECT_EQ(child1, web_contents->GetFocusedFrame()); 246 EXPECT_EQ(child1, web_contents->GetFocusedFrame());
230 EXPECT_EQ("\"child1-focused-input1\"", press_tab_and_wait_for_message(true)); 247 EXPECT_EQ("\"child1-focused-input1\"", press_tab_and_wait_for_message(true));
231 EXPECT_EQ("\"root-focused-input1\"", press_tab_and_wait_for_message(true)); 248 EXPECT_EQ("\"root-focused-input1\"", press_tab_and_wait_for_message(true));
232 EXPECT_EQ(main_frame, web_contents->GetFocusedFrame()); 249 EXPECT_EQ(main_frame, web_contents->GetFocusedFrame());
233 } 250 }
234 251
252 namespace {
253
254 // Helper to retrieve the frame's (window.innerWidth, window.innerHeight).
255 gfx::Size GetFrameSize(content::RenderFrameHost* frame) {
256 int width = 0;
257 EXPECT_TRUE(ExecuteScriptAndExtractInt(
258 frame, "domAutomationController.send(window.innerWidth);", &width));
259
260 int height = 0;
261 EXPECT_TRUE(ExecuteScriptAndExtractInt(
262 frame, "domAutomationController.send(window.innerHeight);", &height));
263
264 return gfx::Size(width, height);
265 }
266
267 // Helper to check |frame|'s document.webkitFullscreenElement and return its ID
268 // if it's defined (which is the case when |frame| is in fullscreen mode), or
269 // "none" otherwise.
270 std::string GetFullscreenElementId(content::RenderFrameHost* frame) {
271 std::string fullscreen_element;
272 EXPECT_TRUE(ExecuteScriptAndExtractString(
273 frame,
274 "domAutomationController.send("
275 " document.webkitFullscreenElement ? "
276 " document.webkitFullscreenElement.id : 'none')",
277 &fullscreen_element));
278 return fullscreen_element;
279 }
280
281 // Helper to check if an element with ID |element_id| has the
282 // :-webkit-full-screen style.
283 bool ElementHasFullscreenStyle(content::RenderFrameHost* frame,
284 const std::string& element_id) {
285 bool has_style = false;
286 std::string script = base::StringPrintf(
287 "domAutomationController.send("
288 " document.querySelectorAll('#%s:-webkit-full-screen').length == 1)",
289 element_id.c_str());
290 EXPECT_TRUE(ExecuteScriptAndExtractBool(frame, script, &has_style));
291 return has_style;
292 }
293
294 // Helper to check if an element with ID |element_id| has the
295 // :-webkit-full-screen-ancestor style.
296 bool ElementHasFullscreenAncestorStyle(content::RenderFrameHost* host,
297 const std::string& element_id) {
298 bool has_style = false;
299 std::string script = base::StringPrintf(
300 "domAutomationController.send("
301 " document.querySelectorAll("
302 " '#%s:-webkit-full-screen-ancestor').length == 1)",
303 element_id.c_str());
304 EXPECT_TRUE(ExecuteScriptAndExtractBool(host, script, &has_style));
305 return has_style;
306 }
307
308 // Set the allowFullscreen attribute on the <iframe> element identified by
309 // |frame_id|.
310 void SetAllowFullscreenForFrame(content::RenderFrameHost* host,
311 const std::string& frame_id) {
312 EXPECT_TRUE(ExecuteScript(
313 host, base::StringPrintf(
314 "document.getElementById('%s').allowFullscreen = true;",
315 frame_id.c_str())));
316 }
317
318 // Add a listener that will send back a message whenever the (prefixed)
319 // fullscreenchange event fires. The message will be "fullscreenchange",
320 // followed by a space and the provided |id|.
321 void AddFullscreenChangeListener(content::RenderFrameHost* frame,
322 const std::string& id) {
323 std::string script = base::StringPrintf(
324 "document.addEventListener('webkitfullscreenchange', function() {"
325 " domAutomationController.setAutomationId(0);"
326 " domAutomationController.send('fullscreenchange %s');});",
327 id.c_str());
328 EXPECT_TRUE(ExecuteScript(frame, script));
329 }
330
331 // Helper to add a listener that will send back a "resize" message when the
332 // target |frame| is resized to |expected_size|.
333 void AddResizeListener(content::RenderFrameHost* frame,
334 const gfx::Size& expected_size) {
335 std::string script =
336 base::StringPrintf("addResizeListener(%d, %d);",
337 expected_size.width(), expected_size.height());
338 EXPECT_TRUE(ExecuteScript(frame, script));
339 }
340
341 // Helper to wait for a toggle fullscreen operation to complete in all affected
342 // frames. This means waiting for:
343 // 1. All fullscreenchange events with id's matching the list in
344 // |expected_fullscreen_event_ids|. Typically the list will correspond to
345 // events from the actual fullscreen element and all of its ancestor
346 // <iframe> elements.
347 // 2. A resize event. This will verify that the frame containing the
348 // fullscreen element is properly resized. This assumes that the expected
349 // size is already registered via AddResizeListener().
350 void WaitForMultipleFullscreenEvents(
351 const std::set<std::string>& expected_fullscreen_event_ids,
352 content::DOMMessageQueue& queue) {
353 std::set<std::string> remaining_events(expected_fullscreen_event_ids);
354 bool resize_validated = false;
355 std::string response;
356 while (queue.WaitForMessage(&response)) {
357 base::TrimString(response, "\"", &response);
358 std::vector<std::string> response_params = base::SplitString(
359 response, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
360 if (response_params[0] == "fullscreenchange") {
361 EXPECT_TRUE(ContainsKey(remaining_events, response_params[1]));
362 remaining_events.erase(response_params[1]);
363 } else if (response_params[0] == "resize") {
364 resize_validated = true;
365 }
366 if (remaining_events.empty() && resize_validated)
367 break;
368 }
369 }
370
371 } // namespace
372
373 // Check that an element in a cross-process subframe can enter and exit
374 // fullscreen. The test will verify that:
375 // - the subframe is properly resized
376 // - the WebContents properly enters/exits fullscreen.
377 // - document.webkitFullscreenElement is correctly updated in both frames.
378 // - fullscreenchange events fire in both frames.
379 // - fullscreen CSS is applied correctly in both frames.
380 IN_PROC_BROWSER_TEST_F(SitePerProcessInteractiveBrowserTest,
381 FullscreenElementInSubframe) {
382 // Start on a page with one subframe (id "child-0") that has
383 // "allowfullscreen" enabled.
384 GURL main_url(embedded_test_server()->GetURL(
385 "a.com", "/page_with_allowfullscreen_frame.html"));
386 ui_test_utils::NavigateToURL(browser(), main_url);
387 content::WebContents* web_contents =
388 browser()->tab_strip_model()->GetActiveWebContents();
389
390 // Navigate the subframe cross-site to a page with a fullscreenable <div>.
391 GURL frame_url(
392 embedded_test_server()->GetURL("b.com", "/fullscreen_frame.html"));
393 EXPECT_TRUE(NavigateIframeToURL(web_contents, "child-0", frame_url));
394
395 content::RenderFrameHost* main_frame = web_contents->GetMainFrame();
396 content::RenderFrameHost* child = ChildFrameAt(main_frame, 0);
397 gfx::Size original_child_size = GetFrameSize(child);
398
399 // Fullscreen the <div> inside the cross-site child frame. Wait until:
400 // (1) the fullscreenchange events in main frame and child send a response,
401 // (2) the child frame is resized to fill the whole screen.
402 // (3) the browser has finished the fullscreen transition.
403 AddFullscreenChangeListener(main_frame, "main_frame");
404 AddFullscreenChangeListener(child, "child");
405 std::set<std::string> expected_events = {"main_frame", "child"};
406 AddResizeListener(child, GetScreenSize());
407 {
408 content::DOMMessageQueue queue;
409 std::unique_ptr<FullscreenNotificationObserver> observer(
410 new FullscreenNotificationObserver());
411 EXPECT_TRUE(ExecuteScript(child, "activateFullscreen()"));
412 WaitForMultipleFullscreenEvents(expected_events, queue);
413 observer->Wait();
414 }
415
416 // Verify that the browser has entered fullscreen for the current tab.
417 EXPECT_TRUE(browser()->window()->IsFullscreen());
418 EXPECT_TRUE(browser()->exclusive_access_manager()
419 ->fullscreen_controller()
420 ->IsFullscreenForTabOrPending(web_contents));
421
422 // Verify that the <div> has fullscreen style (:-webkit-full-screen) in the
423 // subframe.
424 EXPECT_TRUE(ElementHasFullscreenStyle(child, "fullscreen-div"));
425
426 // Verify that the main frame has applied proper fullscreen styles to the
427 // <iframe> element (:-webkit-full-screen and :-webkit-full-screen-ancestor).
428 // This is what causes the <iframe> to stretch and fill the whole viewport.
429 EXPECT_TRUE(ElementHasFullscreenStyle(main_frame, "child-0"));
430 EXPECT_TRUE(ElementHasFullscreenAncestorStyle(main_frame, "child-0"));
431
432 // Check document.webkitFullscreenElement. For main frame, it should point
433 // to the subframe, and for subframe, it should point to the fullscreened
434 // <div>.
435 EXPECT_EQ("child-0", GetFullscreenElementId(main_frame));
436 EXPECT_EQ("fullscreen-div", GetFullscreenElementId(child));
437
438 // Now exit fullscreen from the subframe. Wait for two fullscreenchange
439 // events from both frames, and also for the child to be resized to its
440 // original size.
441 AddResizeListener(child, original_child_size);
442 {
443 content::DOMMessageQueue queue;
444 std::unique_ptr<FullscreenNotificationObserver> observer(
445 new FullscreenNotificationObserver());
446 EXPECT_TRUE(ExecuteScript(child, "exitFullscreen()"));
447 WaitForMultipleFullscreenEvents(expected_events, queue);
448 observer->Wait();
449 }
450
451 EXPECT_FALSE(browser()->window()->IsFullscreen());
452
453 // Verify that the fullscreen styles were removed from the <div> and its
454 // container <iframe>.
455 EXPECT_FALSE(ElementHasFullscreenStyle(child, "fullscreen-div"));
456 EXPECT_FALSE(ElementHasFullscreenStyle(main_frame, "child-0"));
457 EXPECT_FALSE(ElementHasFullscreenAncestorStyle(main_frame, "child-0"));
458
459 // Check that both frames cleared their document.webkitFullscreenElement.
460 EXPECT_EQ("none", GetFullscreenElementId(main_frame));
461 EXPECT_EQ("none", GetFullscreenElementId(child));
462 }
463
464 // Check that on a page with A-embed-B-embed-A frame hierarchy, an element in
465 // the bottom frame can enter and exit fullscreen.
466 //
467 // TODO(alexmos): For now, the test will verify sizing and fullscreen CSS
468 // styles, but additional refactoring of Blink's Fullscreen class is required
469 // to fully handle fullscreenchange events and webkitFullscreenElement in the
470 // main frame.
471 IN_PROC_BROWSER_TEST_F(SitePerProcessInteractiveBrowserTest,
472 FullscreenElementInABA) {
473 GURL main_url(embedded_test_server()->GetURL(
474 "a.com", "/cross_site_iframe_factory.html?a(b(a))"));
475 ui_test_utils::NavigateToURL(browser(), main_url);
476 content::WebContents* web_contents =
477 browser()->tab_strip_model()->GetActiveWebContents();
478
479 content::RenderFrameHost* main_frame = web_contents->GetMainFrame();
480 content::RenderFrameHost* child = ChildFrameAt(main_frame, 0);
481 content::RenderFrameHost* grandchild = ChildFrameAt(child, 0);
482
483 // Navigate the bottom frame to a page that has a fullscreenable <div>.
484 content::TestNavigationObserver observer(web_contents);
485 EXPECT_TRUE(
486 ExecuteScript(grandchild, "location.href = '/fullscreen_frame.html'"));
487 observer.Wait();
488 EXPECT_EQ(embedded_test_server()->GetURL("a.com", "/fullscreen_frame.html"),
489 grandchild->GetLastCommittedURL());
490
491 // Add allowFullscreen attribute to both <iframe> elements.
492 SetAllowFullscreenForFrame(main_frame, "child-0");
493 SetAllowFullscreenForFrame(child, "child-0");
494
495 // Make fullscreenchange events in all three frames send a message.
496 AddFullscreenChangeListener(main_frame, "main_frame");
497 AddFullscreenChangeListener(child, "child");
498 AddFullscreenChangeListener(grandchild, "grandchild");
499
500 // Add a resize event handler that will send a message when the grandchild
501 // frame is resized to the screen size. Also save its original size.
502 AddResizeListener(grandchild, GetScreenSize());
503 gfx::Size original_grandchild_size = GetFrameSize(grandchild);
504
505 // Fullscreen a <div> inside the bottom subframe. This will block until
506 // (1) the fullscreenchange events in all frames send a response, and
507 // (2) the frame is resized to fill the whole screen.
508 // (3) the browser has finished the fullscreen transition.
509 //
510 // TODO(alexmos): Also wait for "main_frame" once
511 // blink::Fullscreen::requestFullscreen() and exitFullscreen() are fixed to
512 // process all local ancestors.
513 std::set<std::string> expected_events = {"child", "grandchild"};
514 {
515 content::DOMMessageQueue queue;
516 std::unique_ptr<FullscreenNotificationObserver> observer(
517 new FullscreenNotificationObserver());
518 EXPECT_TRUE(ExecuteScript(grandchild, "activateFullscreen()"));
519 WaitForMultipleFullscreenEvents(expected_events, queue);
520 observer->Wait();
521 }
522
523 // Verify that the browser has entered fullscreen for the current tab.
524 EXPECT_TRUE(browser()->window()->IsFullscreen());
525 EXPECT_TRUE(browser()->exclusive_access_manager()
526 ->fullscreen_controller()
527 ->IsFullscreenForTabOrPending(web_contents));
528
529 // Verify that the <div> has fullscreen style in the bottom frame, and that
530 // the proper <iframe> elements have fullscreen style in its ancestor frames.
531 EXPECT_TRUE(ElementHasFullscreenStyle(grandchild, "fullscreen-div"));
532 EXPECT_TRUE(ElementHasFullscreenStyle(child, "child-0"));
533 EXPECT_TRUE(ElementHasFullscreenAncestorStyle(child, "child-0"));
534 EXPECT_TRUE(ElementHasFullscreenStyle(main_frame, "child-0"));
535 EXPECT_TRUE(ElementHasFullscreenAncestorStyle(main_frame, "child-0"));
536
537 // Check document.webkitFullscreenElement in all frames.
538 EXPECT_EQ("child-0", GetFullscreenElementId(child));
539 EXPECT_EQ("fullscreen-div", GetFullscreenElementId(grandchild));
540 // TODO(alexmos): Also check that |main_frame|'s webkitFullscreenElement is
541 // "child-0" once blink::Fullscreen::requestFullscreen() is fixed to handle
542 // all local ancestors.
543
544 // Now exit fullscreen from the subframe.
545 AddResizeListener(grandchild, original_grandchild_size);
546 {
547 content::DOMMessageQueue queue;
548 std::unique_ptr<FullscreenNotificationObserver> observer(
549 new FullscreenNotificationObserver());
550 EXPECT_TRUE(ExecuteScript(grandchild, "exitFullscreen()"));
551 WaitForMultipleFullscreenEvents(expected_events, queue);
552 observer->Wait();
553 }
554
555 EXPECT_FALSE(browser()->window()->IsFullscreen());
556
557 // Verify that the fullscreen styles were removed from the <div> and its
558 // container <iframe>'s.
559 EXPECT_FALSE(ElementHasFullscreenStyle(grandchild, "fullscreen-div"));
560 EXPECT_FALSE(ElementHasFullscreenStyle(child, "child-0"));
561 EXPECT_FALSE(ElementHasFullscreenAncestorStyle(child, "child-0"));
562 EXPECT_FALSE(ElementHasFullscreenStyle(main_frame, "child-0"));
563 EXPECT_FALSE(ElementHasFullscreenAncestorStyle(main_frame, "child-0"));
564
565 // Check that document.webkitFullscreenElement was cleared in all three
566 // frames.
567 EXPECT_EQ("none", GetFullscreenElementId(main_frame));
568 EXPECT_EQ("none", GetFullscreenElementId(child));
569 EXPECT_EQ("none", GetFullscreenElementId(grandchild));
570 }
571
572 // Check that fullscreen works on a more complex page hierarchy with multiple
573 // local and remote ancestors. The test uses this frame tree:
574 //
575 // A (a_top)
576 // |
577 // A (a_bottom)
578 // / \ .
579 // (b_first) B B (b_second)
580 // |
581 // C (c_top)
582 // |
583 // C (c_middle) <- fullscreen target
584 // |
585 // C (c_bottom)
586 //
587 // The c_middle frame will trigger fullscreen for its <div> element. The test
588 // verifies that its ancestor chain is properly updated for fullscreen, and
589 // that the b_first node that's not on the chain is not affected.
590 //
591 // The test also exits fullscreen by simulating pressing ESC rather than using
592 // document.webkitExitFullscreen(), which tests the browser-initiated
593 // fullscreen exit path.
594 IN_PROC_BROWSER_TEST_F(SitePerProcessInteractiveBrowserTest,
595 FullscreenElementInMultipleSubframes) {
596 GURL main_url(embedded_test_server()->GetURL(
597 "a.com", "/cross_site_iframe_factory.html?a(a(b,b(c(c))))"));
598 ui_test_utils::NavigateToURL(browser(), main_url);
599 content::WebContents* web_contents =
600 browser()->tab_strip_model()->GetActiveWebContents();
601
602 content::RenderFrameHost* a_top = web_contents->GetMainFrame();
603 content::RenderFrameHost* a_bottom = ChildFrameAt(a_top, 0);
604 content::RenderFrameHost* b_first = ChildFrameAt(a_bottom, 0);
605 content::RenderFrameHost* b_second = ChildFrameAt(a_bottom, 1);
606 content::RenderFrameHost* c_top = ChildFrameAt(b_second, 0);
607 content::RenderFrameHost* c_middle = ChildFrameAt(c_top, 0);
608
609 // Allow fullscreen in all iframes descending to |c_middle|. This relies on
610 // IDs that cross_site_iframe_factory assigns to child frames.
611 SetAllowFullscreenForFrame(a_top, "child-0");
612 SetAllowFullscreenForFrame(a_bottom, "child-1");
613 SetAllowFullscreenForFrame(b_second, "child-0");
614 SetAllowFullscreenForFrame(c_top, "child-0");
615
616 // Navigate |c_middle| to a page that has a fullscreenable <div> and another
617 // frame.
618 content::TestNavigationObserver observer(web_contents);
619 EXPECT_TRUE(
620 ExecuteScript(c_middle, "location.href = '/fullscreen_frame.html'"));
621 observer.Wait();
622 EXPECT_EQ(embedded_test_server()->GetURL("c.com", "/fullscreen_frame.html"),
623 c_middle->GetLastCommittedURL());
624 content::RenderFrameHost* c_bottom = ChildFrameAt(c_middle, 0);
625
626 // Save the size of the frame to be fullscreened.
627 gfx::Size c_middle_original_size = GetFrameSize(c_middle);
628
629 // Add fullscreenchange and resize event handlers to all frames.
630 AddFullscreenChangeListener(a_top, "a_top");
631 AddFullscreenChangeListener(a_bottom, "a_bottom");
632 AddFullscreenChangeListener(b_first, "b_first");
633 AddFullscreenChangeListener(b_second, "b_second");
634 AddFullscreenChangeListener(c_top, "c_top");
635 AddFullscreenChangeListener(c_middle, "c_middle");
636 AddFullscreenChangeListener(c_bottom, "c_bottom");
637 AddResizeListener(c_middle, GetScreenSize());
638
639 // Note that expected fullscreenchange events do NOT include |b_first| and
640 // |c_bottom|, which aren't on the ancestor chain of |c_middle|.
641 // WaitForMultipleFullscreenEvents() below will fail if it hears an
642 // unexpected fullscreenchange from one of these frames.
643 std::set<std::string> expected_events = {"a_top", "a_bottom", "b_second",
644 "c_top", "c_middle"};
645
646 // Fullscreen a <div> inside |c_middle|. Block until (1) the
647 // fullscreenchange events in |c_middle| and all its ancestors send a
648 // response, (2) |c_middle| is resized to fill the whole screen, and (3) the
649 // browser finishes the fullscreen transition.
650 {
651 content::DOMMessageQueue queue;
652 std::unique_ptr<FullscreenNotificationObserver> observer(
653 new FullscreenNotificationObserver());
654 EXPECT_TRUE(ExecuteScript(c_middle, "activateFullscreen()"));
655 WaitForMultipleFullscreenEvents(expected_events, queue);
656 observer->Wait();
657 }
658
659 // Verify that the browser has entered fullscreen for the current tab.
660 EXPECT_TRUE(browser()->window()->IsFullscreen());
661 EXPECT_TRUE(browser()->exclusive_access_manager()
662 ->fullscreen_controller()
663 ->IsFullscreenForTabOrPending(web_contents));
664
665 // Check document.webkitFullscreenElement. It should point to corresponding
666 // <iframe> element IDs on |c_middle|'s ancestor chain, and it should be null
667 // in b_first and c_bottom.
668 EXPECT_EQ("child-0", GetFullscreenElementId(a_top));
669 EXPECT_EQ("child-1", GetFullscreenElementId(a_bottom));
670 EXPECT_EQ("child-0", GetFullscreenElementId(b_second));
671 EXPECT_EQ("child-0", GetFullscreenElementId(c_top));
672 EXPECT_EQ("fullscreen-div", GetFullscreenElementId(c_middle));
673 EXPECT_EQ("none", GetFullscreenElementId(b_first));
674 EXPECT_EQ("none", GetFullscreenElementId(c_bottom));
675
676 // Verify that the fullscreen element and all <iframe> elements on its
677 // ancestor chain have fullscreen style, but other frames do not.
678 EXPECT_TRUE(ElementHasFullscreenStyle(a_top, "child-0"));
679 EXPECT_FALSE(ElementHasFullscreenStyle(a_bottom, "child-0"));
680 EXPECT_TRUE(ElementHasFullscreenStyle(a_bottom, "child-1"));
681 EXPECT_TRUE(ElementHasFullscreenStyle(b_second, "child-0"));
682 EXPECT_TRUE(ElementHasFullscreenStyle(c_top, "child-0"));
683 EXPECT_TRUE(ElementHasFullscreenStyle(c_middle, "fullscreen-div"));
684 EXPECT_FALSE(ElementHasFullscreenStyle(c_middle, "child-0"));
685
686 // Now exit fullscreen by pressing escape. Wait for all fullscreenchange
687 // events fired for fullscreen exit and verify that the bottom frame was
688 // resized back to its original size.
689 AddResizeListener(c_middle, c_middle_original_size);
690 {
691 content::DOMMessageQueue queue;
692 std::unique_ptr<FullscreenNotificationObserver> observer(
693 new FullscreenNotificationObserver());
694 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_ESCAPE,
695 false, false, false, false));
696 WaitForMultipleFullscreenEvents(expected_events, queue);
697 observer->Wait();
698 }
699
700 EXPECT_FALSE(browser()->window()->IsFullscreen());
701
702 // Check that document.webkitFullscreenElement has been cleared in all
703 // frames.
704 EXPECT_EQ("none", GetFullscreenElementId(a_top));
705 EXPECT_EQ("none", GetFullscreenElementId(a_bottom));
706 EXPECT_EQ("none", GetFullscreenElementId(b_first));
707 EXPECT_EQ("none", GetFullscreenElementId(b_second));
708 EXPECT_EQ("none", GetFullscreenElementId(c_top));
709 EXPECT_EQ("none", GetFullscreenElementId(c_middle));
710 EXPECT_EQ("none", GetFullscreenElementId(c_bottom));
711
712 // Verify that all fullscreen styles have been cleared.
713 EXPECT_FALSE(ElementHasFullscreenStyle(a_top, "child-0"));
714 EXPECT_FALSE(ElementHasFullscreenStyle(a_bottom, "child-0"));
715 EXPECT_FALSE(ElementHasFullscreenStyle(a_bottom, "child-1"));
716 EXPECT_FALSE(ElementHasFullscreenStyle(b_second, "child-0"));
717 EXPECT_FALSE(ElementHasFullscreenStyle(c_top, "child-0"));
718 EXPECT_FALSE(ElementHasFullscreenStyle(c_middle, "fullscreen-div"));
719 EXPECT_FALSE(ElementHasFullscreenStyle(c_middle, "child-0"));
720 }
721
OLDNEW
« no previous file with comments | « no previous file | content/browser/frame_host/render_frame_host_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698