diff --git a/content/browser/xr/service/vr_service_impl.cc b/content/browser/xr/service/vr_service_impl.cc index eb9239c969a74..e26b484bf233c 100644 --- a/content/browser/xr/service/vr_service_impl.cc +++ b/content/browser/xr/service/vr_service_impl.cc @@ -545,6 +545,21 @@ void VRServiceImpl::RequestSession( return; } + // The WebXR spec's "immersive session request is allowed" algorithm requires + // the requesting document to be visible. Blink enforces this in + // XRSystem::CheckImmersiveSessionRequestAllowed(), but a compromised + // renderer can bypass that check, so re-validate it here alongside the + // user-activation re-check below. + if (device::XRSessionModeUtils::IsImmersive(options->mode) && + render_frame_host_ && + render_frame_host_->GetVisibilityState() != + blink::mojom::PageVisibilityState::kVisible) { + RejectSession(std::move(callback), options->trace_id, + device::mojom::RequestSessionError::UNKNOWN_FAILURE, + "Page is not visible."); + return; + } + auto* runtime = runtime_manager_->GetRuntimeForOptions(options.get()); if (!runtime) { RejectSession(std::move(callback), options->trace_id,