[WebAuthn] Implement _WKWebAuthenticationPanel SPI
authorjiewen_tan@apple.com <jiewen_tan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 4 Oct 2019 16:50:01 +0000 (16:50 +0000)
committerjiewen_tan@apple.com <jiewen_tan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 4 Oct 2019 16:50:01 +0000 (16:50 +0000)
https://bugs.webkit.org/show_bug.cgi?id=202559
<rdar://problem/55932094>

Reviewed by Brent Fulgham.

Source/WebKit:

This patch implements _WKWebAuthenticationPanel SPI. Here is the structure:
1) API::WebAuthenticationPanel is the APIObject of _WKWebAuthenticationPanel. It is owned by AuthenticatorManager.
The lifetime of _WKWebAuthenticationPanel on the other hand is managed by clients. This binding is the surface
where clients could interact with WebKit's WebAuthentication implementation.
2) API::WebAuthenticationPanelClient is a base class representing _WKWebAuthenticationPanelDelegate. Its subclass
WebKit::WebAuthenticationPanelClient implements bridges to _WKWebAuthenticationPanelDelegate methods. It is owned by
API::WebAuthenticationPanel. A weak pointer of WebKit::WebAuthenticationPanelClient is kept in _WKWebAuthenticationPanel
to get the _WKWebAuthenticationPanelDelegate set by clients or nil otherwise. This binding is the surface where WebKit
interacts with clients.
3) WebAuthenticationPanelFlags is the mirror of enums within _WKWebAuthenticationPanel.

Implementation wise, this patch implements:
1) -[WKUIDelegatePrivate webView:runWebAuthenticationPanel:initiatedByFrame:completionHandler:], this is bridged from
the regular UIDelegate route. Noted, WKFrameInfo is nil for now, a follow up on Bug 202563 will take care of it. This
will be called from AuthenticatorManager::runPanel() which gates the start of discovery on the callback. For clients
that don't implement the delegate, the callback will always be called with _WKWebAuthenticationPanelResultUnavailable
to allow WebKit run on non-UI mode. A specific C API hack is added to always return _WKWebAuthenticationPanelResultPresented
in WebKitTestRunner for layout tests.
2) -[_WKWebAuthenticationPanelDelegate panel:updateWebAuthenticationPanel:] will be implemented in Bug 200932.
3) -[_WKWebAuthenticationPanelDelegate panel:dismissWebAuthenticationPanelWithResult:], this is bridged from
API::WebAuthenticationPanel/API::WebAuthenticationPanelClient. This will be called whenever AuthenticatorManager::m_pendingCompletionHandler
is invoked. Depending on the respond, _WKWebAuthenticationResult will be returned accordingly. To facilitate that,
invokePendingCompletionHandler is crafted to bundle those two operations.
4) -[_WKWebAuthenticationPanel cancel] will be implemented in Bug 191523.

Besides the above, this patch also silents the NFC action sheet.

* Platform/spi/Cocoa/NearFieldSPI.h:
* Shared/API/APIObject.h:
* Shared/Cocoa/APIObject.mm:
(API::Object::newObject):
* Sources.txt:
* SourcesCocoa.txt:
* UIProcess/API/APIUIClient.h:
(API::UIClient::runWebAuthenticationPanel):
* UIProcess/API/APIWebAuthenticationPanel.cpp: Copied from Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm.
(API::WebAuthenticationPanel::create):
(API::WebAuthenticationPanel::WebAuthenticationPanel):
(API::WebAuthenticationPanel::setClient):
* UIProcess/API/APIWebAuthenticationPanel.h: Copied from Source/WebKit/UIProcess/WebAuthentication/WebAuthenticationRequestData.h.
* UIProcess/API/APIWebAuthenticationPanelClient.h: Copied from Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanelInternal.h.
(API::WebAuthenticationPanelClient::dismissPanel const):
* UIProcess/API/C/WKPage.cpp:
(WKPageSetPageUIClient):
* UIProcess/API/C/WKPageUIClient.h:
* UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm:
(-[_WKWebAuthenticationPanel dealloc]):
(-[_WKWebAuthenticationPanel relyingPartyID]):
(-[_WKWebAuthenticationPanel delegate]):
(-[_WKWebAuthenticationPanel setDelegate:]):
(-[_WKWebAuthenticationPanel _apiObject]):
(-[_WKWebAuthenticationPanel _initWithRelayingPartyID:]): Deleted.
* UIProcess/API/Cocoa/_WKWebAuthenticationPanelInternal.h:
* UIProcess/Cocoa/UIDelegate.h:
* UIProcess/Cocoa/UIDelegate.mm:
(WebKit::UIDelegate::setDelegate):
(WebKit::webAuthenticationPanelResult):
(WebKit::UIDelegate::UIClient::runWebAuthenticationPanel):
* UIProcess/WebAuthentication/AuthenticatorManager.cpp:
(WebKit::WebCore::isFeatureEnabled):
(WebKit::WebCore::getRpId):
(WebKit::AuthenticatorManager::handleRequest):
(WebKit::AuthenticatorManager::respondReceived):
(WebKit::AuthenticatorManager::startDiscovery):
(WebKit::AuthenticatorManager::initTimeOutTimer):
(WebKit::AuthenticatorManager::timeOutTimerFired):
(WebKit::AuthenticatorManager::runPanel):
(WebKit::AuthenticatorManager::startRequest):
(WebKit::AuthenticatorManager::invokePendingCompletionHandler):
(WebKit::AuthenticatorManagerInternal::collectTransports): Deleted.
(WebKit::AuthenticatorManagerInternal::processGoogleLegacyAppIdSupportExtension): Deleted.
* UIProcess/WebAuthentication/AuthenticatorManager.h:
(WebKit::AuthenticatorManager::pendingCompletionHandler): Deleted.
* UIProcess/WebAuthentication/Cocoa/NfcConnection.mm:
(WebKit::NfcConnection::NfcConnection):
* UIProcess/WebAuthentication/Cocoa/NfcService.mm:
(WebKit::NfcService::platformStartDiscovery):
* UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.h: Copied from Source/WebKit/UIProcess/WebAuthentication/WebAuthenticationRequestData.h.
* UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm: Copied from Source/WebKit/UIProcess/WebAuthentication/Mock/MockAuthenticatorManager.cpp.
(WebKit::WebAuthenticationPanelClient::WebAuthenticationPanelClient):
(WebKit::wkWebAuthenticationResult):
(WebKit::WebAuthenticationPanelClient::dismissPanel const):
* UIProcess/WebAuthentication/Mock/MockAuthenticatorManager.cpp:
(WebKit::MockAuthenticatorManager::respondReceivedInternal):
* UIProcess/WebAuthentication/WebAuthenticationPanelFlags.h: Copied from Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanelInternal.h.
* UIProcess/WebAuthentication/WebAuthenticationRequestData.h:
* UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp:
(WebKit::WebAuthenticatorCoordinatorProxy::makeCredential):
(WebKit::WebAuthenticatorCoordinatorProxy::getAssertion):
* WebKit.xcodeproj/project.pbxproj:

Tools:

This patch adds a very limited test case to _WKWebAuthenticationPanel.
Bug 202560 and Bug 202565 will follow up to write more tests.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm: Added.
(-[TestWebAuthenticationPanelDelegate panel:dismissWebAuthenticationPanelWithResult:]):
(-[TestWebAuthenticationPanelUIDelegate webView:runWebAuthenticationPanel:initiatedByFrame:completionHandler:]):
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion.html: Added.
* WebKitTestRunner/TestController.cpp:
(WTR::runWebAuthenticationPanel):
(WTR::TestController::createWebViewWithOptions):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@250729 268f45cc-cd09-0410-ab3c-d52691b4dbfc

32 files changed:
Source/WebKit/ChangeLog
Source/WebKit/Platform/spi/Cocoa/NearFieldSPI.h
Source/WebKit/Shared/API/APIObject.h
Source/WebKit/Shared/Cocoa/APIObject.mm
Source/WebKit/Sources.txt
Source/WebKit/SourcesCocoa.txt
Source/WebKit/UIProcess/API/APIUIClient.h
Source/WebKit/UIProcess/API/APIWebAuthenticationPanel.cpp [new file with mode: 0644]
Source/WebKit/UIProcess/API/APIWebAuthenticationPanel.h [new file with mode: 0644]
Source/WebKit/UIProcess/API/APIWebAuthenticationPanelClient.h [new file with mode: 0644]
Source/WebKit/UIProcess/API/C/WKPage.cpp
Source/WebKit/UIProcess/API/C/WKPageUIClient.h
Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm
Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanelInternal.h
Source/WebKit/UIProcess/Cocoa/UIDelegate.h
Source/WebKit/UIProcess/Cocoa/UIDelegate.mm
Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp
Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h
Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcConnection.mm
Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcService.mm
Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.h [new file with mode: 0644]
Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm [new file with mode: 0644]
Source/WebKit/UIProcess/WebAuthentication/Mock/MockAuthenticatorManager.cpp
Source/WebKit/UIProcess/WebAuthentication/WebAuthenticationPanelFlags.h [new file with mode: 0644]
Source/WebKit/UIProcess/WebAuthentication/WebAuthenticationRequestData.h
Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp
Source/WebKit/WebKit.xcodeproj/project.pbxproj
Tools/ChangeLog
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion.html [new file with mode: 0644]
Tools/WebKitTestRunner/TestController.cpp

