diff options
author | yvt <i@yvt.jp> | 2021-07-10 17:24:27 +0900 |
---|---|---|
committer | yvt <i@yvt.jp> | 2021-07-10 17:55:42 +0900 |
commit | 01a7de50ab1843d85295f9dccad7f4c099e7208c (patch) | |
tree | ee53fb6e8889deb7b880ee969e6c662e6128d210 /components/script/dom/xrtest.rs | |
parent | ff8d2cdbbfc7a9dc7f38b7dd47cb350fde39388f (diff) | |
parent | 94b613fbdaa2b98f2179fc0bbda13c64e6fa0d38 (diff) | |
download | servo-01a7de50ab1843d85295f9dccad7f4c099e7208c.tar.gz servo-01a7de50ab1843d85295f9dccad7f4c099e7208c.zip |
Merge remote-tracking branch 'upstream/master' into feat-cow-infra
`tests/wpt/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects.html`
was reverted to the upstream version.
Diffstat (limited to 'components/script/dom/xrtest.rs')
-rw-r--r-- | components/script/dom/xrtest.rs | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/components/script/dom/xrtest.rs b/components/script/dom/xrtest.rs new file mode 100644 index 00000000000..37707c3ce8e --- /dev/null +++ b/components/script/dom/xrtest.rs @@ -0,0 +1,230 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use crate::dom::bindings::callback::ExceptionHandling; +use crate::dom::bindings::cell::DomRefCell; +use crate::dom::bindings::codegen::Bindings::FunctionBinding::Function; +use crate::dom::bindings::codegen::Bindings::XRSystemBinding::XRSessionMode; +use crate::dom::bindings::codegen::Bindings::XRTestBinding::{FakeXRDeviceInit, XRTestMethods}; +use crate::dom::bindings::refcounted::{Trusted, TrustedPromise}; +use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; +use crate::dom::bindings::root::{Dom, DomRoot}; +use crate::dom::fakexrdevice::{get_origin, get_views, get_world, FakeXRDevice}; +use crate::dom::globalscope::GlobalScope; +use crate::dom::promise::Promise; +use crate::script_thread::ScriptThread; +use crate::task_source::TaskSource; +use dom_struct::dom_struct; +use ipc_channel::ipc::IpcSender; +use ipc_channel::router::ROUTER; +use profile_traits::ipc; +use std::rc::Rc; +use webxr_api::{self, Error as XRError, MockDeviceInit, MockDeviceMsg}; + +#[dom_struct] +pub struct XRTest { + reflector: Reflector, + devices_connected: DomRefCell<Vec<Dom<FakeXRDevice>>>, +} + +impl XRTest { + pub fn new_inherited() -> XRTest { + XRTest { + reflector: Reflector::new(), + devices_connected: DomRefCell::new(vec![]), + } + } + + pub fn new(global: &GlobalScope) -> DomRoot<XRTest> { + reflect_dom_object(Box::new(XRTest::new_inherited()), global) + } + + fn device_obtained( + &self, + response: Result<IpcSender<MockDeviceMsg>, XRError>, + trusted: TrustedPromise, + ) { + let promise = trusted.root(); + if let Ok(sender) = response { + let device = FakeXRDevice::new(&self.global(), sender); + self.devices_connected + .borrow_mut() + .push(Dom::from_ref(&device)); + promise.resolve_native(&device); + } else { + promise.reject_native(&()); + } + } +} + +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 global = self.global(); + let p = Promise::new(&global); + + let origin = if let Some(ref o) = init.viewerOrigin { + match get_origin(&o) { + Ok(origin) => Some(origin), + Err(e) => { + p.reject_error(e); + return p; + }, + } + } else { + None + }; + + let floor_origin = if let Some(ref o) = init.floorOrigin { + match get_origin(&o) { + Ok(origin) => Some(origin), + Err(e) => { + p.reject_error(e); + return p; + }, + } + } else { + None + }; + + let views = match get_views(&init.views) { + Ok(views) => views, + Err(e) => { + p.reject_error(e); + return p; + }, + }; + + let supported_features = if let Some(ref s) = init.supportedFeatures { + s.iter().cloned().map(String::from).collect() + } else { + vec![] + }; + + let world = if let Some(ref w) = init.world { + let w = match get_world(w) { + Ok(w) => w, + Err(e) => { + p.reject_error(e); + return p; + }, + }; + Some(w) + } else { + None + }; + + let (mut supports_inline, mut supports_vr, mut supports_ar) = (false, false, false); + + if let Some(ref modes) = init.supportedModes { + for mode in modes { + match mode { + XRSessionMode::Immersive_vr => supports_vr = true, + XRSessionMode::Immersive_ar => supports_ar = true, + XRSessionMode::Inline => supports_inline = true, + } + } + } + + let init = MockDeviceInit { + viewer_origin: origin, + views, + supports_inline, + supports_vr, + supports_ar, + floor_origin, + supported_features, + world, + }; + + let global = self.global(); + let window = global.as_window(); + let this = Trusted::new(self); + let mut trusted = Some(TrustedPromise::new(p.clone())); + + let (task_source, canceller) = window + .task_manager() + .dom_manipulation_task_source_with_canceller(); + let (sender, receiver) = ipc::channel(global.time_profiler_chan().clone()).unwrap(); + ROUTER.add_route( + receiver.to_opaque(), + Box::new(move |message| { + let trusted = trusted + .take() + .expect("SimulateDeviceConnection callback called twice"); + let this = this.clone(); + let message = message + .to() + .expect("SimulateDeviceConnection callback given incorrect payload"); + + let _ = task_source.queue_with_canceller( + task!(request_session: move || { + this.root().device_obtained(message, trusted); + }), + &canceller, + ); + }), + ); + window + .webxr_registry() + .simulate_device_connection(init, sender); + + p + } + + /// https://github.com/immersive-web/webxr-test-api/blob/master/explainer.md + fn SimulateUserActivation(&self, f: Rc<Function>) { + ScriptThread::set_user_interacting(true); + let _ = f.Call__(vec![], ExceptionHandling::Rethrow); + ScriptThread::set_user_interacting(false); + } + + /// https://github.com/immersive-web/webxr-test-api/blob/master/explainer.md + fn DisconnectAllDevices(&self) -> Rc<Promise> { + // XXXManishearth implement device disconnection and session ending + let global = self.global(); + let p = Promise::new(&global); + let mut devices = self.devices_connected.borrow_mut(); + if devices.is_empty() { + p.resolve_native(&()); + } else { + let mut len = devices.len(); + + let (sender, receiver) = ipc::channel(global.time_profiler_chan().clone()).unwrap(); + let mut rooted_devices: Vec<_> = + devices.iter().map(|x| DomRoot::from_ref(&**x)).collect(); + devices.clear(); + + let mut trusted = Some(TrustedPromise::new(p.clone())); + let (task_source, canceller) = global + .as_window() + .task_manager() + .dom_manipulation_task_source_with_canceller(); + + ROUTER.add_route( + receiver.to_opaque(), + Box::new(move |_| { + len -= 1; + if len == 0 { + let trusted = trusted + .take() + .expect("DisconnectAllDevices disconnected more devices than expected"); + let _ = + task_source.queue_with_canceller(trusted.resolve_task(()), &canceller); + } + }), + ); + + for device in rooted_devices.drain(..) { + device.disconnect(sender.clone()); + } + }; + p + } +} |