VREventObserver.cpp (5249B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "VREventObserver.h" 8 9 #include "nsContentUtils.h" 10 #include "nsGlobalWindowInner.h" 11 12 namespace mozilla::dom { 13 14 using namespace gfx; 15 16 /** 17 * This class is used by nsGlobalWindowInner to implement 18 * window.onvrdisplayactivate, window.onvrdisplaydeactivate, 19 * window.onvrdisplayconnected, window.onvrdisplaydisconnected, and 20 * window.onvrdisplaypresentchange. 21 */ 22 VREventObserver::VREventObserver(nsGlobalWindowInner* aGlobalWindow) 23 : mWindow(aGlobalWindow), mIs2DView(true), mStopActivity(false) { 24 MOZ_ASSERT(aGlobalWindow); 25 26 VRManagerChild* vmc = VRManagerChild::Get(); 27 if (vmc) { 28 vmc->AddListener(this); 29 } 30 } 31 32 VREventObserver::~VREventObserver() { DisconnectFromOwner(); } 33 34 void VREventObserver::DisconnectFromOwner() { 35 // In the event that nsGlobalWindowInner is deallocated, VREventObserver may 36 // still be AddRef'ed elsewhere. Ensure that we don't UAF by 37 // dereferencing mWindow. 38 mWindow = nullptr; 39 40 // Unregister from VRManagerChild 41 if (VRManagerChild::IsCreated()) { 42 VRManagerChild* vmc = VRManagerChild::Get(); 43 vmc->RemoveListener(this); 44 } 45 mStopActivity = true; 46 } 47 48 void VREventObserver::StartActivity() { 49 mStopActivity = false; 50 VRManagerChild* vmc = VRManagerChild::Get(); 51 vmc->StartActivity(); 52 } 53 54 void VREventObserver::StopActivity() { 55 mStopActivity = true; 56 VRManagerChild* vmc = VRManagerChild::Get(); 57 vmc->StopActivity(); 58 } 59 60 bool VREventObserver::GetStopActivityStatus() const { return mStopActivity; } 61 62 void VREventObserver::NotifyAfterLoad() { 63 if (VRManagerChild::IsCreated()) { 64 VRManagerChild* vmc = VRManagerChild::Get(); 65 vmc->FireDOMVRDisplayConnectEventsForLoad(this); 66 } 67 } 68 69 void VREventObserver::NotifyVRDisplayMounted(uint32_t aDisplayID) { 70 if (mWindow && mWindow->IsCurrentInnerWindow() && IsWebVR(aDisplayID)) { 71 MOZ_ASSERT(nsContentUtils::IsSafeToRunScript()); 72 mWindow->DispatchVRDisplayActivate(aDisplayID, 73 VRDisplayEventReason::Mounted); 74 } 75 } 76 77 void VREventObserver::NotifyVRDisplayNavigation(uint32_t aDisplayID) { 78 if (mWindow && mWindow->IsCurrentInnerWindow() && IsWebVR(aDisplayID)) { 79 MOZ_ASSERT(nsContentUtils::IsSafeToRunScript()); 80 mWindow->DispatchVRDisplayActivate(aDisplayID, 81 VRDisplayEventReason::Navigation); 82 } 83 } 84 85 void VREventObserver::NotifyVRDisplayRequested(uint32_t aDisplayID) { 86 if (mWindow && mWindow->IsCurrentInnerWindow() && IsWebVR(aDisplayID)) { 87 MOZ_ASSERT(nsContentUtils::IsSafeToRunScript()); 88 mWindow->DispatchVRDisplayActivate(aDisplayID, 89 VRDisplayEventReason::Requested); 90 } 91 } 92 93 void VREventObserver::NotifyVRDisplayUnmounted(uint32_t aDisplayID) { 94 if (mWindow && mWindow->IsCurrentInnerWindow() && IsWebVR(aDisplayID)) { 95 MOZ_ASSERT(nsContentUtils::IsSafeToRunScript()); 96 mWindow->DispatchVRDisplayDeactivate(aDisplayID, 97 VRDisplayEventReason::Unmounted); 98 } 99 } 100 101 void VREventObserver::NotifyVRDisplayConnect(uint32_t aDisplayID) { 102 /** 103 * We do not call nsGlobalWindowInner::NotifyActiveVRDisplaysChanged here, as 104 * we can assume that a newly enumerated display is not presenting WebVR 105 * content. 106 */ 107 if (mWindow && mWindow->IsCurrentInnerWindow() && IsWebVR(aDisplayID)) { 108 MOZ_ASSERT(nsContentUtils::IsSafeToRunScript()); 109 mWindow->DispatchVRDisplayConnect(aDisplayID); 110 } 111 } 112 113 void VREventObserver::NotifyVRDisplayDisconnect(uint32_t aDisplayID) { 114 if (mWindow && mWindow->IsCurrentInnerWindow() && IsWebVR(aDisplayID)) { 115 mWindow->NotifyActiveVRDisplaysChanged(); 116 MOZ_ASSERT(nsContentUtils::IsSafeToRunScript()); 117 mWindow->DispatchVRDisplayDisconnect(aDisplayID); 118 } 119 } 120 121 void VREventObserver::NotifyVRDisplayPresentChange(uint32_t aDisplayID) { 122 // When switching to HMD present mode, it is no longer 123 // to be a 2D view. 124 mIs2DView = false; 125 126 if (mWindow && mWindow->IsCurrentInnerWindow() && IsWebVR(aDisplayID)) { 127 mWindow->NotifyActiveVRDisplaysChanged(); 128 MOZ_ASSERT(nsContentUtils::IsSafeToRunScript()); 129 mWindow->DispatchVRDisplayPresentChange(aDisplayID); 130 } 131 } 132 133 void VREventObserver::NotifyPresentationGenerationChanged(uint32_t aDisplayID) { 134 if (mWindow && mWindow->IsCurrentInnerWindow() && IsWebVR(aDisplayID)) { 135 MOZ_ASSERT(nsContentUtils::IsSafeToRunScript()); 136 mWindow->NotifyPresentationGenerationChanged(aDisplayID); 137 } 138 } 139 140 void VREventObserver::NotifyEnumerationCompleted() {} 141 142 void VREventObserver::NotifyDetectRuntimesCompleted() { 143 if (mWindow && mWindow->IsCurrentInnerWindow()) { 144 MOZ_ASSERT(nsContentUtils::IsSafeToRunScript()); 145 mWindow->NotifyDetectXRRuntimesCompleted(); 146 } 147 } 148 149 bool VREventObserver::IsWebVR(uint32_t aDisplayID) const { 150 VRManagerChild* vmc = VRManagerChild::Get(); 151 if (vmc) { 152 return vmc->GetVRAPIMode(aDisplayID) == gfx::VRAPIMode::WebVR; 153 } 154 return true; 155 } 156 157 } // namespace mozilla::dom