Title: [251645] trunk
Revision
251645
Author
[email protected]
Date
2019-10-27 15:53:33 -0700 (Sun, 27 Oct 2019)

Log Message

[WebAuthn] Warn users when multiple NFC tags present
https://bugs.webkit.org/show_bug.cgi?id=200932
<rdar://problem/54890736>

Reviewed by Brent Fulgham.

Source/WebCore:

Covered by new tests in existing test file.

* testing/MockWebAuthenticationConfiguration.h:
(WebCore::MockWebAuthenticationConfiguration::NfcConfiguration::encode const):
(WebCore::MockWebAuthenticationConfiguration::NfcConfiguration::decode):
* testing/MockWebAuthenticationConfiguration.idl:
Adds a new test option.

Source/WebKit:

This patch utilizes -[_WKWebAuthenticationPanelDelegate panel:updateWebAuthenticationPanel:] to
inform clients about multiple physical tags are presenting such that clients can instruct users
to select only one of them physically. Given a physical tag could have multiple different
interfaces, which NearField will treat them into different NFTags, the tagID is then used to
identify if there are actually multiple physical tags.

This patch also adds the ability to restart polling of a partiuclar NFReaderSession to NfcConnection
and the ability to restart the whole session to NfcService. The former is used to recover from errors
in the discovery stages, and the latter is used to recover from errors returned from authenticators
in the request stages. For the latter, given NfcConnection is not awared of the syntax of FIDO2/U2F
protocol, and CtapAuthenticator/U2fAuthenticator are not awared the transport of the underneath driver.
A generic restartDiscovery process is added to each service and it is up to the actual service to
implement the actual process such that AuthenticatorManager can arbitrarily call it after exceptions
are returned to restart the whole NFC session. To achieve restartDiscovery, NfcConnection is made
RefCounted as well such that both the NfcService and the CtapNfcDriver could hold it at the same time.
CtapNfcDriver uses the connection to complete requests as before while NfcService has the new capability
to use it to stop the current session when restartDiscovery kicks off.

* Platform/spi/Cocoa/NearFieldSPI.h:
* UIProcess/WebAuthentication/AuthenticatorManager.cpp:
(WebKit::AuthenticatorManager::serviceStatusUpdated):
(WebKit::AuthenticatorManager::respondReceived):
(WebKit::AuthenticatorManager::restartDiscovery):
* UIProcess/WebAuthentication/AuthenticatorManager.h:
* UIProcess/WebAuthentication/AuthenticatorTransportService.cpp:
(WebKit::AuthenticatorTransportService::startDiscovery):
(WebKit::AuthenticatorTransportService::restartDiscovery):
* UIProcess/WebAuthentication/AuthenticatorTransportService.h:
(WebKit::AuthenticatorTransportService::restartDiscoveryInternal):
* UIProcess/WebAuthentication/Cocoa/NfcConnection.h:
* UIProcess/WebAuthentication/Cocoa/NfcConnection.mm:
(WebKit::NfcConnection::create):
(WebKit::NfcConnection::NfcConnection):
(WebKit::NfcConnection::~NfcConnection):
(WebKit::NfcConnection::stop const):
(WebKit::NfcConnection::didDetectTags):
(WebKit::NfcConnection::restartPolling):
(WebKit::NfcConnection::startPolling):
(WebKit::NfcConnection::didDetectTags const): Deleted.
* UIProcess/WebAuthentication/Cocoa/NfcService.h:
* UIProcess/WebAuthentication/Cocoa/NfcService.mm:
(WebKit::NfcService::NfcService):
(WebKit::NfcService::didConnectTag):
(WebKit::NfcService::didDetectMultipleTags const):
(WebKit::NfcService::setConnection):
(WebKit::NfcService::restartDiscoveryInternal):
(WebKit::NfcService::platformStartDiscovery):
(WebKit::NfcService::setDriver): Deleted.
* UIProcess/WebAuthentication/Mock/MockNfcService.h:
* UIProcess/WebAuthentication/Mock/MockNfcService.mm:
(-[WKMockNFTag tagID]):
(-[WKMockNFTag initWithNFTag:]):
(-[WKMockNFTag dealloc]):
(-[WKMockNFTag initWithType:]):
(-[WKMockNFTag initWithType:tagID:]):
(WebKit::MockNfcService::receiveStopPolling):
(WebKit::MockNfcService::receiveStartPolling):
(WebKit::MockNfcService::platformStartDiscovery):
(WebKit::MockNfcService::detectTags):
(WebKit::MockNfcService::detectTags const): Deleted.
* UIProcess/WebAuthentication/fido/CtapNfcDriver.cpp:
(WebKit::CtapNfcDriver::CtapNfcDriver):
* UIProcess/WebAuthentication/fido/CtapNfcDriver.h:
* UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp:

Tools:

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm:
(-[TestWebAuthenticationPanelDelegate panel:updateWebAuthenticationPanel:]):
(TestWebKitAPI::TEST):
Adds a new test for -[_WKWebAuthenticationPanelDelegate panel:updateWebAuthenticationPanel:].
* TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion-nfc-multiple-tags.html: Added.

LayoutTests:

* http/wpt/webauthn/public-key-credential-create-success-nfc.https-expected.txt:
* http/wpt/webauthn/public-key-credential-create-success-nfc.https.html:
Adds new tests for multiple physical tags and service restart.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (251644 => 251645)


--- trunk/LayoutTests/ChangeLog	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/LayoutTests/ChangeLog	2019-10-27 22:53:33 UTC (rev 251645)
@@ -1,3 +1,15 @@
+2019-10-21  Jiewen Tan  <[email protected]>
+
+        [WebAuthn] Warn users when multiple NFC tags present
+        https://bugs.webkit.org/show_bug.cgi?id=200932
+        <rdar://problem/54890736>
+
+        Reviewed by Brent Fulgham.
+
+        * http/wpt/webauthn/public-key-credential-create-success-nfc.https-expected.txt:
+        * http/wpt/webauthn/public-key-credential-create-success-nfc.https.html:
+        Adds new tests for multiple physical tags and service restart.
+
 2019-10-27  Simon Fraser  <[email protected]>
 
         Import css/css-position WPT

Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-nfc.https-expected.txt (251644 => 251645)


