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
--- 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();
}