summaryrefslogtreecommitdiffstats
path: root/accessible/tests/browser/e10s
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--accessible/tests/browser/e10s/browser.ini60
-rw-r--r--accessible/tests/browser/e10s/browser_caching_attributes.js134
-rw-r--r--accessible/tests/browser/e10s/browser_caching_description.js214
-rw-r--r--accessible/tests/browser/e10s/browser_caching_name.js539
-rw-r--r--accessible/tests/browser/e10s/browser_caching_relations.js96
-rw-r--r--accessible/tests/browser/e10s/browser_caching_states.js154
-rw-r--r--accessible/tests/browser/e10s/browser_caching_uniqueid.js30
-rw-r--r--accessible/tests/browser/e10s/browser_caching_value.js195
-rw-r--r--accessible/tests/browser/e10s/browser_events_announcement.js30
-rw-r--r--accessible/tests/browser/e10s/browser_events_caretmove.js22
-rw-r--r--accessible/tests/browser/e10s/browser_events_hide.js44
-rw-r--r--accessible/tests/browser/e10s/browser_events_show.js22
-rw-r--r--accessible/tests/browser/e10s/browser_events_statechange.js71
-rw-r--r--accessible/tests/browser/e10s/browser_events_textchange.js114
-rw-r--r--accessible/tests/browser/e10s/browser_events_vcchange.js87
-rw-r--r--accessible/tests/browser/e10s/browser_text_paragraph_boundary.js22
-rw-r--r--accessible/tests/browser/e10s/browser_treeupdate_ariadialog.js45
-rw-r--r--accessible/tests/browser/e10s/browser_treeupdate_ariaowns.js294
-rw-r--r--accessible/tests/browser/e10s/browser_treeupdate_canvas.js28
-rw-r--r--accessible/tests/browser/e10s/browser_treeupdate_cssoverflow.js60
-rw-r--r--accessible/tests/browser/e10s/browser_treeupdate_doc.js320
-rw-r--r--accessible/tests/browser/e10s/browser_treeupdate_gencontent.js94
-rw-r--r--accessible/tests/browser/e10s/browser_treeupdate_hidden.js32
-rw-r--r--accessible/tests/browser/e10s/browser_treeupdate_imagemap.js187
-rw-r--r--accessible/tests/browser/e10s/browser_treeupdate_list.js52
-rw-r--r--accessible/tests/browser/e10s/browser_treeupdate_list_editabledoc.js48
-rw-r--r--accessible/tests/browser/e10s/browser_treeupdate_listener.js38
-rw-r--r--accessible/tests/browser/e10s/browser_treeupdate_optgroup.js103
-rw-r--r--accessible/tests/browser/e10s/browser_treeupdate_removal.js58
-rw-r--r--accessible/tests/browser/e10s/browser_treeupdate_select_dropdown.js77
-rw-r--r--accessible/tests/browser/e10s/browser_treeupdate_table.js48
-rw-r--r--accessible/tests/browser/e10s/browser_treeupdate_textleaf.js38
-rw-r--r--accessible/tests/browser/e10s/browser_treeupdate_visibility.js342
-rw-r--r--accessible/tests/browser/e10s/browser_treeupdate_whitespace.js68
-rw-r--r--accessible/tests/browser/e10s/doc_treeupdate_ariadialog.html23
-rw-r--r--accessible/tests/browser/e10s/doc_treeupdate_ariaowns.html44
-rw-r--r--accessible/tests/browser/e10s/doc_treeupdate_imagemap.html21
-rw-r--r--accessible/tests/browser/e10s/doc_treeupdate_removal.xhtml11
-rw-r--r--accessible/tests/browser/e10s/doc_treeupdate_visibility.html78
-rw-r--r--accessible/tests/browser/e10s/doc_treeupdate_whitespace.html10
-rw-r--r--accessible/tests/browser/e10s/head.js19
41 files changed, 3972 insertions, 0 deletions
diff --git a/accessible/tests/browser/e10s/browser.ini b/accessible/tests/browser/e10s/browser.ini
new file mode 100644
index 0000000000..a582b9b8bb
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser.ini
@@ -0,0 +1,60 @@
+[DEFAULT]
+support-files =
+ head.js
+ doc_treeupdate_ariadialog.html
+ doc_treeupdate_ariaowns.html
+ doc_treeupdate_imagemap.html
+ doc_treeupdate_removal.xhtml
+ doc_treeupdate_visibility.html
+ doc_treeupdate_whitespace.html
+ !/accessible/tests/browser/shared-head.js
+ !/accessible/tests/browser/*.jsm
+ !/accessible/tests/mochitest/*.js
+ !/accessible/tests/mochitest/letters.gif
+ !/accessible/tests/mochitest/moz.png
+
+# Caching tests
+[browser_caching_attributes.js]
+[browser_caching_description.js]
+[browser_caching_name.js]
+skip-if = (os == "linux" && bits == 64) || (debug && os == "mac") || (debug && os == "win") #Bug 1388256
+[browser_caching_relations.js]
+[browser_caching_states.js]
+[browser_caching_value.js]
+[browser_caching_uniqueid.js]
+
+# Events tests
+[browser_events_announcement.js]
+skip-if = e10s && os == 'win' # Bug 1288839
+[browser_events_caretmove.js]
+[browser_events_hide.js]
+[browser_events_show.js]
+[browser_events_statechange.js]
+[browser_events_textchange.js]
+[browser_events_vcchange.js]
+
+# Text tests
+[browser_text_paragraph_boundary.js]
+
+# Tree update tests
+[browser_treeupdate_ariadialog.js]
+[browser_treeupdate_ariaowns.js]
+[browser_treeupdate_canvas.js]
+skip-if = (os == 'win' && os_version == '10.0' && bits == 64 && !debug) #Bug 1462638 - Disabled on Win10 opt/pgo for frequent failures
+[browser_treeupdate_cssoverflow.js]
+[browser_treeupdate_doc.js]
+skip-if = e10s && os == 'win' # Bug 1288839
+[browser_treeupdate_gencontent.js]
+[browser_treeupdate_hidden.js]
+[browser_treeupdate_imagemap.js]
+[browser_treeupdate_list.js]
+[browser_treeupdate_list_editabledoc.js]
+[browser_treeupdate_listener.js]
+[browser_treeupdate_optgroup.js]
+[browser_treeupdate_removal.js]
+[browser_treeupdate_select_dropdown.js]
+[browser_treeupdate_table.js]
+[browser_treeupdate_textleaf.js]
+[browser_treeupdate_visibility.js]
+[browser_treeupdate_whitespace.js]
+skip-if = true # Failing due to incorrect index of test container children on document load.
diff --git a/accessible/tests/browser/e10s/browser_caching_attributes.js b/accessible/tests/browser/e10s/browser_caching_attributes.js
new file mode 100644
index 0000000000..b8e157b068
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_caching_attributes.js
@@ -0,0 +1,134 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/attributes.js */
+loadScripts({ name: "attributes.js", dir: MOCHITESTS_DIR });
+
+/**
+ * Default textbox accessible attributes.
+ */
+const defaultAttributes = {
+ "margin-top": "0px",
+ "margin-right": "0px",
+ "margin-bottom": "0px",
+ "margin-left": "0px",
+ "text-align": "start",
+ "text-indent": "0px",
+ id: "textbox",
+ tag: "input",
+ display: "inline-block",
+};
+
+/**
+ * Test data has the format of:
+ * {
+ * desc {String} description for better logging
+ * expected {Object} expected attributes for given accessibles
+ * unexpected {Object} unexpected attributes for given accessibles
+ *
+ * action {?AsyncFunction} an optional action that awaits a change in
+ * attributes
+ * attrs {?Array} an optional list of attributes to update
+ * waitFor {?Number} an optional event to wait for
+ * }
+ */
+const attributesTests = [
+ {
+ desc: "Initiall accessible attributes",
+ expected: defaultAttributes,
+ unexpected: {
+ "line-number": "1",
+ "explicit-name": "true",
+ "container-live": "polite",
+ live: "polite",
+ },
+ },
+ {
+ desc: "@line-number attribute is present when textbox is focused",
+ async action(browser) {
+ await invokeFocus(browser, "textbox");
+ },
+ waitFor: EVENT_FOCUS,
+ expected: Object.assign({}, defaultAttributes, { "line-number": "1" }),
+ unexpected: {
+ "explicit-name": "true",
+ "container-live": "polite",
+ live: "polite",
+ },
+ },
+ {
+ desc: "@aria-live sets container-live and live attributes",
+ attrs: [
+ {
+ attr: "aria-live",
+ value: "polite",
+ },
+ ],
+ expected: Object.assign({}, defaultAttributes, {
+ "line-number": "1",
+ "container-live": "polite",
+ live: "polite",
+ }),
+ unexpected: {
+ "explicit-name": "true",
+ },
+ },
+ {
+ desc: "@title attribute sets explicit-name attribute to true",
+ attrs: [
+ {
+ attr: "title",
+ value: "textbox",
+ },
+ ],
+ expected: Object.assign({}, defaultAttributes, {
+ "line-number": "1",
+ "explicit-name": "true",
+ "container-live": "polite",
+ live: "polite",
+ }),
+ unexpected: {},
+ },
+];
+
+/**
+ * Test caching of accessible object attributes
+ */
+addAccessibleTask(
+ `
+ <input id="textbox" value="hello">`,
+ async function(browser, accDoc) {
+ let textbox = findAccessibleChildByID(accDoc, "textbox");
+ for (let {
+ desc,
+ action,
+ attrs,
+ expected,
+ waitFor,
+ unexpected,
+ } of attributesTests) {
+ info(desc);
+ let onUpdate;
+
+ if (waitFor) {
+ onUpdate = waitForEvent(waitFor, "textbox");
+ }
+
+ if (action) {
+ await action(browser);
+ } else if (attrs) {
+ for (let { attr, value } of attrs) {
+ await invokeSetAttribute(browser, "textbox", attr, value);
+ }
+ }
+
+ await onUpdate;
+ testAttrs(textbox, expected);
+ testAbsentAttrs(textbox, unexpected);
+ }
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_caching_description.js b/accessible/tests/browser/e10s/browser_caching_description.js
new file mode 100644
index 0000000000..5b9e70ce07
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_caching_description.js
@@ -0,0 +1,214 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/name.js */
+loadScripts({ name: "name.js", dir: MOCHITESTS_DIR });
+
+/**
+ * Test data has the format of:
+ * {
+ * desc {String} description for better logging
+ * expected {String} expected description value for a given accessible
+ * attrs {?Array} an optional list of attributes to update
+ * waitFor {?Array} an optional list of accessible events to wait for when
+ * attributes are updated
+ * }
+ */
+const tests = [
+ {
+ desc: "No description when there are no @alt, @title and @aria-describedby",
+ expected: "",
+ },
+ {
+ desc: "Description from @aria-describedby attribute",
+ attrs: [
+ {
+ attr: "aria-describedby",
+ value: "description",
+ },
+ ],
+ waitFor: [[EVENT_DESCRIPTION_CHANGE, "image"]],
+ expected: "aria description",
+ },
+ {
+ desc:
+ "No description from @aria-describedby since it is the same as the " +
+ "@alt attribute which is used as the name",
+ attrs: [
+ {
+ attr: "alt",
+ value: "aria description",
+ },
+ ],
+ waitFor: [[EVENT_REORDER, matchContentDoc]],
+ expected: "",
+ },
+ {
+ desc:
+ "Description from @aria-describedby attribute when @alt and " +
+ "@aria-describedby are not the same",
+ attrs: [
+ {
+ attr: "aria-describedby",
+ value: "description2",
+ },
+ ],
+ waitFor: [[EVENT_DESCRIPTION_CHANGE, "image"]],
+ expected: "another description",
+ },
+ {
+ desc:
+ "Description from @aria-describedby attribute when @title (used for " +
+ "name) and @aria-describedby are not the same",
+ attrs: [
+ {
+ attr: "alt",
+ },
+ {
+ attr: "title",
+ value: "title",
+ },
+ ],
+ waitFor: [[EVENT_REORDER, matchContentDoc]],
+ expected: "another description",
+ },
+ {
+ desc:
+ "No description from @aria-describedby since it is the same as the " +
+ "@title attribute which is used as the name",
+ attrs: [
+ {
+ attr: "title",
+ value: "another description",
+ },
+ ],
+ waitFor: [[EVENT_NAME_CHANGE, "image"]],
+ expected: "",
+ },
+ {
+ desc: "No description with only @title attribute which is used as the name",
+ attrs: [
+ {
+ attr: "aria-describedby",
+ },
+ ],
+ waitFor: [[EVENT_DESCRIPTION_CHANGE, "image"]],
+ expected: "",
+ },
+ {
+ desc:
+ "Description from @title attribute when @alt and @atitle are not the " +
+ "same",
+ attrs: [
+ {
+ attr: "alt",
+ value: "aria description",
+ },
+ ],
+ waitFor: [[EVENT_REORDER, matchContentDoc]],
+ expected: "another description",
+ },
+ {
+ desc:
+ "No description from @title since it is the same as the @alt " +
+ "attribute which is used as the name",
+ attrs: [
+ {
+ attr: "alt",
+ value: "another description",
+ },
+ ],
+ waitFor: [[EVENT_NAME_CHANGE, "image"]],
+ expected: "",
+ },
+ {
+ desc:
+ "No description from @aria-describedby since it is the same as the " +
+ "@alt (used for name) and @title attributes",
+ attrs: [
+ {
+ attr: "aria-describedby",
+ value: "description2",
+ },
+ ],
+ waitFor: [[EVENT_DESCRIPTION_CHANGE, "image"]],
+ expected: "",
+ },
+ {
+ desc:
+ "Description from @aria-describedby attribute when it is different " +
+ "from @alt (used for name) and @title attributes",
+ attrs: [
+ {
+ attr: "aria-describedby",
+ value: "description",
+ },
+ ],
+ waitFor: [[EVENT_DESCRIPTION_CHANGE, "image"]],
+ expected: "aria description",
+ },
+ {
+ desc:
+ "No description from @aria-describedby since it is the same as the " +
+ "@alt attribute (used for name) but different from title",
+ attrs: [
+ {
+ attr: "alt",
+ value: "aria description",
+ },
+ ],
+ waitFor: [[EVENT_NAME_CHANGE, "image"]],
+ expected: "",
+ },
+ {
+ desc:
+ "Description from @aria-describedby attribute when @alt (used for " +
+ "name) and @aria-describedby are not the same but @title and " +
+ "aria-describedby are",
+ attrs: [
+ {
+ attr: "aria-describedby",
+ value: "description2",
+ },
+ ],
+ waitFor: [[EVENT_DESCRIPTION_CHANGE, "image"]],
+ expected: "another description",
+ },
+];
+
+/**
+ * Test caching of accessible object description
+ */
+addAccessibleTask(
+ `
+ <p id="description">aria description</p>
+ <p id="description2">another description</p>
+ <img id="image" />`,
+ async function(browser, accDoc) {
+ let imgAcc = findAccessibleChildByID(accDoc, "image");
+
+ for (let { desc, waitFor, attrs, expected } of tests) {
+ info(desc);
+ let onUpdate;
+ if (waitFor) {
+ onUpdate = waitForOrderedEvents(waitFor);
+ }
+ if (attrs) {
+ for (let { attr, value } of attrs) {
+ await invokeSetAttribute(browser, "image", attr, value);
+ }
+ }
+ await onUpdate;
+ // When attribute change (alt) triggers reorder event, accessible will
+ // become defunct.
+ if (isDefunct(imgAcc)) {
+ imgAcc = findAccessibleChildByID(accDoc, "image");
+ }
+ testDescr(imgAcc, expected);
+ }
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_caching_name.js b/accessible/tests/browser/e10s/browser_caching_name.js
new file mode 100644
index 0000000000..cac05a04de
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_caching_name.js
@@ -0,0 +1,539 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/name.js */
+loadScripts({ name: "name.js", dir: MOCHITESTS_DIR });
+
+/**
+ * Rules for name tests that are inspired by
+ * accessible/tests/mochitest/name/markuprules.xul
+ *
+ * Each element in the list of rules represents a name calculation rule for a
+ * particular test case.
+ *
+ * The rules have the following format:
+ * { attr } - calculated from attribute
+ * { elm } - calculated from another element
+ * { fromsubtree } - calculated from element's subtree
+ *
+ *
+ * Options include:
+ * * waitFor - changes in the subtree will result in an accessible event
+ * being fired, the test must only continue after the event
+ * is receieved.
+ */
+const ARIARule = [
+ { attr: "aria-labelledby" },
+ { attr: "aria-label", waitFor: EVENT_NAME_CHANGE },
+];
+const HTMLControlHeadRule = [...ARIARule, { elm: "label", isSibling: true }];
+const rules = {
+ CSSContent: [{ elm: "style", isSibling: true }, { fromsubtree: true }],
+ HTMLARIAGridCell: [...ARIARule, { fromsubtree: true }, { attr: "title" }],
+ HTMLControl: [
+ ...HTMLControlHeadRule,
+ { fromsubtree: true },
+ { attr: "title" },
+ ],
+ HTMLElm: [...ARIARule, { attr: "title" }],
+ HTMLImg: [
+ ...ARIARule,
+ { attr: "alt", waitFor: EVENT_NAME_CHANGE },
+ { attr: "title" },
+ ],
+ HTMLImgEmptyAlt: [...ARIARule, { attr: "title" }, { attr: "alt" }],
+ HTMLInputButton: [
+ ...HTMLControlHeadRule,
+ { attr: "value" },
+ { attr: "title" },
+ ],
+ HTMLInputImage: [
+ ...HTMLControlHeadRule,
+ { attr: "alt", waitFor: EVENT_NAME_CHANGE },
+ { attr: "value" },
+ { attr: "title" },
+ ],
+ HTMLInputImageNoValidSrc: [
+ ...HTMLControlHeadRule,
+ { attr: "alt", waitFor: EVENT_NAME_CHANGE },
+ { attr: "value" },
+ ],
+ HTMLInputReset: [
+ ...HTMLControlHeadRule,
+ { attr: "value", waitFor: EVENT_TEXT_INSERTED },
+ ],
+ HTMLInputSubmit: [
+ ...HTMLControlHeadRule,
+ { attr: "value", waitFor: EVENT_TEXT_INSERTED },
+ ],
+ HTMLLink: [...ARIARule, { fromsubtree: true }, { attr: "title" }],
+ HTMLLinkImage: [...ARIARule, { elm: "img" }, { attr: "title" }],
+ HTMLOption: [
+ ...ARIARule,
+ { attr: "label" },
+ { fromsubtree: true },
+ { attr: "title" },
+ ],
+ HTMLTable: [
+ ...ARIARule,
+ { elm: "caption" },
+ { attr: "summary" },
+ { attr: "title" },
+ ],
+};
+
+const markupTests = [
+ {
+ id: "btn",
+ ruleset: "HTMLControl",
+ markup: `
+ <span id="l1">test2</span>
+ <span id="l2">test3</span>
+ <label for="btn">test4</label>
+ <button id="btn"
+ aria-label="test1"
+ aria-labelledby="l1 l2"
+ title="test5">press me</button>`,
+ expected: ["test2 test3", "test1", "test4", "press me", "test5"],
+ },
+ {
+ id: "btn",
+ ruleset: "HTMLInputButton",
+ markup: `
+ <span id="l1">test2</span>
+ <span id="l2">test3</span>
+ <label for="btn">test4</label>
+ <input id="btn"
+ type="button"
+ aria-label="test1"
+ aria-labelledby="l1 l2"
+ value="name from value"
+ alt="no name from al"
+ src="no name from src"
+ data="no name from data"
+ title="name from title"/>`,
+ expected: [
+ "test2 test3",
+ "test1",
+ "test4",
+ "name from value",
+ "name from title",
+ ],
+ },
+ {
+ id: "btn-submit",
+ ruleset: "HTMLInputSubmit",
+ markup: `
+ <span id="l1">test2</span>
+ <span id="l2">test3</span>
+ <label for="btn-submit">test4</label>
+ <input id="btn-submit"
+ type="submit"
+ aria-label="test1"
+ aria-labelledby="l1 l2"
+ value="name from value"
+ alt="no name from atl"
+ src="no name from src"
+ data="no name from data"
+ title="no name from title"/>`,
+ expected: ["test2 test3", "test1", "test4", "name from value"],
+ },
+ {
+ id: "btn-reset",
+ ruleset: "HTMLInputReset",
+ markup: `
+ <span id="l1">test2</span>
+ <span id="l2">test3</span>
+ <label for="btn-reset">test4</label>
+ <input id="btn-reset"
+ type="reset"
+ aria-label="test1"
+ aria-labelledby="l1 l2"
+ value="name from value"
+ alt="no name from alt"
+ src="no name from src"
+ data="no name from data"
+ title="no name from title"/>`,
+ expected: ["test2 test3", "test1", "test4", "name from value"],
+ },
+ {
+ id: "btn-image",
+ ruleset: "HTMLInputImage",
+ markup: `
+ <span id="l1">test2</span>
+ <span id="l2">test3</span>
+ <label for="btn-image">test4</label>
+ <input id="btn-image"
+ type="image"
+ aria-label="test1"
+ aria-labelledby="l1 l2"
+ alt="name from alt"
+ value="name from value"
+ src="http://example.com/a11y/accessible/tests/mochitest/moz.png"
+ data="no name from data"
+ title="name from title"/>`,
+ expected: [
+ "test2 test3",
+ "test1",
+ "test4",
+ "name from alt",
+ "name from value",
+ "name from title",
+ ],
+ },
+ {
+ id: "btn-image",
+ ruleset: "HTMLInputImageNoValidSrc",
+ markup: `
+ <span id="l1">test2</span>
+ <span id="l2">test3</span>
+ <label for="btn-image">test4</label>
+ <input id="btn-image"
+ type="image"
+ aria-label="test1"
+ aria-labelledby="l1 l2"
+ alt="name from alt"
+ value="name from value"
+ data="no name from data"
+ title="no name from title"/>`,
+ expected: [
+ "test2 test3",
+ "test1",
+ "test4",
+ "name from alt",
+ "name from value",
+ ],
+ },
+ {
+ id: "opt",
+ ruleset: "HTMLOption",
+ markup: `
+ <span id="l1">test2</span>
+ <span id="l2">test3</span>
+ <select>
+ <option id="opt"
+ aria-label="test1"
+ aria-labelledby="l1 l2"
+ label="test4"
+ title="test5">option1</option>
+ <option>option2</option>
+ </select>`,
+ expected: ["test2 test3", "test1", "test4", "option1", "test5"],
+ },
+ {
+ id: "img",
+ ruleset: "HTMLImg",
+ markup: `
+ <span id="l1">test2</span>
+ <span id="l2">test3</span>
+ <img id="img"
+ aria-label="Logo of Mozilla"
+ aria-labelledby="l1 l2"
+ alt="Mozilla logo"
+ title="This is a logo"
+ src="http://example.com/a11y/accessible/tests/mochitest/moz.png"/>`,
+ expected: [
+ "test2 test3",
+ "Logo of Mozilla",
+ "Mozilla logo",
+ "This is a logo",
+ ],
+ },
+ {
+ id: "imgemptyalt",
+ ruleset: "HTMLImgEmptyAlt",
+ markup: `
+ <span id="l1">test2</span>
+ <span id="l2">test3</span>
+ <img id="imgemptyalt"
+ aria-label="Logo of Mozilla"
+ aria-labelledby="l1 l2"
+ title="This is a logo"
+ alt=""
+ src="http://example.com/a11y/accessible/tests/mochitest/moz.png"/>`,
+ expected: ["test2 test3", "Logo of Mozilla", "This is a logo", ""],
+ },
+ {
+ id: "tc",
+ ruleset: "HTMLElm",
+ markup: `
+ <span id="l1">test2</span>
+ <span id="l2">test3</span>
+ <label for="tc">test4</label>
+ <table>
+ <tr>
+ <td id="tc"
+ aria-label="test1"
+ aria-labelledby="l1 l2"
+ title="test5">
+ <p>This is a paragraph</p>
+ <a href="#">This is a link</a>
+ <ul>
+ <li>This is a list</li>
+ </ul>
+ </td>
+ </tr>
+ </table>`,
+ expected: ["test2 test3", "test1", "test5"],
+ },
+ {
+ id: "gc",
+ ruleset: "HTMLARIAGridCell",
+ markup: `
+ <span id="l1">test2</span>
+ <span id="l2">test3</span>
+ <label for="gc">test4</label>
+ <table>
+ <tr>
+ <td id="gc"
+ role="gridcell"
+ aria-label="test1"
+ aria-labelledby="l1 l2"
+ title="This is a paragraph This is a link This is a list">
+ <p>This is a paragraph</p>
+ <a href="#">This is a link</a>
+ <ul>
+ <li>Listitem1</li>
+ <li>Listitem2</li>
+ </ul>
+ </td>
+ </tr>
+ </table>`,
+ expected: [
+ "test2 test3",
+ "test1",
+ "This is a paragraph This is a link \u2022 Listitem1 \u2022 Listitem2",
+ "This is a paragraph This is a link This is a list",
+ ],
+ },
+ {
+ id: "t",
+ ruleset: "HTMLTable",
+ markup: `
+ <span id="l1">lby_tst6_1</span>
+ <span id="l2">lby_tst6_2</span>
+ <label for="t">label_tst6</label>
+ <table id="t"
+ aria-label="arialabel_tst6"
+ aria-labelledby="l1 l2"
+ summary="summary_tst6"
+ title="title_tst6">
+ <caption>caption_tst6</caption>
+ <tr>
+ <td>cell1</td>
+ <td>cell2</td>
+ </tr>
+ </table>`,
+ expected: [
+ "lby_tst6_1 lby_tst6_2",
+ "arialabel_tst6",
+ "caption_tst6",
+ "summary_tst6",
+ "title_tst6",
+ ],
+ },
+ {
+ id: "btn",
+ ruleset: "CSSContent",
+ markup: `
+ <div role="main">
+ <style>
+ button::before {
+ content: "do not ";
+ }
+ </style>
+ <button id="btn">press me</button>
+ </div>`,
+ expected: ["do not press me", "press me"],
+ },
+ {
+ // TODO: uncomment when Bug-1256382 is resoved.
+ // id: 'li',
+ // ruleset: 'CSSContent',
+ // markup: `
+ // <style>
+ // ul {
+ // list-style-type: decimal;
+ // }
+ // </style>
+ // <ul id="ul">
+ // <li id="li">Listitem</li>
+ // </ul>`,
+ // expected: ['1. Listitem', `${String.fromCharCode(0x2022)} Listitem`]
+ // }, {
+ id: "a",
+ ruleset: "HTMLLink",
+ markup: `
+ <span id="l1">test2</span>
+ <span id="l2">test3</span>
+ <a id="a"
+ aria-label="test1"
+ aria-labelledby="l1 l2"
+ title="test4">test5</a>`,
+ expected: ["test2 test3", "test1", "test5", "test4"],
+ },
+ {
+ id: "a-img",
+ ruleset: "HTMLLinkImage",
+ markup: `
+ <span id="l1">test2</span>
+ <span id="l2">test3</span>
+ <a id="a-img"
+ aria-label="test1"
+ aria-labelledby="l1 l2"
+ title="test4"><img alt="test5"/></a>`,
+ expected: ["test2 test3", "test1", "test5", "test4"],
+ },
+];
+
+/**
+ * Test accessible name that is calculated from an attribute, remove the
+ * attribute before proceeding to the next name test. If attribute removal
+ * results in a reorder or text inserted event - wait for it. If accessible
+ * becomes defunct, update its reference using the one that is attached to one
+ * of the above events.
+ * @param {Object} browser current "tabbrowser" element
+ * @param {Object} target { acc, parent, id } structure that contains an
+ * accessible, its parent and its content element
+ * id.
+ * @param {Object} rule current attr rule for name calculation
+ * @param {[type]} expected expected name value
+ */
+async function testAttrRule(browser, target, rule, expected) {
+ let { id, parent, acc } = target;
+ let { waitFor, attr } = rule;
+
+ testName(acc, expected);
+
+ if (waitFor) {
+ let [event] = await contentSpawnMutation(
+ browser,
+ {
+ expected: [[waitFor, waitFor === EVENT_REORDER ? parent : id]],
+ },
+ (contentId, contentAttr) =>
+ content.document.getElementById(contentId).removeAttribute(contentAttr),
+ [id, attr]
+ );
+
+ // Update accessible just in case it is now defunct.
+ target.acc = findAccessibleChildByID(event.accessible, id);
+ } else {
+ await invokeSetAttribute(browser, id, attr);
+ }
+}
+
+/**
+ * Test accessible name that is calculated from an element name, remove the
+ * element before proceeding to the next name test. If element removal results
+ * in a reorder event - wait for it. If accessible becomes defunct, update its
+ * reference using the one that is attached to a possible reorder event.
+ * @param {Object} browser current "tabbrowser" element
+ * @param {Object} target { acc, parent, id } structure that contains an
+ * accessible, its parent and its content element
+ * id.
+ * @param {Object} rule current elm rule for name calculation
+ * @param {[type]} expected expected name value
+ */
+async function testElmRule(browser, target, rule, expected) {
+ let { id, parent, acc } = target;
+ let { isSibling, elm } = rule;
+
+ testName(acc, expected);
+ let [event] = await contentSpawnMutation(
+ browser,
+ {
+ expected: [[EVENT_REORDER, isSibling ? parent : id]],
+ },
+ contentElm => content.document.querySelector(`${contentElm}`).remove(),
+ [elm]
+ );
+
+ // Update accessible just in case it is now defunct.
+ target.acc = findAccessibleChildByID(event.accessible, id);
+}
+
+/**
+ * Test accessible name that is calculated from its subtree, remove the subtree
+ * and wait for a reorder event before proceeding to the next name test. If
+ * accessible becomes defunct, update its reference using the one that is
+ * attached to a reorder event.
+ * @param {Object} browser current "tabbrowser" element
+ * @param {Object} target { acc, parent, id } structure that contains an
+ * accessible, its parent and its content element
+ * id.
+ * @param {Object} rule current subtree rule for name calculation
+ * @param {[type]} expected expected name value
+ */
+async function testSubtreeRule(browser, target, rule, expected) {
+ let { id, acc } = target;
+
+ testName(acc, expected);
+ let [event] = await contentSpawnMutation(
+ browser,
+ {
+ expected: [[EVENT_REORDER, id]],
+ },
+ contentId => {
+ let elm = content.document.getElementById(contentId);
+ while (elm.firstChild) {
+ elm.firstChild.remove();
+ }
+ },
+ [id]
+ );
+
+ // Update accessible just in case it is now defunct.
+ target.acc = findAccessibleChildByID(event.accessible, id);
+}
+
+/**
+ * Iterate over a list of rules and test accessible names for each one of the
+ * rules.
+ * @param {Object} browser current "tabbrowser" element
+ * @param {Object} target { acc, parent, id } structure that contains an
+ * accessible, its parent and its content element
+ * id.
+ * @param {Array} ruleset A list of rules to test a target with
+ * @param {Array} expected A list of expected name value for each rule
+ */
+async function testNameRule(browser, target, ruleset, expected) {
+ for (let i = 0; i < ruleset.length; ++i) {
+ let rule = ruleset[i];
+ let testFn;
+ if (rule.attr) {
+ testFn = testAttrRule;
+ } else if (rule.elm) {
+ testFn = testElmRule;
+ } else if (rule.fromsubtree) {
+ testFn = testSubtreeRule;
+ }
+ await testFn(browser, target, rule, expected[i]);
+ }
+}
+
+markupTests.forEach(({ id, ruleset, markup, expected }) =>
+ addAccessibleTask(
+ markup,
+ async function(browser, accDoc) {
+ const observer = {
+ observe(subject, topic, data) {
+ const event = subject.QueryInterface(nsIAccessibleEvent);
+ console.log(eventToString(event));
+ },
+ };
+ Services.obs.addObserver(observer, "accessible-event");
+ // Find a target accessible from an accessible subtree.
+ let acc = findAccessibleChildByID(accDoc, id);
+ // Find target's parent accessible from an accessible subtree.
+ let parent = getAccessibleDOMNodeID(acc.parent);
+ let target = { id, parent, acc };
+ await testNameRule(browser, target, rules[ruleset], expected);
+ Services.obs.removeObserver(observer, "accessible-event");
+ },
+ { iframe: true, remoteIframe: true }
+ )
+);
diff --git a/accessible/tests/browser/e10s/browser_caching_relations.js b/accessible/tests/browser/e10s/browser_caching_relations.js
new file mode 100644
index 0000000000..38d3a0c63b
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_caching_relations.js
@@ -0,0 +1,96 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/relations.js */
+loadScripts({ name: "relations.js", dir: MOCHITESTS_DIR });
+
+/**
+ * A test specification that has the following format:
+ * [
+ * attr relevant aria attribute
+ * hostRelation corresponding host relation type
+ * dependantRelation corresponding dependant relation type
+ * ]
+ */
+const attrRelationsSpec = [
+ ["aria-labelledby", RELATION_LABELLED_BY, RELATION_LABEL_FOR],
+ ["aria-describedby", RELATION_DESCRIBED_BY, RELATION_DESCRIPTION_FOR],
+ ["aria-controls", RELATION_CONTROLLER_FOR, RELATION_CONTROLLED_BY],
+ ["aria-flowto", RELATION_FLOWS_TO, RELATION_FLOWS_FROM],
+];
+
+async function testRelated(
+ browser,
+ accDoc,
+ attr,
+ hostRelation,
+ dependantRelation
+) {
+ let host = findAccessibleChildByID(accDoc, "host");
+ let dependant1 = findAccessibleChildByID(accDoc, "dependant1");
+ let dependant2 = findAccessibleChildByID(accDoc, "dependant2");
+
+ /**
+ * Test data has the format of:
+ * {
+ * desc {String} description for better logging
+ * attrs {?Array} an optional list of attributes to update
+ * expected {Array} expected relation values for dependant1, dependant2
+ * and host respectively.
+ * }
+ */
+ const tests = [
+ {
+ desc: "No attribute",
+ expected: [null, null, null],
+ },
+ {
+ desc: "Set attribute",
+ attrs: [{ key: attr, value: "dependant1" }],
+ expected: [host, null, dependant1],
+ },
+ {
+ desc: "Change attribute",
+ attrs: [{ key: attr, value: "dependant2" }],
+ expected: [null, host, dependant2],
+ },
+ {
+ desc: "Remove attribute",
+ attrs: [{ key: attr }],
+ expected: [null, null, null],
+ },
+ ];
+
+ for (let { desc, attrs, expected } of tests) {
+ info(desc);
+
+ if (attrs) {
+ for (let { key, value } of attrs) {
+ await invokeSetAttribute(browser, "host", key, value);
+ }
+ }
+
+ testRelation(dependant1, dependantRelation, expected[0]);
+ testRelation(dependant2, dependantRelation, expected[1]);
+ testRelation(host, hostRelation, expected[2]);
+ }
+}
+
+/**
+ * Test caching of relations between accessible objects.
+ */
+addAccessibleTask(
+ `
+ <div id="dependant1">label</div>
+ <div id="dependant2">label2</div>
+ <div role="checkbox" id="host"></div>`,
+ async function(browser, accDoc) {
+ for (let spec of attrRelationsSpec) {
+ await testRelated(browser, accDoc, ...spec);
+ }
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_caching_states.js b/accessible/tests/browser/e10s/browser_caching_states.js
new file mode 100644
index 0000000000..e6dbc33d65
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_caching_states.js
@@ -0,0 +1,154 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/role.js */
+/* import-globals-from ../../mochitest/states.js */
+loadScripts(
+ { name: "role.js", dir: MOCHITESTS_DIR },
+ { name: "states.js", dir: MOCHITESTS_DIR }
+);
+
+/**
+ * Test data has the format of:
+ * {
+ * desc {String} description for better logging
+ * expected {Array} expected states for a given accessible that have the
+ * following format:
+ * [
+ * expected state,
+ * expected extra state,
+ * absent state,
+ * absent extra state
+ * ]
+ * attrs {?Array} an optional list of attributes to update
+ * }
+ */
+
+// State caching tests for attribute changes
+const attributeTests = [
+ {
+ desc:
+ "Checkbox with @checked attribute set to true should have checked " +
+ "state",
+ attrs: [
+ {
+ attr: "checked",
+ value: "true",
+ },
+ ],
+ expected: [STATE_CHECKED, 0],
+ },
+ {
+ desc: "Checkbox with no @checked attribute should not have checked state",
+ attrs: [
+ {
+ attr: "checked",
+ },
+ ],
+ expected: [0, 0, STATE_CHECKED],
+ },
+];
+
+// State caching tests for ARIA changes
+const ariaTests = [
+ {
+ desc: "File input has busy state when @aria-busy attribute is set to true",
+ attrs: [
+ {
+ attr: "aria-busy",
+ value: "true",
+ },
+ ],
+ expected: [STATE_BUSY, 0, STATE_REQUIRED | STATE_INVALID],
+ },
+ {
+ desc:
+ "File input has required state when @aria-required attribute is set " +
+ "to true",
+ attrs: [
+ {
+ attr: "aria-required",
+ value: "true",
+ },
+ ],
+ expected: [STATE_REQUIRED, 0, STATE_INVALID],
+ },
+ {
+ desc:
+ "File input has invalid state when @aria-invalid attribute is set to " +
+ "true",
+ attrs: [
+ {
+ attr: "aria-invalid",
+ value: "true",
+ },
+ ],
+ expected: [STATE_INVALID, 0],
+ },
+];
+
+// Extra state caching tests
+const extraStateTests = [
+ {
+ desc:
+ "Input has no extra enabled state when aria and native disabled " +
+ "attributes are set at once",
+ attrs: [
+ {
+ attr: "aria-disabled",
+ value: "true",
+ },
+ {
+ attr: "disabled",
+ value: "true",
+ },
+ ],
+ expected: [0, 0, 0, EXT_STATE_ENABLED],
+ },
+ {
+ desc:
+ "Input has an extra enabled state when aria and native disabled " +
+ "attributes are unset at once",
+ attrs: [
+ {
+ attr: "aria-disabled",
+ },
+ {
+ attr: "disabled",
+ },
+ ],
+ expected: [0, EXT_STATE_ENABLED],
+ },
+];
+
+async function runStateTests(browser, accDoc, id, tests) {
+ let acc = findAccessibleChildByID(accDoc, id);
+ for (let { desc, attrs, expected } of tests) {
+ info(desc);
+ let onUpdate = waitForEvent(EVENT_STATE_CHANGE, id);
+ for (let { attr, value } of attrs) {
+ await invokeSetAttribute(browser, id, attr, value);
+ }
+ await onUpdate;
+ testStates(acc, ...expected);
+ }
+}
+
+/**
+ * Test caching of accessible object states
+ */
+addAccessibleTask(
+ `
+ <input id="checkbox" type="checkbox">
+ <input id="file" type="file">
+ <input id="text">`,
+ async function(browser, accDoc) {
+ await runStateTests(browser, accDoc, "checkbox", attributeTests);
+ await runStateTests(browser, accDoc, "file", ariaTests);
+ await runStateTests(browser, accDoc, "text", extraStateTests);
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_caching_uniqueid.js b/accessible/tests/browser/e10s/browser_caching_uniqueid.js
new file mode 100644
index 0000000000..287f896c36
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_caching_uniqueid.js
@@ -0,0 +1,30 @@
+/* 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";
+
+/**
+ * Test UniqueID property.
+ */
+addAccessibleTask(
+ '<div id="div"></div>',
+ async function(browser, accDoc) {
+ const div = findAccessibleChildByID(accDoc, "div");
+ const accUniqueID = await invokeContentTask(browser, [], () => {
+ const accService = Cc["@mozilla.org/accessibilityService;1"].getService(
+ Ci.nsIAccessibilityService
+ );
+
+ return accService.getAccessibleFor(content.document.getElementById("div"))
+ .uniqueID;
+ });
+
+ is(
+ accUniqueID,
+ div.uniqueID,
+ "Both proxy and the accessible return correct unique ID."
+ );
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_caching_value.js b/accessible/tests/browser/e10s/browser_caching_value.js
new file mode 100644
index 0000000000..c727fc5252
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_caching_value.js
@@ -0,0 +1,195 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/value.js */
+loadScripts({ name: "value.js", dir: MOCHITESTS_DIR });
+
+/**
+ * Test data has the format of:
+ * {
+ * desc {String} description for better logging
+ * id {String} given accessible DOMNode ID
+ * expected {String} expected value for a given accessible
+ * action {?AsyncFunction} an optional action that awaits a value change
+ * attrs {?Array} an optional list of attributes to update
+ * waitFor {?Number} an optional value change event to wait for
+ * }
+ */
+const valueTests = [
+ {
+ desc: "Initially value is set to 1st element of select",
+ id: "select",
+ expected: "1st",
+ },
+ {
+ desc: "Value should update to 3rd when 3 is pressed",
+ id: "select",
+ async action(browser) {
+ await invokeFocus(browser, "select");
+ await invokeContentTask(browser, [], () => {
+ const { ContentTaskUtils } = ChromeUtils.import(
+ "resource://testing-common/ContentTaskUtils.jsm"
+ );
+ const EventUtils = ContentTaskUtils.getEventUtils(content);
+ EventUtils.synthesizeKey("3", {}, content);
+ });
+ },
+ waitFor: EVENT_TEXT_VALUE_CHANGE,
+ expected: "3rd",
+ },
+ {
+ desc: "Initially value is set to @aria-valuenow for slider",
+ id: "slider",
+ expected: ["5", 5, 0, 7, 0],
+ },
+ {
+ desc: "Value should change when @aria-valuenow is updated",
+ id: "slider",
+ attrs: [
+ {
+ attr: "aria-valuenow",
+ value: "6",
+ },
+ ],
+ waitFor: EVENT_VALUE_CHANGE,
+ expected: ["6", 6, 0, 7, 0],
+ },
+ {
+ desc: "Value should change when @aria-valuetext is set",
+ id: "slider",
+ attrs: [
+ {
+ attr: "aria-valuetext",
+ value: "plain",
+ },
+ ],
+ waitFor: EVENT_TEXT_VALUE_CHANGE,
+ expected: ["plain", 6, 0, 7, 0],
+ },
+ {
+ desc: "Value should change when @aria-valuetext is updated",
+ id: "slider",
+ attrs: [
+ {
+ attr: "aria-valuetext",
+ value: "hey!",
+ },
+ ],
+ waitFor: EVENT_TEXT_VALUE_CHANGE,
+ expected: ["hey!", 6, 0, 7, 0],
+ },
+ {
+ desc:
+ "Value should change to @aria-valuetext when @aria-valuenow is removed",
+ id: "slider",
+ attrs: [
+ {
+ attr: "aria-valuenow",
+ },
+ ],
+ expected: ["hey!", 3.5, 0, 7, 0],
+ },
+ {
+ desc: "Initially value is not set for combobox",
+ id: "combobox",
+ expected: "",
+ },
+ {
+ desc: "Value should change when @value attribute is updated",
+ id: "combobox",
+ attrs: [
+ {
+ attr: "value",
+ value: "hello",
+ },
+ ],
+ waitFor: EVENT_TEXT_VALUE_CHANGE,
+ expected: "hello",
+ },
+ {
+ desc: "Initially value corresponds to @value attribute for progress",
+ id: "progress",
+ expected: "22%",
+ },
+ {
+ desc: "Value should change when @value attribute is updated",
+ id: "progress",
+ attrs: [
+ {
+ attr: "value",
+ value: "50",
+ },
+ ],
+ waitFor: EVENT_VALUE_CHANGE,
+ expected: "50%",
+ },
+ {
+ desc: "Initially value corresponds to @value attribute for range",
+ id: "range",
+ expected: "6",
+ },
+ {
+ desc: "Value should change when slider is moved",
+ id: "range",
+ async action(browser) {
+ await invokeFocus(browser, "range");
+ await invokeContentTask(browser, [], () => {
+ const { ContentTaskUtils } = ChromeUtils.import(
+ "resource://testing-common/ContentTaskUtils.jsm"
+ );
+ const EventUtils = ContentTaskUtils.getEventUtils(content);
+ EventUtils.synthesizeKey("VK_LEFT", {}, content);
+ });
+ },
+ waitFor: EVENT_VALUE_CHANGE,
+ expected: "5",
+ },
+];
+
+/**
+ * Test caching of accessible object values
+ */
+addAccessibleTask(
+ `
+ <div id="slider" role="slider" aria-valuenow="5"
+ aria-valuemin="0" aria-valuemax="7">slider</div>
+ <select id="select">
+ <option>1st</option>
+ <option>2nd</option>
+ <option>3rd</option>
+ </select>
+ <input id="combobox" role="combobox" aria-autocomplete="inline">
+ <progress id="progress" value="22" max="100"></progress>
+ <input type="range" id="range" min="0" max="10" value="6">`,
+ async function(browser, accDoc) {
+ for (let { desc, id, action, attrs, expected, waitFor } of valueTests) {
+ info(desc);
+ let acc = findAccessibleChildByID(accDoc, id);
+ let onUpdate;
+
+ if (waitFor) {
+ onUpdate = waitForEvent(waitFor, id);
+ }
+
+ if (action) {
+ await action(browser);
+ } else if (attrs) {
+ for (let { attr, value } of attrs) {
+ await invokeSetAttribute(browser, id, attr, value);
+ }
+ }
+
+ await onUpdate;
+ if (Array.isArray(expected)) {
+ acc.QueryInterface(nsIAccessibleValue);
+ testValue(acc, ...expected);
+ } else {
+ is(acc.value, expected, `Correct value for ${prettyName(acc)}`);
+ }
+ }
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_events_announcement.js b/accessible/tests/browser/e10s/browser_events_announcement.js
new file mode 100644
index 0000000000..2de6d4b005
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_events_announcement.js
@@ -0,0 +1,30 @@
+/* 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(
+ `<p id="p">abc</p>`,
+ async function(browser, accDoc) {
+ let acc = findAccessibleChildByID(accDoc, "p");
+ let onAnnounce = waitForEvent(EVENT_ANNOUNCEMENT, acc);
+ acc.announce("please", nsIAccessibleAnnouncementEvent.POLITE);
+ let evt = await onAnnounce;
+ evt.QueryInterface(nsIAccessibleAnnouncementEvent);
+ is(evt.announcement, "please", "announcement matches.");
+ is(evt.priority, nsIAccessibleAnnouncementEvent.POLITE, "priority matches");
+
+ onAnnounce = waitForEvent(EVENT_ANNOUNCEMENT, acc);
+ acc.announce("do it", nsIAccessibleAnnouncementEvent.ASSERTIVE);
+ evt = await onAnnounce;
+ evt.QueryInterface(nsIAccessibleAnnouncementEvent);
+ is(evt.announcement, "do it", "announcement matches.");
+ is(
+ evt.priority,
+ nsIAccessibleAnnouncementEvent.ASSERTIVE,
+ "priority matches"
+ );
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_events_caretmove.js b/accessible/tests/browser/e10s/browser_events_caretmove.js
new file mode 100644
index 0000000000..a39d16e710
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_events_caretmove.js
@@ -0,0 +1,22 @@
+/* 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";
+
+/**
+ * Test caret move event and its interface:
+ * - caretOffset
+ */
+addAccessibleTask(
+ '<input id="textbox" value="hello"/>',
+ async function(browser) {
+ let onCaretMoved = waitForEvent(EVENT_TEXT_CARET_MOVED, "textbox");
+ await invokeFocus(browser, "textbox");
+ let event = await onCaretMoved;
+
+ let caretMovedEvent = event.QueryInterface(nsIAccessibleCaretMoveEvent);
+ is(caretMovedEvent.caretOffset, 5, "Correct caret offset.");
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_events_hide.js b/accessible/tests/browser/e10s/browser_events_hide.js
new file mode 100644
index 0000000000..d46921d051
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_events_hide.js
@@ -0,0 +1,44 @@
+/* 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";
+
+/**
+ * Test hide event and its interface:
+ * - targetParent
+ * - targetNextSibling
+ * - targetPrevSibling
+ */
+addAccessibleTask(
+ `
+ <div id="parent">
+ <div id="previous"></div>
+ <div id="to-hide"></div>
+ <div id="next"></div>
+ </div>`,
+ async function(browser, accDoc) {
+ let acc = findAccessibleChildByID(accDoc, "to-hide");
+ let onHide = waitForEvent(EVENT_HIDE, acc);
+ await invokeSetStyle(browser, "to-hide", "visibility", "hidden");
+ let event = await onHide;
+ let hideEvent = event.QueryInterface(Ci.nsIAccessibleHideEvent);
+
+ is(
+ getAccessibleDOMNodeID(hideEvent.targetParent),
+ "parent",
+ "Correct target parent."
+ );
+ is(
+ getAccessibleDOMNodeID(hideEvent.targetNextSibling),
+ "next",
+ "Correct target next sibling."
+ );
+ is(
+ getAccessibleDOMNodeID(hideEvent.targetPrevSibling),
+ "previous",
+ "Correct target previous sibling."
+ );
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_events_show.js b/accessible/tests/browser/e10s/browser_events_show.js
new file mode 100644
index 0000000000..d464d8fb9d
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_events_show.js
@@ -0,0 +1,22 @@
+/* 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";
+
+/**
+ * Test show event
+ */
+addAccessibleTask(
+ '<div id="div" style="visibility: hidden;"></div>',
+ async function(browser) {
+ let onShow = waitForEvent(EVENT_SHOW, "div");
+ await invokeSetStyle(browser, "div", "visibility", "visible");
+ let showEvent = await onShow;
+ ok(
+ showEvent.accessibleDocument instanceof nsIAccessibleDocument,
+ "Accessible document not present."
+ );
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_events_statechange.js b/accessible/tests/browser/e10s/browser_events_statechange.js
new file mode 100644
index 0000000000..a027a974e4
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_events_statechange.js
@@ -0,0 +1,71 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/role.js */
+/* import-globals-from ../../mochitest/states.js */
+loadScripts(
+ { name: "role.js", dir: MOCHITESTS_DIR },
+ { name: "states.js", dir: MOCHITESTS_DIR }
+);
+
+function checkStateChangeEvent(event, state, isExtraState, isEnabled) {
+ let scEvent = event.QueryInterface(nsIAccessibleStateChangeEvent);
+ is(scEvent.state, state, "Correct state of the statechange event.");
+ is(
+ scEvent.isExtraState,
+ isExtraState,
+ "Correct extra state bit of the statechange event."
+ );
+ is(scEvent.isEnabled, isEnabled, "Correct state of statechange event state");
+}
+
+// Insert mock source into the iframe to be able to verify the right document
+// body id.
+let iframeSrc = `data:text/html,
+ <html>
+ <head>
+ <meta charset='utf-8'/>
+ <title>Inner Iframe</title>
+ </head>
+ <body id='iframe'></body>
+ </html>`;
+
+/**
+ * Test state change event and its interface:
+ * - state
+ * - isExtraState
+ * - isEnabled
+ */
+addAccessibleTask(
+ `
+ <iframe id="iframe" src="${iframeSrc}"></iframe>
+ <input id="checkbox" type="checkbox" />`,
+ async function(browser) {
+ // Test state change
+ let onStateChange = waitForEvent(EVENT_STATE_CHANGE, "checkbox");
+ // Set checked for a checkbox.
+ await invokeContentTask(browser, [], () => {
+ content.document.getElementById("checkbox").checked = true;
+ });
+ let event = await onStateChange;
+
+ checkStateChangeEvent(event, STATE_CHECKED, false, true);
+ testStates(event.accessible, STATE_CHECKED, 0);
+
+ // Test extra state
+ onStateChange = waitForEvent(EVENT_STATE_CHANGE, "iframe");
+ // Set design mode on.
+ await invokeContentTask(browser, [], () => {
+ content.document.getElementById("iframe").contentDocument.designMode =
+ "on";
+ });
+ event = await onStateChange;
+
+ checkStateChangeEvent(event, EXT_STATE_EDITABLE, true, true);
+ testStates(event.accessible, 0, EXT_STATE_EDITABLE);
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_events_textchange.js b/accessible/tests/browser/e10s/browser_events_textchange.js
new file mode 100644
index 0000000000..1e822dc65a
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_events_textchange.js
@@ -0,0 +1,114 @@
+/* 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";
+
+function checkTextChangeEvent(
+ event,
+ id,
+ text,
+ start,
+ end,
+ isInserted,
+ isFromUserInput
+) {
+ let tcEvent = event.QueryInterface(nsIAccessibleTextChangeEvent);
+ is(tcEvent.start, start, `Correct start offset for ${prettyName(id)}`);
+ is(tcEvent.length, end - start, `Correct length for ${prettyName(id)}`);
+ is(
+ tcEvent.isInserted,
+ isInserted,
+ `Correct isInserted flag for ${prettyName(id)}`
+ );
+ is(tcEvent.modifiedText, text, `Correct text for ${prettyName(id)}`);
+ is(
+ tcEvent.isFromUserInput,
+ isFromUserInput,
+ `Correct value of isFromUserInput for ${prettyName(id)}`
+ );
+ ok(
+ tcEvent.accessibleDocument instanceof nsIAccessibleDocument,
+ "Accessible document not present."
+ );
+}
+
+async function changeText(browser, id, value, events) {
+ let onEvents = waitForOrderedEvents(
+ events.map(({ isInserted }) => {
+ let eventType = isInserted ? EVENT_TEXT_INSERTED : EVENT_TEXT_REMOVED;
+ return [eventType, id];
+ })
+ );
+ // Change text in the subtree.
+ await invokeContentTask(browser, [id, value], (contentId, contentValue) => {
+ content.document.getElementById(
+ contentId
+ ).firstChild.textContent = contentValue;
+ });
+ let resolvedEvents = await onEvents;
+
+ events.forEach(({ isInserted, str, offset }, idx) =>
+ checkTextChangeEvent(
+ resolvedEvents[idx],
+ id,
+ str,
+ offset,
+ offset + str.length,
+ isInserted,
+ false
+ )
+ );
+}
+
+async function removeTextFromInput(browser, id, value, start, end) {
+ let onTextRemoved = waitForEvent(EVENT_TEXT_REMOVED, id);
+ // Select text and delete it.
+ await invokeContentTask(
+ browser,
+ [id, start, end],
+ (contentId, contentStart, contentEnd) => {
+ let el = content.document.getElementById(contentId);
+ el.focus();
+ el.setSelectionRange(contentStart, contentEnd);
+ }
+ );
+ await invokeContentTask(browser, [], () => {
+ const { ContentTaskUtils } = ChromeUtils.import(
+ "resource://testing-common/ContentTaskUtils.jsm"
+ );
+ const EventUtils = ContentTaskUtils.getEventUtils(content);
+ EventUtils.sendChar("VK_DELETE", content);
+ });
+
+ let event = await onTextRemoved;
+ checkTextChangeEvent(event, id, value, start, end, false, true);
+}
+
+/**
+ * Test text change event and its interface:
+ * - start
+ * - length
+ * - isInserted
+ * - modifiedText
+ * - isFromUserInput
+ */
+addAccessibleTask(
+ `
+ <p id="p">abc</p>
+ <input id="input" value="input" />`,
+ async function(browser) {
+ let events = [
+ { isInserted: false, str: "abc", offset: 0 },
+ { isInserted: true, str: "def", offset: 0 },
+ ];
+ await changeText(browser, "p", "def", events);
+
+ events = [{ isInserted: true, str: "DEF", offset: 2 }];
+ await changeText(browser, "p", "deDEFf", events);
+
+ // Test isFromUserInput property.
+ await removeTextFromInput(browser, "input", "n", 1, 2);
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_events_vcchange.js b/accessible/tests/browser/e10s/browser_events_vcchange.js
new file mode 100644
index 0000000000..bf649fe045
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_events_vcchange.js
@@ -0,0 +1,87 @@
+/* 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(
+ `
+ <p id="p1">abc</p>
+ <input id="input1" value="input" />`,
+ async function(browser) {
+ let onVCChanged = waitForEvent(
+ EVENT_VIRTUALCURSOR_CHANGED,
+ matchContentDoc
+ );
+ await invokeContentTask(browser, [], () => {
+ const { CommonUtils } = ChromeUtils.import(
+ "chrome://mochitests/content/browser/accessible/tests/browser/Common.jsm"
+ );
+ let vc = CommonUtils.getAccessible(
+ content.document,
+ Ci.nsIAccessibleDocument
+ ).virtualCursor;
+ vc.position = CommonUtils.getAccessible(
+ "p1",
+ null,
+ null,
+ null,
+ content.document
+ );
+ });
+ let vccEvent = (await onVCChanged).QueryInterface(
+ nsIAccessibleVirtualCursorChangeEvent
+ );
+ is(vccEvent.newAccessible.id, "p1", "New position is correct");
+ is(vccEvent.newStartOffset, -1, "New start offset is correct");
+ is(vccEvent.newEndOffset, -1, "New end offset is correct");
+ ok(!vccEvent.isFromUserInput, "not user initiated");
+
+ onVCChanged = waitForEvent(EVENT_VIRTUALCURSOR_CHANGED, matchContentDoc);
+ await invokeContentTask(browser, [], () => {
+ const { CommonUtils } = ChromeUtils.import(
+ "chrome://mochitests/content/browser/accessible/tests/browser/Common.jsm"
+ );
+ let vc = CommonUtils.getAccessible(
+ content.document,
+ Ci.nsIAccessibleDocument
+ ).virtualCursor;
+ vc.moveNextByText(Ci.nsIAccessiblePivot.CHAR_BOUNDARY);
+ });
+ vccEvent = (await onVCChanged).QueryInterface(
+ nsIAccessibleVirtualCursorChangeEvent
+ );
+ is(vccEvent.newAccessible.id, vccEvent.oldAccessible.id, "Same position");
+ is(vccEvent.newStartOffset, 0, "New start offset is correct");
+ is(vccEvent.newEndOffset, 1, "New end offset is correct");
+ ok(vccEvent.isFromUserInput, "user initiated");
+
+ onVCChanged = waitForEvent(EVENT_VIRTUALCURSOR_CHANGED, matchContentDoc);
+ await invokeContentTask(browser, [], () => {
+ const { CommonUtils } = ChromeUtils.import(
+ "chrome://mochitests/content/browser/accessible/tests/browser/Common.jsm"
+ );
+ let vc = CommonUtils.getAccessible(
+ content.document,
+ Ci.nsIAccessibleDocument
+ ).virtualCursor;
+ vc.position = CommonUtils.getAccessible(
+ "input1",
+ null,
+ null,
+ null,
+ content.document
+ );
+ });
+ vccEvent = (await onVCChanged).QueryInterface(
+ nsIAccessibleVirtualCursorChangeEvent
+ );
+ isnot(vccEvent.oldAccessible, vccEvent.newAccessible, "positions differ");
+ is(vccEvent.oldAccessible.id, "p1", "Old position is correct");
+ is(vccEvent.newAccessible.id, "input1", "New position is correct");
+ is(vccEvent.newStartOffset, -1, "New start offset is correct");
+ is(vccEvent.newEndOffset, -1, "New end offset is correct");
+ ok(!vccEvent.isFromUserInput, "not user initiated");
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_text_paragraph_boundary.js b/accessible/tests/browser/e10s/browser_text_paragraph_boundary.js
new file mode 100644
index 0000000000..04e64520e8
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_text_paragraph_boundary.js
@@ -0,0 +1,22 @@
+/* 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";
+
+// Test that we don't crash the parent process when querying the paragraph
+// boundary on an Accessible which has remote ProxyAccessible descendants.
+addAccessibleTask(
+ `test`,
+ async function testParagraphBoundaryWithRemoteDescendants(browser, accDoc) {
+ const root = getRootAccessible(document).QueryInterface(
+ Ci.nsIAccessibleText
+ );
+ let start = {};
+ let end = {};
+ // The offsets will change as the Firefox UI changes. We don't really care
+ // what they are, just that we don't crash.
+ root.getTextAtOffset(0, nsIAccessibleText.BOUNDARY_PARAGRAPH, start, end);
+ ok(true, "Getting paragraph boundary succeeded");
+ }
+);
diff --git a/accessible/tests/browser/e10s/browser_treeupdate_ariadialog.js b/accessible/tests/browser/e10s/browser_treeupdate_ariadialog.js
new file mode 100644
index 0000000000..8b4a575d75
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_treeupdate_ariadialog.js
@@ -0,0 +1,45 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/role.js */
+loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
+
+// Test ARIA Dialog
+addAccessibleTask(
+ "e10s/doc_treeupdate_ariadialog.html",
+ async function(browser, accDoc) {
+ testAccessibleTree(accDoc, {
+ role: ROLE_DOCUMENT,
+ children: [],
+ });
+
+ // Make dialog visible and update its inner content.
+ let onShow = waitForEvent(EVENT_SHOW, "dialog");
+ await invokeContentTask(browser, [], () => {
+ content.document.getElementById("dialog").style.display = "block";
+ });
+ await onShow;
+
+ testAccessibleTree(accDoc, {
+ role: ROLE_DOCUMENT,
+ children: [
+ {
+ role: ROLE_DIALOG,
+ children: [
+ {
+ role: ROLE_PUSHBUTTON,
+ children: [{ role: ROLE_TEXT_LEAF }],
+ },
+ {
+ role: ROLE_ENTRY,
+ },
+ ],
+ },
+ ],
+ });
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_treeupdate_ariaowns.js b/accessible/tests/browser/e10s/browser_treeupdate_ariaowns.js
new file mode 100644
index 0000000000..dfd6401c48
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_treeupdate_ariaowns.js
@@ -0,0 +1,294 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/role.js */
+loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
+
+async function testContainer1(browser, accDoc) {
+ const id = "t1_container";
+ const docID = getAccessibleDOMNodeID(accDoc);
+ const acc = findAccessibleChildByID(accDoc, id);
+
+ /* ================= Initial tree test ==================================== */
+ // children are swapped by ARIA owns
+ let tree = {
+ SECTION: [{ CHECKBUTTON: [{ SECTION: [] }] }, { PUSHBUTTON: [] }],
+ };
+ testAccessibleTree(acc, tree);
+
+ /* ================ Change ARIA owns ====================================== */
+ let onReorder = waitForEvent(EVENT_REORDER, id);
+ await invokeSetAttribute(browser, id, "aria-owns", "t1_button t1_subdiv");
+ await onReorder;
+
+ // children are swapped again, button and subdiv are appended to
+ // the children.
+ tree = {
+ SECTION: [
+ { CHECKBUTTON: [] }, // checkbox, native order
+ { PUSHBUTTON: [] }, // button, rearranged by ARIA own
+ { SECTION: [] }, // subdiv from the subtree, ARIA owned
+ ],
+ };
+ testAccessibleTree(acc, tree);
+
+ /* ================ Remove ARIA owns ====================================== */
+ onReorder = waitForEvent(EVENT_REORDER, id);
+ await invokeSetAttribute(browser, id, "aria-owns");
+ await onReorder;
+
+ // children follow the DOM order
+ tree = {
+ SECTION: [{ PUSHBUTTON: [] }, { CHECKBUTTON: [{ SECTION: [] }] }],
+ };
+ testAccessibleTree(acc, tree);
+
+ /* ================ Set ARIA owns ========================================= */
+ onReorder = waitForEvent(EVENT_REORDER, id);
+ await invokeSetAttribute(browser, id, "aria-owns", "t1_button t1_subdiv");
+ await onReorder;
+
+ // children are swapped again, button and subdiv are appended to
+ // the children.
+ tree = {
+ SECTION: [
+ { CHECKBUTTON: [] }, // checkbox
+ { PUSHBUTTON: [] }, // button, rearranged by ARIA own
+ { SECTION: [] }, // subdiv from the subtree, ARIA owned
+ ],
+ };
+ testAccessibleTree(acc, tree);
+
+ /* ================ Add ID to ARIA owns =================================== */
+ onReorder = waitForEvent(EVENT_REORDER, docID);
+ await invokeSetAttribute(
+ browser,
+ id,
+ "aria-owns",
+ "t1_button t1_subdiv t1_group"
+ );
+ await onReorder;
+
+ // children are swapped again, button and subdiv are appended to
+ // the children.
+ tree = {
+ SECTION: [
+ { CHECKBUTTON: [] }, // t1_checkbox
+ { PUSHBUTTON: [] }, // button, t1_button
+ { SECTION: [] }, // subdiv from the subtree, t1_subdiv
+ { GROUPING: [] }, // group from outside, t1_group
+ ],
+ };
+ testAccessibleTree(acc, tree);
+
+ /* ================ Append element ======================================== */
+ onReorder = waitForEvent(EVENT_REORDER, id);
+ await invokeContentTask(browser, [id], contentId => {
+ let div = content.document.createElement("div");
+ div.setAttribute("id", "t1_child3");
+ div.setAttribute("role", "radio");
+ content.document.getElementById(contentId).appendChild(div);
+ });
+ await onReorder;
+
+ // children are invalidated, they includes aria-owns swapped kids and
+ // newly inserted child.
+ tree = {
+ SECTION: [
+ { CHECKBUTTON: [] }, // existing explicit, t1_checkbox
+ { RADIOBUTTON: [] }, // new explicit, t1_child3
+ { PUSHBUTTON: [] }, // ARIA owned, t1_button
+ { SECTION: [] }, // ARIA owned, t1_subdiv
+ { GROUPING: [] }, // ARIA owned, t1_group
+ ],
+ };
+ testAccessibleTree(acc, tree);
+
+ /* ================ Remove element ======================================== */
+ onReorder = waitForEvent(EVENT_REORDER, id);
+ await invokeContentTask(browser, [], () => {
+ content.document.getElementById("t1_span").remove();
+ });
+ await onReorder;
+
+ // subdiv should go away
+ tree = {
+ SECTION: [
+ { CHECKBUTTON: [] }, // explicit, t1_checkbox
+ { RADIOBUTTON: [] }, // explicit, t1_child3
+ { PUSHBUTTON: [] }, // ARIA owned, t1_button
+ { GROUPING: [] }, // ARIA owned, t1_group
+ ],
+ };
+ testAccessibleTree(acc, tree);
+
+ /* ================ Remove ID ============================================= */
+ onReorder = waitForEvent(EVENT_REORDER, docID);
+ await invokeSetAttribute(browser, "t1_group", "id");
+ await onReorder;
+
+ tree = {
+ SECTION: [
+ { CHECKBUTTON: [] },
+ { RADIOBUTTON: [] },
+ { PUSHBUTTON: [] }, // ARIA owned, t1_button
+ ],
+ };
+ testAccessibleTree(acc, tree);
+
+ /* ================ Set ID ================================================ */
+ onReorder = waitForEvent(EVENT_REORDER, docID);
+ await invokeSetAttribute(browser, "t1_grouptmp", "id", "t1_group");
+ await onReorder;
+
+ tree = {
+ SECTION: [
+ { CHECKBUTTON: [] },
+ { RADIOBUTTON: [] },
+ { PUSHBUTTON: [] }, // ARIA owned, t1_button
+ { GROUPING: [] }, // ARIA owned, t1_group, previously t1_grouptmp
+ ],
+ };
+ testAccessibleTree(acc, tree);
+}
+
+async function removeContainer(browser, accDoc) {
+ const id = "t2_container1";
+ const acc = findAccessibleChildByID(accDoc, id);
+
+ let tree = {
+ SECTION: [
+ { CHECKBUTTON: [] }, // ARIA owned, 't2_owned'
+ ],
+ };
+ testAccessibleTree(acc, tree);
+
+ let onReorder = waitForEvent(EVENT_REORDER, id);
+ await invokeContentTask(browser, [], () => {
+ content.document
+ .getElementById("t2_container2")
+ .removeChild(content.document.getElementById("t2_container3"));
+ });
+ await onReorder;
+
+ tree = {
+ SECTION: [],
+ };
+ testAccessibleTree(acc, tree);
+}
+
+async function stealAndRecacheChildren(browser, accDoc) {
+ const id1 = "t3_container1";
+ const id2 = "t3_container2";
+ const acc1 = findAccessibleChildByID(accDoc, id1);
+ const acc2 = findAccessibleChildByID(accDoc, id2);
+
+ /* ================ Attempt to steal from other ARIA owns ================= */
+ let onReorder = waitForEvent(EVENT_REORDER, id2);
+ await invokeSetAttribute(browser, id2, "aria-owns", "t3_child");
+ await invokeContentTask(browser, [id2], id => {
+ let div = content.document.createElement("div");
+ div.setAttribute("role", "radio");
+ content.document.getElementById(id).appendChild(div);
+ });
+ await onReorder;
+
+ let tree = {
+ SECTION: [
+ { CHECKBUTTON: [] }, // ARIA owned
+ ],
+ };
+ testAccessibleTree(acc1, tree);
+
+ tree = {
+ SECTION: [{ RADIOBUTTON: [] }],
+ };
+ testAccessibleTree(acc2, tree);
+}
+
+async function showHiddenElement(browser, accDoc) {
+ const id = "t4_container1";
+ const acc = findAccessibleChildByID(accDoc, id);
+
+ let tree = {
+ SECTION: [{ RADIOBUTTON: [] }],
+ };
+ testAccessibleTree(acc, tree);
+
+ let onReorder = waitForEvent(EVENT_REORDER, id);
+ await invokeSetStyle(browser, "t4_child1", "display", "block");
+ await onReorder;
+
+ tree = {
+ SECTION: [{ CHECKBUTTON: [] }, { RADIOBUTTON: [] }],
+ };
+ testAccessibleTree(acc, tree);
+}
+
+async function rearrangeARIAOwns(browser, accDoc) {
+ const id = "t5_container";
+ const acc = findAccessibleChildByID(accDoc, id);
+ const tests = [
+ {
+ val: "t5_checkbox t5_radio t5_button",
+ roleList: ["CHECKBUTTON", "RADIOBUTTON", "PUSHBUTTON"],
+ },
+ {
+ val: "t5_radio t5_button t5_checkbox",
+ roleList: ["RADIOBUTTON", "PUSHBUTTON", "CHECKBUTTON"],
+ },
+ ];
+
+ for (let { val, roleList } of tests) {
+ let onReorder = waitForEvent(EVENT_REORDER, id);
+ await invokeSetAttribute(browser, id, "aria-owns", val);
+ await onReorder;
+
+ let tree = { SECTION: [] };
+ for (let role of roleList) {
+ let ch = {};
+ ch[role] = [];
+ tree.SECTION.push(ch);
+ }
+ testAccessibleTree(acc, tree);
+ }
+}
+
+async function removeNotARIAOwnedEl(browser, accDoc) {
+ const id = "t6_container";
+ const acc = findAccessibleChildByID(accDoc, id);
+
+ let tree = {
+ SECTION: [{ TEXT_LEAF: [] }, { GROUPING: [] }],
+ };
+ testAccessibleTree(acc, tree);
+
+ let onReorder = waitForEvent(EVENT_REORDER, id);
+ await invokeContentTask(browser, [id], contentId => {
+ content.document
+ .getElementById(contentId)
+ .removeChild(content.document.getElementById("t6_span"));
+ });
+ await onReorder;
+
+ tree = {
+ SECTION: [{ GROUPING: [] }],
+ };
+ testAccessibleTree(acc, tree);
+}
+
+addAccessibleTask(
+ "e10s/doc_treeupdate_ariaowns.html",
+ async function(browser, accDoc) {
+ await testContainer1(browser, accDoc);
+ await removeContainer(browser, accDoc);
+ await stealAndRecacheChildren(browser, accDoc);
+ await showHiddenElement(browser, accDoc);
+ await rearrangeARIAOwns(browser, accDoc);
+ await removeNotARIAOwnedEl(browser, accDoc);
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_treeupdate_canvas.js b/accessible/tests/browser/e10s/browser_treeupdate_canvas.js
new file mode 100644
index 0000000000..5fcd1eb773
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_treeupdate_canvas.js
@@ -0,0 +1,28 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/role.js */
+loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
+
+addAccessibleTask(
+ `
+ <canvas id="canvas">
+ <div id="dialog" role="dialog" style="display: none;"></div>
+ </canvas>`,
+ async function(browser, accDoc) {
+ let canvas = findAccessibleChildByID(accDoc, "canvas");
+ let dialog = findAccessibleChildByID(accDoc, "dialog");
+
+ testAccessibleTree(canvas, { CANVAS: [] });
+
+ let onShow = waitForEvent(EVENT_SHOW, "dialog");
+ await invokeSetStyle(browser, "dialog", "display", "block");
+ await onShow;
+
+ testAccessibleTree(dialog, { DIALOG: [] });
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_treeupdate_cssoverflow.js b/accessible/tests/browser/e10s/browser_treeupdate_cssoverflow.js
new file mode 100644
index 0000000000..629f9fb89f
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_treeupdate_cssoverflow.js
@@ -0,0 +1,60 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/role.js */
+loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
+
+addAccessibleTask(
+ `
+ <div id="container"><div id="scrollarea" style="overflow:auto;"><input>`,
+ async function(browser, accDoc) {
+ const id1 = "container";
+ const container = findAccessibleChildByID(accDoc, id1);
+
+ /* ================= Change scroll range ================================== */
+ let tree = {
+ SECTION: [
+ {
+ // container
+ SECTION: [
+ {
+ // scroll area
+ ENTRY: [], // child content
+ },
+ ],
+ },
+ ],
+ };
+ testAccessibleTree(container, tree);
+
+ let onReorder = waitForEvent(EVENT_REORDER, id1);
+ await invokeContentTask(browser, [id1], id => {
+ let doc = content.document;
+ doc.getElementById("scrollarea").style.width = "20px";
+ doc.getElementById(id).appendChild(doc.createElement("input"));
+ });
+ await onReorder;
+
+ tree = {
+ SECTION: [
+ {
+ // container
+ SECTION: [
+ {
+ // scroll area
+ ENTRY: [], // child content
+ },
+ ],
+ },
+ {
+ ENTRY: [], // inserted input
+ },
+ ],
+ };
+ testAccessibleTree(container, tree);
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_treeupdate_doc.js b/accessible/tests/browser/e10s/browser_treeupdate_doc.js
new file mode 100644
index 0000000000..98f399695c
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_treeupdate_doc.js
@@ -0,0 +1,320 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/role.js */
+loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
+
+const iframeSrc = `data:text/html,
+ <html>
+ <head>
+ <meta charset='utf-8'/>
+ <title>Inner Iframe</title>
+ </head>
+ <body id='inner-iframe'></body>
+ </html>`;
+
+addAccessibleTask(
+ `
+ <iframe id="iframe" src="${iframeSrc}"></iframe>`,
+ async function(browser, accDoc) {
+ // ID of the iframe that is being tested
+ const id = "inner-iframe";
+
+ let iframe = findAccessibleChildByID(accDoc, id);
+
+ /* ================= Initial tree check =================================== */
+ let tree = {
+ role: ROLE_DOCUMENT,
+ children: [],
+ };
+ testAccessibleTree(iframe, tree);
+
+ /* ================= Write iframe document ================================ */
+ let reorderEventPromise = waitForEvent(EVENT_REORDER, id);
+ await invokeContentTask(browser, [id], contentId => {
+ let docNode = content.document.getElementById("iframe").contentDocument;
+ let newHTMLNode = docNode.createElement("html");
+ let newBodyNode = docNode.createElement("body");
+ let newTextNode = docNode.createTextNode("New Wave");
+ newBodyNode.id = contentId;
+ newBodyNode.appendChild(newTextNode);
+ newHTMLNode.appendChild(newBodyNode);
+ docNode.replaceChild(newHTMLNode, docNode.documentElement);
+ });
+ await reorderEventPromise;
+
+ tree = {
+ role: ROLE_DOCUMENT,
+ children: [
+ {
+ role: ROLE_TEXT_LEAF,
+ name: "New Wave",
+ },
+ ],
+ };
+ testAccessibleTree(iframe, tree);
+
+ /* ================= Replace iframe HTML element ========================== */
+ reorderEventPromise = waitForEvent(EVENT_REORDER, id);
+ await invokeContentTask(browser, [id], contentId => {
+ let docNode = content.document.getElementById("iframe").contentDocument;
+ // We can't use open/write/close outside of iframe document because of
+ // security error.
+ let script = docNode.createElement("script");
+ script.textContent = `
+ document.open();
+ document.write('<body id="${contentId}">hello</body>');
+ document.close();`;
+ docNode.body.appendChild(script);
+ });
+ await reorderEventPromise;
+
+ tree = {
+ role: ROLE_DOCUMENT,
+ children: [
+ {
+ role: ROLE_TEXT_LEAF,
+ name: "hello",
+ },
+ ],
+ };
+ testAccessibleTree(iframe, tree);
+
+ /* ================= Replace iframe body ================================== */
+ reorderEventPromise = waitForEvent(EVENT_REORDER, id);
+ await invokeContentTask(browser, [id], contentId => {
+ let docNode = content.document.getElementById("iframe").contentDocument;
+ let newBodyNode = docNode.createElement("body");
+ let newTextNode = docNode.createTextNode("New Hello");
+ newBodyNode.id = contentId;
+ newBodyNode.appendChild(newTextNode);
+ newBodyNode.setAttribute("role", "application");
+ docNode.documentElement.replaceChild(newBodyNode, docNode.body);
+ });
+ await reorderEventPromise;
+
+ tree = {
+ role: ROLE_APPLICATION,
+ children: [
+ {
+ role: ROLE_TEXT_LEAF,
+ name: "New Hello",
+ },
+ ],
+ };
+ testAccessibleTree(iframe, tree);
+
+ /* ================= Open iframe document ================================= */
+ reorderEventPromise = waitForEvent(EVENT_REORDER, id);
+ await invokeContentTask(browser, [id], contentId => {
+ // Open document.
+ let docNode = content.document.getElementById("iframe").contentDocument;
+ let script = docNode.createElement("script");
+ script.textContent = `
+ function closeMe() {
+ document.write('Works?');
+ document.close();
+ }
+ window.closeMe = closeMe;
+ document.open();
+ document.write('<body id="${contentId}"></body>');`;
+ docNode.body.appendChild(script);
+ });
+ await reorderEventPromise;
+
+ tree = {
+ role: ROLE_DOCUMENT,
+ children: [],
+ };
+ testAccessibleTree(iframe, tree);
+
+ /* ================= Close iframe document ================================ */
+ reorderEventPromise = waitForEvent(EVENT_REORDER, id);
+ await invokeContentTask(browser, [], () => {
+ // Write and close document.
+ let docNode = content.document.getElementById("iframe").contentDocument;
+ docNode.write("Works?");
+ docNode.close();
+ });
+ await reorderEventPromise;
+
+ tree = {
+ role: ROLE_DOCUMENT,
+ children: [
+ {
+ role: ROLE_TEXT_LEAF,
+ name: "Works?",
+ },
+ ],
+ };
+ testAccessibleTree(iframe, tree);
+
+ /* ================= Remove HTML from iframe document ===================== */
+ reorderEventPromise = waitForEvent(EVENT_REORDER, iframe);
+ await invokeContentTask(browser, [], () => {
+ // Remove HTML element.
+ let docNode = content.document.getElementById("iframe").contentDocument;
+ docNode.firstChild.remove();
+ });
+ let event = await reorderEventPromise;
+
+ ok(
+ event.accessible instanceof nsIAccessibleDocument,
+ "Reorder should happen on the document"
+ );
+ tree = {
+ role: ROLE_DOCUMENT,
+ children: [],
+ };
+ testAccessibleTree(iframe, tree);
+
+ /* ================= Insert HTML to iframe document ======================= */
+ reorderEventPromise = waitForEvent(EVENT_REORDER, id);
+ await invokeContentTask(browser, [id], contentId => {
+ // Insert HTML element.
+ let docNode = content.document.getElementById("iframe").contentDocument;
+ let html = docNode.createElement("html");
+ let body = docNode.createElement("body");
+ let text = docNode.createTextNode("Haha");
+ body.appendChild(text);
+ body.id = contentId;
+ html.appendChild(body);
+ docNode.appendChild(html);
+ });
+ await reorderEventPromise;
+
+ tree = {
+ role: ROLE_DOCUMENT,
+ children: [
+ {
+ role: ROLE_TEXT_LEAF,
+ name: "Haha",
+ },
+ ],
+ };
+ testAccessibleTree(iframe, tree);
+
+ /* ================= Remove body from iframe document ===================== */
+ reorderEventPromise = waitForEvent(EVENT_REORDER, iframe);
+ await invokeContentTask(browser, [], () => {
+ // Remove body element.
+ let docNode = content.document.getElementById("iframe").contentDocument;
+ docNode.documentElement.removeChild(docNode.body);
+ });
+ event = await reorderEventPromise;
+
+ ok(
+ event.accessible instanceof nsIAccessibleDocument,
+ "Reorder should happen on the document"
+ );
+ tree = {
+ role: ROLE_DOCUMENT,
+ children: [],
+ };
+ testAccessibleTree(iframe, tree);
+
+ /* ================ Insert element under document element while body missed */
+ reorderEventPromise = waitForEvent(EVENT_REORDER, iframe);
+ await invokeContentTask(browser, [], () => {
+ let docNode = content.document.getElementById("iframe").contentDocument;
+ let inputNode = (content.window.inputNode = docNode.createElement(
+ "input"
+ ));
+ docNode.documentElement.appendChild(inputNode);
+ });
+ event = await reorderEventPromise;
+
+ ok(
+ event.accessible instanceof nsIAccessibleDocument,
+ "Reorder should happen on the document"
+ );
+ tree = {
+ DOCUMENT: [{ ENTRY: [] }],
+ };
+ testAccessibleTree(iframe, tree);
+
+ reorderEventPromise = waitForEvent(EVENT_REORDER, iframe);
+ await invokeContentTask(browser, [], () => {
+ let docEl = content.document.getElementById("iframe").contentDocument
+ .documentElement;
+ // Remove aftermath of this test before next test starts.
+ docEl.firstChild.remove();
+ });
+ // Make sure reorder event was fired and that the input was removed.
+ await reorderEventPromise;
+ tree = {
+ role: ROLE_DOCUMENT,
+ children: [],
+ };
+ testAccessibleTree(iframe, tree);
+
+ /* ================= Insert body to iframe document ======================= */
+ reorderEventPromise = waitForEvent(EVENT_REORDER, id);
+ await invokeContentTask(browser, [id], contentId => {
+ // Write and close document.
+ let docNode = content.document.getElementById("iframe").contentDocument;
+ // Insert body element.
+ let body = docNode.createElement("body");
+ let text = docNode.createTextNode("Yo ho ho i butylka roma!");
+ body.appendChild(text);
+ body.id = contentId;
+ docNode.documentElement.appendChild(body);
+ });
+ await reorderEventPromise;
+
+ tree = {
+ role: ROLE_DOCUMENT,
+ children: [
+ {
+ role: ROLE_TEXT_LEAF,
+ name: "Yo ho ho i butylka roma!",
+ },
+ ],
+ };
+ testAccessibleTree(iframe, tree);
+
+ /* ================= Change source ======================================== */
+ reorderEventPromise = waitForEvent(EVENT_REORDER, "iframe");
+ await invokeSetAttribute(
+ browser,
+ "iframe",
+ "src",
+ `data:text/html,<html><body id="${id}"><input></body></html>`
+ );
+ event = await reorderEventPromise;
+
+ tree = {
+ INTERNAL_FRAME: [{ DOCUMENT: [{ ENTRY: [] }] }],
+ };
+ testAccessibleTree(event.accessible, tree);
+ iframe = findAccessibleChildByID(event.accessible, id);
+
+ /* ================= Replace iframe body on ARIA role body ================ */
+ reorderEventPromise = waitForEvent(EVENT_REORDER, id);
+ await invokeContentTask(browser, [id], contentId => {
+ let docNode = content.document.getElementById("iframe").contentDocument;
+ let newBodyNode = docNode.createElement("body");
+ let newTextNode = docNode.createTextNode("New Hello");
+ newBodyNode.appendChild(newTextNode);
+ newBodyNode.setAttribute("role", "application");
+ newBodyNode.id = contentId;
+ docNode.documentElement.replaceChild(newBodyNode, docNode.body);
+ });
+ await reorderEventPromise;
+
+ tree = {
+ role: ROLE_APPLICATION,
+ children: [
+ {
+ role: ROLE_TEXT_LEAF,
+ name: "New Hello",
+ },
+ ],
+ };
+ testAccessibleTree(iframe, tree);
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_treeupdate_gencontent.js b/accessible/tests/browser/e10s/browser_treeupdate_gencontent.js
new file mode 100644
index 0000000000..ca1150f9dd
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_treeupdate_gencontent.js
@@ -0,0 +1,94 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/role.js */
+loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
+
+addAccessibleTask(
+ `
+ <style>
+ .gentext:before {
+ content: "START"
+ }
+ .gentext:after {
+ content: "END"
+ }
+ </style>
+ <div id="container1"></div>
+ <div id="container2"><div id="container2_child">text</div></div>`,
+ async function(browser, accDoc) {
+ const id1 = "container1";
+ const id2 = "container2";
+ let container1 = findAccessibleChildByID(accDoc, id1);
+ let container2 = findAccessibleChildByID(accDoc, id2);
+
+ let tree = {
+ SECTION: [], // container
+ };
+ testAccessibleTree(container1, tree);
+
+ tree = {
+ SECTION: [
+ {
+ // container2
+ SECTION: [
+ {
+ // container2 child
+ TEXT_LEAF: [], // primary text
+ },
+ ],
+ },
+ ],
+ };
+ testAccessibleTree(container2, tree);
+
+ let onReorder = waitForEvent(EVENT_REORDER, id1);
+ // Create and add an element with CSS generated content to container1
+ await invokeContentTask(browser, [id1], id => {
+ let node = content.document.createElement("div");
+ node.textContent = "text";
+ node.setAttribute("class", "gentext");
+ content.document.getElementById(id).appendChild(node);
+ });
+ await onReorder;
+
+ tree = {
+ SECTION: [
+ // container
+ {
+ SECTION: [
+ // inserted node
+ { STATICTEXT: [] }, // :before
+ { TEXT_LEAF: [] }, // primary text
+ { STATICTEXT: [] }, // :after
+ ],
+ },
+ ],
+ };
+ testAccessibleTree(container1, tree);
+
+ onReorder = waitForEvent(EVENT_REORDER, "container2_child");
+ // Add CSS generated content to an element in container2's subtree
+ await invokeSetAttribute(browser, "container2_child", "class", "gentext");
+ await onReorder;
+
+ tree = {
+ SECTION: [
+ // container2
+ {
+ SECTION: [
+ // container2 child
+ { STATICTEXT: [] }, // :before
+ { TEXT_LEAF: [] }, // primary text
+ { STATICTEXT: [] }, // :after
+ ],
+ },
+ ],
+ };
+ testAccessibleTree(container2, tree);
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_treeupdate_hidden.js b/accessible/tests/browser/e10s/browser_treeupdate_hidden.js
new file mode 100644
index 0000000000..725999db36
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_treeupdate_hidden.js
@@ -0,0 +1,32 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/role.js */
+loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
+
+async function setHidden(browser, value) {
+ let onReorder = waitForEvent(EVENT_REORDER, "container");
+ await invokeSetAttribute(browser, "child", "hidden", value);
+ await onReorder;
+}
+
+addAccessibleTask(
+ '<div id="container"><input id="child"></div>',
+ async function(browser, accDoc) {
+ let container = findAccessibleChildByID(accDoc, "container");
+
+ testAccessibleTree(container, { SECTION: [{ ENTRY: [] }] });
+
+ // Set @hidden attribute
+ await setHidden(browser, "true");
+ testAccessibleTree(container, { SECTION: [] });
+
+ // Remove @hidden attribute
+ await setHidden(browser);
+ testAccessibleTree(container, { SECTION: [{ ENTRY: [] }] });
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_treeupdate_imagemap.js b/accessible/tests/browser/e10s/browser_treeupdate_imagemap.js
new file mode 100644
index 0000000000..e206b83276
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_treeupdate_imagemap.js
@@ -0,0 +1,187 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/role.js */
+loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
+
+async function testImageMap(browser, accDoc) {
+ const id = "imgmap";
+ const acc = findAccessibleChildByID(accDoc, id);
+
+ /* ================= Initial tree test ==================================== */
+ let tree = {
+ IMAGE_MAP: [{ role: ROLE_LINK, name: "b", children: [] }],
+ };
+ testAccessibleTree(acc, tree);
+
+ /* ================= Insert area ========================================== */
+ let onReorder = waitForEvent(EVENT_REORDER, id);
+ await invokeContentTask(browser, [], () => {
+ let areaElm = content.document.createElement("area");
+ let mapNode = content.document.getElementById("map");
+ areaElm.setAttribute(
+ "href",
+ "http://www.bbc.co.uk/radio4/atoz/index.shtml#a"
+ );
+ areaElm.setAttribute("coords", "0,0,13,14");
+ areaElm.setAttribute("alt", "a");
+ areaElm.setAttribute("shape", "rect");
+ mapNode.insertBefore(areaElm, mapNode.firstChild);
+ });
+ await onReorder;
+
+ tree = {
+ IMAGE_MAP: [
+ { role: ROLE_LINK, name: "a", children: [] },
+ { role: ROLE_LINK, name: "b", children: [] },
+ ],
+ };
+ testAccessibleTree(acc, tree);
+
+ /* ================= Append area ========================================== */
+ onReorder = waitForEvent(EVENT_REORDER, id);
+ await invokeContentTask(browser, [], () => {
+ let areaElm = content.document.createElement("area");
+ let mapNode = content.document.getElementById("map");
+ areaElm.setAttribute(
+ "href",
+ "http://www.bbc.co.uk/radio4/atoz/index.shtml#c"
+ );
+ areaElm.setAttribute("coords", "34,0,47,14");
+ areaElm.setAttribute("alt", "c");
+ areaElm.setAttribute("shape", "rect");
+ mapNode.appendChild(areaElm);
+ });
+ await onReorder;
+
+ tree = {
+ IMAGE_MAP: [
+ { role: ROLE_LINK, name: "a", children: [] },
+ { role: ROLE_LINK, name: "b", children: [] },
+ { role: ROLE_LINK, name: "c", children: [] },
+ ],
+ };
+ testAccessibleTree(acc, tree);
+
+ /* ================= Remove area ========================================== */
+ onReorder = waitForEvent(EVENT_REORDER, id);
+ await invokeContentTask(browser, [], () => {
+ let mapNode = content.document.getElementById("map");
+ mapNode.removeChild(mapNode.firstElementChild);
+ });
+ await onReorder;
+
+ tree = {
+ IMAGE_MAP: [
+ { role: ROLE_LINK, name: "b", children: [] },
+ { role: ROLE_LINK, name: "c", children: [] },
+ ],
+ };
+ testAccessibleTree(acc, tree);
+}
+
+async function testContainer(browser) {
+ const id = "container";
+ /* ================= Remove name on map =================================== */
+ let onReorder = waitForEvent(EVENT_REORDER, id);
+ await invokeSetAttribute(browser, "map", "name");
+ let event = await onReorder;
+ const acc = event.accessible;
+
+ let tree = {
+ SECTION: [{ GRAPHIC: [] }],
+ };
+ testAccessibleTree(acc, tree);
+
+ /* ================= Restore name on map ================================== */
+ onReorder = waitForEvent(EVENT_REORDER, id);
+ await invokeSetAttribute(browser, "map", "name", "atoz_map");
+ // XXX: force repainting of the image (see bug 745788 for details).
+ await invokeContentTask(browser, [], () => {
+ const { ContentTaskUtils } = ChromeUtils.import(
+ "resource://testing-common/ContentTaskUtils.jsm"
+ );
+ const EventUtils = ContentTaskUtils.getEventUtils(content);
+ EventUtils.synthesizeMouse(
+ content.document.getElementById("imgmap"),
+ 10,
+ 10,
+ { type: "mousemove" },
+ content
+ );
+ });
+ await onReorder;
+
+ tree = {
+ SECTION: [
+ {
+ IMAGE_MAP: [{ LINK: [] }, { LINK: [] }],
+ },
+ ],
+ };
+ testAccessibleTree(acc, tree);
+
+ /* ================= Remove map =========================================== */
+ onReorder = waitForEvent(EVENT_REORDER, id);
+ await invokeContentTask(browser, [], () => {
+ let mapNode = content.document.getElementById("map");
+ mapNode.remove();
+ });
+ await onReorder;
+
+ tree = {
+ SECTION: [{ GRAPHIC: [] }],
+ };
+ testAccessibleTree(acc, tree);
+
+ /* ================= Insert map =========================================== */
+ onReorder = waitForEvent(EVENT_REORDER, id);
+ await invokeContentTask(browser, [id], contentId => {
+ let map = content.document.createElement("map");
+ let area = content.document.createElement("area");
+
+ map.setAttribute("name", "atoz_map");
+ map.setAttribute("id", "map");
+
+ area.setAttribute("href", "http://www.bbc.co.uk/radio4/atoz/index.shtml#b");
+ area.setAttribute("coords", "17,0,30,14");
+ area.setAttribute("alt", "b");
+ area.setAttribute("shape", "rect");
+
+ map.appendChild(area);
+ content.document.getElementById(contentId).appendChild(map);
+ });
+ await onReorder;
+
+ tree = {
+ SECTION: [
+ {
+ IMAGE_MAP: [{ LINK: [] }],
+ },
+ ],
+ };
+ testAccessibleTree(acc, tree);
+
+ /* ================= Hide image map ======================================= */
+ onReorder = waitForEvent(EVENT_REORDER, id);
+ await invokeSetStyle(browser, "imgmap", "display", "none");
+ await onReorder;
+
+ tree = {
+ SECTION: [],
+ };
+ testAccessibleTree(acc, tree);
+}
+
+addAccessibleTask(
+ "e10s/doc_treeupdate_imagemap.html",
+ async function(browser, accDoc) {
+ await waitForImageMap(browser, accDoc);
+ await testImageMap(browser, accDoc);
+ await testContainer(browser);
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_treeupdate_list.js b/accessible/tests/browser/e10s/browser_treeupdate_list.js
new file mode 100644
index 0000000000..d14b983c10
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_treeupdate_list.js
@@ -0,0 +1,52 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/role.js */
+loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
+
+async function setDisplayAndWaitForReorder(browser, value) {
+ let onReorder = waitForEvent(EVENT_REORDER, "ul");
+ await invokeSetStyle(browser, "li", "display", value);
+ return onReorder;
+}
+
+addAccessibleTask(
+ `
+ <ul id="ul">
+ <li id="li">item1</li>
+ </ul>`,
+ async function(browser, accDoc) {
+ let li = findAccessibleChildByID(accDoc, "li");
+ let bullet = li.firstChild;
+ let accTree = {
+ role: ROLE_LISTITEM,
+ children: [
+ {
+ role: ROLE_LISTITEM_MARKER,
+ children: [],
+ },
+ {
+ role: ROLE_TEXT_LEAF,
+ children: [],
+ },
+ ],
+ };
+ testAccessibleTree(li, accTree);
+
+ await setDisplayAndWaitForReorder(browser, "none");
+
+ ok(isDefunct(li), "Check that li is defunct.");
+ ok(isDefunct(bullet), "Check that bullet is defunct.");
+
+ let event = await setDisplayAndWaitForReorder(browser, "list-item");
+
+ testAccessibleTree(
+ findAccessibleChildByID(event.accessible, "li"),
+ accTree
+ );
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_treeupdate_list_editabledoc.js b/accessible/tests/browser/e10s/browser_treeupdate_list_editabledoc.js
new file mode 100644
index 0000000000..9c672f3c7c
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_treeupdate_list_editabledoc.js
@@ -0,0 +1,48 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/role.js */
+loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
+
+addAccessibleTask(
+ '<ol id="list"></ol>',
+ async function(browser, accDoc) {
+ let list = findAccessibleChildByID(accDoc, "list");
+
+ testAccessibleTree(list, {
+ role: ROLE_LIST,
+ children: [],
+ });
+
+ await invokeSetAttribute(
+ browser,
+ currentContentDoc(),
+ "contentEditable",
+ "true"
+ );
+ let onReorder = waitForEvent(EVENT_REORDER, "list");
+ await invokeContentTask(browser, [], () => {
+ let li = content.document.createElement("li");
+ li.textContent = "item";
+ content.document.getElementById("list").appendChild(li);
+ });
+ await onReorder;
+
+ testAccessibleTree(list, {
+ role: ROLE_LIST,
+ children: [
+ {
+ role: ROLE_LISTITEM,
+ children: [
+ { role: ROLE_LISTITEM_MARKER, name: "1. ", children: [] },
+ { role: ROLE_TEXT_LEAF, children: [] },
+ ],
+ },
+ ],
+ });
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_treeupdate_listener.js b/accessible/tests/browser/e10s/browser_treeupdate_listener.js
new file mode 100644
index 0000000000..35baf28667
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_treeupdate_listener.js
@@ -0,0 +1,38 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/role.js */
+loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
+
+addAccessibleTask(
+ '<span id="parent"><span id="child"></span></span>',
+ async function(browser, accDoc) {
+ is(
+ findAccessibleChildByID(accDoc, "parent"),
+ null,
+ "Check that parent is not accessible."
+ );
+ is(
+ findAccessibleChildByID(accDoc, "child"),
+ null,
+ "Check that child is not accessible."
+ );
+
+ let onReorder = waitForEvent(EVENT_REORDER, matchContentDoc);
+ // Add an event listener to parent.
+ await invokeContentTask(browser, [], () => {
+ content.window.dummyListener = () => {};
+ content.document
+ .getElementById("parent")
+ .addEventListener("click", content.window.dummyListener);
+ });
+ await onReorder;
+
+ let tree = { TEXT: [] };
+ testAccessibleTree(findAccessibleChildByID(accDoc, "parent"), tree);
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_treeupdate_optgroup.js b/accessible/tests/browser/e10s/browser_treeupdate_optgroup.js
new file mode 100644
index 0000000000..15fed8112d
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_treeupdate_optgroup.js
@@ -0,0 +1,103 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/role.js */
+loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
+
+addAccessibleTask(
+ '<select id="select"></select>',
+ async function(browser, accDoc) {
+ let select = findAccessibleChildByID(accDoc, "select");
+
+ let onEvent = waitForEvent(EVENT_REORDER, "select");
+ // Create a combobox with grouping and 2 standalone options
+ await invokeContentTask(browser, [], () => {
+ let doc = content.document;
+ let contentSelect = doc.getElementById("select");
+ let optGroup = doc.createElement("optgroup");
+
+ for (let i = 0; i < 2; i++) {
+ let opt = doc.createElement("option");
+ opt.value = i;
+ opt.text = "Option: Value " + i;
+ optGroup.appendChild(opt);
+ }
+ contentSelect.add(optGroup, null);
+
+ for (let i = 0; i < 2; i++) {
+ let opt = doc.createElement("option");
+ contentSelect.add(opt, null);
+ }
+ contentSelect.firstChild.firstChild.id = "option1Node";
+ });
+ let event = await onEvent;
+ let option1Node = findAccessibleChildByID(event.accessible, "option1Node");
+
+ let tree = {
+ COMBOBOX: [
+ {
+ COMBOBOX_LIST: [
+ {
+ GROUPING: [
+ { COMBOBOX_OPTION: [{ TEXT_LEAF: [] }] },
+ { COMBOBOX_OPTION: [{ TEXT_LEAF: [] }] },
+ ],
+ },
+ {
+ COMBOBOX_OPTION: [],
+ },
+ {
+ COMBOBOX_OPTION: [],
+ },
+ ],
+ },
+ ],
+ };
+ testAccessibleTree(select, tree);
+ ok(!isDefunct(option1Node), "option shouldn't be defunct");
+
+ onEvent = waitForEvent(EVENT_REORDER, "select");
+ // Remove grouping from combobox
+ await invokeContentTask(browser, [], () => {
+ let contentSelect = content.document.getElementById("select");
+ contentSelect.firstChild.remove();
+ });
+ await onEvent;
+
+ tree = {
+ COMBOBOX: [
+ {
+ COMBOBOX_LIST: [{ COMBOBOX_OPTION: [] }, { COMBOBOX_OPTION: [] }],
+ },
+ ],
+ };
+ testAccessibleTree(select, tree);
+ ok(
+ isDefunct(option1Node),
+ "removed option shouldn't be accessible anymore!"
+ );
+
+ onEvent = waitForEvent(EVENT_REORDER, "select");
+ // Remove all options from combobox
+ await invokeContentTask(browser, [], () => {
+ let contentSelect = content.document.getElementById("select");
+ while (contentSelect.length) {
+ contentSelect.remove(0);
+ }
+ });
+ await onEvent;
+
+ tree = {
+ COMBOBOX: [
+ {
+ COMBOBOX_LIST: [],
+ },
+ ],
+ };
+ testAccessibleTree(select, tree);
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_treeupdate_removal.js b/accessible/tests/browser/e10s/browser_treeupdate_removal.js
new file mode 100644
index 0000000000..eb791525b3
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_treeupdate_removal.js
@@ -0,0 +1,58 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/role.js */
+loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
+
+addAccessibleTask(
+ "e10s/doc_treeupdate_removal.xhtml",
+ async function(browser, accDoc) {
+ ok(
+ isAccessible(findAccessibleChildByID(accDoc, "the_table")),
+ "table should be accessible"
+ );
+
+ // Move the_table element into hidden subtree.
+ let onReorder = waitForEvent(EVENT_REORDER, matchContentDoc);
+ await invokeContentTask(browser, [], () => {
+ content.document
+ .getElementById("the_displaynone")
+ .appendChild(content.document.getElementById("the_table"));
+ });
+ await onReorder;
+
+ ok(
+ !isAccessible(findAccessibleChildByID(accDoc, "the_table")),
+ "table in display none tree shouldn't be accessible"
+ );
+ ok(
+ !isAccessible(findAccessibleChildByID(accDoc, "the_row")),
+ "row shouldn't be accessible"
+ );
+
+ // Remove the_row element (since it did not have accessible, no event needed).
+ await invokeContentTask(browser, [], () => {
+ content.document.body.removeChild(
+ content.document.getElementById("the_row")
+ );
+ });
+
+ // make sure no accessibles have stuck around.
+ ok(
+ !isAccessible(findAccessibleChildByID(accDoc, "the_row")),
+ "row shouldn't be accessible"
+ );
+ ok(
+ !isAccessible(findAccessibleChildByID(accDoc, "the_table")),
+ "table shouldn't be accessible"
+ );
+ ok(
+ !isAccessible(findAccessibleChildByID(accDoc, "the_displayNone")),
+ "display none things shouldn't be accessible"
+ );
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_treeupdate_select_dropdown.js b/accessible/tests/browser/e10s/browser_treeupdate_select_dropdown.js
new file mode 100644
index 0000000000..add454ceac
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_treeupdate_select_dropdown.js
@@ -0,0 +1,77 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/role.js */
+loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
+
+const snippet = `
+<select id="select">
+ <option>o1</option>
+ <optgroup label="g1">
+ <option>g1o1</option>
+ <option>g1o2</option>
+ </optgroup>
+ <optgroup label="g2">
+ <option>g2o1</option>
+ <option>g2o2</option>
+ </optgroup>
+ <option>o2</option>
+</select>
+`;
+
+addAccessibleTask(
+ snippet,
+ async function(browser, accDoc) {
+ await invokeFocus(browser, "select");
+ // Expand the select. A dropdown item should get focus.
+ // Note that the dropdown is rendered in the parent process.
+ let focused = waitForEvent(
+ EVENT_FOCUS,
+ event => event.accessible.role == ROLE_COMBOBOX_OPTION,
+ "Dropdown item focused after select expanded"
+ );
+ await invokeContentTask(browser, [], () => {
+ const { ContentTaskUtils } = ChromeUtils.import(
+ "resource://testing-common/ContentTaskUtils.jsm"
+ );
+ const EventUtils = ContentTaskUtils.getEventUtils(content);
+ EventUtils.synthesizeKey("VK_DOWN", { altKey: true }, content);
+ });
+ let event = await focused;
+ let dropdown = event.accessible.parent;
+
+ let selectedOptionChildren = [];
+ if (MAC) {
+ // Checkmark is part of the Mac menu styling.
+ selectedOptionChildren = [{ STATICTEXT: [] }];
+ }
+ let tree = {
+ COMBOBOX_LIST: [
+ { COMBOBOX_OPTION: selectedOptionChildren },
+ { GROUPING: [{ COMBOBOX_OPTION: [] }, { COMBOBOX_OPTION: [] }] },
+ { GROUPING: [{ COMBOBOX_OPTION: [] }, { COMBOBOX_OPTION: [] }] },
+ { COMBOBOX_OPTION: [] },
+ ],
+ };
+ testAccessibleTree(dropdown, tree);
+
+ // Collapse the select. Focus should return to the select.
+ focused = waitForEvent(
+ EVENT_FOCUS,
+ "select",
+ "select focused after collapsed"
+ );
+ await invokeContentTask(browser, [], () => {
+ const { ContentTaskUtils } = ChromeUtils.import(
+ "resource://testing-common/ContentTaskUtils.jsm"
+ );
+ const EventUtils = ContentTaskUtils.getEventUtils(content);
+ EventUtils.synthesizeKey("VK_ESCAPE", {}, content);
+ });
+ await focused;
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_treeupdate_table.js b/accessible/tests/browser/e10s/browser_treeupdate_table.js
new file mode 100644
index 0000000000..5c2903225a
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_treeupdate_table.js
@@ -0,0 +1,48 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/role.js */
+loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
+
+addAccessibleTask(
+ `
+ <table id="table">
+ <tr>
+ <td>cell1</td>
+ <td>cell2</td>
+ </tr>
+ </table>`,
+ async function(browser, accDoc) {
+ let table = findAccessibleChildByID(accDoc, "table");
+
+ let tree = {
+ TABLE: [
+ { ROW: [{ CELL: [{ TEXT_LEAF: [] }] }, { CELL: [{ TEXT_LEAF: [] }] }] },
+ ],
+ };
+ testAccessibleTree(table, tree);
+
+ let onReorder = waitForEvent(EVENT_REORDER, "table");
+ await invokeContentTask(browser, [], () => {
+ // append a caption, it should appear as a first element in the
+ // accessible tree.
+ let doc = content.document;
+ let caption = doc.createElement("caption");
+ caption.textContent = "table caption";
+ doc.getElementById("table").appendChild(caption);
+ });
+ await onReorder;
+
+ tree = {
+ TABLE: [
+ { CAPTION: [{ TEXT_LEAF: [] }] },
+ { ROW: [{ CELL: [{ TEXT_LEAF: [] }] }, { CELL: [{ TEXT_LEAF: [] }] }] },
+ ],
+ };
+ testAccessibleTree(table, tree);
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_treeupdate_textleaf.js b/accessible/tests/browser/e10s/browser_treeupdate_textleaf.js
new file mode 100644
index 0000000000..6f89105b86
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_treeupdate_textleaf.js
@@ -0,0 +1,38 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/role.js */
+loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
+
+async function removeTextData(browser, accessible, id, role) {
+ let tree = {
+ role,
+ children: [{ role: ROLE_TEXT_LEAF, name: "text" }],
+ };
+ testAccessibleTree(accessible, tree);
+
+ let onReorder = waitForEvent(EVENT_REORDER, id);
+ await invokeContentTask(browser, [id], contentId => {
+ content.document.getElementById(contentId).firstChild.textContent = "";
+ });
+ await onReorder;
+
+ tree = { role, children: [] };
+ testAccessibleTree(accessible, tree);
+}
+
+addAccessibleTask(
+ `
+ <p id="p">text</p>
+ <pre id="pre">text</pre>`,
+ async function(browser, accDoc) {
+ let p = findAccessibleChildByID(accDoc, "p");
+ let pre = findAccessibleChildByID(accDoc, "pre");
+ await removeTextData(browser, p, "p", ROLE_PARAGRAPH);
+ await removeTextData(browser, pre, "pre", ROLE_TEXT_CONTAINER);
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_treeupdate_visibility.js b/accessible/tests/browser/e10s/browser_treeupdate_visibility.js
new file mode 100644
index 0000000000..4583056586
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_treeupdate_visibility.js
@@ -0,0 +1,342 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/role.js */
+loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
+
+async function testTreeOnHide(browser, accDoc, containerID, id, before, after) {
+ let acc = findAccessibleChildByID(accDoc, containerID);
+ testAccessibleTree(acc, before);
+
+ let onReorder = waitForEvent(EVENT_REORDER, containerID);
+ await invokeSetStyle(browser, id, "visibility", "hidden");
+ await onReorder;
+
+ testAccessibleTree(acc, after);
+}
+
+async function test3(browser, accessible) {
+ let tree = {
+ SECTION: [
+ // container
+ {
+ SECTION: [
+ // parent
+ {
+ SECTION: [
+ // child
+ { TEXT_LEAF: [] },
+ ],
+ },
+ ],
+ },
+ {
+ SECTION: [
+ // parent2
+ {
+ SECTION: [
+ // child2
+ { TEXT_LEAF: [] },
+ ],
+ },
+ ],
+ },
+ ],
+ };
+ testAccessibleTree(accessible, tree);
+
+ let onReorder = waitForEvent(EVENT_REORDER, "t3_container");
+ await invokeContentTask(browser, [], () => {
+ let doc = content.document;
+ doc.getElementById("t3_container").style.color = "red";
+ doc.getElementById("t3_parent").style.visibility = "hidden";
+ doc.getElementById("t3_parent2").style.visibility = "hidden";
+ });
+ await onReorder;
+
+ tree = {
+ SECTION: [
+ // container
+ {
+ SECTION: [
+ // child
+ { TEXT_LEAF: [] },
+ ],
+ },
+ {
+ SECTION: [
+ // child2
+ { TEXT_LEAF: [] },
+ ],
+ },
+ ],
+ };
+ testAccessibleTree(accessible, tree);
+}
+
+async function test4(browser, accessible) {
+ let tree = {
+ SECTION: [{ TABLE: [{ ROW: [{ CELL: [] }] }] }],
+ };
+ testAccessibleTree(accessible, tree);
+
+ let onReorder = waitForEvent(EVENT_REORDER, "t4_parent");
+ await invokeContentTask(browser, [], () => {
+ let doc = content.document;
+ doc.getElementById("t4_container").style.color = "red";
+ doc.getElementById("t4_child").style.visibility = "visible";
+ });
+ await onReorder;
+
+ tree = {
+ SECTION: [
+ {
+ TABLE: [
+ {
+ ROW: [
+ {
+ CELL: [
+ {
+ SECTION: [
+ {
+ TEXT_LEAF: [],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ };
+ testAccessibleTree(accessible, tree);
+}
+
+addAccessibleTask(
+ "e10s/doc_treeupdate_visibility.html",
+ async function(browser, accDoc) {
+ let t3Container = findAccessibleChildByID(accDoc, "t3_container");
+ let t4Container = findAccessibleChildByID(accDoc, "t4_container");
+
+ await testTreeOnHide(
+ browser,
+ accDoc,
+ "t1_container",
+ "t1_parent",
+ {
+ SECTION: [
+ {
+ SECTION: [
+ {
+ SECTION: [{ TEXT_LEAF: [] }],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ SECTION: [
+ {
+ SECTION: [{ TEXT_LEAF: [] }],
+ },
+ ],
+ }
+ );
+
+ await testTreeOnHide(
+ browser,
+ accDoc,
+ "t2_container",
+ "t2_grandparent",
+ {
+ SECTION: [
+ {
+ // container
+ SECTION: [
+ {
+ // grand parent
+ SECTION: [
+ {
+ SECTION: [
+ {
+ // child
+ TEXT_LEAF: [],
+ },
+ ],
+ },
+ {
+ SECTION: [
+ {
+ // child2
+ TEXT_LEAF: [],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ SECTION: [
+ {
+ // container
+ SECTION: [
+ {
+ // child
+ TEXT_LEAF: [],
+ },
+ ],
+ },
+ {
+ SECTION: [
+ {
+ // child2
+ TEXT_LEAF: [],
+ },
+ ],
+ },
+ ],
+ }
+ );
+
+ await test3(browser, t3Container);
+ await test4(browser, t4Container);
+
+ await testTreeOnHide(
+ browser,
+ accDoc,
+ "t5_container",
+ "t5_subcontainer",
+ {
+ SECTION: [
+ {
+ // container
+ SECTION: [
+ {
+ // subcontainer
+ TABLE: [
+ {
+ ROW: [
+ {
+ CELL: [
+ {
+ SECTION: [
+ {
+ // child
+ TEXT_LEAF: [],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ SECTION: [
+ {
+ // container
+ SECTION: [
+ {
+ // child
+ TEXT_LEAF: [],
+ },
+ ],
+ },
+ ],
+ }
+ );
+
+ await testTreeOnHide(
+ browser,
+ accDoc,
+ "t6_container",
+ "t6_subcontainer",
+ {
+ SECTION: [
+ {
+ // container
+ SECTION: [
+ {
+ // subcontainer
+ TABLE: [
+ {
+ ROW: [
+ {
+ CELL: [
+ {
+ TABLE: [
+ {
+ // nested table
+ ROW: [
+ {
+ CELL: [
+ {
+ SECTION: [
+ {
+ // child
+ TEXT_LEAF: [],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ SECTION: [
+ {
+ // child2
+ TEXT_LEAF: [],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ SECTION: [
+ {
+ // container
+ SECTION: [
+ {
+ // child
+ TEXT_LEAF: [],
+ },
+ ],
+ },
+ {
+ SECTION: [
+ {
+ // child2
+ TEXT_LEAF: [],
+ },
+ ],
+ },
+ ],
+ }
+ );
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/browser_treeupdate_whitespace.js b/accessible/tests/browser/e10s/browser_treeupdate_whitespace.js
new file mode 100644
index 0000000000..7f7e4ba97d
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_treeupdate_whitespace.js
@@ -0,0 +1,68 @@
+/* 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";
+
+/* import-globals-from ../../mochitest/role.js */
+loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
+
+addAccessibleTask(
+ "e10s/doc_treeupdate_whitespace.html",
+ async function(browser, accDoc) {
+ let container1 = findAccessibleChildByID(accDoc, "container1");
+ let container2Parent = findAccessibleChildByID(accDoc, "container2-parent");
+
+ let tree = {
+ SECTION: [
+ { GRAPHIC: [] },
+ { TEXT_LEAF: [] },
+ { GRAPHIC: [] },
+ { TEXT_LEAF: [] },
+ { GRAPHIC: [] },
+ ],
+ };
+ testAccessibleTree(container1, tree);
+
+ let onReorder = waitForEvent(EVENT_REORDER, "container1");
+ // Remove img1 from container1
+ await invokeContentTask(browser, [], () => {
+ let doc = content.document;
+ doc.getElementById("container1").removeChild(doc.getElementById("img1"));
+ });
+ await onReorder;
+
+ tree = {
+ SECTION: [{ GRAPHIC: [] }, { TEXT_LEAF: [] }, { GRAPHIC: [] }],
+ };
+ testAccessibleTree(container1, tree);
+
+ tree = {
+ SECTION: [{ LINK: [] }, { LINK: [{ GRAPHIC: [] }] }],
+ };
+ testAccessibleTree(container2Parent, tree);
+
+ onReorder = waitForEvent(EVENT_REORDER, "container2-parent");
+ // Append an img with valid src to container2
+ await invokeContentTask(browser, [], () => {
+ let doc = content.document;
+ let img = doc.createElement("img");
+ img.setAttribute(
+ "src",
+ "http://example.com/a11y/accessible/tests/mochitest/moz.png"
+ );
+ doc.getElementById("container2").appendChild(img);
+ });
+ await onReorder;
+
+ tree = {
+ SECTION: [
+ { LINK: [{ GRAPHIC: [] }] },
+ { TEXT_LEAF: [] },
+ { LINK: [{ GRAPHIC: [] }] },
+ ],
+ };
+ testAccessibleTree(container2Parent, tree);
+ },
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/e10s/doc_treeupdate_ariadialog.html b/accessible/tests/browser/e10s/doc_treeupdate_ariadialog.html
new file mode 100644
index 0000000000..9d08854b9a
--- /dev/null
+++ b/accessible/tests/browser/e10s/doc_treeupdate_ariadialog.html
@@ -0,0 +1,23 @@
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>Tree Update ARIA Dialog Test</title>
+ </head>
+ <body id="body">
+ <div id="dialog" role="dialog" style="display: none;">
+ <table id="table" role="presentation"
+ style="display: block; position: fixed; top: 88px; left: 312.5px; z-index: 10010;">
+ <tbody>
+ <tr>
+ <td role="presentation">
+ <div role="presentation">
+ <a id="a" role="button">text</a>
+ </div>
+ <input id="input">
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </body>
+</html>
diff --git a/accessible/tests/browser/e10s/doc_treeupdate_ariaowns.html b/accessible/tests/browser/e10s/doc_treeupdate_ariaowns.html
new file mode 100644
index 0000000000..38b5c333a1
--- /dev/null
+++ b/accessible/tests/browser/e10s/doc_treeupdate_ariaowns.html
@@ -0,0 +1,44 @@
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>Tree Update ARIA Owns Test</title>
+ </head>
+ <body id="body">
+ <div id="t1_container" aria-owns="t1_checkbox t1_button">
+ <div role="button" id="t1_button"></div>
+ <div role="checkbox" id="t1_checkbox">
+ <span id="t1_span">
+ <div id="t1_subdiv"></div>
+ </span>
+ </div>
+ </div>
+ <div id="t1_group" role="group"></div>
+ <div id="t1_grouptmp" role="group"></div>
+
+ <div id="t2_container1" aria-owns="t2_owned"></div>
+ <div id="t2_container2">
+ <div id="t2_container3"><div id="t2_owned" role="checkbox"></div></div>
+ </div>
+
+ <div id="t3_container1" aria-owns="t3_child"></div>
+ <div id="t3_child" role="checkbox"></div>
+ <div id="t3_container2"></div>
+
+ <div id="t4_container1" aria-owns="t4_child1 t4_child2"></div>
+ <div id="t4_container2">
+ <div id="t4_child1" style="display:none" role="checkbox"></div>
+ <div id="t4_child2" role="radio"></div>
+ </div>
+
+ <div id="t5_container">
+ <div role="button" id="t5_button"></div>
+ <div role="checkbox" id="t5_checkbox"></div>
+ <div role="radio" id="t5_radio"></div>
+ </div>
+
+ <div id="t6_container" aria-owns="t6_fake">
+ <span id="t6_span">hey</span>
+ </div>
+ <div id="t6_fake" role="group"></div>
+ </body>
+</html>
diff --git a/accessible/tests/browser/e10s/doc_treeupdate_imagemap.html b/accessible/tests/browser/e10s/doc_treeupdate_imagemap.html
new file mode 100644
index 0000000000..4dd230fc28
--- /dev/null
+++ b/accessible/tests/browser/e10s/doc_treeupdate_imagemap.html
@@ -0,0 +1,21 @@
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>Tree Update Imagemap Test</title>
+ </head>
+ <body id="body">
+ <map name="atoz_map" id="map">
+ <area href="http://www.bbc.co.uk/radio4/atoz/index.shtml#b"
+ coords="17,0,30,14" alt="b" shape="rect">
+ </map>
+
+ <div id="container">
+ <img id="imgmap" width="447" height="15"
+ usemap="#atoz_map"
+ src="http://example.com/a11y/accessible/tests/mochitest/letters.gif"><!--
+ Important: no whitespace between the <img> and the </div>, so we
+ don't end up with textframes there, because those would be reflected
+ in our accessible tree in some cases.
+ --></div>
+ </body>
+</html>
diff --git a/accessible/tests/browser/e10s/doc_treeupdate_removal.xhtml b/accessible/tests/browser/e10s/doc_treeupdate_removal.xhtml
new file mode 100644
index 0000000000..9c59fb9d11
--- /dev/null
+++ b/accessible/tests/browser/e10s/doc_treeupdate_removal.xhtml
@@ -0,0 +1,11 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta charset="utf-8"/>
+ <title>Tree Update Removal Test</title>
+ </head>
+ <body id="body">
+ <div id="the_displaynone" style="display: none;"></div>
+ <table id="the_table"></table>
+ <tr id="the_row"></tr>
+ </body>
+</html>
diff --git a/accessible/tests/browser/e10s/doc_treeupdate_visibility.html b/accessible/tests/browser/e10s/doc_treeupdate_visibility.html
new file mode 100644
index 0000000000..00213b2b70
--- /dev/null
+++ b/accessible/tests/browser/e10s/doc_treeupdate_visibility.html
@@ -0,0 +1,78 @@
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>Tree Update Visibility Test</title>
+ </head>
+ <body id="body">
+ <!-- hide parent while child stays visible -->
+ <div id="t1_container">
+ <div id="t1_parent">
+ <div id="t1_child" style="visibility: visible">text</div>
+ </div>
+ </div>
+
+ <!-- hide grandparent while its children stay visible -->
+ <div id="t2_container">
+ <div id="t2_grandparent">
+ <div id="t2_parent">
+ <div id="t2_child" style="visibility: visible">text</div>
+ <div id="t2_child2" style="visibility: visible">text</div>
+ </div>
+ </div>
+ </div>
+
+ <!-- change container style, hide parents while their children stay visible -->
+ <div id="t3_container">
+ <div id="t3_parent">
+ <div id="t3_child" style="visibility: visible">text</div>
+ </div>
+ <div id="t3_parent2">
+ <div id="t3_child2" style="visibility: visible">text</div>
+ </div>
+ </div>
+
+ <!-- change container style, show child inside the table -->
+ <div id="t4_container">
+ <table>
+ <tr>
+ <td id="t4_parent">
+ <div id="t4_child" style="visibility: hidden;">text</div>
+ </td>
+ </tr>
+ </table>
+ </div>
+
+ <!-- hide subcontainer while child inside the table stays visible -->
+ <div id="t5_container">
+ <div id="t5_subcontainer">
+ <table>
+ <tr>
+ <td>
+ <div id="t5_child" style="visibility: visible;">text</div>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </div>
+
+ <!-- hide subcontainer while its child and child inside the nested table stays visible -->
+ <div id="t6_container">
+ <div id="t6_subcontainer">
+ <table>
+ <tr>
+ <td>
+ <table>
+ <tr>
+ <td>
+ <div id="t6_child" style="visibility: visible;">text</div>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ <div id="t6_child2" style="visibility: visible">text</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/accessible/tests/browser/e10s/doc_treeupdate_whitespace.html b/accessible/tests/browser/e10s/doc_treeupdate_whitespace.html
new file mode 100644
index 0000000000..f17dbbd60e
--- /dev/null
+++ b/accessible/tests/browser/e10s/doc_treeupdate_whitespace.html
@@ -0,0 +1,10 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta charset="utf-8"/>
+ <title>Whitespace text accessible creation/destruction</title>
+ </head>
+ <body id="body">
+ <div id="container1"> <img src="http://example.com/a11y/accessible/tests/mochitest/moz.png"> <img id="img1" src="http://example.com/a11y/accessible/tests/mochitest/moz.png"> <img src="http://example.com/a11y/accessible/tests/mochitest/moz.png"> </div>
+ <div id="container2-parent"> <a id="container2"></a> <a><img src="http://example.com/a11y/accessible/tests/mochitest/moz.png"></a> </div>
+ </body>
+</html>
diff --git a/accessible/tests/browser/e10s/head.js b/accessible/tests/browser/e10s/head.js
new file mode 100644
index 0000000000..672aa46171
--- /dev/null
+++ b/accessible/tests/browser/e10s/head.js
@@ -0,0 +1,19 @@
+/* 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.
+/* import-globals-from ../shared-head.js */
+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 }
+);