--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-nfc.https-expected.txt	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-nfc.https-expected.txt	2019-10-27 22:53:33 UTC (rev 251645)
@@ -3,4 +3,6 @@
 PASS PublicKeyCredential's [[create]] with authenticatorSelection { 'cross-platform' } in a mock nfc authenticator. 
 PASS PublicKeyCredential's [[create]] with multiple tags in a mock nfc authenticator. 
 PASS PublicKeyCredential's [[create]] with U2F in a mock nfc authenticator. 
+PASS PublicKeyCredential's [[create]] with multiple physical tags in a mock nfc authenticator. 
+PASS PublicKeyCredential's [[create]] with service restart in a mock nfc authenticator. 
 

Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-nfc.https.html (251644 => 251645)


--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-nfc.https.html	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-nfc.https.html	2019-10-27 22:53:33 UTC (rev 251645)
@@ -21,8 +21,7 @@
                     displayName: "Appleseed",
                 },
                 challenge: Base64URL.parse("MTIzNDU2"),
-                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
-                timeout: 100
+                pubKeyCredParams: [{ type: "public-key", alg: -7 }]
             }
         };
 
@@ -44,8 +43,7 @@
                 },
                 challenge: Base64URL.parse("MTIzNDU2"),
                 pubKeyCredParams: [{ type: "public-key", alg: -7 }],
-                authenticatorSelection: { authenticatorAttachment: "cross-platform" },
-                timeout: 100
+                authenticatorSelection: { authenticatorAttachment: "cross-platform" }
             }
         };
 
@@ -66,8 +64,7 @@
                     displayName: "Appleseed",
                 },
                 challenge: Base64URL.parse("MTIzNDU2"),
-                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
-                timeout: 100
+                pubKeyCredParams: [{ type: "public-key", alg: -7 }]
             }
         };
 
@@ -90,8 +87,7 @@
                     displayName: "Appleseed",
                 },
                 challenge: Base64URL.parse("MTIzNDU2"),
-                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
-                timeout: 100
+                pubKeyCredParams: [{ type: "public-key", alg: -7 }]
             }
         };
 
@@ -101,4 +97,50 @@
             checkU2fMakeCredentialResult(credential);
         });
     }, "PublicKeyCredential's [[create]] with U2F in a mock nfc authenticator.");
+
+    promise_test(t => {
+        const options = {
+            publicKey: {
+                rp: {
+                    name: "localhost",
+                },
+                user: {
+                    name: "John Appleseed",
+                    id: Base64URL.parse(testUserhandleBase64),
+                    displayName: "Appleseed",
+                },
+                challenge: Base64URL.parse("MTIzNDU2"),
+                pubKeyCredParams: [{ type: "public-key", alg: -7 }]
+            }
+        };
+
+        if (window.internals)
+            internals.setMockWebAuthenticationConfiguration({ nfc: { error: "success", payloadBase64: [testNfcCtapVersionBase64, testGetInfoResponseApduBase64, testCreationMessageApduBase64], multiplePhysicalTags: true } });
+        return navigator.credentials.create(options).then(credential => {
+            checkCtapMakeCredentialResult(credential);
+        });
+    }, "PublicKeyCredential's [[create]] with multiple physical tags in a mock nfc authenticator.");
+
+    promise_test(t => {
+        const options = {
+            publicKey: {
+                rp: {
+                    name: "localhost",
+                },
+                user: {
+                    name: "John Appleseed",
+                    id: Base64URL.parse(testUserhandleBase64),
+                    displayName: "Appleseed",
+                },
+                challenge: Base64URL.parse("MTIzNDU2"),
+                pubKeyCredParams: [{ type: "public-key", alg: -7 }]
+            }
+        };
+
+        if (window.internals)
+            internals.setMockWebAuthenticationConfiguration({ silentFailure: true, nfc: { error: "malicious-payload", payloadBase64: [testDummyMessagePayloadBase64, testNfcCtapVersionBase64, testGetInfoResponseApduBase64, testCreationMessageApduBase64] } });
+        return navigator.credentials.create(options).then(credential => {
+            checkCtapMakeCredentialResult(credential);
+        });
+    }, "PublicKeyCredential's [[create]] with service restart in a mock nfc authenticator.");
 </script>

Modified: trunk/Source/WebCore/ChangeLog (251644 => 251645)


--- trunk/Source/WebCore/ChangeLog	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/Source/WebCore/ChangeLog	2019-10-27 22:53:33 UTC (rev 251645)
@@ -1,3 +1,19 @@
+2019-10-21  Jiewen Tan  <[email protected]>
+
+        [WebAuthn] Warn users when multiple NFC tags present
+        https://bugs.webkit.org/show_bug.cgi?id=200932
+        <rdar://problem/54890736>
+
+        Reviewed by Brent Fulgham.
+
+        Covered by new tests in existing test file.
+
+        * testing/MockWebAuthenticationConfiguration.h:
+        (WebCore::MockWebAuthenticationConfiguration::NfcConfiguration::encode const):
+        (WebCore::MockWebAuthenticationConfiguration::NfcConfiguration::decode):
+        * testing/MockWebAuthenticationConfiguration.idl:
+        Adds a new test option.
+
 2019-10-27  Antti Koivisto  <[email protected]>
 
         Move resolving direction and writing mode to PropertyCascade

Modified: trunk/Source/WebCore/testing/MockWebAuthenticationConfiguration.h (251644 => 251645)


