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 JSContext
* aCx
, XRSessionMode aMode
, const XRSessionInit
& aOptions
,
126 CallerType aCallerType
, ErrorResult
& aRv
) {
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 BindingCallContext
callCx(aCx
, "XRSystem.requestSession");
171 if (aOptions
.mRequiredFeatures
.WasPassed()) {
172 const Sequence
<JS::Value
>& arr
= (aOptions
.mRequiredFeatures
.Value());
173 for (const JS::Value
& val
: arr
) {
174 if (!val
.isNull() && !val
.isUndefined()) {
176 JS::Rooted
<JS::Value
> v(aCx
, val
);
178 if (FindEnumStringIndex
<false>(
179 callCx
, v
, XRReferenceSpaceTypeValues::strings
,
180 "XRReferenceSpaceType", "Argument 2 of XR.requestSession",
183 requiredReferenceSpaceTypes
.AppendElement(
184 static_cast<XRReferenceSpaceType
>(index
));
189 promise
->MaybeRejectWithNotSupportedError(
190 "A required feature for the XRSession is not available.");
191 return promise
.forget();
197 if (aOptions
.mOptionalFeatures
.WasPassed()) {
198 const Sequence
<JS::Value
>& arr
= (aOptions
.mOptionalFeatures
.Value());
199 for (const JS::Value
& val
: arr
) {
200 if (!val
.isNull() && !val
.isUndefined()) {
201 JS::Rooted
<JS::Value
> v(aCx
, val
);
203 if (FindEnumStringIndex
<false>(
204 callCx
, v
, XRReferenceSpaceTypeValues::strings
,
205 "XRReferenceSpaceType", "Argument 2 of XR.requestSession",
208 optionalReferenceSpaceTypes
.AppendElement(
209 static_cast<XRReferenceSpaceType
>(index
));
217 if (mPendingImmersiveSession
|| mActiveImmersiveSession
) {
218 promise
->MaybeRejectWithInvalidStateError(
219 "There can only be one immersive XRSession.");
220 return promise
.forget();
222 mPendingImmersiveSession
= true;
225 bool isChromeSession
= aCallerType
== CallerType::System
;
226 uint32_t presentationGroup
=
227 isChromeSession
? gfx::kVRGroupChrome
: gfx::kVRGroupContent
;
228 RefPtr
<RequestSessionRequest
> request
= new RequestSessionRequest(
229 aMode
, presentationGroup
, promise
, requiredReferenceSpaceTypes
,
230 optionalReferenceSpaceTypes
);
231 if (request
->WantsHardware()) {
232 QueueSessionRequestWithEnumeration(request
);
234 QueueSessionRequestWithoutEnumeration(request
);
237 return promise
.forget();
240 void XRSystem::QueueSessionRequestWithEnumeration(
241 RequestSessionRequest
* aRequest
) {
242 MOZ_ASSERT(aRequest
->WantsHardware());
243 mRequestSessionRequestsWaitingForRuntimeDetection
.AppendElement(aRequest
);
244 gfx::VRManagerChild
* vm
= gfx::VRManagerChild::Get();
245 vm
->DetectRuntimes();
248 void XRSystem::QueueSessionRequestWithoutEnumeration(
249 RequestSessionRequest
* aRequest
) {
250 MOZ_ASSERT(!aRequest
->NeedsHardware());
251 mRequestSessionRequestsWithoutHardware
.AppendElement(aRequest
);
253 ResolveSessionRequestsWithoutHardware();
256 bool XRSystem::CancelHardwareRequest(RequestSessionRequest
* aRequest
) {
257 if (!aRequest
->NeedsHardware()) {
258 // If hardware access was an optional requirement and the user
259 // opted not to provide access, queue the request
260 // to be resolved without hardware.
261 QueueSessionRequestWithoutEnumeration(aRequest
);
265 if (aRequest
->IsImmersive()) {
266 mPendingImmersiveSession
= false;
271 bool XRSystem::OnXRPermissionRequestAllow() {
272 if (!gfx::VRManagerChild::IsCreated()) {
273 // It's possible that this callback returns after
274 // we have already started shutting down.
277 if (!mEnumerationInFlight
) {
278 mEnumerationInFlight
= true;
279 gfx::VRManagerChild
* vm
= gfx::VRManagerChild::Get();
280 Unused
<< vm
->EnumerateVRDisplays();
282 return mEnumerationInFlight
||
283 !mRequestSessionRequestsWaitingForEnumeration
.IsEmpty();
286 void XRSystem::OnXRPermissionRequestCancel() {
287 nsTArray
<RefPtr
<RequestSessionRequest
>> requestSessionRequests(
288 std::move(mRequestSessionRequestsWaitingForEnumeration
));
289 for (RefPtr
<RequestSessionRequest
>& request
: requestSessionRequests
) {
290 if (CancelHardwareRequest(request
)) {
291 request
->mPromise
->MaybeRejectWithSecurityError(
292 "A device supporting the requested session "
293 "configuration could not be found.");
298 bool XRSystem::FeaturePolicyBlocked() const {
299 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(GetOwner());
303 RefPtr
<XRPermissionRequest
> request
=
304 new XRPermissionRequest(win
, win
->WindowID());
305 return !(request
->CheckPermissionDelegate());
308 bool XRSystem::HasActiveImmersiveSession() const {
309 return mActiveImmersiveSession
;
312 void XRSystem::ResolveSessionRequestsWithoutHardware() {
313 // Resolve promises returned by RequestSession
314 nsTArray
<RefPtr
<gfx::VRDisplayClient
>> displays
;
315 // Try resolving support without a device, for inline sessions.
316 displays
.AppendElement(nullptr);
318 nsTArray
<RefPtr
<RequestSessionRequest
>> requestSessionRequests(
319 std::move(mRequestSessionRequestsWithoutHardware
));
321 ResolveSessionRequests(requestSessionRequests
, displays
);
324 void XRSystem::NotifyEnumerationCompleted() {
325 // Enumeration has completed.
326 mEnumerationInFlight
= false;
328 if (!gfx::VRManagerChild::IsCreated()) {
329 // It's possible that this callback returns after
330 // we have already started shutting down.
334 // Resolve promises returned by RequestSession
335 nsTArray
<RefPtr
<gfx::VRDisplayClient
>> displays
;
336 gfx::VRManagerChild
* vm
= gfx::VRManagerChild::Get();
337 vm
->GetVRDisplays(displays
);
339 nsTArray
<RefPtr
<RequestSessionRequest
>> requestSessionRequests(
340 std::move(mRequestSessionRequestsWaitingForEnumeration
));
342 ResolveSessionRequests(requestSessionRequests
, displays
);
345 void XRSystem::ResolveSessionRequests(
346 nsTArray
<RefPtr
<RequestSessionRequest
>>& aRequests
,
347 const nsTArray
<RefPtr
<gfx::VRDisplayClient
>>& aDisplays
) {
348 for (RefPtr
<RequestSessionRequest
>& request
: aRequests
) {
349 RefPtr
<XRSession
> session
;
350 if (request
->IsImmersive()) {
351 mPendingImmersiveSession
= false;
353 // Select an XR device
354 for (const RefPtr
<gfx::VRDisplayClient
>& display
: aDisplays
) {
355 nsTArray
<XRReferenceSpaceType
> enabledReferenceSpaceTypes
;
356 if (request
->ResolveSupport(display
, enabledReferenceSpaceTypes
)) {
357 if (request
->IsImmersive()) {
358 session
= XRSession::CreateImmersiveSession(
359 GetOwner(), this, display
, request
->GetPresentationGroup(),
360 enabledReferenceSpaceTypes
);
361 mActiveImmersiveSession
= session
;
363 session
= XRSession::CreateInlineSession(GetOwner(), this,
364 enabledReferenceSpaceTypes
);
365 mInlineSessions
.AppendElement(session
);
367 request
->mPromise
->MaybeResolve(session
);
372 request
->mPromise
->MaybeRejectWithNotSupportedError(
373 "A device supporting the required XRSession configuration "
374 "could not be found.");
379 void XRSystem::NotifyDetectRuntimesCompleted() {
380 ResolveIsSessionSupportedRequests();
381 if (!mRequestSessionRequestsWaitingForRuntimeDetection
.IsEmpty()) {
382 ProcessSessionRequestsWaitingForRuntimeDetection();
386 void XRSystem::ResolveIsSessionSupportedRequests() {
387 // Resolve promises returned by IsSessionSupported
388 gfx::VRManagerChild
* vm
= gfx::VRManagerChild::Get();
389 nsTArray
<RefPtr
<IsSessionSupportedRequest
>> isSessionSupportedRequests(
390 std::move(mIsSessionSupportedRequests
));
391 bool featurePolicyBlocked
= FeaturePolicyBlocked();
393 for (RefPtr
<IsSessionSupportedRequest
>& request
:
394 isSessionSupportedRequests
) {
395 if (featurePolicyBlocked
) {
396 request
->mPromise
->MaybeRejectWithSecurityError(
397 "The xr-spatial-tracking feature policy is required.");
401 bool supported
= false;
402 switch (request
->GetSessionMode()) {
403 case XRSessionMode::Immersive_vr
:
404 supported
= vm
->RuntimeSupportsVR();
406 case XRSessionMode::Immersive_ar
:
407 supported
= vm
->RuntimeSupportsAR();
412 request
->mPromise
->MaybeResolve(supported
);
416 void XRSystem::ProcessSessionRequestsWaitingForRuntimeDetection() {
417 bool alreadyRequestedPermission
=
418 !mRequestSessionRequestsWaitingForEnumeration
.IsEmpty();
419 bool featurePolicyBlocked
= FeaturePolicyBlocked();
420 gfx::VRManagerChild
* vm
= gfx::VRManagerChild::Get();
422 nsTArray
<RefPtr
<RequestSessionRequest
>> sessionRequests(
423 std::move(mRequestSessionRequestsWaitingForRuntimeDetection
));
425 for (RefPtr
<RequestSessionRequest
>& request
: sessionRequests
) {
426 bool compatibleRuntime
= false;
427 switch (request
->GetSessionMode()) {
428 case XRSessionMode::Immersive_vr
:
429 compatibleRuntime
= vm
->RuntimeSupportsVR();
431 case XRSessionMode::Immersive_ar
:
432 compatibleRuntime
= vm
->RuntimeSupportsAR();
434 case XRSessionMode::Inline
:
435 compatibleRuntime
= vm
->RuntimeSupportsInline();
440 if (!compatibleRuntime
) {
441 // If none of the requested sessions are supported by a
442 // runtime, early exit without showing a permission prompt.
443 if (CancelHardwareRequest(request
)) {
444 request
->mPromise
->MaybeRejectWithNotSupportedError(
445 "A device supporting the required XRSession configuration "
446 "could not be found.");
450 if (featurePolicyBlocked
) {
451 // Don't show a permission prompt if blocked by feature policy.
452 if (CancelHardwareRequest(request
)) {
453 request
->mPromise
->MaybeRejectWithSecurityError(
454 "The xr-spatial-tracking feature policy is required.");
458 // To continue evaluating this request, it must wait for hardware
459 // enumeration and permission request.
460 mRequestSessionRequestsWaitingForEnumeration
.AppendElement(request
);
463 if (!mRequestSessionRequestsWaitingForEnumeration
.IsEmpty() &&
464 !alreadyRequestedPermission
) {
466 * Inline sessions will require only a user gesture
467 * and should not trigger XR permission UI.
468 * This is not a problem currently, as the only platforms
469 * allowing xr-spatial-tracking for inline sessions do not
470 * present a modal XR permission UI. (eg. Android Firefox Reality)
472 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(GetOwner());
473 win
->RequestXRPermission();
477 void XRSystem::NotifyVRDisplayMounted(uint32_t aDisplayID
) {}
478 void XRSystem::NotifyVRDisplayUnmounted(uint32_t aDisplayID
) {}
480 void XRSystem::NotifyVRDisplayConnect(uint32_t aDisplayID
) {
481 DispatchTrustedEvent(u
"devicechange"_ns
);
484 void XRSystem::NotifyVRDisplayDisconnect(uint32_t aDisplayID
) {
485 DispatchTrustedEvent(u
"devicechange"_ns
);
488 void XRSystem::NotifyVRDisplayPresentChange(uint32_t aDisplayID
) {}
489 void XRSystem::NotifyPresentationGenerationChanged(uint32_t aDisplayID
) {
490 if (mActiveImmersiveSession
) {
491 mActiveImmersiveSession
->ExitPresent();
494 bool XRSystem::GetStopActivityStatus() const { return true; }
496 RequestSessionRequest::RequestSessionRequest(
497 XRSessionMode aSessionMode
, uint32_t aPresentationGroup
, Promise
* aPromise
,
498 const nsTArray
<XRReferenceSpaceType
>& aRequiredReferenceSpaceTypes
,
499 const nsTArray
<XRReferenceSpaceType
>& aOptionalReferenceSpaceTypes
)
500 : mPromise(aPromise
),
501 mSessionMode(aSessionMode
),
502 mPresentationGroup(aPresentationGroup
),
503 mRequiredReferenceSpaceTypes(aRequiredReferenceSpaceTypes
.Clone()),
504 mOptionalReferenceSpaceTypes(aOptionalReferenceSpaceTypes
.Clone()) {}
506 bool RequestSessionRequest::ResolveSupport(
507 const gfx::VRDisplayClient
* aDisplay
,
508 nsTArray
<XRReferenceSpaceType
>& aEnabledReferenceSpaceTypes
) const {
510 if (!aDisplay
->GetIsConnected()) {
513 if ((aDisplay
->GetDisplayInfo().GetPresentingGroups() &
514 mPresentationGroup
) != 0) {
518 const gfx::VRDisplayInfo
& info
= aDisplay
->GetDisplayInfo();
519 switch (mSessionMode
) {
520 case XRSessionMode::Inline
:
521 if (!bool(info
.mDisplayState
.capabilityFlags
&
522 gfx::VRDisplayCapabilityFlags::Cap_Inline
)) {
526 case XRSessionMode::Immersive_vr
:
527 if (!bool(info
.mDisplayState
.capabilityFlags
&
528 gfx::VRDisplayCapabilityFlags::Cap_ImmersiveVR
)) {
532 case XRSessionMode::Immersive_ar
:
533 if (!bool(info
.mDisplayState
.capabilityFlags
&
534 gfx::VRDisplayCapabilityFlags::Cap_ImmersiveAR
)) {
541 } else if (mSessionMode
!= XRSessionMode::Inline
) {
542 // If we don't have a device, we can only support inline sessions
546 // All sessions support XRReferenceSpaceType::Viewer by default
547 aEnabledReferenceSpaceTypes
.AppendElement(XRReferenceSpaceType::Viewer
);
549 // Immersive sessions support XRReferenceSpaceType::Local by default
551 aEnabledReferenceSpaceTypes
.AppendElement(XRReferenceSpaceType::Local
);
554 for (XRReferenceSpaceType type
: mRequiredReferenceSpaceTypes
) {
556 if (!aDisplay
->IsReferenceSpaceTypeSupported(type
)) {
559 } else if (type
!= XRReferenceSpaceType::Viewer
) {
560 // If we don't have a device, We only support
561 // XRReferenceSpaceType::Viewer
564 if (!aEnabledReferenceSpaceTypes
.Contains(type
)) {
565 aEnabledReferenceSpaceTypes
.AppendElement(type
);
569 for (XRReferenceSpaceType type
: mOptionalReferenceSpaceTypes
) {
570 if (aDisplay
->IsReferenceSpaceTypeSupported(type
) &&
571 !aEnabledReferenceSpaceTypes
.Contains(type
)) {
572 aEnabledReferenceSpaceTypes
.AppendElement(type
);
579 bool RequestSessionRequest::IsImmersive() const {
580 return (mSessionMode
== XRSessionMode::Immersive_vr
||
581 mSessionMode
== XRSessionMode::Immersive_ar
);
584 bool RequestSessionRequest::WantsHardware() const {
585 for (XRReferenceSpaceType type
: mOptionalReferenceSpaceTypes
) {
586 // Any XRReferenceSpaceType other than Viewer requires hardware
587 if (type
!= XRReferenceSpaceType::Viewer
) {
591 return NeedsHardware();
594 bool RequestSessionRequest::NeedsHardware() const {
595 for (XRReferenceSpaceType type
: mRequiredReferenceSpaceTypes
) {
596 // Any XRReferenceSpaceType other than Viewer requires hardware
597 if (type
!= XRReferenceSpaceType::Viewer
) {
604 XRSessionMode
RequestSessionRequest::GetSessionMode() const {
608 uint32_t RequestSessionRequest::GetPresentationGroup() const {
609 return mPresentationGroup
;
612 ////////////////////////////////////////////////////////////////////////////////
613 // IsSessionSupportedRequest cycle collection
614 NS_IMPL_CYCLE_COLLECTION(IsSessionSupportedRequest
, mPromise
)
616 XRSessionMode
IsSessionSupportedRequest::GetSessionMode() const {
620 ////////////////////////////////////////////////////////////////////////////////
621 // XRRequestSessionPermissionRequest cycle collection
622 NS_IMPL_CYCLE_COLLECTION_INHERITED(XRRequestSessionPermissionRequest
,
623 ContentPermissionRequestBase
)
625 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(
626 XRRequestSessionPermissionRequest
, ContentPermissionRequestBase
)
628 XRRequestSessionPermissionRequest::XRRequestSessionPermissionRequest(
629 nsPIDOMWindowInner
* aWindow
, nsIPrincipal
* aNodePrincipal
,
630 AllowCallback
&& aAllowCallback
,
631 AllowAnySiteCallback
&& aAllowAnySiteCallback
,
632 CancelCallback
&& aCancelCallback
)
633 : ContentPermissionRequestBase(aNodePrincipal
, aWindow
, "dom.xr"_ns
,
635 mAllowCallback(std::move(aAllowCallback
)),
636 mAllowAnySiteCallback(std::move(aAllowAnySiteCallback
)),
637 mCancelCallback(std::move(aCancelCallback
)),
638 mCallbackCalled(false) {
639 mPermissionRequests
.AppendElement(
640 PermissionRequest(mType
, nsTArray
<nsString
>()));
643 XRRequestSessionPermissionRequest::~XRRequestSessionPermissionRequest() {
648 XRRequestSessionPermissionRequest::Cancel() {
649 if (!mCallbackCalled
) {
650 mCallbackCalled
= true;
657 XRRequestSessionPermissionRequest::Allow(JS::Handle
<JS::Value
> aChoices
) {
658 nsTArray
<PermissionChoice
> choices
;
659 nsresult rv
= TranslateChoices(aChoices
, mPermissionRequests
, choices
);
664 // There is no support to allow grants automatically from the prompting code
667 if (!mCallbackCalled
) {
668 mCallbackCalled
= true;
669 if (choices
.Length() == 1 &&
670 choices
[0].choice().EqualsLiteral("allow-on-any-site")) {
671 mAllowAnySiteCallback();
672 } else if (choices
.Length() == 1 &&
673 choices
[0].choice().EqualsLiteral("allow")) {
680 already_AddRefed
<XRRequestSessionPermissionRequest
>
681 XRRequestSessionPermissionRequest::Create(
682 nsPIDOMWindowInner
* aWindow
, AllowCallback
&& aAllowCallback
,
683 AllowAnySiteCallback
&& aAllowAnySiteCallback
,
684 CancelCallback
&& aCancelCallback
) {
688 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(aWindow
);
689 if (!win
->GetPrincipal()) {
692 RefPtr
<XRRequestSessionPermissionRequest
> request
=
693 new XRRequestSessionPermissionRequest(
694 aWindow
, win
->GetPrincipal(), std::move(aAllowCallback
),
695 std::move(aAllowAnySiteCallback
), std::move(aCancelCallback
));
696 return request
.forget();
699 ////////////////////////////////////////////////////////////////////////////////
700 // RequestSessionRequest cycle collection
701 NS_IMPL_CYCLE_COLLECTION(RequestSessionRequest
, mPromise
)
703 } // namespace mozilla::dom