partitioned-utils.js (3228B)
1 // The resolve function for the current pending event listener's promise. 2 // It is nulled once the promise is resolved. 3 var message_event_promise_resolve = null; 4 5 function messageEventHandler(evt) { 6 if (message_event_promise_resolve) { 7 local_resolve = message_event_promise_resolve; 8 message_event_promise_resolve = null; 9 local_resolve(evt.data); 10 } 11 } 12 13 function makeMessagePromise() { 14 if (message_event_promise_resolve != null) { 15 // Do not create a new promise until the previous is settled. 16 return; 17 } 18 19 return new Promise(resolve => { 20 message_event_promise_resolve = resolve; 21 }); 22 } 23 24 // Loads a url for the frame type and then returns a promise for 25 // the data that was postMessage'd from the loaded frame. 26 // If the frame type is 'window' then `url` is encoded into the search param 27 // as the url the 3p window is meant to iframe. 28 function loadAndReturnSwData(t, url, frame_type) { 29 if (frame_type !== 'iframe' && frame_type !== 'window') { 30 return; 31 } 32 33 const message_promise = makeMessagePromise(); 34 35 // Create the iframe or window and then return the promise for data. 36 if ( frame_type === 'iframe' ) { 37 const frame = with_iframe(url, false); 38 t.add_cleanup(async () => { 39 const f = await frame; 40 f.remove(); 41 }); 42 } 43 else { 44 // 'window' case. 45 const search_param = new URLSearchParams(); 46 search_param.append('target', url); 47 48 const third_party_window_url = new URL( 49 './resources/partitioned-service-worker-third-party-window.html' + 50 '?' + search_param, 51 get_host_info().HTTPS_NOTSAMESITE_ORIGIN + self.location.pathname); 52 53 const w = window.open(third_party_window_url); 54 t.add_cleanup(() => w.close()); 55 } 56 57 return message_promise; 58 } 59 60 // Checks for an existing service worker registration. If not present, 61 // registers and maintains a service worker. Used in windows or iframes 62 // that will be partitioned from the main frame. 63 async function setupServiceWorker() { 64 65 const script = './partitioned-storage-sw.js'; 66 const scope = './partitioned-'; 67 68 var reg = await navigator.serviceWorker.register(script, { scope: scope }); 69 70 // We should keep track if we installed a worker or not. If we did then we 71 // need to uninstall it. Otherwise we let the top level test uninstall it 72 // (If partitioning is not working). 73 var installed_a_worker = true; 74 await new Promise(resolve => { 75 // Check if a worker is already activated. 76 var worker = reg.active; 77 // If so, just resolve. 78 if ( worker ) { 79 installed_a_worker = false; 80 resolve(); 81 return; 82 } 83 84 //Otherwise check if one is waiting. 85 worker = reg.waiting; 86 // If not waiting, grab the installing worker. 87 if ( !worker ) { 88 worker = reg.installing; 89 } 90 91 // Resolve once it's activated. 92 worker.addEventListener('statechange', evt => { 93 if (worker.state === 'activated') { 94 resolve(); 95 } 96 }); 97 }); 98 99 self.addEventListener('unload', async () => { 100 // If we didn't install a worker then that means the top level test did, and 101 // that test is therefore responsible for cleaning it up. 102 if ( !installed_a_worker ) { 103 return; 104 } 105 106 await reg.unregister(); 107 }); 108 109 return reg; 110 }