// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

/**
 * @fileoverview The file contains the base class for input devices such as
 * the keyboard, mouse, and touchscreen.
 */

goog.provide('bot.Device');
goog.provide('bot.Device.EventEmitter');

goog.require('bot');
goog.require('bot.Error');
goog.require('bot.ErrorCode');
goog.require('bot.dom');
goog.require('bot.events');
goog.require('bot.locators');
goog.require('bot.userAgent');
goog.require('goog.array');
goog.require('goog.dom');
goog.require('goog.dom.TagName');
goog.require('goog.userAgent');
goog.require('goog.userAgent.product');



/**
 * A Device class that provides common functionality for input devices.
 * @param {bot.Device.ModifiersState=} opt_modifiersState state of modifier
 * keys. The state is shared, not copied from this parameter.
 * @param {bot.Device.EventEmitter=} opt_eventEmitter An object that should be
 *     used to fire events.
 * @constructor
 */
bot.Device = function (opt_modifiersState, opt_eventEmitter) {
  /**
   * Element being interacted with.
   * @private {!Element}
   */
  this.element_ = bot.getDocument().documentElement;

  /**
   * If the element is an option, this is its parent select element.
   * @private {Element}
   */
  this.select_ = null;

  // If there is an active element, make that the current element instead.
  var activeElement = bot.dom.getActiveElement(this.element_);
  if (activeElement) {
    this.setElement(activeElement);
  }

  /**
   * State of modifier keys for this device.
   * @protected {bot.Device.ModifiersState}
   */
  this.modifiersState = opt_modifiersState || new bot.Device.ModifiersState();

  /** @protected {!bot.Device.EventEmitter} */
  this.eventEmitter = opt_eventEmitter || new bot.Device.EventEmitter();
};


/**
 * Returns the element with which the device is interacting.
 *
 * @return {!Element} Element being interacted with.
 * @protected
 */
bot.Device.prototype.getElement = function () {
  return this.element_;
};


/**
 * Sets the element with which the device is interacting.
 *
 * @param {!Element} element Element being interacted with.
 * @protected
 */
bot.Device.prototype.setElement = function (element) {
  this.element_ = element;
  if (bot.dom.isElement(element, goog.dom.TagName.OPTION)) {
    this.select_ = /** @type {Element} */ (goog.dom.getAncestor(element,
      function (node) {
        return bot.dom.isElement(node, goog.dom.TagName.SELECT);
      }));
  } else {
    this.select_ = null;
  }
};


/**
 * Fires an HTML event given the state of the device.
 *
 * @param {!bot.events.EventFactory_} type HTML Event type.
 * @return {boolean} Whether the event fired successfully; false if cancelled.
 * @protected
 */
bot.Device.prototype.fireHtmlEvent = function (type) {
  return this.eventEmitter.fireHtmlEvent(this.element_, type);
};


/**
 * Fires a keyboard event given the state of the device and the given arguments.
 * TODO: Populate the modifier keys in this method.
 *
 * @param {!bot.events.EventFactory_} type Keyboard event type.
 * @param {bot.events.KeyboardArgs} args Keyboard event arguments.
 * @return {boolean} Whether the event fired successfully; false if cancelled.
 * @protected
 */
bot.Device.prototype.fireKeyboardEvent = function (type, args) {
  return this.eventEmitter.fireKeyboardEvent(this.element_, type, args);
};


/**
 * Fires a mouse event given the state of the device and the given arguments.
 * TODO: Populate the modifier keys in this method.
 *
 * @param {!bot.events.EventFactory_} type Mouse event type.
 * @param {!goog.math.Coordinate} coord The coordinate where event will fire.
 * @param {number} button The mouse button value for the event.
 * @param {Element=} opt_related The related element of this event.
 * @param {?number=} opt_wheelDelta The wheel delta value for the event.
 * @param {boolean=} opt_force Whether the event should be fired even if the
 *     element is not interactable, such as the case of a mousemove or
 *     mouseover event that immediately follows a mouseout.
 * @param {?number=} opt_pointerId The pointerId associated with the event.
 * @param {?number=} opt_count Number of clicks that have been performed.
 * @return {boolean} Whether the event fired successfully; false if cancelled.
 * @protected
 */
