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

Side by Side Diff: third_party/WebKit/Source/core/dom/Fullscreen.cpp

Issue 2550703002: Move pending state from FullscreenController to Fullscreen (Closed)
Patch Set: tests and documentation Created 4 years 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org) 4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org) 5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org)
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All
7 * rights reserved. 7 * rights reserved.
8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
9 * (http://www.torchmobile.com/) 9 * (http://www.torchmobile.com/)
10 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) 10 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
(...skipping 15 matching lines...) Expand all
26 * Boston, MA 02110-1301, USA. 26 * Boston, MA 02110-1301, USA.
27 * 27 *
28 */ 28 */
29 29
30 #include "core/dom/Fullscreen.h" 30 #include "core/dom/Fullscreen.h"
31 31
32 #include "core/dom/Document.h" 32 #include "core/dom/Document.h"
33 #include "core/dom/ElementTraversal.h" 33 #include "core/dom/ElementTraversal.h"
34 #include "core/dom/StyleEngine.h" 34 #include "core/dom/StyleEngine.h"
35 #include "core/events/Event.h" 35 #include "core/events/Event.h"
36 #include "core/frame/FrameHost.h"
37 #include "core/frame/HostsUsingFeatures.h" 36 #include "core/frame/HostsUsingFeatures.h"
38 #include "core/frame/LocalFrame.h" 37 #include "core/frame/LocalFrame.h"
39 #include "core/frame/Settings.h" 38 #include "core/frame/Settings.h"
40 #include "core/frame/UseCounter.h" 39 #include "core/frame/UseCounter.h"
41 #include "core/html/HTMLIFrameElement.h" 40 #include "core/html/HTMLIFrameElement.h"
42 #include "core/input/EventHandler.h" 41 #include "core/input/EventHandler.h"
43 #include "core/inspector/ConsoleMessage.h" 42 #include "core/inspector/ConsoleMessage.h"
44 #include "core/layout/LayoutBlockFlow.h" 43 #include "core/layout/LayoutBlockFlow.h"
45 #include "core/layout/LayoutFullScreen.h" 44 #include "core/layout/LayoutFullScreen.h"
46 #include "core/layout/api/LayoutFullScreenItem.h" 45 #include "core/layout/api/LayoutFullScreenItem.h"
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 if (!forCrossProcessDescendant) { 290 if (!forCrossProcessDescendant) {
292 if (document.isSecureContext()) { 291 if (document.isSecureContext()) {
293 UseCounter::count(document, UseCounter::FullscreenSecureOrigin); 292 UseCounter::count(document, UseCounter::FullscreenSecureOrigin);
294 } else { 293 } else {
295 UseCounter::count(document, UseCounter::FullscreenInsecureOrigin); 294 UseCounter::count(document, UseCounter::FullscreenInsecureOrigin);
296 HostsUsingFeatures::countAnyWorld( 295 HostsUsingFeatures::countAnyWorld(
297 document, HostsUsingFeatures::Feature::FullscreenInsecureHost); 296 document, HostsUsingFeatures::Feature::FullscreenInsecureHost);
298 } 297 }
299 } 298 }
300 299
301 // Ignore this request if the document is not in a live frame. 300 // Ignore this call if the document is not in a live frame.
302 if (!document.isActive()) 301 if (!document.isActive() || !document.frame())
303 return; 302 return;
304 303
305 // If |element| is on top of |doc|'s fullscreen element stack, terminate these 304 // If |element| is on top of |doc|'s fullscreen element stack, terminate these
306 // substeps. 305 // substeps.
307 if (&element == fullscreenElementFrom(document)) 306 if (&element == fullscreenElementFrom(document))
308 return; 307 return;
309 308
310 do { 309 do {
311 // 1. If any of the following conditions are false, then terminate these 310 // 1. If any of the following conditions are false, then terminate these
312 // steps and queue a task to fire an event named fullscreenerror with its 311 // steps and queue a task to fire an event named fullscreenerror with its
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 continue; 391 continue;
393 } 392 }
394 393
395 // 4. Otherwise, do nothing for this document. It stays the same. 394 // 4. Otherwise, do nothing for this document. It stays the same.
396 } while (++current != docs.end()); 395 } while (++current != docs.end());
397 396
398 from(document).m_forCrossProcessDescendant = forCrossProcessDescendant; 397 from(document).m_forCrossProcessDescendant = forCrossProcessDescendant;
399 398
400 // 5. Return, and run the remaining steps asynchronously. 399 // 5. Return, and run the remaining steps asynchronously.
401 // 6. Optionally, perform some animation. 400 // 6. Optionally, perform some animation.
402 document.frameHost()->chromeClient().enterFullscreenForElement(&element); 401 from(document).m_pendingFullscreenElement = &element;
402 document.frame()->chromeClient().enterFullscreen(*document.frame());
403 403
404 // 7. Optionally, display a message indicating how the user can exit 404 // 7. Optionally, display a message indicating how the user can exit
405 // displaying the context object fullscreen. 405 // displaying the context object fullscreen.
406 return; 406 return;
407 } while (false); 407 } while (false);
408 408
409 from(document).enqueueErrorEvent(element, requestType); 409 from(document).enqueueErrorEvent(element, requestType);
410 } 410 }
411 411
412 // https://fullscreen.spec.whatwg.org/#fully-exit-fullscreen 412 // https://fullscreen.spec.whatwg.org/#fully-exit-fullscreen
(...skipping 21 matching lines...) Expand all
434 DCHECK_EQ(from(doc).m_fullscreenElementStack.size(), 1u); 434 DCHECK_EQ(from(doc).m_fullscreenElementStack.size(), 1u);
435 435
436 // 4. Act as if the exitFullscreen() method was invoked on |doc|. 436 // 4. Act as if the exitFullscreen() method was invoked on |doc|.
437 exitFullscreen(doc); 437 exitFullscreen(doc);
438 } 438 }
439 439
440 // https://fullscreen.spec.whatwg.org/#exit-fullscreen 440 // https://fullscreen.spec.whatwg.org/#exit-fullscreen
441 void Fullscreen::exitFullscreen(Document& document) { 441 void Fullscreen::exitFullscreen(Document& document) {
442 // The exitFullscreen() method must run these steps: 442 // The exitFullscreen() method must run these steps:
443 443
444 // 1. Let doc be the context object. (i.e. "this") 444 // Ignore this call if the document is not in a live frame.
445 if (!document.isActive()) 445 if (!document.isActive() || !document.frame())
446 return; 446 return;
447 447
448 // 1. Let doc be the context object. (i.e. "this")
448 // 2. If doc's fullscreen element stack is empty, terminate these steps. 449 // 2. If doc's fullscreen element stack is empty, terminate these steps.
449 if (!fullscreenElementFrom(document)) 450 if (!fullscreenElementFrom(document))
450 return; 451 return;
451 452
452 // 3. Let descendants be all the doc's descendant browsing context's documents 453 // 3. Let descendants be all the doc's descendant browsing context's documents
453 // with a non-empty fullscreen element stack (if any), ordered so that the 454 // with a non-empty fullscreen element stack (if any), ordered so that the
454 // child of the doc is last and the document furthest away from the doc is 455 // child of the doc is last and the document furthest away from the doc is
455 // first. 456 // first.
456 HeapDeque<Member<Document>> descendants; 457 HeapDeque<Member<Document>> descendants;
457 for (Frame* descendant = 458 for (Frame* descendant = document.frame()->tree().traverseNext(); descendant;
458 document.frame() ? document.frame()->tree().traverseNext() : nullptr; 459 descendant = descendant->tree().traverseNext()) {
459 descendant; descendant = descendant->tree().traverseNext()) {
460 if (!descendant->isLocalFrame()) 460 if (!descendant->isLocalFrame())
461 continue; 461 continue;
462 DCHECK(toLocalFrame(descendant)->document()); 462 DCHECK(toLocalFrame(descendant)->document());
463 if (fullscreenElementFrom(*toLocalFrame(descendant)->document())) 463 if (fullscreenElementFrom(*toLocalFrame(descendant)->document()))
464 descendants.prepend(toLocalFrame(descendant)->document()); 464 descendants.prepend(toLocalFrame(descendant)->document());
465 } 465 }
466 466
467 // 4. For each descendant in descendants, empty descendant's fullscreen 467 // 4. For each descendant in descendants, empty descendant's fullscreen
468 // element stack, and queue a task to fire an event named fullscreenchange 468 // element stack, and queue a task to fire an event named fullscreenchange
469 // with its bubbles attribute set to true on descendant. 469 // with its bubbles attribute set to true on descendant.
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 } 514 }
515 } 515 }
516 516
517 // 4. Otherwise, set doc to null. 517 // 4. Otherwise, set doc to null.
518 currentDoc = nullptr; 518 currentDoc = nullptr;
519 } 519 }
520 520
521 // 6. Return, and run the remaining steps asynchronously. 521 // 6. Return, and run the remaining steps asynchronously.
522 // 7. Optionally, perform some animation. 522 // 7. Optionally, perform some animation.
523 523
524 FrameHost* host = document.frameHost(); 524 // Only exit fullscreen mode if the fullscreen element stack is empty.
525
526 // Speculative fix for engaget.com/videos per crbug.com/336239.
527 // FIXME: This check is wrong. We DCHECK(document->isActive()) above
528 // so this should be redundant and should be removed!
529 if (!host)
530 return;
531
532 // Only exit out of full screen window mode if there are no remaining elements
533 // in the full screen stack.
534 if (!newTop) { 525 if (!newTop) {
535 host->chromeClient().exitFullscreen(document.frame()); 526 document.frame()->chromeClient().exitFullscreen(*document.frame());
536 return; 527 return;
537 } 528 }
538 529
539 // Otherwise, notify the chrome of the new full screen element. 530 // Otherwise, enter fullscreen for the fullscreen element stack's top element.
540 host->chromeClient().enterFullscreenForElement(newTop); 531 from(document).m_pendingFullscreenElement = newTop;
532 from(document).didEnterFullscreen();
541 } 533 }
542 534
543 // https://fullscreen.spec.whatwg.org/#dom-document-fullscreenenabled 535 // https://fullscreen.spec.whatwg.org/#dom-document-fullscreenenabled
544 bool Fullscreen::fullscreenEnabled(Document& document) { 536 bool Fullscreen::fullscreenEnabled(Document& document) {
545 // The fullscreenEnabled attribute's getter must return true if the context 537 // The fullscreenEnabled attribute's getter must return true if the context
546 // object is allowed to use the feature indicated by attribute name 538 // object is allowed to use the feature indicated by attribute name
547 // allowfullscreen and fullscreen is supported, and false otherwise. 539 // allowfullscreen and fullscreen is supported, and false otherwise.
548 return allowedToUseFullscreen(document.frame()) && 540 return allowedToUseFullscreen(document.frame()) &&
549 fullscreenIsSupported(document); 541 fullscreenIsSupported(document);
550 } 542 }
551 543
552 void Fullscreen::didEnterFullscreenForElement(Element* element) { 544 void Fullscreen::didEnterFullscreen() {
553 DCHECK(element);
554 if (!document()->isActive() || !document()->frame()) 545 if (!document()->isActive() || !document()->frame())
555 return; 546 return;
556 547
548 // Start the timer for events enqueued by |requestFullscreen()|. The hover
549 // state update is scheduled first so that it's done when the events fire.
550 document()->frame()->eventHandler().scheduleHoverStateUpdate();
551 m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE);
552
553 Element* element = m_pendingFullscreenElement.release();
554 if (!element)
555 return;
556
557 if (m_currentFullScreenElement == element) 557 if (m_currentFullScreenElement == element)
558 return; 558 return;
559 559
560 if (!element->isConnected() || &element->document() != document()) {
561 // The element was removed or has moved to another document since the
562 // |requestFullscreen()| call. Exit fullscreen again to recover.
563 // TODO(foolip): Fire a fullscreenerror event. This is currently difficult
564 // because the fullscreenchange event has already been enqueued and possibly
565 // even fired. https://crbug.com/402376
566 LocalFrame& frame = *document()->frame();
567 frame.chromeClient().exitFullscreen(frame);
568 return;
569 }
570
560 if (m_fullScreenLayoutObject) 571 if (m_fullScreenLayoutObject)
561 m_fullScreenLayoutObject->unwrapLayoutObject(); 572 m_fullScreenLayoutObject->unwrapLayoutObject();
562 573
563 Element* previousElement = m_currentFullScreenElement; 574 Element* previousElement = m_currentFullScreenElement;
564 m_currentFullScreenElement = element; 575 m_currentFullScreenElement = element;
565 576
566 // Create a placeholder block for a the full-screen element, to keep the page 577 // Create a placeholder block for a the full-screen element, to keep the page
567 // from reflowing when the element is removed from the normal flow. Only do 578 // from reflowing when the element is removed from the normal flow. Only do
568 // this for a LayoutBox, as only a box will have a frameRect. The placeholder 579 // this for a LayoutBox, as only a box will have a frameRect. The placeholder
569 // will be created in setFullScreenLayoutObject() during layout. 580 // will be created in setFullScreenLayoutObject() during layout.
(...skipping 27 matching lines...) Expand all
597 608
598 m_currentFullScreenElement 609 m_currentFullScreenElement
599 ->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(true); 610 ->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(true);
600 611
601 document()->styleEngine().ensureUAStyleForFullscreen(); 612 document()->styleEngine().ensureUAStyleForFullscreen();
602 m_currentFullScreenElement->pseudoStateChanged(CSSSelector::PseudoFullScreen); 613 m_currentFullScreenElement->pseudoStateChanged(CSSSelector::PseudoFullScreen);
603 614
604 // FIXME: This should not call updateStyleAndLayoutTree. 615 // FIXME: This should not call updateStyleAndLayoutTree.
605 document()->updateStyleAndLayoutTree(); 616 document()->updateStyleAndLayoutTree();
606 617
607 document()->frame()->eventHandler().scheduleHoverStateUpdate();
608
609 m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE);
610
611 document()->frame()->chromeClient().fullscreenElementChanged(previousElement, 618 document()->frame()->chromeClient().fullscreenElementChanged(previousElement,
612 element); 619 element);
613 } 620 }
614 621
615 void Fullscreen::didExitFullscreen() { 622 void Fullscreen::didExitFullscreen() {
616 if (!document()->isActive() || !document()->frame()) 623 if (!document()->isActive() || !document()->frame())
617 return; 624 return;
618 625
626 // Start the timer for events enqueued by |exitFullscreen()|. The hover state
627 // update is scheduled first so that it's done when the events fire.
628 document()->frame()->eventHandler().scheduleHoverStateUpdate();
629 m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE);
630
631 // If fullscreen was canceled by the browser, e.g. if the user pressed Esc,
632 // then |exitFullscreen()| was never called. Let |fullyExitFullscreen()| clear
633 // the fullscreen element stack and fire any events as necessary.
634 // TODO(foolip): Remove this when state changes and events are synchronized
635 // with animation frames. https://crbug.com/402376
636 fullyExitFullscreen(*document());
637
619 if (!m_currentFullScreenElement) 638 if (!m_currentFullScreenElement)
620 return; 639 return;
621 640
622 if (m_forCrossProcessDescendant) 641 if (m_forCrossProcessDescendant)
623 m_currentFullScreenElement->setContainsFullScreenElement(false); 642 m_currentFullScreenElement->setContainsFullScreenElement(false);
624 643
625 m_currentFullScreenElement 644 m_currentFullScreenElement
626 ->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false); 645 ->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false);
627 646
628 if (m_fullScreenLayoutObject) 647 if (m_fullScreenLayoutObject)
629 LayoutFullScreenItem(m_fullScreenLayoutObject).unwrapLayoutObject(); 648 LayoutFullScreenItem(m_fullScreenLayoutObject).unwrapLayoutObject();
630 649
631 document()->styleEngine().ensureUAStyleForFullscreen(); 650 document()->styleEngine().ensureUAStyleForFullscreen();
632 m_currentFullScreenElement->pseudoStateChanged(CSSSelector::PseudoFullScreen); 651 m_currentFullScreenElement->pseudoStateChanged(CSSSelector::PseudoFullScreen);
633 Element* previousElement = m_currentFullScreenElement; 652 Element* previousElement = m_currentFullScreenElement;
634 m_currentFullScreenElement = nullptr; 653 m_currentFullScreenElement = nullptr;
635 654
636 document()->frame()->eventHandler().scheduleHoverStateUpdate();
637
638 // When fullyExitFullscreen is called, we call exitFullscreen on the
639 // topDocument(). That means that the events will be queued there. So if we
640 // have no events here, start the timer on the exiting document.
641 Document* exitingDocument = document();
642 if (m_eventQueue.isEmpty())
643 exitingDocument = &topmostLocalAncestor(*document());
644 DCHECK(exitingDocument);
645 from(*exitingDocument).m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE);
646
647 m_forCrossProcessDescendant = false; 655 m_forCrossProcessDescendant = false;
648 656
649 document()->frame()->chromeClient().fullscreenElementChanged(previousElement, 657 document()->frame()->chromeClient().fullscreenElementChanged(previousElement,
650 nullptr); 658 nullptr);
651 } 659 }
652 660
653 void Fullscreen::setFullScreenLayoutObject(LayoutFullScreen* layoutObject) { 661 void Fullscreen::setFullScreenLayoutObject(LayoutFullScreen* layoutObject) {
654 if (layoutObject == m_fullScreenLayoutObject) 662 if (layoutObject == m_fullScreenLayoutObject)
655 return; 663 return;
656 664
(...skipping 28 matching lines...) Expand all
685 DCHECK(document.hasFullscreenSupplement()); 693 DCHECK(document.hasFullscreenSupplement());
686 Fullscreen& fullscreen = from(document); 694 Fullscreen& fullscreen = from(document);
687 EventTarget* target = fullscreen.fullscreenElement(); 695 EventTarget* target = fullscreen.fullscreenElement();
688 if (!target) 696 if (!target)
689 target = fullscreen.currentFullScreenElement(); 697 target = fullscreen.currentFullScreenElement();
690 if (!target) 698 if (!target)
691 target = &document; 699 target = &document;
692 event = createEvent(EventTypeNames::webkitfullscreenchange, *target); 700 event = createEvent(EventTypeNames::webkitfullscreenchange, *target);
693 } 701 }
694 m_eventQueue.append(event); 702 m_eventQueue.append(event);
695 // NOTE: The timer is started in 703 // NOTE: The timer is started in didEnterFullscreen/didExitFullscreen.
696 // didEnterFullscreenForElement/didExitFullscreen.
697 } 704 }
698 705
699 void Fullscreen::enqueueErrorEvent(Element& element, RequestType requestType) { 706 void Fullscreen::enqueueErrorEvent(Element& element, RequestType requestType) {
700 Event* event; 707 Event* event;
701 if (requestType == UnprefixedRequest) 708 if (requestType == UnprefixedRequest)
702 event = createEvent(EventTypeNames::fullscreenerror, element.document()); 709 event = createEvent(EventTypeNames::fullscreenerror, element.document());
703 else 710 else
704 event = createEvent(EventTypeNames::webkitfullscreenerror, element); 711 event = createEvent(EventTypeNames::webkitfullscreenerror, element);
705 m_eventQueue.append(event); 712 m_eventQueue.append(event);
706 m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE); 713 m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
759 766
760 m_fullscreenElementStack.pop_back(); 767 m_fullscreenElementStack.pop_back();
761 } 768 }
762 769
763 void Fullscreen::pushFullscreenElementStack(Element& element, 770 void Fullscreen::pushFullscreenElementStack(Element& element,
764 RequestType requestType) { 771 RequestType requestType) {
765 m_fullscreenElementStack.append(std::make_pair(&element, requestType)); 772 m_fullscreenElementStack.append(std::make_pair(&element, requestType));
766 } 773 }
767 774
768 DEFINE_TRACE(Fullscreen) { 775 DEFINE_TRACE(Fullscreen) {
776 visitor->trace(m_pendingFullscreenElement);
777 visitor->trace(m_fullscreenElementStack);
769 visitor->trace(m_currentFullScreenElement); 778 visitor->trace(m_currentFullScreenElement);
770 visitor->trace(m_fullscreenElementStack);
771 visitor->trace(m_eventQueue); 779 visitor->trace(m_eventQueue);
772 Supplement<Document>::trace(visitor); 780 Supplement<Document>::trace(visitor);
773 ContextLifecycleObserver::trace(visitor); 781 ContextLifecycleObserver::trace(visitor);
774 } 782 }
775 783
776 } // namespace blink 784 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698