Unreviewed, rolling out r242697.
[WebKit-https.git] / Source / WebKit / UIProcess / Cocoa / UIDelegate.mm
1 /*
2  * Copyright (C) 2014-2018 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 #import "APIFrameInfo.h"
30 #import "APIHitTestResult.h"
31 #import "CompletionHandlerCallChecker.h"
32 #import "MediaCaptureUtilities.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 "WKNSDictionary.h"
40 #import "WKNavigationActionInternal.h"
41 #import "WKOpenPanelParametersInternal.h"
42 #import "WKSecurityOriginInternal.h"
43 #import "WKUIDelegatePrivate.h"
44 #import "WKWebViewConfigurationInternal.h"
45 #import "WKWebViewInternal.h"
46 #import "WKWindowFeaturesInternal.h"
47 #import "WebEventFactory.h"
48 #import "WebOpenPanelResultListenerProxy.h"
49 #import "WebProcessProxy.h"
50 #import "_WKContextMenuElementInfo.h"
51 #import "_WKFrameHandleInternal.h"
52 #import "_WKHitTestResultInternal.h"
53 #import <WebCore/FontAttributes.h>
54 #import <WebCore/SecurityOriginData.h>
55 #import <wtf/BlockPtr.h>
56 #import <wtf/URL.h>
57
58 #if HAVE(AUTHORIZATION_STATUS_FOR_MEDIA_TYPE)
59 #import <AVFoundation/AVCaptureDevice.h>
60 #import <AVFoundation/AVMediaFormat.h>
61 #import <wtf/SoftLinking.h>
62
63 SOFT_LINK_FRAMEWORK(AVFoundation);
64 SOFT_LINK_CLASS(AVFoundation, AVCaptureDevice);
65 SOFT_LINK_CONSTANT(AVFoundation, AVMediaTypeAudio, NSString *);
66 SOFT_LINK_CONSTANT(AVFoundation, AVMediaTypeVideo, NSString *);
67 #endif
68
69 namespace WebKit {
70
71 UIDelegate::UIDelegate(WKWebView *webView)
72     : m_webView(webView)
73 {
74 }
75
76 UIDelegate::~UIDelegate()
77 {
78 }
79
80 #if ENABLE(CONTEXT_MENUS)
81 std::unique_ptr<API::ContextMenuClient> UIDelegate::createContextMenuClient()
82 {
83     return std::make_unique<ContextMenuClient>(*this);
84 }
85 #endif
86
87 std::unique_ptr<API::UIClient> UIDelegate::createUIClient()
88 {
89     return std::make_unique<UIClient>(*this);
90 }
91
92 RetainPtr<id <WKUIDelegate> > UIDelegate::delegate()
93 {
94     return m_delegate.get();
95 }
96
97 void UIDelegate::setDelegate(id <WKUIDelegate> delegate)
98 {
99     m_delegate = delegate;
100
101     m_delegateMethods.webViewCreateWebViewWithConfigurationForNavigationActionWindowFeatures = [delegate respondsToSelector:@selector(webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:)];
102     m_delegateMethods.webViewCreateWebViewWithConfigurationForNavigationActionWindowFeaturesAsync = [delegate respondsToSelector:@selector(_webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:completionHandler:)];
103     m_delegateMethods.webViewRunJavaScriptAlertPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:)];
104     m_delegateMethods.webViewRunJavaScriptConfirmPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:)];
105     m_delegateMethods.webViewRunJavaScriptTextInputPanelWithPromptDefaultTextInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:completionHandler:)];
106     m_delegateMethods.webViewRequestStorageAccessPanelForTopPrivatelyControlledDomainUnderFirstPartyTopPrivatelyControlledDomainCompletionHandler = [delegate respondsToSelector:@selector(_webView:requestStorageAccessPanelForDomain:underCurrentDomain:completionHandler:)];
107     m_delegateMethods.webViewRunBeforeUnloadConfirmPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(_webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:completionHandler:)];
108     m_delegateMethods.webViewRequestGeolocationPermissionForFrameDecisionHandler = [delegate respondsToSelector:@selector(_webView:requestGeolocationPermissionForFrame:decisionHandler:)];
109     m_delegateMethods.webViewDidResignInputElementStrongPasswordAppearanceWithUserInfo = [delegate respondsToSelector:@selector(_webView:didResignInputElementStrongPasswordAppearanceWithUserInfo:)];
110     m_delegateMethods.webViewTakeFocus = [delegate respondsToSelector:@selector(_webView:takeFocus:)];
111
112 #if PLATFORM(MAC)
113     m_delegateMethods.showWebView = [delegate respondsToSelector:@selector(_showWebView:)];
114     m_delegateMethods.focusWebView = [delegate respondsToSelector:@selector(_focusWebView:)];
115     m_delegateMethods.unfocusWebView = [delegate respondsToSelector:@selector(_unfocusWebView:)];
116     m_delegateMethods.webViewRunModal = [delegate respondsToSelector:@selector(_webViewRunModal:)];
117     m_delegateMethods.webViewDidScroll = [delegate respondsToSelector:@selector(_webViewDidScroll:)];
118     m_delegateMethods.webViewGetToolbarsAreVisibleWithCompletionHandler = [delegate respondsToSelector:@selector(_webView:getToolbarsAreVisibleWithCompletionHandler:)];
119     m_delegateMethods.webViewDidNotHandleWheelEvent = [delegate respondsToSelector:@selector(_webView:didNotHandleWheelEvent:)];
120     m_delegateMethods.webViewSetResizable = [delegate respondsToSelector:@selector(_webView:setResizable:)];
121     m_delegateMethods.webViewGetWindowFrameWithCompletionHandler = [delegate respondsToSelector:@selector(_webView:getWindowFrameWithCompletionHandler:)];
122     m_delegateMethods.webViewSetWindowFrame = [delegate respondsToSelector:@selector(_webView:setWindowFrame:)];
123     m_delegateMethods.webViewUnavailablePlugInButtonClicked = [delegate respondsToSelector:@selector(_webView:unavailablePlugInButtonClickedWithReason:plugInInfo:)];
124     m_delegateMethods.webViewHandleAutoplayEventWithFlags = [delegate respondsToSelector:@selector(_webView:handleAutoplayEvent:withFlags:)];
125     m_delegateMethods.webViewDidClickAutoFillButtonWithUserInfo = [delegate respondsToSelector:@selector(_webView:didClickAutoFillButtonWithUserInfo:)];
126     m_delegateMethods.webViewDrawHeaderInRectForPageWithTitleURL = [delegate respondsToSelector:@selector(_webView:drawHeaderInRect:forPageWithTitle:URL:)];
127     m_delegateMethods.webViewDrawFooterInRectForPageWithTitleURL = [delegate respondsToSelector:@selector(_webView:drawFooterInRect:forPageWithTitle:URL:)];
128     m_delegateMethods.webViewHeaderHeight = [delegate respondsToSelector:@selector(_webViewHeaderHeight:)];
129     m_delegateMethods.webViewFooterHeight = [delegate respondsToSelector:@selector(_webViewFooterHeight:)];
130     m_delegateMethods.webViewMouseDidMoveOverElementWithFlagsUserInfo = [delegate respondsToSelector:@selector(_webView:mouseDidMoveOverElement:withFlags:userInfo:)];
131     m_delegateMethods.webViewDidExceedBackgroundResourceLimitWhileInForeground = [delegate respondsToSelector:@selector(_webView:didExceedBackgroundResourceLimitWhileInForeground:)];
132     m_delegateMethods.webViewSaveDataToFileSuggestedFilenameMimeTypeOriginatingURL = [delegate respondsToSelector:@selector(_webView:saveDataToFile:suggestedFilename:mimeType:originatingURL:)];
133     m_delegateMethods.webViewRunOpenPanelWithParametersInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runOpenPanelWithParameters:initiatedByFrame:completionHandler:)];
134     m_delegateMethods.webViewRequestNotificationPermissionForSecurityOriginDecisionHandler = [delegate respondsToSelector:@selector(_webView:requestNotificationPermissionForSecurityOrigin:decisionHandler:)];
135 #endif
136 #if ENABLE(DEVICE_ORIENTATION)
137     m_delegateMethods.webViewShouldAllowDeviceOrientationAndMotionAccessForSecurityOriginDecisionHandler = [delegate respondsToSelector:@selector(_webView:shouldAllowDeviceOrientationAndMotionAccessForSecurityOrigin:decisionHandler:)];
138 #endif
139     m_delegateMethods.webViewDecideDatabaseQuotaForSecurityOriginCurrentQuotaCurrentOriginUsageCurrentDatabaseUsageExpectedUsageDecisionHandler = [delegate respondsToSelector:@selector(_webView:decideDatabaseQuotaForSecurityOrigin:currentQuota:currentOriginUsage:currentDatabaseUsage:expectedUsage:decisionHandler:)];
140     m_delegateMethods.webViewDecideDatabaseQuotaForSecurityOriginDatabaseNameDisplayNameCurrentQuotaCurrentOriginUsageCurrentDatabaseUsageExpectedUsageDecisionHandler = [delegate respondsToSelector:@selector(_webView:decideDatabaseQuotaForSecurityOrigin:databaseName:displayName:currentQuota:currentOriginUsage:currentDatabaseUsage:expectedUsage:decisionHandler:)];
141     m_delegateMethods.webViewDecideWebApplicationCacheQuotaForSecurityOriginCurrentQuotaTotalBytesNeeded = [delegate respondsToSelector:@selector(_webView:decideWebApplicationCacheQuotaForSecurityOrigin:currentQuota:totalBytesNeeded:decisionHandler:)];
142     m_delegateMethods.webViewPrintFrame = [delegate respondsToSelector:@selector(_webView:printFrame:)];
143     m_delegateMethods.webViewDidClose = [delegate respondsToSelector:@selector(webViewDidClose:)];
144     m_delegateMethods.webViewClose = [delegate respondsToSelector:@selector(_webViewClose:)];
145     m_delegateMethods.webViewFullscreenMayReturnToInline = [delegate respondsToSelector:@selector(_webViewFullscreenMayReturnToInline:)];
146     m_delegateMethods.webViewDidEnterFullscreen = [delegate respondsToSelector:@selector(_webViewDidEnterFullscreen:)];
147     m_delegateMethods.webViewDidExitFullscreen = [delegate respondsToSelector:@selector(_webViewDidExitFullscreen:)];
148 #if PLATFORM(IOS_FAMILY)
149 #if HAVE(APP_LINKS)
150     m_delegateMethods.webViewShouldIncludeAppLinkActionsForElement = [delegate respondsToSelector:@selector(_webView:shouldIncludeAppLinkActionsForElement:)];
151 #endif
152     m_delegateMethods.webViewActionsForElementDefaultActions = [delegate respondsToSelector:@selector(_webView:actionsForElement:defaultActions:)];
153     m_delegateMethods.webViewDidNotHandleTapAsClickAtPoint = [delegate respondsToSelector:@selector(_webView:didNotHandleTapAsClickAtPoint:)];
154     m_delegateMethods.presentingViewControllerForWebView = [delegate respondsToSelector:@selector(_presentingViewControllerForWebView:)];
155 #endif
156     m_delegateMethods.webViewRequestMediaCaptureAuthorizationForFrameDecisionHandler = [delegate respondsToSelector:@selector(_webView:requestUserMediaAuthorizationForDevices:url:mainFrameURL:decisionHandler:)] || [delegate respondsToSelector:@selector(_webView:requestMediaCaptureAuthorization:decisionHandler:)];
157     m_delegateMethods.webViewIsMediaCaptureAuthorizedForFrameDecisionHandler = [delegate respondsToSelector:@selector(_webView:checkUserMediaPermissionForURL:mainFrameURL:frameIdentifier:decisionHandler:)] || [delegate respondsToSelector:@selector(_webView:includeSensitiveMediaDeviceDetails:)];
158
159     m_delegateMethods.webViewMediaCaptureStateDidChange = [delegate respondsToSelector:@selector(_webView:mediaCaptureStateDidChange:)];
160     m_delegateMethods.webViewDidChangeFontAttributes = [delegate respondsToSelector:@selector(_webView:didChangeFontAttributes:)];
161     m_delegateMethods.dataDetectionContextForWebView = [delegate respondsToSelector:@selector(_dataDetectionContextForWebView:)];
162     m_delegateMethods.webViewImageOrMediaDocumentSizeChanged = [delegate respondsToSelector:@selector(_webView:imageOrMediaDocumentSizeChanged:)];
163
164 #if ENABLE(POINTER_LOCK)
165     m_delegateMethods.webViewRequestPointerLock = [delegate respondsToSelector:@selector(_webViewRequestPointerLock:)];
166     m_delegateMethods.webViewDidRequestPointerLockCompletionHandler = [delegate respondsToSelector:@selector(_webViewDidRequestPointerLock:completionHandler:)];
167     m_delegateMethods.webViewDidLosePointerLock = [delegate respondsToSelector:@selector(_webViewDidLosePointerLock:)];
168 #endif
169 #if ENABLE(CONTEXT_MENUS)
170     m_delegateMethods.webViewContextMenuForElement = [delegate respondsToSelector:@selector(_webView:contextMenu:forElement:)];
171     m_delegateMethods.webViewContextMenuForElementUserInfo = [delegate respondsToSelector:@selector(_webView:contextMenu:forElement:userInfo:)];
172     m_delegateMethods.webViewGetContextMenuFromProposedMenuForElementUserInfoCompletionHandler = [delegate respondsToSelector:@selector(_webView:getContextMenuFromProposedMenu:forElement:userInfo:completionHandler:)];
173 #endif
174     
175     m_delegateMethods.webViewHasVideoInPictureInPictureDidChange = [delegate respondsToSelector:@selector(_webView:hasVideoInPictureInPictureDidChange:)];
176     m_delegateMethods.webViewDidShowSafeBrowsingWarning = [delegate respondsToSelector:@selector(_webViewDidShowSafeBrowsingWarning:)];
177 }
178
179 #if ENABLE(CONTEXT_MENUS)
180 UIDelegate::ContextMenuClient::ContextMenuClient(UIDelegate& uiDelegate)
181     : m_uiDelegate(uiDelegate)
182 {
183 }
184
185 UIDelegate::ContextMenuClient::~ContextMenuClient()
186 {
187 }
188
189 void UIDelegate::ContextMenuClient::menuFromProposedMenu(WebPageProxy&, NSMenu *menu, const WebHitTestResultData&, API::Object* userInfo, CompletionHandler<void(RetainPtr<NSMenu>&&)>&& completionHandler)
190 {
191     if (!m_uiDelegate.m_delegateMethods.webViewContextMenuForElement
192         && !m_uiDelegate.m_delegateMethods.webViewContextMenuForElementUserInfo
193         && !m_uiDelegate.m_delegateMethods.webViewGetContextMenuFromProposedMenuForElementUserInfoCompletionHandler)
194         return completionHandler(menu);
195
196     auto delegate = m_uiDelegate.m_delegate.get();
197     if (!delegate)
198         return completionHandler(menu);
199
200     auto contextMenuElementInfo = adoptNS([[_WKContextMenuElementInfo alloc] init]);
201
202     if (m_uiDelegate.m_delegateMethods.webViewGetContextMenuFromProposedMenuForElementUserInfoCompletionHandler) {
203         auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:getContextMenuFromProposedMenu:forElement:userInfo:completionHandler:));
204         [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView getContextMenuFromProposedMenu:menu forElement:contextMenuElementInfo.get() userInfo:userInfo ? static_cast<id <NSSecureCoding>>(userInfo->wrapper()) : nil completionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)] (NSMenu *menu) mutable {
205             if (checker->completionHandlerHasBeenCalled())
206                 return;
207             checker->didCallCompletionHandler();
208             completionHandler(menu);
209         }).get()];
210         return;
211     }
212     
213     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
214     if (m_uiDelegate.m_delegateMethods.webViewContextMenuForElement)
215         return completionHandler([(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView contextMenu:menu forElement:contextMenuElementInfo.get()]);
216
217     completionHandler([(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView contextMenu:menu forElement:contextMenuElementInfo.get() userInfo:userInfo ? static_cast<id <NSSecureCoding>>(userInfo->wrapper()) : nil]);
218     ALLOW_DEPRECATED_DECLARATIONS_END
219 }
220 #endif
221
222 UIDelegate::UIClient::UIClient(UIDelegate& uiDelegate)
223     : m_uiDelegate(uiDelegate)
224 {
225 }
226
227 UIDelegate::UIClient::~UIClient()
228 {
229 }
230
231 void UIDelegate::UIClient::createNewPage(WebPageProxy& page, Ref<API::FrameInfo>&& sourceFrameInfo, WebCore::ResourceRequest&& request, WebCore::WindowFeatures&& windowFeatures, NavigationActionData&& navigationActionData, CompletionHandler<void(RefPtr<WebPageProxy>&&)>&& completionHandler)
232 {
233     auto delegate = m_uiDelegate.m_delegate.get();
234     ASSERT(delegate);
235
236     auto configuration = adoptNS([m_uiDelegate.m_webView->_configuration copy]);
237     [configuration _setRelatedWebView:m_uiDelegate.m_webView];
238
239     auto userInitiatedActivity = page.process().userInitiatedActivity(navigationActionData.userGestureTokenIdentifier);
240     bool shouldOpenAppLinks = !hostsAreEqual(sourceFrameInfo->request().url(), request.url());
241     auto apiNavigationAction = API::NavigationAction::create(WTFMove(navigationActionData), sourceFrameInfo.ptr(), nullptr, WTF::nullopt, WTFMove(request), URL(), shouldOpenAppLinks, WTFMove(userInitiatedActivity));
242
243     auto apiWindowFeatures = API::WindowFeatures::create(windowFeatures);
244
245     if (m_uiDelegate.m_delegateMethods.webViewCreateWebViewWithConfigurationForNavigationActionWindowFeaturesAsync) {
246         auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:completionHandler:));
247
248         [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView createWebViewWithConfiguration:configuration.get() forNavigationAction:wrapper(apiNavigationAction) windowFeatures:wrapper(apiWindowFeatures) completionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker), relatedWebView = RetainPtr<WKWebView>(m_uiDelegate.m_webView)] (WKWebView *webView) mutable {
249             if (checker->completionHandlerHasBeenCalled())
250                 return;
251             checker->didCallCompletionHandler();
252
253             if (!webView) {
254                 completionHandler(nullptr);
255                 return;
256             }
257
258             if ([webView->_configuration _relatedWebView] != relatedWebView.get())
259                 [NSException raise:NSInternalInconsistencyException format:@"Returned WKWebView was not created with the given configuration."];
260
261             completionHandler(webView->_page.get());
262         }).get()];
263         return;
264     }
265     if (!m_uiDelegate.m_delegateMethods.webViewCreateWebViewWithConfigurationForNavigationActionWindowFeatures)
266         return completionHandler(nullptr);
267
268     RetainPtr<WKWebView> webView = [delegate webView:m_uiDelegate.m_webView createWebViewWithConfiguration:configuration.get() forNavigationAction:wrapper(apiNavigationAction) windowFeatures:wrapper(apiWindowFeatures)];
269     if (!webView)
270         return completionHandler(nullptr);
271
272     if ([webView->_configuration _relatedWebView] != m_uiDelegate.m_webView)
273         [NSException raise:NSInternalInconsistencyException format:@"Returned WKWebView was not created with the given configuration."];
274     completionHandler(webView->_page.get());
275 }
276
277 void UIDelegate::UIClient::runJavaScriptAlert(WebPageProxy*, const WTF::String& message, WebFrameProxy* webFrameProxy, const WebCore::SecurityOriginData& securityOriginData, Function<void()>&& completionHandler)
278 {
279     if (!m_uiDelegate.m_delegateMethods.webViewRunJavaScriptAlertPanelWithMessageInitiatedByFrameCompletionHandler) {
280         completionHandler();
281         return;
282     }
283
284     auto delegate = m_uiDelegate.m_delegate.get();
285     if (!delegate) {
286         completionHandler();
287         return;
288     }
289
290     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:));
291     [delegate webView:m_uiDelegate.m_webView runJavaScriptAlertPanelWithMessage:message initiatedByFrame:wrapper(API::FrameInfo::create(*webFrameProxy, securityOriginData.securityOrigin())) completionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)] {
292         if (checker->completionHandlerHasBeenCalled())
293             return;
294         completionHandler();
295         checker->didCallCompletionHandler();
296     }).get()];
297 }
298
299 void UIDelegate::UIClient::runJavaScriptConfirm(WebPageProxy*, const WTF::String& message, WebFrameProxy* webFrameProxy, const WebCore::SecurityOriginData& securityOriginData, Function<void(bool)>&& completionHandler)
300 {
301     if (!m_uiDelegate.m_delegateMethods.webViewRunJavaScriptConfirmPanelWithMessageInitiatedByFrameCompletionHandler) {
302         completionHandler(false);
303         return;
304     }
305
306     auto delegate = m_uiDelegate.m_delegate.get();
307     if (!delegate) {
308         completionHandler(false);
309         return;
310     }
311
312     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:));
313     [delegate webView:m_uiDelegate.m_webView runJavaScriptConfirmPanelWithMessage:message initiatedByFrame:wrapper(API::FrameInfo::create(*webFrameProxy, securityOriginData.securityOrigin())) completionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)] (BOOL result) mutable {
314         if (checker->completionHandlerHasBeenCalled())
315             return;
316         completionHandler(result);
317         checker->didCallCompletionHandler();
318     }).get()];
319 }
320
321 void UIDelegate::UIClient::runJavaScriptPrompt(WebPageProxy*, const WTF::String& message, const WTF::String& defaultValue, WebFrameProxy* webFrameProxy, const WebCore::SecurityOriginData& securityOriginData, Function<void(const WTF::String&)>&& completionHandler)
322 {
323     if (!m_uiDelegate.m_delegateMethods.webViewRunJavaScriptTextInputPanelWithPromptDefaultTextInitiatedByFrameCompletionHandler) {
324         completionHandler(String());
325         return;
326     }
327
328     auto delegate = m_uiDelegate.m_delegate.get();
329     if (!delegate) {
330         completionHandler(String());
331         return;
332     }
333
334     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:completionHandler:));
335     [delegate webView:m_uiDelegate.m_webView runJavaScriptTextInputPanelWithPrompt:message defaultText:defaultValue initiatedByFrame:wrapper(API::FrameInfo::create(*webFrameProxy, securityOriginData.securityOrigin())) completionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)] (NSString *result) mutable {
336         if (checker->completionHandlerHasBeenCalled())
337             return;
338         completionHandler(result);
339         checker->didCallCompletionHandler();
340     }).get()];
341 }
342
343 void UIDelegate::UIClient::requestStorageAccessConfirm(WebPageProxy&, WebFrameProxy*, const WTF::String& requestingDomain, const WTF::String& currentDomain, CompletionHandler<void(bool)>&& completionHandler)
344 {
345     if (!m_uiDelegate.m_delegateMethods.webViewRequestStorageAccessPanelForTopPrivatelyControlledDomainUnderFirstPartyTopPrivatelyControlledDomainCompletionHandler) {
346         completionHandler(true);
347         return;
348     }
349
350     auto delegate = m_uiDelegate.m_delegate.get();
351     if (!delegate) {
352         completionHandler(true);
353         return;
354     }
355     
356     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:requestStorageAccessPanelForDomain:underCurrentDomain:completionHandler:));
357     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView requestStorageAccessPanelForDomain:requestingDomain underCurrentDomain:currentDomain completionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)] (BOOL result) mutable {
358         if (checker->completionHandlerHasBeenCalled())
359             return;
360         completionHandler(result);
361         checker->didCallCompletionHandler();
362     }).get()];
363 }
364
365 void UIDelegate::UIClient::decidePolicyForGeolocationPermissionRequest(WebKit::WebPageProxy&, WebKit::WebFrameProxy& frame, API::SecurityOrigin& securityOrigin, Function<void(bool)>& completionHandler)
366 {
367     if (!m_uiDelegate.m_delegateMethods.webViewRequestGeolocationPermissionForFrameDecisionHandler)
368         return;
369     
370     auto delegate = m_uiDelegate.m_delegate.get();
371     if (!delegate)
372         return;
373
374     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:requestGeolocationPermissionForFrame:decisionHandler:));
375     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView requestGeolocationPermissionForFrame:wrapper(API::FrameInfo::create(frame, securityOrigin.securityOrigin())) decisionHandler:makeBlockPtr([completionHandler = std::exchange(completionHandler, nullptr), checker = WTFMove(checker)] (BOOL result) mutable {
376         if (checker->completionHandlerHasBeenCalled())
377             return;
378         checker->didCallCompletionHandler();
379         completionHandler(result);
380     }).get()];
381 }
382
383 void UIDelegate::UIClient::didResignInputElementStrongPasswordAppearance(WebPageProxy&, API::Object* userInfo)
384 {
385     if (!m_uiDelegate.m_delegateMethods.webViewDidResignInputElementStrongPasswordAppearanceWithUserInfo)
386         return;
387
388     auto delegate = m_uiDelegate.m_delegate.get();
389     if (!delegate)
390         return;
391
392     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView didResignInputElementStrongPasswordAppearanceWithUserInfo:userInfo ? static_cast<id <NSSecureCoding>>(userInfo->wrapper()) : nil];
393 }
394
395 bool UIDelegate::UIClient::canRunBeforeUnloadConfirmPanel() const
396 {
397     return m_uiDelegate.m_delegateMethods.webViewRunBeforeUnloadConfirmPanelWithMessageInitiatedByFrameCompletionHandler;
398 }
399
400 void UIDelegate::UIClient::runBeforeUnloadConfirmPanel(WebPageProxy*, const WTF::String& message, WebFrameProxy* webFrameProxy, const WebCore::SecurityOriginData& securityOriginData, Function<void(bool)>&& completionHandler)
401 {
402     if (!m_uiDelegate.m_delegateMethods.webViewRunBeforeUnloadConfirmPanelWithMessageInitiatedByFrameCompletionHandler) {
403         completionHandler(false);
404         return;
405     }
406
407     auto delegate = m_uiDelegate.m_delegate.get();
408     if (!delegate) {
409         completionHandler(false);
410         return;
411     }
412
413     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:completionHandler:));
414     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView runBeforeUnloadConfirmPanelWithMessage:message initiatedByFrame:wrapper(API::FrameInfo::create(*webFrameProxy, securityOriginData.securityOrigin())) completionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)] (BOOL result) mutable {
415         if (checker->completionHandlerHasBeenCalled())
416             return;
417         completionHandler(result);
418         checker->didCallCompletionHandler();
419     }).get()];
420 }
421
422 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)
423 {
424     if (!m_uiDelegate.m_delegateMethods.webViewDecideDatabaseQuotaForSecurityOriginCurrentQuotaCurrentOriginUsageCurrentDatabaseUsageExpectedUsageDecisionHandler && !m_uiDelegate.m_delegateMethods.webViewDecideDatabaseQuotaForSecurityOriginDatabaseNameDisplayNameCurrentQuotaCurrentOriginUsageCurrentDatabaseUsageExpectedUsageDecisionHandler) {
425
426         // Use 50 MB as the default database quota.
427         unsigned long long defaultPerOriginDatabaseQuota = 50 * 1024 * 1024;
428
429         completionHandler(defaultPerOriginDatabaseQuota);
430         return;
431     }
432
433     auto delegate = m_uiDelegate.m_delegate.get();
434     if (!delegate) {
435         completionHandler(currentQuota);
436         return;
437     }
438
439     ASSERT(securityOrigin);
440
441     if (m_uiDelegate.m_delegateMethods.webViewDecideDatabaseQuotaForSecurityOriginDatabaseNameDisplayNameCurrentQuotaCurrentOriginUsageCurrentDatabaseUsageExpectedUsageDecisionHandler) {
442         auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:decideDatabaseQuotaForSecurityOrigin:databaseName:displayName:currentQuota:currentOriginUsage:currentDatabaseUsage:expectedUsage:decisionHandler:));
443         [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView decideDatabaseQuotaForSecurityOrigin:wrapper(*securityOrigin) databaseName:databaseName displayName:displayName currentQuota:currentQuota currentOriginUsage:currentOriginUsage currentDatabaseUsage:currentUsage expectedUsage:expectedUsage decisionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)](unsigned long long newQuota) {
444             if (checker->completionHandlerHasBeenCalled())
445                 return;
446             checker->didCallCompletionHandler();
447             completionHandler(newQuota);
448         }).get()];
449         return;
450     }
451
452     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:decideDatabaseQuotaForSecurityOrigin:currentQuota:currentOriginUsage:currentDatabaseUsage:expectedUsage:decisionHandler:));
453     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView decideDatabaseQuotaForSecurityOrigin:wrapper(*securityOrigin) currentQuota:currentQuota currentOriginUsage:currentOriginUsage currentDatabaseUsage:currentUsage expectedUsage:expectedUsage decisionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)](unsigned long long newQuota) {
454         if (checker->completionHandlerHasBeenCalled())
455             return;
456         checker->didCallCompletionHandler();
457         completionHandler(newQuota);
458     }).get()];
459 }
460
461 static inline _WKFocusDirection toWKFocusDirection(WKFocusDirection direction)
462 {
463     switch (direction) {
464     case kWKFocusDirectionBackward:
465         return _WKFocusDirectionBackward;
466     case kWKFocusDirectionForward:
467         return _WKFocusDirectionForward;
468     }
469     ASSERT_NOT_REACHED();
470     return _WKFocusDirectionForward;
471 }
472
473 bool UIDelegate::UIClient::takeFocus(WebPageProxy*, WKFocusDirection direction)
474 {
475     if (!m_uiDelegate.m_delegateMethods.webViewTakeFocus)
476         return false;
477     
478     auto delegate = m_uiDelegate.m_delegate.get();
479     if (!delegate)
480         return false;
481     
482     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView takeFocus:toWKFocusDirection(direction)];
483     return true;
484 }
485
486 #if PLATFORM(MAC)
487 bool UIDelegate::UIClient::canRunModal() const
488 {
489     return m_uiDelegate.m_delegateMethods.webViewRunModal;
490 }
491
492 void UIDelegate::UIClient::runModal(WebPageProxy&)
493 {
494     if (!m_uiDelegate.m_delegateMethods.webViewRunModal)
495         return;
496     
497     auto delegate = m_uiDelegate.m_delegate.get();
498     if (!delegate)
499         return;
500
501     [(id <WKUIDelegatePrivate>)delegate _webViewRunModal:m_uiDelegate.m_webView];
502 }
503
504 float UIDelegate::UIClient::headerHeight(WebPageProxy&, WebFrameProxy& webFrameProxy)
505 {
506     if (!m_uiDelegate.m_delegateMethods.webViewHeaderHeight)
507         return 0;
508     
509     auto delegate = m_uiDelegate.m_delegate.get();
510     if (!delegate)
511         return 0;
512     
513     return [(id <WKUIDelegatePrivate>)delegate _webViewHeaderHeight:m_uiDelegate.m_webView];
514 }
515
516 float UIDelegate::UIClient::footerHeight(WebPageProxy&, WebFrameProxy&)
517 {
518     if (!m_uiDelegate.m_delegateMethods.webViewFooterHeight)
519         return 0;
520     
521     auto delegate = m_uiDelegate.m_delegate.get();
522     if (!delegate)
523         return 0;
524     
525     return [(id <WKUIDelegatePrivate>)delegate _webViewFooterHeight:m_uiDelegate.m_webView];
526 }
527
528 void UIDelegate::UIClient::drawHeader(WebPageProxy&, WebFrameProxy& frame, WebCore::FloatRect&& rect)
529 {
530     if (!m_uiDelegate.m_delegateMethods.webViewDrawHeaderInRectForPageWithTitleURL)
531         return;
532     
533     auto delegate = m_uiDelegate.m_delegate.get();
534     if (!delegate)
535         return;
536     
537     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView drawHeaderInRect:rect forPageWithTitle:frame.title() URL:frame.url()];
538 }
539
540 void UIDelegate::UIClient::drawFooter(WebPageProxy&, WebFrameProxy& frame, WebCore::FloatRect&& rect)
541 {
542     if (!m_uiDelegate.m_delegateMethods.webViewDrawFooterInRectForPageWithTitleURL)
543         return;
544     
545     auto delegate = m_uiDelegate.m_delegate.get();
546     if (!delegate)
547         return;
548     
549     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView drawFooterInRect:rect forPageWithTitle:frame.title() URL:frame.url()];
550 }
551
552 void UIDelegate::UIClient::pageDidScroll(WebPageProxy*)
553 {
554     if (!m_uiDelegate.m_delegateMethods.webViewDidScroll)
555         return;
556     
557     auto delegate = m_uiDelegate.m_delegate.get();
558     if (!delegate)
559         return;
560     
561     [(id <WKUIDelegatePrivate>)delegate _webViewDidScroll:m_uiDelegate.m_webView];
562 }
563
564 void UIDelegate::UIClient::focus(WebPageProxy*)
565 {
566     if (!m_uiDelegate.m_delegateMethods.focusWebView)
567         return;
568     
569     auto delegate = m_uiDelegate.m_delegate.get();
570     if (!delegate)
571         return;
572     
573     [(id <WKUIDelegatePrivate>)delegate _focusWebView:m_uiDelegate.m_webView];
574 }
575
576 void UIDelegate::UIClient::unfocus(WebPageProxy*)
577 {
578     if (!m_uiDelegate.m_delegateMethods.unfocusWebView)
579         return;
580     
581     auto delegate = m_uiDelegate.m_delegate.get();
582     if (!delegate)
583         return;
584     
585     [(id <WKUIDelegatePrivate>)delegate _unfocusWebView:m_uiDelegate.m_webView];
586 }
587
588 static _WKPlugInUnavailabilityReason toWKPlugInUnavailabilityReason(WKPluginUnavailabilityReason reason)
589 {
590     switch (reason) {
591     case kWKPluginUnavailabilityReasonPluginMissing:
592         return _WKPlugInUnavailabilityReasonPluginMissing;
593     case kWKPluginUnavailabilityReasonPluginCrashed:
594         return _WKPlugInUnavailabilityReasonPluginCrashed;
595     case kWKPluginUnavailabilityReasonInsecurePluginVersion:
596         return _WKPlugInUnavailabilityReasonInsecurePluginVersion;
597     }
598     ASSERT_NOT_REACHED();
599     return _WKPlugInUnavailabilityReasonPluginMissing;
600 }
601     
602 void UIDelegate::UIClient::unavailablePluginButtonClicked(WebPageProxy&, WKPluginUnavailabilityReason reason, API::Dictionary& plugInInfo)
603 {
604     if (!m_uiDelegate.m_delegateMethods.webViewUnavailablePlugInButtonClicked)
605         return;
606     
607     auto delegate = m_uiDelegate.m_delegate.get();
608     if (!delegate)
609         return;
610
611     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView unavailablePlugInButtonClickedWithReason:toWKPlugInUnavailabilityReason(reason) plugInInfo:wrapper(plugInInfo)];
612 }
613     
614 static _WKResourceLimit toWKResourceLimit(WKResourceLimit limit)
615 {
616     switch (limit) {
617     case kWKResourceLimitMemory:
618         return _WKResourceLimitMemory;
619     case kWKResourceLimitCPU:
620         return _WKResourceLimitCPU;
621     }
622     ASSERT_NOT_REACHED();
623     return _WKResourceLimitMemory;
624 }
625
626 void UIDelegate::UIClient::didExceedBackgroundResourceLimitWhileInForeground(WebPageProxy&, WKResourceLimit limit)
627 {
628     if (!m_uiDelegate.m_delegateMethods.webViewDidExceedBackgroundResourceLimitWhileInForeground)
629         return;
630     
631     auto delegate = m_uiDelegate.m_delegate.get();
632     if (!delegate)
633         return;
634     
635     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webView:m_uiDelegate.m_webView didExceedBackgroundResourceLimitWhileInForeground:toWKResourceLimit(limit)];
636 }
637
638 void UIDelegate::UIClient::didNotHandleWheelEvent(WebPageProxy*, const NativeWebWheelEvent& event)
639 {
640     if (!m_uiDelegate.m_delegateMethods.webViewDidNotHandleWheelEvent)
641         return;
642     
643     auto delegate = m_uiDelegate.m_delegate.get();
644     if (!delegate)
645         return;
646     
647     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView didNotHandleWheelEvent:event.nativeEvent()];
648 }
649
650 void UIDelegate::UIClient::setIsResizable(WebKit::WebPageProxy&, bool resizable)
651 {
652     if (!m_uiDelegate.m_delegateMethods.webViewSetResizable)
653         return;
654     
655     auto delegate = m_uiDelegate.m_delegate.get();
656     if (!delegate)
657         return;
658     
659     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView setResizable:resizable];
660 }
661
662 void UIDelegate::UIClient::setWindowFrame(WebKit::WebPageProxy&, const WebCore::FloatRect& frame)
663 {
664     if (!m_uiDelegate.m_delegateMethods.webViewSetWindowFrame)
665         return;
666     
667     auto delegate = m_uiDelegate.m_delegate.get();
668     if (!delegate)
669         return;
670     
671     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView setWindowFrame:frame];
672 }
673
674 void UIDelegate::UIClient::windowFrame(WebKit::WebPageProxy&, Function<void(WebCore::FloatRect)>&& completionHandler)
675 {
676     if (!m_uiDelegate.m_delegateMethods.webViewGetWindowFrameWithCompletionHandler)
677         return completionHandler({ });
678     
679     auto delegate = m_uiDelegate.m_delegate.get();
680     if (!delegate)
681         return completionHandler({ });
682     
683     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView getWindowFrameWithCompletionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:getWindowFrameWithCompletionHandler:))](CGRect frame) {
684         if (checker->completionHandlerHasBeenCalled())
685             return;
686         checker->didCallCompletionHandler();
687         completionHandler(frame);
688     }).get()];
689 }
690
691 void UIDelegate::UIClient::mouseDidMoveOverElement(WebPageProxy&, const WebHitTestResultData& data, OptionSet<WebEvent::Modifier> modifiers, API::Object* userInfo)
692 {
693     if (!m_uiDelegate.m_delegateMethods.webViewMouseDidMoveOverElementWithFlagsUserInfo)
694         return;
695
696     auto delegate = m_uiDelegate.m_delegate.get();
697     if (!delegate)
698         return;
699
700     auto apiHitTestResult = API::HitTestResult::create(data);
701     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView mouseDidMoveOverElement:wrapper(apiHitTestResult.get()) withFlags:WebEventFactory::toNSEventModifierFlags(modifiers) userInfo:userInfo ? static_cast<id <NSSecureCoding>>(userInfo->wrapper()) : nil];
702 }
703
704 static _WKAutoplayEventFlags toWKAutoplayEventFlags(OptionSet<WebCore::AutoplayEventFlags> flags)
705 {
706     _WKAutoplayEventFlags wkFlags = _WKAutoplayEventFlagsNone;
707     if (flags.contains(WebCore::AutoplayEventFlags::HasAudio))
708         wkFlags |= _WKAutoplayEventFlagsHasAudio;
709     if (flags.contains(WebCore::AutoplayEventFlags::PlaybackWasPrevented))
710         wkFlags |= _WKAutoplayEventFlagsPlaybackWasPrevented;
711     if (flags.contains(WebCore::AutoplayEventFlags::MediaIsMainContent))
712         wkFlags |= _WKAutoplayEventFlagsMediaIsMainContent;
713     
714     return wkFlags;
715 }
716
717 static _WKAutoplayEvent toWKAutoplayEvent(WebCore::AutoplayEvent event)
718 {
719     switch (event) {
720     case WebCore::AutoplayEvent::DidPreventMediaFromPlaying:
721         return _WKAutoplayEventDidPreventFromAutoplaying;
722     case WebCore::AutoplayEvent::DidPlayMediaWithUserGesture:
723         return _WKAutoplayEventDidPlayMediaWithUserGesture;
724     case WebCore::AutoplayEvent::DidAutoplayMediaPastThresholdWithoutUserInterference:
725         return _WKAutoplayEventDidAutoplayMediaPastThresholdWithoutUserInterference;
726     case WebCore::AutoplayEvent::UserDidInterfereWithPlayback:
727         return _WKAutoplayEventUserDidInterfereWithPlayback;
728     }
729     ASSERT_NOT_REACHED();
730     return _WKAutoplayEventDidPlayMediaWithUserGesture;
731 }
732
733 void UIDelegate::UIClient::toolbarsAreVisible(WebPageProxy&, Function<void(bool)>&& completionHandler)
734 {
735     if (!m_uiDelegate.m_delegateMethods.webViewGetToolbarsAreVisibleWithCompletionHandler)
736         return completionHandler(true);
737     
738     auto delegate = m_uiDelegate.m_delegate.get();
739     if (!delegate)
740         return completionHandler(true);
741     
742     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView getToolbarsAreVisibleWithCompletionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:getToolbarsAreVisibleWithCompletionHandler:))](BOOL visible) {
743         if (checker->completionHandlerHasBeenCalled())
744             return;
745         checker->didCallCompletionHandler();
746         completionHandler(visible);
747     }).get()];
748 }
749
750 void UIDelegate::UIClient::didClickAutoFillButton(WebPageProxy&, API::Object* userInfo)
751 {
752     if (!m_uiDelegate.m_delegateMethods.webViewDidClickAutoFillButtonWithUserInfo)
753         return;
754     
755     auto delegate = m_uiDelegate.m_delegate.get();
756     if (!delegate)
757         return;
758     
759     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView didClickAutoFillButtonWithUserInfo:userInfo ? static_cast<id <NSSecureCoding>>(userInfo->wrapper()) : nil];
760 }
761
762 void UIDelegate::UIClient::handleAutoplayEvent(WebPageProxy&, WebCore::AutoplayEvent event, OptionSet<WebCore::AutoplayEventFlags> flags)
763 {
764     if (!m_uiDelegate.m_delegateMethods.webViewHandleAutoplayEventWithFlags)
765         return;
766     
767     auto delegate = m_uiDelegate.m_delegate.get();
768     if (!delegate)
769         return;
770     
771     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView handleAutoplayEvent:toWKAutoplayEvent(event) withFlags:toWKAutoplayEventFlags(flags)];
772 }
773
774 void UIDelegate::UIClient::showPage(WebPageProxy*)
775 {
776     if (!m_uiDelegate.m_delegateMethods.showWebView)
777         return;
778
779     auto delegate = m_uiDelegate.m_delegate.get();
780     if (!delegate)
781         return;
782     
783     [(id <WKUIDelegatePrivate>)delegate _showWebView:m_uiDelegate.m_webView];
784 }
785     
786 void UIDelegate::UIClient::saveDataToFileInDownloadsFolder(WebPageProxy*, const WTF::String& suggestedFilename, const WTF::String& mimeType, const URL& originatingURL, API::Data& data)
787 {
788     if (!m_uiDelegate.m_delegateMethods.webViewSaveDataToFileSuggestedFilenameMimeTypeOriginatingURL)
789         return;
790     
791     auto delegate = m_uiDelegate.m_delegate.get();
792     if (!delegate)
793         return;
794
795     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView saveDataToFile:wrapper(data) suggestedFilename:suggestedFilename mimeType:mimeType originatingURL:originatingURL];
796 }
797
798 void UIDelegate::UIClient::decidePolicyForNotificationPermissionRequest(WebKit::WebPageProxy&, API::SecurityOrigin& securityOrigin, WTF::Function<void(bool)>&& completionHandler)
799 {
800     if (!m_uiDelegate.m_delegateMethods.webViewRequestNotificationPermissionForSecurityOriginDecisionHandler)
801         return completionHandler(false);
802     
803     auto delegate = m_uiDelegate.m_delegate.get();
804     if (!delegate)
805         return completionHandler(false);
806
807     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:requestNotificationPermissionForSecurityOrigin:decisionHandler:));
808     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView requestNotificationPermissionForSecurityOrigin:wrapper(securityOrigin) decisionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)] (BOOL result) mutable {
809         if (checker->completionHandlerHasBeenCalled())
810             return;
811         checker->didCallCompletionHandler();
812         completionHandler(result);
813     }).get()];
814 }
815
816 bool UIDelegate::UIClient::runOpenPanel(WebPageProxy*, WebFrameProxy* webFrameProxy, const WebCore::SecurityOriginData& securityOriginData, API::OpenPanelParameters* openPanelParameters, WebOpenPanelResultListenerProxy* listener)
817 {
818     if (!m_uiDelegate.m_delegateMethods.webViewRunOpenPanelWithParametersInitiatedByFrameCompletionHandler)
819         return false;
820
821     auto delegate = m_uiDelegate.m_delegate.get();
822     if (!delegate)
823         return false;
824
825     auto frame = API::FrameInfo::create(*webFrameProxy, securityOriginData.securityOrigin());
826
827     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(webView:runOpenPanelWithParameters:initiatedByFrame:completionHandler:));
828
829     [delegate webView:m_uiDelegate.m_webView runOpenPanelWithParameters:wrapper(*openPanelParameters) initiatedByFrame:wrapper(frame) completionHandler:makeBlockPtr([checker = WTFMove(checker), listener = WTFMove(listener)] (NSArray *URLs) mutable {
830         if (checker->completionHandlerHasBeenCalled())
831             return;
832         checker->didCallCompletionHandler();
833
834         if (!URLs) {
835             listener->cancel();
836             return;
837         }
838
839         Vector<String> filenames;
840         for (NSURL *url in URLs)
841             filenames.append(url.path);
842
843         listener->chooseFiles(filenames);
844     }).get()];
845
846     return true;
847 }
848 #endif
849
850 #if ENABLE(DEVICE_ORIENTATION)
851 void UIDelegate::UIClient::shouldAllowDeviceOrientationAndMotionAccess(WebKit::WebPageProxy&, API::SecurityOrigin& securityOrigin, CompletionHandler<void(bool)>&& completionHandler)
852 {
853     if (!m_uiDelegate.m_delegateMethods.webViewShouldAllowDeviceOrientationAndMotionAccessForSecurityOriginDecisionHandler)
854         return completionHandler(true);
855
856     auto delegate = m_uiDelegate.m_delegate.get();
857     if (!delegate)
858         return completionHandler(true);
859
860     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:shouldAllowDeviceOrientationAndMotionAccessForSecurityOrigin:decisionHandler:));
861     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView shouldAllowDeviceOrientationAndMotionAccessForSecurityOrigin:wrapper(securityOrigin) decisionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)] (BOOL granted) mutable {
862         if (checker->completionHandlerHasBeenCalled())
863             return;
864         checker->didCallCompletionHandler();
865         completionHandler(granted);
866     }).get()];
867 }
868 #endif
869
870 void UIDelegate::UIClient::didChangeFontAttributes(const WebCore::FontAttributes& fontAttributes)
871 {
872     if (!needsFontAttributes())
873         return;
874
875     auto privateUIDelegate = (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get();
876     [privateUIDelegate _webView:m_uiDelegate.m_webView didChangeFontAttributes:fontAttributes.createDictionary().get()];
877 }
878
879 #if ENABLE(MEDIA_STREAM)
880 static void requestUserMediaAuthorizationForFrame(const WebFrameProxy& frame, API::SecurityOrigin& topLevelOrigin, UserMediaPermissionRequestProxy& request, id <WKUIDelegatePrivate> delegate, WKWebView& webView)
881 {
882     auto checker = CompletionHandlerCallChecker::create(delegate, @selector(_webView:requestMediaCaptureAuthorization:decisionHandler:));
883     auto decisionHandler = makeBlockPtr([protectedRequest = makeRef(request), checker = WTFMove(checker)](BOOL authorized) {
884         if (checker->completionHandlerHasBeenCalled())
885             return;
886         checker->didCallCompletionHandler();
887
888         if (!authorized) {
889             protectedRequest->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
890             return;
891         }
892         const String& videoDeviceUID = (protectedRequest->requiresVideoCapture() || protectedRequest->requiresDisplayCapture()) ? protectedRequest->videoDeviceUIDs().first() : String();
893         const String& audioDeviceUID = protectedRequest->requiresAudioCapture() ? protectedRequest->audioDeviceUIDs().first() : String();
894         protectedRequest->allow(audioDeviceUID, videoDeviceUID);
895     });
896
897     _WKCaptureDevices devices = 0;
898     if (request.requiresAudioCapture())
899         devices |= _WKCaptureDeviceMicrophone;
900     if (request.requiresVideoCapture())
901         devices |= _WKCaptureDeviceCamera;
902     if (request.requiresDisplayCapture()) {
903         devices |= _WKCaptureDeviceDisplay;
904         ASSERT(!(devices & _WKCaptureDeviceCamera));
905     }
906
907     const auto* mainFrame = frame.page()->mainFrame();
908
909     // FIXME: Provide a specific delegate for display capture.
910     if (!request.requiresDisplayCapture() && [delegate respondsToSelector:@selector(_webView:requestMediaCaptureAuthorization:decisionHandler:)]) {
911
912         [delegate _webView:&webView requestMediaCaptureAuthorization:devices decisionHandler:decisionHandler.get()];
913         return;
914     }
915
916     URL requestFrameURL { URL(), frame.url() };
917     URL mainFrameURL { URL(), mainFrame->url() };
918
919     [delegate _webView:&webView requestUserMediaAuthorizationForDevices:devices url:requestFrameURL mainFrameURL:mainFrameURL decisionHandler:decisionHandler.get()];
920 }
921 #endif
922
923 void UIDelegate::UIClient::decidePolicyForUserMediaPermissionRequest(WebPageProxy& page, WebFrameProxy& frame, API::SecurityOrigin& userMediaOrigin, API::SecurityOrigin& topLevelOrigin, UserMediaPermissionRequestProxy& request)
924 {
925 #if ENABLE(MEDIA_STREAM)
926     auto delegate = m_uiDelegate.m_delegate.get();
927     if (!delegate || !m_uiDelegate.m_delegateMethods.webViewRequestMediaCaptureAuthorizationForFrameDecisionHandler) {
928         request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::UserMediaDisabled);
929         return;
930     }
931
932     bool requiresAudioCapture = request.requiresAudioCapture();
933     bool requiresVideoCapture = request.requiresVideoCapture();
934     bool requiresDisplayCapture = request.requiresDisplayCapture();
935     if (!requiresAudioCapture && !requiresVideoCapture && !requiresDisplayCapture) {
936         request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::NoConstraints);
937         return;
938     }
939
940 #if HAVE(AUTHORIZATION_STATUS_FOR_MEDIA_TYPE)
941     bool usingMockCaptureDevices = page.preferences().mockCaptureDevicesEnabled();
942     auto requestCameraAuthorization = makeBlockPtr([this, &frame, protectedRequest = makeRef(request), webView = RetainPtr<WKWebView>(m_uiDelegate.m_webView), topLevelOrigin = makeRef(topLevelOrigin), usingMockCaptureDevices]() mutable {
943
944         if (!protectedRequest->requiresVideoCapture()) {
945             requestUserMediaAuthorizationForFrame(frame, topLevelOrigin, protectedRequest, (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get(), *webView.get());
946             return;
947         }
948         AVAuthorizationStatus cameraAuthorizationStatus = usingMockCaptureDevices ? AVAuthorizationStatusAuthorized : [getAVCaptureDeviceClass() authorizationStatusForMediaType:getAVMediaTypeVideo()];
949         switch (cameraAuthorizationStatus) {
950         case AVAuthorizationStatusAuthorized:
951             requestUserMediaAuthorizationForFrame(frame, topLevelOrigin, protectedRequest, (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get(), *webView.get());
952             break;
953         case AVAuthorizationStatusDenied:
954         case AVAuthorizationStatusRestricted:
955             protectedRequest->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
956             return;
957         case AVAuthorizationStatusNotDetermined:
958             auto decisionHandler = makeBlockPtr([this, &frame, protectedRequest = makeRef(protectedRequest.get()), webView = RetainPtr<WKWebView>(m_uiDelegate.m_webView), topLevelOrigin = WTFMove(topLevelOrigin)](BOOL authorized) {
959                 if (!authorized) {
960                     protectedRequest->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
961                     return;
962                 }
963                 requestUserMediaAuthorizationForFrame(frame, topLevelOrigin, protectedRequest, (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get(), *webView.get());
964             });
965
966             [getAVCaptureDeviceClass() requestAccessForMediaType:getAVMediaTypeVideo() completionHandler:decisionHandler.get()];
967             break;
968         }
969     });
970
971     if (requiresAudioCapture) {
972         AVAuthorizationStatus microphoneAuthorizationStatus = usingMockCaptureDevices ? AVAuthorizationStatusAuthorized : [getAVCaptureDeviceClass() authorizationStatusForMediaType:getAVMediaTypeAudio()];
973         switch (microphoneAuthorizationStatus) {
974         case AVAuthorizationStatusAuthorized:
975             requestCameraAuthorization();
976             break;
977         case AVAuthorizationStatusDenied:
978         case AVAuthorizationStatusRestricted:
979             request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
980             return;
981         case AVAuthorizationStatusNotDetermined:
982             auto decisionHandler = makeBlockPtr([protectedRequest = makeRef(request), requestCameraAuthorization](BOOL authorized) {
983                 if (!authorized) {
984                     protectedRequest->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
985                     return;
986                 }
987                 requestCameraAuthorization();
988             });
989
990             [getAVCaptureDeviceClass() requestAccessForMediaType:getAVMediaTypeAudio() completionHandler:decisionHandler.get()];
991             break;
992         }
993     } else
994         requestCameraAuthorization();
995 #else
996     requestUserMediaAuthorizationForFrame(frame, topLevelOrigin, request, (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get(), *m_uiDelegate.m_webView);
997 #endif
998 #endif
999 }
1000
1001 void UIDelegate::UIClient::checkUserMediaPermissionForOrigin(WebPageProxy& page, WebFrameProxy& frame, API::SecurityOrigin& userMediaOrigin, API::SecurityOrigin& topLevelOrigin, UserMediaPermissionCheckProxy& request)
1002 {
1003     auto delegate = m_uiDelegate.m_delegate.get();
1004     if (!delegate || !m_uiDelegate.m_delegateMethods.webViewIsMediaCaptureAuthorizedForFrameDecisionHandler) {
1005         request.setUserMediaAccessInfo(false);
1006         return;
1007     }
1008
1009     const auto* mainFrame = frame.page()->mainFrame();
1010
1011     if ([delegate respondsToSelector:@selector(_webView:includeSensitiveMediaDeviceDetails:)]) {
1012         auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:includeSensitiveMediaDeviceDetails:));
1013         auto decisionHandler = makeBlockPtr([protectedRequest = makeRef(request), checker = WTFMove(checker)](BOOL includeSensitiveDetails) {
1014             if (checker->completionHandlerHasBeenCalled())
1015                 return;
1016             checker->didCallCompletionHandler();
1017
1018             protectedRequest->setUserMediaAccessInfo(includeSensitiveDetails);
1019         });
1020
1021         [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView includeSensitiveMediaDeviceDetails:decisionHandler.get()];
1022         return;
1023     }
1024
1025     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:checkUserMediaPermissionForURL:mainFrameURL:frameIdentifier:decisionHandler:));
1026     auto decisionHandler = makeBlockPtr([protectedRequest = makeRef(request), checker = WTFMove(checker)](NSString*, BOOL authorized) {
1027         if (checker->completionHandlerHasBeenCalled())
1028             return;
1029         checker->didCallCompletionHandler();
1030
1031         protectedRequest->setUserMediaAccessInfo(authorized);
1032     });
1033
1034     URL requestFrameURL { URL(), frame.url() };
1035     URL mainFrameURL { URL(), mainFrame->url() };
1036
1037     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView checkUserMediaPermissionForURL:requestFrameURL mainFrameURL:mainFrameURL frameIdentifier:frame.frameID() decisionHandler:decisionHandler.get()];
1038 }
1039
1040 void UIDelegate::UIClient::mediaCaptureStateDidChange(WebCore::MediaProducer::MediaStateFlags state)
1041 {
1042     WKWebView *webView = m_uiDelegate.m_webView;
1043
1044     [webView didChangeValueForKey:@"mediaCaptureState"];
1045
1046     auto delegate = m_uiDelegate.m_delegate.get();
1047     if (!delegate || !m_uiDelegate.m_delegateMethods.webViewMediaCaptureStateDidChange)
1048         return;
1049
1050     [(id <WKUIDelegatePrivate>)delegate _webView:webView mediaCaptureStateDidChange:toWKMediaCaptureState(state)];
1051 }
1052
1053 void UIDelegate::UIClient::reachedApplicationCacheOriginQuota(WebPageProxy*, const WebCore::SecurityOrigin& securityOrigin, uint64_t currentQuota, uint64_t totalBytesNeeded, Function<void (unsigned long long)>&& completionHandler)
1054 {
1055     if (!m_uiDelegate.m_delegateMethods.webViewDecideWebApplicationCacheQuotaForSecurityOriginCurrentQuotaTotalBytesNeeded) {
1056         completionHandler(currentQuota);
1057         return;
1058     }
1059
1060     auto delegate = m_uiDelegate.m_delegate.get();
1061     if (!delegate) {
1062         completionHandler(currentQuota);
1063         return;
1064     }
1065
1066     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:decideWebApplicationCacheQuotaForSecurityOrigin:currentQuota:totalBytesNeeded:decisionHandler:));
1067     auto apiOrigin = API::SecurityOrigin::create(securityOrigin);
1068     
1069     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView decideWebApplicationCacheQuotaForSecurityOrigin:wrapper(apiOrigin.get()) currentQuota:currentQuota totalBytesNeeded:totalBytesNeeded decisionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)](unsigned long long newQuota) {
1070         if (checker->completionHandlerHasBeenCalled())
1071             return;
1072         checker->didCallCompletionHandler();
1073         completionHandler(newQuota);
1074     }).get()];
1075 }
1076
1077 void UIDelegate::UIClient::printFrame(WebPageProxy&, WebFrameProxy& webFrameProxy)
1078 {
1079     if (!m_uiDelegate.m_delegateMethods.webViewPrintFrame)
1080         return;
1081
1082     auto delegate = m_uiDelegate.m_delegate.get();
1083     if (!delegate)
1084         return;
1085
1086     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView printFrame:wrapper(API::FrameHandle::create(webFrameProxy.frameID()))];
1087 }
1088
1089 void UIDelegate::UIClient::close(WebPageProxy*)
1090 {
1091     if (m_uiDelegate.m_delegateMethods.webViewClose) {
1092         auto delegate = m_uiDelegate.m_delegate.get();
1093         if (!delegate)
1094             return;
1095
1096         [(id <WKUIDelegatePrivate>)delegate _webViewClose:m_uiDelegate.m_webView];
1097         return;
1098     }
1099
1100     if (!m_uiDelegate.m_delegateMethods.webViewDidClose)
1101         return;
1102
1103     auto delegate = m_uiDelegate.m_delegate.get();
1104     if (!delegate)
1105         return;
1106
1107     [delegate webViewDidClose:m_uiDelegate.m_webView];
1108 }
1109
1110 void UIDelegate::UIClient::fullscreenMayReturnToInline(WebPageProxy*)
1111 {
1112     if (!m_uiDelegate.m_delegateMethods.webViewFullscreenMayReturnToInline)
1113         return;
1114     
1115     auto delegate = m_uiDelegate.m_delegate.get();
1116     if (!delegate)
1117         return;
1118     
1119     [(id <WKUIDelegatePrivate>)delegate _webViewFullscreenMayReturnToInline:m_uiDelegate.m_webView];
1120 }
1121
1122 void UIDelegate::UIClient::didEnterFullscreen(WebPageProxy*)
1123 {
1124     if (!m_uiDelegate.m_delegateMethods.webViewDidEnterFullscreen)
1125         return;
1126
1127     auto delegate = m_uiDelegate.m_delegate.get();
1128     if (!delegate)
1129         return;
1130
1131     [(id <WKUIDelegatePrivate>)delegate _webViewDidEnterFullscreen:m_uiDelegate.m_webView];
1132 }
1133
1134 void UIDelegate::UIClient::didExitFullscreen(WebPageProxy*)
1135 {
1136     if (!m_uiDelegate.m_delegateMethods.webViewDidExitFullscreen)
1137         return;
1138
1139     auto delegate = m_uiDelegate.m_delegate.get();
1140     if (!delegate)
1141         return;
1142
1143     [(id <WKUIDelegatePrivate>)delegate _webViewDidExitFullscreen:m_uiDelegate.m_webView];
1144 }
1145     
1146 #if PLATFORM(IOS_FAMILY)
1147 #if HAVE(APP_LINKS)
1148 bool UIDelegate::UIClient::shouldIncludeAppLinkActionsForElement(_WKActivatedElementInfo *elementInfo)
1149 {
1150     if (!m_uiDelegate.m_delegateMethods.webViewShouldIncludeAppLinkActionsForElement)
1151         return true;
1152
1153     auto delegate = m_uiDelegate.m_delegate.get();
1154     if (!delegate)
1155         return true;
1156
1157     return [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView shouldIncludeAppLinkActionsForElement:elementInfo];
1158 }
1159 #endif
1160
1161 RetainPtr<NSArray> UIDelegate::UIClient::actionsForElement(_WKActivatedElementInfo *elementInfo, RetainPtr<NSArray> defaultActions)
1162 {
1163     if (!m_uiDelegate.m_delegateMethods.webViewActionsForElementDefaultActions)
1164         return defaultActions;
1165
1166     auto delegate = m_uiDelegate.m_delegate.get();
1167     if (!delegate)
1168         return defaultActions;
1169
1170     return [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView actionsForElement:elementInfo defaultActions:defaultActions.get()];
1171 }
1172
1173 void UIDelegate::UIClient::didNotHandleTapAsClick(const WebCore::IntPoint& point)
1174 {
1175     if (!m_uiDelegate.m_delegateMethods.webViewDidNotHandleTapAsClickAtPoint)
1176         return;
1177
1178     auto delegate = m_uiDelegate.m_delegate.get();
1179     if (!delegate)
1180         return;
1181
1182     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webView:m_uiDelegate.m_webView didNotHandleTapAsClickAtPoint:point];
1183 }
1184
1185 UIViewController *UIDelegate::UIClient::presentingViewController()
1186 {
1187     if (!m_uiDelegate.m_delegateMethods.presentingViewControllerForWebView)
1188         return nullptr;
1189
1190     auto delegate = m_uiDelegate.m_delegate.get();
1191     if (!delegate)
1192         return nullptr;
1193
1194     return [static_cast<id <WKUIDelegatePrivate>>(delegate) _presentingViewControllerForWebView:m_uiDelegate.m_webView];
1195 }
1196
1197 #endif
1198
1199 NSDictionary *UIDelegate::UIClient::dataDetectionContext()
1200 {
1201     if (!m_uiDelegate.m_delegateMethods.dataDetectionContextForWebView)
1202         return nullptr;
1203
1204     auto delegate = m_uiDelegate.m_delegate.get();
1205     if (!delegate)
1206         return nullptr;
1207
1208     return [static_cast<id <WKUIDelegatePrivate>>(delegate) _dataDetectionContextForWebView:m_uiDelegate.m_webView];
1209 }
1210
1211 #if ENABLE(POINTER_LOCK)
1212
1213 void UIDelegate::UIClient::requestPointerLock(WebPageProxy* page)
1214 {
1215     if (!m_uiDelegate.m_delegateMethods.webViewRequestPointerLock && !m_uiDelegate.m_delegateMethods.webViewDidRequestPointerLockCompletionHandler)
1216         return;
1217
1218     auto delegate = m_uiDelegate.m_delegate.get();
1219     if (!delegate)
1220         return;
1221
1222     if (m_uiDelegate.m_delegateMethods.webViewRequestPointerLock) {
1223         [static_cast<id <WKUIDelegatePrivate>>(delegate) _webViewRequestPointerLock:m_uiDelegate.m_webView];
1224         return;
1225     }
1226
1227     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webViewDidRequestPointerLock:completionHandler:));
1228     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webViewDidRequestPointerLock:m_uiDelegate.m_webView completionHandler:makeBlockPtr([checker = WTFMove(checker), page = makeRefPtr(page)] (BOOL allow) {
1229         if (checker->completionHandlerHasBeenCalled())
1230             return;
1231         checker->didCallCompletionHandler();
1232
1233         if (allow)
1234             page->didAllowPointerLock();
1235         else
1236             page->didDenyPointerLock();
1237     }).get()];
1238 }
1239
1240 void UIDelegate::UIClient::didLosePointerLock(WebPageProxy*)
1241 {
1242     if (!m_uiDelegate.m_delegateMethods.webViewDidLosePointerLock)
1243         return;
1244
1245     auto delegate = m_uiDelegate.m_delegate.get();
1246     if (!delegate)
1247         return;
1248
1249     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webViewDidLosePointerLock:m_uiDelegate.m_webView];
1250 }
1251
1252 #endif
1253     
1254 void UIDelegate::UIClient::didShowSafeBrowsingWarning()
1255 {
1256     if (!m_uiDelegate.m_delegateMethods.webViewDidShowSafeBrowsingWarning)
1257         return;
1258
1259     auto delegate = m_uiDelegate.m_delegate.get();
1260     if (!delegate)
1261         return;
1262
1263     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webViewDidShowSafeBrowsingWarning:m_uiDelegate.m_webView];
1264 }
1265
1266 void UIDelegate::UIClient::hasVideoInPictureInPictureDidChange(WebPageProxy*, bool hasVideoInPictureInPicture)
1267 {
1268     if (!m_uiDelegate.m_delegateMethods.webViewHasVideoInPictureInPictureDidChange)
1269         return;
1270     
1271     auto delegate = m_uiDelegate.m_delegate.get();
1272     if (!delegate)
1273         return;
1274     
1275     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webView:m_uiDelegate.m_webView hasVideoInPictureInPictureDidChange:hasVideoInPictureInPicture];
1276 }
1277
1278 void UIDelegate::UIClient::imageOrMediaDocumentSizeChanged(const WebCore::IntSize& newSize)
1279 {
1280     if (!m_uiDelegate.m_delegateMethods.webViewImageOrMediaDocumentSizeChanged)
1281         return;
1282
1283     auto delegate = m_uiDelegate.m_delegate.get();
1284     if (!delegate)
1285         return;
1286
1287     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webView:m_uiDelegate.m_webView imageOrMediaDocumentSizeChanged:newSize];
1288 }
1289
1290 } // namespace WebKit