bot.Device.prototype.fireMouseEvent = function (type, coord, button,
  opt_related, opt_wheelDelta, opt_force, opt_pointerId, opt_count) {
  if (!opt_force && !bot.dom.isInteractable(this.element_)) {
    return false;
  }

  if (opt_related &&
    !(bot.events.EventType.MOUSEOVER == type ||
      bot.events.EventType.MOUSEOUT == type)) {
    throw new bot.Error(bot.ErrorCode.INVALID_ELEMENT_STATE,
      'Event type does not allow related target: ' + type);
  }

  var args = {
    clientX: coord.x,
    clientY: coord.y,
    button: button,
    altKey: this.modifiersState.isAltPressed(),
    ctrlKey: this.modifiersState.isControlPressed(),
    shiftKey: this.modifiersState.isShiftPressed(),
    metaKey: this.modifiersState.isMetaPressed(),
    wheelDelta: opt_wheelDelta || 0,
    relatedTarget: opt_related || null,
    count: opt_count || 1
  };

  var pointerId = opt_pointerId || bot.Device.MOUSE_MS_POINTER_ID;

  var target = this.element_;
  // On click and mousedown events, captured pointers are ignored and the
  // event always fires on the original element.
  if (type != bot.events.EventType.CLICK &&
    type != bot.events.EventType.MOUSEDOWN &&
    pointerId in bot.Device.pointerElementMap_) {
    target = bot.Device.pointerElementMap_[pointerId];
  } else if (this.select_) {
    target = this.getTargetOfOptionMouseEvent_(type);
  }
  return target ? this.eventEmitter.fireMouseEvent(target, type, args) : true;
};


/**
 * Fires a touch event given the state of the device and the given arguments.
 *
 * @param {!bot.events.EventFactory_} type Event type.
 * @param {number} id The touch identifier.
 * @param {!goog.math.Coordinate} coord The coordinate where event will fire.
 * @param {number=} opt_id2 The touch identifier of the second finger.
 * @param {!goog.math.Coordinate=} opt_coord2 The coordinate of the second
 *    finger, if any.
 * @return {boolean} Whether the event fired successfully or was cancelled.
 * @protected
 */
bot.Device.prototype.fireTouchEvent = function (type, id, coord, opt_id2,
  opt_coord2) {
  var args = {
    touches: [],
    targetTouches: [],
    changedTouches: [],
    altKey: this.modifiersState.isAltPressed(),
    ctrlKey: this.modifiersState.isControlPressed(),
    shiftKey: this.modifiersState.isShiftPressed(),
    metaKey: this.modifiersState.isMetaPressed(),
    relatedTarget: null,
    scale: 0,
    rotation: 0
  };
  var pageOffset = goog.dom.getDomHelper(this.element_).getDocumentScroll();

  function addTouch(identifier, coords) {
    // Android devices leave identifier to zero.
    var touch = {
      identifier: identifier,
      screenX: coords.x,
      screenY: coords.y,
      clientX: coords.x,
      clientY: coords.y,
      pageX: coords.x + pageOffset.x,
      pageY: coords.y + pageOffset.y
    };

    args.changedTouches.push(touch);
    if (type == bot.events.EventType.TOUCHSTART ||
      type == bot.events.EventType.TOUCHMOVE) {
      args.touches.push(touch);
      args.targetTouches.push(touch);
    }
  }

  addTouch(id, coord);
  if (opt_id2 !== undefined) {
    addTouch(opt_id2, opt_coord2);
  }

  return this.eventEmitter.fireTouchEvent(this.element_, type, args);
};


