Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp
Warning:line 178, column 9
Value stored to 'found' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_gfx_vr0.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/gfx/vr -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/gfx/vr -resource-dir /usr/lib/llvm-18/lib/clang/18 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/gfx/vr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/gfx/vr -I /var/lib/jenkins/workspace/firefox-scan-build/dom/base -I /var/lib/jenkins/workspace/firefox-scan-build/dom/canvas -I /var/lib/jenkins/workspace/firefox-scan-build/gfx/cairo/cairo/src -I /var/lib/jenkins/workspace/firefox-scan-build/gfx/layers/d3d11 -I /var/lib/jenkins/workspace/firefox-scan-build/gfx/thebes -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /var/lib/jenkins/workspace/firefox-scan-build/ipc/chromium/src -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gtk-3.0/unix-print -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-07-21-021012-413605-1 -x c++ Unified_cpp_gfx_vr0.cpp
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 "VRManagerChild.h"
8
9#include "VRLayerChild.h"
10#include "VRManagerParent.h"
11#include "VRThread.h"
12#include "VRDisplayClient.h"
13#include "nsGlobalWindowInner.h"
14#include "mozilla/ProfilerMarkers.h"
15#include "mozilla/StaticPtr.h"
16#include "mozilla/layers/CompositorThread.h" // for CompositorThread
17#include "mozilla/dom/Navigator.h"
18#include "mozilla/dom/VREventObserver.h"
19#include "mozilla/dom/WebXRBinding.h"
20#include "mozilla/dom/WindowBinding.h" // for FrameRequestCallback
21#include "mozilla/dom/XRSystem.h"
22#include "mozilla/dom/XRFrame.h"
23#include "mozilla/dom/ContentChild.h"
24#include "nsContentUtils.h"
25#include "mozilla/dom/GamepadManager.h"
26#include "mozilla/ipc/Endpoint.h"
27#include "mozilla/layers/SyncObject.h"
28#include "mozilla/layers/TextureForwarder.h"
29
30using namespace mozilla::dom;
31
32namespace {
33const nsTArray<RefPtr<mozilla::gfx::VRManagerEventObserver>>::index_type
34 kNoIndex = nsTArray<RefPtr<mozilla::gfx::VRManagerEventObserver>>::NoIndex;
35} // namespace
36
37namespace mozilla {
38namespace gfx {
39
40static StaticRefPtr<VRManagerChild> sVRManagerChildSingleton;
41static StaticRefPtr<VRManagerParent> sVRManagerParentSingleton;
42
43static TimeStamp sMostRecentFrameEnd;
44static TimeDuration sAverageFrameInterval;
45
46void ReleaseVRManagerParentSingleton() { sVRManagerParentSingleton = nullptr; }
47
48VRManagerChild::VRManagerChild()
49 : mRuntimeCapabilities(VRDisplayCapabilityFlags::Cap_None),
50 mFrameRequestCallbackCounter(0),
51 mWaitingForEnumeration(false),
52 mBackend(layers::LayersBackend::LAYERS_NONE) {
53 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp"
, 53); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 53; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
54
55 mStartTimeStamp = TimeStamp::Now();
56}
57
58VRManagerChild::~VRManagerChild() { MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp"
, 58); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 58; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; }
59
60/*static*/
61void VRManagerChild::IdentifyTextureHost(
62 const TextureFactoryIdentifier& aIdentifier) {
63 if (sVRManagerChildSingleton) {
64 sVRManagerChildSingleton->mBackend = aIdentifier.mParentBackend;
65 }
66}
67
68layers::LayersBackend VRManagerChild::GetBackendType() const {
69 return mBackend;
70}
71
72/*static*/
73VRManagerChild* VRManagerChild::Get() {
74 MOZ_ASSERT(sVRManagerChildSingleton)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sVRManagerChildSingleton)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sVRManagerChildSingleton))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("sVRManagerChildSingleton"
, "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp"
, 74); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sVRManagerChildSingleton"
")"); do { *((volatile int*)__null) = 74; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
75 return sVRManagerChildSingleton;
76}
77
78/* static */
79bool VRManagerChild::IsCreated() { return !!sVRManagerChildSingleton; }
80
81/* static */
82bool VRManagerChild::IsPresenting() {
83 if (!VRManagerChild::IsCreated()) {
84 return false;
85 }
86
87 nsTArray<RefPtr<VRDisplayClient>> displays;
88 sVRManagerChildSingleton->GetVRDisplays(displays);
89
90 bool result = false;
91 for (auto& display : displays) {
92 result |= display->IsPresenting();
93 }
94 return result;
95}
96
97TimeStamp VRManagerChild::GetIdleDeadlineHint(TimeStamp aDefault) {
98 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp"
, 98); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 98; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
99 if (!VRManagerChild::IsCreated() || sMostRecentFrameEnd.IsNull()) {
100 return aDefault;
101 }
102
103 TimeStamp idleEnd = sMostRecentFrameEnd + sAverageFrameInterval;
104 return idleEnd < aDefault ? idleEnd : aDefault;
105}
106
107/* static */
108bool VRManagerChild::InitForContent(Endpoint<PVRManagerChild>&& aEndpoint) {
109 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp"
, 109); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 109; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
110
111 RefPtr<VRManagerChild> child(new VRManagerChild());
112 if (!aEndpoint.Bind(child)) {
113 return false;
114 }
115 sVRManagerChildSingleton = child;
116 return true;
117}
118
119/*static*/
120void VRManagerChild::InitSameProcess() {
121 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp"
, 121); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 121; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
122 MOZ_ASSERT(!sVRManagerChildSingleton)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!sVRManagerChildSingleton)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!sVRManagerChildSingleton)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("!sVRManagerChildSingleton"
, "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp"
, 122); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sVRManagerChildSingleton"
")"); do { *((volatile int*)__null) = 122; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
123
124 sVRManagerChildSingleton = new VRManagerChild();
125 sVRManagerParentSingleton = VRManagerParent::CreateSameProcess();
126 sVRManagerChildSingleton->Open(sVRManagerParentSingleton, CompositorThread(),
127 mozilla::ipc::ChildSide);
128}
129
130/* static */
131void VRManagerChild::InitWithGPUProcess(Endpoint<PVRManagerChild>&& aEndpoint) {
132 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp"
, 132); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 132; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
133 MOZ_ASSERT(!sVRManagerChildSingleton)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!sVRManagerChildSingleton)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!sVRManagerChildSingleton)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("!sVRManagerChildSingleton"
, "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp"
, 133); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sVRManagerChildSingleton"
")"); do { *((volatile int*)__null) = 133; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
134
135 sVRManagerChildSingleton = new VRManagerChild();
136 if (!aEndpoint.Bind(sVRManagerChildSingleton)) {
137 MOZ_CRASH("Couldn't Open() Compositor channel.")do { do { } while (false); MOZ_ReportCrash("" "Couldn't Open() Compositor channel."
, "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp"
, 137); AnnotateMozCrashReason("MOZ_CRASH(" "Couldn't Open() Compositor channel."
")"); do { *((volatile int*)__null) = 137; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
138 }
139}
140
141/*static*/
142void VRManagerChild::ShutDown() {
143 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp"
, 143); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 143; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
144 if (!sVRManagerChildSingleton) {
145 return;
146 }
147 sVRManagerChildSingleton->Close();
148 sVRManagerChildSingleton = nullptr;
149}
150
151void VRManagerChild::ActorDestroy(ActorDestroyReason aReason) {
152 if (sVRManagerChildSingleton == this) {
153 sVRManagerChildSingleton = nullptr;
154 }
155}
156
157PVRLayerChild* VRManagerChild::AllocPVRLayerChild(const uint32_t& aDisplayID,
158 const uint32_t& aGroup) {
159 return VRLayerChild::CreateIPDLActor();
160}
161
162bool VRManagerChild::DeallocPVRLayerChild(PVRLayerChild* actor) {
163 return VRLayerChild::DestroyIPDLActor(actor);
164}
165
166void VRManagerChild::UpdateDisplayInfo(const VRDisplayInfo& aDisplayInfo) {
167 nsTArray<uint32_t> disconnectedDisplays;
168 nsTArray<uint32_t> connectedDisplays;
169
170 const nsTArray<RefPtr<VRDisplayClient>> prevDisplays(mDisplays.Clone());
171
172 // Check if any displays have been disconnected
173 for (auto& display : prevDisplays) {
174 bool found = false;
175 if (aDisplayInfo.GetDisplayID() != 0) {
176 if (display->GetDisplayInfo().GetDisplayID() ==
177 aDisplayInfo.GetDisplayID()) {
178 found = true;
Value stored to 'found' is never read
179 break;
180 }
181 }
182 if (!found) {
183 // In order to make the current VRDisplay can continue to apply for the
184 // newest VRDisplayInfo, we need to exit presentionation before
185 // disconnecting.
186 if (display->IsPresentationGenerationCurrent()) {
187 NotifyPresentationGenerationChangedInternal(
188 display->GetDisplayInfo().GetDisplayID());
189
190 RefPtr<VRManagerChild> vm = VRManagerChild::Get();
191 vm->FireDOMVRDisplayPresentChangeEvent(
192 display->GetDisplayInfo().GetDisplayID());
193 }
194 display->NotifyDisconnected();
195 disconnectedDisplays.AppendElement(
196 display->GetDisplayInfo().GetDisplayID());
197 }
198 }
199
200 // mDisplays could be a hashed container for more scalability, but not worth
201 // it now as we expect < 10 entries.
202 nsTArray<RefPtr<VRDisplayClient>> displays;
203 if (aDisplayInfo.GetDisplayID() != 0) {
204 bool isNewDisplay = true;
205 for (auto& display : prevDisplays) {
206 const VRDisplayInfo& prevInfo = display->GetDisplayInfo();
207 if (prevInfo.GetDisplayID() == aDisplayInfo.GetDisplayID()) {
208 if (aDisplayInfo.GetIsConnected() && !prevInfo.GetIsConnected()) {
209 connectedDisplays.AppendElement(aDisplayInfo.GetDisplayID());
210 }
211 if (!aDisplayInfo.GetIsConnected() && prevInfo.GetIsConnected()) {
212 disconnectedDisplays.AppendElement(aDisplayInfo.GetDisplayID());
213 }
214 // MOZ_KnownLive because 'prevDisplays' is guaranteed to keep it alive.
215 //
216 // This can go away once
217 // https://bugzilla.mozilla.org/show_bug.cgi?id=1620312 is fixed.
218 MOZ_KnownLive(display)(display)->UpdateDisplayInfo(aDisplayInfo);
219 displays.AppendElement(display);
220 isNewDisplay = false;
221 break;
222 }
223 }
224 if (isNewDisplay) {
225 displays.AppendElement(new VRDisplayClient(aDisplayInfo));
226 connectedDisplays.AppendElement(aDisplayInfo.GetDisplayID());
227 }
228 }
229
230 mDisplays = std::move(displays);
231
232 // We wish to fire the events only after mDisplays is updated
233 for (uint32_t displayID : disconnectedDisplays) {
234 FireDOMVRDisplayDisconnectEvent(displayID);
235 }
236
237 for (uint32_t displayID : connectedDisplays) {
238 FireDOMVRDisplayConnectEvent(displayID);
239 }
240}
241
242bool VRManagerChild::RuntimeSupportsVR() const {
243 return bool(mRuntimeCapabilities & VRDisplayCapabilityFlags::Cap_ImmersiveVR);
244}
245bool VRManagerChild::RuntimeSupportsAR() const {
246 return bool(mRuntimeCapabilities & VRDisplayCapabilityFlags::Cap_ImmersiveAR);
247}
248bool VRManagerChild::RuntimeSupportsInline() const {
249 return bool(mRuntimeCapabilities & VRDisplayCapabilityFlags::Cap_Inline);
250}
251
252mozilla::ipc::IPCResult VRManagerChild::RecvUpdateRuntimeCapabilities(
253 const VRDisplayCapabilityFlags& aCapabilities) {
254 mRuntimeCapabilities = aCapabilities;
255 nsContentUtils::AddScriptRunner(NewRunnableMethod<>(
256 "gfx::VRManagerChild::NotifyRuntimeCapabilitiesUpdatedInternal", this,
257 &VRManagerChild::NotifyRuntimeCapabilitiesUpdatedInternal));
258 return IPC_OK()mozilla::ipc::IPCResult::Ok();
259}
260
261void VRManagerChild::NotifyRuntimeCapabilitiesUpdatedInternal() {
262 const nsTArray<RefPtr<VRManagerEventObserver>> listeners = mListeners.Clone();
263 for (auto& listener : listeners) {
264 listener->NotifyDetectRuntimesCompleted();
265 }
266}
267
268mozilla::ipc::IPCResult VRManagerChild::RecvUpdateDisplayInfo(
269 const VRDisplayInfo& aDisplayInfo) {
270 UpdateDisplayInfo(aDisplayInfo);
271 for (auto& windowId : mNavigatorCallbacks) {
272 /** We must call NotifyVRDisplaysUpdated for every
273 * window's Navigator in mNavigatorCallbacks to ensure that
274 * the promise returned by Navigator.GetVRDevices
275 * can resolve. This must happen even if no changes
276 * to VRDisplays have been detected here.
277 */
278 nsGlobalWindowInner* window =
279 nsGlobalWindowInner::GetInnerWindowWithId(windowId);
280 if (!window) {
281 continue;
282 }
283 dom::Navigator* nav = window->Navigator();
284 if (!nav) {
285 continue;
286 }
287 nav->NotifyVRDisplaysUpdated();
288 }
289 mNavigatorCallbacks.Clear();
290 if (mWaitingForEnumeration) {
291 nsContentUtils::AddScriptRunner(NewRunnableMethod<>(
292 "gfx::VRManagerChild::NotifyEnumerationCompletedInternal", this,
293 &VRManagerChild::NotifyEnumerationCompletedInternal));
294 mWaitingForEnumeration = false;
295 }
296 return IPC_OK()mozilla::ipc::IPCResult::Ok();
297}
298
299mozilla::ipc::IPCResult VRManagerChild::RecvNotifyPuppetCommandBufferCompleted(
300 bool aSuccess) {
301 RefPtr<dom::Promise> promise = mRunPuppetPromise;
302 mRunPuppetPromise = nullptr;
303 if (aSuccess) {
304 promise->MaybeResolve(JS::UndefinedHandleValue);
305 } else {
306 promise->MaybeRejectWithUndefined();
307 }
308 return IPC_OK()mozilla::ipc::IPCResult::Ok();
309}
310
311mozilla::ipc::IPCResult VRManagerChild::RecvNotifyPuppetResetComplete() {
312 nsTArray<RefPtr<dom::Promise>> promises;
313 promises.AppendElements(mResetPuppetPromises);
314 mResetPuppetPromises.Clear();
315 for (const auto& promise : promises) {
316 promise->MaybeResolve(JS::UndefinedHandleValue);
317 }
318 return IPC_OK()mozilla::ipc::IPCResult::Ok();
319}
320
321void VRManagerChild::RunPuppet(const nsTArray<uint64_t>& aBuffer,
322 dom::Promise* aPromise, ErrorResult& aRv) {
323 if (mRunPuppetPromise) {
324 // We only allow one puppet script to run simultaneously.
325 // The prior promise must be resolved before running a new
326 // script.
327 aRv.Throw(NS_ERROR_INVALID_ARG);
328 return;
329 }
330 if (!SendRunPuppet(aBuffer)) {
331 aRv.Throw(NS_ERROR_FAILURE);
332 return;
333 }
334 mRunPuppetPromise = aPromise;
335}
336
337void VRManagerChild::ResetPuppet(dom::Promise* aPromise, ErrorResult& aRv) {
338 if (!SendResetPuppet()) {
339 aRv.Throw(NS_ERROR_FAILURE);
340 return;
341 }
342 mResetPuppetPromises.AppendElement(aPromise);
343}
344
345void VRManagerChild::GetVRDisplays(
346 nsTArray<RefPtr<VRDisplayClient>>& aDisplays) {
347 aDisplays = mDisplays.Clone();
348}
349
350bool VRManagerChild::RefreshVRDisplaysWithCallback(uint64_t aWindowId) {
351 bool success = SendRefreshDisplays();
352 if (success) {
353 mNavigatorCallbacks.AppendElement(aWindowId);
354 }
355 return success;
356}
357
358bool VRManagerChild::EnumerateVRDisplays() {
359 bool success = SendRefreshDisplays();
360 if (success) {
361 mWaitingForEnumeration = true;
362 }
363 return success;
364}
365
366void VRManagerChild::DetectRuntimes() { Unused << SendDetectRuntimes(); }
367
368PVRLayerChild* VRManagerChild::CreateVRLayer(uint32_t aDisplayID,
369 uint32_t aGroup) {
370 PVRLayerChild* vrLayerChild = AllocPVRLayerChild(aDisplayID, aGroup);
371 return SendPVRLayerConstructor(vrLayerChild, aDisplayID, aGroup);
372}
373
374void VRManagerChild::XRFrameRequest::Call(
375 const DOMHighResTimeStamp& aTimeStamp) {
376 if (mCallback) {
377 RefPtr<mozilla::dom::FrameRequestCallback> callback = mCallback;
378 callback->Call(aTimeStamp);
379 } else {
380 RefPtr<mozilla::dom::XRFrameRequestCallback> callback = mXRCallback;
381 RefPtr<mozilla::dom::XRFrame> frame = mXRFrame;
382 callback->Call(aTimeStamp, *frame);
383 }
384}
385
386nsresult VRManagerChild::ScheduleFrameRequestCallback(
387 mozilla::dom::FrameRequestCallback& aCallback, int32_t* aHandle) {
388 if (mFrameRequestCallbackCounter == INT32_MAX(2147483647)) {
389 // Can't increment without overflowing; bail out
390 return NS_ERROR_NOT_AVAILABLE;
391 }
392 int32_t newHandle = ++mFrameRequestCallbackCounter;
393
394 mFrameRequestCallbacks.AppendElement(XRFrameRequest(aCallback, newHandle));
395
396 *aHandle = newHandle;
397 return NS_OK;
398}
399
400void VRManagerChild::CancelFrameRequestCallback(int32_t aHandle) {
401 // mFrameRequestCallbacks is stored sorted by handle
402 mFrameRequestCallbacks.RemoveElementSorted(aHandle);
403}
404
405void VRManagerChild::RunFrameRequestCallbacks() {
406 AUTO_PROFILER_TRACING_MARKER("VR", "RunFrameRequestCallbacks", GRAPHICS)AutoProfilerTracing raiiObject406("VR", "RunFrameRequestCallbacks"
, geckoprofiler::category::GRAPHICS, mozilla::Nothing())
;
407
408 TimeStamp nowTime = TimeStamp::Now();
409 mozilla::TimeDuration duration = nowTime - mStartTimeStamp;
410 DOMHighResTimeStamp timeStamp = duration.ToMilliseconds();
411
412 if (!sMostRecentFrameEnd.IsNull()) {
413 TimeDuration frameInterval = nowTime - sMostRecentFrameEnd;
414 if (sAverageFrameInterval.IsZero()) {
415 sAverageFrameInterval = frameInterval;
416 } else {
417 // Calculate the average interval between frame end and next frame start.
418 // Apply some smoothing to make it more stable.
419 const double smooth = 0.9;
420 sAverageFrameInterval = sAverageFrameInterval.MultDouble(smooth) +
421 frameInterval.MultDouble(1.0 - smooth);
422 }
423 }
424
425 nsTArray<XRFrameRequest> callbacks;
426 callbacks.AppendElements(mFrameRequestCallbacks);
427 mFrameRequestCallbacks.Clear();
428 for (auto& callback : callbacks) {
429 // The FrameRequest copied into the on-stack array holds a strong ref to its
430 // mCallback and there's nothing that can drop that ref until we return.
431 MOZ_KnownLive(callback.mCallback)(callback.mCallback)->Call(timeStamp);
432 }
433
434 if (IsPresenting()) {
435 sMostRecentFrameEnd = TimeStamp::Now();
436 }
437}
438
439void VRManagerChild::NotifyPresentationGenerationChanged(uint32_t aDisplayID) {
440 nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(
441 "gfx::VRManagerChild::NotifyPresentationGenerationChangedInternal", this,
442 &VRManagerChild::NotifyPresentationGenerationChangedInternal,
443 aDisplayID));
444}
445
446void VRManagerChild::FireDOMVRDisplayMountedEvent(uint32_t aDisplayID) {
447 nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(
448 "gfx::VRManagerChild::FireDOMVRDisplayMountedEventInternal", this,
449 &VRManagerChild::FireDOMVRDisplayMountedEventInternal, aDisplayID));
450}
451
452void VRManagerChild::FireDOMVRDisplayUnmountedEvent(uint32_t aDisplayID) {
453 nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(
454 "gfx::VRManagerChild::FireDOMVRDisplayUnmountedEventInternal", this,
455 &VRManagerChild::FireDOMVRDisplayUnmountedEventInternal, aDisplayID));
456}
457
458void VRManagerChild::FireDOMVRDisplayConnectEvent(uint32_t aDisplayID) {
459 nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(
460 "gfx::VRManagerChild::FireDOMVRDisplayConnectEventInternal", this,
461 &VRManagerChild::FireDOMVRDisplayConnectEventInternal, aDisplayID));
462}
463
464void VRManagerChild::FireDOMVRDisplayDisconnectEvent(uint32_t aDisplayID) {
465 nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(
466 "gfx::VRManagerChild::FireDOMVRDisplayDisconnectEventInternal", this,
467 &VRManagerChild::FireDOMVRDisplayDisconnectEventInternal, aDisplayID));
468}
469
470void VRManagerChild::FireDOMVRDisplayPresentChangeEvent(uint32_t aDisplayID) {
471 nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(
472 "gfx::VRManagerChild::FireDOMVRDisplayPresentChangeEventInternal", this,
473 &VRManagerChild::FireDOMVRDisplayPresentChangeEventInternal, aDisplayID));
474
475 if (!IsPresenting()) {
476 sMostRecentFrameEnd = TimeStamp();
477 sAverageFrameInterval = 0;
478 }
479}
480
481void VRManagerChild::FireDOMVRDisplayMountedEventInternal(uint32_t aDisplayID) {
482 // Iterate over a copy of mListeners, as dispatched events may modify it.
483 for (auto& listener : mListeners.Clone()) {
484 listener->NotifyVRDisplayMounted(aDisplayID);
485 }
486}
487
488void VRManagerChild::FireDOMVRDisplayUnmountedEventInternal(
489 uint32_t aDisplayID) {
490 // Iterate over a copy of mListeners, as dispatched events may modify it.
491 for (auto& listener : mListeners.Clone()) {
492 listener->NotifyVRDisplayUnmounted(aDisplayID);
493 }
494}
495
496void VRManagerChild::FireDOMVRDisplayConnectEventInternal(uint32_t aDisplayID) {
497 // Iterate over a copy of mListeners, as dispatched events may modify it.
498 for (auto& listener : mListeners.Clone()) {
499 listener->NotifyVRDisplayConnect(aDisplayID);
500 }
501}
502
503void VRManagerChild::FireDOMVRDisplayDisconnectEventInternal(
504 uint32_t aDisplayID) {
505 // Iterate over a copy of mListeners, as dispatched events may modify it.
506 for (auto& listener : mListeners.Clone()) {
507 listener->NotifyVRDisplayDisconnect(aDisplayID);
508 }
509}
510
511void VRManagerChild::FireDOMVRDisplayPresentChangeEventInternal(
512 uint32_t aDisplayID) {
513 // Iterate over a copy of mListeners, as dispatched events may modify it.
514 for (auto& listener : mListeners.Clone()) {
515 // MOZ_KnownLive because 'listeners' is guaranteed to keep it alive.
516 //
517 // This can go away once
518 // https://bugzilla.mozilla.org/show_bug.cgi?id=1620312 is fixed.
519 MOZ_KnownLive(listener)(listener)->NotifyVRDisplayPresentChange(aDisplayID);
520 }
521}
522
523void VRManagerChild::FireDOMVRDisplayConnectEventsForLoadInternal(
524 uint32_t aDisplayID, VRManagerEventObserver* aObserver) {
525 aObserver->NotifyVRDisplayConnect(aDisplayID);
526}
527
528void VRManagerChild::NotifyPresentationGenerationChangedInternal(
529 uint32_t aDisplayID) {
530 for (auto& listener : mListeners.Clone()) {
531 listener->NotifyPresentationGenerationChanged(aDisplayID);
532 }
533}
534
535void VRManagerChild::NotifyEnumerationCompletedInternal() {
536 for (auto& listener : mListeners.Clone()) {
537 listener->NotifyEnumerationCompleted();
538 }
539}
540
541void VRManagerChild::FireDOMVRDisplayConnectEventsForLoad(
542 VRManagerEventObserver* aObserver) {
543 // We need to fire the VRDisplayConnect event when a page is loaded
544 // for each VR Display that has already been enumerated
545 for (const auto& display : mDisplays.Clone()) {
546 const VRDisplayInfo& info = display->GetDisplayInfo();
547 if (info.GetIsConnected()) {
548 nsContentUtils::AddScriptRunner(NewRunnableMethod<
549 uint32_t, RefPtr<VRManagerEventObserver>>(
550 "gfx::VRManagerChild::FireDOMVRDisplayConnectEventsForLoadInternal",
551 this, &VRManagerChild::FireDOMVRDisplayConnectEventsForLoadInternal,
552 info.GetDisplayID(), aObserver));
553 }
554 }
555}
556
557void VRManagerChild::AddListener(VRManagerEventObserver* aObserver) {
558 MOZ_ASSERT(aObserver)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aObserver)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aObserver))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aObserver", "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp"
, 558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aObserver" ")"
); do { *((volatile int*)__null) = 558; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
559
560 if (mListeners.IndexOf(aObserver) != kNoIndex) {
561 return; // already exists
562 }
563
564 mListeners.AppendElement(aObserver);
565 if (mListeners.Length() == 1) {
566 Unused << SendSetHaveEventListener(true);
567 }
568}
569
570void VRManagerChild::RemoveListener(VRManagerEventObserver* aObserver) {
571 MOZ_ASSERT(aObserver)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aObserver)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aObserver))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aObserver", "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp"
, 571); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aObserver" ")"
); do { *((volatile int*)__null) = 571; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
572
573 mListeners.RemoveElement(aObserver);
574 if (mListeners.IsEmpty()) {
575 Unused << SendSetHaveEventListener(false);
576 }
577}
578
579void VRManagerChild::StartActivity() { Unused << SendStartActivity(); }
580
581void VRManagerChild::StopActivity() {
582 for (auto& listener : mListeners) {
583 if (!listener->GetStopActivityStatus()) {
584 // We are still showing VR in the active window.
585 return;
586 }
587 }
588
589 Unused << SendStopActivity();
590}
591
592void VRManagerChild::HandleFatalError(const char* aMsg) {
593 dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aMsg, OtherPid());
594}
595
596void VRManagerChild::AddPromise(const uint32_t& aID, dom::Promise* aPromise) {
597 MOZ_ASSERT(!mGamepadPromiseList.Contains(aID))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mGamepadPromiseList.Contains(aID))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mGamepadPromiseList.Contains
(aID)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mGamepadPromiseList.Contains(aID)", "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp"
, 597); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mGamepadPromiseList.Contains(aID)"
")"); do { *((volatile int*)__null) = 597; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
598 mGamepadPromiseList.InsertOrUpdate(aID, RefPtr{aPromise});
599}
600
601gfx::VRAPIMode VRManagerChild::GetVRAPIMode(uint32_t aDisplayID) const {
602 for (auto& display : mDisplays) {
603 if (display->GetDisplayInfo().GetDisplayID() == aDisplayID) {
604 return display->GetXRAPIMode();
605 }
606 }
607 return VRAPIMode::WebXR;
608}
609
610mozilla::ipc::IPCResult VRManagerChild::RecvReplyGamepadVibrateHaptic(
611 const uint32_t& aPromiseID) {
612 // VRManagerChild could be at other processes, but GamepadManager
613 // only exists at the content process or the same process
614 // in non-e10s mode.
615 MOZ_ASSERT(XRE_IsContentProcess() || IsSameProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsContentProcess() || IsSameProcess())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(XRE_IsContentProcess() || IsSameProcess()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("XRE_IsContentProcess() || IsSameProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp"
, 615); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsContentProcess() || IsSameProcess()"
")"); do { *((volatile int*)__null) = 615; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
616
617 RefPtr<dom::Promise> p;
618 if (!mGamepadPromiseList.Get(aPromiseID, getter_AddRefs(p))) {
619 MOZ_CRASH("We should always have a promise.")do { do { } while (false); MOZ_ReportCrash("" "We should always have a promise."
, "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp"
, 619); AnnotateMozCrashReason("MOZ_CRASH(" "We should always have a promise."
")"); do { *((volatile int*)__null) = 619; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
620 }
621
622 p->MaybeResolve(true);
623 mGamepadPromiseList.Remove(aPromiseID);
624 return IPC_OK()mozilla::ipc::IPCResult::Ok();
625}
626
627} // namespace gfx
628} // namespace mozilla