tor-browser

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

util.js (6574B)


      1 // META: script=/common/utils.js
      2 // META: script=/fenced-frame/resources/utils.js
      3 'use strict';
      4 
      5 async function IsSharedStorageSelectUrlAllowed() {
      6  let allowed = true;
      7  try {
      8    await sharedStorage.selectURL("operation", [{url: "1.html"}]);
      9  } catch (e) {
     10    allowed = false;
     11  }
     12 
     13  return allowed;
     14 }
     15 
     16 // Execute all shared storage methods (excluding createWorklet).
     17 // and capture their errors. Return true if all methods succeed.
     18 async function AreRegularSharedStorageMethodsAllowed() {
     19  let deniedCount = 0;
     20 
     21  try {
     22    await window.sharedStorage.worklet.addModule('/shared-storage/resources/simple-module.js');
     23  } catch (e) {
     24    ++deniedCount;
     25  }
     26 
     27  try {
     28    await window.sharedStorage.run('operation', {keepAlive: true});
     29  } catch (e) {
     30    ++deniedCount;
     31  }
     32 
     33  try {
     34    await sharedStorage.selectURL("operation", [{url: "1.html"}], {keepAlive: true});
     35  } catch (e) {
     36    ++deniedCount;
     37  }
     38 
     39  try {
     40    await window.sharedStorage.set('a', 'b');
     41  } catch (e) {
     42    ++deniedCount;
     43  }
     44 
     45  try {
     46    await window.sharedStorage.append('a', 'b');
     47  } catch (e) {
     48    ++deniedCount;
     49  }
     50 
     51  try {
     52    await window.sharedStorage.clear();
     53  } catch (e) {
     54    ++deniedCount;
     55  }
     56 
     57  try {
     58    await window.sharedStorage.delete('a');
     59  } catch (e) {
     60    ++deniedCount;
     61  }
     62 
     63  if (deniedCount === 0)
     64    return true;
     65 
     66  return false;
     67 }
     68 
     69 // Run sharedStorage.worklet.addModule once.
     70 // @param {string} module - The URL to the module.
     71 async function addModuleOnce(module) {
     72  try {
     73    await sharedStorage.worklet.addModule(module);
     74  } catch (e) {
     75    // Shared Storage needs to have a module added before we can operate on it.
     76    // It is generated on the fly with this call, and since there's no way to
     77    // tell through the API if a module already exists, wrap the addModule call
     78    // in a try/catch so that if it runs a second time in a test, it will
     79    // gracefully fail rather than bring the whole test down.
     80  }
     81 }
     82 
     83 // Validate the type of the result of sharedStorage.worklet.selectURL.
     84 // @param result - The result of sharedStorage.worklet.selectURL.
     85 // @param {boolean} - Whether sharedStorage.worklet.selectURL is resolved to
     86 //                    a fenced frame config (true) or an urn:uuid (false).
     87 // @return {boolean} Whether sharedStorage.worklet.selectURL returns an expected
     88 //                   result type or not.
     89 function validateSelectURLResult(result, resolve_to_config) {
     90  if (resolve_to_config) {
     91    return result instanceof FencedFrameConfig;
     92  }
     93 
     94  return result.startsWith('urn:uuid:');
     95 }
     96 
     97 function updateUrlToUseNewOrigin(url, newOriginString) {
     98  const origin = url.origin;
     99  return new URL(url.toString().replace(origin, newOriginString));
    100 }
    101 
    102 function appendExpectedKeyAndValue(url, expectedKey, expectedValue) {
    103  url.searchParams.append('expectedKey', expectedKey);
    104  url.searchParams.append('expectedValue', expectedValue);
    105  return url;
    106 }
    107 
    108 function parseExpectedKeyAndValueData() {
    109  const url = new URL(location.href);
    110  const key = url.searchParams.get('expectedKey');
    111  const value = url.searchParams.get('expectedValue');
    112  return {'expectedKey': key, 'expectedValue': value};
    113 }
    114 
    115 function appendExpectedKey(url, expectedKey) {
    116  url.searchParams.append('expectedKey', expectedKey);
    117  return url;
    118 }
    119 
    120 function parseExpectedKeyData() {
    121  const url = new URL(location.href);
    122  const key = url.searchParams.get('expectedKey');
    123  return {'expectedKey': key};
    124 }
    125 
    126 async function verifyKeyValueForOrigin(key, value, origin) {
    127  const outerKey = token();
    128  const innerKey = token();
    129  let iframeUrl = generateURL(
    130      '/shared-storage/resources/verify-key-value.https.html',
    131      [outerKey, innerKey]);
    132  iframeUrl = updateUrlToUseNewOrigin(iframeUrl, origin);
    133  iframeUrl = appendExpectedKeyAndValue(iframeUrl, key, value);
    134 
    135  attachIFrame(iframeUrl);
    136  const result = await nextValueFromServer(outerKey);
    137  assert_equals(result, 'verify_key_value_loaded');
    138 }
    139 
    140 async function verifyKeyNotFoundForOrigin(key, origin) {
    141  const outerKey = token();
    142  const innerKey = token();
    143  let iframeUrl = generateURL(
    144      '/shared-storage/resources/verify-key-not-found.https.html',
    145      [outerKey, innerKey]);
    146  iframeUrl = updateUrlToUseNewOrigin(iframeUrl, origin);
    147  iframeUrl = appendExpectedKey(iframeUrl, key);
    148 
    149  attachIFrame(iframeUrl);
    150  const result = await nextValueFromServer(outerKey);
    151  assert_equals(result, 'verify_key_not_found_loaded');
    152 }
    153 
    154 async function setKeyValueForOrigin(key, value, origin) {
    155  const outerKey = token();
    156  let setIframeUrl = generateURL(
    157      '/shared-storage/resources/set-key-value.https.html', [outerKey]);
    158  setIframeUrl = updateUrlToUseNewOrigin(setIframeUrl, origin);
    159  setIframeUrl = appendExpectedKeyAndValue(setIframeUrl, key, value);
    160 
    161  attachIFrame(setIframeUrl);
    162  const result = await nextValueFromServer(outerKey);
    163  assert_equals(result, 'set_key_value_loaded');
    164 }
    165 
    166 async function deleteKeyForOrigin(key, origin) {
    167  const outerKey = token();
    168  let deleteIframeUrl = generateURL(
    169      '/shared-storage/resources/delete-key.https.html', [outerKey]);
    170  deleteIframeUrl = updateUrlToUseNewOrigin(deleteIframeUrl, origin);
    171  deleteIframeUrl = appendExpectedKey(deleteIframeUrl, key);
    172 
    173  attachIFrame(deleteIframeUrl);
    174  const result = await nextValueFromServer(outerKey);
    175  assert_equals(result, 'delete_key_loaded');
    176 }
    177 
    178 function getFetchedUrls(worker) {
    179  return new Promise(function(resolve) {
    180    var channel = new MessageChannel();
    181    channel.port1.onmessage = function(msg) {
    182      resolve(msg);
    183    };
    184    worker.postMessage({port: channel.port2}, [channel.port2]);
    185  });
    186 }
    187 
    188 function checkInterceptedUrls(worker, expectedRequests) {
    189  return getFetchedUrls(worker).then(function(msg) {
    190    let actualRequests = msg.data.requests;
    191    assert_equals(actualRequests.length, expectedRequests.length);
    192    assert_equals(
    193        JSON.stringify(actualRequests), JSON.stringify(expectedRequests));
    194  });
    195 }
    196 
    197 function attachIFrameWithEventListenerForSelectURLStatus(url) {
    198  const frame = document.createElement('iframe');
    199  frame.src = url;
    200 
    201  const promise = new Promise((resolve, reject) => {
    202    window.addEventListener('message', async function handler(evt) {
    203      if (evt.source === frame.contentWindow && evt.data.selectURLStatus) {
    204        document.body.removeChild(frame);
    205        window.removeEventListener('message', handler);
    206        if (evt.data.selectURLStatus === 'success') {
    207          resolve(evt.data);
    208        } else {
    209          reject(new Error(JSON.stringify(evt.data)));
    210        }
    211      }
    212    });
    213  });
    214 
    215  document.body.appendChild(frame);
    216  return promise;
    217 }