index 83246c0..a178800 100644 (file)
@@ -1,3 +1,102 @@
+2019-10-04  Jiewen Tan  <jiewen_tan@apple.com>
+
+        [WebAuthn] Implement _WKWebAuthenticationPanel SPI
+        https://bugs.webkit.org/show_bug.cgi?id=202559
+        <rdar://problem/55932094>
+
+        Reviewed by Brent Fulgham.
+
+        This patch implements _WKWebAuthenticationPanel SPI. Here is the structure:
+        1) API::WebAuthenticationPanel is the APIObject of _WKWebAuthenticationPanel. It is owned by AuthenticatorManager.
+        The lifetime of _WKWebAuthenticationPanel on the other hand is managed by clients. This binding is the surface
+        where clients could interact with WebKit's WebAuthentication implementation.
+        2) API::WebAuthenticationPanelClient is a base class representing _WKWebAuthenticationPanelDelegate. Its subclass
+        WebKit::WebAuthenticationPanelClient implements bridges to _WKWebAuthenticationPanelDelegate methods. It is owned by
+        API::WebAuthenticationPanel. A weak pointer of WebKit::WebAuthenticationPanelClient is kept in _WKWebAuthenticationPanel
+        to get the _WKWebAuthenticationPanelDelegate set by clients or nil otherwise. This binding is the surface where WebKit
+        interacts with clients.
+        3) WebAuthenticationPanelFlags is the mirror of enums within _WKWebAuthenticationPanel.
+
+        Implementation wise, this patch implements:
+        1) -[WKUIDelegatePrivate webView:runWebAuthenticationPanel:initiatedByFrame:completionHandler:], this is bridged from
+        the regular UIDelegate route. Noted, WKFrameInfo is nil for now, a follow up on Bug 202563 will take care of it. This
+        will be called from AuthenticatorManager::runPanel() which gates the start of discovery on the callback. For clients
+        that don't implement the delegate, the callback will always be called with _WKWebAuthenticationPanelResultUnavailable
+        to allow WebKit run on non-UI mode. A specific C API hack is added to always return _WKWebAuthenticationPanelResultPresented
+        in WebKitTestRunner for layout tests.
+        2) -[_WKWebAuthenticationPanelDelegate panel:updateWebAuthenticationPanel:] will be implemented in Bug 200932.
+        3) -[_WKWebAuthenticationPanelDelegate panel:dismissWebAuthenticationPanelWithResult:], this is bridged from
+        API::WebAuthenticationPanel/API::WebAuthenticationPanelClient. This will be called whenever AuthenticatorManager::m_pendingCompletionHandler
+        is invoked. Depending on the respond, _WKWebAuthenticationResult will be returned accordingly. To facilitate that,
+        invokePendingCompletionHandler is crafted to bundle those two operations.
+        4) -[_WKWebAuthenticationPanel cancel] will be implemented in Bug 191523.
+
+        Besides the above, this patch also silents the NFC action sheet.
+
+        * Platform/spi/Cocoa/NearFieldSPI.h:
+        * Shared/API/APIObject.h:
+        * Shared/Cocoa/APIObject.mm:
+        (API::Object::newObject):
+        * Sources.txt:
+        * SourcesCocoa.txt:
+        * UIProcess/API/APIUIClient.h:
+        (API::UIClient::runWebAuthenticationPanel):
+        * UIProcess/API/APIWebAuthenticationPanel.cpp: Copied from Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm.
+        (API::WebAuthenticationPanel::create):
+        (API::WebAuthenticationPanel::WebAuthenticationPanel):
+        (API::WebAuthenticationPanel::setClient):
+        * UIProcess/API/APIWebAuthenticationPanel.h: Copied from Source/WebKit/UIProcess/WebAuthentication/WebAuthenticationRequestData.h.
+        * UIProcess/API/APIWebAuthenticationPanelClient.h: Copied from Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanelInternal.h.
+        (API::WebAuthenticationPanelClient::dismissPanel const):
+        * UIProcess/API/C/WKPage.cpp:
+        (WKPageSetPageUIClient):
+        * UIProcess/API/C/WKPageUIClient.h:
+        * UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm:
+        (-[_WKWebAuthenticationPanel dealloc]):
+        (-[_WKWebAuthenticationPanel relyingPartyID]):
+        (-[_WKWebAuthenticationPanel delegate]):
+        (-[_WKWebAuthenticationPanel setDelegate:]):
+        (-[_WKWebAuthenticationPanel _apiObject]):
+        (-[_WKWebAuthenticationPanel _initWithRelayingPartyID:]): Deleted.
+        * UIProcess/API/Cocoa/_WKWebAuthenticationPanelInternal.h:
+        * UIProcess/Cocoa/UIDelegate.h:
+        * UIProcess/Cocoa/UIDelegate.mm:
+        (WebKit::UIDelegate::setDelegate):
+        (WebKit::webAuthenticationPanelResult):
+        (WebKit::UIDelegate::UIClient::runWebAuthenticationPanel):
+        * UIProcess/WebAuthentication/AuthenticatorManager.cpp:
+        (WebKit::WebCore::isFeatureEnabled):
+        (WebKit::WebCore::getRpId):
+        (WebKit::AuthenticatorManager::handleRequest):
+        (WebKit::AuthenticatorManager::respondReceived):
+        (WebKit::AuthenticatorManager::startDiscovery):
+        (WebKit::AuthenticatorManager::initTimeOutTimer):
+        (WebKit::AuthenticatorManager::timeOutTimerFired):
+        (WebKit::AuthenticatorManager::runPanel):
+        (WebKit::AuthenticatorManager::startRequest):
+        (WebKit::AuthenticatorManager::invokePendingCompletionHandler):
+        (WebKit::AuthenticatorManagerInternal::collectTransports): Deleted.
+        (WebKit::AuthenticatorManagerInternal::processGoogleLegacyAppIdSupportExtension): Deleted.
+        * UIProcess/WebAuthentication/AuthenticatorManager.h:
+        (WebKit::AuthenticatorManager::pendingCompletionHandler): Deleted.
+        * UIProcess/WebAuthentication/Cocoa/NfcConnection.mm:
+        (WebKit::NfcConnection::NfcConnection):
+        * UIProcess/WebAuthentication/Cocoa/NfcService.mm:
+        (WebKit::NfcService::platformStartDiscovery):
+        * UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.h: Copied from Source/WebKit/UIProcess/WebAuthentication/WebAuthenticationRequestData.h.
+        * UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm: Copied from Source/WebKit/UIProcess/WebAuthentication/Mock/MockAuthenticatorManager.cpp.
+        (WebKit::WebAuthenticationPanelClient::WebAuthenticationPanelClient):
+        (WebKit::wkWebAuthenticationResult):
+        (WebKit::WebAuthenticationPanelClient::dismissPanel const):
+        * UIProcess/WebAuthentication/Mock/MockAuthenticatorManager.cpp:
+        (WebKit::MockAuthenticatorManager::respondReceivedInternal):
+        * UIProcess/WebAuthentication/WebAuthenticationPanelFlags.h: Copied from Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanelInternal.h.
+        * UIProcess/WebAuthentication/WebAuthenticationRequestData.h:
+        * UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp:
+        (WebKit::WebAuthenticatorCoordinatorProxy::makeCredential):
+        (WebKit::WebAuthenticatorCoordinatorProxy::getAssertion):
+        * WebKit.xcodeproj/project.pbxproj:
+
 2019-10-04  Alex Christensen  <achristensen@webkit.org>
 
         Move WKProcessPool._registerURLSchemeServiceWorkersCanHandle to _WKWebsiteDataStoreConfiguration