/**
 * Fires a MSPointer event given the state of the device and the given
 * arguments.
 *
 * @param {!bot.events.EventFactory_} type MSPointer event type.
 * @param {!goog.math.Coordinate} coord The coordinate where event will fire.
 * @param {number} button The mouse button value for the event.
 * @param {number} pointerId The pointer id for this event.
 * @param {number} device The device type used for this event.
 * @param {boolean} isPrimary Whether the pointer represents the primary point
 *     of contact.
 * @param {Element=} opt_related The related element of this event.
 * @param {boolean=} opt_force Whether the event should be fired even if the
 *     element is not interactable, such as the case of a mousemove or
 *     mouseover event that immediately follows a mouseout.
 * @return {boolean} Whether the event fired successfully; false if cancelled.
 * @protected
 */
bot.Device.prototype.fireMSPointerEvent = function (type, coord, button,
  pointerId, device, isPrimary, opt_related, opt_force) {
  if (!opt_force && !bot.dom.isInteractable(this.element_)) {
    return false;
  }

  if (opt_related &&
    !(bot.events.EventType.MSPOINTEROVER == type ||
      bot.events.EventType.MSPOINTEROUT == type)) {
    throw new bot.Error(bot.ErrorCode.INVALID_ELEMENT_STATE,
      'Event type does not allow related target: ' + type);
  }

  var args = {
    clientX: coord.x,
    clientY: coord.y,
    button: button,
    altKey: false,
    ctrlKey: false,
    shiftKey: false,
    metaKey: false,
    relatedTarget: opt_related || null,
    width: 0,
    height: 0,
    pressure: 0, // Pressure is only given when a stylus is used.
    rotation: 0,
    pointerId: pointerId,
    tiltX: 0,
    tiltY: 0,
    pointerType: device,
    isPrimary: isPrimary
  };

  var target = this.select_ ?
    this.getTargetOfOptionMouseEvent_(type) : this.element_;
  if (bot.Device.pointerElementMap_[pointerId]) {
    target = bot.Device.pointerElementMap_[pointerId];
  }
  var owner = goog.dom.getWindow(goog.dom.getOwnerDocument(this.element_));
  var originalMsSetPointerCapture;
  if (owner && type == bot.events.EventType.MSPOINTERDOWN) {
    // Overwrite msSetPointerCapture on the Element's msSetPointerCapture
    // because synthetic pointer events cause an access denied exception.
    // The prototype is modified because the pointer event will bubble up and
    // we do not know which element will handle the pointer event.
    originalMsSetPointerCapture =
      owner['Element'].prototype.msSetPointerCapture;
    owner['Element'].prototype.msSetPointerCapture = function (id) {
      bot.Device.pointerElementMap_[id] = this;
    };
  }
  var result =
    target ? this.eventEmitter.fireMSPointerEvent(target, type, args) : true;
  if (originalMsSetPointerCapture) {
    owner['Element'].prototype.msSetPointerCapture =
      originalMsSetPointerCapture;
  }
  return result;
};


/**
 * A mouse event fired "on" an option element, doesn't always fire on the
 * option element itself. Sometimes it fires on the parent select element
 * and sometimes not at all, depending on the browser and event type. This
 * returns the true target element of the event, or null if none is fired.
 *
 * @param {!bot.events.EventFactory_} type Type of event.
 * @return {Element} Element the event should be fired on, null if none.
 * @private
 */
bot.Device.prototype.getTargetOfOptionMouseEvent_ = function (type) {
  // IE either fires the event on the parent select or not at all.
  if (goog.userAgent.IE) {
    switch (type) {
      case bot.events.EventType.MOUSEOVER:
      case bot.events.EventType.MSPOINTEROVER:
        return null;
      case bot.events.EventType.CONTEXTMENU:
      case bot.events.EventType.MOUSEMOVE:
      case bot.events.EventType.MSPOINTERMOVE:
        return this.select_.multiple ? this.select_ : null;
      default:
        return this.select_;
    }
  }

  // WebKit always fires on the option element of multi-selects.
  // On single-selects, it either fires on the parent or not at all.
  if (goog.userAgent.WEBKIT) {
    switch (type) {
      case bot.events.EventType.CLICK:
      case bot.events.EventType.MOUSEUP:
        return this.select_.multiple ? this.element_ : this.select_;
      default:
        return this.select_.multiple ? this.element_ : null;
    }
  }

  // Firefox fires every event or the option element.
  return this.element_;
};