--- trunk/Source/WebCore/testing/MockWebAuthenticationConfiguration.h	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/Source/WebCore/testing/MockWebAuthenticationConfiguration.h	2019-10-27 22:53:33 UTC (rev 251645)
@@ -93,6 +93,7 @@
         NfcError error { NfcError::Success };
         Vector<String> payloadBase64;
         bool multipleTags { false };
+        bool multiplePhysicalTags { false };
 
         template<class Encoder> void encode(Encoder&) const;
         template<class Decoder> static Optional<NfcConfiguration> decode(Decoder&);
@@ -193,7 +194,7 @@
 template<class Encoder>
 void MockWebAuthenticationConfiguration::NfcConfiguration::encode(Encoder& encoder) const
 {
-    encoder << error << payloadBase64 << multipleTags;
+    encoder << error << payloadBase64 << multipleTags << multiplePhysicalTags;
 }
 
 template<class Decoder>
@@ -206,6 +207,8 @@
         return WTF::nullopt;
     if (!decoder.decode(result.multipleTags))
         return WTF::nullopt;
+    if (!decoder.decode(result.multiplePhysicalTags))
+        return WTF::nullopt;
     return result;
 }
 

Modified: trunk/Source/WebCore/testing/MockWebAuthenticationConfiguration.idl (251644 => 251645)


--- trunk/Source/WebCore/testing/MockWebAuthenticationConfiguration.idl	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/Source/WebCore/testing/MockWebAuthenticationConfiguration.idl	2019-10-27 22:53:33 UTC (rev 251645)
@@ -100,4 +100,5 @@
     MockNfcError error = "success";
     sequence<DOMString> payloadBase64;
     boolean multipleTags = false;
+    boolean multiplePhysicalTags = false;
 };

Modified: trunk/Source/WebKit/ChangeLog (251644 => 251645)


--- trunk/Source/WebKit/ChangeLog	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/Source/WebKit/ChangeLog	2019-10-27 22:53:33 UTC (rev 251645)
@@ -1,3 +1,76 @@
+2019-10-21  Jiewen Tan  <[email protected]>
+
+        [WebAuthn] Warn users when multiple NFC tags present
+        https://bugs.webkit.org/show_bug.cgi?id=200932
+        <rdar://problem/54890736>
+
+        Reviewed by Brent Fulgham.
+
+        This patch utilizes -[_WKWebAuthenticationPanelDelegate panel:updateWebAuthenticationPanel:] to
+        inform clients about multiple physical tags are presenting such that clients can instruct users
+        to select only one of them physically. Given a physical tag could have multiple different
+        interfaces, which NearField will treat them into different NFTags, the tagID is then used to
+        identify if there are actually multiple physical tags.
+
+        This patch also adds the ability to restart polling of a partiuclar NFReaderSession to NfcConnection
+        and the ability to restart the whole session to NfcService. The former is used to recover from errors
+        in the discovery stages, and the latter is used to recover from errors returned from authenticators
+        in the request stages. For the latter, given NfcConnection is not awared of the syntax of FIDO2/U2F
+        protocol, and CtapAuthenticator/U2fAuthenticator are not awared the transport of the underneath driver.
+        A generic restartDiscovery process is added to each service and it is up to the actual service to
+        implement the actual process such that AuthenticatorManager can arbitrarily call it after exceptions
+        are returned to restart the whole NFC session. To achieve restartDiscovery, NfcConnection is made
+        RefCounted as well such that both the NfcService and the CtapNfcDriver could hold it at the same time.
+        CtapNfcDriver uses the connection to complete requests as before while NfcService has the new capability
+        to use it to stop the current session when restartDiscovery kicks off.
+
+        * Platform/spi/Cocoa/NearFieldSPI.h:
+        * UIProcess/WebAuthentication/AuthenticatorManager.cpp:
+        (WebKit::AuthenticatorManager::serviceStatusUpdated):
+        (WebKit::AuthenticatorManager::respondReceived):
+        (WebKit::AuthenticatorManager::restartDiscovery):
+        * UIProcess/WebAuthentication/AuthenticatorManager.h:
+        * UIProcess/WebAuthentication/AuthenticatorTransportService.cpp:
+        (WebKit::AuthenticatorTransportService::startDiscovery):
+        (WebKit::AuthenticatorTransportService::restartDiscovery):
+        * UIProcess/WebAuthentication/AuthenticatorTransportService.h:
+        (WebKit::AuthenticatorTransportService::restartDiscoveryInternal):
+        * UIProcess/WebAuthentication/Cocoa/NfcConnection.h:
+        * UIProcess/WebAuthentication/Cocoa/NfcConnection.mm:
+        (WebKit::NfcConnection::create):
+        (WebKit::NfcConnection::NfcConnection):
+        (WebKit::NfcConnection::~NfcConnection):
+        (WebKit::NfcConnection::stop const):
+        (WebKit::NfcConnection::didDetectTags):
+        (WebKit::NfcConnection::restartPolling):
+        (WebKit::NfcConnection::startPolling):
+        (WebKit::NfcConnection::didDetectTags const): Deleted.
+        * UIProcess/WebAuthentication/Cocoa/NfcService.h:
+        * UIProcess/WebAuthentication/Cocoa/NfcService.mm:
+        (WebKit::NfcService::NfcService):
+        (WebKit::NfcService::didConnectTag):
+        (WebKit::NfcService::didDetectMultipleTags const):
+        (WebKit::NfcService::setConnection):
+        (WebKit::NfcService::restartDiscoveryInternal):
+        (WebKit::NfcService::platformStartDiscovery):
+        (WebKit::NfcService::setDriver): Deleted.
+        * UIProcess/WebAuthentication/Mock/MockNfcService.h:
+        * UIProcess/WebAuthentication/Mock/MockNfcService.mm:
+        (-[WKMockNFTag tagID]):
+        (-[WKMockNFTag initWithNFTag:]):
+        (-[WKMockNFTag dealloc]):
+        (-[WKMockNFTag initWithType:]):
+        (-[WKMockNFTag initWithType:tagID:]):
+        (WebKit::MockNfcService::receiveStopPolling):
+        (WebKit::MockNfcService::receiveStartPolling):
+        (WebKit::MockNfcService::platformStartDiscovery):
+        (WebKit::MockNfcService::detectTags):
+        (WebKit::MockNfcService::detectTags const): Deleted.
+        * UIProcess/WebAuthentication/fido/CtapNfcDriver.cpp:
+        (WebKit::CtapNfcDriver::CtapNfcDriver):
+        * UIProcess/WebAuthentication/fido/CtapNfcDriver.h:
+        * UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp:
+
 2019-10-26  youenn fablet  <[email protected]>
 
         Enforce user gesture for getUserMedia in case a previous getUserMedia call was denied

