| Differences between
and this patch
- a/Source/WebCore/ChangeLog +16 lines
Lines 1-3 a/Source/WebCore/ChangeLog_sec1
1
2019-10-21  Jiewen Tan  <jiewen_tan@apple.com>
2
3
        [WebAuthn] Warn users when multiple NFC tags present
4
        https://bugs.webkit.org/show_bug.cgi?id=200932
5
        <rdar://problem/54890736>
6
7
        Reviewed by NOBODY (OOPS!).
8
9
        Covered by new tests in existing test file.
10
11
        * testing/MockWebAuthenticationConfiguration.h:
12
        (WebCore::MockWebAuthenticationConfiguration::NfcConfiguration::encode const):
13
        (WebCore::MockWebAuthenticationConfiguration::NfcConfiguration::decode):
14
        * testing/MockWebAuthenticationConfiguration.idl:
15
        Adds a new test option.
16
1
2019-10-21  Simon Fraser  <simon.fraser@apple.com>
17
2019-10-21  Simon Fraser  <simon.fraser@apple.com>
2
18
3
        [iOS WK2] Support hiding iframe scrollbars via ::-webkit-scrollbar style
19
        [iOS WK2] Support hiding iframe scrollbars via ::-webkit-scrollbar style
- a/Source/WebKit/ChangeLog +73 lines
Lines 1-3 a/Source/WebKit/ChangeLog_sec1
1
2019-10-21  Jiewen Tan  <jiewen_tan@apple.com>
2
3
        [WebAuthn] Warn users when multiple NFC tags present
4
        https://bugs.webkit.org/show_bug.cgi?id=200932
5
        <rdar://problem/54890736>
6
7
        Reviewed by NOBODY (OOPS!).
8
9
        This patch utilizes -[_WKWebAuthenticationPanelDelegate panel:updateWebAuthenticationPanel:] to
10
        inform clients about multiple physical tags are presenting such that clients can instruct users
11
        to select only one of them physically. Given a physical tag could have multiple different
12
        interfaces, which NearField will treat them into different NFTags, the tagID is then used to
13
        identify if there are actually multiple physical tags.
14
15
        This patch also adds the ability to restart polling of a partiuclar NFReaderSession to NfcConnection
16
        and the ability to restart the whole session to NfcService. The former is used to recover from errors
17
        in the discovery stages, and the latter is used to recover from errors returned from authenticators
18
        in the request stages. For the latter, given NfcConnection is not awared of the syntax of FIDO2/U2F
19
        protocol, and CtapAuthenticator/U2fAuthenticator are not awared the transport of the underneath driver.
20
        A generic restartDiscovery process is added to each service and it is up to the actual service to
21
        implement the actual process such that AuthenticatorManager can arbitrarily call it after exceptions
22
        are returned to restart the whole NFC session. To achieve restartDiscovery, NfcConnection is made
23
        RefCounted as well such that both the NfcService and the CtapNfcDriver could hold it at the same time.
24
        CtapNfcDriver uses the connection to complete requests as before while NfcService has the new capability
25
        to use it to stop the current session when restartDiscovery kicks off.
26
27
        * Platform/spi/Cocoa/NearFieldSPI.h:
28
        * UIProcess/WebAuthentication/AuthenticatorManager.cpp:
29
        (WebKit::AuthenticatorManager::serviceStatusUpdated):
30
        (WebKit::AuthenticatorManager::respondReceived):
31
        (WebKit::AuthenticatorManager::restartDiscovery):
32
        * UIProcess/WebAuthentication/AuthenticatorManager.h:
33
        * UIProcess/WebAuthentication/AuthenticatorTransportService.cpp:
34
        (WebKit::AuthenticatorTransportService::startDiscovery):
35
        (WebKit::AuthenticatorTransportService::restartDiscovery):
36
        * UIProcess/WebAuthentication/AuthenticatorTransportService.h:
37
        (WebKit::AuthenticatorTransportService::restartDiscoveryInternal):
38
        * UIProcess/WebAuthentication/Cocoa/NfcConnection.h:
39
        * UIProcess/WebAuthentication/Cocoa/NfcConnection.mm:
40
        (WebKit::NfcConnection::create):
41
        (WebKit::NfcConnection::NfcConnection):
42
        (WebKit::NfcConnection::~NfcConnection):
43
        (WebKit::NfcConnection::stop const):
44
        (WebKit::NfcConnection::didDetectTags):
45
        (WebKit::NfcConnection::restartPolling):
46
        (WebKit::NfcConnection::startPolling):
47
        (WebKit::NfcConnection::didDetectTags const): Deleted.
48
        * UIProcess/WebAuthentication/Cocoa/NfcService.h:
49
        * UIProcess/WebAuthentication/Cocoa/NfcService.mm:
50
        (WebKit::NfcService::NfcService):
51
        (WebKit::NfcService::didConnectTag):
52
        (WebKit::NfcService::didDetectMultipleTags const):
53
        (WebKit::NfcService::setConnection):
54
        (WebKit::NfcService::restartDiscoveryInternal):
55
        (WebKit::NfcService::platformStartDiscovery):
56
        (WebKit::NfcService::setDriver): Deleted.
57
        * UIProcess/WebAuthentication/Mock/MockNfcService.h:
58
        * UIProcess/WebAuthentication/Mock/MockNfcService.mm:
59
        (-[WKMockNFTag tagID]):
60
        (-[WKMockNFTag initWithNFTag:]):
61
        (-[WKMockNFTag dealloc]):
62
        (-[WKMockNFTag initWithType:]):
63
        (-[WKMockNFTag initWithType:tagID:]):
64
        (WebKit::MockNfcService::receiveStopPolling):
65
        (WebKit::MockNfcService::receiveStartPolling):
66
        (WebKit::MockNfcService::platformStartDiscovery):
67
        (WebKit::MockNfcService::detectTags):
68
        (WebKit::MockNfcService::detectTags const): Deleted.
69
        * UIProcess/WebAuthentication/fido/CtapNfcDriver.cpp:
70
        (WebKit::CtapNfcDriver::CtapNfcDriver):
71
        * UIProcess/WebAuthentication/fido/CtapNfcDriver.h:
72
        * UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp:
73
1
2019-10-21  Chris Dumez  <cdumez@apple.com>
74
2019-10-21  Chris Dumez  <cdumez@apple.com>
2
75
3
        Add more release logging for "Unexpectedly resumed" assertion
76
        Add more release logging for "Unexpectedly resumed" assertion
- a/Source/WebCore/testing/MockWebAuthenticationConfiguration.h -1 / +4 lines
Lines 93-98 struct MockWebAuthenticationConfiguration { a/Source/WebCore/testing/MockWebAuthenticationConfiguration.h_sec1
93
        NfcError error { NfcError::Success };
93
        NfcError error { NfcError::Success };
94
        Vector<String> payloadBase64;
94
        Vector<String> payloadBase64;
95
        bool multipleTags { false };
95
        bool multipleTags { false };
96
        bool multiplePhysicalTags { false };
96
97
97
        template<class Encoder> void encode(Encoder&) const;
98
        template<class Encoder> void encode(Encoder&) const;
98
        template<class Decoder> static Optional<NfcConfiguration> decode(Decoder&);
99
        template<class Decoder> static Optional<NfcConfiguration> decode(Decoder&);
Lines 193-199 Optional<MockWebAuthenticationConfiguration::HidConfiguration> MockWebAuthentica a/Source/WebCore/testing/MockWebAuthenticationConfiguration.h_sec2
193
template<class Encoder>
194
template<class Encoder>
194
void MockWebAuthenticationConfiguration::NfcConfiguration::encode(Encoder& encoder) const
195
void MockWebAuthenticationConfiguration::NfcConfiguration::encode(Encoder& encoder) const
195
{
196
{
196
    encoder << error << payloadBase64 << multipleTags;
197
    encoder << error << payloadBase64 << multipleTags << multiplePhysicalTags;
197
}
198
}
198
199
199
template<class Decoder>
200
template<class Decoder>
Lines 206-211 Optional<MockWebAuthenticationConfiguration::NfcConfiguration> MockWebAuthentica a/Source/WebCore/testing/MockWebAuthenticationConfiguration.h_sec3
206
        return WTF::nullopt;
207
        return WTF::nullopt;
207
    if (!decoder.decode(result.multipleTags))
208
    if (!decoder.decode(result.multipleTags))
208
        return WTF::nullopt;
209
        return WTF::nullopt;
210
    if (!decoder.decode(result.multiplePhysicalTags))
211
        return WTF::nullopt;
209
    return result;
212
    return result;
210
}
213
}
211
214
- a/Source/WebCore/testing/MockWebAuthenticationConfiguration.idl +1 lines
Lines 100-103 a/Source/WebCore/testing/MockWebAuthenticationConfiguration.idl_sec1
100
    MockNfcError error = "success";