index edcb562..6bcbaa5 100644 (file)
@@ -108,7 +108,7 @@ typedef NS_ENUM(uint32_t, NFNdefAvailability) {
 
 @interface NFHardwareManager : NSObject
 + (instancetype)sharedHardwareManager;
-- (NSObject<NFSession> *)startReaderSessionWithActionSheetUI:(void(^)(NFReaderSession *session, NSError *error))theStartCallback;
+- (NSObject<NFSession> *)startReaderSession:(void(^)(NFReaderSession *session, NSError *error))theStartCallback;
 - (BOOL)areFeaturesSupported:(NFFeature)featureMask outError:(NSError**)outError;
 @end
 
index 4029df9..b7ca97a 100644 (file)
@@ -178,6 +178,10 @@ public:
         MediaSessionMetadata,
 #endif
 
+#if ENABLE(WEB_AUTHN)
+        WebAuthenticationPanel,
+#endif
+
         // Bundle types
         Bundle,
         BundleBackForwardList,
index 57c32b2..143eb08 100644 (file)
@@ -84,6 +84,7 @@
 #import "_WKUserInitiatedActionInternal.h"
 #import "_WKUserStyleSheetInternal.h"
 #import "_WKVisitedLinkStoreInternal.h"
+#import "_WKWebAuthenticationPanelInternal.h"
 #import "_WKWebsiteDataStoreConfigurationInternal.h"
 
 #if ENABLE(APPLICATION_MANIFEST)
@@ -364,6 +365,12 @@ void* Object::newObject(size_t size, Type type)
         wrapper = [WKWindowFeatures alloc];
         break;
 
+#if ENABLE(WEB_AUTHN)
+    case Type::WebAuthenticationPanel:
+        wrapper = [_WKWebAuthenticationPanel alloc];
+        break;
+#endif
+
     case Type::BundleFrame:
         wrapper = [WKWebProcessPlugInFrame alloc];
         break;
index fa5261f..373d655 100644 (file)
@@ -318,6 +318,7 @@ UIProcess/API/APIURLSchemeTask.cpp
 UIProcess/API/APIUserContentWorld.cpp
 UIProcess/API/APIUserScript.cpp
 UIProcess/API/APIUserStyleSheet.cpp
+UIProcess/API/APIWebAuthenticationPanel.cpp
 UIProcess/API/APIWebsitePolicies.cpp
 UIProcess/API/APIWindowFeatures.cpp
 
index b7f0ab6..b3f1222 100644 (file)
@@ -503,6 +503,7 @@ UIProcess/WebAuthentication/Cocoa/NearFieldSoftLink.mm @no-unify
 UIProcess/WebAuthentication/Cocoa/NfcConnection.mm
 UIProcess/WebAuthentication/Cocoa/NfcService.mm
 UIProcess/WebAuthentication/Cocoa/WKNFReaderSessionDelegate.mm
+UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm
 
 UIProcess/WebAuthentication/Mock/MockLocalConnection.mm
 UIProcess/WebAuthentication/Mock/MockLocalService.mm
index 772da6e..ddd6e62 100644 (file)
@@ -38,6 +38,10 @@ OBJC_CLASS _WKActivatedElementInfo;
 OBJC_CLASS UIViewController;
 #endif
 
+#if ENABLE(WEB_AUTHN)
+#include "WebAuthenticationPanelFlags.h"
+#endif
+
 namespace WebCore {
 class RegistrableDomain;
 class ResourceRequest;
@@ -69,6 +73,9 @@ class Dictionary;
 class Object;
 class OpenPanelParameters;
 class SecurityOrigin;
+#if ENABLE(WEB_AUTHN)
+class WebAuthenticationPanel;
+#endif
 
 class UIClient {
     WTF_MAKE_FAST_ALLOCATED;
@@ -188,6 +195,10 @@ public:
     virtual void didExceedBackgroundResourceLimitWhileInForeground(WebKit::WebPageProxy&, WKResourceLimit) { }
     
     virtual void didShowSafeBrowsingWarning() { }
+
+#if ENABLE(WEB_AUTHN)
+    virtual void runWebAuthenticationPanel(WebKit::WebPageProxy&, WebAuthenticationPanel&, CompletionHandler<void(WebKit::WebAuthenticationPanelResult)>&& completionHandler) { completionHandler(WebKit::WebAuthenticationPanelResult::Unavailable); }
+#endif
 };
 
 } // namespace API
diff --git a/Source/WebKit/UIProcess/API/APIWebAuthenticationPanel.cpp b/Source/WebKit/UIProcess/API/APIWebAuthenticationPanel.cpp
new file mode 100644 (file)
index 0000000..00d2d1a
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "APIWebAuthenticationPanel.h"
+
+#if ENABLE(WEB_AUTHN)
+
+#include "APIWebAuthenticationPanelClient.h"
+
+namespace API {
+
+Ref<WebAuthenticationPanel> WebAuthenticationPanel::create(const String& rpId)
+{
+    return adoptRef(*new WebAuthenticationPanel(rpId));
+}
+
+WebAuthenticationPanel::WebAuthenticationPanel(const String& rpId)
+    : m_rpId(rpId)
+    , m_client(WTF::makeUniqueRef<WebAuthenticationPanelClient>())
+{
+}
+
+WebAuthenticationPanel::~WebAuthenticationPanel() = default;
+
+void WebAuthenticationPanel::setClient(UniqueRef<WebAuthenticationPanelClient>&& client)
+{
+    m_client = WTFMove(client);
+}
+
+} // namespace API
+
+#endif // ENABLE(WEB_AUTHN)
diff --git a/Source/WebKit/UIProcess/API/APIWebAuthenticationPanel.h b/Source/WebKit/UIProcess/API/APIWebAuthenticationPanel.h
new file mode 100644 (file)
index 0000000..7504886
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEB_AUTHN)
+
+#include "APIObject.h"
+#include <wtf/UniqueRef.h>
+#include <wtf/WeakPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace API {
+
+class WebAuthenticationPanelClient;
+
+class WebAuthenticationPanel final : public ObjectImpl<Object::Type::WebAuthenticationPanel>, public CanMakeWeakPtr<WebAuthenticationPanel> {
+public:
+    static Ref<WebAuthenticationPanel> create(const String& rpId);
+    ~WebAuthenticationPanel();
+
+    WTF::String rpId() const { return m_rpId; }
+
+    const WebAuthenticationPanelClient& client() const { return m_client.get(); }
+    void setClient(UniqueRef<WebAuthenticationPanelClient>&&);
+
+private:
+    WebAuthenticationPanel(const String& rpId);
+
+    WTF::String m_rpId;
+    UniqueRef<WebAuthenticationPanelClient> m_client;
+};
+
+} // namespace API
+
+#endif // ENABLE(WEB_AUTHN)
diff --git a/Source/WebKit/UIProcess/API/APIWebAuthenticationPanelClient.h b/Source/WebKit/UIProcess/API/APIWebAuthenticationPanelClient.h
new file mode 100644 (file)
index 0000000..5b6a9c7
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEB_AUTHN)
+
+namespace WebKit {
+enum class WebAuthenticationResult : bool;
+}
+
+namespace API {
+
+class WebAuthenticationPanelClient {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    virtual ~WebAuthenticationPanelClient() = default;
+
+    virtual void dismissPanel(WebKit::WebAuthenticationResult) const { }
+};
+
+} // namespace API
+
+#endif // ENABLE(WEB_AUTHN)
index 2f5f80c..104552b 100644 (file)
@@ -116,7 +116,7 @@ template<> struct ClientTraits<WKPagePolicyClientBase> {
 };
 
 template<> struct ClientTraits<WKPageUIClientBase> {
-    typedef std::tuple<WKPageUIClientV0, WKPageUIClientV1, WKPageUIClientV2, WKPageUIClientV3, WKPageUIClientV4, WKPageUIClientV5, WKPageUIClientV6, WKPageUIClientV7, WKPageUIClientV8, WKPageUIClientV9, WKPageUIClientV10, WKPageUIClientV11, WKPageUIClientV12, WKPageUIClientV13> Versions;
+    typedef std::tuple<WKPageUIClientV0, WKPageUIClientV1, WKPageUIClientV2, WKPageUIClientV3, WKPageUIClientV4, WKPageUIClientV5, WKPageUIClientV6, WKPageUIClientV7, WKPageUIClientV8, WKPageUIClientV9, WKPageUIClientV10, WKPageUIClientV11, WKPageUIClientV12, WKPageUIClientV13, WKPageUIClientV14> Versions;
 };
 
 #if ENABLE(CONTEXT_MENUS)
@@ -2073,6 +2073,18 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient
 
             m_client.handleAutoplayEvent(toAPI(&page), toWKAutoplayEvent(event), toWKAutoplayEventFlags(flags), m_client.base.clientInfo);
         }
+
+#if ENABLE(WEB_AUTHN)
+        // The current method is specialized for WebKitTestRunner.
+        void runWebAuthenticationPanel(WebPageProxy&, API::WebAuthenticationPanel&, CompletionHandler<void(WebKit::WebAuthenticationPanelResult)>&& completionHandler) final
+        {
+            if (!m_client.runWebAuthenticationPanel) {
+                completionHandler(WebKit::WebAuthenticationPanelResult::Unavailable);
+                return;
+            }
+            completionHandler(WebKit::WebAuthenticationPanelResult::Presented);
+        }
+#endif
     };
 
     toImpl(pageRef)->setUIClient(makeUnique<UIClient>(wkClient));
index d26ee92..1d2febf 100644 (file)
@@ -136,6 +136,8 @@ typedef void (*WKDidExceedBackgroundResourceLimitWhileInForegroundCallback)(WKPa
 typedef void (*WKPageDidResignInputElementStrongPasswordAppearanceCallback)(WKPageRef page, WKTypeRef userData, const void *clientInfo);
 typedef bool (*WKPageShouldAllowDeviceOrientationAndMotionAccessCallback)(WKPageRef page, WKSecurityOriginRef securityOrigin, const void *clientInfo);
 
+typedef void (*WKPageRunWebAuthenticationPanelCallback)();
+
 // Deprecated
 typedef WKPageRef (*WKPageCreateNewPageCallback_deprecatedForUseWithV0)(WKPageRef page, WKDictionaryRef features, WKEventModifiers modifiers, WKEventMouseButton mouseButton, const void *clientInfo);
 typedef void      (*WKPageMouseDidMoveOverElementCallback_deprecatedForUseWithV0)(WKPageRef page, WKEventModifiers modifiers, WKTypeRef userData, const void *clientInfo);
@@ -1245,6 +1247,113 @@ typedef struct WKPageUIClientV13 {
     WKPageShouldAllowDeviceOrientationAndMotionAccessCallback           shouldAllowDeviceOrientationAndMotionAccess;
 } WKPageUIClientV13;
 
+typedef struct WKPageUIClientV14 {
+    WKPageUIClientBase                                                  base;
+
+    // Version 0.
+    WKPageCreateNewPageCallback_deprecatedForUseWithV0                  createNewPage_deprecatedForUseWithV0;
+    WKPageUIClientCallback                                              showPage;
+    WKPageUIClientCallback                                              close;
+    WKPageTakeFocusCallback                                             takeFocus;
+    WKPageFocusCallback                                                 focus;
+    WKPageUnfocusCallback                                               unfocus;
+    WKPageRunJavaScriptAlertCallback_deprecatedForUseWithV0             runJavaScriptAlert_deprecatedForUseWithV0;
+    WKPageRunJavaScriptConfirmCallback_deprecatedForUseWithV0           runJavaScriptConfirm_deprecatedForUseWithV0;
+    WKPageRunJavaScriptPromptCallback_deprecatedForUseWithV0            runJavaScriptPrompt_deprecatedForUseWithV0;
+    WKPageSetStatusTextCallback                                         setStatusText;
+    WKPageMouseDidMoveOverElementCallback_deprecatedForUseWithV0        mouseDidMoveOverElement_deprecatedForUseWithV0;
+    WKPageMissingPluginButtonClickedCallback_deprecatedForUseWithV0     missingPluginButtonClicked_deprecatedForUseWithV0;
+    WKPageDidNotHandleKeyEventCallback                                  didNotHandleKeyEvent;
+    WKPageDidNotHandleWheelEventCallback                                didNotHandleWheelEvent;
+    WKPageGetToolbarsAreVisibleCallback                                 toolbarsAreVisible;
+    WKPageSetToolbarsAreVisibleCallback                                 setToolbarsAreVisible;
+    WKPageGetMenuBarIsVisibleCallback                                   menuBarIsVisible;
+    WKPageSetMenuBarIsVisibleCallback                                   setMenuBarIsVisible;
+    WKPageGetStatusBarIsVisibleCallback                                 statusBarIsVisible;
+    WKPageSetStatusBarIsVisibleCallback                                 setStatusBarIsVisible;
+    WKPageGetIsResizableCallback                                        isResizable;
+    WKPageSetIsResizableCallback                                        setIsResizable;
+    WKPageGetWindowFrameCallback                                        getWindowFrame;
+    WKPageSetWindowFrameCallback                                        setWindowFrame;
+    WKPageRunBeforeUnloadConfirmPanelCallback_deprecatedForUseWithV6    runBeforeUnloadConfirmPanel_deprecatedForUseWithV6;
+    WKPageUIClientCallback                                              didDraw;
+    WKPageUIClientCallback                                              pageDidScroll;
+    WKPageExceededDatabaseQuotaCallback                                 exceededDatabaseQuota;
+    WKPageRunOpenPanelCallback                                          runOpenPanel;
+    WKPageDecidePolicyForGeolocationPermissionRequestCallback           decidePolicyForGeolocationPermissionRequest;
+    WKPageHeaderHeightCallback                                          headerHeight;
+    WKPageFooterHeightCallback                                          footerHeight;
+    WKPageDrawHeaderCallback                                            drawHeader;
+    WKPageDrawFooterCallback                                            drawFooter;
+    WKPagePrintFrameCallback                                            printFrame;
+    WKPageUIClientCallback                                              runModal;
+    void*                                                               unused1; // Used to be didCompleteRubberBandForMainFrame
+    WKPageSaveDataToFileInDownloadsFolderCallback                       saveDataToFileInDownloadsFolder;
+    void*                                                               shouldInterruptJavaScript_unavailable;
+
+    // Version 1.
+    WKPageCreateNewPageCallback_deprecatedForUseWithV1                  createNewPage_deprecatedForUseWithV1;
+    WKPageMouseDidMoveOverElementCallback                               mouseDidMoveOverElement;
+    WKPageDecidePolicyForNotificationPermissionRequestCallback          decidePolicyForNotificationPermissionRequest;
+    WKPageUnavailablePluginButtonClickedCallback_deprecatedForUseWithV1 unavailablePluginButtonClicked_deprecatedForUseWithV1;
+
+    // Version 2.
+    WKPageShowColorPickerCallback                                       showColorPicker;
+    WKPageHideColorPickerCallback                                       hideColorPicker;
+    WKPageUnavailablePluginButtonClickedCallback                        unavailablePluginButtonClicked;
+
+    // Version 3.
+    WKPagePinnedStateDidChangeCallback                                  pinnedStateDidChange;
+
+    // Version 4.
+    void*                                                               unused2; // Used to be didBeginTrackingPotentialLongMousePress.
+    void*                                                               unused3; // Used to be didRecognizeLongMousePress.
+    void*                                                               unused4; // Used to be didCancelTrackingPotentialLongMousePress.
+    WKPageIsPlayingAudioDidChangeCallback                               isPlayingAudioDidChange;
+
+    // Version 5.
+    WKPageDecidePolicyForUserMediaPermissionRequestCallback             decidePolicyForUserMediaPermissionRequest;
+    WKPageDidClickAutoFillButtonCallback                                didClickAutoFillButton;
+    WKPageRunJavaScriptAlertCallback_deprecatedForUseWithV5             runJavaScriptAlert_deprecatedForUseWithV5;
+    WKPageRunJavaScriptConfirmCallback_deprecatedForUseWithV5           runJavaScriptConfirm_deprecatedForUseWithV5;
+    WKPageRunJavaScriptPromptCallback_deprecatedForUseWithV5            runJavaScriptPrompt_deprecatedForUseWithV5;
+    WKPageMediaSessionMetadataDidChangeCallback                         mediaSessionMetadataDidChange;
+
+    // Version 6.
+    WKPageCreateNewPageCallback                                         createNewPage;
+    WKPageRunJavaScriptAlertCallback                                    runJavaScriptAlert;
+    WKPageRunJavaScriptConfirmCallback                                  runJavaScriptConfirm;
+    WKPageRunJavaScriptPromptCallback                                   runJavaScriptPrompt;
+    WKCheckUserMediaPermissionCallback                                  checkUserMediaPermissionForOrigin;
+
+    // Version 7.
+    WKPageRunBeforeUnloadConfirmPanelCallback                           runBeforeUnloadConfirmPanel;
+    WKFullscreenMayReturnToInlineCallback                               fullscreenMayReturnToInline;
+
+    // Version 8.
+    WKRequestPointerLockCallback                                        requestPointerLock;
+    WKDidLosePointerLockCallback                                        didLosePointerLock;
+
+    // Version 9.
+    WKHandleAutoplayEventCallback                                       handleAutoplayEvent;
+
+    // Version 10.
+    WKHasVideoInPictureInPictureDidChangeCallback                       hasVideoInPictureInPictureDidChange;
+    WKDidExceedBackgroundResourceLimitWhileInForegroundCallback         didExceedBackgroundResourceLimitWhileInForeground;
+
+    // Version 11.
+    WKPageDidResignInputElementStrongPasswordAppearanceCallback         didResignInputElementStrongPasswordAppearance;
+
+    // Version 12.
+    WKPageRequestStorageAccessConfirmCallback                           requestStorageAccessConfirm;
+
+    // Version 13.
+    WKPageShouldAllowDeviceOrientationAndMotionAccessCallback           shouldAllowDeviceOrientationAndMotionAccess;
+
+    // Version 14.
+    WKPageRunWebAuthenticationPanelCallback                             runWebAuthenticationPanel;
+} WKPageUIClientV14;
+
 #ifdef __cplusplus
 }
 #endif
