2 * Copyright (C) 2014-2016 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #import "UIDelegate.h"
31 #import "APIFrameInfo.h"
32 #import "CompletionHandlerCallChecker.h"
33 #import "NavigationActionData.h"
34 #import "UserMediaPermissionCheckProxy.h"
35 #import "UserMediaPermissionRequestProxy.h"
36 #import "WKFrameInfoInternal.h"
37 #import "WKNavigationActionInternal.h"
38 #import "WKOpenPanelParametersInternal.h"
39 #import "WKSecurityOriginInternal.h"
40 #import "WKUIDelegatePrivate.h"
41 #import "WKWebViewConfigurationInternal.h"
42 #import "WKWebViewInternal.h"
43 #import "WKWindowFeaturesInternal.h"
44 #import "WebOpenPanelResultListenerProxy.h"
45 #import "WebProcessProxy.h"
46 #import "_WKContextMenuElementInfo.h"
47 #import "_WKFrameHandleInternal.h"
48 #import <WebCore/SecurityOriginData.h>
49 #import <WebCore/URL.h>
50 #import <wtf/BlockPtr.h>
53 #import <AVFoundation/AVCaptureDevice.h>
54 #import <AVFoundation/AVMediaFormat.h>
55 #import <WebCore/SoftLinking.h>
57 SOFT_LINK_FRAMEWORK(AVFoundation);
58 SOFT_LINK_CLASS(AVFoundation, AVCaptureDevice);
59 SOFT_LINK_CONSTANT(AVFoundation, AVMediaTypeAudio, NSString *);
60 SOFT_LINK_CONSTANT(AVFoundation, AVMediaTypeVideo, NSString *);
65 UIDelegate::UIDelegate(WKWebView *webView)
70 UIDelegate::~UIDelegate()
74 #if ENABLE(CONTEXT_MENUS)
75 std::unique_ptr<API::ContextMenuClient> UIDelegate::createContextMenuClient()
77 return std::make_unique<ContextMenuClient>(*this);
81 std::unique_ptr<API::UIClient> UIDelegate::createUIClient()
83 return std::make_unique<UIClient>(*this);
86 RetainPtr<id <WKUIDelegate> > UIDelegate::delegate()
88 return m_delegate.get();
91 void UIDelegate::setDelegate(id <WKUIDelegate> delegate)
93 m_delegate = delegate;
95 m_delegateMethods.webViewCreateWebViewWithConfigurationForNavigationActionWindowFeatures = [delegate respondsToSelector:@selector(webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:)];
96 m_delegateMethods.webViewCreateWebViewWithConfigurationForNavigationActionWindowFeaturesAsync = [delegate respondsToSelector:@selector(_webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:completionHandler:)];
97 m_delegateMethods.webViewRunJavaScriptAlertPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:)];
98 m_delegateMethods.webViewRunJavaScriptConfirmPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:)];
99 m_delegateMethods.webViewRunJavaScriptTextInputPanelWithPromptDefaultTextInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:completionHandler:)];
100 m_delegateMethods.webViewRunBeforeUnloadConfirmPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(_webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:completionHandler:)];
103 m_delegateMethods.webViewRunOpenPanelWithParametersInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runOpenPanelWithParameters:initiatedByFrame:completionHandler:)];
106 m_delegateMethods.webViewDecideDatabaseQuotaForSecurityOriginCurrentQuotaCurrentOriginUsageCurrentDatabaseUsageExpectedUsageDecisionHandler = [delegate respondsToSelector:@selector(_webView:decideDatabaseQuotaForSecurityOrigin:currentQuota:currentOriginUsage:currentDatabaseUsage:expectedUsage:decisionHandler:)];
107 m_delegateMethods.webViewDecideWebApplicationCacheQuotaForSecurityOriginCurrentQuotaTotalBytesNeeded = [delegate respondsToSelector:@selector(_webView:decideWebApplicationCacheQuotaForSecurityOrigin:currentQuota:totalBytesNeeded:decisionHandler:)];
108 m_delegateMethods.webViewPrintFrame = [delegate respondsToSelector:@selector(_webView:printFrame:)];
109 m_delegateMethods.webViewDidClose = [delegate respondsToSelector:@selector(webViewDidClose:)];
110 m_delegateMethods.webViewClose = [delegate respondsToSelector:@selector(_webViewClose:)];
111 m_delegateMethods.webViewFullscreenMayReturnToInline = [delegate respondsToSelector:@selector(_webViewFullscreenMayReturnToInline:)];
112 m_delegateMethods.webViewDidEnterFullscreen = [delegate respondsToSelector:@selector(_webViewDidEnterFullscreen:)];
113 m_delegateMethods.webViewDidExitFullscreen = [delegate respondsToSelector:@selector(_webViewDidExitFullscreen:)];
116 m_delegateMethods.webViewShouldIncludeAppLinkActionsForElement = [delegate respondsToSelector:@selector(_webView:shouldIncludeAppLinkActionsForElement:)];
118 m_delegateMethods.webViewActionsForElementDefaultActions = [delegate respondsToSelector:@selector(_webView:actionsForElement:defaultActions:)];
119 m_delegateMethods.webViewDidNotHandleTapAsClickAtPoint = [delegate respondsToSelector:@selector(_webView:didNotHandleTapAsClickAtPoint:)];
120 m_delegateMethods.presentingViewControllerForWebView = [delegate respondsToSelector:@selector(_presentingViewControllerForWebView:)];
122 m_delegateMethods.webViewRequestUserMediaAuthorizationForDevicesURLMainFrameURLDecisionHandler = [delegate respondsToSelector:@selector(_webView:requestUserMediaAuthorizationForDevices:url:mainFrameURL:decisionHandler:)];
123 m_delegateMethods.webViewCheckUserMediaPermissionForURLMainFrameURLFrameIdentifierDecisionHandler = [delegate respondsToSelector:@selector(_webView:checkUserMediaPermissionForURL:mainFrameURL:frameIdentifier:decisionHandler:)];
124 m_delegateMethods.webViewMediaCaptureStateDidChange = [delegate respondsToSelector:@selector(_webView:mediaCaptureStateDidChange:)];
125 m_delegateMethods.dataDetectionContextForWebView = [delegate respondsToSelector:@selector(_dataDetectionContextForWebView:)];
126 m_delegateMethods.webViewImageOrMediaDocumentSizeChanged = [delegate respondsToSelector:@selector(_webView:imageOrMediaDocumentSizeChanged:)];
128 #if ENABLE(POINTER_LOCK)
129 m_delegateMethods.webViewRequestPointerLock = [delegate respondsToSelector:@selector(_webViewRequestPointerLock:)];
130 m_delegateMethods.webViewDidLosePointerLock = [delegate respondsToSelector:@selector(_webViewDidLosePointerLock:)];
132 #if ENABLE(CONTEXT_MENUS)
133 m_delegateMethods.webViewContextMenuForElement = [delegate respondsToSelector:@selector(_webView:contextMenu:forElement:)];
134 m_delegateMethods.webViewContextMenuForElementUserInfo = [delegate respondsToSelector:@selector(_webView:contextMenu:forElement:userInfo:)];
137 m_delegateMethods.webViewHasVideoInPictureInPictureDidChange = [delegate respondsToSelector:@selector(_webView:hasVideoInPictureInPictureDidChange:)];
140 #if ENABLE(CONTEXT_MENUS)
141 UIDelegate::ContextMenuClient::ContextMenuClient(UIDelegate& uiDelegate)
142 : m_uiDelegate(uiDelegate)
146 UIDelegate::ContextMenuClient::~ContextMenuClient()
150 RetainPtr<NSMenu> UIDelegate::ContextMenuClient::menuFromProposedMenu(WebKit::WebPageProxy&, NSMenu *menu, const WebKit::WebHitTestResultData&, API::Object* userInfo)
152 if (!m_uiDelegate.m_delegateMethods.webViewContextMenuForElement && !m_uiDelegate.m_delegateMethods.webViewContextMenuForElementUserInfo)
155 auto delegate = m_uiDelegate.m_delegate.get();
159 auto contextMenuElementInfo = adoptNS([[_WKContextMenuElementInfo alloc] init]);
161 if (m_uiDelegate.m_delegateMethods.webViewContextMenuForElement)
162 return [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView contextMenu:menu forElement:contextMenuElementInfo.get()];
164 return [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView contextMenu:menu forElement:contextMenuElementInfo.get() userInfo:static_cast<id <NSSecureCoding>>(userInfo->wrapper())];
168 UIDelegate::UIClient::UIClient(UIDelegate& uiDelegate)
169 : m_uiDelegate(uiDelegate)
173 UIDelegate::UIClient::~UIClient()
177 RefPtr<WebKit::WebPageProxy> UIDelegate::UIClient::createNewPageCommon(WebKit::WebPageProxy* page, API::FrameInfo& sourceFrameInfo, const WebCore::ResourceRequest& request, const WebCore::WindowFeatures& windowFeatures, const WebKit::NavigationActionData& navigationActionData, WTF::Function<void (RefPtr<WebKit::WebPageProxy>)>&& completionHandler)
179 auto delegate = m_uiDelegate.m_delegate.get();
182 auto configuration = adoptNS([m_uiDelegate.m_webView->_configuration copy]);
183 [configuration _setRelatedWebView:m_uiDelegate.m_webView];
185 auto userInitiatedActivity = page->process().userInitiatedActivity(navigationActionData.userGestureTokenIdentifier);
186 bool shouldOpenAppLinks = !hostsAreEqual(sourceFrameInfo.request().url(), request.url());
187 auto apiNavigationAction = API::NavigationAction::create(navigationActionData, &sourceFrameInfo, nullptr, request, WebCore::URL(), shouldOpenAppLinks, userInitiatedActivity);
189 auto apiWindowFeatures = API::WindowFeatures::create(windowFeatures);
191 if (completionHandler) {
192 RefPtr<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:completionHandler:));
194 [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView createWebViewWithConfiguration:configuration.get() forNavigationAction:wrapper(apiNavigationAction) windowFeatures:wrapper(apiWindowFeatures) completionHandler:BlockPtr<void (WKWebView *)>::fromCallable([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker), relatedWebView = RetainPtr<WKWebView>(m_uiDelegate.m_webView)](WKWebView *webView) {
195 if (checker->completionHandlerHasBeenCalled())
197 checker->didCallCompletionHandler();
200 completionHandler(nullptr);
204 if ([webView->_configuration _relatedWebView] != relatedWebView.get())
205 [NSException raise:NSInternalInconsistencyException format:@"Returned WKWebView was not created with the given configuration."];
207 completionHandler(webView->_page.get());
213 RetainPtr<WKWebView> webView = [delegate webView:m_uiDelegate.m_webView createWebViewWithConfiguration:configuration.get() forNavigationAction:wrapper(apiNavigationAction) windowFeatures:wrapper(apiWindowFeatures)];
218 if ([webView->_configuration _relatedWebView] != m_uiDelegate.m_webView)
219 [NSException raise:NSInternalInconsistencyException format:@"Returned WKWebView was not created with the given configuration."];
221 return webView->_page.get();
224 RefPtr<WebKit::WebPageProxy> UIDelegate::UIClient::createNewPage(WebKit::WebPageProxy* page, API::FrameInfo& originatingFrameInfo, const WebCore::ResourceRequest& request, const WebCore::WindowFeatures& windowFeatures, const WebKit::NavigationActionData& navigationActionData)
226 if (!m_uiDelegate.m_delegateMethods.webViewCreateWebViewWithConfigurationForNavigationActionWindowFeatures)
229 auto delegate = m_uiDelegate.m_delegate.get();
233 return createNewPageCommon(page, originatingFrameInfo, request, windowFeatures, navigationActionData, nullptr);
236 bool UIDelegate::UIClient::createNewPageAsync(WebKit::WebPageProxy* page, API::FrameInfo& originatingFrameInfo, const WebCore::ResourceRequest& request, const WebCore::WindowFeatures& windowFeatures, const WebKit::NavigationActionData& navigationActionData, WTF::Function<void (RefPtr<WebKit::WebPageProxy>)>&& completionHandler)
238 if (!m_uiDelegate.m_delegateMethods.webViewCreateWebViewWithConfigurationForNavigationActionWindowFeaturesAsync)
241 auto delegate = m_uiDelegate.m_delegate.get();
245 createNewPageCommon(page, originatingFrameInfo, request, windowFeatures, navigationActionData, WTFMove(completionHandler));
250 void UIDelegate::UIClient::runJavaScriptAlert(WebKit::WebPageProxy*, const WTF::String& message, WebKit::WebFrameProxy* webFrameProxy, const WebCore::SecurityOriginData& securityOriginData, Function<void ()>&& completionHandler)
252 if (!m_uiDelegate.m_delegateMethods.webViewRunJavaScriptAlertPanelWithMessageInitiatedByFrameCompletionHandler) {
257 auto delegate = m_uiDelegate.m_delegate.get();
263 RefPtr<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:));
264 [delegate webView:m_uiDelegate.m_webView runJavaScriptAlertPanelWithMessage:message initiatedByFrame:wrapper(API::FrameInfo::create(*webFrameProxy, securityOriginData.securityOrigin())) completionHandler:BlockPtr<void ()>::fromCallable([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)] {
265 if (checker->completionHandlerHasBeenCalled())
268 checker->didCallCompletionHandler();
272 void UIDelegate::UIClient::runJavaScriptConfirm(WebKit::WebPageProxy*, const WTF::String& message, WebKit::WebFrameProxy* webFrameProxy, const WebCore::SecurityOriginData& securityOriginData, Function<void (bool)>&& completionHandler)
274 if (!m_uiDelegate.m_delegateMethods.webViewRunJavaScriptConfirmPanelWithMessageInitiatedByFrameCompletionHandler) {
275 completionHandler(false);
279 auto delegate = m_uiDelegate.m_delegate.get();
281 completionHandler(false);
285 RefPtr<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:));
286 [delegate webView:m_uiDelegate.m_webView runJavaScriptConfirmPanelWithMessage:message initiatedByFrame:wrapper(API::FrameInfo::create(*webFrameProxy, securityOriginData.securityOrigin())) completionHandler:BlockPtr<void (BOOL)>::fromCallable([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)](BOOL result) {
287 if (checker->completionHandlerHasBeenCalled())
289 completionHandler(result);
290 checker->didCallCompletionHandler();
294 void UIDelegate::UIClient::runJavaScriptPrompt(WebKit::WebPageProxy*, const WTF::String& message, const WTF::String& defaultValue, WebKit::WebFrameProxy* webFrameProxy, const WebCore::SecurityOriginData& securityOriginData, Function<void (const WTF::String&)>&& completionHandler)
296 if (!m_uiDelegate.m_delegateMethods.webViewRunJavaScriptTextInputPanelWithPromptDefaultTextInitiatedByFrameCompletionHandler) {
297 completionHandler(String());
301 auto delegate = m_uiDelegate.m_delegate.get();
303 completionHandler(String());
307 RefPtr<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:completionHandler:));
308 [delegate webView:m_uiDelegate.m_webView runJavaScriptTextInputPanelWithPrompt:message defaultText:defaultValue initiatedByFrame:wrapper(API::FrameInfo::create(*webFrameProxy, securityOriginData.securityOrigin())) completionHandler:BlockPtr<void (NSString *)>::fromCallable([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)](NSString *result) {
309 if (checker->completionHandlerHasBeenCalled())
311 completionHandler(result);
312 checker->didCallCompletionHandler();
316 bool UIDelegate::UIClient::canRunBeforeUnloadConfirmPanel() const
318 return m_uiDelegate.m_delegateMethods.webViewRunBeforeUnloadConfirmPanelWithMessageInitiatedByFrameCompletionHandler;
321 void UIDelegate::UIClient::runBeforeUnloadConfirmPanel(WebKit::WebPageProxy*, const WTF::String& message, WebKit::WebFrameProxy* webFrameProxy, const WebCore::SecurityOriginData& securityOriginData, Function<void (bool)>&& completionHandler)
323 if (!m_uiDelegate.m_delegateMethods.webViewRunBeforeUnloadConfirmPanelWithMessageInitiatedByFrameCompletionHandler) {
324 completionHandler(false);
328 auto delegate = m_uiDelegate.m_delegate.get();
330 completionHandler(false);
334 RefPtr<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:completionHandler:));
335 [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView runBeforeUnloadConfirmPanelWithMessage:message initiatedByFrame:wrapper(API::FrameInfo::create(*webFrameProxy, securityOriginData.securityOrigin())) completionHandler:BlockPtr<void (BOOL)>::fromCallable([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)](BOOL result) {
336 if (checker->completionHandlerHasBeenCalled())
338 completionHandler(result);
339 checker->didCallCompletionHandler();
343 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)
345 if (!m_uiDelegate.m_delegateMethods.webViewDecideDatabaseQuotaForSecurityOriginCurrentQuotaCurrentOriginUsageCurrentDatabaseUsageExpectedUsageDecisionHandler) {
347 // Use 50 MB as the default database quota.
348 unsigned long long defaultPerOriginDatabaseQuota = 50 * 1024 * 1024;
350 completionHandler(defaultPerOriginDatabaseQuota);
354 auto delegate = m_uiDelegate.m_delegate.get();
356 completionHandler(currentQuota);
360 ASSERT(securityOrigin);
361 RefPtr<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:decideDatabaseQuotaForSecurityOrigin:currentQuota:currentOriginUsage:currentDatabaseUsage:expectedUsage:decisionHandler:));
362 [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView decideDatabaseQuotaForSecurityOrigin:wrapper(*securityOrigin) currentQuota:currentQuota currentOriginUsage:currentOriginUsage currentDatabaseUsage:currentUsage expectedUsage:expectedUsage decisionHandler:BlockPtr<void (unsigned long long newQuota)>::fromCallable([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)](unsigned long long newQuota) {
363 if (checker->completionHandlerHasBeenCalled())
365 checker->didCallCompletionHandler();
366 completionHandler(newQuota);
371 bool UIDelegate::UIClient::runOpenPanel(WebPageProxy*, WebFrameProxy* webFrameProxy, const WebCore::SecurityOriginData& securityOriginData, API::OpenPanelParameters* openPanelParameters, WebOpenPanelResultListenerProxy* listener)
373 if (!m_uiDelegate.m_delegateMethods.webViewRunOpenPanelWithParametersInitiatedByFrameCompletionHandler)
376 auto delegate = m_uiDelegate.m_delegate.get();
380 auto frame = API::FrameInfo::create(*webFrameProxy, securityOriginData.securityOrigin());
381 RefPtr<WebOpenPanelResultListenerProxy> resultListener = listener;
383 RefPtr<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(webView:runOpenPanelWithParameters:initiatedByFrame:completionHandler:));
385 [delegate webView:m_uiDelegate.m_webView runOpenPanelWithParameters:wrapper(*openPanelParameters) initiatedByFrame:wrapper(frame) completionHandler:[checker, resultListener](NSArray *URLs) {
386 if (checker->completionHandlerHasBeenCalled())
388 checker->didCallCompletionHandler();
391 resultListener->cancel();
395 Vector<String> filenames;
396 for (NSURL *url in URLs)
397 filenames.append(url.path);
399 resultListener->chooseFiles(filenames);
406 bool UIDelegate::UIClient::decidePolicyForUserMediaPermissionRequest(WebKit::WebPageProxy& page, WebKit::WebFrameProxy& frame, API::SecurityOrigin& userMediaOrigin, API::SecurityOrigin& topLevelOrigin, WebKit::UserMediaPermissionRequestProxy& request)
408 auto delegate = m_uiDelegate.m_delegate.get();
409 if (!delegate || !m_uiDelegate.m_delegateMethods.webViewRequestUserMediaAuthorizationForDevicesURLMainFrameURLDecisionHandler) {
410 request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::UserMediaDisabled);
414 bool requiresAudio = request.requiresAudio();
415 bool requiresVideo = request.requiresVideo();
416 if (!requiresAudio && !requiresVideo) {
417 request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::NoConstraints);
421 __block WKWebView *webView = m_uiDelegate.m_webView;
422 void (^uiDelegateAuthorizationBlock)(void) = ^ {
423 const WebFrameProxy* mainFrame = frame.page()->mainFrame();
424 WebCore::URL requestFrameURL(WebCore::URL(), frame.url());
425 WebCore::URL mainFrameURL(WebCore::URL(), mainFrame->url());
427 _WKCaptureDevices devices = 0;
429 devices |= _WKCaptureDeviceMicrophone;
431 devices |= _WKCaptureDeviceCamera;
433 [(id <WKUIDelegatePrivate>)delegate _webView:webView requestUserMediaAuthorizationForDevices:devices url:requestFrameURL mainFrameURL:mainFrameURL decisionHandler:^(BOOL authorized) {
435 request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
438 const String& videoDeviceUID = requiresVideo ? request.videoDeviceUIDs().first() : String();
439 const String& audioDeviceUID = requiresAudio ? request.audioDeviceUIDs().first() : String();
440 request.allow(audioDeviceUID, videoDeviceUID);
445 void (^cameraAuthorizationBlock)(void) = ^ {
447 AVAuthorizationStatus cameraAuthorizationStatus = [getAVCaptureDeviceClass() authorizationStatusForMediaType:getAVMediaTypeVideo()];
448 switch (cameraAuthorizationStatus) {
449 case AVAuthorizationStatusDenied:
450 case AVAuthorizationStatusRestricted:
451 request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
453 case AVAuthorizationStatusNotDetermined:
454 [getAVCaptureDeviceClass() requestAccessForMediaType:getAVMediaTypeVideo() completionHandler:^(BOOL authorized) {
456 request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
459 uiDelegateAuthorizationBlock();
463 uiDelegateAuthorizationBlock();
466 uiDelegateAuthorizationBlock();
470 AVAuthorizationStatus microphoneAuthorizationStatus = [getAVCaptureDeviceClass() authorizationStatusForMediaType:getAVMediaTypeAudio()];
471 switch (microphoneAuthorizationStatus) {
472 case AVAuthorizationStatusDenied:
473 case AVAuthorizationStatusRestricted:
474 request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
476 case AVAuthorizationStatusNotDetermined:
477 [getAVCaptureDeviceClass() requestAccessForMediaType:getAVMediaTypeAudio() completionHandler:^(BOOL authorized) {
479 request.deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
482 cameraAuthorizationBlock();
486 cameraAuthorizationBlock();
489 cameraAuthorizationBlock();
491 uiDelegateAuthorizationBlock();
497 bool UIDelegate::UIClient::checkUserMediaPermissionForOrigin(WebKit::WebPageProxy& page, WebKit::WebFrameProxy& frame, API::SecurityOrigin& userMediaOrigin, API::SecurityOrigin& topLevelOrigin, WebKit::UserMediaPermissionCheckProxy& request)
499 auto delegate = m_uiDelegate.m_delegate.get();
500 if (!delegate || !m_uiDelegate.m_delegateMethods.webViewCheckUserMediaPermissionForURLMainFrameURLFrameIdentifierDecisionHandler) {
501 request.setUserMediaAccessInfo(String(), false);
505 WKWebView *webView = m_uiDelegate.m_webView;
506 const WebFrameProxy* mainFrame = frame.page()->mainFrame();
507 WebCore::URL requestFrameURL(WebCore::URL(), frame.url());
508 WebCore::URL mainFrameURL(WebCore::URL(), mainFrame->url());
510 [(id <WKUIDelegatePrivate>)delegate _webView:webView checkUserMediaPermissionForURL:requestFrameURL mainFrameURL:mainFrameURL frameIdentifier:frame.frameID() decisionHandler:^(NSString *salt, BOOL authorized) {
511 request.setUserMediaAccessInfo(String(salt), authorized);
517 void UIDelegate::UIClient::mediaCaptureStateDidChange(WebCore::MediaProducer::MediaStateFlags state)
519 WKWebView *webView = m_uiDelegate.m_webView;
520 auto delegate = m_uiDelegate.m_delegate.get();
521 if (!delegate || !m_uiDelegate.m_delegateMethods.webViewMediaCaptureStateDidChange)
524 _WKMediaCaptureState mediaCaptureState = _WKMediaCaptureStateNone;
525 if (state & WebCore::MediaProducer::HasActiveAudioCaptureDevice)
526 mediaCaptureState |= _WKMediaCaptureStateActiveMicrophone;
527 if (state & WebCore::MediaProducer::HasActiveVideoCaptureDevice)
528 mediaCaptureState |= _WKMediaCaptureStateActiveCamera;
529 if (state & WebCore::MediaProducer::HasMutedAudioCaptureDevice)
530 mediaCaptureState |= _WKMediaCaptureStateMutedMicrophone;
531 if (state & WebCore::MediaProducer::HasMutedVideoCaptureDevice)
532 mediaCaptureState |= _WKMediaCaptureStateMutedCamera;
534 [(id <WKUIDelegatePrivate>)delegate _webView:webView mediaCaptureStateDidChange:mediaCaptureState];
537 void UIDelegate::UIClient::reachedApplicationCacheOriginQuota(WebPageProxy*, const WebCore::SecurityOrigin& securityOrigin, uint64_t currentQuota, uint64_t totalBytesNeeded, Function<void (unsigned long long)>&& completionHandler)
539 if (!m_uiDelegate.m_delegateMethods.webViewDecideWebApplicationCacheQuotaForSecurityOriginCurrentQuotaTotalBytesNeeded) {
540 completionHandler(currentQuota);
544 auto delegate = m_uiDelegate.m_delegate.get();
546 completionHandler(currentQuota);
550 RefPtr<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:decideWebApplicationCacheQuotaForSecurityOrigin:currentQuota:totalBytesNeeded:decisionHandler:));
551 RefPtr<API::SecurityOrigin> apiOrigin = API::SecurityOrigin::create(securityOrigin);
553 [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView decideWebApplicationCacheQuotaForSecurityOrigin:wrapper(*apiOrigin) currentQuota:currentQuota totalBytesNeeded:totalBytesNeeded decisionHandler:BlockPtr<void (unsigned long long)>::fromCallable([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)](unsigned long long newQuota) {
554 if (checker->completionHandlerHasBeenCalled())
556 checker->didCallCompletionHandler();
557 completionHandler(newQuota);
561 void UIDelegate::UIClient::printFrame(WebKit::WebPageProxy*, WebKit::WebFrameProxy* webFrameProxy)
563 ASSERT_ARG(webFrameProxy, webFrameProxy);
565 if (!m_uiDelegate.m_delegateMethods.webViewPrintFrame)
568 auto delegate = m_uiDelegate.m_delegate.get();
572 [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView printFrame:wrapper(API::FrameHandle::create(webFrameProxy->frameID()))];
575 void UIDelegate::UIClient::close(WebKit::WebPageProxy*)
577 if (m_uiDelegate.m_delegateMethods.webViewClose) {
578 auto delegate = m_uiDelegate.m_delegate.get();
582 [(id <WKUIDelegatePrivate>)delegate _webViewClose:m_uiDelegate.m_webView];
586 if (!m_uiDelegate.m_delegateMethods.webViewDidClose)
589 auto delegate = m_uiDelegate.m_delegate.get();
593 [delegate webViewDidClose:m_uiDelegate.m_webView];
596 void UIDelegate::UIClient::fullscreenMayReturnToInline(WebKit::WebPageProxy*)
598 if (!m_uiDelegate.m_delegateMethods.webViewFullscreenMayReturnToInline)
601 auto delegate = m_uiDelegate.m_delegate.get();
605 [(id <WKUIDelegatePrivate>)delegate _webViewFullscreenMayReturnToInline:m_uiDelegate.m_webView];
608 void UIDelegate::UIClient::didEnterFullscreen(WebKit::WebPageProxy*)
610 if (!m_uiDelegate.m_delegateMethods.webViewDidEnterFullscreen)
613 auto delegate = m_uiDelegate.m_delegate.get();
617 [(id <WKUIDelegatePrivate>)delegate _webViewDidEnterFullscreen:m_uiDelegate.m_webView];
620 void UIDelegate::UIClient::didExitFullscreen(WebKit::WebPageProxy*)
622 if (!m_uiDelegate.m_delegateMethods.webViewDidExitFullscreen)
625 auto delegate = m_uiDelegate.m_delegate.get();
629 [(id <WKUIDelegatePrivate>)delegate _webViewDidExitFullscreen:m_uiDelegate.m_webView];
634 bool UIDelegate::UIClient::shouldIncludeAppLinkActionsForElement(_WKActivatedElementInfo *elementInfo)
636 if (!m_uiDelegate.m_delegateMethods.webViewShouldIncludeAppLinkActionsForElement)
639 auto delegate = m_uiDelegate.m_delegate.get();
643 return [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView shouldIncludeAppLinkActionsForElement:elementInfo];
647 RetainPtr<NSArray> UIDelegate::UIClient::actionsForElement(_WKActivatedElementInfo *elementInfo, RetainPtr<NSArray> defaultActions)
649 if (!m_uiDelegate.m_delegateMethods.webViewActionsForElementDefaultActions)
650 return defaultActions;
652 auto delegate = m_uiDelegate.m_delegate.get();
654 return defaultActions;
656 return [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView actionsForElement:elementInfo defaultActions:defaultActions.get()];
659 void UIDelegate::UIClient::didNotHandleTapAsClick(const WebCore::IntPoint& point)
661 if (!m_uiDelegate.m_delegateMethods.webViewDidNotHandleTapAsClickAtPoint)
664 auto delegate = m_uiDelegate.m_delegate.get();
668 [static_cast<id <WKUIDelegatePrivate>>(delegate) _webView:m_uiDelegate.m_webView didNotHandleTapAsClickAtPoint:point];
671 UIViewController *UIDelegate::UIClient::presentingViewController()
673 if (!m_uiDelegate.m_delegateMethods.presentingViewControllerForWebView)
676 auto delegate = m_uiDelegate.m_delegate.get();
680 return [static_cast<id <WKUIDelegatePrivate>>(delegate) _presentingViewControllerForWebView:m_uiDelegate.m_webView];
685 NSDictionary *UIDelegate::UIClient::dataDetectionContext()
687 if (!m_uiDelegate.m_delegateMethods.dataDetectionContextForWebView)
690 auto delegate = m_uiDelegate.m_delegate.get();
694 return [static_cast<id <WKUIDelegatePrivate>>(delegate) _dataDetectionContextForWebView:m_uiDelegate.m_webView];
697 #if ENABLE(POINTER_LOCK)
699 void UIDelegate::UIClient::requestPointerLock(WebKit::WebPageProxy*)
701 if (!m_uiDelegate.m_delegateMethods.webViewRequestPointerLock)
704 auto delegate = m_uiDelegate.m_delegate.get();
708 [static_cast<id <WKUIDelegatePrivate>>(delegate) _webViewRequestPointerLock:m_uiDelegate.m_webView];
711 void UIDelegate::UIClient::didLosePointerLock(WebKit::WebPageProxy*)
713 if (!m_uiDelegate.m_delegateMethods.webViewDidLosePointerLock)
716 auto delegate = m_uiDelegate.m_delegate.get();
720 [static_cast<id <WKUIDelegatePrivate>>(delegate) _webViewDidLosePointerLock:m_uiDelegate.m_webView];
725 void UIDelegate::UIClient::hasVideoInPictureInPictureDidChange(WebKit::WebPageProxy*, bool hasVideoInPictureInPicture)
727 if (!m_uiDelegate.m_delegateMethods.webViewHasVideoInPictureInPictureDidChange)
730 auto delegate = m_uiDelegate.m_delegate.get();
734 [static_cast<id <WKUIDelegatePrivate>>(delegate) _webView:m_uiDelegate.m_webView hasVideoInPictureInPictureDidChange:hasVideoInPictureInPicture];
737 void UIDelegate::UIClient::imageOrMediaDocumentSizeChanged(const WebCore::IntSize& newSize)
739 if (!m_uiDelegate.m_delegateMethods.webViewImageOrMediaDocumentSizeChanged)
742 auto delegate = m_uiDelegate.m_delegate.get();
746 [static_cast<id <WKUIDelegatePrivate>>(delegate) _webView:m_uiDelegate.m_webView imageOrMediaDocumentSizeChanged:newSize];
749 } // namespace WebKit
751 #endif // WK_API_ENABLED