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