index 41b2c07..f535c60 100644 (file)
  */
 
 #import "config.h"
+#import "WebAuthenticationPanelClient.h"
 #import "_WKWebAuthenticationPanelInternal.h"
 
 #import <wtf/RetainPtr.h>
 
-@implementation _WKWebAuthenticationPanel  {
-    RetainPtr<NSString> _relyingPartyID;
+@implementation _WKWebAuthenticationPanel {
+    WeakPtr<WebKit::WebAuthenticationPanelClient> _client;
 }
 
-- (instancetype)_initWithRelayingPartyID:(NSString *)relayingPartyID
+- (void)dealloc
 {
-    if (!(self = [super init]))
-        return nil;
-    _relyingPartyID = relayingPartyID;
-    return self;
+    _panel->~WebAuthenticationPanel();
+
+    [super dealloc];
 }
 
 - (NSString *)relyingPartyID
 {
-    return _relyingPartyID.get();
+    return _panel->rpId();
+}
+
+- (id <_WKWebAuthenticationPanelDelegate>)delegate
+{
+    if (!_client)
+        return nil;
+    return _client->delegate().autorelease();
+}
+
+- (void)setDelegate:(id<_WKWebAuthenticationPanelDelegate>)delegate
+{
+    auto client = WTF::makeUniqueRef<WebKit::WebAuthenticationPanelClient>(self, delegate);
+    _client = makeWeakPtr(client.get());
+    _panel->setClient(WTFMove(client));
 }
 
 - (void)cancel
 {
 }
 
+#pragma mark WKObject protocol implementation
+
+- (API::Object&)_apiObject
+{
+    return *_panel;
+}
+
 @end
index 435a4ac..ca02667 100644 (file)
 
 #import "_WKWebAuthenticationPanel.h"
 
-@interface _WKWebAuthenticationPanel ()
+#import "APIWebAuthenticationPanel.h"
+#import "WKObject.h"
 
-- (instancetype)_initWithRelayingPartyID:(NSString *)relayingPartyID;
+namespace WebKit {
 
+template<> struct WrapperTraits<API::WebAuthenticationPanel> {
+    using WrapperClass = _WKWebAuthenticationPanel;
+};
+
+}
+
+@interface _WKWebAuthenticationPanel () <WKObject> {
+@package
+    API::ObjectStorage<API::WebAuthenticationPanel> _panel;
+}
 @end
index bd20a81..81f78aa 100644 (file)
@@ -154,6 +154,9 @@ private:
 
         void imageOrMediaDocumentSizeChanged(const WebCore::IntSize&) final;
         void didShowSafeBrowsingWarning() final;
+#if ENABLE(WEB_AUTHN)
+        void runWebAuthenticationPanel(WebPageProxy&, API::WebAuthenticationPanel&, CompletionHandler<void(WebAuthenticationPanelResult)>&&) final;
+#endif
 
         UIDelegate& m_uiDelegate;
     };
@@ -234,6 +237,9 @@ private:
 #endif
         bool webViewHasVideoInPictureInPictureDidChange : 1;
         bool webViewDidShowSafeBrowsingWarning : 1;
+#if ENABLE(WEB_AUTHN)
+        bool webViewRunWebAuthenticationPanelInitiatedByFrameCompletionHandler : 1;
+#endif
     } m_delegateMethods;
 };
 
index 7b624ab..3ec42ce 100644 (file)
@@ -52,6 +52,7 @@
 #import "_WKContextMenuElementInfo.h"
 #import "_WKFrameHandleInternal.h"
 #import "_WKHitTestResultInternal.h"
+#import "_WKWebAuthenticationPanelInternal.h"
 #import <WebCore/FontAttributes.h>
 #import <WebCore/SecurityOriginData.h>
 #import <wtf/BlockPtr.h>
@@ -172,6 +173,9 @@ void UIDelegate::setDelegate(id <WKUIDelegate> delegate)
     
     m_delegateMethods.webViewHasVideoInPictureInPictureDidChange = [delegate respondsToSelector:@selector(_webView:hasVideoInPictureInPictureDidChange:)];
     m_delegateMethods.webViewDidShowSafeBrowsingWarning = [delegate respondsToSelector:@selector(_webViewDidShowSafeBrowsingWarning:)];
+#if ENABLE(WEB_AUTHN)
+    m_delegateMethods.webViewRunWebAuthenticationPanelInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runWebAuthenticationPanel:initiatedByFrame:completionHandler:)];
+#endif
 }
 
 #if ENABLE(CONTEXT_MENUS)
@@ -1261,6 +1265,46 @@ void UIDelegate::UIClient::didShowSafeBrowsingWarning()
     [static_cast<id <WKUIDelegatePrivate>>(delegate) _webViewDidShowSafeBrowsingWarning:m_uiDelegate.m_webView];
 }
 
