Bug 1306422 - VRDisplay.exitPresent must only be allowed by content that started VR Presentation draft
authorKearwood (Kip) Gilbert <kgilbert@mozilla.com>
Thu, 29 Sep 2016 16:11:25 -0700
changeset 419194 8fd7f700385c4838e7d1b19fd000d32abdcbe28e
parent 419033 9baec74b3db1bf005c66ae2f50bafbdb02c3be38
child 532532 d069cd73c8621d6bca08bfc8fc0367566992c9e0
push id30884
push userkgilbert@mozilla.com
push dateThu, 29 Sep 2016 23:15:43 +0000
bugs1306422
milestone52.0a1
Bug 1306422 - VRDisplay.exitPresent must only be allowed by content that started VR Presentation - While fixing the VRDisplay.exitPresent to resolve fail its returned promise, I noticed that VRDisplay.isPresenting is returning the global state of the VRDisplay. I have updated this as well in the patch so that the isPresenting attribute only returns true for VR presentations started within the same Javascript context. MozReview-Commit-ID: D8KVsGCxcuD
dom/vr/VRDisplay.cpp
--- a/dom/vr/VRDisplay.cpp
+++ b/dom/vr/VRDisplay.cpp
@@ -525,17 +525,17 @@ VRDisplay::RequestPresent(const nsTArray
   }
 
   RefPtr<Promise> promise = Promise::Create(global, aRv);
   NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
 
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   NS_ENSURE_TRUE(obs, nullptr);
 
-  if (IsPresenting()) {
+  if (mClient->GetIsPresenting()) {
     // Only one presentation allowed per VRDisplay
     // on a first-come-first-serve basis.
     promise->MaybeRejectWithUndefined();
   } else {
     mPresentation = mClient->BeginPresentation(aLayers);
 
     nsresult rv = obs->AddObserver(this, "inner-window-destroyed", false);
     if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -576,22 +576,30 @@ VRDisplay::Observe(nsISupports* aSubject
 already_AddRefed<Promise>
 VRDisplay::ExitPresent(ErrorResult& aRv)
 {
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
   if (!global) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
-  ExitPresentInternal();
+
 
   RefPtr<Promise> promise = Promise::Create(global, aRv);
   NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
 
-  promise->MaybeResolve(JS::UndefinedHandleValue);
+  if (!IsPresenting()) {
+    // We can not exit a presentation outside of the context that
+    // started the presentation.
+    promise->MaybeRejectWithUndefined();
+    ExitPresentInternal();
+  } else {
+    promise->MaybeResolve(JS::UndefinedHandleValue);
+  }
+
   return promise.forget();
 }
 
 void
 VRDisplay::ExitPresentInternal()
 {
   mPresentation = nullptr;
 }
@@ -635,17 +643,19 @@ VRDisplay::CancelAnimationFrame(int32_t 
   gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
   vm->CancelFrameRequestCallback(aHandle);
 }
 
 
 bool
 VRDisplay::IsPresenting() const
 {
-  return mClient->GetIsPresenting();
+  // IsPresenting returns true only if this Javascript context is presenting
+  // and will return false if another context is presenting.
+  return mPresentation != nullptr;
 }
 
 bool
 VRDisplay::IsConnected() const
 {
   return mClient->GetIsConnected();
 }