From 15cde34bad230eb1bef3426cb8b4064a6a755e30 Mon Sep 17 00:00:00 2001 From: Sandor Molnar Date: Thu, 19 Oct 2023 03:53:41 +0300 Subject: [PATCH] Backed out 3 changesets (bug 1854908, bug 1854620, bug 1854618) for causing bc failures at browser/base/content/test/static/browser_all_files_referenced.js CLOSED TREE Backed out changeset e059b0995a2a (bug 1854908) Backed out changeset 689737898f5b (bug 1854620) Backed out changeset 0464e2c6681d (bug 1854618) --- docshell/base/nsAboutRedirector.cpp | 4 - docshell/build/components.conf | 2 - dom/webauthn/AndroidWebAuthnService.cpp | 8 - dom/webauthn/WebAuthnService.cpp | 16 - .../authrs_bridge/src/about_webauthn_controller.rs | 155 ------- dom/webauthn/authrs_bridge/src/lib.rs | 244 ++-------- dom/webauthn/nsIWebAuthnService.idl | 4 - .../aboutwebauthn/content/aboutWebauthn.css | 79 ---- .../aboutwebauthn/content/aboutWebauthn.html | 180 -------- .../aboutwebauthn/content/aboutWebauthn.js | 493 --------------------- toolkit/components/aboutwebauthn/jar.mn | 8 - toolkit/components/aboutwebauthn/moz.build | 13 - .../aboutwebauthn/tests/browser/browser.ini | 13 - .../browser/browser_aboutwebauthn_credentials.js | 346 --------------- .../tests/browser/browser_aboutwebauthn_info.js | 218 --------- .../browser/browser_aboutwebauthn_no_token.js | 49 -- .../tests/browser/browser_aboutwebauthn_pin.js | 205 --------- .../components/aboutwebauthn/tests/browser/head.js | 43 -- toolkit/components/moz.build | 1 - .../locales/en-US/toolkit/about/aboutWebauthn.ftl | 127 ------ 20 files changed, 34 insertions(+), 2174 deletions(-) delete mode 100644 dom/webauthn/authrs_bridge/src/about_webauthn_controller.rs delete mode 100644 toolkit/components/aboutwebauthn/content/aboutWebauthn.css delete mode 100644 toolkit/components/aboutwebauthn/content/aboutWebauthn.html delete mode 100644 toolkit/components/aboutwebauthn/content/aboutWebauthn.js delete mode 100644 toolkit/components/aboutwebauthn/jar.mn delete mode 100644 toolkit/components/aboutwebauthn/moz.build delete mode 100644 toolkit/components/aboutwebauthn/tests/browser/browser.ini delete mode 100644 toolkit/components/aboutwebauthn/tests/browser/browser_aboutwebauthn_credentials.js delete mode 100644 toolkit/components/aboutwebauthn/tests/browser/browser_aboutwebauthn_info.js delete mode 100644 toolkit/components/aboutwebauthn/tests/browser/browser_aboutwebauthn_no_token.js delete mode 100644 toolkit/components/aboutwebauthn/tests/browser/browser_aboutwebauthn_pin.js delete mode 100644 toolkit/components/aboutwebauthn/tests/browser/head.js delete mode 100644 toolkit/locales/en-US/toolkit/about/aboutWebauthn.ftl diff --git a/docshell/base/nsAboutRedirector.cpp b/docshell/base/nsAboutRedirector.cpp index 8a08e8031983..64891bea546e 100644 --- a/docshell/base/nsAboutRedirector.cpp +++ b/docshell/base/nsAboutRedirector.cpp @@ -131,10 +131,6 @@ static const RedirEntry kRedirMap[] = { nsIAboutModule::IS_SECURE_CHROME_UI}, {"mozilla", "chrome://global/content/mozilla.html", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT}, -#if !defined(ANDROID) && !defined(XP_WIN) - {"webauthn", "chrome://global/content/aboutWebauthn.html", - nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::IS_SECURE_CHROME_UI}, -#endif {"neterror", "chrome://global/content/aboutNetError.xhtml", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | nsIAboutModule::URI_CAN_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT | diff --git a/docshell/build/components.conf b/docshell/build/components.conf index 6053d4d6ddbc..b3071cc549d2 100644 --- a/docshell/build/components.conf +++ b/docshell/build/components.conf @@ -45,8 +45,6 @@ if buildconfig.substs['MOZ_WIDGET_TOOLKIT'] == 'windows': about_pages.append('windows-messages') if not defined('MOZ_GLEAN_ANDROID'): about_pages.append('glean') -if buildconfig.substs['MOZ_WIDGET_TOOLKIT'] != 'android' and buildconfig.substs['MOZ_WIDGET_TOOLKIT'] != 'windows': - about_pages.append('webauthn') Headers = ['/docshell/build/nsDocShellModule.h'] diff --git a/dom/webauthn/AndroidWebAuthnService.cpp b/dom/webauthn/AndroidWebAuthnService.cpp index ad53f298579b..deec2d5afbc0 100644 --- a/dom/webauthn/AndroidWebAuthnService.cpp +++ b/dom/webauthn/AndroidWebAuthnService.cpp @@ -369,13 +369,5 @@ AndroidWebAuthnService::SetUserVerified(uint64_t authenticatorId, return NS_ERROR_NOT_IMPLEMENTED; } -NS_IMETHODIMP -AndroidWebAuthnService::Listen() { return NS_ERROR_NOT_IMPLEMENTED; } - -NS_IMETHODIMP -AndroidWebAuthnService::RunCommand(const nsACString& cmd) { - return NS_ERROR_NOT_IMPLEMENTED; -} - } // namespace dom } // namespace mozilla diff --git a/dom/webauthn/WebAuthnService.cpp b/dom/webauthn/WebAuthnService.cpp index d8401698b7a7..de0a9556d058 100644 --- a/dom/webauthn/WebAuthnService.cpp +++ b/dom/webauthn/WebAuthnService.cpp @@ -160,20 +160,4 @@ WebAuthnService::SetUserVerified(uint64_t authenticatorId, return mPlatformService->SetUserVerified(authenticatorId, isUserVerified); } -NS_IMETHODIMP -WebAuthnService::Listen() { - if (StaticPrefs::security_webauth_webauthn_enable_softtoken()) { - return mTestService->Listen(); - } - return mPlatformService->Listen(); -} - -NS_IMETHODIMP -WebAuthnService::RunCommand(const nsACString& cmd) { - if (StaticPrefs::security_webauth_webauthn_enable_softtoken()) { - return mTestService->RunCommand(cmd); - } - return mPlatformService->RunCommand(cmd); -} - } // namespace mozilla::dom diff --git a/dom/webauthn/authrs_bridge/src/about_webauthn_controller.rs b/dom/webauthn/authrs_bridge/src/about_webauthn_controller.rs deleted file mode 100644 index a4fd5f5e1a6f..000000000000 --- a/dom/webauthn/authrs_bridge/src/about_webauthn_controller.rs +++ /dev/null @@ -1,155 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use super::*; -use authenticator::{ - ctap2::commands::{PinUvAuthResult, StatusCode}, - errors::{CommandError, HIDError}, - CredManagementCmd, InteractiveRequest, InteractiveUpdate, PinError, -}; -use serde::{Deserialize, Serialize}; - -pub(crate) type InteractiveManagementReceiver = Option>; -pub(crate) fn send_about_prompt(prompt: &BrowserPromptType) -> Result<(), nsresult> { - let json = nsString::from(&serde_json::to_string(&prompt).unwrap_or_default()); - notify_observers(PromptTarget::AboutPage, json) -} - -// A wrapper around InteractiveRequest, that leaves out the PUAT -// so that we can easily de/serialize it to/from JSON for the JS-side -// and then add our cached PUAT, if we have one. -#[derive(Debug, Serialize, Deserialize)] -pub enum RequestWrapper { - Quit, - ChangePIN(Pin, Pin), - SetPIN(Pin), - CredentialManagement(CredManagementCmd), -} - -pub(crate) fn authrs_to_prompt<'a>(e: AuthenticatorError) -> BrowserPromptType<'a> { - match e { - AuthenticatorError::PinError(PinError::PinIsTooShort) => BrowserPromptType::PinIsTooShort, - AuthenticatorError::PinError(PinError::PinRequired) => BrowserPromptType::PinRequired, - AuthenticatorError::PinError(PinError::PinIsTooLong(_)) => BrowserPromptType::PinIsTooLong, - AuthenticatorError::PinError(PinError::InvalidPin(r)) => { - BrowserPromptType::PinInvalid { retries: r } - } - AuthenticatorError::PinError(PinError::PinAuthBlocked) => BrowserPromptType::PinAuthBlocked, - AuthenticatorError::PinError(PinError::PinBlocked) => BrowserPromptType::DeviceBlocked, - AuthenticatorError::PinError(PinError::UvBlocked) => BrowserPromptType::UvBlocked, - AuthenticatorError::PinError(PinError::InvalidUv(r)) => { - BrowserPromptType::UvInvalid { retries: r } - } - AuthenticatorError::CancelledByUser - | AuthenticatorError::HIDError(HIDError::Command(CommandError::StatusCode( - StatusCode::KeepaliveCancel, - _, - ))) => BrowserPromptType::Cancel, - _ => BrowserPromptType::UnknownError, - } -} - -pub(crate) fn cache_puat( - transaction: Arc>>, - puat: Option, -) { - let mut guard = transaction.lock().unwrap(); - if let Some(transaction) = guard.as_mut() { - transaction.puat_cache = puat; - }; -} - -pub(crate) fn interactive_status_callback( - status_rx: Receiver, - transaction: Arc>>, /* Shared with an AuthrsTransport */ - upcoming_error: Arc>>, -) -> Result<(), nsresult> { - loop { - match status_rx.recv() { - Ok(StatusUpdate::InteractiveManagement(InteractiveUpdate::StartManagement(( - tx, - auth_info, - )))) => { - let mut guard = transaction.lock().unwrap(); - let Some(transaction) = guard.as_mut() else { - warn!("STATUS: received status update after end of transaction."); - break; - }; - transaction.interactive_receiver.replace(tx); - let prompt = BrowserPromptType::SelectedDevice { auth_info }; - send_about_prompt(&prompt)?; - } - Ok(StatusUpdate::InteractiveManagement( - InteractiveUpdate::CredentialManagementUpdate((cfg_result, puat_res)), - )) => { - cache_puat(transaction.clone(), puat_res); // We don't care if we fail here. Worst-case: User has to enter PIN more often. - let prompt = BrowserPromptType::CredentialManagementUpdate { result: cfg_result }; - send_about_prompt(&prompt)?; - continue; - } - Ok(StatusUpdate::SelectDeviceNotice) => { - info!("STATUS: Please select a device by touching one of them."); - let prompt = BrowserPromptType::SelectDevice; - send_about_prompt(&prompt)?; - } - Ok(StatusUpdate::PinUvError(e)) => { - let mut guard = transaction.lock().unwrap(); - let Some(transaction) = guard.as_mut() else { - warn!("STATUS: received status update after end of transaction."); - break; - }; - let autherr = match e { - StatusPinUv::PinRequired(pin_sender) => { - transaction.pin_receiver.replace((0, pin_sender)); - send_about_prompt(&BrowserPromptType::PinRequired)?; - continue; - } - StatusPinUv::InvalidPin(pin_sender, r) => { - transaction.pin_receiver.replace((0, pin_sender)); - send_about_prompt(&BrowserPromptType::PinInvalid { retries: r })?; - continue; - } - StatusPinUv::PinIsTooShort => { - AuthenticatorError::PinError(PinError::PinIsTooShort) - } - StatusPinUv::PinIsTooLong(s) => { - AuthenticatorError::PinError(PinError::PinIsTooLong(s)) - } - StatusPinUv::InvalidUv(r) => { - send_about_prompt(&BrowserPromptType::UvInvalid { retries: r })?; - continue; - } - StatusPinUv::PinAuthBlocked => { - AuthenticatorError::PinError(PinError::PinAuthBlocked) - } - StatusPinUv::PinBlocked => AuthenticatorError::PinError(PinError::PinBlocked), - StatusPinUv::PinNotSet => AuthenticatorError::PinError(PinError::PinNotSet), - StatusPinUv::UvBlocked => AuthenticatorError::PinError(PinError::UvBlocked), - }; - // We will cause auth-rs to return an error, once we leave this block - // due to us 'hanging up'. Before we do that, we will safe the actual - // error that caused this, so our callback-function can return the true - // error to JS, instead of "cancelled by user". - let guard = upcoming_error.lock(); - if let Ok(mut entry) = guard { - entry.replace(autherr); - } else { - return Err(NS_ERROR_DOM_INVALID_STATE_ERR); - } - warn!("STATUS: Pin Error {:?}", e); - break; - } - - Ok(_) => { - // currently not handled - continue; - } - Err(RecvError) => { - info!("STATUS: end"); - break; - } - } - } - Ok(()) -} diff --git a/dom/webauthn/authrs_bridge/src/lib.rs b/dom/webauthn/authrs_bridge/src/lib.rs index 34234497827b..2ad1d8460dd4 100644 --- a/dom/webauthn/authrs_bridge/src/lib.rs +++ b/dom/webauthn/authrs_bridge/src/lib.rs @@ -11,7 +11,7 @@ extern crate xpcom; use authenticator::{ authenticatorservice::{RegisterArgs, SignArgs}, ctap2::attestation::AttestationObject, - ctap2::commands::{get_info::AuthenticatorVersion, PinUvAuthResult}, + ctap2::commands::get_info::AuthenticatorVersion, ctap2::server::{ AuthenticationExtensionsClientInputs, AuthenticatorAttachment, PublicKeyCredentialDescriptor, PublicKeyCredentialParameters, @@ -20,16 +20,15 @@ use authenticator::{ }, errors::AuthenticatorError, statecallback::StateCallback, - AuthenticatorInfo, CredentialManagementResult, InteractiveRequest, ManageResult, Pin, - RegisterResult, SignResult, StateMachine, StatusPinUv, StatusUpdate, + Pin, RegisterResult, SignResult, StateMachine, StatusPinUv, StatusUpdate, }; use base64::Engine; use cstr::cstr; use moz_task::{get_main_thread, RunnableBuilder}; use nserror::{ nsresult, NS_ERROR_DOM_ABORT_ERR, NS_ERROR_DOM_INVALID_STATE_ERR, NS_ERROR_DOM_NOT_ALLOWED_ERR, - NS_ERROR_DOM_OPERATION_ERR, NS_ERROR_FAILURE, NS_ERROR_INVALID_ARG, NS_ERROR_NOT_AVAILABLE, - NS_ERROR_NOT_IMPLEMENTED, NS_ERROR_NULL_POINTER, NS_OK, + NS_ERROR_FAILURE, NS_ERROR_INVALID_ARG, NS_ERROR_NOT_AVAILABLE, NS_ERROR_NOT_IMPLEMENTED, + NS_ERROR_NULL_POINTER, NS_OK, }; use nsstring::{nsACString, nsAString, nsCString, nsString}; use serde::Serialize; @@ -45,8 +44,7 @@ use xpcom::interfaces::{ nsIWebAuthnSignPromise, nsIWebAuthnSignResult, }; use xpcom::{xpcom_method, RefPtr}; -mod about_webauthn_controller; -use about_webauthn_controller::*; + mod test_token; use test_token::TestTokenManager; @@ -79,14 +77,9 @@ enum BrowserPromptType<'a> { SelectDevice, UvBlocked, PinRequired, - SelectedDevice { - auth_info: Option, - }, PinInvalid { retries: Option, }, - PinIsTooLong, - PinIsTooShort, RegisterDirect, UvInvalid { retries: Option, @@ -94,20 +87,6 @@ enum BrowserPromptType<'a> { SelectSignResult { entities: &'a [PublicKeyCredentialUserEntity], }, - ListenSuccess, - ListenError { - error: Box>, - }, - CredentialManagementUpdate { - result: CredentialManagementResult, - }, - UnknownError, -} - -#[derive(Debug)] -enum PromptTarget { - Browser, - AboutPage, } #[derive(Serialize)] @@ -119,29 +98,13 @@ struct BrowserPromptMessage<'a> { browsing_context_id: Option, } -fn notify_observers(prompt_target: PromptTarget, json: nsString) -> Result<(), nsresult> { - let main_thread = get_main_thread()?; - let target = match prompt_target { - PromptTarget::Browser => cstr!("webauthn-prompt"), - PromptTarget::AboutPage => cstr!("about-webauthn-prompt"), - }; - - RunnableBuilder::new("AuthrsService::send_prompt", move || { - if let Ok(obs_svc) = xpcom::components::Observer::service::() { - unsafe { - obs_svc.NotifyObservers(std::ptr::null(), target.as_ptr(), json.as_ptr()); - } - } - }) - .dispatch(main_thread.coerce()) -} - fn send_prompt( prompt: BrowserPromptType, tid: u64, origin: Option<&str>, browsing_context_id: Option, ) -> Result<(), nsresult> { + let main_thread = get_main_thread()?; let mut json = nsString::new(); write!( json, @@ -154,7 +117,18 @@ fn send_prompt( }) ) .or(Err(NS_ERROR_FAILURE))?; - notify_observers(PromptTarget::Browser, json) + RunnableBuilder::new("AuthrsService::send_prompt", move || { + if let Ok(obs_svc) = xpcom::components::Observer::service::() { + unsafe { + obs_svc.NotifyObservers( + std::ptr::null(), + cstr!("webauthn-prompt").as_ptr(), + json.as_ptr(), + ); + } + } + }) + .dispatch(main_thread.coerce()) } fn cancel_prompts(tid: u64) -> Result<(), nsresult> { @@ -512,7 +486,6 @@ impl SignPromise { #[derive(Clone)] enum TransactionPromise { - Listen, Register(RegisterPromise), Sign(SignPromise), } @@ -520,7 +493,6 @@ enum TransactionPromise { impl TransactionPromise { fn reject(&self, err: nsresult) -> Result<(), nsresult> { match self { - TransactionPromise::Listen => Ok(()), TransactionPromise::Register(promise) => promise.resolve_or_reject(Err(err)), TransactionPromise::Sign(promise) => promise.resolve_or_reject(Err(err)), } @@ -540,8 +512,6 @@ struct TransactionState { promise: TransactionPromise, pin_receiver: PinReceiver, selection_receiver: SelectionReceiver, - interactive_receiver: InteractiveManagementReceiver, - puat_cache: Option, // Cached credential to avoid repeated PIN-entries } // AuthrsService provides an nsIWebAuthnService built on top of authenticator-rs. @@ -555,29 +525,23 @@ pub struct AuthrsService { impl AuthrsService { xpcom_method!(pin_callback => PinCallback(aTransactionId: u64, aPin: *const nsACString)); fn pin_callback(&self, transaction_id: u64, pin: &nsACString) -> Result<(), nsresult> { - if static_prefs::pref!("security.webauth.webauthn_enable_usbtoken") { - let mut guard = self.transaction.lock().unwrap(); - let Some(transaction) = guard.as_mut() else { - // No ongoing transaction - return Err(NS_ERROR_FAILURE); - }; - let Some((tid, channel)) = transaction.pin_receiver.take() else { - // We weren't expecting a pin. - return Err(NS_ERROR_FAILURE); - }; - if tid != transaction_id { - // The browser is confused about which transaction is active. - // This shouldn't happen - return Err(NS_ERROR_FAILURE); - } - channel - .send(Pin::new(&pin.to_string())) - .or(Err(NS_ERROR_FAILURE)) - } else { - // Silently accept request, if all webauthn-options are disabled. - // Used for testing. - Ok(()) + let mut guard = self.transaction.lock().unwrap(); + let Some(transaction) = guard.as_mut() else { + // No ongoing transaction + return Err(NS_ERROR_FAILURE); + }; + let Some((tid, channel)) = transaction.pin_receiver.take() else { + // We weren't expecting a pin. + return Err(NS_ERROR_FAILURE); + }; + if tid != transaction_id { + // The browser is confused about which transaction is active. + // This shouldn't happen + return Err(NS_ERROR_FAILURE); } + channel + .send(Pin::new(&pin.to_string())) + .or(Err(NS_ERROR_FAILURE)) } xpcom_method!(selection_callback => SelectionCallback(aTransactionId: u64, aSelection: u64)); @@ -740,10 +704,8 @@ impl AuthrsService { browsing_context_id, pending_args: Some(TransactionArgs::Register(timeout_ms as u64, info)), promise: TransactionPromise::Register(promise), - interactive_receiver: None, pin_receiver: None, selection_receiver: None, - puat_cache: None, }); if none_attestation @@ -777,10 +739,6 @@ impl AuthrsService { let Some(TransactionArgs::Register(timeout_ms, info)) = state.pending_args.take() else { return Err(NS_ERROR_FAILURE); }; - // We have to drop the guard here, as there _may_ still be another operation - // ongoing and `register()` below will try to cancel it. This will call the state - // callback of that operation, which in turn may try to access `transaction`, deadlocking. - drop(guard); let (status_tx, status_rx) = channel::(); let status_transaction = self.transaction.clone(); @@ -832,7 +790,6 @@ impl AuthrsService { let _ = cancel_prompts(tid); } let _ = promise.resolve_or_reject(result.map_err(authrs_to_nserror)); - *guard = None; }), ); @@ -965,7 +922,6 @@ impl AuthrsService { let _ = cancel_prompts(tid); } let _ = promise.resolve_or_reject(result.map_err(authrs_to_nserror)); - *guard = None; }), ); @@ -997,10 +953,8 @@ impl AuthrsService { browsing_context_id, pending_args: None, promise: TransactionPromise::Sign(promise), - interactive_receiver: None, pin_receiver: None, selection_receiver: None, - puat_cache: None, }); // As in `register`, we are intentionally avoiding `AuthenticatorService` here. @@ -1176,136 +1130,6 @@ impl AuthrsService { self.test_token_manager .set_user_verified(authenticator_id, is_user_verified) } - - xpcom_method!(listen => Listen()); - pub(crate) fn listen(&self) -> Result<(), nsresult> { - // For now, we don't support softtokens - if static_prefs::pref!("security.webauth.webauthn_enable_softtoken") { - return Ok(()); - } - - { - let mut guard = self.transaction.lock().unwrap(); - if guard.as_ref().is_some() { - // ignore listen() and continue with ongoing transaction - return Ok(()); - } - *guard = Some(TransactionState { - tid: 0, - browsing_context_id: 0, - pending_args: None, - promise: TransactionPromise::Listen, - interactive_receiver: None, - pin_receiver: None, - selection_receiver: None, - puat_cache: None, - }); - } - - // We may get from status_updates info about certain errors (e.g. PinErrors) - // which we want to present to the user. We will ignore the following error - // which is caused by us "hanging up" on the StatusUpdate-channel and return - // the PinError instead, via `upcoming_error`. - let upcoming_error = Arc::new(Mutex::new(None)); - let upcoming_error_c = upcoming_error.clone(); - let callback_transaction = self.transaction.clone(); - let state_callback = StateCallback::>::new( - Box::new(move |result| { - let mut guard = callback_transaction.lock().unwrap(); - match guard.as_mut() { - Some(state) => { - match state.promise { - TransactionPromise::Listen => (), - _ => return, - } - *guard = None; - } - // We have no transaction anymore, this means cancel() was called - None => (), - } - let msg = match result { - Ok(_) => BrowserPromptType::ListenSuccess, - Err(e) => { - // See if we have a cached error that should replace this error - let replacement = if let Ok(mut x) = upcoming_error_c.lock() { - x.take() - } else { - None - }; - let replaced_err = replacement.unwrap_or(e); - let err = authrs_to_prompt(replaced_err); - BrowserPromptType::ListenError { - error: Box::new(err), - } - } - }; - let _ = send_about_prompt(&msg); - }), - ); - - // Calling `manage()` within the lock, to avoid race conditions - // where we might check listen_blocked, see that it's false, - // continue along, but in parallel `make_credential()` aborts the - // interactive process shortly after, setting listen_blocked to true, - // then accessing usb_token_manager afterwards and at the same time - // we do it here, causing a runtime crash for trying to mut-borrow it twice. - let (status_tx, status_rx) = channel::(); - let status_transaction = self.transaction.clone(); - RunnableBuilder::new( - "AuthrsTransport::AboutWebauthn::StatusReceiver", - move || { - let _ = interactive_status_callback(status_rx, status_transaction, upcoming_error); - }, - ) - .may_block(true) - .dispatch_background_task()?; - if static_prefs::pref!("security.webauth.webauthn_enable_usbtoken") { - self.usb_token_manager.lock().unwrap().manage( - 60 * 1000 * 1000, - status_tx, - state_callback, - ); - } else if static_prefs::pref!("security.webauth.webauthn_enable_softtoken") { - // We don't yet support softtoken - } else { - // Silently accept request, if all webauthn-options are disabled. - // Used for testing. - } - Ok(()) - } - - xpcom_method!(run_command => RunCommand(c_cmd: *const nsACString)); - pub fn run_command(&self, c_cmd: &nsACString) -> Result<(), nsresult> { - // Always test if it can be parsed from incoming JSON (even for tests) - let incoming: RequestWrapper = - serde_json::from_str(&c_cmd.to_utf8()).or(Err(NS_ERROR_DOM_OPERATION_ERR))?; - if static_prefs::pref!("security.webauth.webauthn_enable_usbtoken") { - let guard = self.transaction.lock().unwrap(); - let puat = guard.as_ref().and_then(|g| g.puat_cache.clone()); - let command = match incoming { - RequestWrapper::Quit => InteractiveRequest::Quit, - RequestWrapper::ChangePIN(a, b) => InteractiveRequest::ChangePIN(a, b), - RequestWrapper::SetPIN(a) => InteractiveRequest::SetPIN(a), - RequestWrapper::CredentialManagement(c) => { - InteractiveRequest::CredentialManagement(c, puat) - } - }; - match &guard.as_ref().unwrap().interactive_receiver { - Some(channel) => channel.send(command).or(Err(NS_ERROR_FAILURE)), - // Either we weren't expecting a pin, or the controller is confused - // about which transaction is active. Neither is recoverable, so it's - // OK to drop the PinReceiver here. - _ => Err(NS_ERROR_FAILURE), - } - } else if static_prefs::pref!("security.webauth.webauthn_enable_softtoken") { - // We don't yet support softtoken - Ok(()) - } else { - // Silently accept request, if all webauthn-options are disabled. - // Used for testing. - Ok(()) - } - } } #[no_mangle] diff --git a/dom/webauthn/nsIWebAuthnService.idl b/dom/webauthn/nsIWebAuthnService.idl index cd46b809921b..65f4a6ddd18b 100644 --- a/dom/webauthn/nsIWebAuthnService.idl +++ b/dom/webauthn/nsIWebAuthnService.idl @@ -90,8 +90,4 @@ interface nsIWebAuthnService : nsISupports // Sets the "isUserVerified" bit on a virtual authenticator. See // https://w3c.github.io/webauthn/#sctn-automation-set-user-verified void setUserVerified(in uint64_t authenticatorId, in bool isUserVerified); - - // about:webauthn-specific functions - void listen(); - void runCommand(in ACString aCommand); }; diff --git a/toolkit/components/aboutwebauthn/content/aboutWebauthn.css b/toolkit/components/aboutwebauthn/content/aboutWebauthn.css deleted file mode 100644 index f50584dcf3b5..000000000000 --- a/toolkit/components/aboutwebauthn/content/aboutWebauthn.css +++ /dev/null @@ -1,79 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -@import url("chrome://global/skin/in-content/common.css"); - -html { - height: 100%; -} - -body { - display: flex; - align-items: stretch; - height: 100%; -} - -label { - display: block; -} - -#info-text-div { - padding: 20px; -} - -#ctap-listen-div { - padding-top: 15px; -} -#ctap-listen-result { - font-weight: 600; - font-size: 1.5em; - padding-inline-start: 15px; - - &.success { - background-color: var(--green-50); - } - - &.error { - background-color: var(--red-50); - } -} - -.category { - cursor: pointer; - /* Center category names */ - display: flex; - align-items: center; -} - -.disabled-category { - pointer-events: none; -} - -@media (max-width: 830px){ - #categories > .category { - padding-inline-start: 5px; - margin-inline-start: 0; - } -} - -#main-content { - flex: 1; -} - -.token-info-flex-box { - display: flex; -} - -.token-info-flex-child { - flex: 1; -} - -.token-info-flex-child#authenticator-options { - margin-inline-end: 2px; -} - -.button-row { - display: inline-block; - margin-inline-end: 5px; -} diff --git a/toolkit/components/aboutwebauthn/content/aboutWebauthn.html b/toolkit/components/aboutwebauthn/content/aboutWebauthn.html deleted file mode 100644 index 8ba145daa67c..000000000000 --- a/toolkit/components/aboutwebauthn/content/aboutWebauthn.html +++ /dev/null @@ -1,180 +0,0 @@ - - - - - - - - - - - - - - - -
- -
- - - - - - diff --git a/toolkit/components/aboutwebauthn/content/aboutWebauthn.js b/toolkit/components/aboutwebauthn/content/aboutWebauthn.js deleted file mode 100644 index 65c5b263665d..000000000000 --- a/toolkit/components/aboutwebauthn/content/aboutWebauthn.js +++ /dev/null @@ -1,493 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -let AboutWebauthnService = null; - -var AboutWebauthnManagerJS = { - _topic: "about-webauthn-prompt", - _initialized: false, - _l10n: null, - _current_tab: "", - _previous_tab: "", - - init() { - if (this._initialized) { - return; - } - this._l10n = new Localization(["toolkit/about/aboutWebauthn.ftl"], true); - Services.obs.addObserver(this, this._topic); - this._initialized = true; - reset_page(); - }, - - uninit() { - Services.obs.removeObserver(this, this._topic); - }, - - observe(aSubject, aTopic, aData) { - let data = JSON.parse(aData); - - // We have token - if (data.type == "selected-device") { - fake_click_event_for_id("info-tab-button"); - this.show_ui_based_on_authenticator_info(data); - } else if (data.type == "select-device") { - set_info_text("about-webauthn-text-select-device"); - } else if (data.type == "pin-required") { - open_pin_required_tab(); - } else if (data.type == "pin-invalid") { - let retries = data.retries ? data.retries : 0; - show_results_banner( - "error", - "about-webauthn-results-pin-invalid-error", - JSON.stringify({ retriesLeft: retries }) - ); - open_pin_required_tab(); - } else if (data.type == "credential-management-update") { - credential_management_in_progress(false); - if (data.result.CredentialList) { - show_results_banner("success", "about-webauthn-results-success"); - this.show_credential_list(data.result.CredentialList.credential_list); - } else { - // DeleteSuccess or UpdateSuccess - show_results_banner("success", "about-webauthn-results-success"); - list_credentials(); - } - } else if (data.type == "listen-success") { - reset_page(); - // Show results - show_results_banner("success", "about-webauthn-results-success"); - this._reset_in_progress = ""; - AboutWebauthnService.listen(); - } else if (data.type == "listen-error") { - reset_page(); - - if (!data.error) { - show_results_banner("error", "about-webauthn-results-general-error"); - } else if (data.error.type == "pin-auth-blocked") { - show_results_banner( - "error", - "about-webauthn-results-pin-auth-blocked-error" - ); - } else if (data.error.type == "device-blocked") { - show_results_banner( - "error", - "about-webauthn-results-pin-blocked-error" - ); - } else if (data.error.type == "pin-is-too-short") { - show_results_banner( - "error", - "about-webauthn-results-pin-too-short-error" - ); - } else if (data.error.type == "pin-is-too-long") { - show_results_banner( - "error", - "about-webauthn-results-pin-too-long-error" - ); - } else if (data.error.type == "pin-invalid") { - let retries = data.error.retries - ? JSON.stringify({ retriesLeft: data.error.retries }) - : null; - show_results_banner( - "error", - "about-webauthn-results-pin-invalid-error", - retries - ); - } else if (data.error.type == "cancel") { - show_results_banner( - "error", - "about-webauthn-results-cancelled-by-user-error" - ); - } else { - show_results_banner("error", "about-webauthn-results-general-error"); - } - AboutWebauthnService.listen(); - } - }, - - show_authenticator_options(options, element, l10n_base) { - let table = document.getElementById(element); - var empty_table = document.createElement("table"); - empty_table.id = element; - table.parentNode.replaceChild(empty_table, table); - table = document.getElementById(element); - for (let key in options) { - if (key == "options") { - continue; - } - // Create an empty element and add it to the 1st position of the table: - var row = table.insertRow(0); - - // Insert new cells ( elements) at the 1st and 2nd position of the "new" element: - var cell1 = row.insertCell(0); - var cell2 = row.insertCell(1); - - // Add some text to the new cells: - let key_text = this._l10n.formatValueSync( - l10n_base + "-" + key.toLowerCase().replace(/_/g, "-") - ); - var key_node = document.createTextNode(key_text); - cell1.appendChild(key_node); - var raw_value = JSON.stringify(options[key]); - var value = raw_value; - if (["true", "false", "null"].includes(raw_value)) { - value = this._l10n.formatValueSync(l10n_base + "-" + raw_value); - } - var value_node = document.createTextNode(value); - cell2.appendChild(value_node); - } - }, - - show_ui_based_on_authenticator_info(data) { - // Hide the "Please plug in a token"-message - document.getElementById("info-text-div").hidden = true; - // Show options, based on what the token supports - if (data.auth_info) { - document.getElementById("main-content").hidden = false; - document.getElementById("categories").hidden = false; - this.show_authenticator_options( - data.auth_info.options, - "authenticator-options", - "about-webauthn-auth-option" - ); - this.show_authenticator_options( - data.auth_info, - "authenticator-info", - "about-webauthn-auth-info" - ); - // Check if token supports PINs - if (data.auth_info.options.clientPin != null) { - document.getElementById("pin-tab-button").style.display = "flex"; - if (data.auth_info.options.clientPin === true) { - // It has a Pin set - document.getElementById("change-pin-button").style.display = "block"; - document.getElementById("set-pin-button").style.display = "none"; - document.getElementById("current-pin-div").hidden = false; - } else { - // It does not have a Pin set yet - document.getElementById("change-pin-button").style.display = "none"; - document.getElementById("set-pin-button").style.display = "block"; - document.getElementById("current-pin-div").hidden = true; - } - } else { - document.getElementById("pin-tab-button").style.display = "none"; - } - - if ( - data.auth_info.options.credMgmt || - data.auth_info.options.credentialMgmtPreview - ) { - document.getElementById("credentials-tab-button").style.display = - "flex"; - } else { - document.getElementById("credentials-tab-button").style.display = - "none"; - } - } else { - // Currently auth-rs doesn't send this, because it filters out ctap2-devices. - // U2F / CTAP1 tokens can't be managed - set_info_text("about-webauthn-text-non-ctap2-device"); - } - }, - - show_credential_list(credential_list) { - // We may have temporarily hidden the tab when asking the user for a PIN - // so we have to show it again. - fake_click_event_for_id("credentials-tab-button"); - document.getElementById("credential-list-subsection").hidden = false; - let table = document.getElementById("credential-list"); - var empty_table = document.createElement("table"); - empty_table.id = "credential-list"; - table.parentNode.replaceChild(empty_table, table); - if (!credential_list.length) { - document.getElementById("credential-list-empty-label").hidden = false; - return; - } - document.getElementById("credential-list-empty-label").hidden = true; - table = document.getElementById("credential-list"); - credential_list.forEach(rp => { - // Add some text to the new cells: - let key_text = rp.rp.id; - rp.credentials.forEach(cred => { - let value_text = cred.user.name; - // Create an empty element and add it to the 1st position of the table: - var row = table.insertRow(0); - var key_node = document.createTextNode(key_text); - var value_node = document.createTextNode(value_text); - row.insertCell(0).appendChild(key_node); - row.insertCell(1).appendChild(value_node); - var delete_button = document.createElement("button"); - delete_button.classList.add("credentials-button"); - // TODO: Garbage-can symbol instead? See https://bugzilla.mozilla.org/show_bug.cgi?id=1859727 - delete_button.setAttribute( - "data-l10n-id", - "about-webauthn-delete-button" - ); - delete_button.addEventListener("click", function () { - credential_management_in_progress(true); - let cmd = { - CredentialManagement: { DeleteCredential: cred.credential_id }, - }; - AboutWebauthnService.runCommand(JSON.stringify(cmd)); - }); - row.insertCell(2).appendChild(delete_button); - }); - }); - }, -}; - -function set_info_text(l10nId) { - document.getElementById("info-text-div").hidden = false; - let field = document.getElementById("info-text-field"); - field.setAttribute("data-l10n-id", l10nId); -} - -function show_results_banner(result, l10n, l10n_args) { - document.getElementById("ctap-listen-div").hidden = false; - let ctap_result = document.getElementById("ctap-listen-result"); - ctap_result.setAttribute("data-l10n-id", l10n); - ctap_result.classList.add(result); - if (l10n_args) { - ctap_result.setAttribute("data-l10n-args", l10n_args); - } -} - -function hide_results_banner() { - document - .getElementById("ctap-listen-result") - .classList.remove("success", "error"); - document.getElementById("ctap-listen-div").hidden = true; -} - -function credential_management_in_progress(in_progress) { - let buttons = Array.from( - document.getElementsByClassName("credentials-button") - ); - buttons.forEach(button => { - button.disabled = in_progress; - }); -} - -function fake_click_event_for_id(id) { - // Not using document.getElementById(id).click(); - // here, because we have to add additional data, so we don't - // hide the results-div here, if there is any. 'Normal' clicking - // by the user will hide it. - const evt = new CustomEvent("click", { - detail: { skip_results_clearing: true }, - }); - document.getElementById(id).dispatchEvent(evt); -} - -function reset_page() { - // Hide all main sections - document.getElementById("main-content").hidden = true; - document.getElementById("categories").hidden = true; - - // Clear results and input fields - hide_results_banner(); - var divs = Array.from(document.getElementsByTagName("input")); - divs.forEach(div => { - div.value = ""; - }); - - sidebar_set_disabled(false); - - // ListCredentials - credential_management_in_progress(false); - document.getElementById("credential-list-subsection").hidden = true; - - // Only display the "please connect a device" - text - set_info_text("about-webauthn-text-connect-device"); - - AboutWebauthnManagerJS._previous_tab = ""; - AboutWebauthnManagerJS._current_tab = ""; -} - -function sidebar_set_disabled(disabled) { - var cats = Array.from(document.getElementsByClassName("category")); - cats.forEach(cat => { - if (disabled) { - cat.classList.add("disabled-category"); - } else { - cat.classList.remove("disabled-category"); - } - }); -} - -function check_pin_repeat_is_correct(button) { - let pin = document.getElementById("new-pin"); - let pin_repeat = document.getElementById("new-pin-repeat"); - let has_current_pin = !document.getElementById("current-pin-div").hidden; - let current_pin = document.getElementById("current-pin"); - let can_enable_button = - pin.value != null && pin.value != "" && pin.value == pin_repeat.value; - if (has_current_pin && !current_pin.value) { - can_enable_button = false; - } - if (!can_enable_button) { - pin.classList.add("different"); - pin_repeat.classList.add("different"); - document.getElementById("set-pin-button").disabled = true; - document.getElementById("change-pin-button").disabled = true; - return false; - } - pin.classList.remove("different"); - pin_repeat.classList.remove("different"); - document.getElementById("set-pin-button").disabled = false; - document.getElementById("change-pin-button").disabled = false; - return true; -} - -function send_pin() { - close_pin_required_tab(); - let pin = document.getElementById("pin-required").value; - AboutWebauthnService.pinCallback(0, pin); -} - -function set_pin() { - let pin = document.getElementById("new-pin").value; - let cmd = { SetPIN: pin }; - AboutWebauthnService.runCommand(JSON.stringify(cmd)); -} - -function change_pin() { - let curr_pin = document.getElementById("current-pin").value; - let new_pin = document.getElementById("new-pin").value; - let cmd = { ChangePIN: [curr_pin, new_pin] }; - AboutWebauthnService.runCommand(JSON.stringify(cmd)); -} - -function list_credentials() { - credential_management_in_progress(true); - let cmd = { CredentialManagement: "GetCredentials" }; - AboutWebauthnService.runCommand(JSON.stringify(cmd)); -} - -function cancel_transaction() { - credential_management_in_progress(false); - AboutWebauthnService.cancel(0); -} - -async function onLoad() { - AboutWebauthnManagerJS.init(); - try { - AboutWebauthnService.listen(); - } catch (ex) { - set_info_text("about-webauthn-text-not-available"); - AboutWebauthnManagerJS.uninit(); - return; - } - document.getElementById("set-pin-button").addEventListener("click", set_pin); - document - .getElementById("change-pin-button") - .addEventListener("click", change_pin); - document - .getElementById("list-credentials-button") - .addEventListener("click", list_credentials); - document - .getElementById("new-pin") - .addEventListener("input", check_pin_repeat_is_correct); - document - .getElementById("new-pin-repeat") - .addEventListener("input", check_pin_repeat_is_correct); - document - .getElementById("current-pin") - .addEventListener("input", check_pin_repeat_is_correct); - document - .getElementById("info-tab-button") - .addEventListener("click", open_info_tab); - document - .getElementById("pin-tab-button") - .addEventListener("click", open_pin_tab); - document - .getElementById("credentials-tab-button") - .addEventListener("click", open_credentials_tab); - document - .getElementById("send-pin-button") - .addEventListener("click", send_pin); - document - .getElementById("cancel-send-pin-button") - .addEventListener("click", cancel_transaction); -} - -function open_tab(evt, tabName) { - var tabcontent, tablinks; - // Hide all others - tabcontent = Array.from(document.getElementsByClassName("tabcontent")); - tabcontent.forEach(tab => { - tab.style.display = "none"; - }); - // Display the one we selected - document.getElementById(tabName).style.display = "block"; - - // If this is a temporary overlay, like pin-required, we don't - // touch the sidebar and which button is selected. - if (!evt.detail.temporary_overlay) { - tablinks = Array.from(document.getElementsByClassName("category")); - tablinks.forEach(tablink => { - tablink.removeAttribute("selected"); - tablink.disabled = false; - }); - evt.currentTarget.setAttribute("selected", "true"); - } - - if (!evt.detail.skip_results_clearing) { - hide_results_banner(); - } - sidebar_set_disabled(false); - AboutWebauthnManagerJS._previous_tab = AboutWebauthnManagerJS._current_tab; - AboutWebauthnManagerJS._current_tab = tabName; -} - -function open_info_tab(evt) { - open_tab(evt, "token-info-section"); -} -function open_pin_tab(evt) { - open_tab(evt, "set-change-pin-section"); -} -function open_credentials_tab(evt) { - open_tab(evt, "credential-management-section"); -} -function open_pin_required_tab() { - // Remove any old value we might have had - document.getElementById("pin-required").value = ""; - const evt = new CustomEvent("click", { - detail: { - temporary_overlay: true, - skip_results_clearing: true, // We might be called multiple times, if PIN was invalid - }, - }); - open_tab(evt, "pin-required-section"); - document.getElementById("pin-required").focus(); - // This is a temporary overlay, so we don't want the - // user to click away from it, unless via the Cancel-button. - sidebar_set_disabled(true); -} -function close_pin_required_tab() { - const evt = new CustomEvent("click", { - detail: { temporary_overlay: true }, - }); - open_tab(evt, AboutWebauthnManagerJS._previous_tab); - sidebar_set_disabled(false); -} - -try { - AboutWebauthnService = Cc["@mozilla.org/webauthn/service;1"].getService( - Ci.nsIWebAuthnService - ); - document.addEventListener("DOMContentLoaded", onLoad); - window.addEventListener("beforeunload", event => { - AboutWebauthnManagerJS.uninit(); - if (AboutWebauthnService) { - AboutWebauthnService.cancel(0); - } - }); -} catch (ex) { - // Do nothing if we fail to create a singleton instance, - // showing the default no-module message. - console.error(ex); -} diff --git a/toolkit/components/aboutwebauthn/jar.mn b/toolkit/components/aboutwebauthn/jar.mn deleted file mode 100644 index 7478168bbd2c..000000000000 --- a/toolkit/components/aboutwebauthn/jar.mn +++ /dev/null @@ -1,8 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -toolkit.jar: - content/global/aboutWebauthn.css (content/aboutWebauthn.css) - content/global/aboutWebauthn.html (content/aboutWebauthn.html) - content/global/aboutWebauthn.js (content/aboutWebauthn.js) \ No newline at end of file diff --git a/toolkit/components/aboutwebauthn/moz.build b/toolkit/components/aboutwebauthn/moz.build deleted file mode 100644 index 9ce8ce8e22d0..000000000000 --- a/toolkit/components/aboutwebauthn/moz.build +++ /dev/null @@ -1,13 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -with Files("**"): - BUG_COMPONENT = ("Core", "DOM: Web Authentication") - -if CONFIG["MOZ_WIDGET_TOOLKIT"] not in ("windows", "android"): - BROWSER_CHROME_MANIFESTS += ["tests/browser/browser.ini"] - -JAR_MANIFESTS += ["jar.mn"] diff --git a/toolkit/components/aboutwebauthn/tests/browser/browser.ini b/toolkit/components/aboutwebauthn/tests/browser/browser.ini deleted file mode 100644 index 7fa26859fe42..000000000000 --- a/toolkit/components/aboutwebauthn/tests/browser/browser.ini +++ /dev/null @@ -1,13 +0,0 @@ -[DEFAULT] -head = head.js -prefs = - security.webauth.webauthn=true - security.webauth.webauthn_enable_softtoken=false - security.webauth.webauthn_enable_android_fido2=false - security.webauth.webauthn_enable_usbtoken=false - security.webauthn.ctap2=true - -[browser_aboutwebauthn_credentials.js] -[browser_aboutwebauthn_info.js] -[browser_aboutwebauthn_no_token.js] -[browser_aboutwebauthn_pin.js] diff --git a/toolkit/components/aboutwebauthn/tests/browser/browser_aboutwebauthn_credentials.js b/toolkit/components/aboutwebauthn/tests/browser/browser_aboutwebauthn_credentials.js deleted file mode 100644 index 9ff6d2fd649a..000000000000 --- a/toolkit/components/aboutwebauthn/tests/browser/browser_aboutwebauthn_credentials.js +++ /dev/null @@ -1,346 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -var doc, tab; - -add_setup(async function () { - info("Starting about:webauthn"); - tab = await BrowserTestUtils.openNewForegroundTab({ - gBrowser, - opening: "about:webauthn", - waitForLoad: true, - }); - - doc = tab.linkedBrowser.contentDocument; -}); - -registerCleanupFunction(async function () { - // Close tab. - await BrowserTestUtils.removeTab(tab); -}); - -function send_credential_list(credlist) { - let num_of_creds = 0; - credlist.forEach(domain => { - domain.credentials.forEach(c => { - num_of_creds += 1; - }); - }); - let msg = JSON.stringify({ - type: "credential-management-update", - result: { - CredentialList: { - existing_resident_credentials_count: num_of_creds, - max_possible_remaining_resident_credentials_count: 20, - credential_list: credlist, - }, - }, - }); - Services.obs.notifyObservers(null, "about-webauthn-prompt", msg); -} - -function check_cred_buttons_disabled(disabled) { - let buttons = Array.from(doc.getElementsByClassName("credentials-button")); - buttons.forEach(button => { - is(button.disabled, disabled); - }); - return buttons; -} - -async function send_authinfo_and_open_cred_section(ops) { - reset_about_page(doc); - send_auth_info_and_check_categories(doc, ops); - - let button = doc.getElementById("pin-tab-button"); - is(button.style.display, "none", "pin-tab-button in the sidebar not hidden"); - - if (ops.credMgmt !== null || ops.credentialMgmtPreview !== null) { - let credentials_tab_button = doc.getElementById("credentials-tab-button"); - // Check if credentials section is visible - isnot( - credentials_tab_button.style.display, - "none", - "credentials button in the sidebar not visible" - ); - - // Click the section and wait for it to open - let credentials_section = doc.getElementById( - "credential-management-section" - ); - credentials_tab_button.click(); - isnot( - credentials_section.style.display, - "none", - "credentials section not visible" - ); - is( - credentials_tab_button.getAttribute("selected"), - "true", - "credentials section button not selected" - ); - } -} - -add_task(async function cred_mgmt_not_supported() { - // Not setting credMgmt at all should lead to not showing it in the sidebar - send_authinfo_and_open_cred_section({ - credMgmt: null, - credentialMgmtPreview: null, - }); - let credentials_tab_button = doc.getElementById("credentials-tab-button"); - is( - credentials_tab_button.style.display, - "none", - "credentials button in the sidebar visible" - ); -}); - -add_task(async function cred_mgmt_supported() { - // Setting credMgmt should show the button in the sidebar - // The function is checking this for us. - send_authinfo_and_open_cred_section({ - credMgmt: true, - credentialMgmtPreview: null, - }); - // Setting credMgmtPreview should show the button in the sidebar - send_authinfo_and_open_cred_section({ - credMgmt: null, - credentialMgmtPreview: true, - }); - // Setting both should also work - send_authinfo_and_open_cred_section({ - credMgmt: true, - credentialMgmtPreview: true, - }); -}); - -add_task(async function cred_mgmt_empty_list() { - send_authinfo_and_open_cred_section({ credMgmt: true }); - - let list_credentials_button = doc.getElementById("list-credentials-button"); - isnot( - list_credentials_button.style.display, - "none", - "credentials button in the sidebar not visible" - ); - - // Credential list should initially not be visible - let credential_list = doc.getElementById("credential-list-subsection"); - is(credential_list.hidden, true, "credentials list visible"); - - list_credentials_button.click(); - is( - list_credentials_button.disabled, - true, - "credentials button not disabled while op in progress" - ); - - send_credential_list([]); - is(list_credentials_button.disabled, false, "credentials button disabled"); - - is(credential_list.hidden, false, "credentials list visible"); - let credential_list_empty_label = doc.getElementById( - "credential-list-empty-label" - ); - is( - credential_list_empty_label.hidden, - false, - "credentials list empty label not visible" - ); -}); - -add_task(async function cred_mgmt_real_data() { - send_authinfo_and_open_cred_section({ credMgmt: true }); - let list_credentials_button = doc.getElementById("list-credentials-button"); - list_credentials_button.click(); - send_credential_list(REAL_DATA); - is(list_credentials_button.disabled, false, "credentials button disabled"); - let credential_list = doc.getElementById("credential-list"); - is( - credential_list.rows.length, - 4, - "credential list table doesn't contain 4 credentials" - ); - is(credential_list.rows[0].cells[0].textContent, "webauthn.io"); - is(credential_list.rows[0].cells[1].textContent, "fasdfasd"); - is(credential_list.rows[1].cells[0].textContent, "webauthn.io"); - is(credential_list.rows[1].cells[1].textContent, "twetwetw"); - is(credential_list.rows[2].cells[0].textContent, "webauthn.io"); - is(credential_list.rows[2].cells[1].textContent, "hhhhhg"); - is(credential_list.rows[3].cells[0].textContent, "example.com"); - is(credential_list.rows[3].cells[1].textContent, "A. Nother"); - let buttons = check_cred_buttons_disabled(false); - // 4 for each cred + 1 for the list button - is(buttons.length, 5); - - list_credentials_button.click(); - buttons = check_cred_buttons_disabled(true); - send_credential_list(REAL_DATA); - buttons[2].click(); - check_cred_buttons_disabled(true); -}); - -const REAL_DATA = [ - { - rp: { id: "example.com" }, - rp_id_hash: [ - 163, 121, 166, 246, 238, 175, 185, 165, 94, 55, 140, 17, 128, 52, 226, - 117, 30, 104, 47, 171, 159, 45, 48, 171, 19, 210, 18, 85, 134, 206, 25, - 71, - ], - credentials: [ - { - user: { - id: [65, 46, 32, 78, 111, 116, 104, 101, 114], - name: "A. Nother", - }, - credential_id: { - id: [ - 195, 239, 221, 151, 76, 77, 255, 242, 217, 50, 87, 144, 238, 79, - 199, 120, 234, 148, 142, 69, 163, 133, 189, 254, 74, 138, 119, 140, - 197, 171, 36, 215, 191, 176, 36, 111, 113, 158, 204, 147, 101, 200, - 20, 239, 191, 174, 51, 15, - ], - type: "public-key", - }, - public_key: { - 1: 2, - 3: -7, - "-1": 1, - "-2": [ - 195, 239, 221, 151, 76, 77, 255, 242, 217, 50, 87, 144, 238, 235, - 230, 51, 155, 142, 121, 60, 136, 63, 80, 184, 41, 238, 217, 61, 1, - 206, 253, 141, - ], - "-3": [ - 15, 81, 111, 204, 199, 48, 18, 121, 134, 243, 26, 49, 6, 244, 25, - 156, 188, 71, 245, 122, 93, 47, 218, 235, 25, 222, 191, 116, 20, 14, - 195, 114, - ], - }, - cred_protect: 1, - large_blob_key: [ - 223, 32, 77, 171, 223, 133, 38, 175, 229, 40, 85, 216, 203, 79, 194, - 223, 32, 191, 119, 241, 115, 6, 101, 180, 92, 194, 208, 193, 181, 163, - 164, 64, - ], - }, - ], - }, - { - rp: { id: "webauthn.io" }, - rp_id_hash: [ - 116, 166, 234, 146, 19, 201, 156, 47, 116, 178, 36, 146, 179, 32, 207, 64, - 38, 42, 148, 193, 169, 80, 160, 57, 127, 41, 37, 11, 96, 132, 30, 240, - ], - credentials: [ - { - user: { id: [97, 71, 104, 111, 97, 71, 104, 110], name: "hhhhhg" }, - credential_id: { - id: [ - 64, 132, 129, 5, 185, 62, 86, 253, 199, 113, 219, 14, 207, 113, 145, - 78, 177, 198, 130, 217, 122, 105, 225, 111, 32, 227, 237, 209, 6, - 220, 202, 234, 144, 227, 246, 42, 73, 68, 37, 142, 95, 139, 224, 36, - 156, 168, 118, 181, - ], - type: "public-key", - }, - public_key: { - 1: 2, - 3: -7, - "-1": 1, - "-2": [ - 64, 132, 129, 5, 185, 62, 86, 253, 199, 113, 219, 14, 207, 22, 10, - 241, 230, 152, 5, 204, 35, 94, 22, 191, 213, 2, 247, 220, 227, 62, - 76, 182, - ], - "-3": [ - 13, 30, 30, 149, 170, 118, 78, 115, 101, 218, 245, 52, 154, 242, 67, - 146, 17, 184, 112, 225, 51, 47, 242, 157, 195, 80, 76, 101, 147, - 161, 3, 185, - ], - }, - cred_protect: 1, - large_blob_key: [ - 10, 67, 27, 233, 8, 115, 69, 191, 105, 213, 77, 123, 210, 118, 193, - 234, 3, 12, 234, 228, 215, 106, 24, 228, 102, 247, 255, 156, 99, 196, - 215, 230, - ], - }, - { - user: { - id: [100, 72, 100, 108, 100, 72, 100, 108, 100, 72, 99], - name: "twetwetw", - }, - credential_id: { - id: [ - 29, 8, 25, 57, 66, 234, 22, 27, 227, 141, 77, 93, 233, 234, 251, 61, - 100, 199, 176, 97, 112, 48, 172, 118, 145, 0, 156, 76, 156, 215, 18, - 25, 118, 32, 241, 127, 13, 177, 249, 101, 26, 209, 142, 116, 74, 95, - 117, 29, - ], - type: "public-key", - }, - public_key: { - 1: 2, - 3: -7, - "-1": 1, - "-2": [ - 29, 8, 25, 57, 66, 234, 22, 27, 227, 141, 77, 93, 233, 154, 113, - 177, 251, 161, 54, 76, 150, 15, 6, 143, 117, 214, 232, 215, 118, 41, - 116, 19, - ], - "-3": [ - 201, 6, 43, 178, 3, 249, 175, 123, 149, 81, 127, 20, 116, 152, 238, - 84, 52, 113, 3, 165, 176, 105, 200, 137, 209, 0, 141, 50, 42, 192, - 174, 26, - ], - }, - cred_protect: 1, - large_blob_key: [ - 125, 175, 155, 1, 14, 247, 182, 241, 234, 66, 115, 236, 200, 223, 176, - 88, 88, 88, 202, 173, 147, 217, 9, 193, 114, 7, 29, 169, 224, 179, - 187, 188, - ], - }, - { - user: { - id: [90, 109, 70, 122, 90, 71, 90, 104, 99, 50, 81], - name: "fasdfasd", - }, - credential_id: { - id: [ - 58, 174, 92, 116, 17, 108, 28, 203, 233, 192, 182, 60, 80, 236, 133, - 196, 98, 32, 103, 53, 107, 48, 46, 236, 228, 166, 21, 33, 228, 75, - 85, 191, 71, 18, 214, 177, 56, 254, 89, 28, 187, 220, 241, 7, 21, - 11, 45, 151, - ], - type: "public-key", - }, - public_key: { - 1: 2, - 3: -7, - "-1": 1, - "-2": [ - 58, 174, 92, 116, 17, 108, 28, 203, 233, 192, 182, 60, 80, 111, 150, - 192, 102, 255, 211, 156, 5, 186, 29, 105, 154, 79, 14, 2, 106, 159, - 57, 156, - ], - "-3": [ - 182, 164, 251, 221, 237, 36, 239, 109, 146, 184, 146, 29, 143, 16, - 35, 188, 84, 148, 247, 83, 181, 40, 88, 111, 245, 13, 254, 206, 242, - 164, 234, 159, - ], - }, - cred_protect: 1, - large_blob_key: [ - 113, 154, 217, 69, 45, 108, 115, 20, 104, 43, 214, 120, 253, 93, 223, - 204, 125, 234, 220, 148, 98, 118, 98, 157, 175, 41, 154, 97, 87, 233, - 208, 171, - ], - }, - ], - }, -]; diff --git a/toolkit/components/aboutwebauthn/tests/browser/browser_aboutwebauthn_info.js b/toolkit/components/aboutwebauthn/tests/browser/browser_aboutwebauthn_info.js deleted file mode 100644 index f66f5929fc74..000000000000 --- a/toolkit/components/aboutwebauthn/tests/browser/browser_aboutwebauthn_info.js +++ /dev/null @@ -1,218 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -var doc, tab; - -add_setup(async function () { - info("Starting about:webauthn"); - tab = await BrowserTestUtils.openNewForegroundTab({ - gBrowser, - opening: "about:webauthn", - waitForLoad: true, - }); - - doc = tab.linkedBrowser.contentDocument; -}); - -registerCleanupFunction(async function () { - // Close tab. - await BrowserTestUtils.removeTab(tab); -}); - -function send_auth_data_and_check(auth_data) { - Services.obs.notifyObservers( - null, - "about-webauthn-prompt", - JSON.stringify({ type: "selected-device", auth_info: auth_data }) - ); - - let info_text = doc.getElementById("info-text-div"); - is(info_text.hidden, true, "Start prompt not hidden"); - - let info_section = doc.getElementById("token-info-section"); - isnot(info_section.style.display, "none", "Info section hidden"); -} - -add_task(async function multiple_devices() { - Services.obs.notifyObservers( - null, - "about-webauthn-prompt", - JSON.stringify({ type: "select-device" }) - ); - - let info_text = doc.getElementById("info-text-div"); - is(info_text.hidden, false, "Start prompt hidden"); - let field = doc.getElementById("info-text-field"); - is( - field.getAttribute("data-l10n-id"), - "about-webauthn-text-select-device", - "Field does not prompt user to touch device for selection" - ); -}); - -add_task(async function multiple_devices() { - send_auth_data_and_check(REAL_AUTH_INFO_1); - reset_about_page(doc); - send_auth_data_and_check(REAL_AUTH_INFO_2); - reset_about_page(doc); - send_auth_data_and_check(REAL_AUTH_INFO_3); - reset_about_page(doc); -}); - -// Yubikey BIO -const REAL_AUTH_INFO_1 = { - versions: ["U2F_V2", "FIDO_2_0", "FIDO_2_1_PRE", "FIDO_2_1"], - extensions: [ - "credProtect", - "hmac-secret", - "largeBlobKey", - "credBlob", - "minPinLength", - ], - aaguid: [ - 216, 82, 45, 159, 87, 91, 72, 102, 136, 169, 186, 153, 250, 2, 243, 91, - ], - options: { - plat: false, - rk: true, - clientPin: true, - up: true, - uv: true, - pinUvAuthToken: true, - noMcGaPermissionsWithClientPin: null, - largeBlobs: true, - ep: null, - bioEnroll: true, - userVerificationMgmtPreview: true, - uvBioEnroll: null, - authnrCfg: true, - uvAcfg: null, - credMgmt: true, - credentialMgmtPreview: true, - setMinPINLength: true, - makeCredUvNotRqd: true, - alwaysUv: false, - }, - max_msg_size: 1200, - pin_protocols: [2, 1], - max_credential_count_in_list: 8, - max_credential_id_length: 128, - transports: ["usb"], - algorithms: [ - { alg: -7, type: "public-key" }, - { alg: -8, type: "public-key" }, - ], - max_ser_large_blob_array: 1024, - force_pin_change: false, - min_pin_length: 4, - firmware_version: 328966, - max_cred_blob_length: 32, - max_rpids_for_set_min_pin_length: 1, - preferred_platform_uv_attempts: 3, - uv_modality: 2, - certifications: null, - remaining_discoverable_credentials: 20, - vendor_prototype_config_commands: null, -}; - -// Yubikey 5 -const REAL_AUTH_INFO_2 = { - versions: ["U2F_V2", "FIDO_2_0", "FIDO_2_1_PRE"], - extensions: ["credProtect", "hmac-secret"], - aaguid: [ - 47, 192, 87, 159, 129, 19, 71, 234, 177, 22, 187, 90, 141, 185, 32, 42, - ], - options: { - plat: false, - rk: true, - clientPin: true, - up: true, - uv: null, - pinUvAuthToken: null, - noMcGaPermissionsWithClientPin: null, - largeBlobs: null, - ep: null, - bioEnroll: null, - userVerificationMgmtPreview: null, - uvBioEnroll: null, - authnrCfg: null, - uvAcfg: null, - credMgmt: null, - credentialMgmtPreview: true, - setMinPINLength: null, - makeCredUvNotRqd: null, - alwaysUv: null, - }, - max_msg_size: 1200, - pin_protocols: [1], - max_credential_count_in_list: 8, - max_credential_id_length: 128, - transports: ["nfc", "usb"], - algorithms: [ - { alg: -7, type: "public-key" }, - { alg: -8, type: "public-key" }, - ], - max_ser_large_blob_array: null, - force_pin_change: null, - min_pin_length: null, - firmware_version: null, - max_cred_blob_length: null, - max_rpids_for_set_min_pin_length: null, - preferred_platform_uv_attempts: null, - uv_modality: null, - certifications: null, - remaining_discoverable_credentials: null, - vendor_prototype_config_commands: null, -}; - -// Nitrokey 3 -const REAL_AUTH_INFO_3 = { - versions: ["U2F_V2", "FIDO_2_0", "FIDO_2_1_PRE"], - extensions: ["credProtect", "hmac-secret"], - aaguid: [ - 47, 192, 87, 159, 129, 19, 71, 234, 177, 22, 187, 90, 141, 185, 32, 42, - ], - options: { - plat: false, - rk: true, - clientPin: true, - up: true, - uv: null, - pinUvAuthToken: null, - noMcGaPermissionsWithClientPin: null, - largeBlobs: null, - ep: null, - bioEnroll: null, - userVerificationMgmtPreview: null, - uvBioEnroll: null, - authnrCfg: null, - uvAcfg: null, - credMgmt: null, - credentialMgmtPreview: true, - setMinPINLength: null, - makeCredUvNotRqd: null, - alwaysUv: null, - }, - max_msg_size: 1200, - pin_protocols: [1], - max_credential_count_in_list: 8, - max_credential_id_length: 128, - transports: ["nfc", "usb"], - algorithms: [ - { alg: -7, type: "public-key" }, - { alg: -8, type: "public-key" }, - ], - max_ser_large_blob_array: null, - force_pin_change: null, - min_pin_length: null, - firmware_version: null, - max_cred_blob_length: null, - max_rpids_for_set_min_pin_length: null, - preferred_platform_uv_attempts: null, - uv_modality: null, - certifications: null, - remaining_discoverable_credentials: null, - vendor_prototype_config_commands: null, -}; diff --git a/toolkit/components/aboutwebauthn/tests/browser/browser_aboutwebauthn_no_token.js b/toolkit/components/aboutwebauthn/tests/browser/browser_aboutwebauthn_no_token.js deleted file mode 100644 index 3d6359f91216..000000000000 --- a/toolkit/components/aboutwebauthn/tests/browser/browser_aboutwebauthn_no_token.js +++ /dev/null @@ -1,49 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -var doc, tab; - -add_setup(async function () { - info("Starting about:webauthn"); - tab = await BrowserTestUtils.openNewForegroundTab({ - gBrowser, - opening: "about:webauthn", - waitForLoad: true, - }); - - doc = tab.linkedBrowser.contentDocument; -}); - -registerCleanupFunction(async function () { - // Close tab. - await BrowserTestUtils.removeTab(tab); -}); - -add_task(async function verify_page_no_token() { - let info_text = doc.getElementById("info-text-div"); - is(info_text.hidden, false, "info-text-div should be visible"); - let categories = doc.getElementById("categories"); - is(categories.hidden, true, "categories-sidebar should be invisible"); -}); - -add_task(async function verify_no_auth_info() { - let field = doc.getElementById("info-text-field"); - let promise = BrowserTestUtils.waitForMutationCondition( - field, - { attributes: true, attributeFilter: ["data-l10n-id"] }, - () => - field.getAttribute("data-l10n-id") === - "about-webauthn-text-non-ctap2-device" - ); - Services.obs.notifyObservers( - null, - "about-webauthn-prompt", - JSON.stringify({ type: "selected-device", auth_info: null }) - ); - await promise; - - let info_text = doc.getElementById("info-text-div"); - is(info_text.hidden, false); -}); diff --git a/toolkit/components/aboutwebauthn/tests/browser/browser_aboutwebauthn_pin.js b/toolkit/components/aboutwebauthn/tests/browser/browser_aboutwebauthn_pin.js deleted file mode 100644 index bdb70bda9873..000000000000 --- a/toolkit/components/aboutwebauthn/tests/browser/browser_aboutwebauthn_pin.js +++ /dev/null @@ -1,205 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -const ABOUT_URL = "about:webauthn"; - -var doc, tab; - -async function send_authinfo_and_open_pin_section(ops) { - reset_about_page(doc); - send_auth_info_and_check_categories(doc, ops); - - if (ops.clientPin !== null) { - let pin_tab_button = doc.getElementById("pin-tab-button"); - // Check if PIN section is visible - isnot( - pin_tab_button.style.display, - "none", - "PIN button in the sidebar not visible" - ); - - // Click the section and wait for it to open - let pin_section = doc.getElementById("set-change-pin-section"); - pin_tab_button.click(); - isnot(pin_section.style.display, "none", "PIN section not visible"); - is( - pin_tab_button.getAttribute("selected"), - "true", - "PIN section button not selected" - ); - } -} - -add_setup(async function () { - info("Starting about:webauthn"); - tab = await BrowserTestUtils.openNewForegroundTab({ - gBrowser, - opening: "about:webauthn", - waitForLoad: true, - }); - - doc = tab.linkedBrowser.contentDocument; -}); - -registerCleanupFunction(async function () { - // Close tab. - await BrowserTestUtils.removeTab(tab); -}); - -add_task(async function pin_not_supported() { - // Not setting clientPIN at all should lead to not showing it in the sidebar - send_authinfo_and_open_pin_section({ uv: true, clientPin: null }); - // Check if PIN section is invisible - let pin_tab_button = doc.getElementById("pin-tab-button"); - is(pin_tab_button.style.display, "none", "PIN button in the sidebar visible"); -}); - -add_task(async function pin_already_set() { - send_authinfo_and_open_pin_section({ clientPin: true }); - - let set_pin_button = doc.getElementById("set-pin-button"); - is(set_pin_button.style.display, "none", "Set PIN button visible"); - - let change_pin_button = doc.getElementById("change-pin-button"); - isnot( - change_pin_button.style.display, - "none", - "Change PIN button not visible" - ); - - let current_pin_div = doc.getElementById("current-pin-div"); - is(current_pin_div.hidden, false, "Current PIN field not visible"); - - // Test that the button is only active if both inputs are set the same - let new_pin = doc.getElementById("new-pin"); - let new_pin_repeat = doc.getElementById("new-pin-repeat"); - let current_pin = doc.getElementById("current-pin"); - - set_text(new_pin, "abcdefg"); - is(change_pin_button.disabled, true, "Change PIN button not disabled"); - set_text(new_pin_repeat, "abcde"); - is(change_pin_button.disabled, true, "Change PIN button not disabled"); - set_text(new_pin_repeat, "abcdefg"); - is(change_pin_button.disabled, true, "Change PIN button not disabled"); - set_text(current_pin, "1234567"); - is(change_pin_button.disabled, false, "Change PIN button disabled"); -}); - -add_task(async function pin_not_yet_set() { - send_authinfo_and_open_pin_section({ clientPin: false }); - - let set_pin_button = doc.getElementById("set-pin-button"); - isnot(set_pin_button.style.display, "none", "Set PIN button not visible"); - - let change_pin_button = doc.getElementById("change-pin-button"); - is(change_pin_button.style.display, "none", "Change PIN button visible"); - - let current_pin_div = doc.getElementById("current-pin-div"); - is(current_pin_div.hidden, true, "Current PIN field visible"); - - // Test that the button is only active if both inputs are set the same - let new_pin = doc.getElementById("new-pin"); - let new_pin_repeat = doc.getElementById("new-pin-repeat"); - - set_text(new_pin, "abcdefg"); - is(set_pin_button.disabled, true, "Set PIN button not disabled"); - set_text(new_pin_repeat, "abcde"); - is(set_pin_button.disabled, true, "Set PIN button not disabled"); - set_text(new_pin_repeat, "abcdefg"); - is(set_pin_button.disabled, false, "Set PIN button disabled"); -}); - -add_task(async function pin_switch_back_and_forth() { - // This will click the PIN section button - send_authinfo_and_open_pin_section({ clientPin: false }); - - let pin_tab_button = doc.getElementById("pin-tab-button"); - let pin_section = doc.getElementById("set-change-pin-section"); - let info_tab_button = doc.getElementById("info-tab-button"); - let info_section = doc.getElementById("token-info-section"); - - // Now click the "info"-button and verify the correct buttons are highlighted - info_tab_button.click(); - // await info_promise; - isnot(info_section.style.display, "none", "info section not visible"); - is( - info_tab_button.getAttribute("selected"), - "true", - "Info tab button not selected" - ); - isnot( - pin_tab_button.getAttribute("selected"), - "true", - "PIN tab button selected" - ); - - // Click back to the PIN section - pin_tab_button.click(); - isnot(pin_section.style.display, "none", "PIN section not visible"); - is( - pin_tab_button.getAttribute("selected"), - "true", - "PIN tab button not selected" - ); - isnot( - info_tab_button.getAttribute("selected"), - "true", - "Info button selected" - ); -}); - -add_task(async function invalid_pin() { - send_authinfo_and_open_pin_section({ clientPin: true }); - let pin_tab_button = doc.getElementById("pin-tab-button"); - // Click the section and wait for it to open - pin_tab_button.click(); - is( - pin_tab_button.getAttribute("selected"), - "true", - "PIN section button not selected" - ); - - let change_pin_button = doc.getElementById("change-pin-button"); - - // Test that the button is only active if both inputs are set the same - let new_pin = doc.getElementById("new-pin"); - let new_pin_repeat = doc.getElementById("new-pin-repeat"); - let current_pin = doc.getElementById("current-pin"); - - // Needed to activate change_pin_button - set_text(new_pin, "abcdefg"); - set_text(new_pin_repeat, "abcdefg"); - set_text(current_pin, "1234567"); - - // This should silently error out since we have no authenticator - change_pin_button.click(); - - // Now we fake a response from the authenticator, saying the PIN was invalid - let pin_required = doc.getElementById("pin-required-section"); - let msg = JSON.stringify({ type: "pin-required" }); - Services.obs.notifyObservers(null, "about-webauthn-prompt", msg); - isnot(pin_required.style.display, "none", "PIN required dialog not visible"); - - let info_tab_button = doc.getElementById("info-tab-button"); - is( - info_tab_button.classList.contains("disabled-category"), - true, - "Sidebar not disabled" - ); - - let pin_field = doc.getElementById("pin-required"); - let send_pin_button = doc.getElementById("send-pin-button"); - - set_text(pin_field, "654321"); - send_pin_button.click(); - - is( - pin_required.style.display, - "none", - "PIN required dialog did not disappear" - ); - let pin_section = doc.getElementById("set-change-pin-section"); - isnot(pin_section.style.display, "none", "PIN section did not reappear"); -}); diff --git a/toolkit/components/aboutwebauthn/tests/browser/head.js b/toolkit/components/aboutwebauthn/tests/browser/head.js deleted file mode 100644 index 8d99631f0610..000000000000 --- a/toolkit/components/aboutwebauthn/tests/browser/head.js +++ /dev/null @@ -1,43 +0,0 @@ -function set_text(field, text) { - field.value = text; - field.dispatchEvent(new Event("input")); -} - -async function reset_about_page(doc) { - let info_text = doc.getElementById("info-text-div"); - let msg = JSON.stringify({ type: "listen-success" }); - let promise = BrowserTestUtils.waitForMutationCondition( - info_text, - { attributes: true, attributeFilter: ["hidden"] }, - () => info_text.hidden !== false - ); - Services.obs.notifyObservers(null, "about-webauthn-prompt", msg); - await promise; -} - -async function send_auth_info_and_check_categories(doc, ops) { - let info_text = doc.getElementById("info-text-div"); - let msg = JSON.stringify({ - type: "selected-device", - auth_info: { options: ops }, - }); - - let promise = BrowserTestUtils.waitForMutationCondition( - info_text, - { attributes: true, attributeFilter: ["hidden"] }, - () => info_text.hidden - ); - Services.obs.notifyObservers(null, "about-webauthn-prompt", msg); - await promise; - - let categories = doc.getElementById("categories"); - is(categories.hidden, false, "categories sidebar not visible"); - - // Info should be shown always, so we use it as a canary - let info_tab_button = doc.getElementById("info-tab-button"); - isnot( - info_tab_button.style.display, - "none", - "Info button in the sidebar not visible" - ); -} diff --git a/toolkit/components/moz.build b/toolkit/components/moz.build index 4aa77c74c242..02d119e7f414 100644 --- a/toolkit/components/moz.build +++ b/toolkit/components/moz.build @@ -15,7 +15,6 @@ DIRS += [ "aboutcheckerboard", "aboutmemory", "aboutprocesses", - "aboutwebauthn", "alerts", "antitracking", "apppicker", diff --git a/toolkit/locales/en-US/toolkit/about/aboutWebauthn.ftl b/toolkit/locales/en-US/toolkit/about/aboutWebauthn.ftl deleted file mode 100644 index 4deb1f6d2846..000000000000 --- a/toolkit/locales/en-US/toolkit/about/aboutWebauthn.ftl +++ /dev/null @@ -1,127 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -### Localization for about:webauthn, a security token management page - -# Page title -# 'WebAuthn' is a protocol name and should not be translated -about-webauthn-page-title = About WebAuthn - -## Section titles - -about-webauthn-info-section-title = Device info -about-webauthn-info-subsection-title = Authenticator info -about-webauthn-options-subsection-title = Authenticator options -about-webauthn-pin-section-title = PIN Management -about-webauthn-credential-management-section-title = Manage credentials -about-webauthn-pin-required-section-title = PIN required - -## Info field texts - -about-webauthn-text-connect-device = Please connect a security token. -# If multiple devices are plugged in, they will blink and we are asking the user to select one by touching the device they want. -about-webauthn-text-select-device = Please select your desired security token by touching the device. -# CTAP2 refers to Client to Authenticator Protocol version 2 -about-webauthn-text-non-ctap2-device = Unable to manage options because your security token does not support CTAP2. -about-webauthn-text-not-available = Not available on this platform. - -## Results label - -about-webauthn-results-success = Success! -about-webauthn-results-general-error = Error! -# Variables: -# $retriesLeft (Number): number of tries left -about-webauthn-results-pin-invalid-error = - { $retriesLeft -> - [0] Error: Incorrect PIN. Try again. - [one] Error: Incorrect PIN. Try again. You have one attempt left. - *[other] Error: Incorrect PIN. Try again. You have { $retriesLeft } attempts left. - } -about-webauthn-results-pin-blocked-error = Error: There are no attempts left and your device has been locked, because the wrong PIN was provided too many times. The device needs a reset. -about-webauthn-results-pin-too-short-error = Error: The given PIN is too short. -about-webauthn-results-pin-too-long-error = Error: The given PIN is too long. -about-webauthn-results-pin-auth-blocked-error = Error: There were too many failed attempts in a row and PIN authentication has been temporarily blocked. Your device needs a power cycle (unplug and re-insert). -about-webauthn-results-cancelled-by-user-error = Error: Operation has been canceled by the user. - -## Labels - -about-webauthn-new-pin-label = New PIN: -about-webauthn-repeat-pin-label = Repeat new PIN: -about-webauthn-current-pin-label = Current PIN: -about-webauthn-pin-required-label = Please enter your PIN: -about-webauthn-credential-list-subsection-title = Credentials: -about-webauthn-credential-list-empty = No credentials found on device. - -## Buttons - -about-webauthn-current-set-pin-button = Set PIN -about-webauthn-current-change-pin-button = Change PIN -# List is a verb, as in "Show list of credentials" -about-webauthn-list-credentials-button = List credentials -about-webauthn-cancel-button = Cancel -about-webauthn-send-pin-button = OK -about-webauthn-delete-button = Delete - -## Authenticator options fields -## Option fields correspond to the CTAP2 option IDs and definitions found in https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#option-id - -about-webauthn-auth-option-uv = User verification -about-webauthn-auth-option-up = User presence -about-webauthn-auth-option-clientpin = Client PIN -about-webauthn-auth-option-rk = Resident key -about-webauthn-auth-option-plat = Platform device -# pinUvAuthToken should not be translated. -about-webauthn-auth-option-pinuvauthtoken = Command permissions (pinUvAuthToken) -# MakeCredential and GetAssertion should not be translated. -about-webauthn-auth-option-nomcgapermissionswithclientpin = No MakeCredential / GetAssertion permissions with client PIN -about-webauthn-auth-option-largeblobs = Large blobs -about-webauthn-auth-option-ep = Enterprise attestation -about-webauthn-auth-option-bioenroll = Biometric enrollment -# FIDO_2_1_PRE should not be translated. -about-webauthn-auth-option-userverificationmgmtpreview = Prototype of biometric enrollment (FIDO_2_1_PRE) -about-webauthn-auth-option-uvbioenroll = Biometric enrollment permission -about-webauthn-auth-option-authnrcfg = Authenticator config -about-webauthn-auth-option-uvacfg = Authenticator config permission -about-webauthn-auth-option-credmgmt = Credential management -about-webauthn-auth-option-credentialmgmtpreview = Prototype credential management -about-webauthn-auth-option-setminpinlength = Set minimum PIN length -# MakeCredential should not be translated. -about-webauthn-auth-option-makecreduvnotrqd = MakeCredential without user verification -about-webauthn-auth-option-alwaysuv = Always require user verification -# Shows when boolean value for an option is True. True should not be translated. -about-webauthn-auth-option-true = True -# Shows when boolean value of an option is False. False should not be translated. -about-webauthn-auth-option-false = False -# If the value is missing (null), it means a certain feature is not supported. -about-webauthn-auth-option-null = Not supported - -## Authenticator info fields -## Info fields correspond to the CTAP2 authenticatorGetInfo field member name and definitions found in https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#authenticatorGetInfo - -about-webauthn-auth-info-vendor-prototype-config-commands = Vendor prototype config commands -about-webauthn-auth-info-remaining-discoverable-credentials = Remaining discoverable credentials -about-webauthn-auth-info-certifications = Certifications -about-webauthn-auth-info-uv-modality = User verification modality -about-webauthn-auth-info-preferred-platform-uv-attempts = Preferred platform user verification attempts -about-webauthn-auth-info-max-rpids-for-set-min-pin-length = Max relying party IDs for set minimum PIN length -about-webauthn-auth-info-max-cred-blob-length = Max credential blob length -about-webauthn-auth-info-firmware-version = Firmware version -about-webauthn-auth-info-min-pin-length = Minimum PIN length -about-webauthn-auth-info-force-pin-change = Force PIN change -about-webauthn-auth-info-max-ser-large-blob-array = Max size of large blob array -about-webauthn-auth-info-algorithms = Algorithms -about-webauthn-auth-info-transports = Transports -about-webauthn-auth-info-max-credential-id-length = Max credential ID length -about-webauthn-auth-info-max-credential-count-in-list = Max credential count in list -about-webauthn-auth-info-pin-protocols = PIN protocols -about-webauthn-auth-info-max-msg-size = Max message size -# AAGUID should not be translated. -about-webauthn-auth-info-aaguid = AAGUID -about-webauthn-auth-info-extensions = Extensions -about-webauthn-auth-info-versions = Versions -# Shows when boolean value for an info field is True. True should not be translated. -about-webauthn-auth-info-true = True -# Shows when boolean value for an info field is False. False should not be translated. -about-webauthn-auth-info-false = False -about-webauthn-auth-info-null = Not supported -- 2.11.4.GIT