Wed, 31 Dec 2014 07:53:36 +0100
Correct small whitespace inconsistency, lost while renaming variables.
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, you can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | var EXPORTED_SYMBOLS = ["applicationName", "assert", "Copy", "getBrowserObject", |
michael@0 | 6 | "getChromeWindow", "getWindows", "getWindowByTitle", |
michael@0 | 7 | "getWindowByType", "getWindowId", "getMethodInWindows", |
michael@0 | 8 | "getPreference", "saveDataURL", "setPreference", |
michael@0 | 9 | "sleep", "startTimer", "stopTimer", "takeScreenshot", |
michael@0 | 10 | "unwrapNode", "waitFor" |
michael@0 | 11 | ]; |
michael@0 | 12 | |
michael@0 | 13 | const Cc = Components.classes; |
michael@0 | 14 | const Ci = Components.interfaces; |
michael@0 | 15 | const Cu = Components.utils; |
michael@0 | 16 | |
michael@0 | 17 | |
michael@0 | 18 | Cu.import("resource://gre/modules/NetUtil.jsm"); |
michael@0 | 19 | Cu.import("resource://gre/modules/Services.jsm"); |
michael@0 | 20 | |
michael@0 | 21 | const applicationIdMap = { |
michael@0 | 22 | '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}': 'Firefox', |
michael@0 | 23 | '{99bceaaa-e3c6-48c1-b981-ef9b46b67d60}': 'MetroFirefox' |
michael@0 | 24 | } |
michael@0 | 25 | const applicationName = applicationIdMap[Services.appinfo.ID] || Services.appinfo.name; |
michael@0 | 26 | |
michael@0 | 27 | var assertions = {}; Cu.import('resource://mozmill/modules/assertions.js', assertions); |
michael@0 | 28 | var broker = {}; Cu.import('resource://mozmill/driver/msgbroker.js', broker); |
michael@0 | 29 | var errors = {}; Cu.import('resource://mozmill/modules/errors.js', errors); |
michael@0 | 30 | |
michael@0 | 31 | var assert = new assertions.Assert(); |
michael@0 | 32 | |
michael@0 | 33 | var hwindow = Services.appShell.hiddenDOMWindow; |
michael@0 | 34 | |
michael@0 | 35 | var uuidgen = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator); |
michael@0 | 36 | |
michael@0 | 37 | function Copy (obj) { |
michael@0 | 38 | for (var n in obj) { |
michael@0 | 39 | this[n] = obj[n]; |
michael@0 | 40 | } |
michael@0 | 41 | } |
michael@0 | 42 | |
michael@0 | 43 | /** |
michael@0 | 44 | * Returns the browser object of the specified window |
michael@0 | 45 | * |
michael@0 | 46 | * @param {Window} aWindow |
michael@0 | 47 | * Window to get the browser element from. |
michael@0 | 48 | * |
michael@0 | 49 | * @returns {Object} The browser element |
michael@0 | 50 | */ |
michael@0 | 51 | function getBrowserObject(aWindow) { |
michael@0 | 52 | switch(applicationName) { |
michael@0 | 53 | case "MetroFirefox": |
michael@0 | 54 | return aWindow.Browser; |
michael@0 | 55 | case "Firefox": |
michael@0 | 56 | default: |
michael@0 | 57 | return aWindow.gBrowser; |
michael@0 | 58 | } |
michael@0 | 59 | } |
michael@0 | 60 | |
michael@0 | 61 | function getChromeWindow(aWindow) { |
michael@0 | 62 | var chromeWin = aWindow.QueryInterface(Ci.nsIInterfaceRequestor) |
michael@0 | 63 | .getInterface(Ci.nsIWebNavigation) |
michael@0 | 64 | .QueryInterface(Ci.nsIDocShellTreeItem) |
michael@0 | 65 | .rootTreeItem |
michael@0 | 66 | .QueryInterface(Ci.nsIInterfaceRequestor) |
michael@0 | 67 | .getInterface(Ci.nsIDOMWindow) |
michael@0 | 68 | .QueryInterface(Ci.nsIDOMChromeWindow); |
michael@0 | 69 | |
michael@0 | 70 | return chromeWin; |
michael@0 | 71 | } |
michael@0 | 72 | |
michael@0 | 73 | function getWindows(type) { |
michael@0 | 74 | if (type == undefined) { |
michael@0 | 75 | type = ""; |
michael@0 | 76 | } |
michael@0 | 77 | |
michael@0 | 78 | var windows = []; |
michael@0 | 79 | var enumerator = Services.wm.getEnumerator(type); |
michael@0 | 80 | |
michael@0 | 81 | while (enumerator.hasMoreElements()) { |
michael@0 | 82 | windows.push(enumerator.getNext()); |
michael@0 | 83 | } |
michael@0 | 84 | |
michael@0 | 85 | if (type == "") { |
michael@0 | 86 | windows.push(hwindow); |
michael@0 | 87 | } |
michael@0 | 88 | |
michael@0 | 89 | return windows; |
michael@0 | 90 | } |
michael@0 | 91 | |
michael@0 | 92 | function getMethodInWindows(methodName) { |
michael@0 | 93 | for each (var w in getWindows()) { |
michael@0 | 94 | if (w[methodName] != undefined) { |
michael@0 | 95 | return w[methodName]; |
michael@0 | 96 | } |
michael@0 | 97 | } |
michael@0 | 98 | |
michael@0 | 99 | throw new Error("Method with name: '" + methodName + "' is not in any open window."); |
michael@0 | 100 | } |
michael@0 | 101 | |
michael@0 | 102 | function getWindowByTitle(title) { |
michael@0 | 103 | for each (var w in getWindows()) { |
michael@0 | 104 | if (w.document.title && w.document.title == title) { |
michael@0 | 105 | return w; |
michael@0 | 106 | } |
michael@0 | 107 | } |
michael@0 | 108 | |
michael@0 | 109 | throw new Error("Window with title: '" + title + "' not found."); |
michael@0 | 110 | } |
michael@0 | 111 | |
michael@0 | 112 | function getWindowByType(type) { |
michael@0 | 113 | return Services.wm.getMostRecentWindow(type); |
michael@0 | 114 | } |
michael@0 | 115 | |
michael@0 | 116 | /** |
michael@0 | 117 | * Retrieve the outer window id for the given window. |
michael@0 | 118 | * |
michael@0 | 119 | * @param {Number} aWindow |
michael@0 | 120 | * Window to retrieve the id from. |
michael@0 | 121 | * @returns {Boolean} The outer window id |
michael@0 | 122 | **/ |
michael@0 | 123 | function getWindowId(aWindow) { |
michael@0 | 124 | try { |
michael@0 | 125 | // Normally we can retrieve the id via window utils |
michael@0 | 126 | return aWindow.QueryInterface(Ci.nsIInterfaceRequestor). |
michael@0 | 127 | getInterface(Ci.nsIDOMWindowUtils). |
michael@0 | 128 | outerWindowID; |
michael@0 | 129 | } catch (e) { |
michael@0 | 130 | // ... but for observer notifications we need another interface |
michael@0 | 131 | return aWindow.QueryInterface(Ci.nsISupportsPRUint64).data; |
michael@0 | 132 | } |
michael@0 | 133 | } |
michael@0 | 134 | |
michael@0 | 135 | var checkChrome = function () { |
michael@0 | 136 | var loc = window.document.location.href; |
michael@0 | 137 | try { |
michael@0 | 138 | loc = window.top.document.location.href; |
michael@0 | 139 | } catch (e) { |
michael@0 | 140 | } |
michael@0 | 141 | |
michael@0 | 142 | return /^chrome:\/\//.test(loc); |
michael@0 | 143 | } |
michael@0 | 144 | |
michael@0 | 145 | /** |
michael@0 | 146 | * Called to get the state of an individual preference. |
michael@0 | 147 | * |
michael@0 | 148 | * @param aPrefName string The preference to get the state of. |
michael@0 | 149 | * @param aDefaultValue any The default value if preference was not found. |
michael@0 | 150 | * |
michael@0 | 151 | * @returns any The value of the requested preference |
michael@0 | 152 | * |
michael@0 | 153 | * @see setPref |
michael@0 | 154 | * Code by Henrik Skupin: <hskupin@gmail.com> |
michael@0 | 155 | */ |
michael@0 | 156 | function getPreference(aPrefName, aDefaultValue) { |
michael@0 | 157 | try { |
michael@0 | 158 | var branch = Services.prefs; |
michael@0 | 159 | |
michael@0 | 160 | switch (typeof aDefaultValue) { |
michael@0 | 161 | case ('boolean'): |
michael@0 | 162 | return branch.getBoolPref(aPrefName); |
michael@0 | 163 | case ('string'): |
michael@0 | 164 | return branch.getCharPref(aPrefName); |
michael@0 | 165 | case ('number'): |
michael@0 | 166 | return branch.getIntPref(aPrefName); |
michael@0 | 167 | default: |
michael@0 | 168 | return branch.getComplexValue(aPrefName); |
michael@0 | 169 | } |
michael@0 | 170 | } catch (e) { |
michael@0 | 171 | return aDefaultValue; |
michael@0 | 172 | } |
michael@0 | 173 | } |
michael@0 | 174 | |
michael@0 | 175 | /** |
michael@0 | 176 | * Called to set the state of an individual preference. |
michael@0 | 177 | * |
michael@0 | 178 | * @param aPrefName string The preference to set the state of. |
michael@0 | 179 | * @param aValue any The value to set the preference to. |
michael@0 | 180 | * |
michael@0 | 181 | * @returns boolean Returns true if value was successfully set. |
michael@0 | 182 | * |
michael@0 | 183 | * @see getPref |
michael@0 | 184 | * Code by Henrik Skupin: <hskupin@gmail.com> |
michael@0 | 185 | */ |
michael@0 | 186 | function setPreference(aName, aValue) { |
michael@0 | 187 | try { |
michael@0 | 188 | var branch = Services.prefs; |
michael@0 | 189 | |
michael@0 | 190 | switch (typeof aValue) { |
michael@0 | 191 | case ('boolean'): |
michael@0 | 192 | branch.setBoolPref(aName, aValue); |
michael@0 | 193 | break; |
michael@0 | 194 | case ('string'): |
michael@0 | 195 | branch.setCharPref(aName, aValue); |
michael@0 | 196 | break; |
michael@0 | 197 | case ('number'): |
michael@0 | 198 | branch.setIntPref(aName, aValue); |
michael@0 | 199 | break; |
michael@0 | 200 | default: |
michael@0 | 201 | branch.setComplexValue(aName, aValue); |
michael@0 | 202 | } |
michael@0 | 203 | } catch (e) { |
michael@0 | 204 | return false; |
michael@0 | 205 | } |
michael@0 | 206 | |
michael@0 | 207 | return true; |
michael@0 | 208 | } |
michael@0 | 209 | |
michael@0 | 210 | /** |
michael@0 | 211 | * Sleep for the given amount of milliseconds |
michael@0 | 212 | * |
michael@0 | 213 | * @param {number} milliseconds |
michael@0 | 214 | * Sleeps the given number of milliseconds |
michael@0 | 215 | */ |
michael@0 | 216 | function sleep(milliseconds) { |
michael@0 | 217 | var timeup = false; |
michael@0 | 218 | |
michael@0 | 219 | hwindow.setTimeout(function () { timeup = true; }, milliseconds); |
michael@0 | 220 | var thread = Services.tm.currentThread; |
michael@0 | 221 | |
michael@0 | 222 | while (!timeup) { |
michael@0 | 223 | thread.processNextEvent(true); |
michael@0 | 224 | } |
michael@0 | 225 | |
michael@0 | 226 | broker.pass({'function':'utils.sleep()'}); |
michael@0 | 227 | } |
michael@0 | 228 | |
michael@0 | 229 | /** |
michael@0 | 230 | * Check if the callback function evaluates to true |
michael@0 | 231 | */ |
michael@0 | 232 | function assert(callback, message, thisObject) { |
michael@0 | 233 | var result = callback.call(thisObject); |
michael@0 | 234 | |
michael@0 | 235 | if (!result) { |
michael@0 | 236 | throw new Error(message || arguments.callee.name + ": Failed for '" + callback + "'"); |
michael@0 | 237 | } |
michael@0 | 238 | |
michael@0 | 239 | return true; |
michael@0 | 240 | } |
michael@0 | 241 | |
michael@0 | 242 | /** |
michael@0 | 243 | * Unwraps a node which is wrapped into a XPCNativeWrapper or XrayWrapper |
michael@0 | 244 | * |
michael@0 | 245 | * @param {DOMnode} Wrapped DOM node |
michael@0 | 246 | * @returns {DOMNode} Unwrapped DOM node |
michael@0 | 247 | */ |
michael@0 | 248 | function unwrapNode(aNode) { |
michael@0 | 249 | var node = aNode; |
michael@0 | 250 | if (node) { |
michael@0 | 251 | // unwrap is not available on older branches (3.5 and 3.6) - Bug 533596 |
michael@0 | 252 | if ("unwrap" in XPCNativeWrapper) { |
michael@0 | 253 | node = XPCNativeWrapper.unwrap(node); |
michael@0 | 254 | } |
michael@0 | 255 | else if (node.wrappedJSObject != null) { |
michael@0 | 256 | node = node.wrappedJSObject; |
michael@0 | 257 | } |
michael@0 | 258 | } |
michael@0 | 259 | |
michael@0 | 260 | return node; |
michael@0 | 261 | } |
michael@0 | 262 | |
michael@0 | 263 | /** |
michael@0 | 264 | * Waits for the callback evaluates to true |
michael@0 | 265 | */ |
michael@0 | 266 | function waitFor(callback, message, timeout, interval, thisObject) { |
michael@0 | 267 | broker.log({'function': 'utils.waitFor() - DEPRECATED', |
michael@0 | 268 | 'message': 'utils.waitFor() is deprecated. Use assert.waitFor() instead'}); |
michael@0 | 269 | assert.waitFor(callback, message, timeout, interval, thisObject); |
michael@0 | 270 | } |
michael@0 | 271 | |
michael@0 | 272 | /** |
michael@0 | 273 | * Calculates the x and y chrome offset for an element |
michael@0 | 274 | * See https://developer.mozilla.org/en/DOM/window.innerHeight |
michael@0 | 275 | * |
michael@0 | 276 | * Note this function will not work if the user has custom toolbars (via extension) at the bottom or left/right of the screen |
michael@0 | 277 | */ |
michael@0 | 278 | function getChromeOffset(elem) { |
michael@0 | 279 | var win = elem.ownerDocument.defaultView; |
michael@0 | 280 | // Calculate x offset |
michael@0 | 281 | var chromeWidth = 0; |
michael@0 | 282 | |
michael@0 | 283 | if (win["name"] != "sidebar") { |
michael@0 | 284 | chromeWidth = win.outerWidth - win.innerWidth; |
michael@0 | 285 | } |
michael@0 | 286 | |
michael@0 | 287 | // Calculate y offset |
michael@0 | 288 | var chromeHeight = win.outerHeight - win.innerHeight; |
michael@0 | 289 | // chromeHeight == 0 means elem is already in the chrome and doesn't need the addonbar offset |
michael@0 | 290 | if (chromeHeight > 0) { |
michael@0 | 291 | // window.innerHeight doesn't include the addon or find bar, so account for these if present |
michael@0 | 292 | var addonbar = win.document.getElementById("addon-bar"); |
michael@0 | 293 | if (addonbar) { |
michael@0 | 294 | chromeHeight -= addonbar.scrollHeight; |
michael@0 | 295 | } |
michael@0 | 296 | |
michael@0 | 297 | var findbar = win.document.getElementById("FindToolbar"); |
michael@0 | 298 | if (findbar) { |
michael@0 | 299 | chromeHeight -= findbar.scrollHeight; |
michael@0 | 300 | } |
michael@0 | 301 | } |
michael@0 | 302 | |
michael@0 | 303 | return {'x':chromeWidth, 'y':chromeHeight}; |
michael@0 | 304 | } |
michael@0 | 305 | |
michael@0 | 306 | /** |
michael@0 | 307 | * Takes a screenshot of the specified DOM node |
michael@0 | 308 | */ |
michael@0 | 309 | function takeScreenshot(node, highlights) { |
michael@0 | 310 | var rect, win, width, height, left, top, needsOffset; |
michael@0 | 311 | // node can be either a window or an arbitrary DOM node |
michael@0 | 312 | try { |
michael@0 | 313 | // node is an arbitrary DOM node |
michael@0 | 314 | win = node.ownerDocument.defaultView; |
michael@0 | 315 | rect = node.getBoundingClientRect(); |
michael@0 | 316 | width = rect.width; |
michael@0 | 317 | height = rect.height; |
michael@0 | 318 | top = rect.top; |
michael@0 | 319 | left = rect.left; |
michael@0 | 320 | // offset for highlights not needed as they will be relative to this node |
michael@0 | 321 | needsOffset = false; |
michael@0 | 322 | } catch (e) { |
michael@0 | 323 | // node is a window |
michael@0 | 324 | win = node; |
michael@0 | 325 | width = win.innerWidth; |
michael@0 | 326 | height = win.innerHeight; |
michael@0 | 327 | top = 0; |
michael@0 | 328 | left = 0; |
michael@0 | 329 | // offset needed for highlights to take 'outerHeight' of window into account |
michael@0 | 330 | needsOffset = true; |
michael@0 | 331 | } |
michael@0 | 332 | |
michael@0 | 333 | var canvas = win.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"); |
michael@0 | 334 | canvas.width = width; |
michael@0 | 335 | canvas.height = height; |
michael@0 | 336 | |
michael@0 | 337 | var ctx = canvas.getContext("2d"); |
michael@0 | 338 | // Draws the DOM contents of the window to the canvas |
michael@0 | 339 | ctx.drawWindow(win, left, top, width, height, "rgb(255,255,255)"); |
michael@0 | 340 | |
michael@0 | 341 | // This section is for drawing a red rectangle around each element passed in via the highlights array |
michael@0 | 342 | if (highlights) { |
michael@0 | 343 | ctx.lineWidth = "2"; |
michael@0 | 344 | ctx.strokeStyle = "red"; |
michael@0 | 345 | ctx.save(); |
michael@0 | 346 | |
michael@0 | 347 | for (var i = 0; i < highlights.length; ++i) { |
michael@0 | 348 | var elem = highlights[i]; |
michael@0 | 349 | rect = elem.getBoundingClientRect(); |
michael@0 | 350 | |
michael@0 | 351 | var offsetY = 0, offsetX = 0; |
michael@0 | 352 | if (needsOffset) { |
michael@0 | 353 | var offset = getChromeOffset(elem); |
michael@0 | 354 | offsetX = offset.x; |
michael@0 | 355 | offsetY = offset.y; |
michael@0 | 356 | } else { |
michael@0 | 357 | // Don't need to offset the window chrome, just make relative to containing node |
michael@0 | 358 | offsetY = -top; |
michael@0 | 359 | offsetX = -left; |
michael@0 | 360 | } |
michael@0 | 361 | |
michael@0 | 362 | // Draw the rectangle |
michael@0 | 363 | ctx.strokeRect(rect.left + offsetX, rect.top + offsetY, rect.width, rect.height); |
michael@0 | 364 | } |
michael@0 | 365 | } |
michael@0 | 366 | |
michael@0 | 367 | return canvas.toDataURL("image/jpeg", 0.5); |
michael@0 | 368 | } |
michael@0 | 369 | |
michael@0 | 370 | /** |
michael@0 | 371 | * Save the dataURL content to the specified file. It will be stored in either the persisted screenshot or temporary folder. |
michael@0 | 372 | * |
michael@0 | 373 | * @param {String} aDataURL |
michael@0 | 374 | * The dataURL to save |
michael@0 | 375 | * @param {String} aFilename |
michael@0 | 376 | * Target file name without extension |
michael@0 | 377 | * |
michael@0 | 378 | * @returns {Object} The hash containing the path of saved file, and the failure bit |
michael@0 | 379 | */ |
michael@0 | 380 | function saveDataURL(aDataURL, aFilename) { |
michael@0 | 381 | var frame = {}; Cu.import('resource://mozmill/modules/frame.js', frame); |
michael@0 | 382 | const FILE_PERMISSIONS = parseInt("0644", 8); |
michael@0 | 383 | |
michael@0 | 384 | var file; |
michael@0 | 385 | file = Cc['@mozilla.org/file/local;1'] |
michael@0 | 386 | .createInstance(Ci.nsILocalFile); |
michael@0 | 387 | file.initWithPath(frame.persisted['screenshots']['path']); |
michael@0 | 388 | file.append(aFilename + ".jpg"); |
michael@0 | 389 | file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, FILE_PERMISSIONS); |
michael@0 | 390 | |
michael@0 | 391 | // Create an output stream to write to file |
michael@0 | 392 | let foStream = Cc["@mozilla.org/network/file-output-stream;1"] |
michael@0 | 393 | .createInstance(Ci.nsIFileOutputStream); |
michael@0 | 394 | foStream.init(file, 0x02 | 0x08 | 0x10, FILE_PERMISSIONS, foStream.DEFER_OPEN); |
michael@0 | 395 | |
michael@0 | 396 | let dataURI = NetUtil.newURI(aDataURL, "UTF8", null); |
michael@0 | 397 | if (!dataURI.schemeIs("data")) { |
michael@0 | 398 | throw TypeError("aDataURL parameter has to have 'data'" + |
michael@0 | 399 | " scheme instead of '" + dataURI.scheme + "'"); |
michael@0 | 400 | } |
michael@0 | 401 | |
michael@0 | 402 | // Write asynchronously to buffer; |
michael@0 | 403 | // Input and output streams are closed after write |
michael@0 | 404 | |
michael@0 | 405 | let ready = false; |
michael@0 | 406 | let failure = false; |
michael@0 | 407 | |
michael@0 | 408 | function sync(aStatus) { |
michael@0 | 409 | if (!Components.isSuccessCode(aStatus)) { |
michael@0 | 410 | failure = true; |
michael@0 | 411 | } |
michael@0 | 412 | ready = true; |
michael@0 | 413 | } |
michael@0 | 414 | |
michael@0 | 415 | NetUtil.asyncFetch(dataURI, function (aInputStream, aAsyncFetchResult) { |
michael@0 | 416 | if (!Components.isSuccessCode(aAsyncFetchResult)) { |
michael@0 | 417 | // An error occurred! |
michael@0 | 418 | sync(aAsyncFetchResult); |
michael@0 | 419 | } else { |
michael@0 | 420 | // Consume the input stream. |
michael@0 | 421 | NetUtil.asyncCopy(aInputStream, foStream, function (aAsyncCopyResult) { |
michael@0 | 422 | sync(aAsyncCopyResult); |
michael@0 | 423 | }); |
michael@0 | 424 | } |
michael@0 | 425 | }); |
michael@0 | 426 | |
michael@0 | 427 | assert.waitFor(function () { |
michael@0 | 428 | return ready; |
michael@0 | 429 | }, "DataURL has been saved to '" + file.path + "'"); |
michael@0 | 430 | |
michael@0 | 431 | return {filename: file.path, failure: failure}; |
michael@0 | 432 | } |
michael@0 | 433 | |
michael@0 | 434 | /** |
michael@0 | 435 | * Some very brain-dead timer functions useful for performance optimizations |
michael@0 | 436 | * This is only enabled in debug mode |
michael@0 | 437 | * |
michael@0 | 438 | **/ |
michael@0 | 439 | var gutility_mzmltimer = 0; |
michael@0 | 440 | /** |
michael@0 | 441 | * Starts timer initializing with current EPOC time in milliseconds |
michael@0 | 442 | * |
michael@0 | 443 | * @returns none |
michael@0 | 444 | **/ |
michael@0 | 445 | function startTimer(){ |
michael@0 | 446 | dump("TIMERCHECK:: starting now: " + Date.now() + "\n"); |
michael@0 | 447 | gutility_mzmltimer = Date.now(); |
michael@0 | 448 | } |
michael@0 | 449 | |
michael@0 | 450 | /** |
michael@0 | 451 | * Checks the timer and outputs current elapsed time since start of timer. It |
michael@0 | 452 | * will print out a message you provide with its "time check" so you can |
michael@0 | 453 | * correlate in the log file and figure out elapsed time of specific functions. |
michael@0 | 454 | * |
michael@0 | 455 | * @param aMsg string The debug message to print with the timer check |
michael@0 | 456 | * |
michael@0 | 457 | * @returns none |
michael@0 | 458 | **/ |
michael@0 | 459 | function checkTimer(aMsg){ |
michael@0 | 460 | var end = Date.now(); |
michael@0 | 461 | dump("TIMERCHECK:: at " + aMsg + " is: " + (end - gutility_mzmltimer) + "\n"); |
michael@0 | 462 | } |