Diff
Modified: trunk/LayoutTests/ChangeLog (236841 => 236842)
--- trunk/LayoutTests/ChangeLog 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/LayoutTests/ChangeLog 2018-10-04 19:32:14 UTC (rev 236842)
@@ -1,3 +1,27 @@
+2018-10-04 Jiewen Tan <[email protected]>
+
+ [WebAuthN] Move time out control from WebProcess to UIProcess
+ https://bugs.webkit.org/show_bug.cgi?id=189642
+ <rdar://problem/44476765>
+
+ Reviewed by Chris Dumez.
+
+ This patch also fixes some flaky behaviours regarding to the dirty ASN.1 decoder.
+
+ * http/wpt/webauthn/public-key-credential-create-failure-local-silent.https-expected.txt: Added.
+ * http/wpt/webauthn/public-key-credential-create-failure-local-silent.https.html: Copied from LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local.https.html.
+ * http/wpt/webauthn/public-key-credential-create-failure-local.https-expected.txt:
+ * http/wpt/webauthn/public-key-credential-create-failure-local.https.html:
+ * http/wpt/webauthn/public-key-credential-create-failure.https-expected.txt:
+ * http/wpt/webauthn/public-key-credential-create-failure.https.html:
+ * http/wpt/webauthn/public-key-credential-get-failure-local-silent.https-expected.txt: Added.
+ * http/wpt/webauthn/public-key-credential-get-failure-local-silent.https.html: Copied from LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local.https.html.
+ * http/wpt/webauthn/public-key-credential-get-failure-local.https-expected.txt:
+ * http/wpt/webauthn/public-key-credential-get-failure-local.https.html:
+ * http/wpt/webauthn/public-key-credential-get-failure.https-expected.txt:
+ * http/wpt/webauthn/public-key-credential-get-failure.https.html:
+ * http/wpt/webauthn/resources/util.js:
+
2018-10-04 Chris Dumez <[email protected]>
Regression(r236779): Crash when changing the input element type from inside an 'input' event listener
Added: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local-silent.https-expected.txt (0 => 236842)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local-silent.https-expected.txt (rev 0)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local-silent.https-expected.txt 2018-10-04 19:32:14 UTC (rev 236842)
@@ -0,0 +1,8 @@
+
+PASS PublicKeyCredential's [[create]] with silent failure in a mock local authenticator.
+PASS PublicKeyCredential's [[create]] with silent failure in a mock local authenticator. 2
+PASS PublicKeyCredential's [[create]] with silent failure in a mock local authenticator. 3
+PASS PublicKeyCredential's [[create]] with silent failure in a mock local authenticator. 4
+PASS PublicKeyCredential's [[create]] with silent failure in a mock local authenticator. 5
+PASS PublicKeyCredential's [[create]] with silent failure in a mock local authenticator. 6
+
Copied: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local-silent.https.html (from rev 236841, trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local.https.html) (0 => 236842)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local-silent.https.html (rev 0)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local-silent.https.html 2018-10-04 19:32:14 UTC (rev 236842)
@@ -0,0 +1,150 @@
+<!DOCTYPE html>
+<title>Web Authentication API: PublicKeyCredential's [[create]] silent failure cases with a mock local authenticator.</title>
+<script src=""
+<script src=""
+<script src=""
+<script>
+ // Default mock configuration. Tests need to override if they need different configuration.
+ if (window.testRunner)
+ testRunner.setWebAuthenticationMockConfiguration({ silentFailure: true, local: { acceptAuthentication: false, acceptAttestation: false } });
+
+ promise_test(t => {
+ const options = {
+ publicKey: {
+ rp: {
+ name: "example.com"
+ },
+ user: {
+ name: "John Appleseed",
+ id: Base64URL.parse(testUserhandleBase64),
+ displayName: "John",
+ },
+ challenge: asciiToUint8Array("123456"),
+ pubKeyCredParams: [{ type: "public-key", alg: -35 }, { type: "public-key", alg: -257 }], // ES384, RS256
+ timeout: 10
+ }
+ };
+ return promiseRejects(t, "NotAllowedError", navigator.credentials.create(options), "Operation timed out.");
+ }, "PublicKeyCredential's [[create]] with silent failure in a mock local authenticator.");
+
+ promise_test(t => {
+ const options = {
+ publicKey: {
+ rp: {
+ name: "example.com"
+ },
+ user: {
+ name: "John Appleseed",
+ id: Base64URL.parse(testUserhandleBase64),
+ displayName: "John",
+ },
+ challenge: asciiToUint8Array("123456"),
+ pubKeyCredParams: [{ type: "public-key", alg: -7 }],
+ excludeCredentials: [{ type: "public-key", id: Base64URL.parse(testCredentialIdBase64) }],
+ timeout: 10
+ }
+ };
+ if (window.testRunner)
+ testRunner.addTestKeyToKeychain(testES256PrivateKeyBase64, testRpId, testUserhandleBase64);
+ return promiseRejects(t, "NotAllowedError", navigator.credentials.create(options), "Operation timed out.").then(() => {
+ if (window.testRunner)
+ testRunner.cleanUpKeychain(testRpId);
+ });
+ }, "PublicKeyCredential's [[create]] with silent failure in a mock local authenticator. 2");
+
+ promise_test(t => {
+ const options = {
+ publicKey: {
+ rp: {
+ name: "example.com"
+ },
+ user: {
+ name: "John Appleseed",
+ id: Base64URL.parse(testUserhandleBase64),
+ displayName: "John",
+ },
+ challenge: asciiToUint8Array("123456"),
+ pubKeyCredParams: [{ type: "public-key", alg: -7 }],
+ excludeCredentials: [
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["usb"] },
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["nfc"] },
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["ble"] },
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["internal"] }
+ ],
+ timeout: 10
+ }
+ };
+ if (window.testRunner)
+ testRunner.addTestKeyToKeychain(testES256PrivateKeyBase64, testRpId, testUserhandleBase64);
+ return promiseRejects(t, "NotAllowedError", navigator.credentials.create(options), "Operation timed out.").then(() => {
+ if (window.testRunner)
+ testRunner.cleanUpKeychain(testRpId);
+ });
+ }, "PublicKeyCredential's [[create]] with silent failure in a mock local authenticator. 3");
+
+ promise_test(t => {
+ const options = {
+ publicKey: {
+ rp: {
+ name: "example.com"
+ },
+ user: {
+ name: "John Appleseed",
+ id: Base64URL.parse(testUserhandleBase64),
+ displayName: "John",
+ },
+ challenge: asciiToUint8Array("123456"),
+ pubKeyCredParams: [{ type: "public-key", alg: -7 }],
+ timeout: 10
+ }
+ };
+ return promiseRejects(t, "NotAllowedError", navigator.credentials.create(options), "Operation timed out.");
+ }, "PublicKeyCredential's [[create]] with silent failure in a mock local authenticator. 4");
+
+ promise_test(t => {
+ const options = {
+ publicKey: {
+ rp: {
+ name: "example.com"
+ },
+ user: {
+ name: "John Appleseed",
+ id: Base64URL.parse(testUserhandleBase64),
+ displayName: "John",
+ },
+ challenge: asciiToUint8Array("123456"),
+ pubKeyCredParams: [{ type: "public-key", alg: -7 }],
+ timeout: 10
+ }
+ };
+ if (window.testRunner)
+ testRunner.setWebAuthenticationMockConfiguration({ silentFailure: true, local: { acceptAuthentication: true, acceptAttestation: false } });
+ return promiseRejects(t, "NotAllowedError", navigator.credentials.create(options), "Operation timed out.");
+ }, "PublicKeyCredential's [[create]] with silent failure in a mock local authenticator. 5");
+
+ promise_test(t => {
+ const options = {
+ publicKey: {
+ rp: {
+ name: "example.com"
+ },
+ user: {
+ name: "John Appleseed",
+ id: Base64URL.parse(testUserhandleBase64),
+ displayName: "John",
+ },
+ challenge: asciiToUint8Array("123456"),
+ pubKeyCredParams: [{ type: "public-key", alg: -7 }],
+ timeout: 10
+ }
+ };
+ if (window.testRunner) {
+ testRunner.setWebAuthenticationMockConfiguration({ silentFailure: true, local: { acceptAuthentication: true, acceptAttestation: false } });
+ testRunner.addTestKeyToKeychain(testES256PrivateKeyBase64, testRpId, testUserhandleBase64);
+ }
+ return promiseRejects(t, "NotAllowedError", navigator.credentials.create(options), "Operation timed out.").then(() => {
+ if (window.testRunner)
+ assert_false(testRunner.keyExistsInKeychain(testRpId, testUserhandleBase64));
+ });
+ }, "PublicKeyCredential's [[create]] with silent failure in a mock local authenticator. 6");
+</script>
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local.https-expected.txt (236841 => 236842)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local.https-expected.txt 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local.https-expected.txt 2018-10-04 19:32:14 UTC (rev 236842)
@@ -5,4 +5,5 @@
PASS PublicKeyCredential's [[create]] without user consent in a mock local authenticator.
PASS PublicKeyCredential's [[create]] without attestation in a mock local authenticator.
PASS PublicKeyCredential's [[create]] deleting old credential in a mock local authenticator.
+PASS PublicKeyCredential's [[create]] with timeout in a mock local authenticator.
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local.https.html (236841 => 236842)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local.https.html 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local.https.html 2018-10-04 19:32:14 UTC (rev 236842)
@@ -141,4 +141,27 @@
assert_false(testRunner.keyExistsInKeychain(testRpId, testUserhandleBase64));
});
}, "PublicKeyCredential's [[create]] deleting old credential in a mock local authenticator.");
+
+ promise_test(function(t) {
+ const options = {
+ publicKey: {
+ rp: {
+ name: "example.com"
+ },
+ user: {
+ name: "John Appleseed",
+ id: asciiToUint8Array("123456"),
+ displayName: "John",
+ },
+ challenge: asciiToUint8Array("123456"),
+ pubKeyCredParams: [{ type: "public-key", alg: -7 }],
+ timeout: 10,
+ authenticatorSelection: { authenticatorAttachment: "cross-platform" }
+ }
+ };
+
+ if (window.testRunner)
+ testRunner.setWebAuthenticationMockConfiguration({ local: { acceptAuthentication: false, acceptAttestation: false } });
+ return promiseRejects(t, "NotAllowedError", navigator.credentials.create(options), "Operation timed out.");
+ }, "PublicKeyCredential's [[create]] with timeout in a mock local authenticator.");
</script>
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure.https-expected.txt (236841 => 236842)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure.https-expected.txt 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure.https-expected.txt 2018-10-04 19:32:14 UTC (rev 236842)
@@ -1,4 +1,5 @@
+PASS PublicKeyCredential's [[create]] with timeout
PASS PublicKeyCredential's [[create]] with a mismatched RP ID
PASS PublicKeyCredential's [[create]] with an empty pubKeyCredParams
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure.https.html (236841 => 236842)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure.https.html 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure.https.html 2018-10-04 19:32:14 UTC (rev 236842)
@@ -8,28 +8,27 @@
if (window.testRunner)
testRunner.setWebAuthenticationMockConfiguration({ });
- // FIXME(189642): Re-enable the following test.
- // promise_test(function(t) {
- // const options = {
- // publicKey: {
- // rp: {
- // name: "example.com"
- // },
- // user: {
- // name: "John Appleseed",
- // id: asciiToUint8Array("123456"),
- // displayName: "John",
- // },
- // challenge: asciiToUint8Array("123456"),
- // pubKeyCredParams: [{ type: "public-key", alg: -7 }],
- // timeout: 0,
- // }
- // };
- //
- // return promiseRejects(t, "NotAllowedError",
- // navigator.credentials.create(options), "Operation timed out.");
- // }, "PublicKeyCredential's [[create]] with timeout");
+ promise_test(function(t) {
+ const options = {
+ publicKey: {
+ rp: {
+ name: "example.com"
+ },
+ user: {
+ name: "John Appleseed",
+ id: asciiToUint8Array("123456"),
+ displayName: "John",
+ },
+ challenge: asciiToUint8Array("123456"),
+ pubKeyCredParams: [{ type: "public-key", alg: -7 }],
+ timeout: 10,
+ }
+ };
+ return promiseRejects(t, "NotAllowedError",
+ navigator.credentials.create(options), "Operation timed out.");
+ }, "PublicKeyCredential's [[create]] with timeout");
+
promise_test(function(t) {
const options = {
publicKey: {
Added: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local-silent.https-expected.txt (0 => 236842)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local-silent.https-expected.txt (rev 0)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local-silent.https-expected.txt 2018-10-04 19:32:14 UTC (rev 236842)
@@ -0,0 +1,5 @@
+
+PASS PublicKeyCredential's [[get]] with silent failure in a mock local authenticator.
+PASS PublicKeyCredential's [[get]] with silent failure in a mock local authenticator. 2
+PASS PublicKeyCredential's [[get]] with silent failure in a mock local authenticator. 3
+
Copied: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local-silent.https.html (from rev 236841, trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local.https.html) (0 => 236842)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local-silent.https.html (rev 0)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local-silent.https.html 2018-10-04 19:32:14 UTC (rev 236842)
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<title>Web Authentication API: PublicKeyCredential's [[get]] failure cases.</title>
+<script src=""
+<script src=""
+<script src=""
+<script>
+ // Default mock configuration. Tests need to override if they need different configuration.
+ if (window.testRunner)
+ testRunner.setWebAuthenticationMockConfiguration({ silentFailure: true, local: { acceptAuthentication: false, acceptAttestation: false } });
+
+ promise_test(t => {
+ const options = {
+ publicKey: {
+ challenge: asciiToUint8Array("123456"),
+ allowCredentials: [
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["usb"] },
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["nfc"] },
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["ble"] },
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["internal"] }
+ ],
+ timeout: 10
+ }
+ };
+
+ return promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "Operation timed out.");
+ }, "PublicKeyCredential's [[get]] with silent failure in a mock local authenticator.");
+
+ promise_test(t => {
+ const options = {
+ publicKey: {
+ challenge: asciiToUint8Array("123456"),
+ allowCredentials: [
+ { type: "public-key", id: Base64URL.parse(testUserhandleBase64) }
+ ],
+ timeout: 10
+ }
+ };
+
+ if (window.testRunner)
+ testRunner.addTestKeyToKeychain(testES256PrivateKeyBase64, testRpId, testUserhandleBase64);
+ return promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "Operation timed out.").then(() => {
+ if (window.testRunner)
+ testRunner.cleanUpKeychain(testRpId);
+ });
+ }, "PublicKeyCredential's [[get]] with silent failure in a mock local authenticator. 2");
+
+ promise_test(t => {
+ const options = {
+ publicKey: {
+ challenge: asciiToUint8Array("123456"),
+ timeout: 10
+ }
+ };
+
+ if (window.testRunner)
+ testRunner.addTestKeyToKeychain(testES256PrivateKeyBase64, testRpId, testUserhandleBase64);
+ return promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "Operation timed out.").then(() => {
+ if (window.testRunner)
+ testRunner.cleanUpKeychain(testRpId);
+ });
+ }, "PublicKeyCredential's [[get]] with silent failure in a mock local authenticator. 3");
+</script>
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local.https-expected.txt (236841 => 236842)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local.https-expected.txt 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local.https-expected.txt 2018-10-04 19:32:14 UTC (rev 236842)
@@ -2,4 +2,5 @@
PASS PublicKeyCredential's [[get]] with no matched credentials in a mock local authenticator.
PASS PublicKeyCredential's [[get]] with no matched credentials in a mock local authenticator. 2nd
PASS PublicKeyCredential's [[get]] without user consent in a mock local authenticator.
+PASS PublicKeyCredential's [[get]] with timeout in a mock local authenticator.
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local.https.html (236841 => 236842)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local.https.html 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local.https.html 2018-10-04 19:32:14 UTC (rev 236842)
@@ -56,4 +56,20 @@
testRunner.cleanUpKeychain(testRpId);
});
}, "PublicKeyCredential's [[get]] without user consent in a mock local authenticator.");
+
+ promise_test(t => {
+ const options = {
+ publicKey: {
+ challenge: asciiToUint8Array("123456"),
+ allowCredentials: [
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["usb"] },
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["nfc"] },
+ { type: "public-key", id: Base64URL.parse(testCredentialIdBase64), transports: ["ble"] }
+ ],
+ timeout: 10
+ }
+ };
+
+ return promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "Operation timed out.");
+ }, "PublicKeyCredential's [[get]] with timeout in a mock local authenticator.");
</script>
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure.https-expected.txt (236841 => 236842)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure.https-expected.txt 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure.https-expected.txt 2018-10-04 19:32:14 UTC (rev 236842)
@@ -1,3 +1,4 @@
+PASS PublicKeyCredential's [[get]] with timeout
PASS PublicKeyCredential's [[get]] with a mismatched RP ID
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure.https.html (236841 => 236842)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure.https.html 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure.https.html 2018-10-04 19:32:14 UTC (rev 236842)
@@ -8,26 +8,26 @@
if (window.testRunner)
testRunner.setWebAuthenticationMockConfiguration({ });
- // FIXME(189642): Re-enable the following test.
- // promise_test(function(t) {
- // const options = {
- // publicKey: {
- // challenge: asciiToUint8Array("123456"),
- // timeout: 0,
- // }
- // };
- //
- // return promiseRejects(t, "NotAllowedError",
- // navigator.credentials.get(options), "Operation timed out.");
- // }, "PublicKeyCredential's [[get]] with timeout");
+ promise_test(t => {
+ const options = {
+ publicKey: {
+ challenge: asciiToUint8Array("123456"),
+ timeout: 10
+ }
+ };
- promise_test(function(t) {
+ return promiseRejects(t, "NotAllowedError",
+ navigator.credentials.get(options), "Operation timed out.");
+ }, "PublicKeyCredential's [[get]] with timeout");
+
+ promise_test(t => {
const options = {
publicKey: {
rpId: "example.com",
- challenge: asciiToUint8Array("123456"),
+ challenge: asciiToUint8Array("123456")
}
};
+
return promiseRejects(t, "SecurityError",
navigator.credentials.get(options), "The origin of the document is not a registrable domain suffix of the provided RP ID.");
}, "PublicKeyCredential's [[get]] with a mismatched RP ID");
Modified: trunk/LayoutTests/http/wpt/webauthn/resources/util.js (236841 => 236842)
--- trunk/LayoutTests/http/wpt/webauthn/resources/util.js 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/LayoutTests/http/wpt/webauthn/resources/util.js 2018-10-04 19:32:14 UTC (rev 236842)
@@ -172,10 +172,19 @@
{
const signature = new Uint8Array(asn1signature);
let tmp = new Uint8Array(64);
+
const rStart = signature[3] - 32;
- tmp.set(new Uint8Array(signature.slice(4 + rStart, 36 + rStart)), 0);
+ if (rStart >= 0)
+ tmp.set(new Uint8Array(signature.slice(4 + rStart, 36 + rStart)), 0);
+ else
+ tmp.set(new Uint8Array(signature.slice(4, 36 + rStart)), -rStart);
+
const sStart = signature[37 + rStart] - 32;
- tmp.set(new Uint8Array(signature.slice(38 + rStart + sStart)), 32);
+ if (sStart >= 0)
+ tmp.set(new Uint8Array(signature.slice(38 + rStart + sStart)), 32);
+ else
+ tmp.set(new Uint8Array(signature.slice(38 + rStart)), 32 - sStart);
+
return tmp.buffer;
}
Modified: trunk/Source/WebCore/ChangeLog (236841 => 236842)
--- trunk/Source/WebCore/ChangeLog 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/Source/WebCore/ChangeLog 2018-10-04 19:32:14 UTC (rev 236842)
@@ -1,3 +1,29 @@
+2018-10-04 Jiewen Tan <[email protected]>
+
+ [WebAuthN] Move time out control from WebProcess to UIProcess
+ https://bugs.webkit.org/show_bug.cgi?id=189642
+ <rdar://problem/44476765>
+
+ Reviewed by Chris Dumez.
+
+ Since now the control unit of WebAuthN has been moved to UI Process, i.e. AuthenticatorManager,
+ the time out timer should move to UI Process as well.
+
+ Tests: http/wpt/webauthn/public-key-credential-create-failure-local-silent.https.html
+ http/wpt/webauthn/public-key-credential-get-failure-local-silent.https.html
+
+ * Modules/webauthn/AuthenticatorCoordinator.cpp:
+ (WebCore::AuthenticatorCoordinator::create const):
+ (WebCore::AuthenticatorCoordinator::discoverFromExternalSource const):
+ (WebCore::AuthenticatorCoordinatorInternal::initTimeoutTimer): Deleted.
+ (WebCore::AuthenticatorCoordinatorInternal::didTimeoutTimerFire): Deleted.
+ * Modules/webauthn/PublicKeyCredentialCreationOptions.h:
+ (WebCore::PublicKeyCredentialCreationOptions::encode const):
+ (WebCore::PublicKeyCredentialCreationOptions::decode):
+ * Modules/webauthn/PublicKeyCredentialRequestOptions.h:
+ (WebCore::PublicKeyCredentialRequestOptions::encode const):
+ (WebCore::PublicKeyCredentialRequestOptions::decode):
+
2018-10-04 Chris Dumez <[email protected]>
Regression(r236779): Crash when changing the input element type from inside an 'input' event listener
Modified: trunk/Source/WebCore/Modules/webauthn/AuthenticatorCoordinator.cpp (236841 => 236842)
--- trunk/Source/WebCore/Modules/webauthn/AuthenticatorCoordinator.cpp 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/Source/WebCore/Modules/webauthn/AuthenticatorCoordinator.cpp 2018-10-04 19:32:14 UTC (rev 236842)
@@ -38,7 +38,6 @@
#include "PublicKeyCredentialData.h"
#include "PublicKeyCredentialRequestOptions.h"
#include "SecurityOrigin.h"
-#include "Timer.h"
#include <pal/crypto/CryptoDigest.h>
#include <wtf/JSONValues.h>
#include <wtf/NeverDestroyed.h>
@@ -82,29 +81,6 @@
return crypto->computeHash();
}
-// FIXME(181947): We should probably trim timeOutInMs to some max allowable number.
-static std::unique_ptr<Timer> initTimeoutTimer(std::optional<unsigned long> timeOutInMs, const CredentialPromise& promise)
-{
- if (!timeOutInMs)
- return nullptr;
-
- auto timer = std::make_unique<Timer>([promise = promise] () mutable {
- promise.reject(Exception { NotAllowedError, "Operation timed out."_s });
- });
- timer->startOneShot(Seconds::fromMilliseconds(*timeOutInMs));
- return timer;
-}
-
-static bool didTimeoutTimerFire(Timer* timer)
-{
- if (!timer)
- return false;
- if (!timer->isActive())
- return true;
- timer->stop();
- return false;
-}
-
} // namespace AuthenticatorCoordinatorInternal
AuthenticatorCoordinator::AuthenticatorCoordinator(std::unique_ptr<AuthenticatorCoordinatorClient>&& client)
@@ -130,9 +106,6 @@
return;
}
- // Step 4 & 17.
- std::unique_ptr<Timer> timeoutTimer = initTimeoutTimer(options.timeout, promise);
-
// Step 5-7.
// FIXME(181950): We lack fundamental support from SecurityOrigin to determine if a host is a valid domain or not.
// Step 6 is therefore skipped. Also, we lack the support to determine whether a domain is a registrable
@@ -156,7 +129,7 @@
auto clientDataJson = produceClientDataJson(ClientDataType::Create, options.challenge, callerOrigin);
auto clientDataJsonHash = produceClientDataJsonHash(clientDataJson);
- // Step 18-21.
+ // Step 4, 17-21.
// Only platform attachments will be supported at this stage. Assuming one authenticator per device.
// Also, resident keys, user verifications and direct attestation are enforced at this tage.
// For better performance, transports of options.excludeCredentials are checked in LocalAuthenticator.
@@ -165,9 +138,7 @@
return;
}
- auto completionHandler = [clientDataJson = WTFMove(clientDataJson), promise = WTFMove(promise), timeoutTimer = WTFMove(timeoutTimer), abortSignal = WTFMove(abortSignal)] (const WebCore::PublicKeyCredentialData& data, const WebCore::ExceptionData& exception) mutable {
- if (didTimeoutTimerFire(timeoutTimer.get()))
- return;
+ auto completionHandler = [clientDataJson = WTFMove(clientDataJson), promise = WTFMove(promise), abortSignal = WTFMove(abortSignal)] (const WebCore::PublicKeyCredentialData& data, const WebCore::ExceptionData& exception) mutable {
if (abortSignal && abortSignal->aborted()) {
promise.reject(Exception { AbortError, "Aborted by AbortSignal."_s });
return;
@@ -198,9 +169,6 @@
return;
}
- // Step 4 & 16.
- std::unique_ptr<Timer> timeoutTimer = initTimeoutTimer(options.timeout, promise);
-
// Step 5-7.
// FIXME(181950): We lack fundamental support from SecurityOrigin to determine if a host is a valid domain or not.
// Step 6 is therefore skipped. Also, we lack the support to determine whether a domain is a registrable
@@ -216,7 +184,7 @@
auto clientDataJson = produceClientDataJson(ClientDataType::Get, options.challenge, callerOrigin);
auto clientDataJsonHash = produceClientDataJsonHash(clientDataJson);
- // Step 14-15, 17-19.
+ // Step 4, 14-19.
// Only platform attachments will be supported at this stage. Assuming one authenticator per device.
// Also, resident keys, user verifications and direct attestation are enforced at this tage.
// For better performance, filtering of options.allowCredentials is done in LocalAuthenticator.
@@ -225,9 +193,7 @@
return;
}
- auto completionHandler = [clientDataJson = WTFMove(clientDataJson), promise = WTFMove(promise), timeoutTimer = WTFMove(timeoutTimer), abortSignal = WTFMove(abortSignal)] (const WebCore::PublicKeyCredentialData& data, const WebCore::ExceptionData& exception) mutable {
- if (didTimeoutTimerFire(timeoutTimer.get()))
- return;
+ auto completionHandler = [clientDataJson = WTFMove(clientDataJson), promise = WTFMove(promise), abortSignal = WTFMove(abortSignal)] (const WebCore::PublicKeyCredentialData& data, const WebCore::ExceptionData& exception) mutable {
if (abortSignal && abortSignal->aborted()) {
promise.reject(Exception { AbortError, "Aborted by AbortSignal."_s });
return;
Modified: trunk/Source/WebCore/Modules/webauthn/PublicKeyCredentialCreationOptions.h (236841 => 236842)
--- trunk/Source/WebCore/Modules/webauthn/PublicKeyCredentialCreationOptions.h 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/Source/WebCore/Modules/webauthn/PublicKeyCredentialCreationOptions.h 2018-10-04 19:32:14 UTC (rev 236842)
@@ -78,7 +78,7 @@
BufferSource challenge;
Vector<Parameters> pubKeyCredParams;
- std::optional<unsigned long> timeout;
+ std::optional<unsigned> timeout;
Vector<PublicKeyCredentialDescriptor> excludeCredentials;
std::optional<AuthenticatorSelectionCriteria> authenticatorSelection;
@@ -125,7 +125,7 @@
encoder << rp.id << rp.name << rp.icon;
encoder << static_cast<uint64_t>(user.id.length());
encoder.encodeFixedLengthData(user.id.data(), user.id.length(), 1);
- encoder << user.displayName << user.name << user.icon << pubKeyCredParams << excludeCredentials << authenticatorSelection;
+ encoder << user.displayName << user.name << user.icon << pubKeyCredParams << timeout << excludeCredentials << authenticatorSelection;
}
template<class Decoder>
@@ -148,6 +148,13 @@
return std::nullopt;
if (!decoder.decode(result.pubKeyCredParams))
return std::nullopt;
+
+ std::optional<std::optional<unsigned>> timeout;
+ decoder >> timeout;
+ if (!timeout)
+ return std::nullopt;
+ result.timeout = WTFMove(*timeout);
+
if (!decoder.decode(result.excludeCredentials))
return std::nullopt;
@@ -155,7 +162,7 @@
decoder >> authenticatorSelection;
if (!authenticatorSelection)
return std::nullopt;
- result.authenticatorSelection = WTFMove(authenticatorSelection.value());
+ result.authenticatorSelection = WTFMove(*authenticatorSelection);
return result;
}
Modified: trunk/Source/WebCore/Modules/webauthn/PublicKeyCredentialRequestOptions.h (236841 => 236842)
--- trunk/Source/WebCore/Modules/webauthn/PublicKeyCredentialRequestOptions.h 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/Source/WebCore/Modules/webauthn/PublicKeyCredentialRequestOptions.h 2018-10-04 19:32:14 UTC (rev 236842)
@@ -35,7 +35,7 @@
struct PublicKeyCredentialRequestOptions {
BufferSource challenge;
- std::optional<unsigned long> timeout;
+ std::optional<unsigned> timeout;
mutable String rpId;
Vector<PublicKeyCredentialDescriptor> allowCredentials;
@@ -47,7 +47,7 @@
template<class Encoder>
void PublicKeyCredentialRequestOptions::encode(Encoder& encoder) const
{
- encoder << rpId << allowCredentials;
+ encoder << timeout << rpId << allowCredentials;
}
template<class Decoder>
@@ -54,6 +54,13 @@
std::optional<PublicKeyCredentialRequestOptions> PublicKeyCredentialRequestOptions::decode(Decoder& decoder)
{
PublicKeyCredentialRequestOptions result;
+
+ std::optional<std::optional<unsigned>> timeout;
+ decoder >> timeout;
+ if (!timeout)
+ return std::nullopt;
+ result.timeout = WTFMove(*timeout);
+
if (!decoder.decode(result.rpId))
return std::nullopt;
if (!decoder.decode(result.allowCredentials))
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (236841 => 236842)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2018-10-04 19:32:14 UTC (rev 236842)
@@ -18819,13 +18819,6 @@
path = cbor;
sourceTree = "<group>";
};
- 574F55DD204F3744002948C6 /* cocoa */ = {
- isa = PBXGroup;
- children = (
- );
- path = cocoa;
- sourceTree = "<group>";
- };
57C7A6881E56946D00C67D71 /* credentialmanagement */ = {
isa = PBXGroup;
children = (
@@ -18867,7 +18860,6 @@
isa = PBXGroup;
children = (
57303BB32006C6ED00355965 /* cbor */,
- 574F55DD204F3744002948C6 /* cocoa */,
57303C272009B2FC00355965 /* AuthenticatorAssertionResponse.h */,
57303C292009B2FC00355965 /* AuthenticatorAssertionResponse.idl */,
57303C1B2009A98600355965 /* AuthenticatorAttestationResponse.h */,
Modified: trunk/Source/WebKit/ChangeLog (236841 => 236842)
--- trunk/Source/WebKit/ChangeLog 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/Source/WebKit/ChangeLog 2018-10-04 19:32:14 UTC (rev 236842)
@@ -1,3 +1,29 @@
+2018-10-04 Jiewen Tan <[email protected]>
+
+ [WebAuthN] Move time out control from WebProcess to UIProcess
+ https://bugs.webkit.org/show_bug.cgi?id=189642
+ <rdar://problem/44476765>
+
+ Reviewed by Chris Dumez.
+
+ Besides adding a time out timer in the AuthenticatorManager, this patch also adds a new
+ option in MockWebAuthenticationConfiguration to turn on silent failure which is the
+ default policy of treating authenticators' error as suggested by spec.
+
+ * UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
+ (WKWebsiteDataStoreSetWebAuthenticationMockConfiguration):
+ * UIProcess/WebAuthentication/AuthenticatorManager.cpp:
+ (WebKit::AuthenticatorManagerInternal::collectTransports):
+ (WebKit::AuthenticatorManager::makeCredential):
+ (WebKit::AuthenticatorManager::getAssertion):
+ (WebKit::AuthenticatorManager::respondReceived):
+ (WebKit::AuthenticatorManager::initTimeOutTimer):
+ * UIProcess/WebAuthentication/AuthenticatorManager.h:
+ (WebKit::AuthenticatorManager::requestTimeOutTimer):
+ * UIProcess/WebAuthentication/Mock/MockAuthenticatorManager.cpp:
+ (WebKit::MockAuthenticatorManager::respondReceivedInternal):
+ * UIProcess/WebAuthentication/Mock/MockWebAuthenticationConfiguration.h:
+
2018-10-04 Yuhan Wu <[email protected]>
runtime flag and IDL for MediaRecorder
Modified: trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp (236841 => 236842)
--- trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp 2018-10-04 19:32:14 UTC (rev 236842)
@@ -577,6 +577,10 @@
#if ENABLE(WEB_AUTHN)
MockWebAuthenticationConfiguration configuration;
+ auto silentFailureRef = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(configurationRef, adoptWK(WKStringCreateWithUTF8CString("SilentFailure")).get()));
+ if (silentFailureRef)
+ configuration.silentFailure = WKBooleanGetValue(silentFailureRef);
+
auto localRef = static_cast<WKDictionaryRef>(WKDictionaryGetItemForKey(configurationRef, adoptWK(WKStringCreateWithUTF8CString("Local")).get()));
if (localRef) {
MockWebAuthenticationConfiguration::Local local;
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp (236841 => 236842)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp 2018-10-04 19:32:14 UTC (rev 236842)
@@ -38,6 +38,8 @@
namespace AuthenticatorManagerInternal {
const size_t maxTransportNumber = 1;
+// Suggested by WebAuthN spec as of 7 August 2018.
+const unsigned maxTimeOutValue = 120000;
// FIXME(188623, 188624, 188625): Support USB, NFC and BLE authenticators.
static AuthenticatorManager::TransportSet collectTransports(const std::optional<PublicKeyCredentialCreationOptions::AuthenticatorSelectionCriteria>& authenticatorSelection)
@@ -49,12 +51,12 @@
return result;
}
- if (authenticatorSelection.value().authenticatorAttachment == PublicKeyCredentialCreationOptions::AuthenticatorAttachment::Platform) {
+ if (authenticatorSelection->authenticatorAttachment == PublicKeyCredentialCreationOptions::AuthenticatorAttachment::Platform) {
auto addResult = result.add(AuthenticatorTransport::Internal);
ASSERT_UNUSED(addResult, addResult.isNewEntry);
return result;
}
- if (authenticatorSelection.value().authenticatorAttachment == PublicKeyCredentialCreationOptions::AuthenticatorAttachment::CrossPlatform)
+ if (authenticatorSelection->authenticatorAttachment == PublicKeyCredentialCreationOptions::AuthenticatorAttachment::CrossPlatform)
return result;
ASSERT_NOT_REACHED();
@@ -104,6 +106,7 @@
// 1. Save request for async operations.
m_pendingRequestData = { hash, true, options, { } };
m_pendingCompletionHandler = WTFMove(callback);
+ initTimeOutTimer(options.timeout);
// 2. Get available transports and start discovering authenticators on them.
startDiscovery(collectTransports(options.authenticatorSelection));
@@ -121,6 +124,7 @@
// 1. Save request for async operations.
m_pendingRequestData = { hash, false, { }, options };
m_pendingCompletionHandler = WTFMove(callback);
+ initTimeOutTimer(options.timeout);
// 2. Get available transports and start discovering authenticators on them.
ASSERT(m_services.isEmpty());
@@ -147,11 +151,15 @@
void AuthenticatorManager::respondReceived(Respond&& respond)
{
ASSERT(RunLoop::isMain());
+ ASSERT(m_requestTimeOutTimer);
+ if (!m_requestTimeOutTimer->isActive())
+ return;
+
ASSERT(m_pendingCompletionHandler);
- // FIXME(189642)
if (WTF::holds_alternative<PublicKeyCredentialData>(respond)) {
m_pendingCompletionHandler(WTFMove(respond));
clearState();
+ m_requestTimeOutTimer->stop();
return;
}
respondReceivedInternal(WTFMove(respond));
@@ -178,6 +186,19 @@
}
}
+void AuthenticatorManager::initTimeOutTimer(const std::optional<unsigned>& timeOutInMs)
+{
+ using namespace AuthenticatorManagerInternal;
+
+ unsigned timeOutInMsValue = std::min(maxTimeOutValue, timeOutInMs.value_or(maxTimeOutValue));
+
+ m_requestTimeOutTimer = std::make_unique<Timer>([context = this]() mutable {
+ context->m_pendingCompletionHandler((ExceptionData { NotAllowedError, "Operation timed out."_s }));
+ context->clearState();
+ });
+ m_requestTimeOutTimer->startOneShot(Seconds::fromMilliseconds(timeOutInMsValue));
+}
+
} // namespace WebKit
#endif // ENABLE(WEB_AUTHN)
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h (236841 => 236842)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h 2018-10-04 19:32:14 UTC (rev 236842)
@@ -32,6 +32,7 @@
#include "WebAuthenticationRequestData.h"
#include <WebCore/ExceptionData.h>
#include <WebCore/PublicKeyCredentialData.h>
+#include <WebCore/Timer.h>
#include <wtf/CompletionHandler.h>
#include <wtf/HashSet.h>
#include <wtf/Noncopyable.h>
@@ -57,6 +58,7 @@
protected:
Callback& pendingCompletionHandler() { return m_pendingCompletionHandler; }
+ WebCore::Timer* requestTimeOutTimer() { return m_requestTimeOutTimer.get(); }
void clearState();
private:
@@ -72,10 +74,12 @@
virtual void respondReceivedInternal(Respond&&);
void startDiscovery(const TransportSet&);
+ void initTimeOutTimer(const std::optional<unsigned>& timeOutInMs);
// Request: We only allow one request per time.
WebAuthenticationRequestData m_pendingRequestData;
Callback m_pendingCompletionHandler;
+ std::unique_ptr<WebCore::Timer> m_requestTimeOutTimer;
Vector<UniqueRef<AuthenticatorTransportService>> m_services;
HashSet<Ref<Authenticator>> m_authenticators;
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockAuthenticatorManager.cpp (236841 => 236842)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockAuthenticatorManager.cpp 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockAuthenticatorManager.cpp 2018-10-04 19:32:14 UTC (rev 236842)
@@ -42,8 +42,12 @@
void MockAuthenticatorManager::respondReceivedInternal(Respond&& respond)
{
+ if (m_testConfiguration.silentFailure)
+ return;
+
pendingCompletionHandler()(WTFMove(respond));
clearState();
+ requestTimeOutTimer()->stop();
}
} // namespace WebKit
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockWebAuthenticationConfiguration.h (236841 => 236842)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockWebAuthenticationConfiguration.h 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockWebAuthenticationConfiguration.h 2018-10-04 19:32:14 UTC (rev 236842)
@@ -38,6 +38,7 @@
String intermediateCACertificateBase64;
};
+ bool silentFailure { false };
std::optional<Local> local;
};
Modified: trunk/Tools/ChangeLog (236841 => 236842)
--- trunk/Tools/ChangeLog 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/Tools/ChangeLog 2018-10-04 19:32:14 UTC (rev 236842)
@@ -1,3 +1,14 @@
+2018-10-04 Jiewen Tan <[email protected]>
+
+ [WebAuthN] Move time out control from WebProcess to UIProcess
+ https://bugs.webkit.org/show_bug.cgi?id=189642
+ <rdar://problem/44476765>
+
+ Reviewed by Chris Dumez.
+
+ * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+ (WTR::TestRunner::setWebAuthenticationMockConfiguration):
+
2018-10-04 YUHAN WU <[email protected]>
Runtime flag and IDL for MediaRecorder
Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp (236841 => 236842)
--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp 2018-10-04 19:31:15 UTC (rev 236841)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp 2018-10-04 19:32:14 UTC (rev 236842)
@@ -2355,9 +2355,19 @@
Vector<WKRetainPtr<WKStringRef>> configurationKeys;
Vector<WKRetainPtr<WKTypeRef>> configurationValues;
+ JSRetainPtr<JSStringRef> silentFailurePropertyName(Adopt, JSStringCreateWithUTF8CString("silentFailure"));
+ JSValueRef silentFailureValue = JSObjectGetProperty(context, configuration, silentFailurePropertyName.get(), 0);
+ if (!JSValueIsUndefined(context, silentFailureValue)) {
+ if (!JSValueIsBoolean(context, silentFailureValue))
+ return;
+ bool silentFailure = JSValueToBoolean(context, silentFailureValue);
+ configurationKeys.append({ AdoptWK, WKStringCreateWithUTF8CString("SilentFailure") });
+ configurationValues.append(adoptWK(WKBooleanCreate(silentFailure)).get());
+ }
+
JSRetainPtr<JSStringRef> localPropertyName(Adopt, JSStringCreateWithUTF8CString("local"));
JSValueRef localValue = JSObjectGetProperty(context, configuration, localPropertyName.get(), 0);
- if (!JSValueIsNull(context, localValue)) {
+ if (!JSValueIsUndefined(context, localValue) && !JSValueIsNull(context, localValue)) {
if (!JSValueIsObject(context, localValue))
return;
JSObjectRef local = JSValueToObject(context, localValue, 0);