file.js (7569B)
1 /** 2 * Any copyright is dedicated to the Public Domain. 3 * http://creativecommons.org/publicdomain/zero/1.0/ 4 */ 5 6 /* import-globals-from helpers.js */ 7 8 var bufferCache = []; 9 var utils = SpecialPowers.getDOMWindowUtils(window); 10 11 function getBuffer(size) { 12 let buffer = new ArrayBuffer(size); 13 is(buffer.byteLength, size, "Correct byte length"); 14 return buffer; 15 } 16 17 function getRandomBuffer(size) { 18 let buffer = getBuffer(size); 19 let view = new Uint8Array(buffer); 20 for (let i = 0; i < size; i++) { 21 view[i] = parseInt(Math.random() * 255); 22 } 23 return buffer; 24 } 25 26 function getView(size) { 27 let buffer = new ArrayBuffer(size); 28 let view = new Uint8Array(buffer); 29 is(buffer.byteLength, size, "Correct byte length"); 30 return view; 31 } 32 33 function getRandomView(size) { 34 let view = getView(size); 35 for (let i = 0; i < size; i++) { 36 view[i] = parseInt(Math.random() * 255); 37 } 38 return view; 39 } 40 41 function compareBuffers(buffer1, buffer2) { 42 if (buffer1.byteLength != buffer2.byteLength) { 43 return false; 44 } 45 let view1 = buffer1 instanceof Uint8Array ? buffer1 : new Uint8Array(buffer1); 46 let view2 = buffer2 instanceof Uint8Array ? buffer2 : new Uint8Array(buffer2); 47 for (let i = 0; i < buffer1.byteLength; i++) { 48 if (view1[i] != view2[i]) { 49 return false; 50 } 51 } 52 return true; 53 } 54 55 function getBlob(type, view) { 56 return new Blob([view], { type }); 57 } 58 59 function getFile(name, type, view) { 60 return new File([view], name, { type }); 61 } 62 63 function getRandomBlob(size) { 64 return getBlob("binary/random", getRandomView(size)); 65 } 66 67 function getRandomFile(name, size) { 68 return getFile(name, "binary/random", getRandomView(size)); 69 } 70 71 function getNullBlob(size) { 72 return getBlob("binary/null", getView(size)); 73 } 74 75 function getNullFile(name, size) { 76 return getFile(name, "binary/null", getView(size)); 77 } 78 79 function getWasmModule(binary) { 80 let module = new WebAssembly.Module(binary); 81 return module; 82 } 83 84 function verifyBuffers(buffer1, buffer2) { 85 ok(compareBuffers(buffer1, buffer2), "Correct buffer data"); 86 } 87 88 function verifyBlobProperties(blob1, blob2, fileId) { 89 // eslint-disable-next-line mozilla/use-cc-etc 90 is(SpecialPowers.wrap(Blob).isInstance(blob1), true, "Instance of Blob"); 91 is(blob1 instanceof File, blob2 instanceof File, "Instance of DOM File"); 92 is(blob1.size, blob2.size, "Correct size"); 93 is(blob1.type, blob2.type, "Correct type"); 94 if (blob2 instanceof File) { 95 is(blob1.name, blob2.name, "Correct name"); 96 } 97 is(utils.getFileId(blob1), fileId, "Correct file id"); 98 } 99 100 /** 101 * verifyBlobAsync checks that blob1 has the same size, type and buffer as 102 * blob2, and the given fileId. Additionally, if blob2 is a File, the names 103 * of two blobs must be equal. 104 * 105 * Note: Unlike the generator based verifyBlob routine, verifyBlobAsync uses 106 * bufferCache for both blob1 and blob2 arguments. 107 * 108 * @param {Blob} blob1 actual Blob value 109 * @param {Blob} blob2 Blob with expected properties 110 * @param {number} fileId expected id 111 */ 112 async function verifyBlobAsync(blob1, blob2, fileId) { 113 verifyBlobProperties(blob1, blob2, fileId); 114 115 let buffer1; 116 let buffer2; 117 118 for (let i = 0; i < bufferCache.length; i++) { 119 if (!buffer1 && bufferCache[i].blob == blob1) { 120 buffer1 = bufferCache[i].buffer; 121 } 122 123 if (!buffer2 && bufferCache[i].blob == blob2) { 124 buffer2 = bufferCache[i].buffer; 125 } 126 127 if (!!buffer1 && !!buffer2) { 128 break; 129 } 130 } 131 132 const getBuffer = blobItem => { 133 return new Promise((resolve, reject) => { 134 const reader = new FileReader(); 135 reader.addEventListener("loadend", () => { 136 if (reader.error) { 137 reject(reader.error); 138 } 139 140 resolve(reader.result); 141 }); 142 reader.readAsArrayBuffer(blobItem); 143 }); 144 }; 145 146 if (!buffer1) { 147 buffer1 = await getBuffer(blob1); 148 bufferCache.push({ blob: blob1, buffer: buffer1 }); 149 } 150 151 if (!buffer2) { 152 buffer2 = await getBuffer(blob2); 153 bufferCache.push({ blob: blob2, buffer: buffer2 }); 154 } 155 156 verifyBuffers(buffer1, buffer2); 157 } 158 159 function verifyBlob(blob1, blob2, fileId, blobReadHandler) { 160 verifyBlobProperties(blob1, blob2, fileId); 161 162 let buffer1; 163 let buffer2; 164 165 for (let i = 0; i < bufferCache.length; i++) { 166 if (bufferCache[i].blob == blob2) { 167 buffer2 = bufferCache[i].buffer; 168 break; 169 } 170 } 171 172 if (!buffer2) { 173 let reader = new FileReader(); 174 reader.readAsArrayBuffer(blob2); 175 reader.onload = function (event) { 176 buffer2 = event.target.result; 177 bufferCache.push({ blob: blob2, buffer: buffer2 }); 178 if (buffer1) { 179 verifyBuffers(buffer1, buffer2); 180 if (blobReadHandler) { 181 blobReadHandler(); 182 } else { 183 testGenerator.next(); 184 } 185 } 186 }; 187 } 188 189 let reader = new FileReader(); 190 reader.readAsArrayBuffer(blob1); 191 reader.onload = function (event) { 192 buffer1 = event.target.result; 193 if (buffer2) { 194 verifyBuffers(buffer1, buffer2); 195 if (blobReadHandler) { 196 blobReadHandler(); 197 } else { 198 testGenerator.next(); 199 } 200 } 201 }; 202 } 203 204 function verifyBlobArray(blobs1, blobs2, expectedFileIds) { 205 is(blobs1 instanceof Array, true, "Got an array object"); 206 is(blobs1.length, blobs2.length, "Correct length"); 207 208 if (!blobs1.length) { 209 return; 210 } 211 212 let verifiedCount = 0; 213 214 function blobReadHandler() { 215 if (++verifiedCount == blobs1.length) { 216 testGenerator.next(); 217 } else { 218 verifyBlob( 219 blobs1[verifiedCount], 220 blobs2[verifiedCount], 221 expectedFileIds[verifiedCount], 222 blobReadHandler 223 ); 224 } 225 } 226 227 verifyBlob( 228 blobs1[verifiedCount], 229 blobs2[verifiedCount], 230 expectedFileIds[verifiedCount], 231 blobReadHandler 232 ); 233 } 234 235 function verifyView(view1, view2) { 236 is(view1.byteLength, view2.byteLength, "Correct byteLength"); 237 verifyBuffers(view1, view2); 238 } 239 240 function verifyWasmModule(module1, module2) { 241 // We assume the given modules have no imports and export a single function 242 // named 'run'. 243 var instance1 = new WebAssembly.Instance(module1); 244 var instance2 = new WebAssembly.Instance(module2); 245 is(instance1.exports.run(), instance2.exports.run(), "same run() result"); 246 247 continueToNextStep(); 248 } 249 250 function grabFileUsageAndContinueHandler(request) { 251 testGenerator.next(request.result.fileUsage); 252 } 253 254 function getCurrentUsage(usageHandler) { 255 let qms = SpecialPowers.Services.qms; 256 let principal = SpecialPowers.wrap(document).nodePrincipal; 257 let cb = SpecialPowers.wrapCallback(usageHandler); 258 qms.getUsageForPrincipal(principal, cb); 259 } 260 261 function getFileId(file) { 262 return utils.getFileId(file); 263 } 264 265 function getFilePath(file) { 266 return utils.getFilePath(file); 267 } 268 269 function* assertEventuallyHasFileInfo(name, id) { 270 yield* assertEventuallyWithGC( 271 () => utils.getFileReferences(name, id), 272 `Expect existing DatabaseFileInfo for ${name}/${id}` 273 ); 274 } 275 276 function* assertEventuallyHasNoFileInfo(name, id) { 277 yield* assertEventuallyWithGC( 278 () => !utils.getFileReferences(name, id), 279 `Expect no existing DatabaseFileInfo for ${name}/${id}` 280 ); 281 } 282 283 function* assertEventuallyFileRefCount(name, id, expectedCount) { 284 yield* assertEventuallyWithGC(() => { 285 let count = {}; 286 utils.getFileReferences(name, id, count); 287 return count.value == expectedCount; 288 }, `Expect ${expectedCount} existing references for ${name}/${id}`); 289 } 290 291 function getFileDBRefCount(name, id) { 292 let count = {}; 293 utils.getFileReferences(name, id, {}, count); 294 return count.value; 295 } 296 297 function flushPendingFileDeletions() { 298 utils.flushPendingFileDeletions(); 299 }