Add support for requesting features

This commit is contained in:
Manish Goregaokar 2020-01-13 17:50:13 +05:30
parent e0135fe783
commit d33d21ce72
6 changed files with 66 additions and 15 deletions

View file

@ -25,8 +25,8 @@ enum XRSessionMode {
}; };
dictionary XRSessionInit { dictionary XRSessionInit {
sequence<DOMString> requiredFeatures; sequence<any> requiredFeatures;
sequence<DOMString> optionalFeatures; sequence<any> optionalFeatures;
}; };
partial interface XR { partial interface XR {

View file

@ -23,6 +23,9 @@ dictionary FakeXRDeviceInit {
required boolean supportsImmersive; required boolean supportsImmersive;
required sequence<FakeXRViewInit> views; required sequence<FakeXRViewInit> views;
// this is actually sequence<any>, but we don't support
// non-string features anyway
sequence<DOMString> supportedFeatures;
boolean supportsUnbounded = false; boolean supportsUnbounded = false;
// Whether the space supports tracking in inline sessions // Whether the space supports tracking in inline sessions
boolean supportsTrackingInInline = true; boolean supportsTrackingInInline = true;

View file

@ -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;
use crate::dom::bindings::codegen::Bindings::XRBinding::XRSessionInit; use crate::dom::bindings::codegen::Bindings::XRBinding::XRSessionInit;
use crate::dom::bindings::codegen::Bindings::XRBinding::{XRMethods, XRSessionMode}; 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::error::Error;
use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::refcounted::{Trusted, TrustedPromise}; use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom}; use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
use crate::dom::bindings::trace::RootedTraceableBox;
use crate::dom::event::Event; use crate::dom::event::Event;
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
use crate::dom::gamepad::Gamepad; use crate::dom::gamepad::Gamepad;
@ -33,7 +35,7 @@ use std::cell::Cell;
use std::rc::Rc; use std::rc::Rc;
use webvr_traits::{WebVRDisplayData, WebVRDisplayEvent, WebVREvent, WebVRMsg}; use webvr_traits::{WebVRDisplayData, WebVRDisplayEvent, WebVREvent, WebVRMsg};
use webvr_traits::{WebVRGamepadData, WebVRGamepadEvent, WebVRGamepadState}; 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] #[dom_struct]
pub struct XR { pub struct XR {
@ -154,13 +156,16 @@ impl XRMethods for XR {
} }
/// https://immersive-web.github.io/webxr/#dom-xr-requestsession /// https://immersive-web.github.io/webxr/#dom-xr-requestsession
#[allow(unsafe_code)]
fn RequestSession( fn RequestSession(
&self, &self,
mode: XRSessionMode, mode: XRSessionMode,
_: &XRSessionInit, init: RootedTraceableBox<XRSessionInit>,
comp: InCompartment, comp: InCompartment,
) -> Rc<Promise> { ) -> 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 mode != XRSessionMode::Inline {
if !ScriptThread::is_user_interacting() { if !ScriptThread::is_user_interacting() {
@ -176,11 +181,48 @@ impl XRMethods for XR {
self.set_pending(); 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 promise = Promise::new_in_current_compartment(&self.global(), comp);
let mut trusted = Some(TrustedPromise::new(promise.clone())); let mut trusted = Some(TrustedPromise::new(promise.clone()));
let this = Trusted::new(self); let this = Trusted::new(self);
let global = self.global();
let window = global.as_window();
let (task_source, canceller) = window let (task_source, canceller) = window
.task_manager() .task_manager()
.dom_manipulation_task_source_with_canceller(); .dom_manipulation_task_source_with_canceller();
@ -210,7 +252,7 @@ impl XRMethods for XR {
); );
window window
.webxr_registry() .webxr_registry()
.request_session(mode.into(), sender, frame_sender); .request_session(mode.into(), init, sender, frame_sender);
promise promise
} }
@ -232,7 +274,7 @@ impl XR {
let session = match response { let session = match response {
Ok(session) => session, Ok(session) => session,
Err(_) => { Err(_) => {
promise.reject_native(&()); promise.reject_error(Error::NotSupported);
return; return;
}, },
}; };

View file

@ -69,8 +69,10 @@ impl XRTest {
impl XRTestMethods for XRTest { impl XRTestMethods for XRTest {
/// https://github.com/immersive-web/webxr-test-api/blob/master/explainer.md /// https://github.com/immersive-web/webxr-test-api/blob/master/explainer.md
#[allow(unsafe_code)]
fn SimulateDeviceConnection(&self, init: &FakeXRDeviceInit) -> Rc<Promise> { 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 { let origin = if let Some(ref o) = init.viewerOrigin {
match get_origin(&o) { 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 { let init = MockDeviceInit {
viewer_origin: origin, viewer_origin: origin,
views, views,
supports_immersive: init.supportsImmersive, supports_immersive: init.supportsImmersive,
supports_unbounded: init.supportsUnbounded, supports_unbounded: init.supportsUnbounded,
floor_origin, floor_origin,
supported_features,
}; };
let global = self.global(); let global = self.global();

View file

@ -1,4 +0,0 @@
[xrDevice_requestSession_immersive_unsupported.https.html]
[Requesting an immersive session when unsupported rejects]
expected: FAIL

View file

@ -1,4 +1,5 @@
[xrSession_features_deviceSupport.https.html] [xrSession_features_deviceSupport.https.html]
expected: ERROR
[Immersive XRSession requests with no supported device should reject] [Immersive XRSession requests with no supported device should reject]
expected: FAIL expected: TIMEOUT