script: Initial stubs for Credential Management API (#38839)

Stubs `Credential`, `CredentialContainer`, and `PasswordCredential` and
adds the credentials attribute to navigator.

Testing: WPT
Fixes: Partially #38788

---------

Signed-off-by: Ashwin Naren <arihant2math@gmail.com>
This commit is contained in:
Ashwin Naren 2025-09-06 12:48:38 -07:00 committed by GitHub
parent 643ac08cf0
commit 3ac8875697
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 347 additions and 0 deletions

View file

@ -0,0 +1,73 @@
/* 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 https://mozilla.org/MPL/2.0/. */
use std::rc::Rc;
use dom_struct::dom_struct;
use script_bindings::realms::{AlreadyInRealm, InRealm};
use script_bindings::str::{DOMString, USVString};
use crate::dom::bindings::codegen::Bindings::CredentialBinding::CredentialMethods;
use crate::dom::bindings::codegen::DomTypeHolder::DomTypeHolder;
use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
use crate::dom::bindings::root::DomRoot;
use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise;
use crate::dom::window::Window;
use crate::script_runtime::CanGc;
#[dom_struct]
pub(crate) struct Credential {
reflector_: Reflector,
id: USVString,
credential_type: DOMString,
}
impl Credential {
pub(crate) fn new_inherited(id: USVString, credential_type: DOMString) -> Credential {
Credential {
reflector_: Reflector::new(),
id,
credential_type,
}
}
#[expect(dead_code)]
pub(crate) fn new(
global: &GlobalScope,
id: USVString,
credential_type: DOMString,
can_gc: CanGc,
) -> DomRoot<Credential> {
reflect_dom_object(
Box::new(Credential::new_inherited(id, credential_type)),
global,
can_gc,
)
}
}
impl CredentialMethods<DomTypeHolder> for Credential {
// https://www.w3.org/TR/credential-management-1/#dom-credential-id
fn Id(&self) -> USVString {
self.id.clone()
}
// https://www.w3.org/TR/credential-management-1/#dom-credential-type
fn Type(&self) -> DOMString {
self.credential_type.clone()
}
// https://www.w3.org/TR/credential-management-1/#dom-credential-isconditionalmediationavailable
fn IsConditionalMediationAvailable(_global: &Window) -> Rc<Promise> {
let in_realm_proof = AlreadyInRealm::assert::<DomTypeHolder>();
// FIXME:(arihant2math) return false
Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), CanGc::note())
}
// https://www.w3.org/TR/credential-management-1/#dom-credential-willrequestconditionalcreation
fn WillRequestConditionalCreation(_global: &Window) -> Rc<Promise> {
let in_realm_proof = AlreadyInRealm::assert::<DomTypeHolder>();
Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), CanGc::note())
}
}

View file

@ -0,0 +1,62 @@
/* 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 https://mozilla.org/MPL/2.0/. */
use std::rc::Rc;
use dom_struct::dom_struct;
use script_bindings::codegen::GenericBindings::CredentialsContainerBinding::{
CredentialCreationOptions, CredentialRequestOptions,
};
use script_bindings::error::{Error, Fallible};
use crate::dom::bindings::codegen::Bindings::CredentialsContainerBinding::CredentialsContainerMethods;
use crate::dom::bindings::codegen::DomTypeHolder::DomTypeHolder;
use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
use crate::dom::bindings::root::DomRoot;
use crate::dom::credentialmanagement::credential::Credential;
use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise;
use crate::script_runtime::CanGc;
#[dom_struct]
pub(crate) struct CredentialsContainer {
reflector_: Reflector,
}
impl CredentialsContainer {
pub(crate) fn new_inherited() -> CredentialsContainer {
CredentialsContainer {
reflector_: Reflector::new(),
}
}
pub(crate) fn new(global: &GlobalScope, can_gc: CanGc) -> DomRoot<CredentialsContainer> {
reflect_dom_object(
Box::new(CredentialsContainer::new_inherited()),
global,
can_gc,
)
}
}
impl CredentialsContainerMethods<DomTypeHolder> for CredentialsContainer {
// https://www.w3.org/TR/credential-management-1/#dom-credentialscontainer-get
fn Get(&self, _options: &CredentialRequestOptions<DomTypeHolder>) -> Fallible<Rc<Promise>> {
Err(Error::NotSupported)
}
// https://www.w3.org/TR/credential-management-1/#dom-credentialscontainer-store
fn Store(&self, _credential: &Credential) -> Fallible<Rc<Promise>> {
Err(Error::NotSupported)
}
// https://www.w3.org/TR/credential-management-1/#dom-credentialscontainer-create
fn Create(&self, _options: &CredentialCreationOptions<DomTypeHolder>) -> Fallible<Rc<Promise>> {
Err(Error::NotSupported)
}
// https://www.w3.org/TR/credential-management-1/#dom-credentialscontainer-preventsilentaccess
fn PreventSilentAccess(&self) -> Fallible<Rc<Promise>> {
Err(Error::NotSupported)
}
}

