Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  common.js   Sprache: JAVA

 
// This file has circular dependencies that may require other files. Rather
// than use import-globals-from, we list the globals individually here to save
// confusing ESLint.
// actions.js
/* globals testActionNames */
// attributes.js
/* globals testAttrs, testAbsentAttrs, testTextAttrs */
// relations.js
/* globals testRelation */
// role.js
/* globals isRole */
// state.js
/* globals testStates */

// //////////////////////////////////////////////////////////////////////////////
// Interfaces

const nsIAccessibilityService = Ci.nsIAccessibilityService;

const nsIAccessibleEvent = Ci.nsIAccessibleEvent;
const nsIAccessibleStateChangeEvent = Ci.nsIAccessibleStateChangeEvent;
const nsIAccessibleCaretMoveEvent = Ci.nsIAccessibleCaretMoveEvent;
const nsIAccessibleScrollingEvent = Ci.nsIAccessibleScrollingEvent;
const nsIAccessibleTextChangeEvent = Ci.nsIAccessibleTextChangeEvent;
const nsIAccessibleTextSelectionChangeEvent =
  Ci.nsIAccessibleTextSelectionChangeEvent;
const nsIAccessibleObjectAttributeChangedEvent =
  Ci.nsIAccessibleObjectAttributeChangedEvent;
const nsIAccessibleAnnouncementEvent = Ci.nsIAccessibleAnnouncementEvent;

const nsIAccessibleStates = Ci.nsIAccessibleStates;
const nsIAccessibleRole = Ci.nsIAccessibleRole;
const nsIAccessibleScrollType = Ci.nsIAccessibleScrollType;
const nsIAccessibleCoordinateType = Ci.nsIAccessibleCoordinateType;

const nsIAccessibleRelation = Ci.nsIAccessibleRelation;
const nsIAccessibleTextRange = Ci.nsIAccessibleTextRange;

const nsIAccessible = Ci.nsIAccessible;

const nsIAccessibleDocument = Ci.nsIAccessibleDocument;
const nsIAccessibleApplication = Ci.nsIAccessibleApplication;

const nsIAccessibleText = Ci.nsIAccessibleText;
const nsIAccessibleEditableText = Ci.nsIAccessibleEditableText;

const nsIAccessibleHyperLink = Ci.nsIAccessibleHyperLink;
const nsIAccessibleHyperText = Ci.nsIAccessibleHyperText;

const nsIAccessibleImage = Ci.nsIAccessibleImage;
const nsIAccessiblePivot = Ci.nsIAccessiblePivot;
const nsIAccessibleSelectable = Ci.nsIAccessibleSelectable;
const nsIAccessibleTable = Ci.nsIAccessibleTable;
const nsIAccessibleTableCell = Ci.nsIAccessibleTableCell;
const nsIAccessibleTraversalRule = Ci.nsIAccessibleTraversalRule;
const nsIAccessibleValue = Ci.nsIAccessibleValue;

const nsIObserverService = Ci.nsIObserverService;

const nsIDOMWindow = Ci.nsIDOMWindow;

const nsIPropertyElement = Ci.nsIPropertyElement;

// //////////////////////////////////////////////////////////////////////////////
// OS detect

const MAC = navigator.platform.includes("Mac");
const LINUX = navigator.platform.includes("Linux");
const SOLARIS = navigator.platform.includes("SunOS");
const WIN = navigator.platform.includes("Win");

// //////////////////////////////////////////////////////////////////////////////
// Application detect
// Firefox is assumed by default.