/**
 * A helper function to fire click events.  This method is shared between
 * the mouse and touchscreen devices.
 *
 * @param {!goog.math.Coordinate} coord The coordinate where event will fire.
 * @param {number} button The mouse button value for the event.
 * @param {boolean=} opt_force Whether the click should occur even if the
 *     element is not interactable, such as when an element is hidden by a
 *     mouseup handler.
 * @param {?number=} opt_pointerId The pointer id associated with the click.
 * @protected
 */
bot.Device.prototype.clickElement = function (coord, button, opt_force,
  opt_pointerId) {
  if (!opt_force && !bot.dom.isInteractable(this.element_)) {
    return;
  }

  // bot.events.fire(element, 'click') can trigger all onclick events, but may
  // not follow links (FORM.action or A.href).
  //     TAG      IE   GECKO  WebKit
  // A(href)      No    No     Yes
  // FORM(action) No    Yes    Yes
  var targetLink = null;
  var targetButton = null;
  if (!bot.Device.ALWAYS_FOLLOWS_LINKS_ON_CLICK_) {
    for (var e = this.element_; e; e = e.parentNode) {
      if (bot.dom.isElement(e, goog.dom.TagName.A)) {
        targetLink = /**@type {!Element}*/ (e);
        break;
      } else if (bot.Device.isFormSubmitElement(e)) {
        targetButton = e;
        break;
      }
    }
  }

  // When an element is toggled as the result of a click, the toggling and the
  // change event happens before the click event on some browsers. However, on
  // radio buttons and checkboxes, the click handler can prevent the toggle from
  // happening, so we must fire the click first to see if it is cancelled.
  var isRadioOrCheckbox = !this.select_ && bot.dom.isSelectable(this.element_);
  var wasChecked = isRadioOrCheckbox && bot.dom.isSelected(this.element_);

  // NOTE: Clicking on a form submit button is a little broken:
  // (1) When clicking a form submit button in IE, firing a click event or
  // calling Form.submit() will not by itself submit the form, so we call
  // Element.click() explicitly, but as a result, the coordinates of the click
  // event are not provided. Also, when clicking on an <input type=image>, the
  // coordinates click that are submitted with the form are always (0, 0).
  // (2) When clicking a form submit button in GECKO, while the coordinates of
  // the click event are correct, those submitted with the form are always (0,0)
  // .
  // TODO: See if either of these can be resolved, perhaps by adding
  // hidden form elements with the coordinates before the form is submitted.
  if (goog.userAgent.IE && targetButton) {
    targetButton.click();
    return;
  }

  var performDefault = this.fireMouseEvent(
    bot.events.EventType.CLICK, coord, button, null, 0, opt_force,
    opt_pointerId);
  if (!performDefault) {
    return;
  }

  if (targetLink && bot.Device.shouldFollowHref_(targetLink)) {
    bot.Device.followHref_(targetLink);
  } else if (isRadioOrCheckbox) {
    this.toggleRadioButtonOrCheckbox_(wasChecked);
  }
};


/**
 * Focuses on the given element and returns true if it supports being focused
 * and does not already have focus; otherwise, returns false. If another element
 * has focus, that element will be blurred before focusing on the given element.
 *
 * @return {boolean} Whether the element was given focus.
 * @protected
 */
