author | Yura Zenevich <yzenevich@mozilla.com> |
Mon, 07 Nov 2016 12:15:08 -0500 | |
changeset 321422 | 4e6109ba565cc525681a1d3a4bfd343de1830b37 |
parent 321421 | cd40a468ed9c1da2403dd54d2c472bcf14d21118 |
child 321423 | f88d94ae4967e2bd71ce2a7de16af7d8b9129291 |
child 321458 | e388e453977c7bf257d87e97ff003c43f44b7c0f |
push id | 30927 |
push user | philringnalda@gmail.com |
push date | Tue, 08 Nov 2016 04:37:38 +0000 |
treeherder | mozilla-central@f88d94ae4967 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | ato |
bugs | 1312816 |
milestone | 52.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
testing/marionette/accessibility.js | file | annotate | diff | comparison | revisions | |
testing/marionette/driver.js | file | annotate | diff | comparison | revisions |
--- a/testing/marionette/accessibility.js +++ b/testing/marionette/accessibility.js @@ -4,44 +4,57 @@ "use strict"; const {classes: Cc, interfaces: Ci, utils: Cu} = Components; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Log.jsm"); +const logger = Log.repository.getLogger("Marionette"); + Cu.import("chrome://marionette/content/error.js"); XPCOMUtils.defineLazyModuleGetter( this, "setInterval", "resource://gre/modules/Timer.jsm"); XPCOMUtils.defineLazyModuleGetter( this, "clearInterval", "resource://gre/modules/Timer.jsm"); -XPCOMUtils.defineLazyGetter(this, "service", - () => Cc["@mozilla.org/accessibilityService;1"].getService(Ci.nsIAccessibilityService)); +XPCOMUtils.defineLazyGetter(this, "service", () => { + let service; + try { + service = Cc["@mozilla.org/accessibilityService;1"].getService( + Ci.nsIAccessibilityService); + } catch (e) { + logger.warn("Accessibility module is not present"); + } finally { + return service; + } +}); this.EXPORTED_SYMBOLS = ["accessibility"]; -const logger = Log.repository.getLogger("Marionette"); - /** * Number of attempts to get an accessible object for an element. * We attempt more than once because accessible tree can be out of sync * with the DOM tree for a short period of time. */ const GET_ACCESSIBLE_ATTEMPTS = 100; /** * An interval between attempts to retrieve an accessible object for an * element. */ const GET_ACCESSIBLE_ATTEMPT_INTERVAL = 10; -this.accessibility = {}; +this.accessibility = { + get service() { + return service; + } +}; /** * Accessible states used to check element"s state from the accessiblity API * perspective. * Note: if gecko is built with --disable-accessibility, the interfaces are not * defined. This is why we use getters instead to be able to use these * statically. */ @@ -118,40 +131,42 @@ accessibility.Checks = class { * Get an accessible object for an element. * * @param {DOMElement|XULElement} element * Element to get the accessible object for. * @param {boolean=} mustHaveAccessible * Flag indicating that the element must have an accessible object. * Defaults to not require this. * - * @return {nsIAccessible} - * Accessibility object for the given element. + * @return {Promise: nsIAccessible} + * Promise with an accessibility object for the given element. */ getAccessible(element, mustHaveAccessible = false) { - return new Promise((resolve, reject) => { - let acc = service.getAccessibleFor(element); + if (!this.strict) { + return Promise.resolve(); + } - // if accessible object is found, return it; - // if it is not required, also resolve - if (acc || !mustHaveAccessible) { - resolve(acc); + return new Promise((resolve, reject) => { + if (!accessibility.service) { + reject(); + return; + } - // if we must have an accessible but are strict, - // reject now and avoid polling for an accessible object - } else if (mustHaveAccessible && !this.strict) { - reject(); - - // if we require an accessible object, we need to poll for it - // because accessible tree might be - // out of sync with DOM tree for a short time + let acc = accessibility.service.getAccessibleFor(element); + if (acc || !mustHaveAccessible) { + // if accessible object is found, return it; + // if it is not required, also resolve + resolve(acc); } else { + // if we require an accessible object, we need to poll for it + // because accessible tree might be + // out of sync with DOM tree for a short time let attempts = GET_ACCESSIBLE_ATTEMPTS; let intervalId = setInterval(() => { - let acc = service.getAccessibleFor(element); + let acc = accessibility.service.getAccessibleFor(element); if (acc || --attempts <= 0) { clearInterval(intervalId); if (acc) { resolve(acc); } else { reject(); } } @@ -169,17 +184,17 @@ accessibility.Checks = class { * Accessible object. * * @return {boolean} * True if an actionable role is found on the accessible, false * otherwise. */ isActionableRole(accessible) { return accessibility.ActionableRoles.has( - service.getStringRole(accessible.role)); + accessibility.service.getStringRole(accessible.role)); } /** * Test if an accessible has at least one action that it supports. * * @param {nsIAccessible} accessible * Accessible object. * @@ -407,22 +422,20 @@ accessibility.Checks = class { * @param {string} message * @param {DOMElement|XULElement} element * Element that caused an error. * * @throws ElementNotAccessibleError * If |strict| is true. */ error(message, element) { - if (!message) { + if (!message || !this.strict) { return; } if (element) { let {id, tagName, className} = element; message += `: id: ${id}, tagName: ${tagName}, className: ${className}`; } - if (this.strict) { - throw new ElementNotAccessibleError(message); - } - logger.debug(message); + + throw new ElementNotAccessibleError(message); } };
--- a/testing/marionette/driver.js +++ b/testing/marionette/driver.js @@ -12,16 +12,17 @@ var loader = Cc["@mozilla.org/moz/jssubs Cu.import("resource://gre/modules/Log.jsm"); Cu.import("resource://gre/modules/Preferences.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyServiceGetter( this, "cookieManager", "@mozilla.org/cookiemanager;1", "nsICookieManager2"); +Cu.import("chrome://marionette/content/accessibility.js"); Cu.import("chrome://marionette/content/atom.js"); Cu.import("chrome://marionette/content/browser.js"); Cu.import("chrome://marionette/content/element.js"); Cu.import("chrome://marionette/content/error.js"); Cu.import("chrome://marionette/content/evaluate.js"); Cu.import("chrome://marionette/content/event.js"); Cu.import("chrome://marionette/content/interaction.js"); Cu.import("chrome://marionette/content/legacyaction.js"); @@ -479,16 +480,24 @@ GeckoDriver.prototype.newSession = funct throw new SessionNotCreatedError("Maximum number of active sessions.") } this.sessionId = cmd.parameters.sessionId || cmd.parameters.session_id || element.generateUUID(); this.newSessionCommandId = cmd.id; this.setSessionCapabilities(cmd.parameters.capabilities); + // If we are testing accessibility with marionette, start a11y service in + // chrome first. This will ensure that we do not have any content-only + // services hanging around. + if (this.sessionCapabilities.raisesAccessibilityExceptions && + accessibility.service) { + logger.info("Preemptively starting accessibility service in Chrome"); + } + this.scriptTimeout = 10000; let registerBrowsers = this.registerPromise(); let browserListening = this.listeningPromise(); let waitForWindow = function() { let win = this.getCurrentWindow(); if (!win) {