services/sync/tps/extensions/mozmill/resource/driver/controller.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/services/sync/tps/extensions/mozmill/resource/driver/controller.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1150 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, you can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +var EXPORTED_SYMBOLS = ["MozMillController", "globalEventRegistry",
     1.9 +                        "sleep", "windowMap"];
    1.10 +
    1.11 +const Cc = Components.classes;
    1.12 +const Ci = Components.interfaces;
    1.13 +const Cu = Components.utils;
    1.14 +
    1.15 +var EventUtils = {}; Cu.import('resource://mozmill/stdlib/EventUtils.js', EventUtils);
    1.16 +
    1.17 +var assertions = {}; Cu.import('resource://mozmill/modules/assertions.js', assertions);
    1.18 +var broker = {}; Cu.import('resource://mozmill/driver/msgbroker.js', broker);
    1.19 +var elementslib = {}; Cu.import('resource://mozmill/driver/elementslib.js', elementslib);
    1.20 +var errors = {}; Cu.import('resource://mozmill/modules/errors.js', errors);
    1.21 +var mozelement = {}; Cu.import('resource://mozmill/driver/mozelement.js', mozelement);
    1.22 +var utils = {}; Cu.import('resource://mozmill/stdlib/utils.js', utils);
    1.23 +var windows = {}; Cu.import('resource://mozmill/modules/windows.js', windows);
    1.24 +
    1.25 +// Declare most used utils functions in the controller namespace
    1.26 +var assert = new assertions.Assert();
    1.27 +var waitFor = assert.waitFor;
    1.28 +
    1.29 +var sleep = utils.sleep;
    1.30 +
    1.31 +// For Mozmill 1.5 backward compatibility
    1.32 +var windowMap = windows.map;
    1.33 +
    1.34 +waitForEvents = function () {
    1.35 +}
    1.36 +
    1.37 +waitForEvents.prototype = {
    1.38 +  /**
    1.39 +   * Initialize list of events for given node
    1.40 +   */
    1.41 +  init: function waitForEvents_init(node, events) {
    1.42 +    if (node.getNode != undefined)
    1.43 +      node = node.getNode();
    1.44 +
    1.45 +    this.events = events;
    1.46 +    this.node = node;
    1.47 +    node.firedEvents = {};
    1.48 +    this.registry = {};
    1.49 +
    1.50 +    for each (var e in events) {
    1.51 +      var listener = function (event) {
    1.52 +        this.firedEvents[event.type] = true;
    1.53 +      }
    1.54 +
    1.55 +      this.registry[e] = listener;
    1.56 +      this.registry[e].result = false;
    1.57 +      this.node.addEventListener(e, this.registry[e], true);
    1.58 +    }
    1.59 +  },
    1.60 +
    1.61 +  /**
    1.62 +   * Wait until all assigned events have been fired
    1.63 +   */
    1.64 +  wait: function waitForEvents_wait(timeout, interval) {
    1.65 +    for (var e in this.registry) {
    1.66 +      assert.waitFor(function () {
    1.67 +        return this.node.firedEvents[e] == true;
    1.68 +      }, "waitForEvents.wait(): Event '" + ex + "' has been fired.", timeout, interval);
    1.69 +
    1.70 +      this.node.removeEventListener(e, this.registry[e], true);
    1.71 +    }
    1.72 +  }
    1.73 +}
    1.74 +
    1.75 +/**
    1.76 + * Class to handle menus and context menus
    1.77 + *
    1.78 + * @constructor
    1.79 + * @param {MozMillController} controller
    1.80 + *        Mozmill controller of the window under test
    1.81 + * @param {string} menuSelector
    1.82 + *        jQuery like selector string of the element
    1.83 + * @param {object} document
    1.84 + *        Document to use for finding the menu
    1.85 + *        [optional - default: aController.window.document]
    1.86 + */
    1.87 +var Menu = function (controller, menuSelector, document) {
    1.88 +  this._controller = controller;
    1.89 +  this._menu = null;
    1.90 +
    1.91 +  document = document || controller.window.document;
    1.92 +  var node = document.querySelector(menuSelector);
    1.93 +  if (node) {
    1.94 +    // We don't unwrap nodes automatically yet (Bug 573185)
    1.95 +    node = node.wrappedJSObject || node;
    1.96 +    this._menu = new mozelement.Elem(node);
    1.97 +  } else {
    1.98 +    throw new Error("Menu element '" + menuSelector + "' not found.");
    1.99 +  }
   1.100 +}
   1.101 +
   1.102 +Menu.prototype = {
   1.103 +
   1.104 +  /**
   1.105 +   * Open and populate the menu
   1.106 +   *
   1.107 +   * @param {ElemBase} contextElement
   1.108 +   *        Element whose context menu has to be opened
   1.109 +   * @returns {Menu} The Menu instance
   1.110 +   */
   1.111 +  open: function Menu_open(contextElement) {
   1.112 +    // We have to open the context menu
   1.113 +    var menu = this._menu.getNode();
   1.114 +    if ((menu.localName == "popup" || menu.localName == "menupopup") &&
   1.115 +        contextElement && contextElement.exists()) {
   1.116 +      this._controller.rightClick(contextElement);
   1.117 +      assert.waitFor(function () {
   1.118 +        return menu.state == "open";
   1.119 +      }, "Context menu has been opened.");
   1.120 +    }
   1.121 +
   1.122 +    // Run through the entire menu and populate with dynamic entries
   1.123 +    this._buildMenu(menu);
   1.124 +
   1.125 +    return this;
   1.126 +  },
   1.127 +
   1.128 +  /**
   1.129 +   * Close the menu
   1.130 +   *
   1.131 +   * @returns {Menu} The Menu instance
   1.132 +   */
   1.133 +  close: function Menu_close() {
   1.134 +    var menu = this._menu.getNode();
   1.135 +
   1.136 +    this._controller.keypress(this._menu, "VK_ESCAPE", {});
   1.137 +    assert.waitFor(function () {
   1.138 +      return menu.state == "closed";
   1.139 +    }, "Context menu has been closed.");
   1.140 +
   1.141 +    return this;
   1.142 +  },
   1.143 +
   1.144 +  /**
   1.145 +   * Retrieve the specified menu entry
   1.146 +   *
   1.147 +   * @param {string} itemSelector
   1.148 +   *        jQuery like selector string of the menu item
   1.149 +   * @returns {ElemBase} Menu element
   1.150 +   * @throws Error If menu element has not been found
   1.151 +   */
   1.152 +  getItem: function Menu_getItem(itemSelector) {
   1.153 +    // Run through the entire menu and populate with dynamic entries
   1.154 +    this._buildMenu(this._menu.getNode());
   1.155 +
   1.156 +    var node = this._menu.getNode().querySelector(itemSelector);
   1.157 +
   1.158 +    if (!node) {
   1.159 +      throw new Error("Menu entry '" + itemSelector + "' not found.");
   1.160 +    }
   1.161 +
   1.162 +    return new mozelement.Elem(node);
   1.163 +  },
   1.164 +
   1.165 +  /**
   1.166 +   * Click the specified menu entry
   1.167 +   *
   1.168 +   * @param {string} itemSelector
   1.169 +   *        jQuery like selector string of the menu item
   1.170 +   *
   1.171 +   * @returns {Menu} The Menu instance
   1.172 +   */
   1.173 +  click: function Menu_click(itemSelector) {
   1.174 +    this._controller.click(this.getItem(itemSelector));
   1.175 +
   1.176 +    return this;
   1.177 +  },
   1.178 +
   1.179 +  /**
   1.180 +   * Synthesize a keypress against the menu
   1.181 +   *
   1.182 +   * @param {string} key
   1.183 +   *        Key to press
   1.184 +   * @param {object} modifier
   1.185 +   *        Key modifiers
   1.186 +   * @see MozMillController#keypress
   1.187 +   *
   1.188 +   * @returns {Menu} The Menu instance
   1.189 +   */
   1.190 +  keypress: function Menu_keypress(key, modifier) {
   1.191 +    this._controller.keypress(this._menu, key, modifier);
   1.192 +
   1.193 +    return this;
   1.194 +  },
   1.195 +
   1.196 +  /**
   1.197 +   * Opens the context menu, click the specified entry and
   1.198 +   * make sure that the menu has been closed.
   1.199 +   *
   1.200 +   * @param {string} itemSelector
   1.201 +   *        jQuery like selector string of the element
   1.202 +   * @param {ElemBase} contextElement
   1.203 +   *        Element whose context menu has to be opened
   1.204 +   *
   1.205 +   * @returns {Menu} The Menu instance
   1.206 +   */
   1.207 +  select: function Menu_select(itemSelector, contextElement) {
   1.208 +    this.open(contextElement);
   1.209 +    this.click(itemSelector);
   1.210 +    this.close();
   1.211 +  },
   1.212 +
   1.213 +  /**
   1.214 +   * Recursive function which iterates through all menu elements and
   1.215 +   * populates the menus with dynamic menu entries.
   1.216 +   *
   1.217 +   * @param {node} menu
   1.218 +   *        Top menu node whose elements have to be populated
   1.219 +   */
   1.220 +  _buildMenu: function Menu__buildMenu(menu) {
   1.221 +    var items = menu ? menu.childNodes : null;
   1.222 +
   1.223 +    Array.forEach(items, function (item) {
   1.224 +      // When we have a menu node, fake a click onto it to populate
   1.225 +      // the sub menu with dynamic entries
   1.226 +      if (item.tagName == "menu") {
   1.227 +        var popup = item.querySelector("menupopup");
   1.228 +
   1.229 +        if (popup) {
   1.230 +          var popupEvent = this._controller.window.document.createEvent("MouseEvent");
   1.231 +          popupEvent.initMouseEvent("popupshowing", true, true,
   1.232 +                                    this._controller.window, 0, 0, 0, 0, 0,
   1.233 +                                    false, false, false, false, 0, null);
   1.234 +          popup.dispatchEvent(popupEvent);
   1.235 +
   1.236 +          this._buildMenu(popup);
   1.237 +        }
   1.238 +      }
   1.239 +    }, this);
   1.240 +  }
   1.241 +};
   1.242 +
   1.243 +var MozMillController = function (window) {
   1.244 +  this.window = window;
   1.245 +
   1.246 +  this.mozmillModule = {};
   1.247 +  Cu.import('resource://mozmill/driver/mozmill.js', this.mozmillModule);
   1.248 +
   1.249 +  var self = this;
   1.250 +  assert.waitFor(function () {
   1.251 +    return window != null && self.isLoaded();
   1.252 +  }, "controller(): Window has been initialized.");
   1.253 +
   1.254 +  // Ensure to focus the window which will move it virtually into the foreground
   1.255 +  // when focusmanager.testmode is set enabled.
   1.256 +  this.window.focus();
   1.257 +
   1.258 +  var windowType = window.document.documentElement.getAttribute('windowtype');
   1.259 +  if (controllerAdditions[windowType] != undefined ) {
   1.260 +    this.prototype = new utils.Copy(this.prototype);
   1.261 +    controllerAdditions[windowType](this);
   1.262 +    this.windowtype = windowType;
   1.263 +  }
   1.264 +}
   1.265 +
   1.266 +/**
   1.267 + * Returns the global browser object of the window
   1.268 + *
   1.269 + * @returns {Object} The browser object
   1.270 + */
   1.271 +MozMillController.prototype.__defineGetter__("browserObject", function () {
   1.272 +  return utils.getBrowserObject(this.window);
   1.273 +});
   1.274 +
   1.275 +// constructs a MozMillElement from the controller's window
   1.276 +MozMillController.prototype.__defineGetter__("rootElement", function () {
   1.277 +  if (this._rootElement == undefined) {
   1.278 +    let docElement = this.window.document.documentElement;
   1.279 +    this._rootElement = new mozelement.MozMillElement("Elem", docElement);
   1.280 +  }
   1.281 +
   1.282 +  return this._rootElement;
   1.283 +});
   1.284 +
   1.285 +MozMillController.prototype.sleep = utils.sleep;
   1.286 +MozMillController.prototype.waitFor = assert.waitFor;
   1.287 +
   1.288 +// Open the specified url in the current tab
   1.289 +MozMillController.prototype.open = function (url) {
   1.290 +  switch (this.mozmillModule.Application) {
   1.291 +    case "Firefox":
   1.292 +    case "MetroFirefox":
   1.293 +      // Stop a running page load to not overlap requests
   1.294 +      if (this.browserObject.selectedBrowser) {
   1.295 +        this.browserObject.selectedBrowser.stop();
   1.296 +      }
   1.297 +
   1.298 +      this.browserObject.loadURI(url);
   1.299 +      break;
   1.300 +
   1.301 +    default:
   1.302 +      throw new Error("MozMillController.open not supported.");
   1.303 +  }
   1.304 +
   1.305 +  broker.pass({'function':'Controller.open()'});
   1.306 +}
   1.307 +
   1.308 +/**
   1.309 + * Take a screenshot of specified node
   1.310 + *
   1.311 + * @param {Element} node
   1.312 + *        The window or DOM element to capture
   1.313 + * @param {String} name
   1.314 + *        The name of the screenshot used in reporting and as filename
   1.315 + * @param {Boolean} save
   1.316 + *        If true saves the screenshot as 'name.jpg' in tempdir,
   1.317 + *        otherwise returns a dataURL
   1.318 + * @param {Element[]} highlights
   1.319 + *        A list of DOM elements to highlight by drawing a red rectangle around them
   1.320 + *
   1.321 + * @returns {Object} Object which contains properties like filename, dataURL,
   1.322 + *          name and timestamp of the screenshot
   1.323 + */
   1.324 +MozMillController.prototype.screenshot = function (node, name, save, highlights) {
   1.325 +  if (!node) {
   1.326 +    throw new Error("node is undefined");
   1.327 +  }
   1.328 +
   1.329 +  // Unwrap the node and highlights
   1.330 +  if ("getNode" in node) {
   1.331 +    node = node.getNode();
   1.332 +  }
   1.333 +
   1.334 +  if (highlights) {
   1.335 +    for (var i = 0; i < highlights.length; ++i) {
   1.336 +      if ("getNode" in highlights[i]) {
   1.337 +        highlights[i] = highlights[i].getNode();
   1.338 +      }
   1.339 +    }
   1.340 +  }
   1.341 +
   1.342 +  // If save is false, a dataURL is used
   1.343 +  // Include both in the report anyway to avoid confusion and make the report easier to parse
   1.344 +  var screenshot = {"filename": undefined,
   1.345 +                    "dataURL": utils.takeScreenshot(node, highlights),
   1.346 +                    "name": name,
   1.347 +                    "timestamp": new Date().toLocaleString()};
   1.348 +
   1.349 +  if (!save) {
   1.350 +    return screenshot;
   1.351 +  }
   1.352 +
   1.353 +  // Save the screenshot to disk
   1.354 +
   1.355 +  let {filename, failure} = utils.saveDataURL(screenshot.dataURL, name);
   1.356 +  screenshot.filename = filename;
   1.357 +  screenshot.failure = failure;
   1.358 +
   1.359 +  if (failure) {
   1.360 +    broker.log({'function': 'controller.screenshot()',
   1.361 +                'message': 'Error writing to file: ' + screenshot.filename});
   1.362 +  } else {
   1.363 +    // Send the screenshot object to python over jsbridge
   1.364 +    broker.sendMessage("screenshot", screenshot);
   1.365 +    broker.pass({'function': 'controller.screenshot()'});
   1.366 +  }
   1.367 +
   1.368 +  return screenshot;
   1.369 +}
   1.370 +
   1.371 +/**
   1.372 + * Checks if the specified window has been loaded
   1.373 + *
   1.374 + * @param {DOMWindow} [aWindow=this.window] Window object to check for loaded state
   1.375 + */
   1.376 +MozMillController.prototype.isLoaded = function (aWindow) {
   1.377 +  var win = aWindow || this.window;
   1.378 +
   1.379 +  return windows.map.getValue(utils.getWindowId(win), "loaded") || false;
   1.380 +};
   1.381 +
   1.382 +MozMillController.prototype.__defineGetter__("waitForEvents", function () {
   1.383 +  if (this._waitForEvents == undefined) {
   1.384 +    this._waitForEvents = new waitForEvents();
   1.385 +  }
   1.386 +
   1.387 +  return this._waitForEvents;
   1.388 +});
   1.389 +
   1.390 +/**
   1.391 + * Wrapper function to create a new instance of a menu
   1.392 + * @see Menu
   1.393 + */
   1.394 +MozMillController.prototype.getMenu = function (menuSelector, document) {
   1.395 +  return new Menu(this, menuSelector, document);
   1.396 +};
   1.397 +
   1.398 +MozMillController.prototype.__defineGetter__("mainMenu", function () {
   1.399 +  return this.getMenu("menubar");
   1.400 +});
   1.401 +
   1.402 +MozMillController.prototype.__defineGetter__("menus", function () {
   1.403 +  logDeprecated('controller.menus', 'Use controller.mainMenu instead');
   1.404 +});
   1.405 +
   1.406 +MozMillController.prototype.waitForImage = function (aElement, timeout, interval) {
   1.407 +  this.waitFor(function () {
   1.408 +    return aElement.getNode().complete == true;
   1.409 +  }, "timeout exceeded for waitForImage " + aElement.getInfo(), timeout, interval);
   1.410 +
   1.411 +  broker.pass({'function':'Controller.waitForImage()'});
   1.412 +}
   1.413 +
   1.414 +MozMillController.prototype.startUserShutdown = function (timeout, restart, next, resetProfile) {
   1.415 +  if (restart && resetProfile) {
   1.416 +    throw new Error("You can't have a user-restart and reset the profile; there is a race condition");
   1.417 +  }
   1.418 +
   1.419 +  let shutdownObj = {
   1.420 +    'user': true,
   1.421 +    'restart': Boolean(restart),
   1.422 +    'next': next,
   1.423 +    'resetProfile': Boolean(resetProfile),
   1.424 +    'timeout': timeout
   1.425 +  };
   1.426 +
   1.427 +  broker.sendMessage('shutdown', shutdownObj);
   1.428 +}
   1.429 +
   1.430 +/**
   1.431 + * Restart the application
   1.432 + *
   1.433 + * @param {string} aNext
   1.434 + *        Name of the next test function to run after restart
   1.435 + * @param {boolean} [aFlags=undefined]
   1.436 + *        Additional flags how to handle the shutdown or restart. The attributes
   1.437 + *        eRestarti386 (0x20) and eRestartx86_64 (0x30) have not been documented yet.
   1.438 + * @see https://developer.mozilla.org/nsIAppStartup#Attributes
   1.439 + */
   1.440 +MozMillController.prototype.restartApplication = function (aNext, aFlags) {
   1.441 +  var flags = Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart;
   1.442 +
   1.443 +  if (aFlags) {
   1.444 +    flags |= aFlags;
   1.445 +  }
   1.446 +
   1.447 +  broker.sendMessage('shutdown', {'user': false,
   1.448 +                                  'restart': true,
   1.449 +                                  'flags': flags,
   1.450 +                                  'next': aNext,
   1.451 +                                  'timeout': 0 });
   1.452 +
   1.453 +  // We have to ensure to stop the test from continuing until the application is
   1.454 +  // shutting down. The only way to do that is by throwing an exception.
   1.455 +  throw new errors.ApplicationQuitError();
   1.456 +}
   1.457 +
   1.458 +/**
   1.459 + * Stop the application
   1.460 + *
   1.461 + * @param {boolean} [aResetProfile=false]
   1.462 + *        Whether to reset the profile during restart
   1.463 + * @param {boolean} [aFlags=undefined]
   1.464 + *        Additional flags how to handle the shutdown or restart. The attributes
   1.465 + *        eRestarti386 and eRestartx86_64 have not been documented yet.
   1.466 + * @see https://developer.mozilla.org/nsIAppStartup#Attributes
   1.467 + */
   1.468 +MozMillController.prototype.stopApplication = function (aResetProfile, aFlags) {
   1.469 +  var flags = Ci.nsIAppStartup.eAttemptQuit;
   1.470 +
   1.471 +  if (aFlags) {
   1.472 +    flags |= aFlags;
   1.473 +  }
   1.474 +
   1.475 +  broker.sendMessage('shutdown', {'user': false,
   1.476 +                                  'restart': false,
   1.477 +                                  'flags': flags,
   1.478 +                                  'resetProfile': aResetProfile,
   1.479 +                                  'timeout': 0 });
   1.480 +
   1.481 +  // We have to ensure to stop the test from continuing until the application is
   1.482 +  // shutting down. The only way to do that is by throwing an exception.
   1.483 +  throw new errors.ApplicationQuitError();
   1.484 +}
   1.485 +
   1.486 +//Browser navigation functions
   1.487 +MozMillController.prototype.goBack = function () {
   1.488 +  this.window.content.history.back();
   1.489 +  broker.pass({'function':'Controller.goBack()'});
   1.490 +
   1.491 +  return true;
   1.492 +}
   1.493 +
   1.494 +MozMillController.prototype.goForward = function () {
   1.495 +  this.window.content.history.forward();
   1.496 +  broker.pass({'function':'Controller.goForward()'});
   1.497 +
   1.498 +  return true;
   1.499 +}
   1.500 +
   1.501 +MozMillController.prototype.refresh = function () {
   1.502 +  this.window.content.location.reload(true);
   1.503 +  broker.pass({'function':'Controller.refresh()'});
   1.504 +
   1.505 +  return true;
   1.506 +}
   1.507 +
   1.508 +function logDeprecated(funcName, message) {
   1.509 +  broker.log({'function': funcName + '() - DEPRECATED',
   1.510 +              'message': funcName + '() is deprecated. ' + message});
   1.511 +}
   1.512 +
   1.513 +function logDeprecatedAssert(funcName) {
   1.514 +   logDeprecated('controller.' + funcName,
   1.515 +                 '. Use the generic `assertion` module instead.');
   1.516 +}
   1.517 +
   1.518 +MozMillController.prototype.assertText = function (el, text) {
   1.519 +  logDeprecatedAssert("assertText");
   1.520 +
   1.521 +  var n = el.getNode();
   1.522 +
   1.523 +  if (n && n.innerHTML == text) {
   1.524 +    broker.pass({'function': 'Controller.assertText()'});
   1.525 +  } else {
   1.526 +    throw new Error("could not validate element " + el.getInfo() +
   1.527 +                    " with text "+ text);
   1.528 +  }
   1.529 +
   1.530 +  return true;
   1.531 +};
   1.532 +
   1.533 +/**
   1.534 + * Assert that a specified node exists
   1.535 + */
   1.536 +MozMillController.prototype.assertNode = function (el) {
   1.537 +  logDeprecatedAssert("assertNode");
   1.538 +
   1.539 +  //this.window.focus();
   1.540 +  var element = el.getNode();
   1.541 +  if (!element) {
   1.542 +    throw new Error("could not find element " + el.getInfo());
   1.543 +  }
   1.544 +
   1.545 +  broker.pass({'function': 'Controller.assertNode()'});
   1.546 +  return true;
   1.547 +};
   1.548 +
   1.549 +/**
   1.550 + * Assert that a specified node doesn't exist
   1.551 + */
   1.552 +MozMillController.prototype.assertNodeNotExist = function (el) {
   1.553 +  logDeprecatedAssert("assertNodeNotExist");
   1.554 +
   1.555 +  try {
   1.556 +    var element = el.getNode();
   1.557 +  } catch (e) {
   1.558 +    broker.pass({'function': 'Controller.assertNodeNotExist()'});
   1.559 +  }
   1.560 +
   1.561 +  if (element) {
   1.562 +    throw new Error("Unexpectedly found element " + el.getInfo());
   1.563 +  } else {
   1.564 +    broker.pass({'function':'Controller.assertNodeNotExist()'});
   1.565 +  }
   1.566 +
   1.567 +  return true;
   1.568 +};
   1.569 +
   1.570 +/**
   1.571 + * Assert that a form element contains the expected value
   1.572 + */
   1.573 +MozMillController.prototype.assertValue = function (el, value) {
   1.574 +  logDeprecatedAssert("assertValue");
   1.575 +
   1.576 +  var n = el.getNode();
   1.577 +
   1.578 +  if (n && n.value == value) {
   1.579 +    broker.pass({'function': 'Controller.assertValue()'});
   1.580 +  } else {
   1.581 +    throw new Error("could not validate element " + el.getInfo() +
   1.582 +                    " with value " + value);
   1.583 +  }
   1.584 +
   1.585 +  return false;
   1.586 +};
   1.587 +
   1.588 +/**
   1.589 + * Check if the callback function evaluates to true
   1.590 + */
   1.591 +MozMillController.prototype.assert = function (callback, message, thisObject) {
   1.592 +  logDeprecatedAssert("assert");
   1.593 +
   1.594 +  utils.assert(callback, message, thisObject);
   1.595 +  broker.pass({'function': ": controller.assert('" + callback + "')"});
   1.596 +
   1.597 +  return true;
   1.598 +}
   1.599 +
   1.600 +/**
   1.601 + * Assert that a provided value is selected in a select element
   1.602 + */
   1.603 +MozMillController.prototype.assertSelected = function (el, value) {
   1.604 +  logDeprecatedAssert("assertSelected");
   1.605 +
   1.606 +  var n = el.getNode();
   1.607 +  var validator = value;
   1.608 +
   1.609 +  if (n && n.options[n.selectedIndex].value == validator) {
   1.610 +    broker.pass({'function':'Controller.assertSelected()'});
   1.611 +  } else {
   1.612 +    throw new Error("could not assert value for element " + el.getInfo() +
   1.613 +                    " with value " + value);
   1.614 +  }
   1.615 +
   1.616 +  return true;
   1.617 +};
   1.618 +
   1.619 +/**
   1.620 + * Assert that a provided checkbox is checked
   1.621 + */
   1.622 +MozMillController.prototype.assertChecked = function (el) {
   1.623 +  logDeprecatedAssert("assertChecked");
   1.624 +
   1.625 +  var element = el.getNode();
   1.626 +
   1.627 +  if (element && element.checked == true) {
   1.628 +    broker.pass({'function':'Controller.assertChecked()'});
   1.629 +  } else {
   1.630 +    throw new Error("assert failed for checked element " + el.getInfo());
   1.631 +  }
   1.632 +
   1.633 +  return true;
   1.634 +};
   1.635 +
   1.636 +/**
   1.637 + * Assert that a provided checkbox is not checked
   1.638 + */
   1.639 +MozMillController.prototype.assertNotChecked = function (el) {
   1.640 +  logDeprecatedAssert("assertNotChecked");
   1.641 +
   1.642 +  var element = el.getNode();
   1.643 +
   1.644 +  if (!element) {
   1.645 +    throw new Error("Could not find element" + el.getInfo());
   1.646 +  }
   1.647 +
   1.648 +  if (!element.hasAttribute("checked") || element.checked != true) {
   1.649 +    broker.pass({'function': 'Controller.assertNotChecked()'});
   1.650 +  } else {
   1.651 +    throw new Error("assert failed for not checked element " + el.getInfo());
   1.652 +  }
   1.653 +
   1.654 +  return true;
   1.655 +};
   1.656 +
   1.657 +/**
   1.658 + * Assert that an element's javascript property exists or has a particular value
   1.659 + *
   1.660 + * if val is undefined, will return true if the property exists.
   1.661 + * if val is specified, will return true if the property exists and has the correct value
   1.662 + */
   1.663 +MozMillController.prototype.assertJSProperty = function (el, attrib, val) {
   1.664 +  logDeprecatedAssert("assertJSProperty");
   1.665 +
   1.666 +  var element = el.getNode();
   1.667 +
   1.668 +  if (!element){
   1.669 +    throw new Error("could not find element " + el.getInfo());
   1.670 +  }
   1.671 +
   1.672 +  var value = element[attrib];
   1.673 +  var res = (value !== undefined && (val === undefined ? true :
   1.674 +                                                         String(value) == String(val)));
   1.675 +  if (res) {
   1.676 +    broker.pass({'function':'Controller.assertJSProperty("' + el.getInfo() + '") : ' + val});
   1.677 +  } else {
   1.678 +    throw new Error("Controller.assertJSProperty(" + el.getInfo() + ") : " +
   1.679 +                    (val === undefined ? "property '" + attrib +
   1.680 +                    "' doesn't exist" : val + " == " + value));
   1.681 +  }
   1.682 +
   1.683 +  return true;
   1.684 +};
   1.685 +
   1.686 +/**
   1.687 + * Assert that an element's javascript property doesn't exist or doesn't have a particular value
   1.688 + *
   1.689 + * if val is undefined, will return true if the property doesn't exist.
   1.690 + * if val is specified, will return true if the property doesn't exist or doesn't have the specified value
   1.691 + */
   1.692 +MozMillController.prototype.assertNotJSProperty = function (el, attrib, val) {
   1.693 +  logDeprecatedAssert("assertNotJSProperty");
   1.694 +
   1.695 +  var element = el.getNode();
   1.696 +
   1.697 +  if (!element){
   1.698 +    throw new Error("could not find element " + el.getInfo());
   1.699 +  }
   1.700 +
   1.701 +  var value = element[attrib];
   1.702 +  var res = (val === undefined ? value === undefined : String(value) != String(val));
   1.703 +  if (res) {
   1.704 +    broker.pass({'function':'Controller.assertNotProperty("' + el.getInfo() + '") : ' + val});
   1.705 +  } else {
   1.706 +    throw new Error("Controller.assertNotJSProperty(" + el.getInfo() + ") : " +
   1.707 +                    (val === undefined ? "property '" + attrib +
   1.708 +                    "' exists" : val + " != " + value));
   1.709 +  }
   1.710 +
   1.711 +  return true;
   1.712 +};
   1.713 +
   1.714 +/**
   1.715 + * Assert that an element's dom property exists or has a particular value
   1.716 + *
   1.717 + * if val is undefined, will return true if the property exists.
   1.718 + * if val is specified, will return true if the property exists and has the correct value
   1.719 + */
   1.720 +MozMillController.prototype.assertDOMProperty = function (el, attrib, val) {
   1.721 +  logDeprecatedAssert("assertDOMProperty");
   1.722 +
   1.723 +  var element = el.getNode();
   1.724 +
   1.725 +  if (!element){
   1.726 +    throw new Error("could not find element " + el.getInfo());
   1.727 +  }
   1.728 +
   1.729 +  var value, res = element.hasAttribute(attrib);
   1.730 +  if (res && val !== undefined) {
   1.731 +    value = element.getAttribute(attrib);
   1.732 +    res = (String(value) == String(val));
   1.733 +  }
   1.734 +
   1.735 +  if (res) {
   1.736 +    broker.pass({'function':'Controller.assertDOMProperty("' + el.getInfo() + '") : ' + val});
   1.737 +  } else {
   1.738 +    throw new Error("Controller.assertDOMProperty(" + el.getInfo() + ") : " +
   1.739 +                    (val === undefined ? "property '" + attrib +
   1.740 +                    "' doesn't exist" : val + " == " + value));
   1.741 +  }
   1.742 +
   1.743 +  return true;
   1.744 +};
   1.745 +
   1.746 +/**
   1.747 + * Assert that an element's dom property doesn't exist or doesn't have a particular value
   1.748 + *
   1.749 + * if val is undefined, will return true if the property doesn't exist.
   1.750 + * if val is specified, will return true if the property doesn't exist or doesn't have the specified value
   1.751 + */
   1.752 +MozMillController.prototype.assertNotDOMProperty = function (el, attrib, val) {
   1.753 +  logDeprecatedAssert("assertNotDOMProperty");
   1.754 +
   1.755 +  var element = el.getNode();
   1.756 +
   1.757 +  if (!element) {
   1.758 +    throw new Error("could not find element " + el.getInfo());
   1.759 +  }
   1.760 +
   1.761 +  var value, res = element.hasAttribute(attrib);
   1.762 +  if (res && val !== undefined) {
   1.763 +    value = element.getAttribute(attrib);
   1.764 +    res = (String(value) == String(val));
   1.765 +  }
   1.766 +
   1.767 +  if (!res) {
   1.768 +    broker.pass({'function':'Controller.assertNotDOMProperty("' + el.getInfo() + '") : ' + val});
   1.769 +  } else {
   1.770 +    throw new Error("Controller.assertNotDOMProperty(" + el.getInfo() + ") : " +
   1.771 +                    (val == undefined ? "property '" + attrib +
   1.772 +                    "' exists" : val + " == " + value));
   1.773 +  }
   1.774 +
   1.775 +  return true;
   1.776 +};
   1.777 +
   1.778 +/**
   1.779 + * Assert that a specified image has actually loaded. The Safari workaround results
   1.780 + * in additional requests for broken images (in Safari only) but works reliably
   1.781 + */
   1.782 +MozMillController.prototype.assertImageLoaded = function (el) {
   1.783 +  logDeprecatedAssert("assertImageLoaded");
   1.784 +
   1.785 +  var img = el.getNode();
   1.786 +
   1.787 +  if (!img || img.tagName != 'IMG') {
   1.788 +    throw new Error('Controller.assertImageLoaded() failed.')
   1.789 +    return false;
   1.790 +  }
   1.791 +
   1.792 +  var comp = img.complete;
   1.793 +  var ret = null; // Return value
   1.794 +
   1.795 +  // Workaround for Safari -- it only supports the
   1.796 +  // complete attrib on script-created images
   1.797 +  if (typeof comp == 'undefined') {
   1.798 +    test = new Image();
   1.799 +    // If the original image was successfully loaded,
   1.800 +    // src for new one should be pulled from cache
   1.801 +    test.src = img.src;
   1.802 +    comp = test.complete;
   1.803 +  }
   1.804 +
   1.805 +  // Check the complete attrib. Note the strict
   1.806 +  // equality check -- we don't want undefined, null, etc.
   1.807 +  // --------------------------
   1.808 +  if (comp === false) {
   1.809 +    // False -- Img failed to load in IE/Safari, or is
   1.810 +    // still trying to load in FF
   1.811 +    ret = false;
   1.812 +  } else if (comp === true && img.naturalWidth == 0) {
   1.813 +    // True, but image has no size -- image failed to
   1.814 +    // load in FF
   1.815 +    ret = false;
   1.816 +  } else {
   1.817 +    // Otherwise all we can do is assume everything's
   1.818 +    // hunky-dory
   1.819 +   ret = true;
   1.820 +  }
   1.821 +
   1.822 +  if (ret) {
   1.823 +    broker.pass({'function':'Controller.assertImageLoaded'});
   1.824 +  } else {
   1.825 +    throw new Error('Controller.assertImageLoaded() failed.')
   1.826 +  }
   1.827 +
   1.828 +  return true;
   1.829 +};
   1.830 +
   1.831 +/**
   1.832 + * Drag one element to the top x,y coords of another specified element
   1.833 + */
   1.834 +MozMillController.prototype.mouseMove = function (doc, start, dest) {
   1.835 +  // if one of these elements couldn't be looked up
   1.836 +  if (typeof start != 'object'){
   1.837 +    throw new Error("received bad coordinates");
   1.838 +  }
   1.839 +
   1.840 +  if (typeof dest != 'object'){
   1.841 +    throw new Error("received bad coordinates");
   1.842 +  }
   1.843 +
   1.844 +  var triggerMouseEvent = function (element, clientX, clientY) {
   1.845 +    clientX = clientX ? clientX: 0;
   1.846 +    clientY = clientY ? clientY: 0;
   1.847 +
   1.848 +    // make the mouse understand where it is on the screen
   1.849 +    var screenX = element.boxObject.screenX ? element.boxObject.screenX : 0;
   1.850 +    var screenY = element.boxObject.screenY ? element.boxObject.screenY : 0;
   1.851 +
   1.852 +    var evt = element.ownerDocument.createEvent('MouseEvents');
   1.853 +    if (evt.initMouseEvent) {
   1.854 +      evt.initMouseEvent('mousemove', true, true, element.ownerDocument.defaultView,
   1.855 +                         1, screenX, screenY, clientX, clientY);
   1.856 +    } else {
   1.857 +      evt.initEvent('mousemove', true, true);
   1.858 +    }
   1.859 +
   1.860 +    element.dispatchEvent(evt);
   1.861 +  };
   1.862 +
   1.863 +  // Do the initial move to the drag element position
   1.864 +  triggerMouseEvent(doc.body, start[0], start[1]);
   1.865 +  triggerMouseEvent(doc.body, dest[0], dest[1]);
   1.866 +
   1.867 +  broker.pass({'function':'Controller.mouseMove()'});
   1.868 +  return true;
   1.869 +}
   1.870 +
   1.871 +/**
   1.872 + * Drag an element to the specified offset on another element, firing mouse and
   1.873 + * drag events. Adapted from ChromeUtils.js synthesizeDrop()
   1.874 + *
   1.875 + * @deprecated Use the MozMillElement object
   1.876 + *
   1.877 + * @param {MozElement} aSrc
   1.878 + *        Source element to be dragged
   1.879 + * @param {MozElement} aDest
   1.880 + *        Destination element over which the drop occurs
   1.881 + * @param {Number} [aOffsetX=element.width/2]
   1.882 + *        Relative x offset for dropping on the aDest element
   1.883 + * @param {Number} [aOffsetY=element.height/2]
   1.884 + *        Relative y offset for dropping on the aDest element
   1.885 + * @param {DOMWindow} [aSourceWindow=this.element.ownerDocument.defaultView]
   1.886 + *        Custom source Window to be used.
   1.887 + * @param {String} [aDropEffect="move"]
   1.888 + *        Effect used for the drop event
   1.889 + * @param {Object[]} [aDragData]
   1.890 + *        An array holding custom drag data to be used during the drag event
   1.891 + *        Format: [{ type: "text/plain", "Text to drag"}, ...]
   1.892 + *
   1.893 + * @returns {String} the captured dropEffect
   1.894 + */
   1.895 +MozMillController.prototype.dragToElement = function (aSrc, aDest, aOffsetX,
   1.896 +                                                      aOffsetY, aSourceWindow,
   1.897 +                                                      aDropEffect, aDragData) {
   1.898 +  logDeprecated("controller.dragToElement", "Use the MozMillElement object.");
   1.899 +  return aSrc.dragToElement(aDest, aOffsetX, aOffsetY, aSourceWindow, null,
   1.900 +                            aDropEffect, aDragData);
   1.901 +};
   1.902 +
   1.903 +function Tabs(controller) {
   1.904 +  this.controller = controller;
   1.905 +}
   1.906 +
   1.907 +Tabs.prototype.getTab = function (index) {
   1.908 +  return this.controller.browserObject.browsers[index].contentDocument;
   1.909 +}
   1.910 +
   1.911 +Tabs.prototype.__defineGetter__("activeTab", function () {
   1.912 +  return this.controller.browserObject.selectedBrowser.contentDocument;
   1.913 +});
   1.914 +
   1.915 +Tabs.prototype.selectTab = function (index) {
   1.916 +  // GO in to tab manager and grab the tab by index and call focus.
   1.917 +}
   1.918 +
   1.919 +Tabs.prototype.findWindow = function (doc) {
   1.920 +  for (var i = 0; i <= (this.controller.window.frames.length - 1); i++) {
   1.921 +    if (this.controller.window.frames[i].document == doc) {
   1.922 +      return this.controller.window.frames[i];
   1.923 +    }
   1.924 +  }
   1.925 +
   1.926 +  throw new Error("Cannot find window for document. Doc title == " + doc.title);
   1.927 +}
   1.928 +
   1.929 +Tabs.prototype.getTabWindow = function (index) {
   1.930 +  return this.findWindow(this.getTab(index));
   1.931 +}
   1.932 +
   1.933 +Tabs.prototype.__defineGetter__("activeTabWindow", function () {
   1.934 +  return this.findWindow(this.activeTab);
   1.935 +});
   1.936 +
   1.937 +Tabs.prototype.__defineGetter__("length", function () {
   1.938 +  return this.controller.browserObject.browsers.length;
   1.939 +});
   1.940 +
   1.941 +Tabs.prototype.__defineGetter__("activeTabIndex", function () {
   1.942 +  var browser = this.controller.browserObject;
   1.943 +
   1.944 +  switch(this.controller.mozmillModule.Application) {
   1.945 +    case "MetroFirefox":
   1.946 +      return browser.tabs.indexOf(browser.selectedTab);
   1.947 +    case "Firefox":
   1.948 +    default:
   1.949 +      return browser.tabContainer.selectedIndex;
   1.950 +  }
   1.951 +});
   1.952 +
   1.953 +Tabs.prototype.selectTabIndex = function (aIndex) {
   1.954 +  var browser = this.controller.browserObject;
   1.955 +
   1.956 +  switch(this.controller.mozmillModule.Application) {
   1.957 +    case "MetroFirefox":
   1.958 +      browser.selectedTab = browser.tabs[aIndex];
   1.959 +      break;
   1.960 +    case "Firefox":
   1.961 +    default:
   1.962 +      browser.selectTabAtIndex(aIndex);
   1.963 +  }
   1.964 +}
   1.965 +
   1.966 +function browserAdditions (controller) {
   1.967 +  controller.tabs = new Tabs(controller);
   1.968 +
   1.969 +  controller.waitForPageLoad = function (aDocument, aTimeout, aInterval) {
   1.970 +    var timeout = aTimeout || 30000;
   1.971 +    var win = null;
   1.972 +    var timed_out = false;
   1.973 +
   1.974 +    // If a user tries to do waitForPageLoad(2000), this will assign the
   1.975 +    // interval the first arg which is most likely what they were expecting
   1.976 +    if (typeof(aDocument) == "number"){
   1.977 +      timeout = aDocument;
   1.978 +    }
   1.979 +
   1.980 +    // If we have a real document use its default view
   1.981 +    if (aDocument && (typeof(aDocument) === "object") &&
   1.982 +        "defaultView" in aDocument)
   1.983 +      win = aDocument.defaultView;
   1.984 +
   1.985 +    // If no document has been specified, fallback to the default view of the
   1.986 +    // currently selected tab browser
   1.987 +    win = win || this.browserObject.selectedBrowser.contentWindow;
   1.988 +
   1.989 +    // Wait until the content in the tab has been loaded
   1.990 +    try {
   1.991 +      this.waitFor(function () {
   1.992 +        return windows.map.hasPageLoaded(utils.getWindowId(win));
   1.993 +      }, "Timeout", timeout, aInterval);
   1.994 +    }
   1.995 +    catch (ex if ex instanceof errors.TimeoutError) {
   1.996 +      timed_out = true;
   1.997 +    }
   1.998 +    finally {
   1.999 +      state = 'URI=' + win.document.location.href +
  1.1000 +              ', readyState=' + win.document.readyState;
  1.1001 +      message = "controller.waitForPageLoad(" + state + ")";
  1.1002 +
  1.1003 +      if (timed_out) {
  1.1004 +        throw new errors.AssertionError(message);
  1.1005 +      }
  1.1006 +
  1.1007 +      broker.pass({'function': message});
  1.1008 +    }
  1.1009 +  }
  1.1010 +}
  1.1011 +
  1.1012 +var controllerAdditions = {
  1.1013 +  'navigator:browser'  :browserAdditions
  1.1014 +};
  1.1015 +
  1.1016 +/**
  1.1017 + *  DEPRECATION WARNING
  1.1018 + *
  1.1019 + * The following methods have all been DEPRECATED as of Mozmill 2.0
  1.1020 + */
  1.1021 +MozMillController.prototype.assertProperty = function (el, attrib, val) {
  1.1022 +  logDeprecatedAssert("assertProperty");
  1.1023 +
  1.1024 +  return this.assertJSProperty(el, attrib, val);
  1.1025 +};
  1.1026 +
  1.1027 +MozMillController.prototype.assertPropertyNotExist = function (el, attrib) {
  1.1028 +  logDeprecatedAssert("assertPropertyNotExist");
  1.1029 +  return this.assertNotJSProperty(el, attrib);
  1.1030 +};
  1.1031 +
  1.1032 +/**
  1.1033 + *  DEPRECATION WARNING
  1.1034 + *
  1.1035 + * The following methods have all been DEPRECATED as of Mozmill 2.0
  1.1036 + * Use the MozMillElement object instead (https://developer.mozilla.org/en/Mozmill/Mozmill_Element_Object)
  1.1037 + */
  1.1038 +MozMillController.prototype.select = function (aElement, index, option, value) {
  1.1039 +  logDeprecated("controller.select", "Use the MozMillElement object.");
  1.1040 +
  1.1041 +  return aElement.select(index, option, value);
  1.1042 +};
  1.1043 +
  1.1044 +MozMillController.prototype.keypress = function (aElement, aKey, aModifiers, aExpectedEvent) {
  1.1045 +  logDeprecated("controller.keypress", "Use the MozMillElement object.");
  1.1046 +
  1.1047 +  if (!aElement) {
  1.1048 +    aElement = new mozelement.MozMillElement("Elem", this.window);
  1.1049 +  }
  1.1050 +
  1.1051 +  return aElement.keypress(aKey, aModifiers, aExpectedEvent);
  1.1052 +}
  1.1053 +
  1.1054 +MozMillController.prototype.type = function (aElement, aText, aExpectedEvent) {
  1.1055 +  logDeprecated("controller.type", "Use the MozMillElement object.");
  1.1056 +
  1.1057 +  if (!aElement) {
  1.1058 +    aElement = new mozelement.MozMillElement("Elem", this.window);
  1.1059 +  }
  1.1060 +
  1.1061 +  var that = this;
  1.1062 +  var retval = true;
  1.1063 +  Array.forEach(aText, function (letter) {
  1.1064 +    if (!that.keypress(aElement, letter, {}, aExpectedEvent)) {
  1.1065 +      retval = false; }
  1.1066 +  });
  1.1067 +
  1.1068 +  return retval;
  1.1069 +}
  1.1070 +
  1.1071 +MozMillController.prototype.mouseEvent = function (aElement, aOffsetX, aOffsetY, aEvent, aExpectedEvent) {
  1.1072 +  logDeprecated("controller.mouseEvent", "Use the MozMillElement object.");
  1.1073 +
  1.1074 +  return aElement.mouseEvent(aOffsetX, aOffsetY, aEvent, aExpectedEvent);
  1.1075 +}
  1.1076 +
  1.1077 +MozMillController.prototype.click = function (aElement, left, top, expectedEvent) {
  1.1078 +  logDeprecated("controller.click", "Use the MozMillElement object.");
  1.1079 +
  1.1080 +  return aElement.click(left, top, expectedEvent);
  1.1081 +}
  1.1082 +
  1.1083 +MozMillController.prototype.doubleClick = function (aElement, left, top, expectedEvent) {
  1.1084 +  logDeprecated("controller.doubleClick", "Use the MozMillElement object.");
  1.1085 +
  1.1086 +  return aElement.doubleClick(left, top, expectedEvent);
  1.1087 +}
  1.1088 +
  1.1089 +MozMillController.prototype.mouseDown = function (aElement, button, left, top, expectedEvent) {
  1.1090 +  logDeprecated("controller.mouseDown", "Use the MozMillElement object.");
  1.1091 +
  1.1092 +  return aElement.mouseDown(button, left, top, expectedEvent);
  1.1093 +};
  1.1094 +
  1.1095 +MozMillController.prototype.mouseOut = function (aElement, button, left, top, expectedEvent) {
  1.1096 +  logDeprecated("controller.mouseOut", "Use the MozMillElement object.");
  1.1097 +
  1.1098 +  return aElement.mouseOut(button, left, top, expectedEvent);
  1.1099 +};
  1.1100 +
  1.1101 +MozMillController.prototype.mouseOver = function (aElement, button, left, top, expectedEvent) {
  1.1102 +  logDeprecated("controller.mouseOver", "Use the MozMillElement object.");
  1.1103 +
  1.1104 +  return aElement.mouseOver(button, left, top, expectedEvent);
  1.1105 +};
  1.1106 +
  1.1107 +MozMillController.prototype.mouseUp = function (aElement, button, left, top, expectedEvent) {
  1.1108 +  logDeprecated("controller.mouseUp", "Use the MozMillElement object.");
  1.1109 +
  1.1110 +  return aElement.mouseUp(button, left, top, expectedEvent);
  1.1111 +};
  1.1112 +
  1.1113 +MozMillController.prototype.middleClick = function (aElement, left, top, expectedEvent) {
  1.1114 +  logDeprecated("controller.middleClick", "Use the MozMillElement object.");
  1.1115 +
  1.1116 +  return aElement.middleClick(aElement, left, top, expectedEvent);
  1.1117 +}
  1.1118 +
  1.1119 +MozMillController.prototype.rightClick = function (aElement, left, top, expectedEvent) {
  1.1120 +  logDeprecated("controller.rightClick", "Use the MozMillElement object.");
  1.1121 +
  1.1122 +  return aElement.rightClick(left, top, expectedEvent);
  1.1123 +}
  1.1124 +
  1.1125 +MozMillController.prototype.check = function (aElement, state) {
  1.1126 +  logDeprecated("controller.check", "Use the MozMillElement object.");
  1.1127 +
  1.1128 +  return aElement.check(state);
  1.1129 +}
  1.1130 +
  1.1131 +MozMillController.prototype.radio = function (aElement) {
  1.1132 +  logDeprecated("controller.radio", "Use the MozMillElement object.");
  1.1133 +
  1.1134 +  return aElement.select();
  1.1135 +}
  1.1136 +
  1.1137 +MozMillController.prototype.waitThenClick = function (aElement, timeout, interval) {
  1.1138 +  logDeprecated("controller.waitThenClick", "Use the MozMillElement object.");
  1.1139 +
  1.1140 +  return aElement.waitThenClick(timeout, interval);
  1.1141 +}
  1.1142 +
  1.1143 +MozMillController.prototype.waitForElement = function (aElement, timeout, interval) {
  1.1144 +  logDeprecated("controller.waitForElement", "Use the MozMillElement object.");
  1.1145 +
  1.1146 +  return aElement.waitForElement(timeout, interval);
  1.1147 +}
  1.1148 +
  1.1149 +MozMillController.prototype.waitForElementNotPresent = function (aElement, timeout, interval) {
  1.1150 +  logDeprecated("controller.waitForElementNotPresent", "Use the MozMillElement object.");
  1.1151 +
  1.1152 +  return aElement.waitForElementNotPresent(timeout, interval);
  1.1153 +}

mercurial