XRSystem.cpp (23302B)
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/. */ 6 7 #include "mozilla/dom/XRSystem.h" 8 9 #include "VRDisplayClient.h" 10 #include "VRManagerChild.h" 11 #include "gfxVR.h" 12 #include "mozilla/StaticPrefs_dom.h" 13 #include "mozilla/dom/BindingCallContext.h" 14 #include "mozilla/dom/Document.h" 15 #include "mozilla/dom/FeaturePolicyUtils.h" 16 #include "mozilla/dom/PermissionMessageUtils.h" 17 #include "mozilla/dom/Promise.h" 18 #include "mozilla/dom/XRPermissionRequest.h" 19 #include "mozilla/dom/XRSession.h" 20 #include "nsGlobalWindowInner.h" 21 #include "nsThreadUtils.h" 22 23 namespace mozilla::dom { 24 25 using namespace gfx; 26 27 //////////////////////////////////////////////////////////////////////////////// 28 // XRSystem cycle collection 29 NS_IMPL_CYCLE_COLLECTION_CLASS(XRSystem) 30 31 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(XRSystem, 32 DOMEventTargetHelper) 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 42 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 54 55 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(XRSystem, DOMEventTargetHelper) 56 57 JSObject* XRSystem::WrapObject(JSContext* aCx, 58 JS::Handle<JSObject*> aGivenProto) { 59 return XRSystem_Binding::Wrap(aCx, this, aGivenProto); 60 } 61 62 // static 63 already_AddRefed<XRSystem> XRSystem::Create(nsPIDOMWindowInner* aWindow) { 64 MOZ_ASSERT(aWindow); 65 66 RefPtr<XRSystem> service = new XRSystem(aWindow); 67 return service.forget(); 68 } 69 70 XRSystem::XRSystem(nsPIDOMWindowInner* aWindow) 71 : DOMEventTargetHelper(aWindow), 72 mShuttingDown(false), 73 mPendingImmersiveSession(false), 74 mEnumerationInFlight(false) { 75 // Unregister with VRManagerChild 76 VRManagerChild* vmc = VRManagerChild::Get(); 77 if (vmc) { 78 vmc->AddListener(this); 79 } 80 } 81 82 void XRSystem::Shutdown() { 83 MOZ_ASSERT(!mShuttingDown); 84 mShuttingDown = true; 85 86 // Unregister from VRManagerChild 87 if (VRManagerChild::IsCreated()) { 88 VRManagerChild* vmc = VRManagerChild::Get(); 89 vmc->RemoveListener(this); 90 } 91 } 92 93 void XRSystem::SessionEnded(XRSession* aSession) { 94 if (mActiveImmersiveSession == aSession) { 95 mActiveImmersiveSession = nullptr; 96 } 97 mInlineSessions.RemoveElement(aSession); 98 } 99 100 already_AddRefed<Promise> XRSystem::IsSessionSupported(XRSessionMode aMode, 101 ErrorResult& aRv) { 102 nsCOMPtr<nsIGlobalObject> global = GetParentObject(); 103 NS_ENSURE_TRUE(global, nullptr); 104 105 RefPtr<Promise> promise = Promise::Create(global, aRv); 106 NS_ENSURE_TRUE(!aRv.Failed(), nullptr); 107 108 if (aMode == XRSessionMode::Inline) { 109 promise->MaybeResolve(true); 110 return promise.forget(); 111 } 112 113 if (mIsSessionSupportedRequests.IsEmpty()) { 114 gfx::VRManagerChild* vm = gfx::VRManagerChild::Get(); 115 vm->DetectRuntimes(); 116 } 117 118 RefPtr<IsSessionSupportedRequest> request = 119 new IsSessionSupportedRequest(aMode, promise); 120 mIsSessionSupportedRequests.AppendElement(request); 121 return promise.forget(); 122 } 123 124 already_AddRefed<Promise> XRSystem::RequestSession( 125 XRSessionMode aMode, const XRSessionInit& aOptions, CallerType aCallerType, 126 ErrorResult& aRv) { 127 nsCOMPtr<nsIGlobalObject> global = GetParentObject(); 128 NS_ENSURE_TRUE(global, nullptr); 129 130 RefPtr<Promise> promise = Promise::Create(global, aRv); 131 NS_ENSURE_TRUE(!aRv.Failed(), nullptr); 132 133 bool immersive = (aMode == XRSessionMode::Immersive_vr || 134 aMode == XRSessionMode::Immersive_ar); 135 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(); 142 } 143 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(); 152 } 153 } 154 155 nsTArray<XRReferenceSpaceType> requiredReferenceSpaceTypes; 156 nsTArray<XRReferenceSpaceType> optionalReferenceSpaceTypes; 157 158 /** 159 * By default, all sessions will require XRReferenceSpaceType::Viewer 160 * and immersive sessions will require XRReferenceSpaceType::Local. 161 * 162 * https://www.w3.org/TR/webxr/#default-features 163 */ 164 requiredReferenceSpaceTypes.AppendElement(XRReferenceSpaceType::Viewer); 165 if (immersive) { 166 requiredReferenceSpaceTypes.AppendElement(XRReferenceSpaceType::Local); 167 } 168 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(); 177 } 178 requiredReferenceSpaceTypes.AppendElement(type.value()); 179 } 180 } 181 182 if (aOptions.mOptionalFeatures.WasPassed()) { 183 for (const nsString& val : aOptions.mOptionalFeatures.Value()) { 184 Maybe<XRReferenceSpaceType> type = 185 StringToEnum<XRReferenceSpaceType>(val); 186 if (type.isSome()) { 187 optionalReferenceSpaceTypes.AppendElement(type.value()); 188 } 189 } 190 } 191 192 if (immersive) { 193 if (mPendingImmersiveSession || mActiveImmersiveSession) { 194 promise->MaybeRejectWithInvalidStateError( 195 "There can only be one immersive XRSession."); 196 return promise.forget(); 197 } 198 mPendingImmersiveSession = true; 199 } 200 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); 209 } else { 210 QueueSessionRequestWithoutEnumeration(request); 211 } 212 213 return promise.forget(); 214 } 215 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(); 222 } 223 224 void XRSystem::QueueSessionRequestWithoutEnumeration( 225 RequestSessionRequest* aRequest) { 226 MOZ_ASSERT(!aRequest->NeedsHardware()); 227 mRequestSessionRequestsWithoutHardware.AppendElement(aRequest); 228 229 ResolveSessionRequestsWithoutHardware(); 230 } 231 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); 238 return false; 239 } 240 241 if (aRequest->IsImmersive()) { 242 mPendingImmersiveSession = false; 243 } 244 return true; 245 } 246 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. 251 return false; 252 } 253 if (!mEnumerationInFlight) { 254 mEnumerationInFlight = true; 255 gfx::VRManagerChild* vm = gfx::VRManagerChild::Get(); 256 (void)vm->EnumerateVRDisplays(); 257 } 258 return mEnumerationInFlight || 259 !mRequestSessionRequestsWaitingForEnumeration.IsEmpty(); 260 } 261 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."); 270 } 271 } 272 } 273 274 bool XRSystem::FeaturePolicyBlocked() const { 275 nsGlobalWindowInner* win = GetOwnerWindow(); 276 if (!win) { 277 return true; 278 } 279 RefPtr<XRPermissionRequest> request = 280 new XRPermissionRequest(win, win->WindowID()); 281 return !(request->CheckPermissionDelegate()); 282 } 283 284 bool XRSystem::HasActiveImmersiveSession() const { 285 return mActiveImmersiveSession; 286 } 287 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); 293 294 nsTArray<RefPtr<RequestSessionRequest>> requestSessionRequests( 295 std::move(mRequestSessionRequestsWithoutHardware)); 296 297 ResolveSessionRequests(requestSessionRequests, displays); 298 } 299 300 void XRSystem::NotifyEnumerationCompleted() { 301 // Enumeration has completed. 302 mEnumerationInFlight = false; 303 304 if (!gfx::VRManagerChild::IsCreated()) { 305 // It's possible that this callback returns after 306 // we have already started shutting down. 307 return; 308 } 309 310 // Resolve promises returned by RequestSession 311 nsTArray<RefPtr<gfx::VRDisplayClient>> displays; 312 gfx::VRManagerChild* vm = gfx::VRManagerChild::Get(); 313 vm->GetVRDisplays(displays); 314 315 nsTArray<RefPtr<RequestSessionRequest>> requestSessionRequests( 316 std::move(mRequestSessionRequestsWaitingForEnumeration)); 317 318 ResolveSessionRequests(requestSessionRequests, displays); 319 } 320 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; 328 } 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; 338 } else { 339 session = XRSession::CreateInlineSession(GetOwnerWindow(), this, 340 enabledReferenceSpaceTypes); 341 mInlineSessions.AppendElement(session); 342 } 343 request->mPromise->MaybeResolve(session); 344 break; 345 } 346 } 347 if (!session) { 348 request->mPromise->MaybeRejectWithNotSupportedError( 349 "A device supporting the required XRSession configuration " 350 "could not be found."); 351 } 352 } 353 } 354 355 void XRSystem::NotifyDetectRuntimesCompleted() { 356 ResolveIsSessionSupportedRequests(); 357 if (!mRequestSessionRequestsWaitingForRuntimeDetection.IsEmpty()) { 358 ProcessSessionRequestsWaitingForRuntimeDetection(); 359 } 360 } 361 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(); 368 369 for (RefPtr<IsSessionSupportedRequest>& request : 370 isSessionSupportedRequests) { 371 if (featurePolicyBlocked) { 372 request->mPromise->MaybeRejectWithSecurityError( 373 "The xr-spatial-tracking feature policy is required."); 374 continue; 375 } 376 377 bool supported = false; 378 switch (request->GetSessionMode()) { 379 case XRSessionMode::Immersive_vr: 380 supported = vm->RuntimeSupportsVR(); 381 break; 382 case XRSessionMode::Immersive_ar: 383 supported = vm->RuntimeSupportsAR(); 384 break; 385 default: 386 break; 387 } 388 request->mPromise->MaybeResolve(supported); 389 } 390 } 391 392 void XRSystem::ProcessSessionRequestsWaitingForRuntimeDetection() { 393 bool alreadyRequestedPermission = 394 !mRequestSessionRequestsWaitingForEnumeration.IsEmpty(); 395 bool featurePolicyBlocked = FeaturePolicyBlocked(); 396 gfx::VRManagerChild* vm = gfx::VRManagerChild::Get(); 397 398 nsTArray<RefPtr<RequestSessionRequest>> sessionRequests( 399 std::move(mRequestSessionRequestsWaitingForRuntimeDetection)); 400 401 for (RefPtr<RequestSessionRequest>& request : sessionRequests) { 402 bool compatibleRuntime = false; 403 switch (request->GetSessionMode()) { 404 case XRSessionMode::Immersive_vr: 405 compatibleRuntime = vm->RuntimeSupportsVR(); 406 break; 407 case XRSessionMode::Immersive_ar: 408 compatibleRuntime = vm->RuntimeSupportsAR(); 409 break; 410 case XRSessionMode::Inline: 411 compatibleRuntime = vm->RuntimeSupportsInline(); 412 break; 413 default: 414 break; 415 } 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."); 423 } 424 continue; 425 } 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."); 431 } 432 continue; 433 } 434 // To continue evaluating this request, it must wait for hardware 435 // enumeration and permission request. 436 mRequestSessionRequestsWaitingForEnumeration.AppendElement(request); 437 } 438 439 if (!mRequestSessionRequestsWaitingForEnumeration.IsEmpty() && 440 !alreadyRequestedPermission) { 441 /** 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) 447 */ 448 GetOwnerWindow()->RequestXRPermission(); 449 } 450 } 451 452 void XRSystem::NotifyVRDisplayMounted(uint32_t aDisplayID) {} 453 void XRSystem::NotifyVRDisplayUnmounted(uint32_t aDisplayID) {} 454 455 void XRSystem::NotifyVRDisplayConnect(uint32_t aDisplayID) { 456 DispatchTrustedEvent(u"devicechange"_ns); 457 } 458 459 void XRSystem::NotifyVRDisplayDisconnect(uint32_t aDisplayID) { 460 DispatchTrustedEvent(u"devicechange"_ns); 461 } 462 463 void XRSystem::NotifyVRDisplayPresentChange(uint32_t aDisplayID) {} 464 void XRSystem::NotifyPresentationGenerationChanged(uint32_t aDisplayID) { 465 if (mActiveImmersiveSession) { 466 mActiveImmersiveSession->ExitPresent(); 467 } 468 } 469 bool XRSystem::GetStopActivityStatus() const { return true; } 470 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()) {} 480 481 bool RequestSessionRequest::ResolveSupport( 482 const gfx::VRDisplayClient* aDisplay, 483 nsTArray<XRReferenceSpaceType>& aEnabledReferenceSpaceTypes) const { 484 if (aDisplay) { 485 if (!aDisplay->GetIsConnected()) { 486 return false; 487 } 488 if ((aDisplay->GetDisplayInfo().GetPresentingGroups() & 489 mPresentationGroup) != 0) { 490 return false; 491 } 492 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)) { 498 return false; 499 } 500 break; 501 case XRSessionMode::Immersive_vr: 502 if (!bool(info.mDisplayState.capabilityFlags & 503 gfx::VRDisplayCapabilityFlags::Cap_ImmersiveVR)) { 504 return false; 505 } 506 break; 507 case XRSessionMode::Immersive_ar: 508 if (!bool(info.mDisplayState.capabilityFlags & 509 gfx::VRDisplayCapabilityFlags::Cap_ImmersiveAR)) { 510 return false; 511 } 512 break; 513 default: 514 break; 515 } 516 } else if (mSessionMode != XRSessionMode::Inline) { 517 // If we don't have a device, we can only support inline sessions 518 return false; 519 } 520 521 // All sessions support XRReferenceSpaceType::Viewer by default 522 aEnabledReferenceSpaceTypes.AppendElement(XRReferenceSpaceType::Viewer); 523 524 // Immersive sessions support XRReferenceSpaceType::Local by default 525 if (IsImmersive()) { 526 aEnabledReferenceSpaceTypes.AppendElement(XRReferenceSpaceType::Local); 527 } 528 529 for (XRReferenceSpaceType type : mRequiredReferenceSpaceTypes) { 530 if (aDisplay) { 531 if (!aDisplay->IsReferenceSpaceTypeSupported(type)) { 532 return false; 533 } 534 } else if (type != XRReferenceSpaceType::Viewer) { 535 // If we don't have a device, We only support 536 // XRReferenceSpaceType::Viewer 537 return false; 538 } 539 if (!aEnabledReferenceSpaceTypes.Contains(type)) { 540 aEnabledReferenceSpaceTypes.AppendElement(type); 541 } 542 } 543 if (aDisplay) { 544 for (XRReferenceSpaceType type : mOptionalReferenceSpaceTypes) { 545 if (aDisplay->IsReferenceSpaceTypeSupported(type) && 546 !aEnabledReferenceSpaceTypes.Contains(type)) { 547 aEnabledReferenceSpaceTypes.AppendElement(type); 548 } 549 } 550 } 551 return true; 552 } 553 554 bool RequestSessionRequest::IsImmersive() const { 555 return (mSessionMode == XRSessionMode::Immersive_vr || 556 mSessionMode == XRSessionMode::Immersive_ar); 557 } 558 559 bool RequestSessionRequest::WantsHardware() const { 560 for (XRReferenceSpaceType type : mOptionalReferenceSpaceTypes) { 561 // Any XRReferenceSpaceType other than Viewer requires hardware 562 if (type != XRReferenceSpaceType::Viewer) { 563 return true; 564 } 565 } 566 return NeedsHardware(); 567 } 568 569 bool RequestSessionRequest::NeedsHardware() const { 570 for (XRReferenceSpaceType type : mRequiredReferenceSpaceTypes) { 571 // Any XRReferenceSpaceType other than Viewer requires hardware 572 if (type != XRReferenceSpaceType::Viewer) { 573 return true; 574 } 575 } 576 return false; 577 } 578 579 XRSessionMode RequestSessionRequest::GetSessionMode() const { 580 return mSessionMode; 581 } 582 583 uint32_t RequestSessionRequest::GetPresentationGroup() const { 584 return mPresentationGroup; 585 } 586 587 //////////////////////////////////////////////////////////////////////////////// 588 // IsSessionSupportedRequest cycle collection 589 NS_IMPL_CYCLE_COLLECTION(IsSessionSupportedRequest, mPromise) 590 591 XRSessionMode IsSessionSupportedRequest::GetSessionMode() const { 592 return mSessionMode; 593 } 594 595 //////////////////////////////////////////////////////////////////////////////// 596 // XRRequestSessionPermissionRequest cycle collection 597 NS_IMPL_CYCLE_COLLECTION_INHERITED(XRRequestSessionPermissionRequest, 598 ContentPermissionRequestBase) 599 600 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0( 601 XRRequestSessionPermissionRequest, ContentPermissionRequestBase) 602 603 XRRequestSessionPermissionRequest::XRRequestSessionPermissionRequest( 604 nsPIDOMWindowInner* aWindow, nsIPrincipal* aNodePrincipal, 605 AllowCallback&& aAllowCallback, 606 AllowAnySiteCallback&& aAllowAnySiteCallback, 607 CancelCallback&& aCancelCallback) 608 : ContentPermissionRequestBase(aNodePrincipal, aWindow, "dom.xr"_ns, 609 "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>())); 616 } 617 618 XRRequestSessionPermissionRequest::~XRRequestSessionPermissionRequest() { 619 Cancel(); 620 } 621 622 NS_IMETHODIMP 623 XRRequestSessionPermissionRequest::Cancel() { 624 if (!mCallbackCalled) { 625 mCallbackCalled = true; 626 mCancelCallback(); 627 } 628 return NS_OK; 629 } 630 631 NS_IMETHODIMP 632 XRRequestSessionPermissionRequest::Allow(JS::Handle<JS::Value> aChoices) { 633 nsTArray<PermissionChoice> choices; 634 nsresult rv = TranslateChoices(aChoices, mPermissionRequests, choices); 635 if (NS_FAILED(rv)) { 636 return rv; 637 } 638 639 // There is no support to allow grants automatically from the prompting code 640 // path. 641 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")) { 649 mAllowCallback(); 650 } 651 } 652 return NS_OK; 653 } 654 655 already_AddRefed<XRRequestSessionPermissionRequest> 656 XRRequestSessionPermissionRequest::Create( 657 nsPIDOMWindowInner* aWindow, AllowCallback&& aAllowCallback, 658 AllowAnySiteCallback&& aAllowAnySiteCallback, 659 CancelCallback&& aCancelCallback) { 660 if (!aWindow) { 661 return nullptr; 662 } 663 nsGlobalWindowInner* win = nsGlobalWindowInner::Cast(aWindow); 664 if (!win->GetPrincipal()) { 665 return nullptr; 666 } 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(); 672 } 673 674 //////////////////////////////////////////////////////////////////////////////// 675 // RequestSessionRequest cycle collection 676 NS_IMPL_CYCLE_COLLECTION(RequestSessionRequest, mPromise) 677 678 } // namespace mozilla::dom