[Cocoa] Add SPI to check if a WKWebView has an inspector frontend
[WebKit-https.git] / Source / WebKit / WebProcess / FullScreen / WebFullScreenManager.cpp
1 /*
2  * Copyright (C) 2011 Apple 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
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 #include "config.h"
26 #include "WebFullScreenManager.h"
27
28 #if ENABLE(FULLSCREEN_API)
29
30 #include "Connection.h"
31 #include "Logging.h"
32 #include "WebCoreArgumentCoders.h"
33 #include "WebFrame.h"
34 #include "WebFullScreenManagerProxyMessages.h"
35 #include "WebPage.h"
36 #include <WebCore/Color.h>
37 #include <WebCore/Element.h>
38 #include <WebCore/Frame.h>
39 #include <WebCore/FrameView.h>
40 #include <WebCore/HTMLVideoElement.h>
41 #include <WebCore/Page.h>
42 #include <WebCore/RenderLayer.h>
43 #include <WebCore/RenderLayerBacking.h>
44 #include <WebCore/RenderObject.h>
45 #include <WebCore/RenderView.h>
46 #include <WebCore/Settings.h>
47 #include <WebCore/TypedElementDescendantIterator.h>
48
49 #if PLATFORM(IOS_FAMILY) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
50 #include "PlaybackSessionManager.h"
51 #endif
52
53 namespace WebKit {
54 using namespace WebCore;
55
56 static IntRect screenRectOfContents(Element* element)
57 {
58     ASSERT(element);
59     if (element->renderer() && element->renderer()->hasLayer() && element->renderer()->enclosingLayer()->isComposited()) {
60         FloatQuad contentsBox = static_cast<FloatRect>(element->renderer()->enclosingLayer()->backing()->contentsBox());
61         contentsBox = element->renderer()->localToAbsoluteQuad(contentsBox);
62         return element->renderer()->view().frameView().contentsToScreen(contentsBox.enclosingBoundingBox());
63     }
64
65     return element->screenRect();
66 }
67
68 Ref<WebFullScreenManager> WebFullScreenManager::create(WebPage* page)
69 {
70     return adoptRef(*new WebFullScreenManager(page));
71 }
72
73 WebFullScreenManager::WebFullScreenManager(WebPage* page)
74     : m_page(page)
75 {
76 }
77     
78 WebFullScreenManager::~WebFullScreenManager()
79 {
80 }
81
82 WebCore::Element* WebFullScreenManager::element() 
83
84     return m_element.get(); 
85 }
86
87 void WebFullScreenManager::videoControlsManagerDidChange()
88 {
89 #if PLATFORM(IOS_FAMILY) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
90     LOG(Fullscreen, "WebFullScreenManager %p videoControlsManagerDidChange()", this);
91
92     auto* currentPlaybackControlsElement = m_page->playbackSessionManager().currentPlaybackControlsElement();
93     if (!m_element || !is<HTMLVideoElement>(currentPlaybackControlsElement)) {
94         setPIPStandbyElement(nullptr);
95         return;
96     }
97
98     setPIPStandbyElement(downcast<HTMLVideoElement>(currentPlaybackControlsElement));
99 #endif
100 }
101
102 void WebFullScreenManager::setPIPStandbyElement(WebCore::HTMLVideoElement* pipStandbyElement)
103 {
104 #if ENABLE(VIDEO)
105     if (pipStandbyElement == m_pipStandbyElement)
106         return;
107
108     LOG(Fullscreen, "WebFullScreenManager %p setPIPStandbyElement() - old element %p, new element %p", this, m_pipStandbyElement.get(), pipStandbyElement);
109
110     if (m_pipStandbyElement)
111         m_pipStandbyElement->setVideoFullscreenStandby(false);
112
113     m_pipStandbyElement = pipStandbyElement;
114
115     if (m_pipStandbyElement)
116         m_pipStandbyElement->setVideoFullscreenStandby(true);
117 #endif
118 }
119
120 void WebFullScreenManager::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
121 {
122     didReceiveWebFullScreenManagerMessage(connection, decoder);
123 }
124
125 bool WebFullScreenManager::supportsFullScreen(bool withKeyboard)
126 {
127     if (!m_page->corePage()->settings().fullScreenEnabled())
128         return false;
129
130     return m_page->injectedBundleFullScreenClient().supportsFullScreen(m_page.get(), withKeyboard);
131 }
132
133 void WebFullScreenManager::enterFullScreenForElement(WebCore::Element* element)
134 {
135     LOG(Fullscreen, "WebFullScreenManager %p enterFullScreenForElement(%p)", this, element);
136
137     ASSERT(element);
138     m_element = element;
139     m_initialFrame = screenRectOfContents(m_element.get());
140     m_page->injectedBundleFullScreenClient().enterFullScreenForElement(m_page.get(), element);
141 }
142
143 void WebFullScreenManager::exitFullScreenForElement(WebCore::Element* element)
144 {
145     LOG(Fullscreen, "WebFullScreenManager %p exitFullScreenForElement(%p) - fullscreen element %p", this, element, m_element.get());
146     m_page->injectedBundleFullScreenClient().exitFullScreenForElement(m_page.get(), element);
147 }
148
149 void WebFullScreenManager::willEnterFullScreen()
150 {
151     LOG(Fullscreen, "WebFullScreenManager %p willEnterFullScreen() - element %p", this, m_element.get());
152
153     m_element->document().webkitWillEnterFullScreenForElement(m_element.get());
154 #if !PLATFORM(IOS_FAMILY)
155     m_page->hidePageBanners();
156 #endif
157     m_element->document().updateLayout();
158     m_page->forceRepaintWithoutCallback();
159     m_finalFrame = screenRectOfContents(m_element.get());
160     m_page->injectedBundleFullScreenClient().beganEnterFullScreen(m_page.get(), m_initialFrame, m_finalFrame);
161 }
162
163 void WebFullScreenManager::didEnterFullScreen()
164 {
165     LOG(Fullscreen, "WebFullScreenManager %p didEnterFullScreen() - element %p", this, m_element.get());
166
167     m_element->document().webkitDidEnterFullScreenForElement(m_element.get());
168
169 #if PLATFORM(IOS_FAMILY) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
170     auto* currentPlaybackControlsElement = m_page->playbackSessionManager().currentPlaybackControlsElement();
171     setPIPStandbyElement(is<HTMLVideoElement>(currentPlaybackControlsElement) ? downcast<HTMLVideoElement>(currentPlaybackControlsElement) : nullptr);
172 #endif
173 }
174
175 void WebFullScreenManager::willExitFullScreen()
176 {
177     LOG(Fullscreen, "WebFullScreenManager %p willExitFullScreen() - element %p", this, m_element.get());
178     ASSERT(m_element);
179
180 #if ENABLE(VIDEO)
181     setPIPStandbyElement(nullptr);
182 #endif
183
184     m_finalFrame = screenRectOfContents(m_element.get());
185     m_element->document().webkitWillExitFullScreenForElement(m_element.get());
186 #if !PLATFORM(IOS_FAMILY)
187     m_page->showPageBanners();
188 #endif
189     m_page->injectedBundleFullScreenClient().beganExitFullScreen(m_page.get(), m_finalFrame, m_initialFrame);
190 }
191
192 void WebFullScreenManager::didExitFullScreen()
193 {
194     LOG(Fullscreen, "WebFullScreenManager %p didExitFullScreen() - element %p", this, m_element.get());
195
196     ASSERT(m_element);
197     setFullscreenInsets(FloatBoxExtent());
198     setFullscreenAutoHideDuration(0_s);
199     m_element->document().webkitDidExitFullScreenForElement(m_element.get());
200 }
201
202 void WebFullScreenManager::setAnimatingFullScreen(bool animating)
203 {
204     ASSERT(m_element);
205     m_element->document().setAnimatingFullScreen(animating);
206 }
207
208 void WebFullScreenManager::requestExitFullScreen()
209 {
210     ASSERT(m_element);
211     m_element->document().webkitCancelFullScreen();
212 }
213
214 void WebFullScreenManager::close()
215 {
216     LOG(Fullscreen, "WebFullScreenManager %p close()", this);
217     m_page->injectedBundleFullScreenClient().closeFullScreen(m_page.get());
218 }
219
220 void WebFullScreenManager::saveScrollPosition()
221 {
222     m_scrollPosition = m_page->corePage()->mainFrame().view()->scrollPosition();
223 }
224
225 void WebFullScreenManager::restoreScrollPosition()
226 {
227     m_page->corePage()->mainFrame().view()->setScrollPosition(m_scrollPosition);
228 }
229
230 void WebFullScreenManager::setFullscreenInsets(const WebCore::FloatBoxExtent& insets)
231 {
232     m_page->corePage()->setFullscreenInsets(insets);
233 }
234
235 void WebFullScreenManager::setFullscreenAutoHideDuration(Seconds duration)
236 {
237     m_page->corePage()->setFullscreenAutoHideDuration(duration);
238 }
239
240 void WebFullScreenManager::setFullscreenControlsHidden(bool hidden)
241 {
242     m_page->corePage()->setFullscreenControlsHidden(hidden);
243 }
244
245 } // namespace WebKit
246
247 #endif // ENABLE(FULLSCREEN_API)