bot.Device.prototype.focusOnElement = function () {
  var elementToFocus = goog.dom.getAncestor(
    this.element_,
    function (node) {
      return !!node && bot.dom.isElement(node) &&
        bot.dom.isFocusable(/** @type {!Element} */(node));
    },
    true /* Return this.element_ if it is focusable. */);
  elementToFocus = elementToFocus || this.element_;

  var activeElement = bot.dom.getActiveElement(elementToFocus);
  if (elementToFocus == activeElement) {
    return false;
  }

  // If there is a currently active element, try to blur it.
  if (activeElement && (typeof activeElement.blur === 'function' ||
    // IE reports native functions as being objects.
    goog.userAgent.IE && (typeof activeElement.blur === 'object' && activeElement.blur !== null))) {
    // In IE, the focus() and blur() functions fire their respective events
    // asynchronously, and as the result, the focus/blur events fired by the
    // the atoms actions will often be in the wrong order on IE. Firing a blur
    // out of order sometimes causes IE to throw an "Unspecified error", so we
    // wrap it in a try-catch and catch and ignore the error in this case.
    if (!bot.dom.isElement(activeElement, goog.dom.TagName.BODY)) {
      try {
        activeElement.blur();
      } catch (e) {
        if (!(goog.userAgent.IE && e.message == 'Unspecified error.')) {
          throw e;
        }
      }
    }

    // Sometimes IE6 and IE7 will not fire an onblur event after blur()
    // is called, unless window.focus() is called immediately afterward.
    // Note that IE8 will hit this branch unless the page is forced into
    // IE8-strict mode. This shouldn't hurt anything, we just use the
    // useragent sniff so we can compile this out for proper browsers.
    if (goog.userAgent.IE && !bot.userAgent.isEngineVersion(8)) {
      goog.dom.getWindow(goog.dom.getOwnerDocument(elementToFocus)).focus();
    }
  }

  // Try to focus on the element.
  if (typeof elementToFocus.focus === 'function' ||
    goog.userAgent.IE && (typeof elementToFocus.focus === 'object' && elementToFocus.focus !== null)) {
    /** @type {function()} */ (elementToFocus.focus).call(elementToFocus);
    return true;
  }

  return false;
};


/**
 * Whether links must be manually followed when clicking (because firing click
 * events doesn't follow them).
 * @private {boolean}
 * @const
 */
bot.Device.ALWAYS_FOLLOWS_LINKS_ON_CLICK_ = goog.userAgent.WEBKIT;


/**
 * @param {Node} element The element to check.
 * @return {boolean} Whether the element is a submit element in form.
 * @protected
 */
bot.Device.isFormSubmitElement = function (element) {
  if (bot.dom.isElement(element, goog.dom.TagName.INPUT)) {
    var type = element.type.toLowerCase();
    if (type == 'submit' || type == 'image') {
      return true;
    }
  }

  if (bot.dom.isElement(element, goog.dom.TagName.BUTTON)) {
    var type = element.type.toLowerCase();
    if (type == 'submit') {
      return true;
    }
  }
  return false;
};


/**
 * Indicates whether we should manually follow the href of the element we're
 * clicking.
 *
 * Versions of firefox from 4+ will handle links properly when this is used in
 * an extension. Versions of Firefox prior to this may or may not do the right
 * thing depending on whether a target window is opened and whether the click
 * has caused a change in just the hash part of the URL.
 *
 * @param {!Element} element The element to consider.
 * @return {boolean} Whether following an href should be skipped.
 * @private
 */
bot.Device.shouldFollowHref_ = function (element) {
  if (bot.Device.ALWAYS_FOLLOWS_LINKS_ON_CLICK_ || !element.href) {
    return false;
  }

  if (!(bot.userAgent.WEBEXTENSION)) {
    return true;
  }

  if (element.target || element.href.toLowerCase().indexOf('javascript') == 0) {
    return false;
  }

  var owner = goog.dom.getWindow(goog.dom.getOwnerDocument(element));
  var sourceUrl = owner.location.href;
  var destinationUrl = bot.Device.resolveUrl_(owner.location, element.href);
  var isOnlyHashChange =
    sourceUrl.split('#')[0] === destinationUrl.split('#')[0];

  return !isOnlyHashChange;
};


/**
 * Explicitly follows the href of an anchor.
 *
 * @param {!Element} anchorElement An anchor element.
 * @private
 */
bot.Device.followHref_ = function (anchorElement) {
  var targetHref = anchorElement.href;
  var owner = goog.dom.getWindow(goog.dom.getOwnerDocument(anchorElement));

  // IE7 and earlier incorrect resolve a relative href against the top window
  // location instead of the window to which the href is assigned. As a result,
  // we have to resolve the relative URL ourselves. We do not use Closure's
  // goog.Uri to resolve, because it incorrectly fails to support empty but
  // undefined query and fragment components and re-encodes the given url.
  if (goog.userAgent.IE && !bot.userAgent.isEngineVersion(8)) {
    targetHref = bot.Device.resolveUrl_(owner.location, targetHref);
  }

  if (anchorElement.target) {
    owner.open(targetHref, anchorElement.target);
  } else {
    owner.location.href = targetHref;
  }
};