100
    MockNfcError error = "success";
101
    sequence<DOMString> payloadBase64;
101
    sequence<DOMString> payloadBase64;
102
    boolean multipleTags = false;
102
    boolean multipleTags = false;
103
    boolean multiplePhysicalTags = false;
103
};
104
};
- a/Source/WebKit/Platform/spi/Cocoa/NearFieldSPI.h -2 / +1 lines
Lines 93-104 typedef NS_ENUM(uint32_t, NFNdefAvailability) { a/Source/WebKit/Platform/spi/Cocoa/NearFieldSPI.h_sec1
93
@interface NFReaderSession : NFSession
93
@interface NFReaderSession : NFSession
94
@property (assign) id<NFReaderSessionDelegate> delegate;
94
@property (assign) id<NFReaderSessionDelegate> delegate;
95
95
96
- (BOOL)startPolling;
96
- (BOOL)startPollingWithError:(NSError **)outError;
97
- (BOOL)stopPolling;
97
- (BOOL)stopPolling;
98
- (BOOL)connectTag:(NFTag*)tag;
98
- (BOOL)connectTag:(NFTag*)tag;
99
- (BOOL)disconnectTag;
99
- (BOOL)disconnectTag;
100
- (NSData*)transceive:(NSData*)capdu;
100
- (NSData*)transceive:(NSData*)capdu;
101
- (NSError *)updateUIAlertMessage:(NSString *)message;
102
@end
101
@end
103
102
104
@protocol NFReaderSessionDelegate <NSObject>
103
@protocol NFReaderSessionDelegate <NSObject>
- a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp +13 lines
Lines 213-218 void AuthenticatorManager::authenticatorAdded(Ref<Authenticator>&& authenticator a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp_sec1
213
    ASSERT_UNUSED(addResult, addResult.isNewEntry);
213
    ASSERT_UNUSED(addResult, addResult.isNewEntry);
214
}
214
}
215
215
216
void AuthenticatorManager::serviceStatusUpdated(WebAuthenticationStatus status)
217
{
218
    if (auto *panel = m_pendingRequestData.panel.get())
219
        panel->client().updatePanel(status);
220
}
221
216
void AuthenticatorManager::respondReceived(Respond&& respond)
222
void AuthenticatorManager::respondReceived(Respond&& respond)
217
{
223
{
218
    ASSERT(RunLoop::isMain());
224
    ASSERT(RunLoop::isMain());
Lines 230-235 void AuthenticatorManager::respondReceived(Respond&& respond) a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp_sec2
230
        return;
236
        return;
231
    }
237
    }
232
    respondReceivedInternal(WTFMove(respond));
238
    respondReceivedInternal(WTFMove(respond));
239
    restartDiscovery();
233
}
240
}
234
241
235
void AuthenticatorManager::downgrade(Authenticator* id, Ref<Authenticator>&& downgradedAuthenticator)
242
void AuthenticatorManager::downgrade(Authenticator* id, Ref<Authenticator>&& downgradedAuthenticator)
Lines 341-346 void AuthenticatorManager::resetState() a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp_sec3
341
    m_pendingRequestData = { };
348
    m_pendingRequestData = { };
342
}
349
}
343
350
351
void AuthenticatorManager::restartDiscovery()
352
{
353
    for (auto& service : m_services)
354
        service->restartDiscovery();
355
}
356
344
} // namespace WebKit
357
} // namespace WebKit
345
358
346
#endif // ENABLE(WEB_AUTHN)
359
#endif // ENABLE(WEB_AUTHN)
- a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h +2 lines
Lines 73-78 protected: a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h_sec1
73
private:
73
private:
74
    // AuthenticatorTransportService::Observer
74
    // AuthenticatorTransportService::Observer
75
    void authenticatorAdded(Ref<Authenticator>&&) final;
75
    void authenticatorAdded(Ref<Authenticator>&&) final;
76
    void serviceStatusUpdated(WebAuthenticationStatus) final;
76
77
77
    // Authenticator::Observer
78
    // Authenticator::Observer
78
    void respondReceived(Respond&&) final;
79
    void respondReceived(Respond&&) final;
Lines 90-95 private: a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h_sec2
90
    void runPanel();
91
    void runPanel();
91
    void startRequest();
92
    void startRequest();
92
    void resetState();
93
    void resetState();
94
    void restartDiscovery();
93
95
94
    // Request: We only allow one request per time. A new request will cancel any pending ones.
96
    // Request: We only allow one request per time. A new request will cancel any pending ones.
95
    WebAuthenticationRequestData m_pendingRequestData;
97
    WebAuthenticationRequestData m_pendingRequestData;
- a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorTransportService.cpp -1 / +9 lines
Lines 75-81 AuthenticatorTransportService::AuthenticatorTransportService(Observer& observer) a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorTransportService.cpp_sec1
75
75
76
void AuthenticatorTransportService::startDiscovery()
76
void AuthenticatorTransportService::startDiscovery()
77
{
77
{
78
    // Enforce asynchronous execution of makeCredential.
79
    RunLoop::main().dispatch([weakThis = makeWeakPtr(*this)] {
78
    RunLoop::main().dispatch([weakThis = makeWeakPtr(*this)] {
80
        if (!weakThis)
79
        if (!weakThis)
81
            return;
80
            return;
Lines 83-88 void AuthenticatorTransportService::startDiscovery() a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorTransportService.cpp_sec2
83
    });
82
    });
84
}
83
}
85
84
85
void AuthenticatorTransportService::restartDiscovery()
86
{
87
    RunLoop::main().dispatch([weakThis = makeWeakPtr(*this)] {
88
        if (!weakThis)
89
            return;
90
        weakThis->restartDiscoveryInternal();
91
    });
92
}
93
86
} // namespace WebKit
94
} // namespace WebKit
87
95
88
#endif // ENABLE(WEB_AUTHN)
96
#endif // ENABLE(WEB_AUTHN)
- a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorTransportService.h -1 / +7 lines
Lines 27-32 a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorTransportService.h_sec1
27
27
28
#if ENABLE(WEB_AUTHN)
28
#if ENABLE(WEB_AUTHN)
29
29
30
#include "WebAuthenticationFlags.h"
30
#include <WebCore/AuthenticatorTransport.h>
31
#include <WebCore/AuthenticatorTransport.h>
31
#include <wtf/UniqueRef.h>
32
#include <wtf/UniqueRef.h>
32
#include <wtf/WeakPtr.h>
33
#include <wtf/WeakPtr.h>
Lines 48-53 public: a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorTransportService.h_sec2
48
        virtual ~Observer() = default;
