tor-browser

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

browser_private_idb.js (5313B)


      1 async function idbCheckFunc() {
      2  let factory, console;
      3  try {
      4    // in a worker, this resolves directly.
      5    factory = indexedDB;
      6    console = self.console;
      7  } catch (ex) {
      8    // in a frame-script, we need to pierce "content"
      9    factory = content.indexedDB;
     10    console = content.console;
     11  }
     12  try {
     13    console.log("opening db");
     14    const req = factory.open("db", 1);
     15    const result = await new Promise(resolve => {
     16      req.onerror = () => {
     17        resolve("error");
     18      };
     19      // we expect the db to not exist and for created to resolve first
     20      req.onupgradeneeded = () => {
     21        resolve("created");
     22      };
     23      // ...so this will lose the race
     24      req.onsuccess = () => {
     25        resolve("already-exists");
     26      };
     27    });
     28    const db = req.result;
     29    console.log("db req completed:", result);
     30    if (result !== "error") {
     31      db.close();
     32      console.log("deleting database");
     33      await new Promise((resolve, reject) => {
     34        const delReq = factory.deleteDatabase("db");
     35        delReq.onerror = reject;
     36        delReq.onsuccess = resolve;
     37      });
     38      console.log("deleted database");
     39    }
     40    return result;
     41  } catch (ex) {
     42    console.error("received error:", ex);
     43    return "exception";
     44  }
     45 }
     46 
     47 async function workerDriverFunc() {
     48  const resultPromise = idbCheckFunc();
     49  /* eslint-env worker */
     50  // (SharedWorker)
     51  if (!("postMessage" in self)) {
     52    addEventListener("connect", function (evt) {
     53      const port = evt.ports[0];
     54      resultPromise.then(result => {
     55        console.log("worker test completed, postMessage-ing result:", result);
     56        port.postMessage({ idbResult: result });
     57      });
     58    });
     59  }
     60  const result = await resultPromise;
     61  // (DedicatedWorker)
     62  if ("postMessage" in self) {
     63    console.log("worker test completed, postMessage-ing result:", result);
     64    postMessage({ idbResult: result });
     65  }
     66 }
     67 
     68 const workerScript = `
     69 ${idbCheckFunc.toSource()}
     70 (${workerDriverFunc.toSource()})();
     71 `;
     72 const workerScriptBlob = new Blob([workerScript]);
     73 
     74 /**
     75 * This function is deployed via ContextTask.spawn and operates in a tab
     76 * frame script context.  Its job is to create the worker that will run the
     77 * idbCheckFunc and return the result to us.
     78 */
     79 async function workerCheckDeployer({ srcBlob, workerType }) {
     80  const { console } = content;
     81  let worker, port;
     82  const url = content.URL.createObjectURL(srcBlob);
     83  if (workerType === "dedicated") {
     84    worker = new content.Worker(url);
     85    port = worker;
     86  } else if (workerType === "shared") {
     87    worker = new content.SharedWorker(url);
     88    port = worker.port;
     89    port.start();
     90  } else {
     91    throw new Error("bad worker type!");
     92  }
     93 
     94  const result = await new Promise((resolve, reject) => {
     95    port.addEventListener(
     96      "message",
     97      function (evt) {
     98        resolve(evt.data.idbResult);
     99      },
    100      { once: true }
    101    );
    102    worker.addEventListener("error", function (evt) {
    103      console.error("worker problem:", evt);
    104      reject(evt);
    105    });
    106  });
    107  console.log("worker completed test with result:", result);
    108 
    109  return result;
    110 }
    111 
    112 function checkTabWindowIDB(tab) {
    113  return SpecialPowers.spawn(tab.linkedBrowser, [], idbCheckFunc);
    114 }
    115 
    116 async function checkTabDedicatedWorkerIDB(tab) {
    117  return SpecialPowers.spawn(
    118    tab.linkedBrowser,
    119    [
    120      {
    121        srcBlob: workerScriptBlob,
    122        workerType: "dedicated",
    123      },
    124    ],
    125    workerCheckDeployer
    126  );
    127 }
    128 
    129 async function checkTabSharedWorkerIDB(tab) {
    130  return SpecialPowers.spawn(
    131    tab.linkedBrowser,
    132    [
    133      {
    134        srcBlob: workerScriptBlob,
    135        workerType: "shared",
    136      },
    137    ],
    138    workerCheckDeployer
    139  );
    140 }
    141 
    142 add_setup(async function () {
    143  await SpecialPowers.pushPrefEnv({
    144    set: [["test.wait300msAfterTabSwitch", true]],
    145  });
    146 });
    147 
    148 add_task(async function () {
    149  const pageUrl =
    150    "http://example.com/browser/dom/indexedDB/test/page_private_idb.html";
    151 
    152  const enabled = SpecialPowers.getBoolPref(
    153    "dom.indexedDB.privateBrowsing.enabled"
    154  );
    155 
    156  let normalWin = await BrowserTestUtils.openNewBrowserWindow();
    157  let privateWin = await BrowserTestUtils.openNewBrowserWindow({
    158    private: true,
    159  });
    160 
    161  let normalTab = await BrowserTestUtils.openNewForegroundTab(
    162    normalWin.gBrowser,
    163    pageUrl
    164  );
    165  let privateTab = await BrowserTestUtils.openNewForegroundTab(
    166    privateWin.gBrowser,
    167    pageUrl
    168  );
    169 
    170  is(
    171    await checkTabWindowIDB(normalTab),
    172    "created",
    173    "IndexedDB works in a non-private-browsing page."
    174  );
    175  is(
    176    await checkTabWindowIDB(privateTab),
    177    enabled ? "created" : "error",
    178    "IndexedDB does not work in a private-browsing page."
    179  );
    180 
    181  is(
    182    await checkTabDedicatedWorkerIDB(normalTab),
    183    "created",
    184    "IndexedDB works in a non-private-browsing Worker."
    185  );
    186  is(
    187    await checkTabDedicatedWorkerIDB(privateTab),
    188    enabled ? "created" : "error",
    189    "IndexedDB does not work in a private-browsing Worker."
    190  );
    191 
    192  is(
    193    await checkTabSharedWorkerIDB(normalTab),
    194    "created",
    195    "IndexedDB works in a non-private-browsing SharedWorker."
    196  );
    197  is(
    198    await checkTabSharedWorkerIDB(privateTab),
    199    enabled ? "created" : "error",
    200    "IndexedDB does not work in a private-browsing SharedWorker."
    201  );
    202 
    203  await BrowserTestUtils.closeWindow(normalWin);
    204  await BrowserTestUtils.closeWindow(privateWin);
    205 });