+#if ENABLE(WEB_AUTHN)
+
+static WebAuthenticationPanelResult webAuthenticationPanelResult(_WKWebAuthenticationPanelResult result)
+{
+    switch (result) {
+    case _WKWebAuthenticationPanelResultUnavailable:
+        return WebAuthenticationPanelResult::Unavailable;
+    case _WKWebAuthenticationPanelResultPresented:
+        return WebAuthenticationPanelResult::Presented;
+    case _WKWebAuthenticationPanelResultDidNotPresent:
+        return WebAuthenticationPanelResult::DidNotPresent;
+    }
+    ASSERT_NOT_REACHED();
+    return WebAuthenticationPanelResult::Unavailable;
+}
+
+void UIDelegate::UIClient::runWebAuthenticationPanel(WebPageProxy&, API::WebAuthenticationPanel& panel, CompletionHandler<void(WebAuthenticationPanelResult)>&& completionHandler)
+{
+    if (!m_uiDelegate.m_delegateMethods.webViewRunWebAuthenticationPanelInitiatedByFrameCompletionHandler) {
+        completionHandler(WebAuthenticationPanelResult::Unavailable);
+        return;
+    }
+
+    auto delegate = m_uiDelegate.m_delegate.get();
+    if (!delegate) {
+        completionHandler(WebAuthenticationPanelResult::Unavailable);
+        return;
+    }
+
+    auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(webView:runWebAuthenticationPanel:initiatedByFrame:completionHandler:));
+    [(id <WKUIDelegatePrivate>)delegate webView:m_uiDelegate.m_webView runWebAuthenticationPanel:wrapper(panel) initiatedByFrame:nil completionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)] (_WKWebAuthenticationPanelResult result) mutable {
+        if (checker->completionHandlerHasBeenCalled())
+            return;
+        checker->didCallCompletionHandler();
+        completionHandler(webAuthenticationPanelResult(result));
+    }).get()];
+}
+
+#endif // ENABLE(WEB_AUTHN)
+
 void UIDelegate::UIClient::hasVideoInPictureInPictureDidChange(WebPageProxy*, bool hasVideoInPictureInPicture)
 {
     if (!m_uiDelegate.m_delegateMethods.webViewHasVideoInPictureInPictureDidChange)
index 9a2b348..1c41a3c 100644 (file)
 
 #if ENABLE(WEB_AUTHN)
 
+#include "APIUIClient.h"
+#include "APIWebAuthenticationPanel.h"
+#include "APIWebAuthenticationPanelClient.h"
+#include "WebPageProxy.h"
 #include "WebPreferencesKeys.h"
 #include <WebCore/AuthenticatorTransport.h>
 #include <WebCore/PublicKeyCredentialCreationOptions.h>
@@ -36,7 +40,7 @@
 namespace WebKit {
 using namespace WebCore;
 
-namespace AuthenticatorManagerInternal {
+namespace {
 
 const size_t maxTransportNumber = 3;
 
@@ -123,7 +127,21 @@ static void processGoogleLegacyAppIdSupportExtension(const Optional<Authenticati
     transports.remove(AuthenticatorTransport::Internal);
 }
 
-} // namespace AuthenticatorManagerInternal
+static bool isFeatureEnabled(WebPageProxy* page, const String& featureKey)
+{
+    if (!page)
+        return false;
+    return page->preferences().store().getBoolValueForKey(featureKey);
+}
+
+static String getRpId(const Variant<PublicKeyCredentialCreationOptions, PublicKeyCredentialRequestOptions>& options)
+{
+    if (WTF::holds_alternative<PublicKeyCredentialCreationOptions>(options))
+        return WTF::get<PublicKeyCredentialCreationOptions>(options).rp.id;
+    return WTF::get<PublicKeyCredentialRequestOptions>(options).rpId;
+}
+
+} // namespace
 
 AuthenticatorManager::AuthenticatorManager()
     : m_requestTimeOutTimer(RunLoop::main(), this, &AuthenticatorManager::timeOutTimerFired)
@@ -132,10 +150,8 @@ AuthenticatorManager::AuthenticatorManager()
 
 void AuthenticatorManager::handleRequest(WebAuthenticationRequestData&& data, Callback&& callback)
 {
-    using namespace AuthenticatorManagerInternal;
-
     if (m_pendingCompletionHandler) {
-        m_pendingCompletionHandler(ExceptionData { NotAllowedError, "This request has been cancelled by a new request."_s });
+        invokePendingCompletionHandler(ExceptionData { NotAllowedError, "This request has been cancelled by a new request."_s });
         m_requestTimeOutTimer.stop();
     }
     clearState();
@@ -144,17 +160,8 @@ void AuthenticatorManager::handleRequest(WebAuthenticationRequestData&& data, Ca
     m_pendingRequestData = WTFMove(data);
     m_pendingCompletionHandler = WTFMove(callback);
 
-    // 2. Get available transports and start discovering authenticators on them.
-    WTF::switchOn(m_pendingRequestData.options, [&](const PublicKeyCredentialCreationOptions& options) {
-        initTimeOutTimer(options.timeout);
-
-        auto transports = collectTransports(options.authenticatorSelection);
-        processGoogleLegacyAppIdSupportExtension(options.extensions, transports);
-        startDiscovery(WTFMove(transports));
-    }, [&](const  PublicKeyCredentialRequestOptions& options) {
-        initTimeOutTimer(options.timeout);
-        startDiscovery(collectTransports(options.allowCredentials));
-    });
+    // 2. Ask clients to show appropriate UI if any and then start the request.
+    runPanel();
 }
 
 void AuthenticatorManager::clearStateAsync()
@@ -195,7 +202,7 @@ void AuthenticatorManager::respondReceived(Respond&& respond)
     if (!shouldComplete)
         shouldComplete = WTF::get<ExceptionData>(respond).code == InvalidStateError;
     if (shouldComplete) {
-        m_pendingCompletionHandler(WTFMove(respond));
+        invokePendingCompletionHandler(WTFMove(respond));
         clearStateAsync();
         m_requestTimeOutTimer.stop();
         return;
@@ -225,11 +232,12 @@ void AuthenticatorManager::respondReceivedInternal(Respond&&)
 
 void AuthenticatorManager::startDiscovery(const TransportSet& transports)
 {
-    using namespace AuthenticatorManagerInternal;
-
-    ASSERT(m_services.isEmpty() && transports.size() <= maxTransportNumber && m_pendingRequestData.preferences);
+    ASSERT(m_services.isEmpty() && transports.size() <= maxTransportNumber);
     for (auto& transport : transports) {
-        if (transport == AuthenticatorTransport::Internal && !m_pendingRequestData.preferences->store().getBoolValueForKey(WebPreferencesKey::webAuthenticationLocalAuthenticatorEnabledKey()))
+        if (transport == AuthenticatorTransport::Internal && !isFeatureEnabled(m_pendingRequestData.page.get(), WebPreferencesKey::webAuthenticationLocalAuthenticatorEnabledKey()))
+            continue;
+        // Only allow USB authenticators when clients don't have dedicated UI.
+        if (transport != AuthenticatorTransport::Usb && (m_pendingRequestData.panelResult == WebAuthenticationPanelResult::Unavailable))
             continue;
         auto service = createService(transport, *this);
         service->startDiscovery();
@@ -239,8 +247,6 @@ void AuthenticatorManager::startDiscovery(const TransportSet& transports)
 
 void AuthenticatorManager::initTimeOutTimer(const Optional<unsigned>& timeOutInMs)
 {
-    using namespace AuthenticatorManagerInternal;
-
     unsigned timeOutInMsValue = std::min(maxTimeOutValue, timeOutInMs.valueOr(maxTimeOutValue));
     m_requestTimeOutTimer.startOneShot(Seconds::fromMilliseconds(timeOutInMsValue));
 }
@@ -248,10 +254,57 @@ void AuthenticatorManager::initTimeOutTimer(const Optional<unsigned>& timeOutInM
 void AuthenticatorManager::timeOutTimerFired()
 {
     ASSERT(m_requestTimeOutTimer.isActive());
-    m_pendingCompletionHandler((ExceptionData { NotAllowedError, "Operation timed out."_s }));
+    invokePendingCompletionHandler((ExceptionData { NotAllowedError, "Operation timed out."_s }));
     clearState();
 }
 
+void AuthenticatorManager::runPanel()
+{
+    auto* page = m_pendingRequestData.page.get();
+    if (!page)
+        return;
+
+    m_pendingRequestData.panel = API::WebAuthenticationPanel::create(getRpId(m_pendingRequestData.options));
+    auto& panel = *m_pendingRequestData.panel;
+    page->uiClient().runWebAuthenticationPanel(*page, panel, [weakPanel = makeWeakPtr(panel), weakThis = makeWeakPtr(*this), this] (WebAuthenticationPanelResult result) {
+        // The panel address is used to determine if the current pending request is still the same.
+        if (!weakThis || !weakPanel
+            || (result == WebAuthenticationPanelResult::DidNotPresent)
+            || (weakPanel.get() != m_pendingRequestData.panel.get()))
+            return;
+        m_pendingRequestData.panelResult = result;
+        startRequest();
+    });
+}
+
+void AuthenticatorManager::startRequest()
+{
+    ASSERT(RunLoop::isMain());
+    // Get available transports and start discovering authenticators on them.
+    WTF::switchOn(m_pendingRequestData.options, [&](const PublicKeyCredentialCreationOptions& options) {
+        initTimeOutTimer(options.timeout);
+
+        auto transports = collectTransports(options.authenticatorSelection);
+        processGoogleLegacyAppIdSupportExtension(options.extensions, transports);
+        startDiscovery(collectTransports(options.authenticatorSelection));
+    }, [&](const  PublicKeyCredentialRequestOptions& options) {
+        initTimeOutTimer(options.timeout);
+        startDiscovery(collectTransports(options.allowCredentials));
+    });
+}
+
+void AuthenticatorManager::invokePendingCompletionHandler(Respond&& respond)
+{
+    if (auto *panel = m_pendingRequestData.panel.get()) {
+        WTF::switchOn(respond, [&](const WebCore::PublicKeyCredentialData&) {
+            panel->client().dismissPanel(WebAuthenticationResult::Succeeded);
+        }, [&](const  WebCore::ExceptionData&) {
+            panel->client().dismissPanel(WebAuthenticationResult::Failed);
+        });
+    }
+    m_pendingCompletionHandler(WTFMove(respond));
+}
+
 } // namespace WebKit
 
 #endif // ENABLE(WEB_AUTHN)
index 07207d7..d3766ad 100644 (file)
@@ -59,10 +59,10 @@ public:
     virtual bool isMock() const { return false; }
 
 protected:
-    Callback& pendingCompletionHandler() { return m_pendingCompletionHandler; }
     RunLoop::Timer<AuthenticatorManager>& requestTimeOutTimer() { return m_requestTimeOutTimer; }
     void clearStateAsync(); // To void cyclic dependence.
     void clearState();
+    void invokePendingCompletionHandler(Respond&&);
 
 private:
     // AuthenticatorTransportService::Observer
@@ -80,10 +80,12 @@ private:
     void startDiscovery(const TransportSet&);
     void initTimeOutTimer(const Optional<unsigned>& timeOutInMs);
     void timeOutTimerFired();
+    void runPanel();
+    void startRequest();
 
     // Request: We only allow one request per time. A new request will cancel any pending ones.
     WebAuthenticationRequestData m_pendingRequestData;
-    Callback m_pendingCompletionHandler;
+    Callback m_pendingCompletionHandler; // Should be invoked directly, use invokePendingCompletionHandler.
     RunLoop::Timer<AuthenticatorManager> m_requestTimeOutTimer;
 
     Vector<UniqueRef<AuthenticatorTransportService>> m_services;
index 97237f7..3246ee7 100644 (file)
@@ -51,8 +51,6 @@ NfcConnection::NfcConnection(RetainPtr<NFReaderSession>&& session, NfcService& s
     , m_service(makeWeakPtr(service))
 {
     [m_session setDelegate:m_delegate.get()];
-    // FIXME(200933)
-    [m_session updateUIAlertMessage:@"Insert your security key or hold the key against the top of your device."];
     [m_session startPolling];
 }
 
index 33b608e..752d788 100644 (file)
@@ -91,7 +91,7 @@ void NfcService::platformStartDiscovery()
             m_driver = WTF::makeUnique<CtapNfcDriver>(makeUniqueRef<NfcConnection>(WTFMove(session), *this));
         });
     });
-    [[getNFHardwareManagerClass() sharedHardwareManager] startReaderSessionWithActionSheetUI:callback.get()];
+    [[getNFHardwareManagerClass() sharedHardwareManager] startReaderSession:callback.get()];
 #endif // HAVE(NEAR_FIELD)
 }
 
diff --git a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.h b/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.h
new file mode 100644 (file)
index 0000000..c9c8558
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEB_AUTHN)
+
+#import "WKFoundation.h"
+
+#import "APIWebAuthenticationPanelClient.h"
+#import <wtf/RetainPtr.h>
+#import <wtf/WeakObjCPtr.h>
+#import <wtf/WeakPtr.h>
+
+@class _WKWebAuthenticationPanel;
+@protocol _WKWebAuthenticationPanelDelegate;
+
+namespace WebKit {
+
+class WebAuthenticationPanelClient : public API::WebAuthenticationPanelClient, public CanMakeWeakPtr<WebAuthenticationPanelClient> {
+public:
+    WebAuthenticationPanelClient(_WKWebAuthenticationPanel *, id <_WKWebAuthenticationPanelDelegate>);
+
+    RetainPtr<id <_WKWebAuthenticationPanelDelegate> > delegate();
+
+private:
+    // API::WebAuthenticationPanelClient
+    void dismissPanel(WebAuthenticationResult) const final;
+
+    _WKWebAuthenticationPanel *m_panel;
+    WeakObjCPtr<id <_WKWebAuthenticationPanelDelegate> > m_delegate;
+
+    struct {
+        bool panelDismissWebAuthenticationPanelWithResult : 1;
+    } m_delegateMethods;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(WEB_AUTHN)
diff --git a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm b/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm
new file mode 100644 (file)
index 0000000..c184e58
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "WebAuthenticationPanelClient.h"
+
+#if ENABLE(WEB_AUTHN)
+
+#import "WebAuthenticationPanelFlags.h"
+#import "_WKWebAuthenticationPanel.h"
+
+namespace WebKit {
+
+WebAuthenticationPanelClient::WebAuthenticationPanelClient(_WKWebAuthenticationPanel *panel, id <_WKWebAuthenticationPanelDelegate> delegate)
+    : m_panel(panel)
+    , m_delegate(delegate)
+{
+    m_delegateMethods.panelDismissWebAuthenticationPanelWithResult = [delegate respondsToSelector:@selector(panel:dismissWebAuthenticationPanelWithResult:)];
+}
+
+RetainPtr<id <_WKWebAuthenticationPanelDelegate> > WebAuthenticationPanelClient::delegate()
+{
+    return m_delegate.get();
+}
+
+static _WKWebAuthenticationResult wkWebAuthenticationResult(WebAuthenticationResult result)
+{
+    switch (result) {
+    case WebAuthenticationResult::Succeeded:
+        return _WKWebAuthenticationResultSucceeded;
+    case WebAuthenticationResult::Failed:
+        return _WKWebAuthenticationResultFailed;
+    }
+    ASSERT_NOT_REACHED();
+    return _WKWebAuthenticationResultFailed;
+}
+
+void WebAuthenticationPanelClient::dismissPanel(WebAuthenticationResult result) const
+{
+    if (!m_delegateMethods.panelDismissWebAuthenticationPanelWithResult)
+        return;
+
+    auto delegate = m_delegate.get();
+    if (!delegate)
+        return;
+
+    [delegate panel:m_panel dismissWebAuthenticationPanelWithResult:wkWebAuthenticationResult(result)];
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(WEB_AUTHN)
index 4db2760..084c9be 100644 (file)
@@ -45,7 +45,7 @@ void MockAuthenticatorManager::respondReceivedInternal(Respond&& respond)
     if (m_testConfiguration.silentFailure)
         return;
 
-    pendingCompletionHandler()(WTFMove(respond));
+    invokePendingCompletionHandler(WTFMove(respond));
     clearStateAsync();
     requestTimeOutTimer().stop();
 }
diff --git a/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticationPanelFlags.h b/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticationPanelFlags.h
new file mode 100644 (file)
index 0000000..0d146b2
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEB_AUTHN)
+
+namespace WebKit {
+
+enum class WebAuthenticationPanelResult : uint8_t {
+    Unavailable,
+    Presented,
+    DidNotPresent
+};
+
+enum class WebAuthenticationResult : bool {
+    Succeeded,
+    Failed
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(WEB_AUTHN)
index 66ebb7c..4bb5485 100644 (file)
 
 #if ENABLE(WEB_AUTHN)
 
-#include "WebPreferences.h"
+#include "APIWebAuthenticationPanel.h"
+#include "WebAuthenticationPanelFlags.h"
 #include <WebCore/PublicKeyCredentialCreationOptions.h>
 #include <WebCore/PublicKeyCredentialRequestOptions.h>
 #include <wtf/Variant.h>
 #include <wtf/Vector.h>
+#include <wtf/WeakPtr.h>
 
 namespace WebKit {
 
+class WebPageProxy;
+
 struct WebAuthenticationRequestData {
     Vector<uint8_t> hash;
     Variant<WebCore::PublicKeyCredentialCreationOptions, WebCore::PublicKeyCredentialRequestOptions> options;
-    RefPtr<WebPreferences> preferences;
+    WeakPtr<WebPageProxy> page;
+    WebAuthenticationPanelResult panelResult { WebAuthenticationPanelResult::Unavailable };
+    RefPtr<API::WebAuthenticationPanel> panel;
 };
 
 } // namespace WebKit
index 87e28a1..4fcd8cd 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "AuthenticatorManager.h"
 #include "LocalService.h"
+#include "WebAuthenticationPanelFlags.h"
 #include "WebAuthenticatorCoordinatorMessages.h"
 #include "WebAuthenticatorCoordinatorProxyMessages.h"
 #include "WebPageProxy.h"
@@ -55,12 +56,12 @@ WebAuthenticatorCoordinatorProxy::~WebAuthenticatorCoordinatorProxy()
 
 void WebAuthenticatorCoordinatorProxy::makeCredential(uint64_t messageId, const Vector<uint8_t>& hash, const WebCore::PublicKeyCredentialCreationOptions& options)
 {
-    handleRequest(messageId, { hash, options, m_webPageProxy.preferences().copy() });
+    handleRequest(messageId, { hash, options, makeWeakPtr(m_webPageProxy), WebAuthenticationPanelResult::Unavailable, nullptr });
 }
 
 void WebAuthenticatorCoordinatorProxy::getAssertion(uint64_t messageId, const Vector<uint8_t>& hash, const WebCore::PublicKeyCredentialRequestOptions& options)
 {
-    handleRequest(messageId, { hash, options, m_webPageProxy.preferences().copy() });
+    handleRequest(messageId, { hash, options, makeWeakPtr(m_webPageProxy), WebAuthenticationPanelResult::Unavailable, nullptr });
 }
 
 void WebAuthenticatorCoordinatorProxy::handleRequest(uint64_t messageId, WebAuthenticationRequestData&& data)
index ebf6f07..daaa17e 100644 (file)
                57597EBD218184900037F924 /* CtapAuthenticator.h in Headers */ = {isa = PBXBuildFile; fileRef = 57597EBB2181848F0037F924 /* CtapAuthenticator.h */; };
                576CA9D722B862180030143C /* SOAuthorizationNSURLExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = 57FD317322B35148008D0E8B /* SOAuthorizationNSURLExtras.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5772F206217DBD6A0056BF2C /* HidService.h in Headers */ = {isa = PBXBuildFile; fileRef = 5772F204217DBD6A0056BF2C /* HidService.h */; };
+               577FF7822346E81C004EDFB9 /* APIWebAuthenticationPanelClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 577FF7812346E81C004EDFB9 /* APIWebAuthenticationPanelClient.h */; };
+               577FF7852346ECAA004EDFB9 /* WebAuthenticationPanelClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 577FF7832346ECAA004EDFB9 /* WebAuthenticationPanelClient.h */; };
                578DC2982155A0020074E815 /* LocalAuthenticationSoftLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 578DC2972155A0010074E815 /* LocalAuthenticationSoftLink.h */; };
                57AC8F50217FEED90055438C /* HidConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 57AC8F4E217FEED90055438C /* HidConnection.h */; };
                57B4B46020B504AC00D4AD79 /* ClientCertificateAuthenticationXPCConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 57B4B45E20B504AB00D4AD79 /* ClientCertificateAuthenticationXPCConstants.h */; };
                57B8264823050C5100B72EB0 /* FidoService.h in Headers */ = {isa = PBXBuildFile; fileRef = 57B8264623050C5100B72EB0 /* FidoService.h */; };
                57B8264C230603C100B72EB0 /* MockNfcService.h in Headers */ = {isa = PBXBuildFile; fileRef = 57B8264A230603C100B72EB0 /* MockNfcService.h */; };
                57BBEA6D22BC0BFE00273995 /* SOAuthorizationLoadPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = 57BBEA6C22BC0BFE00273995 /* SOAuthorizationLoadPolicy.h */; };
