tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

actions.js (5934B)


      1 /* import-globals-from common.js */
      2 /* import-globals-from events.js */
      3 
      4 // //////////////////////////////////////////////////////////////////////////////
      5 // Event constants
      6 
      7 const MOUSEDOWN_EVENT = 1;
      8 const MOUSEUP_EVENT = 2;
      9 const CLICK_EVENT = 4;
     10 const COMMAND_EVENT = 8;
     11 const FOCUS_EVENT = 16;
     12 
     13 const CLICK_EVENTS = MOUSEDOWN_EVENT | MOUSEUP_EVENT | CLICK_EVENT;
     14 const XUL_EVENTS = CLICK_EVENTS | COMMAND_EVENT;
     15 
     16 // //////////////////////////////////////////////////////////////////////////////
     17 // Public functions
     18 
     19 /**
     20 * Test default accessible actions.
     21 *
     22 * Action tester interface is:
     23 *
     24 * ```js
     25 *  var actionObj = {
     26 *    // identifier of accessible to perform an action on
     27 *    get ID() {},
     28 *
     29 *    // index of the action
     30 *    get actionIndex() {},
     31 *
     32 *    // name of the action
     33 *    get actionName() {},
     34 *
     35 *    // DOM events (see constants defined above)
     36 *    get events() {},
     37 *
     38 *    // [optional] identifier of target DOM events listeners are registered on,
     39 *    // used with 'events', if missing then 'ID' is used instead.
     40 *    get targetID() {},
     41 *
     42 *    // [optional] true to match DOM events bubbled up to the target,
     43 *    // false (default) to only match events fired directly on the target.
     44 *    get allowBubbling() {},
     45 *
     46 *    // [optional] perform checks when 'click' event is handled if 'events'
     47 *    // is used.
     48 *    checkOnClickEvent: function() {},
     49 *
     50 *    // [optional] an array of invoker's checker objects (see eventQueue
     51 *    // constructor events.js)
     52 *    get eventSeq() {}
     53 *  };
     54 * ```
     55 *
     56 * @param  aArray [in] an array of action cheker objects
     57 */
     58 function testActions(aArray) {
     59  gActionsQueue = new eventQueue();
     60 
     61  for (var idx = 0; idx < aArray.length; idx++) {
     62    var actionObj = aArray[idx];
     63    var accOrElmOrID = actionObj.ID;
     64    var actionIndex = actionObj.actionIndex;
     65    var actionName = actionObj.actionName;
     66    var events = actionObj.events;
     67    var accOrElmOrIDOfTarget = actionObj.targetID
     68      ? actionObj.targetID
     69      : accOrElmOrID;
     70 
     71    var eventSeq = [];
     72    if (events) {
     73      var elm = getNode(accOrElmOrIDOfTarget);
     74      if (events & MOUSEDOWN_EVENT) {
     75        eventSeq.push(new checkerOfActionInvoker("mousedown", elm, actionObj));
     76      }
     77 
     78      if (events & MOUSEUP_EVENT) {
     79        eventSeq.push(new checkerOfActionInvoker("mouseup", elm, actionObj));
     80      }
     81 
     82      if (events & CLICK_EVENT) {
     83        eventSeq.push(new checkerOfActionInvoker("click", elm, actionObj));
     84      }
     85 
     86      if (events & COMMAND_EVENT) {
     87        eventSeq.push(new checkerOfActionInvoker("command", elm, actionObj));
     88      }
     89 
     90      if (events & FOCUS_EVENT) {
     91        eventSeq.push(new focusChecker(elm));
     92      }
     93    }
     94 
     95    if (actionObj.eventSeq) {
     96      eventSeq = eventSeq.concat(actionObj.eventSeq);
     97    }
     98 
     99    var invoker = new actionInvoker(
    100      accOrElmOrID,
    101      actionIndex,
    102      actionName,
    103      eventSeq
    104    );
    105    gActionsQueue.push(invoker);
    106  }
    107 
    108  gActionsQueue.invoke();
    109 }
    110 
    111 /**
    112 * Test action names and descriptions.
    113 */
    114 function testActionNames(aID, aActions) {
    115  var actions = typeof aActions == "string" ? [aActions] : aActions || [];
    116 
    117  var acc = getAccessible(aID);
    118  is(acc.actionCount, actions.length, "Wrong number of actions.");
    119  for (var i = 0; i < actions.length; i++) {
    120    is(
    121      acc.getActionName(i),
    122      actions[i],
    123      "Wrong action name at " + i + " index."
    124    );
    125    is(
    126      acc.getActionDescription(0),
    127      gActionDescrMap[actions[i]],
    128      "Wrong action description at " + i + "index."
    129    );
    130  }
    131 }
    132 
    133 // //////////////////////////////////////////////////////////////////////////////
    134 // Private
    135 
    136 var gActionsQueue = null;
    137 
    138 function actionInvoker(aAccOrElmOrId, aActionIndex, aActionName, aEventSeq) {
    139  this.invoke = function actionInvoker_invoke() {
    140    var acc = getAccessible(aAccOrElmOrId);
    141    if (!acc) {
    142      return INVOKER_ACTION_FAILED;
    143    }
    144 
    145    var isThereActions = acc.actionCount > 0;
    146    ok(
    147      isThereActions,
    148      "No actions on the accessible for " + prettyName(aAccOrElmOrId)
    149    );
    150 
    151    if (!isThereActions) {
    152      return INVOKER_ACTION_FAILED;
    153    }
    154 
    155    is(
    156      acc.getActionName(aActionIndex),
    157      aActionName,
    158      "Wrong action name of the accessible for " + prettyName(aAccOrElmOrId)
    159    );
    160 
    161    try {
    162      acc.doAction(aActionIndex);
    163    } catch (e) {
    164      ok(false, "doAction(" + aActionIndex + ") failed with: " + e.name);
    165      return INVOKER_ACTION_FAILED;
    166    }
    167    return null;
    168  };
    169 
    170  this.eventSeq = aEventSeq;
    171 
    172  this.getID = function actionInvoker_getID() {
    173    return (
    174      "invoke an action " +
    175      aActionName +
    176      " at index " +
    177      aActionIndex +
    178      " on " +
    179      prettyName(aAccOrElmOrId)
    180    );
    181  };
    182 }
    183 
    184 function checkerOfActionInvoker(aType, aTarget, aActionObj) {
    185  this.type = aType;
    186 
    187  this.target = aTarget;
    188 
    189  if (aActionObj && "eventTarget" in aActionObj) {
    190    this.eventTarget = aActionObj.eventTarget;
    191  }
    192 
    193  if (aActionObj && aActionObj.allowBubbling) {
    194    // Normally, we add event listeners on the document. To catch bubbled
    195    // events, we need to add the listener on the target itself.
    196    this.eventTarget = "element";
    197    // Normally, we only match an event fired directly on the target. Override
    198    // this to match a bubbled event.
    199    this.match = function (aEvent) {
    200      return aEvent.currentTarget == aTarget;
    201    };
    202  }
    203 
    204  this.phase = false;
    205 
    206  this.getID = function getID() {
    207    return aType + " event handling";
    208  };
    209 
    210  this.check = function check(aEvent) {
    211    if (aType == "click" && aActionObj && "checkOnClickEvent" in aActionObj) {
    212      aActionObj.checkOnClickEvent(aEvent);
    213    }
    214  };
    215 }
    216 
    217 var gActionDescrMap = {
    218  jump: "Jump",
    219  press: "Press",
    220  check: "Check",
    221  uncheck: "Uncheck",
    222  select: "Select",
    223  open: "Open",
    224  close: "Close",
    225  switch: "Switch",
    226  click: "Click",
    227  collapse: "Collapse",
    228  expand: "Expand",
    229  activate: "Activate",
    230  cycle: "Cycle",
    231  clickAncestor: "Click ancestor",
    232 };