Modified: trunk/Source/WebKit/Platform/spi/Cocoa/NearFieldSPI.h (251644 => 251645)


--- trunk/Source/WebKit/Platform/spi/Cocoa/NearFieldSPI.h	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/Source/WebKit/Platform/spi/Cocoa/NearFieldSPI.h	2019-10-27 22:53:33 UTC (rev 251645)
@@ -93,12 +93,11 @@
 @interface NFReaderSession : NFSession
 @property (assign) id<NFReaderSessionDelegate> delegate;
 
-- (BOOL)startPolling;
+- (BOOL)startPollingWithError:(NSError **)outError;
 - (BOOL)stopPolling;
 - (BOOL)connectTag:(NFTag*)tag;
 - (BOOL)disconnectTag;
 - (NSData*)transceive:(NSData*)capdu;
-- (NSError *)updateUIAlertMessage:(NSString *)message;
 @end
 
 @protocol NFReaderSessionDelegate <NSObject>

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp (251644 => 251645)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp	2019-10-27 22:53:33 UTC (rev 251645)
@@ -213,6 +213,12 @@
     ASSERT_UNUSED(addResult, addResult.isNewEntry);
 }
 
+void AuthenticatorManager::serviceStatusUpdated(WebAuthenticationStatus status)
+{
+    if (auto *panel = m_pendingRequestData.panel.get())
+        panel->client().updatePanel(status);
+}
+
 void AuthenticatorManager::respondReceived(Respond&& respond)
 {
     ASSERT(RunLoop::isMain());
@@ -230,6 +236,7 @@
         return;
     }
     respondReceivedInternal(WTFMove(respond));
+    restartDiscovery();
 }
 
 void AuthenticatorManager::downgrade(Authenticator* id, Ref<Authenticator>&& downgradedAuthenticator)
@@ -345,6 +352,12 @@
     m_pendingRequestData = { };
 }
 
+void AuthenticatorManager::restartDiscovery()
+{
+    for (auto& service : m_services)
+        service->restartDiscovery();
+}
+
 } // namespace WebKit
 
 #endif // ENABLE(WEB_AUTHN)

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h (251644 => 251645)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h	2019-10-27 22:53:33 UTC (rev 251645)
@@ -73,6 +73,7 @@
 private:
     // AuthenticatorTransportService::Observer
     void authenticatorAdded(Ref<Authenticator>&&) final;
+    void serviceStatusUpdated(WebAuthenticationStatus) final;
 
     // Authenticator::Observer
     void respondReceived(Respond&&) final;
@@ -90,6 +91,7 @@
     void runPanel();
     void startRequest();
     void resetState();
+    void restartDiscovery();
 
     // Request: We only allow one request per time. A new request will cancel any pending ones.
     WebAuthenticationRequestData m_pendingRequestData;

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorTransportService.cpp (251644 => 251645)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorTransportService.cpp	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorTransportService.cpp	2019-10-27 22:53:33 UTC (rev 251645)
@@ -75,7 +75,6 @@
 
 void AuthenticatorTransportService::startDiscovery()
 {
-    // Enforce asynchronous execution of makeCredential.
     RunLoop::main().dispatch([weakThis = makeWeakPtr(*this)] {
         if (!weakThis)
             return;
@@ -83,6 +82,15 @@
     });
 }
 
+void AuthenticatorTransportService::restartDiscovery()
+{
+    RunLoop::main().dispatch([weakThis = makeWeakPtr(*this)] {
+        if (!weakThis)
+            return;
+        weakThis->restartDiscoveryInternal();
+    });
+}
+
 } // namespace WebKit
 
 #endif // ENABLE(WEB_AUTHN)

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorTransportService.h (251644 => 251645)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorTransportService.h	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorTransportService.h	2019-10-27 22:53:33 UTC (rev 251645)
@@ -27,6 +27,7 @@
 
 #if ENABLE(WEB_AUTHN)
 
+#include "WebAuthenticationFlags.h"
 #include <WebCore/AuthenticatorTransport.h>
 #include <wtf/UniqueRef.h>
 #include <wtf/WeakPtr.h>
@@ -48,6 +49,7 @@
         virtual ~Observer() = default;
 
         virtual void authenticatorAdded(Ref<Authenticator>&&) = 0;
+        virtual void serviceStatusUpdated(WebAuthenticationStatus) = 0;
     };
 
     static UniqueRef<AuthenticatorTransportService> create(WebCore::AuthenticatorTransport, Observer&);
@@ -55,8 +57,9 @@
 
     virtual ~AuthenticatorTransportService() = default;
 
-    // This operation is guaranteed to execute asynchronously.
+    // These operations are guaranteed to execute asynchronously.
     void startDiscovery();
+    void restartDiscovery();
 
 protected:
     explicit AuthenticatorTransportService(Observer&);
@@ -65,6 +68,9 @@
 
 private:
     virtual void startDiscoveryInternal() = 0;
+    // NFC service's polling is one shot. It halts after the first tags are detected.
+    // Therefore, a restart process is needed to resume polling after exceptions.
+    virtual void restartDiscoveryInternal() { };
 
     WeakPtr<Observer> m_observer;
 };

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcConnection.h (251644 => 251645)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcConnection.h	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcConnection.h	2019-10-27 22:53:33 UTC (rev 251645)
@@ -27,9 +27,9 @@
 
 #if ENABLE(WEB_AUTHN) && HAVE(NEAR_FIELD)
 