const SEAMONKEY = navigator.userAgent.match(/ SeaMonkey\//);

// //////////////////////////////////////////////////////////////////////////////
// Accessible general

const STATE_BUSY = nsIAccessibleStates.STATE_BUSY;

const SCROLL_TYPE_TOP_EDGE = nsIAccessibleScrollType.SCROLL_TYPE_TOP_EDGE;
const SCROLL_TYPE_ANYWHERE = nsIAccessibleScrollType.SCROLL_TYPE_ANYWHERE;

const COORDTYPE_SCREEN_RELATIVE =
  nsIAccessibleCoordinateType.COORDTYPE_SCREEN_RELATIVE;
const COORDTYPE_WINDOW_RELATIVE =
  nsIAccessibleCoordinateType.COORDTYPE_WINDOW_RELATIVE;
const COORDTYPE_PARENT_RELATIVE =
  nsIAccessibleCoordinateType.COORDTYPE_PARENT_RELATIVE;

const kEmbedChar = String.fromCharCode(0xfffc);

const kDiscBulletChar = String.fromCharCode(0x2022);
const kDiscBulletText = kDiscBulletChar + " ";
const kCircleBulletText = String.fromCharCode(0x25e6) + " ";
const kSquareBulletText = String.fromCharCode(0x25aa) + " ";

const MAX_TRIM_LENGTH = 100;

/**
 * Services to determine if e10s is enabled.
 */


/**
 * nsIAccessibilityService service.
 */

var gAccService = Cc["@mozilla.org/accessibilityService;1"].getService(
  nsIAccessibilityService
);

/**
 * Enable/disable logging.
 */

function enableLogging(aModules) {
  gAccService.setLogging(aModules);
}
function disableLogging() {
  gAccService.setLogging("");
}
function isLogged(aModule) {
  return gAccService.isLogged(aModule);
}

/**
 * Dumps the accessible tree into console.
 */

function dumpTree(aId, aMsg) {
  function dumpTreeIntl(acc, indent) {
    dump(indent + prettyName(acc) + "\n");

    var children = acc.children;
    for (var i = 0; i < children.length; i++) {
      var child = children.queryElementAt(i, nsIAccessible);
      dumpTreeIntl(child, indent + " ");
    }
  }

  function dumpDOMTreeIntl(node, indent) {
    dump(indent + prettyName(node) + "\n");

    var children = node.childNodes;
    for (var i = 0; i < children.length; i++) {
      var child = children.item(i);
      dumpDOMTreeIntl(child, indent + " ");
    }
  }

  dump(aMsg + "\n");
  var root = getAccessible(aId);
  dumpTreeIntl(root, " ");

  dump("DOM tree:\n");
  dumpDOMTreeIntl(getNode(aId), " ");
}

/**
 * Invokes the given function when document is loaded and focused. Preferable
 * to mochitests 'addLoadEvent' function -- additionally ensures state of the
 * document accessible is not busy.
 *
 * @param aFunc  the function to invoke
 */

function addA11yLoadEvent(aFunc, aWindow) {
  function waitForDocLoad() {
    window.setTimeout(function () {
      var targetDocument = aWindow ? aWindow.document : document;
      var accDoc = getAccessible(targetDocument);
      var state = {};
      accDoc.getState(state, {});
      if (state.value & STATE_BUSY) {
        waitForDocLoad();
        return;
      }

      window.setTimeout(aFunc, 0);
    }, 0);
  }

  if (
    aWindow &&
    aWindow.document.activeElement &&
    aWindow.document.activeElement.localName == "browser"
  ) {
    waitForDocLoad();
  } else {
    SimpleTest.waitForFocus(waitForDocLoad, aWindow);
  }
}

/**
 * Analogy of SimpleTest.is function used to compare objects.
 */

function isObject(aObj, aExpectedObj, aMsg) {
  if (aObj == aExpectedObj) {
    ok(true, aMsg);
    return;
  }

  ok(
    false,
    aMsg +
      " - got '" +
      prettyName(aObj) +
      "', expected '" +
      prettyName(aExpectedObj) +
      "'"
  );
}

/**
 * is() function checking the expected value is within the range.
 */

function isWithin(aExpected, aGot, aWithin, aMsg) {
  if (Math.abs(aGot - aExpected) <= aWithin) {
    ok(true, `${aMsg} - Got ${aGot}`);
  } else {
    ok(
      false,
      `${aMsg} - Got ${aGot}, expected ${aExpected} with error of ${aWithin}`
    );
  }
}

// //////////////////////////////////////////////////////////////////////////////
// Helpers for getting DOM node/accessible

/**
 * Return the DOM node by identifier (may be accessible, DOM node or ID).
 */

function getNode(aAccOrNodeOrID, aDocument) {
  if (!aAccOrNodeOrID) {
    return null;
  }

  if (Node.isInstance(aAccOrNodeOrID)) {
    return aAccOrNodeOrID;
  }

  if (aAccOrNodeOrID instanceof nsIAccessible) {
    return aAccOrNodeOrID.DOMNode;
  }

  var node = (aDocument || document).getElementById(aAccOrNodeOrID);
  if (!node) {
    ok(false"Can't get DOM element for " + aAccOrNodeOrID);
    return null;
  }

  return node;
}

/**
 * Constants indicates getAccessible doesn't fail if there is no accessible.
 */

const DONOTFAIL_IF_NO_ACC = 1;

/**
 * Constants indicates getAccessible won't fail if accessible doesn't implement
 * the requested interfaces.
 */

const DONOTFAIL_IF_NO_INTERFACE = 2;

/**
 * Return accessible for the given identifier (may be ID attribute or DOM
 * element or accessible object) or null.
 *
 * @param aAccOrElmOrID      [in] identifier to get an accessible implementing
 *                           the given interfaces
 * @param aInterfaces        [in, optional] the interface or an array interfaces
 *                           to query it/them from obtained accessible
 * @param aElmObj            [out, optional] object to store DOM element which
 *                           accessible is obtained for
 * @param aDoNotFailIf       [in, optional] no error for special cases (see
 *                            constants above)
 */

function getAccessible(aAccOrElmOrID, aInterfaces, aElmObj, aDoNotFailIf) {
  if (!aAccOrElmOrID) {
    return null;
  }

  var elm = null;

  if (aAccOrElmOrID instanceof nsIAccessible) {
    try {
      elm = aAccOrElmOrID.DOMNode;
    } catch (e) {}
  } else if (Node.isInstance(aAccOrElmOrID)) {
    elm = aAccOrElmOrID;
  } else {
    elm = document.getElementById(aAccOrElmOrID);
    if (!elm) {
      ok(false"Can't get DOM element for " + aAccOrElmOrID);
      return null;
    }
  }

  if (aElmObj && typeof aElmObj == "object") {
    aElmObj.value = elm;
  }

  var acc = aAccOrElmOrID instanceof nsIAccessible ? aAccOrElmOrID : null;
  if (!acc) {
    try {
      acc = gAccService.getAccessibleFor(elm);
    } catch (e) {}

    if (!acc) {
      if (!(aDoNotFailIf & DONOTFAIL_IF_NO_ACC)) {
        ok(false"Can't get accessible for " + prettyName(aAccOrElmOrID));
      }

      return null;
    }
  }

  if (!aInterfaces) {
    return acc;
  }

  if (!(aInterfaces instanceof Array)) {
    aInterfaces = [aInterfaces];
  }

  for (var index = 0; index < aInterfaces.length; index++) {
    if (acc instanceof aInterfaces[index]) {
      continue;
    }
    try {
      acc.QueryInterface(aInterfaces[index]);
    } catch (e) {
      if (!(aDoNotFailIf & DONOTFAIL_IF_NO_INTERFACE)) {
        ok(
          false,
          "Can't query " + aInterfaces[index] + " for " + aAccOrElmOrID
        );
      }

      return null;
    }
  }

  return acc;
}

/**
 * Return true if the given identifier has an accessible, or exposes the wanted
 * interfaces.
 */

function isAccessible(aAccOrElmOrID, aInterfaces) {
  return !!getAccessible(
    aAccOrElmOrID,
    aInterfaces,
    null,
    DONOTFAIL_IF_NO_ACC | DONOTFAIL_IF_NO_INTERFACE
  );
}

/**
 * Return an accessible that contains the DOM node for the given identifier.
 */

function getContainerAccessible(aAccOrElmOrID) {
  var node = getNode(aAccOrElmOrID);
  if (!node) {
    return null;
  }

  // eslint-disable-next-line no-empty
  while ((node = node.parentNode) && !isAccessible(node)) {}
  return node ? getAccessible(node) : null;
}

/**
 * Return root accessible for the given identifier.
 */

function getRootAccessible(aAccOrElmOrID) {
  var acc = getAccessible(aAccOrElmOrID ? aAccOrElmOrID : document);
  return acc ? acc.rootDocument.QueryInterface(nsIAccessible) : null;
}

/**
 * Return tab document accessible the given accessible is contained by.
 */

function getTabDocAccessible(aAccOrElmOrID) {
  var acc = getAccessible(aAccOrElmOrID ? aAccOrElmOrID : document);

  var docAcc = acc.document.QueryInterface(nsIAccessible);
  var containerDocAcc = docAcc.parent.document;

  // Test is running is stand-alone mode.
  if (acc.rootDocument == containerDocAcc) {
    return docAcc;
  }

  // In the case of running all tests together.
  return containerDocAcc.QueryInterface(nsIAccessible);
}

/**
 * Return application accessible.
 */

function getApplicationAccessible() {
  return gAccService
    .getApplicationAccessible()
    .QueryInterface(nsIAccessibleApplication);
}

/**
 * A version of accessible tree testing, doesn't fail if tree is not complete.
 */

function testElm(aID, aTreeObj) {
  testAccessibleTree(aID, aTreeObj, kSkipTreeFullCheck);
}

/**
 * Flags used for testAccessibleTree
 */

const kSkipTreeFullCheck = 1;

/**
 * Compare expected and actual accessibles trees.
 *
 * @param  aAccOrElmOrID  [in] accessible identifier
 * @param  aAccTree       [in] JS object, each field corresponds to property of
 *                         accessible object. Additionally special properties
 *                         are presented:
 *                          children - an array of JS objects representing
 *                                      children of accessible
 *                          states   - an object having states and extraStates
 *                                      fields
 * @param aFlags          [in, optional] flags, see constants above
 */

// eslint-disable-next-line complexity
function testAccessibleTree(aAccOrElmOrID, aAccTree, aFlags) {
  var acc = getAccessible(aAccOrElmOrID);
  if (!acc) {
    return;
  }

  var accTree = aAccTree;

  // Support of simplified accessible tree object.
  accTree = normalizeAccTreeObj(accTree);

  // Test accessible properties.
  for (var prop in accTree) {
    var msg =
      "Wrong value of property '" + prop + "' for " + prettyName(acc) + ".";

    switch (prop) {
      case "actions": {
        testActionNames(acc, accTree.actions);
        break;
      }

      case "attributes":
        testAttrs(acc, accTree[prop], true);
        break;

      case "absentAttributes":
        testAbsentAttrs(acc, accTree[prop]);
        break;

      case "interfaces": {
        var ifaces =
          accTree[prop] instanceof Array ? accTree[prop] : [accTree[prop]];
        for (let i = 0; i < ifaces.length; i++) {
          ok(
            acc instanceof ifaces[i],
            "No " + ifaces[i] + " interface on " + prettyName(acc)
          );
        }
        break;
      }

      case "relations": {
        for (var rel in accTree[prop]) {
          testRelation(acc, window[rel], accTree[prop][rel]);
        }
        break;
      }

      case "role":
        isRole(acc, accTree[prop], msg);
        break;

      case "states":
      case "extraStates":
      case "absentStates":
      case "absentExtraStates": {
        testStates(
          acc,
          accTree.states,
          accTree.extraStates,
          accTree.absentStates,
          accTree.absentExtraStates
        );
        break;
      }

      case "tagName":
        is(accTree[prop], acc.DOMNode.tagName, msg);
        break;

      case "textAttrs": {
        var prevOffset = -1;
        for (var offset in accTree[prop]) {
          if (prevOffset != -1) {
            let attrs = accTree[prop][prevOffset];
            testTextAttrs(
              acc,
              prevOffset,
              attrs,
              {},
              prevOffset,
              +offset,
              true
            );
          }
          prevOffset = +offset;
        }

        if (prevOffset != -1) {
          var charCount = getAccessible(acc, [
            nsIAccessibleText,
          ]).characterCount;
          let attrs = accTree[prop][prevOffset];
          testTextAttrs(
            acc,
            prevOffset,
            attrs,
            {},
            prevOffset,
            charCount,
            true
          );
        }

        break;
      }

      default:
        if (prop.indexOf("todo_") == 0) {
          todo(false, msg);
        } else if (prop != "children") {
          is(acc[prop], accTree[prop], msg);
        }
    }
  }

  // Test children.
  if ("children" in accTree && accTree.children instanceof Array) {
    var children = acc.children;
    var childCount = children.length;

    if (accTree.children.length != childCount) {
      for (let i = 0; i < Math.max(accTree.children.length, childCount); i++) {
        var accChild = null,
          testChild = null;
        try {
          testChild = accTree.children[i];
          accChild = children.queryElementAt(i, nsIAccessible);

          if (!testChild) {
            ok(
              false,
              prettyName(acc) +
                " has an extra child at index " +
                i +
                " : " +
                prettyName(accChild)
            );
            continue;
          }

          testChild = normalizeAccTreeObj(testChild);
          if (accChild.role !== testChild.role) {
            ok(
              false,
              prettyName(accTree) +
                " and " +
                prettyName(acc) +
                " have different children at index " +
                i +
                " : " +
                prettyName(testChild) +
                ", " +
                prettyName(accChild)
            );
          }
          info(
            "Matching " +
              prettyName(accTree) +
              " and " +
              prettyName(acc) +
              " child at index " +
              i +
              " : " +
              prettyName(accChild)
          );
        } catch (e) {
          ok(
            false,
            prettyName(accTree) +
              " is expected to have a child at index " +
              i +
              " : " +
              prettyName(testChild) +
              ", original tested: " +
              prettyName(aAccOrElmOrID) +
              ", " +
              e
          );
        }
      }
    } else {
      if (aFlags & kSkipTreeFullCheck) {
        for (let i = 0; i < childCount; i++) {
          let child = children.queryElementAt(i, nsIAccessible);
          testAccessibleTree(child, accTree.children[i], aFlags);
        }
        return;
      }

      // nsIAccessible::firstChild
      var expectedFirstChild =
        childCount > 0 ? children.queryElementAt(0, nsIAccessible) : null;
      var firstChild = null;
      try {
        firstChild = acc.firstChild;
      } catch (e) {}
      is(
        firstChild,
        expectedFirstChild,
        "Wrong first child of " + prettyName(acc)
      );

      // nsIAccessible::lastChild
      var expectedLastChild =
        childCount > 0
          ? children.queryElementAt(childCount - 1, nsIAccessible)
          : null;
      var lastChild = null;
      try {
        lastChild = acc.lastChild;
      } catch (e) {}
      is(
        lastChild,
        expectedLastChild,
        "Wrong last child of " + prettyName(acc)
      );

      for (var i = 0; i < childCount; i++) {
        let child = children.queryElementAt(i, nsIAccessible);

        // nsIAccessible::parent
        var parent = null;
        try {
          parent = child.parent;
        } catch (e) {}
        is(parent, acc, "Wrong parent of " + prettyName(child));

        // nsIAccessible::indexInParent
        var indexInParent = -1;
        try {
          indexInParent = child.indexInParent;
        } catch (e) {}
        is(indexInParent, i, "Wrong index in parent of " + prettyName(child));

        // nsIAccessible::nextSibling
        var expectedNextSibling =
          i < childCount - 1
            ? children.queryElementAt(i + 1, nsIAccessible)
            : null;
        var nextSibling = null;
        try {
          nextSibling = child.nextSibling;
        } catch (e) {}
        is(
          nextSibling,
          expectedNextSibling,
          "Wrong next sibling of " + prettyName(child)
        );

        // nsIAccessible::previousSibling
        var expectedPrevSibling =
          i > 0 ? children.queryElementAt(i - 1, nsIAccessible) : null;
        var prevSibling = null;
        try {
          prevSibling = child.previousSibling;
        } catch (e) {}
        is(
          prevSibling,
          expectedPrevSibling,
          "Wrong previous sibling of " + prettyName(child)
        );

        // Go down through subtree
        testAccessibleTree(child, accTree.children[i], aFlags);
      }
    }
  }
}

/**
 * Return true if accessible for the given node is in cache.
 */

function isAccessibleInCache(aNodeOrId) {
  var node = getNode(aNodeOrId);
  return !!gAccService.getAccessibleFromCache(node);
}

/**
 * Test accessible tree for defunct accessible.
 *
 * @param  aAcc       [in] the defunct accessible
 * @param  aNodeOrId  [in] the DOM node identifier for the defunct accessible
 */

function testDefunctAccessible(aAcc, aNodeOrId) {
  if (aNodeOrId) {
    ok(
      !isAccessible(aNodeOrId),
      "Accessible for " + aNodeOrId + " wasn't properly shut down!"
    );
  }

  var msg =
    " doesn't fail for shut down accessible " + prettyName(aNodeOrId) + "!";

  // firstChild
  var success = false;
  try {
    aAcc.firstChild;
  } catch (e) {
    success = e.result == Cr.NS_ERROR_FAILURE;
  }
  ok(success, "firstChild" + msg);

  // lastChild
  success = false;
  try {
    aAcc.lastChild;
  } catch (e) {
    success = e.result == Cr.NS_ERROR_FAILURE;
  }
  ok(success, "lastChild" + msg);

  // childCount
  success = false;
  try {
    aAcc.childCount;
  } catch (e) {
    success = e.result == Cr.NS_ERROR_FAILURE;
  }
  ok(success, "childCount" + msg);

  // children
  success = false;
  try {
    aAcc.children;
  } catch (e) {
    success = e.result == Cr.NS_ERROR_FAILURE;
  }
  ok(success, "children" + msg);

  // nextSibling
  success = false;
  try {
    aAcc.nextSibling;
  } catch (e) {
    success = e.result == Cr.NS_ERROR_FAILURE;
  }
  ok(success, "nextSibling" + msg);

  // previousSibling
  success = false;
  try {
    aAcc.previousSibling;
  } catch (e) {
    success = e.result == Cr.NS_ERROR_FAILURE;
  }
  ok(success, "previousSibling" + msg);

  // parent
  success = false;
  try {
    aAcc.parent;
  } catch (e) {
    success = e.result == Cr.NS_ERROR_FAILURE;
  }
  ok(success, "parent" + msg);
}

/**
 * Convert role to human readable string.
 */

function roleToString(aRole) {
  return gAccService.getStringRole(aRole);
}

/**
 * Convert states to human readable string.
 */

function statesToString(aStates, aExtraStates) {
  var list = gAccService.getStringStates(aStates, aExtraStates);

  var str = "";
  for (var index = 0; index < list.length - 1; index++) {
    str += list.item(index) + ", ";
  }

  if (list.length) {
    str += list.item(index);
  }

  return str;
}

/**
 * Convert event type to human readable string.
 */

function eventTypeToString(aEventType) {
  return gAccService.getStringEventType(aEventType);
}

/**
 * Convert relation type to human readable string.
 */

function relationTypeToString(aRelationType) {
  return gAccService.getStringRelationType(aRelationType);
}

function getLoadContext() {
  return window.docShell.QueryInterface(Ci.nsILoadContext);
}

/**
 * Return text from clipboard.
 */

function getTextFromClipboard() {
  var trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(
    Ci.nsITransferable
  );
  trans.init(getLoadContext());
  if (!trans) {
    return "";
  }

  trans.addDataFlavor("text/plain");
  Services.clipboard.getData(
    trans,
    Services.clipboard.kGlobalClipboard,
    SpecialPowers.wrap(window).browsingContext.currentWindowContext
  );

  var str = {};
  trans.getTransferData("text/plain", str);

  if (str) {
    str = str.value.QueryInterface(Ci.nsISupportsString);
  }
  if (str) {
    return str.data;
  }

  return "";
}

/**
 * Extract DOMNode id from an accessible. If e10s is enabled, DOMNode is not
 * present in parent process but, if available, DOMNode id is attached to an
 * accessible object.
 * @param  {nsIAccessible} accessible  accessible
 * @return {String?}                   DOMNode id if available
 */

function getAccessibleDOMNodeID(accessible) {
  if (accessible instanceof nsIAccessibleDocument) {
    // If accessible is a document, trying to find its document body id.
    try {
      return accessible.DOMNode.body.id;
    } catch (e) {
      /* This only works if accessible is not a proxy. */
    }
  }
  try {
    return accessible.DOMNode.id;
  } catch (e) {
    /* This will fail if DOMNode is in different process. */
  }
  try {
    // When e10s is enabled, accessible will have an "id" property if its
    // corresponding DOMNode has an id. If accessible is a document, its "id"
    // property corresponds to the "id" of its body element.
    return accessible.id;
  } catch (e) {
    /* This will fail if accessible is not a proxy. */
  }
  return null;
}

/**
 * Return pretty name for identifier, it may be ID, DOM node or accessible.
 */

function prettyName(aIdentifier) {
  if (aIdentifier instanceof Array) {
    let msg = "";
    for (var idx = 0; idx < aIdentifier.length; idx++) {
      if (msg != "") {
        msg += ", ";
      }

      msg += prettyName(aIdentifier[idx]);
    }
    return msg;
  }

  if (aIdentifier instanceof nsIAccessible) {
    var acc = getAccessible(aIdentifier);
    var domID = getAccessibleDOMNodeID(acc);
    let msg = "[";
    try {
      if (Services.appinfo.browserTabsRemoteAutostart) {
        if (domID) {
          msg += `DOM node id: ${domID}, `;
        }
      } else {
        msg += `${getNodePrettyName(acc.DOMNode)}, `;
      }
      msg += "role: " + roleToString(acc.role);
      if (acc.name) {
        msg += ", name: '" + shortenString(acc.name) + "'";
      }
    } catch (e) {
      msg += "defunct";
    }

    if (acc) {
      msg += ", address: " + getObjAddress(acc);
    }
    msg += "]";

    return msg;
  }

  if (Node.isInstance(aIdentifier)) {
    return "[ " + getNodePrettyName(aIdentifier) + " ]";
  }

  if (aIdentifier && typeof aIdentifier === "object") {
    var treeObj = normalizeAccTreeObj(aIdentifier);
    if ("role" in treeObj) {
      function stringifyTree(aObj) {
        var text = roleToString(aObj.role) + ": [ ";
        if ("children" in aObj) {
          for (var i = 0; i < aObj.children.length; i++) {
            var c = normalizeAccTreeObj(aObj.children[i]);
            text += stringifyTree(c);
            if (i < aObj.children.length - 1) {
              text += ", ";
            }
          }
        }
        return text + "] ";
      }
      return `{ ${stringifyTree(treeObj)} }`;
    }
    return JSON.stringify(aIdentifier);
  }

  return " '" + aIdentifier + "' ";
}

/**
 * Shorten a long string if it exceeds MAX_TRIM_LENGTH.
 * @param aString the string to shorten.
 * @returns the shortened string.
 */

function shortenString(aString) {
  if (aString.length <= MAX_TRIM_LENGTH) {
    return aString;
  }

  // Trim the string if its length is > MAX_TRIM_LENGTH characters.
  var trimOffset = MAX_TRIM_LENGTH / 2;
  return (
    aString.substring(0, trimOffset - 1) +
    "..." +
    aString.substring(aString.length - trimOffset, aString.length)
  );
}

// //////////////////////////////////////////////////////////////////////////////
// General Utils
// //////////////////////////////////////////////////////////////////////////////
/**
 * Return main chrome window (crosses chrome boundary)
 */

function getMainChromeWindow(aWindow) {
  return aWindow.browsingContext.topChromeWindow;
}

// //////////////////////////////////////////////////////////////////////////////
// Private
// //////////////////////////////////////////////////////////////////////////////

// //////////////////////////////////////////////////////////////////////////////
// Accessible general

function getNodePrettyName(aNode) {
  try {
    var tag = "";
    if (aNode.nodeType == Node.DOCUMENT_NODE) {
      tag = "document";
    } else {
      tag = aNode.localName;
      if (aNode.nodeType == Node.ELEMENT_NODE && aNode.hasAttribute("id")) {
        tag += '@id="' + aNode.getAttribute("id") + '"';
      }
    }

    return "'" + tag + " node', address: " + getObjAddress(aNode);
  } catch (e) {
    return "' no node info '";
  }
}

function getObjAddress(aObj) {
  var exp = /native\s*@\s*(0x[a-f0-9]+)/g;
  var match = exp.exec(aObj.toString());
  if (match) {
    return match[1];
  }

  return aObj.toString();
}

function normalizeAccTreeObj(aObj) {
  var key = Object.keys(aObj)[0];
  var roleName = "ROLE_" + key;
  if (roleName in nsIAccessibleRole) {
    return {
      role: nsIAccessibleRole[roleName],
      children: aObj[key],
    };
  }
  return aObj;
}

Messung V0.5
C=92 H=90 G=90

¤ Dauer der Verarbeitung: 0.16 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge