Backed out 8 changesets (bug 1828816, bug 1822112, bug 1572512, bug 1824935) for causing multiple failures. CLOSED TREE

Backed out changeset 8886f7011919 (bug 1822112)
Backed out changeset df566bce405d (bug 1828816)
Backed out changeset 5857e8ef63e1 (bug 1828816)
Backed out changeset 50324d39e9c1 (bug 1822112)
Backed out changeset 7f6bee1959fb (bug 1572512)
Backed out changeset 4effd0bdc4db (bug 1824935)
Backed out changeset a8faf17fcce8 (bug 1824935)
Backed out changeset 0370b0032eb6 (bug 1824935)
This commit is contained in:
Stanca Serban 2023-04-25 07:45:58 +03:00
parent 68b9ed8368
commit 041c4044bd
37 changed files with 334 additions and 582 deletions

View File

@ -564,8 +564,8 @@ void AccessibleWrap::SetVirtualViewID(Accessible* aAccessible,
}
int32_t AccessibleWrap::GetAndroidClass(role aRole) {
#define ROLE(geckoRole, stringRole, ariaRole, atkRole, macRole, macSubrole, \
msaaRole, ia2Role, androidClass, nameRule) \
#define ROLE(geckoRole, stringRole, atkRole, macRole, macSubrole, msaaRole, \
ia2Role, androidClass, nameRule) \
case roles::geckoRole: \
return androidClass;

View File

@ -64,8 +64,8 @@ void a11y::PlatformInit() {
}
// Preload any roles that have localized versions
#define ROLE(geckoRole, stringRole, ariaRole, atkRole, macRole, macSubrole, \
msaaRole, ia2Role, androidClass, nameRule) \
#define ROLE(geckoRole, stringRole, atkRole, macRole, macSubrole, msaaRole, \
ia2Role, androidClass, nameRule) \
rv = stringBundle->GetStringFromName(stringRole, localizedStr); \
if (NS_SUCCEEDED(rv)) { \
sLocalizedStrings.InsertOrUpdate(u##stringRole##_ns, localizedStr); \

View File

@ -581,8 +581,8 @@ AtkRole getRoleCB(AtkObject* aAtkObj) {
}
#endif
#define ROLE(geckoRole, stringRole, ariaRole, atkRole, macRole, macSubrole, \
msaaRole, ia2Role, androidClass, nameRule) \
#define ROLE(geckoRole, stringRole, atkRole, macRole, macSubrole, msaaRole, \
ia2Role, androidClass, nameRule) \
case roles::geckoRole: \
aAtkObj->role = atkRole; \
break;

View File

@ -11,8 +11,8 @@
using namespace mozilla::a11y;
#define ROLE(geckoRole, stringRole, ariaRole, atkRole, macRole, macSubrole, \
msaaRole, ia2Role, androidClass, nameRule) \
#define ROLE(geckoRole, stringRole, atkRole, macRole, macSubrole, msaaRole, \
ia2Role, androidClass, nameRule) \
static_assert( \
static_cast<uint32_t>(roles::geckoRole) == \
static_cast<uint32_t>(nsIAccessibleRole::ROLE_##geckoRole), \

File diff suppressed because it is too large Load Diff

View File

@ -786,8 +786,8 @@ void nsAccessibilityService::RecreateAccessible(PresShell* aPresShell,
}
void nsAccessibilityService::GetStringRole(uint32_t aRole, nsAString& aString) {
#define ROLE(geckoRole, stringRole, ariaRole, atkRole, macRole, macSubrole, \
msaaRole, ia2Role, androidClass, nameRule) \
#define ROLE(geckoRole, stringRole, atkRole, macRole, macSubrole, msaaRole, \
ia2Role, androidClass, nameRule) \
case roles::geckoRole: \
aString.AssignLiteral(stringRole); \
return;

View File

@ -312,8 +312,8 @@ bool nsTextEquivUtils::AppendString(nsAString* aString,
}
uint32_t nsTextEquivUtils::GetRoleRule(role aRole) {
#define ROLE(geckoRole, stringRole, ariaRole, atkRole, macRole, macSubrole, \
msaaRole, ia2Role, androidClass, nameRule) \
#define ROLE(geckoRole, stringRole, atkRole, macRole, macSubrole, msaaRole, \
ia2Role, androidClass, nameRule) \
case roles::geckoRole: \
return nameRule;

View File

