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