View file

@ -0,0 +1,7 @@
/* 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 https://mozilla.org/MPL/2.0/. */
pub(crate) mod credential;
pub(crate) mod credentialscontainer;
pub(crate) mod passwordcredential;

View file

@ -0,0 +1,98 @@
/* 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 https://mozilla.org/MPL/2.0/. */
use dom_struct::dom_struct;
use js::gc::HandleObject;
use script_bindings::codegen::GenericBindings::PasswordCredentialBinding::PasswordCredentialData;
use script_bindings::error::{Error, Fallible};
use script_bindings::str::USVString;
use crate::dom::bindings::codegen::Bindings::PasswordCredentialBinding::PasswordCredentialMethods;
use crate::dom::bindings::codegen::DomTypeHolder::DomTypeHolder;
use crate::dom::bindings::reflector::{reflect_dom_object, reflect_dom_object_with_proto};
use crate::dom::bindings::root::DomRoot;
use crate::dom::credentialmanagement::credential::Credential;
use crate::dom::globalscope::GlobalScope;
use crate::dom::htmlformelement::HTMLFormElement;
use crate::dom::window::Window;
use crate::script_runtime::CanGc;
#[dom_struct]
pub(crate) struct PasswordCredential {
credential: Credential,
origin: USVString,
password: USVString,
}
impl PasswordCredential {
fn new_inherited(id: USVString, origin: USVString, password: USVString) -> PasswordCredential {
PasswordCredential {
credential: Credential::new_inherited(id, "password".into()),
origin,
password,
}
}
#[expect(dead_code)]
pub(crate) fn new(
global: &GlobalScope,
id: USVString,
origin: USVString,
password: USVString,
can_gc: CanGc,
) -> DomRoot<PasswordCredential> {
reflect_dom_object(
Box::new(PasswordCredential::new_inherited(id, origin, password)),
global,
can_gc,
)
}
pub(crate) fn new_with_proto(
global: &GlobalScope,
proto: Option<HandleObject>,
id: USVString,
origin: USVString,
password: USVString,
can_gc: CanGc,
) -> DomRoot<PasswordCredential> {
reflect_dom_object_with_proto(
Box::new(PasswordCredential::new_inherited(id, origin, password)),
global,
proto,
can_gc,
)
}
}
impl PasswordCredentialMethods<DomTypeHolder> for PasswordCredential {
fn Password(&self) -> USVString {
self.password.clone()
}
fn Constructor(
_global: &Window,
_proto: Option<HandleObject>,
_can_gc: CanGc,
_form: &HTMLFormElement,
) -> Fallible<DomRoot<PasswordCredential>> {
Err(Error::NotSupported)
}
fn Constructor_(
global: &Window,
proto: Option<HandleObject>,
can_gc: CanGc,
data: &PasswordCredentialData,
) -> Fallible<DomRoot<PasswordCredential>> {
Ok(Self::new_with_proto(
global.as_global_scope(),
proto,
data.parent.id.clone(),
data.origin.clone(),
data.password.clone(),
can_gc,
))
}
}