Commit bf861661 authored by Iker Jamardo's avatar Iker Jamardo Committed by Commit Bot

Add explicit requestSession call to the browser process for WebXR.

Improves the support for requestSession in WebXR mainly focused on
allowing ARCoreDevice to receive a call when the session request
is made.

Also adds a check to both supportSession and requestSession to ensure
the device supports AR capabilities when the hit-test flag is enabled.

Bug: 835037

Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_vr
Change-Id: I8090f64a981114b130e446025ec6299fbb5619e4
Reviewed-on: https://chromium-review.googlesource.com/1046107
Commit-Queue: Iker Jamardo <ijamardo@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarKlaus Weidner <klausw@chromium.org>
Reviewed-by: default avatarBiao She <bshe@chromium.org>
Reviewed-by: default avatarDavid Dorwin <ddorwin@chromium.org>
Reviewed-by: default avatarBill Orr <billorr@chromium.org>
Reviewed-by: default avatarYaron Friedman <yfriedman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#562044}
parent 50da791e
......@@ -104,6 +104,13 @@ void ARCoreDevice::PostTaskToGlThread(base::OnceClosure task) {
FROM_HERE, std::move(task));
}
void ARCoreDevice::RequestSession(
VRDisplayImpl* display,
mojom::VRDisplayHost::RequestSessionCallback callback) {
// TODO(https://crbug.com/837116): Hook up ARCoreDevice to ARCore library
std::move(callback).Run(true);
}
void ARCoreDevice::OnMagicWindowFrameDataRequest(
const gfx::Size& frame_size,
display::Display::Rotation display_rotation,
......
......@@ -25,6 +25,11 @@ class ARCoreDevice : public VRDeviceBase {
ARCoreDevice();
~ARCoreDevice() override;
// VRDeviceBase implementation.
void RequestSession(
VRDisplayImpl* display,
mojom::VRDisplayHost::RequestSessionCallback callback) override;
base::WeakPtr<ARCoreDevice> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
......
......@@ -58,17 +58,22 @@ VRDisplayHost::~VRDisplayHost() {
browser_device_->OnDisplayHostRemoved(this);
}
void VRDisplayHost::RequestSession(RequestSessionCallback callback) {
if (!IsSecureContextRequirementSatisfied()) {
std::move(callback).Run(false);
return;
}
display_->RequestSession(std::move(callback));
}
void VRDisplayHost::RequestPresent(
device::mojom::VRSubmitFrameClientPtr client,
device::mojom::VRPresentationProviderRequest request,
device::mojom::VRRequestPresentOptionsPtr options,
bool triggered_by_displayactive,
RequestPresentCallback callback) {
bool requires_secure_context =
!kAllowHTTPWebVRWithFlag ||
!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableWebVR);
if (requires_secure_context && !IsSecureContext(render_frame_host_)) {
if (!IsSecureContextRequirementSatisfied()) {
std::move(callback).Run(false, nullptr);
return;
}
......@@ -143,4 +148,16 @@ void VRDisplayHost::OnDeactivate(device::mojom::VRDisplayEventReason reason) {
client_->OnDeactivate(reason);
}
bool VRDisplayHost::IsSecureContextRequirementSatisfied() {
// We require secure connections unless both the webvr flag and the
// http flag are enabled.
bool requires_secure_context =
!kAllowHTTPWebVRWithFlag ||
!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableWebVR);
if (!requires_secure_context)
return true;
return IsSecureContext(render_frame_host_);
}
} // namespace vr
......@@ -36,6 +36,7 @@ class VRDisplayHost : public device::mojom::VRDisplayHost {
~VRDisplayHost() override;
// device::mojom::VRDisplayHost
void RequestSession(RequestSessionCallback callback) override;
void RequestPresent(device::mojom::VRSubmitFrameClientPtr client,
device::mojom::VRPresentationProviderRequest request,
device::mojom::VRRequestPresentOptionsPtr options,
......@@ -59,6 +60,10 @@ class VRDisplayHost : public device::mojom::VRDisplayHost {
private:
void ReportRequestPresent();
// TODO(https://crbug.com/837538): Instead, check before returning this
// object.
bool IsSecureContextRequirementSatisfied();
std::unique_ptr<device::VRDisplayImpl> display_;
BrowserXrDevice* browser_device_ = nullptr;
bool in_focused_frame_ = false;
......
......@@ -250,6 +250,16 @@ interface VRSubmitFrameClient {
// Provides a communication channel from the renderer to the browser-side host
// of a (device/) VrDisplayImpl.
interface VRDisplayHost {
// Request to initialize a session in the browser process. The return value
// indicates if the session was successfully initialized or not. This method
// must be called before RequestPresent and the magic window provider
// methods.
// TODO(https://crbug.com/842042): Call VRDisplayHost::RequestSession() from
// WebVR.
// TODO(https://crbug.com/842025): Refactor VR device interfaces to better
// reflect WebXR.
RequestSession() => (bool success);
// The returned transport_options is marked optional: it's null for
// a failure result but must be non-null for a success result.
RequestPresent(VRSubmitFrameClient client,
......@@ -258,6 +268,7 @@ interface VRDisplayHost {
bool triggered_by_displayactive) => (
bool success,
VRDisplayFrameTransportOptions? transport_options);
ExitPresent();
};
......
......@@ -12,6 +12,8 @@
namespace device {
class VRDisplayImpl;
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class VrViewerType {
......@@ -60,6 +62,9 @@ class DEVICE_VR_EXPORT VRDevice {
virtual mojom::VRDisplayInfoPtr GetVRDisplayInfo() = 0;
virtual void SetMagicWindowEnabled(bool enabled) = 0;
virtual void ExitPresent() = 0;
virtual void RequestSession(
VRDisplayImpl* display,
mojom::VRDisplayHost::RequestSessionCallback callback) = 0;
virtual void RequestPresent(
mojom::VRSubmitFrameClientPtr submit_client,
mojom::VRPresentationProviderRequest request,
......
......@@ -27,6 +27,15 @@ void VRDeviceBase::PauseTracking() {}
void VRDeviceBase::ResumeTracking() {}
mojom::VRDisplayInfoPtr VRDeviceBase::GetVRDisplayInfo() {
DCHECK(display_info_);
return display_info_.Clone();
}
bool VRDeviceBase::IsFallbackDevice() {
return false;
};
void VRDeviceBase::OnExitPresent() {
if (listener_)
listener_->OnExitPresent();
......@@ -37,13 +46,11 @@ void VRDeviceBase::SetIsPresenting() {
presenting_ = true;
}
bool VRDeviceBase::IsFallbackDevice() {
return false;
};
mojom::VRDisplayInfoPtr VRDeviceBase::GetVRDisplayInfo() {
DCHECK(display_info_);
return display_info_.Clone();
void VRDeviceBase::RequestSession(
VRDisplayImpl* display,
mojom::VRDisplayHost::RequestSessionCallback callback) {
// TODO(https://crbug.com/842025): Implement this for all devices.
std::move(callback).Run(true);
}
void VRDeviceBase::RequestPresent(
......
......@@ -14,8 +14,6 @@
namespace device {
class VRDisplayImpl;
// Represents one of the platform's VR devices. Owned by the respective
// VRDeviceProvider.
// TODO(mthiesse, crbug.com/769373): Remove DEVICE_VR_EXPORT.
......@@ -32,7 +30,9 @@ class DEVICE_VR_EXPORT VRDeviceBase : public VRDevice {
mojom::VRDisplayInfoPtr GetVRDisplayInfo() final;
void SetMagicWindowEnabled(bool enabled) final;
void SetVRDeviceEventListener(VRDeviceEventListener* listener) final;
void RequestSession(
VRDisplayImpl* display,
mojom::VRDisplayHost::RequestSessionCallback callback) override;
void RequestPresent(
mojom::VRSubmitFrameClientPtr submit_client,
mojom::VRPresentationProviderRequest request,
......@@ -40,9 +40,9 @@ class DEVICE_VR_EXPORT VRDeviceBase : public VRDevice {
mojom::VRDisplayHost::RequestPresentCallback callback) override;
void ExitPresent() override;
bool IsFallbackDevice() override;
void SetListeningForActivate(bool is_listening) override;
bool IsAccessAllowed(VRDisplayImpl* display);
void SetListeningForActivate(bool is_listening) override;
void OnListeningForActivateChanged(VRDisplayImpl* display);
void OnFrameFocusChanged(VRDisplayImpl* display);
void GetMagicWindowPose(
......
......@@ -33,6 +33,15 @@ VRDisplayImpl::VRDisplayImpl(VRDevice* device,
VRDisplayImpl::~VRDisplayImpl() = default;
void VRDisplayImpl::RequestSession(
mojom::VRDisplayHost::RequestSessionCallback callback) {
if (!CanStartNewSession()) {
std::move(callback).Run(false);
return;
}
device_->RequestSession(this, std::move(callback));
}
// Gets a pose for magic window sessions.
void VRDisplayImpl::GetPose(GetPoseCallback callback) {
if (!device_->IsAccessAllowed(this)) {
......@@ -65,6 +74,10 @@ void VRDisplayImpl::GetFrameData(const gfx::Size& frame_size,
device_->GetMagicWindowFrameData(frame_size, rotation, std::move(callback));
}
bool VRDisplayImpl::CanStartNewSession() {
return device_->IsAccessAllowed(this) && InFocusedFrame();
}
void VRDisplayImpl::SetListeningForActivate(bool listening) {
listening_for_activate_ = listening;
device_->OnListeningForActivateChanged(this);
......
......@@ -40,6 +40,8 @@ class DEVICE_VR_EXPORT VRDisplayImpl : public mojom::VRMagicWindowProvider {
virtual bool ListeningForActivate();
virtual bool InFocusedFrame();
void RequestSession(mojom::VRDisplayHost::RequestSessionCallback callback);
private:
// mojom::VRMagicWindowProvider
void GetPose(GetPoseCallback callback) override;
......@@ -47,6 +49,8 @@ class DEVICE_VR_EXPORT VRDisplayImpl : public mojom::VRMagicWindowProvider {
display::Display::Rotation rotation,
GetFrameDataCallback callback) override;
bool CanStartNewSession();
mojo::Binding<mojom::VRMagicWindowProvider> binding_;
device::VRDeviceBase* device_;
bool listening_for_activate_ = false;
......
......@@ -274,6 +274,10 @@ class MockDevice {
}
}
requestSession() {
return Promise.resolve({success:true});
}
requestPresent(submitFrameClient, request, presentOptions) {
this.presentation_provider_.bind(
submitFrameClient, request, presentOptions);
......
......@@ -25,13 +25,16 @@ function xr_session_promise_test(
// Run the test with each set of sessionOptions from the array one
// at a time.
function nextSessionTest(i) {
// Check if it's time to break the loop.
if (i == sessionOptions.length) {
if (sessionOptions.length == 0) {
reject('No option for the session. Test Did not run.');
} else {
resolve();
}
return;
}
// Perform the session request in a user gesture.
runWithUserGesture(() => {
let nextOptions = sessionOptions[i];
......@@ -41,21 +44,14 @@ function xr_session_promise_test(
testSession = session;
return func(session, t);
})
.then(() => {
// Wrap in a try in case the session was ended in the
// test itself.
try {
// If there's another test to run after this one make
// sure to end the session so that we don't
// accidentally try to have, for example, two
// exclusive sessions at once.
if (i < sessionOptions.length - 1) {
testSession.end();
}
} finally {
nextSessionTest(++i);
}
})
.then(
() => {// End the session. Silence any errors
// generated if the session was already ended.
// TODO(offenwanger): This throw error when a
// session is already ended is not defined by
// the spec.
testSession.end().catch(() => {})})
.then(() => nextSessionTest(++i))
.catch((err) => {
let optionsString = '{';
let firstOption = true;
......
......@@ -30,6 +30,9 @@ const char kNoOutputContext[] =
const char kRequestRequiresUserActivation[] =
"The requested session requires user activation.";
const char kSessionNotSupported[] =
"The specified session configuration is not supported.";
} // namespace
XRDevice::XRDevice(
......@@ -67,6 +70,25 @@ const char* XRDevice::checkSessionSupport(
}
}
// TODO(https://crbug.com/828321): Use session options instead of the flag.
bool is_ar = RuntimeEnabledFeatures::WebXRHitTestEnabled();
if (is_ar) {
if (!supports_ar_) {
return kSessionNotSupported;
}
// TODO(https://crbug.com/828321): Expose information necessary to check
// combinations.
// For now, exclusive AR is not supported.
if (options.exclusive()) {
return kSessionNotSupported;
}
} else {
// TODO(https://crbug.com/828321): Remove this check when properly
// supporting multiple VRDevice registration.
DCHECK(!supports_ar_);
// TODO(https://crbug.com/828321): Check that VR is supported.
}
return nullptr;
}
......@@ -145,6 +167,23 @@ ScriptPromise XRDevice::requestSession(
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
display_->RequestSession(WTF::Bind(&XRDevice::OnRequestSessionComplete,
WrapWeakPersistent(this),
WrapPersistent(resolver), options));
return promise;
}
void XRDevice::OnRequestSessionComplete(ScriptPromiseResolver* resolver,
const XRSessionCreationOptions& options,
bool success) {
if (!success) {
DOMException* exception =
DOMException::Create(kNotSupportedError, kSessionNotSupported);
resolver->Reject(exception);
return;
}
XRPresentationContext* output_context = nullptr;
if (options.hasOutputContext()) {
output_context = options.outputContext();
......@@ -158,8 +197,6 @@ ScriptPromise XRDevice::requestSession(
} else {
resolver->Resolve(session);
}
return promise;
}
void XRDevice::OnFrameFocusChanged() {
......@@ -220,6 +257,7 @@ void XRDevice::SetXRDisplayInfo(
display_info_ = std::move(display_info);
is_external_ = display_info_->capabilities->hasExternalDisplay;
supports_exclusive_ = (display_info_->capabilities->canPresent);
supports_ar_ = display_info_->capabilities->can_provide_pass_through_images;
}
void XRDevice::Trace(blink::Visitor* visitor) {
......
......@@ -16,6 +16,7 @@
namespace blink {
class ScriptPromiseResolver;
class XR;
class XRFrameProvider;
class XRSession;
......@@ -86,6 +87,10 @@ class XRDevice final : public EventTargetWithInlineData,
const char* checkSessionSupport(const XRSessionCreationOptions&) const;
void OnRequestSessionComplete(ScriptPromiseResolver* resolver,
const XRSessionCreationOptions& options,
bool success);
// There are two components to focus - whether the frame itself has
// traditional focus and whether the device reports that we have focus. These
// are aggregated so we can hand out focus/blur events on sessions and
......@@ -96,8 +101,9 @@ class XRDevice final : public EventTargetWithInlineData,
Member<XR> xr_;
Member<XRFrameProvider> frame_provider_;
HeapHashSet<WeakMember<XRSession>> sessions_;
bool is_external_;
bool supports_exclusive_;
bool is_external_ = false;
bool supports_exclusive_ = false;
bool supports_ar_ = false;
bool has_device_focus_ = true;
// Indicates whether we've already logged a request for an exclusive session.
......
......@@ -430,10 +430,16 @@ void XRFrameProvider::ProcessScheduledFrame(
frame_pose_->input_state.value());
}
if (!exclusive_session_can_send_frames_)
return;
if (frame_pose_ && frame_pose_->pose_reset) {
exclusive_session_->OnPoseReset();
}
if (!exclusive_session_can_send_frames_)
return;
// If there's an exclusive session active only process its frame.
std::unique_ptr<TransformationMatrix> pose_matrix =
getPoseMatrix(frame_pose_);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment