5eaa27175f0f1ea455512b9f47c48908296728d0
[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 "WKOrientationAccessAlert.h"
43 #import "WKSecurityOriginInternal.h"
44 #import "WKStorageAccessAlert.h"
45 #import "WKUIDelegatePrivate.h"
46 #import "WKWebViewConfigurationInternal.h"
47 #import "WKWebViewInternal.h"
48 #import "WKWindowFeaturesInternal.h"
49 #import "WebEventFactory.h"
50 #import "WebOpenPanelResultListenerProxy.h"
51 #import "WebProcessProxy.h"
52 #import "_WKContextMenuElementInfo.h"
53 #import "_WKFrameHandleInternal.h"
54 #import "_WKHitTestResultInternal.h"
55 #import <WebCore/FontAttributes.h>
56 #import <WebCore/SecurityOriginData.h>
57 #import <wtf/BlockPtr.h>
58 #import <wtf/URL.h>
59
60 #if HAVE(AUTHORIZATION_STATUS_FOR_MEDIA_TYPE)
61 #import <AVFoundation/AVCaptureDevice.h>
62 #import <AVFoundation/AVMediaFormat.h>
63 #import <wtf/SoftLinking.h>
64
65 SOFT_LINK_FRAMEWORK(AVFoundation);
66 SOFT_LINK_CLASS(AVFoundation, AVCaptureDevice);
67 SOFT_LINK_CONSTANT(AVFoundation, AVMediaTypeAudio, NSString *);
68 SOFT_LINK_CONSTANT(AVFoundation, AVMediaTypeVideo, NSString *);
69 #endif
70
71 namespace WebKit {
72
73 UIDelegate::UIDelegate(WKWebView *webView)
74     : m_webView(webView)
75 {
76 }
77
78 UIDelegate::~UIDelegate()
79 {
80 }
81
82 #if ENABLE(CONTEXT_MENUS)
83 std::unique_ptr<API::ContextMenuClient> UIDelegate::createContextMenuClient()
84 {
85     return std::make_unique<ContextMenuClient>(*this);
86 }
87 #endif
88
89 std::unique_ptr<API::UIClient> UIDelegate::createUIClient()
90 {
91     return std::make_unique<UIClient>(*this);
92 }
93
94 RetainPtr<id <WKUIDelegate> > UIDelegate::delegate()
95 {
96     return m_delegate.get();
97 }
98
99 void UIDelegate::setDelegate(id <WKUIDelegate> delegate)
100 {
101     m_delegate = delegate;
102
103     m_delegateMethods.webViewCreateWebViewWithConfigurationForNavigationActionWindowFeatures = [delegate respondsToSelector:@selector(webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:)];
104     m_delegateMethods.webViewCreateWebViewWithConfigurationForNavigationActionWindowFeaturesAsync = [delegate respondsToSelector:@selector(_webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:completionHandler:)];
105     m_delegateMethods.webViewRunJavaScriptAlertPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:)];
106     m_delegateMethods.webViewRunJavaScriptConfirmPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:)];
107     m_delegateMethods.webViewRunJavaScriptTextInputPanelWithPromptDefaultTextInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:completionHandler:)];
108     m_delegateMethods.webViewRequestStorageAccessPanelUnderFirstPartyCompletionHandler = [delegate respondsToSelector:@selector(_webView:requestStorageAccessPanelForDomain:underCurrentDomain:completionHandler:)];
109     m_delegateMethods.webViewRunBeforeUnloadConfirmPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(_webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:completionHandler:)];
110     m_delegateMethods.webViewRequestGeolocationPermissionForFrameDecisionHandler = [delegate respondsToSelector:@selector(_webView:requestGeolocationPermissionForFrame:decisionHandler:)];
111     m_delegateMethods.webViewDidResignInputElementStrongPasswordAppearanceWithUserInfo = [delegate respondsToSelector:@selector(_webView:didResignInputElementStrongPasswordAppearanceWithUserInfo:)];
112     m_delegateMethods.webViewTakeFocus = [delegate respondsToSelector:@selector(_webView:takeFocus:)];
113
114 #if PLATFORM(MAC)
115     m_delegateMethods.showWebView = [delegate respondsToSelector:@selector(_showWebView:)];
116     m_delegateMethods.focusWebView = [delegate respondsToSelector:@selector(_focusWebView:)];
117     m_delegateMethods.unfocusWebView = [delegate respondsToSelector:@selector(_unfocusWebView:)];
118     m_delegateMethods.webViewRunModal = [delegate respondsToSelector:@selector(_webViewRunModal:)];
119     m_delegateMethods.webViewDidScroll = [delegate respondsToSelector:@selector(_webViewDidScroll:)];
120     m_delegateMethods.webViewGetToolbarsAreVisibleWithCompletionHandler = [delegate respondsToSelector:@selector(_webView:getToolbarsAreVisibleWithCompletionHandler:)];
121     m_delegateMethods.webViewDidNotHandleWheelEvent = [delegate respondsToSelector:@selector(_webView:didNotHandleWheelEvent:)];
122     m_delegateMethods.webViewSetResizable = [delegate respondsToSelector:@selector(_webView:setResizable:)];
123     m_delegateMethods.webViewGetWindowFrameWithCompletionHandler = [delegate respondsToSelector:@selector(_webView:getWindowFrameWithCompletionHandler:)];
124     m_delegateMethods.webViewSetWindowFrame = [delegate respondsToSelector:@selector(_webView:setWindowFrame:)];
125     m_delegateMethods.webViewUnavailablePlugInButtonClicked = [delegate respondsToSelector:@selector(_webView:unavailablePlugInButtonClickedWithReason:plugInInfo:)];
126     m_delegateMethods.webViewHandleAutoplayEventWithFlags = [delegate respondsToSelector:@selector(_webView:handleAutoplayEvent:withFlags:)];
127     m_delegateMethods.webViewDidClickAutoFillButtonWithUserInfo = [delegate respondsToSelector:@selector(_webView:didClickAutoFillButtonWithUserInfo:)];
128     m_delegateMethods.webViewDrawHeaderInRectForPageWithTitleURL = [delegate respondsToSelector:@selector(_webView:drawHeaderInRect:forPageWithTitle:URL:)];
129     m_delegateMethods.webViewDrawFooterInRectForPageWithTitleURL = [delegate respondsToSelector:@selector(_webView:drawFooterInRect:forPageWithTitle:URL:)];
130     m_delegateMethods.webViewHeaderHeight = [delegate respondsToSelector:@selector(_webViewHeaderHeight:)];
131     m_delegateMethods.webViewFooterHeight = [delegate respondsToSelector:@selector(_webViewFooterHeight:)];
132     m_delegateMethods.webViewMouseDidMoveOverElementWithFlagsUserInfo = [delegate respondsToSelector:@selector(_webView:mouseDidMoveOverElement:withFlags:userInfo:)];
133     m_delegateMethods.webViewDidExceedBackgroundResourceLimitWhileInForeground = [delegate respondsToSelector:@selector(_webView:didExceedBackgroundResourceLimitWhileInForeground:)];
134     m_delegateMethods.webViewSaveDataToFileSuggestedFilenameMimeTypeOriginatingURL = [delegate respondsToSelector:@selector(_webView:saveDataToFile:suggestedFilename:mimeType:originatingURL:)];
135     m_delegateMethods.webViewRunOpenPanelWithParametersInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runOpenPanelWithParameters:initiatedByFrame:completionHandler:)];
136     m_delegateMethods.webViewRequestNotificationPermissionForSecurityOriginDecisionHandler = [delegate respondsToSelector:@selector(_webView:requestNotificationPermissionForSecurityOrigin:decisionHandler:)];
137 #endif
138 #if ENABLE(DEVICE_ORIENTATION)
139     m_delegateMethods.webViewShouldAllowDeviceOrientationAndMotionAccessRequestedByFrameDecisionHandler = [delegate respondsToSelector:@selector(_webView:shouldAllowDeviceOrientationAndMotionAccessRequestedByFrame:decisionHandler:)];
140 #endif
141     m_delegateMethods.webViewDecideDatabaseQuotaForSecurityOriginCurrentQuotaCurrentOriginUsageCurrentDatabaseUsageExpectedUsageDecisionHandler = [delegate respondsToSelector:@selector(_webView:decideDatabaseQuotaForSecurityOrigin:currentQuota:currentOriginUsage:currentDatabaseUsage:expectedUsage:decisionHandler:)];
142     m_delegateMethods.webViewDecideDatabaseQuotaForSecurityOriginDatabaseNameDisplayNameCurrentQuotaCurrentOriginUsageCurrentDatabaseUsageExpectedUsageDecisionHandler = [delegate respondsToSelector:@selector(_webView:decideDatabaseQuotaForSecurityOrigin:databaseName:displayName:currentQuota:currentOriginUsage:currentDatabaseUsage:expectedUsage:decisionHandler:)];
143     m_delegateMethods.webViewDecideWebApplicationCacheQuotaForSecurityOriginCurrentQuotaTotalBytesNeeded = [delegate respondsToSelector:@selector(_webView:decideWebApplicationCacheQuotaForSecurityOrigin:currentQuota:totalBytesNeeded:decisionHandler:)];
144     m_delegateMethods.webViewPrintFrame = [delegate respondsToSelector:@selector(_webView:printFrame:)];
145     m_delegateMethods.webViewDidClose = [delegate respondsToSelector:@selector(webViewDidClose:)];
146     m_delegateMethods.webViewClose = [delegate respondsToSelector:@selector(_webViewClose:)];
147     m_delegateMethods.webViewFullscreenMayReturnToInline = [delegate respondsToSelector:@selector(_webViewFullscreenMayReturnToInline:)];
148     m_delegateMethods.webViewDidEnterFullscreen = [delegate respondsToSelector:@selector(_webViewDidEnterFullscreen:)];
149     m_delegateMethods.webViewDidExitFullscreen = [delegate respondsToSelector:@selector(_webViewDidExitFullscreen:)];
150 #if PLATFORM(IOS_FAMILY)
151 #if HAVE(APP_LINKS)
152     m_delegateMethods.webViewShouldIncludeAppLinkActionsForElement = [delegate respondsToSelector:@selector(_webView:shouldIncludeAppLinkActionsForElement:)];
153 #endif
154     m_delegateMethods.webViewActionsForElementDefaultActions = [delegate respondsToSelector:@selector(_webView:actionsForElement:defaultActions:)];
155     m_delegateMethods.webViewDidNotHandleTapAsClickAtPoint = [delegate respondsToSelector:@selector(_webView:didNotHandleTapAsClickAtPoint:)];
156     m_delegateMethods.presentingViewControllerForWebView = [delegate respondsToSelector:@selector(_presentingViewControllerForWebView:)];
157 #endif
158     m_delegateMethods.webViewRequestMediaCaptureAuthorizationForFrameDecisionHandler = [delegate respondsToSelector:@selector(_webView:requestUserMediaAuthorizationForDevices:url:mainFrameURL:decisionHandler:)] || [delegate respondsToSelector:@selector(_webView:requestMediaCaptureAuthorization:decisionHandler:)];
159     m_delegateMethods.webViewIsMediaCaptureAuthorizedForFrameDecisionHandler = [delegate respondsToSelector:@selector(_webView:checkUserMediaPermissionForURL:mainFrameURL:frameIdentifier:decisionHandler:)] || [delegate respondsToSelector:@selector(_webView:includeSensitiveMediaDeviceDetails:)];
160
161     m_delegateMethods.webViewMediaCaptureStateDidChange = [delegate respondsToSelector:@selector(_webView:mediaCaptureStateDidChange:)];
162     m_delegateMethods.webViewDidChangeFontAttributes = [delegate respondsToSelector:@selector(_webView:didChangeFontAttributes:)];
163     m_delegateMethods.dataDetectionContextForWebView = [delegate respondsToSelector:@selector(_dataDetectionContextForWebView:)];
164     m_delegateMethods.webViewImageOrMediaDocumentSizeChanged = [delegate respondsToSelector:@selector(_webView:imageOrMediaDocumentSizeChanged:)];
165
166 #if ENABLE(POINTER_LOCK)
167     m_delegateMethods.webViewRequestPointerLock = [delegate respondsToSelector:@selector(_webViewRequestPointerLock:)];
168     m_delegateMethods.webViewDidRequestPointerLockCompletionHandler = [delegate respondsToSelector:@selector(_webViewDidRequestPointerLock:completionHandler:)];
169     m_delegateMethods.webViewDidLosePointerLock = [delegate respondsToSelector:@selector(_webViewDidLosePointerLock:)];
170 #endif
171 #if ENABLE(CONTEXT_MENUS)
172     m_delegateMethods.webViewContextMenuForElement = [delegate respondsToSelector:@selector(_webView:contextMenu:forElement:)];
173     m_delegateMethods.webViewContextMenuForElementUserInfo = [delegate respondsToSelector:@selector(_webView:contextMenu:forElement:userInfo:)];
174     m_delegateMethods.webViewGetContextMenuFromProposedMenuForElementUserInfoCompletionHandler = [delegate respondsToSelector:@selector(_webView:getContextMenuFromProposedMenu:forElement:userInfo:completionHandler:)];
175 #endif
176     
177     m_delegateMethods.webViewHasVideoInPictureInPictureDidChange = [delegate respondsToSelector:@selector(_webView:hasVideoInPictureInPictureDidChange:)];
178     m_delegateMethods.webViewDidShowSafeBrowsingWarning = [delegate respondsToSelector:@selector(_webViewDidShowSafeBrowsingWarning:)];
179 }
180
181 #if ENABLE(CONTEXT_MENUS)
182 UIDelegate::ContextMenuClient::ContextMenuClient(UIDelegate& uiDelegate)
183     : m_uiDelegate(uiDelegate)
184 {
185 }
186
187 UIDelegate::ContextMenuClient::~ContextMenuClient()
188 {
189 }
190
191 void UIDelegate::ContextMenuClient::menuFromProposedMenu(WebPageProxy&, NSMenu *menu, const WebHitTestResultData&, API::Object* userInfo, CompletionHandler<void(RetainPtr<NSMenu>&&)>&& completionHandler)
192 {
193     if (!m_uiDelegate.m_delegateMethods.webViewContextMenuForElement
194         && !m_uiDelegate.m_delegateMethods.webViewContextMenuForElementUserInfo
195         && !m_uiDelegate.m_delegateMethods.webViewGetContextMenuFromProposedMenuForElementUserInfoCompletionHandler)
196         return completionHandler(menu);
197
198     auto delegate = m_uiDelegate.m_delegate.get();
199     if (!delegate)
200         return completionHandler(menu);
201
202     auto contextMenuElementInfo = adoptNS([[_WKContextMenuElementInfo alloc] init]);
203
204     if (m_uiDelegate.m_delegateMethods.webViewGetContextMenuFromProposedMenuForElementUserInfoCompletionHandler) {
205         auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:getContextMenuFromProposedMenu:forElement:userInfo:completionHandler:));
206         [(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 {
207             if (checker->completionHandlerHasBeenCalled())
208                 return;
209             checker->didCallCompletionHandler();
210             completionHandler(menu);
211         }).get()];
212         return;
213     }
214     
215     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
216     if (m_uiDelegate.m_delegateMethods.webViewContextMenuForElement)
217         return completionHandler([(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView contextMenu:menu forElement:contextMenuElementInfo.get()]);
218
219     completionHandler([(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView contextMenu:menu forElement:contextMenuElementInfo.get() userInfo:userInfo ? static_cast<id <NSSecureCoding>>(userInfo->wrapper()) : nil]);
220     ALLOW_DEPRECATED_DECLARATIONS_END
221 }
222 #endif
223
224 UIDelegate::UIClient::UIClient(UIDelegate& uiDelegate)
225     : m_uiDelegate(uiDelegate)
226 {
227 }
228
229 UIDelegate::UIClient::~UIClient()
230 {
231 }
232
233 void UIDelegate::UIClient::createNewPage(WebKit::WebPageProxy&, WebCore::WindowFeatures&& windowFeatures, Ref<API::NavigationAction>&& navigationAction, CompletionHandler<void(RefPtr<WebPageProxy>&&)>&& completionHandler)
234 {
235     auto delegate = m_uiDelegate.m_delegate.get();
236     ASSERT(delegate);
237
238     auto configuration = adoptNS([m_uiDelegate.m_webView->_configuration copy]);
239     [configuration _setRelatedWebView:m_uiDelegate.m_webView];
240
241     auto apiWindowFeatures = API::WindowFeatures::create(windowFeatures);
242
243     if (m_uiDelegate.m_delegateMethods.webViewCreateWebViewWithConfigurationForNavigationActionWindowFeaturesAsync) {
244         auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:completionHandler:));
245
246         [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView createWebViewWithConfiguration:configuration.get() forNavigationAction:wrapper(navigationAction) windowFeatures:wrapper(apiWindowFeatures) completionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker), relatedWebView = RetainPtr<WKWebView>(m_uiDelegate.m_webView)] (WKWebView *webView) mutable {
247             if (checker->completionHandlerHasBeenCalled())
248                 return;
249             checker->didCallCompletionHandler();
250
251             if (!webView) {
252                 completionHandler(nullptr);
253                 return;
254             }
255
256             if ([webView->_configuration _relatedWebView] != relatedWebView.get())
257                 [NSException raise:NSInternalInconsistencyException format:@"Returned WKWebView was not created with the given configuration."];
258
259             completionHandler(webView->_page.get());
260         }).get()];
261         return;
262     }
263     if (!m_uiDelegate.m_delegateMethods.webViewCreateWebViewWithConfigurationForNavigationActionWindowFeatures)
264         return completionHandler(nullptr);
265
266     RetainPtr<WKWebView> webView = [delegate webView:m_uiDelegate.m_webView createWebViewWithConfiguration:configuration.get() forNavigationAction:wrapper(navigationAction) windowFeatures:wrapper(apiWindowFeatures)];
267     if (!webView)
268         return completionHandler(nullptr);
269
270     if ([webView->_configuration _relatedWebView] != m_uiDelegate.m_webView)
271         [NSException raise:NSInternalInconsistencyException format:@"Returned WKWebView was not created with the given configuration."];
272     completionHandler(webView->_page.get());
273 }
274
275 void UIDelegate::UIClient::runJavaScriptAlert(WebPageProxy*, const WTF::String& message, WebFrameProxy* webFrameProxy, const WebCore::SecurityOriginData& securityOriginData, Function<void()>&& completionHandler)
276 {
277     if (!m_uiDelegate.m_delegateMethods.webViewRunJavaScriptAlertPanelWithMessageInitiatedByFrameCompletionHandler) {
278         completionHandler();
279         return;
280     }
281
282     auto delegate = m_uiDelegate.m_delegate.get();
283     if (!delegate) {
284         completionHandler();
285         return;
286     }
287
288     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:));
289     [delegate webView:m_uiDelegate.m_webView runJavaScriptAlertPanelWithMessage:message initiatedByFrame:wrapper(API::FrameInfo::create(*webFrameProxy, securityOriginData.securityOrigin())) completionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)] {
290         if (checker->completionHandlerHasBeenCalled())
291             return;
292         completionHandler();
293         checker->didCallCompletionHandler();
294     }).get()];
295 }
296
297 void UIDelegate::UIClient::runJavaScriptConfirm(WebPageProxy*, const WTF::String& message, WebFrameProxy* webFrameProxy, const WebCore::SecurityOriginData& securityOriginData, Function<void(bool)>&& completionHandler)
298 {
299     if (!m_uiDelegate.m_delegateMethods.webViewRunJavaScriptConfirmPanelWithMessageInitiatedByFrameCompletionHandler) {
300         completionHandler(false);
301         return;
302     }
303
304     auto delegate = m_uiDelegate.m_delegate.get();
305     if (!delegate) {
306         completionHandler(false);
307         return;
308     }
309
310     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:));
311     [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 {
312         if (checker->completionHandlerHasBeenCalled())
313             return;
314         completionHandler(result);
315         checker->didCallCompletionHandler();
316     }).get()];
317 }
318
319 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)
320 {
321     if (!m_uiDelegate.m_delegateMethods.webViewRunJavaScriptTextInputPanelWithPromptDefaultTextInitiatedByFrameCompletionHandler) {
322         completionHandler(String());
323         return;
324     }
325
326     auto delegate = m_uiDelegate.m_delegate.get();
327     if (!delegate) {
328         completionHandler(String());
329         return;
330     }
331
332     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:completionHandler:));
333     [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 {
334         if (checker->completionHandlerHasBeenCalled())
335             return;
336         completionHandler(result);
337         checker->didCallCompletionHandler();
338     }).get()];
339 }
340
341 void UIDelegate::UIClient::requestStorageAccessConfirm(WebPageProxy&, WebFrameProxy*, const WebCore::RegistrableDomain& requestingDomain, const WebCore::RegistrableDomain& currentDomain, CompletionHandler<void(bool)>&& completionHandler)
342 {
343     auto delegate = m_uiDelegate.m_delegate.get();
344     if (!delegate) {
345         completionHandler(false);
346         return;
347     }
348     
349     if (!m_uiDelegate.m_delegateMethods.webViewRequestStorageAccessPanelUnderFirstPartyCompletionHandler) {
350 #if !PLATFORM(WATCHOS) && !PLATFORM(APPLETV)
351         presentStorageAccessAlert(m_uiDelegate.m_webView, requestingDomain, currentDomain, WTFMove(completionHandler));
352 #endif
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.string() underCurrentDomain:currentDomain.string() 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&, WebFrameProxy& webFrameProxy, const WebCore::SecurityOriginData& securityOriginData, CompletionHandler<void(bool)>&& completionHandler)
852 {
853     auto delegate = m_uiDelegate.m_delegate.get();
854     if (!delegate)
855         return completionHandler(false);
856
857     if (!m_uiDelegate.m_delegateMethods.webViewShouldAllowDeviceOrientationAndMotionAccessRequestedByFrameDecisionHandler) {
858         presentOrientationAccessAlert(m_uiDelegate.m_webView, securityOriginData.host, WTFMove(completionHandler));
859         return;
860     }
861
862     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:shouldAllowDeviceOrientationAndMotionAccessRequestedByFrame:decisionHandler:));
863     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView shouldAllowDeviceOrientationAndMotionAccessRequestedByFrame:wrapper(API::FrameInfo::create(webFrameProxy, securityOriginData.securityOrigin())) decisionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)] (BOOL granted) mutable {
864         if (checker->completionHandlerHasBeenCalled())
865             return;
866         checker->didCallCompletionHandler();
867         completionHandler(granted);
868     }).get()];
869 }
870 #endif
871
872 void UIDelegate::UIClient::didChangeFontAttributes(const WebCore::FontAttributes& fontAttributes)
873 {
874     if (!needsFontAttributes())
875         return;
876
877     auto privateUIDelegate = (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get();
878     [privateUIDelegate _webView:m_uiDelegate.m_webView didChangeFontAttributes:fontAttributes.createDictionary().get()];
879 }
880
881 #if ENABLE(MEDIA_STREAM)
882 static void requestUserMediaAuthorizationForFrame(const WebFrameProxy& frame, API::SecurityOrigin& topLevelOrigin, UserMediaPermissionRequestProxy& request, id <WKUIDelegatePrivate> delegate, WKWebView& webView)
883 {
884     auto checker = CompletionHandlerCallChecker::create(delegate, @selector(_webView:requestMediaCaptureAuthorization:decisionHandler:));
885     auto decisionHandler = makeBlockPtr([protectedRequest = makeRef(request), checker = WTFMove(checker)](BOOL authorized) {
886         if (checker->completionHandlerHasBeenCalled())
887             return;
888         checker->didCallCompletionHandler();
889
890         if (!authorized) {
891             protectedRequest->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
892             return;
893         }
894         const String& videoDeviceUID = (protectedRequest->requiresVideoCapture() || protectedRequest->requiresDisplayCapture()) ? protectedRequest->videoDeviceUIDs().first() : String();
895         const String& audioDeviceUID = protectedRequest->requiresAudioCapture() ? protectedRequest->audioDeviceUIDs().first() : String();
896         protectedRequest->allow(audioDeviceUID, videoDeviceUID);
897     });
898
899     _WKCaptureDevices devices = 0;
900     if (request.requiresAudioCapture())
901         devices |= _WKCaptureDeviceMicrophone;
902     if (request.requiresVideoCapture())
903         devices |= _WKCaptureDeviceCamera;
904     if (request.requiresDisplayCapture()) {
905         devices |= _WKCaptureDeviceDisplay;
906         ASSERT(!(devices & _WKCaptureDeviceCamera));
907     }
908
909     const auto* mainFrame = frame.page()->mainFrame();
910
911     // FIXME: Provide a specific delegate for display capture.
912     if (!request.requiresDisplayCapture() && [delegate respondsToSelector:@selector(_webView:requestMediaCaptureAuthorization:decisionHandler:)]) {
913
914         [delegate _webView:&webView requestMediaCaptureAuthorization:devices decisionHandler:decisionHandler.get()];
915         return;
916     }
917
918     URL requestFrameURL { URL(), frame.url() };
919     URL mainFrameURL { URL(), mainFrame->url() };
920
921     [delegate _webView:&webView requestUserMediaAuthorizationForDevices:devices url:requestFrameURL mainFrameURL:mainFrameURL decisionHandler:decisionHandler.get()];
922 }
923 #endif
924
925 void UIDelegate::UIClient::decidePolicyForUserMediaPermissionRequest(WebPageProxy& page, WebFrameProxy& frame, API::SecurityOrigin& userMediaOrigin, API::SecurityOrigin& topLevelOrigin, UserMediaPermissionRequestProxy& request)
926 {
927 #if ENABLE(MEDIA_STREAM)
928     auto delegate = m_uiDelegate.m_delegate.get();
929     if (!delegate || !m_uiDelegate.m_delegateMethods.webViewRequestMediaCaptureAuthorizationForFrameDecisionHandler) {
930         request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::UserMediaDisabled);
931         return;
932     }
933
934     bool requiresAudioCapture = request.requiresAudioCapture();
935     bool requiresVideoCapture = request.requiresVideoCapture();
936     bool requiresDisplayCapture = request.requiresDisplayCapture();
937     if (!requiresAudioCapture && !requiresVideoCapture && !requiresDisplayCapture) {
938         request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::NoConstraints);
939         return;
940     }
941
942 #if HAVE(AUTHORIZATION_STATUS_FOR_MEDIA_TYPE)
943     bool usingMockCaptureDevices = page.preferences().mockCaptureDevicesEnabled();
944     auto requestCameraAuthorization = makeBlockPtr([this, &frame, protectedRequest = makeRef(request), webView = RetainPtr<WKWebView>(m_uiDelegate.m_webView), topLevelOrigin = makeRef(topLevelOrigin), usingMockCaptureDevices]() mutable {
945
946         if (!protectedRequest->requiresVideoCapture()) {
947             requestUserMediaAuthorizationForFrame(frame, topLevelOrigin, protectedRequest, (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get(), *webView.get());
948             return;
949         }
950         AVAuthorizationStatus cameraAuthorizationStatus = usingMockCaptureDevices ? AVAuthorizationStatusAuthorized : [getAVCaptureDeviceClass() authorizationStatusForMediaType:getAVMediaTypeVideo()];
951         switch (cameraAuthorizationStatus) {
952         case AVAuthorizationStatusAuthorized:
953             requestUserMediaAuthorizationForFrame(frame, topLevelOrigin, protectedRequest, (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get(), *webView.get());
954             break;
955         case AVAuthorizationStatusDenied:
956         case AVAuthorizationStatusRestricted:
957             protectedRequest->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
958             return;
959         case AVAuthorizationStatusNotDetermined:
960             auto decisionHandler = makeBlockPtr([this, &frame, protectedRequest = makeRef(protectedRequest.get()), webView = RetainPtr<WKWebView>(m_uiDelegate.m_webView), topLevelOrigin = WTFMove(topLevelOrigin)](BOOL authorized) {
961                 if (!authorized) {
962                     protectedRequest->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
963                     return;
964                 }
965                 requestUserMediaAuthorizationForFrame(frame, topLevelOrigin, protectedRequest, (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get(), *webView.get());
966             });
967
968             [getAVCaptureDeviceClass() requestAccessForMediaType:getAVMediaTypeVideo() completionHandler:decisionHandler.get()];
969             break;
970         }
971     });
972
973     if (requiresAudioCapture) {
974         AVAuthorizationStatus microphoneAuthorizationStatus = usingMockCaptureDevices ? AVAuthorizationStatusAuthorized : [getAVCaptureDeviceClass() authorizationStatusForMediaType:getAVMediaTypeAudio()];
975         switch (microphoneAuthorizationStatus) {
976         case AVAuthorizationStatusAuthorized:
977             requestCameraAuthorization();
978             break;
979         case AVAuthorizationStatusDenied:
980         case AVAuthorizationStatusRestricted:
981             request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
982             return;
983         case AVAuthorizationStatusNotDetermined:
984             auto decisionHandler = makeBlockPtr([protectedRequest = makeRef(request), requestCameraAuthorization](BOOL authorized) {
985                 if (!authorized) {
986                     protectedRequest->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
987                     return;
988                 }
989                 requestCameraAuthorization();
990             });
991
992             [getAVCaptureDeviceClass() requestAccessForMediaType:getAVMediaTypeAudio() completionHandler:decisionHandler.get()];
993             break;
994         }
995     } else
996         requestCameraAuthorization();
997 #else
998     requestUserMediaAuthorizationForFrame(frame, topLevelOrigin, request, (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get(), *m_uiDelegate.m_webView);
999 #endif
1000 #endif
1001 }
1002
1003 void UIDelegate::UIClient::checkUserMediaPermissionForOrigin(WebPageProxy& page, WebFrameProxy& frame, API::SecurityOrigin& userMediaOrigin, API::SecurityOrigin& topLevelOrigin, UserMediaPermissionCheckProxy& request)
1004 {
1005     auto delegate = m_uiDelegate.m_delegate.get();
1006     if (!delegate || !m_uiDelegate.m_delegateMethods.webViewIsMediaCaptureAuthorizedForFrameDecisionHandler) {
1007         request.setUserMediaAccessInfo(false);
1008         return;
1009     }
1010
1011     const auto* mainFrame = frame.page()->mainFrame();
1012
1013     if ([delegate respondsToSelector:@selector(_webView:includeSensitiveMediaDeviceDetails:)]) {
1014         auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:includeSensitiveMediaDeviceDetails:));
1015         auto decisionHandler = makeBlockPtr([protectedRequest = makeRef(request), checker = WTFMove(checker)](BOOL includeSensitiveDetails) {
1016             if (checker->completionHandlerHasBeenCalled())
1017                 return;
1018             checker->didCallCompletionHandler();
1019
1020             protectedRequest->setUserMediaAccessInfo(includeSensitiveDetails);
1021         });
1022
1023         [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView includeSensitiveMediaDeviceDetails:decisionHandler.get()];
1024         return;
1025     }
1026
1027     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:checkUserMediaPermissionForURL:mainFrameURL:frameIdentifier:decisionHandler:));
1028     auto decisionHandler = makeBlockPtr([protectedRequest = makeRef(request), checker = WTFMove(checker)](NSString*, BOOL authorized) {
1029         if (checker->completionHandlerHasBeenCalled())
1030             return;
1031         checker->didCallCompletionHandler();
1032
1033         protectedRequest->setUserMediaAccessInfo(authorized);
1034     });
1035
1036     URL requestFrameURL { URL(), frame.url() };
1037     URL mainFrameURL { URL(), mainFrame->url() };
1038
1039     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView checkUserMediaPermissionForURL:requestFrameURL mainFrameURL:mainFrameURL frameIdentifier:frame.frameID() decisionHandler:decisionHandler.get()];
1040 }
1041
1042 void UIDelegate::UIClient::mediaCaptureStateDidChange(WebCore::MediaProducer::MediaStateFlags state)
1043 {
1044     WKWebView *webView = m_uiDelegate.m_webView;
1045
1046     [webView didChangeValueForKey:@"mediaCaptureState"];
1047
1048     auto delegate = m_uiDelegate.m_delegate.get();
1049     if (!delegate || !m_uiDelegate.m_delegateMethods.webViewMediaCaptureStateDidChange)
1050         return;
1051
1052     [(id <WKUIDelegatePrivate>)delegate _webView:webView mediaCaptureStateDidChange:toWKMediaCaptureState(state)];
1053 }
1054
1055 void UIDelegate::UIClient::reachedApplicationCacheOriginQuota(WebPageProxy*, const WebCore::SecurityOrigin& securityOrigin, uint64_t currentQuota, uint64_t totalBytesNeeded, Function<void (unsigned long long)>&& completionHandler)
1056 {
1057     if (!m_uiDelegate.m_delegateMethods.webViewDecideWebApplicationCacheQuotaForSecurityOriginCurrentQuotaTotalBytesNeeded) {
1058         completionHandler(currentQuota);
1059         return;
1060     }
1061
1062     auto delegate = m_uiDelegate.m_delegate.get();
1063     if (!delegate) {
1064         completionHandler(currentQuota);
1065         return;
1066     }
1067
1068     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:decideWebApplicationCacheQuotaForSecurityOrigin:currentQuota:totalBytesNeeded:decisionHandler:));
1069     auto apiOrigin = API::SecurityOrigin::create(securityOrigin);
1070     
1071     [(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) {
1072         if (checker->completionHandlerHasBeenCalled())
1073             return;
1074         checker->didCallCompletionHandler();
1075         completionHandler(newQuota);
1076     }).get()];
1077 }
1078
1079 void UIDelegate::UIClient::printFrame(WebPageProxy&, WebFrameProxy& webFrameProxy)
1080 {
1081     if (!m_uiDelegate.m_delegateMethods.webViewPrintFrame)
1082         return;
1083
1084     auto delegate = m_uiDelegate.m_delegate.get();
1085     if (!delegate)
1086         return;
1087
1088     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView printFrame:wrapper(API::FrameHandle::create(webFrameProxy.frameID()))];
1089 }
1090
1091 void UIDelegate::UIClient::close(WebPageProxy*)
1092 {
1093     if (m_uiDelegate.m_delegateMethods.webViewClose) {
1094         auto delegate = m_uiDelegate.m_delegate.get();
1095         if (!delegate)
1096             return;
1097
1098         [(id <WKUIDelegatePrivate>)delegate _webViewClose:m_uiDelegate.m_webView];
1099         return;
1100     }
1101
1102     if (!m_uiDelegate.m_delegateMethods.webViewDidClose)
1103         return;
1104
1105     auto delegate = m_uiDelegate.m_delegate.get();
1106     if (!delegate)
1107         return;
1108
1109     [delegate webViewDidClose:m_uiDelegate.m_webView];
1110 }
1111
1112 void UIDelegate::UIClient::fullscreenMayReturnToInline(WebPageProxy*)
1113 {
1114     if (!m_uiDelegate.m_delegateMethods.webViewFullscreenMayReturnToInline)
1115         return;
1116     
1117     auto delegate = m_uiDelegate.m_delegate.get();
1118     if (!delegate)
1119         return;
1120     
1121     [(id <WKUIDelegatePrivate>)delegate _webViewFullscreenMayReturnToInline:m_uiDelegate.m_webView];
1122 }
1123
1124 void UIDelegate::UIClient::didEnterFullscreen(WebPageProxy*)
1125 {
1126     if (!m_uiDelegate.m_delegateMethods.webViewDidEnterFullscreen)
1127         return;
1128
1129     auto delegate = m_uiDelegate.m_delegate.get();
1130     if (!delegate)
1131         return;
1132
1133     [(id <WKUIDelegatePrivate>)delegate _webViewDidEnterFullscreen:m_uiDelegate.m_webView];
1134 }
1135
1136 void UIDelegate::UIClient::didExitFullscreen(WebPageProxy*)
1137 {
1138     if (!m_uiDelegate.m_delegateMethods.webViewDidExitFullscreen)
1139         return;
1140
1141     auto delegate = m_uiDelegate.m_delegate.get();
1142     if (!delegate)
1143         return;
1144
1145     [(id <WKUIDelegatePrivate>)delegate _webViewDidExitFullscreen:m_uiDelegate.m_webView];
1146 }
1147     
1148 #if PLATFORM(IOS_FAMILY)
1149 #if HAVE(APP_LINKS)
1150 bool UIDelegate::UIClient::shouldIncludeAppLinkActionsForElement(_WKActivatedElementInfo *elementInfo)
1151 {
1152     if (!m_uiDelegate.m_delegateMethods.webViewShouldIncludeAppLinkActionsForElement)
1153         return true;
1154
1155     auto delegate = m_uiDelegate.m_delegate.get();
1156     if (!delegate)
1157         return true;
1158
1159     return [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView shouldIncludeAppLinkActionsForElement:elementInfo];
1160 }
1161 #endif
1162
1163 RetainPtr<NSArray> UIDelegate::UIClient::actionsForElement(_WKActivatedElementInfo *elementInfo, RetainPtr<NSArray> defaultActions)
1164 {
1165     if (!m_uiDelegate.m_delegateMethods.webViewActionsForElementDefaultActions)
1166         return defaultActions;
1167
1168     auto delegate = m_uiDelegate.m_delegate.get();
1169     if (!delegate)
1170         return defaultActions;
1171
1172     return [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView actionsForElement:elementInfo defaultActions:defaultActions.get()];
1173 }
1174
1175 void UIDelegate::UIClient::didNotHandleTapAsClick(const WebCore::IntPoint& point)
1176 {
1177     if (!m_uiDelegate.m_delegateMethods.webViewDidNotHandleTapAsClickAtPoint)
1178         return;
1179
1180     auto delegate = m_uiDelegate.m_delegate.get();
1181     if (!delegate)
1182         return;
1183
1184     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webView:m_uiDelegate.m_webView didNotHandleTapAsClickAtPoint:point];
1185 }
1186
1187 UIViewController *UIDelegate::UIClient::presentingViewController()
1188 {
1189     if (!m_uiDelegate.m_delegateMethods.presentingViewControllerForWebView)
1190         return nullptr;
1191
1192     auto delegate = m_uiDelegate.m_delegate.get();
1193     if (!delegate)
1194         return nullptr;
1195
1196     return [static_cast<id <WKUIDelegatePrivate>>(delegate) _presentingViewControllerForWebView:m_uiDelegate.m_webView];
1197 }
1198
1199 #endif
1200
1201 NSDictionary *UIDelegate::UIClient::dataDetectionContext()
1202 {
1203     if (!m_uiDelegate.m_delegateMethods.dataDetectionContextForWebView)
1204         return nullptr;
1205
1206     auto delegate = m_uiDelegate.m_delegate.get();
1207     if (!delegate)
1208         return nullptr;
1209
1210     return [static_cast<id <WKUIDelegatePrivate>>(delegate) _dataDetectionContextForWebView:m_uiDelegate.m_webView];
1211 }
1212
1213 #if ENABLE(POINTER_LOCK)
1214
1215 void UIDelegate::UIClient::requestPointerLock(WebPageProxy* page)
1216 {
1217     if (!m_uiDelegate.m_delegateMethods.webViewRequestPointerLock && !m_uiDelegate.m_delegateMethods.webViewDidRequestPointerLockCompletionHandler)
1218         return;
1219
1220     auto delegate = m_uiDelegate.m_delegate.get();
1221     if (!delegate)
1222         return;
1223
1224     if (m_uiDelegate.m_delegateMethods.webViewRequestPointerLock) {
1225         [static_cast<id <WKUIDelegatePrivate>>(delegate) _webViewRequestPointerLock:m_uiDelegate.m_webView];
1226         return;
1227     }
1228
1229     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webViewDidRequestPointerLock:completionHandler:));
1230     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webViewDidRequestPointerLock:m_uiDelegate.m_webView completionHandler:makeBlockPtr([checker = WTFMove(checker), page = makeRefPtr(page)] (BOOL allow) {
1231         if (checker->completionHandlerHasBeenCalled())
1232             return;
1233         checker->didCallCompletionHandler();
1234
1235         if (allow)
1236             page->didAllowPointerLock();
1237         else
1238             page->didDenyPointerLock();
1239     }).get()];
1240 }
1241
1242 void UIDelegate::UIClient::didLosePointerLock(WebPageProxy*)
1243 {
1244     if (!m_uiDelegate.m_delegateMethods.webViewDidLosePointerLock)
1245         return;
1246
1247     auto delegate = m_uiDelegate.m_delegate.get();
1248     if (!delegate)
1249         return;
1250
1251     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webViewDidLosePointerLock:m_uiDelegate.m_webView];
1252 }
1253
1254 #endif
1255     
1256 void UIDelegate::UIClient::didShowSafeBrowsingWarning()
1257 {
1258     if (!m_uiDelegate.m_delegateMethods.webViewDidShowSafeBrowsingWarning)
1259         return;
1260
1261     auto delegate = m_uiDelegate.m_delegate.get();
1262     if (!delegate)
1263         return;
1264
1265     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webViewDidShowSafeBrowsingWarning:m_uiDelegate.m_webView];
1266 }
1267
1268 void UIDelegate::UIClient::hasVideoInPictureInPictureDidChange(WebPageProxy*, bool hasVideoInPictureInPicture)
1269 {
1270     if (!m_uiDelegate.m_delegateMethods.webViewHasVideoInPictureInPictureDidChange)
1271         return;
1272     
1273     auto delegate = m_uiDelegate.m_delegate.get();
1274     if (!delegate)
1275         return;
1276     
1277     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webView:m_uiDelegate.m_webView hasVideoInPictureInPictureDidChange:hasVideoInPictureInPicture];
1278 }
1279
1280 void UIDelegate::UIClient::imageOrMediaDocumentSizeChanged(const WebCore::IntSize& newSize)
1281 {
1282     if (!m_uiDelegate.m_delegateMethods.webViewImageOrMediaDocumentSizeChanged)
1283         return;
1284
1285     auto delegate = m_uiDelegate.m_delegate.get();
1286     if (!delegate)
1287         return;
1288
1289     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webView:m_uiDelegate.m_webView imageOrMediaDocumentSizeChanged:newSize];
1290 }
1291
1292 } // namespace WebKit