Make WebEvent::Modifiers an OptionSet
[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     m_delegateMethods.webViewDidClickGoBackFromSafeBrowsingWarning = [delegate respondsToSelector:@selector(_webViewDidClickGoBackFromSafeBrowsingWarning:)];
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 static NSEventModifierFlags toNSEventModifierFlags(OptionSet<WebEvent::Modifier> modifiers)
691 {
692     NSEventModifierFlags flags = 0;
693     if (modifiers.contains(WebEvent::Modifier::ShiftKey))
694         flags |= NSEventModifierFlagShift;
695     if (modifiers.contains(WebEvent::Modifier::ControlKey))
696         flags |= NSEventModifierFlagControl;
697     if (modifiers.contains(WebEvent::Modifier::AltKey))
698         flags |= NSEventModifierFlagOption;
699     if (modifiers.contains(WebEvent::Modifier::MetaKey))
700         flags |= NSEventModifierFlagCommand;
701     if (modifiers.contains(WebEvent::CapsLockKey))
702         flags |= NSEventModifierFlagCapsLock;
703     return flags;
704 }
705
706 void UIDelegate::UIClient::mouseDidMoveOverElement(WebPageProxy&, const WebHitTestResultData& data, OptionSet<WebEvent::Modifier> modifiers, API::Object* userInfo)
707 {
708     if (!m_uiDelegate.m_delegateMethods.webViewMouseDidMoveOverElementWithFlagsUserInfo)
709         return;
710
711     auto delegate = m_uiDelegate.m_delegate.get();
712     if (!delegate)
713         return;
714
715     auto apiHitTestResult = API::HitTestResult::create(data);
716     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView mouseDidMoveOverElement:wrapper(apiHitTestResult.get()) withFlags:toNSEventModifierFlags(modifiers) userInfo:userInfo ? static_cast<id <NSSecureCoding>>(userInfo->wrapper()) : nil];
717 }
718
719 static _WKAutoplayEventFlags toWKAutoplayEventFlags(OptionSet<WebCore::AutoplayEventFlags> flags)
720 {
721     _WKAutoplayEventFlags wkFlags = _WKAutoplayEventFlagsNone;
722     if (flags.contains(WebCore::AutoplayEventFlags::HasAudio))
723         wkFlags |= _WKAutoplayEventFlagsHasAudio;
724     if (flags.contains(WebCore::AutoplayEventFlags::PlaybackWasPrevented))
725         wkFlags |= _WKAutoplayEventFlagsPlaybackWasPrevented;
726     if (flags.contains(WebCore::AutoplayEventFlags::MediaIsMainContent))
727         wkFlags |= _WKAutoplayEventFlagsMediaIsMainContent;
728     
729     return wkFlags;
730 }
731
732 static _WKAutoplayEvent toWKAutoplayEvent(WebCore::AutoplayEvent event)
733 {
734     switch (event) {
735     case WebCore::AutoplayEvent::DidPreventMediaFromPlaying:
736         return _WKAutoplayEventDidPreventFromAutoplaying;
737     case WebCore::AutoplayEvent::DidPlayMediaWithUserGesture:
738         return _WKAutoplayEventDidPlayMediaWithUserGesture;
739     case WebCore::AutoplayEvent::DidAutoplayMediaPastThresholdWithoutUserInterference:
740         return _WKAutoplayEventDidAutoplayMediaPastThresholdWithoutUserInterference;
741     case WebCore::AutoplayEvent::UserDidInterfereWithPlayback:
742         return _WKAutoplayEventUserDidInterfereWithPlayback;
743     }
744     ASSERT_NOT_REACHED();
745     return _WKAutoplayEventDidPlayMediaWithUserGesture;
746 }
747
748 void UIDelegate::UIClient::toolbarsAreVisible(WebPageProxy&, Function<void(bool)>&& completionHandler)
749 {
750     if (!m_uiDelegate.m_delegateMethods.webViewGetToolbarsAreVisibleWithCompletionHandler)
751         return completionHandler(true);
752     
753     auto delegate = m_uiDelegate.m_delegate.get();
754     if (!delegate)
755         return completionHandler(true);
756     
757     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView getToolbarsAreVisibleWithCompletionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:getToolbarsAreVisibleWithCompletionHandler:))](BOOL visible) {
758         if (checker->completionHandlerHasBeenCalled())
759             return;
760         checker->didCallCompletionHandler();
761         completionHandler(visible);
762     }).get()];
763 }
764
765 void UIDelegate::UIClient::didClickAutoFillButton(WebPageProxy&, API::Object* userInfo)
766 {
767     if (!m_uiDelegate.m_delegateMethods.webViewDidClickAutoFillButtonWithUserInfo)
768         return;
769     
770     auto delegate = m_uiDelegate.m_delegate.get();
771     if (!delegate)
772         return;
773     
774     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView didClickAutoFillButtonWithUserInfo:userInfo ? static_cast<id <NSSecureCoding>>(userInfo->wrapper()) : nil];
775 }
776
777 void UIDelegate::UIClient::handleAutoplayEvent(WebPageProxy&, WebCore::AutoplayEvent event, OptionSet<WebCore::AutoplayEventFlags> flags)
778 {
779     if (!m_uiDelegate.m_delegateMethods.webViewHandleAutoplayEventWithFlags)
780         return;
781     
782     auto delegate = m_uiDelegate.m_delegate.get();
783     if (!delegate)
784         return;
785     
786     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView handleAutoplayEvent:toWKAutoplayEvent(event) withFlags:toWKAutoplayEventFlags(flags)];
787 }
788
789 void UIDelegate::UIClient::showPage(WebPageProxy*)
790 {
791     if (!m_uiDelegate.m_delegateMethods.showWebView)
792         return;
793
794     auto delegate = m_uiDelegate.m_delegate.get();
795     if (!delegate)
796         return;
797     
798     [(id <WKUIDelegatePrivate>)delegate _showWebView:m_uiDelegate.m_webView];
799 }
800     
801 void UIDelegate::UIClient::saveDataToFileInDownloadsFolder(WebPageProxy*, const WTF::String& suggestedFilename, const WTF::String& mimeType, const URL& originatingURL, API::Data& data)
802 {
803     if (!m_uiDelegate.m_delegateMethods.webViewSaveDataToFileSuggestedFilenameMimeTypeOriginatingURL)
804         return;
805     
806     auto delegate = m_uiDelegate.m_delegate.get();
807     if (!delegate)
808         return;
809
810     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView saveDataToFile:wrapper(data) suggestedFilename:suggestedFilename mimeType:mimeType originatingURL:originatingURL];
811 }
812
813 void UIDelegate::UIClient::decidePolicyForNotificationPermissionRequest(WebKit::WebPageProxy&, API::SecurityOrigin& securityOrigin, WTF::Function<void(bool)>&& completionHandler)
814 {
815     if (!m_uiDelegate.m_delegateMethods.webViewRequestNotificationPermissionForSecurityOriginDecisionHandler)
816         return completionHandler(false);
817     
818     auto delegate = m_uiDelegate.m_delegate.get();
819     if (!delegate)
820         return completionHandler(false);
821
822     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:requestNotificationPermissionForSecurityOrigin:decisionHandler:));
823     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView requestNotificationPermissionForSecurityOrigin:wrapper(securityOrigin) decisionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)] (BOOL result) mutable {
824         if (checker->completionHandlerHasBeenCalled())
825             return;
826         checker->didCallCompletionHandler();
827         completionHandler(result);
828     }).get()];
829 }
830
831 bool UIDelegate::UIClient::runOpenPanel(WebPageProxy*, WebFrameProxy* webFrameProxy, const WebCore::SecurityOriginData& securityOriginData, API::OpenPanelParameters* openPanelParameters, WebOpenPanelResultListenerProxy* listener)
832 {
833     if (!m_uiDelegate.m_delegateMethods.webViewRunOpenPanelWithParametersInitiatedByFrameCompletionHandler)
834         return false;
835
836     auto delegate = m_uiDelegate.m_delegate.get();
837     if (!delegate)
838         return false;
839
840     auto frame = API::FrameInfo::create(*webFrameProxy, securityOriginData.securityOrigin());
841
842     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(webView:runOpenPanelWithParameters:initiatedByFrame:completionHandler:));
843
844     [delegate webView:m_uiDelegate.m_webView runOpenPanelWithParameters:wrapper(*openPanelParameters) initiatedByFrame:wrapper(frame) completionHandler:makeBlockPtr([checker = WTFMove(checker), listener = WTFMove(listener)] (NSArray *URLs) mutable {
845         if (checker->completionHandlerHasBeenCalled())
846             return;
847         checker->didCallCompletionHandler();
848
849         if (!URLs) {
850             listener->cancel();
851             return;
852         }
853
854         Vector<String> filenames;
855         for (NSURL *url in URLs)
856             filenames.append(url.path);
857
858         listener->chooseFiles(filenames);
859     }).get()];
860
861     return true;
862 }
863 #endif
864
865 void UIDelegate::UIClient::didChangeFontAttributes(const WebCore::FontAttributes& fontAttributes)
866 {
867     if (!needsFontAttributes())
868         return;
869
870     auto privateUIDelegate = (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get();
871     [privateUIDelegate _webView:m_uiDelegate.m_webView didChangeFontAttributes:fontAttributes.createDictionary().get()];
872 }
873
874 #if ENABLE(MEDIA_STREAM)
875 static void requestUserMediaAuthorizationForFrame(const WebFrameProxy& frame, API::SecurityOrigin& topLevelOrigin, UserMediaPermissionRequestProxy& request, id <WKUIDelegatePrivate> delegate, WKWebView& webView)
876 {
877     auto checker = CompletionHandlerCallChecker::create(delegate, @selector(_webView:requestMediaCaptureAuthorization:decisionHandler:));
878     auto decisionHandler = makeBlockPtr([protectedRequest = makeRef(request), checker = WTFMove(checker)](BOOL authorized) {
879         if (checker->completionHandlerHasBeenCalled())
880             return;
881         checker->didCallCompletionHandler();
882
883         if (!authorized) {
884             protectedRequest->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
885             return;
886         }
887         const String& videoDeviceUID = (protectedRequest->requiresVideoCapture() || protectedRequest->requiresDisplayCapture()) ? protectedRequest->videoDeviceUIDs().first() : String();
888         const String& audioDeviceUID = protectedRequest->requiresAudioCapture() ? protectedRequest->audioDeviceUIDs().first() : String();
889         protectedRequest->allow(audioDeviceUID, videoDeviceUID);
890     });
891
892     _WKCaptureDevices devices = 0;
893     if (request.requiresAudioCapture())
894         devices |= _WKCaptureDeviceMicrophone;
895     if (request.requiresVideoCapture())
896         devices |= _WKCaptureDeviceCamera;
897     if (request.requiresDisplayCapture()) {
898         devices |= _WKCaptureDeviceDisplay;
899         ASSERT(!(devices & _WKCaptureDeviceCamera));
900     }
901
902     const auto* mainFrame = frame.page()->mainFrame();
903
904     // FIXME: Provide a specific delegate for display capture.
905     if (!request.requiresDisplayCapture() && [delegate respondsToSelector:@selector(_webView:requestMediaCaptureAuthorization:decisionHandler:)]) {
906
907         [delegate _webView:&webView requestMediaCaptureAuthorization:devices decisionHandler:decisionHandler.get()];
908         return;
909     }
910
911     URL requestFrameURL { URL(), frame.url() };
912     URL mainFrameURL { URL(), mainFrame->url() };
913
914     [delegate _webView:&webView requestUserMediaAuthorizationForDevices:devices url:requestFrameURL mainFrameURL:mainFrameURL decisionHandler:decisionHandler.get()];
915 }
916 #endif
917
918 void UIDelegate::UIClient::decidePolicyForUserMediaPermissionRequest(WebPageProxy& page, WebFrameProxy& frame, API::SecurityOrigin& userMediaOrigin, API::SecurityOrigin& topLevelOrigin, UserMediaPermissionRequestProxy& request)
919 {
920 #if ENABLE(MEDIA_STREAM)
921     auto delegate = m_uiDelegate.m_delegate.get();
922     if (!delegate || !m_uiDelegate.m_delegateMethods.webViewRequestMediaCaptureAuthorizationForFrameDecisionHandler) {
923         request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::UserMediaDisabled);
924         return;
925     }
926
927     bool requiresAudioCapture = request.requiresAudioCapture();
928     bool requiresVideoCapture = request.requiresVideoCapture();
929     bool requiresDisplayCapture = request.requiresDisplayCapture();
930     if (!requiresAudioCapture && !requiresVideoCapture && !requiresDisplayCapture) {
931         request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::NoConstraints);
932         return;
933     }
934
935 #if HAVE(AUTHORIZATION_STATUS_FOR_MEDIA_TYPE)
936     bool usingMockCaptureDevices = page.preferences().mockCaptureDevicesEnabled();
937     auto requestCameraAuthorization = makeBlockPtr([this, &frame, protectedRequest = makeRef(request), webView = RetainPtr<WKWebView>(m_uiDelegate.m_webView), topLevelOrigin = makeRef(topLevelOrigin), usingMockCaptureDevices]() mutable {
938
939         if (!protectedRequest->requiresVideoCapture()) {
940             requestUserMediaAuthorizationForFrame(frame, topLevelOrigin, protectedRequest, (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get(), *webView.get());
941             return;
942         }
943         AVAuthorizationStatus cameraAuthorizationStatus = usingMockCaptureDevices ? AVAuthorizationStatusAuthorized : [getAVCaptureDeviceClass() authorizationStatusForMediaType:getAVMediaTypeVideo()];
944         switch (cameraAuthorizationStatus) {
945         case AVAuthorizationStatusAuthorized:
946             requestUserMediaAuthorizationForFrame(frame, topLevelOrigin, protectedRequest, (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get(), *webView.get());
947             break;
948         case AVAuthorizationStatusDenied:
949         case AVAuthorizationStatusRestricted:
950             protectedRequest->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
951             return;
952         case AVAuthorizationStatusNotDetermined:
953             auto decisionHandler = makeBlockPtr([this, &frame, protectedRequest = makeRef(protectedRequest.get()), webView = RetainPtr<WKWebView>(m_uiDelegate.m_webView), topLevelOrigin = WTFMove(topLevelOrigin)](BOOL authorized) {
954                 if (!authorized) {
955                     protectedRequest->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
956                     return;
957                 }
958                 requestUserMediaAuthorizationForFrame(frame, topLevelOrigin, protectedRequest, (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get(), *webView.get());
959             });
960
961             [getAVCaptureDeviceClass() requestAccessForMediaType:getAVMediaTypeVideo() completionHandler:decisionHandler.get()];
962             break;
963         }
964     });
965
966     if (requiresAudioCapture) {
967         AVAuthorizationStatus microphoneAuthorizationStatus = usingMockCaptureDevices ? AVAuthorizationStatusAuthorized : [getAVCaptureDeviceClass() authorizationStatusForMediaType:getAVMediaTypeAudio()];
968         switch (microphoneAuthorizationStatus) {
969         case AVAuthorizationStatusAuthorized:
970             requestCameraAuthorization();
971             break;
972         case AVAuthorizationStatusDenied:
973         case AVAuthorizationStatusRestricted:
974             request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
975             return;
976         case AVAuthorizationStatusNotDetermined:
977             auto decisionHandler = makeBlockPtr([protectedRequest = makeRef(request), requestCameraAuthorization](BOOL authorized) {
978                 if (!authorized) {
979                     protectedRequest->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
980                     return;
981                 }
982                 requestCameraAuthorization();
983             });
984
985             [getAVCaptureDeviceClass() requestAccessForMediaType:getAVMediaTypeAudio() completionHandler:decisionHandler.get()];
986             break;
987         }
988     } else
989         requestCameraAuthorization();
990 #else
991     requestUserMediaAuthorizationForFrame(frame, topLevelOrigin, request, (id <WKUIDelegatePrivate>)m_uiDelegate.m_delegate.get(), *m_uiDelegate.m_webView);
992 #endif
993 #endif
994 }
995
996 void UIDelegate::UIClient::checkUserMediaPermissionForOrigin(WebPageProxy& page, WebFrameProxy& frame, API::SecurityOrigin& userMediaOrigin, API::SecurityOrigin& topLevelOrigin, UserMediaPermissionCheckProxy& request)
997 {
998     auto delegate = m_uiDelegate.m_delegate.get();
999     if (!delegate || !m_uiDelegate.m_delegateMethods.webViewIsMediaCaptureAuthorizedForFrameDecisionHandler) {
1000         request.setUserMediaAccessInfo(false);
1001         return;
1002     }
1003
1004     const auto* mainFrame = frame.page()->mainFrame();
1005
1006     if ([delegate respondsToSelector:@selector(_webView:includeSensitiveMediaDeviceDetails:)]) {
1007         auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:includeSensitiveMediaDeviceDetails:));
1008         auto decisionHandler = makeBlockPtr([protectedRequest = makeRef(request), checker = WTFMove(checker)](BOOL includeSensitiveDetails) {
1009             if (checker->completionHandlerHasBeenCalled())
1010                 return;
1011             checker->didCallCompletionHandler();
1012
1013             protectedRequest->setUserMediaAccessInfo(includeSensitiveDetails);
1014         });
1015
1016         [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView includeSensitiveMediaDeviceDetails:decisionHandler.get()];
1017         return;
1018     }
1019
1020     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:checkUserMediaPermissionForURL:mainFrameURL:frameIdentifier:decisionHandler:));
1021     auto decisionHandler = makeBlockPtr([protectedRequest = makeRef(request), checker = WTFMove(checker)](NSString*, BOOL authorized) {
1022         if (checker->completionHandlerHasBeenCalled())
1023             return;
1024         checker->didCallCompletionHandler();
1025
1026         protectedRequest->setUserMediaAccessInfo(authorized);
1027     });
1028
1029     URL requestFrameURL { URL(), frame.url() };
1030     URL mainFrameURL { URL(), mainFrame->url() };
1031
1032     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView checkUserMediaPermissionForURL:requestFrameURL mainFrameURL:mainFrameURL frameIdentifier:frame.frameID() decisionHandler:decisionHandler.get()];
1033 }
1034
1035 void UIDelegate::UIClient::mediaCaptureStateDidChange(WebCore::MediaProducer::MediaStateFlags state)
1036 {
1037     WKWebView *webView = m_uiDelegate.m_webView;
1038
1039     [webView didChangeValueForKey:@"mediaCaptureState"];
1040
1041     auto delegate = m_uiDelegate.m_delegate.get();
1042     if (!delegate || !m_uiDelegate.m_delegateMethods.webViewMediaCaptureStateDidChange)
1043         return;
1044
1045     [(id <WKUIDelegatePrivate>)delegate _webView:webView mediaCaptureStateDidChange:toWKMediaCaptureState(state)];
1046 }
1047
1048 void UIDelegate::UIClient::reachedApplicationCacheOriginQuota(WebPageProxy*, const WebCore::SecurityOrigin& securityOrigin, uint64_t currentQuota, uint64_t totalBytesNeeded, Function<void (unsigned long long)>&& completionHandler)
1049 {
1050     if (!m_uiDelegate.m_delegateMethods.webViewDecideWebApplicationCacheQuotaForSecurityOriginCurrentQuotaTotalBytesNeeded) {
1051         completionHandler(currentQuota);
1052         return;
1053     }
1054
1055     auto delegate = m_uiDelegate.m_delegate.get();
1056     if (!delegate) {
1057         completionHandler(currentQuota);
1058         return;
1059     }
1060
1061     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:decideWebApplicationCacheQuotaForSecurityOrigin:currentQuota:totalBytesNeeded:decisionHandler:));
1062     auto apiOrigin = API::SecurityOrigin::create(securityOrigin);
1063     
1064     [(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) {
1065         if (checker->completionHandlerHasBeenCalled())
1066             return;
1067         checker->didCallCompletionHandler();
1068         completionHandler(newQuota);
1069     }).get()];
1070 }
1071
1072 void UIDelegate::UIClient::printFrame(WebPageProxy&, WebFrameProxy& webFrameProxy)
1073 {
1074     if (!m_uiDelegate.m_delegateMethods.webViewPrintFrame)
1075         return;
1076
1077     auto delegate = m_uiDelegate.m_delegate.get();
1078     if (!delegate)
1079         return;
1080
1081     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView printFrame:wrapper(API::FrameHandle::create(webFrameProxy.frameID()))];
1082 }
1083
1084 void UIDelegate::UIClient::close(WebPageProxy*)
1085 {
1086     if (m_uiDelegate.m_delegateMethods.webViewClose) {
1087         auto delegate = m_uiDelegate.m_delegate.get();
1088         if (!delegate)
1089             return;
1090
1091         [(id <WKUIDelegatePrivate>)delegate _webViewClose:m_uiDelegate.m_webView];
1092         return;
1093     }
1094
1095     if (!m_uiDelegate.m_delegateMethods.webViewDidClose)
1096         return;
1097
1098     auto delegate = m_uiDelegate.m_delegate.get();
1099     if (!delegate)
1100         return;
1101
1102     [delegate webViewDidClose:m_uiDelegate.m_webView];
1103 }
1104
1105 void UIDelegate::UIClient::fullscreenMayReturnToInline(WebPageProxy*)
1106 {
1107     if (!m_uiDelegate.m_delegateMethods.webViewFullscreenMayReturnToInline)
1108         return;
1109     
1110     auto delegate = m_uiDelegate.m_delegate.get();
1111     if (!delegate)
1112         return;
1113     
1114     [(id <WKUIDelegatePrivate>)delegate _webViewFullscreenMayReturnToInline:m_uiDelegate.m_webView];
1115 }
1116
1117 void UIDelegate::UIClient::didEnterFullscreen(WebPageProxy*)
1118 {
1119     if (!m_uiDelegate.m_delegateMethods.webViewDidEnterFullscreen)
1120         return;
1121
1122     auto delegate = m_uiDelegate.m_delegate.get();
1123     if (!delegate)
1124         return;
1125
1126     [(id <WKUIDelegatePrivate>)delegate _webViewDidEnterFullscreen:m_uiDelegate.m_webView];
1127 }
1128
1129 void UIDelegate::UIClient::didExitFullscreen(WebPageProxy*)
1130 {
1131     if (!m_uiDelegate.m_delegateMethods.webViewDidExitFullscreen)
1132         return;
1133
1134     auto delegate = m_uiDelegate.m_delegate.get();
1135     if (!delegate)
1136         return;
1137
1138     [(id <WKUIDelegatePrivate>)delegate _webViewDidExitFullscreen:m_uiDelegate.m_webView];
1139 }
1140     
1141 #if PLATFORM(IOS_FAMILY)
1142 #if HAVE(APP_LINKS)
1143 bool UIDelegate::UIClient::shouldIncludeAppLinkActionsForElement(_WKActivatedElementInfo *elementInfo)
1144 {
1145     if (!m_uiDelegate.m_delegateMethods.webViewShouldIncludeAppLinkActionsForElement)
1146         return true;
1147
1148     auto delegate = m_uiDelegate.m_delegate.get();
1149     if (!delegate)
1150         return true;
1151
1152     return [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView shouldIncludeAppLinkActionsForElement:elementInfo];
1153 }
1154 #endif
1155
1156 RetainPtr<NSArray> UIDelegate::UIClient::actionsForElement(_WKActivatedElementInfo *elementInfo, RetainPtr<NSArray> defaultActions)
1157 {
1158     if (!m_uiDelegate.m_delegateMethods.webViewActionsForElementDefaultActions)
1159         return defaultActions;
1160
1161     auto delegate = m_uiDelegate.m_delegate.get();
1162     if (!delegate)
1163         return defaultActions;
1164
1165     return [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView actionsForElement:elementInfo defaultActions:defaultActions.get()];
1166 }
1167
1168 void UIDelegate::UIClient::didNotHandleTapAsClick(const WebCore::IntPoint& point)
1169 {
1170     if (!m_uiDelegate.m_delegateMethods.webViewDidNotHandleTapAsClickAtPoint)
1171         return;
1172
1173     auto delegate = m_uiDelegate.m_delegate.get();
1174     if (!delegate)
1175         return;
1176
1177     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webView:m_uiDelegate.m_webView didNotHandleTapAsClickAtPoint:point];
1178 }
1179
1180 UIViewController *UIDelegate::UIClient::presentingViewController()
1181 {
1182     if (!m_uiDelegate.m_delegateMethods.presentingViewControllerForWebView)
1183         return nullptr;
1184
1185     auto delegate = m_uiDelegate.m_delegate.get();
1186     if (!delegate)
1187         return nullptr;
1188
1189     return [static_cast<id <WKUIDelegatePrivate>>(delegate) _presentingViewControllerForWebView:m_uiDelegate.m_webView];
1190 }
1191
1192 #endif
1193
1194 NSDictionary *UIDelegate::UIClient::dataDetectionContext()
1195 {
1196     if (!m_uiDelegate.m_delegateMethods.dataDetectionContextForWebView)
1197         return nullptr;
1198
1199     auto delegate = m_uiDelegate.m_delegate.get();
1200     if (!delegate)
1201         return nullptr;
1202
1203     return [static_cast<id <WKUIDelegatePrivate>>(delegate) _dataDetectionContextForWebView:m_uiDelegate.m_webView];
1204 }
1205
1206 #if ENABLE(POINTER_LOCK)
1207
1208 void UIDelegate::UIClient::requestPointerLock(WebPageProxy* page)
1209 {
1210     if (!m_uiDelegate.m_delegateMethods.webViewRequestPointerLock && !m_uiDelegate.m_delegateMethods.webViewDidRequestPointerLockCompletionHandler)
1211         return;
1212
1213     auto delegate = m_uiDelegate.m_delegate.get();
1214     if (!delegate)
1215         return;
1216
1217     if (m_uiDelegate.m_delegateMethods.webViewRequestPointerLock) {
1218         [static_cast<id <WKUIDelegatePrivate>>(delegate) _webViewRequestPointerLock:m_uiDelegate.m_webView];
1219         return;
1220     }
1221
1222     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webViewDidRequestPointerLock:completionHandler:));
1223     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webViewDidRequestPointerLock:m_uiDelegate.m_webView completionHandler:makeBlockPtr([checker = WTFMove(checker), page = makeRefPtr(page)] (BOOL allow) {
1224         if (checker->completionHandlerHasBeenCalled())
1225             return;
1226         checker->didCallCompletionHandler();
1227
1228         if (allow)
1229             page->didAllowPointerLock();
1230         else
1231             page->didDenyPointerLock();
1232     }).get()];
1233 }
1234
1235 void UIDelegate::UIClient::didLosePointerLock(WebPageProxy*)
1236 {
1237     if (!m_uiDelegate.m_delegateMethods.webViewDidLosePointerLock)
1238         return;
1239
1240     auto delegate = m_uiDelegate.m_delegate.get();
1241     if (!delegate)
1242         return;
1243
1244     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webViewDidLosePointerLock:m_uiDelegate.m_webView];
1245 }
1246
1247 #endif
1248     
1249 void UIDelegate::UIClient::didShowSafeBrowsingWarning()
1250 {
1251     if (!m_uiDelegate.m_delegateMethods.webViewDidShowSafeBrowsingWarning)
1252         return;
1253
1254     auto delegate = m_uiDelegate.m_delegate.get();
1255     if (!delegate)
1256         return;
1257
1258     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webViewDidShowSafeBrowsingWarning:m_uiDelegate.m_webView];
1259 }
1260
1261 void UIDelegate::UIClient::didClickGoBackFromSafeBrowsingWarning()
1262 {
1263     if (!m_uiDelegate.m_delegateMethods.webViewDidClickGoBackFromSafeBrowsingWarning)
1264         return;
1265     
1266     auto delegate = m_uiDelegate.m_delegate.get();
1267     if (!delegate)
1268         return;
1269
1270     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webViewDidClickGoBackFromSafeBrowsingWarning:m_uiDelegate.m_webView];
1271 }
1272
1273 void UIDelegate::UIClient::hasVideoInPictureInPictureDidChange(WebPageProxy*, bool hasVideoInPictureInPicture)
1274 {
1275     if (!m_uiDelegate.m_delegateMethods.webViewHasVideoInPictureInPictureDidChange)
1276         return;
1277     
1278     auto delegate = m_uiDelegate.m_delegate.get();
1279     if (!delegate)
1280         return;
1281     
1282     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webView:m_uiDelegate.m_webView hasVideoInPictureInPictureDidChange:hasVideoInPictureInPicture];
1283 }
1284
1285 void UIDelegate::UIClient::imageOrMediaDocumentSizeChanged(const WebCore::IntSize& newSize)
1286 {
1287     if (!m_uiDelegate.m_delegateMethods.webViewImageOrMediaDocumentSizeChanged)
1288         return;
1289
1290     auto delegate = m_uiDelegate.m_delegate.get();
1291     if (!delegate)
1292         return;
1293
1294     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webView:m_uiDelegate.m_webView imageOrMediaDocumentSizeChanged:newSize];
1295 }
1296
1297 } // namespace WebKit
1298
1299 #endif // WK_API_ENABLED