Refactoring: Pull all fullscreen code out of Document and into its own helper class
authorjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 18 Apr 2019 22:16:54 +0000 (22:16 +0000)
committerjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 18 Apr 2019 22:16:54 +0000 (22:16 +0000)
https://bugs.webkit.org/show_bug.cgi?id=197017

Reviewed by Eric Carlson.

Source/WebCore:

* CMakeLists.txt:
* DerivedSources-input.xcfilelist:
* DerivedSources-output.xcfilelist:
* DerivedSources.make:
* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* css/CSSDefaultStyleSheets.cpp:
(WebCore::CSSDefaultStyleSheets::ensureDefaultStyleSheetsForElement):
* css/SelectorCheckerTestFunctions.h:
(WebCore::matchesFullScreenPseudoClass):
(WebCore::matchesFullScreenAnimatingFullScreenTransitionPseudoClass):
(WebCore::matchesFullScreenDocumentPseudoClass):
(WebCore::matchesFullScreenControlsHiddenPseudoClass):
* dom/Document.cpp:
(WebCore::Document::removedLastRef):
(WebCore::Document::prepareForDestruction):
(WebCore::Document::nodeChildrenWillBeRemoved):
(WebCore::Document::nodeWillBeRemoved):
(WebCore::isAttributeOnAllOwners): Deleted.
(WebCore::Document::fullScreenIsAllowedForElement const): Deleted.
(WebCore::Document::requestFullScreenForElement): Deleted.
(WebCore::Document::webkitCancelFullScreen): Deleted.
(WebCore::Document::webkitExitFullscreen): Deleted.
(WebCore::Document::webkitFullscreenEnabled const): Deleted.
(WebCore::unwrapFullScreenRenderer): Deleted.
(WebCore::Document::webkitWillEnterFullScreen): Deleted.
(WebCore::Document::webkitDidEnterFullScreen): Deleted.
(WebCore::Document::webkitWillExitFullScreen): Deleted.
(WebCore::Document::webkitDidExitFullScreen): Deleted.
(WebCore::Document::setFullScreenRenderer): Deleted.
(WebCore::Document::dispatchFullScreenChangeEvents): Deleted.
(WebCore::Document::dispatchFullScreenChangeOrErrorEvent): Deleted.
(WebCore::Document::fullScreenElementRemoved): Deleted.
(WebCore::Document::adjustFullScreenElementOnNodeRemoval): Deleted.
(WebCore::Document::isAnimatingFullScreen const): Deleted.
(WebCore::Document::setAnimatingFullScreen): Deleted.
(WebCore::Document::areFullscreenControlsHidden const): Deleted.
(WebCore::Document::setFullscreenControlsHidden): Deleted.
(WebCore::Document::clearFullscreenElementStack): Deleted.
(WebCore::Document::popFullscreenElementStack): Deleted.
(WebCore::Document::pushFullscreenElementStack): Deleted.
(WebCore::Document::addDocumentToFullScreenChangeEventQueue): Deleted.
* dom/Document.h:
(WebCore::Document::fullscreenManager):
(WebCore::Document::webkitIsFullScreen const): Deleted.
(WebCore::Document::webkitFullScreenKeyboardInputAllowed const): Deleted.
(WebCore::Document::webkitCurrentFullScreenElement const): Deleted.
(WebCore::Document::webkitCurrentFullScreenElementForBindings const): Deleted.
(WebCore::Document::fullScreenRenderer const): Deleted.
(WebCore::Document::webkitFullscreenElement const): Deleted.
(WebCore::Document::webkitFullscreenElementForBindings const): Deleted.
* dom/Document.idl:
* dom/DocumentFullscreen.h:
(WebCore::DocumentFullscreen::webkitFullscreenEnabled):
(WebCore::DocumentFullscreen::webkitFullscreenElement):
(WebCore::DocumentFullscreen::webkitExitFullscreen):
(WebCore::DocumentFullscreen::webkitIsFullScreen):
(WebCore::DocumentFullscreen::webkitFullScreenKeyboardInputAllowed):
(WebCore::DocumentFullscreen::webkitCurrentFullScreenElement):
(WebCore::DocumentFullscreen::webkitCancelFullScreen):
* dom/DocumentFullscreen.idl:
* dom/Element.cpp:
(WebCore::Element::webkitRequestFullscreen):
* dom/EventPath.cpp:
(WebCore::shouldEventCrossShadowBoundary):
* dom/FullscreenManager.cpp: Added.
(WebCore::isAttributeOnAllOwners):
(WebCore::FullscreenManager::FullscreenManager):
(WebCore::FullscreenManager::fullscreenIsAllowedForElement const):
(WebCore::FullscreenManager::requestFullscreenForElement):
(WebCore::FullscreenManager::cancelFullscreen):
(WebCore::FullscreenManager::requestExitFullscreen):
(WebCore::FullscreenManager::exitFullscreen):
(WebCore::FullscreenManager::isFullscreenEnabled const):
(WebCore::unwrapFullscreenRenderer):
(WebCore::FullscreenManager::willEnterFullscreen):
(WebCore::FullscreenManager::didEnterFullscreen):
(WebCore::FullscreenManager::willExitFullscreen):
(WebCore::FullscreenManager::didExitFullscreen):
(WebCore::FullscreenManager::setFullscreenRenderer):
(WebCore::FullscreenManager::dispatchFullscreenChangeEvents):
(WebCore::FullscreenManager::dispatchFullscreenChangeOrErrorEvent):
(WebCore::FullscreenManager::fullscreenElementRemoved):
(WebCore::FullscreenManager::adjustFullscreenElementOnNodeRemoval):
(WebCore::FullscreenManager::isAnimatingFullscreen const):
(WebCore::FullscreenManager::setAnimatingFullscreen):
(WebCore::FullscreenManager::areFullscreenControlsHidden const):
(WebCore::FullscreenManager::setFullscreenControlsHidden):
(WebCore::FullscreenManager::clear):
(WebCore::FullscreenManager::emptyEventQueue):
(WebCore::FullscreenManager::clearFullscreenElementStack):
(WebCore::FullscreenManager::popFullscreenElementStack):
(WebCore::FullscreenManager::pushFullscreenElementStack):
(WebCore::FullscreenManager::addDocumentToFullscreenChangeEventQueue):
* dom/FullscreenManager.h: Added.
(WebCore::FullscreenManager::document):
(WebCore::FullscreenManager::document const):
(WebCore::FullscreenManager::topDocument const):
(WebCore::FullscreenManager::page const):
(WebCore::FullscreenManager::frame const):
(WebCore::FullscreenManager::documentElement const):
(WebCore::FullscreenManager::hasLivingRenderTree const):
(WebCore::FullscreenManager::pageCacheState const):
(WebCore::FullscreenManager::scheduleFullStyleRebuild):
(WebCore::FullscreenManager::fullscreenElement const):
(WebCore::FullscreenManager::isFullscreen const):
(WebCore::FullscreenManager::isFullscreenKeyboardInputAllowed const):
(WebCore::FullscreenManager::currentFullscreenElement const):
(WebCore::FullscreenManager::fullscreenRenderer const):
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::isFullscreen const):
(WebCore::HTMLMediaElement::isStandardFullscreen const):
(WebCore::HTMLMediaElement::enterFullscreen):
(WebCore::HTMLMediaElement::exitFullscreen):
* html/MediaElementSession.cpp:
(WebCore::MediaElementSession::canShowControlsManager const):
* html/shadow/MediaControlElements.cpp:
(WebCore::MediaControlFullscreenButtonElement::defaultEventHandler):
* inspector/agents/InspectorDOMAgent.cpp:
* page/EventHandler.cpp:
(WebCore::EventHandler::isKeyEventAllowedInFullScreen const):
(WebCore::EventHandler::internalKeyEvent):
* page/Page.cpp:
(WebCore::Page::setFullscreenControlsHidden):
* rendering/RenderFullScreen.cpp:
(WebCore::RenderFullScreen::wrapNewRenderer):
(WebCore::RenderFullScreen::wrapExistingRenderer):
* rendering/RenderLayerCompositor.cpp:
(WebCore::isDescendantOfFullScreenLayer):
* rendering/updating/RenderTreeBuilder.h:
* rendering/updating/RenderTreeBuilderInline.cpp:
(WebCore::RenderTreeBuilder::Inline::splitInlines):
* rendering/updating/RenderTreeUpdater.cpp:
(WebCore::RenderTreeUpdater::createRenderer):
* style/StyleSharingResolver.cpp:
(WebCore::Style::SharingResolver::canShareStyleWithElement const):
* testing/Internals.cpp:
(WebCore::Internals::webkitWillEnterFullScreenForElement):
(WebCore::Internals::webkitDidEnterFullScreenForElement):
(WebCore::Internals::webkitWillExitFullScreenForElement):
(WebCore::Internals::webkitDidExitFullScreenForElement):
(WebCore::Internals::isAnimatingFullScreen const):

Source/WebKit:

* WebProcess/FullScreen/WebFullScreenManager.cpp:
(WebKit::WebFullScreenManager::willEnterFullScreen):
(WebKit::WebFullScreenManager::didEnterFullScreen):
(WebKit::WebFullScreenManager::willExitFullScreen):
(WebKit::WebFullScreenManager::didExitFullScreen):
(WebKit::WebFullScreenManager::setAnimatingFullScreen):
(WebKit::WebFullScreenManager::requestExitFullScreen):
* WebProcess/InjectedBundle/API/gtk/DOM/WebKitDOMDocumentGtk.cpp:
(webkit_dom_document_webkit_cancel_fullscreen):
(webkit_dom_document_webkit_exit_fullscreen):
(webkit_dom_document_get_webkit_is_fullscreen):
(webkit_dom_document_get_webkit_fullscreen_keyboard_input_allowed):
(webkit_dom_document_get_webkit_current_fullscreen_element):
(webkit_dom_document_get_webkit_fullscreen_element):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::createWindow):

Source/WebKitLegacy/mac:

* DOM/DOMDocument.mm:
(-[DOMDocument webkitIsFullScreen]):
(-[DOMDocument webkitFullScreenKeyboardInputAllowed]):
(-[DOMDocument webkitCurrentFullScreenElement]):
(-[DOMDocument webkitFullscreenEnabled]):
(-[DOMDocument webkitFullscreenElement]):
(-[DOMDocument webkitCancelFullScreen]):
(-[DOMDocument webkitExitFullscreen]):
* WebCoreSupport/WebChromeClient.mm:
(WebChromeClient::createWindow):
* WebCoreSupport/WebKitFullScreenListener.mm:
(-[WebKitFullScreenListener webkitWillEnterFullScreen]):
(-[WebKitFullScreenListener webkitDidEnterFullScreen]):
(-[WebKitFullScreenListener webkitWillExitFullScreen]):
(-[WebKitFullScreenListener webkitDidExitFullScreen]):
* WebView/WebFullScreenController.mm:
(-[WebFullScreenController enterFullScreen:]):
(-[WebFullScreenController finishedEnterFullScreenAnimation:]):
(-[WebFullScreenController requestExitFullScreen]):
(-[WebFullScreenController exitFullScreen]):
(-[WebFullScreenController finishedExitFullScreenAnimation:]):
(-[WebFullScreenController _manager]):
* WebView/WebView.mm:
(-[WebView _didStartProvisionalLoadForFrame:]):

Source/WebKitLegacy/win:

* WebCoreSupport/WebChromeClient.cpp:
(WebChromeClient::createWindow):
* WebView.cpp:
(WebView::fullScreenClientWillEnterFullScreen):
(WebView::fullScreenClientDidEnterFullScreen):
(WebView::fullScreenClientWillExitFullScreen):
(WebView::fullScreenClientDidExitFullScreen):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244440 268f45cc-cd09-0410-ab3c-d52691b4dbfc

45 files changed:
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/DerivedSources-input.xcfilelist
Source/WebCore/DerivedSources-output.xcfilelist
Source/WebCore/DerivedSources.make
Source/WebCore/Sources.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/CSSDefaultStyleSheets.cpp
Source/WebCore/css/SelectorCheckerTestFunctions.h
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/dom/Document.idl
Source/WebCore/dom/DocumentFullscreen.h [new file with mode: 0644]
Source/WebCore/dom/DocumentFullscreen.idl [new file with mode: 0644]
Source/WebCore/dom/Element.cpp
Source/WebCore/dom/EventPath.cpp
Source/WebCore/dom/FullscreenManager.cpp [new file with mode: 0644]
Source/WebCore/dom/FullscreenManager.h [new file with mode: 0644]
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/MediaElementSession.cpp
Source/WebCore/html/shadow/MediaControlElements.cpp
Source/WebCore/inspector/agents/InspectorDOMAgent.cpp
Source/WebCore/page/EventHandler.cpp
Source/WebCore/page/Page.cpp
Source/WebCore/rendering/RenderFullScreen.cpp
Source/WebCore/rendering/RenderLayerCompositor.cpp
Source/WebCore/rendering/updating/RenderTreeBuilder.h
Source/WebCore/rendering/updating/RenderTreeBuilderInline.cpp
Source/WebCore/rendering/updating/RenderTreeUpdater.cpp
Source/WebCore/style/StyleSharingResolver.cpp
Source/WebCore/testing/Internals.cpp
Source/WebKit/ChangeLog
Source/WebKit/WebProcess/FullScreen/WebFullScreenManager.cpp
Source/WebKit/WebProcess/InjectedBundle/API/gtk/DOM/WebKitDOMDocumentGtk.cpp
Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Source/WebKitLegacy/mac/ChangeLog
Source/WebKitLegacy/mac/DOM/DOMDocument.mm
Source/WebKitLegacy/mac/WebCoreSupport/WebChromeClient.mm
Source/WebKitLegacy/mac/WebCoreSupport/WebKitFullScreenListener.mm
Source/WebKitLegacy/mac/WebView/WebFullScreenController.mm
Source/WebKitLegacy/mac/WebView/WebView.mm
Source/WebKitLegacy/win/ChangeLog
Source/WebKitLegacy/win/WebCoreSupport/WebChromeClient.cpp
Source/WebKitLegacy/win/WebView.cpp