+               57C6244B234679A400383FE7 /* WebAuthenticationPanelFlags.h in Headers */ = {isa = PBXBuildFile; fileRef = 57C6244A234679A400383FE7 /* WebAuthenticationPanelFlags.h */; };
                57DCED6E2142EE5E0016B847 /* WebAuthenticatorCoordinatorMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57DCED6B2142EAE20016B847 /* WebAuthenticatorCoordinatorMessageReceiver.cpp */; };
                57DCED6F2142EE630016B847 /* WebAuthenticatorCoordinatorMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 57DCED6A2142EAE20016B847 /* WebAuthenticatorCoordinatorMessages.h */; };
                57DCED702142EE680016B847 /* WebAuthenticatorCoordinatorProxyMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57DCED6C2142EAF90016B847 /* WebAuthenticatorCoordinatorProxyMessageReceiver.cpp */; };
                57DCEDC7214F18300016B847 /* MockLocalConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 57DCEDC5214F18300016B847 /* MockLocalConnection.h */; };
                57DCEDCB214F4E420016B847 /* MockAuthenticatorManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 57DCEDC9214F4E420016B847 /* MockAuthenticatorManager.h */; };
                57EB2E3A21E1983E00B89CDF /* U2fAuthenticator.h in Headers */ = {isa = PBXBuildFile; fileRef = 57EB2E3821E1983E00B89CDF /* U2fAuthenticator.h */; };
