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
= GetOwnerWindow();
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 GetOwnerWindow(), this, display
, request
->GetPresentationGroup(),
336 enabledReferenceSpaceTypes
);
337 mActiveImmersiveSession
= session
;
339 session
= XRSession::CreateInlineSession(GetOwnerWindow(), 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 GetOwnerWindow()->RequestXRPermission();
452 void XRSystem::NotifyVRDisplayMounted(uint32_t aDisplayID
) {}
453 void XRSystem::NotifyVRDisplayUnmounted(uint32_t aDisplayID
) {}
455 void XRSystem::NotifyVRDisplayConnect(uint32_t aDisplayID
) {
456 DispatchTrustedEvent(u
"devicechange"_ns
);
459 void XRSystem::NotifyVRDisplayDisconnect(uint32_t aDisplayID
) {
460 DispatchTrustedEvent(u
"devicechange"_ns
);
463 void XRSystem::NotifyVRDisplayPresentChange(uint32_t aDisplayID
) {}
464 void XRSystem::NotifyPresentationGenerationChanged(uint32_t aDisplayID
) {
465 if (mActiveImmersiveSession
) {
466 mActiveImmersiveSession
->ExitPresent();
469 bool XRSystem::GetStopActivityStatus() const { return true; }
471 RequestSessionRequest::RequestSessionRequest(
472 XRSessionMode aSessionMode
, uint32_t aPresentationGroup
, Promise
* aPromise
,
473 const nsTArray
<XRReferenceSpaceType
>& aRequiredReferenceSpaceTypes
,
474 const nsTArray
<XRReferenceSpaceType
>& aOptionalReferenceSpaceTypes
)
475 : mPromise(aPromise
),
476 mSessionMode(aSessionMode
),
477 mPresentationGroup(aPresentationGroup
),
478 mRequiredReferenceSpaceTypes(aRequiredReferenceSpaceTypes
.Clone()),
479 mOptionalReferenceSpaceTypes(aOptionalReferenceSpaceTypes
.Clone()) {}
481 bool RequestSessionRequest::ResolveSupport(
482 const gfx::VRDisplayClient
* aDisplay
,
483 nsTArray
<XRReferenceSpaceType
>& aEnabledReferenceSpaceTypes
) const {
485 if (!aDisplay
->GetIsConnected()) {
488 if ((aDisplay
->GetDisplayInfo().GetPresentingGroups() &
489 mPresentationGroup
) != 0) {
493 const gfx::VRDisplayInfo
& info
= aDisplay
->GetDisplayInfo();
494 switch (mSessionMode
) {
495 case XRSessionMode::Inline
:
496 if (!bool(info
.mDisplayState
.capabilityFlags
&
497 gfx::VRDisplayCapabilityFlags::Cap_Inline
)) {
501 case XRSessionMode::Immersive_vr
:
502 if (!bool(info
.mDisplayState
.capabilityFlags
&
503 gfx::VRDisplayCapabilityFlags::Cap_ImmersiveVR
)) {
507 case XRSessionMode::Immersive_ar
:
508 if (!bool(info
.mDisplayState
.capabilityFlags
&
509 gfx::VRDisplayCapabilityFlags::Cap_ImmersiveAR
)) {
516 } else if (mSessionMode
!= XRSessionMode::Inline
) {
517 // If we don't have a device, we can only support inline sessions
521 // All sessions support XRReferenceSpaceType::Viewer by default
522 aEnabledReferenceSpaceTypes
.AppendElement(XRReferenceSpaceType::Viewer
);
524 // Immersive sessions support XRReferenceSpaceType::Local by default
526 aEnabledReferenceSpaceTypes
.AppendElement(XRReferenceSpaceType::Local
);
529 for (XRReferenceSpaceType type
: mRequiredReferenceSpaceTypes
) {
531 if (!aDisplay
->IsReferenceSpaceTypeSupported(type
)) {
534 } else if (type
!= XRReferenceSpaceType::Viewer
) {
535 // If we don't have a device, We only support
536 // XRReferenceSpaceType::Viewer
539 if (!aEnabledReferenceSpaceTypes
.Contains(type
)) {
540 aEnabledReferenceSpaceTypes
.AppendElement(type
);
544 for (XRReferenceSpaceType type
: mOptionalReferenceSpaceTypes
) {
545 if (aDisplay
->IsReferenceSpaceTypeSupported(type
) &&
546 !aEnabledReferenceSpaceTypes
.Contains(type
)) {
547 aEnabledReferenceSpaceTypes
.AppendElement(type
);
554 bool RequestSessionRequest::IsImmersive() const {
555 return (mSessionMode
== XRSessionMode::Immersive_vr
||
556 mSessionMode
== XRSessionMode::Immersive_ar
);
559 bool RequestSessionRequest::WantsHardware() const {
560 for (XRReferenceSpaceType type
: mOptionalReferenceSpaceTypes
) {
561 // Any XRReferenceSpaceType other than Viewer requires hardware
562 if (type
!= XRReferenceSpaceType::Viewer
) {
566 return NeedsHardware();
569 bool RequestSessionRequest::NeedsHardware() const {
570 for (XRReferenceSpaceType type
: mRequiredReferenceSpaceTypes
) {
571 // Any XRReferenceSpaceType other than Viewer requires hardware
572 if (type
!= XRReferenceSpaceType::Viewer
) {
579 XRSessionMode
RequestSessionRequest::GetSessionMode() const {
583 uint32_t RequestSessionRequest::GetPresentationGroup() const {
584 return mPresentationGroup
;
587 ////////////////////////////////////////////////////////////////////////////////
588 // IsSessionSupportedRequest cycle collection
589 NS_IMPL_CYCLE_COLLECTION(IsSessionSupportedRequest
, mPromise
)
591 XRSessionMode
IsSessionSupportedRequest::GetSessionMode() const {
595 ////////////////////////////////////////////////////////////////////////////////
596 // XRRequestSessionPermissionRequest cycle collection
597 NS_IMPL_CYCLE_COLLECTION_INHERITED(XRRequestSessionPermissionRequest
,
598 ContentPermissionRequestBase
)
600 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(
601 XRRequestSessionPermissionRequest
, ContentPermissionRequestBase
)
603 XRRequestSessionPermissionRequest::XRRequestSessionPermissionRequest(
604 nsPIDOMWindowInner
* aWindow
, nsIPrincipal
* aNodePrincipal
,
605 AllowCallback
&& aAllowCallback
,
606 AllowAnySiteCallback
&& aAllowAnySiteCallback
,
607 CancelCallback
&& aCancelCallback
)
608 : ContentPermissionRequestBase(aNodePrincipal
, aWindow
, "dom.xr"_ns
,
610 mAllowCallback(std::move(aAllowCallback
)),
611 mAllowAnySiteCallback(std::move(aAllowAnySiteCallback
)),
612 mCancelCallback(std::move(aCancelCallback
)),
613 mCallbackCalled(false) {
614 mPermissionRequests
.AppendElement(
615 PermissionRequest(mType
, nsTArray
<nsString
>()));
618 XRRequestSessionPermissionRequest::~XRRequestSessionPermissionRequest() {
623 XRRequestSessionPermissionRequest::Cancel() {
624 if (!mCallbackCalled
) {
625 mCallbackCalled
= true;
632 XRRequestSessionPermissionRequest::Allow(JS::Handle
<JS::Value
> aChoices
) {
633 nsTArray
<PermissionChoice
> choices
;
634 nsresult rv
= TranslateChoices(aChoices
, mPermissionRequests
, choices
);
639 // There is no support to allow grants automatically from the prompting code
642 if (!mCallbackCalled
) {
643 mCallbackCalled
= true;
644 if (choices
.Length() == 1 &&
645 choices
[0].choice().EqualsLiteral("allow-on-any-site")) {
646 mAllowAnySiteCallback();
647 } else if (choices
.Length() == 1 &&
648 choices
[0].choice().EqualsLiteral("allow")) {
655 already_AddRefed
<XRRequestSessionPermissionRequest
>
656 XRRequestSessionPermissionRequest::Create(
657 nsPIDOMWindowInner
* aWindow
, AllowCallback
&& aAllowCallback
,
658 AllowAnySiteCallback
&& aAllowAnySiteCallback
,
659 CancelCallback
&& aCancelCallback
) {
663 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(aWindow
);
664 if (!win
->GetPrincipal()) {
667 RefPtr
<XRRequestSessionPermissionRequest
> request
=
668 new XRRequestSessionPermissionRequest(
669 aWindow
, win
->GetPrincipal(), std::move(aAllowCallback
),
670 std::move(aAllowAnySiteCallback
), std::move(aCancelCallback
));
671 return request
.forget();
674 ////////////////////////////////////////////////////////////////////////////////
675 // RequestSessionRequest cycle collection
676 NS_IMPL_CYCLE_COLLECTION(RequestSessionRequest
, mPromise
)
678 } // namespace mozilla::dom