index 9a66248..55ca75b 100644 (file)
@@ -685,6 +685,7 @@ set(WebCore_NON_SVG_IDL_FILES
     dom/Document.idl
     dom/DocumentAndElementEventHandlers.idl
     dom/DocumentFragment.idl
+    dom/DocumentFullscreen.idl
     dom/DocumentOrShadowRoot.idl
     dom/DocumentTouch.idl
     dom/DocumentType.idl
index 7f84ea3..2e048fc 100644 (file)
@@ -1,5 +1,155 @@
 2019-04-18  Jer Noble  <jer.noble@apple.com>
 
+        Refactoring: Pull all fullscreen code out of Document and into its own helper class
+        https://bugs.webkit.org/show_bug.cgi?id=197017
+
+        Reviewed by Eric Carlson.
+
+        * CMakeLists.txt:
+        * DerivedSources-input.xcfilelist:
+        * DerivedSources-output.xcfilelist:
+        * DerivedSources.make:
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * css/CSSDefaultStyleSheets.cpp:
+        (WebCore::CSSDefaultStyleSheets::ensureDefaultStyleSheetsForElement):
+        * css/SelectorCheckerTestFunctions.h:
+        (WebCore::matchesFullScreenPseudoClass):
+        (WebCore::matchesFullScreenAnimatingFullScreenTransitionPseudoClass):
+        (WebCore::matchesFullScreenDocumentPseudoClass):
+        (WebCore::matchesFullScreenControlsHiddenPseudoClass):
+        * dom/Document.cpp:
+        (WebCore::Document::removedLastRef):
+        (WebCore::Document::prepareForDestruction):
+        (WebCore::Document::nodeChildrenWillBeRemoved):
+        (WebCore::Document::nodeWillBeRemoved):
+        (WebCore::isAttributeOnAllOwners): Deleted.
+        (WebCore::Document::fullScreenIsAllowedForElement const): Deleted.
+        (WebCore::Document::requestFullScreenForElement): Deleted.
+        (WebCore::Document::webkitCancelFullScreen): Deleted.
+        (WebCore::Document::webkitExitFullscreen): Deleted.
+        (WebCore::Document::webkitFullscreenEnabled const): Deleted.
+        (WebCore::unwrapFullScreenRenderer): Deleted.
+        (WebCore::Document::webkitWillEnterFullScreen): Deleted.
+        (WebCore::Document::webkitDidEnterFullScreen): Deleted.
+        (WebCore::Document::webkitWillExitFullScreen): Deleted.
+        (WebCore::Document::webkitDidExitFullScreen): Deleted.
+        (WebCore::Document::setFullScreenRenderer): Deleted.
+        (WebCore::Document::dispatchFullScreenChangeEvents): Deleted.
+        (WebCore::Document::dispatchFullScreenChangeOrErrorEvent): Deleted.
+        (WebCore::Document::fullScreenElementRemoved): Deleted.
+        (WebCore::Document::adjustFullScreenElementOnNodeRemoval): Deleted.
+        (WebCore::Document::isAnimatingFullScreen const): Deleted.
+        (WebCore::Document::setAnimatingFullScreen): Deleted.
+        (WebCore::Document::areFullscreenControlsHidden const): Deleted.
+        (WebCore::Document::setFullscreenControlsHidden): Deleted.
+        (WebCore::Document::clearFullscreenElementStack): Deleted.
+        (WebCore::Document::popFullscreenElementStack): Deleted.
+        (WebCore::Document::pushFullscreenElementStack): Deleted.
+        (WebCore::Document::addDocumentToFullScreenChangeEventQueue): Deleted.
+        * dom/Document.h:
+        (WebCore::Document::fullscreenManager):
+        (WebCore::Document::webkitIsFullScreen const): Deleted.
+        (WebCore::Document::webkitFullScreenKeyboardInputAllowed const): Deleted.
+        (WebCore::Document::webkitCurrentFullScreenElement const): Deleted.
+        (WebCore::Document::webkitCurrentFullScreenElementForBindings const): Deleted.
+        (WebCore::Document::fullScreenRenderer const): Deleted.
+        (WebCore::Document::webkitFullscreenElement const): Deleted.
+        (WebCore::Document::webkitFullscreenElementForBindings const): Deleted.
+        * dom/Document.idl:
+        * dom/DocumentFullscreen.h:
+        (WebCore::DocumentFullscreen::webkitFullscreenEnabled):
+        (WebCore::DocumentFullscreen::webkitFullscreenElement):
+        (WebCore::DocumentFullscreen::webkitExitFullscreen):
+        (WebCore::DocumentFullscreen::webkitIsFullScreen):
+        (WebCore::DocumentFullscreen::webkitFullScreenKeyboardInputAllowed):
+        (WebCore::DocumentFullscreen::webkitCurrentFullScreenElement):
+        (WebCore::DocumentFullscreen::webkitCancelFullScreen):
+        * dom/DocumentFullscreen.idl:
+        * dom/Element.cpp:
+        (WebCore::Element::webkitRequestFullscreen):
+        * dom/EventPath.cpp:
+        (WebCore::shouldEventCrossShadowBoundary):
+        * dom/FullscreenManager.cpp: Added.
+        (WebCore::isAttributeOnAllOwners):
+        (WebCore::FullscreenManager::FullscreenManager):
+        (WebCore::FullscreenManager::fullscreenIsAllowedForElement const):
+        (WebCore::FullscreenManager::requestFullscreenForElement):
+        (WebCore::FullscreenManager::cancelFullscreen):
+        (WebCore::FullscreenManager::requestExitFullscreen):
+        (WebCore::FullscreenManager::exitFullscreen):
+        (WebCore::FullscreenManager::isFullscreenEnabled const):
+        (WebCore::unwrapFullscreenRenderer):
+        (WebCore::FullscreenManager::willEnterFullscreen):
+        (WebCore::FullscreenManager::didEnterFullscreen):
+        (WebCore::FullscreenManager::willExitFullscreen):
+        (WebCore::FullscreenManager::didExitFullscreen):
+        (WebCore::FullscreenManager::setFullscreenRenderer):
+        (WebCore::FullscreenManager::dispatchFullscreenChangeEvents):
+        (WebCore::FullscreenManager::dispatchFullscreenChangeOrErrorEvent):
+        (WebCore::FullscreenManager::fullscreenElementRemoved):
+        (WebCore::FullscreenManager::adjustFullscreenElementOnNodeRemoval):
+        (WebCore::FullscreenManager::isAnimatingFullscreen const):
+        (WebCore::FullscreenManager::setAnimatingFullscreen):
+        (WebCore::FullscreenManager::areFullscreenControlsHidden const):
+        (WebCore::FullscreenManager::setFullscreenControlsHidden):
+        (WebCore::FullscreenManager::clear):
+        (WebCore::FullscreenManager::emptyEventQueue):
+        (WebCore::FullscreenManager::clearFullscreenElementStack):
+        (WebCore::FullscreenManager::popFullscreenElementStack):
+        (WebCore::FullscreenManager::pushFullscreenElementStack):
+        (WebCore::FullscreenManager::addDocumentToFullscreenChangeEventQueue):
+        * dom/FullscreenManager.h: Added.
+        (WebCore::FullscreenManager::document):
+        (WebCore::FullscreenManager::document const):
+        (WebCore::FullscreenManager::topDocument const):
+        (WebCore::FullscreenManager::page const):
+        (WebCore::FullscreenManager::frame const):
+        (WebCore::FullscreenManager::documentElement const):
+        (WebCore::FullscreenManager::hasLivingRenderTree const):
+        (WebCore::FullscreenManager::pageCacheState const):
+        (WebCore::FullscreenManager::scheduleFullStyleRebuild):
+        (WebCore::FullscreenManager::fullscreenElement const):
+        (WebCore::FullscreenManager::isFullscreen const):
+        (WebCore::FullscreenManager::isFullscreenKeyboardInputAllowed const):
+        (WebCore::FullscreenManager::currentFullscreenElement const):
+        (WebCore::FullscreenManager::fullscreenRenderer const):
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::isFullscreen const):
+        (WebCore::HTMLMediaElement::isStandardFullscreen const):
+        (WebCore::HTMLMediaElement::enterFullscreen):
+        (WebCore::HTMLMediaElement::exitFullscreen):
+        * html/MediaElementSession.cpp:
+        (WebCore::MediaElementSession::canShowControlsManager const):
+        * html/shadow/MediaControlElements.cpp:
+        (WebCore::MediaControlFullscreenButtonElement::defaultEventHandler):
+        * inspector/agents/InspectorDOMAgent.cpp:
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::isKeyEventAllowedInFullScreen const):
+        (WebCore::EventHandler::internalKeyEvent):
+        * page/Page.cpp:
+        (WebCore::Page::setFullscreenControlsHidden):
+        * rendering/RenderFullScreen.cpp:
+        (WebCore::RenderFullScreen::wrapNewRenderer):
+        (WebCore::RenderFullScreen::wrapExistingRenderer):
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::isDescendantOfFullScreenLayer):
+        * rendering/updating/RenderTreeBuilder.h:
+        * rendering/updating/RenderTreeBuilderInline.cpp:
+        (WebCore::RenderTreeBuilder::Inline::splitInlines):
+        * rendering/updating/RenderTreeUpdater.cpp:
+        (WebCore::RenderTreeUpdater::createRenderer):
+        * style/StyleSharingResolver.cpp:
+        (WebCore::Style::SharingResolver::canShareStyleWithElement const):
+        * testing/Internals.cpp:
+        (WebCore::Internals::webkitWillEnterFullScreenForElement):
+        (WebCore::Internals::webkitDidEnterFullScreenForElement):
+        (WebCore::Internals::webkitWillExitFullScreenForElement):
+        (WebCore::Internals::webkitDidExitFullScreenForElement):
+        (WebCore::Internals::isAnimatingFullScreen const):
+
+2019-04-18  Jer Noble  <jer.noble@apple.com>
+
         Add support for parsing FairPlayStreaming PSSH boxes.
         https://bugs.webkit.org/show_bug.cgi?id=197064
 
index 4df74bb..6b24a94 100644 (file)
@@ -559,6 +559,7 @@ $(PROJECT_DIR)/dom/DeviceOrientationOrMotionPermissionState.idl
 $(PROJECT_DIR)/dom/Document.idl
 $(PROJECT_DIR)/dom/DocumentAndElementEventHandlers.idl
 $(PROJECT_DIR)/dom/DocumentFragment.idl
+$(PROJECT_DIR)/dom/DocumentFullscreen.idl
 $(PROJECT_DIR)/dom/DocumentOrShadowRoot.idl
 $(PROJECT_DIR)/dom/DocumentTouch.idl
 $(PROJECT_DIR)/dom/DocumentType.idl
index 8b642a7..26b65ff 100644 (file)
@@ -471,6 +471,8 @@ $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSDocumentAndElementEventHandlers.c
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSDocumentAndElementEventHandlers.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSDocumentFragment.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSDocumentFragment.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSDocumentFullscreen.cpp
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSDocumentFullscreen.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSDocumentOrShadowRoot.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSDocumentOrShadowRoot.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSDocumentTimeline.cpp
index 3728302..033e64b 100644 (file)
@@ -581,6 +581,7 @@ JS_BINDING_IDLS = \
     $(WebCore)/dom/DeviceOrientationOrMotionPermissionState.idl \
     $(WebCore)/dom/Document.idl \
     $(WebCore)/dom/DocumentAndElementEventHandlers.idl \
+    $(WebCore)/dom/DocumentFullscreen.idl \
     $(WebCore)/dom/DocumentFragment.idl \
     $(WebCore)/dom/DocumentOrShadowRoot.idl \
     $(WebCore)/dom/DocumentType.idl \
index 23dd2a5..2da5cef 100644 (file)
@@ -858,6 +858,7 @@ dom/EventTarget.cpp
 dom/ExceptionData.cpp
 dom/ExtensionStyleSheets.cpp
 dom/FocusEvent.cpp
+dom/FullscreenManager.cpp
 dom/GenericEventQueue.cpp
 dom/IdTargetObserver.cpp
 dom/IdTargetObserverRegistry.cpp
index 5d16b33..b6f0523 100644 (file)
                CD8B5A46180DFF4E008B8E65 /* VideoTrackMediaSource.h in Headers */ = {isa = PBXBuildFile; fileRef = CD8B5A45180DFF4E008B8E65 /* VideoTrackMediaSource.h */; };
                CD8B5A49180E138B008B8E65 /* TextTrackMediaSource.h in Headers */ = {isa = PBXBuildFile; fileRef = CD8B5A48180E138B008B8E65 /* TextTrackMediaSource.h */; };
                CD8B5A4C180E17C0008B8E65 /* AudioTrackMediaSource.h in Headers */ = {isa = PBXBuildFile; fileRef = CD8B5A4B180E17C0008B8E65 /* AudioTrackMediaSource.h */; };