@ -476,7 +476,7 @@ const Accessible* Accessible::ActionAncestor() const {
return nullptr;
}
nsStaticAtom* Accessible::LandmarkRole() const {
nsAtom* Accessible::LandmarkRole() const {
nsAtom* tagName = TagName();
if (!tagName) {
// Either no associated content, or no cache.
@ -529,47 +529,6 @@ nsStaticAtom* Accessible::LandmarkRole() const {
: nullptr;
}
nsStaticAtom* Accessible::ComputedARIARole() const {
const nsRoleMapEntry* roleMap = ARIARoleMap();
if (roleMap && roleMap->roleAtom != nsGkAtoms::_empty &&
// region has its own Gecko role and it needs to be handled specially.
roleMap->roleAtom != nsGkAtoms::region &&
(roleMap->roleRule == kUseNativeRole || roleMap->IsOfType(eLandmark) ||
roleMap->roleAtom == nsGkAtoms::alertdialog ||
roleMap->roleAtom == nsGkAtoms::feed ||
roleMap->roleAtom == nsGkAtoms::rowgroup ||
roleMap->roleAtom == nsGkAtoms::searchbox)) {
// Explicit ARIA role (e.g. specified via the role attribute) which does not
// map to a unique Gecko role.
return roleMap->roleAtom;
}
role geckoRole = Role();
if (geckoRole == roles::LANDMARK) {
// Landmark role from native markup; e.g. <main>, <nav>.
return LandmarkRole();
}
if (geckoRole == roles::GROUPING) {
// Gecko doesn't differentiate between group and rowgroup. It uses
// roles::GROUPING for both.
nsAtom* tag = TagName();
if (tag == nsGkAtoms::tbody || tag == nsGkAtoms::tfoot ||
tag == nsGkAtoms::thead) {
return nsGkAtoms::rowgroup;
}
}
// Role from native markup or layout.
#define ROLE(_geckoRole, stringRole, ariaRole, atkRole, macRole, macSubrole, \
msaaRole, ia2Role, androidClass, nameRule) \
case roles::_geckoRole: \
return ariaRole;
switch (geckoRole) {
#include "RoleMap.h"
}
#undef ROLE
MOZ_ASSERT_UNREACHABLE("Unknown role");
return nullptr;
}
void Accessible::ApplyImplicitState(uint64_t& aState) const {
// nsAccessibilityService (and thus FocusManager) can be shut down before
// RemoteAccessibles.

View File

@ -13,7 +13,6 @@
#include "Units.h"
class nsAtom;
class nsStaticAtom;
struct nsRoleMapEntry;
@ -352,13 +351,6 @@ class Accessible {
*/
virtual void Language(nsAString& aLocale) = 0;
/**
* Get the role of this Accessible as an ARIA role token. This might have been
* set explicitly (e.g. role="button") or it might be implicit in native
* markup (e.g. <button> returns "button").
*/
nsStaticAtom* ComputedARIARole() const;
// Methods that interact with content.
virtual void TakeFocus() const = 0;
@ -382,7 +374,7 @@ class Accessible {
/**
* Return a landmark role if applied.
*/
virtual nsStaticAtom* LandmarkRole() const;
virtual nsAtom* LandmarkRole() const;
/**
* Return the id of the dom node this accessible represents.

View File

@ -345,13 +345,6 @@ interface nsIAccessible : nsISupports
*/
void announce(in AString announcement, in unsigned short priority);
/**
* Get the role of this Accessible as an ARIA role token. This might have been
* set explicitly (e.g. role="button") or it might be implicit in native
* markup (e.g. <button> returns "button").
*/
readonly attribute AString computedARIARole;
[notxpcom, nostdcall] InternalLocalAccessible toInternalAccessible();
[notxpcom, nostdcall] InternalAccessible toInternalGeneric();

View File

@ -127,7 +127,7 @@ bool RemoteAccessible::IsSearchbox() const {
return retVal;
}
nsStaticAtom* RemoteAccessible::LandmarkRole() const {
nsAtom* RemoteAccessible::LandmarkRole() const {
if (StaticPrefs::accessibility_cache_enabled_AtStartup()) {
return RemoteAccessibleBase<RemoteAccessible>::LandmarkRole();
}

View File

@ -73,7 +73,7 @@ class RemoteAccessible : public RemoteAccessibleBase<RemoteAccessible> {
virtual bool SelectAll() override;
virtual bool UnselectAll() override;
virtual nsStaticAtom* LandmarkRole() const override;
virtual nsAtom* LandmarkRole() const override;
virtual bool IsSearchbox() const override;

View File

@ -356,8 +356,8 @@ static const uint64_t kCacheInitialized = ((uint64_t)0x1) << 63;
}
- (NSString*)moxRole {
#define ROLE(geckoRole, stringRole, ariaRole, atkRole, macRole, macSubrole, \
msaaRole, ia2Role, androidClass, nameRule) \
#define ROLE(geckoRole, stringRole, atkRole, macRole, macSubrole, msaaRole, \
ia2Role, androidClass, nameRule) \
case roles::geckoRole: \
return macRole;
@ -430,8 +430,8 @@ static const uint64_t kCacheInitialized = ((uint64_t)0x1) << 63;
}
}
#define ROLE(geckoRole, stringRole, ariaRole, atkRole, macRole, macSubrole, \
msaaRole, ia2Role, androidClass, nameRule) \
#define ROLE(geckoRole, stringRole, atkRole, macRole, macSubrole, msaaRole, \
ia2Role, androidClass, nameRule) \
case roles::geckoRole: \
if (![macSubrole isEqualToString:NSAccessibilityUnknownSubrole]) { \
return macSubrole; \

View File

@ -40,7 +40,6 @@ BROWSER_CHROME_MANIFESTS += [
"tests/browser/general/browser.ini",
"tests/browser/hittest/browser.ini",
"tests/browser/mac/browser.ini",
"tests/browser/role/browser.ini",
"tests/browser/scroll/browser.ini",
"tests/browser/selectable/browser.ini",
"tests/browser/states/browser.ini",

View File

@ -1,11 +0,0 @@
[DEFAULT]
subsuite = a11y
support-files =
head.js
!/accessible/tests/browser/shared-head.js
!/accessible/tests/mochitest/*.js
!/accessible/tests/browser/*.mjs
prefs =
javascript.options.asyncstack_capture_debuggee_only=false
[browser_computedARIARole.js]

View File

@ -1,88 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
addAccessibleTask(
`
<div id="ariaButton" role="button">ARIA button</div>
<div id="ariaLog" role="log">ARIA log</div>
<div id="ariaMain" role="main">ARIA main</div>
<div id="ariaRegion" role="region" aria-label="ARIA region">ARIA region</div>
<nav id="ariaUnnamedRegion" role="region">ARIA unnamed region</nav>
<div id="ariaDirectory" role="directory">ARIA directory</div>
<div id="ariaAlertdialog" role="alertdialog">ARIA alertdialog</div>
<div id="ariaFeed" role="feed">ARIA feed</div>
<div id="ariaRowgroup" role="rowgroup">ARIA rowgroup</div>
<div id="ariaSearchbox" role="searchbox">ARIA searchbox</div>
<div id="ariaUnknown" role="unknown">unknown ARIA role</div>
<button id="htmlButton">HTML button</button>
<button id="toggleButton" aria-pressed="true">toggle button</button>
<main id="htmlMain">HTML main</main>
<header id="htmlHeader">HTML header</header>
<section id="htmlSection">
<header id="htmlSectionHeader">HTML header inside section</header>
</section>
<section id="htmlRegion" aria-label="HTML region">HTML region</section>
<fieldset id="htmlFieldset">HTML fieldset</fieldset>
<table>
<tbody id="htmlTbody" tabindex="-1"><tr><th>HTML tbody</th></tr></tbody>
</table>
<table role="grid">
<tr>
<td id="htmlGridcell">HTML implicit gridcell</td>
</tr>
</table>
<div id="htmlDiv">HTML div</div>
<span id="htmlSpan" aria-label="HTML span">HTML span</span>
<iframe id="iframe"></iframe>
`,
async function(browser, docAcc) {
function testComputedARIARole(id, role) {
const acc = findAccessibleChildByID(docAcc, id);
is(acc.computedARIARole, role, `computedARIARole for ${id} is correct`);
}
testComputedARIARole("ariaButton", "button");
testComputedARIARole("ariaLog", "log");
// Landmarks map to a single Gecko role.
testComputedARIARole("ariaMain", "main");
testComputedARIARole("ariaRegion", "region");
// Unnamed ARIA regions should ignore the ARIA role.
testComputedARIARole("ariaUnnamedRegion", "navigation");
// The directory ARIA role is an alias of list.
testComputedARIARole("ariaDirectory", "list");
// alertdialog, feed, rowgroup and searchbox map to a Gecko role, but it
// isn't unique.
testComputedARIARole("ariaAlertdialog", "alertdialog");
testComputedARIARole("ariaFeed", "feed");
testComputedARIARole("ariaRowgroup", "rowgroup");
testComputedARIARole("ariaSearchbox", "searchbox");
testComputedARIARole("ariaUnknown", "generic");
testComputedARIARole("htmlButton", "button");
// There is only a single ARIA role for buttons, but Gecko uses different
// roles depending on states.
testComputedARIARole("toggleButton", "button");
testComputedARIARole("htmlMain", "main");
testComputedARIARole("htmlHeader", "banner");
// <section> only maps to the region ARIA role if it has a label.
testComputedARIARole("htmlSection", "generic");
// <header> only maps to the banner role if it is not a child of a
// sectioning element.
testComputedARIARole("htmlSectionHeader", "generic");
testComputedARIARole("htmlRegion", "region");
// Gecko doesn't have a rowgroup role. Ensure we differentiate for
// computedARIARole.
testComputedARIARole("htmlFieldset", "group");
testComputedARIARole("htmlTbody", "rowgroup");
// <td> inside <table role="grid"> implicitly maps to ARIA gridcell.
testComputedARIARole("htmlGridcell", "gridcell");
// Test generics.
testComputedARIARole("htmlDiv", "generic");
testComputedARIARole("htmlSpan", "generic");
// Some roles can't be mapped to ARIA role tokens.
testComputedARIARole("iframe", "");
},
{ chrome: true, topLevel: true }
);

View File

@ -1,18 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
// Load the shared-head file first.
Services.scriptloader.loadSubScript(
"chrome://mochitests/content/browser/accessible/tests/browser/shared-head.js",
this
);
// Loading and common.js from accessible/tests/mochitest/ for all tests, as
// well as promisified-events.js.
loadScripts(
{ name: "common.js", dir: MOCHITESTS_DIR },
{ name: "promisified-events.js", dir: MOCHITESTS_DIR }
);

View File

@ -161,8 +161,8 @@ ia2Accessible::role(long* aRole) {
Accessible* acc = Acc();
if (!acc) return CO_E_OBJNOTCONNECTED;
#define ROLE(_geckoRole, stringRole, ariaRole, atkRole, macRole, macSubrole, \
msaaRole, ia2Role, androidClass, nameRule) \
#define ROLE(_geckoRole, stringRole, atkRole, macRole, macSubrole, msaaRole, \
ia2Role, androidClass, nameRule) \
case roles::_geckoRole: \
*aRole = ia2Role; \
break;

View File

@ -1104,10 +1104,10 @@ MsaaAccessible::get_accRole(
uint32_t msaaRole = 0;
#define ROLE(_geckoRole, stringRole, ariaRole, atkRole, macRole, macSubrole, \
_msaaRole, ia2Role, androidClass, nameRule) \
case roles::_geckoRole: \
msaaRole = _msaaRole; \
#define ROLE(_geckoRole, stringRole, atkRole, macRole, macSubrole, _msaaRole, \
ia2Role, androidClass, nameRule) \
case roles::_geckoRole: \
msaaRole = _msaaRole; \
break;
switch (geckoRole) {

View File

@ -762,17 +762,3 @@ xpcAccessible::Announce(const nsAString& aAnnouncement, uint16_t aPriority) {
return NS_OK;
}
NS_IMETHODIMP
xpcAccessible::GetComputedARIARole(nsAString& aRole) {
if (!IntlGeneric()) {
return NS_ERROR_FAILURE;
}
nsStaticAtom* ariaRole = IntlGeneric()->ComputedARIARole();
if (ariaRole) {
ariaRole->ToString(aRole);
}
return NS_OK;
}

View File

@ -93,8 +93,6 @@ class xpcAccessible : public nsIAccessible {
NS_IMETHOD Announce(const nsAString& aAnnouncement, uint16_t aPriority) final;
NS_IMETHOD GetComputedARIARole(nsAString& aRole) final;
protected:
xpcAccessible() {}
virtual ~xpcAccessible() {}

View File

@ -167,7 +167,7 @@ function getSnapshot(acc, a11yService, targetActor) {
const { nodeType, nodeCssSelector } = getNodeDescription(acc.DOMNode);
const snapshot = {
name: acc.name,
role: getStringRole(acc, a11yService),
role: a11yService.getStringRole(acc.role),
actions,
value: acc.value,
nodeCssSelector,
@ -192,27 +192,6 @@ function getSnapshot(acc, a11yService, targetActor) {
return snapshot;
}
/**
* Get a string indicating the role of the nsIAccessible object.
* An ARIA role token will be returned unless the role can't be mapped to an
* ARIA role (e.g. <iframe>), in which case a Gecko role string will be
* returned.
* @param {nsIAccessible} acc
* Accessible object to take a snapshot of.
* @param {nsIAccessibilityService} a11yService
* Accessibility service instance in the current process, used to get localized
* string representation of various accessible properties.
* @return String
*/
function getStringRole(acc, a11yService) {
let role = acc.computedARIARole;
if (!role) {
// We couldn't map to an ARIA role, so use a Gecko role string.
role = a11yService.getStringRole(acc.role);
}
return role;
}
/**
* The AccessibleActor provides information about a given accessible object: its
* role, name, states, etc.
@ -253,7 +232,7 @@ class AccessibleActor extends Actor {
if (this.isDefunct) {
return null;
}
return getStringRole(this.rawAccessible, this.walker.a11yService);
return this.walker.a11yService.getStringRole(this.rawAccessible.role);
}
get name() {

View File

@ -23,7 +23,7 @@ add_task(async function() {
checkA11yFront(accessibleFront, {
name: "Accessible Button",
role: "button",
role: "pushbutton",
childCount: 1,
});
@ -31,7 +31,7 @@ add_task(async function() {
checkA11yFront(accessibleFront, {
name: "Accessible Button",
role: "button",
role: "pushbutton",
value: "",
description: "Accessibility Test",
keyboardShortcut: modifiers + "b",
@ -92,7 +92,7 @@ add_task(async function() {
const snapshot = await controlAccessibleFront.snapshot();
Assert.deepEqual(snapshot, {
name: "Label",
role: "textbox",
role: "entry",
actions: ["Activate"],
value: "",
nodeCssSelector: "#control",
@ -126,30 +126,6 @@ add_task(async function() {
},
});
// Check that we're using ARIA role tokens for landmarks implicit in native
// markup.
const headerNode = await walker.querySelector(walker.rootNode, "#header");
const headerAccessibleFront = await a11yWalker.getAccessibleFor(headerNode);
checkA11yFront(headerAccessibleFront, {
name: null,
role: "banner",
childCount: 1,
});
const navNode = await walker.querySelector(walker.rootNode, "#nav");
const navAccessibleFront = await a11yWalker.getAccessibleFor(navNode);
checkA11yFront(navAccessibleFront, {
name: null,
role: "navigation",
childCount: 1,
});
const footerNode = await walker.querySelector(walker.rootNode, "#footer");
const footerAccessibleFront = await a11yWalker.getAccessibleFor(footerNode);
checkA11yFront(footerAccessibleFront, {
name: null,
role: "contentinfo",
childCount: 1,
});
await waitForA11yShutdown(parentAccessibility);
await target.destroy();
gBrowser.removeCurrentTab();

View File

@ -28,7 +28,7 @@ add_task(async function() {
checkA11yFront(accessibleFront, {
name: "Accessible Button",
role: "button",
role: "pushbutton",
childCount: 1,
});
@ -36,7 +36,7 @@ add_task(async function() {
checkA11yFront(accessibleFront, {
name: "Accessible Button",
role: "button",
role: "pushbutton",
value: "",
description: "Accessibility Test",
keyboardShortcut: modifiers + "b",

View File

@ -38,7 +38,7 @@ add_task(async function() {
checkA11yFront(accessibleFront, {
name: "Accessible Button",
role: "button",
role: "pushbutton",
});
const ancestry = await a11yWalker.getAncestry(accessibleFront);
@ -50,7 +50,7 @@ add_task(async function() {
);
is(
ancestry[0].children.length,
7,
4,
"Root doc should have correct number of children"
);
ok(
@ -79,7 +79,7 @@ add_task(async function() {
// Ensure reorder event is emitted by walker when DOM tree changes.
let docChildren = await a11yDoc.children();
is(docChildren.length, 7, "Root doc should have correct number of children");
is(docChildren.length, 4, "Root doc should have correct number of children");
await emitA11yEvent(
a11yWalker,
@ -96,7 +96,7 @@ add_task(async function() {
);
docChildren = await a11yDoc.children();
is(docChildren.length, 8, "Root doc should have correct number of children");
is(docChildren.length, 5, "Root doc should have correct number of children");
let shown = await a11yWalker.highlightAccessible(docChildren[0]);
ok(shown, "AccessibleHighlighter highlighted the node");

View File

@ -11,8 +11,5 @@
<label id="label" for="control">Label
<input id="control">
</label>
<header id="header">header</header>
<nav id="nav">nav</nav>
<footer id="footer">footer</footer>
</body>
</html>

View File

@ -92,6 +92,38 @@ accessibility.get = function(strict = false) {
return new accessibility.Checks(!!strict);
};
/**
* Wait for the document accessibility state to be different from STATE_BUSY.
*
* @param {Document} doc
* The document to wait for.
* @returns {Promise}
* A promise which resolves when the document's accessibility state is no
* longer busy.
*/
function waitForDocumentAccessibility(doc) {
const documentAccessible = accessibility.service.getAccessibleFor(doc);
const state = {};
documentAccessible.getState(state, {});
if ((state.value & Ci.nsIAccessibleStates.STATE_BUSY) == 0) {
return Promise.resolve();
}
// Accessibility for the doc is busy, so wait for the state to change.
return lazy.waitForObserverTopic("accessible-event", {
checkFn: subject => {
// If event type does not match expected type, skip the event.
// If event's accessible does not match expected accessible,
// skip the event.
const event = subject.QueryInterface(Ci.nsIAccessibleEvent);
return (
event.eventType === Ci.nsIAccessibleEvent.EVENT_STATE_CHANGE &&
event.accessible === documentAccessible
);
},
});
}
/**
* Retrieve the Accessible for the provided element.
*
@ -107,30 +139,8 @@ accessibility.getAccessible = async function(element) {
return null;
}
const acc = accessibility.service.getAccessibleFor(element);
if (acc) {
return acc;
}
// The Accessible doesn't exist yet. This can happen because a11y tree
// mutations happen during refresh driver ticks. Wait for a11y events,
// checking after each event to see if the Accessible exists yet and returning
// it if it does. Stop waiting after a short timeout because the Accessible
// might never be created and we want to report a failure without breaking
// subsequent tests.
try {
await lazy.waitForObserverTopic("accessible-event", {
checkFn: subject => {
return !!accessibility.service.getAccessibleFor(element);
},
timeout: 100,
});
} catch (e) {
// Don't treat a timeout as an error. We will most likely return null below.
if (!(e instanceof lazy.error.TimeoutError)) {
throw e;
}
}
// First, wait for accessibility to be ready for the element's document.
await waitForDocumentAccessibility(element.ownerDocument);
return accessibility.service.getAccessibleFor(element);
};

View File

@ -311,7 +311,8 @@ export class MarionetteCommandsChild extends JSWindowActorChild {
return null;
}
return accessible.computedARIARole;
// TODO: Bug 1822112. Accessibility service is not returning WAI-ARIA roles.
return lazy.accessibility.service.getStringRole(accessible.role);
}
/**

View File

@ -468,73 +468,32 @@ export function waitForMessage(
* if the notification is the expected one, or false if it should be
* ignored and listening should continue. If not specified, the first
* notification for the specified topic resolves the returned promise.
* @param {number=} options.timeout
* Timeout duration in milliseconds, if provided.
* If specified, then the returned promise will be rejected with
* TimeoutError, if not already resolved, after this duration has elapsed.
* If not specified, then no timeout is used. Defaults to null.
*
* @returns {Promise.<Array<string, object>>}
* Promise which is either resolved to an array of ``subject``, and ``data``
* from the observed notification, or rejected with TimeoutError after
* options.timeout milliseconds if specified.
*
* @throws {TypeError}
* @throws {RangeError}
* Promise which resolves to an array of ``subject``, and ``data`` from
* the observed notification.
*/
export function waitForObserverTopic(topic, options = {}) {
const { checkFn = null, timeout = null } = options;
export function waitForObserverTopic(topic, { checkFn = null } = {}) {
if (typeof topic != "string") {
throw new TypeError();
}
if (
(checkFn != null && typeof checkFn != "function") ||
(timeout !== null && typeof timeout != "number")
) {
if (checkFn != null && typeof checkFn != "function") {
throw new TypeError();
}
if (timeout && (!Number.isInteger(timeout) || timeout < 0)) {
throw new RangeError();
}
return new Promise((resolve, reject) => {
let timer;
function cleanUp() {
Services.obs.removeObserver(observer, topic);
timer?.cancel();
}
function observer(subject, topic, data) {
Services.obs.addObserver(function observer(subject, topic, data) {
lazy.logger.trace(`Received observer notification ${topic}`);
try {
if (checkFn && !checkFn(subject, data)) {
return;
}
cleanUp();
Services.obs.removeObserver(observer, topic);
resolve({ subject, data });
} catch (ex) {
cleanUp();
Services.obs.removeObserver(observer, topic);
reject(ex);
}
}
Services.obs.addObserver(observer, topic);
if (timeout !== null) {
timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.init(
() => {
cleanUp();
reject(
new lazy.error.TimeoutError(
`waitForObserverTopic timed out after ${timeout} ms`
)
);
},
timeout,
TYPE_ONE_SHOT
);
}
}, topic);
});
}

View File

@ -382,38 +382,3 @@ add_task(async function test_waitForObserverTopic_checkFnTypes() {
equal(expected_data, result.data);
}
});
add_task(async function test_waitForObserverTopic_timeoutTypes() {
for (let timeout of ["foo", true, [], {}]) {
Assert.throws(
() => waitForObserverTopic("message", { timeout }),
/TypeError/
);
}
for (let timeout of [1.2, -1]) {
Assert.throws(
() => waitForObserverTopic("message", { timeout }),
/RangeError/
);
}
for (let timeout of [null, undefined, 42]) {
let data = { foo: "bar" };
let sent = waitForObserverTopic("message", { timeout });
Services.obs.notifyObservers(this, "message", data);
let result = await sent;
equal(this, result.subject);
equal(data, result.data);
}
});
add_task(async function test_waitForObserverTopic_timeoutElapse() {
try {
await waitForObserverTopic("message", { timeout: 0 });
ok(false, "Expected Timeout error not raised");
} catch (e) {
ok(
e.message.includes("waitForObserverTopic timed out after"),
"Expected error received"
);
}
});

View File

@ -16,7 +16,7 @@ class TestGetComputedRole(MarionetteTestCase):
def test_can_get_computed_role(self):
self.marionette.navigate(inline("<button id=a>btn</button>"))
computed_role = self.marionette.find_element(By.ID, "a").computed_role
self.assertEqual(computed_role, "button")
self.assertEqual(computed_role, "pushbutton")
def test_get_computed_role_no_such_element(self):
self.marionette.navigate(inline("<div id=a>"))

View File

@ -0,0 +1,4 @@
[basic.html]
[tests explicit role]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1822112

View File

@ -0,0 +1,3 @@
[region-roles.html]
[region without label]
expected: FAIL

View File

@ -1,20 +1,251 @@
[roles.html]
[role: alertdialog]
expected: FAIL
[role: application]
expected:
if (os == "win") and debug and (processor == "x86_64") and not swgl: [FAIL, PASS]
if (os == "linux") and (processor == "x86"): [FAIL, PASS]
[PASS, FAIL]
[role: article]
expected:
if (os == "win") and (processor == "x86_64") and debug and not swgl: [FAIL, PASS]
if (os == "win") and (processor == "x86_64") and not debug: [FAIL, PASS]
if (os == "mac") and not debug: [FAIL, PASS]
[PASS, FAIL]
[role: banner]
expected: FAIL
[role: button]
expected: FAIL
[role: checkbox]
expected: FAIL
[role: combobox]
expected: FAIL
[role: complementary]
expected: FAIL
[role: contentinfo]
expected: FAIL
[role: definition]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1829028
[role: deletion]
expected: FAIL
[role: document]
expected: FAIL
[role: emphasis]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1732306
[role: feed]
expected: FAIL
[role: generic]
expected: FAIL
[role: group]
expected: FAIL
[role: insertion]
expected: FAIL
[role: log]
expected: FAIL
[role: main]
expected: FAIL
[role: marquee]
expected: FAIL
[role: math]
expected: FAIL
[role: navigation]
expected: FAIL
[role: radio]
expected: FAIL
[role: radiogroup]
expected: FAIL
[role: search]
expected: FAIL
[role: searchbox]
expected: FAIL
[role: status]
expected: FAIL
[role: strong]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1732306
[role: textbox]
expected: FAIL
[role: time]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1732306
[role: timer]
expected: FAIL
[role: blockquote]
expected:
if (os == "win") and not debug and (processor == "x86"): [FAIL, PASS]
if (os == "mac") and not debug: [FAIL, PASS]
[PASS, FAIL]
[role: caption]
expected:
if (os == "win") and not debug and (processor == "x86"): [FAIL, PASS]
[PASS, FAIL]
[role: code]
expected:
if (os == "mac") and not debug: [FAIL, PASS]
if (os == "win") and not debug: [FAIL, PASS]
[PASS, FAIL]
[role: dialog]
expected:
if (os == "mac") and not debug: [FAIL, PASS]
[PASS, FAIL]
[role: figure]
expected:
if (os == "win") and not debug and (processor == "x86"): [FAIL, PASS]
if (os == "win") and not debug and (processor == "x86_64"): [FAIL, PASS]
[PASS, FAIL]
[role: form]
expected:
if (os == "win") and not debug and (processor == "x86"): [FAIL, PASS]
if (os == "win") and not debug and (processor == "x86_64"): [FAIL, PASS]
if (os == "linux") and not debug and (processor == "x86"): [FAIL, PASS]
if (os == "mac") and not debug: [FAIL, PASS]
[PASS, FAIL]
[role: heading]
expected:
if (os == "mac") and not debug: [FAIL, PASS]
[PASS, FAIL]
[role: link]
expected:
if (os == "win") and not debug: [FAIL, PASS]
[PASS, FAIL]
[role: meter]
expected:
if (os == "win") and not debug: [FAIL, PASS]
if (os == "mac") and not debug: [FAIL, PASS]
if (os == "linux") and (processor == "x86"): [FAIL, PASS]
[PASS, FAIL]
[role: note]
expected:
if (os == "linux") and not debug and fission and (processor == "x86"): [FAIL, PASS]
if (os == "win") and not debug: [FAIL, PASS]
[PASS, FAIL]
[role: paragraph]
expected:
if (os == "win") and not debug and (processor == "x86"): [FAIL, PASS]
if (os == "win") and not debug and (processor == "x86_64"): [FAIL, PASS]
if (os == "mac") and not debug: [FAIL, PASS]
if (os == "linux") and (processor == "x86"): [FAIL, PASS]
[PASS, FAIL]
[role: progressbar]
expected:
if (os == "linux") and not debug and fission and (processor == "x86"): [FAIL, PASS]
if (os == "win") and not debug and (processor == "x86"): [FAIL, PASS]
[PASS, FAIL]
[role: scrollbar]
expected:
if (os == "win") and (processor == "x86_64") and not debug: [FAIL, PASS]
if (os == "linux") and (processor == "x86"): [FAIL, PASS]
if (os == "mac") and not debug: [FAIL, PASS]
[PASS, FAIL]
[role: separator]
expected:
if (os == "linux") and not debug and (processor == "x86"): [FAIL, PASS]
if (os == "win") and not debug: [FAIL, PASS]
if (os == "mac") and not debug: [FAIL, PASS]
[PASS, FAIL]
[role: slider]
expected:
if (os == "win") and not debug and (processor == "x86_64"): [FAIL, PASS]
if (os == "win") and not debug and (processor == "x86"): [FAIL, PASS]
if (os == "linux") and (processor == "x86"): [FAIL, PASS]
[PASS, FAIL]
[role: spinbutton]
expected:
if (os == "win") and not swgl and not debug and (processor == "x86"): [FAIL, PASS]
if (os == "mac") and not debug: [FAIL, PASS]
if (os == "linux") and (processor == "x86"): [FAIL, PASS]
[PASS, FAIL]
[role: subscript]
expected:
if (os == "mac") and not debug: [FAIL, PASS]
if (os == "mac") and debug: [FAIL, PASS]
[PASS, FAIL]
[role: suggestion]
expected:
if (os == "win") and not debug and (processor == "x86_64"): [FAIL, PASS]
if (os == "mac") and not debug: [FAIL, PASS]
if (os == "linux") and (processor == "x86"): [FAIL, PASS]
[PASS, FAIL]
[role: superscript]
expected:
if (os == "linux") and (processor == "x86"): [FAIL, PASS]
if (os == "win") and not debug: [FAIL, PASS]
[PASS, FAIL]
[role: switch]
expected:
if (os == "win") and not debug and (processor == "x86"): [FAIL, PASS]
if (os == "win") and not debug and (processor == "x86_64"): [FAIL, PASS]
if (os == "linux") and (processor == "x86"): [FAIL, PASS]
if (os == "mac") and not debug: [FAIL, PASS]
[PASS, FAIL]
[role: term]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1829028
expected:
if (os == "linux") and not debug and (processor == "x86"): [FAIL, PASS]
if (os == "win") and not debug: [FAIL, PASS]
if (os == "mac") and not debug: [FAIL, PASS]
[PASS, FAIL]
[role: toolbar]
expected:
if (os == "linux") and fission and not debug and (processor == "x86_64"): [FAIL, PASS]
if (os == "linux") and fission and debug and not swgl: [FAIL, PASS]
if (os == "linux") and not fission and not swgl: [FAIL, PASS]
[PASS, FAIL]
[role: tooltip]
expected:
if (os == "linux") and not swgl and fission and not debug and (processor == "x86_64"): [FAIL, PASS]
if (os == "linux") and not swgl and fission and debug: [FAIL, PASS]
if (os == "linux") and not swgl and not fission: [FAIL, PASS]
if (os == "win") and not debug and (processor == "x86"): [FAIL, PASS]
if (os == "mac") and debug: [FAIL, PASS]
[PASS, FAIL]

View File

@ -1,11 +1,9 @@
[synonym-roles.html]
[none role == computedrole none]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1828600
[synonym presentation role == computedrole none]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1828600
[image role == computedrole image]
expected: FAIL

View File

@ -0,0 +1,7 @@
[get.py]
[test_computed_roles[<input role=searchbox>-input-searchbox\]]
bug: 1822112
expected: FAIL
[test_computed_roles[<img role=button tabindex=0>-img-button\]]
expected: FAIL

View File

@ -482,7 +482,6 @@ STATIC_ATOMS = [
Atom("fullscreenerror", "fullscreenerror"),
Atom("functionAvailable", "function-available"),
Atom("generateId", "generate-id"),
Atom("generic", "generic"),
Atom("getter", "getter"),
Atom("graphicsDocument", "graphics-document"),
Atom("graphicsObject", "graphics-object"),