tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

helpers.js (3468B)


      1 // Test helpers used by multiple Web Locks API tests.
      2 (() => {
      3 
      4  // Generate a unique resource identifier, using the script path and
      5  // test case name. This is useful to avoid lock interference between
      6  // test cases.
      7  let res_num = 0;
      8  self.uniqueName = (testCase, prefix) => {
      9    return `${self.location.pathname}-${prefix}-${testCase.name}-${++res_num}`;
     10  };
     11  self.uniqueNameByQuery = () => {
     12    const prefix = new URL(location.href).searchParams.get('prefix');
     13    // Add randomness to prevent tests from timing out on leaked locks from
     14    // previous sub-tests in the same file.
     15    return `${prefix}-${++res_num}-${Math.random()}`;
     16  }
     17 
     18  // Inject an iframe showing the given url into the page, and resolve
     19  // the returned promise when the frame is loaded.
     20  self.iframe = url => new Promise(resolve => {
     21    const element = document.createElement('iframe');
     22    element.addEventListener(
     23      'load', () => { resolve(element); }, { once: true });
     24    element.src = url;
     25    document.documentElement.appendChild(element);
     26  });
     27 
     28  // Post a message to the target frame, and resolve the returned
     29  // promise when a response comes back. The posted data is annotated
     30  // with unique id to track the response. This assumes the use of
     31  // 'iframe.html' as the frame, which implements this protocol.
     32  let next_request_id = 0;
     33  self.postToFrameAndWait = (frame, data) => {
     34    const iframe_window = frame.contentWindow;
     35    data.rqid = next_request_id++;
     36    iframe_window.postMessage(data, '*');
     37    return new Promise(resolve => {
     38      const listener = event => {
     39        if (event.source !== iframe_window || event.data.rqid !== data.rqid)
     40          return;
     41        self.removeEventListener('message', listener);
     42        resolve(event.data);
     43      };
     44      self.addEventListener('message', listener);
     45    });
     46  };
     47 
     48  // Post a message to the target worker, and resolve the returned
     49  // promise when a response comes back. The posted data is annotated
     50  // with unique id to track the response. This assumes the use of
     51  // 'worker.js' as the worker, which implements this protocol.
     52  self.postToWorkerAndWait = (worker, data) => {
     53    return new Promise(resolve => {
     54      data.rqid = next_request_id++;
     55      worker.postMessage(data);
     56      const listener = event => {
     57        if (event.data.rqid !== data.rqid)
     58          return;
     59        worker.removeEventListener('message', listener);
     60        resolve(event.data);
     61      };
     62      worker.addEventListener('message', listener);
     63    });
     64  };
     65 
     66  /**
     67   * Request a lock and hold it until the subtest ends.
     68   * @param {*} t test runner object
     69   * @param {string} name lock name
     70   * @param {LockOptions=} options lock options
     71   * @returns
     72   */
     73  self.requestLockAndHold = (t, name, options = {}) => {
     74    let [promise, resolve] = self.makePromiseAndResolveFunc();
     75    const released = navigator.locks.request(name, options, () => promise);
     76    // Add a cleanup function that releases the lock by resolving the promise,
     77    // and then waits until the lock is really released, to avoid contaminating
     78    // following tests with temporarily held locks.
     79    t.add_cleanup(() => {
     80      resolve();
     81      // Cleanup shouldn't fail if the request is aborted.
     82      return released.catch(() => undefined);
     83    });
     84    return released;
     85  };
     86 
     87  self.makePromiseAndResolveFunc = () => {
     88    let resolve;
     89    const promise = new Promise(r => { resolve = r; });
     90    return [promise, resolve];
     91  };
     92 
     93 })();