From 4e4b137eaa242fea4356e30b36f9ef3262781968 Mon Sep 17 00:00:00 2001 From: Daniel Adams <70986246+msub2@users.noreply.github.com> Date: Sat, 21 Sep 2024 09:50:05 +0000 Subject: [PATCH] bindings: Allow Guard to take multiple conditions, check for SecureContext in ConstructorEnabled (#33508) * Update condition handling for exposing values - Let Guard take a list of conditions - Check for secure context condition when exposing constructor Signed-off-by: Daniel Adams * Update WPT expectations Signed-off-by: Daniel Adams * Python tidy Signed-off-by: Daniel Adams * Make interfaces test run in secure context Signed-off-by: Daniel Adams --------- Signed-off-by: Daniel Adams --- .../dom/bindings/codegen/CodegenRust.py | 35 ++++++++++++------- components/script/dom/bindings/guard.rs | 27 ++++++++++---- .../webxr_availability.http.sub.html.ini | 7 ---- .../webxr_availability.http.sub.html.ini | 6 ---- ...ces.html.ini => interfaces.https.html.ini} | 0 tests/wpt/mozilla/meta/MANIFEST.json | 2 +- ...ces.html.ini => interfaces.https.html.ini} | 0 ...{interfaces.html => interfaces.https.html} | 0 8 files changed, 45 insertions(+), 32 deletions(-) delete mode 100644 tests/wpt/meta-legacy-layout/webxr/webxr_availability.http.sub.html.ini delete mode 100644 tests/wpt/meta/webxr/webxr_availability.http.sub.html.ini rename tests/wpt/mozilla/meta-legacy-layout/mozilla/{interfaces.html.ini => interfaces.https.html.ini} (100%) rename tests/wpt/mozilla/meta/mozilla/{interfaces.html.ini => interfaces.https.html.ini} (100%) rename tests/wpt/mozilla/tests/mozilla/{interfaces.html => interfaces.https.html} (100%) diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 498979c3b63..78e9588877e 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -1545,15 +1545,20 @@ def MemberCondition(pref, func, exposed, secure): assert func is None or isinstance(func, str) assert exposed is None or isinstance(exposed, set) assert func is None or pref is None or exposed is None or secure is None + conditions = [] if secure: - return 'Condition::SecureContext()' + conditions.append('Condition::SecureContext()') if pref: - return f'Condition::Pref("{pref}")' + conditions.append(f'Condition::Pref("{pref}")') if func: - return f'Condition::Func({func})' + conditions.append(f'Condition::Func({func})') if exposed: - return [f"Condition::Exposed(InterfaceObjectMap::Globals::{camel_to_upper_snake(i)})" for i in exposed] - return "Condition::Satisfied" + conditions.extend([ + f"Condition::Exposed(InterfaceObjectMap::Globals::{camel_to_upper_snake(i)})" for i in exposed + ]) + if len(conditions) == 0: + conditions.append("Condition::Satisfied") + return conditions class PropertyDefiner: @@ -1639,13 +1644,10 @@ class PropertyDefiner: currentSpecs.append(specTerminator) joinedCurrentSpecs = ',\n'.join(currentSpecs) specs.append(f"&[\n{joinedCurrentSpecs}]\n") - if isinstance(cond, list): - for i in cond: - prefableSpecs.append( - prefableTemplate % (i, f"{name}_specs", len(specs) - 1)) - else: - prefableSpecs.append( - prefableTemplate % (cond, f"{name}_specs", len(specs) - 1)) + conds = ','.join(cond) if isinstance(cond, list) else cond + prefableSpecs.append( + prefableTemplate % (f"&[{conds}]", f"{name}_specs", len(specs) - 1) + ) joinedSpecs = ',\n'.join(specs) specsArray = (f"const {name}_specs: &[&[{specType}]] = &[\n" @@ -2815,6 +2817,15 @@ class CGConstructorEnabled(CGAbstractMethod): assert isinstance(func, list) and len(func) == 1 conditions.append(f"{func[0]}(aCx, aObj)") + secure = iface.getExtendedAttribute("SecureContext") + if secure: + conditions.append(""" +unsafe { + let in_realm_proof = AlreadyInRealm::assert_for_cx(aCx); + GlobalScope::from_context(*aCx, InRealm::Already(&in_realm_proof)).is_secure_context() +} +""") + return CGList((CGGeneric(cond) for cond in conditions), " &&\n") diff --git a/components/script/dom/bindings/guard.rs b/components/script/dom/bindings/guard.rs index ca8dbb1d1cd..883d3067214 100644 --- a/components/script/dom/bindings/guard.rs +++ b/components/script/dom/bindings/guard.rs @@ -13,23 +13,37 @@ use crate::dom::globalscope::GlobalScope; use crate::realms::{AlreadyInRealm, InRealm}; use crate::script_runtime::JSContext; -/// A container with a condition. +/// A container with a list of conditions. pub struct Guard { - condition: Condition, + conditions: &'static [Condition], value: T, } impl Guard { /// Construct a new guarded value. - pub const fn new(condition: Condition, value: T) -> Self { - Guard { condition, value } + pub const fn new(conditions: &'static [Condition], value: T) -> Self { + Guard { conditions, value } } - /// Expose the value if the condition is satisfied. + /// Expose the value if the conditions are satisfied. /// /// The passed handle is the object on which the value may be exposed. pub fn expose(&self, cx: JSContext, obj: HandleObject, global: HandleObject) -> Option { - if self.condition.is_satisfied(cx, obj, global) { + let mut exposed_on_global = false; + let conditions_satisfied = self.conditions.iter().all(|c| match c { + Condition::Satisfied => { + exposed_on_global = true; + true + }, + // If there are multiple Exposed conditions, we just need one of them to be true + Condition::Exposed(globals) => { + exposed_on_global |= is_exposed_in(global, *globals); + true + }, + _ => c.is_satisfied(cx, obj, global), + }); + + if conditions_satisfied && exposed_on_global { Some(self.value) } else { None @@ -38,6 +52,7 @@ impl Guard { } /// A condition to expose things. +#[derive(Clone, Copy)] pub enum Condition { /// The condition is satisfied if the function returns true. Func(fn(JSContext, HandleObject) -> bool), diff --git a/tests/wpt/meta-legacy-layout/webxr/webxr_availability.http.sub.html.ini b/tests/wpt/meta-legacy-layout/webxr/webxr_availability.http.sub.html.ini deleted file mode 100644 index bff309dd988..00000000000 --- a/tests/wpt/meta-legacy-layout/webxr/webxr_availability.http.sub.html.ini +++ /dev/null @@ -1,7 +0,0 @@ -[webxr_availability.http.sub.html] - [Test webxr not available in secure context in insecure context] - expected: FAIL - - [Test webxr not available in insecure context] - expected: FAIL - diff --git a/tests/wpt/meta/webxr/webxr_availability.http.sub.html.ini b/tests/wpt/meta/webxr/webxr_availability.http.sub.html.ini deleted file mode 100644 index 35d87850911..00000000000 --- a/tests/wpt/meta/webxr/webxr_availability.http.sub.html.ini +++ /dev/null @@ -1,6 +0,0 @@ -[webxr_availability.http.sub.html] - [Test webxr not available in insecure context] - expected: FAIL - - [Test webxr not available in secure context in insecure context] - expected: FAIL diff --git a/tests/wpt/mozilla/meta-legacy-layout/mozilla/interfaces.html.ini b/tests/wpt/mozilla/meta-legacy-layout/mozilla/interfaces.https.html.ini similarity index 100% rename from tests/wpt/mozilla/meta-legacy-layout/mozilla/interfaces.html.ini rename to tests/wpt/mozilla/meta-legacy-layout/mozilla/interfaces.https.html.ini diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index 2fa080d0353..7910cd2ddb2 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -13494,7 +13494,7 @@ {} ] ], - "interfaces.html": [ + "interfaces.https.html": [ "94f1102da478919d2948ebb96f81450f5d545635", [ null, diff --git a/tests/wpt/mozilla/meta/mozilla/interfaces.html.ini b/tests/wpt/mozilla/meta/mozilla/interfaces.https.html.ini similarity index 100% rename from tests/wpt/mozilla/meta/mozilla/interfaces.html.ini rename to tests/wpt/mozilla/meta/mozilla/interfaces.https.html.ini diff --git a/tests/wpt/mozilla/tests/mozilla/interfaces.html b/tests/wpt/mozilla/tests/mozilla/interfaces.https.html similarity index 100% rename from tests/wpt/mozilla/tests/mozilla/interfaces.html rename to tests/wpt/mozilla/tests/mozilla/interfaces.https.html