Source/WebCore/ChangeLog

 12020-05-14 Sergio Villar Senin <svillar@igalia.com>
 2
 3 [WebXR] Implement requestSession()
 4 https://bugs.webkit.org/show_bug.cgi?id=211888
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 This patch adds a preliminar implementation of the requestSession()
 9 API used to get a WebXRSession from the UA. It includes a fairly good
 10 amount of checks to verify that the request can be satisfied given the
 11 device's enabled features per session modes. The specs also describe how
 12 to request persmission for some actions using the Permissions API which
 13 WebKit does not currently implement. That should be done in a follow up
 14 patch perhaps using a similar approach to other APIs as Geolocation for
 15 example.
 16
 17 In order to get some of the requestSession() tests passing the session
 18 finalization (shutdown) had to be implemented too.
 19
 20 Several tests where unskipped for WPE port as they're now passing.
 21
 22 * Modules/webxr/WebXRRenderState.cpp:
 23 (WebCore::WebXRRenderState::create): Pass XRSessionMode as argument
 24 instead of a WebXRSession.
 25 * Modules/webxr/WebXRRenderState.h: Ditto.
 26 * Modules/webxr/WebXRSession.cpp:
 27 (WebCore::WebXRSession::create): Added.
 28 (WebCore::WebXRSession::WebXRSession): Added.
 29 (WebCore::WebXRSession::renderState const):
 30 (WebCore::WebXRSession::inputSources const):
 31 (WebCore::WebXRSession::shutdown): Shutdown process called on session end.
 32 (WebCore::WebXRSession::end): Implemented session ending.
 33 * Modules/webxr/WebXRSession.h: Added create() and private constructor. Fixed some naming.
 34 * Modules/webxr/WebXRSystem.cpp:
 35 (WebCore::WebXRSystem::DummyInlineDevice::DummyInlineDevice): Contructor for the
 36 dummy inline device.
 37 (WebCore::WebXRSystem::ensureImmersiveXRDeviceIsSelected): Use a counter instead of a boolean
 38 to track testing devices as there might be more than 1.
 39 (WebCore::WebXRSystem::obtainCurrentDevice): Implemented from specs text.
 40 (WebCore::WebXRSystem::immersiveSessionRequestIsAllowedForGlobalObject const): Ditto.
 41 (WebCore::WebXRSystem::inlineSessionRequestIsAllowedForGlobalObject const): Ditto.
 42 (WebCore::WebXRSystem::resolveRequestedFeatures const): Ditto.
 43 (WebCore::WebXRSystem::isXRPermissionGranted const): Ditto.
 44 (WebCore::WebXRSystem::requestSession): Ditto.
 45 (WebCore::WebXRSystem::registerSimulatedXRDeviceForTesting): Use a counter instead of a bool.
 46 (WebCore::WebXRSystem::unregisterSimulatedXRDeviceForTesting): Ditto.
 47 (WebCore::WebXRSystem::sessionEnded): Added, used by sessions to notify the XRSystem.
 48 * Modules/webxr/WebXRSystem.h:
 49 * Modules/webxr/WebXRSystem.idl: Call requestSession with Document.
 50 * dom/TaskSource.h: Added a WebXR task source.
 51 * platform/xr/PlatformXR.h: Specs state that devices have a list of enabled features per session
 52 mode so store them in a hashmap instead of in a Vector.
 53 (PlatformXR::Device::supports const): Use the new Hashmap of session modes.
 54 (PlatformXR::Device::setEnabledFeatures): Ditto.
 55 (PlatformXR::Device::enabledFeatures const): Ditto.
 56 (PlatformXR::Device::setSupportedModes): Deleted.
 57 * platform/xr/openxr/PlatformXR.cpp:
 58 (PlatformXR::Instance::Impl::collectSupportedSessionModes): Return session modes if any.
 59 (PlatformXR::Instance::enumerateImmersiveXRDevices): Fill in features per session mode.
 60 * testing/WebXRTest.cpp:
 61 (WebCore::WebXRTest::simulateDeviceConnection): Fill in features per session mode.
 62
1632020-05-14 Sergio Villar Senin <svillar@igalia.com>
264
365 Unreviewed build fix.

Source/WebCore/Modules/webxr/WebXRInputSourceArray.h

@@class WebXRInputSourceArray : public RefCounted<WebXRInputSourceArray> {
3939public:
4040 unsigned length() const;
4141 WebXRInputSource* item(unsigned) const;
 42
 43private:
 44 WebXRInputSourceArray();
4245};
4346
4447} // namespace WebCore

Source/WebCore/Modules/webxr/WebXRRenderState.cpp