49
        virtual ~Observer() = default;
49
50
50
        virtual void authenticatorAdded(Ref<Authenticator>&&) = 0;
51
        virtual void authenticatorAdded(Ref<Authenticator>&&) = 0;
52
        virtual void serviceStatusUpdated(WebAuthenticationStatus) = 0;
51
    };
53
    };
52
54
53
    static UniqueRef<AuthenticatorTransportService> create(WebCore::AuthenticatorTransport, Observer&);
55
    static UniqueRef<AuthenticatorTransportService> create(WebCore::AuthenticatorTransport, Observer&);
Lines 55-62 public: a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorTransportService.h_sec3
55
57
56
    virtual ~AuthenticatorTransportService() = default;
58
    virtual ~AuthenticatorTransportService() = default;
57
59
58
    // This operation is guaranteed to execute asynchronously.
60
    // These operation are guaranteed to execute asynchronously.
59
    void startDiscovery();
61
    void startDiscovery();
62
    void restartDiscovery();
60
63
61
protected:
64
protected:
62
    explicit AuthenticatorTransportService(Observer&);
65
    explicit AuthenticatorTransportService(Observer&);
Lines 65-70 protected: a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorTransportService.h_sec4
65
68
66
private:
69
private:
67
    virtual void startDiscoveryInternal() = 0;
70
    virtual void startDiscoveryInternal() = 0;
71
    // NFC service's polling is one shot. It halts after the first tags are detected.
72
    // Therefore, a restart process is needed to resume polling after exceptions.
73
    virtual void restartDiscoveryInternal() { };
68
74
69
    WeakPtr<Observer> m_observer;
75
    WeakPtr<Observer> m_observer;
70
};
76
};
- a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcConnection.h -7 / +12 lines
Lines 27-35 a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcConnection.h_sec1
27
27
28
#if ENABLE(WEB_AUTHN) && HAVE(NEAR_FIELD)
28
#if ENABLE(WEB_AUTHN) && HAVE(NEAR_FIELD)
29
29
30
#include <wtf/FastMalloc.h>
30
#include <wtf/RefCounted.h>
31
#include <wtf/Noncopyable.h>
32
#include <wtf/RetainPtr.h>
31
#include <wtf/RetainPtr.h>
32
#include <wtf/RunLoop.h>
33
#include <wtf/WeakPtr.h>
33
#include <wtf/WeakPtr.h>
34
34
35
OBJC_CLASS NFReaderSession;
35
OBJC_CLASS NFReaderSession;
Lines 40-61 namespace WebKit { a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcConnection.h_sec2
40
40
41
class NfcService;
41
class NfcService;
42
42
43
class NfcConnection : public CanMakeWeakPtr<NfcConnection> {
43
class NfcConnection : public RefCounted<NfcConnection>, public CanMakeWeakPtr<NfcConnection> {
44
    WTF_MAKE_FAST_ALLOCATED;
45
    WTF_MAKE_NONCOPYABLE(NfcConnection);
46
public:
44
public:
47
    NfcConnection(RetainPtr<NFReaderSession>&&, NfcService&);
45
    static Ref<NfcConnection> create(RetainPtr<NFReaderSession>&&, NfcService&);
48
    ~NfcConnection();
46
    ~NfcConnection();
49
47
50
    Vector<uint8_t> transact(Vector<uint8_t>&& data) const;
48
    Vector<uint8_t> transact(Vector<uint8_t>&& data) const;
49
    void stop() const;
51
50
52
    // For WKNFReaderSessionDelegate
51
    // For WKNFReaderSessionDelegate
53
    void didDetectTags(NSArray *) const;
52
    void didDetectTags(NSArray *);
54
53
55
private:
54
private:
55
    NfcConnection(RetainPtr<NFReaderSession>&&, NfcService&);
56
57
    void restartPolling();
58
    void startPolling();
59
56
    RetainPtr<NFReaderSession> m_session;
60
    RetainPtr<NFReaderSession> m_session;
57
    RetainPtr<WKNFReaderSessionDelegate> m_delegate;
61
    RetainPtr<WKNFReaderSessionDelegate> m_delegate;
58
    WeakPtr<NfcService> m_service;
62
    WeakPtr<NfcService> m_service;
63
    RunLoop::Timer<NfcConnection> m_retryTimer;
59
};
64
};
60
65
61
} // namespace WebKit
66
} // namespace WebKit
- a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcConnection.mm -11 / +49 lines
Lines 45-64 inline bool compareVersion(NSData *data, const uint8_t version[], size_t version a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcConnection.mm_sec1
45
}
45
}
46
} // namespace
46
} // namespace
47
47
48
Ref<NfcConnection> NfcConnection::create(RetainPtr<NFReaderSession>&& session, NfcService& service)
49
{
50
    return adoptRef(*new NfcConnection(WTFMove(session), service));
51
}
52
48
NfcConnection::NfcConnection(RetainPtr<NFReaderSession>&& session, NfcService& service)
53
NfcConnection::NfcConnection(RetainPtr<NFReaderSession>&& session, NfcService& service)
49
    : m_session(WTFMove(session))
54
    : m_session(WTFMove(session))
50
    , m_delegate(adoptNS([[WKNFReaderSessionDelegate alloc] initWithConnection:*this]))
55
    , m_delegate(adoptNS([[WKNFReaderSessionDelegate alloc] initWithConnection:*this]))
51
    , m_service(makeWeakPtr(service))
56
    , m_service(makeWeakPtr(service))
57
    , m_retryTimer(RunLoop::main(), this, &NfcConnection::startPolling)
52
{
58
{
53
    [m_session setDelegate:m_delegate.get()];
59
    [m_session setDelegate:m_delegate.get()];
54
    [m_session startPolling];
60
    startPolling();
55
}
61
}
56
62
57
NfcConnection::~NfcConnection()
63
NfcConnection::~NfcConnection()
58
{
64
{
59
    [m_session disconnectTag];
65
    stop();
60
    [m_session stopPolling];
61
    [m_session endSession];
62
}
66
}
63
67
64
Vector<uint8_t> NfcConnection::transact(Vector<uint8_t>&& data) const
68
Vector<uint8_t> NfcConnection::transact(Vector<uint8_t>&& data) const
Lines 71-86 Vector<uint8_t> NfcConnection::transact(Vector<uint8_t>&& data) const a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcConnection.mm_sec2
71
    return response;
75
    return response;
72
}
76
}
73
77
74
void NfcConnection::didDetectTags(NSArray *tags) const
78
void NfcConnection::stop() const
79
{
80
    [m_session disconnectTag];
81
    [m_session stopPolling];
82
    [m_session endSession];
83
}
84
85
void NfcConnection::didDetectTags(NSArray *tags)
75
{
86
{
76
    if (!m_service)
87
    if (!m_service || !tags.count)
77
        return;
88
        return;
78
89
79
    // FIXME(200932): Warn users when multiple NFC tags present
90
    // A physical NFC tag could have multiple interfaces.
80
    for (NFTag *tag in tags) {
91
    // Therefore, we use tagID to detect if there are multiple physical tags.
81
        if (tag.type != NFTagTypeGeneric4A)
92
    NSData *tagID = ((NFTag *)tags[0]).tagID;
93
    for (NFTag *tag : tags) {
94
        if ([tagID isEqualToData:tag.tagID])
82
            continue;
95
            continue;
83
        if (![m_session connectTag:tag])
96
        m_service->didDetectMultipleTags();
97
        restartPolling();
98
        return;
99
    }
100
101
    // FIXME(203234): Tell users to switch to a different tag if the tag is not of type NFTagTypeGeneric4A
102
    // or can't speak U2F/FIDO2.
103
    for (NFTag *tag : tags) {
104
        if (tag.type != NFTagTypeGeneric4A || ![m_session connectTag:tag])
84
            continue;
105
            continue;
85
106
86
        // Confirm the FIDO applet is avaliable before return.
107
        // Confirm the FIDO applet is avaliable before return.
Lines 94-101 void NfcConnection::didDetectTags(NSArray *tags) const a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcConnection.mm_sec3
94
        }
115
        }
95
116
96
        m_service->didConnectTag();
117
        m_service->didConnectTag();
97
        break;
118
        return;
98
    }
119
    }
