diff --git a/lint.ignore b/lint.ignore index 8d0ac45b8c88ab..23cf8609bf2540 100644 --- a/lint.ignore +++ b/lint.ignore @@ -688,6 +688,7 @@ MISSING-LINK: css/filter-effects/*.any.js # Tests that use WebKit/Blink testing APIs LAYOUTTESTS APIS: import-maps/common/resources/common-test-helper.js +LAYOUTTESTS APIS: resources/test-only-api.js LAYOUTTESTS APIS: resources/chromium/enable-hyperlink-auditing.js LAYOUTTESTS APIS: resources/chromium/generic_sensor_mocks.js LAYOUTTESTS APIS: resources/chromium/nfc-mock.js @@ -709,6 +710,7 @@ WEB-PLATFORM.TEST:web-bundle/resources/wbn/*.wbn # Tests that depend on resources in /gen/ in Chromium: # https://github.com/web-platform-tests/wpt/issues/16455 # Please consult with ecosystem-infra@chromium.org before adding more. +MISSING DEPENDENCY: resources/test-only-api.js MISSING DEPENDENCY: idle-detection/interceptor.https.html MISSING DEPENDENCY: credential-management/support/otpcredential-helper.js MISSING DEPENDENCY: web-nfc/resources/nfc-helpers.js diff --git a/resources/test-only-api.js b/resources/test-only-api.js new file mode 100644 index 00000000000000..1247e295360e4d --- /dev/null +++ b/resources/test-only-api.js @@ -0,0 +1,68 @@ +'use strict'; + +/* Whether the browser is Chromium-based with MojoJS enabled */ +const isChromiumBased = 'MojoInterfaceInterceptor' in self; +/* Whether the browser is WebKit-based with internal test-only API enabled */ +const isWebKitBased = !isChromiumBased && 'internals' in self; + +/** + * Loads a script in a window or worker. + * + * @param {string} path - A script path + * @returns {Promise} + */ +function loadScript(path) { + if (typeof document === 'undefined') { + // Workers (importScripts is synchronous and may throw.) + importScripts(path); + return Promise.resolve(); + } else { + // Window + const script = document.createElement('script'); + script.src = path; + script.async = false; + const p = new Promise((resolve, reject) => { + script.onload = () => { resolve(); }; + script.onerror = e => { reject(e); }; + }) + document.head.appendChild(script); + return p; + } +} + +/** + * A helper for Chromium-based browsers to load Mojo JS bindingds + * + * This is an async function that works in both workers and windows. It first + * loads mojo_bindings.js, disables automatic dependency loading, and loads all + * resources sequentially. The promise resolves if everything loads + * successfully, or rejects if any exception is raised. If testharness.js is + * used, an uncaught exception will terminate the test with a harness error + * (unless `allow_uncaught_exception` is true), which is usually the desired + * behaviour. Only call this function if isChromiumBased === true. + * + * @param {Array.} resources - A list of scripts to load: Mojo JS + * bindings should be of the form '/gen/../*.mojom.js', the ordering of which + * does not matter. Do not include mojo_bindings.js in this list. You may + * include other non-mojom.js scripts for convenience. + * @returns {Promise} + */ +async function loadMojoResources(resources) { + if (!('MojoInterfaceInterceptor' in self)) { + throw new Error('MojoJS not enabled; start Chrome with --enable-blink-features=MojoJS,MojoJSTest'); + } + if (resources.length == 0) { + return; + } + + // We want to load mojo_bindings.js separately to set mojo.config. + if (resources.some(p => p.endsWith('/mojo_bindings.js'))) { + throw new Error('Do not load mojo_bindings.js explicitly.'); + } + await loadScript('/gen/layout_test_data/mojo/public/js/mojo_bindings.js'); + mojo.config.autoLoadMojomDeps = false; + + for (const path of resources) { + await loadScript(path); + } +} diff --git a/resources/test-only-api.js.headers b/resources/test-only-api.js.headers new file mode 100644 index 00000000000000..5e8f640c6659d1 --- /dev/null +++ b/resources/test-only-api.js.headers @@ -0,0 +1,2 @@ +Content-Type: text/javascript; charset=utf-8 +Cache-Control: max-age=3600 diff --git a/webxr/resources/webxr_util.js b/webxr/resources/webxr_util.js index 81dc3d620aa1f7..a987ca1f4420c1 100644 --- a/webxr/resources/webxr_util.js +++ b/webxr/resources/webxr_util.js @@ -1,3 +1,5 @@ +'use strict'; + // These tests rely on the User Agent providing an implementation of the // WebXR Testing API (https://github.com/immersive-web/webxr-test-api). // @@ -9,22 +11,34 @@ // Debugging message helper, by default does nothing. Implementations can // override this. -var xr_debug = function(name, msg) {} -var isChromiumBased = 'MojoInterfaceInterceptor' in self; -var isWebKitBased = 'internals' in self && 'xrTest' in internals; +var xr_debug = function(name, msg) {}; function xr_promise_test(name, func, properties) { promise_test(async (t) => { // Perform any required test setup: xr_debug(name, 'setup'); + // Only set up once. if (!navigator.xr.test) { + // Load test-only API helpers. + const script = document.createElement('script'); + script.src = '/resources/test-only-api.js'; + script.async = false; + const p = new Promise((resolve, reject) => { + script.onload = () => { resolve(); }; + script.onerror = e => { reject(e); }; + }) + document.head.appendChild(script); + await p; + if (isChromiumBased) { // Chrome setup await loadChromiumResources(); } else if (isWebKitBased) { // WebKit setup await setupWebKitWebXRTestAPI(); + } else { + assert_implements(false, "missing navigator.xr.test"); } } @@ -185,19 +199,27 @@ function forEachWebxrObject(callback) { } // Code for loading test API in Chromium. -function loadChromiumResources() { +async function loadChromiumResources() { let chromiumResources = [ - '/gen/layout_test_data/mojo/public/js/mojo_bindings.js', '/gen/mojo/public/mojom/base/time.mojom.js', - '/gen/gpu/ipc/common/mailbox_holder.mojom.js', + '/gen/mojo/public/mojom/base/shared_memory.mojom.js', + '/gen/mojo/public/mojom/base/unguessable_token.mojom.js', '/gen/gpu/ipc/common/sync_token.mojom.js', - '/gen/ui/display/mojom/display.mojom.js', + '/gen/gpu/ipc/common/mailbox.mojom.js', + '/gen/gpu/ipc/common/mailbox_holder.mojom.js', '/gen/ui/gfx/geometry/mojom/geometry.mojom.js', + '/gen/ui/gfx/mojom/native_handle_types.mojom.js', + '/gen/ui/gfx/mojom/buffer_types.mojom.js', + '/gen/ui/gfx/mojom/color_space.mojom.js', + '/gen/ui/gfx/mojom/display_color_spaces.mojom.js', '/gen/ui/gfx/mojom/gpu_fence_handle.mojom.js', '/gen/ui/gfx/mojom/transform.mojom.js', + '/gen/ui/display/mojom/display.mojom.js', + '/gen/device/gamepad/public/mojom/gamepad.mojom.js', '/gen/device/vr/public/mojom/vr_service.mojom.js', '/resources/chromium/webxr-test-math-helper.js', '/resources/chromium/webxr-test.js', + // Required only by resources/chromium/webxr-test.js '/resources/testdriver.js', '/resources/testdriver-vendor.js', ]; @@ -210,22 +232,9 @@ function loadChromiumResources() { chromiumResources = chromiumResources.concat(additionalChromiumResources); } - let chain = Promise.resolve(); - chromiumResources.forEach(path => { - let script = document.createElement('script'); - script.src = path; - script.async = false; - chain = chain.then(() => new Promise(resolve => { - script.onload = () => resolve(); - })); - document.head.appendChild(script); - }); - - chain = chain.then(() => { - xr_debug = navigator.xr.test.Debug; - }); + await loadMojoResources(chromiumResources); - return chain; + xr_debug = navigator.xr.test.Debug; } function setupWebKitWebXRTestAPI() {