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