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