use dom_struct::dom_struct;
use js::context::JSContext;
use js::jsapi::Type;
use js::rust::CustomAutoRooterGuard;
use js::typedarray::{ArrayBufferView, HeapArrayBufferView};
use script_bindings::buffer_source::HeapBufferSource;
use script_bindings::reflector::{Reflector, reflect_dom_object};
use script_bindings::trace::RootedTraceableBox;
use uuid::Uuid;
use crate::dom::bindings::codegen::Bindings::CryptoBinding::CryptoMethods;
use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::reflector::DomGlobal;
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
use crate::dom::bindings::str::DOMString;
use crate::dom::globalscope::GlobalScope;
use crate::dom::subtlecrypto::SubtleCrypto;
#[dom_struct]
pub(crate) struct Crypto {
reflector_: Reflector,
subtle: MutNullableDom<SubtleCrypto>,
}
impl Crypto {
fn new_inherited() -> Crypto {
Crypto {
reflector_: Reflector::new(),
subtle: MutNullableDom::default(),
}
}
pub(crate) fn new(cx: &mut JSContext, global: &GlobalScope) -> DomRoot<Crypto> {
reflect_dom_object(cx, Box::new(Crypto::new_inherited()), global)
}
}
impl CryptoMethods<crate::DomTypeHolder> for Crypto {
fn Subtle(&self, cx: &mut JSContext) -> DomRoot<SubtleCrypto> {
self.subtle
.or_init(|| SubtleCrypto::new(cx, &self.global()))
}
fn GetRandomValues(
&self,
cx: &mut JSContext,
mut array: CustomAutoRooterGuard<ArrayBufferView>,
) -> Fallible<RootedTraceableBox<HeapArrayBufferView>> {
if !matches!(
array.get_array_type(),
Type::Int8 |
Type::Uint8 |
Type::Uint8Clamped |
Type::Int16 |
Type::Uint16 |
Type::Int32 |
Type::Uint32 |
Type::BigInt64 |
Type::BigUint64
) {
return Err(Error::TypeMismatch(Some(
"The array must be an integer-based TypedArray".into(),
)));
}
let bytes = array.as_mut_slice_safe(cx.no_gc()).unwrap_or_default();
let byte_length = bytes.len();
if byte_length > 65536 {
return Err(Error::QuotaExceeded {
quota: None,
requested: None,
});
}
rand::fill(bytes);
let array = HeapBufferSource::from_view(cx, array);
array.get_typed_array().map_err(|_| Error::JSFailed)
}
fn RandomUUID(&self) -> DOMString {
let uuid = Uuid::new_v4();
uuid.hyphenated()
.encode_lower(&mut Uuid::encode_buffer())
.to_owned()
.into()
}
}