-#include <wtf/FastMalloc.h>
-#include <wtf/Noncopyable.h>
+#include <wtf/RefCounted.h>
 #include <wtf/RetainPtr.h>
+#include <wtf/RunLoop.h>
 #include <wtf/WeakPtr.h>
 
 OBJC_CLASS NFReaderSession;
@@ -40,22 +40,27 @@
 
 class NfcService;
 
-class NfcConnection : public CanMakeWeakPtr<NfcConnection> {
-    WTF_MAKE_FAST_ALLOCATED;
-    WTF_MAKE_NONCOPYABLE(NfcConnection);
+class NfcConnection : public RefCounted<NfcConnection>, public CanMakeWeakPtr<NfcConnection> {
 public:
-    NfcConnection(RetainPtr<NFReaderSession>&&, NfcService&);
+    static Ref<NfcConnection> create(RetainPtr<NFReaderSession>&&, NfcService&);
     ~NfcConnection();
 
     Vector<uint8_t> transact(Vector<uint8_t>&& data) const;
+    void stop() const;
 
     // For WKNFReaderSessionDelegate
-    void didDetectTags(NSArray *) const;
+    void didDetectTags(NSArray *);
 
 private:
+    NfcConnection(RetainPtr<NFReaderSession>&&, NfcService&);
+
+    void restartPolling();
+    void startPolling();
+
     RetainPtr<NFReaderSession> m_session;
     RetainPtr<WKNFReaderSessionDelegate> m_delegate;
     WeakPtr<NfcService> m_service;
+    RunLoop::Timer<NfcConnection> m_retryTimer;
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcConnection.mm (251644 => 251645)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcConnection.mm	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcConnection.mm	2019-10-27 22:53:33 UTC (rev 251645)
@@ -45,20 +45,24 @@
 }
 } // namespace
 
+Ref<NfcConnection> NfcConnection::create(RetainPtr<NFReaderSession>&& session, NfcService& service)
+{
+    return adoptRef(*new NfcConnection(WTFMove(session), service));
+}
+
 NfcConnection::NfcConnection(RetainPtr<NFReaderSession>&& session, NfcService& service)
     : m_session(WTFMove(session))
     , m_delegate(adoptNS([[WKNFReaderSessionDelegate alloc] initWithConnection:*this]))
     , m_service(makeWeakPtr(service))
+    , m_retryTimer(RunLoop::main(), this, &NfcConnection::startPolling)
 {
     [m_session setDelegate:m_delegate.get()];
-    [m_session startPolling];
+    startPolling();
 }
 
 NfcConnection::~NfcConnection()
 {
-    [m_session disconnectTag];
-    [m_session stopPolling];
-    [m_session endSession];
+    stop();
 }
 
 Vector<uint8_t> NfcConnection::transact(Vector<uint8_t>&& data) const
@@ -71,16 +75,33 @@
     return response;
 }
 
-void NfcConnection::didDetectTags(NSArray *tags) const
+void NfcConnection::stop() const
 {
-    if (!m_service)
+    [m_session disconnectTag];
+    [m_session stopPolling];
+    [m_session endSession];
+}
+
+void NfcConnection::didDetectTags(NSArray *tags)
+{
+    if (!m_service || !tags.count)
         return;
 
-    // FIXME(200932): Warn users when multiple NFC tags present
-    for (NFTag *tag in tags) {
-        if (tag.type != NFTagTypeGeneric4A)
+    // A physical NFC tag could have multiple interfaces.
+    // Therefore, we use tagID to detect if there are multiple physical tags.
+    NSData *tagID = ((NFTag *)tags[0]).tagID;
+    for (NFTag *tag : tags) {
+        if ([tagID isEqualToData:tag.tagID])
             continue;
-        if (![m_session connectTag:tag])
+        m_service->didDetectMultipleTags();
+        restartPolling();
+        return;
+    }
+
+    // FIXME(203234): Tell users to switch to a different tag if the tag is not of type NFTagTypeGeneric4A
+    // or can't speak U2F/FIDO2.
+    for (NFTag *tag : tags) {
+        if (tag.type != NFTagTypeGeneric4A || ![m_session connectTag:tag])
             continue;
 
         // Confirm the FIDO applet is avaliable before return.
@@ -94,10 +115,27 @@
         }
 
         m_service->didConnectTag();
-        break;
+        return;
     }
+    restartPolling();
 }
 
+// NearField polling is a one shot polling. It halts after tags are detected.
+// Therefore, a restart process is needed to resume polling after error.
+void NfcConnection::restartPolling()
+{
+    [m_session stopPolling];
+    m_retryTimer.startOneShot(1_s); // Magic number to give users enough time for reactions.
+}
+
+void NfcConnection::startPolling()
+{
+    NSError *error = nil;
+    [m_session startPollingWithError:&error];
+    if (error)
+        LOG_ERROR("Couldn't start NFC reader polling: %@", error);
+}
+
 } // namespace WebKit
 
 #endif // ENABLE(WEB_AUTHN) && HAVE(NEAR_FIELD)

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcService.h (251644 => 251645)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcService.h	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcService.h	2019-10-27 22:53:33 UTC (rev 251645)
@@ -28,12 +28,13 @@
 #if ENABLE(WEB_AUTHN)
 
 #include "FidoService.h"
