| <!DOCTYPE html> | |
| <title>Helper IFrame</title> | |
| <script> | |
| 'use strict'; | |
| // Map of lock_id => function that releases a lock. | |
| const held = new Map(); | |
| let next_lock_id = 1; | |
| self.addEventListener('message', e => { | |
| function respond(data) { | |
| parent.postMessage(Object.assign(data, {rqid: e.data.rqid}), '*'); | |
| } | |
| switch (e.data.op) { | |
| case 'request': | |
| navigator.locks.request( | |
| e.data.name, { | |
| mode: e.data.mode || 'exclusive', | |
| ifAvailable: e.data.ifAvailable || false | |
| }, lock => { | |
| if (lock === null) { | |
| respond({ack: 'request', failed: true}); | |
| return; | |
| } | |
| let lock_id = next_lock_id++; | |
| let release; | |
| const promise = new Promise(r => { release = r; }); | |
| held.set(lock_id, release); | |
| respond({ack: 'request', lock_id: lock_id}); | |
| return promise | |
| }); | |
| break; | |
| case 'release': | |
| held.get(e.data.lock_id)(); | |
| held.delete(e.data.lock_id); | |
| respond({ack: 'release', lock_id: e.data.lock_id}); | |
| break; | |
| case 'client_id': | |
| navigator.locks.request(e.data.name, async lock => { | |
| const lock_state = await navigator.locks.query(); | |
| const held_lock = | |
| lock_state.held.filter(l => l.name === lock.name)[0]; | |
| respond({ack: 'client_id', client_id: held_lock.clientId}); | |
| }); | |
| break; | |
| } | |
| }); | |
| </script> |