aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2019-02-19 17:45:44 +0530
committerManish Goregaokar <manishsmail@gmail.com>2019-02-19 17:50:46 +0530
commitc44b63f335dacc26f68655c417a9edd1b9bb2706 (patch)
tree4a95d6ff5cf44a782a3237066c74dacd8f6ec84b /components/script/dom
parent37872b8b9c57ab6d08ef32721cf653835b8e6a9a (diff)
downloadservo-c44b63f335dacc26f68655c417a9edd1b9bb2706.tar.gz
servo-c44b63f335dacc26f68655c417a9edd1b9bb2706.zip
Handle erroring out when there are multiple immersive sessions
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/vrdisplay.rs32
-rw-r--r--components/script/dom/xr.rs36
2 files changed, 59 insertions, 9 deletions
diff --git a/components/script/dom/vrdisplay.rs b/components/script/dom/vrdisplay.rs
index 6c4bea1568c..dd8f29195b7 100644
--- a/components/script/dom/vrdisplay.rs
+++ b/components/script/dom/vrdisplay.rs
@@ -4,6 +4,7 @@
use crate::dom::bindings::callback::ExceptionHandling;
use crate::dom::bindings::cell::DomRefCell;
+use crate::dom::bindings::codegen::Bindings::NavigatorBinding::NavigatorMethods;
use crate::dom::bindings::codegen::Bindings::PerformanceBinding::PerformanceMethods;
use crate::dom::bindings::codegen::Bindings::VRDisplayBinding;
use crate::dom::bindings::codegen::Bindings::VRDisplayBinding::VRDisplayMethods;
@@ -13,6 +14,7 @@ use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGL
use crate::dom::bindings::codegen::Bindings::WindowBinding::FrameRequestCallback;
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XRFrameRequestCallback;
+use crate::dom::bindings::error::Error;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::num::Finite;
use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
@@ -347,6 +349,24 @@ impl VRDisplayMethods for VRDisplay {
},
};
+ // WebVR spec: Repeat calls while already presenting will update the VRLayers being displayed.
+ if self.presenting.get() {
+ *self.layer.borrow_mut() = layer_bounds;
+ self.layer_ctx.set(Some(&layer_ctx));
+ promise.resolve_native(&());
+ return promise;
+ }
+
+ let xr = self.global().as_window().Navigator().Xr();
+
+ if xr.pending_or_active_session() {
+ // WebVR spec doesn't mandate anything here, however
+ // the WebXR spec expects there to be only one immersive XR session at a time,
+ // and WebVR is deprecated
+ promise.reject_error(Error::InvalidState);
+ return promise;
+ }
+
self.request_present(layer_bounds, Some(&layer_ctx), Some(promise.clone()), |p| {
p.resolve_native(&())
});
@@ -447,14 +467,6 @@ impl VRDisplay {
) where
F: FnOnce(Rc<Promise>) + Send + 'static,
{
- // WebVR spec: Repeat calls while already presenting will update the VRLayers being displayed.
- if self.presenting.get() {
- *self.layer.borrow_mut() = layer_bounds;
- self.layer_ctx.set(ctx);
- promise.map(resolve);
- return;
- }
-
// Request Present
let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap();
self.webvr_thread()
@@ -557,6 +569,8 @@ impl VRDisplay {
fn init_present(&self) {
self.presenting.set(true);
+ let xr = self.global().as_window().Navigator().Xr();
+ xr.set_active_immersive_session(&self);
let (sync_sender, sync_receiver) = webgl_channel().unwrap();
*self.frame_data_receiver.borrow_mut() = Some(sync_receiver);
@@ -623,6 +637,8 @@ impl VRDisplay {
fn stop_present(&self) {
self.presenting.set(false);
+ let xr = self.global().as_window().Navigator().Xr();
+ xr.deactivate_session();
*self.frame_data_receiver.borrow_mut() = None;
let api_sender = self.layer_ctx.get().unwrap().webgl_sender();
diff --git a/components/script/dom/xr.rs b/components/script/dom/xr.rs
index 3e18ee0d279..13838ac2b20 100644
--- a/components/script/dom/xr.rs
+++ b/components/script/dom/xr.rs
@@ -10,7 +10,7 @@ use crate::dom::bindings::codegen::Bindings::XRBinding::{XRMethods, XRSessionMod
use crate::dom::bindings::error::Error;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
-use crate::dom::bindings::root::{Dom, DomRoot};
+use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
use crate::dom::event::Event;
use crate::dom::eventtarget::EventTarget;
use crate::dom::gamepad::Gamepad;
@@ -23,6 +23,7 @@ use crate::dom::xrsession::XRSession;
use dom_struct::dom_struct;
use ipc_channel::ipc::IpcSender;
use profile_traits::ipc;
+use std::cell::Cell;
use std::rc::Rc;
use webvr_traits::{WebVRDisplayData, WebVRDisplayEvent, WebVREvent, WebVRMsg};
use webvr_traits::{WebVRGamepadData, WebVRGamepadEvent, WebVRGamepadState};
@@ -32,6 +33,8 @@ pub struct XR {
eventtarget: EventTarget,
displays: DomRefCell<Vec<Dom<VRDisplay>>>,
gamepads: DomRefCell<Vec<Dom<Gamepad>>>,
+ pending_immersive_session: Cell<bool>,
+ active_immersive_session: MutNullableDom<VRDisplay>,
}
impl XR {
@@ -40,6 +43,8 @@ impl XR {
eventtarget: EventTarget::new_inherited(),
displays: DomRefCell::new(Vec::new()),
gamepads: DomRefCell::new(Vec::new()),
+ pending_immersive_session: Cell::new(false),
+ active_immersive_session: Default::default(),
}
}
@@ -48,6 +53,26 @@ impl XR {
root.register();
root
}
+
+ pub fn pending_or_active_session(&self) -> bool {
+ self.pending_immersive_session.get() || self.active_immersive_session.get().is_some()
+ }
+
+ pub fn set_pending(&self) {
+ self.pending_immersive_session.set(true)
+ }
+
+ pub fn set_active_immersive_session(&self, session: &VRDisplay) {
+ // XXXManishearth when we support non-immersive (inline) sessions we should
+ // ensure they never reach these codepaths
+ self.pending_immersive_session.set(false);
+ self.active_immersive_session.set(Some(session))
+ }
+
+ pub fn deactivate_session(&self) {
+ self.pending_immersive_session.set(false);
+ self.active_immersive_session.set(None)
+ }
}
impl Drop for XR {
@@ -79,6 +104,13 @@ impl XRMethods for XR {
return promise;
}
+ if self.pending_or_active_session() {
+ promise.reject_error(Error::InvalidState);
+ return promise;
+ }
+ // we set pending immersive session to true further down
+ // to handle rejections in a cleaner way
+
let displays = self.get_displays();
let displays = match displays {
@@ -94,6 +126,8 @@ impl XRMethods for XR {
promise.reject_error(Error::Security);
}
+ self.set_pending();
+
let session = XRSession::new(&self.global(), &displays[0]);
session.xr_present(promise.clone());
promise