+#include <wtf/RunLoop.h>
 
 OBJC_CLASS NFReaderSession;
 
 namespace WebKit {
 
-class CtapNfcDriver;
+class NfcConnection;
 
 class NfcService : public FidoService {
 public:
@@ -42,15 +43,16 @@
 
     // For NfcConnection.
     void didConnectTag();
+    void didDetectMultipleTags() const;
 
 #if HAVE(NEAR_FIELD)
 protected:
-    void setDriver(std::unique_ptr<CtapNfcDriver>&&);
+    void setConnection(Ref<NfcConnection>&&); // For MockNfcConnection
 #endif
 
 private:
     void startDiscoveryInternal() final;
-    void continueAddDeviceAfterGetInfo(Vector<uint8_t>&& response);
+    void restartDiscoveryInternal() final;
 
     // Overrided by MockNfcService.
     virtual void platformStartDiscovery();
@@ -58,8 +60,9 @@
 #if HAVE(NEAR_FIELD)
     // Only one reader session is allowed per time.
     // Keep the reader session alive here when it tries to connect to a tag.
-    std::unique_ptr<CtapNfcDriver> m_driver;
+    RefPtr<NfcConnection> m_connection;
 #endif
+    RunLoop::Timer<NfcService> m_restartTimer;
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcService.mm (251644 => 251645)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcService.mm	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcService.mm	2019-10-27 22:53:33 UTC (rev 251645)
@@ -41,6 +41,7 @@
 
 NfcService::NfcService(Observer& observer)
     : FidoService(observer)
+    , m_restartTimer(RunLoop::main(), this, &NfcService::platformStartDiscovery)
 {
 }
 
@@ -51,14 +52,22 @@
 void NfcService::didConnectTag()
 {
 #if HAVE(NEAR_FIELD)
-    getInfo(WTFMove(m_driver));
+    auto connection = m_connection;
+    ASSERT(connection);
+    getInfo(WTF::makeUnique<CtapNfcDriver>(connection.releaseNonNull()));
 #endif
 }
 
+void NfcService::didDetectMultipleTags() const
+{
+    if (auto* observer = this->observer())
+        observer->serviceStatusUpdated(WebAuthenticationStatus::MultipleNFCTagsPresent);
+}
+
 #if HAVE(NEAR_FIELD)
-void NfcService::setDriver(std::unique_ptr<CtapNfcDriver>&& driver)
+void NfcService::setConnection(Ref<NfcConnection>&& connection)
 {
-    m_driver = WTFMove(driver);
+    m_connection = WTFMove(connection);
 }
 #endif
 
@@ -67,6 +76,15 @@
     platformStartDiscovery();
 }
 
+void NfcService::restartDiscoveryInternal()
+{
+#if HAVE(NEAR_FIELD)
+    if (m_connection)
+        m_connection->stop();
+#endif
+    m_restartTimer.startOneShot(1_s); // Magic number to give users enough time for reactions.
+}
+
 void NfcService::platformStartDiscovery()
 {
 #if HAVE(NEAR_FIELD)
@@ -87,8 +105,8 @@
                 return;
             }
 
-            // CtapNfcDriver and NfcConnection will take care of polling tags and connecting to them.
-            m_driver = WTF::makeUnique<CtapNfcDriver>(makeUniqueRef<NfcConnection>(WTFMove(session), *this));
+            // NfcConnection will take care of polling tags and connecting to them.
+            m_connection = NfcConnection::create(WTFMove(session), *this);
         });
     });
     [[getNFHardwareManagerClass() sharedHardwareManager] startReaderSession:callback.get()];

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockNfcService.h (251644 => 251645)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockNfcService.h	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockNfcService.h	2019-10-27 22:53:33 UTC (rev 251645)
@@ -39,6 +39,8 @@
     MockNfcService(Observer&, const WebCore::MockWebAuthenticationConfiguration&);
 
     NSData* transceive();
+    void receiveStopPolling();
+    void receiveStartPolling();
 
 private:
     void platformStartDiscovery() final;

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockNfcService.mm (251644 => 251645)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockNfcService.mm	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockNfcService.mm	2019-10-27 22:53:33 UTC (rev 251645)
@@ -38,20 +38,26 @@
 
 #import "NearFieldSoftLink.h"
 
+namespace {
+uint8_t tagID1[] = { 0x01 };
+uint8_t tagID2[] = { 0x02 };
+}
+
 #if HAVE(NEAR_FIELD)
 
 @interface WKMockNFTag : NSObject <NFTag>
 
 - (instancetype)initWithType:(NFTagType)type;
+- (instancetype)initWithType:(NFTagType)type tagID:(NSData *)tagID;
 
 @end
 
 @implementation WKMockNFTag {
     NFTagType _type;
+    RetainPtr<NSData> _tagID;
 }
 
 @synthesize technology=_technology;
-@synthesize tagID=_tagID;
 @synthesize AppData=_AppData;
 @synthesize UID=_UID;
 @synthesize ndefAvailability=_ndefAvailability;
@@ -66,17 +72,22 @@
     return _type;
 }
 
+- (NSData *)tagID
+{
+    return _tagID.get();
+}
+
 - (instancetype)initWithNFTag:(id<NFTag>)tag
 {
-    if ((self = [super init]))
+    if ((self = [super init])) {
         _type = tag.type;
+        _tagID = tag.tagID;
+    }
     return self;
 }
 
 - (void)dealloc
 {
-    [_tagID release];
-    _tagID = nil;
     [_AppData release];
     _AppData = nil;
     [_UID release];
@@ -97,8 +108,15 @@
 
 - (instancetype)initWithType:(NFTagType)type
 {
-    if ((self = [super init]))
+    return [self initWithType:type tagID:adoptNS([[NSData alloc] initWithBytes:tagID1 length:sizeof(tagID1)]).get()];
+}
+
+- (instancetype)initWithType:(NFTagType)type tagID:(NSData *)tagID
+{
+    if ((self = [super init])) {
         _type = type;
+        _tagID = tagID;
+    }
     return self;
 }
 
@@ -132,6 +150,22 @@
     return YES;
 }
 
