| <!doctype html> |
| <title>Credential Manager: get() basics.</title> |
| <script src="../resources/testharness.js"></script> |
| <script src="../resources/testharnessreport.js"></script> |
| <script type="module"> |
| import {SmsStatus} from '/gen/third_party/blink/public/mojom/sms/webotp_service.mojom.m.js'; |
| import {AuthenticatorStatus} from '/gen/third_party/blink/public/mojom/webauthn/authenticator.mojom.m.js'; |
| import {MockAuthenticator, MockCredentialManager, MockWebOTPService} from './resources/mock-navigator-credentials.js'; |
| import {assertValidGetCredentialResponse, CABLE_AUTHENTICATION, CABLE_REGISTRATION, deepCopy, GET_CREDENTIAL_OPTIONS, RAW_ID} from './resources/test-inputs.js'; |
| |
| if (document.location.host != "subdomain.example.test:8443") { |
| document.location = "https://subdomain.example.test:8443/credentialmanager/credentialscontainer-get-basics.html"; |
| promise_test(_ => new Promise(_ => {}), "Stall tests on the wrong host."); |
| } |
| |
| const mockAuthenticator = new MockAuthenticator; |
| const mockCredentialManager = new MockCredentialManager; |
| const mockWebOTPService = new MockWebOTPService; |
| |
| add_completion_callback(() => { |
| mockCredentialManager.reset(); |
| mockWebOTPService.reset(); |
| }); |
| |
| promise_test(_ => { |
| return navigator.credentials.get().then(r => { |
| assert_equals(r, null); |
| }); |
| }, "navigator.credentials.get() with no argument."); |
| |
| promise_test(_ => { |
| return navigator.credentials.get({}).then(r => { |
| assert_equals(r, null); |
| }); |
| }, "navigator.credentials.get({})."); |
| |
| promise_test(_ => { |
| return navigator.credentials.get({ |
| federated: { |
| providers: [ 'https://example.com/' ] |
| } |
| }).then(r => { |
| assert_equals(r, null); |
| }); |
| }, "navigator.credentials.get() with a valid options including FederatedCredentialRequestOptions."); |
| |
| promise_test(_ => { |
| return navigator.credentials.get({ |
| password: true, |
| unmediated: true |
| }).then(r => { |
| assert_equals(r, null); |
| }); |
| }, "navigator.credentials.get() with a valid options including password and unmediated."); |
| |
| promise_test(_ => { |
| return navigator.credentials.get({ |
| federated: { |
| providers: [ 'https://example.com/' ] |
| }, |
| unmediated: true |
| }).then(r => { |
| assert_equals(r, null); |
| }); |
| }, "navigator.credentials.get() with a valid options including federated and unmediated."); |
| |
| promise_test(_ => { |
| return navigator.credentials.get({ |
| password: true, |
| federated: { |
| providers: [ 'https://example.com/' ] |
| }, |
| unmediated: true |
| }).then(r => { |
| assert_equals(r, null); |
| }); |
| }, "navigator.credentials.get() with a valid options including federated, password and unmediated."); |
| |
| promise_test(_ => { |
| return navigator.credentials.get({ |
| unmediated: true |
| }).then(r => { |
| assert_equals(r, null); |
| }); |
| }, "navigator.credentials.get() with a valid options including unmediated."); |
| |
| promise_test(_ => { |
| return navigator.credentials.get({ |
| mediation: "silent" |
| }).then(r => { |
| assert_equals(r, null); |
| }); |
| }, "navigator.credentials.get() with a valid options including mediation."); |
| |
| promise_test(_ => { |
| return navigator.credentials.get({ |
| notValid: 'yay!' |
| }).then(r => { |
| assert_equals(r, null); |
| }); |
| }, "navigator.credentials.get() with an options including an unknown attribute."); |
| |
| promise_test(_ => { |
| var id = "id"; |
| var password = "pencil"; |
| var name = "name"; |
| var icon = "http://example.com/"; |
| |
| mockCredentialManager.setResponse(id, password, name, icon); |
| |
| return navigator.credentials.get({ |
| password: true |
| }).then(r => { |
| assert_equals(r.id, id, "id"); |
| assert_equals(r.password, password, "password"); |
| assert_equals(r.name, name, "name"); |
| assert_equals(r.iconURL, icon, "icon"); |
| }); |
| }, "Verify that the mock returns the values we give it."); |
| |
| promise_test(_ => { |
| mockAuthenticator.setRawId(RAW_ID); |
| mockAuthenticator.setDefaultsForSuccessfulGetAssertion(); |
| return navigator.credentials.get({publicKey : GET_CREDENTIAL_OPTIONS}).then(r => { |
| assertValidGetCredentialResponse(r); |
| }); |
| }, "Verify that mockAuthenticator returns the values we give it."); |
| |
| promise_test(_ => { |
| var otp = "ABC123"; |
| mockWebOTPService.setOtp(otp); |
| mockWebOTPService.setStatus(SmsStatus.kSuccess); |
| return navigator.credentials.get({otp: {transport: ["sms"]}}).then(r => { |
| assert_equals(r.type, "otp", "type"); |
| assert_equals(r.id, "", "id"); |
| assert_equals(r.code, otp, "code"); |
| }); |
| }, "Verify that mockWebOTPService returns the values we give it."); |
| |
| promise_test(t => { |
| mockWebOTPService.setStatus(SmsStatus.kCancelled); |
| return promise_rejects_dom(t, "AbortError", |
| navigator.credentials.get({otp: {transport: ["sms"]}})); |
| }, "Verify that cancelled status returned by mock is properly handled."); |
| |
| promise_test(t => { |
| mockWebOTPService.setStatus(SmsStatus.kAborted); |
| return promise_rejects_dom(t, "AbortError", |
| navigator.credentials.get({otp: {transport: ["sms"]}})); |
| }, "Verify that abort status returned by mock is properly handled."); |
| |
| promise_test(t => { |
| mockWebOTPService.setStatus(SmsStatus.kUnhandledRequest); |
| return promise_rejects_dom(t, "InvalidStateError", |
| navigator.credentials.get({otp: {transport: ["sms"]}})); |
| }, "Verify that unhandled request status returned by mock is properly handled."); |
| |
| promise_test(t => { |
| mockWebOTPService.setStatus(SmsStatus.kTimeout); |
| return promise_rejects_dom(t, "InvalidStateError", |
| navigator.credentials.get({otp: {transport: ["sms"]}})); |
| }, "Verify that timeout status returned by mock is properly handled."); |
| |
| promise_test(t => { |
| mockWebOTPService.setStatus(SmsStatus.kBackendNotAvailable); |
| return promise_rejects_dom(t, "InvalidStateError", |
| navigator.credentials.get({otp: {transport: ["sms"]}})); |
| }, "Verify that backend unavailable status returned by mock is properly handled."); |
| |
| promise_test(t => { |
| mockWebOTPService.setStatus(SmsStatus.kTimeout); |
| return promise_rejects_dom(t, "NotSupportedError", |
| navigator.credentials.get({otp: {transport: []}})); |
| }, "Verify that invalid transport is properly handled"); |
| |
| promise_test(t => { |
| mockAuthenticator.setAuthenticatorStatus(AuthenticatorStatus.PENDING_REQUEST); |
| return promise_rejects_dom(t, "InvalidStateError", |
| navigator.credentials.get({ publicKey : GET_CREDENTIAL_OPTIONS})); |
| }, "Verify that pending request error returned by mock is properly handled."); |
| |
| promise_test(function (t) { |
| mockAuthenticator.setAuthenticatorStatus(AuthenticatorStatus.UNKNOWN_ERROR); |
| return promise_rejects_dom(t, "NotReadableError", |
| navigator.credentials.get({ publicKey : GET_CREDENTIAL_OPTIONS})); |
| }, "Verify that unknown error returned by mock is properly handled."); |
| |
| promise_test(t => { |
| mockAuthenticator.setAuthenticatorStatus( |
| AuthenticatorStatus.NOT_ALLOWED_ERROR); |
| return promise_rejects_dom(t, "NotAllowedError", |
| navigator.credentials.get({ publicKey : GET_CREDENTIAL_OPTIONS})); |
| }, "Verify that not allowed error returned by mock is properly handled."); |
| |
| promise_test(t => { |
| mockAuthenticator.setAuthenticatorStatus( |
| AuthenticatorStatus.USER_VERIFICATION_UNSUPPORTED); |
| return promise_rejects_dom(t, "NotSupportedError", |
| navigator.credentials.get({ publicKey : GET_CREDENTIAL_OPTIONS})); |
| }, "Verify that user verification unsupported error returned by mock is properly handled."); |
| |
| promise_test(t => { |
| mockAuthenticator.setAuthenticatorStatus( |
| AuthenticatorStatus.EMPTY_ALLOW_CREDENTIALS); |
| var customGetCredentialOptions = deepCopy(GET_CREDENTIAL_OPTIONS); |
| delete customGetCredentialOptions.allowCredentials; |
| return promise_rejects_dom(t, "NotSupportedError", |
| navigator.credentials.get({ publicKey : customGetCredentialOptions})); |
| }, "Verify that empty allow credentials error returned by mock is properly handled."); |
| |
| promise_test(t => { |
| mockAuthenticator.setAuthenticatorStatus(AuthenticatorStatus.ABORT_ERROR); |
| return promise_rejects_dom(t, "AbortError", |
| navigator.credentials.get({ publicKey : GET_CREDENTIAL_OPTIONS})); |
| }, "Verify that abort error returned by mock is properly handled."); |
| |
| promise_test(function(t) { |
| var customGetCredentialOptions = deepCopy(GET_CREDENTIAL_OPTIONS); |
| delete customGetCredentialOptions.challenge; |
| return promise_rejects_js(t, TypeError, |
| navigator.credentials.get({publicKey: customGetCredentialOptions})); |
| }, "navigator.credentials.get() with missing challenge"); |
| |
| promise_test(_ => { |
| mockAuthenticator.reset(); |
| mockAuthenticator.setDefaultsForSuccessfulGetAssertion(); |
| var customGetCredentialOptions = deepCopy(GET_CREDENTIAL_OPTIONS); |
| delete customGetCredentialOptions.rpId; |
| console.log(customGetCredentialOptions); |
| return navigator.credentials.get({publicKey: customGetCredentialOptions}).then(r => { |
| assertValidGetCredentialResponse(r); |
| }); |
| }, "navigator.credentials.get() with missing rpId"); |
| |
| promise_test(_ => { |
| mockAuthenticator.reset(); |
| mockAuthenticator.setDefaultsForSuccessfulGetAssertion(); |
| var customGetCredentialOptions = deepCopy(GET_CREDENTIAL_OPTIONS); |
| delete customGetCredentialOptions.userVerification; |
| return navigator.credentials.get({publicKey: customGetCredentialOptions}).then(r => { |
| assertValidGetCredentialResponse(r); |
| }); |
| }, "navigator.credentials.get() with missing user verification requirement"); |
| |
| promise_test(t => { |
| mockAuthenticator.reset(); |
| mockAuthenticator.setDefaultsForSuccessfulGetAssertion(); |
| var customGetCredentialOptions = deepCopy(GET_CREDENTIAL_OPTIONS); |
| customGetCredentialOptions.extensions = {cableRegistration: CABLE_REGISTRATION}; |
| return promise_rejects_dom(t, "NotSupportedError", |
| navigator.credentials.get({ publicKey : customGetCredentialOptions})); |
| }, "navigator.credentials.get() with cableRegistration extension not supported"); |
| |
| promise_test(_ => { |
| mockAuthenticator.reset(); |
| mockAuthenticator.setDefaultsForSuccessfulGetAssertion(); |
| var customGetCredentialOptions = deepCopy(GET_CREDENTIAL_OPTIONS); |
| customGetCredentialOptions.extensions = {cableAuthentication: [CABLE_AUTHENTICATION]}; |
| return navigator.credentials.get({publicKey: customGetCredentialOptions}).then(r => { |
| assertValidGetCredentialResponse(r); |
| }); |
| }, "navigator.credentials.get() with cableAuthentication extension"); |
| |
| promise_test(t => { |
| var authAbortController = new AbortController(); |
| var authAbortSignal = authAbortController.signal; |
| authAbortController.abort() |
| return promise_rejects_dom(t, "AbortError", |
| navigator.credentials.get({ publicKey : GET_CREDENTIAL_OPTIONS, signal : authAbortSignal})); |
| }, "navigator.credentials.get() with abort signal."); |
| |
| </script> |