/**
 * Toggles the selected state of the current element if it is an option. This
 * is a noop if the element is not an option, or if it is selected and belongs
 * to a single-select, because it can't be toggled off.
 *
 * @protected
 */
bot.Device.prototype.maybeToggleOption = function () {
  // If this is not an <option> or not interactable, exit.
  if (!this.select_ || !bot.dom.isInteractable(this.element_)) {
    return;
  }
  var select = /** @type {!Element} */ (this.select_);
  var wasSelected = bot.dom.isSelected(this.element_);
  // Cannot toggle off options in single-selects.
  if (wasSelected && !select.multiple) {
    return;
  }

  // TODO: In a multiselect, clicking an option without the ctrl key down
  // should deselect all other selected options. Right now multiselect click
  // works as ctrl+click should (and unit tests written so that they pass).

  this.element_.selected = !wasSelected;
  // Only WebKit fires the change event itself and only for multi-selects,
  // except for Android versions >= 4.0 and Chrome >= 28.
  if (!(goog.userAgent.WEBKIT && select.multiple) ||
    (goog.userAgent.product.CHROME && bot.userAgent.isProductVersion(28)) ||
    (goog.userAgent.product.ANDROID && bot.userAgent.isProductVersion(4))) {
    bot.events.fire(select, bot.events.EventType.CHANGE);
  }
};


/**
 * Toggles the checked state of a radio button or checkbox. This is a noop if
 * it is a radio button that is checked, because it can't be toggled off.
 *
 * @param {boolean} wasChecked Whether the element was originally checked.
 * @private
 */
bot.Device.prototype.toggleRadioButtonOrCheckbox_ = function (wasChecked) {
  // Gecko and WebKit toggle the element as a result of a click.
  if (goog.userAgent.GECKO || goog.userAgent.WEBKIT) {
    return;
  }
  // Cannot toggle off radio buttons.
  if (wasChecked && this.element_.type.toLowerCase() == 'radio') {
    return;
  }
  this.element_.checked = !wasChecked;
};


/**
 * Find FORM element that is an ancestor of the passed in element.
 * @param {Node} node The node to find a FORM for.
 * @return {Element} The ancestor FORM element if it exists.
 * @protected
 */
bot.Device.findAncestorForm = function (node) {
  return /** @type {Element} */ (goog.dom.getAncestor(
    node, bot.Device.isForm_, /*includeNode=*/true));
};


/**
 * @param {Node} node The node to test.
 * @return {boolean} Whether the node is a FORM element.
 * @private
 */
bot.Device.isForm_ = function (node) {
  return bot.dom.isElement(node, goog.dom.TagName.FORM);
};


/**
 * Submits the specified form. Unlike the public function, it expects to be
 * given a form element and fails if it is not.
 * @param {!Element} form The form to submit.
 * @protected
 */
