Auto merge of #24133 - paulrouget:userAction, r=jdm

Do not allow XR session on non user-activated events

This sets the thread in "user interaction mode" when the dispatched event is trusted. I also tried an approach where we would not rely on the dispatched event but just set "user interaction mode" when we get a compositor event (which, we can assume, are only user generated). That worked as well.

Fixes #23787.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/24133)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2019-09-20 06:54:19 -04:00 committed by GitHub
commit 293ccd07e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 54 additions and 15 deletions

View file

@ -23,6 +23,7 @@ use crate::dom::vrdisplay::VRDisplay;
use crate::dom::vrdisplayevent::VRDisplayEvent;
use crate::dom::xrsession::XRSession;
use crate::dom::xrtest::XRTest;
use crate::script_thread::ScriptThread;
use crate::task_source::TaskSource;
use dom_struct::dom_struct;
use ipc_channel::ipc::IpcSender;
@ -157,6 +158,11 @@ impl XRMethods for XR {
) -> Rc<Promise> {
let promise = Promise::new_in_current_compartment(&self.global(), comp);
if !ScriptThread::is_user_interacting() {
promise.reject_error(Error::Security);
return promise;
}
if self.pending_or_active_session() {
promise.reject_error(Error::InvalidState);
return promise;

View file

@ -18,6 +18,7 @@ use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::fakexrdevice::{get_origin, get_views, 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 euclid::RigidTransform3D;
@ -159,8 +160,9 @@ impl XRTestMethods for XRTest {
/// https://github.com/immersive-web/webxr-test-api/blob/master/explainer.md
fn SimulateUserActivation(&self, f: Rc<Function>) {
// XXXManishearth actually check for activation in XRSession
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

View file

@ -690,6 +690,9 @@ pub struct ScriptThread {
/// A set of all nodes ever created in this script thread
node_ids: DomRefCell<HashSet<String>>,
/// Code is running as a consequence of a user interaction
is_user_interacting: Cell<bool>,
}
/// In the event of thread panic, all data on the stack runs its destructor. However, there
@ -1030,6 +1033,24 @@ impl ScriptThread {
})
}
pub fn set_user_interacting(interacting: bool) {
SCRIPT_THREAD_ROOT.with(|root| {
if let Some(script_thread) = root.get() {
let script_thread = unsafe { &*script_thread };
script_thread.is_user_interacting.set(interacting);
}
});
}
pub fn is_user_interacting() -> bool {
SCRIPT_THREAD_ROOT.with(|root| {
root.get().map_or(false, |script_thread| {
let script_thread = unsafe { &*script_thread };
script_thread.is_user_interacting.get()
})
})
}
pub fn get_fully_active_document_ids() -> HashSet<PipelineId> {
SCRIPT_THREAD_ROOT.with(|root| {
root.get().map_or(HashSet::new(), |script_thread| {
@ -1339,6 +1360,7 @@ impl ScriptThread {
event_loop_waker: state.event_loop_waker,
node_ids: Default::default(),
is_user_interacting: Cell::new(false),
}
}
@ -3356,6 +3378,9 @@ impl ScriptThread {
///
/// TODO: Actually perform DOM event dispatch.
fn handle_event(&self, pipeline_id: PipelineId, event: CompositorEvent) {
// Assuming all CompositionEvent are generated by user interactions.
ScriptThread::set_user_interacting(true);
match event {
ResizeEvent(new_size, size_type) => {
self.handle_resize_event(pipeline_id, new_size, size_type);
@ -3489,6 +3514,8 @@ impl ScriptThread {
document.dispatch_composition_event(composition_event);
},
}
ScriptThread::set_user_interacting(false);
}
fn handle_mouse_event(