Diff
Modified: trunk/Source/WebKit/ChangeLog (264542 => 264543)
--- trunk/Source/WebKit/ChangeLog 2020-07-17 22:57:05 UTC (rev 264542)
+++ trunk/Source/WebKit/ChangeLog 2020-07-17 22:58:51 UTC (rev 264543)
@@ -1,3 +1,36 @@
+2020-07-17 Jiewen Tan <[email protected]>
+
+ [WebAuthn] Cache the PIN to improve NFC user experience
+ https://bugs.webkit.org/show_bug.cgi?id=213900
+ <rdar://problem/60073622>
+
+ Reviewed by Brent Fulgham.
+
+ Cache the PIN to improve NFC user experience. Users might not hold the NFC key against the NFC scanner all the time
+ while entering the PIN. Therefore, we cache the PIN from the previous connection and immediately return the cached PIN to
+ the current connection such that users don't need to enter the PIN again.
+
+ The only downside for this optimization is that a wrong PIN could be used if the user switch to another authenticator for
+ the new connection. Given there is no UUID to identify a particular authenticator, there is nothing we can do to resolve the
+ issue. The probability of the issue, however, should be rare.
+
+ Covered by new API tests.
+
+ * UIProcess/WebAuthentication/AuthenticatorManager.cpp:
+ (WebKit::AuthenticatorManager::authenticatorStatusUpdated):
+ (WebKit::AuthenticatorManager::requestPin):
+ Where the above logic is implemented.
+
+ * UIProcess/WebAuthentication/Cocoa/NfcConnection.mm:
+ (WebKit::NfcConnection::transact const):
+ Adds a comment.
+
+ * UIProcess/WebAuthentication/WebAuthenticationRequestData.h:
+ * UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp:
+ (WebKit::WebAuthenticatorCoordinatorProxy::makeCredential):
+ (WebKit::WebAuthenticatorCoordinatorProxy::getAssertion):
+ Adds a field for the cached PIN.
+
2020-07-17 Per Arne Vollan <[email protected]>
[iOS] Crash under WebProcess::handleXPCEndpointMessages
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp (264542 => 264543)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp 2020-07-17 22:57:05 UTC (rev 264542)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp 2020-07-17 22:58:51 UTC (rev 264543)
@@ -264,6 +264,10 @@
void AuthenticatorManager::authenticatorStatusUpdated(WebAuthenticationStatus status)
{
+ // Immediately invalidate the cache if the PIN is incorrect. A status update often means
+ // an error. We don't really care what kind of error it really is.
+ m_pendingRequestData.cachedPin = String();
+
dispatchPanelClientCall([status] (const API::WebAuthenticationPanel& panel) {
panel.client().updatePanel(status);
});
@@ -271,8 +275,25 @@
void AuthenticatorManager::requestPin(uint64_t retries, CompletionHandler<void(const WTF::String&)>&& completionHandler)
{
- dispatchPanelClientCall([retries, completionHandler = WTFMove(completionHandler)] (const API::WebAuthenticationPanel& panel) mutable {
- panel.client().requestPin(retries, WTFMove(completionHandler));
+ // Cache the PIN to improve NFC user experience so that a momentary movement of the NFC key away from the scanner doesn't
+ // force the PIN entry to be re-entered.
+ // We don't distinguish USB and NFC here becuase there is no harms to have this optimization for USB even though it is useless.
+ if (!m_pendingRequestData.cachedPin.isNull()) {
+ completionHandler(m_pendingRequestData.cachedPin);
+ m_pendingRequestData.cachedPin = String();
+ return;
+ }
+
+ auto callback = [weakThis = makeWeakPtr(*this), this, completionHandler = WTFMove(completionHandler)] (const WTF::String& pin) mutable {
+ if (!weakThis)
+ return;
+
+ m_pendingRequestData.cachedPin = pin;
+ completionHandler(pin);
+ };
+
+ dispatchPanelClientCall([retries, callback = WTFMove(callback)] (const API::WebAuthenticationPanel& panel) mutable {
+ panel.client().requestPin(retries, WTFMove(callback));
});
}
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcConnection.mm (264542 => 264543)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcConnection.mm 2020-07-17 22:57:05 UTC (rev 264542)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcConnection.mm 2020-07-17 22:58:51 UTC (rev 264543)
@@ -91,6 +91,7 @@
Vector<uint8_t> NfcConnection::transact(Vector<uint8_t>&& data) const
{
Vector<uint8_t> response;
+ // The method will return an empty NSData if the tag is disconnected.
auto *responseData = [m_session transceive:adoptNS([[NSData alloc] initWithBytes:data.data() length:data.size()]).get()];
response.append(reinterpret_cast<const uint8_t*>(responseData.bytes), responseData.length);
return response;
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticationRequestData.h (264542 => 264543)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticationRequestData.h 2020-07-17 22:57:05 UTC (rev 264542)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticationRequestData.h 2020-07-17 22:58:51 UTC (rev 264543)
@@ -51,6 +51,7 @@
WTF::Optional<WebCore::GlobalFrameIdentifier> frameID;
WebKit::FrameInfoData frameInfo;
bool processingUserGesture;
+ String cachedPin; // Only used to improve NFC Client PIN experience.
};
WebCore::ClientDataType getClientDataType(const Variant<WebCore::PublicKeyCredentialCreationOptions, WebCore::PublicKeyCredentialRequestOptions>&);
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp (264542 => 264543)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp 2020-07-17 22:57:05 UTC (rev 264542)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp 2020-07-17 22:58:51 UTC (rev 264543)
@@ -57,12 +57,12 @@
void WebAuthenticatorCoordinatorProxy::makeCredential(FrameIdentifier frameId, FrameInfoData&& frameInfo, Vector<uint8_t>&& hash, PublicKeyCredentialCreationOptions&& options, bool processingUserGesture, RequestCompletionHandler&& handler)
{
- handleRequest({ WTFMove(hash), WTFMove(options), makeWeakPtr(m_webPageProxy), WebAuthenticationPanelResult::Unavailable, nullptr, GlobalFrameIdentifier { m_webPageProxy.webPageID(), frameId }, WTFMove(frameInfo), processingUserGesture }, WTFMove(handler));
+ handleRequest({ WTFMove(hash), WTFMove(options), makeWeakPtr(m_webPageProxy), WebAuthenticationPanelResult::Unavailable, nullptr, GlobalFrameIdentifier { m_webPageProxy.webPageID(), frameId }, WTFMove(frameInfo), processingUserGesture, String() }, WTFMove(handler));
}
void WebAuthenticatorCoordinatorProxy::getAssertion(FrameIdentifier frameId, FrameInfoData&& frameInfo, Vector<uint8_t>&& hash, PublicKeyCredentialRequestOptions&& options, bool processingUserGesture, RequestCompletionHandler&& handler)
{
- handleRequest({ WTFMove(hash), WTFMove(options), makeWeakPtr(m_webPageProxy), WebAuthenticationPanelResult::Unavailable, nullptr, GlobalFrameIdentifier { m_webPageProxy.webPageID(), frameId }, WTFMove(frameInfo), processingUserGesture }, WTFMove(handler));
+ handleRequest({ WTFMove(hash), WTFMove(options), makeWeakPtr(m_webPageProxy), WebAuthenticationPanelResult::Unavailable, nullptr, GlobalFrameIdentifier { m_webPageProxy.webPageID(), frameId }, WTFMove(frameInfo), processingUserGesture, String() }, WTFMove(handler));
}
void WebAuthenticatorCoordinatorProxy::handleRequest(WebAuthenticationRequestData&& data, RequestCompletionHandler&& handler)
Modified: trunk/Tools/ChangeLog (264542 => 264543)
--- trunk/Tools/ChangeLog 2020-07-17 22:57:05 UTC (rev 264542)
+++ trunk/Tools/ChangeLog 2020-07-17 22:58:51 UTC (rev 264543)
@@ -1,3 +1,16 @@
+2020-07-17 Jiewen Tan <[email protected]>
+
+ [WebAuthn] Cache the PIN to improve NFC user experience
+ https://bugs.webkit.org/show_bug.cgi?id=213900
+ <rdar://problem/60073622>
+
+ Reviewed by Brent Fulgham.
+
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm:
+ (TestWebKitAPI::TEST):
+ * TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion-nfc-pin-disconnect.html: Added.
+
2020-07-17 Wenson Hsieh <[email protected]>
Recommended article titles on csdn.net are clipped after translating to English
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (264542 => 264543)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2020-07-17 22:57:05 UTC (rev 264542)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2020-07-17 22:58:51 UTC (rev 264543)
@@ -373,6 +373,7 @@
5742178E2400D2DF002B303D /* web-authentication-make-credential-la.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5742178D2400D26C002B303D /* web-authentication-make-credential-la.html */; };
574F55D2204D47F0002948C6 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 574F55D0204D471C002948C6 /* Security.framework */; };
5751B28A249D5BC500664C2A /* web-authentication-make-credential-hid-pin-get-pin-token-fake-pin-invalid-error-retry.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5751B289249D5B9900664C2A /* web-authentication-make-credential-hid-pin-get-pin-token-fake-pin-invalid-error-retry.html */; };
+ 57537EE824BEA05F0048DBA5 /* web-authentication-get-assertion-nfc-pin-disconnect.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 57537EE724BEA0190048DBA5 /* web-authentication-get-assertion-nfc-pin-disconnect.html */; };
5758597F23A2527A00C74572 /* CtapPinTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5758597E23A2527A00C74572 /* CtapPinTest.cpp */; };
5758598423C3C3A400C74572 /* web-authentication-make-credential-hid-pin-get-retries-error.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5758598323C3C36200C74572 /* web-authentication-make-credential-hid-pin-get-retries-error.html */; };
57599E211F07191900A3FB8C /* IndexedDBStructuredCloneBackwardCompatibility.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57599E201F07191700A3FB8C /* IndexedDBStructuredCloneBackwardCompatibility.mm */; };
@@ -1602,6 +1603,7 @@
57EDFC60245A299C00959521 /* web-authentication-get-assertion-la-no-mock.html in Copy Resources */,
572CEF71240F874700C412A2 /* web-authentication-get-assertion-la.html in Copy Resources */,
579833922368FA37008E5547 /* web-authentication-get-assertion-nfc-multiple-tags.html in Copy Resources */,
+ 57537EE824BEA05F0048DBA5 /* web-authentication-get-assertion-nfc-pin-disconnect.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 */,
@@ -2076,6 +2078,7 @@
5742178D2400D26C002B303D /* web-authentication-make-credential-la.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-make-credential-la.html"; sourceTree = "<group>"; };
574F55D0204D471C002948C6 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
5751B289249D5B9900664C2A /* web-authentication-make-credential-hid-pin-get-pin-token-fake-pin-invalid-error-retry.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-make-credential-hid-pin-get-pin-token-fake-pin-invalid-error-retry.html"; sourceTree = "<group>"; };
+ 57537EE724BEA0190048DBA5 /* web-authentication-get-assertion-nfc-pin-disconnect.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-get-assertion-nfc-pin-disconnect.html"; sourceTree = "<group>"; };
5758597D23A2527A00C74572 /* CtapPinTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CtapPinTest.h; sourceTree = "<group>"; };
5758597E23A2527A00C74572 /* CtapPinTest.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CtapPinTest.cpp; sourceTree = "<group>"; };
5758598323C3C36200C74572 /* web-authentication-make-credential-hid-pin-get-retries-error.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-make-credential-hid-pin-get-retries-error.html"; sourceTree = "<group>"; };
@@ -3784,6 +3787,7 @@
57EDFC5F245A279900959521 /* web-authentication-get-assertion-la-no-mock.html */,
572CEF70240F86AE00C412A2 /* web-authentication-get-assertion-la.html */,
5798337B235EB65C008E5547 /* web-authentication-get-assertion-nfc-multiple-tags.html */,
+ 57537EE724BEA0190048DBA5 /* web-authentication-get-assertion-nfc-pin-disconnect.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 (264542 => 264543)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm 2020-07-17 22:57:05 UTC (rev 264542)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm 2020-07-17 22:58:51 UTC (rev 264543)
@@ -1158,6 +1158,25 @@
EXPECT_TRUE(webAuthenticationPanelUpdatePINInvalid);
}
+#if HAVE(NEAR_FIELD)
+TEST(WebAuthenticationPanel, NfcPinCachedDisconnect)
+{
+ reset();
+ RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-nfc-pin-disconnect" 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()];
+
+ webAuthenticationPanelPin = "1234";
+ [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
+ [webView waitForMessage:@"Succeeded!"];
+}
+#endif // HAVE(NEAR_FIELD)
+
TEST(WebAuthenticationPanel, MultipleAccountsNullDelegate)
{
reset();
Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion-nfc-pin-disconnect.html (0 => 264543)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion-nfc-pin-disconnect.html (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion-nfc-pin-disconnect.html 2020-07-17 22:58:51 UTC (rev 264543)
@@ -0,0 +1,34 @@
+<input type="text" id="input">
+<script>
+ const testNfcCtapVersionBase64 = "RklET18yXzCQAA==";
+ const testGetInfoResponseApduBase64 =
+ "AKYBgmZVMkZfVjJoRklET18yXzACgWtobWFjLXNlY3JldANQbUS6m/bsLkm5MAyP" +
+ "6SDLcwSkYnJr9WJ1cPVkcGxhdPRpY2xpZW50UGlu9QUZBLAGgQGQAA==";
+ const testCtapPinAuthInvalidErrorBase64 = "M5AA";
+ const testPinGetRetriesResponseBase64 = "AKEDCJAA";
+ const testPinGetKeyAgreementResponseBase64 = "AKEBpQECAzgYIAEhWCDodiWJbuTkbcAydm6Ah5YvNt+d/otWfzdjAVsZkKYOFCJYICfeYS1mQYvaGVBYHrxcjB2tcQyxTCL4yXBF9GEvsgyRkAA=";
+ const testPinGetPinTokenResponseBase64 = "AKECUBOk7rcOyRrqAB6TFvYeQfeQAA==";
+ const testAssertionMessageBase64 =
+ "AKQBomJpZFDmAkMt8gsltnzy15Zp9MbpZHR5cGVqcHVibGljLWtleQJYJeRTKdA6" +
+ "IGjRyvf3uwrpVOaw5iWXRfMvSCn3UPBQEfnCBQAAAGcDWEcwRQIgGGBmLZRfmUfs" +
+ "uB3H2yBZTnRhBacx68E+XWFgEQ0oayUCIQCrEBEg7t9//lVkK68mSFNGaBUpRhLI" +
+ "8YfFb+82Pzf6SAShYmlkT2JvYkBleGFtcGxlLmNvbZAA"
+ if (window.internals) {
+ internals.setMockWebAuthenticationConfiguration({ silentFailure: true, nfc: { payloadBase64: [testNfcCtapVersionBase64, testGetInfoResponseApduBase64, testCtapPinAuthInvalidErrorBase64, testPinGetRetriesResponseBase64, testPinGetKeyAgreementResponseBase64, "", testNfcCtapVersionBase64, testGetInfoResponseApduBase64, testCtapPinAuthInvalidErrorBase64, testPinGetRetriesResponseBase64, testPinGetKeyAgreementResponseBase64, testPinGetPinTokenResponseBase64, testAssertionMessageBase64] } });
+ internals.withUserGesture(() => { input.focus(); });
+ }
+
+ const options = {
+ publicKey: {
+ challenge: new Uint8Array(16),
+ }
+ };
+
+ navigator.credentials.get(options).then(credential => {
+ // console.log("Succeeded!");
+ window.webkit.messageHandlers.testHandler.postMessage("Succeeded!");
+ }, error => {
+ // console.log(error.message);
+ window.webkit.messageHandlers.testHandler.postMessage(error.message);
+ });
+</script>