bot.Device.prototype.submitForm = function (form) {
  if (!bot.Device.isForm_(form)) {
    throw new bot.Error(bot.ErrorCode.INVALID_ELEMENT_STATE,
      'Element is not a form, so could not submit.');
  }
  if (bot.events.fire(form, bot.events.EventType.SUBMIT)) {
    // When a form has an element with an id or name exactly equal to "submit"
    // (not uncommon) it masks the form.submit function. We  can avoid this by
    // calling the prototype's submit function, except in IE < 8, where DOM id
    // elements don't let you reference their prototypes. For IE < 8, can change
    // the id and names of the elements and revert them back, but they must be
    // reverted before the submit call, because the onsubmit handler might rely
    // on their being correct, and the HTTP request might otherwise be left with
    // incorrect value names. Fortunately, saving the submit function and
    // calling it after reverting the ids and names works! Oh, and goog.typeOf
    // (and thus goog.isFunction) doesn't work for form.submit in IE < 8.
    if (!bot.dom.isElement(form.submit)) {
      form.submit();
    } else if (!goog.userAgent.IE || bot.userAgent.isEngineVersion(8)) {
      /** @type {Function} */ (form.constructor.prototype['submit']).call(form);
    } else {
      var idMasks = bot.locators.findElements({ 'id': 'submit' }, form);
      var nameMasks = bot.locators.findElements({ 'name': 'submit' }, form);
      goog.array.forEach(idMasks, function (m) {
        m.removeAttribute('id');
      });
      goog.array.forEach(nameMasks, function (m) {
        m.removeAttribute('name');
      });
      var submitFunction = form.submit;
      goog.array.forEach(idMasks, function (m) {
        m.setAttribute('id', 'submit');
      });
      goog.array.forEach(nameMasks, function (m) {
        m.setAttribute('name', 'submit');
      });
      submitFunction();
    }
  }
};


/**
 * Regular expression for splitting up a URL into components.
 * @private {!RegExp}
 * @const
 */
bot.Device.URL_REGEXP_ = new RegExp(
  '^' +
  '([^:/?#.]+:)?' +   // protocol
  '(?://([^/]*))?' +  // host
  '([^?#]+)?' +       // pathname
  '(\\?[^#]*)?' +     // search
  '(#.*)?' +          // hash
  '$');


/**
 * Resolves a potentially relative URL against a base location.
 * @param {!Location} base Base location against which to resolve.
 * @param {string} rel Url to resolve against the location.
 * @return {string} Resolution of url against base location.
 * @private
 */
bot.Device.resolveUrl_ = function (base, rel) {
  var m = rel.match(bot.Device.URL_REGEXP_);
  if (!m) {
    return '';
  }
  var target = {
    protocol: m[1] || '',
    host: m[2] || '',
    pathname: m[3] || '',
    search: m[4] || '',
    hash: m[5] || ''
  };

  if (!target.protocol) {
    target.protocol = base.protocol;
    if (!target.host) {
      target.host = base.host;
      if (!target.pathname) {
        target.pathname = base.pathname;
        target.search = target.search || base.search;
      } else if (target.pathname.charAt(0) != '/') {
        var lastSlashIndex = base.pathname.lastIndexOf('/');
        if (lastSlashIndex != -1) {
          var directory = base.pathname.substr(0, lastSlashIndex + 1);
          target.pathname = directory + target.pathname;
        }
      }
    }
  }

  return target.protocol + '//' + target.host + target.pathname +
    target.search + target.hash;
};



/**
 * Stores the state of modifier keys
 *
 * @constructor
 */
bot.Device.ModifiersState = function () {
  /**
   * State of the modifier keys.
   * @private {number}
   */
  this.pressedModifiers_ = 0;
};


/**
 * An enum for the various modifier keys (keycode-independent).
 * @enum {number}
 */
bot.Device.Modifier = {
  SHIFT: 0x1,
  CONTROL: 0x2,
  ALT: 0x4,
  META: 0x8
};


/**
 * Checks whether a specific modifier is pressed
 * @param {!bot.Device.Modifier} modifier The modifier to check.
 * @return {boolean} Whether the modifier is pressed.
 */
bot.Device.ModifiersState.prototype.isPressed = function (modifier) {
  return (this.pressedModifiers_ & modifier) != 0;
};


/**
 * Sets the state of a given modifier.
 * @param {!bot.Device.Modifier} modifier The modifier to set.
 * @param {boolean} isPressed whether the modifier is set or released.
 */
bot.Device.ModifiersState.prototype.setPressed = function (
  modifier, isPressed) {
  if (isPressed) {
    this.pressedModifiers_ = this.pressedModifiers_ | modifier;
  } else {
    this.pressedModifiers_ = this.pressedModifiers_ & (~modifier);
  }
};


/**
 * @return {boolean} State of the Shift key.
 */