+static BOOL NFReaderSessionStopPolling(id, SEL)
+{
+    if (!globalNfcService)
+        return NO;
+    globalNfcService->receiveStopPolling();
+    return YES;
+}
+
+static BOOL NFReaderSessionStartPollingWithError(id, SEL, NSError **)
+{
+    if (!globalNfcService)
+        return NO;
+    globalNfcService->receiveStartPolling();
+    return YES;
+}
+
 static NSData* NFReaderSessionTransceive(id, SEL, NSData *)
 {
     if (!globalNfcService)
@@ -159,6 +193,21 @@
     return [result autorelease];
 }
 
+void MockNfcService::receiveStopPolling()
+{
+    // For purpose of restart polling.
+    m_configuration.nfc->multiplePhysicalTags = false;
+}
+
+void MockNfcService::receiveStartPolling()
+{
+    RunLoop::main().dispatch([weakThis = makeWeakPtr(*this)] {
+        if (!weakThis)
+            return;
+        weakThis->detectTags();
+    });
+}
+
 void MockNfcService::platformStartDiscovery()
 {
 #if HAVE(NEAR_FIELD)
@@ -177,15 +226,14 @@
         Method methodToSwizzle3 = class_getInstanceMethod(getNFReaderSessionClass(), @selector(transceive:));
         method_setImplementation(methodToSwizzle3, (IMP)NFReaderSessionTransceive);
 
+        Method methodToSwizzle4 = class_getInstanceMethod(getNFReaderSessionClass(), @selector(stopPolling));
+        method_setImplementation(methodToSwizzle4, (IMP)NFReaderSessionStopPolling);
+
+        Method methodToSwizzle5 = class_getInstanceMethod(getNFReaderSessionClass(), @selector(startPollingWithError:));
+        method_setImplementation(methodToSwizzle5, (IMP)NFReaderSessionStartPollingWithError);
+
         auto readerSession = adoptNS([allocNFReaderSessionInstance() init]);
-        setDriver(WTF::makeUnique<CtapNfcDriver>(makeUniqueRef<NfcConnection>(readerSession.get(), *this)));
-
-        RunLoop::main().dispatch([weakThis = makeWeakPtr(*this)] {
-            if (!weakThis)
-                return;
-            weakThis->detectTags();
-        });
-        return;
+        setConnection(NfcConnection::create(readerSession.get(), *this));
     }
     LOG_ERROR("No nfc authenticators is available.");
 #endif // HAVE(NEAR_FIELD)
@@ -207,6 +255,9 @@
         if (configuration.nfc->multipleTags)
             [tags addObject:adoptNS([[WKMockNFTag alloc] initWithType:NFTagTypeGeneric4A]).get()];
 
+        if (configuration.nfc->multiplePhysicalTags)
+            [tags addObject:adoptNS([[WKMockNFTag alloc] initWithType:NFTagTypeGeneric4A tagID:adoptNS([[NSData alloc] initWithBytes:tagID2 length:sizeof(tagID2)]).get()]).get()];
+
         [globalNFReaderSessionDelegate readerSession:nil didDetectTags:tags.get()];
     });
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), callback.get());

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapNfcDriver.cpp (251644 => 251645)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapNfcDriver.cpp	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapNfcDriver.cpp	2019-10-27 22:53:33 UTC (rev 251645)
@@ -36,7 +36,7 @@
 using namespace apdu;
 using namespace fido;
 
-CtapNfcDriver::CtapNfcDriver(UniqueRef<NfcConnection>&& connection)
+CtapNfcDriver::CtapNfcDriver(Ref<NfcConnection>&& connection)
     : m_connection(WTFMove(connection))
 {
 }

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapNfcDriver.h (251644 => 251645)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapNfcDriver.h	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapNfcDriver.h	2019-10-27 22:53:33 UTC (rev 251645)
@@ -37,7 +37,7 @@
 // https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#nfc
 class CtapNfcDriver : public CtapDriver {
 public:
-    explicit CtapNfcDriver(UniqueRef<NfcConnection>&&);
+    explicit CtapNfcDriver(Ref<NfcConnection>&&);
 
     void transact(Vector<uint8_t>&& data, ResponseCallback&&) final;
 
@@ -44,7 +44,7 @@
 private:
     void respondAsync(ResponseCallback&&, Vector<uint8_t>&& response) const;
 
-    UniqueRef<NfcConnection> m_connection;
+    Ref<NfcConnection> m_connection;
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp (251644 => 251645)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp	2019-10-27 22:53:33 UTC (rev 251645)
@@ -33,7 +33,6 @@
 #include <WebCore/ExceptionData.h>
 #include <WebCore/U2fCommandConstructor.h>
 #include <WebCore/U2fResponseConverter.h>
-#include <wtf/RunLoop.h>
 #include <wtf/text/StringConcatenateNumbers.h>
 
 namespace WebKit {

Modified: trunk/Tools/ChangeLog (251644 => 251645)


--- trunk/Tools/ChangeLog	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/Tools/ChangeLog	2019-10-27 22:53:33 UTC (rev 251645)
@@ -1,3 +1,18 @@
+2019-10-21  Jiewen Tan  <[email protected]>
+
+        [WebAuthn] Warn users when multiple NFC tags present
+        https://bugs.webkit.org/show_bug.cgi?id=200932
+        <rdar://problem/54890736>
+
+        Reviewed by Brent Fulgham.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm:
+        (-[TestWebAuthenticationPanelDelegate panel:updateWebAuthenticationPanel:]):
+        (TestWebKitAPI::TEST):
+        Adds a new test for -[_WKWebAuthenticationPanelDelegate panel:updateWebAuthenticationPanel:].
+        * TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion-nfc-multiple-tags.html: Added.
+
 2019-10-27  Claudio Saavedra  <[email protected]>
 
         [GTK][WPE] Test PublicSuffix.TopPrivatelyControlledDomain is failing since r250589

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (251644 => 251645)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2019-10-27 22:53:33 UTC (rev 251645)
@@ -350,6 +350,7 @@
 		579651E7216BFDED006EBFE5 /* FidoHidMessageTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 579651E6216BFD53006EBFE5 /* FidoHidMessageTest.cpp */; };
 		5797FE311EB15A6800B2F4A0 /* NavigationClientDefaultCrypto.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5797FE2F1EB15A5F00B2F4A0 /* NavigationClientDefaultCrypto.cpp */; };
 		5797FE331EB15AB100B2F4A0 /* navigation-client-default-crypto.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5797FE321EB15A8900B2F4A0 /* navigation-client-default-crypto.html */; };
