Add WKUIDelegatePrivate equivalent of WKPageUIClient's handleAutoplayEvent
[WebKit-https.git] / Source / WebKit / UIProcess / Cocoa / UIDelegate.mm
1 /*
2  * Copyright (C) 2014-2016 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
26 #import "config.h"
27 #import "UIDelegate.h"
28
29 #if WK_API_ENABLED
30
31 #import "APIFrameInfo.h"
32 #import "CompletionHandlerCallChecker.h"
33 #import "NativeWebWheelEvent.h"
34 #import "NavigationActionData.h"
35 #import "UserMediaPermissionCheckProxy.h"
36 #import "UserMediaPermissionRequestProxy.h"
37 #import "WKFrameInfoInternal.h"
38 #import "WKNavigationActionInternal.h"
39 #import "WKOpenPanelParametersInternal.h"
40 #import "WKSecurityOriginInternal.h"
41 #import "WKUIDelegatePrivate.h"
42 #import "WKWebViewConfigurationInternal.h"
43 #import "WKWebViewInternal.h"
44 #import "WKWindowFeaturesInternal.h"
45 #import "WebOpenPanelResultListenerProxy.h"
46 #import "WebProcessProxy.h"
47 #import "_WKContextMenuElementInfo.h"
48 #import "_WKFrameHandleInternal.h"
49 #import <WebCore/SecurityOriginData.h>
50 #import <WebCore/URL.h>
51 #import <wtf/BlockPtr.h>
52
53 #if PLATFORM(IOS)
54 #import <AVFoundation/AVCaptureDevice.h>
55 #import <AVFoundation/AVMediaFormat.h>
56 #import <wtf/SoftLinking.h>
57
58 SOFT_LINK_FRAMEWORK(AVFoundation);
59 SOFT_LINK_CLASS(AVFoundation, AVCaptureDevice);
60 SOFT_LINK_CONSTANT(AVFoundation, AVMediaTypeAudio, NSString *);
61 SOFT_LINK_CONSTANT(AVFoundation, AVMediaTypeVideo, NSString *);
62 #endif
63
64 namespace WebKit {
65
66 UIDelegate::UIDelegate(WKWebView *webView)
67     : m_webView(webView)
68 {
69 }
70
71 UIDelegate::~UIDelegate()
72 {
73 }
74
75 #if ENABLE(CONTEXT_MENUS)
76 std::unique_ptr<API::ContextMenuClient> UIDelegate::createContextMenuClient()
77 {
78     return std::make_unique<ContextMenuClient>(*this);
79 }
80 #endif
81
82 std::unique_ptr<API::UIClient> UIDelegate::createUIClient()
83 {
84     return std::make_unique<UIClient>(*this);
85 }
86
87 RetainPtr<id <WKUIDelegate> > UIDelegate::delegate()
88 {
89     return m_delegate.get();
90 }
91
92 void UIDelegate::setDelegate(id <WKUIDelegate> delegate)
93 {
94     m_delegate = delegate;
95
96     m_delegateMethods.webViewCreateWebViewWithConfigurationForNavigationActionWindowFeatures = [delegate respondsToSelector:@selector(webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:)];
97     m_delegateMethods.webViewCreateWebViewWithConfigurationForNavigationActionWindowFeaturesAsync = [delegate respondsToSelector:@selector(_webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:completionHandler:)];
98     m_delegateMethods.webViewRunJavaScriptAlertPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:)];
99     m_delegateMethods.webViewRunJavaScriptConfirmPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:)];
100     m_delegateMethods.webViewRunJavaScriptTextInputPanelWithPromptDefaultTextInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:completionHandler:)];
101     m_delegateMethods.webViewRunBeforeUnloadConfirmPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(_webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:completionHandler:)];
102
103 #if PLATFORM(MAC)
104     m_delegateMethods.showWebView = [delegate respondsToSelector:@selector(_showWebView:)];
105     m_delegateMethods.focusWebView = [delegate respondsToSelector:@selector(_focusWebView:)];
106     m_delegateMethods.unfocusWebView = [delegate respondsToSelector:@selector(_unfocusWebView:)];
107     m_delegateMethods.webViewTakeFocus = [delegate respondsToSelector:@selector(_webView:takeFocus:)];
108     m_delegateMethods.webViewDidNotHandleWheelEvent = [delegate respondsToSelector:@selector(_webView:didNotHandleWheelEvent:)];
109     m_delegateMethods.webViewHandleAutoplayEventWithFlags = [delegate respondsToSelector:@selector(_webView:handleAutoplayEvent:withFlags:)];
110     m_delegateMethods.webViewRunOpenPanelWithParametersInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runOpenPanelWithParameters:initiatedByFrame:completionHandler:)];
111 #endif
112
113     m_delegateMethods.webViewDecideDatabaseQuotaForSecurityOriginCurrentQuotaCurrentOriginUsageCurrentDatabaseUsageExpectedUsageDecisionHandler = [delegate respondsToSelector:@selector(_webView:decideDatabaseQuotaForSecurityOrigin:currentQuota:currentOriginUsage:currentDatabaseUsage:expectedUsage:decisionHandler:)];
114     m_delegateMethods.webViewDecideWebApplicationCacheQuotaForSecurityOriginCurrentQuotaTotalBytesNeeded = [delegate respondsToSelector:@selector(_webView:decideWebApplicationCacheQuotaForSecurityOrigin:currentQuota:totalBytesNeeded:decisionHandler:)];
115     m_delegateMethods.webViewPrintFrame = [delegate respondsToSelector:@selector(_webView:printFrame:)];
116     m_delegateMethods.webViewDidClose = [delegate respondsToSelector:@selector(webViewDidClose:)];
117     m_delegateMethods.webViewClose = [delegate respondsToSelector:@selector(_webViewClose:)];
118     m_delegateMethods.webViewFullscreenMayReturnToInline = [delegate respondsToSelector:@selector(_webViewFullscreenMayReturnToInline:)];
119     m_delegateMethods.webViewDidEnterFullscreen = [delegate respondsToSelector:@selector(_webViewDidEnterFullscreen:)];
120     m_delegateMethods.webViewDidExitFullscreen = [delegate respondsToSelector:@selector(_webViewDidExitFullscreen:)];
121 #if PLATFORM(IOS)
122 #if HAVE(APP_LINKS)
123     m_delegateMethods.webViewShouldIncludeAppLinkActionsForElement = [delegate respondsToSelector:@selector(_webView:shouldIncludeAppLinkActionsForElement:)];
124 #endif
125     m_delegateMethods.webViewActionsForElementDefaultActions = [delegate respondsToSelector:@selector(_webView:actionsForElement:defaultActions:)];
126     m_delegateMethods.webViewDidNotHandleTapAsClickAtPoint = [delegate respondsToSelector:@selector(_webView:didNotHandleTapAsClickAtPoint:)];
127     m_delegateMethods.presentingViewControllerForWebView = [delegate respondsToSelector:@selector(_presentingViewControllerForWebView:)];
128 #endif
129     m_delegateMethods.webViewRequestUserMediaAuthorizationForDevicesURLMainFrameURLDecisionHandler = [delegate respondsToSelector:@selector(_webView:requestUserMediaAuthorizationForDevices:url:mainFrameURL:decisionHandler:)];
130     m_delegateMethods.webViewCheckUserMediaPermissionForURLMainFrameURLFrameIdentifierDecisionHandler = [delegate respondsToSelector:@selector(_webView:checkUserMediaPermissionForURL:mainFrameURL:frameIdentifier:decisionHandler:)];
131     m_delegateMethods.webViewMediaCaptureStateDidChange = [delegate respondsToSelector:@selector(_webView:mediaCaptureStateDidChange:)];
132     m_delegateMethods.dataDetectionContextForWebView = [delegate respondsToSelector:@selector(_dataDetectionContextForWebView:)];
133     m_delegateMethods.webViewImageOrMediaDocumentSizeChanged = [delegate respondsToSelector:@selector(_webView:imageOrMediaDocumentSizeChanged:)];
134
135 #if ENABLE(POINTER_LOCK)
136     m_delegateMethods.webViewRequestPointerLock = [delegate respondsToSelector:@selector(_webViewRequestPointerLock:)];
137     m_delegateMethods.webViewDidLosePointerLock = [delegate respondsToSelector:@selector(_webViewDidLosePointerLock:)];
138 #endif
139 #if ENABLE(CONTEXT_MENUS)
140     m_delegateMethods.webViewContextMenuForElement = [delegate respondsToSelector:@selector(_webView:contextMenu:forElement:)];
141     m_delegateMethods.webViewContextMenuForElementUserInfo = [delegate respondsToSelector:@selector(_webView:contextMenu:forElement:userInfo:)];
142 #endif
143     
144     m_delegateMethods.webViewHasVideoInPictureInPictureDidChange = [delegate respondsToSelector:@selector(_webView:hasVideoInPictureInPictureDidChange:)];
145 }
146
147 #if ENABLE(CONTEXT_MENUS)
148 UIDelegate::ContextMenuClient::ContextMenuClient(UIDelegate& uiDelegate)
149     : m_uiDelegate(uiDelegate)
150 {
151 }
152
153 UIDelegate::ContextMenuClient::~ContextMenuClient()
154 {
155 }
156
157 RetainPtr<NSMenu> UIDelegate::ContextMenuClient::menuFromProposedMenu(WebKit::WebPageProxy&, NSMenu *menu, const WebKit::WebHitTestResultData&, API::Object* userInfo)
158 {
159     if (!m_uiDelegate.m_delegateMethods.webViewContextMenuForElement && !m_uiDelegate.m_delegateMethods.webViewContextMenuForElementUserInfo)
160         return menu;
161
162     auto delegate = m_uiDelegate.m_delegate.get();
163     if (!delegate)
164         return menu;
165
166     auto contextMenuElementInfo = adoptNS([[_WKContextMenuElementInfo alloc] init]);
167
168     if (m_uiDelegate.m_delegateMethods.webViewContextMenuForElement)
169         return [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView contextMenu:menu forElement:contextMenuElementInfo.get()];
170
171     return [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView contextMenu:menu forElement:contextMenuElementInfo.get() userInfo:static_cast<id <NSSecureCoding>>(userInfo->wrapper())];
172 }
173 #endif
174
175 UIDelegate::UIClient::UIClient(UIDelegate& uiDelegate)
176     : m_uiDelegate(uiDelegate)
177 {
178 }
179
180 UIDelegate::UIClient::~UIClient()
181 {
182 }
183
184 RefPtr<WebKit::WebPageProxy> UIDelegate::UIClient::createNewPageCommon(WebKit::WebPageProxy* page, API::FrameInfo& sourceFrameInfo, WebCore::ResourceRequest&& request, const WebCore::WindowFeatures& windowFeatures, WebKit::NavigationActionData&& navigationActionData, WTF::Function<void(RefPtr<WebKit::WebPageProxy>&&)>&& completionHandler)
185 {
186     auto delegate = m_uiDelegate.m_delegate.get();
187     ASSERT(delegate);
188
189     auto configuration = adoptNS([m_uiDelegate.m_webView->_configuration copy]);
190     [configuration _setRelatedWebView:m_uiDelegate.m_webView];
191
192     auto userInitiatedActivity = page->process().userInitiatedActivity(navigationActionData.userGestureTokenIdentifier);
193     bool shouldOpenAppLinks = !hostsAreEqual(sourceFrameInfo.request().url(), request.url());
194     auto apiNavigationAction = API::NavigationAction::create(WTFMove(navigationActionData), &sourceFrameInfo, nullptr, WTFMove(request), WebCore::URL(), shouldOpenAppLinks, WTFMove(userInitiatedActivity));
195
196     auto apiWindowFeatures = API::WindowFeatures::create(windowFeatures);
197
198     if (completionHandler) {
199         RefPtr<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:completionHandler:));
200
201         [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView createWebViewWithConfiguration:configuration.get() forNavigationAction:wrapper(apiNavigationAction) windowFeatures:wrapper(apiWindowFeatures) completionHandler:BlockPtr<void (WKWebView *)>::fromCallable([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker), relatedWebView = RetainPtr<WKWebView>(m_uiDelegate.m_webView)](WKWebView *webView) {
202             if (checker->completionHandlerHasBeenCalled())
203                 return;
204             checker->didCallCompletionHandler();
205
206             if (!webView) {
207                 completionHandler(nullptr);
208                 return;
209             }
210
211             if ([webView->_configuration _relatedWebView] != relatedWebView.get())
212                 [NSException raise:NSInternalInconsistencyException format:@"Returned WKWebView was not created with the given configuration."];
213
214             completionHandler(webView->_page.get());
215         }).get()];
216
217         return nullptr;
218     }
219
220     RetainPtr<WKWebView> webView = [delegate webView:m_uiDelegate.m_webView createWebViewWithConfiguration:configuration.get() forNavigationAction:wrapper(apiNavigationAction) windowFeatures:wrapper(apiWindowFeatures)];
221
222     if (!webView)
223         return nullptr;
224
225     if ([webView->_configuration _relatedWebView] != m_uiDelegate.m_webView)
226         [NSException raise:NSInternalInconsistencyException format:@"Returned WKWebView was not created with the given configuration."];
227
228     return webView->_page.get();
229 }
230
231 RefPtr<WebPageProxy> UIDelegate::UIClient::createNewPage(WebPageProxy* page, API::FrameInfo& originatingFrameInfo, WebCore::ResourceRequest&& request, const WebCore::WindowFeatures& windowFeatures, NavigationActionData&& navigationActionData)
232 {
233     if (!m_uiDelegate.m_delegateMethods.webViewCreateWebViewWithConfigurationForNavigationActionWindowFeatures)
234         return nullptr;
235
236     auto delegate = m_uiDelegate.m_delegate.get();
237     if (!delegate)
238         return nullptr;
239
240     return createNewPageCommon(page, originatingFrameInfo, WTFMove(request), windowFeatures, WTFMove(navigationActionData), nullptr);
241 }
242
243 bool UIDelegate::UIClient::canCreateNewPageAsync()
244 {
245     return m_uiDelegate.m_delegateMethods.webViewCreateWebViewWithConfigurationForNavigationActionWindowFeaturesAsync
246         && m_uiDelegate.m_delegate.get();
247 }
248
249 void UIDelegate::UIClient::createNewPageAsync(WebPageProxy* page, API::FrameInfo& originatingFrameInfo, WebCore::ResourceRequest&& request, const WebCore::WindowFeatures& windowFeatures, NavigationActionData&& navigationActionData, WTF::Function<void(RefPtr<WebPageProxy>&&)>&& completionHandler)
250 {
251     ASSERT(canCreateNewPageAsync());
252     ASSERT(m_uiDelegate.m_delegateMethods.webViewCreateWebViewWithConfigurationForNavigationActionWindowFeaturesAsync);
253
254     auto delegate = m_uiDelegate.m_delegate.get();
255     ASSERT(delegate);
256
257     createNewPageCommon(page, originatingFrameInfo, WTFMove(request), windowFeatures, WTFMove(navigationActionData), WTFMove(completionHandler));
258 }
259
260 void UIDelegate::UIClient::runJavaScriptAlert(WebKit::WebPageProxy*, const WTF::String& message, WebKit::WebFrameProxy* webFrameProxy, const WebCore::SecurityOriginData& securityOriginData, Function<void ()>&& completionHandler)
261 {
262     if (!m_uiDelegate.m_delegateMethods.webViewRunJavaScriptAlertPanelWithMessageInitiatedByFrameCompletionHandler) {
263         completionHandler();
264         return;
265     }
266
267     auto delegate = m_uiDelegate.m_delegate.get();
268     if (!delegate) {
269         completionHandler();
270         return;
271     }
272
273     RefPtr<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:));
274     [delegate webView:m_uiDelegate.m_webView runJavaScriptAlertPanelWithMessage:message initiatedByFrame:wrapper(API::FrameInfo::create(*webFrameProxy, securityOriginData.securityOrigin())) completionHandler:BlockPtr<void ()>::fromCallable([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)] {
275         if (checker->completionHandlerHasBeenCalled())
276             return;
277         completionHandler();
278         checker->didCallCompletionHandler();
279     }).get()];
280 }
281
282 void UIDelegate::UIClient::runJavaScriptConfirm(WebKit::WebPageProxy*, const WTF::String& message, WebKit::WebFrameProxy* webFrameProxy, const WebCore::SecurityOriginData& securityOriginData, Function<void (bool)>&& completionHandler)
283 {
284     if (!m_uiDelegate.m_delegateMethods.webViewRunJavaScriptConfirmPanelWithMessageInitiatedByFrameCompletionHandler) {
285         completionHandler(false);
286         return;
287     }
288
289     auto delegate = m_uiDelegate.m_delegate.get();
290     if (!delegate) {
291         completionHandler(false);
292         return;
293     }
294
295     RefPtr<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:));
296     [delegate webView:m_uiDelegate.m_webView runJavaScriptConfirmPanelWithMessage:message initiatedByFrame:wrapper(API::FrameInfo::create(*webFrameProxy, securityOriginData.securityOrigin())) completionHandler:BlockPtr<void (BOOL)>::fromCallable([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)](BOOL result) {
297         if (checker->completionHandlerHasBeenCalled())
298             return;
299         completionHandler(result);
300         checker->didCallCompletionHandler();
301     }).get()];
302 }
303
304 void UIDelegate::UIClient::runJavaScriptPrompt(WebKit::WebPageProxy*, const WTF::String& message, const WTF::String& defaultValue, WebKit::WebFrameProxy* webFrameProxy, const WebCore::SecurityOriginData& securityOriginData, Function<void (const WTF::String&)>&& completionHandler)
305 {
306     if (!m_uiDelegate.m_delegateMethods.webViewRunJavaScriptTextInputPanelWithPromptDefaultTextInitiatedByFrameCompletionHandler) {
307         completionHandler(String());
308         return;
309     }
310
311     auto delegate = m_uiDelegate.m_delegate.get();
312     if (!delegate) {
313         completionHandler(String());
314         return;
315     }
316
317     RefPtr<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:completionHandler:));
318     [delegate webView:m_uiDelegate.m_webView runJavaScriptTextInputPanelWithPrompt:message defaultText:defaultValue initiatedByFrame:wrapper(API::FrameInfo::create(*webFrameProxy, securityOriginData.securityOrigin())) completionHandler:BlockPtr<void (NSString *)>::fromCallable([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)](NSString *result) {
319         if (checker->completionHandlerHasBeenCalled())
320             return;
321         completionHandler(result);
322         checker->didCallCompletionHandler();
323     }).get()];
324 }
325
326 bool UIDelegate::UIClient::canRunBeforeUnloadConfirmPanel() const
327 {
328     return m_uiDelegate.m_delegateMethods.webViewRunBeforeUnloadConfirmPanelWithMessageInitiatedByFrameCompletionHandler;
329 }
330
331 void UIDelegate::UIClient::runBeforeUnloadConfirmPanel(WebKit::WebPageProxy*, const WTF::String& message, WebKit::WebFrameProxy* webFrameProxy, const WebCore::SecurityOriginData& securityOriginData, Function<void (bool)>&& completionHandler)
332 {
333     if (!m_uiDelegate.m_delegateMethods.webViewRunBeforeUnloadConfirmPanelWithMessageInitiatedByFrameCompletionHandler) {
334         completionHandler(false);
335         return;
336     }
337
338     auto delegate = m_uiDelegate.m_delegate.get();
339     if (!delegate) {
340         completionHandler(false);
341         return;
342     }
343
344     RefPtr<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:completionHandler:));
345     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView runBeforeUnloadConfirmPanelWithMessage:message initiatedByFrame:wrapper(API::FrameInfo::create(*webFrameProxy, securityOriginData.securityOrigin())) completionHandler:BlockPtr<void (BOOL)>::fromCallable([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)](BOOL result) {
346         if (checker->completionHandlerHasBeenCalled())
347             return;
348         completionHandler(result);
349         checker->didCallCompletionHandler();
350     }).get()];
351 }
352
353 void UIDelegate::UIClient::exceededDatabaseQuota(WebPageProxy*, WebFrameProxy*, API::SecurityOrigin* securityOrigin, const WTF::String& databaseName, const WTF::String& displayName, unsigned long long currentQuota, unsigned long long currentOriginUsage, unsigned long long currentUsage, unsigned long long expectedUsage, Function<void (unsigned long long)>&& completionHandler)
354 {
355     if (!m_uiDelegate.m_delegateMethods.webViewDecideDatabaseQuotaForSecurityOriginCurrentQuotaCurrentOriginUsageCurrentDatabaseUsageExpectedUsageDecisionHandler) {
356
357         // Use 50 MB as the default database quota.
358         unsigned long long defaultPerOriginDatabaseQuota = 50 * 1024 * 1024;
359
360         completionHandler(defaultPerOriginDatabaseQuota);
361         return;
362     }
363
364     auto delegate = m_uiDelegate.m_delegate.get();
365     if (!delegate) {
366         completionHandler(currentQuota);
367         return;
368     }
369
370     ASSERT(securityOrigin);
371     RefPtr<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:decideDatabaseQuotaForSecurityOrigin:currentQuota:currentOriginUsage:currentDatabaseUsage:expectedUsage:decisionHandler:));
372     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView decideDatabaseQuotaForSecurityOrigin:wrapper(*securityOrigin) currentQuota:currentQuota currentOriginUsage:currentOriginUsage currentDatabaseUsage:currentUsage expectedUsage:expectedUsage decisionHandler:BlockPtr<void (unsigned long long newQuota)>::fromCallable([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)](unsigned long long newQuota) {
373         if (checker->completionHandlerHasBeenCalled())
374             return;
375         checker->didCallCompletionHandler();
376         completionHandler(newQuota);
377     }).get()];
378 }
379
380 #if PLATFORM(MAC)
381 static inline _WKFocusDirection toWKFocusDirection(WKFocusDirection direction)
382 {
383     switch (direction) {
384     case kWKFocusDirectionBackward:
385         return _WKFocusDirectionBackward;
386     case kWKFocusDirectionForward:
387         return _WKFocusDirectionForward;
388     }
389     ASSERT_NOT_REACHED();
390     return _WKFocusDirectionForward;
391 }
392
393 void UIDelegate::UIClient::takeFocus(WebKit::WebPageProxy*, WKFocusDirection direction)
394 {
395     if (!m_uiDelegate.m_delegateMethods.webViewTakeFocus)
396         return;
397     
398     auto delegate = m_uiDelegate.m_delegate.get();
399     if (!delegate)
400         return;
401     
402     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView takeFocus:toWKFocusDirection(direction)];
403 }
404
405 void UIDelegate::UIClient::focus(WebKit::WebPageProxy*)
406 {
407     if (!m_uiDelegate.m_delegateMethods.focusWebView)
408         return;
409     
410     auto delegate = m_uiDelegate.m_delegate.get();
411     if (!delegate)
412         return;
413     
414     [(id <WKUIDelegatePrivate>)delegate _focusWebView:m_uiDelegate.m_webView];
415 }
416
417 void UIDelegate::UIClient::unfocus(WebKit::WebPageProxy*)
418 {
419     if (!m_uiDelegate.m_delegateMethods.unfocusWebView)
420         return;
421     
422     auto delegate = m_uiDelegate.m_delegate.get();
423     if (!delegate)
424         return;
425     
426     [(id <WKUIDelegatePrivate>)delegate _unfocusWebView:m_uiDelegate.m_webView];
427 }
428
429 void UIDelegate::UIClient::didNotHandleWheelEvent(WebKit::WebPageProxy*, const WebKit::NativeWebWheelEvent& event)
430 {
431     if (!m_uiDelegate.m_delegateMethods.webViewDidNotHandleWheelEvent)
432         return;
433     
434     auto delegate = m_uiDelegate.m_delegate.get();
435     if (!delegate)
436         return;
437     
438     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView didNotHandleWheelEvent:event.nativeEvent()];
439 }
440
441 static _WKAutoplayEventFlags toWKAutoplayEventFlags(OptionSet<WebCore::AutoplayEventFlags> flags)
442 {
443     _WKAutoplayEventFlags wkFlags = _WKAutoplayEventFlagsNone;
444     if (flags.contains(WebCore::AutoplayEventFlags::HasAudio))
445         wkFlags |= _WKAutoplayEventFlagsHasAudio;
446     
447     return wkFlags;
448 }
449
450 static _WKAutoplayEvent toWKAutoplayEvent(WebCore::AutoplayEvent event)
451 {
452     switch (event) {
453     case WebCore::AutoplayEvent::DidPreventMediaFromPlaying:
454         return _WKAutoplayEventDidPreventFromAutoplaying;
455     case WebCore::AutoplayEvent::DidPlayMediaPreventedFromPlaying:
456         return _WKAutoplayEventDidPlayMediaPreventedFromAutoplaying;
457     case WebCore::AutoplayEvent::DidAutoplayMediaPastThresholdWithoutUserInterference:
458         return _WKAutoplayEventDidAutoplayMediaPastThresholdWithoutUserInterference;
459     case WebCore::AutoplayEvent::UserDidInterfereWithPlayback:
460         return _WKAutoplayEventUserDidInterfereWithPlayback;
461     }
462     ASSERT_NOT_REACHED();
463     return _WKAutoplayEventDidPlayMediaPreventedFromAutoplaying;
464 }
465
466 void UIDelegate::UIClient::handleAutoplayEvent(WebKit::WebPageProxy&, WebCore::AutoplayEvent event, OptionSet<WebCore::AutoplayEventFlags> flags)
467 {
468     if (!m_uiDelegate.m_delegateMethods.webViewHandleAutoplayEventWithFlags)
469         return;
470     
471     auto delegate = m_uiDelegate.m_delegate.get();
472     if (!delegate)
473         return;
474     
475     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView handleAutoplayEvent:toWKAutoplayEvent(event) withFlags:toWKAutoplayEventFlags(flags)];
476 }
477
478 void UIDelegate::UIClient::showPage(WebPageProxy*)
479 {
480     if (!m_uiDelegate.m_delegateMethods.showWebView)
481         return;
482
483     auto delegate = m_uiDelegate.m_delegate.get();
484     if (!delegate)
485         return;
486     
487     [(id <WKUIDelegatePrivate>)delegate _showWebView:m_uiDelegate.m_webView];
488 }
489
490 bool UIDelegate::UIClient::runOpenPanel(WebPageProxy*, WebFrameProxy* webFrameProxy, const WebCore::SecurityOriginData& securityOriginData, API::OpenPanelParameters* openPanelParameters, WebOpenPanelResultListenerProxy* listener)
491 {
492     if (!m_uiDelegate.m_delegateMethods.webViewRunOpenPanelWithParametersInitiatedByFrameCompletionHandler)
493         return false;
494
495     auto delegate = m_uiDelegate.m_delegate.get();
496     if (!delegate)
497         return false;
498
499     auto frame = API::FrameInfo::create(*webFrameProxy, securityOriginData.securityOrigin());
500     RefPtr<WebOpenPanelResultListenerProxy> resultListener = listener;
501
502     RefPtr<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(webView:runOpenPanelWithParameters:initiatedByFrame:completionHandler:));
503
504     [delegate webView:m_uiDelegate.m_webView runOpenPanelWithParameters:wrapper(*openPanelParameters) initiatedByFrame:wrapper(frame) completionHandler:[checker, resultListener](NSArray *URLs) {
505         if (checker->completionHandlerHasBeenCalled())
506             return;
507         checker->didCallCompletionHandler();
508
509         if (!URLs) {
510             resultListener->cancel();
511             return;
512         }
513
514         Vector<String> filenames;
515         for (NSURL *url in URLs)
516             filenames.append(url.path);
517
518         resultListener->chooseFiles(filenames);
519     }];
520
521     return true;
522 }
523 #endif
524
525 static void requestUserMediaAuthorizationForDevices(const WebKit::WebFrameProxy& frame, WebKit::UserMediaPermissionRequestProxy& request, id <WKUIDelegatePrivate> delegate, WKWebView& webView)
526 {
527     auto decisionHandler = BlockPtr<void(BOOL)>::fromCallable([protectedRequest = makeRef(request)](BOOL authorized) {
528         if (!authorized) {
529             protectedRequest->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
530             return;
531         }
532         const String& videoDeviceUID = protectedRequest->requiresVideo() ? protectedRequest->videoDeviceUIDs().first() : String();
533         const String& audioDeviceUID = protectedRequest->requiresAudio() ? protectedRequest->audioDeviceUIDs().first() : String();
534         protectedRequest->allow(audioDeviceUID, videoDeviceUID);
535     });
536
537     const WebFrameProxy* mainFrame = frame.page()->mainFrame();
538     WebCore::URL requestFrameURL(WebCore::URL(), frame.url());
539     WebCore::URL mainFrameURL(WebCore::URL(), mainFrame->url());
540
541     _WKCaptureDevices devices = 0;
542     if (request.requiresAudio())
543         devices |= _WKCaptureDeviceMicrophone;
544     if (request.requiresVideo())
545         devices |= _WKCaptureDeviceCamera;
546
547     auto protectedWebView = RetainPtr<WKWebView>(&webView);
548     [delegate _webView:protectedWebView.get() requestUserMediaAuthorizationForDevices:devices url:requestFrameURL mainFrameURL:mainFrameURL decisionHandler:decisionHandler.get()];
549 }
550
551 bool UIDelegate::UIClient::decidePolicyForUserMediaPermissionRequest(WebKit::WebPageProxy& page, WebKit::WebFrameProxy& frame, API::SecurityOrigin& userMediaOrigin, API::SecurityOrigin& topLevelOrigin, WebKit::UserMediaPermissionRequestProxy& request)
552 {
553     auto delegate = m_uiDelegate.m_delegate.get();
554     if (!delegate || !m_uiDelegate.m_delegateMethods.webViewRequestUserMediaAuthorizationForDevicesURLMainFrameURLDecisionHandler) {
555         request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::UserMediaDisabled);
556         return true;
557     }
558
559     bool requiresAudio = request.requiresAudio();
560     bool requiresVideo = request.requiresVideo();
561     if (!requiresAudio && !requiresVideo) {
562         request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::NoConstraints);
563         return true;
564     }
565
566 #if PLATFORM(IOS)
567     auto requestCameraAuthorization = BlockPtr<void()>::fromCallable([this, &frame, protectedRequest = makeRef(request), webView = RetainPtr<WKWebView>(m_uiDelegate.m_webView)]() {
568
569         if (!protectedRequest->requiresVideo()) {
570             requestUserMediaAuthorizationForDevices(frame, protectedRequest, (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get(), *webView.get());
571             return;
572         }
573         AVAuthorizationStatus cameraAuthorizationStatus = [getAVCaptureDeviceClass() authorizationStatusForMediaType:getAVMediaTypeVideo()];
574         switch (cameraAuthorizationStatus) {
575         case AVAuthorizationStatusAuthorized:
576             requestUserMediaAuthorizationForDevices(frame, protectedRequest, (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get(), *webView.get());
577             break;
578         case AVAuthorizationStatusDenied:
579         case AVAuthorizationStatusRestricted:
580             protectedRequest->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
581             return;
582         case AVAuthorizationStatusNotDetermined:
583             auto decisionHandler = BlockPtr<void(BOOL)>::fromCallable([this, &frame, protectedRequest = makeRef(protectedRequest.get()), webView = RetainPtr<WKWebView>(m_uiDelegate.m_webView)](BOOL authorized) {
584                 if (!authorized) {
585                     protectedRequest->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
586                     return;
587                 }
588                 requestUserMediaAuthorizationForDevices(frame, protectedRequest, (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get(), *webView.get());
589             });
590
591             [getAVCaptureDeviceClass() requestAccessForMediaType:getAVMediaTypeVideo() completionHandler:decisionHandler.get()];
592             break;
593         }
594     });
595
596     if (requiresAudio) {
597         AVAuthorizationStatus microphoneAuthorizationStatus = [getAVCaptureDeviceClass() authorizationStatusForMediaType:getAVMediaTypeAudio()];
598         switch (microphoneAuthorizationStatus) {
599         case AVAuthorizationStatusAuthorized:
600             requestCameraAuthorization();
601             break;
602         case AVAuthorizationStatusDenied:
603         case AVAuthorizationStatusRestricted:
604             request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
605             return true;
606         case AVAuthorizationStatusNotDetermined:
607             auto decisionHandler = BlockPtr<void(BOOL)>::fromCallable([protectedRequest = makeRef(request), requestCameraAuthorization](BOOL authorized) {
608                 if (!authorized) {
609                     protectedRequest->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
610                     return;
611                 }
612                 requestCameraAuthorization();
613             });
614
615             [getAVCaptureDeviceClass() requestAccessForMediaType:getAVMediaTypeAudio() completionHandler:decisionHandler.get()];
616             break;
617         }
618     } else
619         requestCameraAuthorization();
620 #else
621     requestUserMediaAuthorizationForDevices(frame, request, (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get(), *m_uiDelegate.m_webView);
622 #endif
623
624     return true;
625 }
626
627 bool UIDelegate::UIClient::checkUserMediaPermissionForOrigin(WebKit::WebPageProxy& page, WebKit::WebFrameProxy& frame, API::SecurityOrigin& userMediaOrigin, API::SecurityOrigin& topLevelOrigin, WebKit::UserMediaPermissionCheckProxy& request)
628 {
629     auto delegate = m_uiDelegate.m_delegate.get();
630     if (!delegate || !m_uiDelegate.m_delegateMethods.webViewCheckUserMediaPermissionForURLMainFrameURLFrameIdentifierDecisionHandler) {
631         request.setUserMediaAccessInfo(String(), false);
632         return true;
633     }
634
635     WKWebView *webView = m_uiDelegate.m_webView;
636     const WebFrameProxy* mainFrame = frame.page()->mainFrame();
637     WebCore::URL requestFrameURL(WebCore::URL(), frame.url());
638     WebCore::URL mainFrameURL(WebCore::URL(), mainFrame->url());
639
640     auto decisionHandler = BlockPtr<void(NSString *, BOOL)>::fromCallable([protectedRequest = makeRef(request)](NSString *salt, BOOL authorized) {
641         protectedRequest->setUserMediaAccessInfo(String(salt), authorized);
642     });
643
644     [(id <WKUIDelegatePrivate>)delegate _webView:webView checkUserMediaPermissionForURL:requestFrameURL mainFrameURL:mainFrameURL frameIdentifier:frame.frameID() decisionHandler:decisionHandler.get()];
645
646     return true;
647 }
648
649 void UIDelegate::UIClient::mediaCaptureStateDidChange(WebCore::MediaProducer::MediaStateFlags state)
650 {
651     WKWebView *webView = m_uiDelegate.m_webView;
652     auto delegate = m_uiDelegate.m_delegate.get();
653     if (!delegate || !m_uiDelegate.m_delegateMethods.webViewMediaCaptureStateDidChange)
654         return;
655
656     _WKMediaCaptureState mediaCaptureState = _WKMediaCaptureStateNone;
657     if (state & WebCore::MediaProducer::HasActiveAudioCaptureDevice)
658         mediaCaptureState |= _WKMediaCaptureStateActiveMicrophone;
659     if (state & WebCore::MediaProducer::HasActiveVideoCaptureDevice)
660         mediaCaptureState |= _WKMediaCaptureStateActiveCamera;
661     if (state & WebCore::MediaProducer::HasMutedAudioCaptureDevice)
662         mediaCaptureState |= _WKMediaCaptureStateMutedMicrophone;
663     if (state & WebCore::MediaProducer::HasMutedVideoCaptureDevice)
664         mediaCaptureState |= _WKMediaCaptureStateMutedCamera;
665
666     [(id <WKUIDelegatePrivate>)delegate _webView:webView mediaCaptureStateDidChange:mediaCaptureState];
667 }
668
669 void UIDelegate::UIClient::reachedApplicationCacheOriginQuota(WebPageProxy*, const WebCore::SecurityOrigin& securityOrigin, uint64_t currentQuota, uint64_t totalBytesNeeded, Function<void (unsigned long long)>&& completionHandler)
670 {
671     if (!m_uiDelegate.m_delegateMethods.webViewDecideWebApplicationCacheQuotaForSecurityOriginCurrentQuotaTotalBytesNeeded) {
672         completionHandler(currentQuota);
673         return;
674     }
675
676     auto delegate = m_uiDelegate.m_delegate.get();
677     if (!delegate) {
678         completionHandler(currentQuota);
679         return;
680     }
681
682     RefPtr<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:decideWebApplicationCacheQuotaForSecurityOrigin:currentQuota:totalBytesNeeded:decisionHandler:));
683     RefPtr<API::SecurityOrigin> apiOrigin = API::SecurityOrigin::create(securityOrigin);
684     
685     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView decideWebApplicationCacheQuotaForSecurityOrigin:wrapper(*apiOrigin) currentQuota:currentQuota totalBytesNeeded:totalBytesNeeded decisionHandler:BlockPtr<void (unsigned long long)>::fromCallable([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)](unsigned long long newQuota) {
686         if (checker->completionHandlerHasBeenCalled())
687             return;
688         checker->didCallCompletionHandler();
689         completionHandler(newQuota);
690     }).get()];
691 }
692
693 void UIDelegate::UIClient::printFrame(WebKit::WebPageProxy*, WebKit::WebFrameProxy* webFrameProxy)
694 {
695     ASSERT_ARG(webFrameProxy, webFrameProxy);
696
697     if (!m_uiDelegate.m_delegateMethods.webViewPrintFrame)
698         return;
699
700     auto delegate = m_uiDelegate.m_delegate.get();
701     if (!delegate)
702         return;
703
704     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView printFrame:wrapper(API::FrameHandle::create(webFrameProxy->frameID()))];
705 }
706
707 void UIDelegate::UIClient::close(WebKit::WebPageProxy*)
708 {
709     if (m_uiDelegate.m_delegateMethods.webViewClose) {
710         auto delegate = m_uiDelegate.m_delegate.get();
711         if (!delegate)
712             return;
713
714         [(id <WKUIDelegatePrivate>)delegate _webViewClose:m_uiDelegate.m_webView];
715         return;
716     }
717
718     if (!m_uiDelegate.m_delegateMethods.webViewDidClose)
719         return;
720
721     auto delegate = m_uiDelegate.m_delegate.get();
722     if (!delegate)
723         return;
724
725     [delegate webViewDidClose:m_uiDelegate.m_webView];
726 }
727
728 void UIDelegate::UIClient::fullscreenMayReturnToInline(WebKit::WebPageProxy*)
729 {
730     if (!m_uiDelegate.m_delegateMethods.webViewFullscreenMayReturnToInline)
731         return;
732     
733     auto delegate = m_uiDelegate.m_delegate.get();
734     if (!delegate)
735         return;
736     
737     [(id <WKUIDelegatePrivate>)delegate _webViewFullscreenMayReturnToInline:m_uiDelegate.m_webView];
738 }
739
740 void UIDelegate::UIClient::didEnterFullscreen(WebKit::WebPageProxy*)
741 {
742     if (!m_uiDelegate.m_delegateMethods.webViewDidEnterFullscreen)
743         return;
744
745     auto delegate = m_uiDelegate.m_delegate.get();
746     if (!delegate)
747         return;
748
749     [(id <WKUIDelegatePrivate>)delegate _webViewDidEnterFullscreen:m_uiDelegate.m_webView];
750 }
751
752 void UIDelegate::UIClient::didExitFullscreen(WebKit::WebPageProxy*)
753 {
754     if (!m_uiDelegate.m_delegateMethods.webViewDidExitFullscreen)
755         return;
756
757     auto delegate = m_uiDelegate.m_delegate.get();
758     if (!delegate)
759         return;
760
761     [(id <WKUIDelegatePrivate>)delegate _webViewDidExitFullscreen:m_uiDelegate.m_webView];
762 }
763     
764 #if PLATFORM(IOS)
765 #if HAVE(APP_LINKS)
766 bool UIDelegate::UIClient::shouldIncludeAppLinkActionsForElement(_WKActivatedElementInfo *elementInfo)
767 {
768     if (!m_uiDelegate.m_delegateMethods.webViewShouldIncludeAppLinkActionsForElement)
769         return true;
770
771     auto delegate = m_uiDelegate.m_delegate.get();
772     if (!delegate)
773         return true;
774
775     return [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView shouldIncludeAppLinkActionsForElement:elementInfo];
776 }
777 #endif
778
779 RetainPtr<NSArray> UIDelegate::UIClient::actionsForElement(_WKActivatedElementInfo *elementInfo, RetainPtr<NSArray> defaultActions)
780 {
781     if (!m_uiDelegate.m_delegateMethods.webViewActionsForElementDefaultActions)
782         return defaultActions;
783
784     auto delegate = m_uiDelegate.m_delegate.get();
785     if (!delegate)
786         return defaultActions;
787
788     return [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView actionsForElement:elementInfo defaultActions:defaultActions.get()];
789 }
790
791 void UIDelegate::UIClient::didNotHandleTapAsClick(const WebCore::IntPoint& point)
792 {
793     if (!m_uiDelegate.m_delegateMethods.webViewDidNotHandleTapAsClickAtPoint)
794         return;
795
796     auto delegate = m_uiDelegate.m_delegate.get();
797     if (!delegate)
798         return;
799
800     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webView:m_uiDelegate.m_webView didNotHandleTapAsClickAtPoint:point];
801 }
802
803 UIViewController *UIDelegate::UIClient::presentingViewController()
804 {
805     if (!m_uiDelegate.m_delegateMethods.presentingViewControllerForWebView)
806         return nullptr;
807
808     auto delegate = m_uiDelegate.m_delegate.get();
809     if (!delegate)
810         return nullptr;
811
812     return [static_cast<id <WKUIDelegatePrivate>>(delegate) _presentingViewControllerForWebView:m_uiDelegate.m_webView];
813 }
814
815 #endif
816
817 NSDictionary *UIDelegate::UIClient::dataDetectionContext()
818 {
819     if (!m_uiDelegate.m_delegateMethods.dataDetectionContextForWebView)
820         return nullptr;
821
822     auto delegate = m_uiDelegate.m_delegate.get();
823     if (!delegate)
824         return nullptr;
825
826     return [static_cast<id <WKUIDelegatePrivate>>(delegate) _dataDetectionContextForWebView:m_uiDelegate.m_webView];
827 }
828
829 #if ENABLE(POINTER_LOCK)
830
831 void UIDelegate::UIClient::requestPointerLock(WebKit::WebPageProxy*)
832 {
833     if (!m_uiDelegate.m_delegateMethods.webViewRequestPointerLock)
834         return;
835
836     auto delegate = m_uiDelegate.m_delegate.get();
837     if (!delegate)
838         return;
839
840     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webViewRequestPointerLock:m_uiDelegate.m_webView];
841 }
842
843 void UIDelegate::UIClient::didLosePointerLock(WebKit::WebPageProxy*)
844 {
845     if (!m_uiDelegate.m_delegateMethods.webViewDidLosePointerLock)
846         return;
847
848     auto delegate = m_uiDelegate.m_delegate.get();
849     if (!delegate)
850         return;
851
852     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webViewDidLosePointerLock:m_uiDelegate.m_webView];
853 }
854
855 #endif
856     
857 void UIDelegate::UIClient::hasVideoInPictureInPictureDidChange(WebKit::WebPageProxy*, bool hasVideoInPictureInPicture)
858 {
859     if (!m_uiDelegate.m_delegateMethods.webViewHasVideoInPictureInPictureDidChange)
860         return;
861     
862     auto delegate = m_uiDelegate.m_delegate.get();
863     if (!delegate)
864         return;
865     
866     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webView:m_uiDelegate.m_webView hasVideoInPictureInPictureDidChange:hasVideoInPictureInPicture];
867 }
868
869 void UIDelegate::UIClient::imageOrMediaDocumentSizeChanged(const WebCore::IntSize& newSize)
870 {
871     if (!m_uiDelegate.m_delegateMethods.webViewImageOrMediaDocumentSizeChanged)
872         return;
873
874     auto delegate = m_uiDelegate.m_delegate.get();
875     if (!delegate)
876         return;
877
878     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webView:m_uiDelegate.m_webView imageOrMediaDocumentSizeChanged:newSize];
879 }
880
881 } // namespace WebKit
882
883 #endif // WK_API_ENABLED