head.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /* Any copyright is dedicated to the Public Domain.
  2. http://creativecommons.org/publicdomain/zero/1.0/ */
  3. "use strict";
  4. const {NetUtil} = Cu.import("resource://gre/modules/NetUtil.jsm", {});
  5. const {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm", {});
  6. const {console} = Cu.import("resource://gre/modules/Console.jsm", {});
  7. const {ScratchpadManager} = Cu.import("resource://devtools/client/scratchpad/scratchpad-manager.jsm", {});
  8. const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
  9. const {gDevTools} = require("devtools/client/framework/devtools");
  10. const Services = require("Services");
  11. const DevToolsUtils = require("devtools/shared/DevToolsUtils");
  12. const flags = require("devtools/shared/flags");
  13. const promise = require("promise");
  14. var gScratchpadWindow; // Reference to the Scratchpad chrome window object
  15. flags.testing = true;
  16. SimpleTest.registerCleanupFunction(() => {
  17. flags.testing = false;
  18. });
  19. /**
  20. * Open a Scratchpad window.
  21. *
  22. * @param function aReadyCallback
  23. * Optional. The function you want invoked when the Scratchpad instance
  24. * is ready.
  25. * @param object aOptions
  26. * Optional. Options for opening the scratchpad:
  27. * - window
  28. * Provide this if there's already a Scratchpad window you want to wait
  29. * loading for.
  30. * - state
  31. * Scratchpad state object. This is used when Scratchpad is open.
  32. * - noFocus
  33. * Boolean that tells you do not want the opened window to receive
  34. * focus.
  35. * @return nsIDOMWindow
  36. * The new window object that holds Scratchpad. Note that the
  37. * gScratchpadWindow global is also updated to reference the new window
  38. * object.
  39. */
  40. function openScratchpad(aReadyCallback, aOptions = {})
  41. {
  42. let win = aOptions.window ||
  43. ScratchpadManager.openScratchpad(aOptions.state);
  44. if (!win) {
  45. return;
  46. }
  47. let onLoad = function () {
  48. win.removeEventListener("load", onLoad, false);
  49. win.Scratchpad.addObserver({
  50. onReady: function (aScratchpad) {
  51. aScratchpad.removeObserver(this);
  52. if (aOptions.noFocus) {
  53. aReadyCallback(win, aScratchpad);
  54. } else {
  55. waitForFocus(aReadyCallback.bind(null, win, aScratchpad), win);
  56. }
  57. }
  58. });
  59. };
  60. if (aReadyCallback) {
  61. win.addEventListener("load", onLoad, false);
  62. }
  63. gScratchpadWindow = win;
  64. return gScratchpadWindow;
  65. }
  66. /**
  67. * Open a new tab and then open a scratchpad.
  68. * @param object aOptions
  69. * Optional. Options for opening the tab and scratchpad. In addition
  70. * to the options supported by openScratchpad, the following options
  71. * are supported:
  72. * - tabContent
  73. * A string providing the html content of the tab.
  74. * @return Promise
  75. */
  76. function openTabAndScratchpad(aOptions = {})
  77. {
  78. waitForExplicitFinish();
  79. return new promise(resolve => {
  80. gBrowser.selectedTab = gBrowser.addTab();
  81. let {selectedBrowser} = gBrowser;
  82. selectedBrowser.addEventListener("load", function onLoad() {
  83. selectedBrowser.removeEventListener("load", onLoad, true);
  84. openScratchpad((win, sp) => resolve([win, sp]), aOptions);
  85. }, true);
  86. content.location = "data:text/html;charset=utf8," + (aOptions.tabContent || "");
  87. });
  88. }
  89. /**
  90. * Create a temporary file, write to it and call a callback
  91. * when done.
  92. *
  93. * @param string aName
  94. * Name of your temporary file.
  95. * @param string aContent
  96. * Temporary file's contents.
  97. * @param function aCallback
  98. * Optional callback to be called when we're done writing
  99. * to the file. It will receive two parameters: status code
  100. * and a file object.
  101. */
  102. function createTempFile(aName, aContent, aCallback = function () {})
  103. {
  104. // Create a temporary file.
  105. let file = FileUtils.getFile("TmpD", [aName]);
  106. file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, parseInt("666", 8));
  107. // Write the temporary file.
  108. let fout = Cc["@mozilla.org/network/file-output-stream;1"].
  109. createInstance(Ci.nsIFileOutputStream);
  110. fout.init(file.QueryInterface(Ci.nsILocalFile), 0x02 | 0x08 | 0x20,
  111. parseInt("644", 8), fout.DEFER_OPEN);
  112. let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
  113. createInstance(Ci.nsIScriptableUnicodeConverter);
  114. converter.charset = "UTF-8";
  115. let fileContentStream = converter.convertToInputStream(aContent);
  116. NetUtil.asyncCopy(fileContentStream, fout, function (aStatus) {
  117. aCallback(aStatus, file);
  118. });
  119. }
  120. /**
  121. * Run a set of asychronous tests sequentially defined by input and output.
  122. *
  123. * @param Scratchpad aScratchpad
  124. * The scratchpad to use in running the tests.
  125. * @param array aTests
  126. * An array of test objects, each with the following properties:
  127. * - method
  128. * Scratchpad method to use, one of "run", "display", or "inspect".
  129. * - code
  130. * Code to run in the scratchpad.
  131. * - result
  132. * Expected code that will be in the scratchpad upon completion.
  133. * - label
  134. * The tests label which will be logged in the test runner output.
  135. * @return Promise
  136. * The promise that will be resolved when all tests are finished.
  137. */
  138. function runAsyncTests(aScratchpad, aTests)
  139. {
  140. let deferred = promise.defer();
  141. (function runTest() {
  142. if (aTests.length) {
  143. let test = aTests.shift();
  144. aScratchpad.setText(test.code);
  145. aScratchpad[test.method]().then(function success() {
  146. is(aScratchpad.getText(), test.result, test.label);
  147. runTest();
  148. }, function failure(error) {
  149. ok(false, error.stack + " " + test.label);
  150. runTest();
  151. });
  152. } else {
  153. deferred.resolve();
  154. }
  155. })();
  156. return deferred.promise;
  157. }
  158. /**
  159. * Run a set of asychronous tests sequentially with callbacks to prepare each
  160. * test and to be called when the test result is ready.
  161. *
  162. * @param Scratchpad aScratchpad
  163. * The scratchpad to use in running the tests.
  164. * @param array aTests
  165. * An array of test objects, each with the following properties:
  166. * - method
  167. * Scratchpad method to use, one of "run", "display", or "inspect".
  168. * - prepare
  169. * The callback to run just prior to executing the scratchpad method.
  170. * - then
  171. * The callback to run when the scratchpad execution promise resolves.
  172. * @return Promise
  173. * The promise that will be resolved when all tests are finished.
  174. */
  175. var runAsyncCallbackTests = Task.async(function* (aScratchpad, aTests) {
  176. for (let {prepare, method, then} of aTests) {
  177. yield prepare();
  178. let res = yield aScratchpad[method]();
  179. yield then(res);
  180. }
  181. });
  182. /**
  183. * A simple wrapper for ContentTask.spawn for more compact code.
  184. */
  185. function inContent(generator) {
  186. return ContentTask.spawn(gBrowser.selectedBrowser, {}, generator);
  187. }
  188. function cleanup()
  189. {
  190. if (gScratchpadWindow) {
  191. gScratchpadWindow.close();
  192. gScratchpadWindow = null;
  193. }
  194. while (gBrowser.tabs.length > 1) {
  195. gBrowser.removeCurrentTab();
  196. }
  197. }
  198. registerCleanupFunction(cleanup);