120
    restartPolling();
121
}
122
123
// NearField polling is a one shot polling. It halts after tags are detected.
124
// Therefore, a restart process is needed to resume polling after error.
125
void NfcConnection::restartPolling()
126
{
127
    [m_session stopPolling];
128
    m_retryTimer.startOneShot(1_s); // Magic number to give users enough time for reactions.
129
}
130
131
void NfcConnection::startPolling()
132
{
133
    NSError *error = nil;
134
    [m_session startPollingWithError:&error];
135
    if (error)
136
        LOG_ERROR("Couldn't start NFC reader polling: %@", error);
99
}
137
}
100
138
101
} // namespace WebKit
139
} // namespace WebKit
- a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcService.h -4 / +7 lines
Lines 28-39 a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcService.h_sec1
28
#if ENABLE(WEB_AUTHN)
28
#if ENABLE(WEB_AUTHN)
29
29
30
#include "FidoService.h"
30
#include "FidoService.h"
31
#include <wtf/RunLoop.h>
31
32
32
OBJC_CLASS NFReaderSession;
33
OBJC_CLASS NFReaderSession;
33
34
34
namespace WebKit {
35
namespace WebKit {
35
36
36
class CtapNfcDriver;
37
class NfcConnection;
37
38
38
class NfcService : public FidoService {
39
class NfcService : public FidoService {
39
public:
40
public:
Lines 42-56 public: a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcService.h_sec2
42
43
43
    // For NfcConnection.
44
    // For NfcConnection.
44
    void didConnectTag();
45
    void didConnectTag();
46
    void didDetectMultipleTags() const;
45
47
46
#if HAVE(NEAR_FIELD)
48
#if HAVE(NEAR_FIELD)
47
protected:
49
protected:
48
    void setDriver(std::unique_ptr<CtapNfcDriver>&&);
50
    void setConnection(Ref<NfcConnection>&&); // For MockNfcConnection
49
#endif
51
#endif
50
52
51
private:
53
private:
52
    void startDiscoveryInternal() final;
54
    void startDiscoveryInternal() final;
53
    void continueAddDeviceAfterGetInfo(Vector<uint8_t>&& response);
55
    void restartDiscoveryInternal() final;
54
56
55
    // Overrided by MockNfcService.
57
    // Overrided by MockNfcService.
56
    virtual void platformStartDiscovery();
58
    virtual void platformStartDiscovery();
Lines 58-65 private: a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcService.h_sec3
58
#if HAVE(NEAR_FIELD)
60
#if HAVE(NEAR_FIELD)
59
    // Only one reader session is allowed per time.
61
    // Only one reader session is allowed per time.
60
    // Keep the reader session alive here when it tries to connect to a tag.
62
    // Keep the reader session alive here when it tries to connect to a tag.
61
    std::unique_ptr<CtapNfcDriver> m_driver;
63
    RefPtr<NfcConnection> m_connection;
62
#endif
64
#endif
65
    RunLoop::Timer<NfcService> m_restartTimer;
63
};
66
};
64
67
65
} // namespace WebKit
68
} // namespace WebKit
- a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcService.mm -5 / +23 lines
Lines 41-46 namespace WebKit { a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcService.mm_sec1
41
41
42
NfcService::NfcService(Observer& observer)
42
NfcService::NfcService(Observer& observer)
43
    : FidoService(observer)
43
    : FidoService(observer)
44
    , m_restartTimer(RunLoop::main(), this, &NfcService::platformStartDiscovery)
44
{
45
{
45
}
46
}
46
47
Lines 51-64 NfcService::~NfcService() a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcService.mm_sec2
51
void NfcService::didConnectTag()
52
void NfcService::didConnectTag()
52
{
53
{
53
#if HAVE(NEAR_FIELD)
54
#if HAVE(NEAR_FIELD)
54
    getInfo(WTFMove(m_driver));
55
    auto connection = m_connection;
56
    ASSERT(connection);
57
    getInfo(WTF::makeUnique<CtapNfcDriver>(connection.releaseNonNull()));
55
#endif
58
#endif
56
}
59
}
57
60
61
void NfcService::didDetectMultipleTags() const
62
{
63
    if (auto* observer = this->observer())
64
        observer->serviceStatusUpdated(WebAuthenticationStatus::MultipleNFCTagsPresent);
65
}
66
58
#if HAVE(NEAR_FIELD)
67
#if HAVE(NEAR_FIELD)
59
void NfcService::setDriver(std::unique_ptr<CtapNfcDriver>&& driver)
68
void NfcService::setConnection(Ref<NfcConnection>&& connection)
60
{
69
{
61
    m_driver = WTFMove(driver);
70
    m_connection = WTFMove(connection);
62
}
71
}
63
#endif
72
#endif
64
73
Lines 67-72 void NfcService::startDiscoveryInternal() a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcService.mm_sec3
67
    platformStartDiscovery();
76
    platformStartDiscovery();
68
}
77
}
69
78
79
void NfcService::restartDiscoveryInternal()
80
{
81
#if HAVE(NEAR_FIELD)
82
    if (m_connection)
83
        m_connection->stop();
84
#endif
85
    m_restartTimer.startOneShot(1_s); // Magic number to give users enough time for reactions.
86
}
87
70
void NfcService::platformStartDiscovery()
88
void NfcService::platformStartDiscovery()
71
{
89
{
72
#if HAVE(NEAR_FIELD)
90
#if HAVE(NEAR_FIELD)
Lines 87-94 void NfcService::platformStartDiscovery() a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcService.mm_sec4
87
                return;
105
                return;
88
            }
106
            }
89
107
90
            // CtapNfcDriver and NfcConnection will take care of polling tags and connecting to them.
108
            // NfcConnection will take care of polling tags and connecting to them.
91
            m_driver = WTF::makeUnique<CtapNfcDriver>(makeUniqueRef<NfcConnection>(WTFMove(session), *this));
109
            m_connection = NfcConnection::create(WTFMove(session), *this);
92
        });
110
        });
93
    });
111
    });
94
    [[getNFHardwareManagerClass() sharedHardwareManager] startReaderSession:callback.get()];
112
    [[getNFHardwareManagerClass() sharedHardwareManager] startReaderSession:callback.get()];
- a/Source/WebKit/UIProcess/WebAuthentication/Mock/MockNfcService.h -1 / +3 lines
Lines 39-49 public: a/Source/WebKit/UIProcess/WebAuthentication/Mock/MockNfcService.h_sec1
39
    MockNfcService(Observer&, const WebCore::MockWebAuthenticationConfiguration&);
39
    MockNfcService(Observer&, const WebCore::MockWebAuthenticationConfiguration&);
40
40
41
    NSData* transceive();
41
    NSData* transceive();
42
    void receiveStopPolling();
43
    void receiveStartPolling();
42
44
43
private:
45
private:
44
    void platformStartDiscovery() final;
46
    void platformStartDiscovery() final;
45
47
46
    void detectTags() const;
48
    void detectTags();
47
49
48
    WebCore::MockWebAuthenticationConfiguration m_configuration;
