send-on-deactivate.https.window.js (7209B)
1 // META: script=/common/dispatcher/dispatcher.js 2 // META: script=/common/get-host-info.sub.js 3 // META: script=/common/utils.js 4 // META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js 5 // META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js 6 // META: script=/fetch/fetch-later/resources/fetch-later-helper.js 7 8 'use strict'; 9 10 // NOTE: Due to the restriction of WPT runner, the following tests are all run 11 // with BackgroundSync off, which is different from some browsers, 12 // e.g. Chrome, default behavior, as the testing infra does not support enabling 13 // it. 14 15 parallelPromiseTest(async t => { 16 const uuid = token(); 17 const url = generateSetBeaconURL(uuid); 18 // Sets no option to test the default behavior when a document enters BFCache. 19 const helper = new RemoteContextHelper(); 20 // Opens a window with noopener so that BFCache will work. 21 const rc1 = await helper.addWindow( 22 /*config=*/ null, /*options=*/ {features: 'noopener'}); 23 24 // Creates a fetchLater request with default config in remote, which should 25 // only be sent on page discarded (not on entering BFCache). 26 await rc1.executeScript(url => { 27 fetchLater(url); 28 // Add a pageshow listener to stash the BFCache event. 29 window.addEventListener('pageshow', e => { 30 window.pageshowEvent = e; 31 }); 32 }, [url]); 33 // Navigates away to let page enter BFCache. 34 const rc2 = await rc1.navigateToNew(); 35 // Navigates back. 36 await rc2.historyBack(); 37 // Verifies the page was BFCached. 38 assert_true(await rc1.executeScript(() => { 39 return window.pageshowEvent.persisted; 40 })); 41 42 // Theoretically, the request should still be pending thus 0 request received. 43 // However, 1 request is sent, as by default the WPT test runner, e.g. 44 // content_shell in Chromium, does not enable BackgroundSync permission, 45 // resulting in forcing request sending on every navigation. 46 await expectBeacon(uuid, {count: 1}); 47 }, `fetchLater() sends on page entering BFCache if BackgroundSync is off.`); 48 49 parallelPromiseTest(async t => { 50 const uuid = token(); 51 const url = generateSetBeaconURL(uuid); 52 const helper = new RemoteContextHelper(); 53 // Opens a window with noopener so that BFCache will work. 54 const rc1 = await helper.addWindow( 55 /*config=*/ null, /*options=*/ {features: 'noopener'}); 56 57 // When the remote is put into BFCached, creates a fetchLater request w/ 58 // activateAfter = 0s. It should be sent out immediately. 59 await rc1.executeScript(url => { 60 window.addEventListener('pagehide', e => { 61 if (e.persisted) { 62 fetchLater(url, {activateAfter: 0}); 63 } 64 }); 65 // Add a pageshow listener to stash the BFCache event. 66 window.addEventListener('pageshow', e => { 67 window.pageshowEvent = e; 68 }); 69 }, [url]); 70 // Navigates away to trigger request sending. 71 const rc2 = await rc1.navigateToNew(); 72 // Navigates back. 73 await rc2.historyBack(); 74 // Verifies the page was BFCached. 75 assert_true(await rc1.executeScript(() => { 76 return window.pageshowEvent.persisted; 77 })); 78 79 // NOTE: In this case, it does not matter if BackgroundSync is on or off. 80 await expectBeacon(uuid, {count: 1}); 81 }, `Call fetchLater() when BFCached with activateAfter=0 sends immediately.`); 82 83 parallelPromiseTest(async t => { 84 const uuid = token(); 85 const url = generateSetBeaconURL(uuid); 86 // Sets no option to test the default behavior when a document gets discarded 87 // on navigated away. 88 const helper = new RemoteContextHelper(); 89 // Opens a window without BFCache. 90 const rc1 = await helper.addWindow(); 91 92 // Creates a fetchLater request in remote which should only be sent on 93 // navigating away. 94 await rc1.executeScript(url => { 95 fetchLater(url); 96 // Add a pageshow listener to stash the BFCache event. 97 window.addEventListener('pageshow', e => { 98 window.pageshowEvent = e; 99 }); 100 }, [url]); 101 // Navigates away to trigger request sending. 102 const rc2 = await rc1.navigateToNew(); 103 // Navigates back. 104 await rc2.historyBack(); 105 // Verifies the page was NOT BFCached. 106 assert_equals(undefined, await rc1.executeScript(() => { 107 return window.pageshowEvent; 108 })); 109 110 // NOTE: In this case, it does not matter if BackgroundSync is on or off. 111 await expectBeacon(uuid, {count: 1}); 112 }, `fetchLater() sends on navigating away a page w/o BFCache.`); 113 114 parallelPromiseTest(async t => { 115 const uuid = token(); 116 const url = generateSetBeaconURL(uuid); 117 // Sets no option to test the default behavior when a document gets discarded 118 // on navigated away. 119 const helper = new RemoteContextHelper(); 120 // Opens a window without BFCache. 121 const rc1 = await helper.addWindow(); 122 123 // Creates 2 fetchLater requests in remote, and one of them is aborted 124 // immediately. The other one should only be sent right on navigating away. 125 await rc1.executeScript(url => { 126 const controller = new AbortController(); 127 fetchLater(url, {signal: controller.signal}); 128 fetchLater(url); 129 controller.abort(); 130 // Add a pageshow listener to stash the BFCache event. 131 window.addEventListener('pageshow', e => { 132 window.pageshowEvent = e; 133 }); 134 }, [url]); 135 // Navigates away to trigger request sending. 136 const rc2 = await rc1.navigateToNew(); 137 // Navigates back. 138 await rc2.historyBack(); 139 // Verifies the page was NOT BFCached. 140 assert_equals(undefined, await rc1.executeScript(() => { 141 return window.pageshowEvent; 142 })); 143 144 // NOTE: In this case, it does not matter if BackgroundSync is on or off. 145 await expectBeacon(uuid, {count: 1}); 146 }, `fetchLater() does not send aborted request on navigating away a page w/o BFCache.`); 147 148 parallelPromiseTest(async t => { 149 const uuid = token(); 150 const url = generateSetBeaconURL(uuid); 151 const options = {activateAfter: 60000}; 152 const helper = new RemoteContextHelper(); 153 // Opens a window with noopener so that BFCache will work. 154 const rc1 = await helper.addWindow( 155 /*config=*/ null, /*options=*/ {features: 'noopener'}); 156 157 // Creates a fetchLater request in remote which should only be sent on 158 // navigating away. 159 await rc1.executeScript((url) => { 160 // Sets activateAfter = 1m to indicate the request should NOT be sent out 161 // immediately. 162 fetchLater(url, {activateAfter: 60000}); 163 // Adds a pageshow listener to stash the BFCache event. 164 window.addEventListener('pageshow', e => { 165 window.pageshowEvent = e; 166 }); 167 }, [url]); 168 // Navigates away to trigger request sending. 169 const rc2 = await rc1.navigateToNew(); 170 // Navigates back. 171 await rc2.historyBack(); 172 // Verifies the page was BFCached. 173 assert_true(await rc1.executeScript(() => { 174 return window.pageshowEvent.persisted; 175 })); 176 177 // Theoretically, the request should still be pending thus 0 request received. 178 // However, 1 request is sent, as by default the WPT test runner, e.g. 179 // content_shell in Chromium, does not enable BackgroundSync permission, 180 // resulting in forcing request sending on every navigation, even if page is 181 // put into BFCache. 182 await expectBeacon(uuid, {count: 1}); 183 }, `fetchLater() with activateAfter=1m sends on page entering BFCache if BackgroundSync is off.`);