| <!DOCTYPE html> |
| <meta charset="utf-8"> |
| <title>WebXR - interfaces exposed by origin trial</title> |
| <script src="../../../resources/testharness.js"></script> |
| <script src="../../../resources/testharnessreport.js"></script> |
| <script src="../../../resources/origin-trials-helper.js"></script> |
| <script> |
| let properties_to_check = { |
| 'Navigator': ['xr'] |
| }; |
| |
| // The WebXR APIs should not be present without the token. |
| test(t => { |
| OriginTrialsHelper.check_properties_missing_unless_runtime_flag( |
| this, properties_to_check, 'webXREnabled'); |
| }, "WebXR's entrypoint properties are not available without a token."); |
| |
| test(() => { |
| if (OriginTrialsHelper.is_runtime_flag_enabled('webXREnabled')) { |
| assert_in_array('xr-spatial-tracking', document.featurePolicy.features()); |
| } else { |
| assert_equals(document.featurePolicy.features().indexOf("xr-spatial-tracking"), -1); |
| } |
| }, 'document.featurePolicy.features does not advertise xr-spatial-tracking without a token or flag.'); |
| |
| // Add the token, which was generated with the following command: |
| // tools/origin_trials/generate_token.py http://127.0.0.1:8000 WebXRDeviceM76 --expire-timestamp=2000000000 |
| let token = "AkyVxpb70lHShWfDAoWZVaVN2iZ9BxVFtnErcD8gysTmnF+SNXlduVTCLBpcr1V2q/MFrjeqPb2BlFALolT1bAwAAABWeyJvcmlnaW4iOiAiaHR0cDovLzEyNy4wLjAuMTo4MDAwIiwgImZlYXR1cmUiOiAiV2ViWFJEZXZpY2VNNzYiLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0="; |
| OriginTrialsHelper.add_token(token); |
| |
| // The WebXR APIs should be available now. |
| test(t => { |
| OriginTrialsHelper.check_properties_exist(this, properties_to_check); |
| }, "WebXR's entrypoint properties are available with origin trial token."); |
| |
| test(() => { |
| assert_in_array('xr-spatial-tracking', document.featurePolicy.features()); |
| }, 'document.featurePolicy.features advertises xr-spatial-tracking after token added.'); |
| |
| // Ensure Gamepad Extensions are NOT enabled by the WebXR origin trial token. |
| test(t => { |
| webvr_gamepad_properties = { |
| 'Gamepad': ['pose', 'hand', 'displayId'], |
| }; |
| OriginTrialsHelper.check_properties_missing_unless_runtime_flag( |
| this, webvr_gamepad_properties, 'webVREnabled'); |
| }, "WebVR-specific Gamepad properties are not available with a WebXR token."); |
| test(t => { |
| webvr_gamepad_interfaces = [ |
| 'GamepadPose' |
| ]; |
| OriginTrialsHelper.check_interfaces_missing_unless_runtime_flag( |
| this, webvr_gamepad_interfaces, 'webVREnabled'); |
| }, "WebVR-specific Gamepad interfaces are not available with a WebXR token."); |
| |
| |
| // Ensure that APIs that are not part of the core WebXR set are NOT enabled by |
| // the WebXR origin trial token. |
| |
| test(t => { |
| let ar_properties = { |
| 'XRSession': ['environmentBlendMode'] |
| }; |
| // TODO: Update AR support to use it's own runtime flag |
| OriginTrialsHelper.check_properties_missing_unless_runtime_flag( |
| this, ar_properties, 'webXRARModuleEnabled'); |
| }, "AR properties are not available with a WebXR token."); |
| |
| test(t => { |
| let hittest_properties = { |
| 'XRSession': ['requestHitTest'] |
| }; |
| OriginTrialsHelper.check_properties_missing_unless_runtime_flag( |
| this, hittest_properties, 'webXRHitTestEnabled'); |
| }, "Hit-test properties are not available with a WebXR token."); |
| test(t => { |
| let hittest_interfaces = [ |
| 'XRHitResult', |
| 'XRRay' |
| ]; |
| OriginTrialsHelper.check_interfaces_missing_unless_runtime_flag( |
| this, hittest_interfaces, 'webXRHitTestEnabled'); |
| }, "Hit-test interfaces are not available with a WebXR token."); |
| |
| test(t => { |
| let planes_properties = { |
| 'XRFrame': ['worldInformation'], |
| 'XRSession': ['worldTrackingState', 'updateWorldTrackingState'] |
| }; |
| OriginTrialsHelper.check_properties_missing_unless_runtime_flag( |
| this, planes_properties, 'webXRPlaneDetectionEnabled'); |
| }, "Plane properties are not available with a WebXR token."); |
| test(t => { |
| let planes_interfaces = [ |
| 'XRPlane', |
| 'XRPlaneDetectionState', |
| 'XRWorldInformation', |
| 'XRWorldTrackingState' |
| ]; |
| OriginTrialsHelper.check_interfaces_missing_unless_runtime_flag( |
| this, planes_interfaces, 'webXRPlaneDetectionEnabled'); |
| }, "Plane interfaces are not available with a WebXR token."); |
| |
| |
| // Ensure that AR sessions are not exposed as part of the WebXR origin trial. |
| // The webXREnabled check is effectively checking whether experimental features |
| // are enabled. This works as long as at least one AR feature is experimental. |
| promise_test(t => { |
| let promise = navigator.xr.supportsSession('immersive-ar'); |
| if (OriginTrialsHelper.is_runtime_flag_enabled('webXREnabled')) { |
| return promise_rejects(t, "NotSupportedError", promise); |
| } else { |
| return promise_rejects(t, new TypeError(), promise); |
| } |
| }, "immersive-ar is not recognized by supportsSession() with a WebXR token."); |
| promise_test(t => { |
| let promise = navigator.xr.requestSession('immersive-ar'); |
| if (OriginTrialsHelper.is_runtime_flag_enabled('webXREnabled')) { |
| return promise_rejects(t, "SecurityError", promise); |
| } else { |
| return promise_rejects(t, new TypeError(), promise); |
| } |
| }, "immersive-ar is not recognized by requestSession() with a WebXR token."); |
| // Verify the rejection reason matches that for other invalid enum values. |
| // It only makes sense to run these when the failure occurs. |
| if (!OriginTrialsHelper.is_runtime_flag_enabled('webXREnabled')) { |
| promise_test(t => { |
| return navigator.xr.supportsSession('invalid').then(function() { |
| assert_unreached("Promise should be rejected.") |
| }).catch(function(invalidReason) { |
| return navigator.xr.supportsSession('immersive-ar').then(function() { |
| assert_unreached("Promise should be rejected.") |
| }).catch(function(arReason) { |
| // Replace the enum value in the expected message. That is the only |
| // thing that should be different. |
| invalidReason.message = invalidReason.message.replace('invalid', 'immersive-ar'); |
| assert_object_equals(invalidReason, arReason); |
| }); |
| }); |
| }, "supportsSession('immersive-ar') result matches result for other invalid values."); |
| promise_test(t => { |
| return navigator.xr.requestSession('invalid').then(function() { |
| assert_unreached("Promise should be rejected.") |
| }).catch(function(invalidReason) { |
| return navigator.xr.requestSession('immersive-ar').then(function() { |
| assert_unreached("Promise should be rejected.") |
| }).catch(function(arReason) { |
| // Replace the enum value in the expected message. That is the only |
| // thing that should be different. |
| invalidReason.message = invalidReason.message.replace('invalid', 'immersive-ar'); |
| assert_object_equals(invalidReason, arReason); |
| }); |
| }); |
| }, "requestSession('immersive-ar') result matches result for other invalid values."); |
| } |
| </script> |