50
    WebCore::MockWebAuthenticationConfiguration m_configuration;
49
};
51
};
- a/Source/WebKit/UIProcess/WebAuthentication/Mock/MockNfcService.mm -14 / +65 lines
Lines 38-57 a/Source/WebKit/UIProcess/WebAuthentication/Mock/MockNfcService.mm_sec1
38
38
39
#import "NearFieldSoftLink.h"
39
#import "NearFieldSoftLink.h"
40
40
41
namespace {
42
uint8_t tagID1[] = { 0x01 };
43
uint8_t tagID2[] = { 0x02 };
44
}
45
41
#if HAVE(NEAR_FIELD)
46
#if HAVE(NEAR_FIELD)
42
47
43
@interface WKMockNFTag : NSObject <NFTag>
48
@interface WKMockNFTag : NSObject <NFTag>
44
49
45
- (instancetype)initWithType:(NFTagType)type;
50
- (instancetype)initWithType:(NFTagType)type;
51
- (instancetype)initWithType:(NFTagType)type tagID:(NSData *)tagID;
46
52
47
@end
53
@end
48
54
49
@implementation WKMockNFTag {
55
@implementation WKMockNFTag {
50
    NFTagType _type;
56
    NFTagType _type;
57
    RetainPtr<NSData> _tagID;
51
}
58
}
52
59
53
@synthesize technology=_technology;
60
@synthesize technology=_technology;
54
@synthesize tagID=_tagID;
55
@synthesize AppData=_AppData;
61
@synthesize AppData=_AppData;
56
@synthesize UID=_UID;
62
@synthesize UID=_UID;
57
@synthesize ndefAvailability=_ndefAvailability;
63
@synthesize ndefAvailability=_ndefAvailability;
Lines 66-82 - (NFTagType)type a/Source/WebKit/UIProcess/WebAuthentication/Mock/MockNfcService.mm_sec2
66
    return _type;
72
    return _type;
67
}
73
}
68
74
75
- (NSData *)tagID
76
{
77
    return _tagID.get();
78
}
79
69
- (instancetype)initWithNFTag:(id<NFTag>)tag
80
- (instancetype)initWithNFTag:(id<NFTag>)tag
70
{
81
{
71
    if ((self = [super init]))
82
    if ((self = [super init])) {
72
        _type = tag.type;
83
        _type = tag.type;
84
        _tagID = tag.tagID;
85
    }
73
    return self;
86
    return self;
74
}
87
}
75
88
76
- (void)dealloc
89
- (void)dealloc
77
{
90
{
78
    [_tagID release];
79
    _tagID = nil;
80
    [_AppData release];
91
    [_AppData release];
81
    _AppData = nil;
92
    _AppData = nil;
82
    [_UID release];
93
    [_UID release];
Lines 97-104 - (BOOL)isEqualToNFTag:(id<NFTag>)tag a/Source/WebKit/UIProcess/WebAuthentication/Mock/MockNfcService.mm_sec3
97
108
98
- (instancetype)initWithType:(NFTagType)type
109
- (instancetype)initWithType:(NFTagType)type
99
{
110
{
100
    if ((self = [super init]))
111
    return [self initWithType:type tagID:adoptNS([[NSData alloc] initWithBytes:tagID1 length:sizeof(tagID1)]).get()];
112
}
113
114
- (instancetype)initWithType:(NFTagType)type tagID:(NSData *)tagID
115
{
116
    if ((self = [super init])) {
101
        _type = type;
117
        _type = type;
118
        _tagID = tagID;
119
    }
102
    return self;
120
    return self;
103
}
121
}
104
122
Lines 132-137 static BOOL NFReaderSessionConnectTag(id, SEL, NFTag *) a/Source/WebKit/UIProcess/WebAuthentication/Mock/MockNfcService.mm_sec4
132
    return YES;
150
    return YES;
133
}
151
}
134
152
153
static BOOL NFReaderSessionStopPolling(id, SEL)
154
{
155
    if (!globalNfcService)
156
        return NO;
157
    globalNfcService->receiveStopPolling();
158
    return YES;
159
}
160
161
static BOOL NFReaderSessionStartPollingWithError(id, SEL, NSError **)
162
{
163
    if (!globalNfcService)
164
        return NO;
165
    globalNfcService->receiveStartPolling();
166
    return YES;
167
}
168
135
static NSData* NFReaderSessionTransceive(id, SEL, NSData *)
169
static NSData* NFReaderSessionTransceive(id, SEL, NSData *)
136
{
170
{
137
    if (!globalNfcService)
171
    if (!globalNfcService)
Lines 159-164 NSData* MockNfcService::transceive() a/Source/WebKit/UIProcess/WebAuthentication/Mock/MockNfcService.mm_sec5
159
    return [result autorelease];
193
    return [result autorelease];
160
}
194
}
161
195
196
void MockNfcService::receiveStopPolling()
197
{
198
    // For purpose of restart polling.
199
    m_configuration.nfc->multiplePhysicalTags = false;
200
}
201
202
void MockNfcService::receiveStartPolling()
203
{
204
    RunLoop::main().dispatch([weakThis = makeWeakPtr(*this)] {
205
        if (!weakThis)
206
            return;
207
        weakThis->detectTags();
208
    });
209
}
210
162
void MockNfcService::platformStartDiscovery()
211
void MockNfcService::platformStartDiscovery()
163
{
212
{
164
#if HAVE(NEAR_FIELD)
213
#if HAVE(NEAR_FIELD)
Lines 177-197 void MockNfcService::platformStartDiscovery() a/Source/WebKit/UIProcess/WebAuthentication/Mock/MockNfcService.mm_sec6
177
        Method methodToSwizzle3 = class_getInstanceMethod(getNFReaderSessionClass(), @selector(transceive:));
226
        Method methodToSwizzle3 = class_getInstanceMethod(getNFReaderSessionClass(), @selector(transceive:));
178
        method_setImplementation(methodToSwizzle3, (IMP)NFReaderSessionTransceive);
227
        method_setImplementation(methodToSwizzle3, (IMP)NFReaderSessionTransceive);
179
228
180
        auto readerSession = adoptNS([allocNFReaderSessionInstance() init]);
229
        Method methodToSwizzle4 = class_getInstanceMethod(getNFReaderSessionClass(), @selector(stopPolling));
181
        setDriver(WTF::makeUnique<CtapNfcDriver>(makeUniqueRef<NfcConnection>(readerSession.get(), *this)));
230
        method_setImplementation(methodToSwizzle4, (IMP)NFReaderSessionStopPolling);
182
231
183
        RunLoop::main().dispatch([weakThis = makeWeakPtr(*this)] {
232
        Method methodToSwizzle5 = class_getInstanceMethod(getNFReaderSessionClass(), @selector(startPollingWithError:));
184
            if (!weakThis)
233
        method_setImplementation(methodToSwizzle5, (IMP)NFReaderSessionStartPollingWithError);
185
                return;
234
186
            weakThis->detectTags();
235
        auto readerSession = adoptNS([allocNFReaderSessionInstance() init]);
187
        });
236
        setConnection(NfcConnection::create(readerSession.get(), *this));
188
        return;
189
    }
237
    }
190
    LOG_ERROR("No nfc authenticators is available.");
238
    LOG_ERROR("No nfc authenticators is available.");
