Skip to main content

script/dom/credentialmanagement/
credentialscontainer.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4use dom_struct::dom_struct;
5use js::context::JSContext;
6use js::realm::CurrentRealm;
7use script_bindings::codegen::GenericBindings::CredentialsContainerBinding::{
8    CredentialCreationOptions, CredentialRequestOptions,
9};
10use script_bindings::codegen::GenericBindings::WindowBinding::WindowMethods;
11use script_bindings::error::{Error, Fallible};
12use script_bindings::reflector::{Reflector, reflect_dom_object_with_cx};
13
14use crate::dom::bindings::codegen::Bindings::CredentialsContainerBinding::CredentialsContainerMethods;
15use crate::dom::bindings::codegen::DomTypeHolder::DomTypeHolder;
16use crate::dom::bindings::root::DomRoot;
17use crate::dom::credentialmanagement::credential::Credential;
18use crate::dom::globalscope::GlobalScope;
19use crate::dom::promise::{Promise, RootedPromise};
20
21#[dom_struct]
22pub(crate) struct CredentialsContainer {
23    reflector_: Reflector,
24}
25
26impl CredentialsContainer {
27    pub(crate) fn new_inherited() -> CredentialsContainer {
28        CredentialsContainer {
29            reflector_: Reflector::new(),
30        }
31    }
32
33    pub(crate) fn new(cx: &mut JSContext, global: &GlobalScope) -> DomRoot<CredentialsContainer> {
34        reflect_dom_object_with_cx(Box::new(CredentialsContainer::new_inherited()), global, cx)
35    }
36
37    /// <https://www.w3.org/TR/credential-management-1/#abstract-opdef-request-a-credential>
38    fn request_credential(
39        &self,
40        cx: &mut CurrentRealm,
41        options: &CredentialRequestOptions<DomTypeHolder>,
42    ) -> Fallible<RootedPromise> {
43        // Step 1. Let settings be the current settings object.
44        let global = GlobalScope::from_current_realm(cx);
45        // Step 2. Assert: settings is a secure context.
46        assert!(global.is_secure_context());
47        // Step 3. Let document be settings’s relevant global object's associated Document.
48        let document = global.as_window().Document();
49
50        let promise = Promise::new_in_realm_rooted(cx);
51        // Step 4. If document is not fully active, then return a promise rejected with an "InvalidStateError" DOMException.
52        if !document.is_fully_active() {
53            promise.reject_error(cx, Error::InvalidState(None));
54            return Ok(promise);
55        }
56        // Step 5. If options.signal is aborted, then return a promise rejected with options.signal’s abort reason.
57        if options.signal.as_ref().is_some_and(|s| s.aborted()) {
58            promise.reject_error(cx, Error::Abort(None));
59            return Ok(promise);
60        }
61        promise.reject_error(cx, Error::NotSupported(None));
62        Ok(promise)
63    }
64
65    /// <https://www.w3.org/TR/credential-management-1/#abstract-opdef-store-a-credential>
66    fn store_credential(
67        &self,
68        cx: &mut CurrentRealm,
69        _credential: &Credential,
70    ) -> Fallible<RootedPromise> {
71        // Step 1. Let settings be the current settings object.
72        let global = GlobalScope::from_current_realm(cx);
73        // Step 2. Assert: settings is a secure context.
74        assert!(global.is_secure_context());
75
76        let promise = Promise::new_in_realm_rooted(cx);
77        // Step 3. If settings’s relevant global object's associated Document is not fully active, then return a promise rejected with an "InvalidStateError" DOMException.
78        if !global.as_window().Document().is_fully_active() {
79            promise.reject_error(cx, Error::InvalidState(None));
80            return Ok(promise);
81        }
82        promise.reject_error(cx, Error::NotSupported(None));
83        Ok(promise)
84    }
85
86    /// <https://www.w3.org/TR/credential-management-1/#abstract-opdef-create-a-credential>
87    fn create_credential(
88        &self,
89        cx: &mut CurrentRealm,
90        _options: &CredentialCreationOptions<DomTypeHolder>,
91    ) -> Fallible<RootedPromise> {
92        // Step 1. Let settings be the current settings object.
93        let global = GlobalScope::from_current_realm(cx);
94        // Step 2. Assert: settings is a secure context.
95        assert!(global.is_secure_context());
96        // Step 3. Let global be settings’ global object.
97        // Step 4. Let document be the relevant global object’s associated Document.
98        let document = global.as_window().Document();
99
100        let promise = Promise::new_in_realm_rooted(cx);
101        // Step 5. If document is not fully active, then return a promise rejected with an "InvalidStateError" DOMException.
102        if !document.is_fully_active() {
103            promise.reject_error(cx, Error::InvalidState(None));
104            return Ok(promise);
105        }
106        promise.reject_error(cx, Error::NotSupported(None));
107        Ok(promise)
108    }
109}
110
111impl CredentialsContainerMethods<DomTypeHolder> for CredentialsContainer {
112    /// <https://www.w3.org/TR/credential-management-1/#dom-credentialscontainer-get>
113    fn Get(
114        &self,
115        cx: &mut CurrentRealm,
116        options: &CredentialRequestOptions<DomTypeHolder>,
117    ) -> Fallible<RootedPromise> {
118        self.request_credential(cx, options)
119    }
120
121    /// <https://www.w3.org/TR/credential-management-1/#dom-credentialscontainer-store>
122    fn Store(&self, cx: &mut CurrentRealm, credential: &Credential) -> Fallible<RootedPromise> {
123        self.store_credential(cx, credential)
124    }
125
126    /// <https://www.w3.org/TR/credential-management-1/#dom-credentialscontainer-create>
127    fn Create(
128        &self,
129        cx: &mut CurrentRealm,
130        options: &CredentialCreationOptions<DomTypeHolder>,
131    ) -> Fallible<RootedPromise> {
132        self.create_credential(cx, options)
133    }
134
135    /// <https://www.w3.org/TR/credential-management-1/#dom-credentialscontainer-preventsilentaccess>
136    fn PreventSilentAccess(&self, cx: &mut CurrentRealm) -> Fallible<RootedPromise> {
137        let promise = Promise::new_in_realm_rooted(cx);
138        promise.reject_error(cx, Error::NotSupported(None));
139        Ok(promise)
140    }
141}