1 /* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #include "web/FullscreenController.h" 33 34 #include "core/dom/Document.h" 35 #include "core/dom/FullscreenElementStack.h" 36 #include "core/frame/LocalFrame.h" 37 #include "core/html/HTMLMediaElement.h" 38 #include "platform/LayoutTestSupport.h" 39 #include "platform/RuntimeEnabledFeatures.h" 40 #include "public/web/WebFrame.h" 41 #include "public/web/WebViewClient.h" 42 #include "web/WebSettingsImpl.h" 43 #include "web/WebViewImpl.h" 44 45 using namespace WebCore; 46 47 namespace blink { 48 49 PassOwnPtr<FullscreenController> FullscreenController::create(WebViewImpl* webViewImpl) 50 { 51 return adoptPtr(new FullscreenController(webViewImpl)); 52 } 53 54 FullscreenController::FullscreenController(WebViewImpl* webViewImpl) 55 : m_webViewImpl(webViewImpl) 56 , m_exitFullscreenPageScaleFactor(0) 57 , m_isCancelingFullScreen(false) 58 { 59 } 60 61 void FullscreenController::willEnterFullScreen() 62 { 63 if (!m_provisionalFullScreenElement) 64 return; 65 66 // Ensure that this element's document is still attached. 67 Document& doc = m_provisionalFullScreenElement->document(); 68 if (doc.frame()) { 69 FullscreenElementStack::from(doc).webkitWillEnterFullScreenForElement(m_provisionalFullScreenElement.get()); 70 m_fullScreenFrame = doc.frame(); 71 } 72 m_provisionalFullScreenElement.clear(); 73 } 74 75 void FullscreenController::didEnterFullScreen() 76 { 77 if (!m_fullScreenFrame) 78 return; 79 80 if (Document* doc = m_fullScreenFrame->document()) { 81 if (FullscreenElementStack::isFullScreen(*doc)) { 82 if (!m_exitFullscreenPageScaleFactor) { 83 m_exitFullscreenPageScaleFactor = m_webViewImpl->pageScaleFactor(); 84 m_exitFullscreenScrollOffset = m_webViewImpl->mainFrame()->scrollOffset(); 85 m_exitFullscreenPinchViewportOffset = m_webViewImpl->pinchViewportOffset(); 86 m_webViewImpl->setPageScaleFactor(1.0f); 87 m_webViewImpl->setMainFrameScrollOffset(IntPoint()); 88 m_webViewImpl->setPinchViewportOffset(FloatPoint()); 89 } 90 91 FullscreenElementStack::from(*doc).webkitDidEnterFullScreenForElement(0); 92 if (RuntimeEnabledFeatures::overlayFullscreenVideoEnabled()) { 93 Element* element = FullscreenElementStack::currentFullScreenElementFrom(*doc); 94 ASSERT(element); 95 if (isHTMLMediaElement(*element)) { 96 HTMLMediaElement* mediaElement = toHTMLMediaElement(element); 97 if (mediaElement->webMediaPlayer() && mediaElement->webMediaPlayer()->canEnterFullscreen() 98 // FIXME: There is no embedder-side handling in layout test mode. 99 && !isRunningLayoutTest()) { 100 mediaElement->webMediaPlayer()->enterFullscreen(); 101 } 102 if (m_webViewImpl->layerTreeView()) 103 m_webViewImpl->layerTreeView()->setHasTransparentBackground(true); 104 } 105 } 106 } 107 } 108 } 109 110 void FullscreenController::willExitFullScreen() 111 { 112 if (!m_fullScreenFrame) 113 return; 114 115 if (Document* doc = m_fullScreenFrame->document()) { 116 FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExists(*doc); 117 if (!fullscreen) 118 return; 119 if (fullscreen->isFullScreen(*doc)) { 120 // When the client exits from full screen we have to call webkitCancelFullScreen to 121 // notify the document. While doing that, suppress notifications back to the client. 122 m_isCancelingFullScreen = true; 123 fullscreen->webkitCancelFullScreen(); 124 m_isCancelingFullScreen = false; 125 fullscreen->webkitWillExitFullScreenForElement(0); 126 if (RuntimeEnabledFeatures::overlayFullscreenVideoEnabled() && m_webViewImpl->layerTreeView()) 127 m_webViewImpl->layerTreeView()->setHasTransparentBackground(m_webViewImpl->isTransparent()); 128 } 129 } 130 } 131 132 void FullscreenController::didExitFullScreen() 133 { 134 if (!m_fullScreenFrame) 135 return; 136 137 if (Document* doc = m_fullScreenFrame->document()) { 138 if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExists(*doc)) { 139 if (fullscreen->webkitIsFullScreen()) { 140 if (m_exitFullscreenPageScaleFactor) { 141 m_webViewImpl->setPageScaleFactor(m_exitFullscreenPageScaleFactor); 142 m_webViewImpl->setMainFrameScrollOffset(IntPoint(m_exitFullscreenScrollOffset)); 143 m_webViewImpl->setPinchViewportOffset(m_exitFullscreenPinchViewportOffset); 144 m_exitFullscreenPageScaleFactor = 0; 145 m_exitFullscreenScrollOffset = IntSize(); 146 } 147 148 fullscreen->webkitDidExitFullScreenForElement(0); 149 } 150 } 151 } 152 153 m_fullScreenFrame.clear(); 154 } 155 156 void FullscreenController::enterFullScreenForElement(WebCore::Element* element) 157 { 158 // We are already transitioning to fullscreen for a different element. 159 if (m_provisionalFullScreenElement) { 160 m_provisionalFullScreenElement = element; 161 return; 162 } 163 164 // We are already in fullscreen mode. 165 if (m_fullScreenFrame) { 166 m_provisionalFullScreenElement = element; 167 willEnterFullScreen(); 168 didEnterFullScreen(); 169 return; 170 } 171 172 // We need to transition to fullscreen mode. 173 if (WebViewClient* client = m_webViewImpl->client()) { 174 if (client->enterFullScreen()) 175 m_provisionalFullScreenElement = element; 176 } 177 } 178 179 void FullscreenController::exitFullScreenForElement(WebCore::Element* element) 180 { 181 // The client is exiting full screen, so don't send a notification. 182 if (m_isCancelingFullScreen) 183 return; 184 if (WebViewClient* client = m_webViewImpl->client()) 185 client->exitFullScreen(); 186 } 187 188 } 189 190