diff options
6 files changed, 66 insertions, 15 deletions
diff --git a/components/script/dom/webidls/XR.webidl b/components/script/dom/webidls/XR.webidl index 2bee5c07cd8..8b0311f0c3f 100644 --- a/components/script/dom/webidls/XR.webidl +++ b/components/script/dom/webidls/XR.webidl @@ -25,8 +25,8 @@ enum XRSessionMode { }; dictionary XRSessionInit { - sequence<DOMString> requiredFeatures; - sequence<DOMString> optionalFeatures; + sequence<any> requiredFeatures; + sequence<any> optionalFeatures; }; partial interface XR { diff --git a/components/script/dom/webidls/XRTest.webidl b/components/script/dom/webidls/XRTest.webidl index a190fd75472..914bcb2d54d 100644 --- a/components/script/dom/webidls/XRTest.webidl +++ b/components/script/dom/webidls/XRTest.webidl @@ -23,6 +23,9 @@ dictionary FakeXRDeviceInit { required boolean supportsImmersive; required sequence<FakeXRViewInit> views; + // this is actually sequence<any>, but we don't support + // non-string features anyway + sequence<DOMString> supportedFeatures; boolean supportsUnbounded = false; // Whether the space supports tracking in inline sessions boolean supportsTrackingInInline = true; diff --git a/components/script/dom/xr.rs b/components/script/dom/xr.rs index 5804918a532..a2c4fd059f0 100644 --- a/components/script/dom/xr.rs +++ b/components/script/dom/xr.rs @@ -8,11 +8,13 @@ use crate::dom::bindings::codegen::Bindings::VRDisplayBinding::VRDisplayMethods; use crate::dom::bindings::codegen::Bindings::XRBinding; use crate::dom::bindings::codegen::Bindings::XRBinding::XRSessionInit; use crate::dom::bindings::codegen::Bindings::XRBinding::{XRMethods, XRSessionMode}; +use crate::dom::bindings::conversions::{ConversionResult, FromJSValConvertible}; use crate::dom::bindings::error::Error; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::refcounted::{Trusted, TrustedPromise}; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom}; +use crate::dom::bindings::trace::RootedTraceableBox; use crate::dom::event::Event; use crate::dom::eventtarget::EventTarget; use crate::dom::gamepad::Gamepad; @@ -33,7 +35,7 @@ use std::cell::Cell; use std::rc::Rc; use webvr_traits::{WebVRDisplayData, WebVRDisplayEvent, WebVREvent, WebVRMsg}; use webvr_traits::{WebVRGamepadData, WebVRGamepadEvent, WebVRGamepadState}; -use webxr_api::{Error as XRError, Frame, Session, SessionMode}; +use webxr_api::{Error as XRError, Frame, Session, SessionInit, SessionMode}; #[dom_struct] pub struct XR { @@ -154,13 +156,16 @@ impl XRMethods for XR { } /// https://immersive-web.github.io/webxr/#dom-xr-requestsession + #[allow(unsafe_code)] fn RequestSession( &self, mode: XRSessionMode, - _: &XRSessionInit, + init: RootedTraceableBox<XRSessionInit>, comp: InCompartment, ) -> Rc<Promise> { - let promise = Promise::new_in_current_compartment(&self.global(), comp); + let global = self.global(); + let window = global.as_window(); + let promise = Promise::new_in_current_compartment(&global, comp); if mode != XRSessionMode::Inline { if !ScriptThread::is_user_interacting() { @@ -176,11 +181,48 @@ impl XRMethods for XR { self.set_pending(); } + let mut required_features = vec![]; + let mut optional_features = vec![]; + let cx = global.get_cx(); + + if let Some(ref r) = init.requiredFeatures { + for feature in r { + unsafe { + if let Ok(ConversionResult::Success(s)) = + String::from_jsval(*cx, feature.handle(), ()) + { + required_features.push(s) + } else { + warn!("Unable to convert required feature to string"); + promise.reject_error(Error::NotSupported); + return promise; + } + } + } + } + + if let Some(ref o) = init.optionalFeatures { + for feature in o { + unsafe { + if let Ok(ConversionResult::Success(s)) = + String::from_jsval(*cx, feature.handle(), ()) + { + optional_features.push(s) + } else { + warn!("Unable to convert optional feature to string"); + } + } + } + } + + let init = SessionInit { + required_features, + optional_features, + }; + let promise = Promise::new_in_current_compartment(&self.global(), comp); let mut trusted = Some(TrustedPromise::new(promise.clone())); let this = Trusted::new(self); - let global = self.global(); - let window = global.as_window(); let (task_source, canceller) = window .task_manager() .dom_manipulation_task_source_with_canceller(); @@ -210,7 +252,7 @@ impl XRMethods for XR { ); window .webxr_registry() - .request_session(mode.into(), sender, frame_sender); + .request_session(mode.into(), init, sender, frame_sender); promise } @@ -232,7 +274,7 @@ impl XR { let session = match response { Ok(session) => session, Err(_) => { - promise.reject_native(&()); + promise.reject_error(Error::NotSupported); return; }, }; diff --git a/components/script/dom/xrtest.rs b/components/script/dom/xrtest.rs index b00a69b8fca..4c6852fc121 100644 --- a/components/script/dom/xrtest.rs +++ b/components/script/dom/xrtest.rs @@ -69,8 +69,10 @@ impl XRTest { impl XRTestMethods for XRTest { /// https://github.com/immersive-web/webxr-test-api/blob/master/explainer.md + #[allow(unsafe_code)] fn SimulateDeviceConnection(&self, init: &FakeXRDeviceInit) -> Rc<Promise> { - let p = Promise::new(&self.global()); + let global = self.global(); + let p = Promise::new(&global); let origin = if let Some(ref o) = init.viewerOrigin { match get_origin(&o) { @@ -104,12 +106,19 @@ impl XRTestMethods for XRTest { }, }; + let supported_features = if let Some(ref s) = init.supportedFeatures { + s.iter().cloned().map(String::from).collect() + } else { + vec![] + }; + let init = MockDeviceInit { viewer_origin: origin, views, supports_immersive: init.supportsImmersive, supports_unbounded: init.supportsUnbounded, floor_origin, + supported_features, }; let global = self.global(); diff --git a/tests/wpt/metadata/webxr/xrDevice_requestSession_immersive_unsupported.https.html.ini b/tests/wpt/metadata/webxr/xrDevice_requestSession_immersive_unsupported.https.html.ini deleted file mode 100644 index 58db0b825f9..00000000000 --- a/tests/wpt/metadata/webxr/xrDevice_requestSession_immersive_unsupported.https.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[xrDevice_requestSession_immersive_unsupported.https.html] - [Requesting an immersive session when unsupported rejects] - expected: FAIL - diff --git a/tests/wpt/metadata/webxr/xrSession_features_deviceSupport.https.html.ini b/tests/wpt/metadata/webxr/xrSession_features_deviceSupport.https.html.ini index c2051682335..7bd0c101858 100644 --- a/tests/wpt/metadata/webxr/xrSession_features_deviceSupport.https.html.ini +++ b/tests/wpt/metadata/webxr/xrSession_features_deviceSupport.https.html.ini @@ -1,4 +1,5 @@ [xrSession_features_deviceSupport.https.html] + expected: ERROR [Immersive XRSession requests with no supported device should reject] - expected: FAIL + expected: TIMEOUT |