+               57EBE26A234676C5008D8AF9 /* APIWebAuthenticationPanel.h in Headers */ = {isa = PBXBuildFile; fileRef = 57EBE268234676C5008D8AF9 /* APIWebAuthenticationPanel.h */; };
                57FD318022B35158008D0E8B /* NavigationSOAuthorizationSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 57FD317822B35149008D0E8B /* NavigationSOAuthorizationSession.h */; };
                57FD318122B3515B008D0E8B /* PopUpSOAuthorizationSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 57FD317022B35148008D0E8B /* PopUpSOAuthorizationSession.h */; };
                57FD318222B3515E008D0E8B /* RedirectSOAuthorizationSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 57FD317422B35149008D0E8B /* RedirectSOAuthorizationSession.h */; };
                57608299202BDAE200116678 /* WebAuthenticatorCoordinatorProxy.messages.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = WebAuthenticatorCoordinatorProxy.messages.in; sourceTree = "<group>"; };
                5772F204217DBD6A0056BF2C /* HidService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HidService.h; sourceTree = "<group>"; };
                5772F205217DBD6A0056BF2C /* HidService.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = HidService.mm; sourceTree = "<group>"; };
+               577FF7812346E81C004EDFB9 /* APIWebAuthenticationPanelClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = APIWebAuthenticationPanelClient.h; sourceTree = "<group>"; };
+               577FF7832346ECAA004EDFB9 /* WebAuthenticationPanelClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebAuthenticationPanelClient.h; sourceTree = "<group>"; };
+               577FF7842346ECAA004EDFB9 /* WebAuthenticationPanelClient.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WebAuthenticationPanelClient.mm; sourceTree = "<group>"; };
                578DC2972155A0010074E815 /* LocalAuthenticationSoftLink.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LocalAuthenticationSoftLink.h; sourceTree = "<group>"; };
                57AC8F4E217FEED90055438C /* HidConnection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HidConnection.h; sourceTree = "<group>"; };
                57AC8F4F217FEED90055438C /* HidConnection.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = HidConnection.mm; sourceTree = "<group>"; };
                57B8264A230603C100B72EB0 /* MockNfcService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockNfcService.h; sourceTree = "<group>"; };
                57B8264B230603C100B72EB0 /* MockNfcService.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MockNfcService.mm; sourceTree = "<group>"; };
                57BBEA6C22BC0BFE00273995 /* SOAuthorizationLoadPolicy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOAuthorizationLoadPolicy.h; sourceTree = "<group>"; };
+               57C6244A234679A400383FE7 /* WebAuthenticationPanelFlags.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebAuthenticationPanelFlags.h; sourceTree = "<group>"; };
                57DCED6A2142EAE20016B847 /* WebAuthenticatorCoordinatorMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAuthenticatorCoordinatorMessages.h; path = DerivedSources/WebKit2/WebAuthenticatorCoordinatorMessages.h; sourceTree = BUILT_PRODUCTS_DIR; };
                57DCED6B2142EAE20016B847 /* WebAuthenticatorCoordinatorMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAuthenticatorCoordinatorMessageReceiver.cpp; path = DerivedSources/WebKit2/WebAuthenticatorCoordinatorMessageReceiver.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
                57DCED6C2142EAF90016B847 /* WebAuthenticatorCoordinatorProxyMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAuthenticatorCoordinatorProxyMessageReceiver.cpp; path = DerivedSources/WebKit2/WebAuthenticatorCoordinatorProxyMessageReceiver.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
                57DCEDCD214F51680016B847 /* MockAuthenticatorManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MockAuthenticatorManager.cpp; sourceTree = "<group>"; };
                57EB2E3821E1983E00B89CDF /* U2fAuthenticator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = U2fAuthenticator.h; sourceTree = "<group>"; };
                57EB2E3921E1983E00B89CDF /* U2fAuthenticator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = U2fAuthenticator.cpp; sourceTree = "<group>"; };
+               57EBE268234676C5008D8AF9 /* APIWebAuthenticationPanel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = APIWebAuthenticationPanel.h; sourceTree = "<group>"; };
+               57EBE269234676C5008D8AF9 /* APIWebAuthenticationPanel.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = APIWebAuthenticationPanel.cpp; sourceTree = "<group>"; };
                57FD317022B35148008D0E8B /* PopUpSOAuthorizationSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PopUpSOAuthorizationSession.h; sourceTree = "<group>"; };
                57FD317122B35148008D0E8B /* WKSOAuthorizationDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKSOAuthorizationDelegate.h; sourceTree = "<group>"; };
                57FD317222B35148008D0E8B /* SOAuthorizationCoordinator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOAuthorizationCoordinator.h; sourceTree = "<group>"; };
                                57DCED842147363A0016B847 /* AuthenticatorManager.h */,
                                57DCED9921489F4D0016B847 /* AuthenticatorTransportService.cpp */,
                                57DCED8A214853130016B847 /* AuthenticatorTransportService.h */,
+                               57C6244A234679A400383FE7 /* WebAuthenticationPanelFlags.h */,
                                57DCEDA62149F9DA0016B847 /* WebAuthenticationRequestData.h */,
                                57608296202BD8BA00116678 /* WebAuthenticatorCoordinatorProxy.cpp */,
                                57608295202BD8BA00116678 /* WebAuthenticatorCoordinatorProxy.h */,
                                570DAAC12303730300E8FC04 /* NfcConnection.mm */,
                                570DAAAC23026F5C00E8FC04 /* NfcService.h */,
                                570DAAAD23026F5C00E8FC04 /* NfcService.mm */,
+                               577FF7832346ECAA004EDFB9 /* WebAuthenticationPanelClient.h */,
+                               577FF7842346ECAA004EDFB9 /* WebAuthenticationPanelClient.mm */,
                                570DAAC423037F7E00E8FC04 /* WKNFReaderSessionDelegate.h */,
                                570DAAC523037F7E00E8FC04 /* WKNFReaderSessionDelegate.mm */,
                        );
                                7C89D2921A67122F003A5FDE /* APIUserScript.h */,
                                2D8786211BDB58FF00D02ABB /* APIUserStyleSheet.cpp */,
                                2D8786221BDB58FF00D02ABB /* APIUserStyleSheet.h */,
+                               57EBE269234676C5008D8AF9 /* APIWebAuthenticationPanel.cpp */,
+                               57EBE268234676C5008D8AF9 /* APIWebAuthenticationPanel.h */,
+                               577FF7812346E81C004EDFB9 /* APIWebAuthenticationPanelClient.h */,
                                1AE286811C7F93860069AC4F /* APIWebsiteDataRecord.cpp */,
                                1AE286821C7F93860069AC4F /* APIWebsiteDataRecord.h */,
                                5C8DD37D1FE4501100F2A556 /* APIWebsitePolicies.cpp */,
                                2D8786241BDB58FF00D02ABB /* APIUserStyleSheet.h in Headers */,
                                C5E1AFED16B21017006CC1F2 /* APIWebArchive.h in Headers */,
                                C5E1AFEF16B21029006CC1F2 /* APIWebArchiveResource.h in Headers */,
+                               57EBE26A234676C5008D8AF9 /* APIWebAuthenticationPanel.h in Headers */,
+                               577FF7822346E81C004EDFB9 /* APIWebAuthenticationPanelClient.h in Headers */,
                                1AE286841C7F93860069AC4F /* APIWebsiteDataRecord.h in Headers */,
                                1A6563E51B7A8C50009CF787 /* APIWindowFeatures.h in Headers */,
                                F48D2A8521583A7E00C6752B /* AppKitSPI.h in Headers */,
                                1AF4CEF018BC481800BC2D34 /* VisitedLinkTableController.h in Headers */,
                                1A8E7D3D18C15149005A702A /* VisitedLinkTableControllerMessages.h in Headers */,
                                CEDA12E3152CD1B300D9E08D /* WebAlternativeTextClient.h in Headers */,
+                               577FF7852346ECAA004EDFB9 /* WebAuthenticationPanelClient.h in Headers */,
+                               57C6244B234679A400383FE7 /* WebAuthenticationPanelFlags.h in Headers */,
                                57DCEDB2214C604C0016B847 /* WebAuthenticationRequestData.h in Headers */,
                                57DCED6F2142EE630016B847 /* WebAuthenticatorCoordinatorMessages.h in Headers */,
                                57DCEDB3214C60530016B847 /* WebAuthenticatorCoordinatorProxy.h in Headers */,
index 610c4ba..e796134 100644 (file)
@@ -1,3 +1,24 @@
+2019-10-04  Jiewen Tan  <jiewen_tan@apple.com>
+
+        [WebAuthn] Implement _WKWebAuthenticationPanel SPI
+        https://bugs.webkit.org/show_bug.cgi?id=202559
+        <rdar://problem/55932094>
+
+        Reviewed by Brent Fulgham.
+
+        This patch adds a very limited test case to _WKWebAuthenticationPanel.
+        Bug 202560 and Bug 202565 will follow up to write more tests.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm: Added.
+        (-[TestWebAuthenticationPanelDelegate panel:dismissWebAuthenticationPanelWithResult:]):
+        (-[TestWebAuthenticationPanelUIDelegate webView:runWebAuthenticationPanel:initiatedByFrame:completionHandler:]):
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion.html: Added.
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::runWebAuthenticationPanel):
+        (WTR::TestController::createWebViewWithOptions):
+
 2019-10-04  Alex Christensen  <achristensen@webkit.org>
 
         Move WKProcessPool._registerURLSchemeServiceWorkersCanHandle to _WKWebsiteDataStoreConfiguration
index 6641f5f..88f6d08 100644 (file)
                5797FE331EB15AB100B2F4A0 /* navigation-client-default-crypto.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5797FE321EB15A8900B2F4A0 /* navigation-client-default-crypto.html */; };
                57A79857224AB34E00A7F6F1 /* WebCryptoMasterKey.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57A79856224AB34E00A7F6F1 /* WebCryptoMasterKey.mm */; };
                57C3FA661F7C248F009D4B80 /* WeakPtr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1CB9BC371A67482300FE5678 /* WeakPtr.cpp */; };
