| <!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> |