summaryrefslogtreecommitdiff
path: root/chromium/content/browser/xr
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content/browser/xr')
-rw-r--r--chromium/content/browser/xr/metrics/webxr_session_tracker.cc2
-rw-r--r--chromium/content/browser/xr/service/browser_xr_runtime_impl.cc26
-rw-r--r--chromium/content/browser/xr/service/browser_xr_runtime_impl.h13
-rw-r--r--chromium/content/browser/xr/service/isolated_device_provider.cc5
-rw-r--r--chromium/content/browser/xr/service/isolated_device_provider.h4
-rw-r--r--chromium/content/browser/xr/service/vr_service_impl.cc164
-rw-r--r--chromium/content/browser/xr/service/vr_service_impl.h41
-rw-r--r--chromium/content/browser/xr/service/xr_runtime_manager_impl.cc92
-rw-r--r--chromium/content/browser/xr/service/xr_runtime_manager_impl.h12
9 files changed, 205 insertions, 154 deletions
diff --git a/chromium/content/browser/xr/metrics/webxr_session_tracker.cc b/chromium/content/browser/xr/metrics/webxr_session_tracker.cc
index 1914e7e1289..8bf301013b0 100644
--- a/chromium/content/browser/xr/metrics/webxr_session_tracker.cc
+++ b/chromium/content/browser/xr/metrics/webxr_session_tracker.cc
@@ -73,6 +73,7 @@ void WebXRSessionTracker::ReportFeatureUsed(
case XRSessionFeature::HIT_TEST:
case XRSessionFeature::LIGHT_ESTIMATION:
case XRSessionFeature::ANCHORS:
+ case XRSessionFeature::CAMERA_ACCESS:
// Not recording metrics for these features currently.
// TODO(https://crbug.com/965729): Add metrics for the AR-related features
// that are enabled by default.
@@ -110,6 +111,7 @@ void WebXRSessionTracker::SetFeatureRequest(
case XRSessionFeature::HIT_TEST:
case XRSessionFeature::LIGHT_ESTIMATION:
case XRSessionFeature::ANCHORS:
+ case XRSessionFeature::CAMERA_ACCESS:
// Not recording metrics for these features currently.
// TODO(https://crbug.com/965729): Add metrics for the AR-related features
// that are enabled by default.
diff --git a/chromium/content/browser/xr/service/browser_xr_runtime_impl.cc b/chromium/content/browser/xr/service/browser_xr_runtime_impl.cc
index 59394d2d92d..03827f97e5d 100644
--- a/chromium/content/browser/xr/service/browser_xr_runtime_impl.cc
+++ b/chromium/content/browser/xr/service/browser_xr_runtime_impl.cc
@@ -163,6 +163,7 @@ constexpr device::mojom::XRSessionFeature kARCoreDeviceFeatures[] = {
device::mojom::XRSessionFeature::DOM_OVERLAY,
device::mojom::XRSessionFeature::LIGHT_ESTIMATION,
device::mojom::XRSessionFeature::ANCHORS,
+ device::mojom::XRSessionFeature::CAMERA_ACCESS,
};
#if BUILDFLAG(ENABLE_OPENVR)
@@ -212,9 +213,11 @@ bool ContainsFeature(
BrowserXRRuntimeImpl::BrowserXRRuntimeImpl(
device::mojom::XRDeviceId id,
+ device::mojom::XRDeviceDataPtr device_data,
mojo::PendingRemote<device::mojom::XRRuntime> runtime,
device::mojom::VRDisplayInfoPtr display_info)
: id_(id),
+ device_data_(std::move(device_data)),
runtime_(std::move(runtime)),
display_info_(ValidateVRDisplayInfo(display_info.get(), id)) {
DVLOG(2) << __func__ << ": id=" << id;
@@ -231,7 +234,6 @@ BrowserXRRuntimeImpl::BrowserXRRuntimeImpl(
if (integration_client) {
install_helper_ = integration_client->GetInstallHelper(id_);
- consent_helper_ = integration_client->GetConsentHelper(id_);
}
}
@@ -493,22 +495,6 @@ void BrowserXRRuntimeImpl::OnRequestSessionResult(
}
}
-void BrowserXRRuntimeImpl::ShowConsentPrompt(
- int render_process_id,
- int render_frame_id,
- content::XrConsentPromptLevel consent_level,
- content::OnXrUserConsentCallback consent_callback) {
- // It is the responsibility of the consent prompt to ensure that the callback
- // is run in the event that we get removed (and it gets destroyed).
- if (consent_helper_) {
- consent_helper_->ShowConsentPrompt(render_process_id, render_frame_id,
- consent_level,
- std::move(consent_callback));
- } else {
- std::move(consent_callback).Run(consent_level, false);
- }
-}
-
void BrowserXRRuntimeImpl::EnsureInstalled(
int render_process_id,
int render_frame_id,
@@ -574,4 +560,10 @@ void BrowserXRRuntimeImpl::BeforeRuntimeRemoved() {
StopImmersiveSession(base::DoNothing());
}
+#if defined(OS_WIN)
+base::Optional<LUID> BrowserXRRuntimeImpl::GetLuid() const {
+ return device_data_->luid;
+}
+#endif
+
} // namespace content
diff --git a/chromium/content/browser/xr/service/browser_xr_runtime_impl.h b/chromium/content/browser/xr/service/browser_xr_runtime_impl.h
index 8f96a0d04a1..23a4ed19733 100644
--- a/chromium/content/browser/xr/service/browser_xr_runtime_impl.h
+++ b/chromium/content/browser/xr/service/browser_xr_runtime_impl.h
@@ -10,10 +10,10 @@
#include "base/observer_list.h"
#include "base/observer_list_types.h"
+#include "build/build_config.h"
#include "content/browser/xr/service/vr_service_impl.h"
#include "content/public/browser/browser_xr_runtime.h"
#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/xr_consent_helper.h"
#include "device/vr/public/mojom/isolated_xr_service.mojom.h"
#include "device/vr/public/mojom/vr_service.mojom-forward.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
@@ -36,6 +36,7 @@ class BrowserXRRuntimeImpl : public content::BrowserXRRuntime,
base::OnceCallback<void(device::mojom::XRSessionPtr)>;
explicit BrowserXRRuntimeImpl(
device::mojom::XRDeviceId id,
+ device::mojom::XRDeviceDataPtr device_data,
mojo::PendingRemote<device::mojom::XRRuntime> runtime,
device::mojom::VRDisplayInfoPtr info);
~BrowserXRRuntimeImpl() override;
@@ -59,10 +60,6 @@ class BrowserXRRuntimeImpl : public content::BrowserXRRuntime,
void RequestSession(VRServiceImpl* service,
const device::mojom::XRRuntimeSessionOptionsPtr& options,
RequestSessionCallback callback);
- void ShowConsentPrompt(int render_process_id,
- int render_frame_id,
- content::XrConsentPromptLevel consent_level,
- content::OnXrUserConsentCallback consent_callback);
void EnsureInstalled(int render_process_id,
int render_frame_id,
base::OnceCallback<void(bool)> install_callback);
@@ -76,6 +73,10 @@ class BrowserXRRuntimeImpl : public content::BrowserXRRuntime,
device::mojom::XRDeviceId GetId() const { return id_; }
+#if defined(OS_WIN)
+ base::Optional<LUID> GetLuid() const;
+#endif
+
// BrowserXRRuntime
void AddObserver(Observer* observer) override;
void RemoveObserver(Observer* observer) override;
@@ -105,6 +106,7 @@ class BrowserXRRuntimeImpl : public content::BrowserXRRuntime,
void OnInstallFinished(bool succeeded);
device::mojom::XRDeviceId id_;
+ device::mojom::XRDeviceDataPtr device_data_;
mojo::Remote<device::mojom::XRRuntime> runtime_;
mojo::Remote<device::mojom::XRSessionController>
immersive_session_controller_;
@@ -118,7 +120,6 @@ class BrowserXRRuntimeImpl : public content::BrowserXRRuntime,
this};
base::ObserverList<Observer> observers_;
- std::unique_ptr<content::XrConsentHelper> consent_helper_;
std::unique_ptr<content::XrInstallHelper> install_helper_;
base::OnceCallback<void(bool)> install_finished_callback_;
diff --git a/chromium/content/browser/xr/service/isolated_device_provider.cc b/chromium/content/browser/xr/service/isolated_device_provider.cc
index aae1ae6c654..650a86614e1 100644
--- a/chromium/content/browser/xr/service/isolated_device_provider.cc
+++ b/chromium/content/browser/xr/service/isolated_device_provider.cc
@@ -18,6 +18,7 @@ namespace content {
void IsolatedVRDeviceProvider::Initialize(
base::RepeatingCallback<void(device::mojom::XRDeviceId,
device::mojom::VRDisplayInfoPtr,
+ device::mojom::XRDeviceDataPtr,
mojo::PendingRemote<device::mojom::XRRuntime>)>
add_device_callback,
base::RepeatingCallback<void(device::mojom::XRDeviceId)>
@@ -37,8 +38,10 @@ bool IsolatedVRDeviceProvider::Initialized() {
void IsolatedVRDeviceProvider::OnDeviceAdded(
mojo::PendingRemote<device::mojom::XRRuntime> device,
mojo::PendingRemote<device::mojom::XRCompositorHost> compositor_host,
+ device::mojom::XRDeviceDataPtr device_data,
device::mojom::XRDeviceId device_id) {
- add_device_callback_.Run(device_id, nullptr, std::move(device));
+ add_device_callback_.Run(device_id, nullptr, std::move(device_data),
+ std::move(device));
auto* integration_client = GetXrIntegrationClient();
if (!integration_client)
diff --git a/chromium/content/browser/xr/service/isolated_device_provider.h b/chromium/content/browser/xr/service/isolated_device_provider.h
index e362f18f59c..6495c377198 100644
--- a/chromium/content/browser/xr/service/isolated_device_provider.h
+++ b/chromium/content/browser/xr/service/isolated_device_provider.h
@@ -30,6 +30,7 @@ class IsolatedVRDeviceProvider
base::RepeatingCallback<void(
device::mojom::XRDeviceId,
device::mojom::VRDisplayInfoPtr,
+ device::mojom::XRDeviceDataPtr,
mojo::PendingRemote<device::mojom::XRRuntime>)> add_device_callback,
base::RepeatingCallback<void(device::mojom::XRDeviceId)>
remove_device_callback,
@@ -43,6 +44,7 @@ class IsolatedVRDeviceProvider
void OnDeviceAdded(
mojo::PendingRemote<device::mojom::XRRuntime> device,
mojo::PendingRemote<device::mojom::XRCompositorHost> compositor_host,
+ device::mojom::XRDeviceDataPtr device_data,
device::mojom::XRDeviceId device_id) override;
void OnDeviceRemoved(device::mojom::XRDeviceId id) override;
void OnDevicesEnumerated() override;
@@ -53,8 +55,10 @@ class IsolatedVRDeviceProvider
int retry_count_ = 0;
mojo::Remote<device::mojom::IsolatedXRRuntimeProvider> device_provider_;
+ // TODO(crbug.com/1090029): Wrap XRDeviceId + VRDisplayInfo into XRDeviceData
base::RepeatingCallback<void(device::mojom::XRDeviceId,
device::mojom::VRDisplayInfoPtr,
+ device::mojom::XRDeviceDataPtr,
mojo::PendingRemote<device::mojom::XRRuntime>)>
add_device_callback_;
base::RepeatingCallback<void(device::mojom::XRDeviceId)>
diff --git a/chromium/content/browser/xr/service/vr_service_impl.cc b/chromium/content/browser/xr/service/vr_service_impl.cc
index e01fc6f8494..6dce9c2ff5f 100644
--- a/chromium/content/browser/xr/service/vr_service_impl.cc
+++ b/chromium/content/browser/xr/service/vr_service_impl.cc
@@ -22,8 +22,6 @@
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
-#include "content/public/common/content_features.h"
-#include "content/public/common/content_switches.h"
#include "content/public/common/origin_util.h"
#include "device/vr/buildflags/buildflags.h"
#include "device/vr/public/cpp/session_mode.h"
@@ -38,42 +36,6 @@ device::mojom::XRRuntimeSessionOptionsPtr GetRuntimeOptions(
return runtime_options;
}
-content::XrConsentPromptLevel GetRequiredConsentLevel(
- device::mojom::XRSessionMode mode,
- const content::BrowserXRRuntimeImpl* runtime,
- const std::set<device::mojom::XRSessionFeature>& requested_features) {
- if (base::Contains(
- requested_features,
- device::mojom::XRSessionFeature::REF_SPACE_BOUNDED_FLOOR)) {
- return content::XrConsentPromptLevel::kVRFloorPlan;
- }
-
- // If the device supports a custom IPD and it will be exposed (via immersive),
- // we need to warn about physical features Being exposed.
- if (runtime->SupportsCustomIPD() &&
- device::XRSessionModeUtils::IsImmersive(mode)) {
- return content::XrConsentPromptLevel::kVRFeatures;
- }
-
- // If local-floor is requested and the device supports a user inputted or real
- // height, we need to warn about physical features being exposed.
- // Note that while this is also the case for bounded-floor, that is covered
- // by the stricter kVRFloorPlan Prompt set above.
- if (base::Contains(requested_features,
- device::mojom::XRSessionFeature::REF_SPACE_LOCAL_FLOOR) &&
- runtime->SupportsNonEmulatedHeight()) {
- return content::XrConsentPromptLevel::kVRFeatures;
- }
-
- // In the absence of other items that need to be consented, inline does not
- // require consent.
- if (mode == device::mojom::XRSessionMode::kInline) {
- return content::XrConsentPromptLevel::kNone;
- }
-
- return content::XrConsentPromptLevel::kDefault;
-}
-
content::PermissionType GetRequiredPermission(
device::mojom::XRSessionMode mode) {
switch (mode) {
@@ -115,6 +77,20 @@ VRServiceImpl::SessionRequestData::~SessionRequestData() {
VRServiceImpl::SessionRequestData::SessionRequestData(SessionRequestData&&) =
default;
+VRServiceImpl::XrCompatibleCallback::XrCompatibleCallback(
+ device::mojom::VRService::MakeXrCompatibleCallback callback)
+ : callback(std::move(callback)) {}
+
+VRServiceImpl::XrCompatibleCallback::XrCompatibleCallback(
+ XrCompatibleCallback&& wrapper) {
+ this->callback = std::move(wrapper.callback);
+}
+
+VRServiceImpl::XrCompatibleCallback::~XrCompatibleCallback() {
+ if (!callback.is_null())
+ std::move(callback).Run(device::mojom::XrCompatibleResult::kNotCompatible);
+}
+
VRServiceImpl::VRServiceImpl(content::RenderFrameHost* render_frame_host)
: WebContentsObserver(
content::WebContents::FromRenderFrameHost(render_frame_host)),
@@ -399,11 +375,11 @@ void VRServiceImpl::RequestSession(
SessionRequestData request(std::move(options), std::move(callback),
std::move(requested_features), runtime->GetId());
- ShowConsentPrompt(std::move(request), runtime);
+ GetPermissionStatus(std::move(request), runtime);
}
-void VRServiceImpl::ShowConsentPrompt(SessionRequestData request,
- BrowserXRRuntimeImpl* runtime) {
+void VRServiceImpl::GetPermissionStatus(SessionRequestData request,
+ BrowserXRRuntimeImpl* runtime) {
DVLOG(2) << __func__;
DCHECK(request.options);
DCHECK(runtime);
@@ -413,61 +389,28 @@ void VRServiceImpl::ShowConsentPrompt(SessionRequestData request,
DCHECK_NE(request.options->mode, device::mojom::XRSessionMode::kImmersiveAr);
#endif
- bool consent_granted = false;
- content::XrConsentPromptLevel consent_level = GetRequiredConsentLevel(
- request.options->mode, runtime, request.enabled_features);
- if (!base::FeatureList::IsEnabled(features::kWebXrPermissionsApi)) {
- consent_granted =
- ((consent_level == content::XrConsentPromptLevel::kNone) ||
- IsConsentGrantedForDevice(request.runtime_id, consent_level));
- }
-
- // Skip the consent prompt if the user has already consented for this device,
- // or if consent is not needed.
- if (consent_granted) {
- EnsureRuntimeInstalled(std::move(request), runtime);
- return;
- }
-
- if (base::FeatureList::IsEnabled(features::kWebXrPermissionsApi)) {
- PermissionControllerImpl* permission_controller =
- PermissionControllerImpl::FromBrowserContext(
- GetWebContents()->GetBrowserContext());
- DCHECK(permission_controller);
-
- // Need to calculate the permission before the call below, as otherwise
- // std::move nulls options out before GetRequiredPermission runs.
- PermissionType permission = GetRequiredPermission(request.options->mode);
- permission_controller->RequestPermission(
- permission, render_frame_host_,
- render_frame_host_->GetLastCommittedURL(), true,
- base::BindOnce(&VRServiceImpl::OnPermissionResult,
- weak_ptr_factory_.GetWeakPtr(), std::move(request),
- consent_level));
- return;
- }
-
- runtime->ShowConsentPrompt(
- render_frame_host_->GetProcess()->GetID(),
- render_frame_host_->GetRoutingID(), consent_level,
- base::BindOnce(&VRServiceImpl::OnConsentResult,
+ PermissionControllerImpl* permission_controller =
+ PermissionControllerImpl::FromBrowserContext(
+ GetWebContents()->GetBrowserContext());
+ DCHECK(permission_controller);
+
+ // Need to calculate the permission before the call below, as otherwise
+ // std::move nulls options out before GetRequiredPermission runs.
+ PermissionType permission = GetRequiredPermission(request.options->mode);
+ permission_controller->RequestPermission(
+ permission, render_frame_host_, render_frame_host_->GetLastCommittedURL(),
+ true,
+ base::BindOnce(&VRServiceImpl::OnPermissionResult,
weak_ptr_factory_.GetWeakPtr(), std::move(request)));
}
-// TODO(alcooper): Once the ConsentFlow can be removed expected_runtime_id and
-// consent_level shouldn't be needed.
void VRServiceImpl::OnPermissionResult(
SessionRequestData request,
- content::XrConsentPromptLevel consent_level,
blink::mojom::PermissionStatus permission_status) {
- OnConsentResult(std::move(request), consent_level,
- permission_status == blink::mojom::PermissionStatus::GRANTED);
-}
-
-void VRServiceImpl::OnConsentResult(SessionRequestData request,
- content::XrConsentPromptLevel consent_level,
- bool is_consent_granted) {
DVLOG(2) << __func__;
+ bool is_consent_granted =
+ (permission_status == blink::mojom::PermissionStatus::GRANTED);
+
if (!is_consent_granted) {
std::move(request.callback)
.Run(device::mojom::RequestSessionResult::NewFailureReason(
@@ -475,8 +418,6 @@ void VRServiceImpl::OnConsentResult(SessionRequestData request,
return;
}
- AddConsentGrantedDevice(request.runtime_id, consent_level);
-
// Re-check for another client instance after a potential user consent.
if (runtime_manager_->IsOtherClientPresenting(this)) {
// Can't create sessions while an immersive session exists.
@@ -608,6 +549,31 @@ void VRServiceImpl::SetFramesThrottled(bool throttled) {
}
}
+void VRServiceImpl::MakeXrCompatible(
+ device::mojom::VRService::MakeXrCompatibleCallback callback) {
+ if (!initialization_complete_) {
+ pending_requests_.push_back(base::BindOnce(&VRServiceImpl::MakeXrCompatible,
+ base::Unretained(this),
+ std::move(callback)));
+ return;
+ }
+
+ xr_compatible_callbacks_.emplace_back(std::move(callback));
+
+ // Only request compatibility if there aren't any pending calls.
+ // OnMakeXrCompatibleComplete will run all callbacks.
+ if (xr_compatible_callbacks_.size() == 1)
+ runtime_manager_->MakeXrCompatible();
+}
+
+void VRServiceImpl::OnMakeXrCompatibleComplete(
+ device::mojom::XrCompatibleResult result) {
+ for (XrCompatibleCallback& wrapper : xr_compatible_callbacks_)
+ std::move(wrapper.callback).Run(result);
+
+ xr_compatible_callbacks_.clear();
+}
+
void VRServiceImpl::OnExitPresent() {
DVLOG(2) << __func__;
@@ -632,20 +598,4 @@ content::WebContents* VRServiceImpl::GetWebContents() {
return content::WebContents::FromRenderFrameHost(render_frame_host_);
}
-bool VRServiceImpl::IsConsentGrantedForDevice(
- device::mojom::XRDeviceId device_id,
- content::XrConsentPromptLevel consent_level) {
- auto it = consent_granted_devices_.find(device_id);
- return it != consent_granted_devices_.end() && it->second >= consent_level;
-}
-
-void VRServiceImpl::AddConsentGrantedDevice(
- device::mojom::XRDeviceId device_id,
- content::XrConsentPromptLevel consent_level) {
- auto it = consent_granted_devices_.find(device_id);
- if (it == consent_granted_devices_.end() || it->second < consent_level) {
- consent_granted_devices_[device_id] = consent_level;
- }
-}
-
} // namespace content
diff --git a/chromium/content/browser/xr/service/vr_service_impl.h b/chromium/content/browser/xr/service/vr_service_impl.h
index 70251655801..9932a0c3cea 100644
--- a/chromium/content/browser/xr/service/vr_service_impl.h
+++ b/chromium/content/browser/xr/service/vr_service_impl.h
@@ -16,8 +16,6 @@
#include "content/browser/xr/metrics/session_metrics_helper.h"
#include "content/common/content_export.h"
#include "content/public/browser/web_contents_observer.h"
-#include "content/public/browser/xr_consent_helper.h"
-#include "content/public/browser/xr_consent_prompt_level.h"
#include "device/vr/public/mojom/isolated_xr_service.mojom-forward.h"
#include "device/vr/public/mojom/vr_service.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -64,6 +62,8 @@ class CONTENT_EXPORT VRServiceImpl : public device::mojom::VRService,
device::mojom::VRService::SupportsSessionCallback callback) override;
void ExitPresent(ExitPresentCallback on_exited) override;
void SetFramesThrottled(bool throttled) override;
+ void MakeXrCompatible(
+ device::mojom::VRService::MakeXrCompatibleCallback callback) override;
void InitializationComplete();
@@ -78,6 +78,7 @@ class CONTENT_EXPORT VRServiceImpl : public device::mojom::VRService,
device::mojom::XRVisibilityState visibility_state);
void OnDisplayInfoChanged();
void RuntimesChanged();
+ void OnMakeXrCompatibleComplete(device::mojom::XrCompatibleResult result);
base::WeakPtr<VRServiceImpl> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
@@ -105,6 +106,18 @@ class CONTENT_EXPORT VRServiceImpl : public device::mojom::VRService,
SessionRequestData& operator=(const SessionRequestData&) = delete;
};
+ // Wrapper around MakeXrCompatibleCallback so that the callback gets executed
+ // on destruction if it hasn't already. Otherwise, mojom throws a DCHECK if
+ // the callback is not executed before being destroyed.
+ struct XrCompatibleCallback {
+ device::mojom::VRService::MakeXrCompatibleCallback callback;
+
+ explicit XrCompatibleCallback(
+ device::mojom::VRService::MakeXrCompatibleCallback callback);
+ XrCompatibleCallback(XrCompatibleCallback&& wrapper);
+ ~XrCompatibleCallback();
+ };
+
// content::WebContentsObserver implementation
void OnWebContentsFocused(content::RenderWidgetHost* host) override;
void OnWebContentsLostFocus(content::RenderWidgetHost* host) override;
@@ -121,26 +134,15 @@ class CONTENT_EXPORT VRServiceImpl : public device::mojom::VRService,
bool InternalSupportsSession(device::mojom::XRSessionOptions* options);
- bool IsConsentGrantedForDevice(device::mojom::XRDeviceId device_id,
- content::XrConsentPromptLevel consent_level);
- void AddConsentGrantedDevice(device::mojom::XRDeviceId device_id,
- content::XrConsentPromptLevel consent_level);
-
// The following steps are ordered in the general flow for "RequestSession"
- // If the WebXrPermissionsAPI is enabled ShowConsentPrompt will result in a
- // call to OnPermissionResult which feeds into OnConsentResult.
- // If ShowConsentPrompt determines that no consent/permission is needed (or
- // has already been granted), then it will directly call
- // EnsureRuntimeInstalled. DoRequestSession will continue with OnInline or
+ // GetPermissionStatus will result in a call to OnPermissionResult which then
+ // calls EnsureRuntimeInstalled (with a callback to OnInstallResult), which
+ // then feeds into DoRequestSession, which will continue with OnInline or
// OnImmersive SessionCreated depending on the type of session created.
- void ShowConsentPrompt(SessionRequestData request,
- BrowserXRRuntimeImpl* runtime);
+ void GetPermissionStatus(SessionRequestData request,
+ BrowserXRRuntimeImpl* runtime);
- void OnConsentResult(SessionRequestData request,
- content::XrConsentPromptLevel consent_level,
- bool is_consent_granted);
void OnPermissionResult(SessionRequestData request,
- content::XrConsentPromptLevel consent_level,
blink::mojom::PermissionStatus permission_status);
void EnsureRuntimeInstalled(SessionRequestData request,
@@ -177,8 +179,7 @@ class CONTENT_EXPORT VRServiceImpl : public device::mojom::VRService,
bool in_focused_frame_ = false;
bool frames_throttled_ = false;
- std::map<device::mojom::XRDeviceId, content::XrConsentPromptLevel>
- consent_granted_devices_;
+ std::vector<XrCompatibleCallback> xr_compatible_callbacks_;
base::WeakPtrFactory<VRServiceImpl> weak_ptr_factory_{this};
diff --git a/chromium/content/browser/xr/service/xr_runtime_manager_impl.cc b/chromium/content/browser/xr/service/xr_runtime_manager_impl.cc
index bb096ac8a53..9cfddf411ef 100644
--- a/chromium/content/browser/xr/service/xr_runtime_manager_impl.cc
+++ b/chromium/content/browser/xr/service/xr_runtime_manager_impl.cc
@@ -9,21 +9,27 @@
#include <utility>
#include "base/bind.h"
+#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/lazy_instance.h"
#include "base/memory/singleton.h"
+#include "base/strings/string_number_conversions.h"
#include "base/trace_event/common/trace_event_common.h"
#include "build/build_config.h"
#include "content/browser/xr/xr_utils.h"
#include "content/public/browser/device_service.h"
+#include "content/public/browser/gpu_data_manager.h"
+#include "content/public/browser/gpu_utils.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "device/base/features.h"
#include "device/vr/buildflags/buildflags.h"
#include "device/vr/orientation/orientation_device_provider.h"
#include "device/vr/public/cpp/vr_device_provider.h"
+#include "gpu/config/gpu_info.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/device/public/mojom/sensor_provider.mojom.h"
+#include "ui/gl/gl_switches.h"
#if !defined(OS_ANDROID)
#include "content/browser/xr/service/isolated_device_provider.h"
@@ -310,6 +316,87 @@ void XRRuntimeManagerImpl::SupportsSession(
std::move(callback).Run(true);
}
+void XRRuntimeManagerImpl::MakeXrCompatible() {
+ auto* runtime = GetImmersiveVrRuntime();
+ if (!runtime) {
+ // WebXR spec: if there's no device, xr compatible is false.
+ for (VRServiceImpl* service : services_)
+ service->OnMakeXrCompatibleComplete(
+ device::mojom::XrCompatibleResult::kNotCompatible);
+ return;
+ }
+
+ if (!IsInitializedOnCompatibleAdapter(runtime)) {
+#if defined(OS_WIN)
+ base::Optional<LUID> luid = runtime->GetLuid();
+ // IsInitializedOnCompatibleAdapter should have returned true if the
+ // runtime doesn't specify a LUID.
+ DCHECK(luid && (luid->HighPart != 0 || luid->LowPart != 0));
+
+ // Add the XR compatible adapter LUID to the browser command line.
+ // GpuProcessHost::LaunchGpuProcess passes this to the GPU process.
+ std::string luid_string = base::NumberToString(luid->HighPart) + "," +
+ base::NumberToString(luid->LowPart);
+ base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+ switches::kUseAdapterLuid, luid_string);
+
+ // Get notified when the new GPU process sends back its GPUInfo. This
+ // indicates that the GPU process has finished initializing and the GPUInfo
+ // contains the LUID of the active adapter.
+ content::GpuDataManager::GetInstance()->AddObserver(this);
+
+ content::KillGpuProcess();
+ return;
+#else
+ // MakeXrCompatible is not yet supported on other platforms so
+ // IsInitializedOnCompatibleAdapter should have returned true.
+ NOTREACHED();
+#endif
+ }
+
+ for (VRServiceImpl* service : services_)
+ service->OnMakeXrCompatibleComplete(
+ device::mojom::XrCompatibleResult::kAlreadyCompatible);
+}
+
+bool XRRuntimeManagerImpl::IsInitializedOnCompatibleAdapter(
+ BrowserXRRuntimeImpl* runtime) {
+#if defined(OS_WIN)
+ base::Optional<LUID> luid = runtime->GetLuid();
+ if (luid && (luid->HighPart != 0 || luid->LowPart != 0)) {
+ LUID active_luid =
+ content::GpuDataManager::GetInstance()->GetGPUInfo().active_gpu().luid;
+ return active_luid.HighPart == luid->HighPart &&
+ active_luid.LowPart == luid->LowPart;
+ }
+#endif
+
+ return true;
+}
+
+void XRRuntimeManagerImpl::OnGpuInfoUpdate() {
+ content::GpuDataManager::GetInstance()->RemoveObserver(this);
+
+ device::mojom::XrCompatibleResult xr_compatible_result;
+ auto* runtime = GetImmersiveVrRuntime();
+
+ if (runtime && IsInitializedOnCompatibleAdapter(runtime)) {
+ xr_compatible_result =
+ device::mojom::XrCompatibleResult::kCompatibleAfterRestart;
+ } else {
+ // We can still be incompatible after restarting if either:
+ // 1. The runtime has been removed (usually means the VR headset was
+ // unplugged) since the GPU process restart was triggered. Per the WebXR
+ // spec, if there is no device, xr compatible is false.
+ // 2. The GPU process is still not using the correct GPU after restarting.
+ xr_compatible_result =
+ device::mojom::XrCompatibleResult::kNotCompatibleAfterRestart;
+ }
+
+ for (VRServiceImpl* service : services_)
+ service->OnMakeXrCompatibleComplete(xr_compatible_result);
+}
+
XRRuntimeManagerImpl::XRRuntimeManagerImpl(XRProviderList providers)
: providers_(std::move(providers)) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -385,14 +472,15 @@ bool XRRuntimeManagerImpl::AreAllProvidersInitialized() {
void XRRuntimeManagerImpl::AddRuntime(
device::mojom::XRDeviceId id,
device::mojom::VRDisplayInfoPtr info,
+ device::mojom::XRDeviceDataPtr device_data,
mojo::PendingRemote<device::mojom::XRRuntime> runtime) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(runtimes_.find(id) == runtimes_.end());
TRACE_EVENT_INSTANT1("xr", "AddRuntime", TRACE_EVENT_SCOPE_THREAD, "id", id);
- runtimes_[id] = std::make_unique<BrowserXRRuntimeImpl>(id, std::move(runtime),
- std::move(info));
+ runtimes_[id] = std::make_unique<BrowserXRRuntimeImpl>(
+ id, std::move(device_data), std::move(runtime), std::move(info));
for (Observer& obs : g_xr_runtime_manager_observers.Get())
obs.OnRuntimeAdded(runtimes_[id].get());
diff --git a/chromium/content/browser/xr/service/xr_runtime_manager_impl.h b/chromium/content/browser/xr/service/xr_runtime_manager_impl.h
index 57e5494a3d9..0445b05fb3e 100644
--- a/chromium/content/browser/xr/service/xr_runtime_manager_impl.h
+++ b/chromium/content/browser/xr/service/xr_runtime_manager_impl.h
@@ -21,6 +21,7 @@
#include "content/browser/xr/service/browser_xr_runtime_impl.h"
#include "content/browser/xr/service/vr_service_impl.h"
#include "content/common/content_export.h"
+#include "content/public/browser/gpu_data_manager_observer.h"
#include "content/public/browser/xr_integration_client.h"
#include "content/public/browser/xr_runtime_manager.h"
#include "device/vr/public/mojom/vr_service.mojom-forward.h"
@@ -33,7 +34,8 @@ class XRRuntimeManagerTest;
// instances.
class CONTENT_EXPORT XRRuntimeManagerImpl
: public XRRuntimeManager,
- public base::RefCounted<XRRuntimeManagerImpl> {
+ public base::RefCounted<XRRuntimeManagerImpl>,
+ public content::GpuDataManagerObserver {
public:
friend base::RefCounted<XRRuntimeManagerImpl>;
static constexpr auto kRefCountPreference =
@@ -73,6 +75,11 @@ class CONTENT_EXPORT XRRuntimeManagerImpl
device::mojom::XRSessionOptionsPtr options,
device::mojom::VRService::SupportsSessionCallback callback);
+ void MakeXrCompatible();
+
+ // content::GpuDataManagerObserver
+ void OnGpuInfoUpdate() override;
+
// XRRuntimeManager implementation
BrowserXRRuntimeImpl* GetRuntime(device::mojom::XRDeviceId id) override;
void ForEachRuntime(
@@ -99,9 +106,12 @@ class CONTENT_EXPORT XRRuntimeManagerImpl
void AddRuntime(device::mojom::XRDeviceId id,
device::mojom::VRDisplayInfoPtr info,
+ device::mojom::XRDeviceDataPtr device_data,
mojo::PendingRemote<device::mojom::XRRuntime> runtime);
void RemoveRuntime(device::mojom::XRDeviceId id);
+ bool IsInitializedOnCompatibleAdapter(BrowserXRRuntimeImpl* runtime);
+
// Gets the system default immersive-vr runtime if available.
BrowserXRRuntimeImpl* GetImmersiveVrRuntime();