| Index: third_party/WebKit/Source/web/FullscreenController.cpp
|
| diff --git a/third_party/WebKit/Source/web/FullscreenController.cpp b/third_party/WebKit/Source/web/FullscreenController.cpp
|
| index 09e664a31adbfe5bcc0c31aec95d99c9fb382704..afb46245e455d4dcaa1bec65a7ce4ebf435e413e 100644
|
| --- a/third_party/WebKit/Source/web/FullscreenController.cpp
|
| +++ b/third_party/WebKit/Source/web/FullscreenController.cpp
|
| @@ -37,94 +37,114 @@
|
| #include "core/frame/PageScaleConstraintsSet.h"
|
| #include "core/html/HTMLVideoElement.h"
|
| #include "core/layout/LayoutFullScreen.h"
|
| -#include "platform/RuntimeEnabledFeatures.h"
|
| #include "public/platform/WebLayerTreeView.h"
|
| #include "public/web/WebFrameClient.h"
|
| #include "web/WebLocalFrameImpl.h"
|
| -#include "web/WebSettingsImpl.h"
|
| #include "web/WebViewImpl.h"
|
|
|
| namespace blink {
|
|
|
| -FullscreenController* FullscreenController::create(WebViewImpl* webViewImpl) {
|
| - return new FullscreenController(webViewImpl);
|
| +std::unique_ptr<FullscreenController> FullscreenController::create(
|
| + WebViewImpl* webViewImpl) {
|
| + return wrapUnique(new FullscreenController(webViewImpl));
|
| }
|
|
|
| FullscreenController::FullscreenController(WebViewImpl* webViewImpl)
|
| - : m_webViewImpl(webViewImpl),
|
| - m_haveEnteredFullscreen(false),
|
| - m_exitFullscreenPageScaleFactor(0),
|
| - m_needsScrollAndScaleRestore(false),
|
| - m_isCancelingFullscreen(false) {}
|
| + : m_webViewImpl(webViewImpl) {}
|
|
|
| void FullscreenController::didEnterFullscreen() {
|
| - if (!m_provisionalFullscreenElement)
|
| + // Browser::EnterFullscreenModeForTab can enter fullscreen without going
|
| + // through Fullscreen::requestFullscreen, in which case there will be no
|
| + // fullscreen element. Do nothing.
|
| + if (m_state != State::kEnteringFullscreen)
|
| return;
|
|
|
| - Element* element = m_provisionalFullscreenElement.release();
|
| - Document& document = element->document();
|
| - m_fullscreenFrame = document.frame();
|
| -
|
| - if (!m_fullscreenFrame)
|
| - return;
|
| + updatePageScaleConstraints(false);
|
| + m_webViewImpl->setPageScaleFactor(1.0f);
|
| + if (m_webViewImpl->mainFrame()->isWebLocalFrame())
|
| + m_webViewImpl->mainFrame()->setScrollOffset(WebSize());
|
| + m_webViewImpl->setVisualViewportOffset(FloatPoint());
|
|
|
| - if (!m_haveEnteredFullscreen) {
|
| - updatePageScaleConstraints(false);
|
| - m_webViewImpl->setPageScaleFactor(1.0f);
|
| - if (m_webViewImpl->mainFrame()->isWebLocalFrame())
|
| - m_webViewImpl->mainFrame()->setScrollOffset(WebSize());
|
| - m_webViewImpl->setVisualViewportOffset(FloatPoint());
|
| - m_haveEnteredFullscreen = true;
|
| - }
|
| + DCHECK(!m_callbacksList.isEmpty());
|
| + CallbacksList callbacksList;
|
| + callbacksList.swap(m_callbacksList);
|
| + for (auto& callbacks : callbacksList)
|
| + callbacks->onSuccess();
|
|
|
| - Fullscreen::from(document).didEnterFullscreenForElement(element);
|
| - DCHECK_EQ(Fullscreen::currentFullScreenElementFrom(document), element);
|
| + m_state = State::kFullscreen;
|
| }
|
|
|
| void FullscreenController::didExitFullscreen() {
|
| - if (!m_fullscreenFrame)
|
| + // The browser process can exit fullscreen at any time, e.g. if the user
|
| + // presses Esc. After Browser::EnterFullscreenModeForTab,
|
| + // Browser::ExitFullscreenModeForTab will make it seem like we exit when not
|
| + // even in fullscreen. Do nothing.
|
| + if (m_state == State::kInitial)
|
| return;
|
|
|
| - if (m_haveEnteredFullscreen)
|
| - updatePageScaleConstraints(true);
|
| -
|
| - if (Document* document = m_fullscreenFrame->document()) {
|
| - if (Fullscreen* fullscreen = Fullscreen::fromIfExists(*document)) {
|
| - Element* element = fullscreen->currentFullScreenElement();
|
| - if (element) {
|
| - // When the client exits from full screen we have to call
|
| - // fullyExitFullscreen to notify the document. While doing that,
|
| - // suppress notifications back to the client.
|
| - m_isCancelingFullscreen = true;
|
| - Fullscreen::fullyExitFullscreen(*document);
|
| - m_isCancelingFullscreen = false;
|
| -
|
| - // We need to wait until style and layout are updated in order
|
| - // to propertly restore scroll offsets since content may not be
|
| - // overflowing in the same way until they do.
|
| - if (m_haveEnteredFullscreen)
|
| - m_needsScrollAndScaleRestore = true;
|
| + updatePageScaleConstraints(true);
|
| +
|
| + // If we were transitioning into fullscreen, invoke the error callbacks.
|
| + if (m_state == State::kEnteringFullscreen) {
|
| + DCHECK(!m_callbacksList.isEmpty());
|
| + CallbacksList callbacksList;
|
| + callbacksList.swap(m_callbacksList);
|
| + for (auto& callbacks : callbacksList)
|
| + callbacks->onError();
|
| + } else {
|
| + DCHECK(m_callbacksList.isEmpty());
|
| + }
|
|
|
| + // Set m_state so that any calls to enterFullscreen() or exitFullscreen() from
|
| + // within Fullscreen::didExitFullscreen do nothing.
|
| + m_state = State::kExitingFullscreen;
|
| +
|
| + // Notify all local frames that we have exited fullscreen.
|
| + // TODO(foolip): This should only need to notify the topmost local roots. That
|
| + // doesn't currently work because Fullscreen::m_currentFullScreenElement isn't
|
| + // set for the topmost document when an iframe goes fullscreen, but can be
|
| + // done once m_currentFullScreenElement is gone and all state is in the
|
| + // fullscreen element stack. https://crbug.com/402421
|
| + for (Frame* frame = m_webViewImpl->page()->mainFrame(); frame;
|
| + frame = frame->tree().traverseNext()) {
|
| + if (!frame->isLocalFrame())
|
| + continue;
|
| + if (Document* document = toLocalFrame(frame)->document()) {
|
| + if (Fullscreen* fullscreen = Fullscreen::fromIfExists(*document))
|
| fullscreen->didExitFullscreen();
|
| - }
|
| }
|
| }
|
|
|
| - m_haveEnteredFullscreen = false;
|
| - m_fullscreenFrame.clear();
|
| + // We need to wait until style and layout are updated in order to properly
|
| + // restore scroll offsets since content may not be overflowing in the same way
|
| + // until they are.
|
| + m_state = State::kNeedsScrollAndScaleRestore;
|
| }
|
|
|
| -void FullscreenController::enterFullscreenForElement(Element* element) {
|
| - // We are already transitioning to fullscreen for a different element.
|
| - if (m_provisionalFullscreenElement) {
|
| - m_provisionalFullscreenElement = element;
|
| +namespace {
|
| +
|
| +WebFrameClient& webFrameClient(LocalFrame& frame) {
|
| + WebLocalFrameImpl* webFrame = WebLocalFrameImpl::fromFrame(frame);
|
| + DCHECK(webFrame);
|
| + DCHECK(webFrame->client());
|
| + return *webFrame->client();
|
| +}
|
| +
|
| +} // anonymous namespace
|
| +
|
| +void FullscreenController::enterFullscreen(
|
| + LocalFrame& frame,
|
| + std::unique_ptr<WebFullscreenCallbacks> callbacks) {
|
| + // If already in fullscreen, synchronously invoke the success callback.
|
| + if (m_state == State::kFullscreen) {
|
| + DCHECK(m_callbacksList.isEmpty());
|
| + callbacks->onSuccess();
|
| return;
|
| }
|
|
|
| - // We are already in fullscreen mode.
|
| - if (m_fullscreenFrame) {
|
| - m_provisionalFullscreenElement = element;
|
| - didEnterFullscreen();
|
| + // While exiting fullscreen, reject any attempt to enter.
|
| + if (m_state == State::kExitingFullscreen) {
|
| + callbacks->onError();
|
| return;
|
| }
|
|
|
| @@ -133,36 +153,38 @@ void FullscreenController::enterFullscreenForElement(Element* element) {
|
| // the scroll offset. Don't save values if we're still waiting to restore
|
| // a previous set. This can happen if we exit and quickly reenter fullscreen
|
| // without performing a layout.
|
| - if (!m_haveEnteredFullscreen && !m_needsScrollAndScaleRestore) {
|
| - m_exitFullscreenPageScaleFactor = m_webViewImpl->pageScaleFactor();
|
| - m_exitFullscreenScrollOffset =
|
| - m_webViewImpl->mainFrame()->isWebLocalFrame()
|
| - ? m_webViewImpl->mainFrame()->scrollOffset()
|
| - : WebSize();
|
| - m_exitFullscreenVisualViewportOffset =
|
| - m_webViewImpl->visualViewportOffset();
|
| + if (m_state == State::kInitial) {
|
| + m_initialPageScaleFactor = m_webViewImpl->pageScaleFactor();
|
| + m_initialScrollOffset = m_webViewImpl->mainFrame()->isWebLocalFrame()
|
| + ? m_webViewImpl->mainFrame()->scrollOffset()
|
| + : WebSize();
|
| + m_initialVisualViewportOffset = m_webViewImpl->visualViewportOffset();
|
| }
|
|
|
| - // We need to transition to fullscreen mode.
|
| - WebLocalFrameImpl* frame =
|
| - WebLocalFrameImpl::fromFrame(element->document().frame());
|
| - if (frame && frame->client()) {
|
| - if (!Fullscreen::from(element->document()).forCrossProcessDescendant())
|
| - frame->client()->enterFullscreen();
|
| - m_provisionalFullscreenElement = element;
|
| - }
|
| -}
|
| + m_callbacksList.append(std::move(callbacks));
|
|
|
| -void FullscreenController::exitFullscreen(LocalFrame* frame) {
|
| - DCHECK(frame);
|
| + // If already entering fullscreen, just wait.
|
| + if (m_state == State::kEnteringFullscreen)
|
| + return;
|
|
|
| - // The client is exiting full screen, so don't send a notification.
|
| - if (m_isCancelingFullscreen)
|
| + DCHECK(m_state == State::kInitial ||
|
| + m_state == State::kNeedsScrollAndScaleRestore);
|
| + webFrameClient(frame).enterFullscreen();
|
| +
|
| + m_state = State::kEnteringFullscreen;
|
| +}
|
| +
|
| +void FullscreenController::exitFullscreen(LocalFrame& frame) {
|
| + // If not in fullscreen, ignore any attempt to exit. In particular, for
|
| + // State::kEnteringFullscreen, allow the transition into fullscreen to
|
| + // complete. Note that the browser process is ultimately in control and can
|
| + // still (indirecitly) call didExitFullscreen() at any time to exit.
|
| + if (m_state != State::kFullscreen)
|
| return;
|
|
|
| - WebLocalFrameImpl* webFrame = WebLocalFrameImpl::fromFrame(frame);
|
| - if (webFrame && webFrame->client())
|
| - webFrame->client()->exitFullscreen();
|
| + webFrameClient(frame).exitFullscreen();
|
| +
|
| + m_state = State::kExitingFullscreen;
|
| }
|
|
|
| void FullscreenController::fullscreenElementChanged(Element* fromElement,
|
| @@ -202,32 +224,38 @@ void FullscreenController::fullscreenElementChanged(Element* fromElement,
|
| }
|
|
|
| void FullscreenController::updateSize() {
|
| - if (!isFullscreen())
|
| + DCHECK(m_webViewImpl->page());
|
| +
|
| + if (m_state != State::kFullscreen)
|
| return;
|
|
|
| updatePageScaleConstraints(false);
|
|
|
| - LayoutFullScreen* layoutObject =
|
| - Fullscreen::from(*m_fullscreenFrame->document()).fullScreenLayoutObject();
|
| - if (layoutObject)
|
| - layoutObject->updateStyle();
|
| + // Traverse all local frames and notify the LayoutFullScreen object, if any.
|
| + for (Frame* frame = m_webViewImpl->page()->mainFrame(); frame;
|
| + frame = frame->tree().traverseNext()) {
|
| + if (!frame->isLocalFrame())
|
| + continue;
|
| + if (Document* document = toLocalFrame(frame)->document()) {
|
| + if (Fullscreen* fullscreen = Fullscreen::fromIfExists(*document)) {
|
| + if (LayoutFullScreen* layoutObject =
|
| + fullscreen->fullScreenLayoutObject())
|
| + layoutObject->updateStyle();
|
| + }
|
| + }
|
| + }
|
| }
|
|
|
| void FullscreenController::didUpdateLayout() {
|
| - if (!m_needsScrollAndScaleRestore)
|
| - return;
|
| -
|
| - // If we re-entered fullscreen before we could restore the scroll and scale
|
| - // don't try restoring them yet.
|
| - if (isFullscreen())
|
| + if (m_state != State::kNeedsScrollAndScaleRestore)
|
| return;
|
|
|
| - m_webViewImpl->setPageScaleFactor(m_exitFullscreenPageScaleFactor);
|
| + m_webViewImpl->setPageScaleFactor(m_initialPageScaleFactor);
|
| if (m_webViewImpl->mainFrame()->isWebLocalFrame())
|
| - m_webViewImpl->mainFrame()->setScrollOffset(
|
| - WebSize(m_exitFullscreenScrollOffset));
|
| - m_webViewImpl->setVisualViewportOffset(m_exitFullscreenVisualViewportOffset);
|
| - m_needsScrollAndScaleRestore = false;
|
| + m_webViewImpl->mainFrame()->setScrollOffset(WebSize(m_initialScrollOffset));
|
| + m_webViewImpl->setVisualViewportOffset(m_initialVisualViewportOffset);
|
| +
|
| + m_state = State::kInitial;
|
| }
|
|
|
| void FullscreenController::updatePageScaleConstraints(bool removeConstraints) {
|
| @@ -255,9 +283,4 @@ void FullscreenController::updatePageScaleConstraints(bool removeConstraints) {
|
| m_webViewImpl->updateMainFrameLayoutSize();
|
| }
|
|
|
| -DEFINE_TRACE(FullscreenController) {
|
| - visitor->trace(m_provisionalFullscreenElement);
|
| - visitor->trace(m_fullscreenFrame);
|
| -}
|
| -
|
| } // namespace blink
|
|
|