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 "nsGlobalWindowInner.h"
18 #include "nsThreadUtils.h"
20 #include "VRDisplayClient.h"
21 #include "VRManagerChild.h"
23 namespace mozilla::dom
{
27 ////////////////////////////////////////////////////////////////////////////////
28 // XRSystem cycle collection
29 NS_IMPL_CYCLE_COLLECTION_CLASS(XRSystem
)
31 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(XRSystem
,
33 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mActiveImmersiveSession
)
34 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInlineSessions
)
35 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIsSessionSupportedRequests
)
36 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(
37 mRequestSessionRequestsWaitingForRuntimeDetection
)
38 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRequestSessionRequestsWithoutHardware
)
39 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(
40 mRequestSessionRequestsWaitingForEnumeration
)
41 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
43 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(XRSystem
, DOMEventTargetHelper
)
44 NS_IMPL_CYCLE_COLLECTION_UNLINK(mActiveImmersiveSession
)
45 NS_IMPL_CYCLE_COLLECTION_UNLINK(mInlineSessions
)
46 NS_IMPL_CYCLE_COLLECTION_UNLINK(mIsSessionSupportedRequests
)
47 NS_IMPL_CYCLE_COLLECTION_UNLINK(
48 mRequestSessionRequestsWaitingForRuntimeDetection
)
49 NS_IMPL_CYCLE_COLLECTION_UNLINK(mRequestSessionRequestsWithoutHardware
)
50 NS_IMPL_CYCLE_COLLECTION_UNLINK(mRequestSessionRequestsWaitingForEnumeration
)
51 // Don't need NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER because
52 // DOMEventTargetHelper does it for us.
53 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
55 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(XRSystem
, DOMEventTargetHelper
)
57 JSObject
* XRSystem::WrapObject(JSContext
* aCx
,
58 JS::Handle
<JSObject
*> aGivenProto
) {
59 return XRSystem_Binding::Wrap(aCx
, this, aGivenProto
);
63 already_AddRefed
<XRSystem
> XRSystem::Create(nsPIDOMWindowInner
* aWindow
) {
66 RefPtr
<XRSystem
> service
= new XRSystem(aWindow
);
67 return service
.forget();
70 XRSystem::XRSystem(nsPIDOMWindowInner
* aWindow
)
71 : DOMEventTargetHelper(aWindow
),
73 mPendingImmersiveSession(false),
74 mEnumerationInFlight(false) {
75 // Unregister with VRManagerChild
76 VRManagerChild
* vmc
= VRManagerChild::Get();
78 vmc
->AddListener(this);
82 void XRSystem::Shutdown() {
83 MOZ_ASSERT(!mShuttingDown
);
86 // Unregister from VRManagerChild
87 if (VRManagerChild::IsCreated()) {
88 VRManagerChild
* vmc
= VRManagerChild::Get();
89 vmc
->RemoveListener(this);
93 void XRSystem::SessionEnded(XRSession
* aSession
) {
94 if (mActiveImmersiveSession
== aSession
) {
95 mActiveImmersiveSession
= nullptr;
97 mInlineSessions
.RemoveElement(aSession
);
100 already_AddRefed
<Promise
> XRSystem::IsSessionSupported(XRSessionMode aMode
,
102 nsCOMPtr
<nsIGlobalObject
> global
= GetParentObject();
103 NS_ENSURE_TRUE(global
, nullptr);
105 RefPtr
<Promise
> promise
= Promise::Create(global
, aRv
);
106 NS_ENSURE_TRUE(!aRv
.Failed(), nullptr);
108 if (aMode
== XRSessionMode::Inline
) {
109 promise
->MaybeResolve(true);
110 return promise
.forget();
113 if (mIsSessionSupportedRequests
.IsEmpty()) {
114 gfx::VRManagerChild
* vm
= gfx::VRManagerChild::Get();
115 vm
->DetectRuntimes();
118 RefPtr
<IsSessionSupportedRequest
> request
=
119 new IsSessionSupportedRequest(aMode
, promise
);
120 mIsSessionSupportedRequests
.AppendElement(request
);
121 return promise
.forget();
124 already_AddRefed
<Promise
> XRSystem::RequestSession(
125 XRSessionMode aMode
, const XRSessionInit
& aOptions
, CallerType aCallerType
,
127 nsCOMPtr
<nsIGlobalObject
> global
= GetParentObject();
128 NS_ENSURE_TRUE(global
, nullptr);
130 RefPtr
<Promise
> promise
= Promise::Create(global
, aRv
);
131 NS_ENSURE_TRUE(!aRv
.Failed(), nullptr);
133 bool immersive
= (aMode
== XRSessionMode::Immersive_vr
||
134 aMode
== XRSessionMode::Immersive_ar
);
136 // The document must be a responsible document, active and focused.
137 nsCOMPtr
<Document
> responsibleDocument
= GetDocumentIfCurrent();
138 if (!responsibleDocument
) {
139 // The document is not trustworthy
140 promise
->MaybeRejectWithSecurityError("This document is not responsible.");
141 return promise
.forget();
144 if (immersive
|| aOptions
.mRequiredFeatures
.WasPassed() ||
145 aOptions
.mOptionalFeatures
.WasPassed()) {
146 if (!responsibleDocument
->HasValidTransientUserGestureActivation() &&
147 aCallerType
!= CallerType::System
&&
148 StaticPrefs::dom_vr_require_gesture()) {
149 // A user gesture is required.
150 promise
->MaybeRejectWithSecurityError("A user gesture is required.");
151 return promise
.forget();
155 nsTArray
<XRReferenceSpaceType
> requiredReferenceSpaceTypes
;
156 nsTArray
<XRReferenceSpaceType
> optionalReferenceSpaceTypes
;
159 * By default, all sessions will require XRReferenceSpaceType::Viewer
160 * and immersive sessions will require XRReferenceSpaceType::Local.
162 * https://www.w3.org/TR/webxr/#default-features
164 requiredReferenceSpaceTypes
.AppendElement(XRReferenceSpaceType::Viewer
);
166 requiredReferenceSpaceTypes
.AppendElement(XRReferenceSpaceType::Local
);
169 if (aOptions
.mRequiredFeatures
.WasPassed()) {
170 for (const nsString
& val
: aOptions
.mRequiredFeatures
.Value()) {
171 Maybe
<XRReferenceSpaceType
> type
=
172 StringToEnum
<XRReferenceSpaceType
>(val
);
173 if (type
.isNothing()) {
174 promise
->MaybeRejectWithNotSupportedError(
175 "A required feature for the XRSession is not available.");
176 return promise
.forget();
178 requiredReferenceSpaceTypes
.AppendElement(type
.value());
182 if (aOptions
.mOptionalFeatures
.WasPassed()) {
183 for (const nsString
& val
: aOptions
.mOptionalFeatures
.Value()) {
184 Maybe
<XRReferenceSpaceType
> type
=
185 StringToEnum
<XRReferenceSpaceType
>(val
);
187 optionalReferenceSpaceTypes
.AppendElement(type
.value());
193 if (mPendingImmersiveSession
|| mActiveImmersiveSession
) {
194 promise
->MaybeRejectWithInvalidStateError(
195 "There can only be one immersive XRSession.");
196 return promise
.forget();
198 mPendingImmersiveSession
= true;
201 bool isChromeSession
= aCallerType
== CallerType::System
;
202 uint32_t presentationGroup
=
203 isChromeSession
? gfx::kVRGroupChrome
: gfx::kVRGroupContent
;
204 RefPtr
<RequestSessionRequest
> request
= new RequestSessionRequest(
205 aMode
, presentationGroup
, promise
, requiredReferenceSpaceTypes
,
206 optionalReferenceSpaceTypes
);
207 if (request
->WantsHardware()) {
208 QueueSessionRequestWithEnumeration(request
);
210 QueueSessionRequestWithoutEnumeration(request
);
213 return promise
.forget();
216 void XRSystem::QueueSessionRequestWithEnumeration(
217 RequestSessionRequest
* aRequest
) {
218 MOZ_ASSERT(aRequest
->WantsHardware());
219 mRequestSessionRequestsWaitingForRuntimeDetection
.AppendElement(aRequest
);
220 gfx::VRManagerChild
* vm
= gfx::VRManagerChild::Get();
221 vm
->DetectRuntimes();
224 void XRSystem::QueueSessionRequestWithoutEnumeration(
225 RequestSessionRequest
* aRequest
) {
226 MOZ_ASSERT(!aRequest
->NeedsHardware());
227 mRequestSessionRequestsWithoutHardware
.AppendElement(aRequest
);
229 ResolveSessionRequestsWithoutHardware();
232 bool XRSystem::CancelHardwareRequest(RequestSessionRequest
* aRequest
) {
233 if (!aRequest
->NeedsHardware()) {
234 // If hardware access was an optional requirement and the user
235 // opted not to provide access, queue the request
236 // to be resolved without hardware.
237 QueueSessionRequestWithoutEnumeration(aRequest
);
241 if (aRequest
->IsImmersive()) {
242 mPendingImmersiveSession
= false;
247 bool XRSystem::OnXRPermissionRequestAllow() {
248 if (!gfx::VRManagerChild::IsCreated()) {
249 // It's possible that this callback returns after
250 // we have already started shutting down.
253 if (!mEnumerationInFlight
) {
254 mEnumerationInFlight
= true;
255 gfx::VRManagerChild
* vm
= gfx::VRManagerChild::Get();
256 Unused
<< vm
->EnumerateVRDisplays();
258 return mEnumerationInFlight
||
259 !mRequestSessionRequestsWaitingForEnumeration
.IsEmpty();
262 void XRSystem::OnXRPermissionRequestCancel() {
263 nsTArray
<RefPtr
<RequestSessionRequest
>> requestSessionRequests(
264 std::move(mRequestSessionRequestsWaitingForEnumeration
));
265 for (RefPtr
<RequestSessionRequest
>& request
: requestSessionRequests
) {
266 if (CancelHardwareRequest(request
)) {
267 request
->mPromise
->MaybeRejectWithSecurityError(
268 "A device supporting the requested session "
269 "configuration could not be found.");
274 bool XRSystem::FeaturePolicyBlocked() const {
275 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(GetOwner());
279 RefPtr
<XRPermissionRequest
> request
=
280 new XRPermissionRequest(win
, win
->WindowID());
281 return !(request
->CheckPermissionDelegate());
284 bool XRSystem::HasActiveImmersiveSession() const {
285 return mActiveImmersiveSession
;
288 void XRSystem::ResolveSessionRequestsWithoutHardware() {
289 // Resolve promises returned by RequestSession
290 nsTArray
<RefPtr
<gfx::VRDisplayClient
>> displays
;
291 // Try resolving support without a device, for inline sessions.
292 displays
.AppendElement(nullptr);
294 nsTArray
<RefPtr
<RequestSessionRequest
>> requestSessionRequests(
295 std::move(mRequestSessionRequestsWithoutHardware
));
297 ResolveSessionRequests(requestSessionRequests
, displays
);
300 void XRSystem::NotifyEnumerationCompleted() {
301 // Enumeration has completed.
302 mEnumerationInFlight
= false;
304 if (!gfx::VRManagerChild::IsCreated()) {
305 // It's possible that this callback returns after
306 // we have already started shutting down.
310 // Resolve promises returned by RequestSession
311 nsTArray
<RefPtr
<gfx::VRDisplayClient
>> displays
;
312 gfx::VRManagerChild
* vm
= gfx::VRManagerChild::Get();
313 vm
->GetVRDisplays(displays
);
315 nsTArray
<RefPtr
<RequestSessionRequest
>> requestSessionRequests(
316 std::move(mRequestSessionRequestsWaitingForEnumeration
));
318 ResolveSessionRequests(requestSessionRequests
, displays
);
321 void XRSystem::ResolveSessionRequests(
322 nsTArray
<RefPtr
<RequestSessionRequest
>>& aRequests
,
323 const nsTArray
<RefPtr
<gfx::VRDisplayClient
>>& aDisplays
) {
324 for (RefPtr
<RequestSessionRequest
>& request
: aRequests
) {
325 RefPtr
<XRSession
> session
;
326 if (request
->IsImmersive()) {
327 mPendingImmersiveSession
= false;
329 // Select an XR device
330 for (const RefPtr
<gfx::VRDisplayClient
>& display
: aDisplays
) {
331 nsTArray
<XRReferenceSpaceType
> enabledReferenceSpaceTypes
;
332 if (request
->ResolveSupport(display
, enabledReferenceSpaceTypes
)) {
333 if (request
->IsImmersive()) {
334 session
= XRSession::CreateImmersiveSession(
335 GetOwner(), this, display
, request
->GetPresentationGroup(),
336 enabledReferenceSpaceTypes
);
337 mActiveImmersiveSession
= session
;
339 session
= XRSession::CreateInlineSession(GetOwner(), this,
340 enabledReferenceSpaceTypes
);
341 mInlineSessions
.AppendElement(session
);
343 request
->mPromise
->MaybeResolve(session
);
348 request
->mPromise
->MaybeRejectWithNotSupportedError(
349 "A device supporting the required XRSession configuration "
350 "could not be found.");
355 void XRSystem::NotifyDetectRuntimesCompleted() {
356 ResolveIsSessionSupportedRequests();
357 if (!mRequestSessionRequestsWaitingForRuntimeDetection
.IsEmpty()) {
358 ProcessSessionRequestsWaitingForRuntimeDetection();
362 void XRSystem::ResolveIsSessionSupportedRequests() {
363 // Resolve promises returned by IsSessionSupported
364 gfx::VRManagerChild
* vm
= gfx::VRManagerChild::Get();
365 nsTArray
<RefPtr
<IsSessionSupportedRequest
>> isSessionSupportedRequests(
366 std::move(mIsSessionSupportedRequests
));
367 bool featurePolicyBlocked
= FeaturePolicyBlocked();
369 for (RefPtr
<IsSessionSupportedRequest
>& request
:
370 isSessionSupportedRequests
) {
371 if (featurePolicyBlocked
) {
372 request
->mPromise
->MaybeRejectWithSecurityError(
373 "The xr-spatial-tracking feature policy is required.");
377 bool supported
= false;
378 switch (request
->GetSessionMode()) {
379 case XRSessionMode::Immersive_vr
:
380 supported
= vm
->RuntimeSupportsVR();
382 case XRSessionMode::Immersive_ar
:
383 supported
= vm
->RuntimeSupportsAR();
388 request
->mPromise
->MaybeResolve(supported
);
392 void XRSystem::ProcessSessionRequestsWaitingForRuntimeDetection() {
393 bool alreadyRequestedPermission
=
394 !mRequestSessionRequestsWaitingForEnumeration
.IsEmpty();
395 bool featurePolicyBlocked
= FeaturePolicyBlocked();
396 gfx::VRManagerChild
* vm
= gfx::VRManagerChild::Get();
398 nsTArray
<RefPtr
<RequestSessionRequest
>> sessionRequests(
399 std::move(mRequestSessionRequestsWaitingForRuntimeDetection
));
401 for (RefPtr
<RequestSessionRequest
>& request
: sessionRequests
) {
402 bool compatibleRuntime
= false;
403 switch (request
->GetSessionMode()) {
404 case XRSessionMode::Immersive_vr
:
405 compatibleRuntime
= vm
->RuntimeSupportsVR();
407 case XRSessionMode::Immersive_ar
:
408 compatibleRuntime
= vm
->RuntimeSupportsAR();
410 case XRSessionMode::Inline
:
411 compatibleRuntime
= vm
->RuntimeSupportsInline();
416 if (!compatibleRuntime
) {
417 // If none of the requested sessions are supported by a
418 // runtime, early exit without showing a permission prompt.
419 if (CancelHardwareRequest(request
)) {
420 request
->mPromise
->MaybeRejectWithNotSupportedError(
421 "A device supporting the required XRSession configuration "
422 "could not be found.");
426 if (featurePolicyBlocked
) {
427 // Don't show a permission prompt if blocked by feature policy.
428 if (CancelHardwareRequest(request
)) {
429 request
->mPromise
->MaybeRejectWithSecurityError(
430 "The xr-spatial-tracking feature policy is required.");
434 // To continue evaluating this request, it must wait for hardware
435 // enumeration and permission request.
436 mRequestSessionRequestsWaitingForEnumeration
.AppendElement(request
);
439 if (!mRequestSessionRequestsWaitingForEnumeration
.IsEmpty() &&
440 !alreadyRequestedPermission
) {
442 * Inline sessions will require only a user gesture
443 * and should not trigger XR permission UI.
444 * This is not a problem currently, as the only platforms
445 * allowing xr-spatial-tracking for inline sessions do not
446 * present a modal XR permission UI. (eg. Android Firefox Reality)
448 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(GetOwner());
449 win
->RequestXRPermission();
453 void XRSystem::NotifyVRDisplayMounted(uint32_t aDisplayID
) {}
454 void XRSystem::NotifyVRDisplayUnmounted(uint32_t aDisplayID
) {}
456 void XRSystem::NotifyVRDisplayConnect(uint32_t aDisplayID
) {
457 DispatchTrustedEvent(u
"devicechange"_ns
);
460 void XRSystem::NotifyVRDisplayDisconnect(uint32_t aDisplayID
) {
461 DispatchTrustedEvent(u
"devicechange"_ns
);
464 void XRSystem::NotifyVRDisplayPresentChange(uint32_t aDisplayID
) {}
465 void XRSystem::NotifyPresentationGenerationChanged(uint32_t aDisplayID
) {
466 if (mActiveImmersiveSession
) {
467 mActiveImmersiveSession
->ExitPresent();
470 bool XRSystem::GetStopActivityStatus() const { return true; }
472 RequestSessionRequest::RequestSessionRequest(
473 XRSessionMode aSessionMode
, uint32_t aPresentationGroup
, Promise
* aPromise
,
474 const nsTArray
<XRReferenceSpaceType
>& aRequiredReferenceSpaceTypes
,
475 const nsTArray
<XRReferenceSpaceType
>& aOptionalReferenceSpaceTypes
)
476 : mPromise(aPromise
),
477 mSessionMode(aSessionMode
),
478 mPresentationGroup(aPresentationGroup
),
479 mRequiredReferenceSpaceTypes(aRequiredReferenceSpaceTypes
.Clone()),
480 mOptionalReferenceSpaceTypes(aOptionalReferenceSpaceTypes
.Clone()) {}
482 bool RequestSessionRequest::ResolveSupport(
483 const gfx::VRDisplayClient
* aDisplay
,
484 nsTArray
<XRReferenceSpaceType
>& aEnabledReferenceSpaceTypes
) const {
486 if (!aDisplay
->GetIsConnected()) {
489 if ((aDisplay
->GetDisplayInfo().GetPresentingGroups() &
490 mPresentationGroup
) != 0) {
494 const gfx::VRDisplayInfo
& info
= aDisplay
->GetDisplayInfo();
495 switch (mSessionMode
) {
496 case XRSessionMode::Inline
:
497 if (!bool(info
.mDisplayState
.capabilityFlags
&
498 gfx::VRDisplayCapabilityFlags::Cap_Inline
)) {
502 case XRSessionMode::Immersive_vr
:
503 if (!bool(info
.mDisplayState
.capabilityFlags
&
504 gfx::VRDisplayCapabilityFlags::Cap_ImmersiveVR
)) {
508 case XRSessionMode::Immersive_ar
:
509 if (!bool(info
.mDisplayState
.capabilityFlags
&
510 gfx::VRDisplayCapabilityFlags::Cap_ImmersiveAR
)) {
517 } else if (mSessionMode
!= XRSessionMode::Inline
) {
518 // If we don't have a device, we can only support inline sessions
522 // All sessions support XRReferenceSpaceType::Viewer by default
523 aEnabledReferenceSpaceTypes
.AppendElement(XRReferenceSpaceType::Viewer
);
525 // Immersive sessions support XRReferenceSpaceType::Local by default
527 aEnabledReferenceSpaceTypes
.AppendElement(XRReferenceSpaceType::Local
);
530 for (XRReferenceSpaceType type
: mRequiredReferenceSpaceTypes
) {
532 if (!aDisplay
->IsReferenceSpaceTypeSupported(type
)) {
535 } else if (type
!= XRReferenceSpaceType::Viewer
) {
536 // If we don't have a device, We only support
537 // XRReferenceSpaceType::Viewer
540 if (!aEnabledReferenceSpaceTypes
.Contains(type
)) {
541 aEnabledReferenceSpaceTypes
.AppendElement(type
);
545 for (XRReferenceSpaceType type
: mOptionalReferenceSpaceTypes
) {
546 if (aDisplay
->IsReferenceSpaceTypeSupported(type
) &&
547 !aEnabledReferenceSpaceTypes
.Contains(type
)) {
548 aEnabledReferenceSpaceTypes
.AppendElement(type
);
555 bool RequestSessionRequest::IsImmersive() const {
556 return (mSessionMode
== XRSessionMode::Immersive_vr
||
557 mSessionMode
== XRSessionMode::Immersive_ar
);
560 bool RequestSessionRequest::WantsHardware() const {
561 for (XRReferenceSpaceType type
: mOptionalReferenceSpaceTypes
) {
562 // Any XRReferenceSpaceType other than Viewer requires hardware
563 if (type
!= XRReferenceSpaceType::Viewer
) {
567 return NeedsHardware();
570 bool RequestSessionRequest::NeedsHardware() const {
571 for (XRReferenceSpaceType type
: mRequiredReferenceSpaceTypes
) {
572 // Any XRReferenceSpaceType other than Viewer requires hardware
573 if (type
!= XRReferenceSpaceType::Viewer
) {
580 XRSessionMode
RequestSessionRequest::GetSessionMode() const {
584 uint32_t RequestSessionRequest::GetPresentationGroup() const {
585 return mPresentationGroup
;
588 ////////////////////////////////////////////////////////////////////////////////
589 // IsSessionSupportedRequest cycle collection
590 NS_IMPL_CYCLE_COLLECTION(IsSessionSupportedRequest
, mPromise
)
592 XRSessionMode
IsSessionSupportedRequest::GetSessionMode() const {
596 ////////////////////////////////////////////////////////////////////////////////
597 // XRRequestSessionPermissionRequest cycle collection
598 NS_IMPL_CYCLE_COLLECTION_INHERITED(XRRequestSessionPermissionRequest
,
599 ContentPermissionRequestBase
)
601 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(
602 XRRequestSessionPermissionRequest
, ContentPermissionRequestBase
)
604 XRRequestSessionPermissionRequest::XRRequestSessionPermissionRequest(
605 nsPIDOMWindowInner
* aWindow
, nsIPrincipal
* aNodePrincipal
,
606 AllowCallback
&& aAllowCallback
,
607 AllowAnySiteCallback
&& aAllowAnySiteCallback
,
608 CancelCallback
&& aCancelCallback
)
609 : ContentPermissionRequestBase(aNodePrincipal
, aWindow
, "dom.xr"_ns
,
611 mAllowCallback(std::move(aAllowCallback
)),
612 mAllowAnySiteCallback(std::move(aAllowAnySiteCallback
)),
613 mCancelCallback(std::move(aCancelCallback
)),
614 mCallbackCalled(false) {
615 mPermissionRequests
.AppendElement(
616 PermissionRequest(mType
, nsTArray
<nsString
>()));
619 XRRequestSessionPermissionRequest::~XRRequestSessionPermissionRequest() {
624 XRRequestSessionPermissionRequest::Cancel() {
625 if (!mCallbackCalled
) {
626 mCallbackCalled
= true;
633 XRRequestSessionPermissionRequest::Allow(JS::Handle
<JS::Value
> aChoices
) {
634 nsTArray
<PermissionChoice
> choices
;
635 nsresult rv
= TranslateChoices(aChoices
, mPermissionRequests
, choices
);
640 // There is no support to allow grants automatically from the prompting code
643 if (!mCallbackCalled
) {
644 mCallbackCalled
= true;
645 if (choices
.Length() == 1 &&
646 choices
[0].choice().EqualsLiteral("allow-on-any-site")) {
647 mAllowAnySiteCallback();
648 } else if (choices
.Length() == 1 &&
649 choices
[0].choice().EqualsLiteral("allow")) {
656 already_AddRefed
<XRRequestSessionPermissionRequest
>
657 XRRequestSessionPermissionRequest::Create(
658 nsPIDOMWindowInner
* aWindow
, AllowCallback
&& aAllowCallback
,
659 AllowAnySiteCallback
&& aAllowAnySiteCallback
,
660 CancelCallback
&& aCancelCallback
) {
664 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(aWindow
);
665 if (!win
->GetPrincipal()) {
668 RefPtr
<XRRequestSessionPermissionRequest
> request
=
669 new XRRequestSessionPermissionRequest(
670 aWindow
, win
->GetPrincipal(), std::move(aAllowCallback
),
671 std::move(aAllowAnySiteCallback
), std::move(aCancelCallback
));
672 return request
.forget();
675 ////////////////////////////////////////////////////////////////////////////////
676 // RequestSessionRequest cycle collection
677 NS_IMPL_CYCLE_COLLECTION(RequestSessionRequest
, mPromise
)
679 } // namespace mozilla::dom