xpcshell-head-parent-process.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. /**
  2. * Any copyright is dedicated to the Public Domain.
  3. * http://creativecommons.org/publicdomain/zero/1.0/
  4. */
  5. var { 'classes': Cc, 'interfaces': Ci, 'utils': Cu } = Components;
  6. if (!("self" in this)) {
  7. this.self = this;
  8. }
  9. const DOMException = Ci.nsIDOMDOMException;
  10. var bufferCache = [];
  11. function is(a, b, msg) {
  12. do_check_eq(a, b, Components.stack.caller);
  13. }
  14. function ok(cond, msg) {
  15. do_check_true(!!cond, Components.stack.caller);
  16. }
  17. function isnot(a, b, msg) {
  18. do_check_neq(a, b, Components.stack.caller);
  19. }
  20. function executeSoon(fun) {
  21. do_execute_soon(fun);
  22. }
  23. function todo(condition, name, diag) {
  24. todo_check_true(condition, Components.stack.caller);
  25. }
  26. function info(name, message) {
  27. do_print(name);
  28. }
  29. function run_test() {
  30. runTest();
  31. };
  32. if (!this.runTest) {
  33. this.runTest = function()
  34. {
  35. if (SpecialPowers.isMainProcess()) {
  36. // XPCShell does not get a profile by default.
  37. do_get_profile();
  38. enableTesting();
  39. enableExperimental();
  40. enableWasm();
  41. }
  42. Cu.importGlobalProperties(["indexedDB", "Blob", "File", "FileReader"]);
  43. do_test_pending();
  44. testGenerator.next();
  45. }
  46. }
  47. function finishTest()
  48. {
  49. if (SpecialPowers.isMainProcess()) {
  50. resetWasm();
  51. resetExperimental();
  52. resetTesting();
  53. }
  54. SpecialPowers.removeFiles();
  55. do_execute_soon(function(){
  56. testGenerator.close();
  57. do_test_finished();
  58. })
  59. }
  60. function grabEventAndContinueHandler(event)
  61. {
  62. testGenerator.send(event);
  63. }
  64. function continueToNextStep()
  65. {
  66. do_execute_soon(function() {
  67. testGenerator.next();
  68. });
  69. }
  70. function errorHandler(event)
  71. {
  72. try {
  73. dump("indexedDB error: " + event.target.error.name);
  74. } catch(e) {
  75. dump("indexedDB error: " + e);
  76. }
  77. do_check_true(false);
  78. finishTest();
  79. }
  80. function unexpectedSuccessHandler()
  81. {
  82. do_check_true(false);
  83. finishTest();
  84. }
  85. function expectedErrorHandler(name)
  86. {
  87. return function(event) {
  88. do_check_eq(event.type, "error");
  89. do_check_eq(event.target.error.name, name);
  90. event.preventDefault();
  91. grabEventAndContinueHandler(event);
  92. };
  93. }
  94. function expectUncaughtException(expecting)
  95. {
  96. // This is dummy for xpcshell test.
  97. }
  98. function ExpectError(name, preventDefault)
  99. {
  100. this._name = name;
  101. this._preventDefault = preventDefault;
  102. }
  103. ExpectError.prototype = {
  104. handleEvent: function(event)
  105. {
  106. do_check_eq(event.type, "error");
  107. do_check_eq(this._name, event.target.error.name);
  108. if (this._preventDefault) {
  109. event.preventDefault();
  110. event.stopPropagation();
  111. }
  112. grabEventAndContinueHandler(event);
  113. }
  114. };
  115. function continueToNextStepSync()
  116. {
  117. testGenerator.next();
  118. }
  119. function compareKeys(k1, k2) {
  120. let t = typeof k1;
  121. if (t != typeof k2)
  122. return false;
  123. if (t !== "object")
  124. return k1 === k2;
  125. if (k1 instanceof Date) {
  126. return (k2 instanceof Date) &&
  127. k1.getTime() === k2.getTime();
  128. }
  129. if (k1 instanceof Array) {
  130. if (!(k2 instanceof Array) ||
  131. k1.length != k2.length)
  132. return false;
  133. for (let i = 0; i < k1.length; ++i) {
  134. if (!compareKeys(k1[i], k2[i]))
  135. return false;
  136. }
  137. return true;
  138. }
  139. return false;
  140. }
  141. function addPermission(permission, url)
  142. {
  143. throw "addPermission";
  144. }
  145. function removePermission(permission, url)
  146. {
  147. throw "removePermission";
  148. }
  149. function allowIndexedDB(url)
  150. {
  151. throw "allowIndexedDB";
  152. }
  153. function disallowIndexedDB(url)
  154. {
  155. throw "disallowIndexedDB";
  156. }
  157. function enableExperimental()
  158. {
  159. SpecialPowers.setBoolPref("dom.indexedDB.experimental", true);
  160. }
  161. function resetExperimental()
  162. {
  163. SpecialPowers.clearUserPref("dom.indexedDB.experimental");
  164. }
  165. function enableTesting()
  166. {
  167. SpecialPowers.setBoolPref("dom.indexedDB.testing", true);
  168. }
  169. function resetTesting()
  170. {
  171. SpecialPowers.clearUserPref("dom.indexedDB.testing");
  172. }
  173. function enableWasm()
  174. {
  175. SpecialPowers.setBoolPref("javascript.options.wasm", true);
  176. }
  177. function resetWasm()
  178. {
  179. SpecialPowers.clearUserPref("javascript.options.wasm");
  180. }
  181. function gc()
  182. {
  183. Cu.forceGC();
  184. Cu.forceCC();
  185. }
  186. function scheduleGC()
  187. {
  188. SpecialPowers.exactGC(continueToNextStep);
  189. }
  190. function setTimeout(fun, timeout) {
  191. let timer = Components.classes["@mozilla.org/timer;1"]
  192. .createInstance(Components.interfaces.nsITimer);
  193. var event = {
  194. notify: function (timer) {
  195. fun();
  196. }
  197. };
  198. timer.initWithCallback(event, timeout,
  199. Components.interfaces.nsITimer.TYPE_ONE_SHOT);
  200. return timer;
  201. }
  202. function resetOrClearAllDatabases(callback, clear) {
  203. if (!SpecialPowers.isMainProcess()) {
  204. throw new Error("clearAllDatabases not implemented for child processes!");
  205. }
  206. let quotaManagerService = Cc["@mozilla.org/dom/quota-manager-service;1"]
  207. .getService(Ci.nsIQuotaManagerService);
  208. const quotaPref = "dom.quotaManager.testing";
  209. let oldPrefValue;
  210. if (SpecialPowers._getPrefs().prefHasUserValue(quotaPref)) {
  211. oldPrefValue = SpecialPowers.getBoolPref(quotaPref);
  212. }
  213. SpecialPowers.setBoolPref(quotaPref, true);
  214. let request;
  215. try {
  216. if (clear) {
  217. request = quotaManagerService.clear();
  218. } else {
  219. request = quotaManagerService.reset();
  220. }
  221. } catch(e) {
  222. if (oldPrefValue !== undefined) {
  223. SpecialPowers.setBoolPref(quotaPref, oldPrefValue);
  224. } else {
  225. SpecialPowers.clearUserPref(quotaPref);
  226. }
  227. throw e;
  228. }
  229. request.callback = callback;
  230. }
  231. function resetAllDatabases(callback) {
  232. resetOrClearAllDatabases(callback, false);
  233. }
  234. function clearAllDatabases(callback) {
  235. resetOrClearAllDatabases(callback, true);
  236. }
  237. function installPackagedProfile(packageName)
  238. {
  239. let directoryService = Cc["@mozilla.org/file/directory_service;1"]
  240. .getService(Ci.nsIProperties);
  241. let profileDir = directoryService.get("ProfD", Ci.nsIFile);
  242. let currentDir = directoryService.get("CurWorkD", Ci.nsIFile);
  243. let packageFile = currentDir.clone();
  244. packageFile.append(packageName + ".zip");
  245. let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"]
  246. .createInstance(Ci.nsIZipReader);
  247. zipReader.open(packageFile);
  248. let entryNames = [];
  249. let entries = zipReader.findEntries(null);
  250. while (entries.hasMore()) {
  251. let entry = entries.getNext();
  252. if (entry != "create_db.html") {
  253. entryNames.push(entry);
  254. }
  255. }
  256. entryNames.sort();
  257. for (let entryName of entryNames) {
  258. let zipentry = zipReader.getEntry(entryName);
  259. let file = profileDir.clone();
  260. let split = entryName.split("/");
  261. for(let i = 0; i < split.length; i++) {
  262. file.append(split[i]);
  263. }
  264. if (zipentry.isDirectory) {
  265. file.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("0755", 8));
  266. } else {
  267. let istream = zipReader.getInputStream(entryName);
  268. var ostream = Cc["@mozilla.org/network/file-output-stream;1"]
  269. .createInstance(Ci.nsIFileOutputStream);
  270. ostream.init(file, -1, parseInt("0644", 8), 0);
  271. let bostream = Cc['@mozilla.org/network/buffered-output-stream;1']
  272. .createInstance(Ci.nsIBufferedOutputStream);
  273. bostream.init(ostream, 32768);
  274. bostream.writeFrom(istream, istream.available());
  275. istream.close();
  276. bostream.close();
  277. }
  278. }
  279. zipReader.close();
  280. }
  281. function getChromeFilesDir()
  282. {
  283. let dirService = Cc["@mozilla.org/file/directory_service;1"]
  284. .getService(Ci.nsIProperties);
  285. let profileDir = dirService.get("ProfD", Ci.nsIFile);
  286. let idbDir = profileDir.clone();
  287. idbDir.append("storage");
  288. idbDir.append("permanent");
  289. idbDir.append("chrome");
  290. idbDir.append("idb");
  291. let idbEntries = idbDir.directoryEntries;
  292. while (idbEntries.hasMoreElements()) {
  293. let entry = idbEntries.getNext();
  294. let file = entry.QueryInterface(Ci.nsIFile);
  295. if (file.isDirectory()) {
  296. return file;
  297. }
  298. }
  299. throw new Error("files directory doesn't exist!");
  300. }
  301. function getView(size)
  302. {
  303. let buffer = new ArrayBuffer(size);
  304. let view = new Uint8Array(buffer);
  305. is(buffer.byteLength, size, "Correct byte length");
  306. return view;
  307. }
  308. function getRandomView(size)
  309. {
  310. let view = getView(size);
  311. for (let i = 0; i < size; i++) {
  312. view[i] = parseInt(Math.random() * 255)
  313. }
  314. return view;
  315. }
  316. function getBlob(str)
  317. {
  318. return new Blob([str], {type: "type/text"});
  319. }
  320. function getFile(name, type, str)
  321. {
  322. return new File([str], name, {type: type});
  323. }
  324. function isWasmSupported()
  325. {
  326. let testingFunctions = Cu.getJSTestingFunctions();
  327. return testingFunctions.wasmIsSupported();
  328. }
  329. function getWasmBinarySync(text)
  330. {
  331. let testingFunctions = Cu.getJSTestingFunctions();
  332. let binary = testingFunctions.wasmTextToBinary(text);
  333. return binary;
  334. }
  335. function getWasmBinary(text)
  336. {
  337. let binary = getWasmBinarySync(text);
  338. executeSoon(function() {
  339. testGenerator.send(binary);
  340. });
  341. }
  342. function getWasmModule(binary)
  343. {
  344. let module = new WebAssembly.Module(binary);
  345. return module;
  346. }
  347. function compareBuffers(buffer1, buffer2)
  348. {
  349. if (buffer1.byteLength != buffer2.byteLength) {
  350. return false;
  351. }
  352. let view1 = buffer1 instanceof Uint8Array ? buffer1 : new Uint8Array(buffer1);
  353. let view2 = buffer2 instanceof Uint8Array ? buffer2 : new Uint8Array(buffer2);
  354. for (let i = 0; i < buffer1.byteLength; i++) {
  355. if (view1[i] != view2[i]) {
  356. return false;
  357. }
  358. }
  359. return true;
  360. }
  361. function verifyBuffers(buffer1, buffer2)
  362. {
  363. ok(compareBuffers(buffer1, buffer2), "Correct buffer data");
  364. }
  365. function verifyBlob(blob1, blob2)
  366. {
  367. is(blob1 instanceof Components.interfaces.nsIDOMBlob, true,
  368. "Instance of nsIDOMBlob");
  369. is(blob1 instanceof File, blob2 instanceof File,
  370. "Instance of DOM File");
  371. is(blob1.size, blob2.size, "Correct size");
  372. is(blob1.type, blob2.type, "Correct type");
  373. if (blob2 instanceof File) {
  374. is(blob1.name, blob2.name, "Correct name");
  375. }
  376. let buffer1;
  377. let buffer2;
  378. for (let i = 0; i < bufferCache.length; i++) {
  379. if (bufferCache[i].blob == blob2) {
  380. buffer2 = bufferCache[i].buffer;
  381. break;
  382. }
  383. }
  384. if (!buffer2) {
  385. let reader = new FileReader();
  386. reader.readAsArrayBuffer(blob2);
  387. reader.onload = function(event) {
  388. buffer2 = event.target.result;
  389. bufferCache.push({ blob: blob2, buffer: buffer2 });
  390. if (buffer1) {
  391. verifyBuffers(buffer1, buffer2);
  392. testGenerator.next();
  393. }
  394. }
  395. }
  396. let reader = new FileReader();
  397. reader.readAsArrayBuffer(blob1);
  398. reader.onload = function(event) {
  399. buffer1 = event.target.result;
  400. if (buffer2) {
  401. verifyBuffers(buffer1, buffer2);
  402. testGenerator.next();
  403. }
  404. }
  405. }
  406. function verifyMutableFile(mutableFile1, file2)
  407. {
  408. is(mutableFile1 instanceof IDBMutableFile, true,
  409. "Instance of IDBMutableFile");
  410. is(mutableFile1.name, file2.name, "Correct name");
  411. is(mutableFile1.type, file2.type, "Correct type");
  412. continueToNextStep();
  413. }
  414. function verifyView(view1, view2)
  415. {
  416. is(view1.byteLength, view2.byteLength, "Correct byteLength");
  417. verifyBuffers(view1, view2);
  418. continueToNextStep();
  419. }
  420. function verifyWasmModule(module1, module2)
  421. {
  422. let testingFunctions = Cu.getJSTestingFunctions();
  423. let exp1 = testingFunctions.wasmExtractCode(module1);
  424. let exp2 = testingFunctions.wasmExtractCode(module2);
  425. let code1 = exp1.code;
  426. let code2 = exp2.code;
  427. ok(code1 instanceof Uint8Array, "Instance of Uint8Array");
  428. ok(code1.length == code2.length, "Correct length");
  429. verifyBuffers(code1, code2);
  430. continueToNextStep();
  431. }
  432. function grabResultAndContinueHandler(request)
  433. {
  434. testGenerator.send(request.result);
  435. }
  436. function grabFileUsageAndContinueHandler(request)
  437. {
  438. testGenerator.send(request.result.fileUsage);
  439. }
  440. function getUsage(usageHandler, getAll)
  441. {
  442. let qms = Cc["@mozilla.org/dom/quota-manager-service;1"]
  443. .getService(Ci.nsIQuotaManagerService);
  444. qms.getUsage(usageHandler, getAll)
  445. }
  446. function getCurrentUsage(usageHandler)
  447. {
  448. let qms = Cc["@mozilla.org/dom/quota-manager-service;1"]
  449. .getService(Ci.nsIQuotaManagerService);
  450. let principal = Cc["@mozilla.org/systemprincipal;1"]
  451. .createInstance(Ci.nsIPrincipal);
  452. qms.getUsageForPrincipal(principal, usageHandler);
  453. }
  454. function setTemporaryStorageLimit(limit)
  455. {
  456. const pref = "dom.quotaManager.temporaryStorage.fixedLimit";
  457. if (limit) {
  458. info("Setting temporary storage limit to " + limit);
  459. SpecialPowers.setIntPref(pref, limit);
  460. } else {
  461. info("Removing temporary storage limit");
  462. SpecialPowers.clearUserPref(pref);
  463. }
  464. }
  465. function setDataThreshold(threshold)
  466. {
  467. info("Setting data threshold to " + threshold);
  468. SpecialPowers.setIntPref("dom.indexedDB.dataThreshold", threshold);
  469. }
  470. function setMaxSerializedMsgSize(aSize)
  471. {
  472. info("Setting maximal size of a serialized message to " + aSize);
  473. SpecialPowers.setIntPref("dom.indexedDB.maxSerializedMsgSize", aSize);
  474. }
  475. function getPrincipal(url)
  476. {
  477. let uri = Cc["@mozilla.org/network/io-service;1"]
  478. .getService(Ci.nsIIOService)
  479. .newURI(url, null, null);
  480. let ssm = Cc["@mozilla.org/scriptsecuritymanager;1"]
  481. .getService(Ci.nsIScriptSecurityManager);
  482. return ssm.createCodebasePrincipal(uri, {});
  483. }
  484. var SpecialPowers = {
  485. isMainProcess: function() {
  486. return Components.classes["@mozilla.org/xre/app-info;1"]
  487. .getService(Components.interfaces.nsIXULRuntime)
  488. .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
  489. },
  490. notifyObservers: function(subject, topic, data) {
  491. var obsvc = Cc['@mozilla.org/observer-service;1']
  492. .getService(Ci.nsIObserverService);
  493. obsvc.notifyObservers(subject, topic, data);
  494. },
  495. notifyObserversInParentProcess: function(subject, topic, data) {
  496. if (subject) {
  497. throw new Error("Can't send subject to another process!");
  498. }
  499. return this.notifyObservers(subject, topic, data);
  500. },
  501. getBoolPref: function(prefName) {
  502. return this._getPrefs().getBoolPref(prefName);
  503. },
  504. setBoolPref: function(prefName, value) {
  505. this._getPrefs().setBoolPref(prefName, value);
  506. },
  507. setIntPref: function(prefName, value) {
  508. this._getPrefs().setIntPref(prefName, value);
  509. },
  510. clearUserPref: function(prefName) {
  511. this._getPrefs().clearUserPref(prefName);
  512. },
  513. // Copied (and slightly adjusted) from specialpowersAPI.js
  514. exactGC: function(callback) {
  515. let count = 0;
  516. function doPreciseGCandCC() {
  517. function scheduledGCCallback() {
  518. Components.utils.forceCC();
  519. if (++count < 2) {
  520. doPreciseGCandCC();
  521. } else {
  522. callback();
  523. }
  524. }
  525. Components.utils.schedulePreciseGC(scheduledGCCallback);
  526. }
  527. doPreciseGCandCC();
  528. },
  529. _getPrefs: function() {
  530. var prefService =
  531. Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService);
  532. return prefService.getBranch(null);
  533. },
  534. get Cc() {
  535. return Cc;
  536. },
  537. get Ci() {
  538. return Ci;
  539. },
  540. get Cu() {
  541. return Cu;
  542. },
  543. // Based on SpecialPowersObserver.prototype.receiveMessage
  544. createFiles: function(requests, callback) {
  545. let dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
  546. let filePaths = new Array;
  547. if (!this._createdFiles) {
  548. this._createdFiles = new Array;
  549. }
  550. let createdFiles = this._createdFiles;
  551. requests.forEach(function(request) {
  552. const filePerms = 0o666;
  553. let testFile = dirSvc.get("ProfD", Ci.nsIFile);
  554. if (request.name) {
  555. testFile.append(request.name);
  556. } else {
  557. testFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, filePerms);
  558. }
  559. let outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
  560. outStream.init(testFile, 0x02 | 0x08 | 0x20, // PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE
  561. filePerms, 0);
  562. if (request.data) {
  563. outStream.write(request.data, request.data.length);
  564. outStream.close();
  565. }
  566. filePaths.push(File.createFromFileName(testFile.path, request.options));
  567. createdFiles.push(testFile);
  568. });
  569. setTimeout(function () {
  570. callback(filePaths);
  571. }, 0);
  572. },
  573. removeFiles: function() {
  574. if (this._createdFiles) {
  575. this._createdFiles.forEach(function (testFile) {
  576. try {
  577. testFile.remove(false);
  578. } catch (e) {}
  579. });
  580. this._createdFiles = null;
  581. }
  582. },
  583. };