+               57C6244E2346BCFA00383FE7 /* _WKWebAuthenticationPanel.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57C6244D2346BCFA00383FE7 /* _WKWebAuthenticationPanel.mm */; };
+               57C624502346C21E00383FE7 /* web-authentication-get-assertion.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 57C6244F2346C1EC00383FE7 /* web-authentication-get-assertion.html */; };
                57F4AAA0208FAEF000A68E9E /* SSLKeyGenerator.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57F4AA9F208FA83D00A68E9E /* SSLKeyGenerator.mm */; };
                57F56A5C1C7F8CC100F31D7E /* IsNavigationActionTrusted.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 57F56A5B1C7F8A4000F31D7E /* IsNavigationActionTrusted.html */; };
                5C0160C121A132460077FA32 /* JITEnabled.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C0160C021A132320077FA32 /* JITEnabled.mm */; };
                                CDC8E4971BC6F10800594FEC /* video-without-audio.mp4 in Copy Resources */,
                                2EBD9D0A2134730D002DA758 /* video.html in Copy Resources */,
                                CD577799211CE0E4001B371E /* web-audio-only.html in Copy Resources */,
+                               57C624502346C21E00383FE7 /* web-authentication-get-assertion.html in Copy Resources */,
                                1C2B81861C89259D00A5529F /* webfont.html in Copy Resources */,
                                51714EB41CF8C78C004723C4 /* WebProcessKillIDBCleanup-1.html in Copy Resources */,
                                51714EB51CF8C78C004723C4 /* WebProcessKillIDBCleanup-2.html in Copy Resources */,
                5797FE321EB15A8900B2F4A0 /* navigation-client-default-crypto.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "navigation-client-default-crypto.html"; sourceTree = "<group>"; };
                5798E2AF1CAF5C2800C5CBA0 /* ProvisionalURLNotChange.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ProvisionalURLNotChange.mm; sourceTree = "<group>"; };
                57A79856224AB34E00A7F6F1 /* WebCryptoMasterKey.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCryptoMasterKey.mm; sourceTree = "<group>"; };
+               57C6244D2346BCFA00383FE7 /* _WKWebAuthenticationPanel.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKWebAuthenticationPanel.mm; sourceTree = "<group>"; };
+               57C6244F2346C1EC00383FE7 /* web-authentication-get-assertion.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "web-authentication-get-assertion.html"; sourceTree = "<group>"; };
                57D1D75E21DCB7A80093E86A /* U2fCommandConstructorTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = U2fCommandConstructorTest.cpp; sourceTree = "<group>"; };
                57F10D921C7E7B3800ECDF30 /* IsNavigationActionTrusted.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = IsNavigationActionTrusted.mm; sourceTree = "<group>"; };
                57F4AA9F208FA83D00A68E9E /* SSLKeyGenerator.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SSLKeyGenerator.mm; sourceTree = "<group>"; };
                                A16F66B81C40E9E100BD4D24 /* Resources */,
                                5CEAB5DF1FA937CB00A77FAA /* _WKInputDelegate.mm */,
                                7CEFA9641AC0B9E200B910FD /* _WKUserContentExtensionStore.mm */,
+                               57C6244D2346BCFA00383FE7 /* _WKWebAuthenticationPanel.mm */,
                                0746645822FF630500E3451A /* AccessibilityTestPlugin.mm */,
                                0746645722FF62D000E3451A /* AccessibilityTestSupportProtocol.h */,
                                37E7DD631EA06FF2009B396D /* AdditionalReadAccessAllowedURLs.mm */,
                                F4451C751EB8FD7C0020C5DA /* two-paragraph-contenteditable.html */,
                                CD57779B211CE6CE001B371E /* video-with-audio-and-web-audio.html */,
                                CD577798211CDE8F001B371E /* web-audio-only.html */,
+                               57C6244F2346C1EC00383FE7 /* web-authentication-get-assertion.html */,
                                51714EB21CF8C761004723C4 /* WebProcessKillIDBCleanup-1.html */,
                                51714EB31CF8C761004723C4 /* WebProcessKillIDBCleanup-2.html */,
                                5120C83B1E674E350025B250 /* WebsiteDataStoreCustomPaths.html */,
                        files = (
                                5CEAB5E11FA939F400A77FAA /* _WKInputDelegate.mm in Sources */,
                                7CEFA9661AC0B9E200B910FD /* _WKUserContentExtensionStore.mm in Sources */,
+                               57C6244E2346BCFA00383FE7 /* _WKWebAuthenticationPanel.mm in Sources */,
                                7CCE7EE41A411AE600447C4C /* AboutBlankLoad.cpp in Sources */,
                                7CCE7EB31A411A7E00447C4C /* AcceptsFirstMouse.mm in Sources */,
                                2E205BA41F527746005952DD /* AccessibilityTestsIOS.mm in Sources */,
diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm
new file mode 100644 (file)
index 0000000..ce411be
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "Test.h"
+
+#if ENABLE(WEB_AUTHN)
+
+#import "PlatformUtilities.h"
+#import "TestWKWebView.h"
+#import <WebKit/WKPreferencesPrivate.h>
+#import <WebKit/WKUIDelegatePrivate.h>
+#import <WebKit/_WKExperimentalFeature.h>
+#import <WebKit/_WKWebAuthenticationPanel.h>
+
+static bool webAuthenticationPanelRan = false;
+static bool webAuthenticationPanelDimissed = false;
+
+@interface TestWebAuthenticationPanelDelegate : NSObject <_WKWebAuthenticationPanelDelegate>
+@end
+
+@implementation TestWebAuthenticationPanelDelegate
+
+- (void)panel:(_WKWebAuthenticationPanel *)panel dismissWebAuthenticationPanelWithResult:(_WKWebAuthenticationResult)result
+{
+    ASSERT_NE(panel, nil);
+    EXPECT_EQ(result, _WKWebAuthenticationResultFailed);
+    webAuthenticationPanelDimissed = true;
+}
+
+@end
+
+@interface TestWebAuthenticationPanelUIDelegate : NSObject <WKUIDelegatePrivate>
+@end
+
+@implementation TestWebAuthenticationPanelUIDelegate {
+    RetainPtr<_WKWebAuthenticationPanel> _panel;
+    RetainPtr<TestWebAuthenticationPanelDelegate> _delegate;
+}
+
+- (void)webView:(WKWebView *)webView runWebAuthenticationPanel:(_WKWebAuthenticationPanel *)panel initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(_WKWebAuthenticationPanelResult))completionHandler
+{
+    webAuthenticationPanelRan = true;
+
+    _delegate = adoptNS([[TestWebAuthenticationPanelDelegate alloc] init]);
+    ASSERT_NE(panel, nil);
+    _panel = panel;
+    [_panel setDelegate:_delegate.get()];
+
+    EXPECT_WK_STREQ([_panel relyingPartyID], "");
+
+    completionHandler(_WKWebAuthenticationPanelResultPresented);
+}
+
+@end
+
+namespace TestWebKitAPI {
+
+namespace {
+_WKExperimentalFeature *webAuthenticationExperimentalFeature()
+{
+    static RetainPtr<_WKExperimentalFeature> theFeature;
+    if (theFeature)
+        return theFeature.get();
+
+    NSArray *features = [WKPreferences _experimentalFeatures];
+    for (_WKExperimentalFeature *feature in features) {
+        if ([feature.key isEqual:@"WebAuthenticationEnabled"]) {
+            theFeature = feature;
+            break;
+        }
+    }
+    return theFeature.get();
+}
+}
+
+TEST(WebAuthenticationPanel, BasicTimeout)
+{
+    RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
+
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
+
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration.get()]);
+    auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
+    [webView setUIDelegate:delegate.get()];
+
+    // Only focused documents can trigger WebAuthn.
+#if PLATFORM(MAC)
+    [[webView hostWindow] makeFirstResponder:webView.get()];
+#elif PLATFORM(IOS)
+    [webView becomeFirstResponder];
+#endif
+
+    [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
+    Util::run(&webAuthenticationPanelRan);
+    Util::run(&webAuthenticationPanelDimissed);
+}
+
+} // namespace TestWebKitAPI
+
+#endif // ENABLE(WEB_AUTHN)
diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion.html b/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion.html
new file mode 100644 (file)
index 0000000..bf49a5f
--- /dev/null
@@ -0,0 +1,10 @@
+<script>
+    const options = {
+        publicKey: {
+            challenge: new Uint8Array(16),
+            timeout: 1
+        }
+    };
+
+    navigator.credentials.get(options);
+</script>
index 0bd7761..9b8071d 100644 (file)
@@ -295,6 +295,11 @@ static bool shouldAllowDeviceOrientationAndMotionAccess(WKPageRef, WKSecurityOri
     return TestController::singleton().handleDeviceOrientationAndMotionAccessRequest(origin);
 }
 
+// A placeholder to tell WebKit the client is WebKitTestRunner.
+static void runWebAuthenticationPanel()
+{
+}
+
 WKPageRef TestController::createOtherPage(WKPageRef, WKPageConfigurationRef configuration, WKNavigationActionRef navigationAction, WKWindowFeaturesRef windowFeatures, const void *clientInfo)
 {
     PlatformWebView* parentView = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
@@ -617,8 +622,8 @@ void TestController::createWebViewWithOptions(const TestOptions& options)
     resetPreferencesToConsistentValues(options);
 
     platformCreateWebView(configuration.get(), options);
-    WKPageUIClientV13 pageUIClient = {
-        { 13, m_mainWebView.get() },
+    WKPageUIClientV14 pageUIClient = {
+        { 14, m_mainWebView.get() },
         0, // createNewPage_deprecatedForUseWithV0
         0, // showPage
         0, // close
@@ -690,7 +695,8 @@ void TestController::createWebViewWithOptions(const TestOptions& options)
         0, // didExceedBackgroundResourceLimitWhileInForeground
         0, // didResignInputElementStrongPasswordAppearance
         0, // requestStorageAccessConfirm
-        shouldAllowDeviceOrientationAndMotionAccess
+        shouldAllowDeviceOrientationAndMotionAccess,
+        runWebAuthenticationPanel
     };
     WKPageSetPageUIClient(m_mainWebView->page(), &pageUIClient.base);