191
#endif // HAVE(NEAR_FIELD)
239
#endif // HAVE(NEAR_FIELD)
192
}
240
}
193
241
194
void MockNfcService::detectTags() const
242
void MockNfcService::detectTags()
195
{
243
{
196
#if HAVE(NEAR_FIELD)
244
#if HAVE(NEAR_FIELD)
197
    if (m_configuration.nfc->error == Mock::NfcError::NoTags)
245
    if (m_configuration.nfc->error == Mock::NfcError::NoTags)
Lines 207-212 void MockNfcService::detectTags() const a/Source/WebKit/UIProcess/WebAuthentication/Mock/MockNfcService.mm_sec7
207
        if (configuration.nfc->multipleTags)
255
        if (configuration.nfc->multipleTags)
208
            [tags addObject:adoptNS([[WKMockNFTag alloc] initWithType:NFTagTypeGeneric4A]).get()];
256
            [tags addObject:adoptNS([[WKMockNFTag alloc] initWithType:NFTagTypeGeneric4A]).get()];
209
257
258
        if (configuration.nfc->multiplePhysicalTags)
259
            [tags addObject:adoptNS([[WKMockNFTag alloc] initWithType:NFTagTypeGeneric4A tagID:adoptNS([[NSData alloc] initWithBytes:tagID2 length:sizeof(tagID2)]).get()]).get()];
260
210
        [globalNFReaderSessionDelegate readerSession:nil didDetectTags:tags.get()];
261
        [globalNFReaderSessionDelegate readerSession:nil didDetectTags:tags.get()];
211
    });
262
    });
212
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), callback.get());
263
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), callback.get());
- a/Source/WebKit/UIProcess/WebAuthentication/fido/CtapNfcDriver.cpp -1 / +1 lines
Lines 36-42 namespace WebKit { a/Source/WebKit/UIProcess/WebAuthentication/fido/CtapNfcDriver.cpp_sec1
36
using namespace apdu;
36
using namespace apdu;
37
using namespace fido;
37
using namespace fido;
38
38
39
CtapNfcDriver::CtapNfcDriver(UniqueRef<NfcConnection>&& connection)
39
CtapNfcDriver::CtapNfcDriver(Ref<NfcConnection>&& connection)
40
    : m_connection(WTFMove(connection))
40
    : m_connection(WTFMove(connection))
41
{
41
{
42
}
42
}
- a/Source/WebKit/UIProcess/WebAuthentication/fido/CtapNfcDriver.h -2 / +2 lines
Lines 37-50 namespace WebKit { a/Source/WebKit/UIProcess/WebAuthentication/fido/CtapNfcDriver.h_sec1
37
// https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#nfc
37
// https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#nfc
38
class CtapNfcDriver : public CtapDriver {
38
class CtapNfcDriver : public CtapDriver {
39
public:
39
public:
40
    explicit CtapNfcDriver(UniqueRef<NfcConnection>&&);
40
    explicit CtapNfcDriver(Ref<NfcConnection>&&);
41
41
42
    void transact(Vector<uint8_t>&& data, ResponseCallback&&) final;
42
    void transact(Vector<uint8_t>&& data, ResponseCallback&&) final;
43
43
44
private:
44
private:
45
    void respondAsync(ResponseCallback&&, Vector<uint8_t>&& response) const;
45
    void respondAsync(ResponseCallback&&, Vector<uint8_t>&& response) const;
46
46
47
    UniqueRef<NfcConnection> m_connection;
47
    Ref<NfcConnection> m_connection;
48
};
48
};
49
49
50
} // namespace WebKit
50
} // namespace WebKit
- a/Source/WebKit/UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp -1 lines
Lines 33-39 a/Source/WebKit/UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp_sec1
33
#include <WebCore/ExceptionData.h>
33
#include <WebCore/ExceptionData.h>
34
#include <WebCore/U2fCommandConstructor.h>
34
#include <WebCore/U2fCommandConstructor.h>
35
#include <WebCore/U2fResponseConverter.h>
35
#include <WebCore/U2fResponseConverter.h>
36
#include <wtf/RunLoop.h>
37
#include <wtf/text/StringConcatenateNumbers.h>
36
#include <wtf/text/StringConcatenateNumbers.h>
38
37
39
namespace WebKit {
38
namespace WebKit {
- a/Tools/ChangeLog +15 lines
Lines 1-3 a/Tools/ChangeLog_sec1
1
2019-10-21  Jiewen Tan  <jiewen_tan@apple.com>
2
3
        [WebAuthn] Warn users when multiple NFC tags present
4
        https://bugs.webkit.org/show_bug.cgi?id=200932
5
        <rdar://problem/54890736>
6
7
        Reviewed by NOBODY (OOPS!).
8
9
        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
10
        * TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm:
11
        (-[TestWebAuthenticationPanelDelegate panel:updateWebAuthenticationPanel:]):
12
        (TestWebKitAPI::TEST):
13
        Adds a new test for -[_WKWebAuthenticationPanelDelegate panel:updateWebAuthenticationPanel:].
14
        * TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion-nfc-multiple-tags.html: Added.
15
1
2019-10-18  Aakash Jain  <aakash_jain@apple.com>
16
2019-10-18  Aakash Jain  <aakash_jain@apple.com>
2
17
3
        EWS should have a way to retry a patch
18
        EWS should have a way to retry a patch
- a/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj +4 lines
Lines 350-355 a/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj_sec1
350
		579651E7216BFDED006EBFE5 /* FidoHidMessageTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 579651E6216BFD53006EBFE5 /* FidoHidMessageTest.cpp */; };
350
		579651E7216BFDED006EBFE5 /* FidoHidMessageTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 579651E6216BFD53006EBFE5 /* FidoHidMessageTest.cpp */; };
351
		5797FE311EB15A6800B2F4A0 /* NavigationClientDefaultCrypto.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5797FE2F1EB15A5F00B2F4A0 /* NavigationClientDefaultCrypto.cpp */; };
351
		5797FE311EB15A6800B2F4A0 /* NavigationClientDefaultCrypto.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5797FE2F1EB15A5F00B2F4A0 /* NavigationClientDefaultCrypto.cpp */; };
352
		5797FE331EB15AB100B2F4A0 /* navigation-client-default-crypto.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5797FE321EB15A8900B2F4A0 /* navigation-client-default-crypto.html */; };
352
		5797FE331EB15AB100B2F4A0 /* navigation-client-default-crypto.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5797FE321EB15A8900B2F4A0 /* navigation-client-default-crypto.html */; };
353
		5798337C235EB689008E5547 /* web-authentication-get-assertion-nfc-multiple-tags.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5798337B235EB65C008E5547 /* web-authentication-get-assertion-nfc-multiple-tags.html */; };
353
		57A79857224AB34E00A7F6F1 /* WebCryptoMasterKey.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57A79856224AB34E00A7F6F1 /* WebCryptoMasterKey.mm */; };
354
		57A79857224AB34E00A7F6F1 /* WebCryptoMasterKey.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57A79856224AB34E00A7F6F1 /* WebCryptoMasterKey.mm */; };
354
		57C3FA661F7C248F009D4B80 /* WeakPtr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1CB9BC371A67482300FE5678 /* WeakPtr.cpp */; };
355
		57C3FA661F7C248F009D4B80 /* WeakPtr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1CB9BC371A67482300FE5678 /* WeakPtr.cpp */; };
355
		57C6244E2346BCFA00383FE7 /* _WKWebAuthenticationPanel.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57C6244D2346BCFA00383FE7 /* _WKWebAuthenticationPanel.mm */; };
356
		57C6244E2346BCFA00383FE7 /* _WKWebAuthenticationPanel.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57C6244D2346BCFA00383FE7 /* _WKWebAuthenticationPanel.mm */; };
Lines 1449-1454 a/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj_sec2
1449
				57663DF32357E48900E85E09 /* web-authentication-get-assertion-hid-cancel.html in Copy Resources */,
1450
				57663DF32357E48900E85E09 /* web-authentication-get-assertion-hid-cancel.html in Copy Resources */,
