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