+		5798337C235EB689008E5547 /* web-authentication-get-assertion-nfc-multiple-tags.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5798337B235EB65C008E5547 /* web-authentication-get-assertion-nfc-multiple-tags.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 */; };
@@ -1453,6 +1454,7 @@
 				57663DF32357E48900E85E09 /* web-authentication-get-assertion-hid-cancel.html in Copy Resources */,
 				577454D02359B378008E1ED7 /* web-authentication-get-assertion-hid-no-credentials.html in Copy Resources */,
 				57663DEC234F1F9300E85E09 /* web-authentication-get-assertion-hid.html in Copy Resources */,
+				5798337C235EB689008E5547 /* web-authentication-get-assertion-nfc-multiple-tags.html in Copy Resources */,
 				57663DEA234EA66D00E85E09 /* web-authentication-get-assertion-nfc.html in Copy Resources */,
 				577454D22359BB01008E1ED7 /* web-authentication-get-assertion-u2f-no-credentials.html in Copy Resources */,
 				57C624502346C21E00383FE7 /* web-authentication-get-assertion.html in Copy Resources */,
@@ -1889,6 +1891,7 @@
 		579651E6216BFD53006EBFE5 /* FidoHidMessageTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FidoHidMessageTest.cpp; sourceTree = "<group>"; };
 		5797FE2F1EB15A5F00B2F4A0 /* NavigationClientDefaultCrypto.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NavigationClientDefaultCrypto.cpp; sourceTree = "<group>"; };
 		5797FE321EB15A8900B2F4A0 /* navigation-client-default-crypto.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "navigation-client-default-crypto.html"; sourceTree = "<group>"; };
+		5798337B235EB65C008E5547 /* web-authentication-get-assertion-nfc-multiple-tags.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "web-authentication-get-assertion-nfc-multiple-tags.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>"; };
@@ -3412,6 +3415,7 @@
 				57663DF22357E45D00E85E09 /* web-authentication-get-assertion-hid-cancel.html */,
 				577454CF2359B338008E1ED7 /* web-authentication-get-assertion-hid-no-credentials.html */,
 				57663DEB234F1F8000E85E09 /* web-authentication-get-assertion-hid.html */,
+				5798337B235EB65C008E5547 /* web-authentication-get-assertion-nfc-multiple-tags.html */,
 				57663DE9234EA60B00E85E09 /* web-authentication-get-assertion-nfc.html */,
 				577454D12359BAD5008E1ED7 /* web-authentication-get-assertion-u2f-no-credentials.html */,
 				57C6244F2346C1EC00383FE7 /* web-authentication-get-assertion.html */,

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm (251644 => 251645)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm	2019-10-27 22:12:20 UTC (rev 251644)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm	2019-10-27 22:53:33 UTC (rev 251645)
@@ -42,6 +42,7 @@
 static bool webAuthenticationPanelRan = false;
 static bool webAuthenticationPanelFailed = false;
 static bool webAuthenticationPanelSucceded = false;
+static bool webAuthenticationPanelUpdateMultipleNFCTagsPresent = false;
 static bool webAuthenticationPanelUpdateNoCredentialsFound = false;
 static RetainPtr<_WKWebAuthenticationPanel> gPanel;
 
@@ -53,8 +54,14 @@
 - (void)panel:(_WKWebAuthenticationPanel *)panel updateWebAuthenticationPanel:(_WKWebAuthenticationPanelUpdate)update
 {
     ASSERT_NE(panel, nil);
-    if (update == _WKWebAuthenticationPanelUpdateNoCredentialsFound)
+    if (update == _WKWebAuthenticationPanelUpdateMultipleNFCTagsPresent) {
+        webAuthenticationPanelUpdateMultipleNFCTagsPresent = true;
+        return;
+    }
+    if (update == _WKWebAuthenticationPanelUpdateNoCredentialsFound) {
         webAuthenticationPanelUpdateNoCredentialsFound = true;
+        return;
+    }
 }
 
 - (void)panel:(_WKWebAuthenticationPanel *)panel dismissWebAuthenticationPanelWithResult:(_WKWebAuthenticationResult)result
@@ -606,6 +613,25 @@
     [webView waitForMessage:@"Operation timed out."];
 }
 
+#if HAVE(NEAR_FIELD)
+TEST(WebAuthenticationPanel, PanelMultipleNFCTagsPresent)
+{
+    reset();
+    RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-nfc-multiple-tags" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
+
+    auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
+    [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
+
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
+    auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
+    [webView setUIDelegate:delegate.get()];
+
+    [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
+    Util::run(&webAuthenticationPanelRan);
+    Util::run(&webAuthenticationPanelUpdateMultipleNFCTagsPresent);
+}
+#endif
+
 } // namespace TestWebKitAPI
 
 #endif // ENABLE(WEB_AUTHN)

Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion-nfc-multiple-tags.html (0 => 251645)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion-nfc-multiple-tags.html	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion-nfc-multiple-tags.html	2019-10-27 22:53:33 UTC (rev 251645)
@@ -0,0 +1,16 @@
+<input type="text" id="input">
+<script>
+    if (window.internals) {
+        internals.setMockWebAuthenticationConfiguration({ silentFailure: true, nfc: { multiplePhysicalTags:true } });
+        internals.withUserGesture(() => { input.focus(); });
+    }
+
+    const options = {
+        publicKey: {
+            challenge: new Uint8Array(16),
+            timeout: 100,
+        }
+    };
+
+    navigator.credentials.get(options);
+</script>
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to