@@namespace WebCore {
3737
3838WTF_MAKE_ISO_ALLOCATED_IMPL(WebXRRenderState);
3939
40 Ref<WebXRRenderState> WebXRRenderState::create(const WebXRSession& session)
 40Ref<WebXRRenderState> WebXRRenderState::create(XRSessionMode mode)
4141{
42  // When an XRRenderState object is created for an XRSession session, the user agent MUST initialize the render state by running the following steps:
43  // 1. Let state be the newly created XRRenderState object.
44 
45  // 2. Initialize state’s depthNear to 0.1.
46  // 3. Initialize state’s depthFar to 1000.0.
47  // (Default-initialized in the XRRenderState class definition.)
48 
49  // 4. If session is an immersive session, initialize state’s inlineVerticalFieldOfView to null.
50  // 5. Else initialize state’s inlineVerticalFieldOfView to PI * 0.5.
51  // FIXME: "immersive session" support
52  UNUSED_PARAM(session);
53  Optional<double> inlineVerticalFieldOfView { piOverTwoDouble };
54 
55  // 6. Initialize state’s baseLayer to null.
56  // 7. Initialize state’s outputContext to null.
57  // (Initialized to null by default.)
58 
59  return adoptRef(*new WebXRRenderState(WTFMove(inlineVerticalFieldOfView)));
 42 // https://immersive-web.github.io/webxr/#initialize-the-render-state
 43 // depthNear, depthFar and baseLayer are initialized in the class definition
 44 return adoptRef(*new WebXRRenderState(mode == XRSessionMode::Inline ? makeOptional(piOverTwoDouble) : WTF::nullopt));
6045}
6146
6247WebXRRenderState::WebXRRenderState(Optional<double>&& inlineVerticalFieldOfView)

Source/WebCore/Modules/webxr/WebXRRenderState.h

2727
2828#if ENABLE(WEBXR)
2929
 30#include "XRSessionMode.h"
3031#include <wtf/IsoMalloc.h>
3132#include <wtf/Optional.h>
3233#include <wtf/Ref.h>

@@namespace WebCore {
3738
3839class WebXRWebGLLayer;
3940struct XRRenderStateInit;
40 class WebXRSession;
4141
4242class WebXRRenderState : public RefCounted<WebXRRenderState> {
4343 WTF_MAKE_ISO_ALLOCATED(WebXRRenderState);
4444public:
45  static Ref<WebXRRenderState> create(const WebXRSession&);
 45 static Ref<WebXRRenderState> create(XRSessionMode);
4646 ~WebXRRenderState();
4747
4848 double depthNear() const;

@@public:
5151 RefPtr<WebXRWebGLLayer> baseLayer() const;
5252
5353private:
54  WebXRRenderState(Optional<double>&&);
55  WebXRRenderState(const XRRenderStateInit&);
 54 explicit WebXRRenderState(Optional<double>&& fieldOfView);
 55 explicit WebXRRenderState(const XRRenderStateInit&);
5656
 57 // https://immersive-web.github.io/webxr/#initialize-the-render-state
5758 struct {
58  double near { 0.1 };
59  double far { 1000 };
 59 double near { 0.1 }; // in meters
 60 double far { 1000 }; // in meters
6061 } m_depth;
61  Optional<double> m_inlineVerticalFieldOfView;
 62 Optional<double> m_inlineVerticalFieldOfView; // in radians
6263 RefPtr<WebXRWebGLLayer> m_baseLayer;
6364};
6465

Source/WebCore/Modules/webxr/WebXRSession.cpp

2828
2929#if ENABLE(WEBXR)
3030
 31#include "WebXRSystem.h"
3132#include <wtf/IsoMallocInlines.h>
3233
3334namespace WebCore {
3435
3536WTF_MAKE_ISO_ALLOCATED_IMPL(WebXRSession);
3637
 38Ref<WebXRSession> WebXRSession::create(Document& document, Ref<WebXRSystem>&& system, XRSessionMode mode, WeakPtr<PlatformXR::Device>&& device)
 39{
 40 return adoptRef(*new WebXRSession(document, WTFMove(system), mode, WTFMove(device)));
 41}
 42
 43WebXRSession::WebXRSession(Document& document, Ref<WebXRSystem>&& system, XRSessionMode mode, WeakPtr<PlatformXR::Device>&& device)
 44 : ActiveDOMObject(&document)
 45 , m_xrSystem(WTFMove(system))
 46 , m_mode(mode)
 47 , m_device(WTFMove(device))
 48 , m_activeRenderState(WebXRRenderState::create(mode))
 49{
 50 // TODO: If no other features of the user agent have done so already,
 51 // perform the necessary platform-specific steps to initialize the device’s
 52 // tracking and rendering capabilities, including showing any necessary
 53 // instructions to the user.
 54}
 55
3756WebXRSession::~WebXRSession() = default;
3857
3958XREnvironmentBlendMode WebXRSession::environmentBlendMode() const

@@XRVisibilityState WebXRSession::visibilityState() const
4867
4968const WebXRRenderState& WebXRSession::renderState() const
5069{
51  return *m_renderState;
 70 return *m_activeRenderState;
5271}
5372
5473const WebXRInputSourceArray& WebXRSession::inputSources() const

@@void WebXRSession::cancelAnimationFrame(int)
7392{
7493}
7594
76 void WebXRSession::end(EndPromise&&)
 95// https://immersive-web.github.io/webxr/#shut-down-the-session
 96void WebXRSession::shutdown()
 97{
 98 // 1. Let session be the target XRSession object.
 99 // 2. Set session's ended value to true.
 100 m_ended = true;
 101
 102 // 3. If the active immersive session is equal to session, set the active immersive session to null.
 103 // 4. Remove session from the list of inline sessions.
 104 m_xrSystem->sessionEnded(this);
 105
 106 // TODO: complete the implementation
 107 // 5. Reject any outstanding promises returned by session with an InvalidStateError, except for any promises returned by end().
 108 // 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:
 109 // 6.1. Releasing exclusive access to the XR device if session is an immersive session.
 110 // 6.2. Deallocating any graphics resources acquired by session for presentation to the XR device.
 111 // 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.
 112 // 7. Queue a task that fires an XRSessionEvent named end on session.
 113}
 114
 115// https://immersive-web.github.io/webxr/#dom-xrsession-end
 116void WebXRSession::end(EndPromise&& promise)
77117{
 118 // 1. Let promise be a new Promise.
 119 // 2. Shut down the target XRSession object.
 120 shutdown();
 121
 122 // 3. Queue a task to perform the following steps:
 123 queueTaskKeepingObjectAlive(*this, TaskSource::WebXR, [promise = WTFMove(promise)] () mutable {
 124 // 3.1 Wait until any platform-specific steps related to shutting down the session have completed.
 125 // 3.2 Resolve promise.
 126 promise.resolve();
 127 });
 128
 129 // 4. Return promise.
78130}
79131
80132const char* WebXRSession::activeDOMObjectName() const

Source/WebCore/Modules/webxr/WebXRSession.h

3535#include "WebXRSpace.h"
3636#include "XREnvironmentBlendMode.h"
3737#include "XRReferenceSpaceType.h"
 38#include "XRSessionMode.h"
3839#include "XRVisibilityState.h"
3940#include <wtf/Ref.h>
4041#include <wtf/RefCounted.h>

@@namespace WebCore {
4546
4647class XRFrameRequestCallback;
4748class WebXRReferenceSpace;
 49class WebXRSystem;
4850struct XRRenderStateInit;
4951
5052class WebXRSession final : public RefCounted<WebXRSession>, public EventTargetWithInlineData, public ActiveDOMObject {

@@public:
5355 using RequestReferenceSpacePromise = DOMPromiseDeferred<IDLInterface<WebXRReferenceSpace>>;
5456 using EndPromise = DOMPromiseDeferred<void>;
5557
 58 static Ref<WebXRSession> create(Document&, Ref<WebXRSystem>&&, XRSessionMode, WeakPtr<PlatformXR::Device>&&);
5659 virtual ~WebXRSession();
5760
5861 using RefCounted<WebXRSession>::ref;

@@public:
7477 bool ended() const { return m_ended; }
7578
7679private:
 80 WebXRSession(Document&, Ref<WebXRSystem>&&, XRSessionMode, WeakPtr<PlatformXR::Device>&&);
 81
7782 // EventTarget
7883 EventTargetInterface eventTargetInterface() const override { return WebXRSessionEventTargetInterfaceType; }
7984 ScriptExecutionContext* scriptExecutionContext() const override { return ActiveDOMObject::scriptExecutionContext(); }

@@private:
8489 const char* activeDOMObjectName() const override;
8590 void stop() override;
8691
 92 void shutdown();
 93
8794 XREnvironmentBlendMode m_environmentBlendMode;
8895 XRVisibilityState m_visibilityState;
89  RefPtr<WebXRRenderState> m_renderState;
9096 RefPtr<WebXRInputSourceArray> m_inputSources;
9197 bool m_ended { false };
 98
 99 Ref<WebXRSystem> m_xrSystem;
 100 XRSessionMode m_mode;
 101 WeakPtr<PlatformXR::Device> m_device;
 102 RefPtr<WebXRRenderState> m_activeRenderState;
 103 RefPtr<WebXRRenderState> m_pendingRenderState;
92104};
93105
94106} // namespace WebCore

Source/WebCore/Modules/webxr/WebXRSystem.cpp

2828
2929#if ENABLE(WEBXR)
3030
 31#include "DOMWindow.h"
3132#include "Document.h"
3233#include "FeaturePolicy.h"
 34#include "IDLTypes.h"
 35#include "JSWebXRSession.h"
 36#include "JSXRReferenceSpaceType.h"
3337#include "PlatformXR.h"
3438#include "RuntimeEnabledFeatures.h"
 39#include "SecurityOrigin.h"
 40#include "UserGestureIndicator.h"
3541#include "WebXRSession.h"
 42#include "XRReferenceSpaceType.h"
 43#include "XRSessionInit.h"
 44#include <JavaScriptCore/JSGlobalObject.h>
3645#include <wtf/IsoMallocInlines.h>
 46#include <wtf/Scope.h>
3747
3848namespace WebCore {
3949
4050WTF_MAKE_ISO_ALLOCATED_IMPL(WebXRSystem);
4151
 52WebXRSystem::DummyInlineDevice::DummyInlineDevice()
 53{
 54 setEnabledFeatures(XRSessionMode::Inline, { XRReferenceSpaceType::Viewer });
 55}
 56
4257Ref<WebXRSystem> WebXRSystem::create(ScriptExecutionContext& scriptExecutionContext)
4358{
4459 return adoptRef(*new WebXRSystem(scriptExecutionContext));

@@WebXRSystem::~WebXRSystem() = default;
5671void WebXRSystem::ensureImmersiveXRDeviceIsSelected()
5772{
5873 // Don't ask platform code for XR devices, we're using simulated ones.
59  // TODO: should be have a MockPlatformXR implementation instead ?
60  if (UNLIKELY(m_testingMode))
 74 if (UNLIKELY(m_testingDevices))
6175 return;
6276
6377 if (m_activeImmersiveDevice)

@@void WebXRSystem::ensureImmersiveXRDeviceIsSelected()
96110 // TODO: 9. Queue a task to fire an event named devicechange on the context object.
97111}
98112
 113
 114PlatformXR::Device* WebXRSystem::obtainCurrentDevice(XRSessionMode mode, const JSFeaturesArray& requiredFeatures, const JSFeaturesArray& optionalFeatures)
 115{
 116 if (mode == XRSessionMode::ImmersiveAr || mode == XRSessionMode::ImmersiveVr) {
 117 ensureImmersiveXRDeviceIsSelected();
 118 return m_activeImmersiveDevice.get();
 119 }
 120 if (!requiredFeatures.isEmpty() || !optionalFeatures.isEmpty())
 121 return m_inlineXRDevice.get();
 122
 123 return &m_defaultInlineDevice;
 124}
 125
 126
99127// https://immersive-web.github.io/webxr/#dom-xrsystem-issessionsupported
100128void WebXRSystem::isSessionSupported(XRSessionMode mode, IsSessionSupportedPromise&& promise)
101129{

@@void WebXRSystem::isSessionSupported(XRSessionMode mode, IsSessionSupportedPromi
106134 return;
107135 }
108136
109  // 3. If the requesting documents origin is not allowed to use the "xr-spatial-tracking" feature policy,
 137 // 3. If the requesting document's origin is not allowed to use the "xr-spatial-tracking" feature policy,
110138 // reject promise with a "SecurityError" DOMException and return it.
111139 auto document = downcast<Document>(scriptExecutionContext());
112140 if (!isFeaturePolicyAllowedByDocumentAndAllOwners(FeaturePolicy::Type::XRSpatialTracking, *document, LogFeaturePolicyFailure::Yes)) {

@@void WebXRSystem::isSessionSupported(XRSessionMode mode, IsSessionSupportedPromi
136164 });
137165}
138166
139 void WebXRSystem::requestSession(XRSessionMode, const XRSessionInit&, RequestSessionPromise&&)
 167// https://immersive-web.github.io/webxr/#immersive-session-request-is-allowed
 168bool WebXRSystem::immersiveSessionRequestIsAllowedForGlobalObject(DOMWindow& globalObject, Document& document) const
 169{
 170 // 1. If the request was not made while the global object has transient
 171 // activation or when launching a web application, return false
 172 // TODO: add a check for "not launching a web application".
 173 if (!globalObject.hasTransientActivation())
 174 return false;
 175
 176 // 2. If the requesting document is not considered trustworthy, return false.
 177 // https://immersive-web.github.io/webxr/#trustworthy.
 178 if (&document != globalObject.document())
 179 return false;
 180
 181 // https://immersive-web.github.io/webxr/#active-and-focused
 182 if (!document.hasFocus() || !document.securityOrigin().isSameOriginAs(globalObject.document()->securityOrigin()))
 183 return false;
 184
 185 // 3. If user intent to begin an immersive session is not well understood,
 186 // either via explicit consent or implicit consent, return false
 187 if (!UserGestureIndicator::processingUserGesture())
 188 return false;
 189
 190 return true;
 191}
 192
 193// https://immersive-web.github.io/webxr/#inline-session-request-is-allowed
 194bool WebXRSystem::inlineSessionRequestIsAllowedForGlobalObject(DOMWindow& globalObject, Document& document, const XRSessionInit& init) const
 195{
 196 // 1. If the session request contained any required features or optional features and the request was not made
 197 // while the global object has transient activation or when launching a web application, return false.
 198 bool sessionRequestContainedAnyFeature = !init.optionalFeatures.isEmpty() || !init.requiredFeatures.isEmpty();
 199 if (sessionRequestContainedAnyFeature && !globalObject.hasTransientActivation() /* TODO: || !launching a web app */)
 200 return false;
 201
 202 // 2. If the requesting document is not responsible, return false.
 203 if (&document != globalObject.document())
 204 return false;
 205
 206 return true;
 207}
 208
 209
 210struct WebXRSystem::ResolvedRequestedFeatures {
 211 FeaturesArray granted;
 212 FeaturesArray consentRequired;
 213 FeaturesArray consentOptional;
 214};
 215
 216#define RETURN_FALSE_OR_CONTINUE(mustReturn) { \
 217 if (mustReturn) {\
 218 return false; \
 219 } \
 220 continue; \
 221}
 222
 223// https://immersive-web.github.io/webxr/#resolve-the-requested-features
 224Optional<WebXRSystem::ResolvedRequestedFeatures> WebXRSystem::resolveRequestedFeatures(XRSessionMode mode, const XRSessionInit& init, PlatformXR::Device* device, JSC::JSGlobalObject& globalObject) const
140225{
141  PlatformXR::Instance::singleton();
 226 // 1. Let consentRequired be an empty list of DOMString.
 227 // 2. Let consentOptional be an empty list of DOMString.
 228 ResolvedRequestedFeatures resolvedFeatures;
 229
 230 // 3. Let device be the result of obtaining the current device for mode, requiredFeatures, and optionalFeatures.
 231 // 4. Let granted be a list of DOMString initialized to device's list of enabled features for mode.
 232 if (device)
 233 resolvedFeatures.granted = device->enabledFeatures(mode);
 234
 235 // 5. If device is null or device's list of supported modes does not contain mode, run the following steps:
 236 // 5.1 Return the tuple (consentRequired, consentOptional, granted)
 237 if (!device || !device->supports(mode))
 238 return resolvedFeatures;
 239
 240 // 6. Add every feature descriptor in the default features table associated
 241 // with mode to the indicated feature list if it is not already present.
 242 // https://immersive-web.github.io/webxr/#default-features
 243 auto requiredFeaturesWithDefaultFeatures = init.requiredFeatures;
 244 requiredFeaturesWithDefaultFeatures.append(convertEnumerationToJS(globalObject, XRReferenceSpaceType::Viewer));
 245 if (mode == XRSessionMode::ImmersiveAr || mode == XRSessionMode::ImmersiveVr)
 246 requiredFeaturesWithDefaultFeatures.append(convertEnumerationToJS(globalObject, XRReferenceSpaceType::Local));
 247
 248 // 7. For each feature in requiredFeatures|optionalFeatures perform the following steps:
 249 // 8. For each feature in optionalFeatures perform the following steps:
 250 // We're merging both loops in a single lambda. The only difference is that a failure on any required features
 251 // implies cancelling the whole process while failures in optional features are just skipped.
 252 enum class ParsingMode { Strict, Loose };
 253 auto parseFeatures = [&device, &globalObject, mode, &resolvedFeatures] (const JSFeaturesArray& sessionFeatures, ParsingMode parsingMode) -> bool {
 254 bool returnOnFailure = parsingMode == ParsingMode::Strict;
 255 for (const auto& sessionFeature : sessionFeatures) {
 256 // 1. If the feature is null, continue to the next entry.
 257 if (sessionFeature.isNull())
 258 continue;
 259
 260 // 2. If feature is not a valid feature descriptor, perform the following steps
 261 // 2.1. Let s be the result of calling ? ToString(feature).
 262 // 2.2. If s is not a valid feature descriptor or is undefined, (return null|continue to next entry).
 263 // 2.3. Set feature to s.
 264 auto feature = parseEnumeration<XRReferenceSpaceType>(globalObject, sessionFeature);
 265 if (!feature)
 266 RETURN_FALSE_OR_CONTINUE(returnOnFailure);
 267
 268 // 3. If feature is already in granted, continue to the next entry.
 269 if (resolvedFeatures.granted.contains(feature.value()))
 270 continue;
 271
 272 // 4. If the requesting document's origin is not allowed to use any feature policy required by feature
 273 // as indicated by the feature requirements table, (return null|continue to next entry).
 274
 275 // 5. If session's XR device is not capable of supporting the functionality described by feature or the
 276 // user agent has otherwise determined to reject the feature, (return null|continue to next entry).
 277 if (!device->enabledFeatures(mode).contains(feature.value()))
 278 RETURN_FALSE_OR_CONTINUE(returnOnFailure);
 279
 280 // 6. If the functionality described by feature requires explicit consent, append it to (consentRequired|consentOptional).
 281 // 7. Else append feature to granted.
 282 resolvedFeatures.granted.append(feature.value());
 283 }
 284 return true;
 285 };
 286
 287 if (!parseFeatures(requiredFeaturesWithDefaultFeatures, ParsingMode::Strict))
 288 return WTF::nullopt;
142289
143  // When the requestSession(mode) method is invoked, the user agent MUST return a new Promise promise and run the following steps in parallel:
144  // 1. Let immersive be true if mode is "immersive-vr" or "immersive-ar", and false otherwise.
145  // 2. If immersive is true:
146  // 1. If pending immersive session is true or active immersive session is not null, reject promise with an "InvalidStateError" DOMException and abort these steps.
147  // 2. Else set pending immersive session to be true.
148  // 3. Ensure an XR device is selected.
149  // 4. If the XR device is null, reject promise with null.
150  // 5. Else if the XR device's list of supported modes does not contain mode, reject promise with a "NotSupportedError" DOMException.
151  // 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.
152  // 7. If promise was rejected and immersive is true, set pending immersive session to false.
153  // 8. If promise was rejected, abort these steps.
154  // 9. Let session be a new XRSession object.
155  // 10. Initialize the session with session and mode.
156  // 11. If immersive is true, set the active immersive session to session, and set pending immersive session to false.
157  // 12. Else append session to the list of inline sessions.
158  // 13. Resolve promise with session.
 290 parseFeatures(init.optionalFeatures, ParsingMode::Loose);
 291 return resolvedFeatures;
 292}
 293
 294// https://immersive-web.github.io/webxr/#request-the-xr-permission
 295bool WebXRSystem::isXRPermissionGranted(XRSessionMode mode, const XRSessionInit& init, PlatformXR::Device* device, JSC::JSGlobalObject& globalObject) const
 296{
 297 // 1. Set status's granted to an empty FrozenArray.
 298 // 2. Let requiredFeatures be descriptor's requiredFeatures.
 299 // 3. Let optionalFeatures be descriptor's optionalFeatures.
 300 // 4. Let device be the result of obtaining the current device for mode, requiredFeatures, and optionalFeatures.
 301
 302 // 5. Let result be the result of resolving the requested features given requiredFeatures,optionalFeatures, and mode.
 303 auto resolvedFeatures = resolveRequestedFeatures(mode, init, device, globalObject);
 304
 305 // 6. If result is null, run the following steps:
 306 // 6.1. Set status's state to "denied".
 307 // 6.2. Abort these steps.
 308 if (!resolvedFeatures)
 309 return false;
 310
 311 // 7. Let (consentRequired, consentOptional, granted) be the fields of result.
 312 // 8. The user agent MAY at this point ask the user's permission for the calling algorithm to use any of the features
 313 // in consentRequired and consentOptional. The results of these prompts should be included when determining if there
 314 // is a clear signal of user intent for enabling these features.
 315 // 9. For each feature in consentRequired perform the following steps:
 316 // 9.1. The user agent MAY at this point ask the user's permission for the calling algorithm to use feature. The results
 317 // of these prompts should be included when determining if there is a clear signal of user intent to enable feature.
 318 // 9.2. If a clear signal of user intent to enable feature has not been determined, set status's state to "denied" and
 319 // abort these steps.
 320 // 9.3. If feature is not in granted, append feature to granted.
 321 // 10. For each feature in consentOptional perform the following steps:
 322 // 10.1. The user agent MAY at this point ask the user's permission for the calling algorithm to use feature. The results
 323 // of these prompts should be included when determining if there is a clear signal of user intent to enable feature.
 324 // 10.2. If a clear signal of user intent to enable feature has not been determined, continue to the next entry.
 325 // 10.3. If feature is not in granted, append feature to granted.
 326 // 11. Set status's granted to granted.
 327 // 12. Set device's list of enabled features for mode to granted.
 328 // 13. Set status's state to "granted".
 329 return true;
 330}
 331
 332
 333// https://immersive-web.github.io/webxr/#dom-xrsystem-requestsession
 334void WebXRSystem::requestSession(Document& document, XRSessionMode mode, const XRSessionInit& init, RequestSessionPromise&& promise)
 335{
 336 // 1. Let promise be a new Promise.
 337 // 2. Let immersive be true if mode is an immersive session mode, and false otherwise.
 338 // 3. Let global object be the relevant Global object for the XRSystem on which this method was invoked.
 339 bool immersive = mode == XRSessionMode::ImmersiveAr || mode == XRSessionMode::ImmersiveVr;
 340 auto* globalObject = document.domWindow();
 341 if (!globalObject) {
 342 promise.reject(Exception { InvalidAccessError});
 343 return;
 344 }
 345
 346 // 4. Check whether the session request is allowed as follows:
 347 if (immersive) {
 348 if (!immersiveSessionRequestIsAllowedForGlobalObject(*globalObject, document)) {
 349 promise.reject(Exception { SecurityError });
 350 return;
 351 }
 352 if (m_pendingImmersiveSession || m_activeImmersiveSession) {
 353 promise.reject(Exception { InvalidStateError });
 354 return;
 355 }
 356 m_pendingImmersiveSession = true;
 357 } else {
 358 if (!inlineSessionRequestIsAllowedForGlobalObject(*globalObject, document, init)) {
 359 promise.reject(Exception { SecurityError });
 360 return;
 361 }
 362 }
 363
 364 // 5. Run the following steps in parallel:
 365 queueTaskKeepingObjectAlive(*this, TaskSource::WebXR, [this, document = makeRef(document), immersive, init, mode, promise = WTFMove(promise)] () mutable {
 366 // 5.1 Let requiredFeatures be options' requiredFeatures.
 367 // 5.2 Let optionalFeatures be options' optionalFeatures.
 368 // 5.3 Set device to the result of obtaining the current device for mode, requiredFeatures, and optionalFeatures.
 369 auto* device = obtainCurrentDevice(mode, init.requiredFeatures, init.optionalFeatures);
 370
 371 // 5.4 Queue a task to perform the following steps:
 372 queueTaskKeepingObjectAlive(*this, TaskSource::WebXR, [this, &document, device = makeWeakPtr(device), immersive, init, mode, promise = WTFMove(promise)] () mutable {
 373 auto rejectPromiseWithNotSupportedError = makeScopeExit([&] () {
 374 promise.reject(Exception { NotSupportedError });
 375 m_pendingImmersiveSession = false;
 376 });
 377
 378 // 5.4.1 If device is null or device's list of supported modes does not contain mode, run the following steps:
 379 // - Reject promise with a "NotSupportedError" DOMException.
 380 // - If immersive is true, set pending immersive session to false.
 381 // - Abort these steps.
 382 if (!device || !device->supports(mode))
 383 return;
 384
 385 auto* globalObject = document->execState();
 386 if (!globalObject)
 387 return;
 388
 389 // WebKit does not currently support the Permissions API. https://w3c.github.io/permissions/
 390 // However we do implement here the permission request algorithm without the
 391 // Permissions API bits as it handles, among others, the session features parsing. We also
 392 // do it here before creating the session as there is no need to do it on advance.
 393 // TODO: we just perform basic checks without asking any permission to the user so far. Maybe we should implement
 394 // a mechanism similar to what others do involving passing a message to the UI process.
 395
 396 // 5.4.4 Let descriptor be an XRPermissionDescriptor initialized with session, requiredFeatures, and optionalFeatures
 397 // 5.4.5 Let status be an XRPermissionStatus, initially null
 398 // 5.4.6 Request the xr permission with descriptor and status.
 399 // 5.4.7 If status' state is "denied" run the following steps: (same as above in 5.4.1)
 400 if (!isXRPermissionGranted(mode, init, device.get(), *globalObject))
 401 return;
 402
 403 // 5.4.2 Let session be a new XRSession object.
 404 // 5.4.3 Initialize the session with session, mode, and device.
 405 auto session = WebXRSession::create(document.get(), *this, mode, WTFMove(device));
 406
 407 // 5.4.8 Potentially set the active immersive session as follows:
 408 if (immersive) {
 409 m_activeImmersiveSession = session.copyRef();
 410 m_pendingImmersiveSession = false;
 411 } else
 412 m_listOfInlineSessions.append(session.copyRef());
 413
 414 // 5.4.9 Resolve promise with session.
 415 promise.resolve(session);
 416 rejectPromiseWithNotSupportedError.release();
 417
 418 // TODO:
 419 // 5.4.10 Queue a task to perform the following steps: NOTE: These steps ensure that initial inputsourceschange
 420 // events occur after the initial session is resolved.
 421 // 1. Set session's promise resolved flag to true.
 422 // 2. Let sources be any existing input sources attached to session.
 423 // 3. If sources is non-empty, perform the following steps:
 424 // 1. Set session's list of active XR input sources to sources.
 425 // 2. Fire an XRInputSourcesChangeEvent named inputsourceschange on session with added set to sources.
 426
 427 });
 428 });
159429}
160430
161431const char* WebXRSystem::activeDOMObjectName() const

@@void WebXRSystem::registerSimulatedXRDeviceForTesting(const PlatformXR::Device&
171441{
172442 if (!RuntimeEnabledFeatures::sharedFeatures().webXREnabled())
173443 return;
174  m_testingMode = true;
 444 m_testingDevices++;
175445 if (device.supports(PlatformXR::SessionMode::ImmersiveVr) || device.supports(PlatformXR::SessionMode::ImmersiveAr)) {
176446 m_immersiveDevices.append(makeWeakPtr(device));
177447 m_activeImmersiveDevice = m_immersiveDevices.last();

@@void WebXRSystem::unregisterSimulatedXRDeviceForTesting(PlatformXR::Device* devi
185455 if (!RuntimeEnabledFeatures::sharedFeatures().webXREnabled())
186456 return;
187457 ASSERT(m_immersiveDevices.contains(device));
 458 ASSERT(m_testingDevices);
188459 m_immersiveDevices.removeFirst(device);
189460 if (m_activeImmersiveDevice == device)
190461 m_activeImmersiveDevice = nullptr;
191462 if (m_inlineXRDevice == device)
192463 m_inlineXRDevice = makeWeakPtr(m_defaultInlineDevice);
193  m_testingMode = false;
 464 m_testingDevices--;
194465}
195466
 467void WebXRSystem::sessionEnded(const WebXRSession* session)
 468{
 469 if (m_activeImmersiveSession == session)
 470 m_activeImmersiveSession = nullptr;
 471
 472 m_listOfInlineSessions.removeFirstMatching([session](auto& item) {
 473 return item.ptr() == session;
 474 });
 475}
196476
197477} // namespace WebCore
198478

Source/WebCore/Modules/webxr/WebXRSystem.h

3333#include "JSDOMPromiseDeferred.h"
3434#include "WebGLContextAttributes.h"
3535#include "WebGLRenderingContextBase.h"
 36#include "XRReferenceSpaceType.h"
3637#include "XRSessionMode.h"
3738#include <wtf/IsoMalloc.h>
 39#include <wtf/Optional.h>
3840#include <wtf/RefCounted.h>
3941#include <wtf/WeakPtr.h>
4042
 43namespace JSC {
 44class JSGlobalObject;
 45}
 46
4147namespace WebCore {
4248
 49class DOMWindow;
4350class ScriptExecutionContext;
4451class WebXRSession;
4552struct XRSessionInit;

@@public:
5764 using RefCounted<WebXRSystem>::deref;
5865
5966 void isSessionSupported(XRSessionMode, IsSessionSupportedPromise&&);
60  void requestSession(XRSessionMode, const XRSessionInit&, RequestSessionPromise&&);
 67 void requestSession(Document&, XRSessionMode, const XRSessionInit&, RequestSessionPromise&&);
6168
6269 // This is also needed by WebGLRenderingContextBase::makeXRCompatible() and HTMLCanvasElement::createContextWebGL().
6370 void ensureImmersiveXRDeviceIsSelected();
6471 bool hasActiveImmersiveXRDevice() { return !!m_activeImmersiveDevice; }
6572
 73 void sessionEnded(const WebXRSession*);
 74
6675 // For testing purpouses only.
6776 void registerSimulatedXRDeviceForTesting(const PlatformXR::Device&);
6877 void unregisterSimulatedXRDeviceForTesting(PlatformXR::Device*);

@@protected:
8190private:
8291 WebXRSystem(ScriptExecutionContext&);
8392
 93 using FeaturesArray = PlatformXR::Device::ListOfEnabledFeatures;
 94 using JSFeaturesArray = Vector<JSC::JSValue>;
 95 PlatformXR::Device* obtainCurrentDevice(XRSessionMode, const JSFeaturesArray& requiredFeatures, const JSFeaturesArray& optionalFeatures);
 96
 97 bool immersiveSessionRequestIsAllowedForGlobalObject(DOMWindow&, Document&) const;
 98 bool inlineSessionRequestIsAllowedForGlobalObject(DOMWindow&, Document&, const XRSessionInit&) const;
 99
 100 struct ResolvedRequestedFeatures;
 101 Optional<ResolvedRequestedFeatures> resolveRequestedFeatures(XRSessionMode, const XRSessionInit&, PlatformXR::Device*, JSC::JSGlobalObject&) const;
 102 bool isXRPermissionGranted(XRSessionMode, const XRSessionInit&, PlatformXR::Device*, JSC::JSGlobalObject&) const;
 103
84104 // https://immersive-web.github.io/webxr/#default-inline-xr-device
85105 class DummyInlineDevice final : public PlatformXR::Device {
86106 public:
87  DummyInlineDevice()
88  {
89  m_supportedModes.append(XRSessionMode::Inline);
90  }
 107 DummyInlineDevice();
91108 };
92109 DummyInlineDevice m_defaultInlineDevice;
93110
94111 bool m_immersiveXRDevicesHaveBeenEnumerated { false };
95  bool m_testingMode { false };
 112 uint m_testingDevices { 0 };
96113
97  WeakPtr<WebXRSession> m_activeImmersiveSession;
 114 bool m_pendingImmersiveSession { false };
 115 RefPtr<WebXRSession> m_activeImmersiveSession;
 116 Vector<Ref<WebXRSession>> m_listOfInlineSessions;
98117
99118 WeakPtr<PlatformXR::Device> m_activeImmersiveDevice;
100119 Vector<WeakPtr<PlatformXR::Device>> m_immersiveDevices;

Source/WebCore/Modules/webxr/WebXRSystem.idl

3333] interface WebXRSystem : EventTarget {
3434 // Methods
3535 Promise<void> isSessionSupported(XRSessionMode mode);
36  [NewObject] Promise<WebXRSession> requestSession(XRSessionMode mode, optional XRSessionInit options);
 36 [NewObject, CallWith=Document] Promise<WebXRSession> requestSession(XRSessionMode mode, optional XRSessionInit options);
3737
3838 // Events
3939 attribute EventHandler ondevicechange;

Source/WebCore/dom/TaskSource.h

@@enum class TaskSource : uint8_t {
3939 PostedMessageQueue,
4040 UserInteraction,
4141 WebGL,
 42 WebXR,
4243
4344 // Internal to WebCore
4445 InternalAsyncTask, // Safe to re-order or delay.

Source/WebCore/platform/xr/PlatformXR.h

1919#pragma once
2020
2121#include <memory>
 22#include <wtf/HashMap.h>
2223#include <wtf/Vector.h>
2324#include <wtf/WeakPtr.h>
2425
2526namespace PlatformXR {
2627
27 enum class SessionMode {
 28enum class SessionMode : uint8_t {
2829 Inline,
2930 ImmersiveVr,
3031 ImmersiveAr,

@@public:
4849 Device();
4950 DeviceId id() const { return m_id; }
5051
51  using ListOfSupportedModes = Vector<SessionMode>;
5252 using ListOfEnabledFeatures = Vector<ReferenceSpaceType>;
53 
54  bool supports(SessionMode mode) const { return m_supportedModes.contains(mode); }
55  void setSupportedModes(const ListOfSupportedModes& modes) { m_supportedModes = modes; }
56  void setEnabledFeatures(const ListOfEnabledFeatures& features) { m_enabledFeatures = features; }
 53 bool supports(SessionMode mode) const { return m_enabledFeaturesMap.contains(mode); }
 54 void setEnabledFeatures(SessionMode mode, const ListOfEnabledFeatures& features) { m_enabledFeaturesMap.set(mode, features); }
 55 ListOfEnabledFeatures enabledFeatures(SessionMode mode) const { return m_enabledFeaturesMap.get(mode); }
5756
5857 inline bool operator==(const Device& other) const { return m_id == other.m_id; }
5958
6059protected:
61  ListOfSupportedModes m_supportedModes;
62  ListOfEnabledFeatures m_enabledFeatures;
 60 // https://immersive-web.github.io/webxr/#xr-device-concept
 61 // Each XR device has a list of enabled features for each XRSessionMode in its list of supported modes,
 62 // which is a list of feature descriptors which MUST be initially an empty list.
 63 using EnabledFeaturesPerModeMap = WTF::HashMap<SessionMode, ListOfEnabledFeatures, WTF::IntHash<SessionMode>, WTF::StrongEnumHashTraits<SessionMode>>;
 64 EnabledFeaturesPerModeMap m_enabledFeaturesMap;
6365
6466private:
6567 DeviceId m_id;

Source/WebCore/platform/xr/openxr/PlatformXR.cpp

2424
2525#if USE_OPENXR
2626#include <openxr/openxr.h>
 27#include <wtf/Optional.h>
2728#include <wtf/text/StringConcatenateNumbers.h>
2829#include <wtf/text/WTFString.h>
2930#endif // USE_OPENXR

@@public:
6768 ~Impl();
6869
6970#if USE_OPENXR
70  void collectSupportedSessionModes(Device&, XrSystemId);
 71 Optional<Vector<SessionMode>> collectSupportedSessionModes(Device&, XrSystemId);
7172 XrInstance m_instance { XR_NULL_HANDLE };
7273#endif // USE_OPENXR
7374};

@@Instance::Impl::~Impl()
150151
151152#if USE_OPENXR
152153
153 void Instance::Impl::collectSupportedSessionModes(Device& device, XrSystemId systemId)
 154Optional<Vector<SessionMode>> Instance::Impl::collectSupportedSessionModes(Device& device, XrSystemId systemId)
154155{
155156 uint32_t viewConfigurationCount;
156157 XrResult result = xrEnumerateViewConfigurations(m_instance, systemId, 0, &viewConfigurationCount, nullptr);
157158 if (result != XR_SUCCESS) {
158159 WTFLogAlways("xrEnumerateViewConfigurations(): error %s\n", resultToString(result, m_instance).utf8().data());
159  return;
 160 return WTF::nullopt;
160161 }
161162
162163 XrViewConfigurationType viewConfigurations[viewConfigurationCount];

@@void Instance::Impl::collectSupportedSessionModes(Device& device, XrSystemId sys
164165 if (result != XR_SUCCESS) {
165166 WTFLogAlways("xrEnumerateViewConfigurations(): error %s\n", resultToString(result, m_instance).utf8().data());
166167 WTFLogAlways("xrEnumerateViewConfigurations(): error %s\n", resultToString(result, m_instance).utf8().data());
167  return;
 168 return WTF::nullopt;
168169 }
169170
170  Device::ListOfSupportedModes supportedModes;
 171 Vector<SessionMode> supportedModes;
171172 for (uint32_t i = 0; i < viewConfigurationCount; ++i) {
172173 auto viewConfigurationProperties = createStructure<XrViewConfigurationProperties, XR_TYPE_VIEW_CONFIGURATION_PROPERTIES>();
173174 result = xrGetViewConfigurationProperties(m_instance, systemId, viewConfigurations[i], &viewConfigurationProperties);
174175 if (result != XR_SUCCESS) {
175176 WTFLogAlways("xrGetViewConfigurationProperties(): error %s\n", resultToString(result, m_instance).utf8().data());
176  return;
 177 return WTF::nullopt;
177178 }
178179 if (viewConfigurationProperties.viewConfigurationType == XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO)
179180 supportedModes.append(SessionMode::ImmersiveAr);
180181 else if (viewConfigurationProperties.viewConfigurationType == XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO)
181182 supportedModes.append(SessionMode::ImmersiveVr);
182183 }
183  device.setSupportedModes(supportedModes);
 184 return supportedModes;
184185}
185186
186187#endif // USE_OPENXR

@@void Instance::enumerateImmersiveXRDevices()
218219 }
219220
220221 auto device = makeUnique<Device>();
221  m_impl->collectSupportedSessionModes(*device, systemId);
 222 auto sessionModes = m_impl->collectSupportedSessionModes(*device, systemId);
 223 if (sessionModes) {
 224 for (auto& mode : sessionModes.value()) {
 225 // TODO: fill in features
 226 device->setEnabledFeatures(mode, { });
 227 }
 228 }
 229
222230 m_immersiveXRDevices.append(WTFMove(device));
223231#endif // USE_OPENXR
224232}

Source/WebCore/testing/WebXRTest.cpp

@@void WebXRTest::simulateDeviceConnection(ScriptExecutionContext& context, const
5454 simulatedDevice.views().append(view.releaseReturnValue());
5555 }
5656
 57 Vector<XRReferenceSpaceType> features;
5758 if (init.supportedFeatures) {
58  Vector<XRReferenceSpaceType> features;
59  for (auto& feature : init.supportedFeatures.value()) {
60  if (auto referenceSpaceType = parseEnumeration<XRReferenceSpaceType>(*context.execState(), feature))
61  features.append(referenceSpaceType.value());
 59 if (auto* globalObject = context.execState()) {
 60 for (auto& feature : init.supportedFeatures.value()) {
 61 if (auto referenceSpaceType = parseEnumeration<XRReferenceSpaceType>(*globalObject, feature))
 62 features.append(referenceSpaceType.value());
 63 }
6264 }
63  simulatedDevice.setEnabledFeatures(features);
6465 }
6566
6667 if (init.boundsCoordinates) {

@@void WebXRTest::simulateDeviceConnection(ScriptExecutionContext& context, const
8788 if (init.supportsImmersive)
8889 supportedModes.append(XRSessionMode::ImmersiveVr);
8990 }
90  simulatedDevice.setSupportedModes(supportedModes);
 91
 92 for (auto& mode : supportedModes)
 93 simulatedDevice.setEnabledFeatures(mode, features);
9194
9295 m_context->registerSimulatedXRDeviceForTesting(simulatedDevice);
9396

LayoutTests/ChangeLog

 12020-05-14 Sergio Villar Senin <svillar@igalia.com>
 2
 3 [WebXR] Implement requestSession()
 4 https://bugs.webkit.org/show_bug.cgi?id=211888
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * platform/wpe/TestExpectations: Added several previously skipped tests
 9 that are now passing.
 10
1112020-05-14 Diego Pino Garcia <dpino@igalia.com>
212
313 [GTK] Gardening, update expectations after r261609

LayoutTests/imported/w3c/ChangeLog

 12020-05-14 Sergio Villar Senin <svillar@igalia.com>
 2
 3 [WebXR] Implement requestSession()
 4 https://bugs.webkit.org/show_bug.cgi?id=211888
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * web-platform-tests/webxr/xrDevice_requestSession_immersive.https-expected.txt: Added.
 9 * web-platform-tests/webxr/xrDevice_requestSession_immersive_no_gesture.https-expected.txt: Added.
 10 * web-platform-tests/webxr/xrDevice_requestSession_immersive_unsupported.https-expected.txt: Added.
 11 * web-platform-tests/webxr/xrDevice_requestSession_no_mode.https-expected.txt: Added.
 12 * web-platform-tests/webxr/xrDevice_requestSession_non_immersive_no_gesture.https-expected.txt: Added.
 13 * web-platform-tests/webxr/xrDevice_requestSession_optionalFeatures.https-expected.txt: Added.
 14 * web-platform-tests/webxr/xrDevice_requestSession_requiredFeatures_unknown.https-expected.txt: Added.
 15 * web-platform-tests/webxr/xrSession_features_deviceSupport.https-expected.txt: Added.
 16
1172020-05-12 Alexey Shvayka <shvaikalesh@gmail.com>
218
319 Implement @isConstructor bytecode intrinsic and bytecode for that

LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_immersive.https-expected.txt

 1
 2PASS Tests requestSession resolves when supported
 3PASS Tests requestSession accepts XRSessionInit dictionary
 4PASS Tests requestSession ignores unknown optionalFeatures
 5

LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_immersive_no_gesture.https-expected.txt

 1
 2PASS Requesting immersive session outside of a user gesture rejects
 3

LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_immersive_unsupported.https-expected.txt

 1
 2PASS Requesting an immersive session when unsupported rejects
 3

LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_no_mode.https-expected.txt

 1
 2PASS Requesting a session with no mode rejects
 3

LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_non_immersive_no_gesture.https-expected.txt

 1
 2PASS Requesting non-immersive session outside of a user gesture succeeds
 3

LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_optionalFeatures.https-expected.txt

 1
 2PASS Tests requestSession accepts XRSessionInit dictionary
 3PASS Tests requestSession accepts XRSessionInit dictionary with empty feature lists
 4PASS Tests requestSession ignores unknown strings in optionalFeatures
 5PASS Tests requestSession ignores unknown objects in optionalFeatures
 6

LayoutTests/imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_requiredFeatures_unknown.https-expected.txt

 1
 2PASS Tests requestSession rejects for unknown requiredFeatures
 3

LayoutTests/imported/w3c/web-platform-tests/webxr/xrSession_features_deviceSupport.https-expected.txt

 1
 2PASS Immersive XRSession requests with no supported device should reject
 3

LayoutTests/platform/wpe/TestExpectations

@@webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/idlharness.https.windo
10221022webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/xrDevice_isSessionSupported_inline.https.html [ Pass ]
10231023webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/xrDevice_isSessionSupported_immersive.https.html [ Pass ]
10241024webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/xrDevice_isSessionSupported_immersive_unsupported.https.html [ Pass ]
 1025webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_immersive.https.html [ Pass ]
 1026webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_immersive_no_gesture.https.html [ Pass ]
 1027webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_immersive_unsupported.https.html [ Pass ]
 1028webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_no_mode.https.html [ Pass ]
 1029webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_non_immersive_no_gesture.https.html [ Pass ]
 1030webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_optionalFeatures.https.html [ Pass ]
 1031webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/xrDevice_requestSession_requiredFeatures_unknown.https.html [ Pass ]
 1032webkit.org/b/209859 imported/w3c/web-platform-tests/webxr/xrSession_features_deviceSupport.https.html [ Pass ]
10251033
10261034# Passing since r259006.
10271035imported/w3c/web-platform-tests/css/css-grid/alignment/self-baseline/grid-self-baseline-changes-grid-area-size-010.html