| OLD | NEW |
| 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 14 matching lines...) Expand all Loading... |
| 25 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 25 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| 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 "bindings/core/v8/ConditionalFeatures.h" | 32 #include "bindings/core/v8/ConditionalFeatures.h" |
| 33 #include "core/dom/Document.h" | 33 #include "core/dom/Document.h" |
| 34 #include "core/dom/ElementTraversal.h" | 34 #include "core/dom/ElementTraversal.h" |
| 35 #include "core/dom/FullscreenCallbacks.h" |
| 35 #include "core/dom/StyleEngine.h" | 36 #include "core/dom/StyleEngine.h" |
| 36 #include "core/events/Event.h" | 37 #include "core/events/Event.h" |
| 37 #include "core/frame/HostsUsingFeatures.h" | 38 #include "core/frame/HostsUsingFeatures.h" |
| 38 #include "core/frame/LocalFrame.h" | 39 #include "core/frame/LocalFrame.h" |
| 39 #include "core/frame/Settings.h" | 40 #include "core/frame/Settings.h" |
| 40 #include "core/frame/UseCounter.h" | 41 #include "core/frame/UseCounter.h" |
| 41 #include "core/html/HTMLIFrameElement.h" | 42 #include "core/html/HTMLIFrameElement.h" |
| 42 #include "core/input/EventHandler.h" | 43 #include "core/input/EventHandler.h" |
| 43 #include "core/inspector/ConsoleMessage.h" | 44 #include "core/inspector/ConsoleMessage.h" |
| 44 #include "core/layout/LayoutBlockFlow.h" | 45 #include "core/layout/LayoutBlockFlow.h" |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 306 void Fullscreen::contextDestroyed() { | 307 void Fullscreen::contextDestroyed() { |
| 307 m_eventQueue.clear(); | 308 m_eventQueue.clear(); |
| 308 | 309 |
| 309 if (m_fullScreenLayoutObject) | 310 if (m_fullScreenLayoutObject) |
| 310 m_fullScreenLayoutObject->destroy(); | 311 m_fullScreenLayoutObject->destroy(); |
| 311 | 312 |
| 312 m_currentFullScreenElement = nullptr; | 313 m_currentFullScreenElement = nullptr; |
| 313 m_fullscreenElementStack.clear(); | 314 m_fullscreenElementStack.clear(); |
| 314 } | 315 } |
| 315 | 316 |
| 317 // RequestFullscreenCallbacks hold the data for a pending request. |
| 318 // FullscreenController invokes the success or error callback. |
| 319 class RequestFullscreenCallbacks final : public FullscreenCallbacks { |
| 320 USING_FAST_MALLOC(RequestFullscreenCallbacks); |
| 321 WTF_MAKE_NONCOPYABLE(RequestFullscreenCallbacks); |
| 322 |
| 323 public: |
| 324 static std::unique_ptr<FullscreenCallbacks> |
| 325 create(Document& document, Element& element, Fullscreen::RequestType type) { |
| 326 return wrapUnique(new RequestFullscreenCallbacks(document, element, type)); |
| 327 } |
| 328 |
| 329 void onSuccess() override { |
| 330 Fullscreen::from(*m_document).didEnterFullscreen(*m_element); |
| 331 } |
| 332 |
| 333 void onError() override { |
| 334 Fullscreen::from(*m_document).enqueueErrorEvent(*m_element, m_type); |
| 335 } |
| 336 |
| 337 private: |
| 338 RequestFullscreenCallbacks(Document& document, |
| 339 Element& element, |
| 340 Fullscreen::RequestType type) |
| 341 : m_document(document), m_element(element), m_type(type) {} |
| 342 Persistent<Document> m_document; |
| 343 Persistent<Element> m_element; |
| 344 Fullscreen::RequestType m_type; |
| 345 }; |
| 346 |
| 316 // https://fullscreen.spec.whatwg.org/#dom-element-requestfullscreen | 347 // https://fullscreen.spec.whatwg.org/#dom-element-requestfullscreen |
| 317 void Fullscreen::requestFullscreen(Element& element, | 348 void Fullscreen::requestFullscreen(Element& element, |
| 318 RequestType requestType, | 349 RequestType requestType, |
| 319 bool forCrossProcessDescendant) { | 350 bool forCrossProcessDescendant) { |
| 320 Document& document = element.document(); | 351 Document& document = element.document(); |
| 321 | 352 |
| 322 // Use counters only need to be incremented in the process of the actual | 353 // Use counters only need to be incremented in the process of the actual |
| 323 // fullscreen element. | 354 // fullscreen element. |
| 324 if (!forCrossProcessDescendant) { | 355 if (!forCrossProcessDescendant) { |
| 325 if (document.isSecureContext()) { | 356 if (document.isSecureContext()) { |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 425 continue; | 456 continue; |
| 426 } | 457 } |
| 427 | 458 |
| 428 // 4. Otherwise, do nothing for this document. It stays the same. | 459 // 4. Otherwise, do nothing for this document. It stays the same. |
| 429 } while (++current != docs.end()); | 460 } while (++current != docs.end()); |
| 430 | 461 |
| 431 from(document).m_forCrossProcessDescendant = forCrossProcessDescendant; | 462 from(document).m_forCrossProcessDescendant = forCrossProcessDescendant; |
| 432 | 463 |
| 433 // 5. Return, and run the remaining steps asynchronously. | 464 // 5. Return, and run the remaining steps asynchronously. |
| 434 // 6. Optionally, perform some animation. | 465 // 6. Optionally, perform some animation. |
| 435 from(document).m_pendingFullscreenElement = &element; | 466 document.frame()->chromeClient().enterFullscreen( |
| 436 document.frame()->chromeClient().enterFullscreen(*document.frame()); | 467 *document.frame(), |
| 468 RequestFullscreenCallbacks::create(document, element, requestType)); |
| 437 | 469 |
| 438 // 7. Optionally, display a message indicating how the user can exit | 470 // 7. Optionally, display a message indicating how the user can exit |
| 439 // displaying the context object fullscreen. | 471 // displaying the context object fullscreen. |
| 440 return; | 472 return; |
| 441 } while (false); | 473 } while (false); |
| 442 | 474 |
| 443 from(document).enqueueErrorEvent(element, requestType); | 475 from(document).enqueueErrorEvent(element, requestType); |
| 444 } | 476 } |
| 445 | 477 |
| 446 // https://fullscreen.spec.whatwg.org/#fully-exit-fullscreen | 478 // https://fullscreen.spec.whatwg.org/#fully-exit-fullscreen |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 555 // 6. Return, and run the remaining steps asynchronously. | 587 // 6. Return, and run the remaining steps asynchronously. |
| 556 // 7. Optionally, perform some animation. | 588 // 7. Optionally, perform some animation. |
| 557 | 589 |
| 558 // Only exit fullscreen mode if the fullscreen element stack is empty. | 590 // Only exit fullscreen mode if the fullscreen element stack is empty. |
| 559 if (!newTop) { | 591 if (!newTop) { |
| 560 document.frame()->chromeClient().exitFullscreen(*document.frame()); | 592 document.frame()->chromeClient().exitFullscreen(*document.frame()); |
| 561 return; | 593 return; |
| 562 } | 594 } |
| 563 | 595 |
| 564 // Otherwise, enter fullscreen for the fullscreen element stack's top element. | 596 // Otherwise, enter fullscreen for the fullscreen element stack's top element. |
| 565 from(document).m_pendingFullscreenElement = newTop; | 597 from(document).didEnterFullscreen(*newTop); |
| 566 from(document).didEnterFullscreen(); | |
| 567 } | 598 } |
| 568 | 599 |
| 569 // https://fullscreen.spec.whatwg.org/#dom-document-fullscreenenabled | 600 // https://fullscreen.spec.whatwg.org/#dom-document-fullscreenenabled |
| 570 bool Fullscreen::fullscreenEnabled(Document& document) { | 601 bool Fullscreen::fullscreenEnabled(Document& document) { |
| 571 // The fullscreenEnabled attribute's getter must return true if the context | 602 // The fullscreenEnabled attribute's getter must return true if the context |
| 572 // object is allowed to use the feature indicated by attribute name | 603 // object is allowed to use the feature indicated by attribute name |
| 573 // allowfullscreen and fullscreen is supported, and false otherwise. | 604 // allowfullscreen and fullscreen is supported, and false otherwise. |
| 574 return allowedToUseFullscreen(document.frame()) && | 605 return allowedToUseFullscreen(document.frame()) && |
| 575 fullscreenIsSupported(document); | 606 fullscreenIsSupported(document); |
| 576 } | 607 } |
| 577 | 608 |
| 578 void Fullscreen::didEnterFullscreen() { | 609 void Fullscreen::didEnterFullscreen(Element& element) { |
| 579 if (!document()->isActive() || !document()->frame()) | 610 if (!document() || !document()->isActive() || !document()->frame()) |
| 580 return; | 611 return; |
| 581 | 612 |
| 582 // Start the timer for events enqueued by |requestFullscreen()|. The hover | 613 // Start the timer for events enqueued by |requestFullscreen()|. The hover |
| 583 // state update is scheduled first so that it's done when the events fire. | 614 // state update is scheduled first so that it's done when the events fire. |
| 584 document()->frame()->eventHandler().scheduleHoverStateUpdate(); | 615 document()->frame()->eventHandler().scheduleHoverStateUpdate(); |
| 585 m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE); | 616 m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE); |
| 586 | 617 |
| 587 Element* element = m_pendingFullscreenElement.release(); | 618 if (m_currentFullScreenElement == &element) |
| 588 if (!element) | |
| 589 return; | 619 return; |
| 590 | 620 |
| 591 if (m_currentFullScreenElement == element) | 621 if (!element.isConnected() || &element.document() != document()) { |
| 592 return; | |
| 593 | |
| 594 if (!element->isConnected() || &element->document() != document()) { | |
| 595 // The element was removed or has moved to another document since the | 622 // The element was removed or has moved to another document since the |
| 596 // |requestFullscreen()| call. Exit fullscreen again to recover. | 623 // |requestFullscreen()| call. Exit fullscreen again to recover. |
| 597 // TODO(foolip): Fire a fullscreenerror event. This is currently difficult | 624 // TODO(foolip): Fire a fullscreenerror event. This is currently difficult |
| 598 // because the fullscreenchange event has already been enqueued and possibly | 625 // because the fullscreenchange event has already been enqueued and possibly |
| 599 // even fired. https://crbug.com/402376 | 626 // even fired. https://crbug.com/402376 |
| 600 LocalFrame& frame = *document()->frame(); | 627 LocalFrame& frame = *document()->frame(); |
| 601 frame.chromeClient().exitFullscreen(frame); | 628 frame.chromeClient().exitFullscreen(frame); |
| 602 return; | 629 return; |
| 603 } | 630 } |
| 604 | 631 |
| 632 if (m_currentFullScreenElement == &element) |
| 633 return; |
| 634 |
| 605 if (m_fullScreenLayoutObject) | 635 if (m_fullScreenLayoutObject) |
| 606 m_fullScreenLayoutObject->unwrapLayoutObject(); | 636 m_fullScreenLayoutObject->unwrapLayoutObject(); |
| 607 | 637 |
| 608 Element* previousElement = m_currentFullScreenElement; | 638 Element* previousElement = m_currentFullScreenElement; |
| 609 m_currentFullScreenElement = element; | 639 m_currentFullScreenElement = &element; |
| 610 | 640 |
| 611 // Create a placeholder block for a the full-screen element, to keep the page | 641 // Create a placeholder block for a the full-screen element, to keep the page |
| 612 // from reflowing when the element is removed from the normal flow. Only do | 642 // from reflowing when the element is removed from the normal flow. Only do |
| 613 // this for a LayoutBox, as only a box will have a frameRect. The placeholder | 643 // this for a LayoutBox, as only a box will have a frameRect. The placeholder |
| 614 // will be created in setFullScreenLayoutObject() during layout. | 644 // will be created in setFullScreenLayoutObject() during layout. |
| 615 LayoutObject* layoutObject = m_currentFullScreenElement->layoutObject(); | 645 LayoutObject* layoutObject = m_currentFullScreenElement->layoutObject(); |
| 616 bool shouldCreatePlaceholder = layoutObject && layoutObject->isBox(); | 646 bool shouldCreatePlaceholder = layoutObject && layoutObject->isBox(); |
| 617 if (shouldCreatePlaceholder) { | 647 if (shouldCreatePlaceholder) { |
| 618 m_savedPlaceholderFrameRect = toLayoutBox(layoutObject)->frameRect(); | 648 m_savedPlaceholderFrameRect = toLayoutBox(layoutObject)->frameRect(); |
| 619 m_savedPlaceholderComputedStyle = | 649 m_savedPlaceholderComputedStyle = |
| (...skipping 23 matching lines...) Expand all Loading... |
| 643 m_currentFullScreenElement | 673 m_currentFullScreenElement |
| 644 ->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(true); | 674 ->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(true); |
| 645 | 675 |
| 646 document()->styleEngine().ensureUAStyleForFullscreen(); | 676 document()->styleEngine().ensureUAStyleForFullscreen(); |
| 647 m_currentFullScreenElement->pseudoStateChanged(CSSSelector::PseudoFullScreen); | 677 m_currentFullScreenElement->pseudoStateChanged(CSSSelector::PseudoFullScreen); |
| 648 | 678 |
| 649 // FIXME: This should not call updateStyleAndLayoutTree. | 679 // FIXME: This should not call updateStyleAndLayoutTree. |
| 650 document()->updateStyleAndLayoutTree(); | 680 document()->updateStyleAndLayoutTree(); |
| 651 | 681 |
| 652 document()->frame()->chromeClient().fullscreenElementChanged(previousElement, | 682 document()->frame()->chromeClient().fullscreenElementChanged(previousElement, |
| 653 element); | 683 &element); |
| 654 } | 684 } |
| 655 | 685 |
| 656 void Fullscreen::didExitFullscreen() { | 686 void Fullscreen::didExitFullscreen() { |
| 657 if (!document()->isActive() || !document()->frame()) | 687 if (!document() || !document()->isActive() || !document()->frame()) |
| 658 return; | 688 return; |
| 659 | 689 |
| 660 // Start the timer for events enqueued by |exitFullscreen()|. The hover state | 690 // Start the timer for events enqueued by |exitFullscreen()|. The hover state |
| 661 // update is scheduled first so that it's done when the events fire. | 691 // update is scheduled first so that it's done when the events fire. |
| 662 document()->frame()->eventHandler().scheduleHoverStateUpdate(); | 692 document()->frame()->eventHandler().scheduleHoverStateUpdate(); |
| 663 m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE); | 693 m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE); |
| 664 | 694 |
| 665 // If fullscreen was canceled by the browser, e.g. if the user pressed Esc, | 695 // If fullscreen was canceled by the browser, e.g. if the user pressed Esc, |
| 666 // then |exitFullscreen()| was never called. Let |fullyExitFullscreen()| clear | 696 // then |exitFullscreen()| was never called. Let |fullyExitFullscreen()| clear |
| 667 // the fullscreen element stack and fire any events as necessary. | 697 // the fullscreen element stack and fire any events as necessary. |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 800 | 830 |
| 801 m_fullscreenElementStack.pop_back(); | 831 m_fullscreenElementStack.pop_back(); |
| 802 } | 832 } |
| 803 | 833 |
| 804 void Fullscreen::pushFullscreenElementStack(Element& element, | 834 void Fullscreen::pushFullscreenElementStack(Element& element, |
| 805 RequestType requestType) { | 835 RequestType requestType) { |
| 806 m_fullscreenElementStack.append(std::make_pair(&element, requestType)); | 836 m_fullscreenElementStack.append(std::make_pair(&element, requestType)); |
| 807 } | 837 } |
| 808 | 838 |
| 809 DEFINE_TRACE(Fullscreen) { | 839 DEFINE_TRACE(Fullscreen) { |
| 810 visitor->trace(m_pendingFullscreenElement); | |
| 811 visitor->trace(m_fullscreenElementStack); | 840 visitor->trace(m_fullscreenElementStack); |
| 812 visitor->trace(m_currentFullScreenElement); | 841 visitor->trace(m_currentFullScreenElement); |
| 813 visitor->trace(m_eventQueue); | 842 visitor->trace(m_eventQueue); |
| 814 Supplement<Document>::trace(visitor); | 843 Supplement<Document>::trace(visitor); |
| 815 ContextLifecycleObserver::trace(visitor); | 844 ContextLifecycleObserver::trace(visitor); |
| 816 } | 845 } |
| 817 | 846 |
| 818 } // namespace blink | 847 } // namespace blink |
| OLD | NEW |