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 });