Chrome · XR
CVE-2026-79125
Logic Error in XR
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifcontent/browser/xr/service/vr_service_impl.cc |
modified |
Files Changed
content/browser/xr/service/vr_service_impl.cccontent/browser/xr/service/vr_service_impl.h
Patch
From 86ca49b1d3680f6c9c60ab20d59440b3810df1f8 Mon Sep 17 00:00:00 2001 From: Alexander Cooper <[email protected]> Date: Mon, 13 Jul 2026 11:08:52 -0700 Subject: [PATCH] Gate VRService RuntimesChanged on frame visibility VRServiceImpl previously forwarded XR runtime hot-plug events via RuntimesChanged() without checking if the associated RenderFrameHost was visible. To align with other platform sensors (e.g., DevicePostureProviderImpl) and ensure events are only delivered to visible frames, this change: - Adds an IsRenderFrameHostVisible() helper method to VRServiceImpl. - Checks frame visibility in RuntimesChanged() and sets a pending_device_changed_ flag if the frame is not currently visible. - Overrides WebContentsObserver::OnVisibilityChanged() to flush any deferred device change notifications once the associated frame becomes visible again. TAG=agy Fixed: 533001362 Change-Id: I405b72ce431b100eed229996c48911cce192a617 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8077558 Reviewed-by: Brandon Jones <[email protected]> Commit-Queue: Alexander Cooper <[email protected]> Commit-Queue: Brandon Jones <[email protected]> Auto-Submit: Alexander Cooper <[email protected]> Cr-Commit-Position: refs/heads/main@{#1661243} --- diff --git a/content/browser/xr/service/vr_service_impl.cc b/content/browser/xr/service/vr_service_impl.cc index 2fde838f..8f3cf7f 100644 --- a/content/browser/xr/service/vr_service_impl.cc +++ b/content/browser/xr/service/vr_service_impl.cc @@ -274,6 +274,10 @@ void VRServiceImpl::RuntimesChanged() { DVLOG(2) << __func__; + if (!IsRenderFrameHostVisible()) { + pending_device_changed_ = true; + return; + } if (service_client_) { service_client_->OnDeviceChanged(); } @@ -303,6 +307,18 @@ receiver_->Close(); } +void VRServiceImpl::OnVisibilityChanged(content::Visibility visibility) { + // Re-check frame visibility, as our associated RenderFrameHost may remain + // hidden even when the top-level page becomes visible. + if (!pending_device_changed_ || !IsRenderFrameHostVisible()) { + return; + } + pending_device_changed_ = false; + if (service_client_) { + service_client_->OnDeviceChanged(); + } +} + void VRServiceImpl::OnWebContentsFocusChanged(content::RenderWidgetHost* host, bool focused) { if (!render_frame_host_ || !render_frame_host_->GetView() || @@ -550,8 +566,7 @@ return; } - if (render_frame_host_->GetVisibilityState() != - content::PageVisibilityState::kVisible) { + if (!IsRenderFrameHostVisible()) { // Page visibility is verified blink-side, so this should never fail unless // the requesting client is misbehaving or compromised. Treat non-visible // page as unknown failure: @@ -997,6 +1012,11 @@ return content::WebContents::FromRenderFrameHost(render_frame_host_); } +bool VRServiceImpl::IsRenderFrameHostVisible() const { + return render_frame_host_ && render_frame_host_->GetVisibilityState() == + content::PageVisibilityState::kVisible; +} + void VRServiceImpl::Teardown() { if (!render_frame_host_) { return; diff --git a/content/browser/xr/service/vr_service_impl.h b/content/browser/xr/service/vr_service_impl.h index 65bd2a02..f36d92b 100644 --- a/content/browser/xr/service/vr_service_impl.h +++ b/content/browser/xr/service/vr_service_impl.h @@ -14,6 +14,7 @@ #include "content/browser/xr/metrics/session_metrics_helper.h" #include "content/common/content_export.h" #include "content/public/browser/permission_result.h" +#include "content/public/browser/visibility.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/xr_install_helper.h" #include "device/vr/public/mojom/isolated_xr_service.mojom-forward.h" @@ -126,6 +127,7 @@ void OnWebContentsFocused(content::RenderWidgetHost* host) override; void OnWebContentsLostFocus(content::RenderWidgetHost* host) override; void RenderFrameDeleted(content::RenderFrameHost* host) override; + void OnVisibilityChanged(content::Visibility visibility) override; void OnWebContentsFocusChanged(content::RenderWidgetHost* host, bool focused); @@ -137,6 +139,8 @@ // assumption that we are not already in VR. SessionMetricsHelper* GetSessionMetricsHelper(); + bool IsRenderFrameHostVisible() const; + bool InternalSupportsSession(device::mojom::XRSessionOptions* options); void DoRequestPermissions( @@ -206,6 +210,7 @@ bool in_focused_frame_ = false; bool frames_throttled_ = false; bool has_immersive_session_ = false; + bool pending_device_changed_ = false; std::vector<XrCompatibleCallback> xr_compatible_callbacks_;
Loading diff…
Original Bug Report
The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.
References
On This Page