+               CD92F5132260FFEE00F87BB3 /* DocumentFullscreen.h in Headers */ = {isa = PBXBuildFile; fileRef = CD92F5102260FFEE00F87BB3 /* DocumentFullscreen.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               CD92F5182261038200F87BB3 /* FullscreenManager.h in Headers */ = {isa = PBXBuildFile; fileRef = CD92F5162261038200F87BB3 /* FullscreenManager.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CD94A5DD1F71D5D800F525C5 /* CDMClearKey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD94A5DB1F71CBB000F525C5 /* CDMClearKey.cpp */; };
                CD94A5DE1F72F57B00F525C5 /* CDMClient.h in Headers */ = {isa = PBXBuildFile; fileRef = CD94A5C91F71CA9D00F525C5 /* CDMClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CD9D82761C7AE535006FF066 /* TextureCacheCV.h in Headers */ = {isa = PBXBuildFile; fileRef = CD9D82741C7AE535006FF066 /* TextureCacheCV.h */; };
                CD8B5A48180E138B008B8E65 /* TextTrackMediaSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextTrackMediaSource.h; sourceTree = "<group>"; };
                CD8B5A4A180E17A3008B8E65 /* AudioTrackMediaSource.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = AudioTrackMediaSource.idl; sourceTree = "<group>"; };
                CD8B5A4B180E17C0008B8E65 /* AudioTrackMediaSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioTrackMediaSource.h; sourceTree = "<group>"; };
+               CD92F50F2260FFEE00F87BB3 /* DocumentFullscreen.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = DocumentFullscreen.idl; sourceTree = "<group>"; };
+               CD92F5102260FFEE00F87BB3 /* DocumentFullscreen.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DocumentFullscreen.h; sourceTree = "<group>"; };
+               CD92F5162261038200F87BB3 /* FullscreenManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FullscreenManager.h; sourceTree = "<group>"; };
+               CD92F5172261038200F87BB3 /* FullscreenManager.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FullscreenManager.cpp; sourceTree = "<group>"; };
                CD94A5C91F71CA9D00F525C5 /* CDMClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDMClient.h; sourceTree = "<group>"; };
                CD94A5CC1F71CB6900F525C5 /* CDMRequirement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDMRequirement.h; sourceTree = "<group>"; };
                CD94A5CD1F71CB6900F525C5 /* CDMKeySystemConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDMKeySystemConfiguration.h; sourceTree = "<group>"; };
                                A8185F3709765765005826D9 /* DocumentFragment.cpp */,
                                A8185F3509765765005826D9 /* DocumentFragment.h */,
                                1A494ED50A123F1A00FDAFC1 /* DocumentFragment.idl */,
+                               CD92F5102260FFEE00F87BB3 /* DocumentFullscreen.h */,
+                               CD92F50F2260FFEE00F87BB3 /* DocumentFullscreen.idl */,
                                46E1666C1FCC868700C9710B /* DocumentIdentifier.h */,
                                ED2BA83B09A24B91006C0AC4 /* DocumentMarker.h */,
                                CE057FA31220731100A476D5 /* DocumentMarkerController.cpp */,
                                B6D9D23314EABD260090D75E /* FocusEvent.h */,
                                B6D9D27214EABF030090D75E /* FocusEvent.idl */,
                                A853123C11D0471B00D4D077 /* FragmentScriptingPermission.h */,
+                               CD92F5172261038200F87BB3 /* FullscreenManager.cpp */,
+                               CD92F5162261038200F87BB3 /* FullscreenManager.h */,
                                9BAAC4582151E77A003D4A98 /* GCReachableRef.cpp */,
                                9BAAC4562151E39E003D4A98 /* GCReachableRef.h */,
                                0720B09E14D3323500642955 /* GenericEventQueue.cpp */,
                                A8185F4009765766005826D9 /* Document.h in Headers */,
                                A3BB59F41457A40D00AC56FE /* DocumentEventQueue.h in Headers */,
                                A8185F3D09765766005826D9 /* DocumentFragment.h in Headers */,
+                               CD92F5132260FFEE00F87BB3 /* DocumentFullscreen.h in Headers */,
                                46E1666E1FCC86A200C9710B /* DocumentIdentifier.h in Headers */,
                                656D37360ADBA5DE00A4554D /* DocumentLoader.h in Headers */,
                                ED2BA83C09A24B91006C0AC4 /* DocumentMarker.h in Headers */,
                                113D0B521F9FDD2B00F611BB /* FrameViewLayoutContext.h in Headers */,
                                97205AB0123928CA00B17380 /* FTPDirectoryDocument.h in Headers */,
                                51C81B8A0C4422F70019ECE3 /* FTPDirectoryParser.h in Headers */,
+                               CD92F5182261038200F87BB3 /* FullscreenManager.h in Headers */,
                                26B999931803B9D900D01121 /* FunctionCall.h in Headers */,
                                FD31600D12B0267600C1A359 /* GainNode.h in Headers */,
                                51E399001D6E4750009C8831 /* GameControllerGamepad.h in Headers */,
index 9445e91..b8069d6 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "Chrome.h"
 #include "ChromeClient.h"
+#include "FullscreenManager.h"
 #include "HTMLAnchorElement.h"
 #include "HTMLBRElement.h"
 #include "HTMLBodyElement.h"
@@ -268,7 +269,7 @@ void CSSDefaultStyleSheets::ensureDefaultStyleSheetsForElement(const Element& el
 #endif // ENABLE(MATHML)
 
 #if ENABLE(FULLSCREEN_API)
-    if (!fullscreenStyleSheet && element.document().webkitIsFullScreen()) {
+    if (!fullscreenStyleSheet && element.document().fullscreenManager().isFullscreen()) {
         String fullscreenRules = String(fullscreenUserAgentStyleSheet, sizeof(fullscreenUserAgentStyleSheet)) + RenderTheme::singleton().extraFullScreenStyleSheet();
         fullscreenStyleSheet = parseUASheet(fullscreenRules);
         addToDefaultStyle(*fullscreenStyleSheet);
index b8c7e61..5848fbe 100644 (file)
@@ -27,6 +27,7 @@
 #pragma once
 
 #include "FocusController.h"
+#include "FullscreenManager.h"
 #include "HTMLInputElement.h"
 #include "HTMLOptionElement.h"
 #include "RenderScrollbar.h"
@@ -351,16 +352,16 @@ ALWAYS_INLINE bool matchesFullScreenPseudoClass(const Element& element)
     // context's Document is in the fullscreen state has the 'full-screen' pseudoclass applied.
     if (element.isFrameElementBase() && element.containsFullScreenElement())
         return true;
-    if (!element.document().webkitIsFullScreen())
+    if (!element.document().fullscreenManager().isFullscreen())
         return false;
-    return &element == element.document().webkitCurrentFullScreenElement();
+    return &element == element.document().fullscreenManager().currentFullscreenElement();
 }
 
 ALWAYS_INLINE bool matchesFullScreenAnimatingFullScreenTransitionPseudoClass(const Element& element)
 {
-    if (&element != element.document().webkitCurrentFullScreenElement())
+    if (&element != element.document().fullscreenManager().currentFullscreenElement())
         return false;
-    return element.document().isAnimatingFullScreen();
+    return element.document().fullscreenManager().isAnimatingFullscreen();
 }
 
 ALWAYS_INLINE bool matchesFullScreenAncestorPseudoClass(const Element& element)
@@ -372,16 +373,16 @@ ALWAYS_INLINE bool matchesFullScreenDocumentPseudoClass(const Element& element)
 {
     // While a Document is in the fullscreen state, the 'full-screen-document' pseudoclass applies
     // to all elements of that Document.
-    if (!element.document().webkitIsFullScreen())
+    if (!element.document().fullscreenManager().isFullscreen())
         return false;
     return true;
 }
 
 ALWAYS_INLINE bool matchesFullScreenControlsHiddenPseudoClass(const Element& element)
 {
-    if (&element != element.document().webkitCurrentFullScreenElement())
+    if (&element != element.document().fullscreenManager().currentFullscreenElement())
         return false;
-    return element.document().areFullscreenControlsHidden();
+    return element.document().fullscreenManager().areFullscreenControlsHidden();
 }
 #endif
 
index 4c31bbd..9210d66 100644 (file)
@@ -75,6 +75,7 @@
 #include "FrameLoader.h"
 #include "FrameLoaderClient.h"
 #include "FrameView.h"
+#include "FullscreenManager.h"
 #include "GenericCachedHTMLCollection.h"
 #include "HTMLAllCollection.h"
 #include "HTMLAnchorElement.h"
@@ -509,6 +510,9 @@ Document::Document(Frame* frame, const URL& url, unsigned documentClasses, unsig
     , m_constantPropertyMap(std::make_unique<ConstantPropertyMap>(*this))
     , m_documentClasses(documentClasses)
     , m_eventQueue(*this)
+#if ENABLE(FULLSCREEN_API)
+    , m_fullscreenManager { makeUniqueRef<FullscreenManager>(*this) }
+#endif
 #if ENABLE(INTERSECTION_OBSERVER)
     , m_intersectionObserversNotifyTimer(*this, &Document::notifyIntersectionObserversTimerFired)
 #endif
@@ -560,21 +564,6 @@ Document::Document(Frame* frame, const URL& url, unsigned documentClasses, unsig
     InspectorInstrumentation::addEventListenersToNode(*this);
 }
 
-#if ENABLE(FULLSCREEN_API)
-
-static bool isAttributeOnAllOwners(const WebCore::QualifiedName& attribute, const WebCore::QualifiedName& prefixedAttribute, const HTMLFrameOwnerElement* owner)
-{
-    if (!owner)
-        return true;
-    do {
-        if (!(owner->hasAttribute(attribute) || owner->hasAttribute(prefixedAttribute)))
-            return false;
-    } while ((owner = owner->document().ownerElement()));
-    return true;
-}
-
-#endif
-
 Ref<Document> Document::create(Document& contextDocument)
 {
     auto document = adoptRef(*new Document(nullptr, URL()));
@@ -685,8 +674,7 @@ void Document::removedLastRef()
         m_focusNavigationStartingNode = nullptr;
         m_userActionElements.clear();
 #if ENABLE(FULLSCREEN_API)
-        m_fullScreenElement = nullptr;
-        m_fullScreenElementStack.clear();
+        m_fullscreenManager->clear();
 #endif
         m_associatedFormControls.clear();
 
@@ -2499,8 +2487,7 @@ void Document::prepareForDestruction()
     stopActiveDOMObjects();
     m_eventQueue.close();
 #if ENABLE(FULLSCREEN_API)
-    m_fullScreenChangeEventTargetQueue.clear();
-    m_fullScreenErrorEventTargetQueue.clear();
+    m_fullscreenManager->emptyEventQueue();
 #endif
 
     commonTeardown();
@@ -4437,7 +4424,7 @@ void Document::nodeChildrenWillBeRemoved(ContainerNode& container)
     adjustFocusNavigationNodeOnNodeRemoval(container, NodeRemoval::ChildrenOfNode);
 
 #if ENABLE(FULLSCREEN_API)
-    adjustFullScreenElementOnNodeRemoval(container, NodeRemoval::ChildrenOfNode);
+    m_fullscreenManager->adjustFullscreenElementOnNodeRemoval(container, NodeRemoval::ChildrenOfNode);
 #endif
 
     for (auto* range : m_ranges)
@@ -4470,7 +4457,7 @@ void Document::nodeWillBeRemoved(Node& node)
     adjustFocusNavigationNodeOnNodeRemoval(node);
 
 #if ENABLE(FULLSCREEN_API)
-    adjustFullScreenElementOnNodeRemoval(node);
+    m_fullscreenManager->adjustFullscreenElementOnNodeRemoval(node, NodeRemoval::Node);
 #endif
 
     for (auto* it : m_nodeIterators)
@@ -6339,507 +6326,6 @@ void Document::simulateDeviceOrientationChange(double alpha, double beta, double
 
 #endif
 
-#if ENABLE(FULLSCREEN_API)
-
-bool Document::fullScreenIsAllowedForElement(Element& element) const
-{
-    return isAttributeOnAllOwners(allowfullscreenAttr, webkitallowfullscreenAttr, element.document().ownerElement());
-}
-
-void Document::requestFullScreenForElement(Element* element, FullScreenCheckType checkType)
-{
-    if (!element)
-        element = documentElement();
-
-    auto failedPreflights = [this](auto element) mutable {
-        m_fullScreenErrorEventTargetQueue.append(WTFMove(element));
-        m_fullScreenTaskQueue.enqueueTask([this] {
-            dispatchFullScreenChangeEvents();
-        });
-    };
-
-    // 1. If any of the following conditions are true, terminate these steps and queue a task to fire
-    // an event named fullscreenerror with its bubbles attribute set to true on the context object's
-    // node document:
-
-    // This algorithm is not allowed to show a pop-up:
-    //   An algorithm is allowed to show a pop-up if, in the task in which the algorithm is running, either:
-    //   - an activation behavior is currently being processed whose click event was trusted, or
-    //   - the event listener for a trusted click event is being handled.
-    if (!UserGestureIndicator::processingUserGesture()) {
-        failedPreflights(WTFMove(element));
-        return;
-    }
-
-    // We do not allow pressing the Escape key as a user gesture to enter fullscreen since this is the key
-    // to exit fullscreen.
-    if (UserGestureIndicator::currentUserGesture()->gestureType() == UserGestureType::EscapeKey) {
-        addConsoleMessage(MessageSource::Security, MessageLevel::Error, "The Escape key may not be used as a user gesture to enter fullscreen"_s);
-        failedPreflights(WTFMove(element));
-        return;
-    }
-
-    // There is a previously-established user preference, security risk, or platform limitation.
-    if (!page() || !page()->settings().fullScreenEnabled()) {
-        failedPreflights(WTFMove(element));
-        return;
-    }
-
-    bool hasKeyboardAccess = true;
-    if (!page()->chrome().client().supportsFullScreenForElement(*element, hasKeyboardAccess)) {
-        // The new full screen API does not accept a "flags" parameter, so fall back to disallowing
-        // keyboard input if the chrome client refuses to allow keyboard input.
-        hasKeyboardAccess = false;
-
-        if (!page()->chrome().client().supportsFullScreenForElement(*element, hasKeyboardAccess)) {
-            failedPreflights(WTFMove(element));
-            return;
-        }
-    }
-
-    m_fullScreenTaskQueue.enqueueTask([this, element = makeRefPtr(element), checkType, hasKeyboardAccess, failedPreflights] () mutable {
-        // Don't allow fullscreen if document is hidden.
-        if (hidden()) {
-            failedPreflights(WTFMove(element));
-            return;
-        }
-
-        // The context object is not in a document.
-        if (!element->isConnected()) {
-            failedPreflights(WTFMove(element));
-            return;
-        }
-
-        // The context object's node document, or an ancestor browsing context's document does not have
-        // the fullscreen enabled flag set.
-        if (checkType == EnforceIFrameAllowFullScreenRequirement && !fullScreenIsAllowedForElement(*element)) {
-            failedPreflights(WTFMove(element));
-            return;
-        }
-
-        // The context object's node document fullscreen element stack is not empty and its top element
-        // is not an ancestor of the context object.
-        if (!m_fullScreenElementStack.isEmpty() && !m_fullScreenElementStack.last()->contains(element.get())) {
-            failedPreflights(WTFMove(element));
-            return;
-        }
-
-        // A descendant browsing context's document has a non-empty fullscreen element stack.
-        bool descendentHasNonEmptyStack = false;
-        for (Frame* descendant = frame() ? frame()->tree().traverseNext() : nullptr; descendant; descendant = descendant->tree().traverseNext()) {
-            if (descendant->document()->webkitFullscreenElement()) {
-                descendentHasNonEmptyStack = true;
-                break;
-            }
-        }
-        if (descendentHasNonEmptyStack) {
-            failedPreflights(WTFMove(element));
-            return;
-        }
-
-        // 2. Let doc be element's node document. (i.e. "this")
-        Document* currentDoc = this;
-
-        // 3. Let docs be all doc's ancestor browsing context's documents (if any) and doc.
-        Deque<Document*> docs;
-
-        do {
-            docs.prepend(currentDoc);
-            currentDoc = currentDoc->ownerElement() ? &currentDoc->ownerElement()->document() : nullptr;
-        } while (currentDoc);
-
-        // 4. For each document in docs, run these substeps:
-        Deque<Document*>::iterator current = docs.begin(), following = docs.begin();
-
-        do {
-            ++following;
-
-            // 1. Let following document be the document after document in docs, or null if there is no
-            // such document.
-            Document* currentDoc = *current;
-            Document* followingDoc = following != docs.end() ? *following : nullptr;
-
-            // 2. If following document is null, push context object on document's fullscreen element
-            // stack, and queue a task to fire an event named fullscreenchange with its bubbles attribute
-            // set to true on the document.
-            if (!followingDoc) {
-                currentDoc->pushFullscreenElementStack(*element);
-                addDocumentToFullScreenChangeEventQueue(*currentDoc);
-                continue;
-            }
-
-            // 3. Otherwise, if document's fullscreen element stack is either empty or its top element
-            // is not following document's browsing context container,
-            Element* topElement = currentDoc->webkitFullscreenElement();
-            if (!topElement || topElement != followingDoc->ownerElement()) {
-                // ...push following document's browsing context container on document's fullscreen element
-                // stack, and queue a task to fire an event named fullscreenchange with its bubbles attribute
-                // set to true on document.
-                currentDoc->pushFullscreenElementStack(*followingDoc->ownerElement());
-                addDocumentToFullScreenChangeEventQueue(*currentDoc);
-                continue;
-            }
-
-            // 4. Otherwise, do nothing for this document. It stays the same.
-        } while (++current != docs.end());
-
-        // 5. Return, and run the remaining steps asynchronously.
-        // 6. Optionally, perform some animation.
-        m_areKeysEnabledInFullScreen = hasKeyboardAccess;
-        m_fullScreenTaskQueue.enqueueTask([this, element = WTFMove(element)] {
-            if (auto page = this->page())
-                page->chrome().client().enterFullScreenForElement(*element.get());
-        });
-
-        // 7. Optionally, display a message indicating how the user can exit displaying the context object fullscreen.
-    });
-}
-
-void Document::webkitCancelFullScreen()
-{
-    // The Mozilla "cancelFullScreen()" API behaves like the W3C "fully exit fullscreen" behavior, which
-    // is defined as: 
-    // "To fully exit fullscreen act as if the exitFullscreen() method was invoked on the top-level browsing
-    // context's document and subsequently empty that document's fullscreen element stack."
-    Document& topDocument = this->topDocument();
-    if (!topDocument.webkitFullscreenElement())
-        return;
-
-    // To achieve that aim, remove all the elements from the top document's stack except for the first before
-    // calling webkitExitFullscreen():
-    Vector<RefPtr<Element>> replacementFullscreenElementStack;
-    replacementFullscreenElementStack.append(topDocument.webkitFullscreenElement());
-    topDocument.m_fullScreenElementStack.swap(replacementFullscreenElementStack);
-
-    topDocument.webkitExitFullscreen();
-}
-
-void Document::webkitExitFullscreen()
-{
-    // The exitFullscreen() method must run these steps:
-    
-    // 1. Let doc be the context object. (i.e. "this")
-    Document* currentDoc = this;
-
-    // 2. If doc's fullscreen element stack is empty, terminate these steps.
-    if (m_fullScreenElementStack.isEmpty())
-        return;
-    
-    // 3. Let descendants be all the doc's descendant browsing context's documents with a non-empty fullscreen
-    // element stack (if any), ordered so that the child of the doc is last and the document furthest
-    // away from the doc is first.
-    Deque<RefPtr<Document>> descendants;
-    for (Frame* descendant = frame() ? frame()->tree().traverseNext() : nullptr; descendant; descendant = descendant->tree().traverseNext()) {
-        if (descendant->document()->webkitFullscreenElement())
-            descendants.prepend(descendant->document());
-    }
-        
-    // 4. For each descendant in descendants, empty descendant's fullscreen element stack, and queue a
-    // task to fire an event named fullscreenchange with its bubbles attribute set to true on descendant.
-    for (auto& document : descendants) {
-        document->clearFullscreenElementStack();
-        addDocumentToFullScreenChangeEventQueue(*document);
-    }
-
-    // 5. While doc is not null, run these substeps:
-    Element* newTop = nullptr;
-    while (currentDoc) {
-        // 1. Pop the top element of doc's fullscreen element stack.
-        currentDoc->popFullscreenElementStack();
-
-        //    If doc's fullscreen element stack is non-empty and the element now at the top is either
-        //    not in a document or its node document is not doc, repeat this substep.
-        newTop = currentDoc->webkitFullscreenElement();
-        if (newTop && (!newTop->isConnected() || &newTop->document() != currentDoc))
-            continue;
-
-        // 2. Queue a task to fire an event named fullscreenchange with its bubbles attribute set to true
-        // on doc.
-        addDocumentToFullScreenChangeEventQueue(*currentDoc);
-
-        // 3. If doc's fullscreen element stack is empty and doc's browsing context has a browsing context
-        // container, set doc to that browsing context container's node document.
-        if (!newTop && currentDoc->ownerElement()) {
-            currentDoc = &currentDoc->ownerElement()->document();
-            continue;
-        }
-
-        // 4. Otherwise, set doc to null.
-        currentDoc = nullptr;
-    }
-
-    // 6. Return, and run the remaining steps asynchronously.
-    // 7. Optionally, perform some animation.
-    m_fullScreenTaskQueue.enqueueTask([this, newTop = makeRefPtr(newTop), fullScreenElement = m_fullScreenElement] {
-        auto* page = this->page();
-        if (!page)
-            return;
-
-        // Only exit out of full screen window mode if there are no remaining elements in the 
-        // full screen stack.
-        if (!newTop) {
-            page->chrome().client().exitFullScreenForElement(fullScreenElement.get());
-            return;
-        }
-
-        // Otherwise, notify the chrome of the new full screen element.
-        page->chrome().client().enterFullScreenForElement(*newTop);
-    });
-}
-
-bool Document::webkitFullscreenEnabled() const
-{
-    // 4. The fullscreenEnabled attribute must return true if the context object and all ancestor
-    // browsing context's documents have their fullscreen enabled flag set, or false otherwise.
-
-    // Top-level browsing contexts are implied to have their allowFullScreen attribute set.
-    return isAttributeOnAllOwners(allowfullscreenAttr, webkitallowfullscreenAttr, ownerElement());
-}
-
-static void unwrapFullScreenRenderer(RenderFullScreen* fullScreenRenderer, Element* fullScreenElement)
-{
-    if (!fullScreenRenderer)
-        return;
-    bool requiresRenderTreeRebuild;
-    fullScreenRenderer->unwrapRenderer(requiresRenderTreeRebuild);
-
-    if (requiresRenderTreeRebuild && fullScreenElement && fullScreenElement->parentElement())
-        fullScreenElement->parentElement()->invalidateStyleAndRenderersForSubtree();
-}
-
-void Document::webkitWillEnterFullScreen(Element& element)
-{
-    if (!hasLivingRenderTree() || pageCacheState() != NotInPageCache)
-        return;
-
-    // Protect against being called after the document has been removed from the page.
-    if (!page())
-        return;
-
-    ASSERT(page()->settings().fullScreenEnabled());
-
-    unwrapFullScreenRenderer(m_fullScreenRenderer.get(), m_fullScreenElement.get());
-
-    element.willBecomeFullscreenElement();
-    
-    m_fullScreenElement = &element;
-
-#if USE(NATIVE_FULLSCREEN_VIDEO)
-    if (element.isMediaElement())
-        return;
-#endif
-
-    // Create a placeholder block for a the full-screen element, to keep the page from reflowing
-    // when the element is removed from the normal flow.  Only do this for a RenderBox, as only 
-    // a box will have a frameRect.  The placeholder will be created in setFullScreenRenderer()
-    // during layout.
-    auto renderer = m_fullScreenElement->renderer();
-    bool shouldCreatePlaceholder = is<RenderBox>(renderer);
-    if (shouldCreatePlaceholder) {
-        m_savedPlaceholderFrameRect = downcast<RenderBox>(*renderer).frameRect();
-        m_savedPlaceholderRenderStyle = RenderStyle::clonePtr(renderer->style());
-    }
-
-    if (m_fullScreenElement != documentElement() && renderer)
-        RenderFullScreen::wrapExistingRenderer(*renderer, *this);
-
-    m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(true);
-
-    resolveStyle(ResolveStyleType::Rebuild);
-    dispatchFullScreenChangeEvents();
-}
-
-void Document::webkitDidEnterFullScreen()
-{
-    if (!m_fullScreenElement)
-        return;
-
-    if (!hasLivingRenderTree() || pageCacheState() != NotInPageCache)
-        return;
-
-    m_fullScreenElement->didBecomeFullscreenElement();
-}
-
-void Document::webkitWillExitFullScreen()
-{
-    if (!m_fullScreenElement)
-        return;
-
-    if (!hasLivingRenderTree() || pageCacheState() != NotInPageCache)
-        return;
-
-    m_fullScreenElement->willStopBeingFullscreenElement();
-}
-
-void Document::webkitDidExitFullScreen()
-{
-    if (!m_fullScreenElement)
-        return;
-
-    if (!hasLivingRenderTree() || pageCacheState() != NotInPageCache)
-        return;
-
-    m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false);
-
-    m_areKeysEnabledInFullScreen = false;
-
-    unwrapFullScreenRenderer(m_fullScreenRenderer.get(), m_fullScreenElement.get());
-
-    m_fullScreenElement = nullptr;
-    scheduleFullStyleRebuild();
-
-    // When webkitCancelFullScreen is called, we call webkitExitFullScreen on the topDocument(). That
-    // means that the events will be queued there. So if we have no events here, start the timer on
-    // the exiting document.
-    bool eventTargetQueuesEmpty = m_fullScreenChangeEventTargetQueue.isEmpty() && m_fullScreenErrorEventTargetQueue.isEmpty();
-    Document& exitingDocument = eventTargetQueuesEmpty ? topDocument() : *this;
-
-    exitingDocument.dispatchFullScreenChangeEvents();
-}
-
-void Document::setFullScreenRenderer(RenderTreeBuilder& builder, RenderFullScreen& renderer)
-{
-    if (&renderer == m_fullScreenRenderer)
-        return;
-
-    if (m_savedPlaceholderRenderStyle)
-        builder.createPlaceholderForFullScreen(renderer, WTFMove(m_savedPlaceholderRenderStyle), m_savedPlaceholderFrameRect);
-    else if (m_fullScreenRenderer && m_fullScreenRenderer->placeholder()) {
-        auto* placeholder = m_fullScreenRenderer->placeholder();
-        builder.createPlaceholderForFullScreen(renderer, RenderStyle::clonePtr(placeholder->style()), placeholder->frameRect());
-    }
-
-    if (m_fullScreenRenderer)
-        builder.destroy(*m_fullScreenRenderer);
-    ASSERT(!m_fullScreenRenderer);
-
-    m_fullScreenRenderer = makeWeakPtr(renderer);
-}
-
-void Document::dispatchFullScreenChangeEvents()
-{
-    // Since we dispatch events in this function, it's possible that the
-    // document will be detached and GC'd. We protect it here to make sure we
-    // can finish the function successfully.
-    Ref<Document> protectedThis(*this);
-    Deque<RefPtr<Node>> changeQueue;
-    m_fullScreenChangeEventTargetQueue.swap(changeQueue);
-    Deque<RefPtr<Node>> errorQueue;
-    m_fullScreenErrorEventTargetQueue.swap(errorQueue);
-    dispatchFullScreenChangeOrErrorEvent(changeQueue, eventNames().webkitfullscreenchangeEvent, /* shouldNotifyMediaElement */ true);
-    dispatchFullScreenChangeOrErrorEvent(errorQueue, eventNames().webkitfullscreenerrorEvent, /* shouldNotifyMediaElement */ false);
-}
-
-void Document::dispatchFullScreenChangeOrErrorEvent(Deque<RefPtr<Node>>& queue, const AtomicString& eventName, bool shouldNotifyMediaElement)
-{
-    while (!queue.isEmpty()) {
-        RefPtr<Node> node = queue.takeFirst();
-        if (!node)
-            node = documentElement();
-        // The dispatchEvent below may have blown away our documentElement.
-        if (!node)
-            continue;
-
-        // If the element was removed from our tree, also message the documentElement. Since we may
-        // have a document hierarchy, check that node isn't in another document.
-        if (!node->isConnected())
-            queue.append(documentElement());
-
-#if ENABLE(VIDEO)
-        if (shouldNotifyMediaElement && is<HTMLMediaElement>(*node))
-            downcast<HTMLMediaElement>(*node).enteredOrExitedFullscreen();
-#else
-        UNUSED_PARAM(shouldNotifyMediaElement);
-#endif
-        node->dispatchEvent(Event::create(eventName, Event::CanBubble::Yes, Event::IsCancelable::No));
-    }
-}
-
-void Document::fullScreenElementRemoved()
-{
-    m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false);
-    webkitCancelFullScreen();
-}
-
-void Document::adjustFullScreenElementOnNodeRemoval(Node& node, NodeRemoval nodeRemoval)
-{
-    if (!m_fullScreenElement)
-        return;
-    
-    bool elementInSubtree = false;
-    if (nodeRemoval == NodeRemoval::ChildrenOfNode)
-        elementInSubtree = m_fullScreenElement->isDescendantOf(node);
-    else
-        elementInSubtree = (m_fullScreenElement == &node) || m_fullScreenElement->isDescendantOf(node);
-    
-    if (elementInSubtree)
-        fullScreenElementRemoved();
-}
-
-bool Document::isAnimatingFullScreen() const
-{
-    return m_isAnimatingFullScreen;
-}
-
-void Document::setAnimatingFullScreen(bool flag)
-{
-    if (m_isAnimatingFullScreen == flag)
-        return;
-    m_isAnimatingFullScreen = flag;
-
-    if (m_fullScreenElement && m_fullScreenElement->isDescendantOf(*this)) {
-        m_fullScreenElement->invalidateStyleForSubtree();
-        scheduleFullStyleRebuild();
-    }
-}
-
-bool Document::areFullscreenControlsHidden() const
-{
-    return m_areFullscreenControlsHidden;
-}
-
-void Document::setFullscreenControlsHidden(bool flag)
-{
-    if (m_areFullscreenControlsHidden == flag)
-        return;
-    m_areFullscreenControlsHidden = flag;
-
-    if (m_fullScreenElement && m_fullScreenElement->isDescendantOf(*this)) {
-        m_fullScreenElement->invalidateStyleForSubtree();
-        scheduleFullStyleRebuild();
-    }
-}
-
-void Document::clearFullscreenElementStack()
-{
-    m_fullScreenElementStack.clear();
-}
-
-void Document::popFullscreenElementStack()
-{
-    if (m_fullScreenElementStack.isEmpty())
-        return;
-
-    m_fullScreenElementStack.removeLast();
-}
-
-void Document::pushFullscreenElementStack(Element& element)
-{
-    m_fullScreenElementStack.append(&element);
-}
-
-void Document::addDocumentToFullScreenChangeEventQueue(Document& document)
-{
-    Node* target = document.webkitFullscreenElement();
-    if (!target)
-        target = document.webkitCurrentFullScreenElement();
-    if (!target)
-        target = &document;
-    m_fullScreenChangeEventTargetQueue.append(target);
-}
-
-#endif
-
 #if ENABLE(POINTER_LOCK)
 
 void Document::exitPointerLock()
index 3cd25af..1417c2e 100644 (file)
@@ -123,6 +123,7 @@ class FontFaceSet;
 class FormController;
 class Frame;
 class FrameView;
+class FullscreenManager;
 class HTMLAllCollection;
 class HTMLBodyElement;
 class HTMLCanvasElement;
@@ -162,7 +163,6 @@ class ProcessingInstruction;
 class QualifiedName;
 class Quirks;
 class Range;
-class RenderFullScreen;
 class RenderTreeBuilder;
 class RenderView;
 class RequestAnimationFrameCallback;
@@ -1175,42 +1175,8 @@ public:
     MediaCanStartListener* takeAnyMediaCanStartListener();
 
 #if ENABLE(FULLSCREEN_API)
-    bool webkitIsFullScreen() const { return m_fullScreenElement.get(); }
-    bool webkitFullScreenKeyboardInputAllowed() const { return m_fullScreenElement.get() && m_areKeysEnabledInFullScreen; }
-    Element* webkitCurrentFullScreenElement() const { return m_fullScreenElement.get(); }
-    Element* webkitCurrentFullScreenElementForBindings() const { return ancestorElementInThisScope(webkitCurrentFullScreenElement()); }
-
-    enum FullScreenCheckType {
-        EnforceIFrameAllowFullScreenRequirement,
-        ExemptIFrameAllowFullScreenRequirement,
-    };
-
-    void requestFullScreenForElement(Element*, FullScreenCheckType);
-    WEBCORE_EXPORT void webkitCancelFullScreen();
-    
-    WEBCORE_EXPORT void webkitWillEnterFullScreen(Element&);
-    WEBCORE_EXPORT void webkitDidEnterFullScreen();
-    WEBCORE_EXPORT void webkitWillExitFullScreen();
-    WEBCORE_EXPORT void webkitDidExitFullScreen();
-    
-    void setFullScreenRenderer(RenderTreeBuilder&, RenderFullScreen&);
-    RenderFullScreen* fullScreenRenderer() const { return m_fullScreenRenderer.get(); }
-
-    void dispatchFullScreenChangeEvents();
-    bool fullScreenIsAllowedForElement(Element&) const;
-    void fullScreenElementRemoved();
-    void adjustFullScreenElementOnNodeRemoval(Node&, NodeRemoval = NodeRemoval::Node);
-
-    WEBCORE_EXPORT bool isAnimatingFullScreen() const;
-    WEBCORE_EXPORT void setAnimatingFullScreen(bool);
-
-    WEBCORE_EXPORT bool areFullscreenControlsHidden() const;
-    WEBCORE_EXPORT void setFullscreenControlsHidden(bool);
-
-    WEBCORE_EXPORT bool webkitFullscreenEnabled() const;
-    Element* webkitFullscreenElement() const { return !m_fullScreenElementStack.isEmpty() ? m_fullScreenElementStack.last().get() : nullptr; }
-    Element* webkitFullscreenElementForBindings() const { return ancestorElementInThisScope(webkitFullscreenElement()); }
-    WEBCORE_EXPORT void webkitExitFullscreen();
+    FullscreenManager& fullscreenManager() { return m_fullscreenManager; }
+    const FullscreenManager& fullscreenManager() const { return m_fullscreenManager; }
 #endif
 
 #if ENABLE(POINTER_LOCK)
@@ -1628,14 +1594,6 @@ private:
 
     template<CollectionType> Ref<HTMLCollection> ensureCachedCollection();
 
-#if ENABLE(FULLSCREEN_API)
-    void dispatchFullScreenChangeOrErrorEvent(Deque<RefPtr<Node>>&, const AtomicString& eventName, bool shouldNotifyMediaElement);
-    void clearFullscreenElementStack();
-    void popFullscreenElementStack();
-    void pushFullscreenElementStack(Element&);
-    void addDocumentToFullScreenChangeEventQueue(Document&);
-#endif
-
     void dispatchDisabledAdaptationsDidChangeForMainFrame();
 
     void setVisualUpdatesAllowed(ReadyState);
@@ -1851,18 +1809,7 @@ private:
     HashSet<MediaCanStartListener*> m_mediaCanStartListeners;
 
 #if ENABLE(FULLSCREEN_API)
-    RefPtr<Element> m_fullScreenElement;
-    Vector<RefPtr<Element>> m_fullScreenElementStack;
-    WeakPtr<RenderFullScreen> m_fullScreenRenderer { nullptr };
-    GenericTaskQueue<Timer> m_fullScreenTaskQueue;
-    Deque<RefPtr<Node>> m_fullScreenChangeEventTargetQueue;
-    Deque<RefPtr<Node>> m_fullScreenErrorEventTargetQueue;
-    LayoutRect m_savedPlaceholderFrameRect;
-    std::unique_ptr<RenderStyle> m_savedPlaceholderRenderStyle;
-
-    bool m_areKeysEnabledInFullScreen { false };
-    bool m_isAnimatingFullScreen { false };
-    bool m_areFullscreenControlsHidden { false };
+    UniqueRef<FullscreenManager> m_fullscreenManager;
 #endif
 
     HashSet<HTMLPictureElement*> m_viewportDependentPictures;
index bce2bfe..43b9110 100644 (file)
@@ -140,18 +140,6 @@ typedef (
     XPathNSResolver createNSResolver(Node? nodeResolver);
     [MayThrowException] XPathResult evaluate(optional DOMString expression = "undefined", optional Node? contextNode, optional XPathNSResolver? resolver, optional unsigned short type = 0, optional XPathResult? inResult); // FIXME: Using "undefined" as default parameter value is wrong.
 
-    // Extensions from FullScreen API (https://fullscreen.spec.whatwg.org/#api).
-    // FIXME: Should probably be unprefixed.
-    [Conditional=FULLSCREEN_API, EnabledBySetting=FullScreen] readonly attribute boolean webkitFullscreenEnabled;
-    [Conditional=FULLSCREEN_API, EnabledBySetting=FullScreen, ImplementedAs=webkitFullscreenElementForBindings] readonly attribute Element? webkitFullscreenElement;
-    [Conditional=FULLSCREEN_API, EnabledBySetting=FullScreen] void webkitExitFullscreen();
-    [Conditional=FULLSCREEN_API, EnabledBySetting=FullScreen] readonly attribute boolean webkitIsFullScreen; // Mozilla version.
-    [Conditional=FULLSCREEN_API, EnabledBySetting=FullScreen] readonly attribute boolean webkitFullScreenKeyboardInputAllowed; // Mozilla version.
-    [Conditional=FULLSCREEN_API, EnabledBySetting=FullScreen, ImplementedAs=webkitCurrentFullScreenElementForBindings] readonly attribute Element webkitCurrentFullScreenElement; // Mozilla version.
-    [Conditional=FULLSCREEN_API, EnabledBySetting=FullScreen] void webkitCancelFullScreen(); // Mozilla version.
-    [NotEnumerable, Conditional=FULLSCREEN_API, EnabledBySetting=FullScreen] attribute EventHandler onwebkitfullscreenchange;
-    [NotEnumerable, Conditional=FULLSCREEN_API, EnabledBySetting=FullScreen] attribute EventHandler onwebkitfullscreenerror;
-
     // Extensions from Pointer Lock API (https://www.w3.org/TR/pointerlock/#extensions-to-the-document-interface).
     [NotEnumerable, Conditional=POINTER_LOCK] attribute EventHandler onpointerlockchange; // FIXME: Should be enumerable.
     [NotEnumerable, Conditional=POINTER_LOCK] attribute EventHandler onpointerlockerror; // FIXME: Should be enumerable.
diff --git a/Source/WebCore/dom/DocumentFullscreen.h b/Source/WebCore/dom/DocumentFullscreen.h
new file mode 100644 (file)
index 0000000..b2daf86
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(FULLSCREEN_API)
+
+#include "Document.h"
+#include "FullscreenManager.h"
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class Document;
+class Element;
+
+class DocumentFullscreen {
+public:
+    static bool webkitFullscreenEnabled(Document& document) { return document.fullscreenManager().isFullscreenEnabled(); }
+    static Element* webkitFullscreenElement(Document& document) { return document.ancestorElementInThisScope(document.fullscreenManager().fullscreenElement()); }
+    static void webkitExitFullscreen(Document& document) { document.fullscreenManager().exitFullscreen(); }
+    static bool webkitIsFullScreen(Document& document) { return document.fullscreenManager().isFullscreen(); }
+    static bool webkitFullScreenKeyboardInputAllowed(Document& document) { return document.fullscreenManager().isFullscreenKeyboardInputAllowed(); }
+    static Element* webkitCurrentFullScreenElement(Document& document) { return document.ancestorElementInThisScope(document.fullscreenManager().currentFullscreenElement()); }
+    static void webkitCancelFullScreen(Document& document) { document.fullscreenManager().cancelFullscreen(); }
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/dom/DocumentFullscreen.idl b/Source/WebCore/dom/DocumentFullscreen.idl
new file mode 100644 (file)
index 0000000..6d4cf59
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+[
+    Conditional=FULLSCREEN_API,
+    EnabledBySetting=FullScreen,
+] partial interface Document {
+    // Extensions from FullScreen API (https://fullscreen.spec.whatwg.org/#api).
+    // FIXME: Should probably be unprefixed.
+    readonly attribute boolean webkitFullscreenEnabled;
+    readonly attribute Element? webkitFullscreenElement;
+    void webkitExitFullscreen();
+
+    // Mozilla versions.
+    readonly attribute boolean webkitIsFullScreen;
+    readonly attribute boolean webkitFullScreenKeyboardInputAllowed;
+    readonly attribute Element webkitCurrentFullScreenElement;
+    void webkitCancelFullScreen();
+
+    [NotEnumerable] attribute EventHandler onwebkitfullscreenchange;
+    [NotEnumerable] attribute EventHandler onwebkitfullscreenerror;
+};
index 4d4b9df..bb7b49f 100644 (file)
@@ -55,6 +55,7 @@
 #include "Frame.h"
 #include "FrameSelection.h"
 #include "FrameView.h"
+#include "FullscreenManager.h"
 #include "HTMLBodyElement.h"
 #include "HTMLCanvasElement.h"
 #include "HTMLCollection.h"
@@ -3449,7 +3450,7 @@ static Element* parentCrossingFrameBoundaries(const Element* element)
 
 void Element::webkitRequestFullscreen()
 {
-    document().requestFullScreenForElement(this, Document::EnforceIFrameAllowFullScreenRequirement);
+    document().fullscreenManager().requestFullscreenForElement(this, FullscreenManager::EnforceIFrameAllowFullscreenRequirement);
 }
 
 bool Element::containsFullScreenElement() const
index 7f29c04..db1428d 100644 (file)
@@ -25,6 +25,7 @@
 #include "Event.h"
 #include "EventContext.h"
 #include "EventNames.h"
+#include "FullscreenManager.h"
 #include "HTMLSlotElement.h"
 #include "MouseEvent.h"
 #include "Node.h"
@@ -59,7 +60,7 @@ static inline bool shouldEventCrossShadowBoundary(Event& event, ShadowRoot& shad
     // Video-only full screen is a mode where we use the shadow DOM as an implementation
     // detail that should not be detectable by the web content.
     if (is<Node>(target)) {
-        if (auto* element = downcast<Node>(target).document().webkitCurrentFullScreenElement()) {
+        if (auto* element = downcast<Node>(target).document().fullscreenManager().currentFullscreenElement()) {
             // FIXME: We assume that if the full screen element is a media element that it's
             // the video-only full screen. Both here and elsewhere. But that is probably wrong.
             if (element->isMediaElement() && shadowRoot.host() == element)
diff --git a/Source/WebCore/dom/FullscreenManager.cpp b/Source/WebCore/dom/FullscreenManager.cpp
new file mode 100644 (file)
index 0000000..b55ed2b
--- /dev/null
@@ -0,0 +1,578 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FullscreenManager.h"
+
+#if ENABLE(FULLSCREEN_API)
+
+#include "Chrome.h"
+#include "ChromeClient.h"
+#include "Document.h"
+#include "Element.h"
+#include "EventNames.h"
+#include "Frame.h"
+#include "HTMLFrameOwnerElement.h"
+#include "HTMLMediaElement.h"
+#include "Page.h"
+#include "QualifiedName.h"
+#include "RenderFullScreen.h"
+#include "RenderTreeBuilder.h"
+#include "Settings.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+static bool isAttributeOnAllOwners(const QualifiedName& attribute, const QualifiedName& prefixedAttribute, const HTMLFrameOwnerElement* owner)
+{
+    if (!owner)
+        return true;
+    do {
+        if (!(owner->hasAttribute(attribute) || owner->hasAttribute(prefixedAttribute)))
+            return false;
+    } while ((owner = owner->document().ownerElement()));
+    return true;
+}
+
+FullscreenManager::FullscreenManager(Document& document)
+    : m_document { document }
+{
+}
+
+FullscreenManager::~FullscreenManager() = default;
+
+bool FullscreenManager::fullscreenIsAllowedForElement(Element& element) const
+{
+    return isAttributeOnAllOwners(allowfullscreenAttr, webkitallowfullscreenAttr, element.document().ownerElement());
+}
+
+void FullscreenManager::requestFullscreenForElement(Element* element, FullscreenCheckType checkType)
+{
+    if (!element)
+        element = documentElement();
+
+    auto failedPreflights = [this](auto element) mutable {
+        m_fullscreenErrorEventTargetQueue.append(WTFMove(element));
+        m_fullscreenTaskQueue.enqueueTask([this] {
+            dispatchFullscreenChangeEvents();
+        });
+    };
+
+    // 1. If any of the following conditions are true, terminate these steps and queue a task to fire
+    // an event named fullscreenerror with its bubbles attribute set to true on the context object's
+    // node document:
+
+    // This algorithm is not allowed to show a pop-up:
+    //   An algorithm is allowed to show a pop-up if, in the task in which the algorithm is running, either:
+    //   - an activation behavior is currently being processed whose click event was trusted, or
+    //   - the event listener for a trusted click event is being handled.
+    if (!UserGestureIndicator::processingUserGesture()) {
+        failedPreflights(WTFMove(element));
+        return;
+    }
+
+    // We do not allow pressing the Escape key as a user gesture to enter fullscreen since this is the key
+    // to exit fullscreen.
+    if (UserGestureIndicator::currentUserGesture()->gestureType() == UserGestureType::EscapeKey) {
+        document().addConsoleMessage(MessageSource::Security, MessageLevel::Error, "The Escape key may not be used as a user gesture to enter fullscreen"_s);
+        failedPreflights(WTFMove(element));
+        return;
+    }
+
+    // There is a previously-established user preference, security risk, or platform limitation.
+    if (!page() || !page()->settings().fullScreenEnabled()) {
+        failedPreflights(WTFMove(element));
+        return;
+    }
+
+    bool hasKeyboardAccess = true;
+    if (!page()->chrome().client().supportsFullScreenForElement(*element, hasKeyboardAccess)) {
+        // The new full screen API does not accept a "flags" parameter, so fall back to disallowing
+        // keyboard input if the chrome client refuses to allow keyboard input.
+        hasKeyboardAccess = false;
+
+        if (!page()->chrome().client().supportsFullScreenForElement(*element, hasKeyboardAccess)) {
+            failedPreflights(WTFMove(element));
+            return;
+        }
+    }
+
+    m_fullscreenTaskQueue.enqueueTask([this, element = makeRefPtr(element), checkType, hasKeyboardAccess, failedPreflights] () mutable {
+        // Don't allow fullscreen if document is hidden.
+        if (document().hidden()) {
+            failedPreflights(WTFMove(element));
+            return;
+        }
+
+        // The context object is not in a document.
+        if (!element->isConnected()) {
+            failedPreflights(WTFMove(element));
+            return;
+        }
+
+        // The context object's node document, or an ancestor browsing context's document does not have
+        // the fullscreen enabled flag set.
+        if (checkType == EnforceIFrameAllowFullscreenRequirement && !fullscreenIsAllowedForElement(*element)) {
+            failedPreflights(WTFMove(element));
+            return;
+        }
+
+        // The context object's node document fullscreen element stack is not empty and its top element
+        // is not an ancestor of the context object.
+        if (!m_fullscreenElementStack.isEmpty() && !m_fullscreenElementStack.last()->contains(element.get())) {
+            failedPreflights(WTFMove(element));
+            return;
+        }
+
+        // A descendant browsing context's document has a non-empty fullscreen element stack.
+        bool descendentHasNonEmptyStack = false;
+        for (Frame* descendant = frame() ? frame()->tree().traverseNext() : nullptr; descendant; descendant = descendant->tree().traverseNext()) {
+            if (descendant->document()->fullscreenManager().fullscreenElement()) {
+                descendentHasNonEmptyStack = true;
+                break;
+            }
+        }
+        if (descendentHasNonEmptyStack) {
+            failedPreflights(WTFMove(element));
+            return;
+        }
+
+        // 2. Let doc be element's node document. (i.e. "this")
+        Document* currentDoc = &document();
+
+        // 3. Let docs be all doc's ancestor browsing context's documents (if any) and doc.
+        Deque<Document*> docs;
+
+        do {
+            docs.prepend(currentDoc);
+            currentDoc = currentDoc->ownerElement() ? &currentDoc->ownerElement()->document() : nullptr;
+        } while (currentDoc);
+
+        // 4. For each document in docs, run these substeps:
+        Deque<Document*>::iterator current = docs.begin(), following = docs.begin();
+
+        do {
+            ++following;
+
+            // 1. Let following document be the document after document in docs, or null if there is no
+            // such document.
+            Document* currentDoc = *current;
+            Document* followingDoc = following != docs.end() ? *following : nullptr;
+
+            // 2. If following document is null, push context object on document's fullscreen element
+            // stack, and queue a task to fire an event named fullscreenchange with its bubbles attribute
+            // set to true on the document.
+            if (!followingDoc) {
+                currentDoc->fullscreenManager().pushFullscreenElementStack(*element);
+                addDocumentToFullscreenChangeEventQueue(*currentDoc);
+                continue;
+            }
+
+            // 3. Otherwise, if document's fullscreen element stack is either empty or its top element
+            // is not following document's browsing context container,
+            Element* topElement = currentDoc->fullscreenManager().fullscreenElement();
+            if (!topElement || topElement != followingDoc->ownerElement()) {
+                // ...push following document's browsing context container on document's fullscreen element
+                // stack, and queue a task to fire an event named fullscreenchange with its bubbles attribute
+                // set to true on document.
+                currentDoc->fullscreenManager().pushFullscreenElementStack(*followingDoc->ownerElement());
+                addDocumentToFullscreenChangeEventQueue(*currentDoc);
+                continue;
+            }
+
+            // 4. Otherwise, do nothing for this document. It stays the same.
+        } while (++current != docs.end());
+
+        // 5. Return, and run the remaining steps asynchronously.
+        // 6. Optionally, perform some animation.
+        m_areKeysEnabledInFullscreen = hasKeyboardAccess;
+        m_fullscreenTaskQueue.enqueueTask([this, element = WTFMove(element)] {
+            if (auto page = this->page())
+                page->chrome().client().enterFullScreenForElement(*element.get());
+        });
+
+        // 7. Optionally, display a message indicating how the user can exit displaying the context object fullscreen.
+    });
+}
+
+void FullscreenManager::cancelFullscreen()
+{
+    // The Mozilla "cancelFullscreen()" API behaves like the W3C "fully exit fullscreen" behavior, which
+    // is defined as:
+    // "To fully exit fullscreen act as if the exitFullscreen() method was invoked on the top-level browsing
+    // context's document and subsequently empty that document's fullscreen element stack."
+    Document& topDocument = document().topDocument();
+    if (!topDocument.fullscreenManager().fullscreenElement())
+        return;
+
+    // To achieve that aim, remove all the elements from the top document's stack except for the first before
+    // calling webkitExitFullscreen():
+    Vector<RefPtr<Element>> replacementFullscreenElementStack;
+    replacementFullscreenElementStack.append(topDocument.fullscreenManager().fullscreenElement());
+    topDocument.fullscreenManager().m_fullscreenElementStack.swap(replacementFullscreenElementStack);
+
+    topDocument.fullscreenManager().exitFullscreen();
+}
+
+void FullscreenManager::exitFullscreen()
+{
+    // The exitFullscreen() method must run these steps:
+
+    // 1. Let doc be the context object. (i.e. "this")
+    Document* currentDoc = &document();
+
+    // 2. If doc's fullscreen element stack is empty, terminate these steps.
+    if (m_fullscreenElementStack.isEmpty())
+        return;
+
+    // 3. Let descendants be all the doc's descendant browsing context's documents with a non-empty fullscreen
+    // element stack (if any), ordered so that the child of the doc is last and the document furthest
+    // away from the doc is first.
+    Deque<RefPtr<Document>> descendants;
+    for (Frame* descendant = frame() ? frame()->tree().traverseNext() : nullptr; descendant; descendant = descendant->tree().traverseNext()) {
+        if (descendant->document()->fullscreenManager().fullscreenElement())
+            descendants.prepend(descendant->document());
+    }
+
+    // 4. For each descendant in descendants, empty descendant's fullscreen element stack, and queue a
+    // task to fire an event named fullscreenchange with its bubbles attribute set to true on descendant.
+    for (auto& document : descendants) {
+        document->fullscreenManager().clearFullscreenElementStack();
+        addDocumentToFullscreenChangeEventQueue(*document);
+    }
+
+    // 5. While doc is not null, run these substeps:
+    Element* newTop = nullptr;
+    while (currentDoc) {
+        // 1. Pop the top element of doc's fullscreen element stack.
+        currentDoc->fullscreenManager().popFullscreenElementStack();
+
+        //    If doc's fullscreen element stack is non-empty and the element now at the top is either
+        //    not in a document or its node document is not doc, repeat this substep.
+        newTop = currentDoc->fullscreenManager().fullscreenElement();
+        if (newTop && (!newTop->isConnected() || &newTop->document() != currentDoc))
+            continue;
+
+        // 2. Queue a task to fire an event named fullscreenchange with its bubbles attribute set to true
+        // on doc.
+        addDocumentToFullscreenChangeEventQueue(*currentDoc);
+
+        // 3. If doc's fullscreen element stack is empty and doc's browsing context has a browsing context
+        // container, set doc to that browsing context container's node document.
+        if (!newTop && currentDoc->ownerElement()) {
+            currentDoc = &currentDoc->ownerElement()->document();
+            continue;
+        }
+
+        // 4. Otherwise, set doc to null.
+        currentDoc = nullptr;
+    }
+
+    // 6. Return, and run the remaining steps asynchronously.
+    // 7. Optionally, perform some animation.
+    m_fullscreenTaskQueue.enqueueTask([this, newTop = makeRefPtr(newTop), fullscreenElement = m_fullscreenElement] {
+        auto* page = this->page();
+        if (!page)
+            return;
+
+        // Only exit out of full screen window mode if there are no remaining elements in the
+        // full screen stack.
+        if (!newTop) {
+            page->chrome().client().exitFullScreenForElement(fullscreenElement.get());
+            return;
+        }
+
+        // Otherwise, notify the chrome of the new full screen element.
+        page->chrome().client().enterFullScreenForElement(*newTop);
+    });
+}
+
+bool FullscreenManager::isFullscreenEnabled() const
+{
+    // 4. The fullscreenEnabled attribute must return true if the context object and all ancestor
+    // browsing context's documents have their fullscreen enabled flag set, or false otherwise.
+
+    // Top-level browsing contexts are implied to have their allowFullscreen attribute set.
+    return isAttributeOnAllOwners(allowfullscreenAttr, webkitallowfullscreenAttr, document().ownerElement());
+}
+
+static void unwrapFullscreenRenderer(RenderFullScreen* fullscreenRenderer, Element* fullscreenElement)
+{
+    if (!fullscreenRenderer)
+        return;
+    bool requiresRenderTreeRebuild;
+    fullscreenRenderer->unwrapRenderer(requiresRenderTreeRebuild);
+
+    if (requiresRenderTreeRebuild && fullscreenElement && fullscreenElement->parentElement())
+        fullscreenElement->parentElement()->invalidateStyleAndRenderersForSubtree();
+}
+
+void FullscreenManager::willEnterFullscreen(Element& element)
+{
+    if (!document().hasLivingRenderTree() || document().pageCacheState() != Document::NotInPageCache)
+        return;
+
+    // Protect against being called after the document has been removed from the page.
+    if (!page())
+        return;
+
+    ASSERT(page()->settings().fullScreenEnabled());
+
+    unwrapFullscreenRenderer(m_fullscreenRenderer.get(), m_fullscreenElement.get());
+
+    element.willBecomeFullscreenElement();
+
+    m_fullscreenElement = &element;
+
+#if USE(NATIVE_FULLSCREEN_VIDEO)
+    if (element.isMediaElement())
+        return;
+#endif
+
+    // Create a placeholder block for a the full-screen element, to keep the page from reflowing
+    // when the element is removed from the normal flow. Only do this for a RenderBox, as only
+    // a box will have a frameRect. The placeholder will be created in setFullscreenRenderer()
+    // during layout.
+    auto renderer = m_fullscreenElement->renderer();
+    bool shouldCreatePlaceholder = is<RenderBox>(renderer);
+    if (shouldCreatePlaceholder) {
+        m_savedPlaceholderFrameRect = downcast<RenderBox>(*renderer).frameRect();
+        m_savedPlaceholderRenderStyle = RenderStyle::clonePtr(renderer->style());
+    }
+
+    if (m_fullscreenElement != documentElement() && renderer)
+        RenderFullScreen::wrapExistingRenderer(*renderer, document());
+
+    m_fullscreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(true);
+
+    document().resolveStyle(Document::ResolveStyleType::Rebuild);
+    dispatchFullscreenChangeEvents();
+}
+
+void FullscreenManager::didEnterFullscreen()
+{
+    if (!m_fullscreenElement)
+        return;
+
+    if (!hasLivingRenderTree() || pageCacheState() != Document::NotInPageCache)
+        return;
+
+    m_fullscreenElement->didBecomeFullscreenElement();
+}
+
+void FullscreenManager::willExitFullscreen()
+{
+    if (!m_fullscreenElement)
+        return;
+
+    if (!hasLivingRenderTree() || pageCacheState() != Document::NotInPageCache)
+        return;
+
+    m_fullscreenElement->willStopBeingFullscreenElement();
+}
+
+void FullscreenManager::didExitFullscreen()
+{
+    if (!m_fullscreenElement)
+        return;
+
+    if (!hasLivingRenderTree() || pageCacheState() != Document::NotInPageCache)
+        return;
+
+    m_fullscreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false);
+
+    m_areKeysEnabledInFullscreen = false;
+
+    unwrapFullscreenRenderer(m_fullscreenRenderer.get(), m_fullscreenElement.get());
+
+    m_fullscreenElement = nullptr;
+    scheduleFullStyleRebuild();
+
+    // When webkitCancelFullscreen is called, we call webkitExitFullscreen on the topDocument(). That
+    // means that the events will be queued there. So if we have no events here, start the timer on
+    // the exiting document.
+    bool eventTargetQueuesEmpty = m_fullscreenChangeEventTargetQueue.isEmpty() && m_fullscreenErrorEventTargetQueue.isEmpty();
+    Document& exitingDocument = eventTargetQueuesEmpty ? topDocument() : document();
+
+    exitingDocument.fullscreenManager().dispatchFullscreenChangeEvents();
+}
+
+void FullscreenManager::setFullscreenRenderer(RenderTreeBuilder& builder, RenderFullScreen& renderer)
+{
+    if (&renderer == m_fullscreenRenderer)
+        return;
+
+    if (m_savedPlaceholderRenderStyle)
+        builder.createPlaceholderForFullScreen(renderer, WTFMove(m_savedPlaceholderRenderStyle), m_savedPlaceholderFrameRect);
+    else if (m_fullscreenRenderer && m_fullscreenRenderer->placeholder()) {
+        auto* placeholder = m_fullscreenRenderer->placeholder();
+        builder.createPlaceholderForFullScreen(renderer, RenderStyle::clonePtr(placeholder->style()), placeholder->frameRect());
+    }
+
+    if (m_fullscreenRenderer)
+        builder.destroy(*m_fullscreenRenderer);
+    ASSERT(!m_fullscreenRenderer);
+
+    m_fullscreenRenderer = makeWeakPtr(renderer);
+}
+
+void FullscreenManager::dispatchFullscreenChangeEvents()
+{
+    // Since we dispatch events in this function, it's possible that the
+    // document will be detached and GC'd. We protect it here to make sure we
+    // can finish the function successfully.
+    Ref<Document> protectedDocument(document());
+    Deque<RefPtr<Node>> changeQueue;
+    m_fullscreenChangeEventTargetQueue.swap(changeQueue);
+    Deque<RefPtr<Node>> errorQueue;
+    m_fullscreenErrorEventTargetQueue.swap(errorQueue);
+    dispatchFullscreenChangeOrErrorEvent(changeQueue, eventNames().webkitfullscreenchangeEvent, /* shouldNotifyMediaElement */ true);
+    dispatchFullscreenChangeOrErrorEvent(errorQueue, eventNames().webkitfullscreenerrorEvent, /* shouldNotifyMediaElement */ false);
+}
+
+void FullscreenManager::dispatchFullscreenChangeOrErrorEvent(Deque<RefPtr<Node>>& queue, const AtomicString& eventName, bool shouldNotifyMediaElement)
+{
+    while (!queue.isEmpty()) {
+        RefPtr<Node> node = queue.takeFirst();
+        if (!node)
+            node = documentElement();
+        // The dispatchEvent below may have blown away our documentElement.
+        if (!node)
+            continue;
+
+        // If the element was removed from our tree, also message the documentElement. Since we may
+        // have a document hierarchy, check that node isn't in another document.
+        if (!node->isConnected())
+            queue.append(documentElement());
+
+#if ENABLE(VIDEO)
+        if (shouldNotifyMediaElement && is<HTMLMediaElement>(*node))
+            downcast<HTMLMediaElement>(*node).enteredOrExitedFullscreen();
+#else
+        UNUSED_PARAM(shouldNotifyMediaElement);
+#endif
+        node->dispatchEvent(Event::create(eventName, Event::CanBubble::Yes, Event::IsCancelable::No));
+    }
+}
+
+void FullscreenManager::fullscreenElementRemoved()
+{
+    m_fullscreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false);
+    cancelFullscreen();
+}
+
+void FullscreenManager::adjustFullscreenElementOnNodeRemoval(Node& node, Document::NodeRemoval nodeRemoval)
+{
+    if (!m_fullscreenElement)
+        return;
+
+    bool elementInSubtree = false;
+    if (nodeRemoval == Document::NodeRemoval::ChildrenOfNode)
+        elementInSubtree = m_fullscreenElement->isDescendantOf(node);
+    else
+        elementInSubtree = (m_fullscreenElement == &node) || m_fullscreenElement->isDescendantOf(node);
+
+    if (elementInSubtree)
+        fullscreenElementRemoved();
+}
+
+bool FullscreenManager::isAnimatingFullscreen() const
+{
+    return m_isAnimatingFullscreen;
+}
+
+void FullscreenManager::setAnimatingFullscreen(bool flag)
+{
+    if (m_isAnimatingFullscreen == flag)
+        return;
+    m_isAnimatingFullscreen = flag;
+
+    if (m_fullscreenElement && m_fullscreenElement->isDescendantOf(document())) {
+        m_fullscreenElement->invalidateStyleForSubtree();
+        scheduleFullStyleRebuild();
+    }
+}
+
+bool FullscreenManager::areFullscreenControlsHidden() const
+{
+    return m_areFullscreenControlsHidden;
+}
+
+void FullscreenManager::setFullscreenControlsHidden(bool flag)
+{
+    if (m_areFullscreenControlsHidden == flag)
+        return;
+    m_areFullscreenControlsHidden = flag;
+
+    if (m_fullscreenElement && m_fullscreenElement->isDescendantOf(document())) {
+        m_fullscreenElement->invalidateStyleForSubtree();
+        scheduleFullStyleRebuild();
+    }
+}
+
+void FullscreenManager::clear()
+{
+    m_fullscreenElement = nullptr;
+    m_fullscreenElementStack.clear();
+}
+
+void FullscreenManager::emptyEventQueue()
+{
+    m_fullscreenChangeEventTargetQueue.clear();
+    m_fullscreenErrorEventTargetQueue.clear();
+}
+
+void FullscreenManager::clearFullscreenElementStack()
+{
+    m_fullscreenElementStack.clear();
+}
+
+void FullscreenManager::popFullscreenElementStack()
+{
+    if (m_fullscreenElementStack.isEmpty())
+        return;
+
+    m_fullscreenElementStack.removeLast();
+}
+
+void FullscreenManager::pushFullscreenElementStack(Element& element)
+{
+    m_fullscreenElementStack.append(&element);
+}
+
+void FullscreenManager::addDocumentToFullscreenChangeEventQueue(Document& document)
+{
+    Node* target = document.fullscreenManager().fullscreenElement();
+    if (!target)
+        target = document.fullscreenManager().currentFullscreenElement();
+    if (!target)
+        target = &document;
+    m_fullscreenChangeEventTargetQueue.append(target);
+}
+
+}
+
+#endif
diff --git a/Source/WebCore/dom/FullscreenManager.h b/Source/WebCore/dom/FullscreenManager.h
new file mode 100644 (file)
index 0000000..7ab5a7b
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(FULLSCREEN_API)
+
+#include "Document.h"
+#include "GenericTaskQueue.h"
+#include "LayoutRect.h"
+#include <wtf/Deque.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/WeakHashSet.h>
+
+namespace WebCore {
+
+class RenderFullScreen;
+class RenderTreeBuilder;
+class RenderStyle;
+
+class FullscreenManager {
+public:
+    FullscreenManager(Document&);
+    ~FullscreenManager();
+
+    Document& document() { return m_document; }
+    const Document& document() const { return m_document; }
+    Document& topDocument() const { return m_document.topDocument(); }
+    Page* page() const { return m_document.page(); }
+    Frame* frame() const { return m_document.frame(); }
+    Element* documentElement() const { return m_document.documentElement(); }
+    bool hasLivingRenderTree() const { return m_document.hasLivingRenderTree(); }
+    Document::PageCacheState pageCacheState() const { return m_document.pageCacheState(); }
+    void scheduleFullStyleRebuild() { m_document.scheduleFullStyleRebuild(); }
+
+    // W3C Fullscreen API
+    Element* fullscreenElement() const { return !m_fullscreenElementStack.isEmpty() ? m_fullscreenElementStack.last().get() : nullptr; }
+    WEBCORE_EXPORT bool isFullscreenEnabled() const;
+    WEBCORE_EXPORT void exitFullscreen();
+
+    // Mozilla versions.
+    bool isFullscreen() const { return m_fullscreenElement.get(); }
+    bool isFullscreenKeyboardInputAllowed() const { return m_fullscreenElement.get() && m_areKeysEnabledInFullscreen; }
+    Element* currentFullscreenElement() const { return m_fullscreenElement.get(); }
+    WEBCORE_EXPORT void cancelFullscreen();
+
+    enum FullscreenCheckType {
+        EnforceIFrameAllowFullscreenRequirement,
+        ExemptIFrameAllowFullscreenRequirement,
+    };
+    void requestFullscreenForElement(Element*, FullscreenCheckType);
+
+    WEBCORE_EXPORT void willEnterFullscreen(Element&);
+    WEBCORE_EXPORT void didEnterFullscreen();
+    WEBCORE_EXPORT void willExitFullscreen();
+    WEBCORE_EXPORT void didExitFullscreen();
+
+    void setFullscreenRenderer(RenderTreeBuilder&, RenderFullScreen&);
+    RenderFullScreen* fullscreenRenderer() const { return m_fullscreenRenderer.get(); }
+
+    void dispatchFullscreenChangeEvents();
+    bool fullscreenIsAllowedForElement(Element&) const;
+    void fullscreenElementRemoved();
+
+    void adjustFullscreenElementOnNodeRemoval(Node&, Document::NodeRemoval = Document::NodeRemoval::Node);
+
+    WEBCORE_EXPORT bool isAnimatingFullscreen() const;
+    WEBCORE_EXPORT void setAnimatingFullscreen(bool);
+
+    WEBCORE_EXPORT bool areFullscreenControlsHidden() const;
+    WEBCORE_EXPORT void setFullscreenControlsHidden(bool);
+
+    void clear();
+    void emptyEventQueue();
+
+protected:
+    friend class Document;
+
+    void dispatchFullscreenChangeOrErrorEvent(Deque<RefPtr<Node>>&, const AtomicString& eventName, bool shouldNotifyMediaElement);
+    void clearFullscreenElementStack();
+    void popFullscreenElementStack();
+    void pushFullscreenElementStack(Element&);
+    void addDocumentToFullscreenChangeEventQueue(Document&);
+
+private:
+    Document& m_document;
+
+    RefPtr<Element> m_fullscreenElement;
+    Vector<RefPtr<Element>> m_fullscreenElementStack;
+    WeakPtr<RenderFullScreen> m_fullscreenRenderer { nullptr };
+    GenericTaskQueue<Timer> m_fullscreenTaskQueue;
+    Deque<RefPtr<Node>> m_fullscreenChangeEventTargetQueue;
+    Deque<RefPtr<Node>> m_fullscreenErrorEventTargetQueue;
+    LayoutRect m_savedPlaceholderFrameRect;
+    std::unique_ptr<RenderStyle> m_savedPlaceholderRenderStyle;
+
+    bool m_areKeysEnabledInFullscreen { false };
+    bool m_isAnimatingFullscreen { false };
+    bool m_areFullscreenControlsHidden { false };
+};
+
+}
+
+#endif
index 8f141c1..f223ebb 100644 (file)
@@ -51,6 +51,7 @@
 #include "FrameLoader.h"
 #include "FrameLoaderClient.h"
 #include "FrameView.h"
+#include "FullscreenManager.h"
 #include "HTMLParserIdioms.h"
 #include "HTMLSourceElement.h"
 #include "HTMLVideoElement.h"
@@ -6021,7 +6022,7 @@ bool HTMLMediaElement::isFullscreen() const
         return true;
 
 #if ENABLE(FULLSCREEN_API)
-    if (document().webkitIsFullScreen() && document().webkitCurrentFullScreenElement() == this)
+    if (document().fullscreenManager().isFullscreen() && document().fullscreenManager().currentFullscreenElement() == this)
         return true;
 #endif
 
@@ -6031,7 +6032,7 @@ bool HTMLMediaElement::isFullscreen() const
 bool HTMLMediaElement::isStandardFullscreen() const
 {
 #if ENABLE(FULLSCREEN_API)
-    if (document().webkitIsFullScreen() && document().webkitCurrentFullScreenElement() == this)
+    if (document().fullscreenManager().isFullscreen() && document().fullscreenManager().currentFullscreenElement() == this)
         return true;
 #endif
 
@@ -6059,7 +6060,7 @@ void HTMLMediaElement::enterFullscreen(VideoFullscreenMode mode)
 
 #if ENABLE(FULLSCREEN_API) && ENABLE(VIDEO_USES_ELEMENT_FULLSCREEN)
     if (document().settings().fullScreenEnabled() && mode == VideoFullscreenModeStandard) {
-        document().requestFullScreenForElement(this, Document::ExemptIFrameAllowFullScreenRequirement);
+        document().fullscreenManager().requestFullscreenForElement(this, FullscreenManager::ExemptIFrameAllowFullscreenRequirement);
         return;
     }
 #endif
@@ -6096,9 +6097,9 @@ void HTMLMediaElement::exitFullscreen()
     m_waitingToEnterFullscreen = false;
 
 #if ENABLE(FULLSCREEN_API)
-    if (document().settings().fullScreenEnabled() && document().webkitCurrentFullScreenElement() == this) {
-        if (document().webkitIsFullScreen())
-            document().webkitCancelFullScreen();
+    if (document().settings().fullScreenEnabled() && document().fullscreenManager().currentFullscreenElement() == this) {
+        if (document().fullscreenManager().isFullscreen())
+            document().fullscreenManager().cancelFullscreen();
 
         if (m_videoFullscreenMode == VideoFullscreenModeStandard)
             return;
index 24cab0e..7c3d009 100644 (file)
@@ -33,6 +33,7 @@
 #include "DocumentLoader.h"
 #include "Frame.h"
 #include "FrameView.h"
+#include "FullscreenManager.h"
 #include "HTMLAudioElement.h"
 #include "HTMLMediaElement.h"
 #include "HTMLNames.h"
@@ -481,7 +482,7 @@ bool MediaElementSession::canShowControlsManager(PlaybackControlsPurpose purpose
 
 #if ENABLE(FULLSCREEN_API)
     // Elements which are not descendents of the current fullscreen element cannot be main content.
-    auto* fullscreenElement = m_element.document().webkitCurrentFullScreenElement();
+    auto* fullscreenElement = m_element.document().fullscreenManager().currentFullscreenElement();
     if (fullscreenElement && !m_element.isDescendantOf(*fullscreenElement)) {
         INFO_LOG(LOGIDENTIFIER, "returning FALSE: outside of full screen");
         return false;
index 7c08c43..7fa4ab6 100644 (file)
@@ -37,6 +37,7 @@
 #include "EventHandler.h"
 #include "EventNames.h"
 #include "Frame.h"
+#include "FullscreenManager.h"
 #include "GraphicsContext.h"
 #include "HTMLHeadingElement.h"
 #include "HTMLLIElement.h"
@@ -979,10 +980,10 @@ void MediaControlFullscreenButtonElement::defaultEventHandler(Event& event)
         // video implementation without requiring them to implement their own full
         // screen behavior.
         if (document().settings().fullScreenEnabled()) {
-            if (document().webkitIsFullScreen() && document().webkitCurrentFullScreenElement() == parentMediaElement(this))
-                document().webkitCancelFullScreen();
+            if (document().fullscreenManager().isFullscreen() && document().fullscreenManager().currentFullscreenElement() == parentMediaElement(this))
+                document().fullscreenManager().cancelFullscreen();
             else
-                document().requestFullScreenForElement(parentMediaElement(this).get(), Document::ExemptIFrameAllowFullScreenRequirement);
+                document().fullscreenManager().requestFullscreenForElement(parentMediaElement(this).get(), FullscreenManager::ExemptIFrameAllowFullscreenRequirement);
         } else
 #endif
             mediaController()->enterFullscreen();
index 0121a7a..33955ac 100644 (file)
@@ -59,6 +59,7 @@
 #include "EventNames.h"
 #include "Frame.h"
 #include "FrameTree.h"
+#include "FullscreenManager.h"
 #include "HTMLElement.h"
 #include "HTMLFrameOwnerElement.h"
 #include "HTMLMediaElement.h"
@@ -251,7 +252,7 @@ public:
 
 #if ENABLE(FULLSCREEN_API)
         if (event.type() == eventNames().webkitfullscreenchangeEvent)
-            data->setBoolean("enabled"_s, !!node->document().webkitFullscreenElement());
+            data->setBoolean("enabled"_s, !!node->document().fullscreenManager().fullscreenElement());
 #endif // ENABLE(FULLSCREEN_API)
 
         auto timestamp = m_domAgent.m_environment.executionStopwatch()->elapsedTime().seconds();
index 369e381..22f099c 100644 (file)
@@ -51,6 +51,7 @@
 #include "FrameSelection.h"
 #include "FrameTree.h"
 #include "FrameView.h"
+#include "FullscreenManager.h"
 #include "HTMLDocument.h"
 #include "HTMLFrameElement.h"
 #include "HTMLFrameSetElement.h"
@@ -3134,7 +3135,7 @@ bool EventHandler::needsKeyboardEventDisambiguationQuirks() const
 bool EventHandler::isKeyEventAllowedInFullScreen(const PlatformKeyboardEvent& keyEvent) const
 {
     Document* document = m_frame.document();
-    if (document->webkitFullScreenKeyboardInputAllowed())
+    if (document->fullscreenManager().isFullscreenKeyboardInputAllowed())
         return true;
 
     if (keyEvent.type() == PlatformKeyboardEvent::Char) {
@@ -3206,9 +3207,9 @@ bool EventHandler::internalKeyEvent(const PlatformKeyboardEvent& initialKeyEvent
     }
 
 #if ENABLE(FULLSCREEN_API)
-    if (m_frame.document()->webkitIsFullScreen()) {
+    if (m_frame.document()->fullscreenManager().isFullscreen()) {
         if (initialKeyEvent.type() == PlatformEvent::KeyDown && initialKeyEvent.windowsVirtualKeyCode() == VK_ESCAPE) {
-            m_frame.document()->webkitCancelFullScreen();
+            m_frame.document()->fullscreenManager().cancelFullscreen();
             return true;
         }
 
index 30fe9e3..51d167e 100644 (file)
@@ -57,6 +57,7 @@
 #include "FrameSelection.h"
 #include "FrameTree.h"
 #include "FrameView.h"
+#include "FullscreenManager.h"
 #include "HTMLElement.h"
 #include "HTMLMediaElement.h"
 #include "HistoryController.h"
@@ -2785,7 +2786,7 @@ void Page::setFullscreenControlsHidden(bool hidden)
     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
         if (!frame->document())
             continue;
-        frame->document()->setFullscreenControlsHidden(hidden);
+        frame->document()->fullscreenManager().setFullscreenControlsHidden(hidden);
     }
 #else
     UNUSED_PARAM(hidden);
index cf4164e..d3f4f64 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "RenderFullScreen.h"
 
+#include "FullscreenManager.h"
 #include "RenderBlockFlow.h"
 #include "RenderLayer.h"
 #include "RenderLayerCompositor.h"
@@ -99,7 +100,7 @@ RenderPtr<RenderFullScreen> RenderFullScreen::wrapNewRenderer(RenderTreeBuilder&
     builder.attach(fullscreenRenderer, WTFMove(renderer));
     fullscreenRenderer.setNeedsLayoutAndPrefWidthsRecalc();
 
-    document.setFullScreenRenderer(builder, fullscreenRenderer);
+    document.fullscreenManager().setFullscreenRenderer(builder, fullscreenRenderer);
 
     return newFullscreenRenderer;
 }
@@ -136,7 +137,7 @@ void RenderFullScreen::wrapExistingRenderer(RenderElement& renderer, Document& d
     builder.attach(fullscreenRenderer, WTFMove(toMove));
     fullscreenRenderer.setNeedsLayoutAndPrefWidthsRecalc();
 
-    document.setFullScreenRenderer(builder, fullscreenRenderer);
+    document.fullscreenManager().setFullscreenRenderer(builder, fullscreenRenderer);
 }
 
 void RenderFullScreen::unwrapRenderer(bool& requiresRenderTreeRebuild)
index 3f2f2e5..1a1b2aa 100644 (file)
@@ -35,6 +35,7 @@
 #include "DocumentTimeline.h"
 #include "Frame.h"
 #include "FrameView.h"
+#include "FullscreenManager.h"
 #include "GraphicsLayer.h"
 #include "HTMLCanvasElement.h"
 #include "HTMLIFrameElement.h"
@@ -2185,10 +2186,10 @@ static FullScreenDescendant isDescendantOfFullScreenLayer(const RenderLayer& lay
 {
     auto& document = layer.renderer().document();
 
-    if (!document.webkitIsFullScreen() || !document.fullScreenRenderer())
+    if (!document.fullscreenManager().isFullscreen() || !document.fullscreenManager().fullscreenRenderer())
         return FullScreenDescendant::NotApplicable;
 
-    auto* fullScreenLayer = document.fullScreenRenderer()->layer();
+    auto* fullScreenLayer = document.fullscreenManager().fullscreenRenderer()->layer();
     if (!fullScreenLayer) {
         ASSERT_NOT_REACHED();
         return FullScreenDescendant::NotApplicable;
index 5a7b56d..ad8007d 100644 (file)
@@ -29,6 +29,7 @@
 
 namespace WebCore {
 
+class RenderFullScreen;
 class RenderGrid;
 class RenderTreeUpdater;
 
index ee639d9..f89b751 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "RenderTreeBuilderInline.h"
 
+#include "FullscreenManager.h"
 #include "RenderChildIterator.h"
 #include "RenderFullScreen.h"
 #include "RenderInline.h"
@@ -272,9 +273,9 @@ void RenderTreeBuilder::Inline::splitInlines(RenderInline& parent, RenderBlock*
     // that renderer is wrapped in a RenderFullScreen, so |this| is not its
     // parent. Since the splitting logic expects |this| to be the parent, set
     // |beforeChild| to be the RenderFullScreen.
-    const Element* fullScreenElement = parent.document().webkitCurrentFullScreenElement();
+    const Element* fullScreenElement = parent.document().fullscreenManager().currentFullscreenElement();
     if (fullScreenElement && beforeChild && beforeChild->node() == fullScreenElement)
-        beforeChild = parent.document().fullScreenRenderer();
+        beforeChild = parent.document().fullscreenManager().fullscreenRenderer();
 #endif
     // Now take all of the children from beforeChild to the end and remove
     // them from |this| and place them in the clone.
index f7545a5..f42bca3 100644 (file)
@@ -33,6 +33,7 @@
 #include "Document.h"
 #include "DocumentTimeline.h"
 #include "Element.h"
+#include "FullscreenManager.h"
 #include "HTMLParserIdioms.h"
 #include "HTMLSlotElement.h"
 #include "InspectorInstrumentation.h"
@@ -376,7 +377,7 @@ void RenderTreeUpdater::createRenderer(Element& element, RenderStyle&& style)
     newRenderer->initializeStyle();
 
 #if ENABLE(FULLSCREEN_API)
-    if (m_document.webkitIsFullScreen() && m_document.webkitCurrentFullScreenElement() == &element) {
+    if (m_document.fullscreenManager().isFullscreen() && m_document.fullscreenManager().currentFullscreenElement() == &element) {
         newRenderer = RenderFullScreen::wrapNewRenderer(m_builder, WTFMove(newRenderer), insertionPosition.parent(), m_document);
         if (!newRenderer)
             return;
index 5ae54d7..1052aa6 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "DocumentRuleSets.h"
 #include "ElementRuleCollector.h"
+#include "FullscreenManager.h"
 #include "HTMLInputElement.h"
 #include "HTMLNames.h"
 #include "NodeRenderStyle.h"
@@ -292,7 +293,7 @@ bool SharingResolver::canShareStyleWithElement(const Context& context, const Sty
         return false;
 
 #if ENABLE(FULLSCREEN_API)
-    if (&candidateElement == m_document.webkitCurrentFullScreenElement() || &element == m_document.webkitCurrentFullScreenElement())
+    if (&candidateElement == m_document.fullscreenManager().currentFullscreenElement() || &element == m_document.fullscreenManager().currentFullscreenElement())
         return false;
 #endif
     return true;
index 603ce7c..78d0598 100644 (file)
@@ -75,6 +75,7 @@
 #include "Frame.h"
 #include "FrameLoader.h"
 #include "FrameView.h"
+#include "FullscreenManager.h"
 #include "GCObservation.h"
 #include "GridPosition.h"
 #include "HEVCUtilities.h"
@@ -3003,7 +3004,7 @@ void Internals::webkitWillEnterFullScreenForElement(Element& element)
     Document* document = contextDocument();
     if (!document)
         return;
-    document->webkitWillEnterFullScreen(element);
+    document->fullscreenManager().willEnterFullscreen(element);
 }
 
 void Internals::webkitDidEnterFullScreenForElement(Element&)
@@ -3011,7 +3012,7 @@ void Internals::webkitDidEnterFullScreenForElement(Element&)
     Document* document = contextDocument();
     if (!document)
         return;
-    document->webkitDidEnterFullScreen();
+    document->fullscreenManager().didEnterFullscreen();
 }
 
 void Internals::webkitWillExitFullScreenForElement(Element&)
@@ -3019,7 +3020,7 @@ void Internals::webkitWillExitFullScreenForElement(Element&)
     Document* document = contextDocument();
     if (!document)
         return;
-    document->webkitWillExitFullScreen();
+    document->fullscreenManager().willExitFullscreen();
 }
 
 void Internals::webkitDidExitFullScreenForElement(Element&)
@@ -3027,7 +3028,7 @@ void Internals::webkitDidExitFullScreenForElement(Element&)
     Document* document = contextDocument();
     if (!document)
         return;
-    document->webkitDidExitFullScreen();
+    document->fullscreenManager().didExitFullscreen();
 }
 
 bool Internals::isAnimatingFullScreen() const
@@ -3035,7 +3036,7 @@ bool Internals::isAnimatingFullScreen() const
     Document* document = contextDocument();
     if (!document)
         return false;
-    return document->isAnimatingFullScreen();
+    return document->fullscreenManager().isAnimatingFullscreen();
 }
 
 #endif
index 6e39343..d91083c 100644 (file)
@@ -1,3 +1,27 @@
+2019-04-18  Jer Noble  <jer.noble@apple.com>
+
+        Refactoring: Pull all fullscreen code out of Document and into its own helper class
+        https://bugs.webkit.org/show_bug.cgi?id=197017
+
+        Reviewed by Eric Carlson.
+
+        * WebProcess/FullScreen/WebFullScreenManager.cpp:
+        (WebKit::WebFullScreenManager::willEnterFullScreen):
+        (WebKit::WebFullScreenManager::didEnterFullScreen):
+        (WebKit::WebFullScreenManager::willExitFullScreen):
+        (WebKit::WebFullScreenManager::didExitFullScreen):
+        (WebKit::WebFullScreenManager::setAnimatingFullScreen):
+        (WebKit::WebFullScreenManager::requestExitFullScreen):
+        * WebProcess/InjectedBundle/API/gtk/DOM/WebKitDOMDocumentGtk.cpp:
+        (webkit_dom_document_webkit_cancel_fullscreen):
+        (webkit_dom_document_webkit_exit_fullscreen):
+        (webkit_dom_document_get_webkit_is_fullscreen):
+        (webkit_dom_document_get_webkit_fullscreen_keyboard_input_allowed):
+        (webkit_dom_document_get_webkit_current_fullscreen_element):
+        (webkit_dom_document_get_webkit_fullscreen_element):
+        * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+        (WebKit::WebChromeClient::createWindow):
+
 2019-04-18  Megan Gardner  <megan_gardner@apple.com>
 
         Update UIKit when a cut causes a selection change
index 290a195..f51941e 100644 (file)
@@ -37,6 +37,7 @@
 #include <WebCore/Element.h>
 #include <WebCore/Frame.h>
 #include <WebCore/FrameView.h>
+#include <WebCore/FullscreenManager.h>
 #include <WebCore/HTMLVideoElement.h>
 #include <WebCore/Page.h>
 #include <WebCore/RenderLayer.h>
@@ -150,7 +151,7 @@ void WebFullScreenManager::willEnterFullScreen()
 {
     LOG(Fullscreen, "WebFullScreenManager %p willEnterFullScreen() - element %p", this, m_element.get());
 
-    m_element->document().webkitWillEnterFullScreen(*m_element);
+    m_element->document().fullscreenManager().willEnterFullscreen(*m_element);
 #if !PLATFORM(IOS_FAMILY)
     m_page->hidePageBanners();
 #endif
@@ -164,7 +165,7 @@ void WebFullScreenManager::didEnterFullScreen()
 {
     LOG(Fullscreen, "WebFullScreenManager %p didEnterFullScreen() - element %p", this, m_element.get());
 
-    m_element->document().webkitDidEnterFullScreen();
+    m_element->document().fullscreenManager().didEnterFullscreen();
 
 #if PLATFORM(IOS_FAMILY) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
     auto* currentPlaybackControlsElement = m_page->playbackSessionManager().currentPlaybackControlsElement();
@@ -182,7 +183,7 @@ void WebFullScreenManager::willExitFullScreen()
 #endif
 
     m_finalFrame = screenRectOfContents(m_element.get());
-    m_element->document().webkitWillExitFullScreen();
+    m_element->document().fullscreenManager().willExitFullscreen();
 #if !PLATFORM(IOS_FAMILY)
     m_page->showPageBanners();
 #endif
@@ -196,19 +197,19 @@ void WebFullScreenManager::didExitFullScreen()
     ASSERT(m_element);
     setFullscreenInsets(FloatBoxExtent());
     setFullscreenAutoHideDuration(0_s);
-    m_element->document().webkitDidExitFullScreen();
+    m_element->document().fullscreenManager().didExitFullscreen();
 }
 
 void WebFullScreenManager::setAnimatingFullScreen(bool animating)
 {
     ASSERT(m_element);
-    m_element->document().setAnimatingFullScreen(animating);
+    m_element->document().fullscreenManager().setAnimatingFullscreen(animating);
 }
 
 void WebFullScreenManager::requestExitFullScreen()
 {
     ASSERT(m_element);
-    m_element->document().webkitCancelFullScreen();
+    m_element->document().fullscreenManager().cancelFullscreen();
 }
 
 void WebFullScreenManager::close()
index 533bee9..3849f06 100644 (file)
@@ -55,6 +55,7 @@
 #include <WebCore/CSSImportRule.h>
 #include <WebCore/DOMException.h>
 #include <WebCore/Document.h>
+#include <WebCore/FullscreenManager.h>
 #include <WebCore/JSExecState.h>
 #include <wtf/GetPtr.h>
 #include <wtf/RefPtr.h>
@@ -1308,7 +1309,7 @@ void webkit_dom_document_webkit_cancel_fullscreen(WebKitDOMDocument* self)
     WebCore::JSMainThreadNullState state;
     g_return_if_fail(WEBKIT_DOM_IS_DOCUMENT(self));
     WebCore::Document* item = WebKit::core(self);
-    item->webkitCancelFullScreen();
+    item->fullscreenManager().cancelFullscreen();
 }
 
 void webkit_dom_document_webkit_exit_fullscreen(WebKitDOMDocument* self)
@@ -1316,7 +1317,7 @@ void webkit_dom_document_webkit_exit_fullscreen(WebKitDOMDocument* self)
     WebCore::JSMainThreadNullState state;
     g_return_if_fail(WEBKIT_DOM_IS_DOCUMENT(self));
     WebCore::Document* item = WebKit::core(self);
-    item->webkitExitFullscreen();
+    item->fullscreenManager().exitFullscreen();
 }
 
 void webkit_dom_document_exit_pointer_lock(WebKitDOMDocument* self)
@@ -1818,7 +1819,7 @@ gboolean webkit_dom_document_get_webkit_is_fullscreen(WebKitDOMDocument* self)
     WebCore::JSMainThreadNullState state;
     g_return_val_if_fail(WEBKIT_DOM_IS_DOCUMENT(self), FALSE);
     WebCore::Document* item = WebKit::core(self);
-    gboolean result = item->webkitIsFullScreen();
+    gboolean result = item->fullscreenManager().isFullscreen();
     return result;
 }
 
@@ -1827,7 +1828,7 @@ gboolean webkit_dom_document_get_webkit_fullscreen_keyboard_input_allowed(WebKit
     WebCore::JSMainThreadNullState state;
     g_return_val_if_fail(WEBKIT_DOM_IS_DOCUMENT(self), FALSE);
     WebCore::Document* item = WebKit::core(self);
-    gboolean result = item->webkitFullScreenKeyboardInputAllowed();
+    gboolean result = item->fullscreenManager().isFullscreenKeyboardInputAllowed();
     return result;
 }
 
@@ -1836,7 +1837,7 @@ WebKitDOMElement* webkit_dom_document_get_webkit_current_fullscreen_element(WebK
     WebCore::JSMainThreadNullState state;
     g_return_val_if_fail(WEBKIT_DOM_IS_DOCUMENT(self), 0);
     WebCore::Document* item = WebKit::core(self);
-    RefPtr<WebCore::Element> gobjectResult = WTF::getPtr(item->webkitCurrentFullScreenElement());
+    RefPtr<WebCore::Element> gobjectResult = WTF::getPtr(item->fullscreenManager().currentFullscreenElement());
     return WebKit::kit(gobjectResult.get());
 }
 
@@ -1845,7 +1846,7 @@ gboolean webkit_dom_document_get_webkit_fullscreen_enabled(WebKitDOMDocument* se
     WebCore::JSMainThreadNullState state;
     g_return_val_if_fail(WEBKIT_DOM_IS_DOCUMENT(self), FALSE);
     WebCore::Document* item = WebKit::core(self);
-    gboolean result = item->webkitFullscreenEnabled();
+    gboolean result = item->fullscreenManager().isFullscreenEnabled();
     return result;
 }
 
@@ -1854,7 +1855,7 @@ WebKitDOMElement* webkit_dom_document_get_webkit_fullscreen_element(WebKitDOMDoc
     WebCore::JSMainThreadNullState state;
     g_return_val_if_fail(WEBKIT_DOM_IS_DOCUMENT(self), 0);
     WebCore::Document* item = WebKit::core(self);
-    RefPtr<WebCore::Element> gobjectResult = WTF::getPtr(item->webkitFullscreenElement());
+    RefPtr<WebCore::Element> gobjectResult = WTF::getPtr(item->fullscreenManager().fullscreenElement());
     return WebKit::kit(gobjectResult.get());
 }
 
index 0766cd6..2b6bd73 100644 (file)
@@ -68,6 +68,7 @@
 #include <WebCore/FrameLoadRequest.h>
 #include <WebCore/FrameLoader.h>
 #include <WebCore/FrameView.h>
+#include <WebCore/FullscreenManager.h>
 #include <WebCore/HTMLInputElement.h>
 #include <WebCore/HTMLNames.h>
 #include <WebCore/HTMLParserIdioms.h>
@@ -266,8 +267,8 @@ void WebChromeClient::focusedFrameChanged(Frame* frame)
 Page* WebChromeClient::createWindow(Frame& frame, const FrameLoadRequest& request, const WindowFeatures& windowFeatures, const NavigationAction& navigationAction)
 {
 #if ENABLE(FULLSCREEN_API)
-    if (frame.document() && frame.document()->webkitCurrentFullScreenElement())
-        frame.document()->webkitCancelFullScreen();
+    if (frame.document() && frame.document()->fullscreenManager().currentFullscreenElement())
+        frame.document()->fullscreenManager().cancelFullscreen();
 #endif
 
     auto& webProcess = WebProcess::singleton();
index fbd1553..0393342 100644 (file)
 #include <WebCore/FrameLoadRequest.h>
 #include <WebCore/FrameLoaderTypes.h>
 #include <WebCore/FrameView.h>
+#include <WebCore/FullscreenManager.h>
 #include <WebCore/GraphicsContext3D.h>
 #include <WebCore/HTMLAttachmentElement.h>
 #include <WebCore/HTMLFormElement.h>
@@ -5397,8 +5398,8 @@ void WebPage::elementDidFocus(WebCore::Element& element)
 #if PLATFORM(IOS_FAMILY)
 
 #if ENABLE(FULLSCREEN_API)
-        if (element.document().webkitIsFullScreen())
-            element.document().webkitCancelFullScreen();
+        if (element.document().fullscreenManager().isFullscreen())
+            element.document().fullscreenManager().cancelFullscreen();
 #endif
 
         ++m_currentFocusedElementIdentifier;
index d08a24c..ec5f760 100644 (file)
@@ -1,3 +1,35 @@
+2019-04-18  Jer Noble  <jer.noble@apple.com>
+
+        Refactoring: Pull all fullscreen code out of Document and into its own helper class
+        https://bugs.webkit.org/show_bug.cgi?id=197017
+
+        Reviewed by Eric Carlson.
+
+        * DOM/DOMDocument.mm:
+        (-[DOMDocument webkitIsFullScreen]):
+        (-[DOMDocument webkitFullScreenKeyboardInputAllowed]):
+        (-[DOMDocument webkitCurrentFullScreenElement]):
+        (-[DOMDocument webkitFullscreenEnabled]):
+        (-[DOMDocument webkitFullscreenElement]):
+        (-[DOMDocument webkitCancelFullScreen]):
+        (-[DOMDocument webkitExitFullscreen]):
+        * WebCoreSupport/WebChromeClient.mm:
+        (WebChromeClient::createWindow):
+        * WebCoreSupport/WebKitFullScreenListener.mm:
+        (-[WebKitFullScreenListener webkitWillEnterFullScreen]):
+        (-[WebKitFullScreenListener webkitDidEnterFullScreen]):
+        (-[WebKitFullScreenListener webkitWillExitFullScreen]):
+        (-[WebKitFullScreenListener webkitDidExitFullScreen]):
+        * WebView/WebFullScreenController.mm:
+        (-[WebFullScreenController enterFullScreen:]):
+        (-[WebFullScreenController finishedEnterFullScreenAnimation:]):
+        (-[WebFullScreenController requestExitFullScreen]):
+        (-[WebFullScreenController exitFullScreen]):
+        (-[WebFullScreenController finishedExitFullScreenAnimation:]):
+        (-[WebFullScreenController _manager]):
+        * WebView/WebView.mm:
+        (-[WebView _didStartProvisionalLoadForFrame:]):
+
 2019-04-17  Brady Eidson  <beidson@apple.com>
 
         Link clicks in PDFs shouldn't send referrer headers.
index 46ccdfd..7d33c7e 100644 (file)
@@ -30,6 +30,7 @@
 #import <WebCore/CSSRuleList.h>
 #import <WebCore/CSSStyleDeclaration.h>
 #import <WebCore/Comment.h>
+#import <WebCore/DocumentFullscreen.h>
 #import "DOMAbstractViewInternal.h"
 #import "DOMAttrInternal.h"
 #import "DOMCDATASectionInternal.h"
 - (BOOL)webkitIsFullScreen
 {
     WebCore::JSMainThreadNullState state;
-    return IMPL->webkitIsFullScreen();
+    return WebCore::DocumentFullscreen::webkitIsFullScreen(*IMPL);
 }
 
 - (BOOL)webkitFullScreenKeyboardInputAllowed
 {
     WebCore::JSMainThreadNullState state;
-    return IMPL->webkitFullScreenKeyboardInputAllowed();
+    return WebCore::DocumentFullscreen::webkitFullScreenKeyboardInputAllowed(*IMPL);
 }
 
 - (DOMElement *)webkitCurrentFullScreenElement
 {
     WebCore::JSMainThreadNullState state;
-    return kit(WTF::getPtr(IMPL->webkitCurrentFullScreenElementForBindings()));
+    return kit(WTF::getPtr(WebCore::DocumentFullscreen::webkitCurrentFullScreenElement(*IMPL)));
 }
 
 - (BOOL)webkitFullscreenEnabled
 {
     WebCore::JSMainThreadNullState state;
-    return IMPL->webkitFullscreenEnabled();
+    return WebCore::DocumentFullscreen::webkitFullscreenEnabled(*IMPL);
 }
 
 - (DOMElement *)webkitFullscreenElement
 {
     WebCore::JSMainThreadNullState state;
-    return kit(WTF::getPtr(IMPL->webkitFullscreenElementForBindings()));
+    return kit(WTF::getPtr(WebCore::DocumentFullscreen::webkitFullscreenElement(*IMPL)));
 }
 
 #endif
@@ -716,13 +717,13 @@ static RefPtr<WebCore::XPathNSResolver> wrap(id <DOMXPathNSResolver> resolver)
 - (void)webkitCancelFullScreen
 {
     WebCore::JSMainThreadNullState state;
-    IMPL->webkitCancelFullScreen();
+    WebCore::DocumentFullscreen::webkitCancelFullScreen(*IMPL);
 }
 
 - (void)webkitExitFullscreen
 {
     WebCore::JSMainThreadNullState state;
-    IMPL->webkitExitFullscreen();
+    WebCore::DocumentFullscreen::webkitExitFullscreen(*IMPL);
 }
 
 #endif
index f74a4f6..aac8715 100644 (file)
@@ -68,6 +68,7 @@
 #import <WebCore/Frame.h>
 #import <WebCore/FrameLoadRequest.h>
 #import <WebCore/FrameView.h>
+#import <WebCore/FullscreenManager.h>
 #import <WebCore/GraphicsLayer.h>
 #import <WebCore/HTMLInputElement.h>
 #import <WebCore/HTMLNames.h>
@@ -243,8 +244,8 @@ Page* WebChromeClient::createWindow(Frame& frame, const FrameLoadRequest&, const
     WebView *newWebView;
 
 #if ENABLE(FULLSCREEN_API)
-    if (frame.document() && frame.document()->webkitCurrentFullScreenElement())
-        frame.document()->webkitCancelFullScreen();
+    if (frame.document() && frame.document()->fullscreenManager().currentFullscreenElement())
+        frame.document()->fullscreenManager().cancelFullscreen();
 #endif
     
     if ([delegate respondsToSelector:@selector(webView:createWebViewWithRequest:windowFeatures:)]) {
index 537cc66..560f22b 100644 (file)
@@ -29,6 +29,8 @@
 
 #if ENABLE(FULLSCREEN_API)
 
+#import <WebCore/FullscreenManager.h>
+
 using namespace WebCore;
 
 @implementation WebKitFullScreenListener
@@ -45,25 +47,25 @@ using namespace WebCore;
 - (void)webkitWillEnterFullScreen
 {
     if (_element)
-        _element->document().webkitWillEnterFullScreen(*_element);
+        _element->document().fullscreenManager().willEnterFullscreen(*_element);
 }
 
 - (void)webkitDidEnterFullScreen
 {
     if (_element)
-        _element->document().webkitDidEnterFullScreen();
+        _element->document().fullscreenManager().didEnterFullscreen();
 }
 
 - (void)webkitWillExitFullScreen
 {
     if (_element)
-        _element->document().webkitWillExitFullScreen();
+        _element->document().fullscreenManager().willExitFullscreen();
 }
 
 - (void)webkitDidExitFullScreen
 {
     if (_element)
-        _element->document().webkitDidExitFullScreen();
+        _element->document().fullscreenManager().didExitFullscreen();
 }
 
 @end
index 89bfa70..c4ae63d 100644 (file)
@@ -36,6 +36,7 @@
 #import <WebCore/FloatRect.h>
 #import <WebCore/Frame.h>
 #import <WebCore/FrameView.h>
+#import <WebCore/FullscreenManager.h>
 #import <WebCore/HTMLElement.h>
 #import <WebCore/IntRect.h>
 #import <WebCore/RenderLayer.h>
@@ -65,6 +66,7 @@ static IntRect screenRectOfContents(Element* element)
 - (void)_updateMenuAndDockForFullScreen;
 - (void)_swapView:(NSView*)view with:(NSView*)otherView;
 - (Document*)_document;
+- (FullscreenManager*)_manager;
 - (void)_startEnterFullScreenAnimationWithDuration:(NSTimeInterval)duration;
 - (void)_startExitFullScreenAnimationWithDuration:(NSTimeInterval)duration;
 @end
@@ -237,8 +239,8 @@ static NSRect convertRectToScreen(NSWindow *window, NSRect rect)
 
     _savedScale = [_webView _viewScaleFactor];
     [_webView _scaleWebView:1 atOrigin:NSMakePoint(0, 0)];
-    [self _document]->webkitWillEnterFullScreen(*_element);
-    [self _document]->setAnimatingFullScreen(true);
+    [self _manager]->willEnterFullscreen(*_element);
+    [self _manager]->setAnimatingFullscreen(true);
     [self _document]->updateLayout();
 
     _finalFrame = screenRectOfContents(_element.get());
@@ -271,8 +273,8 @@ static void setClipRectForWindow(NSWindow *window, NSRect clipRect)
         // Screen updates to be re-enabled at the end of this block
         NSDisableScreenUpdates();
         ALLOW_DEPRECATED_DECLARATIONS_END
-        [self _document]->setAnimatingFullScreen(false);
-        [self _document]->webkitDidEnterFullScreen();
+        [self _manager]->setAnimatingFullscreen(false);
+        [self _manager]->didEnterFullscreen();
         
         NSRect windowBounds = [[self window] frame];
         windowBounds.origin = NSZeroPoint;
@@ -303,7 +305,7 @@ static void setClipRectForWindow(NSWindow *window, NSRect clipRect)
 {
     if (!_element)
         return;
-    _element->document().webkitCancelFullScreen();
+    _element->document().fullscreenManager().cancelFullscreen();
 }
 
 - (void)exitFullScreen
@@ -320,8 +322,8 @@ static void setClipRectForWindow(NSWindow *window, NSRect clipRect)
 
     _finalFrame = screenRectOfContents(_element.get());
 
-    [self _document]->webkitWillExitFullScreen();
-    [self _document]->setAnimatingFullScreen(true);
+    [self _manager]->willExitFullscreen();
+    [self _manager]->setAnimatingFullscreen(true);
 
     if (_isEnteringFullScreen)
         [self finishedEnterFullScreenAnimation:NO];
@@ -361,8 +363,8 @@ static void setClipRectForWindow(NSWindow *window, NSRect clipRect)
     NSDisableScreenUpdates();
     ALLOW_DEPRECATED_DECLARATIONS_END
 
-    [self _document]->setAnimatingFullScreen(false);
-    [self _document]->webkitDidExitFullScreen();
+    [self _manager]->setAnimatingFullscreen(false);
+    [self _manager]->didExitFullscreen();
     [_webView _scaleWebView:_savedScale atOrigin:NSMakePoint(0, 0)];
 
     NSResponder *firstResponder = [[self window] firstResponder];
@@ -455,6 +457,11 @@ static void setClipRectForWindow(NSWindow *window, NSRect clipRect)
     return &_element->document();
 }
 
+- (FullscreenManager*)_manager
+{
+    return &_element->document().fullscreenManager();
+}
+
 - (void)_swapView:(NSView*)view with:(NSView*)otherView
 {
     [CATransaction begin];
index 8137188..3998a5b 100644 (file)
 #import <WebCore/FrameSelection.h>
 #import <WebCore/FrameTree.h>
 #import <WebCore/FrameView.h>
+#import <WebCore/FullscreenManager.h>
 #import <WebCore/GCController.h>
 #import <WebCore/GameControllerGamepadProvider.h>
 #import <WebCore/GeolocationController.h>
@@ -3598,7 +3599,7 @@ IGNORE_WARNINGS_END
 
 #if ENABLE(FULLSCREEN_API)
     Document* document = core([frame DOMDocument]);
-    if (Element* element = document ? document->webkitCurrentFullScreenElement() : 0) {
+    if (Element* element = document ? document->fullscreenManager().currentFullscreenElement() : 0) {
         SEL selector = @selector(webView:closeFullScreenWithListener:);
         if ([_private->UIDelegate respondsToSelector:selector]) {
             WebKitFullScreenListener *listener = [[WebKitFullScreenListener alloc] initWithElement:element];
index 0248251..22bb2ce 100644 (file)
@@ -1,3 +1,18 @@
+2019-04-18  Jer Noble  <jer.noble@apple.com>
+
+        Refactoring: Pull all fullscreen code out of Document and into its own helper class
+        https://bugs.webkit.org/show_bug.cgi?id=197017
+
+        Reviewed by Eric Carlson.
+
+        * WebCoreSupport/WebChromeClient.cpp:
+        (WebChromeClient::createWindow):
+        * WebView.cpp:
+        (WebView::fullScreenClientWillEnterFullScreen):
+        (WebView::fullScreenClientDidEnterFullScreen):
+        (WebView::fullScreenClientWillExitFullScreen):
+        (WebView::fullScreenClientDidExitFullScreen):
+
 2019-04-10  Said Abou-Hallawa  <sabouhallawa@apple.com>
 
         requestAnimationFrame should execute before the next frame
index 8f67a11..63b06a2 100644 (file)
@@ -46,6 +46,7 @@
 #include <WebCore/FrameLoadRequest.h>
 #include <WebCore/FrameView.h>
 #include <WebCore/FullScreenController.h>
+#include <WebCore/FullscreenManager.h>
 #include <WebCore/GraphicsLayer.h>
 #include <WebCore/HTMLNames.h>
 #include <WebCore/HTMLVideoElement.h>
@@ -196,8 +197,8 @@ Page* WebChromeClient::createWindow(Frame& frame, const FrameLoadRequest&, const
         return 0;
 
 #if ENABLE(FULLSCREEN_API)
-    if (frame.document() && frame.document()->webkitCurrentFullScreenElement())
-        frame.document()->webkitCancelFullScreen();
+    if (frame.document() && frame.document()->fullscreenManager().currentFullscreenElement())
+        frame.document()->fullscreenManager().cancelFullscreen();
 #endif
 
     COMPtr<WebMutableURLRequest> request = adoptCOM(WebMutableURLRequest::createInstance(ResourceRequest(navigationAction.url())));
index 2ac1483..381f1a6 100644 (file)
 #include <WebCore/FrameView.h>
 #include <WebCore/FrameWin.h>
 #include <WebCore/FullScreenController.h>
+#include <WebCore/FullscreenManager.h>
 #include <WebCore/GDIObjectCounter.h>
 #include <WebCore/GDIUtilities.h>
 #include <WebCore/GeolocationController.h>
@@ -7567,25 +7568,25 @@ void WebView::fullScreenClientSetParentWindow(HWND hostWindow)
 void WebView::fullScreenClientWillEnterFullScreen()
 {
     ASSERT(m_fullScreenElement);
-    m_fullScreenElement->document().webkitWillEnterFullScreen(*m_fullScreenElement);
+    m_fullScreenElement->document().fullscreenManager().willEnterFullscreen(*m_fullScreenElement);
 }
 
 void WebView::fullScreenClientDidEnterFullScreen()
 {
     ASSERT(m_fullScreenElement);
-    m_fullScreenElement->document().webkitDidEnterFullScreen();
+    m_fullScreenElement->document().fullscreenManager().didEnterFullscreen();
 }
 
 void WebView::fullScreenClientWillExitFullScreen()
 {
     ASSERT(m_fullScreenElement);
-    m_fullScreenElement->document().webkitCancelFullScreen();
+    m_fullScreenElement->document().fullscreenManager().cancelFullscreen();
 }
 
 void WebView::fullScreenClientDidExitFullScreen()
 {
     ASSERT(m_fullScreenElement);
-    m_fullScreenElement->document().webkitDidExitFullScreen();
+    m_fullScreenElement->document().fullscreenManager().didExitFullscreen();
     m_fullScreenElement = nullptr;
 }