Diff
Modified: trunk/LayoutTests/ChangeLog (261862 => 261863)
--- trunk/LayoutTests/ChangeLog 2020-05-19 16:08:08 UTC (rev 261862)
+++ trunk/LayoutTests/ChangeLog 2020-05-19 16:08:47 UTC (rev 261863)
@@ -1,3 +1,13 @@
+2020-05-14 Sergio Villar Senin <svil...@igalia.com>
+
+ [WebXR] Implement requestSession()
+ https://bugs.webkit.org/show_bug.cgi?id=211888
+
+ Reviewed by Youenn Fablet.
+
+ * platform/wpe/TestExpectations: Added several previously skipped tests
+ that are now passing.
+
2020-05-19 Antti Koivisto <an...@apple.com>
Animation of font-size with rem values is incorrect
Modified: trunk/LayoutTests/imported/w3c/ChangeLog (261862 => 261863)
--- trunk/LayoutTests/imported/w3c/ChangeLog 2020-05-19 16:08:08 UTC (rev 261862)
+++ trunk/LayoutTests/imported/w3c/ChangeLog 2020-05-19 16:08:47 UTC (rev 261863)
@@ -1,3 +1,19 @@
+2020-05-14 Sergio Villar Senin <svil...@igalia.com>
+
+ [WebXR] Implement requestSession()
+ https://bugs.webkit.org/show_bug.cgi?id=211888
+
+ Reviewed by Youenn Fablet.
+
+ * web-platform-tests/webxr/xrDevice_requestSession_immersive.https-expected.txt: Added.
+ * web-platform-tests/webxr/xrDevice_requestSession_immersive_no_gesture.https-expected.txt: Added.
+ * web-platform-tests/webxr/xrDevice_requestSession_immersive_unsupported.https-expected.txt: Added.
+ * web-platform-tests/webxr/xrDevice_requestSession_no_mode.https-expected.txt: Added.
+ * web-platform-tests/webxr/xrDevice_requestSession_non_immersive_no_gesture.https-expected.txt: Added.
+ * web-platform-tests/webxr/xrDevice_requestSession_optionalFeatures.https-expected.txt: Added.
+ * web-platform-tests/webxr/xrDevice_requestSession_requiredFeatures_unknown.https-expected.txt: Added.
+ * web-platform-tests/webxr/xrSession_features_deviceSupport.https-expected.txt: Added.
+
2020-05-19 Carlos Alberto Lopez Perez <clo...@igalia.com>
Import the Flexbox test suite from the W3C Web Platform Tests
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_immersive.https-expected.txt (0 => 261863)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_immersive.https-expected.txt (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_immersive.https-expected.txt 2020-05-19 16:08:47 UTC (rev 261863)
@@ -0,0 +1,5 @@
+
+PASS Tests requestSession resolves when supported
+PASS Tests requestSession accepts XRSessionInit dictionary
+PASS Tests requestSession ignores unknown optionalFeatures
+
Property changes on: trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_immersive.https-expected.txt
___________________________________________________________________
Added: svn:eol-style
+LF
\ No newline at end of property
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_immersive_no_gesture.https-expected.txt (0 => 261863)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_immersive_no_gesture.https-expected.txt (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_immersive_no_gesture.https-expected.txt 2020-05-19 16:08:47 UTC (rev 261863)
@@ -0,0 +1,3 @@
+
+PASS Requesting immersive session outside of a user gesture rejects
+
Property changes on: trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_immersive_no_gesture.https-expected.txt
___________________________________________________________________
Added: svn:eol-style
+LF
\ No newline at end of property
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_immersive_unsupported.https-expected.txt (0 => 261863)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_immersive_unsupported.https-expected.txt (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_immersive_unsupported.https-expected.txt 2020-05-19 16:08:47 UTC (rev 261863)
@@ -0,0 +1,3 @@
+
+PASS Requesting an immersive session when unsupported rejects
+
Property changes on: trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_immersive_unsupported.https-expected.txt
___________________________________________________________________
Added: svn:eol-style
+LF
\ No newline at end of property
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_no_mode.https-expected.txt (0 => 261863)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_no_mode.https-expected.txt (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_no_mode.https-expected.txt 2020-05-19 16:08:47 UTC (rev 261863)
@@ -0,0 +1,3 @@
+
+PASS Requesting a session with no mode rejects
+
Property changes on: trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_no_mode.https-expected.txt
___________________________________________________________________
Added: svn:eol-style
+LF
\ No newline at end of property
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_non_immersive_no_gesture.https-expected.txt (0 => 261863)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_non_immersive_no_gesture.https-expected.txt (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_non_immersive_no_gesture.https-expected.txt 2020-05-19 16:08:47 UTC (rev 261863)
@@ -0,0 +1,3 @@
+
+PASS Requesting non-immersive session outside of a user gesture succeeds
+
Property changes on: trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_non_immersive_no_gesture.https-expected.txt
___________________________________________________________________
Added: svn:eol-style
+LF
\ No newline at end of property
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_optionalFeatures.https-expected.txt (0 => 261863)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_optionalFeatures.https-expected.txt (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_optionalFeatures.https-expected.txt 2020-05-19 16:08:47 UTC (rev 261863)
@@ -0,0 +1,6 @@
+
+PASS Tests requestSession accepts XRSessionInit dictionary
+PASS Tests requestSession accepts XRSessionInit dictionary with empty feature lists
+PASS Tests requestSession ignores unknown strings in optionalFeatures
+PASS Tests requestSession ignores unknown objects in optionalFeatures
+
Property changes on: trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_optionalFeatures.https-expected.txt
___________________________________________________________________
Added: svn:eol-style
+LF
\ No newline at end of property
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_requiredFeatures_unknown.https-expected.txt (0 => 261863)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_requiredFeatures_unknown.https-expected.txt (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_requiredFeatures_unknown.https-expected.txt 2020-05-19 16:08:47 UTC (rev 261863)
@@ -0,0 +1,3 @@
+
+PASS Tests requestSession rejects for unknown requiredFeatures
+
Property changes on: trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_requiredFeatures_unknown.https-expected.txt
___________________________________________________________________
Added: svn:eol-style
+LF
\ No newline at end of property
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrSession_features_deviceSupport.https-expected.txt (0 => 261863)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrSession_features_deviceSupport.https-expected.txt (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrSession_features_deviceSupport.https-expected.txt 2020-05-19 16:08:47 UTC (rev 261863)
@@ -0,0 +1,3 @@
+
+PASS Immersive XRSession requests with no supported device should reject
+
Property changes on: trunk/LayoutTests/imported/w3c/web-platform-tests/webxr/xrSession_features_deviceSupport.https-expected.txt
___________________________________________________________________
Added: svn:eol-style
+LF
\ No newline at end of property
Modified: trunk/LayoutTests/platform/wpe/TestExpectations (261862 => 261863)
--- trunk/LayoutTests/platform/wpe/TestExpectations 2020-05-19 16:08:08 UTC (rev 261862)
+++ trunk/LayoutTests/platform/wpe/TestExpectations 2020-05-19 16:08:47 UTC (rev 261863)
@@ -1016,6 +1016,14 @@
webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/xrDevice_isSessionSupported_inline.https.html [ Pass ]
webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/xrDevice_isSessionSupported_immersive.https.html [ Pass ]
webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/xrDevice_isSessionSupported_immersive_unsupported.https.html [ Pass ]
+webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_immersive.https.html [ Pass ]
+webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_immersive_no_gesture.https.html [ Pass ]
+webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_immersive_unsupported.https.html [ Pass ]
+webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_no_mode.https.html [ Pass ]
+webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_non_immersive_no_gesture.https.html [ Pass ]
+webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_optionalFeatures.https.html [ Pass ]
+webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_requiredFeatures_unknown.https.html [ Pass ]
+webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/xrSession_features_deviceSupport.https.html [ Pass ]
# Passing since r259006.
imported/w3c/web-platform-tests/css/css-grid/alignment/self-baseline/grid-self-baseline-changes-grid-area-size-010.html
Modified: trunk/Source/WebCore/ChangeLog (261862 => 261863)
--- trunk/Source/WebCore/ChangeLog 2020-05-19 16:08:08 UTC (rev 261862)
+++ trunk/Source/WebCore/ChangeLog 2020-05-19 16:08:47 UTC (rev 261863)
@@ -1,3 +1,67 @@
+2020-05-19 Sergio Villar Senin <svil...@igalia.com>
+
+ [WebXR] Implement requestSession()
+ https://bugs.webkit.org/show_bug.cgi?id=211888
+
+ Reviewed by Youenn Fablet.
+
+ This patch adds a preliminar implementation of the requestSession()
+ API used to get a WebXRSession from the UA. It includes a fairly good
+ amount of checks to verify that the request can be satisfied given the
+ device's enabled features per session modes. The specs also describe how
+ to request persmission for some actions using the Permissions API which
+ WebKit does not currently implement. That should be done in a follow up
+ patch perhaps using a similar approach to other APIs as Geolocation for
+ example.
+
+ In order to get some of the requestSession() tests passing the session
+ finalization (shutdown) had to be implemented too.
+
+ Several tests where unskipped for WPE port as they're now passing.
+
+ * Modules/webxr/WebXRRenderState.cpp:
+ (WebCore::WebXRRenderState::create): Pass XRSessionMode as argument
+ instead of a WebXRSession.
+ * Modules/webxr/WebXRRenderState.h: Ditto.
+ * Modules/webxr/WebXRSession.cpp:
+ (WebCore::WebXRSession::create): Added.
+ (WebCore::WebXRSession::WebXRSession): Added.
+ (WebCore::WebXRSession::renderState const):
+ (WebCore::WebXRSession::inputSources const):
+ (WebCore::WebXRSession::shutdown): Shutdown process called on session end.
+ (WebCore::WebXRSession::end): Implemented session ending.
+ * Modules/webxr/WebXRSession.h: Added create() and private constructor. Fixed some naming.
+ * Modules/webxr/WebXRSystem.cpp:
+ (WebCore::WebXRSystem::DummyInlineDevice::DummyInlineDevice): Contructor for the
+ dummy inline device.
+ (WebCore::WebXRSystem::ensureImmersiveXRDeviceIsSelected): Use a counter instead of a boolean
+ to track testing devices as there might be more than 1.
+ (WebCore::WebXRSystem::obtainCurrentDevice): Implemented from specs text.
+ (WebCore::WebXRSystem::immersiveSessionRequestIsAllowedForGlobalObject const): Ditto.
+ (WebCore::WebXRSystem::inlineSessionRequestIsAllowedForGlobalObject const): Ditto.
+ (WebCore::WebXRSystem::resolveRequestedFeatures const): Ditto.
+ (WebCore::WebXRSystem::isXRPermissionGranted const): Ditto.
+ (WebCore::WebXRSystem::requestSession): Ditto.
+ (WebCore::WebXRSystem::registerSimulatedXRDeviceForTesting): Use a counter instead of a bool.
+ Also use a reference in the method argument.
+ (WebCore::WebXRSystem::unregisterSimulatedXRDeviceForTesting): Ditto.
+ (WebCore::WebXRSystem::sessionEnded): Added, used by sessions to notify the XRSystem.
+ * Modules/webxr/WebXRSystem.h:
+ * Modules/webxr/WebXRSystem.idl: Call requestSession with Document.
+ * dom/TaskSource.h: Added a WebXR task source.
+ * platform/xr/PlatformXR.h: Specs state that devices have a list of enabled features per session
+ mode so store them in a hashmap instead of in a Vector.
+ (PlatformXR::Device::supports const): Use the new Hashmap of session modes.
+ (PlatformXR::Device::setEnabledFeatures): Ditto.
+ (PlatformXR::Device::enabledFeatures const): Ditto.
+ (PlatformXR::Device::setSupportedModes): Deleted.
+ * platform/xr/openxr/PlatformXR.cpp:
+ (PlatformXR::Instance::Impl::collectSupportedSessionModes): Return session modes if any.
+ (PlatformXR::Instance::enumerateImmersiveXRDevices): Fill in features per session mode.
+ * testing/WebXRTest.cpp:
+ (WebCore::WebXRTest::simulateDeviceConnection): Fill in features per session mode.
+ (WebCore::WebXRTest::disconnectAllDevices): Pass a reference to unregister.
+
2020-05-19 Antti Koivisto <an...@apple.com>
Animation of font-size with rem values is incorrect
Modified: trunk/Source/WebCore/Modules/webxr/WebXRInputSourceArray.h (261862 => 261863)
--- trunk/Source/WebCore/Modules/webxr/WebXRInputSourceArray.h 2020-05-19 16:08:08 UTC (rev 261862)
+++ trunk/Source/WebCore/Modules/webxr/WebXRInputSourceArray.h 2020-05-19 16:08:47 UTC (rev 261863)
@@ -39,6 +39,9 @@
public:
unsigned length() const;
WebXRInputSource* item(unsigned) const;
+
+private:
+ WebXRInputSourceArray();
};
} // namespace WebCore
Modified: trunk/Source/WebCore/Modules/webxr/WebXRRenderState.cpp (261862 => 261863)
--- trunk/Source/WebCore/Modules/webxr/WebXRRenderState.cpp 2020-05-19 16:08:08 UTC (rev 261862)
+++ trunk/Source/WebCore/Modules/webxr/WebXRRenderState.cpp 2020-05-19 16:08:47 UTC (rev 261863)
@@ -37,26 +37,11 @@
WTF_MAKE_ISO_ALLOCATED_IMPL(WebXRRenderState);
-Ref<WebXRRenderState> WebXRRenderState::create(const WebXRSession& session)
+Ref<WebXRRenderState> WebXRRenderState::create(XRSessionMode mode)
{
- // When an XRRenderState object is created for an XRSession session, the user agent MUST initialize the render state by running the following steps:
- // 1. Let state be the newly created XRRenderState object.
-
- // 2. Initialize state’s depthNear to 0.1.
- // 3. Initialize state’s depthFar to 1000.0.
- // (Default-initialized in the XRRenderState class definition.)
-
- // 4. If session is an immersive session, initialize state’s inlineVerticalFieldOfView to null.
- // 5. Else initialize state’s inlineVerticalFieldOfView to PI * 0.5.
- // FIXME: "immersive session" support
- UNUSED_PARAM(session);
- Optional<double> inlineVerticalFieldOfView { piOverTwoDouble };
-
- // 6. Initialize state’s baseLayer to null.
- // 7. Initialize state’s outputContext to null.
- // (Initialized to null by default.)
-
- return adoptRef(*new WebXRRenderState(WTFMove(inlineVerticalFieldOfView)));
+ // https://immersive-web.github.io/webxr/#initialize-the-render-state
+ // depthNear, depthFar and baseLayer are initialized in the class definition
+ return adoptRef(*new WebXRRenderState(mode == XRSessionMode::Inline ? makeOptional(piOverTwoDouble) : WTF::nullopt));
}
WebXRRenderState::WebXRRenderState(Optional<double>&& inlineVerticalFieldOfView)
Modified: trunk/Source/WebCore/Modules/webxr/WebXRRenderState.h (261862 => 261863)
--- trunk/Source/WebCore/Modules/webxr/WebXRRenderState.h 2020-05-19 16:08:08 UTC (rev 261862)
+++ trunk/Source/WebCore/Modules/webxr/WebXRRenderState.h 2020-05-19 16:08:47 UTC (rev 261863)
@@ -27,6 +27,7 @@
#if ENABLE(WEBXR)
+#include "XRSessionMode.h"
#include <wtf/IsoMalloc.h>
#include <wtf/Optional.h>
#include <wtf/Ref.h>
@@ -37,12 +38,11 @@
class WebXRWebGLLayer;
struct XRRenderStateInit;
-class WebXRSession;
class WebXRRenderState : public RefCounted<WebXRRenderState> {
WTF_MAKE_ISO_ALLOCATED(WebXRRenderState);
public:
- static Ref<WebXRRenderState> create(const WebXRSession&);
+ static Ref<WebXRRenderState> create(XRSessionMode);
~WebXRRenderState();
double depthNear() const;
@@ -51,14 +51,15 @@
RefPtr<WebXRWebGLLayer> baseLayer() const;
private:
- WebXRRenderState(Optional<double>&&);
- WebXRRenderState(const XRRenderStateInit&);
+ explicit WebXRRenderState(Optional<double>&& fieldOfView);
+ explicit WebXRRenderState(const XRRenderStateInit&);
+ // https://immersive-web.github.io/webxr/#initialize-the-render-state
struct {
- double near { 0.1 };
- double far { 1000 };
+ double near { 0.1 }; // in meters
+ double far { 1000 }; // in meters
} m_depth;
- Optional<double> m_inlineVerticalFieldOfView;
+ Optional<double> m_inlineVerticalFieldOfView; // in radians
RefPtr<WebXRWebGLLayer> m_baseLayer;
};
Modified: trunk/Source/WebCore/Modules/webxr/WebXRSession.cpp (261862 => 261863)
--- trunk/Source/WebCore/Modules/webxr/WebXRSession.cpp 2020-05-19 16:08:08 UTC (rev 261862)
+++ trunk/Source/WebCore/Modules/webxr/WebXRSession.cpp 2020-05-19 16:08:47 UTC (rev 261863)
@@ -28,6 +28,7 @@
#if ENABLE(WEBXR)
+#include "WebXRSystem.h"
#include <wtf/IsoMallocInlines.h>
namespace WebCore {
@@ -34,6 +35,24 @@
WTF_MAKE_ISO_ALLOCATED_IMPL(WebXRSession);
+Ref<WebXRSession> WebXRSession::create(Document& document, WebXRSystem& system, XRSessionMode mode, PlatformXR::Device& device)
+{
+ return adoptRef(*new WebXRSession(document, system, mode, device));
+}
+
+WebXRSession::WebXRSession(Document& document, WebXRSystem& system, XRSessionMode mode, PlatformXR::Device& device)
+ : ActiveDOMObject(&document)
+ , m_xrSystem(system)
+ , m_mode(mode)
+ , m_device(makeWeakPtr(device))
+ , m_activeRenderState(WebXRRenderState::create(mode))
+{
+ // TODO: If no other features of the user agent have done so already,
+ // perform the necessary platform-specific steps to initialize the device’s
+ // tracking and rendering capabilities, including showing any necessary
+ // instructions to the user.
+}
+
WebXRSession::~WebXRSession() = default;
XREnvironmentBlendMode WebXRSession::environmentBlendMode() const
@@ -48,7 +67,7 @@
const WebXRRenderState& WebXRSession::renderState() const
{
- return *m_renderState;
+ return *m_activeRenderState;
}
const WebXRInputSourceArray& WebXRSession::inputSources() const
@@ -73,10 +92,46 @@
{
}
-void WebXRSession::end(EndPromise&&)
+// https://immersive-web.github.io/webxr/#shut-down-the-session
+void WebXRSession::shutdown()
{
+ // 1. Let session be the target XRSession object.
+ // 2. Set session's ended value to true.
+ m_ended = true;
+
+ // 3. If the active immersive session is equal to session, set the active immersive session to null.
+ // 4. Remove session from the list of inline sessions.
+ m_xrSystem.sessionEnded(*this);
+
+ // TODO: complete the implementation
+ // 5. Reject any outstanding promises returned by session with an InvalidStateError, except for any promises returned by end().
+ // 6. If no other features of the user agent are actively using them, perform the necessary platform-specific steps to shut down the device's tracking and rendering capabilities. This MUST include:
+ // 6.1. Releasing exclusive access to the XR device if session is an immersive session.
+ // 6.2. Deallocating any graphics resources acquired by session for presentation to the XR device.
+ // 6.3. Putting the XR device in a state such that a different source may be able to initiate a session with the same device if session is an immersive session.
+ // 7. Queue a task that fires an XRSessionEvent named end on session.
}
+// https://immersive-web.github.io/webxr/#dom-xrsession-end
+void WebXRSession::end(EndPromise&& promise)
+{
+ // The shutdown() call bellow might remove the sole reference to session
+ // that could exist (the XRSystem owns the sessions) so let's protect this.
+ Ref<WebXRSession> protectedThis(*this);
+ // 1. Let promise be a new Promise.
+ // 2. Shut down the target XRSession object.
+ shutdown();
+
+ // 3. Queue a task to perform the following steps:
+ queueTaskKeepingObjectAlive(*this, TaskSource::WebXR, [promise = WTFMove(promise)] () mutable {
+ // 3.1 Wait until any platform-specific steps related to shutting down the session have completed.
+ // 3.2 Resolve promise.
+ promise.resolve();
+ });
+
+ // 4. Return promise.
+}
+
const char* WebXRSession::activeDOMObjectName() const
{
return "XRSession";
Modified: trunk/Source/WebCore/Modules/webxr/WebXRSession.h (261862 => 261863)
--- trunk/Source/WebCore/Modules/webxr/WebXRSession.h 2020-05-19 16:08:08 UTC (rev 261862)
+++ trunk/Source/WebCore/Modules/webxr/WebXRSession.h 2020-05-19 16:08:47 UTC (rev 261863)
@@ -35,6 +35,7 @@
#include "WebXRSpace.h"
#include "XREnvironmentBlendMode.h"
#include "XRReferenceSpaceType.h"
+#include "XRSessionMode.h"
#include "XRVisibilityState.h"
#include <wtf/Ref.h>
#include <wtf/RefCounted.h>
@@ -45,6 +46,7 @@
class XRFrameRequestCallback;
class WebXRReferenceSpace;
+class WebXRSystem;
struct XRRenderStateInit;
class WebXRSession final : public RefCounted<WebXRSession>, public EventTargetWithInlineData, public ActiveDOMObject {
@@ -53,6 +55,7 @@
using RequestReferenceSpacePromise = DOMPromiseDeferred<IDLInterface<WebXRReferenceSpace>>;
using EndPromise = DOMPromiseDeferred<void>;
+ static Ref<WebXRSession> create(Document&, WebXRSystem&, XRSessionMode, PlatformXR::Device&);
virtual ~WebXRSession();
using RefCounted<WebXRSession>::ref;
@@ -74,6 +77,8 @@
bool ended() const { return m_ended; }
private:
+ WebXRSession(Document&, WebXRSystem&, XRSessionMode, PlatformXR::Device&);
+
// EventTarget
EventTargetInterface eventTargetInterface() const override { return WebXRSessionEventTargetInterfaceType; }
ScriptExecutionContext* scriptExecutionContext() const override { return ActiveDOMObject::scriptExecutionContext(); }
@@ -84,11 +89,18 @@
const char* activeDOMObjectName() const override;
void stop() override;
+ void shutdown();
+
XREnvironmentBlendMode m_environmentBlendMode;
XRVisibilityState m_visibilityState;
- RefPtr<WebXRRenderState> m_renderState;
RefPtr<WebXRInputSourceArray> m_inputSources;
bool m_ended { false };
+
+ WebXRSystem& m_xrSystem;
+ XRSessionMode m_mode;
+ WeakPtr<PlatformXR::Device> m_device;
+ RefPtr<WebXRRenderState> m_activeRenderState;
+ RefPtr<WebXRRenderState> m_pendingRenderState;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/Modules/webxr/WebXRSystem.cpp (261862 => 261863)
--- trunk/Source/WebCore/Modules/webxr/WebXRSystem.cpp 2020-05-19 16:08:08 UTC (rev 261862)
+++ trunk/Source/WebCore/Modules/webxr/WebXRSystem.cpp 2020-05-19 16:08:47 UTC (rev 261863)
@@ -28,17 +28,32 @@
#if ENABLE(WEBXR)
+#include "DOMWindow.h"
#include "Document.h"
#include "FeaturePolicy.h"
+#include "IDLTypes.h"
+#include "JSWebXRSession.h"
+#include "JSXRReferenceSpaceType.h"
#include "PlatformXR.h"
#include "RuntimeEnabledFeatures.h"
+#include "SecurityOrigin.h"
+#include "UserGestureIndicator.h"
#include "WebXRSession.h"
+#include "XRReferenceSpaceType.h"
+#include "XRSessionInit.h"
+#include <_javascript_Core/JSGlobalObject.h>
#include <wtf/IsoMallocInlines.h>
+#include <wtf/Scope.h>
namespace WebCore {
WTF_MAKE_ISO_ALLOCATED_IMPL(WebXRSystem);
+WebXRSystem::DummyInlineDevice::DummyInlineDevice()
+{
+ setEnabledFeatures(XRSessionMode::Inline, { XRReferenceSpaceType::Viewer });
+}
+
Ref<WebXRSystem> WebXRSystem::create(ScriptExecutionContext& scriptExecutionContext)
{
return adoptRef(*new WebXRSystem(scriptExecutionContext));
@@ -56,8 +71,7 @@
void WebXRSystem::ensureImmersiveXRDeviceIsSelected()
{
// Don't ask platform code for XR devices, we're using simulated ones.
- // TODO: should be have a MockPlatformXR implementation instead ?
- if (UNLIKELY(m_testingMode))
+ if (UNLIKELY(m_testingDevices))
return;
if (m_activeImmersiveDevice)
@@ -96,6 +110,20 @@
// TODO: 9. Queue a task to fire an event named devicechange on the context object.
}
+
+PlatformXR::Device* WebXRSystem::obtainCurrentDevice(XRSessionMode mode, const JSFeaturesArray& requiredFeatures, const JSFeaturesArray& optionalFeatures)
+{
+ if (mode == XRSessionMode::ImmersiveAr || mode == XRSessionMode::ImmersiveVr) {
+ ensureImmersiveXRDeviceIsSelected();
+ return m_activeImmersiveDevice.get();
+ }
+ if (!requiredFeatures.isEmpty() || !optionalFeatures.isEmpty())
+ return m_inlineXRDevice.get();
+
+ return &m_defaultInlineDevice;
+}
+
+
// https://immersive-web.github.io/webxr/#dom-xrsystem-issessionsupported
void WebXRSystem::isSessionSupported(XRSessionMode mode, IsSessionSupportedPromise&& promise)
{
@@ -106,7 +134,7 @@
return;
}
- // 3. If the requesting document’s origin is not allowed to use the "xr-spatial-tracking" feature policy,
+ // 3. If the requesting document's origin is not allowed to use the "xr-spatial-tracking" feature policy,
// reject promise with a "SecurityError" DOMException and return it.
auto document = downcast<Document>(scriptExecutionContext());
if (!isFeaturePolicyAllowedByDocumentAndAllOwners(FeaturePolicy::Type::XRSpatialTracking, *document, LogFeaturePolicyFailure::Yes)) {
@@ -136,28 +164,267 @@
});
}
-void WebXRSystem::requestSession(XRSessionMode, const XRSessionInit&, RequestSessionPromise&&)
+// https://immersive-web.github.io/webxr/#immersive-session-request-is-allowed
+bool WebXRSystem::immersiveSessionRequestIsAllowedForGlobalObject(DOMWindow& globalObject, Document& document) const
{
- PlatformXR::Instance::singleton();
+ // 1. If the request was not made while the global object has transient
+ // activation or when launching a web application, return false
+ // TODO: add a check for "not launching a web application".
+ if (!globalObject.hasTransientActivation())
+ return false;
- // When the requestSession(mode) method is invoked, the user agent MUST return a new Promise promise and run the following steps in parallel:
- // 1. Let immersive be true if mode is "immersive-vr" or "immersive-ar", and false otherwise.
- // 2. If immersive is true:
- // 1. If pending immersive session is true or active immersive session is not null, reject promise with an "InvalidStateError" DOMException and abort these steps.
- // 2. Else set pending immersive session to be true.
- // 3. Ensure an XR device is selected.
- // 4. If the XR device is null, reject promise with null.
- // 5. Else if the XR device's list of supported modes does not contain mode, reject promise with a "NotSupportedError" DOMException.
- // 6. Else If immersive is true and the algorithm is not triggered by user activation, reject promise with a "SecurityError" DOMException and abort these steps.
- // 7. If promise was rejected and immersive is true, set pending immersive session to false.
- // 8. If promise was rejected, abort these steps.
- // 9. Let session be a new XRSession object.
- // 10. Initialize the session with session and mode.
- // 11. If immersive is true, set the active immersive session to session, and set pending immersive session to false.
- // 12. Else append session to the list of inline sessions.
- // 13. Resolve promise with session.
+ // 2. If the requesting document is not considered trustworthy, return false.
+ // https://immersive-web.github.io/webxr/#trustworthy.
+ if (&document != globalObject.document())
+ return false;
+
+ // https://immersive-web.github.io/webxr/#active-and-focused
+ if (!document.hasFocus() || !document.securityOrigin().isSameOriginAs(globalObject.document()->securityOrigin()))
+ return false;
+
+ // 3. If user intent to begin an immersive session is not well understood,
+ // either via explicit consent or implicit consent, return false
+ if (!UserGestureIndicator::processingUserGesture())
+ return false;
+
+ return true;
}
+// https://immersive-web.github.io/webxr/#inline-session-request-is-allowed
+bool WebXRSystem::inlineSessionRequestIsAllowedForGlobalObject(DOMWindow& globalObject, Document& document, const XRSessionInit& init) const
+{
+ // 1. If the session request contained any required features or optional features and the request was not made
+ // while the global object has transient activation or when launching a web application, return false.
+ bool sessionRequestContainedAnyFeature = !init.optionalFeatures.isEmpty() || !init.requiredFeatures.isEmpty();
+ if (sessionRequestContainedAnyFeature && !globalObject.hasTransientActivation() /* TODO: || !launching a web app */)
+ return false;
+
+ // 2. If the requesting document is not responsible, return false.
+ if (&document != globalObject.document())
+ return false;
+
+ return true;
+}
+
+
+struct WebXRSystem::ResolvedRequestedFeatures {
+ FeaturesArray granted;
+ FeaturesArray consentRequired;
+ FeaturesArray consentOptional;
+};
+
+#define RETURN_FALSE_OR_CONTINUE(mustReturn) { \
+ if (mustReturn) {\
+ return false; \
+ } \
+ continue; \
+}
+
+// https://immersive-web.github.io/webxr/#resolve-the-requested-features
+Optional<WebXRSystem::ResolvedRequestedFeatures> WebXRSystem::resolveRequestedFeatures(XRSessionMode mode, const XRSessionInit& init, PlatformXR::Device* device, JSC::JSGlobalObject& globalObject) const
+{
+ // 1. Let consentRequired be an empty list of DOMString.
+ // 2. Let consentOptional be an empty list of DOMString.
+ ResolvedRequestedFeatures resolvedFeatures;
+
+ // 3. Let device be the result of obtaining the current device for mode, requiredFeatures, and optionalFeatures.
+ // 4. Let granted be a list of DOMString initialized to device's list of enabled features for mode.
+ // 5. If device is null or device's list of supported modes does not contain mode, run the following steps:
+ // 5.1 Return the tuple (consentRequired, consentOptional, granted)
+ if (!device || !device->supports(mode))
+ return resolvedFeatures;
+
+ resolvedFeatures.granted = device->enabledFeatures(mode);
+
+ // 6. Add every feature descriptor in the default features table associated
+ // with mode to the indicated feature list if it is not already present.
+ // https://immersive-web.github.io/webxr/#default-features
+ auto requiredFeaturesWithDefaultFeatures = init.requiredFeatures;
+ requiredFeaturesWithDefaultFeatures.append(convertEnumerationToJS(globalObject, XRReferenceSpaceType::Viewer));
+ if (mode == XRSessionMode::ImmersiveAr || mode == XRSessionMode::ImmersiveVr)
+ requiredFeaturesWithDefaultFeatures.append(convertEnumerationToJS(globalObject, XRReferenceSpaceType::Local));
+
+ // 7. For each feature in requiredFeatures|optionalFeatures perform the following steps:
+ // 8. For each feature in optionalFeatures perform the following steps:
+ // We're merging both loops in a single lambda. The only difference is that a failure on any required features
+ // implies cancelling the whole process while failures in optional features are just skipped.
+ enum class ParsingMode { Strict, Loose };
+ auto parseFeatures = [&device, &globalObject, mode, &resolvedFeatures] (const JSFeaturesArray& sessionFeatures, ParsingMode parsingMode) -> bool {
+ bool returnOnFailure = parsingMode == ParsingMode::Strict;
+ for (const auto& sessionFeature : sessionFeatures) {
+ // 1. If the feature is null, continue to the next entry.
+ if (sessionFeature.isNull())
+ continue;
+
+ // 2. If feature is not a valid feature descriptor, perform the following steps
+ // 2.1. Let s be the result of calling ? ToString(feature).
+ // 2.2. If s is not a valid feature descriptor or is undefined, (return null|continue to next entry).
+ // 2.3. Set feature to s.
+ auto feature = parseEnumeration<XRReferenceSpaceType>(globalObject, sessionFeature);
+ if (!feature)
+ RETURN_FALSE_OR_CONTINUE(returnOnFailure);
+
+ // 3. If feature is already in granted, continue to the next entry.
+ if (resolvedFeatures.granted.contains(feature.value()))
+ continue;
+
+ // 4. If the requesting document's origin is not allowed to use any feature policy required by feature
+ // as indicated by the feature requirements table, (return null|continue to next entry).
+
+ // 5. If session's XR device is not capable of supporting the functionality described by feature or the
+ // user agent has otherwise determined to reject the feature, (return null|continue to next entry).
+ if (!device->enabledFeatures(mode).contains(feature.value()))
+ RETURN_FALSE_OR_CONTINUE(returnOnFailure);
+
+ // 6. If the functionality described by feature requires explicit consent, append it to (consentRequired|consentOptional).
+ // 7. Else append feature to granted.
+ resolvedFeatures.granted.append(feature.value());
+ }
+ return true;
+ };
+
+ if (!parseFeatures(requiredFeaturesWithDefaultFeatures, ParsingMode::Strict))
+ return WTF::nullopt;
+
+ parseFeatures(init.optionalFeatures, ParsingMode::Loose);
+ return resolvedFeatures;
+}
+
+// https://immersive-web.github.io/webxr/#request-the-xr-permission
+bool WebXRSystem::isXRPermissionGranted(XRSessionMode mode, const XRSessionInit& init, PlatformXR::Device* device, JSC::JSGlobalObject& globalObject) const
+{
+ // 1. Set status's granted to an empty FrozenArray.
+ // 2. Let requiredFeatures be descriptor's requiredFeatures.
+ // 3. Let optionalFeatures be descriptor's optionalFeatures.
+ // 4. Let device be the result of obtaining the current device for mode, requiredFeatures, and optionalFeatures.
+
+ // 5. Let result be the result of resolving the requested features given requiredFeatures,optionalFeatures, and mode.
+ auto resolvedFeatures = resolveRequestedFeatures(mode, init, device, globalObject);
+
+ // 6. If result is null, run the following steps:
+ // 6.1. Set status's state to "denied".
+ // 6.2. Abort these steps.
+ if (!resolvedFeatures)
+ return false;
+
+ // 7. Let (consentRequired, consentOptional, granted) be the fields of result.
+ // 8. The user agent MAY at this point ask the user's permission for the calling algorithm to use any of the features
+ // in consentRequired and consentOptional. The results of these prompts should be included when determining if there
+ // is a clear signal of user intent for enabling these features.
+ // 9. For each feature in consentRequired perform the following steps:
+ // 9.1. The user agent MAY at this point ask the user's permission for the calling algorithm to use feature. The results
+ // of these prompts should be included when determining if there is a clear signal of user intent to enable feature.
+ // 9.2. If a clear signal of user intent to enable feature has not been determined, set status's state to "denied" and
+ // abort these steps.
+ // 9.3. If feature is not in granted, append feature to granted.
+ // 10. For each feature in consentOptional perform the following steps:
+ // 10.1. The user agent MAY at this point ask the user's permission for the calling algorithm to use feature. The results
+ // of these prompts should be included when determining if there is a clear signal of user intent to enable feature.
+ // 10.2. If a clear signal of user intent to enable feature has not been determined, continue to the next entry.
+ // 10.3. If feature is not in granted, append feature to granted.
+ // 11. Set status's granted to granted.
+ // 12. Set device's list of enabled features for mode to granted.
+ // 13. Set status's state to "granted".
+ return true;
+}
+
+
+// https://immersive-web.github.io/webxr/#dom-xrsystem-requestsession
+void WebXRSystem::requestSession(Document& document, XRSessionMode mode, const XRSessionInit& init, RequestSessionPromise&& promise)
+{
+ // 1. Let promise be a new Promise.
+ // 2. Let immersive be true if mode is an immersive session mode, and false otherwise.
+ // 3. Let global object be the relevant Global object for the XRSystem on which this method was invoked.
+ bool immersive = mode == XRSessionMode::ImmersiveAr || mode == XRSessionMode::ImmersiveVr;
+ auto* globalObject = document.domWindow();
+ if (!globalObject) {
+ promise.reject(Exception { InvalidAccessError});
+ return;
+ }
+
+ // 4. Check whether the session request is allowed as follows:
+ if (immersive) {
+ if (!immersiveSessionRequestIsAllowedForGlobalObject(*globalObject, document)) {
+ promise.reject(Exception { SecurityError });
+ return;
+ }
+ if (m_pendingImmersiveSession || m_activeImmersiveSession) {
+ promise.reject(Exception { InvalidStateError });
+ return;
+ }
+ m_pendingImmersiveSession = true;
+ } else if (!inlineSessionRequestIsAllowedForGlobalObject(*globalObject, document, init)) {
+ promise.reject(Exception { SecurityError });
+ return;
+ }
+
+ // 5. Run the following steps in parallel:
+ queueTaskKeepingObjectAlive(*this, TaskSource::WebXR, [this, document = makeWeakPtr(document), immersive, init, mode, promise = WTFMove(promise)] () mutable {
+ // 5.1 Let requiredFeatures be options' requiredFeatures.
+ // 5.2 Let optionalFeatures be options' optionalFeatures.
+ // 5.3 Set device to the result of obtaining the current device for mode, requiredFeatures, and optionalFeatures.
+ auto* device = obtainCurrentDevice(mode, init.requiredFeatures, init.optionalFeatures);
+
+ // 5.4 Queue a task to perform the following steps:
+ queueTaskKeepingObjectAlive(*this, TaskSource::WebXR, [this, document = WTFMove(document), device = makeWeakPtr(device), immersive, init, mode, promise = WTFMove(promise)] () mutable {
+ auto rejectPromiseWithNotSupportedError = makeScopeExit([&] () {
+ promise.reject(Exception { NotSupportedError });
+ m_pendingImmersiveSession = false;
+ });
+
+ // 5.4.1 If device is null or device's list of supported modes does not contain mode, run the following steps:
+ // - Reject promise with a "NotSupportedError" DOMException.
+ // - If immersive is true, set pending immersive session to false.
+ // - Abort these steps.
+ if (!device || !device->supports(mode))
+ return;
+
+ auto* globalObject = document ? document->execState() : nullptr;
+ if (!globalObject)
+ return;
+
+ // WebKit does not currently support the Permissions API. https://w3c.github.io/permissions/
+ // However we do implement here the permission request algorithm without the
+ // Permissions API bits as it handles, among others, the session features parsing. We also
+ // do it here before creating the session as there is no need to do it on advance.
+ // TODO: we just perform basic checks without asking any permission to the user so far. Maybe we should implement
+ // a mechanism similar to what others do involving passing a message to the UI process.
+
+ // 5.4.4 Let descriptor be an XRPermissionDescriptor initialized with session, requiredFeatures, and optionalFeatures
+ // 5.4.5 Let status be an XRPermissionStatus, initially null
+ // 5.4.6 Request the xr permission with descriptor and status.
+ // 5.4.7 If status' state is "denied" run the following steps: (same as above in 5.4.1)
+ if (!isXRPermissionGranted(mode, init, device.get(), *globalObject))
+ return;
+
+ // 5.4.2 Let session be a new XRSession object.
+ // 5.4.3 Initialize the session with session, mode, and device.
+ auto session = WebXRSession::create(*document, *this, mode, *device);
+
+ // 5.4.8 Potentially set the active immersive session as follows:
+ if (immersive) {
+ m_activeImmersiveSession = session.copyRef();
+ m_pendingImmersiveSession = false;
+ } else
+ m_inlineSessions.add(session.copyRef());
+
+ // 5.4.9 Resolve promise with session.
+ promise.resolve(session);
+ rejectPromiseWithNotSupportedError.release();
+
+ // TODO:
+ // 5.4.10 Queue a task to perform the following steps: NOTE: These steps ensure that initial inputsourceschange
+ // events occur after the initial session is resolved.
+ // 1. Set session's promise resolved flag to true.
+ // 2. Let sources be any existing input sources attached to session.
+ // 3. If sources is non-empty, perform the following steps:
+ // 1. Set session's list of active XR input sources to sources.
+ // 2. Fire an XRInputSourcesChangeEvent named inputsourceschange on session with added set to sources.
+
+ });
+ });
+}
+
const char* WebXRSystem::activeDOMObjectName() const
{
return "XRSystem";
@@ -167,33 +434,41 @@
{
}
-void WebXRSystem::registerSimulatedXRDeviceForTesting(const PlatformXR::Device& device)
+void WebXRSystem::registerSimulatedXRDeviceForTesting(PlatformXR::Device& device)
{
if (!RuntimeEnabledFeatures::sharedFeatures().webXREnabled())
return;
- m_testingMode = true;
+ m_testingDevices++;
if (device.supports(PlatformXR::SessionMode::ImmersiveVr) || device.supports(PlatformXR::SessionMode::ImmersiveAr)) {
- m_immersiveDevices.append(makeWeakPtr(device));
- m_activeImmersiveDevice = m_immersiveDevices.last();
+ m_immersiveDevices.add(device);
+ m_activeImmersiveDevice = makeWeakPtr(device);
}
if (device.supports(PlatformXR::SessionMode::Inline))
m_inlineXRDevice = makeWeakPtr(device);
}
-void WebXRSystem::unregisterSimulatedXRDeviceForTesting(PlatformXR::Device* device)
+void WebXRSystem::unregisterSimulatedXRDeviceForTesting(PlatformXR::Device& device)
{
if (!RuntimeEnabledFeatures::sharedFeatures().webXREnabled())
return;
ASSERT(m_immersiveDevices.contains(device));
- m_immersiveDevices.removeFirst(device);
- if (m_activeImmersiveDevice == device)
+ ASSERT(m_testingDevices);
+ m_immersiveDevices.remove(device);
+ if (m_activeImmersiveDevice == &device)
m_activeImmersiveDevice = nullptr;
- if (m_inlineXRDevice == device)
+ if (m_inlineXRDevice == &device)
m_inlineXRDevice = makeWeakPtr(m_defaultInlineDevice);
- m_testingMode = false;
+ m_testingDevices--;
}
+void WebXRSystem::sessionEnded(WebXRSession& session)
+{
+ if (m_activeImmersiveSession == &session)
+ m_activeImmersiveSession = nullptr;
+ m_inlineSessions.remove(session);
+}
+
} // namespace WebCore
#endif // ENABLE(WEBXR)
Modified: trunk/Source/WebCore/Modules/webxr/WebXRSystem.h (261862 => 261863)
--- trunk/Source/WebCore/Modules/webxr/WebXRSystem.h 2020-05-19 16:08:08 UTC (rev 261862)
+++ trunk/Source/WebCore/Modules/webxr/WebXRSystem.h 2020-05-19 16:08:47 UTC (rev 261863)
@@ -33,13 +33,22 @@
#include "JSDOMPromiseDeferred.h"
#include "WebGLContextAttributes.h"
#include "WebGLRenderingContextBase.h"
+#include "XRReferenceSpaceType.h"
#include "XRSessionMode.h"
+#include <wtf/HashSet.h>
#include <wtf/IsoMalloc.h>
+#include <wtf/Optional.h>
#include <wtf/RefCounted.h>
+#include <wtf/WeakHashSet.h>
#include <wtf/WeakPtr.h>
+namespace JSC {
+class JSGlobalObject;
+}
+
namespace WebCore {
+class DOMWindow;
class ScriptExecutionContext;
class WebXRSession;
struct XRSessionInit;
@@ -57,15 +66,17 @@
using RefCounted<WebXRSystem>::deref;
void isSessionSupported(XRSessionMode, IsSessionSupportedPromise&&);
- void requestSession(XRSessionMode, const XRSessionInit&, RequestSessionPromise&&);
+ void requestSession(Document&, XRSessionMode, const XRSessionInit&, RequestSessionPromise&&);
// This is also needed by WebGLRenderingContextBase::makeXRCompatible() and HTMLCanvasElement::createContextWebGL().
void ensureImmersiveXRDeviceIsSelected();
bool hasActiveImmersiveXRDevice() { return !!m_activeImmersiveDevice; }
+ void sessionEnded(WebXRSession&);
+
// For testing purpouses only.
- void registerSimulatedXRDeviceForTesting(const PlatformXR::Device&);
- void unregisterSimulatedXRDeviceForTesting(PlatformXR::Device*);
+ void registerSimulatedXRDeviceForTesting(PlatformXR::Device&);
+ void unregisterSimulatedXRDeviceForTesting(PlatformXR::Device&);
protected:
// EventTarget
@@ -81,23 +92,36 @@
private:
WebXRSystem(ScriptExecutionContext&);
+ using FeaturesArray = PlatformXR::Device::ListOfEnabledFeatures;
+ using JSFeaturesArray = Vector<JSC::JSValue>;
+ PlatformXR::Device* obtainCurrentDevice(XRSessionMode, const JSFeaturesArray& requiredFeatures, const JSFeaturesArray& optionalFeatures);
+
+ bool immersiveSessionRequestIsAllowedForGlobalObject(DOMWindow&, Document&) const;
+ bool inlineSessionRequestIsAllowedForGlobalObject(DOMWindow&, Document&, const XRSessionInit&) const;
+
+ struct ResolvedRequestedFeatures;
+ Optional<ResolvedRequestedFeatures> resolveRequestedFeatures(XRSessionMode, const XRSessionInit&, PlatformXR::Device*, JSC::JSGlobalObject&) const;
+ bool isXRPermissionGranted(XRSessionMode, const XRSessionInit&, PlatformXR::Device*, JSC::JSGlobalObject&) const;
+
// https://immersive-web.github.io/webxr/#default-inline-xr-device
class DummyInlineDevice final : public PlatformXR::Device {
public:
- DummyInlineDevice()
- {
- m_supportedModes.append(XRSessionMode::Inline);
- }
+ DummyInlineDevice();
};
DummyInlineDevice m_defaultInlineDevice;
bool m_immersiveXRDevicesHaveBeenEnumerated { false };
- bool m_testingMode { false };
+ uint m_testingDevices { 0 };
- WeakPtr<WebXRSession> m_activeImmersiveSession;
+ bool m_pendingImmersiveSession { false };
+ RefPtr<WebXRSession> m_activeImmersiveSession;
+ // We use a set here although the specs talk about a list of inline sessions
+ // https://immersive-web.github.io/webxr/#list-of-inline-sessions.
+ HashSet<Ref<WebXRSession>> m_inlineSessions;
+
WeakPtr<PlatformXR::Device> m_activeImmersiveDevice;
- Vector<WeakPtr<PlatformXR::Device>> m_immersiveDevices;
+ WeakHashSet<PlatformXR::Device> m_immersiveDevices;
WeakPtr<PlatformXR::Device> m_inlineXRDevice;
};
Modified: trunk/Source/WebCore/Modules/webxr/WebXRSystem.idl (261862 => 261863)
--- trunk/Source/WebCore/Modules/webxr/WebXRSystem.idl 2020-05-19 16:08:08 UTC (rev 261862)
+++ trunk/Source/WebCore/Modules/webxr/WebXRSystem.idl 2020-05-19 16:08:47 UTC (rev 261863)
@@ -33,7 +33,7 @@
] interface WebXRSystem : EventTarget {
// Methods
Promise<void> isSessionSupported(XRSessionMode mode);
- [NewObject] Promise<WebXRSession> requestSession(XRSessionMode mode, optional XRSessionInit options);
+ [NewObject, CallWith=Document] Promise<WebXRSession> requestSession(XRSessionMode mode, optional XRSessionInit options);
// Events
attribute EventHandler ondevicechange;
Modified: trunk/Source/WebCore/dom/TaskSource.h (261862 => 261863)
--- trunk/Source/WebCore/dom/TaskSource.h 2020-05-19 16:08:08 UTC (rev 261862)
+++ trunk/Source/WebCore/dom/TaskSource.h 2020-05-19 16:08:47 UTC (rev 261863)
@@ -39,6 +39,7 @@
PostedMessageQueue,
UserInteraction,
WebGL,
+ WebXR,
// Internal to WebCore
InternalAsyncTask, // Safe to re-order or delay.
Modified: trunk/Source/WebCore/platform/xr/PlatformXR.h (261862 => 261863)
--- trunk/Source/WebCore/platform/xr/PlatformXR.h 2020-05-19 16:08:08 UTC (rev 261862)
+++ trunk/Source/WebCore/platform/xr/PlatformXR.h 2020-05-19 16:08:47 UTC (rev 261863)
@@ -19,12 +19,13 @@
#pragma once
#include <memory>
+#include <wtf/HashMap.h>
#include <wtf/Vector.h>
#include <wtf/WeakPtr.h>
namespace PlatformXR {
-enum class SessionMode {
+enum class SessionMode : uint8_t {
Inline,
ImmersiveVr,
ImmersiveAr,
@@ -48,18 +49,19 @@
Device();
DeviceId id() const { return m_id; }
- using ListOfSupportedModes = Vector<SessionMode>;
using ListOfEnabledFeatures = Vector<ReferenceSpaceType>;
+ bool supports(SessionMode mode) const { return m_enabledFeaturesMap.contains(mode); }
+ void setEnabledFeatures(SessionMode mode, const ListOfEnabledFeatures& features) { m_enabledFeaturesMap.set(mode, features); }
+ ListOfEnabledFeatures enabledFeatures(SessionMode mode) const { return m_enabledFeaturesMap.get(mode); }
- bool supports(SessionMode mode) const { return m_supportedModes.contains(mode); }
- void setSupportedModes(const ListOfSupportedModes& modes) { m_supportedModes = modes; }
- void setEnabledFeatures(const ListOfEnabledFeatures& features) { m_enabledFeatures = features; }
-
inline bool operator==(const Device& other) const { return m_id == other.m_id; }
protected:
- ListOfSupportedModes m_supportedModes;
- ListOfEnabledFeatures m_enabledFeatures;
+ // https://immersive-web.github.io/webxr/#xr-device-concept
+ // Each XR device has a list of enabled features for each XRSessionMode in its list of supported modes,
+ // which is a list of feature descriptors which MUST be initially an empty list.
+ using EnabledFeaturesPerModeMap = WTF::HashMap<SessionMode, ListOfEnabledFeatures, WTF::IntHash<SessionMode>, WTF::StrongEnumHashTraits<SessionMode>>;
+ EnabledFeaturesPerModeMap m_enabledFeaturesMap;
private:
DeviceId m_id;
Modified: trunk/Source/WebCore/platform/xr/openxr/PlatformXR.cpp (261862 => 261863)
--- trunk/Source/WebCore/platform/xr/openxr/PlatformXR.cpp 2020-05-19 16:08:08 UTC (rev 261862)
+++ trunk/Source/WebCore/platform/xr/openxr/PlatformXR.cpp 2020-05-19 16:08:47 UTC (rev 261863)
@@ -24,6 +24,7 @@
#if USE_OPENXR
#include <openxr/openxr.h>
+#include <wtf/Optional.h>
#include <wtf/text/StringConcatenateNumbers.h>
#include <wtf/text/WTFString.h>
#endif // USE_OPENXR
@@ -67,7 +68,7 @@
~Impl();
#if USE_OPENXR
- void collectSupportedSessionModes(Device&, XrSystemId);
+ Optional<Vector<SessionMode>> collectSupportedSessionModes(Device&, XrSystemId);
XrInstance m_instance { XR_NULL_HANDLE };
#endif // USE_OPENXR
};
@@ -150,13 +151,13 @@
#if USE_OPENXR
-void Instance::Impl::collectSupportedSessionModes(Device& device, XrSystemId systemId)
+Optional<Vector<SessionMode>> Instance::Impl::collectSupportedSessionModes(Device& device, XrSystemId systemId)
{
uint32_t viewConfigurationCount;
XrResult result = xrEnumerateViewConfigurations(m_instance, systemId, 0, &viewConfigurationCount, nullptr);
if (result != XR_SUCCESS) {
WTFLogAlways("xrEnumerateViewConfigurations(): error %s\n", resultToString(result, m_instance).utf8().data());
- return;
+ return WTF::nullopt;
}
XrViewConfigurationType viewConfigurations[viewConfigurationCount];
@@ -164,16 +165,16 @@
if (result != XR_SUCCESS) {
WTFLogAlways("xrEnumerateViewConfigurations(): error %s\n", resultToString(result, m_instance).utf8().data());
WTFLogAlways("xrEnumerateViewConfigurations(): error %s\n", resultToString(result, m_instance).utf8().data());
- return;
+ return WTF::nullopt;
}
- Device::ListOfSupportedModes supportedModes;
+ Vector<SessionMode> supportedModes;
for (uint32_t i = 0; i < viewConfigurationCount; ++i) {
auto viewConfigurationProperties = createStructure<XrViewConfigurationProperties, XR_TYPE_VIEW_CONFIGURATION_PROPERTIES>();
result = xrGetViewConfigurationProperties(m_instance, systemId, viewConfigurations[i], &viewConfigurationProperties);
if (result != XR_SUCCESS) {
WTFLogAlways("xrGetViewConfigurationProperties(): error %s\n", resultToString(result, m_instance).utf8().data());
- return;
+ return WTF::nullopt;
}
if (viewConfigurationProperties.viewConfigurationType == XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO)
supportedModes.append(SessionMode::ImmersiveAr);
@@ -180,7 +181,7 @@
else if (viewConfigurationProperties.viewConfigurationType == XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO)
supportedModes.append(SessionMode::ImmersiveVr);
}
- device.setSupportedModes(supportedModes);
+ return supportedModes;
}
#endif // USE_OPENXR
@@ -218,7 +219,14 @@
}
auto device = makeUnique<Device>();
- m_impl->collectSupportedSessionModes(*device, systemId);
+ auto sessionModes = m_impl->collectSupportedSessionModes(*device, systemId);
+ if (sessionModes) {
+ for (auto& mode : sessionModes.value()) {
+ // TODO: fill in features
+ device->setEnabledFeatures(mode, { });
+ }
+ }
+
m_immersiveXRDevices.append(WTFMove(device));
#endif // USE_OPENXR
}
Modified: trunk/Source/WebCore/testing/WebXRTest.cpp (261862 => 261863)
--- trunk/Source/WebCore/testing/WebXRTest.cpp 2020-05-19 16:08:08 UTC (rev 261862)
+++ trunk/Source/WebCore/testing/WebXRTest.cpp 2020-05-19 16:08:47 UTC (rev 261863)
@@ -54,13 +54,14 @@
simulatedDevice.views().append(view.releaseReturnValue());
}
+ Vector<XRReferenceSpaceType> features;
if (init.supportedFeatures) {
- Vector<XRReferenceSpaceType> features;
- for (auto& feature : init.supportedFeatures.value()) {
- if (auto referenceSpaceType = parseEnumeration<XRReferenceSpaceType>(*context.execState(), feature))
- features.append(referenceSpaceType.value());
+ if (auto* globalObject = context.execState()) {
+ for (auto& feature : init.supportedFeatures.value()) {
+ if (auto referenceSpaceType = parseEnumeration<XRReferenceSpaceType>(*globalObject, feature))
+ features.append(referenceSpaceType.value());
+ }
}
- simulatedDevice.setEnabledFeatures(features);
}
if (init.boundsCoordinates) {
@@ -87,8 +88,10 @@
if (init.supportsImmersive)
supportedModes.append(XRSessionMode::ImmersiveVr);
}
- simulatedDevice.setSupportedModes(supportedModes);
+ for (auto& mode : supportedModes)
+ simulatedDevice.setEnabledFeatures(mode, features);
+
m_context->registerSimulatedXRDeviceForTesting(simulatedDevice);
promise.resolve(device.get());
@@ -107,7 +110,7 @@
void WebXRTest::disconnectAllDevices(DOMPromiseDeferred<void>&& promise)
{
for (auto& device : m_devices)
- m_context->unregisterSimulatedXRDeviceForTesting(&device->simulatedXRDevice());
+ m_context->unregisterSimulatedXRDeviceForTesting(device->simulatedXRDevice());
promise.resolve();
}