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 file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/dom/XRSystem.h"
9 #include "mozilla/StaticPrefs_dom.h"
10 #include "mozilla/dom/XRPermissionRequest.h"
11 #include "mozilla/dom/XRSession.h"
12 #include "mozilla/dom/BindingCallContext.h"
13 #include "mozilla/dom/Document.h"
14 #include "mozilla/dom/Promise.h"
15 #include "mozilla/dom/FeaturePolicyUtils.h"
16 #include "mozilla/dom/PermissionMessageUtils.h"
17 #include "nsGlobalWindow.h"
18 #include "nsThreadUtils.h"
20 #include "VRDisplayClient.h"
21 #include "VRManagerChild.h"
28 ////////////////////////////////////////////////////////////////////////////////
29 // XRSystem cycle collection
30 NS_IMPL_CYCLE_COLLECTION_CLASS(XRSystem
)
32 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(XRSystem
,
34 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mActiveImmersiveSession
)
35 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInlineSessions
)
36 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIsSessionSupportedRequests
)
37 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(
38 mRequestSessionRequestsWaitingForRuntimeDetection
)
39 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRequestSessionRequestsWithoutHardware
)
40 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(
41 mRequestSessionRequestsWaitingForEnumeration
)
42 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
44 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(XRSystem
, DOMEventTargetHelper
)
45 NS_IMPL_CYCLE_COLLECTION_UNLINK(mActiveImmersiveSession
)
46 NS_IMPL_CYCLE_COLLECTION_UNLINK(mInlineSessions
)
47 NS_IMPL_CYCLE_COLLECTION_UNLINK(mIsSessionSupportedRequests
)
48 NS_IMPL_CYCLE_COLLECTION_UNLINK(
49 mRequestSessionRequestsWaitingForRuntimeDetection
)
50 NS_IMPL_CYCLE_COLLECTION_UNLINK(mRequestSessionRequestsWithoutHardware
)
51 NS_IMPL_CYCLE_COLLECTION_UNLINK(mRequestSessionRequestsWaitingForEnumeration
)
52 // Don't need NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER because
53 // DOMEventTargetHelper does it for us.
54 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
56 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(XRSystem
, DOMEventTargetHelper
)
58 JSObject
* XRSystem::WrapObject(JSContext
* aCx
,
59 JS::Handle
<JSObject
*> aGivenProto
) {
60 return XRSystem_Binding::Wrap(aCx
, this, aGivenProto
);
64 already_AddRefed
<XRSystem
> XRSystem::Create(nsPIDOMWindowInner
* aWindow
) {
67 RefPtr
<XRSystem
> service
= new XRSystem(aWindow
);
68 return service
.forget();
71 XRSystem::XRSystem(nsPIDOMWindowInner
* aWindow
)
72 : DOMEventTargetHelper(aWindow
),
74 mPendingImmersiveSession(false),
75 mEnumerationInFlight(false) {
76 // Unregister with VRManagerChild
77 VRManagerChild
* vmc
= VRManagerChild::Get();
79 vmc
->AddListener(this);
83 void XRSystem::Shutdown() {
84 MOZ_ASSERT(!mShuttingDown
);
87 // Unregister from VRManagerChild
88 if (VRManagerChild::IsCreated()) {
89 VRManagerChild
* vmc
= VRManagerChild::Get();
90 vmc
->RemoveListener(this);
94 void XRSystem::SessionEnded(XRSession
* aSession
) {
95 if (mActiveImmersiveSession
== aSession
) {
96 mActiveImmersiveSession
= nullptr;
98 mInlineSessions
.RemoveElement(aSession
);
101 already_AddRefed
<Promise
> XRSystem::IsSessionSupported(XRSessionMode aMode
,
103 nsCOMPtr
<nsIGlobalObject
> global
= GetParentObject();
104 NS_ENSURE_TRUE(global
, nullptr);
106 RefPtr
<Promise
> promise
= Promise::Create(global
, aRv
);
107 NS_ENSURE_TRUE(!aRv
.Failed(), nullptr);
109 if (aMode
== XRSessionMode::Inline
) {
110 promise
->MaybeResolve(true);
111 return promise
.forget();
114 if (mIsSessionSupportedRequests
.IsEmpty()) {
115 gfx::VRManagerChild
* vm
= gfx::VRManagerChild::Get();
116 vm
->DetectRuntimes();
119 RefPtr
<IsSessionSupportedRequest
> request
=
120 new IsSessionSupportedRequest(aMode
, promise
);
121 mIsSessionSupportedRequests
.AppendElement(request
);
122 return promise
.forget();
125 already_AddRefed
<Promise
> XRSystem::RequestSession(
126 JSContext
* aCx
, XRSessionMode aMode
, const XRSessionInit
& aOptions
,
127 CallerType aCallerType
, ErrorResult
& aRv
) {
128 nsCOMPtr
<nsIGlobalObject
> global
= GetParentObject();
129 NS_ENSURE_TRUE(global
, nullptr);
131 RefPtr
<Promise
> promise
= Promise::Create(global
, aRv
);
132 NS_ENSURE_TRUE(!aRv
.Failed(), nullptr);
134 bool immersive
= (aMode
== XRSessionMode::Immersive_vr
||
135 aMode
== XRSessionMode::Immersive_ar
);
137 // The document must be a responsible document, active and focused.
138 nsCOMPtr
<Document
> responsibleDocument
= GetDocumentIfCurrent();
139 if (!responsibleDocument
) {
140 // The document is not trustworthy
141 promise
->MaybeRejectWithSecurityError("This document is not responsible.");
142 return promise
.forget();
145 if (immersive
|| aOptions
.mRequiredFeatures
.WasPassed() ||
146 aOptions
.mOptionalFeatures
.WasPassed()) {
147 if (!responsibleDocument
->HasValidTransientUserGestureActivation() &&
148 aCallerType
!= CallerType::System
&&
149 StaticPrefs::dom_vr_require_gesture()) {
150 // A user gesture is required.
151 promise
->MaybeRejectWithSecurityError("A user gesture is required.");
152 return promise
.forget();
156 nsTArray
<XRReferenceSpaceType
> requiredReferenceSpaceTypes
;
157 nsTArray
<XRReferenceSpaceType
> optionalReferenceSpaceTypes
;
160 * By default, all sessions will require XRReferenceSpaceType::Viewer
161 * and immersive sessions will require XRReferenceSpaceType::Local.
163 * https://www.w3.org/TR/webxr/#default-features
165 requiredReferenceSpaceTypes
.AppendElement(XRReferenceSpaceType::Viewer
);
167 requiredReferenceSpaceTypes
.AppendElement(XRReferenceSpaceType::Local
);
170 BindingCallContext
callCx(aCx
, "XRSystem.requestSession");
172 if (aOptions
.mRequiredFeatures
.WasPassed()) {
173 const Sequence
<JS::Value
>& arr
= (aOptions
.mRequiredFeatures
.Value());
174 for (const JS::Value
& val
: arr
) {
175 if (!val
.isNull() && !val
.isUndefined()) {
177 JS::RootedValue
v(aCx
, val
);
179 if (FindEnumStringIndex
<false>(
180 callCx
, v
, XRReferenceSpaceTypeValues::strings
,
181 "XRReferenceSpaceType", "Argument 2 of XR.requestSession",
184 requiredReferenceSpaceTypes
.AppendElement(
185 static_cast<XRReferenceSpaceType
>(index
));
190 promise
->MaybeRejectWithNotSupportedError(
191 "A required feature for the XRSession is not available.");
192 return promise
.forget();
198 if (aOptions
.mOptionalFeatures
.WasPassed()) {
199 const Sequence
<JS::Value
>& arr
= (aOptions
.mOptionalFeatures
.Value());
200 for (const JS::Value
& val
: arr
) {
201 if (!val
.isNull() && !val
.isUndefined()) {
202 JS::RootedValue
v(aCx
, val
);
204 if (FindEnumStringIndex
<false>(
205 callCx
, v
, XRReferenceSpaceTypeValues::strings
,
206 "XRReferenceSpaceType", "Argument 2 of XR.requestSession",
209 optionalReferenceSpaceTypes
.AppendElement(
210 static_cast<XRReferenceSpaceType
>(index
));
218 if (mPendingImmersiveSession
|| mActiveImmersiveSession
) {
219 promise
->MaybeRejectWithInvalidStateError(
220 "There can only be one immersive XRSession.");
221 return promise
.forget();
223 mPendingImmersiveSession
= true;
226 bool isChromeSession
= aCallerType
== CallerType::System
;
227 uint32_t presentationGroup
=
228 isChromeSession
? gfx::kVRGroupChrome
: gfx::kVRGroupContent
;
229 RefPtr
<RequestSessionRequest
> request
= new RequestSessionRequest(
230 aMode
, presentationGroup
, promise
, requiredReferenceSpaceTypes
,
231 optionalReferenceSpaceTypes
);
232 if (request
->WantsHardware()) {
233 QueueSessionRequestWithEnumeration(request
);
235 QueueSessionRequestWithoutEnumeration(request
);
238 return promise
.forget();
241 void XRSystem::QueueSessionRequestWithEnumeration(
242 RequestSessionRequest
* aRequest
) {
243 MOZ_ASSERT(aRequest
->WantsHardware());
244 mRequestSessionRequestsWaitingForRuntimeDetection
.AppendElement(aRequest
);
245 gfx::VRManagerChild
* vm
= gfx::VRManagerChild::Get();
246 vm
->DetectRuntimes();
249 void XRSystem::QueueSessionRequestWithoutEnumeration(
250 RequestSessionRequest
* aRequest
) {
251 MOZ_ASSERT(!aRequest
->NeedsHardware());
252 mRequestSessionRequestsWithoutHardware
.AppendElement(aRequest
);
254 ResolveSessionRequestsWithoutHardware();
257 bool XRSystem::CancelHardwareRequest(RequestSessionRequest
* aRequest
) {
258 if (!aRequest
->NeedsHardware()) {
259 // If hardware access was an optional requirement and the user
260 // opted not to provide access, queue the request
261 // to be resolved without hardware.
262 QueueSessionRequestWithoutEnumeration(aRequest
);
266 if (aRequest
->IsImmersive()) {
267 mPendingImmersiveSession
= false;
272 bool XRSystem::OnXRPermissionRequestAllow() {
273 if (!gfx::VRManagerChild::IsCreated()) {
274 // It's possible that this callback returns after
275 // we have already started shutting down.
278 if (!mEnumerationInFlight
) {
279 mEnumerationInFlight
= true;
280 gfx::VRManagerChild
* vm
= gfx::VRManagerChild::Get();
281 Unused
<< vm
->EnumerateVRDisplays();
283 return mEnumerationInFlight
||
284 !mRequestSessionRequestsWaitingForEnumeration
.IsEmpty();
287 void XRSystem::OnXRPermissionRequestCancel() {
288 nsTArray
<RefPtr
<RequestSessionRequest
>> requestSessionRequests(
289 std::move(mRequestSessionRequestsWaitingForEnumeration
));
290 for (RefPtr
<RequestSessionRequest
>& request
: requestSessionRequests
) {
291 if (CancelHardwareRequest(request
)) {
292 request
->mPromise
->MaybeRejectWithSecurityError(
293 "A device supporting the requested session "
294 "configuration could not be found.");
299 bool XRSystem::FeaturePolicyBlocked() const {
300 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(GetOwner());
304 RefPtr
<XRPermissionRequest
> request
=
305 new XRPermissionRequest(win
, win
->WindowID());
306 return !(request
->CheckPermissionDelegate());
309 bool XRSystem::HasActiveImmersiveSession() const {
310 return mActiveImmersiveSession
;
313 void XRSystem::ResolveSessionRequestsWithoutHardware() {
314 // Resolve promises returned by RequestSession
315 nsTArray
<RefPtr
<gfx::VRDisplayClient
>> displays
;
316 // Try resolving support without a device, for inline sessions.
317 displays
.AppendElement(nullptr);
319 nsTArray
<RefPtr
<RequestSessionRequest
>> requestSessionRequests(
320 std::move(mRequestSessionRequestsWithoutHardware
));
322 ResolveSessionRequests(requestSessionRequests
, displays
);
325 void XRSystem::NotifyEnumerationCompleted() {
326 // Enumeration has completed.
327 mEnumerationInFlight
= false;
329 if (!gfx::VRManagerChild::IsCreated()) {
330 // It's possible that this callback returns after
331 // we have already started shutting down.
335 // Resolve promises returned by RequestSession
336 nsTArray
<RefPtr
<gfx::VRDisplayClient
>> displays
;
337 gfx::VRManagerChild
* vm
= gfx::VRManagerChild::Get();
338 vm
->GetVRDisplays(displays
);
340 nsTArray
<RefPtr
<RequestSessionRequest
>> requestSessionRequests(
341 std::move(mRequestSessionRequestsWaitingForEnumeration
));
343 ResolveSessionRequests(requestSessionRequests
, displays
);
346 void XRSystem::ResolveSessionRequests(
347 nsTArray
<RefPtr
<RequestSessionRequest
>>& aRequests
,
348 const nsTArray
<RefPtr
<gfx::VRDisplayClient
>>& aDisplays
) {
349 for (RefPtr
<RequestSessionRequest
>& request
: aRequests
) {
350 RefPtr
<XRSession
> session
;
351 if (request
->IsImmersive()) {
352 mPendingImmersiveSession
= false;
354 // Select an XR device
355 for (const RefPtr
<gfx::VRDisplayClient
>& display
: aDisplays
) {
356 nsTArray
<XRReferenceSpaceType
> enabledReferenceSpaceTypes
;
357 if (request
->ResolveSupport(display
, enabledReferenceSpaceTypes
)) {
358 if (request
->IsImmersive()) {
359 session
= XRSession::CreateImmersiveSession(
360 GetOwner(), this, display
, request
->GetPresentationGroup(),
361 enabledReferenceSpaceTypes
);
362 mActiveImmersiveSession
= session
;
364 session
= XRSession::CreateInlineSession(GetOwner(), this,
365 enabledReferenceSpaceTypes
);
366 mInlineSessions
.AppendElement(session
);
368 request
->mPromise
->MaybeResolve(session
);
373 request
->mPromise
->MaybeRejectWithNotSupportedError(
374 "A device supporting the required XRSession configuration "
375 "could not be found.");
380 void XRSystem::NotifyDetectRuntimesCompleted() {
381 ResolveIsSessionSupportedRequests();
382 if (!mRequestSessionRequestsWaitingForRuntimeDetection
.IsEmpty()) {
383 ProcessSessionRequestsWaitingForRuntimeDetection();
387 void XRSystem::ResolveIsSessionSupportedRequests() {
388 // Resolve promises returned by IsSessionSupported
389 gfx::VRManagerChild
* vm
= gfx::VRManagerChild::Get();
390 nsTArray
<RefPtr
<IsSessionSupportedRequest
>> isSessionSupportedRequests(
391 std::move(mIsSessionSupportedRequests
));
392 bool featurePolicyBlocked
= FeaturePolicyBlocked();
394 for (RefPtr
<IsSessionSupportedRequest
>& request
:
395 isSessionSupportedRequests
) {
396 if (featurePolicyBlocked
) {
397 request
->mPromise
->MaybeRejectWithSecurityError(
398 "The xr-spatial-tracking feature policy is required.");
402 bool supported
= false;
403 switch (request
->GetSessionMode()) {
404 case XRSessionMode::Immersive_vr
:
405 supported
= vm
->RuntimeSupportsVR();
407 case XRSessionMode::Immersive_ar
:
408 supported
= vm
->RuntimeSupportsAR();
413 request
->mPromise
->MaybeResolve(supported
);
417 void XRSystem::ProcessSessionRequestsWaitingForRuntimeDetection() {
418 bool alreadyRequestedPermission
=
419 !mRequestSessionRequestsWaitingForEnumeration
.IsEmpty();
420 bool featurePolicyBlocked
= FeaturePolicyBlocked();
421 gfx::VRManagerChild
* vm
= gfx::VRManagerChild::Get();
423 nsTArray
<RefPtr
<RequestSessionRequest
>> sessionRequests(
424 std::move(mRequestSessionRequestsWaitingForRuntimeDetection
));
426 for (RefPtr
<RequestSessionRequest
>& request
: sessionRequests
) {
427 bool compatibleRuntime
= false;
428 switch (request
->GetSessionMode()) {
429 case XRSessionMode::Immersive_vr
:
430 compatibleRuntime
= vm
->RuntimeSupportsVR();
432 case XRSessionMode::Immersive_ar
:
433 compatibleRuntime
= vm
->RuntimeSupportsAR();
435 case XRSessionMode::Inline
:
436 compatibleRuntime
= vm
->RuntimeSupportsInline();
441 if (!compatibleRuntime
) {
442 // If none of the requested sessions are supported by a
443 // runtime, early exit without showing a permission prompt.
444 if (CancelHardwareRequest(request
)) {
445 request
->mPromise
->MaybeRejectWithNotSupportedError(
446 "A device supporting the required XRSession configuration "
447 "could not be found.");
451 if (featurePolicyBlocked
) {
452 // Don't show a permission prompt if blocked by feature policy.
453 if (CancelHardwareRequest(request
)) {
454 request
->mPromise
->MaybeRejectWithSecurityError(
455 "The xr-spatial-tracking feature policy is required.");
459 // To continue evaluating this request, it must wait for hardware
460 // enumeration and permission request.
461 mRequestSessionRequestsWaitingForEnumeration
.AppendElement(request
);
464 if (!mRequestSessionRequestsWaitingForEnumeration
.IsEmpty() &&
465 !alreadyRequestedPermission
) {
467 * Inline sessions will require only a user gesture
468 * and should not trigger XR permission UI.
469 * This is not a problem currently, as the only platforms
470 * allowing xr-spatial-tracking for inline sessions do not
471 * present a modal XR permission UI. (eg. Android Firefox Reality)
473 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(GetOwner());
474 win
->RequestXRPermission();
478 void XRSystem::NotifyVRDisplayMounted(uint32_t aDisplayID
) {}
479 void XRSystem::NotifyVRDisplayUnmounted(uint32_t aDisplayID
) {}
481 void XRSystem::NotifyVRDisplayConnect(uint32_t aDisplayID
) {
482 DispatchTrustedEvent(u
"devicechange"_ns
);
485 void XRSystem::NotifyVRDisplayDisconnect(uint32_t aDisplayID
) {
486 DispatchTrustedEvent(u
"devicechange"_ns
);
489 void XRSystem::NotifyVRDisplayPresentChange(uint32_t aDisplayID
) {}
490 void XRSystem::NotifyPresentationGenerationChanged(uint32_t aDisplayID
) {
491 if (mActiveImmersiveSession
) {
492 mActiveImmersiveSession
->ExitPresent();
495 bool XRSystem::GetStopActivityStatus() const { return true; }
497 RequestSessionRequest::RequestSessionRequest(
498 XRSessionMode aSessionMode
, uint32_t aPresentationGroup
, Promise
* aPromise
,
499 const nsTArray
<XRReferenceSpaceType
>& aRequiredReferenceSpaceTypes
,
500 const nsTArray
<XRReferenceSpaceType
>& aOptionalReferenceSpaceTypes
)
501 : mPromise(aPromise
),
502 mSessionMode(aSessionMode
),
503 mPresentationGroup(aPresentationGroup
),
504 mRequiredReferenceSpaceTypes(aRequiredReferenceSpaceTypes
.Clone()),
505 mOptionalReferenceSpaceTypes(aOptionalReferenceSpaceTypes
.Clone()) {}
507 bool RequestSessionRequest::ResolveSupport(
508 const gfx::VRDisplayClient
* aDisplay
,
509 nsTArray
<XRReferenceSpaceType
>& aEnabledReferenceSpaceTypes
) const {
511 if (!aDisplay
->GetIsConnected()) {
514 if ((aDisplay
->GetDisplayInfo().GetPresentingGroups() &
515 mPresentationGroup
) != 0) {
519 const gfx::VRDisplayInfo
& info
= aDisplay
->GetDisplayInfo();
520 switch (mSessionMode
) {
521 case XRSessionMode::Inline
:
522 if (!bool(info
.mDisplayState
.capabilityFlags
&
523 gfx::VRDisplayCapabilityFlags::Cap_Inline
)) {
527 case XRSessionMode::Immersive_vr
:
528 if (!bool(info
.mDisplayState
.capabilityFlags
&
529 gfx::VRDisplayCapabilityFlags::Cap_ImmersiveVR
)) {
533 case XRSessionMode::Immersive_ar
:
534 if (!bool(info
.mDisplayState
.capabilityFlags
&
535 gfx::VRDisplayCapabilityFlags::Cap_ImmersiveAR
)) {
542 } else if (mSessionMode
!= XRSessionMode::Inline
) {
543 // If we don't have a device, we can only support inline sessions
547 // All sessions support XRReferenceSpaceType::Viewer by default
548 aEnabledReferenceSpaceTypes
.AppendElement(XRReferenceSpaceType::Viewer
);
550 // Immersive sessions support XRReferenceSpaceType::Local by default
552 aEnabledReferenceSpaceTypes
.AppendElement(XRReferenceSpaceType::Local
);
555 for (XRReferenceSpaceType type
: mRequiredReferenceSpaceTypes
) {
557 if (!aDisplay
->IsReferenceSpaceTypeSupported(type
)) {
560 } else if (type
!= XRReferenceSpaceType::Viewer
) {
561 // If we don't have a device, We only support
562 // XRReferenceSpaceType::Viewer
565 if (!aEnabledReferenceSpaceTypes
.Contains(type
)) {
566 aEnabledReferenceSpaceTypes
.AppendElement(type
);
570 for (XRReferenceSpaceType type
: mOptionalReferenceSpaceTypes
) {
571 if (aDisplay
->IsReferenceSpaceTypeSupported(type
) &&
572 !aEnabledReferenceSpaceTypes
.Contains(type
)) {
573 aEnabledReferenceSpaceTypes
.AppendElement(type
);
580 bool RequestSessionRequest::IsImmersive() const {
581 return (mSessionMode
== XRSessionMode::Immersive_vr
||
582 mSessionMode
== XRSessionMode::Immersive_ar
);
585 bool RequestSessionRequest::WantsHardware() const {
586 for (XRReferenceSpaceType type
: mOptionalReferenceSpaceTypes
) {
587 // Any XRReferenceSpaceType other than Viewer requires hardware
588 if (type
!= XRReferenceSpaceType::Viewer
) {
592 return NeedsHardware();
595 bool RequestSessionRequest::NeedsHardware() const {
596 for (XRReferenceSpaceType type
: mRequiredReferenceSpaceTypes
) {
597 // Any XRReferenceSpaceType other than Viewer requires hardware
598 if (type
!= XRReferenceSpaceType::Viewer
) {
605 XRSessionMode
RequestSessionRequest::GetSessionMode() const {
609 uint32_t RequestSessionRequest::GetPresentationGroup() const {
610 return mPresentationGroup
;
613 ////////////////////////////////////////////////////////////////////////////////
614 // IsSessionSupportedRequest cycle collection
615 NS_IMPL_CYCLE_COLLECTION(IsSessionSupportedRequest
, mPromise
)
617 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(IsSessionSupportedRequest
, AddRef
)
618 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(IsSessionSupportedRequest
, Release
)
620 XRSessionMode
IsSessionSupportedRequest::GetSessionMode() const {
624 ////////////////////////////////////////////////////////////////////////////////
625 // XRRequestSessionPermissionRequest cycle collection
626 NS_IMPL_CYCLE_COLLECTION_INHERITED(XRRequestSessionPermissionRequest
,
627 ContentPermissionRequestBase
)
629 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(
630 XRRequestSessionPermissionRequest
, ContentPermissionRequestBase
)
632 XRRequestSessionPermissionRequest::XRRequestSessionPermissionRequest(
633 nsPIDOMWindowInner
* aWindow
, nsIPrincipal
* aNodePrincipal
,
634 AllowCallback
&& aAllowCallback
,
635 AllowAnySiteCallback
&& aAllowAnySiteCallback
,
636 CancelCallback
&& aCancelCallback
)
637 : ContentPermissionRequestBase(aNodePrincipal
, aWindow
, "dom.xr"_ns
,
639 mAllowCallback(std::move(aAllowCallback
)),
640 mAllowAnySiteCallback(std::move(aAllowAnySiteCallback
)),
641 mCancelCallback(std::move(aCancelCallback
)),
642 mCallbackCalled(false) {
643 mPermissionRequests
.AppendElement(
644 PermissionRequest(mType
, nsTArray
<nsString
>()));
647 XRRequestSessionPermissionRequest::~XRRequestSessionPermissionRequest() {
652 XRRequestSessionPermissionRequest::Cancel() {
653 if (!mCallbackCalled
) {
654 mCallbackCalled
= true;
661 XRRequestSessionPermissionRequest::Allow(JS::HandleValue aChoices
) {
662 nsTArray
<PermissionChoice
> choices
;
663 nsresult rv
= TranslateChoices(aChoices
, mPermissionRequests
, choices
);
668 // There is no support to allow grants automatically from the prompting code
671 if (!mCallbackCalled
) {
672 mCallbackCalled
= true;
673 if (choices
.Length() == 1 &&
674 choices
[0].choice().EqualsLiteral("allow-on-any-site")) {
675 mAllowAnySiteCallback();
676 } else if (choices
.Length() == 1 &&
677 choices
[0].choice().EqualsLiteral("allow")) {
684 already_AddRefed
<XRRequestSessionPermissionRequest
>
685 XRRequestSessionPermissionRequest::Create(
686 nsPIDOMWindowInner
* aWindow
, AllowCallback
&& aAllowCallback
,
687 AllowAnySiteCallback
&& aAllowAnySiteCallback
,
688 CancelCallback
&& aCancelCallback
) {
692 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(aWindow
);
693 if (!win
->GetPrincipal()) {
696 RefPtr
<XRRequestSessionPermissionRequest
> request
=
697 new XRRequestSessionPermissionRequest(
698 aWindow
, win
->GetPrincipal(), std::move(aAllowCallback
),
699 std::move(aAllowAnySiteCallback
), std::move(aCancelCallback
));
700 return request
.forget();
703 ////////////////////////////////////////////////////////////////////////////////
704 // RequestSessionRequest cycle collection
705 NS_IMPL_CYCLE_COLLECTION(RequestSessionRequest
, mPromise
)
707 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(RequestSessionRequest
, AddRef
)
708 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(RequestSessionRequest
, Release
)
711 } // namespace mozilla