1450
				577454D02359B378008E1ED7 /* web-authentication-get-assertion-hid-no-credentials.html in Copy Resources */,
1451
				577454D02359B378008E1ED7 /* web-authentication-get-assertion-hid-no-credentials.html in Copy Resources */,
1451
				57663DEC234F1F9300E85E09 /* web-authentication-get-assertion-hid.html in Copy Resources */,
1452
				57663DEC234F1F9300E85E09 /* web-authentication-get-assertion-hid.html in Copy Resources */,
1453
				5798337C235EB689008E5547 /* web-authentication-get-assertion-nfc-multiple-tags.html in Copy Resources */,
1452
				57663DEA234EA66D00E85E09 /* web-authentication-get-assertion-nfc.html in Copy Resources */,
1454
				57663DEA234EA66D00E85E09 /* web-authentication-get-assertion-nfc.html in Copy Resources */,
1453
				577454D22359BB01008E1ED7 /* web-authentication-get-assertion-u2f-no-credentials.html in Copy Resources */,
1455
				577454D22359BB01008E1ED7 /* web-authentication-get-assertion-u2f-no-credentials.html in Copy Resources */,
1454
				57C624502346C21E00383FE7 /* web-authentication-get-assertion.html in Copy Resources */,
1456
				57C624502346C21E00383FE7 /* web-authentication-get-assertion.html in Copy Resources */,
Lines 1884-1889 a/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj_sec3
1884
		579651E6216BFD53006EBFE5 /* FidoHidMessageTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FidoHidMessageTest.cpp; sourceTree = "<group>"; };
1886
		579651E6216BFD53006EBFE5 /* FidoHidMessageTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FidoHidMessageTest.cpp; sourceTree = "<group>"; };
1885
		5797FE2F1EB15A5F00B2F4A0 /* NavigationClientDefaultCrypto.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NavigationClientDefaultCrypto.cpp; sourceTree = "<group>"; };
1887
		5797FE2F1EB15A5F00B2F4A0 /* NavigationClientDefaultCrypto.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NavigationClientDefaultCrypto.cpp; sourceTree = "<group>"; };
1886
		5797FE321EB15A8900B2F4A0 /* navigation-client-default-crypto.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "navigation-client-default-crypto.html"; sourceTree = "<group>"; };
1888
		5797FE321EB15A8900B2F4A0 /* navigation-client-default-crypto.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "navigation-client-default-crypto.html"; sourceTree = "<group>"; };
1889
		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>"; };
1887
		5798E2AF1CAF5C2800C5CBA0 /* ProvisionalURLNotChange.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ProvisionalURLNotChange.mm; sourceTree = "<group>"; };
1890
		5798E2AF1CAF5C2800C5CBA0 /* ProvisionalURLNotChange.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ProvisionalURLNotChange.mm; sourceTree = "<group>"; };
1888
		57A79856224AB34E00A7F6F1 /* WebCryptoMasterKey.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCryptoMasterKey.mm; sourceTree = "<group>"; };
1891
		57A79856224AB34E00A7F6F1 /* WebCryptoMasterKey.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCryptoMasterKey.mm; sourceTree = "<group>"; };
1889
		57C6244D2346BCFA00383FE7 /* _WKWebAuthenticationPanel.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKWebAuthenticationPanel.mm; sourceTree = "<group>"; };
1892
		57C6244D2346BCFA00383FE7 /* _WKWebAuthenticationPanel.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKWebAuthenticationPanel.mm; sourceTree = "<group>"; };
Lines 3399-3404 a/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj_sec4
3399
				57663DF22357E45D00E85E09 /* web-authentication-get-assertion-hid-cancel.html */,
3402
				57663DF22357E45D00E85E09 /* web-authentication-get-assertion-hid-cancel.html */,
3400
				577454CF2359B338008E1ED7 /* web-authentication-get-assertion-hid-no-credentials.html */,
3403
				577454CF2359B338008E1ED7 /* web-authentication-get-assertion-hid-no-credentials.html */,
3401
				57663DEB234F1F8000E85E09 /* web-authentication-get-assertion-hid.html */,
3404
				57663DEB234F1F8000E85E09 /* web-authentication-get-assertion-hid.html */,
3405
				5798337B235EB65C008E5547 /* web-authentication-get-assertion-nfc-multiple-tags.html */,
3402
				57663DE9234EA60B00E85E09 /* web-authentication-get-assertion-nfc.html */,
3406
				57663DE9234EA60B00E85E09 /* web-authentication-get-assertion-nfc.html */,
3403
				577454D12359BAD5008E1ED7 /* web-authentication-get-assertion-u2f-no-credentials.html */,
3407
				577454D12359BAD5008E1ED7 /* web-authentication-get-assertion-u2f-no-credentials.html */,
3404
				57C6244F2346C1EC00383FE7 /* web-authentication-get-assertion.html */,
3408
				57C6244F2346C1EC00383FE7 /* web-authentication-get-assertion.html */,
- a/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm -1 / +27 lines
Lines 42-47 a/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm_sec1
42
static bool webAuthenticationPanelRan = false;
42
static bool webAuthenticationPanelRan = false;
43
static bool webAuthenticationPanelFailed = false;
43
static bool webAuthenticationPanelFailed = false;
44
static bool webAuthenticationPanelSucceded = false;
44
static bool webAuthenticationPanelSucceded = false;
45
static bool webAuthenticationPanelUpdateMultipleNFCTagsPresent = false;
45
static bool webAuthenticationPanelUpdateNoCredentialsFound = false;
46
static bool webAuthenticationPanelUpdateNoCredentialsFound = false;
46
static RetainPtr<_WKWebAuthenticationPanel> gPanel;
47
static RetainPtr<_WKWebAuthenticationPanel> gPanel;
47
48
Lines 53-60 @implementation TestWebAuthenticationPanelDelegate a/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm_sec2
53
- (void)panel:(_WKWebAuthenticationPanel *)panel updateWebAuthenticationPanel:(_WKWebAuthenticationPanelUpdate)update
54
- (void)panel:(_WKWebAuthenticationPanel *)panel updateWebAuthenticationPanel:(_WKWebAuthenticationPanelUpdate)update
54
{
55
{
55
    ASSERT_NE(panel, nil);
56
    ASSERT_NE(panel, nil);
56
    if (update == _WKWebAuthenticationPanelUpdateNoCredentialsFound)
57
    if (update == _WKWebAuthenticationPanelUpdateMultipleNFCTagsPresent) {
58
        webAuthenticationPanelUpdateMultipleNFCTagsPresent = true;
59
        return;
60
    }
61
    if (update == _WKWebAuthenticationPanelUpdateNoCredentialsFound) {
57
        webAuthenticationPanelUpdateNoCredentialsFound = true;
62
        webAuthenticationPanelUpdateNoCredentialsFound = true;
63
        return;
64
    }
58
}
65
}
59
66
60
- (void)panel:(_WKWebAuthenticationPanel *)panel dismissWebAuthenticationPanelWithResult:(_WKWebAuthenticationResult)result
67
- (void)panel:(_WKWebAuthenticationPanel *)panel dismissWebAuthenticationPanelWithResult:(_WKWebAuthenticationResult)result
Lines 578-583 TEST(WebAuthenticationPanel, NullPanelHidCtapNoCredentialsFound) a/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm_sec3
578
    [webView waitForMessage:@"Operation timed out."];
585
    [webView waitForMessage:@"Operation timed out."];
