| <!DOCTYPE html> | |
| <meta name="timeout" content="long"> | |
| <script src="/resources/testharness.js"></script> | |
| <script src="/resources/testharnessreport.js"></script> | |
| <script src="/resources/testdriver.js"></script> | |
| <script src="/resources/testdriver-vendor.js"></script> | |
| <script src="/common/utils.js"></script> | |
| <script src="/common/dispatcher/dispatcher.js"></script> | |
| <script src="../resources/utils.js"></script> | |
| <script src="resources/utils.js"></script> | |
| <script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script> | |
| <script> | |
| function getNextWindowMessageFromFrame(frame) { | |
| return new Promise(resolve => { | |
| window.addEventListener('message', event => { | |
| if (event.source === frame.contentWindow) { | |
| resolve(event.data); | |
| } | |
| }); | |
| }); | |
| } | |
| promise_setup(async () => { | |
| assertSpeculationRulesIsSupported() | |
| await test_driver.set_rph_registration_mode('autoAccept'); | |
| await test_driver.bless('handler registration'); | |
| }); | |
| // The overall idea for this test is: | |
| // 1. Register a protocol handler for a custom URI scheme to target 1 (initial). | |
| // 2. Create a prerendered page that registers the same custom URI scheme to | |
| // target 2 (modified). But the registration will defer until after activation. | |
| // 3. Navigate an iframe to the custom URI scheme. It should go to target 1, | |
| // because the deferred registration hasn't yet been applied. | |
| // 4. Activate the prerendered page. This should run the deferred registration. | |
| // 5. Navigate the iframe to the custom URI scheme again. It should go to | |
| // target 2. | |
| promise_test(async t => { | |
| const customUrlScheme = 'web+wptrphtest'; | |
| function getProtocolHandlerUrlTemplate(id) { | |
| return new URL( | |
| `resources/protocol-handler.html?id=${id}&s=%s`, location.href).href; | |
| } | |
| const initialUrlTemplate = getProtocolHandlerUrlTemplate('initial'); | |
| const modifiedUrlTemplate = getProtocolHandlerUrlTemplate('modified'); | |
| // To start we register the initial protocol handler. When there is nothing | |
| // registered for a custom URI scheme, and we navigate to it, there's no | |
| // good event to tell us that the navigation failed. So instead we | |
| // have an initial handler so we can tell that the modified protocol handler | |
| // hasn't been registered yet. | |
| t.add_cleanup(() => { | |
| navigator.unregisterProtocolHandler( | |
| customUrlScheme, initialUrlTemplate); | |
| }); | |
| navigator.registerProtocolHandler(customUrlScheme, initialUrlTemplate); | |
| // Create a prerender page that attempts to register an invalid scheme. | |
| const {exec, activate} = await create_prerendered_page(t); | |
| t.add_cleanup(() => { | |
| navigator.unregisterProtocolHandler( | |
| customUrlScheme, modifiedUrlTemplate); | |
| }); | |
| // First register protocol handler during prerender | |
| const result = await exec( | |
| (customUrlScheme, modifiedUrlTemplate) => { | |
| try { | |
| navigator.registerProtocolHandler( | |
| customUrlScheme, modifiedUrlTemplate); | |
| } catch (registerProtocolHandlerException) { | |
| return 'registerProtocolHandler failed with \'' | |
| + registerProtocolHandlerException.name + '\''; | |
| } | |
| return 'success'; | |
| }, [customUrlScheme, modifiedUrlTemplate]); | |
| assert_equals(result, 'success', | |
| 'registerProtocolHandler should succeed.'); | |
| // Next create the iframe that we will navigate to the custom URI scheme so | |
| // we can validate that the prerenderer registration hasn't yet been applied. | |
| const frame = await with_iframe('about:blank'); | |
| // Navigate to the custom URI scheme. Even though the prerendered page | |
| // registered a handler, registration shouldn't happen until after activation. | |
| // So this navigation should go to the initial handler. | |
| const beforeActivationMessagePromise = getNextWindowMessageFromFrame(frame); | |
| frame.src = `${customUrlScheme}:1`; | |
| assert_equals((await beforeActivationMessagePromise).id, 'initial', | |
| 'Until activation, the initial handler should be registered.'); | |
| // Activate the prerendered page. This should run the deferred registration. | |
| await activate(); | |
| // Now we listen for messages and again navigate to the custom URI scheme | |
| // and by now the prerenderer registration should have applied and we should | |
| // get the modified handler's id. | |
| const afterActivationMessagePromise = getNextWindowMessageFromFrame(frame); | |
| frame.src = `${customUrlScheme}:2`; | |
| assert_equals((await afterActivationMessagePromise).id, 'modified', | |
| 'After activation, the modified handler should be registered.'); | |
| }, 'prerendering page registerProtocolHandler call defers registration until activation.'); | |
| </script> |