1use js::context::JSContext;
8use js::realm::CurrentRealm;
9use js::rust::HandleObject;
10use servo_config::prefs::get;
11
12use crate::DomTypes;
13use crate::codegen::Globals::Globals;
14use crate::interface::is_exposed_in;
15use crate::interfaces::GlobalScopeHelpers;
16
17pub(crate) struct Guard<T: Clone + Copy> {
19 conditions: &'static [Condition],
20 value: T,
21}
22
23impl<T: Clone + Copy> Guard<T> {
24 pub(crate) const fn new(conditions: &'static [Condition], value: T) -> Self {
26 Guard { conditions, value }
27 }
28
29 pub(crate) fn expose<D: DomTypes>(
33 &self,
34 cx: &mut JSContext,
35 obj: HandleObject,
36 global: HandleObject,
37 ) -> Option<T> {
38 let mut exposed_on_global = false;
39 let conditions_satisfied = self.conditions.iter().all(|c| match c {
40 Condition::Satisfied => {
41 exposed_on_global = true;
42 true
43 },
44 Condition::Exposed(globals) => {
46 exposed_on_global |= is_exposed_in(global, *globals);
47 true
48 },
49 _ => c.is_satisfied::<D>(cx, obj, global),
50 });
51
52 if conditions_satisfied && exposed_on_global {
53 Some(self.value)
54 } else {
55 None
56 }
57 }
58}
59
60#[derive(Clone, Copy)]
62pub(crate) enum Condition {
63 Func(fn(&mut JSContext, HandleObject) -> bool),
65 Pref(&'static str),
67 Exposed(Globals),
69 SecureContext(),
70 Satisfied,
72}
73
74fn is_secure_context<D: DomTypes>(cx: &mut JSContext) -> bool {
75 let realm = CurrentRealm::assert(cx);
76 D::GlobalScope::from_current_realm(&realm).is_secure_context()
77}
78
79impl Condition {
80 pub(crate) fn is_satisfied<D: DomTypes>(
81 &self,
82 cx: &mut JSContext,
83 obj: HandleObject,
84 global: HandleObject,
85 ) -> bool {
86 match *self {
87 Condition::Pref(name) => get().get_value(name).try_into().unwrap_or(false),
88 Condition::Func(f) => f(cx, obj),
89 Condition::Exposed(globals) => is_exposed_in(global, globals),
90 Condition::SecureContext() => is_secure_context::<D>(cx),
91 Condition::Satisfied => true,
92 }
93 }
94}