579
}
586
}
580
587
588
#if HAVE(NEAR_FIELD)
589
TEST(WebAuthenticationPanel, PanelMultipleNFCTagsPresent)
590
{
591
    reset();
592
    RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-nfc-multiple-tags" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
593
594
    auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
595
    [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
596
597
    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
598
    auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
599
    [webView setUIDelegate:delegate.get()];
600
601
    [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
602
    Util::run(&webAuthenticationPanelRan);
603
    Util::run(&webAuthenticationPanelUpdateMultipleNFCTagsPresent);
604
}
605
#endif
606
581
} // namespace TestWebKitAPI
607
} // namespace TestWebKitAPI
582
608
583
#endif // ENABLE(WEB_AUTHN)
609
#endif // ENABLE(WEB_AUTHN)
- a/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion-nfc-multiple-tags.html +16 lines
Line 0 a/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion-nfc-multiple-tags.html_sec1
1
<input type="text" id="input">
2
<script>
3
    if (window.internals) {
4
        internals.setMockWebAuthenticationConfiguration({ silentFailure: true, nfc: { multiplePhysicalTags:true } });
5
        internals.withUserGesture(() => { input.focus(); });
6
    }
7
8
    const options = {
9
        publicKey: {
10
            challenge: new Uint8Array(16),
11
            timeout: 100,
12
        }
13
    };
14
15
    navigator.credentials.get(options);
16
</script>
- a/LayoutTests/ChangeLog +12 lines
Lines 1-3 a/LayoutTests/ChangeLog_sec1
1
2019-10-21  Jiewen Tan  <jiewen_tan@apple.com>
2
3
        [WebAuthn] Warn users when multiple NFC tags present
4
        https://bugs.webkit.org/show_bug.cgi?id=200932
5
        <rdar://problem/54890736>
6
7
        Reviewed by NOBODY (OOPS!).
8
9
        * http/wpt/webauthn/public-key-credential-create-success-nfc.https-expected.txt:
10
        * http/wpt/webauthn/public-key-credential-create-success-nfc.https.html:
11
        Adds new tests for multiple physical tags and service restart.
12
1
2019-10-21  Simon Fraser  <simon.fraser@apple.com>
13
2019-10-21  Simon Fraser  <simon.fraser@apple.com>
2
14
3
        [iOS WK2] Support hiding iframe scrollbars via ::-webkit-scrollbar style
15
        [iOS WK2] Support hiding iframe scrollbars via ::-webkit-scrollbar style
- a/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-nfc.https-expected.txt +2 lines
Lines 3-6 PASS PublicKeyCredential's [[create]] with minimum options in a mock nfc authent a/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-nfc.https-expected.txt_sec1
3
PASS PublicKeyCredential's [[create]] with authenticatorSelection { 'cross-platform' } in a mock nfc authenticator. 
3
PASS PublicKeyCredential's [[create]] with authenticatorSelection { 'cross-platform' } in a mock nfc authenticator. 
4
PASS PublicKeyCredential's [[create]] with multiple tags in a mock nfc authenticator. 
4
PASS PublicKeyCredential's [[create]] with multiple tags in a mock nfc authenticator. 
5
PASS PublicKeyCredential's [[create]] with U2F in a mock nfc authenticator. 
5
PASS PublicKeyCredential's [[create]] with U2F in a mock nfc authenticator. 
6
PASS PublicKeyCredential's [[create]] with multiple physical tags in a mock nfc authenticator. 
7
PASS PublicKeyCredential's [[create]] with service restart in a mock nfc authenticator. 
6
8
- a/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-nfc.https.html -8 / +50 lines
Lines 21-28 a/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-nfc.https.html_sec1
21
                    displayName: "Appleseed",
21
                    displayName: "Appleseed",
22
                },
22
                },
23
                challenge: Base64URL.parse("MTIzNDU2"),
23
                challenge: Base64URL.parse("MTIzNDU2"),
24
                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
24
                pubKeyCredParams: [{ type: "public-key", alg: -7 }]
25
                timeout: 100
26
            }
25
            }
27
        };
26
        };
28
27
Lines 44-51 a/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-nfc.https.html_sec2
44
                },
43
                },
45
                challenge: Base64URL.parse("MTIzNDU2"),
44
                challenge: Base64URL.parse("MTIzNDU2"),
46
                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
45
                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
47
                authenticatorSelection: { authenticatorAttachment: "cross-platform" },
46
                authenticatorSelection: { authenticatorAttachment: "cross-platform" }
48
                timeout: 100
49
            }
47
            }
50
        };
48
        };
51
49
Lines 66-73 a/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-nfc.https.html_sec3
66
                    displayName: "Appleseed",
64
                    displayName: "Appleseed",
67
                },
65
                },
68
                challenge: Base64URL.parse("MTIzNDU2"),
66
                challenge: Base64URL.parse("MTIzNDU2"),
69
                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
67
                pubKeyCredParams: [{ type: "public-key", alg: -7 }]
70
                timeout: 100
71
            }
68
            }
72
        };
69
        };
73
70
Lines 90-97 a/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-nfc.https.html_sec4
90
                    displayName: "Appleseed",
87
                    displayName: "Appleseed",
91
                },
88
                },
92
                challenge: Base64URL.parse("MTIzNDU2"),
89
                challenge: Base64URL.parse("MTIzNDU2"),
93
                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
90
                pubKeyCredParams: [{ type: "public-key", alg: -7 }]
94
                timeout: 100
95
            }
91
            }
96
        };
92
        };
97
93
Lines 101-104 a/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-nfc.https.html_sec5
101
            checkU2fMakeCredentialResult(credential);
97
            checkU2fMakeCredentialResult(credential);
102
        });
98
        });
103
    }, "PublicKeyCredential's [[create]] with U2F in a mock nfc authenticator.");
99
    }, "PublicKeyCredential's [[create]] with U2F in a mock nfc authenticator.");
100
101
    promise_test(t => {
102
        const options = {
103
            publicKey: {
104
                rp: {
105
                    name: "localhost",
106
                },
107
                user: {
108
                    name: "John Appleseed",
109
                    id: Base64URL.parse(testUserhandleBase64),
110
                    displayName: "Appleseed",
111
                },
112
                challenge: Base64URL.parse("MTIzNDU2"),
113
                pubKeyCredParams: [{ type: "public-key", alg: -7 }]
114
            }
115
        };
116
117
        if (window.internals)
118
            internals.setMockWebAuthenticationConfiguration({ nfc: { error: "success", payloadBase64: [testNfcCtapVersionBase64, testGetInfoResponseApduBase64, testCreationMessageApduBase64], multiplePhysicalTags: true } });
119
        return navigator.credentials.create(options).then(credential => {
120
            checkCtapMakeCredentialResult(credential);
121
        });
122
    }, "PublicKeyCredential's [[create]] with multiple physical tags in a mock nfc authenticator.");
123
124
    promise_test(t => {
125
        const options = {
126
            publicKey: {
127
                rp: {
128
                    name: "localhost",
129
                },
130
                user: {
131
                    name: "John Appleseed",
132
                    id: Base64URL.parse(testUserhandleBase64),
133
                    displayName: "Appleseed",
134
                },
135
                challenge: Base64URL.parse("MTIzNDU2"),
136
                pubKeyCredParams: [{ type: "public-key", alg: -7 }]
137
            }
138
        };
139
140
        if (window.internals)
141
            internals.setMockWebAuthenticationConfiguration({ silentFailure: true, nfc: { error: "malicious-payload", payloadBase64: [testDummyMessagePayloadBase64, testNfcCtapVersionBase64, testGetInfoResponseApduBase64, testCreationMessageApduBase64] } });
142
        return navigator.credentials.create(options).then(credential => {
143
            checkCtapMakeCredentialResult(credential);
144
        });
145
    }, "PublicKeyCredential's [[create]] with service restart in a mock nfc authenticator.");
104
</script>
146
</script>

Return to Bug 200932