bot.Device.ModifiersState.prototype.isShiftPressed = function () {
  return this.isPressed(bot.Device.Modifier.SHIFT);
};


/**
 * @return {boolean} State of the Control key.
 */
bot.Device.ModifiersState.prototype.isControlPressed = function () {
  return this.isPressed(bot.Device.Modifier.CONTROL);
};


/**
 * @return {boolean} State of the Alt key.
 */
bot.Device.ModifiersState.prototype.isAltPressed = function () {
  return this.isPressed(bot.Device.Modifier.ALT);
};


/**
 * @return {boolean} State of the Meta key.
 */
bot.Device.ModifiersState.prototype.isMetaPressed = function () {
  return this.isPressed(bot.Device.Modifier.META);
};


/**
 * The pointer id used for MSPointer events initiated through a mouse device.
 * @type {number}
 * @const
 */
bot.Device.MOUSE_MS_POINTER_ID = 1;


/**
 * A map of pointer id to Elements.
 * @private {!Object.<number, !Element>}
 */
bot.Device.pointerElementMap_ = {};


/**
 * Gets the element associated with a pointer id.
 * @param {number} pointerId The pointer Id.
 * @return {?Element} The element associated with the pointer id.
 * @protected
 */
bot.Device.getPointerElement = function (pointerId) {
  return bot.Device.pointerElementMap_[pointerId];
};


/**
 * Clear the pointer map.
 * @protected
 */
bot.Device.clearPointerMap = function () {
  bot.Device.pointerElementMap_ = {};
};


/**
 * Fires events, a driver can replace it with a custom implementation
 *
 * @constructor
 */
bot.Device.EventEmitter = function () {
};


/**
 * Fires an HTML event given the state of the device.
 *
 * @param {!Element} target The element on which to fire the event.
 * @param {!bot.events.EventFactory_} type HTML Event type.
 * @return {boolean} Whether the event fired successfully; false if cancelled.
 * @protected
 */
bot.Device.EventEmitter.prototype.fireHtmlEvent = function (target, type) {
  return bot.events.fire(target, type);
};


/**
 * Fires a keyboard event given the state of the device and the given arguments.
 *
 * @param {!Element} target The element on which to fire the event.
 * @param {!bot.events.EventFactory_} type Keyboard event type.
 * @param {bot.events.KeyboardArgs} args Keyboard event arguments.
 * @return {boolean} Whether the event fired successfully; false if cancelled.
 * @protected
 */
bot.Device.EventEmitter.prototype.fireKeyboardEvent = function (
  target, type, args) {
  return bot.events.fire(target, type, args);
};


/**
 * Fires a mouse event given the state of the device and the given arguments.
 *
 * @param {!Element} target The element on which to fire the event.
 * @param {!bot.events.EventFactory_} type Mouse event type.
 * @param {bot.events.MouseArgs} args Mouse event arguments.
 * @return {boolean} Whether the event fired successfully; false if cancelled.
 * @protected
 */
bot.Device.EventEmitter.prototype.fireMouseEvent = function (
  target, type, args) {
  return bot.events.fire(target, type, args);
};


/**
 * Fires a mouse event given the state of the device and the given arguments.
 *
 * @param {!Element} target The element on which to fire the event.
 * @param {!bot.events.EventFactory_} type Touch event type.
 * @param {bot.events.TouchArgs} args Touch event arguments.
 * @return {boolean} Whether the event fired successfully; false if cancelled.
 * @protected
 */
bot.Device.EventEmitter.prototype.fireTouchEvent = function (
  target, type, args) {
  return bot.events.fire(target, type, args);
};


/**
 * Fires an MSPointer event given the state of the device and the given
 * arguments.
 *
 * @param {!Element} target The element on which to fire the event.
 * @param {!bot.events.EventFactory_} type MSPointer event type.
 * @param {bot.events.MSPointerArgs} args MSPointer event arguments.
 * @return {boolean} Whether the event fired successfully; false if cancelled.
 * @protected
 */
bot.Device.EventEmitter.prototype.fireMSPointerEvent = function (
  target, type, args) {
  return bot.events.fire(target, type, args);
};
