Merge old head via |hg debugsetparents d519209bdd0a4dd4c4a74f0a9097851d949eb25f 90025483ae5ab1c0f750346ce8cc0cf439b5b9b8|. CLOSED TREE DONTBUILD a=release
authorffxbld <release@mozilla.com>
Thu, 14 Sep 2017 17:57:19 +0200
changeset 666717 f8a47ef374a54472607aa7adcc59d484989c150d
parent 665292 d519209bdd0a4dd4c4a74f0a9097851d949eb25f (diff)
parent 666716 90025483ae5ab1c0f750346ce8cc0cf439b5b9b8 (current diff)
child 666718 04b633f01c6fe7854136e5b17ee735087855e804
push id80488
push userbmo:mkelly@mozilla.com
push dateTue, 19 Sep 2017 04:42:30 +0000
reviewersrelease
milestone56.0
Merge old head via |hg debugsetparents d519209bdd0a4dd4c4a74f0a9097851d949eb25f 90025483ae5ab1c0f750346ce8cc0cf439b5b9b8|. CLOSED TREE DONTBUILD a=release
--- a/.clang-format-ignore
+++ b/.clang-format-ignore
@@ -7,42 +7,39 @@
 ^widget/android/GeneratedJNIWrappers.h
 ^widget/android/fennec/FennecJNINatives.h
 ^widget/android/fennec/FennecJNIWrappers.cpp
 ^widget/android/fennec/FennecJNIWrappers.h
 
 # Generated from ./tools/rewriting/ThirdPartyPaths.txt
 # awk '{print "^"$1".*"}' ./tools/rewriting/ThirdPartyPaths.txt
 ^browser/components/translation/cld2/.*
-^build/stlport/.*
 ^db/sqlite3/src/.*
 ^dom/media/platforms/ffmpeg/libav.*
 ^extensions/spellcheck/hunspell/src/.*
-^gfx/2d/convolver.*
-^gfx/2d/image_operations.*
 ^gfx/angle/.*
 ^gfx/cairo/.*
 ^gfx/graphite2/.*
 ^gfx/harfbuzz/.*
 ^gfx/ots/.*
 ^gfx/qcms/.*
 ^gfx/skia/.*
 ^gfx/vr/openvr/.*
 ^gfx/webrender.*
-^gfx/webrender_traits.*
+^gfx/webrender_api.*
 ^gfx/ycbcr/.*
 ^intl/hyphenation/hyphen/.*
 ^intl/icu/.*
 ^ipc/chromium/.*
 ^js/src/ctypes/libffi/.*
 ^js/src/dtoa.c.*
 ^js/src/jit/arm64/vixl/.*
+^media/ffvpx/.*
 ^media/gmp-clearkey/0.1/openaes/.*
 ^media/kiss_fft/.*
-^media/ffvpx/.*
 ^media/libav/.*
 ^media/libcubeb/.*
 ^media/libjpeg/.*
 ^media/libmkv/.*
 ^media/libnestegg/.*
 ^media/libogg/.*
 ^media/libopus/.*
 ^media/libpng/.*
@@ -53,30 +50,53 @@
 ^media/libtremor/.*
 ^media/libvorbis/.*
 ^media/libvpx/.*
 ^media/libyuv/.*
 ^media/mtransport/third_party/.*
 ^media/openmax_dl/.*
 ^media/pocketsphinx/.*
 ^media/sphinxbase/.*
+^media/webrtc/signaling/src/sdp/sipcc/.*
 ^media/webrtc/trunk/.*
-^media/webrtc/signaling/src/sdp/sipcc/.*
 ^mfbt/decimal/.*
 ^mfbt/double-conversion/source/.*
 ^mfbt/lz4.*
+^mobile/android/geckoview/src/thirdparty/.*
 ^mobile/android/thirdparty/.*
 ^modules/brotli/.*
 ^modules/fdlibm/.*
 ^modules/freetype2/.*
 ^modules/libbz2/.*
 ^modules/libmar/.*
+^modules/woff2/.*
 ^modules/zlib/.*
 ^netwerk/sctp/src/.*
 ^netwerk/srtp/src/.*
 ^nsprpub/.*
 ^other-licenses/.*
 ^parser/expat/.*
+^security/nss/.*
 ^security/sandbox/chromium/.*
 ^testing/gtest/gmock/.*
 ^testing/gtest/gtest/.*
+^testing/talos/talos/tests/dromaeo/.*
+^third_party/aom/.*
+^third_party/python/blessings/.*
+^third_party/python/configobj/.*
+^third_party/python/futures/.*
+^third_party/python/jsmin/.*
+^third_party/python/mock-*/.*
+^third_party/python/psutil/.*
+^third_party/python/py/.*
+^third_party/python/pyasn1/.*
+^third_party/python/pyasn1-modules/.*
+^third_party/python/PyECC/.*
+^third_party/python/pytest/.*
+^third_party/python/pytoml/.*
+^third_party/python/pyyaml/.*
+^third_party/python/redo/.*
+^third_party/python/requests/.*
+^third_party/python/rsa/.*
+^third_party/python/which/.*
+^toolkit/components/jsoncpp/.*
 ^toolkit/components/protobuf/.*
 ^toolkit/crashreporter/google-breakpad/.*
--- a/.cron.yml
+++ b/.cron.yml
@@ -2,76 +2,86 @@
 # `taskcluster/taskgraph/cron/schema.py`.  For documentation, see
 # `taskcluster/docs/cron.rst`.
 
 jobs:
     - name: nightly-desktop
       job:
           type: decision-task
           treeherder-symbol: Nd
-          target-tasks-method: nightly_linux
+          target-tasks-method: nightly_desktop
       run-on-projects:
           - mozilla-central
-          - mozilla-aurora
           - date
       when:
           by-project:
             # Match buildbot starts for now
             date: [{hour: 15, minute: 0}]
             mozilla-central: [{hour: 10, minute: 0}]
-            mozilla-aurora: [] # bug 1358976
             # No default
 
+    - name: nightly-desktop-linux
+      job:
+          type: decision-task
+          treeherder-symbol: Nd-Ln
+          target-tasks-method: nightly_linux
+      run-on-projects:
+          - mozilla-central
+          - date
+      when: [] # never (hook only)
+
     - name: nightly-desktop-osx
       job:
           type: decision-task
           treeherder-symbol: Nd-OSX
           target-tasks-method: nightly_macosx
       run-on-projects:
+          - mozilla-central
           - date
       when: [] # never (hook only)
 
-    - name: nightly-desktop-win64
+    - name: nightly-desktop-win
       job:
           type: decision-task
-          treeherder-symbol: Nd-Win64
-          target-tasks-method: nightly_win64
+          treeherder-symbol: Nd-Win
+          target-tasks-method: nightly_win
       run-on-projects:
+          - mozilla-central
           - date
       when: [] # never (hook only)
 
     - name: nightly-android
       job:
           type: decision-task
           treeherder-symbol: Na
           target-tasks-method: nightly_fennec
       run-on-projects:
           - mozilla-central
-          - mozilla-aurora
           - date
       when:
         by-project:
             # Match buildbot starts for now
             date: [{hour: 15, minute: 0}]
             mozilla-central: [{hour: 10, minute: 0}]
-            mozilla-aurora: [] # bug 1358976
             # No default
 
     - name: nightly-mochitest-valgrind
       job:
           type: decision-task
           treeherder-symbol: Vg
           target-tasks-method: mochitest_valgrind
       run-on-projects:
           - mozilla-central
       when:
           - {hour: 16, minute: 0}
           - {hour: 4, minute: 0}
 
-    - name: nightly-code-coverage
+    - name: nightly-dmd
       job:
           type: decision-task
-          treeherder-symbol: Nc
-          target-tasks-method: nightly_code_coverage
+          treeherder-symbol: Ndmd
+          target-tasks-method: nightly_dmd
       run-on-projects:
           - mozilla-central
       when:
-          - {hour: 18, minute: 0}
+          by-project:
+            mozilla-central: [{hour: 10, minute: 0}]
+            # No default
--- a/.eslintignore
+++ b/.eslintignore
@@ -3,87 +3,88 @@
 
 # Exclude expected objdirs.
 obj*/**
 
 # We ignore all these directories by default, until we get them enabled.
 # If you are enabling a directory, please add directory specific exclusions
 # below.
 addon-sdk/**
-build/**
 chrome/**
 config/**
-db/**
 docshell/**
 editor/**
 embedding/**
-extensions/**
+extensions/cookie/**
+extensions/spellcheck/**
+extensions/universalchardet/**
 gfx/**
-gradle/**
-hal/**
 image/**
 intl/**
 ipc/**
 layout/**
 media/**
 memory/**
-mfbt/**
 modules/**
-mozglue/**
 netwerk/**
-nsprpub/**
-other-licenses/**
 parser/**
-probes/**
 python/**
 rdf/**
 servo/**
-startupcache/**
 tools/update-packaging/**
 uriloader/**
 view/**
 widget/**
 xpcom/**
+
+# We currently have no js files in these directories, so we ignore them by
+# default to aid ESLint's performance.
+build/**
+db/**
+gradle/**
+hal/**
+mfbt/**
+mozglue/**
+nsprpub/**
+other-licenses/**
+probes/**
+startupcache/**
 xpfe/**
-xulrunner/**
-
-# b2g exclusions (pref files).
-b2g/app/b2g.js
-b2g/graphene/graphene.js
-b2g/locales/en-US/b2g-l10n.js
 
 # browser/ exclusions
 browser/app/**
 browser/branding/**/firefox-branding.js
-browser/base/content/test/general/file_csp_block_all_mixedcontent.html
 # Gzipped test file.
 browser/base/content/test/general/gZipOfflineChild.html
 browser/base/content/test/urlbar/file_blank_but_not_blank.html
+# New tab is likely to be replaced soon.
 browser/base/content/newtab/**
 # Test files that are really json not js, and don't need to be linted.
 browser/components/sessionstore/test/unit/data/sessionstore_valid.js
 browser/components/sessionstore/test/unit/data/sessionstore_invalid.js
-browser/components/tabview/**
 # generated & special files in cld2
 browser/components/translation/cld2/**
 # Screenshots and Follow-on search are imported as a system add-on and have
 # their own lint rules currently.
 browser/extensions/followonsearch/**
 browser/extensions/screenshots/**
 browser/extensions/pdfjs/content/build**
 browser/extensions/pdfjs/content/web**
 # generated or library files in pocket
 browser/extensions/pocket/content/panels/js/tmpl.js
 browser/extensions/pocket/content/panels/js/vendor/**
-browser/locales/**
 # generated or library files in activity-stream
 browser/extensions/activity-stream/data/content/activity-stream.bundle.js
 browser/extensions/activity-stream/vendor/**
+# The only file in browser/locales/ is pre-processed.
+browser/locales/**
 # imported from chromium
 browser/extensions/mortar/**
+# Generated data files
+browser/extensions/formautofill/phonenumberutils/PhoneNumberMetaData.jsm
 
 # devtools/ exclusions
 devtools/client/canvasdebugger/**
 devtools/client/commandline/**
 devtools/client/debugger/**
 devtools/client/framework/**
 !devtools/client/framework/devtools.js
 !devtools/client/framework/devtools-browser.js
@@ -133,19 +134,16 @@ devtools/server/tests/browser/storage-*.
 devtools/server/tests/browser/stylesheets-nested-iframes.html
 devtools/server/tests/unit/xpcshell_debugging_script.js
 devtools/shared/platform/content/test/test_clipboard.html
 devtools/shared/qrcode/tests/mochitest/test_decode.html
 devtools/shared/tests/mochitest/*.html
 devtools/shared/webconsole/test/test_*.html
 
 # Ignore devtools pre-processed files
-devtools/client/framework/toolbox-process-window.js
-devtools/client/performance/system.js
-devtools/client/webide/webide-prefs.js
 devtools/client/preferences/**
 
 # Ignore devtools third-party libs
 devtools/shared/jsbeautify/*
 devtools/shared/acorn/*
 devtools/shared/gcli/source/*
 devtools/shared/node-properties/*
 devtools/shared/pretty-fast/*
@@ -210,16 +208,17 @@ dom/imptests/**
 dom/interfaces/**
 dom/ipc/**
 dom/json/**
 dom/jsurl/**
 dom/locales/**
 dom/manifest/**
 dom/mathml/**
 dom/media/**
+!dom/media/*.js*
 dom/messagechannel/**
 dom/network/**
 dom/notification/**
 dom/offline/**
 dom/payments/**
 dom/performance/**
 dom/permission/**
 dom/plugins/**
@@ -246,69 +245,84 @@ dom/webidl/**
 dom/workers/**
 dom/worklet/**
 dom/xbl/**
 dom/xhr/**
 dom/xml/**
 dom/xslt/**
 dom/xul/**
 
+# Third-party
+dom/media/webvtt/**
+
 # Exclude everything but self-hosted JS
 js/ductwork/**
 js/examples/**
 js/ipc/**
 js/public/**
 js/xpconnect/**
 js/src/devtools/**
 js/src/octane/**
 js/src/jit-test/**
 js/src/tests/**
 js/src/Y.js
 
 # mobile/android/ exclusions
 mobile/android/tests/browser/chrome/tp5/**
 
 # Uses `#filter substitution`
-mobile/android/b2gdroid/app/b2gdroid.js
 mobile/android/app/mobile.js
 mobile/android/chrome/content/healthreport-prefs.js
 
 # Uses `#expand`
 mobile/android/chrome/content/about.js
 
 # Not much JS to lint and non-standard at that
 mobile/android/installer/
 mobile/android/locales/
 
 # Non-standard `(catch ex if ...)`
 mobile/android/chrome/content/browser.js
 mobile/android/components/Snippets.js
 
-# Bug 1178739: Ignore this file as a quick fix for "Illegal yield expression"
-mobile/android/modules/HomeProvider.jsm
-
 # security/ exclusions (pref files).
 security/manager/ssl/security-prefs.js
 
-#NSS
+# NSS / taskcluster only.
 security/nss/**
 
 # services/ exclusions
 
 # Uses `#filter substitution`
 services/sync/modules/constants.js
 services/sync/services-sync.js
 
-# testing/ exclusions
-testing/marionette/**
+# Remote protocol exclusions
+testing/marionette/test_*.js
+testing/marionette/atom.js
+testing/marionette/legacyaction.js
+testing/marionette/client
+testing/marionette/doc
+testing/marionette/harness
+
+# other testing/ exclusions
 testing/mochitest/**
-testing/modules/**
+# third party modules
+testing/modules/ajv-4.1.1.js
+testing/modules/sinon-2.3.2.js
 # octothorpe used for pref file comment causes parsing error
 testing/mozbase/mozprofile/tests/files/prefs_with_comments.js
-testing/talos/**
+testing/talos/talos/scripts/jszip.min.js
+testing/talos/talos/startup_test/sessionrestore/profile/sessionstore.js
+testing/talos/talos/startup_test/sessionrestore/profile-manywindows/sessionstore.js
+testing/talos/talos/tests/canvasmark/**
+testing/talos/talos/tests/dromaeo/**
+testing/talos/talos/tests/v8_7/**
+testing/talos/talos/tests/kraken/**
+
 testing/web-platform/**
 testing/xpcshell/moz-http2/**
 testing/xpcshell/node-http2/**
 
 # Third party services
 services/common/kinto-http-client.js
 services/common/kinto-offline-client.js
 services/sync/tps/extensions/mozmill
@@ -321,29 +335,27 @@ toolkit/components/help/**
 # Intentionally invalid JS
 toolkit/components/workerloader/tests/moduleF-syntax-error.js
 
 # Tests old non-star function generators
 toolkit/modules/tests/xpcshell/test_task.js
 
 # Not yet updated
 toolkit/components/osfile/**
+toolkit/components/url-classifier/**
 
 # External code:
 toolkit/components/microformats/test/**
 toolkit/components/microformats/microformat-shiv.js
 toolkit/components/reader/Readability.js
 toolkit/components/reader/JSDOMParser.js
 
 # Uses preprocessing
 toolkit/content/widgets/wizard.xml
 toolkit/components/jsdownloads/src/DownloadIntegration.jsm
-toolkit/components/url-classifier/**
 toolkit/components/urlformatter/nsURLFormatter.js
 toolkit/modules/AppConstants.jsm
 toolkit/mozapps/downloads/nsHelperAppDlg.js
-toolkit/mozapps/extensions/internal/AddonConstants.jsm
 toolkit/mozapps/update/tests/data/xpcshellConstantsPP.js
-toolkit/webapps/**
 
 # Third party
 toolkit/modules/third_party/**
 third_party/**
--- a/.gitignore
+++ b/.gitignore
@@ -57,16 +57,18 @@ parser/html/java/javaparser/
 # Ignore the files and directory that Eclipse IDE creates
 .project
 .cproject
 .settings/
 
 # Ignore the files and directory that JetBrains IDEs create.
 /.idea/
 *.iml
+# Android Monitor in Android Studio creates a captures/ directory.
+/captures/
 
 # Gradle cache.
 /.gradle/
 
 # Local Gradle configuration properties.
 /local.properties
 
 # Python virtualenv artifacts.
--- a/.hgignore
+++ b/.hgignore
@@ -59,16 +59,18 @@
 # Ignore the files and directory that Eclipse IDE creates
 \.project$
 \.cproject$
 \.settings/
 
 # Ignore the files and directory that JetBrains IDEs create.
 \.idea/
 \.iml$
+# Android Monitor in Android Studio creates a captures/ directory.
+^captures/
 
 # Gradle cache.
 ^.gradle/
 
 # Local Gradle configuration properties.
 ^local.properties$
 
 # Python stuff installed at build time.
@@ -115,16 +117,17 @@ GPATH
 ^testing/mozharness/.coverage
 ^testing/mozharness/nosetests.xml
 
 # Ignore tox generated dir
 .tox/
 
 # Ignore ESLint node_modules
 ^node_modules/
+^tools/lint/eslint/eslint-plugin-mozilla/node_modules/
 
 # Ignore talos virtualenv and tp5n files.
 # The tp5n set is supposed to be decompressed at
 # testing/talos/talos/tests/tp5n in order to run tests like tps
 # locally. Similarly, running talos requires a Python package virtual
 # environment. Both the virtual environment and tp5n files end up littering
 # the status command, so we ignore them.
 ^testing/talos/.Python
--- a/.hgtags
+++ b/.hgtags
@@ -183,68 +183,60 @@ fc98815acf5f041c6269fd256a68af8a92ba222a
 b95583c8e7e7a7ce629b4d4551747e818367d0a0 FIREFOX_RELEASE_37_END
 f33925facceefe32f6347faed2d805551d82e60b FIREFOX_RELEASE_38_END
 9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 1b6bf6612c0f4d4fee81d18bf18016e692f874e1 FIREFOX_AURORA_39_BASE
 d92bf011e305a4a4ad6bb98192a53b86bd64b813 FIREFOX_AURORA_38_END
 5e851d50fb9b8d5a28e4fcd4731dd0f17e8fb4b9 FIREFOX_BETA_39_BASE
 85229fbaf01713caa9ad26c7d3afec271494113c FIREFOX_BETA_38_END
 5fecfbec2e3c934d4646a739bea60d3c93a35f9e FIREFOX_RELEASE_39_BASE
-f33925facceefe32f6347faed2d805551d82e60b FIREFOX_RELEASE_38_END
-971ab60e21d340e0407d2b9eb82fca67a4a9f1cb FIREFOX_RELEASE_38_END
 9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 66a95a483d2c77dfc387019336d18093acd6aac2 FIREFOX_AURORA_40_BASE
 eead3ccdf2d11feefc12907467cebbe07aa91ea9 FIREFOX_AURORA_39_END
 d77cf39268848f8a7e9b38082348b6cd4d1f3b5e FIREFOX_BETA_40_BASE
 0b0822cabbb95d8509852f90c0b7df5da0a4cabc FIREFOX_BETA_39_END
 34e00eb800c52e33059d37f6e41fb255b4bae6b8 FIREFOX_RELEASE_40_BASE
-ec21f96665f7d3fdd5d7944c90373938390096d7 FIREFOX_RELEASE_39_END
 9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 312c68b16549de9cea1557f461d5d234bd5e0a7d FIREFOX_AURORA_41_BASE
 9d83ab013ab61c7f6e987bf0e7cbab1a1aed1ca8 FIREFOX_AURORA_40_END
 a019592053c4d93fbbafab8d0bd709529e3746de FIREFOX_BETA_41_BASE
 f147014ff61a12480d377c8bde1f90891772540f FIREFOX_BETA_40_END
 6c0329aacb73ab0510c6f1026ef066dfaed9139c FIREFOX_RELEASE_41_BASE
-9c898cde2175e9e98b916d996ed286a9dff0c853 FIREFOX_RELEASE_40_END
 9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 7a19194812eb767bee7cdf8fc36ba9a383c1bead FIREFOX_AURORA_42_BASE
 d561dc208e61b2f2b4e82ab61710e14f56da4ddb FIREFOX_AURORA_41_END
 61bbc30704aa104e9929c719c0fd7957f96f00ea FIREFOX_BETA_42_BASE
 a5bf9cf6777519663e8e1db553727e59d3ad5681 FIREFOX_BETA_41_END
 3f2ff85b2f16c1fd161dc5ba77a5f3f2c52fd127 FIREFOX_RELEASE_42_BASE
-dc3a2ec52077a5cea772cdb267380f7debc3080b FIREFOX_RELEASE_41_END
 9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 fcef8ded82219c89298b4e376cfbdfba79a1d35a FIREFOX_AURORA_43_BASE
 b0e20ff87b175424edec414215b325918ccb4792 FIREFOX_AURORA_42_END
 41fdefd640f368bccdeafe6446d42c0a5ad22797 FIREFOX_BETA_43_BASE
 0ec8472a93ac0c7ef0e98ebb91ac780bde12d5a5 FIREFOX_BETA_42_END
 38ffeba26f3e420312e04cb3afb408f4c66a6f2e FIREFOX_RELEASE_43_BASE
-56320bc06404b926b475051ba643950bd78cf221 FIREFOX_RELEASE_42_END
 9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 67a788db9f07822cfef52351bbbe3745dff8bd7f FIREFOX_AURORA_44_BASE
 9d3bc275a924a84ab5f34df58c566af0f87479d0 FIREFOX_AURORA_43_END
 b717b80eec62a7ba9b8842487f157b68c1419edd FIREFOX_BETA_44_BASE
 366dd290472633b06f0942d7737c34e942e0916a FIREFOX_BETA_43_END
 ef3cfadfccb97588653ae06eefdac28ec447c1f6 FIREFOX_RELEASE_44_BASE
-af39a90c443c2fda798c2797e196eeb5a8b5cedd FIREFOX_RELEASE_43_END
 9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 99137d6d4061f408ae0869122649d8bdf489cc30 FIREFOX_AURORA_45_BASE
 4fbd53613240c431522521b953d5a62692909e65 FIREFOX_AURORA_44_END
 3bfa5bc61b626761d487b45c170b115259f69d6b FIREFOX_BETA_45_BASE
 6a7547e4a0f0e213bb8487c773e16543cbea8c73 FIREFOX_BETA_44_END
 3a9789adadcd0de9ee31b16a89a11985822c6a11 FENNEC_45_0b1_RELEASE
 6c0fd1f666e70f2b11f7083f9e7bf4c844a3716a FENNEC_45_0b1_RELEASE
 3a9789adadcd0de9ee31b16a89a11985822c6a11 FENNEC_45_0b1_BUILD1
 6c0fd1f666e70f2b11f7083f9e7bf4c844a3716a FENNEC_45_0b1_BUILD1
 5e1da6523e97d7f8b01004bbe33118ac784b40ea FIREFOX_45_0b1_RELEASE
 6c0fd1f666e70f2b11f7083f9e7bf4c844a3716a FIREFOX_45_0b1_RELEASE
 5e1da6523e97d7f8b01004bbe33118ac784b40ea FIREFOX_45_0b1_BUILD1
 6c0fd1f666e70f2b11f7083f9e7bf4c844a3716a FIREFOX_45_0b1_BUILD1
 bbe048ab30ad3321a6505697703e5fee20e91343 FIREFOX_RELEASE_45_BASE
-5fe8de3ca9bbf8bc18259c3490aca55c97e31979 FIREFOX_RELEASE_44_END
 9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 67c66c2878aed17ae3096d7db483ddbb2293c503 FIREFOX_AURORA_46_BASE
 d82221ba4219e4ac04ecfe2a5301703411e176fa FIREFOX_AURORA_45_END
 89effb961712d4a5f84e90bcdd4e421ed6645eea FIREFOX_BETA_46_BASE
 78fe98c670fcc9a1548ac655ae9a488d940fd9c8 FIREFOX_BETA_45_END
 fb3494d06dfb73e26df72ca7a4bc4ef5ebf8795c FIREFOX_46_0b1_RELEASE
 5904e3eb711dd263a6d2deb63b14e0c44e577054 FIREFOX_46_0b2_BUILD3
 5904e3eb711dd263a6d2deb63b14e0c44e577054 FIREFOX_46_0b2_RELEASE
@@ -258,21 +250,16 @@ 191f5eb4cbd72590277296cdb90d355adb347d45
 191f5eb4cbd72590277296cdb90d355adb347d45 FIREFOX_46_0b7_RELEASE
 0334bcac4033f4f163476677165acd406e08fed8 FIREFOX_46_0b8_BUILD1
 0334bcac4033f4f163476677165acd406e08fed8 FIREFOX_46_0b8_RELEASE
 b007110e90053e58946b59765605bfca766c30d1 FIREFOX_46_0b9_BUILD1
 b007110e90053e58946b59765605bfca766c30d1 FIREFOX_46_0b9_RELEASE
 9ea83990839bd513869018e57bcbedb3454b63bb FIREFOX_46_0b10_BUILD1
 9ea83990839bd513869018e57bcbedb3454b63bb FIREFOX_46_0b10_RELEASE
 6c4646c7a6d6506e744c92a8170310191904c98e FIREFOX_RELEASE_46_BASE
-64b6b8afb34bf8a4416b1d167b48177d0e30bde9 FIREFOX_RELEASE_45_END
-078baf501b55eaa47f3b189fda4dd28dae1fa257 FIREFOX_46_0_BUILD5
-078baf501b55eaa47f3b189fda4dd28dae1fa257 FIREFOX_46_0_RELEASE
-0b8492c110bec959b94e3d54d5bd5ca7f7f97f6c FIREFOX_46_0_1_BUILD1
-0b8492c110bec959b94e3d54d5bd5ca7f7f97f6c FIREFOX_46_0_1_RELEASE
 076bf6a0ac85ec6a4f3ee7c3efe653964d92b9f2 FIREFOX_46_0b11_BUILD1
 076bf6a0ac85ec6a4f3ee7c3efe653964d92b9f2 FIREFOX_46_0b11_RELEASE
 9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 68d3781deda0d4d58ec9877862830db89669b3a5 FIREFOX_AURORA_47_BASE
 43d92f7052e7bab870c9b994d4b0a0f42d26b7a7 FIREFOX_AURORA_46_END
 8551b253f4061db31e4be7829c2f70c2610caf42 FIREFOX_BETA_47_BASE
 a2290938ee6cf794896a9347980bcb00ebb24c68 FIREFOX_BETA_46_END
 5bbf2e7c2fc6ff9010b1948e2f11477f48ee36e2 FIREFOX_47_0b1_BUILD2
@@ -289,21 +276,16 @@ 7d1f3450acc47025876964c1eca854ae027934f3
 7d1f3450acc47025876964c1eca854ae027934f3 FIREFOX_47_0b6_RELEASE
 0723a0212f5e0b30d7532d4e35eba7759fb54507 FIREFOX_47_0b7_BUILD1
 0723a0212f5e0b30d7532d4e35eba7759fb54507 FIREFOX_47_0b7_RELEASE
 cb27eacbe04abc5f91a0379c23617715aab432ec FIREFOX_47_0b8_BUILD1
 cb27eacbe04abc5f91a0379c23617715aab432ec FIREFOX_47_0b8_RELEASE
 2ee4473c729acb2ba7dc723e7affe79ce14bff85 FIREFOX_47_0b9_BUILD1
 2ee4473c729acb2ba7dc723e7affe79ce14bff85 FIREFOX_47_0b9_RELEASE
 cf6ec12bd62001b93387ffb184a8841644255b5e FIREFOX_RELEASE_47_BASE
-32d716995e14ae1e8eb128fde0881b121b7b53d0 FIREFOX_RELEASE_46_END
-b0310cb90fd0158abd0e92850a47768649ba3d77 FIREFOX_47_0_BUILD3
-b0310cb90fd0158abd0e92850a47768649ba3d77 FIREFOX_47_0_RELEASE
-7f5abf95991bda0bc2b8e0d774a8866b726b312b FIREFOX_47_0_1_BUILD1
-7f5abf95991bda0bc2b8e0d774a8866b726b312b FIREFOX_47_0_1_RELEASE
 9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 1c6385ae1fe7e37d8f23f958ce14582f07af729e FIREFOX_AURORA_48_BASE
 037f67a2d6c87e32f60b2753f19e4bed69cb60b3 FIREFOX_AURORA_47_END
 961e7105e527f5b44e2b3cb6e24f6da33756f6ab FIREFOX_BETA_48_BASE
 a86835580095325bf5c85483fad952f5c99d973e FIREFOX_BETA_47_END
 55124c7343021091a61fdddac9f22628ca09642a FIREFOX_48_0b1_BUILD2
 55124c7343021091a61fdddac9f22628ca09642a FIREFOX_48_0b1_RELEASE
 9798772706750302d87a689cbbf056ae04244f80 FIREFOX_48_0b2_BUILD2
@@ -318,23 +300,16 @@ d142c49033c015f67272562b37dbe2912cfc7f14
 d142c49033c015f67272562b37dbe2912cfc7f14 FIREFOX_48_0b6_RELEASE
 9d734024ed35d74449601cc04917b327e0973c0d FIREFOX_48_0b7_BUILD1
 9d734024ed35d74449601cc04917b327e0973c0d FIREFOX_48_0b7_RELEASE
 d2ab9c39bd1059d74acb3d9ac87dbfbba913427b FIREFOX_48_0b9_BUILD1
 d2ab9c39bd1059d74acb3d9ac87dbfbba913427b FIREFOX_48_0b9_RELEASE
 05853bb06a8739b77c2937f418cdf4e1610d0d9f FIREFOX_48_0b10_BUILD1
 05853bb06a8739b77c2937f418cdf4e1610d0d9f FIREFOX_48_0b10_RELEASE
 f3d7abb885c267a7657e3b8ea06c18f76eb69641 FIREFOX_RELEASE_48_BASE
-2366ae84e268c386a292185bddb0e4a24c2e1d07 FIREFOX_RELEASE_47_END
-c1de04f39fa956cfce83f6065b0e709369215ed5 FIREFOX_48_0_BUILD2
-c1de04f39fa956cfce83f6065b0e709369215ed5 FIREFOX_48_0_RELEASE
-f36f7ace6f487e06f315f343d560b205fa8bd736 FIREFOX_48_0_1_BUILD3
-f36f7ace6f487e06f315f343d560b205fa8bd736 FIREFOX_48_0_1_RELEASE
-d4af0671004007e58d316b3e49679b66879c205a FIREFOX_48_0_2_BUILD1
-d4af0671004007e58d316b3e49679b66879c205a FIREFOX_48_0_2_RELEASE
 9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 a8fe75f38163d0af067fea60e951a844fb328db9 FIREFOX_AURORA_48_END
 d2f65d99fd51e5ee2f34d892115cc5d6c39a8ea9 FIREFOX_BETA_49_BASE
 958cee08361af9ed370be06695973bcda3d3aa46 FIREFOX_BETA_48_END
 c14631e328bbbd3aabaf06b51597060b55938ba8 FIREFOX_49_0b1_BUILD3
 c14631e328bbbd3aabaf06b51597060b55938ba8 FIREFOX_49_0b1_RELEASE
 b1bdd0f3482ae07d38a2ec5fbf190a2c4f2310ee FIREFOX_49_0b2_BUILD1
 b1bdd0f3482ae07d38a2ec5fbf190a2c4f2310ee FIREFOX_49_0b2_RELEASE
@@ -350,23 +325,16 @@ b44c72b85a800d9c6e719579d480bb2c3a87a753
 b44c72b85a800d9c6e719579d480bb2c3a87a753 FIREFOX_49_0b7_RELEASE
 68d24e6f784c7e375cf6c84c5c92496464d4f7e0 FIREFOX_49_0b8_BUILD1
 68d24e6f784c7e375cf6c84c5c92496464d4f7e0 FIREFOX_49_0b8_RELEASE
 e3cc699ccef2abb7075c39e7b9a081718eb9c159 FIREFOX_49_0b9_BUILD1
 e3cc699ccef2abb7075c39e7b9a081718eb9c159 FIREFOX_49_0b9_RELEASE
 77a60bbacb97c2f36815b2c395958a354aa581c9 FIREFOX_49_0b10_BUILD1
 77a60bbacb97c2f36815b2c395958a354aa581c9 FIREFOX_49_0b10_RELEASE
 5d1f8216843a6374f3bd2bd74ab2532da67d74ee FIREFOX_RELEASE_49_BASE
-31ca1b4c28a9f64e49d59ed01d08469a9af41951 FIREFOX_RELEASE_48_END
-416dc3163a1f27b8783ed14660d1b373e830df2f FIREFOX_49_0_BUILD4
-416dc3163a1f27b8783ed14660d1b373e830df2f FIREFOX_49_0_RELEASE
-2d931a5eaf8aeee925eca2aea42582a1fb9793c8 FIREFOX_49_0_1_BUILD3
-2d931a5eaf8aeee925eca2aea42582a1fb9793c8 FIREFOX_49_0_1_RELEASE
-7356baae8e736a6c9444bdd21562df806a39766b FIREFOX_49_0_2_BUILD2
-7356baae8e736a6c9444bdd21562df806a39766b FIREFOX_49_0_2_RELEASE
 9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 d98f20c25feeac4dd7ebbd1c022957df1ef58af4 FIREFOX_AURORA_49_BASE
 465d150bc8be5bbf9f02a8607d4552b6a5e1697c FIREFOX_AURORA_50_BASE
 fa80a27f26dfc653d23392c71f562b1827d82174 FIREFOX_AURORA_49_END
 c174d0c3195371011b3bf8044512c06c26f5c741 FIREFOX_BETA_50_BASE
 ddeb7907bc1e854738b164bab5ff71c3dcf1d786 FIREFOX_BETA_49_END
 91faf7ec36cd18a8ebdc0e2edac966e5bbb15da2 FIREFOX_50_0b1_BUILD2
 91faf7ec36cd18a8ebdc0e2edac966e5bbb15da2 FIREFOX_50_0b1_RELEASE
@@ -386,21 +354,16 @@ b7adb2f10487f6f886e047670ba720a248edcb44
 b7adb2f10487f6f886e047670ba720a248edcb44 FIREFOX_50_0b8_RELEASE
 2bb6dc758711c00d84246d74b57e5aa6cae4b447 FIREFOX_50_0b9_BUILD1
 2bb6dc758711c00d84246d74b57e5aa6cae4b447 FIREFOX_50_0b9_RELEASE
 38cfded1705240c5d20baff4aef99bdd0a13bcec FIREFOX_50_0b10_BUILD1
 38cfded1705240c5d20baff4aef99bdd0a13bcec FIREFOX_50_0b10_RELEASE
 829a3f99f2606759305e3db204185242566a4ca6 FIREFOX_50_0b11_BUILD1
 829a3f99f2606759305e3db204185242566a4ca6 FIREFOX_50_0b11_RELEASE
 d7598ee90bc6085d430b2e9e75c13358ef00a5f4 FIREFOX_RELEASE_50_BASE
-dd6c8d2be972cbf8729c01292639b8a03ce94728 FIREFOX_RELEASE_49_END
-dc617d65c9f0cdbbe4351cc1e5c288b05f25f8f7 FIREFOX_50_0_BUILD2
-dc617d65c9f0cdbbe4351cc1e5c288b05f25f8f7 FIREFOX_50_0_RELEASE
-8612c3320053b796678921f8f23358e3e9df997e FIREFOX_50_1_0_BUILD2
-8612c3320053b796678921f8f23358e3e9df997e FIREFOX_50_1_0_RELEASE
 9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 fc69febcbf6c0dcc4b3dfc7a346d8d348798a65f FIREFOX_AURORA_51_BASE
 3fdfaaed6e0fad2d81fc28e49903ff6f0a43b12e FIREFOX_AURORA_50_END
 2d9b6132e7d75327e063a15d8e5e279077adf987 FIREFOX_BETA_51_BASE
 24b8f08f77565f859898b45f62d2132ccc64c6d8 FIREFOX_BETA_50_END
 749a8d32b74eae516b9427f28aad4ec1c11e0a54 FIREFOX_51_0b1_BUILD2
 749a8d32b74eae516b9427f28aad4ec1c11e0a54 FIREFOX_51_0b1_RELEASE
 6296ed3dbefd133bba324230ec4f5a07d37041e1 FIREFOX_51_0b2_BUILD1
@@ -425,21 +388,16 @@ 0a17d39220700e742bf37a960967480b2f8159f1
 0a17d39220700e742bf37a960967480b2f8159f1 FIREFOX_51_0b11_RELEASE
 9ddd4fee07842e72ba49f1583ec5f596f6e60e72 FIREFOX_51_0b12_BUILD1
 9ddd4fee07842e72ba49f1583ec5f596f6e60e72 FIREFOX_51_0b12_RELEASE
 ce55e4d276031458f0730d481acff05d7c797038 FIREFOX_51_0b13_BUILD1
 ce55e4d276031458f0730d481acff05d7c797038 FIREFOX_51_0b13_RELEASE
 09142d07fd735e375fc1ae46886a52d6aef43b60 FIREFOX_51_0b14_BUILD1
 09142d07fd735e375fc1ae46886a52d6aef43b60 FIREFOX_51_0b14_RELEASE
 15467610e733e3549ea86cdf940b0fccd87eff89 FIREFOX_RELEASE_51_BASE
-b1e53b9be6d4834f5b3a58c132dfc5f5c73d2bcd FIREFOX_RELEASE_50_END
-ea82b5e20cbbd103f8fa65f0df0386ee4135cc47 FIREFOX_51_0_BUILD2
-ea82b5e20cbbd103f8fa65f0df0386ee4135cc47 FIREFOX_51_0_RELEASE
-327e081221b064b05a302d7877c6e4be2949a617 FIREFOX_51_0_1_BUILD3
-327e081221b064b05a302d7877c6e4be2949a617 FIREFOX_51_0_1_RELEASE
 9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 1196bf3032e1bce1fb07a01fd9082a767426c5fb FIREFOX_AURORA_52_BASE
 3223a6411d8c8b9ec8bcbc607c990bf099ade099 FIREFOX_AURORA_51_END
 24a81d93e07cc96300f8e1f5c69034dd4743bd63 FIREFOX_BETA_52_BASE
 8e692dd4176cba81ce020b29ae8b352dc1db724a FIREFOX_BETA_51_END
 78ae21055d9f303be257abe155ba9dee466c0651 FIREFOX_52_0b1_BUILD2
 78ae21055d9f303be257abe155ba9dee466c0651 FIREFOX_52_0b1_RELEASE
 0f339c1e154f75c484fe2fac507a9a225990d212 FIREFOX_52_0b2_BUILD1
@@ -454,24 +412,16 @@ 7b8aa893944b94d35e47314e52e0abff576c5ce2
 7b8aa893944b94d35e47314e52e0abff576c5ce2 FIREFOX_52_0b6_RELEASE
 820bc5bd3120853d611af1056f4a2b35528bb927 FIREFOX_52_0b7_BUILD1
 820bc5bd3120853d611af1056f4a2b35528bb927 FIREFOX_52_0b7_RELEASE
 3b31bcb88fe341172e93cc8b1143e617c0988694 FIREFOX_52_0b8_BUILD1
 3b31bcb88fe341172e93cc8b1143e617c0988694 FIREFOX_52_0b8_RELEASE
 61519976b35f2947eeaabefcad83186b7e004167 FIREFOX_52_0b9_BUILD2
 61519976b35f2947eeaabefcad83186b7e004167 FIREFOX_52_0b9_RELEASE
 4bd2e5d2ac0d0b15b4446fca5647bfa821b52d46 FIREFOX_RELEASE_52_BASE
-1f0fc9316e65cd171b03d4382b4c0f7443a258dc FIREFOX_RELEASE_51_END
-2183f7cb4f886e5f0b619dcff101bee72210ef38 FIREFOX_ESR_52_BASE
-44d6a57ab554308585a67a13035d31b264be781e FIREFOX_52_0_BUILD2
-44d6a57ab554308585a67a13035d31b264be781e FIREFOX_52_0_RELEASE
-a38b8538f42412d2c606417264df4abcc183dd57 FIREFOX_52_0_1_BUILD2
-a38b8538f42412d2c606417264df4abcc183dd57 FIREFOX_52_0_1_RELEASE
-e81854d6ce91f3174774a50c9c5813c33b9aac58 FIREFOX_52_0_2_BUILD1
-e81854d6ce91f3174774a50c9c5813c33b9aac58 FIREFOX_52_0_2_RELEASE
 9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 f80dc9fc34680105b714a49b4704bb843f5f7004 FIREFOX_AURORA_53_BASE
 1bf0b129e71adde135eb1eb577d497935c234a50 FIREFOX_AURORA_52_END
 69efeba94b307f236a50a9e5fdd2bbd2e946657b FIREFOX_BETA_53_BASE
 69efeba94b307f236a50a9e5fdd2bbd2e946657b FIREFOX_BETA_53_BASE
 0000000000000000000000000000000000000000 FIREFOX_BETA_53_BASE
 0000000000000000000000000000000000000000 FIREFOX_BETA_53_BASE
 39accab74f27dde4531631a66e95632bd8b4ffd3 FIREFOX_BETA_53_BASE
@@ -510,29 +460,16 @@ 3a2e5c6e4ed33d9cb8b04b32f85b45a9aad4c8d8
 3a2e5c6e4ed33d9cb8b04b32f85b45a9aad4c8d8 FENNEC_53_0b9_RELEASE
 ac874b7422a6747ee5e14e348ebea77ae639a7a5 FIREFOX_53_0b10_BUILD1
 ac874b7422a6747ee5e14e348ebea77ae639a7a5 FIREFOX_53_0b10_RELEASE
 557f09b2881bf2513bc34d3a0fe2a2de04163054 FIREFOX_RELEASE_53_BASE
 557f09b2881bf2513bc34d3a0fe2a2de04163054 FIREFOX_RELEASE_53_BASE
 0000000000000000000000000000000000000000 FIREFOX_RELEASE_53_BASE
 0000000000000000000000000000000000000000 FIREFOX_RELEASE_53_BASE
 db89a02ecfbbbe17831b11f3313814a67621264d FIREFOX_RELEASE_53_BASE
-fef4c3a1cf544e1ced8c477d6ce0e080130cb274 FIREFOX_RELEASE_52_END
-d345b657d381ade5195f1521313ac651618f54a2 FIREFOX_53_0_BUILD6
-d345b657d381ade5195f1521313ac651618f54a2 FIREFOX_53_0_RELEASE
-f239279b709072490993b099832fa8c18f07713a FENNEC_53_0_BUILD1
-f239279b709072490993b099832fa8c18f07713a FENNEC_53_0_RELEASE
-5cbf464688a47129c0ea36fe38f42f59926e4b2c FENNEC_53_0_1_BUILD2
-5cbf464688a47129c0ea36fe38f42f59926e4b2c FENNEC_53_0_1_RELEASE
-f87a819106bd98895e38bd26c134031c534a19ff FENNEC_53_0_2_BUILD1
-f87a819106bd98895e38bd26c134031c534a19ff FENNEC_53_0_2_RELEASE
-f87a819106bd98895e38bd26c134031c534a19ff FIREFOX_53_0_2_BUILD1
-f87a819106bd98895e38bd26c134031c534a19ff FIREFOX_53_0_2_RELEASE
-1fe643b3421a27640a61a3b2b8b0986c7234e314 FIREFOX_53_0_3_BUILD1
-1fe643b3421a27640a61a3b2b8b0986c7234e314 FIREFOX_53_0_3_RELEASE
 35a1b06fe7863e118ce831d9056ad20501eec606 FENNEC_53_0b11_BUILD1
 35a1b06fe7863e118ce831d9056ad20501eec606 FENNEC_53_0b11_RELEASE
 9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 6583496f169cd8a13c531ed16e98e8bf313eda8e FIREFOX_AURORA_54_BASE
 4e1faf8f62eb5edfbbe05c8f0a35cbe57a5ec9b6 FIREFOX_AURORA_53_END
 09e97b55acb30be1f8e13b0f637f9cf152658799 FIREFOX_BETA_54_BASE
 1d36370d5eac6e6927dbc4810ba5cdb760f6eb93 FIREFOX_BETA_53_END
 bfa8f90200d10fb26feb01967dc8a95736b6769a FENNEC_54_0b1_BUILD1
@@ -570,29 +507,19 @@ a6edfa473c7dde50edc14a85374eb400e5ada494
 51c849c595a0b5428d1d56e4ae668653437283e2 FIREFOX_54_0b11_BUILD2
 51c849c595a0b5428d1d56e4ae668653437283e2 FIREFOX_54_0b11_RELEASE
 715d88d0bd826c9e4a5403d6561a2fcc229dd208 FIREFOX_54_0b12_BUILD1
 715d88d0bd826c9e4a5403d6561a2fcc229dd208 FIREFOX_54_0b12_RELEASE
 715d88d0bd826c9e4a5403d6561a2fcc229dd208 FENNEC_54_0b12_BUILD1
 715d88d0bd826c9e4a5403d6561a2fcc229dd208 FENNEC_54_0b12_RELEASE
 cb4a4275b365b126ae56b1df5521756b693d8ff9 FIREFOX_54_0b13_BUILD1
 cb4a4275b365b126ae56b1df5521756b693d8ff9 FIREFOX_54_0b13_RELEASE
+6f0be3ad8512b63a13cb4ec87ae4efae31411ecf FIREFOX_RELEASE_54_BASE
 97767088522e789dd04cf06b24478f052946d1c9 FENNEC_54_0b14_BUILD1
 97767088522e789dd04cf06b24478f052946d1c9 FENNEC_54_0b14_RELEASE
-6f0be3ad8512b63a13cb4ec87ae4efae31411ecf FIREFOX_RELEASE_54_BASE
-f51126f4546c7f438398db1808b852536a1a5f9e FIREFOX_RELEASE_53_END
-e832ed037a3c23004be73178e546d240e57b6ee1 FENNEC_54_0_BUILD2
-e832ed037a3c23004be73178e546d240e57b6ee1 FENNEC_54_0_RELEASE
-e832ed037a3c23004be73178e546d240e57b6ee1 FIREFOX_54_0_BUILD3
-e832ed037a3c23004be73178e546d240e57b6ee1 FIREFOX_54_0_RELEASE
-90f18f9c15f7c71c755e387cfc193974fcf8b29c FENNEC_54_0_1_BUILD1
-90f18f9c15f7c71c755e387cfc193974fcf8b29c FENNEC_54_0_1_RELEASE
-90f18f9c15f7c71c755e387cfc193974fcf8b29c FIREFOX_54_0_1_BUILD1
-90f18f9c15f7c71c755e387cfc193974fcf8b29c FIREFOX_54_0_1_RELEASE
-6f0be3ad8512b63a13cb4ec87ae4efae31411ecf FIREFOX_RELEASE_54_BASE
 9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 f9605772a0c9098ed1bcaa98089b2c944ed69e9b FIREFOX_BETA_55_BASE
 d8424bcbf72f7a451e89f8f625a9ebafecded872 FIREFOX_BETA_54_END
 e8dd9736241ea1989feaf3c85a71593c8a6f3bbb FENNEC_55_0b1_BUILD2
 e8dd9736241ea1989feaf3c85a71593c8a6f3bbb FENNEC_55_0b1_RELEASE
 d956c96a1926c1755d9ce46a110ba7893f4d478a FIREFOX_55_0b1_BUILD5
 d956c96a1926c1755d9ce46a110ba7893f4d478a FIREFOX_55_0b1_RELEASE
 803f16362c14a488b1923b184859f8265f63731f FIREFOX_55_0b2_BUILD1
@@ -627,21 +554,48 @@ e5f14b9ae6c4c1e0ff1c430503671289120db203
 e5f14b9ae6c4c1e0ff1c430503671289120db203 FIREFOX_55_0b11_RELEASE
 5ff8131b551228ca603a76e39925495d7d2a407e FIREFOX_55_0b12_BUILD1
 5ff8131b551228ca603a76e39925495d7d2a407e FIREFOX_55_0b12_RELEASE
 5ff8131b551228ca603a76e39925495d7d2a407e FENNEC_55_0b12_BUILD1
 5ff8131b551228ca603a76e39925495d7d2a407e FENNEC_55_0b12_RELEASE
 271221d4286a7641c21f8a13df2987d655f9d3dc FIREFOX_55_0b13_BUILD1
 271221d4286a7641c21f8a13df2987d655f9d3dc FIREFOX_55_0b13_RELEASE
 2cd8c7f13e6c5ace6955da85a4d95f6e65caad2e FIREFOX_RELEASE_55_BASE
-6f550973dfb0547adcd98430f452e215afb8f687 FIREFOX_RELEASE_54_END
-9e30e915f1325f041d01c722bd640300f32dc9c3 FIREFOX_55_0_BUILD3
-9e30e915f1325f041d01c722bd640300f32dc9c3 FIREFOX_55_0_RELEASE
-9e30e915f1325f041d01c722bd640300f32dc9c3 FENNEC_55_0_BUILD2
-9e30e915f1325f041d01c722bd640300f32dc9c3 FENNEC_55_0_RELEASE
-cace0357d40e875ea45b9ccad99f8785fc2cdb50 FIREFOX_55_0_1_BUILD2
-cace0357d40e875ea45b9ccad99f8785fc2cdb50 FIREFOX_55_0_1_RELEASE
-45ab6e362747102d00fd75378727fcddcfd35f44 FENNEC_55_0_2_BUILD1
-45ab6e362747102d00fd75378727fcddcfd35f44 FENNEC_55_0_2_RELEASE
-45ab6e362747102d00fd75378727fcddcfd35f44 FIREFOX_55_0_2_BUILD1
-45ab6e362747102d00fd75378727fcddcfd35f44 FIREFOX_55_0_2_RELEASE
-10a244c0f835d286d49a571dab59b698d7404e28 FIREFOX_55_0_3_BUILD2
-10a244c0f835d286d49a571dab59b698d7404e28 FIREFOX_55_0_3_RELEASE
+116b3910f1c72ae12ed330ed7942ac1afeea953e FENNEC_55_0b14_BUILD1
+116b3910f1c72ae12ed330ed7942ac1afeea953e FENNEC_55_0b14_RELEASE
+9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
+320642944e42a889db13c6c55b404e32319d4de6 FIREFOX_BETA_56_BASE
+907a3a5c6fede43f359184c4c604390578f8cabe FIREFOX_BETA_55_END
+6c489d5df6d4d85ddb297666e8c1cbbda96a852c FENNEC_56_0b1_BUILD1
+6c489d5df6d4d85ddb297666e8c1cbbda96a852c FENNEC_56_0b1_RELEASE
+da6760885a24e03e13f3b566f319fc255dbb4027 FIREFOX_56_0b1_BUILD5
+da6760885a24e03e13f3b566f319fc255dbb4027 FIREFOX_56_0b1_RELEASE
+2638feb177dd9104a3887fae2ce05931a6b41d6c FIREFOX_56_0b2_BUILD1
+2638feb177dd9104a3887fae2ce05931a6b41d6c FIREFOX_56_0b2_RELEASE
+efabe9b3a88e0cb1bcb092b34e0291ac99759471 FIREFOX_56_0b3_BUILD1
+efabe9b3a88e0cb1bcb092b34e0291ac99759471 FIREFOX_56_0b3_RELEASE
+efabe9b3a88e0cb1bcb092b34e0291ac99759471 FENNEC_56_0b3_BUILD1
+efabe9b3a88e0cb1bcb092b34e0291ac99759471 FENNEC_56_0b3_RELEASE
+05a4dc75c125a80cbaacd44c7b7937c77dc384a8 FIREFOX_56_0b4_BUILD5
+05a4dc75c125a80cbaacd44c7b7937c77dc384a8 FIREFOX_56_0b4_RELEASE
+86e3368b6058c3a298a6fd973de1313cfe706795 FIREFOX_56_0b5_BUILD1
+86e3368b6058c3a298a6fd973de1313cfe706795 FIREFOX_56_0b5_RELEASE
+86e3368b6058c3a298a6fd973de1313cfe706795 FENNEC_56_0b5_BUILD1
+86e3368b6058c3a298a6fd973de1313cfe706795 FENNEC_56_0b5_RELEASE
+acf7e3e5c7fd7b4faff64ebdaba535026172cfba FIREFOX_56_0b6_BUILD2
+acf7e3e5c7fd7b4faff64ebdaba535026172cfba FIREFOX_56_0b6_RELEASE
+8081a895e4353e807a851485e412ed7a907c0b3f FIREFOX_56_0b7_BUILD2
+8081a895e4353e807a851485e412ed7a907c0b3f FIREFOX_56_0b7_RELEASE
+8081a895e4353e807a851485e412ed7a907c0b3f FENNEC_56_0b7_BUILD1
+8081a895e4353e807a851485e412ed7a907c0b3f FENNEC_56_0b7_RELEASE
+dcb3e24852c4b3ddc900d5e2430853cb9a51cdc4 FIREFOX_56_0b8_BUILD1
+dcb3e24852c4b3ddc900d5e2430853cb9a51cdc4 FIREFOX_56_0b8_RELEASE
+da291ce74248b2830a0010a8bf21bba5f408bd43 FENNEC_56_0b9_BUILD3
+da291ce74248b2830a0010a8bf21bba5f408bd43 FENNEC_56_0b9_RELEASE
+da291ce74248b2830a0010a8bf21bba5f408bd43 FIREFOX_56_0b9_BUILD1
+da291ce74248b2830a0010a8bf21bba5f408bd43 FIREFOX_56_0b9_RELEASE
+3484d06e80e135e84167fe95f8a42320308a2adc FIREFOX_56_0b10_BUILD1
+3484d06e80e135e84167fe95f8a42320308a2adc FIREFOX_56_0b10_RELEASE
+6bd183fc69218cdbb69a5f9407c69206dade6ae1 FIREFOX_56_0b11_BUILD1
+6bd183fc69218cdbb69a5f9407c69206dade6ae1 FIREFOX_56_0b11_RELEASE
+6bd183fc69218cdbb69a5f9407c69206dade6ae1 FENNEC_56_0b11_BUILD1
+6bd183fc69218cdbb69a5f9407c69206dade6ae1 FENNEC_56_0b11_RELEASE
+12809a8ce21a7b10c7a4e54baa9ae742c176de87 FIREFOX_RELEASE_56_BASE
--- a/.taskcluster.yml
+++ b/.taskcluster.yml
@@ -1,127 +1,134 @@
----
-version: 0
-metadata:
-  name: 'Taskcluster tasks for Gecko'
-  description: "The taskcluster task graph for Gecko trees"
-  owner: mozilla-taskcluster-maintenance@mozilla.com
-  source: {{{source}}}
+# This file is rendered via JSON-e by
+# - mozilla-taskcluster - https://docs.taskcluster.net/reference/integrations/mozilla-taskcluster/docs/taskcluster-yml
+# - cron tasks - taskcluster/taskgraph/cron/decision.py
+version: 1
+tasks:
+  $let:
+    # sometimes the push user is just `ffxbld` or the like, but we want an email-like field..
+    ownerEmail: {$if: '"@" in push.owner', then: '${push.owner}', else: '${push.owner}@noreply.mozilla.org'}
+    # ensure there's no trailing `/` on the repo URL
+    repoUrl: {$if: 'repository.url[-1] == "/"', then: {$eval: 'repository.url[:-1]'}, else: {$eval: 'repository.url'}}
+  in:
+  - taskId: '${as_slugid("decision")}'
+    taskGroupId: '${as_slugid("decision")}' # same as tsakId; this is how automation identifies a decision tsak
+    schedulerId: 'gecko-level-${repository.level}'
 
-scopes:
-  # Note the below scopes are insecure however these get overriden on the server
-  # side to whatever scopes are set by mozilla-taskcluster.
-  - queue:*
-  - docker-worker:*
-  - scheduler:*
+    created: {$fromNow: ''}
+    deadline: {$fromNow: '1 day'}
+    expires: {$fromNow: '1 year 1 second'} # 1 second so artifacts expire first, despite rounding errors
+    metadata:
+      $merge:
+        - owner: "${ownerEmail}"
+          source: "${repoUrl}/raw-file/${push.revision}/.taskcluster.yml"
+        - $if: 'tasks_for == "hg-push"'
+          then:
+            name: "Gecko Decision Task"
+            description: 'The task that creates all of the other tasks in the task graph'
+          else:
+            name: "Decision Task for cron job ${cron.job_name}"
+            description: 'Created by a [cron task](https://tools.taskcluster.net/tasks/${cron.task_id})'
 
-# This file undergoes substitution to create tasks.  For on-push tasks, that
-# substitution is done by mozilla-taskcluster.  For cron tasks, that substitution
-# is done by `taskcluster/taskgraph/cron/decision.py`.  If you change any of the
-# template parameters, please do so in all three places!
-#
-# Available template parameters:
-#
-# - now:            current time
-# - owner:          push user (email address)
-# - source:         URL of this YAML file
-# - url:            repository URL
-# - project:        alias for the destination repository (basename of
-#                   the repo url)
-# - level:          SCM level of the destination repository
-#                   (1 = try, 3 = core)
-# - revision:       hg revision of the head of the push
-# - comment:        comment of the push
-# - pushlog_id:     id in the pushlog table of the repository
-#
-# and functions:
-# - as_slugid:      convert a label into a slugId
-# - from_now:       generate a timestamp at a fixed offset from now
-# - shellquote:     quote the contents for injection into shell
+    provisionerId: "aws-provisioner-v1"
+    workerType: "gecko-decision"
+
+    tags:
+      $if: 'tasks_for == "hg-push"'
+      then: {createdForUser: "${ownerEmail}"}
 
-# The resulting tasks' taskGroupId will be equal to the taskId of the first
-# task listed here, which should be the decision task.  This gives other tools
-# an easy way to determine the ID of the decision task that created a
-# particular group.
+    routes:
+      $if: 'tasks_for == "hg-push"'
+      then:
+        - "index.gecko.v2.${repository.project}.latest.firefox.decision"
+        - "index.gecko.v2.${repository.project}.pushlog-id.${push.pushlog_id}.decision"
+        - "tc-treeherder.v2.${repository.project}.${push.revision}.${push.pushlog_id}"
+        - "tc-treeherder-stage.v2.${repository.project}.${push.revision}.${push.pushlog_id}"
+        - "notify.email.${ownerEmail}.on-failed"
+        - "notify.email.${ownerEmail}.on-exception"
+      else:
+        - "index.gecko.v2.${repository.project}.latest.firefox.decision-${cron.job_name}"
+        - "tc-treeherder.v2.${repository.project}.${push.revision}.${push.pushlog_id}"
+        - "tc-treeherder-stage.v2.${repository.project}.${push.revision}.${push.pushlog_id}"
 
-tasks:
-  - taskId: '{{#as_slugid}}decision task{{/as_slugid}}'
-    task:
-      created: '{{now}}'
-      deadline: '{{#from_now}}1 day{{/from_now}}'
-      expires: '{{#from_now}}365 day{{/from_now}}'
-      metadata:
-        owner: mozilla-taskcluster-maintenance@mozilla.com
-        source: {{{source}}}
-        name: "Gecko Decision Task"
-        description: |
-            The task that creates all of the other tasks in the task graph
+    scopes:
+      $if: 'tasks_for == "hg-push"'
+      then:
+        - 'assume:repo:${repoUrl[8:]}:*'
+        - 'queue:route:notify.email.${ownerEmail}.*'
+      else:
+        - 'assume:repo:${repoUrl[8:]}:cron:${cron.job_name}'
 
-      workerType: "gecko-decision"
-      provisionerId: "aws-provisioner-v1"
+    dependencies: []
+    requires: all-completed
 
-      tags:
-        createdForUser: {{owner}}
+    priority: lowest
+    retries: 5
 
-      routes:
-        - "index.gecko.v2.{{project}}.latest.firefox.decision"
-        - "tc-treeherder.v2.{{project}}.{{revision}}.{{pushlog_id}}"
-        - "tc-treeherder-stage.v2.{{project}}.{{revision}}.{{pushlog_id}}"
-        - "notify.email.{{owner}}.on-failed"
-        - "notify.email.{{owner}}.on-exception"
+    payload:
+      env:
+        # checkout-gecko uses these to check out the source; the inputs
+        # to `mach taskgraph decision` are all on the command line.
+        GECKO_BASE_REPOSITORY: 'https://hg.mozilla.org/mozilla-unified'
+        GECKO_HEAD_REPOSITORY: '${repoUrl}'
+        GECKO_HEAD_REF: '${push.revision}'
+        GECKO_HEAD_REV: '${push.revision}'
+        GECKO_COMMIT_MSG: '${push.comment}'
+        HG_STORE_PATH: /home/worker/checkouts/hg-store
 
-      payload:
-        env:
-          # checkout-gecko uses these to check out the source; the inputs
-          # to `mach taskgraph decision` are all on the command line.
-          GECKO_BASE_REPOSITORY: 'https://hg.mozilla.org/mozilla-unified'
-          GECKO_HEAD_REPOSITORY: '{{{url}}}'
-          GECKO_HEAD_REF: '{{revision}}'
-          GECKO_HEAD_REV: '{{revision}}'
-          HG_STORE_PATH: /home/worker/checkouts/hg-store
+      cache:
+        level-${repository.level}-checkouts: /home/worker/checkouts
+
+      features:
+        taskclusterProxy: true
+        chainOfTrust: true
 
-        cache:
-          level-{{level}}-checkouts: /home/worker/checkouts
-
-        features:
-          taskclusterProxy: true
-          chainOfTrust: true
+      # Note: This task is built server side without the context or tooling that
+      # exist in tree so we must hard code the hash
+      # XXX Changing this will break Chain of Trust without an associated puppet and
+      # scriptworker patch!
+      image: 'taskcluster/decision:0.1.8@sha256:195d8439c8e90d59311d877bd2a8964849b2e43bfc6c234092618518d8b2891b'
 
-        # Note: This task is built server side without the context or tooling that
-        # exist in tree so we must hard code the hash
-        # XXX Changing this will break Chain of Trust without an associated puppet and
-        # scriptworker patch!
-        image: 'taskcluster/decision:0.1.8@sha256:195d8439c8e90d59311d877bd2a8964849b2e43bfc6c234092618518d8b2891b'
-
-        maxRunTime: 1800
+      maxRunTime: 1800
 
-        # TODO use mozilla-unified for the base repository once the tc-vcs
-        # tar.gz archives are created or tc-vcs isn't being used.
-        command:
-          - /home/worker/bin/run-task
-          - '--vcs-checkout=/home/worker/checkouts/gecko'
-          - '--'
-          - bash
-          - -cx
-          - >
-              cd /home/worker/checkouts/gecko &&
-              ln -s /home/worker/artifacts artifacts &&
-              ./mach --log-no-times taskgraph decision
-              --pushlog-id='{{pushlog_id}}'
-              --pushdate='{{pushdate}}'
-              --project='{{project}}'
-              --message={{#shellquote}}{{{comment}}}{{/shellquote}}
-              --owner='{{owner}}'
-              --level='{{level}}'
-              --base-repository='https://hg.mozilla.org/mozilla-central'
-              --head-repository='{{{url}}}'
-              --head-ref='{{revision}}'
-              --head-rev='{{revision}}'
+      # TODO use mozilla-unified for the base repository once the tc-vcs
+      # tar.gz archives are created or tc-vcs isn't being used.
+      command:
+        - /home/worker/bin/run-task
+        - '--vcs-checkout=/home/worker/checkouts/gecko'
+        - '--'
+        - bash
+        - -cx
+        - $let:
+            extraArgs: {$if: 'tasks_for == "hg-push"', then: '', else: '${cron.quoted_args}'}
+          # NOTE: the explicit reference to mozilla-central below is required because android-stuff
+          # still uses tc-vcs, which does not support mozilla-unified
+          # https://bugzilla.mozilla.org/show_bug.cgi?id=1383973
+          in: >
+            cd /home/worker/checkouts/gecko &&
+            ln -s /home/worker/artifacts artifacts &&
+            ./mach --log-no-times taskgraph decision
+            --pushlog-id='${push.pushlog_id}'
+            --pushdate='${push.pushdate}'
+            --project='${repository.project}'
+            --message="$GECKO_COMMIT_MSG"
+            --owner='${ownerEmail}'
+            --level='${repository.level}'
+            --base-repository='https://hg.mozilla.org/mozilla-central'
+            --head-repository="$GECKO_HEAD_REPOSITORY"
+            --head-ref="$GECKO_HEAD_REF"
+            --head-rev="$GECKO_HEAD_REV"
+            ${extraArgs}
 
-        artifacts:
-          'public':
-            type: 'directory'
-            path: '/home/worker/artifacts'
-            expires: '{{#from_now}}364 days{{/from_now}}'
+      artifacts:
+        'public':
+          type: 'directory'
+          path: '/home/worker/artifacts'
+          expires: {$fromNow: '1 year'}
 
-      extra:
-        treeherder:
+    extra:
+      treeherder:
+        $if: 'tasks_for == "hg-push"'
+        then:
           symbol: D
+        else:
+          groupSymbol: cron
+          symbol: "${cron.job_symbol}"
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -1,23 +1,36 @@
 {
     // See https://go.microsoft.com/fwlink/?LinkId=733558
     // for the documentation about the tasks.json format
     "version": "2.0.0",
-    "command": "${workspaceRoot}/mach",
+    "windows": {
+      "command": "\"\\mozilla-build\\start-shell.bat mach\""
+    },
+    "osx": {
+      "command": "${workspaceRoot}/mach"
+    },
+    "linux": {
+      "command": "${workspaceRoot}/mach"
+    },
     "isShellCommand": true,
     "args": ["--log-no-times"],
     "showOutput": "silent",
     "echoCommand": true,
     "suppressTaskName": false,
     "tasks": [
       {
         "taskName": "clobber"
       },
       {
+        "taskName": "clobber-python",
+        "suppressTaskName": true,
+        "args": ["clobber", "python"]
+      },
+      {
         "taskName": "configure"
       },
       {
         "taskName": "build",
         "isBuildCommand": true,
         "problemMatcher": {
           "owner": "cpp",
           "fileLocation": "absolute",
@@ -27,32 +40,36 @@
             "line": 2,
             "column": 3,
             "severity": 4,
             "message": 5
           }
         }
       },
       {
-        "taskName": "build binaries",
+        "taskName": "build-binaries",
+        "suppressTaskName": true,
+        "args": ["build", "binaries"],
         "problemMatcher": {
           "owner": "cpp",
           "fileLocation": "absolute",
           "pattern": {
             "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
             "file": 1,
             "line": 2,
             "column": 3,
             "severity": 4,
             "message": 5
           }
         }
       },
       {
-        "taskName": "build faster",
+        "taskName": "build-faster",
+        "suppressTaskName": true,
+        "args": ["build", "faster"],
         "problemMatcher": {
           "owner": "cpp",
           "fileLocation": "absolute",
           "pattern": {
             "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
             "file": 1,
             "line": 2,
             "column": 3,
@@ -62,21 +79,27 @@
         }
       },
       {
         "taskName": "run",
         "args": ["-purgecaches"],
         "showOutput": "always"
       },
       {
+        "taskName": "lint-wo",
+        "suppressTaskName": true,
+        "args": ["lint", "-wo"],
+        "problemMatcher": ["$eslint-stylish"]
+      },
+      {
         "taskName": "eslint",
         "problemMatcher": ["$eslint-stylish"]
       },
       {
-        "taskName": "eslint fix",
+        "taskName": "eslint-fix",
         "suppressTaskName": true,
         "args": ["eslint", "--fix", "${file}"],
         "problemMatcher": ["$eslint-stylish"]
       },
       {
         "taskName": "test",
         "args": ["${relativeFile}"],
         "isTestCommand": true,
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,10 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-
 Merge day clobber
\ No newline at end of file
--- a/Makefile.in
+++ b/Makefile.in
@@ -142,17 +142,22 @@ ifneq (,$(filter FasterMake+RecursiveMak
 install-manifests: faster
 .PHONY: faster
 faster: install-dist/idl
 	$(MAKE) -C faster FASTER_RECURSIVE_MAKE=1
 endif
 
 .PHONY: tup
 tup:
-	$(call BUILDSTATUS,TIERS make tup)
+	$(call BUILDSTATUS,TIERS $(if $(MOZ_ARTIFACT_BUILDS),artifact )make tup)
+ifdef MOZ_ARTIFACT_BUILDS
+	$(call BUILDSTATUS,TIER_START artifact)
+	$(MAKE) recurse_artifact
+	$(call BUILDSTATUS,TIER_FINISH artifact)
+endif
 	$(call BUILDSTATUS,TIER_START make)
 	$(MAKE) buildid.h source-repo.h
 	$(call BUILDSTATUS,TIER_FINISH make)
 	$(call BUILDSTATUS,TIER_START tup)
 	@$(TUP) $(if $(findstring s,$(filter-out --%,$(MAKEFLAGS))),,--verbose)
 	$(call BUILDSTATUS,TIER_FINISH tup)
 
 # process_install_manifest needs to be invoked with --no-remove when building
@@ -238,16 +243,21 @@ default all::
 include $(topsrcdir)/config/rules.mk
 
 ifdef SCCACHE_VERBOSE_STATS
 default::
 	-$(CCACHE) --show-stats --stats-format=json > sccache-stats.json
 	@echo "===SCCACHE STATS==="
 	-$(CCACHE) --show-stats
 	@echo "==================="
+ifndef MOZ_PROFILE_GENERATE
+# Ideally we'd do that in the same file as we set the sccache.log location for
+# sccache, but it's too late in the build.
+	-gzip -9 $(DIST)/sccache.log
+endif
 endif
 
 distclean::
 	$(RM) $(DIST_GARBAGE)
 
 ifdef MOZ_CRASHREPORTER
 include $(topsrcdir)/toolkit/mozapps/installer/package-name.mk
 
@@ -260,26 +270,26 @@ prepsymbolsarchive:
 
 ifndef MOZ_AUTOMATION
 prepsymbolsarchive: recurse_syms
 endif
 
 .PHONY: symbolsfullarchive
 symbolsfullarchive: prepsymbolsarchive
 	$(RM) '$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip'
-	$(call py_action,symbols_archive,$(abspath '$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip') \
+	$(call py_action,symbols_archive,'$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip' \
                                      $(abspath $(DIST)/crashreporter-symbols) \
                                      --exclude '*test*' \
                                      --exclude '*Test*' \
                                      --compress '**/*.sym')
 
 .PHONY: symbolsarchive
 symbolsarchive: prepsymbolsarchive
 	$(RM) '$(DIST)/$(PKG_PATH)$(SYMBOL_ARCHIVE_BASENAME).zip'
-	$(call py_action,symbols_archive,$(abspath '$(DIST)/$(PKG_PATH)$(SYMBOL_ARCHIVE_BASENAME).zip') \
+	$(call py_action,symbols_archive,'$(DIST)/$(PKG_PATH)$(SYMBOL_ARCHIVE_BASENAME).zip' \
                                      $(abspath $(DIST)/crashreporter-symbols) \
                                      --include '**/*.sym')
 
 ifdef MOZ_CRASHREPORTER
 buildsymbols: symbolsfullarchive symbolsarchive
 else
 buildsymbols:
 endif
--- a/accessible/.eslintrc.js
+++ b/accessible/.eslintrc.js
@@ -5,24 +5,20 @@ module.exports = {
     // Warn about cyclomatic complexity in functions.
     "complexity": ["error", 42],
 
     // XXX These are rules that are enabled in the recommended configuration, but
     // disabled here due to failures when initially implemented. They should be
     // removed (and hence enabled) at some stage.
     "brace-style": "off",
     "consistent-return": "off",
-    "func-call-spacing": "off",
     "quotes": "off",
     "object-shorthand": "off",
     "space-before-function-paren": "off",
     "space-infix-ops": "off",
-    "key-spacing": "off",
-    "keyword-spacing": "off",
     "no-else-return": "off",
     "no-multi-spaces": "off",
-    "no-trailing-spaces": "off",
     "no-unexpected-multiline": "off",
     "no-unsafe-finally": "off",
     "no-useless-call": "off",
     "spaced-comment": "off",
   }
 };
--- a/accessible/atk/AccessibleWrap.cpp
+++ b/accessible/atk/AccessibleWrap.cpp
@@ -60,17 +60,17 @@ enum MaiInterfaceType {
     MAI_INTERFACE_ACTION,
     MAI_INTERFACE_VALUE,
     MAI_INTERFACE_EDITABLE_TEXT,
     MAI_INTERFACE_HYPERTEXT,
     MAI_INTERFACE_HYPERLINK_IMPL,
     MAI_INTERFACE_SELECTION,
     MAI_INTERFACE_TABLE,
     MAI_INTERFACE_TEXT,
-    MAI_INTERFACE_DOCUMENT, 
+    MAI_INTERFACE_DOCUMENT,
     MAI_INTERFACE_IMAGE, /* 10 */
     MAI_INTERFACE_TABLE_CELL
 };
 
 static GType GetAtkTypeForMai(MaiInterfaceType type)
 {
   switch (type) {
     case MAI_INTERFACE_COMPONENT:
@@ -97,23 +97,23 @@ static GType GetAtkTypeForMai(MaiInterfa
       return ATK_TYPE_IMAGE;
     case MAI_INTERFACE_TABLE_CELL:
       MOZ_ASSERT(false);
   }
   return G_TYPE_INVALID;
 }
 
 #define NON_USER_EVENT ":system"
-    
+
 // The atk interfaces we can expose without checking what version of ATK we are
 // dealing with.  At the moment AtkTableCell is the only interface we can't
 // always expose.
 static const GInterfaceInfo atk_if_infos[] = {
     {(GInterfaceInitFunc)componentInterfaceInitCB,
-     (GInterfaceFinalizeFunc) nullptr, nullptr}, 
+     (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)actionInterfaceInitCB,
      (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)valueInterfaceInitCB,
      (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)editableTextInterfaceInitCB,
      (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)hypertextInterfaceInitCB,
      (GInterfaceFinalizeFunc) nullptr, nullptr},
@@ -323,17 +323,17 @@ AccessibleWrap::GetAtkObject(void)
 
 // Get AtkObject from Accessible interface
 /* static */
 AtkObject *
 AccessibleWrap::GetAtkObject(Accessible* acc)
 {
     void *atkObjPtr = nullptr;
     acc->GetNativeInterface(&atkObjPtr);
-    return atkObjPtr ? ATK_OBJECT(atkObjPtr) : nullptr;    
+    return atkObjPtr ? ATK_OBJECT(atkObjPtr) : nullptr;
 }
 
 /* private */
 uint16_t
 AccessibleWrap::CreateMaiInterfaces(void)
 {
   uint16_t interfacesBits = 0;
 
@@ -367,17 +367,17 @@ AccessibleWrap::CreateMaiInterfaces(void
   // HyperLink interface.
   if (IsLink())
     interfacesBits |= 1 << MAI_INTERFACE_HYPERLINK_IMPL;
 
   if (!nsAccUtils::MustPrune(this)) {  // These interfaces require children
     // Table interface.
     if (AsTable())
       interfacesBits |= 1 << MAI_INTERFACE_TABLE;
- 
+
     if (AsTableCell())
       interfacesBits |= 1 << MAI_INTERFACE_TABLE_CELL;
 
     // Selection interface.
     if (IsSelect()) {
       interfacesBits |= 1 << MAI_INTERFACE_SELECTION;
     }
   }
@@ -692,16 +692,22 @@ getRoleCB(AtkObject *aAtkObj)
 #undef ROLE
 
   if (aAtkObj->role == ATK_ROLE_LIST_BOX && !IsAtkVersionAtLeast(2, 1))
     aAtkObj->role = ATK_ROLE_LIST;
   else if (aAtkObj->role == ATK_ROLE_TABLE_ROW && !IsAtkVersionAtLeast(2, 1))
     aAtkObj->role = ATK_ROLE_LIST_ITEM;
   else if (aAtkObj->role == ATK_ROLE_MATH && !IsAtkVersionAtLeast(2, 12))
     aAtkObj->role = ATK_ROLE_SECTION;
+  else if (aAtkObj->role == ATK_ROLE_COMMENT && !IsAtkVersionAtLeast(2, 12))
+    aAtkObj->role = ATK_ROLE_SECTION;
+  else if (aAtkObj->role == ATK_ROLE_LANDMARK && !IsAtkVersionAtLeast(2, 12))
+    aAtkObj->role = ATK_ROLE_SECTION;
+  else if (aAtkObj->role == ATK_ROLE_FOOTNOTE && !IsAtkVersionAtLeast(2, 25, 2))
+    aAtkObj->role = ATK_ROLE_SECTION;
   else if (aAtkObj->role == ATK_ROLE_STATIC && !IsAtkVersionAtLeast(2, 16))
     aAtkObj->role = ATK_ROLE_TEXT;
   else if ((aAtkObj->role == ATK_ROLE_MATH_FRACTION ||
             aAtkObj->role == ATK_ROLE_MATH_ROOT) && !IsAtkVersionAtLeast(2, 16))
     aAtkObj->role = ATK_ROLE_SECTION;
 
   return aAtkObj->role;
 }
@@ -743,27 +749,18 @@ ConvertToAtkAttributeSet(nsIPersistentPr
     //libspi will free it
     return objAttributeSet;
 }
 
 AtkAttributeSet*
 GetAttributeSet(Accessible* aAccessible)
 {
   nsCOMPtr<nsIPersistentProperties> attributes = aAccessible->Attributes();
-  if (attributes) {
-    // There is no ATK state for haspopup, must use object attribute to expose
-    // the same info.
-    if (aAccessible->State() & states::HASPOPUP) {
-      nsAutoString unused;
-      attributes->SetStringProperty(NS_LITERAL_CSTRING("haspopup"),
-                                    NS_LITERAL_STRING("true"), unused);
-    }
-
+  if (attributes)
     return ConvertToAtkAttributeSet(attributes);
-  }
 
   return nullptr;
 }
 
 AtkAttributeSet *
 getAttributesCB(AtkObject *aAtkObj)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
--- a/accessible/atk/DocAccessibleWrap.h
+++ b/accessible/atk/DocAccessibleWrap.h
@@ -1,15 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* 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/. */
 
-/* For documentation of the accessibility architecture, 
+/* For documentation of the accessibility architecture,
  * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
  */
 
 #ifndef mozilla_a11y_DocAccessibleWrap_h__
 #define mozilla_a11y_DocAccessibleWrap_h__
 
 #include "DocAccessible.h"
 
--- a/accessible/atk/Platform.cpp
+++ b/accessible/atk/Platform.cpp
@@ -21,17 +21,17 @@
 
 #if (MOZ_WIDGET_GTK == 3)
 extern "C" __attribute__((weak,visibility("default"))) int atk_bridge_adaptor_init(int*, char **[]);
 #endif
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
-int atkMajorVersion = 1, atkMinorVersion = 12;
+int atkMajorVersion = 1, atkMinorVersion = 12, atkMicroVersion = 0;
 
 GType (*gAtkTableCellGetTypeFunc)();
 
 extern "C" {
 typedef GType (* AtkGetTypeType) (void);
 typedef void (*GnomeAccessibilityInit) (void);
 typedef void (*GnomeAccessibilityShutdown) (void);
 }
@@ -163,18 +163,21 @@ a11y::PlatformInit()
 
   const char* (*atkGetVersion)() =
     (const char* (*)()) PR_FindFunctionSymbol(sATKLib, "atk_get_version");
   if (atkGetVersion) {
     const char* version = atkGetVersion();
     if (version) {
       char* endPtr = nullptr;
       atkMajorVersion = strtol(version, &endPtr, 10);
-      if (*endPtr == '.')
+      if (atkMajorVersion != 0L) {
         atkMinorVersion = strtol(endPtr + 1, &endPtr, 10);
+        if (atkMinorVersion != 0L)
+          atkMicroVersion = strtol(endPtr + 1, &endPtr, 10);
+      }
     }
   }
 
 #if (MOZ_WIDGET_GTK == 2)
   // Load and initialize gail library.
   nsresult rv = LoadGtkModule(sGail);
   if (NS_SUCCEEDED(rv))
     (*sGail.init)();
--- a/accessible/atk/TextLeafAccessibleWrap.h
+++ b/accessible/atk/TextLeafAccessibleWrap.h
@@ -6,15 +6,15 @@
 
 #ifndef mozilla_a11y_TextLeafAccessibleWrap_h__
 #define mozilla_a11y_TextLeafAccessibleWrap_h__
 
 #include "TextLeafAccessible.h"
 
 namespace mozilla {
 namespace a11y {
- 
+
 typedef class TextLeafAccessible TextLeafAccessibleWrap;
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/atk/nsMai.h
+++ b/accessible/atk/nsMai.h
@@ -70,27 +70,29 @@ typedef struct _MaiAtkSocketClass
 extern "C" GType (*gAtkTableCellGetTypeFunc)();
 
 mozilla::a11y::AccessibleWrap* GetAccessibleWrap(AtkObject* aAtkObj);
 mozilla::a11y::ProxyAccessible* GetProxy(AtkObject* aAtkObj);
 mozilla::a11y::AccessibleOrProxy GetInternalObj(AtkObject* aObj);
 AtkObject* GetWrapperFor(mozilla::a11y::ProxyAccessible* aProxy);
 AtkObject* GetWrapperFor(mozilla::a11y::AccessibleOrProxy aObj);
 
-extern int atkMajorVersion, atkMinorVersion;
+extern int atkMajorVersion, atkMinorVersion, atkMicroVersion;
 
 /**
  * Return true if the loaded version of libatk-1.0.so is at least
- * aMajor.aMinor.0.
+ * aMajor.aMinor.aMicro.
  */
 static inline bool
-IsAtkVersionAtLeast(int aMajor, int aMinor)
+IsAtkVersionAtLeast(int aMajor, int aMinor, int aMicro=0)
 {
   return aMajor < atkMajorVersion ||
-         (aMajor == atkMajorVersion && aMinor <= atkMinorVersion);
+         (aMajor == atkMajorVersion &&
+          (aMinor < atkMinorVersion ||
+           (aMinor == atkMinorVersion && aMicro <= atkMicroVersion)));
 }
 
 // This is or'd with the pointer in MaiAtkObject::accWrap if the wrap-ee is a
 // proxy.
 static const uintptr_t IS_PROXY = 1;
 
 /**
  * This MaiAtkObject is a thin wrapper, in the MAI namespace, for AtkObject
--- a/accessible/atk/nsMaiInterfaceText.cpp
+++ b/accessible/atk/nsMaiInterfaceText.cpp
@@ -121,17 +121,17 @@ ConvertToAtkTextAttributeSet(nsIPersiste
 
   // libatk-adaptor will free it
   return objAttributeSet;
 }
 
 static void
 ConvertTexttoAsterisks(AccessibleWrap* accWrap, nsAString& aString)
 {
-  // convert each char to "*" when it's "password text" 
+  // convert each char to "*" when it's "password text"
   if (accWrap->NativeRole() == roles::PASSWORD_TEXT) {
     for (uint32_t i = 0; i < aString.Length(); i++)
       aString.Replace(i, 1, NS_LITERAL_STRING("*"));
   }
 }
 
 extern "C" {
 
--- a/accessible/atk/nsStateMap.h
+++ b/accessible/atk/nsStateMap.h
@@ -18,28 +18,25 @@ The following accessible states aren't t
                          The nsIAccessible state is not currently supported.
   STATE_SELFVOICING:     No ATK equivalent -- the object has self-TTS.
                          The nsIAccessible state is not currently supported.
   STATE_LINKED:          The object is formatted as a hyperlink. Supported via ATK_ROLE_LINK.
   STATE_EXTSELECTABLE:   Indicates that an object extends its selection.
                          This is supported via STATE_MULTISELECTABLE.
   STATE_PROTECTED:       The object is a password-protected edit control.
                          Supported via ATK_ROLE_PASSWORD_TEXT
-  STATE_HASPOPUP:        Object displays a pop-up menu or window when invoked.
-                         No ATK equivalent. The accessible state is not
-                         currently supported.
   STATE_PINNED:          The object is pinned, usually indicating it is fixed in
                          place and has permanence. No ATK equivalent. The
                          accessible state is not currently supported.
 
 The following ATK states are not supported:
   ATK_STATE_ARMED:       No clear use case, used briefly when button is activated
   ATK_STATE_HAS_TOOLTIP: No clear use case, no IA2 equivalent
   ATK_STATE_ICONIFIED:   Mozilla does not have elements which are collapsable into icons
-  ATK_STATE_TRUNCATED:   No clear use case. Indicates that an object's onscreen content is truncated, 
+  ATK_STATE_TRUNCATED:   No clear use case. Indicates that an object's onscreen content is truncated,
                          e.g. a text value in a spreadsheet cell. No IA2 state.
 ******************************************************************************/
 
 enum EStateMapEntryType {
   kMapDirectly,
   kMapOpposite,   // For example, UNAVAILABLE is the opposite of ENABLED
   kNoStateChange, // Don't fire state change event
   kNoSuchState
@@ -90,17 +87,17 @@ static const AtkStateMap gAtkStateMap[] 
   { kNone,                                    kMapDirectly },   // states::LINKED                  = 1 << 22
   { ATK_STATE_VISITED,                        kMapDirectly },   // states::TRAVERSED               = 1 << 23
   { ATK_STATE_MULTISELECTABLE,                kMapDirectly },   // states::MULTISELECTABLE         = 1 << 24
   { kNone,                                    kMapDirectly },   // states::EXTSELECTABLE           = 1 << 25
   { ATK_STATE_REQUIRED,                       kMapDirectly },   // states::STATE_REQUIRED          = 1 << 26
   { kNone,                                    kMapDirectly },   // states::ALERT_MEDIUM            = 1 << 27
   { ATK_STATE_INVALID_ENTRY,                  kMapDirectly },   // states::INVALID                 = 1 << 28
   { kNone,                                    kMapDirectly },   // states::PROTECTED               = 1 << 29
-  { kNone,                                    kMapDirectly },   // states::HASPOPUP                = 1 << 30
+  { ATK_STATE_HAS_POPUP,                      kMapDirectly },   // states::HASPOPUP                = 1 << 30
   { ATK_STATE_SUPPORTS_AUTOCOMPLETION,        kMapDirectly },   // states::SUPPORTS_AUTOCOMPLETION = 1 << 31
   { ATK_STATE_DEFUNCT,                        kMapDirectly },   // states::DEFUNCT                 = 1 << 32
   { ATK_STATE_SELECTABLE_TEXT,                kMapDirectly },   // states::SELECTABLE_TEXT         = 1 << 33
   { ATK_STATE_EDITABLE,                       kMapDirectly },   // states::EDITABLE                = 1 << 34
   { ATK_STATE_ACTIVE,                         kMapDirectly },   // states::ACTIVE                  = 1 << 35
   { ATK_STATE_MODAL,                          kMapDirectly },   // states::MODAL                   = 1 << 36
   { ATK_STATE_MULTI_LINE,                     kMapDirectly },   // states::MULTI_LINE              = 1 << 37
   { ATK_STATE_HORIZONTAL,                     kMapDirectly },   // states::HORIZONTAL              = 1 << 38
@@ -108,10 +105,11 @@ static const AtkStateMap gAtkStateMap[] 
   { ATK_STATE_SINGLE_LINE,                    kMapDirectly },   // states::SINGLE_LINE             = 1 << 40
   { ATK_STATE_TRANSIENT,                      kMapDirectly },   // states::TRANSIENT               = 1 << 41
   { ATK_STATE_VERTICAL,                       kMapDirectly },   // states::VERTICAL                = 1 << 42
   { ATK_STATE_STALE,                          kMapDirectly },   // states::STALE                   = 1 << 43
   { ATK_STATE_ENABLED,                        kMapDirectly },   // states::ENABLED                 = 1 << 44
   { ATK_STATE_SENSITIVE,                      kMapDirectly },   // states::SENSITIVE               = 1 << 45
   { ATK_STATE_EXPANDABLE,                     kMapDirectly },   // states::EXPANDABLE              = 1 << 46
   { kNone,                                    kMapDirectly },   // states::PINNED                  = 1 << 47
-  { kNone,                                    kNoSuchState },   //                                 = 1 << 48
+  { ATK_STATE_ACTIVE,                         kMapDirectly },   // states::CURRENT                 = 1 << 48
+  { kNone,                                    kNoSuchState },   //                                 = 1 << 49
 };
--- a/accessible/base/ARIAMap.cpp
+++ b/accessible/base/ARIAMap.cpp
@@ -64,17 +64,17 @@ static const nsRoleMapEntry sWAIRoleMaps
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     eLandmark,
     kNoReqStates
   },
   { // article
     &nsGkAtoms::article,
-    roles::DOCUMENT,
+    roles::ARTICLE,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kGenericAccType,
     kNoReqStates,
     eReadonlyUntilEditable
   },
@@ -128,25 +128,25 @@ static const nsRoleMapEntry sWAIRoleMaps
     eNoValue,
     eSortAction,
     eNoLiveAttr,
     eTableCell,
     kNoReqStates,
     eARIASelectableIfDefined,
     eARIAReadonlyOrEditableIfDefined
   },
-  { // combobox
+  { // combobox, which consists of text input and popup
     &nsGkAtoms::combobox,
-    roles::COMBOBOX,
+    roles::EDITCOMBOBOX,
     kUseMapRole,
     eNoValue,
     eOpenCloseAction,
     eNoLiveAttr,
-    kGenericAccType,
-    states::COLLAPSED | states::HASPOPUP | states::VERTICAL,
+    eCombobox,
+    states::COLLAPSED | states::HASPOPUP,
     eARIAAutoComplete,
     eARIAReadonly,
     eARIAOrientation
   },
   { // complementary
     &nsGkAtoms::complementary,
     roles::NOTHING,
     kUseNativeRole,
@@ -181,16 +181,406 @@ static const nsRoleMapEntry sWAIRoleMaps
     roles::LIST,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     eList,
     states::READONLY
   },
+  { // doc-abstract
+    &nsGkAtoms::docAbstract,
+    roles::SECTION,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    kNoReqStates
+  },
+  { // doc-acknowledgments
+    &nsGkAtoms::docAcknowledgments,
+    roles::LANDMARK,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
+  { // doc-afterword
+    &nsGkAtoms::docAfterword,
+    roles::LANDMARK,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
+  { // doc-appendix
+    &nsGkAtoms::docAppendix,
+    roles::LANDMARK,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
+  { // doc-backlink
+    &nsGkAtoms::docBacklink,
+    roles::LINK,
+    kUseMapRole,
+    eNoValue,
+    eJumpAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    states::LINKED
+  },
+  { // doc-biblioentry
+    &nsGkAtoms::docBiblioentry,
+    roles::LISTITEM,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    states::READONLY
+  },
+  { // doc-bibliography
+    &nsGkAtoms::docBibliography,
+    roles::LANDMARK,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
+  { // doc-biblioref
+    &nsGkAtoms::docBiblioref,
+    roles::LINK,
+    kUseMapRole,
+    eNoValue,
+    eJumpAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    states::LINKED
+  },
+  { // doc-chapter
+    &nsGkAtoms::docChapter,
+    roles::LANDMARK,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
+  { // doc-colophon
+    &nsGkAtoms::docColophon,
+    roles::SECTION,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    kNoReqStates
+  },
+  { // doc-conclusion
+    &nsGkAtoms::docConclusion,
+    roles::LANDMARK,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
+  { // doc-cover
+    &nsGkAtoms::docCover,
+    roles::GRAPHIC,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    kNoReqStates
+  },
+  { // doc-credit
+    &nsGkAtoms::docCredit,
+    roles::SECTION,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    kNoReqStates
+  },
+  { // doc-credits
+    &nsGkAtoms::docCredits,
+    roles::LANDMARK,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
+  { // doc-dedication
+    &nsGkAtoms::docDedication,
+    roles::SECTION,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    kNoReqStates
+  },
+  { // doc-endnote
+    &nsGkAtoms::docEndnote,
+    roles::LISTITEM,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    states::READONLY
+  },
+  { // doc-endnotes
+    &nsGkAtoms::docEndnotes,
+    roles::LANDMARK,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
+  { // doc-epigraph
+    &nsGkAtoms::docEpigraph,
+    roles::SECTION,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    kNoReqStates
+  },
+  { // doc-epilogue
+    &nsGkAtoms::docEpilogue,
+    roles::LANDMARK,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
+  { // doc-errata
+    &nsGkAtoms::docErrata,
+    roles::LANDMARK,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
+  { // doc-example
+    &nsGkAtoms::docExample,
+    roles::SECTION,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    kNoReqStates
+  },
+  { // doc-footnote
+    &nsGkAtoms::docFootnote,
+    roles::FOOTNOTE,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
+  { // doc-foreword
+    &nsGkAtoms::docForeword,
+    roles::LANDMARK,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
+  { // doc-glossary
+    &nsGkAtoms::docGlossary,
+    roles::LANDMARK,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
+  { // doc-glossref
+    &nsGkAtoms::docGlossref,
+    roles::LINK,
+    kUseMapRole,
+    eNoValue,
+    eJumpAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    states::LINKED
+  },
+  { // doc-index
+    &nsGkAtoms::docIndex,
+    roles::NAVIGATION,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
+  { // doc-introduction
+    &nsGkAtoms::docIntroduction,
+    roles::LANDMARK,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
+  { // doc-noteref
+    &nsGkAtoms::docNoteref,
+    roles::LINK,
+    kUseMapRole,
+    eNoValue,
+    eJumpAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    states::LINKED
+  },
+  { // doc-notice
+    &nsGkAtoms::docNotice,
+    roles::NOTE,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    kNoReqStates
+  },
+  { // doc-pagebreak
+    &nsGkAtoms::docPagebreak,
+    roles::SEPARATOR,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    kNoReqStates
+  },
+  { // doc-pagelist
+    &nsGkAtoms::docPagelist,
+    roles::NAVIGATION,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
+  { // doc-part
+    &nsGkAtoms::docPart,
+    roles::LANDMARK,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
+  { // doc-preface
+    &nsGkAtoms::docPreface,
+    roles::LANDMARK,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
+  { // doc-prologue
+    &nsGkAtoms::docPrologue,
+    roles::LANDMARK,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
+  { // doc-pullquote
+    &nsGkAtoms::docPullquote,
+    roles::SECTION,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    kNoReqStates
+  },
+  { // doc-qna
+    &nsGkAtoms::docQna,
+    roles::SECTION,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    kNoReqStates
+  },
+  { // doc-subtitle
+    &nsGkAtoms::docSubtitle,
+    roles::HEADING,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    kNoReqStates
+  },
+  { // doc-tip
+    &nsGkAtoms::docTip,
+    roles::NOTE,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    kNoReqStates
+  },
+  { // doc-toc
+    &nsGkAtoms::docToc,
+    roles::NAVIGATION,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
   { // document
     &nsGkAtoms::document,
     roles::DOCUMENT,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kGenericAccType,
@@ -202,16 +592,26 @@ static const nsRoleMapEntry sWAIRoleMaps
     roles::GROUPING,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kGenericAccType,
     kNoReqStates
   },
+  { // figure
+    &nsGkAtoms::figure,
+    roles::FIGURE,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    kNoReqStates
+  },
   { // form
     &nsGkAtoms::form,
     roles::FORM,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     eLandmark,
@@ -393,40 +793,41 @@ static const nsRoleMapEntry sWAIRoleMaps
   { // menuitem
     &nsGkAtoms::menuitem,
     roles::MENUITEM,
     kUseMapRole,
     eNoValue,
     eClickAction,
     eNoLiveAttr,
     kGenericAccType,
-    kNoReqStates,
-    eARIACheckedMixed
+    kNoReqStates
   },
   { // menuitemcheckbox
     &nsGkAtoms::menuitemcheckbox,
     roles::CHECK_MENU_ITEM,
     kUseMapRole,
     eNoValue,
     eClickAction,
     eNoLiveAttr,
     kGenericAccType,
     kNoReqStates,
-    eARIACheckableMixed
+    eARIACheckableMixed,
+    eARIAReadonly
   },
   { // menuitemradio
     &nsGkAtoms::menuitemradio,
     roles::RADIO_MENU_ITEM,
     kUseMapRole,
     eNoValue,
     eClickAction,
     eNoLiveAttr,
     kGenericAccType,
     kNoReqStates,
-    eARIACheckableBool
+    eARIACheckableBool,
+    eARIAReadonly
   },
   { // navigation
     &nsGkAtoms::navigation,
     roles::NOTHING,
     kUseNativeRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
@@ -501,26 +902,27 @@ static const nsRoleMapEntry sWAIRoleMaps
     &nsGkAtoms::radiogroup,
     roles::RADIO_GROUP,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kGenericAccType,
     kNoReqStates,
-    eARIAOrientation
+    eARIAOrientation,
+    eARIAReadonly
   },
   { // region
     &nsGkAtoms::region,
-    roles::PANE,
+    roles::REGION,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
-    kGenericAccType,
+    eLandmark,
     kNoReqStates
   },
   { // row
     &nsGkAtoms::row,
     roles::ROW,
     kUseMapRole,
     eNoValue,
     eNoAction,
@@ -585,17 +987,17 @@ static const nsRoleMapEntry sWAIRoleMaps
     eARIAAutoComplete,
     eARIAMultiline,
     eARIAReadonlyOrEditable
   },
   { // separator
     &nsGkAtoms::separator_,
     roles::SEPARATOR,
     kUseMapRole,
-    eNoValue,
+    eHasValueMinMaxIfFocusable,
     eNoAction,
     eNoLiveAttr,
     kGenericAccType,
     states::HORIZONTAL,
     eARIAOrientation
   },
   { // slider
     &nsGkAtoms::slider,
@@ -634,17 +1036,18 @@ static const nsRoleMapEntry sWAIRoleMaps
     &nsGkAtoms::_switch,
     roles::SWITCH,
     kUseMapRole,
     eNoValue,
     eCheckUncheckAction,
     eNoLiveAttr,
     kGenericAccType,
     kNoReqStates,
-    eARIACheckableBool
+    eARIACheckableBool,
+    eARIAReadonly
   },
   { // tab
     &nsGkAtoms::tab,
     roles::PAGETAB,
     kUseMapRole,
     eNoValue,
     eSwitchAction,
     eNoLiveAttr,
@@ -679,16 +1082,26 @@ static const nsRoleMapEntry sWAIRoleMaps
     roles::PROPERTYPAGE,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kGenericAccType,
     kNoReqStates
   },
+  { // term
+    &nsGkAtoms::term,
+    roles::TERM,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    states::READONLY
+  },
   { // textbox
     &nsGkAtoms::textbox,
     roles::ENTRY,
     kUseMapRole,
     eNoValue,
     eActivateAction,
     eNoLiveAttr,
     kGenericAccType,
@@ -744,17 +1157,17 @@ static const nsRoleMapEntry sWAIRoleMaps
   { // treegrid
     &nsGkAtoms::treegrid,
     roles::TREE_TABLE,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     eSelect | eTable,
-    states::VERTICAL,
+    kNoReqStates,
     eARIAReadonlyOrEditable,
     eARIAMultiSelectable,
     eFocusableUntilDisabled,
     eARIAOrientation
   },
   { // treeitem
     &nsGkAtoms::treeitem,
     roles::OUTLINEITEM,
@@ -794,16 +1207,17 @@ nsRoleMapEntry aria::gEmptyRoleMap = {
 
 /**
  * Universal (Global) states:
  * The following state rules are applied to any accessible element,
  * whether there is an ARIA role or not:
  */
 static const EStateRule sWAIUnivStateMap[] = {
   eARIABusy,
+  eARIACurrent,
   eARIADisabled,
   eARIAExpanded,  // Currently under spec review but precedent exists
   eARIAHasPopup,  // Note this is technically a "property"
   eARIAInvalid,
   eARIAModal,
   eARIARequired,  // XXX not global, Bug 553117
   eARIANone
 };
--- a/accessible/base/ARIAMap.h
+++ b/accessible/base/ARIAMap.h
@@ -29,17 +29,25 @@ enum EValueRule
    * Value interface isn't exposed.
    */
   eNoValue,
 
   /**
    * Value interface is implemented, supports value, min and max from
    * aria-valuenow, aria-valuemin and aria-valuemax.
    */
-  eHasValueMinMax
+  eHasValueMinMax,
+
+  /**
+   * Value interface is implemented, but only if the element is focusable.
+   * For instance, in ARIA 1.1 the ability for authors to create adjustable
+   * splitters was provided by supporting the value interface on separators
+   * that are focusable. Non-focusable separators expose no value information.
+   */
+  eHasValueMinMaxIfFocusable
 };
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // Action constants
 
 /**
  * Used to define if the role requires to expose action.
--- a/accessible/base/ARIAStateMap.cpp
+++ b/accessible/base/ARIAStateMap.cpp
@@ -140,16 +140,26 @@ aria::MapToState(EStateRule aRule, dom::
       static const TokenTypeData data(
         nsGkAtoms::aria_checked, eMixedType,
         states::CHECKABLE, states::CHECKED);
 
       MapTokenType(aElement, aState, data);
       return true;
     }
 
+    case eARIACurrent:
+    {
+      static const TokenTypeData data(
+        nsGkAtoms::aria_current, eBoolType,
+        0, states::CURRENT);
+
+      MapTokenType(aElement, aState, data);
+      return true;
+    }
+
     case eARIADisabled:
     {
       static const TokenTypeData data(
         nsGkAtoms::aria_disabled, eBoolType,
         0, states::UNAVAILABLE);
 
       MapTokenType(aElement, aState, data);
       return true;
@@ -349,20 +359,22 @@ MapEnumType(dom::Element* aElement, uint
   }
 }
 
 static void
 MapTokenType(dom::Element* aElement, uint64_t* aState,
              const TokenTypeData& aData)
 {
   if (nsAccUtils::HasDefinedARIAToken(aElement, aData.mAttrName)) {
-    if ((aData.mType & eMixedType) &&
-        aElement->AttrValueIs(kNameSpaceID_None, aData.mAttrName,
+    if (aElement->AttrValueIs(kNameSpaceID_None, aData.mAttrName,
                               nsGkAtoms::mixed, eCaseMatters)) {
-      *aState |= aData.mPermanentState | states::MIXED;
+      if (aData.mType & eMixedType)
+        *aState |= aData.mPermanentState | states::MIXED;
+      else // unsupported use of 'mixed' is an authoring error
+        *aState |= aData.mPermanentState | aData.mFalseState;
       return;
     }
 
     if (aElement->AttrValueIs(kNameSpaceID_None, aData.mAttrName,
                               nsGkAtoms::_false, eCaseMatters)) {
       *aState |= aData.mPermanentState | aData.mFalseState;
       return;
     }
--- a/accessible/base/ARIAStateMap.h
+++ b/accessible/base/ARIAStateMap.h
@@ -24,16 +24,17 @@ namespace aria {
 enum EStateRule
 {
   eARIANone,
   eARIAAutoComplete,
   eARIABusy,
   eARIACheckableBool,
   eARIACheckableMixed,
   eARIACheckedMixed,
+  eARIACurrent,
   eARIADisabled,
   eARIAExpanded,
   eARIAHasPopup,
   eARIAInvalid,
   eARIAModal,
   eARIAMultiline,
   eARIAMultiSelectable,
   eARIAOrientation,
--- a/accessible/base/FocusManager.cpp
+++ b/accessible/base/FocusManager.cpp
@@ -31,17 +31,17 @@ FocusManager::~FocusManager()
 Accessible*
 FocusManager::FocusedAccessible() const
 {
   if (mActiveItem)
     return mActiveItem;
 
   nsINode* focusedNode = FocusedDOMNode();
   if (focusedNode) {
-    DocAccessible* doc = 
+    DocAccessible* doc =
       GetAccService()->GetDocAccessible(focusedNode->OwnerDoc());
     return doc ? doc->GetAccessibleEvenIfNotInMapOrContainer(focusedNode) : nullptr;
   }
 
   return nullptr;
 }
 
 bool
@@ -54,17 +54,17 @@ FocusManager::IsFocused(const Accessible
   if (focusedNode) {
     // XXX: Before getting an accessible for node having a DOM focus make sure
     // they belong to the same document because it can trigger unwanted document
     // accessible creation for temporary about:blank document. Without this
     // peculiarity we would end up with plain implementation based on
     // FocusedAccessible() method call. Make sure this issue is fixed in
     // bug 638465.
     if (focusedNode->OwnerDoc() == aAccessible->GetNode()->OwnerDoc()) {
-      DocAccessible* doc = 
+      DocAccessible* doc =
         GetAccService()->GetDocAccessible(focusedNode->OwnerDoc());
       return aAccessible ==
         (doc ? doc->GetAccessibleEvenIfNotInMapOrContainer(focusedNode) : nullptr);
     }
   }
   return false;
 }
 
@@ -186,31 +186,29 @@ FocusManager::ActiveItemChanged(Accessib
     if (logging::IsEnabled(logging::eFocus))
       logging::ActiveWidget(widget);
 #endif
     if (!widget || !widget->IsActiveWidget() || !widget->AreItemsOperable())
       return;
   }
   mActiveItem = aItem;
 
-  // If mActiveItem is null, we might need to shift a11y focus to a remote
-  // element.
+  // If mActiveItem is null we may need to shift a11y focus back to a tab
+  // document. For example, when combobox popup is closed, then
+  // the focus should be moved back to the combobox.
   if (!mActiveItem && XRE_IsParentProcess()) {
     nsFocusManager* domfm = nsFocusManager::GetFocusManager();
     if (domfm) {
       nsIContent* focusedElm = domfm->GetFocusedContent();
-      if (focusedElm) {
-        bool remote = EventStateManager::IsRemoteTarget(focusedElm);
-        if (remote) {
-          dom::TabParent* tab = dom::TabParent::GetFrom(focusedElm);
-          if (tab) {
-            a11y::DocAccessibleParent* dap = tab->GetTopLevelDocAccessible();
-            if (dap) {
-              Unused << dap->SendRestoreFocus();
-            }
+      if (EventStateManager::IsRemoteTarget(focusedElm)) {
+        dom::TabParent* tab = dom::TabParent::GetFrom(focusedElm);
+        if (tab) {
+          a11y::DocAccessibleParent* dap = tab->GetTopLevelDocAccessible();
+          if (dap) {
+            Unused << dap->SendRestoreFocus();
           }
         }
       }
     }
   }
 
   // If active item is changed then fire accessible focus event on it, otherwise
   // if there's no an active item then fire focus event to accessible having
--- a/accessible/base/Logging.cpp
+++ b/accessible/base/Logging.cpp
@@ -1021,17 +1021,17 @@ logging::IsEnabled(const nsAString& aMod
     if (aModuleStr.EqualsASCII(sModuleMap[idx].mStr))
       return sModules & sModuleMap[idx].mModule;
   }
 
   return false;
 }
 
 void
-logging::Enable(const nsAFlatCString& aModules)
+logging::Enable(const nsCString& aModules)
 {
   EnableLogging(aModules.get());
 }
 
 
 void
 logging::CheckEnv()
 {
--- a/accessible/base/Logging.h
+++ b/accessible/base/Logging.h
@@ -204,17 +204,17 @@ void DOMEvent(const char* aDescr, nsINod
 /**
  * Log the call stack, two spaces offset is used.
  */
 void Stack();
 
 /**
  * Enable logging of the specified modules, all other modules aren't logged.
  */
-void Enable(const nsAFlatCString& aModules);
+void Enable(const nsCString& aModules);
 
 /**
  * Enable logging of modules specified by A11YLOG environment variable,
  * all other modules aren't logged.
  */
 void CheckEnv();
 
 } // namespace logging
--- a/accessible/base/MarkupMap.h
+++ b/accessible/base/MarkupMap.h
@@ -14,17 +14,17 @@ MARKUPMAP(abbr,
           0)
 
 MARKUPMAP(acronym,
           New_HyperText,
           0)
 
 MARKUPMAP(article,
           New_HyperText,
-          roles::DOCUMENT,
+          roles::ARTICLE,
           Attr(xmlroles, article))
 
 MARKUPMAP(aside,
           New_HyperText,
           roles::NOTE)
 
 MARKUPMAP(blockquote,
           New_HyperText,
--- a/accessible/base/NotificationController.cpp
+++ b/accessible/base/NotificationController.cpp
@@ -266,16 +266,18 @@ void
 NotificationController::DropMutationEvent(AccTreeMutationEvent* aEvent)
 {
   // unset the event bits since the event isn't being fired any more.
   if (aEvent->GetEventType() == nsIAccessibleEvent::EVENT_REORDER) {
     aEvent->GetAccessible()->SetReorderEventTarget(false);
   } else if (aEvent->GetEventType() == nsIAccessibleEvent::EVENT_SHOW) {
     aEvent->GetAccessible()->SetShowEventTarget(false);
   } else {
+    aEvent->GetAccessible()->SetHideEventTarget(false);
+
     AccHideEvent* hideEvent = downcast_accEvent(aEvent);
     MOZ_ASSERT(hideEvent);
 
     if (hideEvent->NeedsShutdown()) {
       mDocument->ShutdownChildrenInSubtree(aEvent->GetAccessible());
     }
   }
 
@@ -585,17 +587,17 @@ NotificationController::ProcessMutationE
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // NotificationCollector: private
 
 void
 NotificationController::WillRefresh(mozilla::TimeStamp aTime)
 {
-  PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);
+  AUTO_PROFILER_LABEL("NotificationController::WillRefresh", OTHER);
 
   // If the document accessible that notification collector was created for is
   // now shut down, don't process notifications anymore.
   NS_ASSERTION(mDocument,
                "The document was shut down while refresh observer is attached!");
   if (!mDocument)
     return;
 
--- a/accessible/base/Platform.h
+++ b/accessible/base/Platform.h
@@ -39,16 +39,20 @@ void PreInit();
 #if defined(MOZ_ACCESSIBILITY_ATK) || defined(XP_MACOSX)
 /**
  * Is platform accessibility enabled.
  * Only used on linux with atk and MacOS for now.
  */
 bool ShouldA11yBeEnabled();
 #endif
 
+#if defined(XP_WIN)
+bool IsHandlerRegistered();
+#endif
+
 /**
  * Called to initialize platform specific accessibility support.
  * Note this is called after internal accessibility support is initialized.
  */
 void PlatformInit();
 
 /**
  * Shutdown platform accessibility.
--- a/accessible/base/RelationTypeMap.h
+++ b/accessible/base/RelationTypeMap.h
@@ -118,37 +118,43 @@ RELATIONTYPE(CONTAINING_DOCUMENT,
              IA2_RELATION_CONTAINING_DOCUMENT)
 
 RELATIONTYPE(CONTAINING_TAB_PANE,
              "containing tab pane",
              ATK_RELATION_NULL,
              NAVRELATION_CONTAINING_TAB_PANE,
              IA2_RELATION_CONTAINING_TAB_PANE)
 
+RELATIONTYPE(CONTAINING_WINDOW,
+             "containing window",
+             ATK_RELATION_NULL,
+             NAVRELATION_CONTAINING_WINDOW,
+             IA2_RELATION_CONTAINING_WINDOW)
+
 RELATIONTYPE(CONTAINING_APPLICATION,
              "containing application",
              ATK_RELATION_NULL,
              NAVRELATION_CONTAINING_APPLICATION,
              IA2_RELATION_CONTAINING_APPLICATION)
 
 RELATIONTYPE(DETAILS,
              "details",
-             ATK_RELATION_NULL,
+             ATK_RELATION_DETAILS,
              NAVRELATION_DETAILS,
              IA2_RELATION_DETAILS)
 
 RELATIONTYPE(DETAILS_FOR,
              "details for",
-             ATK_RELATION_NULL,
+             ATK_RELATION_DETAILS_FOR,
              NAVRELATION_DETAILS_FOR,
              IA2_RELATION_DETAILS_FOR)
 
 RELATIONTYPE(ERRORMSG,
              "error",
-             ATK_RELATION_NULL,
+             ATK_RELATION_ERROR_MESSAGE,
              NAVRELATION_ERROR,
              IA2_RELATION_ERROR)
 
 RELATIONTYPE(ERRORMSG_FOR,
              "error for",
-             ATK_RELATION_NULL,
+             ATK_RELATION_ERROR_FOR,
              NAVRELATION_ERROR_FOR,
              IA2_RELATION_ERROR_FOR)
--- a/accessible/base/Role.h
+++ b/accessible/base/Role.h
@@ -125,17 +125,17 @@ enum Role {
   PANE = 16,
 
   /**
    * Represents a graphical image used to represent data.
    */
   CHART = 17,
 
   /**
-   * Represents a dialog box or message box. It is used for xul:dialog, 
+   * Represents a dialog box or message box. It is used for xul:dialog,
    * role="dialog".
    */
   DIALOG = 18,
 
   /**
    * Represents a window border.
    */
   BORDER = 19,
@@ -290,30 +290,30 @@ enum Role {
    */
   PUSHBUTTON = 43,
 
   /**
    * Represents a check box control. It is used for xul:checkbox,
    * html:input@type="checkbox", role="checkbox".
    */
   CHECKBUTTON = 44,
-  
+
   /**
    * Represents an option button, also called a radio button. It is one of a
    * group of mutually exclusive options. All objects sharing a single parent
    * that have this attribute are assumed to be part of single mutually
    * exclusive group. It is used for xul:radio, html:input@type="radio",
    * role="radio".
    */
   RADIOBUTTON = 45,
-  
+
   /**
-   * Represents a combo box; an edit control with an associated list box that
-   * provides a set of predefined choices. It is used for html:select,
-   * xul:menulist, role="combobox".
+   * Represents a combo box; a popup button with an associated list box that
+   * provides a set of predefined choices. It is used for html:select with a
+   * size of 1 and xul:menulist. See also ROLE_EDITCOMBOBOX.
    */
   COMBOBOX = 46,
 
   /**
    * Represents the calendar control.
    */
   DROPLIST = 47,
 
@@ -348,17 +348,17 @@ enum Role {
    * with the spin box. It is used for xul:spinbuttons.
    */
   SPINBUTTON = 52,
 
   /**
    * Represents a graphical image used to diagram data. It is used for svg:svg.
    */
   DIAGRAM = 53,
-  
+
   /**
    * Represents an animation control, which contains content that changes over
    * time, such as a control that displays a series of bitmap frames.
    */
   ANIMATION = 54,
 
   /**
    * Represents a mathematical equation. It is used by MATHML, where there is a
@@ -977,17 +977,56 @@ enum Role {
    */
   DETAILS = 167,
 
   /**
    * The html:summary element.
    */
   SUMMARY = 168,
 
-  LAST_ROLE = SUMMARY
+  /**
+   * An ARIA landmark. See related NAVIGATION role.
+   */
+  LANDMARK = 169,
+
+  /**
+   * A specific type of ARIA landmark. The ability to distinguish navigation
+   * landmarks from other types of landmarks is, for example, needed on macOS
+   * where specific AXSubrole and AXRoleDescription for navigation landmarks
+   * are used.
+   */
+  NAVIGATION = 170,
+
+  /**
+   * An object that contains the text of a footnote.
+   */
+  FOOTNOTE = 171,
+
+  /**
+   * A complete or self-contained composition in a document, page, application,
+   * or site and that is, in principle, independently distributable or reusable,
+   * e.g. in syndication.
+   */
+  ARTICLE = 172,
+
+  /**
+   * A perceivable section containing content that is relevant to a specific,
+   * author-specified purpose and sufficiently important that users will likely
+   * want to be able to navigate to the section easily and to have it listed in
+   * a summary of the page.
+   */
+  REGION = 173,
+
+  /**
+   * Represents a control with a text input and a popup with a set of predefined
+   * choices. It is used for ARIA's combobox role. See also COMBOBOX.
+   */
+  EDITCOMBOBOX = 174,
+
+  LAST_ROLE = EDITCOMBOBOX
 };
 
 } // namespace role
 
 typedef enum mozilla::a11y::roles::Role role;
 
 } // namespace a11y
 } // namespace mozilla
--- a/accessible/base/RoleMap.h
+++ b/accessible/base/RoleMap.h
@@ -301,18 +301,18 @@ ROLE(OUTLINE,
      ATK_ROLE_TREE,
      NSAccessibilityOutlineRole,
      ROLE_SYSTEM_OUTLINE,
      ROLE_SYSTEM_OUTLINE,
      eNoNameRule)
 
 ROLE(OUTLINEITEM,
      "outlineitem",
-     ATK_ROLE_LIST_ITEM,
-     NSAccessibilityRowRole,  //XXX: use OutlineRow as subrole.
+     ATK_ROLE_TREE_ITEM,
+     NSAccessibilityRowRole,
      ROLE_SYSTEM_OUTLINEITEM,
      ROLE_SYSTEM_OUTLINEITEM,
      eNameFromSubtreeRule)
 
 ROLE(PAGETAB,
      "pagetab",
      ATK_ROLE_PAGE_TAB,
      NSAccessibilityRadioButtonRole,
@@ -379,16 +379,17 @@ ROLE(CHECKBUTTON,
 ROLE(RADIOBUTTON,
      "radiobutton",
      ATK_ROLE_RADIO_BUTTON,
      NSAccessibilityRadioButtonRole,
      ROLE_SYSTEM_RADIOBUTTON,
      ROLE_SYSTEM_RADIOBUTTON,
      eNameFromSubtreeRule)
 
+// Equivalent of HTML select element with size="1". See also EDITCOMBOBOX.
 ROLE(COMBOBOX,
      "combobox",
      ATK_ROLE_COMBO_BOX,
      NSAccessibilityPopUpButtonRole,
      ROLE_SYSTEM_COMBOBOX,
      ROLE_SYSTEM_COMBOBOX,
      eNameFromValueRule)
 
@@ -997,17 +998,17 @@ ROLE(EMBEDDED_OBJECT,
      ATK_ROLE_PANEL,
      NSAccessibilityGroupRole,
      USE_ROLE_STRING,
      IA2_ROLE_EMBEDDED_OBJECT,
      eNoNameRule)
 
 ROLE(NOTE,
      "note",
-     ATK_ROLE_SECTION,
+     ATK_ROLE_COMMENT,
      NSAccessibilityGroupRole,
      USE_ROLE_STRING,
      IA2_ROLE_NOTE,
      eNameFromSubtreeIfReqRule)
 
 ROLE(FIGURE,
      "figure",
      ATK_ROLE_PANEL,
@@ -1029,17 +1030,17 @@ ROLE(DEFINITION_LIST,
      ATK_ROLE_LIST,
      NSAccessibilityListRole,
      ROLE_SYSTEM_LIST,
      ROLE_SYSTEM_LIST,
      eNameFromSubtreeIfReqRule)
 
 ROLE(TERM,
      "term",
-     ATK_ROLE_LIST_ITEM,
+     ATK_ROLE_DESCRIPTION_TERM,
      NSAccessibilityGroupRole,
      ROLE_SYSTEM_LISTITEM,
      ROLE_SYSTEM_LISTITEM,
      eNameFromSubtreeRule)
 
 ROLE(DEFINITION,
      "definition",
      ATK_ROLE_PARAGRAPH,
@@ -1363,8 +1364,57 @@ ROLE(DETAILS,
 ROLE(SUMMARY,
      "summary",
      ATK_ROLE_PUSH_BUTTON,
      NSAccessibilityGroupRole,
      ROLE_SYSTEM_PUSHBUTTON,
      ROLE_SYSTEM_PUSHBUTTON,
      eNameFromSubtreeRule)
 
+ROLE(LANDMARK,
+     "landmark",
+     ATK_ROLE_LANDMARK,
+     NSAccessibilityGroupRole,
+     USE_ROLE_STRING,
+     IA2_ROLE_LANDMARK,
+     eNoNameRule)
+
+ROLE(NAVIGATION,
+     "navigation",
+     ATK_ROLE_LANDMARK,
+     NSAccessibilityGroupRole,
+     USE_ROLE_STRING,
+     IA2_ROLE_LANDMARK,
+     eNoNameRule)
+
+ROLE(FOOTNOTE,
+     "footnote",
+     ATK_ROLE_FOOTNOTE,
+     NSAccessibilityGroupRole,
+     USE_ROLE_STRING,
+     IA2_ROLE_FOOTNOTE,
+     eNoNameRule)
+
+ROLE(ARTICLE,
+     "article",
+     ATK_ROLE_ARTICLE,
+     NSAccessibilityGroupRole,
+     ROLE_SYSTEM_DOCUMENT,
+     ROLE_SYSTEM_DOCUMENT,
+     eNoNameRule)
+
+ROLE(REGION,
+     "region",
+     ATK_ROLE_LANDMARK,
+     NSAccessibilityGroupRole,
+     USE_ROLE_STRING,
+     IA2_ROLE_LANDMARK,
+     eNoNameRule)
+
+// A composite widget with a text input and popup. Used for ARIA role combobox.
+// See also COMBOBOX.
+ROLE(EDITCOMBOBOX,
+     "editcombobox",
+     ATK_ROLE_COMBO_BOX,
+     NSAccessibilityComboBoxRole,
+     ROLE_SYSTEM_COMBOBOX,
+     ROLE_SYSTEM_COMBOBOX,
+     eNameFromValueRule)
--- a/accessible/base/States.h
+++ b/accessible/base/States.h
@@ -68,17 +68,17 @@ namespace states {
    * The expandable object's children are displayed, the opposite of collapsed,
    * applied to trees, list and other controls.
    * @see COLLAPSED state
    */
   const uint64_t EXPANDED = ((uint64_t) 0x1) << 9;
 
   /**
    * The expandable object's children are not displayed, the opposite of
-   * expanded, applied to tree lists and other controls, 
+   * expanded, applied to tree lists and other controls,
    * @see EXPANDED state.
    */
   const uint64_t COLLAPSED = ((uint64_t) 0x1) << 10;
 
   /**
    * The control or document can not accept input at this time.
    */
   const uint64_t BUSY = ((uint64_t) 0x1) << 11;
@@ -272,14 +272,20 @@ namespace states {
    * @see EXPANDED and COLLAPSED states.
    */
   const uint64_t EXPANDABLE = ((uint64_t) 0x1) << 46;
 
   /**
    * The object is pinned, usually indicating it is fixed in place and has permanence.
    */
   const uint64_t PINNED = ((uint64_t) 0x1) << 47;
+
+  /**
+   * The object is the current item within a container or set of related elements.
+   */
+  const uint64_t CURRENT = ((uint64_t) 0x1) << 48;
+
 } // namespace states
 } // namespace a11y
 } // namespace mozilla
 
 #endif
-	
+
--- a/accessible/base/nsAccUtils.cpp
+++ b/accessible/base/nsAccUtils.cpp
@@ -79,17 +79,17 @@ nsAccUtils::GetDefaultLevel(Accessible* 
 
   if (role == roles::OUTLINEITEM)
     return 1;
 
   if (role == roles::ROW) {
     Accessible* parent = aAccessible->Parent();
     // It is a row inside flatten treegrid. Group level is always 1 until it
     // is overriden by aria-level attribute.
-    if (parent && parent->Role() == roles::TREE_TABLE) 
+    if (parent && parent->Role() == roles::TREE_TABLE)
       return 1;
   }
 
   return 0;
 }
 
 int32_t
 nsAccUtils::GetARIAOrDefaultLevel(Accessible* aAccessible)
@@ -410,17 +410,17 @@ nsAccUtils::TextLength(Accessible* aAcce
   }
 
   TextLeafAccessible* textLeaf = aAccessible->AsTextLeaf();
   if (textLeaf)
     return textLeaf->Text().Length();
 
   // For list bullets (or anything other accessible which would compute its own
   // text. They don't have their own frame.
-  // XXX In the future, list bullets may have frame and anon content, so 
+  // XXX In the future, list bullets may have frame and anon content, so
   // we should be able to remove this at that point
   nsAutoString text;
   aAccessible->AppendTextTo(text); // Get all the text
   return text.Length();
 }
 
 bool
 nsAccUtils::MustPrune(Accessible* aAccessible)
--- a/accessible/base/nsAccUtils.h
+++ b/accessible/base/nsAccUtils.h
@@ -85,19 +85,19 @@ public:
    * @param aTopContent    node to end at
    */
   static void SetLiveContainerAttributes(nsIPersistentProperties *aAttributes,
                                          nsIContent* aStartContent,
                                          mozilla::dom::Element* aTopEl);
 
   /**
    * Any ARIA property of type boolean or NMTOKEN is undefined if the ARIA
-   * property is not present, or is "" or "undefined". Do not call 
+   * property is not present, or is "" or "undefined". Do not call
    * this method for properties of type string, decimal, IDREF or IDREFS.
-   * 
+   *
    * Return true if the ARIA property is defined, otherwise false
    */
   static bool HasDefinedARIAToken(nsIContent *aContent, nsIAtom *aAtom);
 
   /**
    * Return atomic value of ARIA attribute of boolean or NMTOKEN type.
    */
   static nsIAtom* GetARIAToken(mozilla::dom::Element* aElement, nsIAtom* aAttr);
--- a/accessible/base/nsAccessibilityService.cpp
+++ b/accessible/base/nsAccessibilityService.cpp
@@ -53,16 +53,17 @@
 #include "Logging.h"
 #endif
 
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
 #endif
 
 #include "nsImageFrame.h"
+#include "nsINamed.h"
 #include "nsIObserverService.h"
 #include "nsLayoutUtils.h"
 #include "nsPluginFrame.h"
 #include "SVGGeometryFrame.h"
 #include "nsTreeBodyFrame.h"
 #include "nsTreeColumns.h"
 #include "nsTreeUtils.h"
 #include "nsXBLPrototypeBinding.h"
@@ -407,16 +408,17 @@ nsAccessibilityService::GetRootDocumentA
   return nullptr;
 }
 
 #ifdef XP_WIN
 static StaticAutoPtr<nsTArray<nsCOMPtr<nsIContent> > > sPendingPlugins;
 static StaticAutoPtr<nsTArray<nsCOMPtr<nsITimer> > > sPluginTimers;
 
 class PluginTimerCallBack final : public nsITimerCallback
+                                , public nsINamed
 {
   ~PluginTimerCallBack() {}
 
 public:
   explicit PluginTimerCallBack(nsIContent* aContent) : mContent(aContent) {}
 
   NS_DECL_ISUPPORTS
 
@@ -439,21 +441,27 @@ public:
 
     // We couldn't get a doc accessible so presumably the document went away.
     // In this case don't leak our ref to the content or timer.
     sPendingPlugins->RemoveElement(mContent);
     sPluginTimers->RemoveElement(aTimer);
     return NS_OK;
   }
 
+  NS_IMETHOD GetName(nsACString& aName) final
+  {
+    aName.AssignLiteral("PluginTimerCallBack");
+    return NS_OK;
+  }
+
 private:
   nsCOMPtr<nsIContent> mContent;
 };
 
-NS_IMPL_ISUPPORTS(PluginTimerCallBack, nsITimerCallback)
+NS_IMPL_ISUPPORTS(PluginTimerCallBack, nsITimerCallback, nsINamed)
 #endif
 
 already_AddRefed<Accessible>
 nsAccessibilityService::CreatePluginAccessible(nsPluginFrame* aFrame,
                                                nsIContent* aContent,
                                                Accessible* aContext)
 {
   // nsPluginFrame means a plugin, so we need to use the accessibility support
@@ -740,17 +748,17 @@ nsAccessibilityService::GetStringRole(ui
 
 #undef ROLE
 }
 
 void
 nsAccessibilityService::GetStringStates(uint32_t aState, uint32_t aExtraState,
                                         nsISupports** aStringStates)
 {
-  RefPtr<DOMStringList> stringStates = 
+  RefPtr<DOMStringList> stringStates =
     GetStringStates(nsAccUtils::To64State(aState, aExtraState));
 
   // unknown state
   if (!stringStates->Length()) {
     stringStates->Add(NS_LITERAL_STRING("unknown"));
   }
 
   stringStates.forget(aStringStates);
--- a/accessible/base/nsCoreUtils.cpp
+++ b/accessible/base/nsCoreUtils.cpp
@@ -628,19 +628,19 @@ nsCoreUtils::ScrollTo(nsIPresShell* aPre
 {
   nsIPresShell::ScrollAxis vertical, horizontal;
   ConvertScrollTypeToPercents(aScrollType, &vertical, &horizontal);
   aPresShell->ScrollContentIntoView(aContent, vertical, horizontal,
                                     nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
 }
 
 bool
-nsCoreUtils::IsWhitespaceString(const nsSubstring& aString)
+nsCoreUtils::IsWhitespaceString(const nsAString& aString)
 {
-  nsSubstring::const_char_iterator iterBegin, iterEnd;
+  nsAString::const_char_iterator iterBegin, iterEnd;
 
   aString.BeginReading(iterBegin);
   aString.EndReading(iterEnd);
 
   while (iterBegin != iterEnd && IsWhitespace(*iterBegin))
     ++iterBegin;
 
   return iterBegin == iterEnd;
--- a/accessible/base/nsCoreUtils.h
+++ b/accessible/base/nsCoreUtils.h
@@ -294,17 +294,17 @@ public:
       aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::scope);
   }
 
   /**
    * Returns true if the given string is empty or contains whitespace symbols
    * only. In contrast to nsWhitespaceTokenizer class it takes into account
    * non-breaking space (0xa0).
    */
-  static bool IsWhitespaceString(const nsSubstring& aString);
+  static bool IsWhitespaceString(const nsAString& aString);
 
   /**
    * Returns true if the given character is whitespace symbol.
    */
   static bool IsWhitespace(char16_t aChar)
   {
     return aChar == ' ' || aChar == '\n' ||
       aChar == '\r' || aChar == '\t' || aChar == 0xa0;
--- a/accessible/base/nsEventShell.cpp
+++ b/accessible/base/nsEventShell.cpp
@@ -55,17 +55,17 @@ nsEventShell::FireEvent(uint32_t aEventT
   NS_ENSURE_TRUE_VOID(aAccessible);
 
   RefPtr<AccEvent> event = new AccEvent(aEventType, aAccessible,
                                           aIsFromUserInput);
 
   FireEvent(event);
 }
 
-void 
+void
 nsEventShell::GetEventAttributes(nsINode *aNode,
                                  nsIPersistentProperties *aAttributes)
 {
   if (aNode != sEventTargetNode)
     return;
 
   nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::eventFromInput,
                          sEventFromUserInput ? NS_LITERAL_STRING("true") :
--- a/accessible/base/nsTextEquivUtils.cpp
+++ b/accessible/base/nsTextEquivUtils.cpp
@@ -130,42 +130,42 @@ nsTextEquivUtils::AppendTextEquivFromTex
             display->mDisplay == StyleDisplay::TableCell) {
           isHTMLBlock = true;
           if (!aString->IsEmpty()) {
             aString->Append(char16_t(' '));
           }
         }
       }
     }
-    
+
     if (aContent->TextLength() > 0) {
       nsIFrame *frame = aContent->GetPrimaryFrame();
       if (frame) {
         nsIFrame::RenderedText text = frame->GetRenderedText(0,
             UINT32_MAX, nsIFrame::TextOffsetType::OFFSETS_IN_CONTENT_TEXT,
             nsIFrame::TrailingWhitespace::DONT_TRIM_TRAILING_WHITESPACE);
         aString->Append(text.mString);
       } else {
         // If aContent is an object that is display: none, we have no a frame.
         aContent->AppendTextTo(*aString);
       }
       if (isHTMLBlock && !aString->IsEmpty()) {
         aString->Append(char16_t(' '));
       }
     }
-    
+
     return NS_OK;
   }
-  
+
   if (aContent->IsHTMLElement() &&
       aContent->NodeInfo()->Equals(nsGkAtoms::br)) {
     aString->AppendLiteral("\r\n");
     return NS_OK;
   }
-  
+
   return NS_OK_NO_NAME_CLAUSE_HANDLED;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsTextEquivUtils. Private.
 
 nsresult
 nsTextEquivUtils::AppendFromAccessibleChildren(Accessible* aAccessible,
--- a/accessible/base/nsTextEquivUtils.h
+++ b/accessible/base/nsTextEquivUtils.h
@@ -116,17 +116,17 @@ public:
 
 private:
   /**
    * Iterates accessible children and calculates text equivalent from each
    * child.
    */
   static nsresult AppendFromAccessibleChildren(Accessible* aAccessible,
                                                nsAString *aString);
-  
+
   /**
    * Calculates text equivalent from the given accessible and its subtree if
    * allowed.
    */
   static nsresult AppendFromAccessible(Accessible* aAccessible,
                                        nsAString *aString);
 
   /**
--- a/accessible/generic/Accessible-inl.h
+++ b/accessible/generic/Accessible-inl.h
@@ -90,17 +90,23 @@ Accessible::HasGenericType(AccGenericTyp
 
 inline bool
 Accessible::HasNumericValue() const
 {
   if (mStateFlags & eHasNumericValue)
     return true;
 
   const nsRoleMapEntry* roleMapEntry = ARIARoleMap();
-  return roleMapEntry && roleMapEntry->valueRule != eNoValue;
+  if (!roleMapEntry || roleMapEntry->valueRule == eNoValue)
+    return false;
+
+  if (roleMapEntry->valueRule == eHasValueMinMaxIfFocusable)
+    return InteractiveState() & states::FOCUSABLE;
+
+  return true;
 }
 
 inline void
 Accessible::ScrollTo(uint32_t aHow) const
 {
   if (mContent)
     nsCoreUtils::ScrollTo(mDoc->PresShell(), mContent, aHow);
 }
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -313,17 +313,19 @@ Accessible::TranslateString(const nsStri
   nsCOMPtr<nsIStringBundle> stringBundle;
   stringBundleService->CreateBundle(
     "chrome://global-platform/locale/accessible.properties",
     getter_AddRefs(stringBundle));
   if (!stringBundle)
     return;
 
   nsXPIDLString xsValue;
-  nsresult rv = stringBundle->GetStringFromName(aKey.get(), getter_Copies(xsValue));
+  nsresult rv =
+    stringBundle->GetStringFromName(NS_ConvertUTF16toUTF8(aKey).get(),
+                                    getter_Copies(xsValue));
   if (NS_SUCCEEDED(rv))
     aStringOut.Assign(xsValue);
 }
 
 uint64_t
 Accessible::VisibilityState()
 {
   nsIFrame* frame = GetFrame();
@@ -940,16 +942,20 @@ Accessible::Attributes()
   while(attribIter.Next(name, value))
     attributes->SetStringProperty(NS_ConvertUTF16toUTF8(name), value, unused);
 
   if (IsARIAHidden()) {
     nsAccUtils::SetAccAttr(attributes, nsGkAtoms::hidden,
                            NS_LITERAL_STRING("true"));
   }
 
+  // XXX: In ARIA 1.1, the value of aria-haspopup became a token (bug 1355449).
+  if (aria::UniversalStatesFor(mContent->AsElement()) & states::HASPOPUP)
+    nsAccUtils::SetAccAttr(attributes, nsGkAtoms::haspopup, NS_LITERAL_STRING("true"));
+
   // If there is no aria-live attribute then expose default value of 'live'
   // object attribute used for ARIA role of this accessible.
   const nsRoleMapEntry* roleMapEntry = ARIARoleMap();
   if (roleMapEntry) {
     if (roleMapEntry->Is(nsGkAtoms::searchbox)) {
       nsAccUtils::SetAccAttr(attributes, nsGkAtoms::textInputType,
                              NS_LITERAL_STRING("search"));
     }
@@ -1405,16 +1411,32 @@ Accessible::SetCurValue(double aValue)
 
   return NS_SUCCEEDED(
     mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_valuenow, strValue, true));
 }
 
 role
 Accessible::ARIATransformRole(role aRole)
 {
+  // Beginning with ARIA 1.1, user agents are expected to use the native host
+  // language role of the element when the region role is used without a name.
+  // https://rawgit.com/w3c/aria/master/core-aam/core-aam.html#role-map-region
+  //
+  // XXX: While the name computation algorithm can be non-trivial in the general
+  // case, it should not be especially bad here: If the author hasn't used the
+  // region role, this calculation won't occur. And the region role's name
+  // calculation rule excludes name from content. That said, this use case is
+  // another example of why we should consider caching the accessible name. See:
+  // https://bugzilla.mozilla.org/show_bug.cgi?id=1378235.
+  if (aRole == roles::REGION) {
+    nsAutoString name;
+    Name(name);
+    return name.IsEmpty() ? NativeRole() : aRole;
+  }
+
   // XXX: these unfortunate exceptions don't fit into the ARIA table. This is
   // where the accessible role depends on both the role and ARIA state.
   if (aRole == roles::PUSHBUTTON) {
     if (nsAccUtils::HasDefinedARIAToken(mContent, nsGkAtoms::aria_pressed)) {
       // For simplicity, any existing pressed attribute except "" or "undefined"
       // indicates a toggle.
       return roles::TOGGLE_BUTTON;
     }
@@ -1425,24 +1447,24 @@ Accessible::ARIATransformRole(role aRole
                               eCaseMatters)) {
       // For button with aria-haspopup="true".
       return roles::BUTTONMENU;
     }
 
   } else if (aRole == roles::LISTBOX) {
     // A listbox inside of a combobox needs a special role because of ATK
     // mapping to menu.
-    if (mParent && mParent->Role() == roles::COMBOBOX) {
+    if (mParent && mParent->IsCombobox()) {
       return roles::COMBOBOX_LIST;
     } else {
       // Listbox is owned by a combobox
       Relation rel = RelationByType(RelationType::NODE_CHILD_OF);
       Accessible* targetAcc = nullptr;
       while ((targetAcc = rel.Next()))
-        if (targetAcc->Role() == roles::COMBOBOX)
+        if (targetAcc->IsCombobox())
           return roles::COMBOBOX_LIST;
     }
 
   } else if (aRole == roles::OPTION) {
     if (mParent && mParent->Role() == roles::COMBOBOX_LIST)
       return roles::COMBOBOX_OPTION;
 
   } else if (aRole == roles::MENUITEM) {
@@ -1794,18 +1816,23 @@ Accessible::GetNativeInterface(void** aN
 }
 
 void
 Accessible::DoCommand(nsIContent *aContent, uint32_t aActionIndex)
 {
   class Runnable final : public mozilla::Runnable
   {
   public:
-    Runnable(Accessible* aAcc, nsIContent* aContent, uint32_t aIdx) :
-      mAcc(aAcc), mContent(aContent), mIdx(aIdx) { }
+    Runnable(Accessible* aAcc, nsIContent* aContent, uint32_t aIdx)
+      : mozilla::Runnable("Runnable")
+      , mAcc(aAcc)
+      , mContent(aContent)
+      , mIdx(aIdx)
+    {
+    }
 
     NS_IMETHOD Run() override
     {
       if (mAcc)
         mAcc->DispatchClickEvent(mContent, mIdx);
 
       return NS_OK;
     }
@@ -2803,46 +2830,46 @@ KeyBinding::ToPlatformFormat(nsAString& 
     stringBundleService->CreateBundle(
       "chrome://global-platform/locale/platformKeys.properties",
       getter_AddRefs(keyStringBundle));
 
   if (!keyStringBundle)
     return;
 
   nsAutoString separator;
-  keyStringBundle->GetStringFromName(u"MODIFIER_SEPARATOR",
+  keyStringBundle->GetStringFromName("MODIFIER_SEPARATOR",
                                      getter_Copies(separator));
 
   nsAutoString modifierName;
   if (mModifierMask & kControl) {
-    keyStringBundle->GetStringFromName(u"VK_CONTROL",
+    keyStringBundle->GetStringFromName("VK_CONTROL",
                                        getter_Copies(modifierName));
 
     aValue.Append(modifierName);
     aValue.Append(separator);
   }
 
   if (mModifierMask & kAlt) {
-    keyStringBundle->GetStringFromName(u"VK_ALT",
+    keyStringBundle->GetStringFromName("VK_ALT",
                                        getter_Copies(modifierName));
 
     aValue.Append(modifierName);
     aValue.Append(separator);
   }
 
   if (mModifierMask & kShift) {
-    keyStringBundle->GetStringFromName(u"VK_SHIFT",
+    keyStringBundle->GetStringFromName("VK_SHIFT",
                                        getter_Copies(modifierName));
 
     aValue.Append(modifierName);
     aValue.Append(separator);
   }
 
   if (mModifierMask & kMeta) {
-    keyStringBundle->GetStringFromName(u"VK_META",
+    keyStringBundle->GetStringFromName("VK_META",
                                        getter_Copies(modifierName));
 
     aValue.Append(modifierName);
     aValue.Append(separator);
   }
 
   aValue.Append(mKey);
 }
--- a/accessible/generic/ApplicationAccessible.cpp
+++ b/accessible/generic/ApplicationAccessible.cpp
@@ -49,18 +49,17 @@ ApplicationAccessible::Name(nsString& aN
 
   nsCOMPtr<nsIStringBundle> bundle;
   nsresult rv = bundleService->CreateBundle("chrome://branding/locale/brand.properties",
                                             getter_AddRefs(bundle));
   if (NS_FAILED(rv))
     return eNameOK;
 
   nsXPIDLString appName;
-  rv = bundle->GetStringFromName(u"brandShortName",
-                                 getter_Copies(appName));
+  rv = bundle->GetStringFromName("brandShortName", getter_Copies(appName));
   if (NS_FAILED(rv) || appName.IsEmpty()) {
     NS_WARNING("brandShortName not found, using default app name");
     appName.AssignLiteral("Gecko based application");
   }
 
   aName.Assign(appName);
   return eNameOK;
 }
--- a/accessible/generic/DocAccessible-inl.h
+++ b/accessible/generic/DocAccessible-inl.h
@@ -130,18 +130,17 @@ DocAccessible::NotifyOfLoad(uint32_t aLo
       new AccStateChangeEvent(this, states::BUSY, false);
     FireDelayedEvent(stateEvent);
   }
 }
 
 inline void
 DocAccessible::MaybeNotifyOfValueChange(Accessible* aAccessible)
 {
-  a11y::role role = aAccessible->Role();
-  if (role == roles::ENTRY || role == roles::COMBOBOX)
+  if (aAccessible->IsCombobox() || aAccessible->Role() == roles::ENTRY)
     FireDelayedEvent(nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE, aAccessible);
 }
 
 inline Accessible*
 DocAccessible::GetAccessibleEvenIfNotInMapOrContainer(nsINode* aNode) const
 {
   Accessible* acc = GetAccessibleEvenIfNotInMap(aNode);
   return acc ? acc : GetContainerAccessible(aNode);
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -644,32 +644,35 @@ DocAccessible::ScrollPositionDidChange(n
   const uint32_t kScrollPosCheckWait = 50;
   if (mScrollWatchTimer) {
     mScrollWatchTimer->SetDelay(kScrollPosCheckWait);  // Create new timer, to avoid leaks
   }
   else {
     mScrollWatchTimer = do_CreateInstance("@mozilla.org/timer;1");
     if (mScrollWatchTimer) {
       NS_ADDREF_THIS(); // Kung fu death grip
-      mScrollWatchTimer->InitWithFuncCallback(ScrollTimerCallback, this,
-                                              kScrollPosCheckWait,
-                                              nsITimer::TYPE_REPEATING_SLACK);
+      mScrollWatchTimer->InitWithNamedFuncCallback(
+        ScrollTimerCallback,
+        this,
+        kScrollPosCheckWait,
+        nsITimer::TYPE_REPEATING_SLACK,
+        "a11y::DocAccessible::ScrollPositionDidChange");
     }
   }
   mScrollPositionChangedTicks = 1;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIObserver
 
 NS_IMETHODIMP
 DocAccessible::Observe(nsISupports* aSubject, const char* aTopic,
                        const char16_t* aData)
 {
-  if (!nsCRT::strcmp(aTopic,"obs_documentCreated")) {    
+  if (!nsCRT::strcmp(aTopic,"obs_documentCreated")) {
     // State editable will now be set, readonly is now clear
     // Normally we only fire delayed events created from the node, not an
     // accessible object. See the AccStateChangeEvent constructor for details
     // about this exceptional case.
     RefPtr<AccEvent> event =
       new AccStateChangeEvent(this, states::EDITABLE, true);
     FireDelayedEvent(event);
   }
@@ -812,17 +815,17 @@ DocAccessible::AttributeChangedImpl(Acce
   // DOM attribute & resulting layout to actually change. Otherwise,
   // assistive technology will retrieve the wrong state/value/selection info.
 
   // XXX todo
   // We still need to handle special HTML cases here
   // For example, if an <img>'s usemap attribute is modified
   // Otherwise it may just be a state change, for example an object changing
   // its visibility
-  // 
+  //
   // XXX todo: report aria state changes for "undefined" literal value changes
   // filed as bug 472142
   //
   // XXX todo:  invalidate accessible when aria state changes affect exposed role
   // filed as bug 472143
 
   // Universal boolean properties that don't require a role. Fire the state
   // change when disabled or aria-disabled attribute is set.
@@ -1046,16 +1049,23 @@ DocAccessible::ARIAAttributeChanged(Acce
   if (aAttribute == nsGkAtoms::aria_valuenow &&
       (!elm->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_valuetext) ||
        elm->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_valuetext,
                         nsGkAtoms::_empty, eCaseMatters))) {
     FireDelayedEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, aAccessible);
     return;
   }
 
+  if (aAttribute == nsGkAtoms::aria_current) {
+    RefPtr<AccEvent> event =
+      new AccStateChangeEvent(aAccessible, states::CURRENT);
+    FireDelayedEvent(event);
+    return;
+  }
+
   if (aAttribute == nsGkAtoms::aria_owns) {
     mNotificationController->ScheduleRelocation(aAccessible);
   }
 }
 
 void
 DocAccessible::ARIAActiveDescendantChanged(Accessible* aAccessible)
 {
@@ -2093,44 +2103,66 @@ DocAccessible::DoARIAOwnsRelocation(Acce
       continue;
     }
 
 #ifdef A11Y_LOG
   logging::TreeInfo("aria owns traversal", logging::eVerbose,
                     "candidate", child, nullptr);
 #endif
 
+    if (owned->IndexOf(child) < idx) {
+      continue; // ignore second entry of same ID
+    }
+
     // Same child on same position, no change.
-    if (child->Parent() == aOwner &&
-        child->IndexInParent() == static_cast<int32_t>(insertIdx)) {
-      MOZ_ASSERT(owned->ElementAt(idx) == child, "Not in sync!");
-      idx++;
-      continue;
+    if (child->Parent() == aOwner) {
+      int32_t indexInParent = child->IndexInParent();
+
+      // The child is being placed in its current index,
+      // eg. aria-owns='id1 id2 id3' is changed to aria-owns='id3 id2 id1'.
+      if (indexInParent == static_cast<int32_t>(insertIdx)) {
+        MOZ_ASSERT(child->IsRelocated(),
+                   "A child, having an index in parent from aria ownded indices range, has to be aria owned");
+        MOZ_ASSERT(owned->ElementAt(idx) == child,
+                   "Unexpected child in ARIA owned array");
+        idx++;
+        continue;
+      }
+
+      // The child is being inserted directly after its current index,
+      // resulting in a no-move case. This will happen when a parent aria-owns
+      // its last ordinal child:
+      // <ul aria-owns='id2'><li id='id1'></li><li id='id2'></li></ul>
+      if (indexInParent == static_cast<int32_t>(insertIdx) - 1) {
+        MOZ_ASSERT(!child->IsRelocated(), "Child should be in its ordinal position");
+        child->SetRelocated(true);
+        owned->InsertElementAt(idx, child);
+        idx++;
+        continue;
+      }
     }
 
     MOZ_ASSERT(owned->SafeElementAt(idx) != child, "Already in place!");
 
-    if (owned->IndexOf(child) < idx) {
-      continue; // ignore second entry of same ID
-    }
-
     // A new child is found, check for loops.
     if (child->Parent() != aOwner) {
       Accessible* parent = aOwner;
       while (parent && parent != child && !parent->IsDoc()) {
         parent = parent->Parent();
       }
       // A referred child cannot be a parent of the owner.
       if (parent == child) {
         continue;
       }
     }
 
     if (MoveChild(child, aOwner, insertIdx)) {
       child->SetRelocated(true);
+      MOZ_ASSERT(owned == mARIAOwnsHash.Get(aOwner));
+      owned = mARIAOwnsHash.LookupOrAdd(aOwner);
       owned->InsertElementAt(idx, child);
       idx++;
     }
   }
 
   // Put back children that are not seized anymore.
   PutChildrenBack(owned, idx);
   if (owned->Length() == 0) {
@@ -2139,17 +2171,16 @@ DocAccessible::DoARIAOwnsRelocation(Acce
 }
 
 void
 DocAccessible::PutChildrenBack(nsTArray<RefPtr<Accessible> >* aChildren,
                                uint32_t aStartIdx)
 {
   MOZ_ASSERT(aStartIdx <= aChildren->Length(), "Wrong removal index");
 
-  nsTArray<RefPtr<Accessible> > containers;
   for (auto idx = aStartIdx; idx < aChildren->Length(); idx++) {
     Accessible* child = aChildren->ElementAt(idx);
     if (!child->IsInDocument()) {
       continue;
     }
 
     // Remove the child from the owner
     Accessible* owner = child->Parent();
@@ -2161,47 +2192,69 @@ DocAccessible::PutChildrenBack(nsTArray<
 #ifdef A11Y_LOG
     logging::TreeInfo("aria owns put child back", 0,
                       "old parent", owner, "child", child, nullptr);
 #endif
 
     // Unset relocated flag to find an insertion point for the child.
     child->SetRelocated(false);
 
+    nsIContent* content = child->GetContent();
     int32_t idxInParent = -1;
-    Accessible* origContainer = GetContainerAccessible(child->GetContent());
+    Accessible* origContainer = AccessibleOrTrueContainer(content->GetParentNode());
     if (origContainer) {
       TreeWalker walker(origContainer);
-      if (walker.Seek(child->GetContent())) {
+      if (walker.Seek(content)) {
         Accessible* prevChild = walker.Prev();
         if (prevChild) {
           idxInParent = prevChild->IndexInParent() + 1;
           MOZ_DIAGNOSTIC_ASSERT(origContainer == prevChild->Parent(), "Broken tree");
           origContainer = prevChild->Parent();
         }
         else {
           idxInParent = 0;
         }
       }
     }
-    MoveChild(child, origContainer, idxInParent);
+
+    // The child may have already be in its ordinal place for 2 reasons:
+    // 1. It was the last ordinal child, and the first aria-owned child.
+    //    given:      <ul id="list" aria-owns="b"><li id="a"></li><li id="b"></li></ul>
+    //    after load: $("list").setAttribute("aria-owns", "");
+    // 2. The preceding adopted children were just reclaimed, eg:
+    //    given:      <ul id="list"><li id="b"></li></ul>
+    //    after load: $("list").setAttribute("aria-owns", "a b");
+    //    later:      $("list").setAttribute("aria-owns", "");
+    if (origContainer != owner || child->IndexInParent() != idxInParent) {
+      DebugOnly<bool> moved = MoveChild(child, origContainer, idxInParent);
+      MOZ_ASSERT(moved, "Failed to put child back.");
+    } else {
+      MOZ_ASSERT(!child->PrevSibling() || !child->PrevSibling()->IsRelocated(),
+                 "No relocated child should appear before this one");
+      MOZ_ASSERT(!child->NextSibling() || child->NextSibling()->IsRelocated(),
+                 "No ordinal child should appear after this one");
+    }
   }
 
   aChildren->RemoveElementsAt(aStartIdx, aChildren->Length() - aStartIdx);
 }
 
 bool
 DocAccessible::MoveChild(Accessible* aChild, Accessible* aNewParent,
                          int32_t aIdxInParent)
 {
   MOZ_ASSERT(aChild, "No child");
   MOZ_ASSERT(aChild->Parent(), "No parent");
   MOZ_ASSERT(aIdxInParent <= static_cast<int32_t>(aNewParent->ChildCount()),
              "Wrong insertion point for a moving child");
 
+  if (!aNewParent->IsAcceptableChild(aChild->GetContent())) {
+    return false;
+  }
+
   Accessible* curParent = aChild->Parent();
 
 #ifdef A11Y_LOG
   logging::TreeInfo("move child", 0,
                     "old parent", curParent, "new parent", aNewParent,
                     "child", aChild, nullptr);
 #endif
 
@@ -2225,20 +2278,16 @@ DocAccessible::MoveChild(Accessible* aCh
 
 #ifdef A11Y_LOG
     logging::TreeInfo("move child: parent tree after",
                       logging::eVerbose, curParent);
 #endif
     return true;
   }
 
-  if (!aNewParent->IsAcceptableChild(aChild->GetContent())) {
-    return false;
-  }
-
   MOZ_ASSERT(aIdxInParent <= static_cast<int32_t>(aNewParent->ChildCount()),
              "Wrong insertion point for a moving child");
 
   // If the child cannot be re-inserted into the tree, then make sure to remove
   // it from its present parent and then shutdown it.
   bool hasInsertionPoint = (aIdxInParent != -1) ||
     (aIdxInParent <= static_cast<int32_t>(aNewParent->ChildCount()));
 
--- a/accessible/generic/DocAccessible.h
+++ b/accessible/generic/DocAccessible.h
@@ -157,17 +157,17 @@ public:
     // document and all its subdocuments are ready
     eCompletelyLoaded = eReady | 1 << 2
   };
 
   /**
    * Return true if the document has given document state.
    */
   bool HasLoadState(LoadState aState) const
-    { return (mLoadState & static_cast<uint32_t>(aState)) == 
+    { return (mLoadState & static_cast<uint32_t>(aState)) ==
         static_cast<uint32_t>(aState); }
 
   /**
    * Return a native window handler or pointer depending on platform.
    */
   virtual void* GetNativeWindow() const;
 
   /**
--- a/accessible/generic/HyperTextAccessible.cpp
+++ b/accessible/generic/HyperTextAccessible.cpp
@@ -1606,18 +1606,18 @@ HyperTextAccessible::SelectionBoundsAt(i
 
   uint32_t rangeCount = ranges.Length();
   if (aSelectionNum < 0 || aSelectionNum >= static_cast<int32_t>(rangeCount))
     return false;
 
   nsRange* range = ranges[aSelectionNum];
 
   // Get start and end points.
-  nsINode* startNode = range->GetStartParent();
-  nsINode* endNode = range->GetEndParent();
+  nsINode* startNode = range->GetStartContainer();
+  nsINode* endNode = range->GetEndContainer();
   int32_t startOffset = range->StartOffset(), endOffset = range->EndOffset();
 
   // Make sure start is before end, by swapping DOM points.  This occurs when
   // the user selects backwards in the text.
   int32_t rangeCompare = nsContentUtils::ComparePoints(endNode, endOffset,
                                                        startNode, startOffset);
   if (rangeCompare < 0) {
     nsINode* tempNode = startNode;
@@ -1782,32 +1782,33 @@ HyperTextAccessible::SelectionRanges(nsT
   dom::Selection* sel = DOMSelection();
   if (!sel)
     return;
 
   aRanges->SetCapacity(sel->RangeCount());
 
   for (uint32_t idx = 0; idx < sel->RangeCount(); idx++) {
     nsRange* DOMRange = sel->GetRangeAt(idx);
-    HyperTextAccessible* startParent =
-      nsAccUtils::GetTextContainer(DOMRange->GetStartParent());
-    HyperTextAccessible* endParent =
-      nsAccUtils::GetTextContainer(DOMRange->GetEndParent());
-    if (!startParent || !endParent)
+    HyperTextAccessible* startContainer =
+      nsAccUtils::GetTextContainer(DOMRange->GetStartContainer());
+    HyperTextAccessible* endContainer =
+      nsAccUtils::GetTextContainer(DOMRange->GetEndContainer());
+    if (!startContainer || !endContainer) {
       continue;
+    }
 
     int32_t startOffset =
-      startParent->DOMPointToOffset(DOMRange->GetStartParent(),
-                                    DOMRange->StartOffset(), false);
+      startContainer->DOMPointToOffset(DOMRange->GetStartContainer(),
+                                       DOMRange->StartOffset(), false);
     int32_t endOffset =
-      endParent->DOMPointToOffset(DOMRange->GetEndParent(),
-                                  DOMRange->EndOffset(), true);
+      endContainer->DOMPointToOffset(DOMRange->GetEndContainer(),
+                                     DOMRange->EndOffset(), true);
 
     TextRange tr(IsTextField() ? const_cast<HyperTextAccessible*>(this) : mDoc,
-                    startParent, startOffset, endParent, endOffset);
+                    startContainer, startOffset, endContainer, endOffset);
     *(aRanges->AppendElement()) = Move(tr);
   }
 }
 
 void
 HyperTextAccessible::VisibleRanges(nsTArray<a11y::TextRange>* aRanges) const
 {
 }
@@ -2145,27 +2146,27 @@ HyperTextAccessible::GetSpellTextAttr(ns
   uint32_t startOffset = 0, endOffset = 0;
   for (int32_t idx = 0; idx < rangeCount; idx++) {
     nsRange* range = domSel->GetRangeAt(idx);
     if (range->Collapsed())
       continue;
 
     // See if the point comes after the range in which case we must continue in
     // case there is another range after this one.
-    nsINode* endNode = range->GetEndParent();
+    nsINode* endNode = range->GetEndContainer();
     int32_t endNodeOffset = range->EndOffset();
     if (nsContentUtils::ComparePoints(aNode, aNodeOffset,
                                       endNode, endNodeOffset) >= 0)
       continue;
 
     // At this point our point is either in this range or before it but after
     // the previous range.  So we check to see if the range starts before the
     // point in which case the point is in the missspelled range, otherwise it
     // must be before the range and after the previous one if any.
-    nsINode* startNode = range->GetStartParent();
+    nsINode* startNode = range->GetStartContainer();
     int32_t startNodeOffset = range->StartOffset();
     if (nsContentUtils::ComparePoints(startNode, startNodeOffset, aNode,
                                       aNodeOffset) <= 0) {
       startOffset = DOMPointToOffset(startNode, startNodeOffset);
 
       endOffset = DOMPointToOffset(endNode, endNodeOffset);
 
       if (startOffset > *aStartOffset)
@@ -2182,17 +2183,17 @@ HyperTextAccessible::GetSpellTextAttr(ns
       return;
     }
 
     // This range came after the point.
     endOffset = DOMPointToOffset(startNode, startNodeOffset);
 
     if (idx > 0) {
       nsRange* prevRange = domSel->GetRangeAt(idx - 1);
-      startOffset = DOMPointToOffset(prevRange->GetEndParent(),
+      startOffset = DOMPointToOffset(prevRange->GetEndContainer(),
                                      prevRange->EndOffset());
     }
 
     if (startOffset > *aStartOffset)
       *aStartOffset = startOffset;
 
     if (endOffset < *aEndOffset)
       *aEndOffset = endOffset;
@@ -2200,17 +2201,17 @@ HyperTextAccessible::GetSpellTextAttr(ns
     return;
   }
 
   // We never found a range that ended after the point, therefore we know that
   // the point is not in a range, that we do not need to compute an end offset,
   // and that we should use the end offset of the last range to compute the
   // start offset of the text attribute range.
   nsRange* prevRange = domSel->GetRangeAt(rangeCount - 1);
-  startOffset = DOMPointToOffset(prevRange->GetEndParent(),
+  startOffset = DOMPointToOffset(prevRange->GetEndContainer(),
                                  prevRange->EndOffset());
 
   if (startOffset > *aStartOffset)
     *aStartOffset = startOffset;
 }
 
 bool
 HyperTextAccessible::IsTextRole()
--- a/accessible/generic/ImageAccessible.cpp
+++ b/accessible/generic/ImageAccessible.cpp
@@ -106,17 +106,17 @@ ImageAccessible::ActionCount()
   return HasLongDesc() ? actionCount + 1 : actionCount;
 }
 
 void
 ImageAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName)
 {
   aName.Truncate();
   if (IsLongDescIndex(aIndex) && HasLongDesc())
-    aName.AssignLiteral("showlongdesc"); 
+    aName.AssignLiteral("showlongdesc");
   else
     LinkableAccessible::ActionNameAt(aIndex, aName);
 }
 
 bool
 ImageAccessible::DoAction(uint8_t aIndex)
 {
   // Get the long description uri and open in a new window.
--- a/accessible/generic/OuterDocAccessible.h
+++ b/accessible/generic/OuterDocAccessible.h
@@ -9,17 +9,17 @@
 #include "AccessibleWrap.h"
 
 namespace mozilla {
 namespace a11y {
 class DocAccessibleParent;
 
 /**
  * Used for <browser>, <frame>, <iframe>, <page> or editor> elements.
- * 
+ *
  * In these variable names, "outer" relates to the OuterDocAccessible as
  * opposed to the DocAccessibleWrap which is "inner". The outer node is
  * a something like tags listed above, whereas the inner node corresponds to
  * the inner document root.
  */
 
 class OuterDocAccessible final : public AccessibleWrap
 {
--- a/accessible/generic/RootAccessible.cpp
+++ b/accessible/generic/RootAccessible.cpp
@@ -99,17 +99,17 @@ RootAccessible::NativeRole()
   return DocAccessibleWrap::NativeRole();
 }
 
 // RootAccessible protected member
 #ifdef MOZ_XUL
 uint32_t
 RootAccessible::GetChromeFlags()
 {
-  // Return the flag set for the top level window as defined 
+  // Return the flag set for the top level window as defined
   // by nsIWebBrowserChrome::CHROME_WINDOW_[FLAGNAME]
   // Not simple: nsIXULWindow is not just a QI from nsIDOMWindow
   nsCOMPtr<nsIDocShell> docShell = nsCoreUtils::GetDocShellFor(mDocumentNode);
   NS_ENSURE_TRUE(docShell, 0);
   nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
   docShell->GetTreeOwner(getter_AddRefs(treeOwner));
   NS_ENSURE_TRUE(treeOwner, 0);
   nsCOMPtr<nsIXULWindow> xulWin(do_GetInterface(treeOwner));
@@ -198,17 +198,17 @@ RootAccessible::AddEventListeners()
 
   return DocAccessible::AddEventListeners();
 }
 
 nsresult
 RootAccessible::RemoveEventListeners()
 {
   nsCOMPtr<EventTarget> target = mDocumentNode;
-  if (target) { 
+  if (target) {
     for (const char* const* e = kEventTypes,
                    * const* e_end = ArrayEnd(kEventTypes);
          e < e_end; ++e) {
       nsresult rv = target->RemoveEventListener(NS_ConvertASCIItoUTF16(*e), this, true);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
@@ -280,17 +280,17 @@ RootAccessible::ProcessDOMEvent(nsIDOMEv
     HandlePopupHidingEvent(origTargetNode);
     return;
   }
 
   DocAccessible* targetDocument = GetAccService()->
     GetDocAccessible(origTargetNode->OwnerDoc());
   NS_ASSERTION(targetDocument, "No document while accessible is in document?!");
 
-  Accessible* accessible = 
+  Accessible* accessible =
     targetDocument->GetAccessibleOrContainer(origTargetNode);
   if (!accessible)
     return;
 
 #ifdef MOZ_XUL
   XULTreeAccessible* treeAcc = accessible->AsXULTree();
   if (treeAcc) {
     if (eventType.EqualsLiteral("TreeRowCountChanged")) {
@@ -512,32 +512,30 @@ RootAccessible::HandlePopupShownEvent(Ac
     // Don't fire menupopup events for combobox and autocomplete lists.
     nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START,
                             aAccessible);
     return;
   }
 
   if (role == roles::TOOLTIP) {
     // There is a single <xul:tooltip> node which Mozilla moves around.
-    // The accessible for it stays the same no matter where it moves. 
-    // AT's expect to get an EVENT_SHOW for the tooltip. 
+    // The accessible for it stays the same no matter where it moves.
+    // AT's expect to get an EVENT_SHOW for the tooltip.
     // In event callback the tooltip's accessible will be ready.
     nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_SHOW, aAccessible);
     return;
   }
 
   if (role == roles::COMBOBOX_LIST) {
     // Fire expanded state change event for comboboxes and autocompeletes.
     Accessible* combobox = aAccessible->Parent();
     if (!combobox)
       return;
 
-    roles::Role comboboxRole = combobox->Role();
-    if (comboboxRole == roles::COMBOBOX || 
-	comboboxRole == roles::AUTOCOMPLETE) {
+    if (combobox->IsCombobox() || combobox->IsAutoComplete()) {
       RefPtr<AccEvent> event =
         new AccStateChangeEvent(combobox, states::EXPANDED, true);
       if (event)
         nsEventShell::FireEvent(event);
     }
   }
 }
 
--- a/accessible/generic/TableAccessible.h
+++ b/accessible/generic/TableAccessible.h
@@ -51,31 +51,31 @@ public:
    * Return the index of the cell at the given row and column.
    */
   virtual int32_t CellIndexAt(uint32_t aRowIdx, uint32_t aColIdx)
     { return ColCount() * aRowIdx + aColIdx; }
 
   /**
    * Return the column index of the cell with the given index.
    */
-  virtual int32_t ColIndexAt(uint32_t aCellIdx) 
+  virtual int32_t ColIndexAt(uint32_t aCellIdx)
     { return aCellIdx % ColCount(); }
 
   /**
    * Return the row index of the cell with the given index.
    */
-  virtual int32_t RowIndexAt(uint32_t aCellIdx) 
+  virtual int32_t RowIndexAt(uint32_t aCellIdx)
     { return aCellIdx / ColCount(); }
 
   /**
    * Get the row and column indices for the cell at the given index.
    */
   virtual void RowAndColIndicesAt(uint32_t aCellIdx, int32_t* aRowIdx,
-                                  int32_t* aColIdx) 
-    { 
+                                  int32_t* aColIdx)
+    {
       uint32_t colCount = ColCount();
       *aRowIdx = aCellIdx / colCount;
       *aColIdx = aCellIdx % colCount;
     }
 
   /**
    * Return the number of columns occupied by the cell at the given row and
    * column indices.
--- a/accessible/generic/TextLeafAccessible.h
+++ b/accessible/generic/TextLeafAccessible.h
@@ -5,17 +5,17 @@
 
 #ifndef mozilla_a11y_TextLeafAccessible_h__
 #define mozilla_a11y_TextLeafAccessible_h__
 
 #include "BaseAccessibles.h"
 
 namespace mozilla {
 namespace a11y {
- 
+
 /**
  * Generic class used for text nodes.
  */
 class TextLeafAccessible : public LinkableAccessible
 {
 public:
   TextLeafAccessible(nsIContent* aContent, DocAccessible* aDoc);
   virtual ~TextLeafAccessible();
--- a/accessible/html/HTMLFormControlAccessible.cpp
+++ b/accessible/html/HTMLFormControlAccessible.cpp
@@ -84,17 +84,17 @@ HTMLCheckboxAccessible::NativeState()
   if (!input)
     return state;
 
   if (input->Indeterminate())
     return state | states::MIXED;
 
   if (input->Checked())
     return state | states::CHECKED;
- 
+
   return state;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLCheckboxAccessible: Widgets
 
 bool
 HTMLCheckboxAccessible::IsWidget() const
--- a/accessible/html/HTMLSelectAccessible.cpp
+++ b/accessible/html/HTMLSelectAccessible.cpp
@@ -147,17 +147,17 @@ ENameValueFlag
 HTMLSelectOptionAccessible::NativeName(nsString& aName)
 {
   // CASE #1 -- great majority of the cases
   // find the label attribute - this is what the W3C says we should use
   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName);
   if (!aName.IsEmpty())
     return eNameOK;
 
-  // CASE #2 -- no label parameter, get the first child, 
+  // CASE #2 -- no label parameter, get the first child,
   // use it if it is a text node
   nsIContent* text = mContent->GetFirstChild();
   if (text && text->IsNodeOfType(nsINode::eTEXT)) {
     nsTextEquivUtils::AppendTextEquivFromTextContent(text, &aName);
     aName.CompressWhitespace();
     return aName.IsEmpty() ? eNameOK : eNameFromSubtree;
   }
 
--- a/accessible/html/HTMLTableAccessible.cpp
+++ b/accessible/html/HTMLTableAccessible.cpp
@@ -971,17 +971,17 @@ HTMLTableAccessible::IsProbablyLayoutTab
   // Check for legitimate data table attributes.
   nsAutoString summary;
   if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::summary, summary) &&
       !summary.IsEmpty())
     RETURN_LAYOUT_ANSWER(false, "Has summary -- legitimate table structures");
 
   // Check for legitimate data table elements.
   Accessible* caption = FirstChild();
-  if (caption && caption->Role() == roles::CAPTION && caption->HasChildren()) 
+  if (caption && caption->Role() == roles::CAPTION && caption->HasChildren())
     RETURN_LAYOUT_ANSWER(false, "Not empty caption -- legitimate table structures");
 
   for (nsIContent* childElm = mContent->GetFirstChild(); childElm;
        childElm = childElm->GetNextSibling()) {
     if (!childElm->IsHTMLElement())
       continue;
 
     if (childElm->IsAnyOfHTMLElements(nsGkAtoms::col,
@@ -1104,19 +1104,18 @@ HTMLTableAccessible::IsProbablyLayoutTab
 
   // Two column rules
   if (rowCount * colCount <= 10) {
     RETURN_LAYOUT_ANSWER(true, "2-4 columns, 10 cells or less, non-bordered");
   }
 
   if (HasDescendant(NS_LITERAL_STRING("embed")) ||
       HasDescendant(NS_LITERAL_STRING("object")) ||
-      HasDescendant(NS_LITERAL_STRING("applet")) ||
       HasDescendant(NS_LITERAL_STRING("iframe"))) {
-    RETURN_LAYOUT_ANSWER(true, "Has no borders, and has iframe, object, applet or iframe, typical of advertisements");
+    RETURN_LAYOUT_ANSWER(true, "Has no borders, and has iframe, object, or iframe, typical of advertisements");
   }
 
   RETURN_LAYOUT_ANSWER(false, "no layout factor strong enough, so will guess data");
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLCaptionAccessible
--- a/accessible/interfaces/nsIAccessibleRelation.idl
+++ b/accessible/interfaces/nsIAccessibleRelation.idl
@@ -115,16 +115,21 @@ interface nsIAccessibleRelation : nsISup
   const unsigned long RELATION_CONTAINING_DOCUMENT = 0x11;
 
   /**
    * The target object is the topmost containing document object in the tab pane.
    */
   const unsigned long RELATION_CONTAINING_TAB_PANE = 0x12;
 
   /**
+   * The target object is the containing window object.
+   */
+  const unsigned long RELATION_CONTAINING_WINDOW = 0x13;
+
+  /**
    * The target object is the containing application object.
    */
   const unsigned long RELATION_CONTAINING_APPLICATION = 0x14;
 
   /**
    * The target object provides the detailed, extended description for this
    * object. It provides more detailed information than would normally be
    * provided using the DESCRIBED_BY relation. A common use for this relation is
--- a/accessible/interfaces/nsIAccessibleRole.idl
+++ b/accessible/interfaces/nsIAccessibleRole.idl
@@ -294,19 +294,19 @@ interface nsIAccessibleRole : nsISupport
    * group of mutually exclusive options. All objects sharing a single parent
    * that have this attribute are assumed to be part of single mutually
    * exclusive group. It is used for xul:radio, html:input@type="radio",
    * role="radio".
    */
   const unsigned long ROLE_RADIOBUTTON = 45;
 
   /**
-   * Represents a combo box; an edit control with an associated list box that
-   * provides a set of predefined choices. It is used for html:select,
-   * xul:menulist, role="combobox".
+   * Represents a combo box; a popup button with an associated list box that
+   * provides a set of predefined choices. It is used for html:select with a
+   * size of 1 and xul:menulist. See also ROLE_EDITCOMBOBOX.
    */
   const unsigned long ROLE_COMBOBOX = 46;
 
   /**
    * Represents the calendar control.
    */
   const unsigned long ROLE_DROPLIST = 47;
 
@@ -972,9 +972,47 @@ interface nsIAccessibleRole : nsISupport
    */
   const unsigned long ROLE_DETAILS = 167;
 
   /**
    * A text container exposing brief amount of information. See related
    * SUMMARY role.
    */
   const unsigned long ROLE_SUMMARY = 168;
+
+  /**
+   * An ARIA landmark. See related NAVIGATION role.
+   */
+  const unsigned long ROLE_LANDMARK = 169;
+
+  /**
+   * A specific type of ARIA landmark. The ability to distinguish navigation
+   * landmarks from other types of landmarks is needed because macOS has a
+   * specific AXSubrole and AXRoleDescription for navigation landmarks.
+   */
+  const unsigned long ROLE_NAVIGATION = 170;
+
+  /**
+   * An object that contains the text of a footnote.
+   */
+  const unsigned long ROLE_FOOTNOTE = 171;
+
+  /**
+   * A complete or self-contained composition in a document, page, application,
+   * or site and that is, in principle, independently distributable or reusable,
+   * e.g. in syndication.
+   */
+  const unsigned long ROLE_ARTICLE = 172;
+
+  /**
+   * A perceivable section containing content that is relevant to a specific,
+   * author-specified purpose and sufficiently important that users will likely
+   * want to be able to navigate to the section easily and to have it listed in
+   * a summary of the page.
+   */
+  const unsigned long ROLE_REGION = 173;
+
+  /**
+   * Represents a control with a text input and a popup with a set of predefined
+   * choices. It is used for ARIA's combobox role. See also ROLE_COMBOBOX.
+   */
+  const unsigned long ROLE_EDITCOMBOBOX = 174;
 };
--- a/accessible/interfaces/nsIAccessibleStates.idl
+++ b/accessible/interfaces/nsIAccessibleStates.idl
@@ -67,10 +67,11 @@ interface nsIAccessibleStates : nsISuppo
   const unsigned long  EXT_STATE_SINGLE_LINE             = 0x00000200;  // This text object can only contain 1 line of text    
   const unsigned long  EXT_STATE_TRANSIENT               = 0x00000400;  // 
   const unsigned long  EXT_STATE_VERTICAL                = 0x00000800;  // Especially used for sliders and scrollbars  
   const unsigned long  EXT_STATE_STALE                   = 0x00001000;  // Object not dead, but not up-to-date either
   const unsigned long  EXT_STATE_ENABLED                 = 0x00002000;  // A widget that is not unavailable
   const unsigned long  EXT_STATE_SENSITIVE               = 0x00004000;  // Same as ENABLED for now
   const unsigned long  EXT_STATE_EXPANDABLE              = 0x00008000;  // If COLLAPSED or EXPANDED
   const unsigned long  EXT_STATE_PINNED                  = 0x00010000;  // Indicates object is pinned.
+  const unsigned long  EXT_STATE_CURRENT                 = 0x00020000;  // Indicates object is the current item in its container
 };
 
--- a/accessible/ipc/DocAccessibleParent.cpp
+++ b/accessible/ipc/DocAccessibleParent.cpp
@@ -28,18 +28,17 @@ DocAccessibleParent::RecvShowEvent(const
                                    const bool& aFromUser)
 {
   if (mShutdown)
     return IPC_OK();
 
   MOZ_ASSERT(CheckDocTree());
 
   if (aData.NewTree().IsEmpty()) {
-    NS_ERROR("no children being added");
-    return IPC_FAIL_NO_REASON(this);
+    return IPC_FAIL(this, "No children being added");
   }
 
   ProxyAccessible* parent = GetAccessible(aData.ID());
 
   // XXX This should really never happen, but sometimes we fail to fire the
   // required show events.
   if (!parent) {
     NS_ERROR("adding child to unknown accessible");
@@ -153,18 +152,17 @@ DocAccessibleParent::RecvHideEvent(const
   if (mShutdown)
     return IPC_OK();
 
   MOZ_ASSERT(CheckDocTree());
 
   // We shouldn't actually need this because mAccessibles shouldn't have an
   // entry for the document itself, but it doesn't hurt to be explicit.
   if (!aRootID) {
-    NS_ERROR("trying to hide entire document?");
-    return IPC_FAIL_NO_REASON(this);
+    return IPC_FAIL(this, "Trying to hide entire document?");
   }
 
   ProxyEntry* rootEntry = mAccessibles.GetEntry(aRootID);
   if (!rootEntry) {
     NS_ERROR("invalid root being removed!");
     return IPC_OK();
   }
 
@@ -392,19 +390,18 @@ DocAccessibleParent::RecvSelectionEvent(
 
 mozilla::ipc::IPCResult
 DocAccessibleParent::RecvRoleChangedEvent(const uint32_t& aRole)
 {
   if (mShutdown) {
     return IPC_OK();
   }
 
- if (aRole >= roles::LAST_ROLE) {
-   NS_ERROR("child sent bad role in RoleChangedEvent");
-   return IPC_FAIL_NO_REASON(this);
+ if (aRole > roles::LAST_ROLE) {
+   return IPC_FAIL(this, "Child sent bad role in RoleChangedEvent");
  }
 
  mRole = static_cast<a11y::role>(aRole);
  return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 DocAccessibleParent::RecvBindChildDoc(PDocAccessibleParent* aChildDoc, const uint64_t& aID)
@@ -621,36 +618,41 @@ DocAccessibleParent::MaybeInitWindowEmul
     nsIntRect rootRect = rootDocument->Bounds();
     rect.x = rootRect.x - rect.x;
     rect.y -= rootRect.y;
 
     auto tab = static_cast<dom::TabParent*>(Manager());
     tab->GetDocShellIsActive(&isActive);
   }
 
-  IAccessibleHolder hWndAccHolder;
-  HWND parentWnd = reinterpret_cast<HWND>(rootDocument->GetNativeWindow());
-  HWND hWnd = nsWinUtils::CreateNativeWindow(kClassNameTabContent,
-                                             parentWnd, rect.x, rect.y,
-                                             rect.width, rect.height,
-                                             isActive);
-  if (hWnd) {
-    // Attach accessible document to the emulated native window
-    ::SetPropW(hWnd, kPropNameDocAccParent, (HANDLE)this);
-    SetEmulatedWindowHandle(hWnd);
+  nsWinUtils::NativeWindowCreateProc onCreate([this](HWND aHwnd) -> void {
+    IAccessibleHolder hWndAccHolder;
+
+    ::SetPropW(aHwnd, kPropNameDocAccParent, reinterpret_cast<HANDLE>(this));
+
+    SetEmulatedWindowHandle(aHwnd);
+
     IAccessible* rawHWNDAcc = nullptr;
-    if (SUCCEEDED(::AccessibleObjectFromWindow(hWnd, OBJID_WINDOW,
+    if (SUCCEEDED(::AccessibleObjectFromWindow(aHwnd, OBJID_WINDOW,
                                                IID_IAccessible,
                                                (void**)&rawHWNDAcc))) {
       hWndAccHolder.Set(IAccessibleHolder::COMPtrType(rawHWNDAcc));
     }
-  }
+
+    Unused << SendEmulatedWindow(reinterpret_cast<uintptr_t>(mEmulatedWindowHandle),
+                                 hWndAccHolder);
+  });
 
-  Unused << SendEmulatedWindow(reinterpret_cast<uintptr_t>(mEmulatedWindowHandle),
-                               hWndAccHolder);
+  HWND parentWnd = reinterpret_cast<HWND>(rootDocument->GetNativeWindow());
+  DebugOnly<HWND> hWnd = nsWinUtils::CreateNativeWindow(kClassNameTabContent,
+                                                        parentWnd,
+                                                        rect.x, rect.y,
+                                                        rect.width, rect.height,
+                                                        isActive, &onCreate);
+  MOZ_ASSERT(hWnd);
 }
 
 /**
  * @param aCOMProxy COM Proxy to the document in the content process.
  */
 void
 DocAccessibleParent::SendParentCOMProxy()
 {
@@ -667,17 +669,23 @@ DocAccessibleParent::SendParentCOMProxy(
   }
 
   IAccessible* rawNative = nullptr;
   outerDoc->GetNativeInterface((void**) &rawNative);
   MOZ_ASSERT(rawNative);
 
   IAccessibleHolder::COMPtrType ptr(rawNative);
   IAccessibleHolder holder(Move(ptr));
-  Unused << PDocAccessibleParent::SendParentCOMProxy(holder);
+  if (!PDocAccessibleParent::SendParentCOMProxy(holder)) {
+    return;
+  }
+
+#if defined(MOZ_CONTENT_SANDBOX)
+  mParentProxyStream = Move(holder.GetPreservedStream());
+#endif // defined(MOZ_CONTENT_SANDBOX)
 }
 
 void
 DocAccessibleParent::SetEmulatedWindowHandle(HWND aWindowHandle)
 {
   if (!aWindowHandle && mEmulatedWindowHandle && IsTopLevel()) {
     ::DestroyWindow(mEmulatedWindowHandle);
   }
--- a/accessible/ipc/DocAccessibleParent.h
+++ b/accessible/ipc/DocAccessibleParent.h
@@ -231,17 +231,21 @@ private:
   xpcAccessibleGeneric* GetXPCAccessible(ProxyAccessible* aProxy);
 
   nsTArray<uint64_t> mChildDocs;
   uint64_t mParentDoc;
 
 #if defined(XP_WIN)
   // The handle associated with the emulated window that contains this document
   HWND mEmulatedWindowHandle;
-#endif
+
+#if defined(MOZ_CONTENT_SANDBOX)
+  mscom::PreservedStreamPtr mParentProxyStream;
+#endif // defined(MOZ_CONTENT_SANDBOX)
+#endif // defined(XP_WIN)
 
   /*
    * Conceptually this is a map from IDs to proxies, but we store the ID in the
    * proxy object so we can't use a real map.
    */
   nsTHashtable<ProxyEntry> mAccessibles;
   uint64_t mActorID;
   bool mTopLevel;
--- a/accessible/ipc/other/ProxyAccessible.cpp
+++ b/accessible/ipc/other/ProxyAccessible.cpp
@@ -834,17 +834,17 @@ ProxyAccessible::GetSelectedItem(uint32_
 
 bool
 ProxyAccessible::IsItemSelected(uint32_t aIndex)
 {
   bool selected = false;
   Unused << mDoc->SendIsItemSelected(mID, aIndex, &selected);
   return selected;
 }
- 
+
 bool
 ProxyAccessible::AddItemToSelection(uint32_t aIndex)
 {
   bool success = false;
   Unused << mDoc->SendAddItemToSelection(mID, aIndex, &success);
   return success;
 }
 
--- a/accessible/ipc/win/COMPtrTypes.cpp
+++ b/accessible/ipc/win/COMPtrTypes.cpp
@@ -4,16 +4,17 @@
  * 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/. */
 
 #include "mozilla/a11y/COMPtrTypes.h"
 
 #include "Accessible2_3.h"
 #include "MainThreadUtils.h"
 #include "mozilla/a11y/Accessible.h"
+#include "mozilla/a11y/Platform.h"
 #include "mozilla/a11y/HandlerProvider.h"
 #include "mozilla/Move.h"
 #include "mozilla/mscom/MainThreadHandoff.h"
 #include "mozilla/mscom/Utils.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/RefPtr.h"
 #include "nsXULAppAPI.h"
 
@@ -35,17 +36,18 @@ CreateHolderFromAccessible(Accessible* a
   STAUniquePtr<IAccessible> iaToProxy;
   aAccToWrap->GetNativeInterface(mscom::getter_AddRefs(iaToProxy));
   MOZ_ASSERT(iaToProxy);
   if (!iaToProxy) {
     return nullptr;
   }
 
   static const bool useHandler =
-    Preferences::GetBool("accessibility.handler.enabled", false);
+    Preferences::GetBool("accessibility.handler.enabled", false) &&
+    IsHandlerRegistered();
 
   RefPtr<HandlerProvider> payload;
   if (useHandler) {
     payload = new HandlerProvider(IID_IAccessible,
                                   mscom::ToInterceptorTargetPtr(iaToProxy));
   }
 
   ProxyUniquePtr<IAccessible> intercepted;
--- a/accessible/ipc/win/HandlerProvider.cpp
+++ b/accessible/ipc/win/HandlerProvider.cpp
@@ -90,17 +90,18 @@ HandlerProvider::GetAndSerializePayload(
   MOZ_ASSERT(mscom::IsCurrentThreadMTA());
 
   if (mSerializer) {
     return;
   }
 
   IA2Payload payload{};
 
-  if (!mscom::InvokeOnMainThread(this, &HandlerProvider::BuildIA2Data,
+  if (!mscom::InvokeOnMainThread("HandlerProvider::BuildIA2Data",
+                                 this, &HandlerProvider::BuildIA2Data,
                                  &payload.mData) ||
       !payload.mData.mUniqueId) {
     return;
   }
 
   // But we set mGeckoBackChannel on the current thread which resides in the
   // MTA. This is important to ensure that COM always invokes
   // IGeckoBackChannel methods in an MTA background thread.
@@ -125,18 +126,20 @@ HandlerProvider::GetHandlerPayloadSize(N
     *aOutPayloadSize = mscom::StructToStream::GetEmptySize();
     return S_OK;
   }
 
   MutexAutoLock lock(mMutex);
 
   GetAndSerializePayload(lock);
 
-  if (!mSerializer) {
-    return E_FAIL;
+  if (!mSerializer || !(*mSerializer)) {
+    // Failed payload serialization is non-fatal
+    *aOutPayloadSize = mscom::StructToStream::GetEmptySize();
+    return S_OK;
   }
 
   *aOutPayloadSize = mSerializer->GetSize();
   return S_OK;
 }
 
 void
 HandlerProvider::BuildIA2Data(IA2Data* aOutIA2Data)
@@ -170,17 +173,18 @@ HandlerProvider::IsTargetInterfaceCachea
   return MarshalAs(mTargetUnkIid) == NEWEST_IA2_IID;
 }
 
 HRESULT
 HandlerProvider::WriteHandlerPayload(NotNull<IStream*> aStream)
 {
   MutexAutoLock lock(mMutex);
 
-  if (!mSerializer) {
+  if (!mSerializer || !(*mSerializer)) {
+    // Failed payload serialization is non-fatal
     mscom::StructToStream emptyStruct;
     return emptyStruct.Write(aStream);
   }
 
   HRESULT hr = mSerializer->Write(aStream);
 
   mSerializer.reset();
 
@@ -231,31 +235,33 @@ HandlerProvider::put_HandlerControl(long
   MOZ_ASSERT(mscom::IsCurrentThreadMTA());
 
   if (!aCtrl) {
     return E_INVALIDARG;
   }
 
   auto ptrProxy = mscom::ToProxyUniquePtr(aCtrl);
 
-  if (!mscom::InvokeOnMainThread(this,
+  if (!mscom::InvokeOnMainThread("HandlerProvider::SetHandlerControlOnMainThread",
+                                 this,
                                  &HandlerProvider::SetHandlerControlOnMainThread,
                                  static_cast<DWORD>(aPid), Move(ptrProxy))) {
     return E_FAIL;
   }
 
   return S_OK;
 }
 
 HRESULT
 HandlerProvider::Refresh(IA2Data* aOutData)
 {
   MOZ_ASSERT(mscom::IsCurrentThreadMTA());
 
-  if (!mscom::InvokeOnMainThread(this, &HandlerProvider::BuildIA2Data,
+  if (!mscom::InvokeOnMainThread("HandlerProvider::BuildIA2Data",
+                                 this, &HandlerProvider::BuildIA2Data,
                                  aOutData)) {
     return E_FAIL;
   }
 
   return S_OK;
 }
 
 } // namespace a11y
--- a/accessible/ipc/win/HandlerProvider.h
+++ b/accessible/ipc/win/HandlerProvider.h
@@ -59,17 +59,17 @@ private:
                                      mscom::ProxyUniquePtr<IHandlerControl> aCtrl);
   void GetAndSerializePayload(const MutexAutoLock&);
   void BuildIA2Data(IA2Data* aOutIA2Data);
   static void ClearIA2Data(IA2Data& aData);
   bool IsTargetInterfaceCacheable();
 
   Atomic<uint32_t>                  mRefCnt;
   Mutex                             mMutex; // Protects mSerializer
-  REFIID                            mTargetUnkIid;
+  const IID                         mTargetUnkIid;
   mscom::InterceptorTargetPtr<IUnknown> mTargetUnk; // Constant, main thread only
   UniquePtr<mscom::StructToStream>  mSerializer;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif // mozilla_a11y_HandlerProvider_h
new file mode 100644
--- /dev/null
+++ b/accessible/ipc/win/IAccessible32.manifest
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+  <assemblyIdentity type="win32" name="Mozilla.Firefox.xul" version="1.0.0.0" />
+  <file name="xul.dll" />
+  <comInterfaceExternalProxyStub
+      iid="{618736E0-3C3D-11CF-810C-00AA00389B71}"
+      proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
+      name="IAccessible"
+      tlbid="{1EA4DBF0-3C3B-11CF-810C-00AA00389B71}"
+  />
+</assembly>
new file mode 100644
--- /dev/null
+++ b/accessible/ipc/win/IAccessible64.manifest
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+  <assemblyIdentity type="win32" name="Mozilla.Firefox.xul" version="1.0.0.0" />
+  <file name="xul.dll" />
+  <comInterfaceExternalProxyStub
+      iid="{618736E0-3C3D-11CF-810C-00AA00389B71}"
+      proxyStubClsid32="{03022430-ABC4-11D0-BDE2-00AA001A1953}"
+      name="IAccessible"
+  />
+</assembly>
--- a/accessible/ipc/win/PlatformChild.cpp
+++ b/accessible/ipc/win/PlatformChild.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* 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/. */
 
+#include "mozilla/a11y/Compatibility.h"
 #include "mozilla/a11y/PlatformChild.h"
 #include "mozilla/mscom/EnsureMTA.h"
 #include "mozilla/mscom/InterceptorLog.h"
 
 #include "Accessible2.h"
 #include "Accessible2_2.h"
 #include "AccessibleHypertext2.h"
 #include "AccessibleTableCell.h"
@@ -43,16 +44,24 @@ static const mozilla::mscom::ArrayData s
 // we intend to instantiate them. Therefore RegisterProxy() must be called
 // via EnsureMTA.
 PlatformChild::PlatformChild()
   : mAccTypelib(mozilla::mscom::RegisterTypelib(L"oleacc.dll",
         mozilla::mscom::RegistrationFlags::eUseSystemDirectory))
   , mMiscTypelib(mozilla::mscom::RegisterTypelib(L"Accessible.tlb"))
   , mSdnTypelib(mozilla::mscom::RegisterTypelib(L"AccessibleMarshal.dll"))
 {
+  WORD actCtxResourceId = Compatibility::GetActCtxResourceId();
+
+  mozilla::mscom::MTADeletePtr<mozilla::mscom::ActivationContextRegion> tmpActCtxMTA;
+  mozilla::mscom::EnsureMTA([actCtxResourceId, &tmpActCtxMTA]() -> void {
+    tmpActCtxMTA.reset(new mozilla::mscom::ActivationContextRegion(actCtxResourceId));
+  });
+  mActCtxMTA = Move(tmpActCtxMTA);
+
   mozilla::mscom::InterceptorLog::Init();
   mozilla::mscom::RegisterArrayData(sPlatformChildArrayData);
 
 
   UniquePtr<mozilla::mscom::RegisteredProxy> customProxy;
   mozilla::mscom::EnsureMTA([&customProxy]() -> void {
     customProxy = Move(mozilla::mscom::RegisterProxy());
   });
--- a/accessible/ipc/win/PlatformChild.h
+++ b/accessible/ipc/win/PlatformChild.h
@@ -2,32 +2,35 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #ifndef mozilla_a11y_PlatformChild_h
 #define mozilla_a11y_PlatformChild_h
 
+#include "mozilla/mscom/ActivationContext.h"
+#include "mozilla/mscom/Ptr.h"
 #include "mozilla/mscom/Registration.h"
 
 namespace mozilla {
 namespace a11y {
 
 class PlatformChild
 {
 public:
   PlatformChild();
 
   PlatformChild(PlatformChild&) = delete;
   PlatformChild(PlatformChild&&) = delete;
   PlatformChild& operator=(PlatformChild&) = delete;
   PlatformChild& operator=(PlatformChild&&) = delete;
 
 private:
+  mscom::MTADeletePtr<mozilla::mscom::ActivationContextRegion> mActCtxMTA;
   UniquePtr<mozilla::mscom::RegisteredProxy> mCustomProxy;
   UniquePtr<mozilla::mscom::RegisteredProxy> mIA2Proxy;
   UniquePtr<mozilla::mscom::RegisteredProxy> mAccTypelib;
   UniquePtr<mozilla::mscom::RegisteredProxy> mMiscTypelib;
   UniquePtr<mozilla::mscom::RegisteredProxy> mSdnTypelib;
 };
 
 } // namespace mozilla
--- a/accessible/ipc/win/handler/AccessibleHandler.cpp
+++ b/accessible/ipc/win/handler/AccessibleHandler.cpp
@@ -217,27 +217,22 @@ AccessibleHandler::ReadHandlerPayload(IS
   if (!deserializer.Read(&mCachedData, &IA2Payload_Decode)) {
     return E_FAIL;
   }
 
   if (!mCachedData.mGeckoBackChannel) {
     return S_OK;
   }
 
-  long pid = static_cast<long>(::GetCurrentProcessId());
-
-  RefPtr<IHandlerControl> ctl;
-  HRESULT hr = gControlFactory.CreateInstance(nullptr, IID_IHandlerControl,
-                                              getter_AddRefs(ctl));
-  if (SUCCEEDED(hr)) {
-    hr = mCachedData.mGeckoBackChannel->put_HandlerControl(pid, ctl);
-    MOZ_ASSERT(SUCCEEDED(hr));
+  RefPtr<AccessibleHandlerControl> ctl(gControlFactory.GetOrCreateSingleton());
+  if (!ctl) {
+    return E_OUTOFMEMORY;
   }
 
-  return hr;
+  return ctl->Register(WrapNotNull(mCachedData.mGeckoBackChannel));
 }
 
 REFIID
 AccessibleHandler::MarshalAs(REFIID aIid)
 {
   static_assert(&NEWEST_IA2_IID == &IID_IAccessible2_3,
                 "You have modified NEWEST_IA2_IID. This code needs updating.");
   if (aIid == IID_IAccessible2_3 || aIid == IID_IAccessible2_2 ||
--- a/accessible/ipc/win/handler/AccessibleHandlerControl.cpp
+++ b/accessible/ipc/win/handler/AccessibleHandlerControl.cpp
@@ -127,17 +127,18 @@ AccessibleHandlerControl::Create(Accessi
   }
 
   RefPtr<AccessibleHandlerControl> ctl(new AccessibleHandlerControl());
   ctl.forget(aOutObject);
   return S_OK;
 }
 
 AccessibleHandlerControl::AccessibleHandlerControl()
-  : mCacheGen(0)
+  : mIsRegistered(false)
+  , mCacheGen(0)
   , mIA2Proxy(mscom::RegisterProxy(L"ia2marshal.dll"))
   , mHandlerProxy(mscom::RegisterProxy())
 {
   MOZ_ASSERT(mIA2Proxy);
 }
 
 IMPL_IUNKNOWN1(AccessibleHandlerControl, IHandlerControl)
 
@@ -184,10 +185,24 @@ AccessibleHandlerControl::GetHandlerType
   if (!mHandlerProxy) {
     return E_UNEXPECTED;
   }
 
   return mHandlerProxy->GetTypeInfoForGuid(CLSID_AccessibleHandler,
                                            aOutTypeInfo);
 }
 
+HRESULT
+AccessibleHandlerControl::Register(NotNull<IGeckoBackChannel*> aGecko)
+{
+  if (mIsRegistered) {
+    return S_OK;
+  }
+
+  long pid = static_cast<long>(::GetCurrentProcessId());
+  HRESULT hr = aGecko->put_HandlerControl(pid, this);
+  mIsRegistered = SUCCEEDED(hr);
+  MOZ_ASSERT(mIsRegistered);
+  return hr;
+}
+
 } // namespace a11y
 } // namespace mozilla
--- a/accessible/ipc/win/handler/AccessibleHandlerControl.h
+++ b/accessible/ipc/win/handler/AccessibleHandlerControl.h
@@ -66,20 +66,23 @@ public:
     return mCacheGen;
   }
 
   HRESULT GetNewText(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutNewText);
   HRESULT GetOldText(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutOldText);
 
   HRESULT GetHandlerTypeInfo(ITypeInfo** aOutTypeInfo);
 
+  HRESULT Register(NotNull<IGeckoBackChannel*> aGecko);
+
 private:
   AccessibleHandlerControl();
   ~AccessibleHandlerControl() = default;
 
+  bool mIsRegistered;
   uint32_t mCacheGen;
   detail::TextChange mTextChange;
   UniquePtr<mscom::RegisteredProxy> mIA2Proxy;
   UniquePtr<mscom::RegisteredProxy> mHandlerProxy;
 };
 
 extern mscom::SingletonFactory<AccessibleHandlerControl> gControlFactory;
 
--- a/accessible/ipc/win/moz.build
+++ b/accessible/ipc/win/moz.build
@@ -8,19 +8,31 @@ if CONFIG['COMPILE_ENVIRONMENT'] and CON
     DIRS += [
         'handler',
         'typelib',
     ]
 
 # With --disable-accessibility, we need to compile PDocAccessible.ipdl (which
 # also depends on COMPtrTypes.h), but not the C++.
 IPDL_SOURCES += ['PDocAccessible.ipdl']
-EXPORTS.mozilla.a11y += ['COMPtrTypes.h']
+
+EXPORTS.mozilla.a11y += [
+    'COMPtrTypes.h',
+]
 
 if CONFIG['ACCESSIBILITY']:
+    if not CONFIG['HAVE_64BIT_BUILD']:
+        EXPORTS += [
+            'IAccessible32.manifest',
+        ]
+
+    EXPORTS += [
+        'IAccessible64.manifest',
+    ]
+
     EXPORTS.mozilla.a11y += [
         'DocAccessibleChild.h',
         'HandlerProvider.h',
         'PlatformChild.h',
         'ProxyAccessible.h'
     ]
 
     SOURCES += [
--- a/accessible/jsat/AccessFu.jsm
+++ b/accessible/jsat/AccessFu.jsm
@@ -301,19 +301,21 @@ this.AccessFu = { // jshint ignore:line
   onEvent: function (event, data, callback) {
     switch (event) {
       case 'Accessibility:Settings':
         this._systemPref = data.enabled;
         this._enableOrDisable();
         break;
       case 'Accessibility:NextObject':
       case 'Accessibility:PreviousObject': {
-        let rule = data ?
-          data.rule.substr(0, 1).toUpperCase() + data.rule.substr(1).toLowerCase() :
-          'Simple';
+        let rule = 'Simple';
+        if (data && data.rule && data.rule.length) {
+          rule = data.rule.substr(0, 1).toUpperCase() +
+            data.rule.substr(1).toLowerCase();
+        }
         let method = event.replace(/Accessibility:(\w+)Object/, 'move$1');
         this.Input.moveCursor(method, rule, 'gesture');
         break;
       }
       case 'Accessibility:ActivateObject':
         this.Input.activateCurrent(data);
         break;
       case 'Accessibility:LongPress':
@@ -372,21 +374,21 @@ this.AccessFu = { // jshint ignore:line
         break;
       }
       case 'TabSelect':
       {
         if (this._focused) {
           // We delay this for half a second so the awesomebar could close,
           // and we could use the current coordinates for the content item.
           // XXX TODO figure out how to avoid magic wait here.
-	  this.autoMove({
-	    delay: 500,
-	    forcePresent: true,
-	    noOpIfOnScreen: true,
-	    moveMethod: 'moveFirst' });
+          this.autoMove({
+            delay: 500,
+            forcePresent: true,
+            noOpIfOnScreen: true,
+            moveMethod: 'moveFirst' });
         }
         break;
       }
       default:
       {
         // A settings change, it does not have an event type
         if (aEvent.settingName == SCREENREADER_SETTING) {
           this._systemPref = aEvent.settingValue;
@@ -589,17 +591,17 @@ var Output = {
 
     for (let androidEvent of aDetails) {
       androidEvent.type = 'Accessibility:Event';
       if (androidEvent.bounds) {
         androidEvent.bounds = AccessFu.adjustContentBounds(
           androidEvent.bounds, aBrowser);
       }
 
-      switch(androidEvent.eventType) {
+      switch (androidEvent.eventType) {
         case ANDROID_VIEW_TEXT_CHANGED:
           androidEvent.brailleOutput = this.brailleState.adjustText(
             androidEvent.text);
           break;
         case ANDROID_VIEW_TEXT_SELECTION_CHANGED:
           androidEvent.brailleOutput = this.brailleState.adjustSelection(
             androidEvent.brailleOutput);
           break;
--- a/accessible/jsat/ContentControl.jsm
+++ b/accessible/jsat/ContentControl.jsm
@@ -319,17 +319,17 @@ this.ContentControl.prototype = {
     return true;
   },
 
   handleMoveByGranularity: function cc_handleMoveByGranularity(aMessage) {
     // XXX: Add sendToChild. Right now this is only used in Android, so no need.
     let direction = aMessage.json.direction;
     let granularity;
 
-    switch(aMessage.json.granularity) {
+    switch (aMessage.json.granularity) {
       case MOVEMENT_GRANULARITY_CHARACTER:
         granularity = Ci.nsIAccessiblePivot.CHAR_BOUNDARY;
         break;
       case MOVEMENT_GRANULARITY_WORD:
         granularity = Ci.nsIAccessiblePivot.WORD_BOUNDARY;
         break;
       default:
         return;
--- a/accessible/jsat/Gestures.jsm
+++ b/accessible/jsat/Gestures.jsm
@@ -45,18 +45,18 @@ Cu.import('resource://gre/modules/XPCOMU
 XPCOMUtils.defineLazyModuleGetter(this, 'Utils', // jshint ignore:line
   'resource://gre/modules/accessibility/Utils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Logger', // jshint ignore:line
   'resource://gre/modules/accessibility/Utils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'setTimeout', // jshint ignore:line
   'resource://gre/modules/Timer.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'clearTimeout', // jshint ignore:line
   'resource://gre/modules/Timer.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Promise', // jshint ignore:line
-  'resource://gre/modules/Promise.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'PromiseUtils', // jshint ignore:line
+  'resource://gre/modules/PromiseUtils.jsm');
 
 // Default maximum duration of swipe
 const SWIPE_MAX_DURATION = 200;
 // Default maximum amount of time allowed for a gesture to be considered a
 // multitouch
 const MAX_MULTITOUCH = 125;
 // Default maximum consecutive pointer event timeout
 const MAX_CONSECUTIVE_GESTURE_DELAY = 200;
@@ -319,17 +319,17 @@ function compileDetail(aType, aPoints, k
  * Default is an empty object.
  * @param {?String} aLastEvent Last pointer event type.
  */
 function Gesture(aTimeStamp, aPoints = {}, aLastEvent = undefined) {
   this.startTime = Date.now();
   Logger.gesture('Creating', this.id, 'gesture.');
   this.points = aPoints;
   this.lastEvent = aLastEvent;
-  this._deferred = Promise.defer();
+  this._deferred = PromiseUtils.defer();
   // Call this._handleResolve or this._handleReject when the promise is
   // fulfilled with either resolve or reject.
   this.promise = this._deferred.promise.then(this._handleResolve.bind(this),
     this._handleReject.bind(this));
   this.startTimer(aTimeStamp);
 }
 
 Gesture.prototype = {
--- a/accessible/jsat/OutputGenerator.jsm
+++ b/accessible/jsat/OutputGenerator.jsm
@@ -209,17 +209,17 @@ var OutputGenerator = {
    * Adds math roles to the output, for a MathML accessible.
    * @param {Array} aOutput Output array.
    * @param {nsIAccessible} aAccessible current accessible object.
    * @param {String} aRoleStr aAccessible's role string.
    */
   _addMathRoles: function _addMathRoles(aOutput, aAccessible, aRoleStr) {
     // First, determine the actual role to use (e.g. mathmlfraction).
     let roleStr = aRoleStr;
-    switch(aAccessible.role) {
+    switch (aAccessible.role) {
       case Roles.MATHML_CELL:
       case Roles.MATHML_ENCLOSED:
       case Roles.MATHML_LABELED_ROW:
       case Roles.MATHML_ROOT:
       case Roles.MATHML_SQUARE_ROOT:
       case Roles.MATHML_TABLE:
       case Roles.MATHML_TABLE_ROW:
         // Use the default role string.
@@ -253,22 +253,22 @@ var OutputGenerator = {
         roleStr = null;
         break;
     }
 
     // Get the math role based on the position in the parent accessible
     // (e.g. numerator for the first child of a mathmlfraction).
     let mathRole = Utils.getMathRole(aAccessible);
     if (mathRole) {
-      aOutput[this.outputOrder === OUTPUT_DESC_FIRST ? 'push' : 'unshift']
-        ({string: this._getOutputName(mathRole)});
+      aOutput[this.outputOrder === OUTPUT_DESC_FIRST ? 'push' : 'unshift']({
+        string: this._getOutputName(mathRole)});
     }
     if (roleStr) {
-      aOutput[this.outputOrder === OUTPUT_DESC_FIRST ? 'push' : 'unshift']
-        ({string: this._getOutputName(roleStr)});
+      aOutput[this.outputOrder === OUTPUT_DESC_FIRST ? 'push' : 'unshift']({
+        string: this._getOutputName(roleStr)});
     }
   },
 
   /**
    * Adds MathML menclose notations to the output.
    * @param {Array} aOutput Output array.
    * @param {nsIAccessible} aAccessible current accessible object.
    */
@@ -679,24 +679,24 @@ this.UtteranceGenerator = {  // jshint i
 
       this._addName(utterance, aAccessible, aFlags);
       this._addLandmark(utterance, aAccessible);
 
       return utterance;
     },
 
     list: function list(aAccessible, aRoleStr, aState, aFlags) {
-      return this._getListUtterance
-        (aAccessible, aRoleStr, aFlags, aAccessible.childCount);
+      return this._getListUtterance(aAccessible, aRoleStr, aFlags,
+        aAccessible.childCount);
     },
 
     definitionlist:
       function definitionlist(aAccessible, aRoleStr, aState, aFlags) {
-        return this._getListUtterance
-          (aAccessible, aRoleStr, aFlags, aAccessible.childCount / 2);
+        return this._getListUtterance(aAccessible, aRoleStr, aFlags,
+          aAccessible.childCount / 2);
       },
 
     application: function application(aAccessible, aRoleStr, aState, aFlags) {
       // Don't utter location of applications, it gets tiring.
       if (aAccessible.name != aAccessible.DOMNode.location) {
         return this.objectOutputFunctions.defaultFunc.apply(this,
           [aAccessible, aRoleStr, aState, aFlags]);
       }
--- a/accessible/jsat/PointerAdapter.jsm
+++ b/accessible/jsat/PointerAdapter.jsm
@@ -34,57 +34,57 @@ var PointerRelay = { // jshint ignore:li
    * value of |false| are cancelled and do not propogate to content.
    */
   get _eventsOfInterest() {
     delete this._eventsOfInterest;
 
     switch (Utils.widgetToolkit) {
       case 'android':
         this._eventsOfInterest = {
-          'touchstart' : true,
-          'touchmove' : true,
-          'touchend' : true };
+          'touchstart': true,
+          'touchmove': true,
+          'touchend': true };
         break;
 
       case 'gonk':
         this._eventsOfInterest = {
-          'touchstart' : true,
-          'touchmove' : true,
-          'touchend' : true,
-          'mousedown' : false,
-          'mousemove' : false,
+          'touchstart': true,
+          'touchmove': true,
+          'touchend': true,
+          'mousedown': false,
+          'mousemove': false,
           'mouseup': false,
           'click': false };
         break;
 
       default:
         // Desktop.
         this._eventsOfInterest = {
-          'mousemove' : true,
-          'mousedown' : true,
+          'mousemove': true,
+          'mousedown': true,
           'mouseup': true,
           'click': false
         };
         if ('ontouchstart' in Utils.win) {
           for (let eventType of ['touchstart', 'touchmove', 'touchend']) {
             this._eventsOfInterest[eventType] = true;
           }
         }
         break;
     }
 
     return this._eventsOfInterest;
   },
 
   _eventMap: {
-    'touchstart' : 'pointerdown',
-    'mousedown' : 'pointerdown',
-    'touchmove' : 'pointermove',
-    'mousemove' : 'pointermove',
-    'touchend' : 'pointerup',
+    'touchstart': 'pointerdown',
+    'mousedown': 'pointerdown',
+    'touchmove': 'pointermove',
+    'mousemove': 'pointermove',
+    'touchend': 'pointerup',
     'mouseup': 'pointerup'
   },
 
   start: function PointerRelay_start(aOnPointerEvent) {
     Logger.debug('PointerRelay.start');
     this.onPointerEvent = aOnPointerEvent;
     for (let eventType in this._eventsOfInterest) {
       Utils.win.addEventListener(eventType, this, true, true);
--- a/accessible/jsat/Presentation.jsm
+++ b/accessible/jsat/Presentation.jsm
@@ -753,15 +753,14 @@ this.Presentation = { // jshint ignore:l
   noMove: function Presentation_noMove(aMoveMethod) {
     return this.presenters.map(p => p.noMove(aMoveMethod));
   },
 
   liveRegion: function Presentation_liveRegion(aAccessible, aIsPolite, aIsHide,
     aModifiedText) {
     let context;
     if (!aModifiedText) {
-      context = new PivotContext(aAccessible, null, -1, -1, true,
-        aIsHide ? true : false);
+      context = new PivotContext(aAccessible, null, -1, -1, true, !!aIsHide);
     }
     return this.presenters.map(p => p.liveRegion(context, aIsPolite, aIsHide,
                                                  aModifiedText));
   }
 };
--- a/accessible/jsat/Utils.jsm
+++ b/accessible/jsat/Utils.jsm
@@ -488,17 +488,17 @@ this.Utils = { // jshint ignore:line
     return parent.role === Roles.LISTITEM && parent.childCount > 1 &&
       aStaticText.indexInParent === 0;
   },
 
   dispatchChromeEvent: function dispatchChromeEvent(aType, aDetails) {
     let details = {
       type: aType,
       details: JSON.stringify(
-        typeof aDetails === 'string' ? { eventType : aDetails } : aDetails)
+        typeof aDetails === 'string' ? { eventType: aDetails } : aDetails)
     };
     let window = this.win;
     let shell = window.shell || window.content.shell;
     if (shell) {
       // On B2G device.
       shell.sendChromeEvent(details);
     } else {
       // Dispatch custom event to have support for desktop and screen reader
@@ -632,17 +632,17 @@ this.Logger = { // jshint ignore:line
   },
 
   accessibleToString: function accessibleToString(aAccessible) {
     if (!aAccessible) {
       return '[ null ]';
     }
 
     try {
-      return'[ ' + Utils.AccService.getStringRole(aAccessible.role) +
+      return '[ ' + Utils.AccService.getStringRole(aAccessible.role) +
         ' | ' + aAccessible.name + ' ]';
     } catch (x) {
       return '[ defunct ]';
     }
   },
 
   eventToString: function eventToString(aEvent) {
     let str = Utils.AccService.getStringEventType(aEvent.eventType);
@@ -655,17 +655,17 @@ this.Logger = { // jshint ignore:line
     }
 
     if (aEvent.eventType == Events.VIRTUALCURSOR_CHANGED) {
       let event = aEvent.QueryInterface(
         Ci.nsIAccessibleVirtualCursorChangeEvent);
       let pivot = aEvent.accessible.QueryInterface(
         Ci.nsIAccessibleDocument).virtualCursor;
       str += ' (' + this.accessibleToString(event.oldAccessible) + ' -> ' +
-	this.accessibleToString(pivot.position) + ')';
+        this.accessibleToString(pivot.position) + ')';
     }
 
     return str;
   },
 
   statesToString: function statesToString(aAccessible) {
     return Utils.getState(aAccessible).toString();
   },
@@ -1063,11 +1063,11 @@ PrefCache.prototype = {
       try {
         this.callback(this.name, this.value, false);
       } catch (x) {
         Logger.logException(x);
       }
     }
   },
 
-  QueryInterface : XPCOMUtils.generateQI([Ci.nsIObserver,
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
                                           Ci.nsISupportsWeakReference])
 };
--- a/accessible/mac/mozAccessible.h
+++ b/accessible/mac/mozAccessible.h
@@ -109,16 +109,19 @@ static const uintptr_t IS_PROXY = 1;
 - (id)value;
 
 // name that is associated with this accessible (for buttons, etc)
 - (NSString*)title;
 
 // the accessible description (help text) of this particular instance.
 - (NSString*)help;
 
+// returns the orientation (vertical, horizontal, or undefined)
+- (NSString*)orientation;
+
 - (BOOL)isEnabled;
 
 // information about focus.
 - (BOOL)isFocused;
 - (BOOL)canBeFocused;
 
 // returns NO if for some reason we were unable to focus the element.
 - (BOOL)focus;
--- a/accessible/mac/mozAccessible.mm
+++ b/accessible/mac/mozAccessible.mm
@@ -28,16 +28,17 @@
 #include "nsCoord.h"
 #include "nsObjCExceptions.h"
 #include "nsWhitespaceTokenizer.h"
 #include <prdtoa.h>
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
+#define NSAccessibilityDOMIdentifierAttribute @"AXDOMIdentifier"
 #define NSAccessibilityMathRootRadicandAttribute @"AXMathRootRadicand"
 #define NSAccessibilityMathRootIndexAttribute @"AXMathRootIndex"
 #define NSAccessibilityMathFractionNumeratorAttribute @"AXMathFractionNumerator"
 #define NSAccessibilityMathFractionDenominatorAttribute @"AXMathFractionDenominator"
 #define NSAccessibilityMathBaseAttribute @"AXMathBase"
 #define NSAccessibilityMathSubscriptAttribute @"AXMathSubscript"
 #define NSAccessibilityMathSuperscriptAttribute @"AXMathSuperscript"
 #define NSAccessibilityMathUnderAttribute @"AXMathUnder"
@@ -154,16 +155,17 @@ ConvertToNSArray(nsTArray<ProxyAccessibl
   return true;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
 }
 
 - (NSArray*)additionalAccessibilityAttributeNames
 {
   NSMutableArray* additional = [NSMutableArray array];
+  [additional addObject:NSAccessibilityDOMIdentifierAttribute];
   switch (mRole) {
     case roles::MATHML_ROOT:
       [additional addObject:NSAccessibilityMathRootIndexAttribute];
       [additional addObject:NSAccessibilityMathRootRadicandAttribute];
       break;
     case roles::MATHML_SQUARE_ROOT:
       [additional addObject:NSAccessibilityMathRootRadicandAttribute];
       break;
@@ -316,16 +318,27 @@ ConvertToNSArray(nsTArray<ProxyAccessibl
       return tempAcc ? GetNativeFromGeckoAccessible(tempAcc) : nil;
     }
     nsTArray<ProxyAccessible*> rel = proxy->RelationByType(RelationType::LABELLED_BY);
     ProxyAccessible* tempProxy = rel.SafeElementAt(0);
     return tempProxy ? GetNativeFromProxy(tempProxy) : nil;
   }
   if ([attribute isEqualToString:NSAccessibilityHelpAttribute])
     return [self help];
+  if ([attribute isEqualToString:NSAccessibilityOrientationAttribute])
+    return [self orientation];
+
+  if ([attribute isEqualToString:NSAccessibilityDOMIdentifierAttribute]) {
+    nsAutoString id;
+    if (accWrap)
+      nsCoreUtils::GetID(accWrap->GetContent(), id);
+    else
+      proxy->DOMNodeID(id);
+    return nsCocoaUtils::ToNSString(id);
+  }
 
   switch (mRole) {
   case roles::MATHML_ROOT:
     if ([attribute isEqualToString:NSAccessibilityMathRootRadicandAttribute])
       return [self childAt:0];
     if ([attribute isEqualToString:NSAccessibilityMathRootIndexAttribute])
       return [self childAt:1];
     break;
@@ -721,16 +734,18 @@ ConvertToNSArray(nsTArray<ProxyAccessibl
 
   // Deal with landmarks first
   nsIAtom* landmark = nullptr;
   if (accWrap)
     landmark = accWrap->LandmarkRole();
   else if (proxy)
     landmark = proxy->LandmarkRole();
 
+  // HTML Elements treated as landmarks
+  // XXX bug 1371712
   if (landmark) {
     if (landmark == nsGkAtoms::application)
       return @"AXLandmarkApplication";
     if (landmark == nsGkAtoms::banner)
       return @"AXLandmarkBanner";
     if (landmark == nsGkAtoms::complementary)
       return @"AXLandmarkComplementary";
     if (landmark == nsGkAtoms::contentinfo)
@@ -742,16 +757,23 @@ ConvertToNSArray(nsTArray<ProxyAccessibl
     if (landmark == nsGkAtoms::navigation)
       return @"AXLandmarkNavigation";
     if (landmark == nsGkAtoms::search)
       return @"AXLandmarkSearch";
     if (landmark == nsGkAtoms::searchbox)
       return @"AXSearchField";
   }
 
+  // macOS groups the specific landmark types of DPub ARIA into two broad
+  // categories with corresponding subroles: Navigation and region/container.
+  if (mRole == roles::NAVIGATION)
+    return @"AXLandmarkNavigation";
+  if (mRole == roles::LANDMARK)
+    return @"AXLandmarkRegion";
+
   // Now, deal with widget roles
   nsIAtom* roleAtom = nullptr;
   if (accWrap && accWrap->HasARIARole()) {
     const nsRoleMapEntry* roleMap = accWrap->ARIARoleMap();
     roleAtom = *roleMap->roleAtom;
   }
   if (proxy)
     roleAtom = proxy->ARIARoleAtom();
@@ -771,17 +793,17 @@ ConvertToNSArray(nsTArray<ProxyAccessibl
       return @"AXApplicationLog";
     if (roleAtom == nsGkAtoms::marquee)
       return @"AXApplicationMarquee";
     if (roleAtom == nsGkAtoms::math)
       return @"AXDocumentMath";
     if (roleAtom == nsGkAtoms::note_)
       return @"AXDocumentNote";
     if (roleAtom == nsGkAtoms::region)
-      return @"AXDocumentRegion";
+      return mRole == roles::REGION ? @"AXLandmarkRegion" : nil;
     if (roleAtom == nsGkAtoms::status)
       return @"AXApplicationStatus";
     if (roleAtom == nsGkAtoms::tabpanel)
       return @"AXTabPanel";
     if (roleAtom == nsGkAtoms::timer)
       return @"AXApplicationTimer";
     if (roleAtom == nsGkAtoms::tooltip)
       return @"AXUserInterfaceTooltip";
@@ -872,28 +894,43 @@ ConvertToNSArray(nsTArray<ProxyAccessibl
       return @"AXMathMultiscript";
 
     case roles::SWITCH:
       return @"AXSwitch";
 
     case roles::ALERT:
       return @"AXApplicationAlert";
 
-    case roles::SEPARATOR:
-      return @"AXContentSeparator";
-
     case roles::PROPERTYPAGE:
       return @"AXTabPanel";
 
     case roles::DETAILS:
       return @"AXDetails";
 
     case roles::SUMMARY:
       return @"AXSummary";
 
+    case roles::NOTE:
+      return @"AXDocumentNote";
+
+    case roles::OUTLINEITEM:
+      return @"AXOutlineRow";
+
+    case roles::ARTICLE:
+      return @"AXDocumentArticle";
+
+    // macOS added an AXSubrole value to distinguish generic AXGroup objects
+    // from those which are AXGroups as a result of an explicit ARIA role,
+    // such as the non-landmark, non-listitem text containers in DPub ARIA.
+    case roles::FOOTNOTE:
+    case roles::SECTION:
+      if (roleAtom)
+        return @"AXApplicationGroup";
+      break;
+
     default:
       break;
   }
 
   return nil;
 }
 
 struct RoleDescrMap
@@ -910,23 +947,23 @@ static const RoleDescrMap sRoleDescrMap[
   { @"AXApplicationStatus", NS_LITERAL_STRING("status") },
   { @"AXApplicationTimer", NS_LITERAL_STRING("timer") },
   { @"AXContentSeparator", NS_LITERAL_STRING("separator") },
   { @"AXDefinition", NS_LITERAL_STRING("definition") },
   { @"AXDocument", NS_LITERAL_STRING("document") },
   { @"AXDocumentArticle", NS_LITERAL_STRING("article") },
   { @"AXDocumentMath", NS_LITERAL_STRING("math") },
   { @"AXDocumentNote", NS_LITERAL_STRING("note") },
-  { @"AXDocumentRegion", NS_LITERAL_STRING("region") },
   { @"AXLandmarkApplication", NS_LITERAL_STRING("application") },
   { @"AXLandmarkBanner", NS_LITERAL_STRING("banner") },
   { @"AXLandmarkComplementary", NS_LITERAL_STRING("complementary") },
   { @"AXLandmarkContentInfo", NS_LITERAL_STRING("content") },
   { @"AXLandmarkMain", NS_LITERAL_STRING("main") },
   { @"AXLandmarkNavigation", NS_LITERAL_STRING("navigation") },
+  { @"AXLandmarkRegion", NS_LITERAL_STRING("region") },
   { @"AXLandmarkSearch", NS_LITERAL_STRING("search") },
   { @"AXSearchField", NS_LITERAL_STRING("searchTextField") },
   { @"AXTabPanel", NS_LITERAL_STRING("tabPanel") },
   { @"AXTerm", NS_LITERAL_STRING("term") },
   { @"AXUserInterfaceTooltip", NS_LITERAL_STRING("tooltip") }
 };
 
 struct RoleDescrComparator
@@ -938,16 +975,22 @@ struct RoleDescrComparator
   }
 };
 
 - (NSString*)roleDescription
 {
   if (mRole == roles::DOCUMENT)
     return utils::LocalizedString(NS_LITERAL_STRING("htmlContent"));
 
+  if (mRole == roles::FIGURE)
+    return utils::LocalizedString(NS_LITERAL_STRING("figure"));
+
+  if (mRole == roles::HEADING)
+    return utils::LocalizedString(NS_LITERAL_STRING("heading"));
+
   NSString* subrole = [self subrole];
 
   if (subrole) {
     size_t idx = 0;
     if (BinarySearchIf(sRoleDescrMap, 0, ArrayLength(sRoleDescrMap),
                        RoleDescrComparator(subrole), &idx)) {
       return utils::LocalizedString(sRoleDescrMap[idx].description);
     }
@@ -1024,16 +1067,38 @@ struct RoleDescrComparator
   else if (ProxyAccessible* proxy = [self getProxyAccessible])
     proxy->Description(helpText);
 
   return nsCocoaUtils::ToNSString(helpText);
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
 }
 
+- (NSString*)orientation
+{
+  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
+
+  uint64_t state;
+  if (AccessibleWrap* accWrap = [self getGeckoAccessible])
+    state = accWrap->InteractiveState();
+  else if (ProxyAccessible* proxy = [self getProxyAccessible])
+    state = proxy->State();
+  else
+    state = 0;
+
+  if (state & states::HORIZONTAL)
+    return NSAccessibilityHorizontalOrientationValue;
+  if (state & states::VERTICAL)
+    return NSAccessibilityVerticalOrientationValue;
+
+  return NSAccessibilityUnknownOrientationValue;
+
+  NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
+}
+
 // objc-style description (from NSObject); not to be confused with the accessible description above.
 - (NSString*)description
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
 
   return [NSString stringWithFormat:@"(%p) %@", self, [self role]];
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
--- a/accessible/moz.build
+++ b/accessible/moz.build
@@ -26,15 +26,19 @@ DIRS += [ 'aom',
 ]
 
 if CONFIG['MOZ_XUL']:
     DIRS += ['xul']
 
 TEST_DIRS += ['tests/mochitest']
 
 BROWSER_CHROME_MANIFESTS += [
+  'tests/browser/bounds/browser.ini',
   'tests/browser/browser.ini',
   'tests/browser/e10s/browser.ini',
-  'tests/browser/states/browser.ini'
+  'tests/browser/events/browser.ini',
+  'tests/browser/scroll/browser.ini',
+  'tests/browser/states/browser.ini',
+  'tests/browser/tree/browser.ini'
 ]
 
 with Files("**"):
-    BUG_COMPONENT = ("Core", "Disability Access APIs")
\ No newline at end of file
+    BUG_COMPONENT = ("Core", "Disability Access APIs")
--- a/accessible/other/AccessibleWrap.cpp
+++ b/accessible/other/AccessibleWrap.cpp
@@ -3,17 +3,17 @@
  * 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/. */
 
 #include "AccessibleWrap.h"
 
 using namespace mozilla::a11y;
 
 //-----------------------------------------------------
-// construction 
+// construction
 //-----------------------------------------------------
 AccessibleWrap::
   AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) :
   Accessible(aContent, aDoc)
 {
 }
 
 //-----------------------------------------------------
--- a/accessible/other/AccessibleWrap.h
+++ b/accessible/other/AccessibleWrap.h
@@ -1,14 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
-/* For documentation of the accessibility architecture, 
+/* For documentation of the accessibility architecture,
  * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
  */
 
 #ifndef mozilla_a11y_AccessibleWrap_h_
 #define mozilla_a11y_AccessibleWrap_h_
 
 #include "nsCOMPtr.h"
 #include "Accessible.h"
--- a/accessible/other/DocAccessibleWrap.h
+++ b/accessible/other/DocAccessibleWrap.h
@@ -1,14 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
-/* For documentation of the accessibility architecture, 
+/* For documentation of the accessibility architecture,
  * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
  */
 
 #ifndef mozilla_a11y_DocAccessibleWrap_h__
 #define mozilla_a11y_DocAccessibleWrap_h__
 
 #include "DocAccessible.h"
 
--- a/accessible/other/RootAccessibleWrap.h
+++ b/accessible/other/RootAccessibleWrap.h
@@ -1,14 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
-/* For documentation of the accessibility architecture, 
+/* For documentation of the accessibility architecture,
  * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
  */
 
 #ifndef mozilla_a11y_RootAccessibleWrap_h__
 #define mozilla_a11y_RootAccessibleWrap_h__
 
 #include "RootAccessible.h"
 
--- a/accessible/other/TextLeafAccessibleWrap.h
+++ b/accessible/other/TextLeafAccessibleWrap.h
@@ -5,15 +5,15 @@
 
 #ifndef mozilla_a11y_TextLeafAccessibleWrap_h__
 #define mozilla_a11y_TextLeafAccessibleWrap_h__
 
 #include "TextLeafAccessible.h"
 
 namespace mozilla {
 namespace a11y {
- 
+
 typedef class TextLeafAccessible TextLeafAccessibleWrap;
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/tests/browser/.eslintrc.js
+++ b/accessible/tests/browser/.eslintrc.js
@@ -8,17 +8,16 @@ module.exports = {
     "mozilla/no-aArgs": "error",
     "mozilla/no-cpows-in-tests": "error",
     "mozilla/reject-importGlobalProperties": "error",
     "mozilla/var-only-at-top-level": "error",
 
     "block-scoped-var": "error",
     "camelcase": "error",
     "comma-dangle": ["error", "never"],
-    "comma-style": ["error", "last"],
     "complexity": ["error", 20],
     "consistent-this": "off",
     "curly": ["error", "multi-line"],
     "default-case": "off",
     "dot-location": ["error", "property"],
     "dot-notation": "error",
     "eqeqeq": "off",
     "func-names": "off",
@@ -62,17 +61,16 @@ module.exports = {
     "no-sequences": "error",
     "no-shadow": "error",
     "no-space-before-semi": "off",
     "no-sync": "off",
     "no-ternary": "off",
     "no-throw-literal": "error",
     "no-underscore-dangle": "off",
     "no-undefined": "off",
-    "no-unneeded-ternary": "error",
     "no-unused-vars": ["error", {"vars": "all", "args": "none"}],
     "no-use-before-define": "off",
     "no-var": "off",
     "no-warning-comments": "off",
     "object-shorthand": "off",
     "one-var": ["error", "never"],
     "padded-blocks": ["error", "never"],
     "quote-props": "off",
new file mode 100644
--- /dev/null
+++ b/accessible/tests/browser/bounds/browser.ini
@@ -0,0 +1,12 @@
+[DEFAULT]
+skip-if = e10s && os == 'win' && release_or_beta
+support-files =
+  head.js
+  !/accessible/tests/browser/events.js
+  !/accessible/tests/browser/shared-head.js
+  !/accessible/tests/mochitest/*.js
+  !/accessible/tests/mochitest/letters.gif
+
+[browser_test_zoom.js]
+[browser_test_zoom_text.js]
+skip-if = true # Bug 1372296, Bug 1379808, Bug 1391453
new file mode 100644
--- /dev/null
+++ b/accessible/tests/browser/bounds/browser_test_zoom.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/layout.js */
+
+async function getContentBoundsForDOMElm(browser, id) {
+  return ContentTask.spawn(browser, id, contentId => {
+    this.ok = ok;
+    return getBoundsForDOMElm(contentId);
+  });
+}
+
+async function testContentBounds(browser, acc) {
+  let [expectedX, expectedY, expectedWidth, expectedHeight] =
+    await getContentBoundsForDOMElm(browser, getAccessibleDOMNodeID(acc));
+
+  let [x, y, width, height] = getBounds(acc);
+  let prettyAccName = prettyName(acc);
+  is(x, expectedX, "Wrong x coordinate of " + prettyAccName);
+  is(y, expectedY, "Wrong y coordinate of " + prettyAccName);
+  is(width, expectedWidth, "Wrong width of " + prettyAccName);
+  is(height, expectedHeight, "Wrong height of " + prettyAccName);
+}
+
+async function runTests(browser, accDoc) {
+  loadFrameScripts(browser, { name: 'layout.js', dir: MOCHITESTS_DIR });
+
+  let p1 = findAccessibleChildByID(accDoc, "p1");
+  let p2 = findAccessibleChildByID(accDoc, "p2");
+  let imgmap = findAccessibleChildByID(accDoc, "imgmap");
+  if (!imgmap.childCount) {
+    // An image map may not be available even after the doc and image load
+    // is complete. We don't recieve any DOM events for this change either,
+    // so we need to wait for a REORDER.
+    await waitForEvent(EVENT_REORDER, "imgmap");
+  }
+  let area = imgmap.firstChild;
+
+  await testContentBounds(browser, p1);
+  await testContentBounds(browser, p2);
+  await testContentBounds(browser, area);
+
+  await ContentTask.spawn(browser, {}, () => {
+    zoomDocument(document, 2.0);
+  });
+
+  await testContentBounds(browser, p1);
+  await testContentBounds(browser, p2);
+  await testContentBounds(browser, area);
+}
+
+/**
+ * Test accessible boundaries when page is zoomed
+ */
+addAccessibleTask(`
+<p id="p1">para 1</p><p id="p2">para 2</p>
+<map name="atoz_map" id="map">
+  <area id="area1" href="http://mozilla.org"
+        coords=17,0,30,14" alt="mozilla.org" shape="rect">
+</map>
+<img id="imgmap" width="447" height="15"
+     usemap="#atoz_map"
+     src="http://example.com/a11y/accessible/tests/mochitest/letters.gif">`,
+  runTests
+);
new file mode 100644
--- /dev/null
+++ b/accessible/tests/browser/bounds/browser_test_zoom_text.js
@@ -0,0 +1,41 @@
+/* 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/layout.js */
+
+async function runTests(browser, accDoc) {
+  function testTextNode(id) {
+    let hyperTextNode = findAccessibleChildByID(accDoc, id);
+    let textNode = hyperTextNode.firstChild;
+
+    let [x, y, width, height] = getBounds(textNode);
+    testTextBounds(hyperTextNode, 0, -1, [x, y, width, height],
+                   COORDTYPE_SCREEN_RELATIVE);
+  }
+
+  loadFrameScripts(browser, { name: 'layout.js', dir: MOCHITESTS_DIR });
+
+  testTextNode("p1");
+  testTextNode("p2");
+
+  await ContentTask.spawn(browser, {}, () => {
+    zoomDocument(document, 2.0);
+  });
+
+  testTextNode("p1");
+
+  await ContentTask.spawn(browser, {}, () => {
+    zoomDocument(document, 1.0);
+  });
+}
+
+/**
+ * Test the text range boundary when page is zoomed
+ */
+addAccessibleTask(`
+  <p id='p1' style='font-family: monospace;'>Tilimilitryamdiya</p>
+  <p id='p2'>ل</p>`, runTests
+);
new file mode 100644
--- /dev/null
+++ b/accessible/tests/browser/bounds/head.js
@@ -0,0 +1,16 @@
+/* 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 events.js.
+loadScripts({ name: 'common.js', dir: MOCHITESTS_DIR },
+            { name: 'layout.js', dir: MOCHITESTS_DIR }, 'events.js');
--- a/accessible/tests/browser/e10s/browser_caching_description.js
+++ b/accessible/tests/browser/e10s/browser_caching_description.js
@@ -21,117 +21,117 @@ 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: [{ eventType: EVENT_DESCRIPTION_CHANGE, id: 'image' }],
+  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: [{ eventType: EVENT_REORDER, id: 'body' }],
+  waitFor: [[EVENT_REORDER, 'body']],
   expected: ''
 }, {
   desc: 'Description from @aria-describedby attribute when @alt and ' +
         '@aria-describedby are not the same',
   attrs: [{
     attr: 'aria-describedby',
     value: 'description2'
   }],
-  waitFor: [{ eventType: EVENT_DESCRIPTION_CHANGE, id: 'image' }],
+  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: [{ eventType: EVENT_REORDER, id: 'body' }],
+  waitFor: [[EVENT_REORDER, 'body']],
   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: [{ eventType: EVENT_NAME_CHANGE, id: 'image' }],
+  waitFor: [[EVENT_NAME_CHANGE, 'image']],
   expected: ''
 }, {
   desc: 'No description with only @title attribute which is used as the name',
   attrs: [{
     attr: 'aria-describedby'
   }],
-  waitFor: [{ eventType: EVENT_DESCRIPTION_CHANGE, id: 'image' }],
+  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: [{ eventType: EVENT_REORDER, id: 'body' }],
+  waitFor: [[EVENT_REORDER, 'body']],
   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: [{ eventType: EVENT_NAME_CHANGE, id: 'image' }],
+  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: [{ eventType: EVENT_DESCRIPTION_CHANGE, id: 'image' }],
+  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: [{ eventType: EVENT_DESCRIPTION_CHANGE, id: 'image' }],
+  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: [{ eventType: EVENT_NAME_CHANGE, id: 'image' }],
+  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: [{ eventType: EVENT_DESCRIPTION_CHANGE, id: 'image' }],
+  waitFor: [[EVENT_DESCRIPTION_CHANGE, 'image']],
   expected: 'another description'
 }];
 
 /**
  * Test caching of accessible object description
  */
 addAccessibleTask(`
   <p id="description">aria description</p>
@@ -139,17 +139,17 @@ addAccessibleTask(`
   <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 = waitForMultipleEvents(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
--- a/accessible/tests/browser/e10s/browser_caching_name.js
+++ b/accessible/tests/browser/e10s/browser_caching_name.js
@@ -234,17 +234,18 @@ const markupTests = [{
           <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',
+  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>
--- a/accessible/tests/browser/e10s/browser_events_textchange.js
+++ b/accessible/tests/browser/e10s/browser_events_textchange.js
@@ -11,19 +11,19 @@ function checkTextChangeEvent(event, 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)}`);
 }
 
 async function changeText(browser, id, value, events) {
-  let onEvents = waitForMultipleEvents(events.map(({ isInserted }) => {
+  let onEvents = waitForOrderedEvents(events.map(({ isInserted }) => {
     let eventType = isInserted ? EVENT_TEXT_INSERTED : EVENT_TEXT_REMOVED;
-    return { id, eventType };
+    return [ eventType, id ];
   }));
   // Change text in the subtree.
   await ContentTask.spawn(browser, [id, value], ([contentId, contentValue]) => {
     content.document.getElementById(contentId).firstChild.textContent =
       contentValue;
   });
   let resolvedEvents = await onEvents;
 
--- a/accessible/tests/browser/e10s/browser_treeupdate_list.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_list.js
@@ -5,17 +5,17 @@
 '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 await onReorder;
+  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;
--- a/accessible/tests/browser/e10s/doc_treeupdate_whitespace.html
+++ b/accessible/tests/browser/e10s/doc_treeupdate_whitespace.html
@@ -1,10 +1,10 @@
 <html xmlns="http://www.w3.org/1999/xhtml">
   <head>
     <meta charset="utf-8"/>
-    <title>Whitespace text accessible creation/desctruction</title>
+    <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>
--- a/accessible/tests/browser/events.js
+++ b/accessible/tests/browser/events.js
@@ -8,31 +8,33 @@
 // globals from there.
 /* import-globals-from shared-head.js */
 /* import-globals-from ../mochitest/common.js */
 
 /* exported EVENT_REORDER, EVENT_SHOW, EVENT_TEXT_INSERTED, EVENT_TEXT_REMOVED,
             EVENT_DOCUMENT_LOAD_COMPLETE, EVENT_HIDE, EVENT_TEXT_CARET_MOVED,
             EVENT_DESCRIPTION_CHANGE, EVENT_NAME_CHANGE, EVENT_STATE_CHANGE,
             EVENT_VALUE_CHANGE, EVENT_TEXT_VALUE_CHANGE, EVENT_FOCUS,
-            waitForEvent, waitForMultipleEvents */
+            EVENT_DOCUMENT_RELOAD,
+            waitForEvent, waitForEvents, waitForOrderedEvents */
 
 const EVENT_DOCUMENT_LOAD_COMPLETE = nsIAccessibleEvent.EVENT_DOCUMENT_LOAD_COMPLETE;
 const EVENT_HIDE = nsIAccessibleEvent.EVENT_HIDE;
 const EVENT_REORDER = nsIAccessibleEvent.EVENT_REORDER;
 const EVENT_SHOW = nsIAccessibleEvent.EVENT_SHOW;
 const EVENT_STATE_CHANGE = nsIAccessibleEvent.EVENT_STATE_CHANGE;
 const EVENT_TEXT_CARET_MOVED = nsIAccessibleEvent.EVENT_TEXT_CARET_MOVED;
 const EVENT_TEXT_INSERTED = nsIAccessibleEvent.EVENT_TEXT_INSERTED;
 const EVENT_TEXT_REMOVED = nsIAccessibleEvent.EVENT_TEXT_REMOVED;
 const EVENT_DESCRIPTION_CHANGE = nsIAccessibleEvent.EVENT_DESCRIPTION_CHANGE;
 const EVENT_NAME_CHANGE = nsIAccessibleEvent.EVENT_NAME_CHANGE;
 const EVENT_VALUE_CHANGE = nsIAccessibleEvent.EVENT_VALUE_CHANGE;
 const EVENT_TEXT_VALUE_CHANGE = nsIAccessibleEvent.EVENT_TEXT_VALUE_CHANGE;
 const EVENT_FOCUS = nsIAccessibleEvent.EVENT_FOCUS;
+const EVENT_DOCUMENT_RELOAD = nsIAccessibleEvent.EVENT_DOCUMENT_RELOAD;
 
 /**
  * Describe an event in string format.
  * @param  {nsIAccessibleEvent}  event  event to strigify
  */
 function eventToString(event) {
   let type = eventTypeToString(event.eventType);
   let info = `Event type: ${type}`;
@@ -45,28 +47,55 @@ function eventToString(event) {
     let tcType = event.isInserted ? 'inserted' : 'removed';
     info += `, start: ${event.start}, length: ${event.length}, ${tcType} text: ${event.modifiedText}`;
   }
 
   info += `. Target: ${prettyName(event.accessible)}`;
   return info;
 }
 
+function matchEvent(event, matchCriteria) {
+  let acc = event.accessible;
+  switch (typeof matchCriteria) {
+    case "string":
+      let id = getAccessibleDOMNodeID(acc);
+      if (id === matchCriteria) {
+        Logger.log(`Event matches DOMNode id: ${id}`);
+        return true;
+      }
+      break;
+    case "function":
+      if (matchCriteria(event)) {
+        Logger.log(`Lambda function matches event: ${eventToString(event)}`);
+        return true;
+      }
+      break;
+    default:
+      if (acc === matchCriteria) {
+        Logger.log(`Event matches accessible: ${prettyName(acc)}`);
+        return true;
+      }
+  }
+
+  return false;
+}
+
 /**
  * A helper function that returns a promise that resolves when an accessible
  * event of the given type with the given target (defined by its id or
  * accessible) is observed.
- * @param  {String|nsIAccessible}  expectedIdOrAcc  expected content element id
- *                                                  for the event
+ * @param  {String|nsIAccessible|Function}  matchCriteria  expected content
+ *                                                         element id
+ *                                                         for the event
  * @param  {Number}                eventType        expected accessible event
  *                                                  type
  * @return {Promise}                                promise that resolves to an
  *                                                  event
  */
-function waitForEvent(eventType, expectedIdOrAcc) {
+function waitForEvent(eventType, matchCriteria) {
   return new Promise(resolve => {
     let eventObserver = {
       observe(subject, topic, data) {
         if (topic !== 'accessible-event') {
           return;
         }
 
         let event = subject.QueryInterface(nsIAccessibleEvent);
@@ -76,54 +105,84 @@ function waitForEvent(eventType, expecte
           Logger.log(eventToString(event));
         }
 
         // If event type does not match expected type, skip the event.
         if (event.eventType !== eventType) {
           return;
         }
 
-        let acc = event.accessible;
-        let id = getAccessibleDOMNodeID(acc);
-        let isID = typeof expectedIdOrAcc === 'string';
-        let actualIdOrAcc = isID ? id : acc;
-        // If event's accessible does not match expected DOMNode id or
-        // accessible, skip the event.
-        if (actualIdOrAcc === expectedIdOrAcc) {
-          if (isID) {
-            Logger.log(`Correct event DOMNode id: ${id}`);
-          } else {
-            Logger.log(`Correct event accessible: ${prettyName(acc)}`);
-          }
+        if (matchEvent(event, matchCriteria)) {
           Logger.log(`Correct event type: ${eventTypeToString(eventType)}`);
           ok(event.accessibleDocument instanceof nsIAccessibleDocument,
             'Accessible document present.');
 
           Services.obs.removeObserver(this, 'accessible-event');
           resolve(event);
         }
       }
     };
     Services.obs.addObserver(eventObserver, 'accessible-event');
   });
 }
 
+class UnexpectedEvents {
+  constructor(unexpected) {
+    if (unexpected.length) {
+      this.unexpected = unexpected;
+      Services.obs.addObserver(this, 'accessible-event');
+    }
+  }
+
+  observe(subject, topic, data) {
+    if (topic !== 'accessible-event') {
+      return;
+    }
+
+    let event = subject.QueryInterface(nsIAccessibleEvent);
+
+    let unexpectedEvent = this.unexpected.find(([etype, criteria]) =>
+      etype === event.eventType && matchEvent(event, criteria));
+
+    if (unexpectedEvent) {
+      ok(false, `Got unexpected event: ${eventToString(event)}`);
+    }
+  }
+
+  stop() {
+    if (this.unexpected) {
+      Services.obs.removeObserver(this, 'accessible-event');
+    }
+  }
+}
+
 /**
  * A helper function that waits for a sequence of accessible events in
  * specified order.
  * @param {Array} events        a list of events to wait (same format as
  *                              waitForEvent arguments)
  */
-function waitForMultipleEvents(events) {
+function waitForEvents(events, ordered = false) {
+  let expected = events.expected || events;
+  let unexpected = events.unexpected || [];
   // Next expected event index.
   let currentIdx = 0;
 
-  return Promise.all(events.map(({ eventType, id }, idx) =>
-    // In addition to waiting for an event, attach an order checker for the
-    // event.
-    waitForEvent(eventType, id).then(resolvedEvent => {
-      // Verify that event happens in order and increment expected index.
-      is(idx, currentIdx++,
-        `Unexpected event order: ${eventToString(resolvedEvent)}`);
-      return resolvedEvent;
-    })
-  ));
+  let unexpectedListener = new UnexpectedEvents(unexpected);
+
+  return Promise.all(expected.map((evt, idx) => {
+    let promise = evt instanceof Array ? waitForEvent(...evt) : evt;
+    return promise.then(result => {
+      if (ordered) {
+        is(idx, currentIdx++,
+          `Unexpected event order: ${result}`);
+      }
+      return result;
+    });
+  })).then(results => {
+    unexpectedListener.stop();
+    return results;
+  });
 }
+
+function waitForOrderedEvents(events) {
+  return waitForEvents(events, true);
+}
new file mode 100644
--- /dev/null
+++ b/accessible/tests/browser/events/browser.ini
@@ -0,0 +1,12 @@
+[DEFAULT]
+skip-if = e10s && os == 'win' && release_or_beta
+support-files =
+  head.js
+  !/accessible/tests/browser/events.js
+  !/accessible/tests/browser/shared-head.js
+  !/accessible/tests/mochitest/*.js
+
+[browser_test_docload.js]
+skip-if = e10s
+[browser_test_focus_browserui.js]
+[browser_test_focus_dialog.js]
new file mode 100644
--- /dev/null
+++ b/accessible/tests/browser/events/browser_test_docload.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 busyChecker(isBusy) {
+  return function (event) {
+    let scEvent;
+    try {
+      scEvent = event.QueryInterface(nsIAccessibleStateChangeEvent);
+    } catch (e) {
+      return false;
+    }
+
+    return scEvent.state == STATE_BUSY && scEvent.isEnabled == isBusy;
+  };
+}
+
+function inIframeChecker(iframeId) {
+  return function (event) {
+    return getAccessibleDOMNodeID(event.accessibleDocument.parent) == iframeId;
+  };
+}
+
+function urlChecker(url) {
+  return function (event) {
+    info(`${event.accessibleDocument.URL} == ${url}`);
+    return event.accessibleDocument.URL == url;
+  };
+}
+
+async function runTests(browser, accDoc) {
+  let onLoadEvents = waitForEvents([
+    [EVENT_REORDER, getAccessible(browser)],
+    [EVENT_DOCUMENT_LOAD_COMPLETE, 'body2'],
+    [EVENT_STATE_CHANGE, busyChecker(false)]
+  ], [ // unexpected
+    [EVENT_DOCUMENT_LOAD_COMPLETE, inIframeChecker("iframe1")],
+    [EVENT_STATE_CHANGE, inIframeChecker("iframe1")]
+  ]);
+
+  browser.loadURI(`data:text/html;charset=utf-8,
+    <html><body id="body2">
+      <iframe id="iframe1" src="http://example.com"></iframe>
+    </body></html>`);
+
+  await onLoadEvents;
+
+  onLoadEvents = waitForEvents([
+      [EVENT_DOCUMENT_LOAD_COMPLETE, urlChecker("about:")],
+      [EVENT_STATE_CHANGE, busyChecker(false)],
+      [EVENT_REORDER, getAccessible(browser)]
+  ]);
+
+  browser.loadURI("about:");
+
+  await onLoadEvents;
+
+  onLoadEvents = waitForEvents([
+    [EVENT_DOCUMENT_RELOAD, evt => evt.isFromUserInput],
+    [EVENT_REORDER, getAccessible(browser)],
+    [EVENT_STATE_CHANGE, busyChecker(false)]
+  ]);
+
+  EventUtils.synthesizeKey("VK_F5", {}, browser.ownerGlobal);
+
+  await onLoadEvents;
+
+  onLoadEvents = waitForEvents([
+    [EVENT_DOCUMENT_LOAD_COMPLETE, urlChecker("about:mozilla")],
+    [EVENT_STATE_CHANGE, busyChecker(false)],
+    [EVENT_REORDER, getAccessible(browser)]
+  ]);
+
+  browser.loadURI("about:mozilla");
+
+  await onLoadEvents;
+
+  onLoadEvents = waitForEvents([
+    [EVENT_DOCUMENT_RELOAD, evt => !evt.isFromUserInput],
+    [EVENT_REORDER, getAccessible(browser)],
+    [EVENT_STATE_CHANGE, busyChecker(false)]
+  ]);
+
+  browser.reload();
+
+  await onLoadEvents;
+
+  onLoadEvents = waitForEvents([
+    [EVENT_DOCUMENT_LOAD_COMPLETE, urlChecker("http://www.wronguri.wronguri/")],
+    [EVENT_STATE_CHANGE, busyChecker(false)],
+    [EVENT_REORDER, getAccessible(browser)]
+  ]);
+
+  browser.loadURI("http://www.wronguri.wronguri/");
+
+  await onLoadEvents;
+
+  onLoadEvents = waitForEvents([
+    [EVENT_DOCUMENT_LOAD_COMPLETE, urlChecker("https://nocert.example.com/")],
+    [EVENT_STATE_CHANGE, busyChecker(false)],
+    [EVENT_REORDER, getAccessible(browser)]
+  ]);
+
+  browser.loadURI("https://nocert.example.com:443/");
+
+  await onLoadEvents;
+}
+
+/**
+ * Test caching of accessible object states
+ */
+addAccessibleTask("", runTests);
new file mode 100644
--- /dev/null
+++ b/accessible/tests/browser/events/browser_test_focus_browserui.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";
+
+/* import-globals-from ../../mochitest/states.js */
+/* import-globals-from ../../mochitest/role.js */
+loadScripts({ name: 'states.js', dir: MOCHITESTS_DIR },
+            { name: 'role.js', dir: MOCHITESTS_DIR });
+
+async function runTests(browser, accDoc) {
+  let onFocus = waitForEvent(EVENT_FOCUS, "input");
+  EventUtils.synthesizeKey("VK_TAB", {}, browser.ownerGlobal);
+  let evt = await onFocus;
+  testStates(evt.accessible, STATE_FOCUSED);
+
+  onFocus = waitForEvent(EVENT_FOCUS, "buttonInputDoc");
+  browser.loadURI(snippetToURL(
+    `<input id="input" type="button" value="button">`, { id: "buttonInputDoc" }));
+  evt = await onFocus;
+  testStates(evt.accessible, STATE_FOCUSED);
+
+  onFocus = waitForEvent(EVENT_FOCUS, "input");
+  browser.goBack();
+  evt = await onFocus;
+  testStates(evt.accessible, STATE_FOCUSED);
+
+  let inputField = browser.ownerDocument.getElementById("urlbar").inputField;
+  onFocus = waitForEvent(EVENT_FOCUS, getAccessible(inputField));
+  EventUtils.synthesizeKey("t", { accelKey: true }, browser.ownerGlobal);
+  evt = await onFocus;
+  testStates(evt.accessible, STATE_FOCUSED);
+
+  onFocus = waitForEvent(EVENT_FOCUS, "input");
+  EventUtils.synthesizeKey("w", { accelKey: true }, browser.ownerGlobal);
+  evt = await onFocus;
+  testStates(evt.accessible, STATE_FOCUSED);
+}
+
+/**
+ * Accessibility loading document events test.
+ */
+addAccessibleTask(`<input id="input">`, runTests);
new file mode 100644
--- /dev/null
+++ b/accessible/tests/browser/events/browser_test_focus_dialog.js
@@ -0,0 +1,67 @@
+/* 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/states.js */
+/* import-globals-from ../../mochitest/role.js */
+loadScripts({ name: 'states.js', dir: MOCHITESTS_DIR },
+            { name: 'role.js', dir: MOCHITESTS_DIR });
+
+async function runTests(browser, accDoc) {
+  let onFocus = waitForEvent(EVENT_FOCUS, "button");
+  await ContentTask.spawn(browser, {}, () => {
+    content.document.getElementById("button").focus();
+  });
+  let button = (await onFocus).accessible;
+  testStates(button, STATE_FOCUSED);
+
+  // Bug 1377942 - The target of the focus event changes under different
+  // circumstances.
+  // In e10s the focus event is the new window, in non-e10s it's the doc.
+  onFocus = waitForEvent(EVENT_FOCUS, () => true);
+  let newWin = await BrowserTestUtils.openNewBrowserWindow();
+  // button should be blurred
+  await onFocus;
+  testStates(button, 0, 0, STATE_FOCUSED);
+
+  onFocus = waitForEvent(EVENT_FOCUS, "button");
+  await BrowserTestUtils.closeWindow(newWin);
+  testStates((await onFocus).accessible, STATE_FOCUSED);
+
+  onFocus = waitForEvent(EVENT_FOCUS, "body2");
+  await ContentTask.spawn(browser, {}, () => {
+    content.document.getElementById("editabledoc").contentWindow.document.body.focus();
+  });
+  testStates((await onFocus).accessible, STATE_FOCUSED);
+
+  onFocus = waitForEvent(EVENT_FOCUS, "body2");
+  newWin = await BrowserTestUtils.openNewBrowserWindow();
+  await BrowserTestUtils.closeWindow(newWin);
+  testStates((await onFocus).accessible, STATE_FOCUSED);
+
+  let onShow = waitForEvent(EVENT_SHOW, "alertdialog");
+  onFocus = waitForEvent(EVENT_FOCUS, "alertdialog");
+  await ContentTask.spawn(browser, {}, () => {
+    let alertDialog = content.document.getElementById("alertdialog");
+    alertDialog.style.display = "block";
+    alertDialog.focus();
+  });
+  await onShow;
+  testStates((await onFocus).accessible, STATE_FOCUSED);
+}
+
+/**
+ * Accessible dialog focus testing
+ */
+addAccessibleTask(`
+  <button id="button">button</button>
+  <iframe id="editabledoc"
+          src="${snippetToURL("", { id: "body2", contentEditable: "true"})}">
+  </iframe>
+  <div id="alertdialog" style="display: none" tabindex="-1" role="alertdialog" aria-labelledby="title2" aria-describedby="desc2">
+    <div id="title2">Blah blah</div>
+    <div id="desc2">Woof woof woof.</div>
+    <button>Close</button>
+  </div>`, runTests);
new file mode 100644
--- /dev/null
+++ b/accessible/tests/browser/events/head.js
@@ -0,0 +1,15 @@
+/* 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 events.js.
+loadScripts({ name: 'common.js', dir: MOCHITESTS_DIR }, 'events.js', 'layout.js');
new file mode 100644
--- /dev/null
+++ b/accessible/tests/browser/scroll/browser.ini
@@ -0,0 +1,10 @@
+[DEFAULT]
+skip-if = e10s && os == 'win' && release_or_beta
+support-files =
+  head.js
+  !/accessible/tests/browser/events.js
+  !/accessible/tests/browser/shared-head.js
+  !/accessible/tests/mochitest/*.js
+
+[browser_test_zoom_text.js]
+skip-if = e10s && os == 'win' # bug 1372296
new file mode 100644
--- /dev/null
+++ b/accessible/tests/browser/scroll/browser_test_zoom_text.js
@@ -0,0 +1,123 @@
+/* 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/layout.js */
+loadScripts({ name: 'layout.js', dir: MOCHITESTS_DIR });
+
+async function runTests(browser, accDoc) {
+  loadFrameScripts(browser, { name: 'layout.js', dir: MOCHITESTS_DIR });
+
+  let paragraph = findAccessibleChildByID(accDoc, "paragraph", [nsIAccessibleText]);
+  let offset = 64; // beginning of 4th stanza
+
+  let [x /*,y*/] = getPos(paragraph);
+  let [docX, docY] = getPos(accDoc);
+
+  paragraph.scrollSubstringToPoint(offset, offset,
+                                   COORDTYPE_SCREEN_RELATIVE, docX, docY);
+  testTextPos(paragraph, offset, [x, docY], COORDTYPE_SCREEN_RELATIVE);
+
+  await ContentTask.spawn(browser, {}, () => {
+    zoomDocument(document, 2.0);
+  });
+
+  paragraph = findAccessibleChildByID(accDoc, "paragraph2", [nsIAccessibleText]);
+  offset = 52; // // beginning of 4th stanza
+  [x /*,y*/] = getPos(paragraph);
+  paragraph.scrollSubstringToPoint(offset, offset,
+                                   COORDTYPE_SCREEN_RELATIVE, docX, docY);
+  testTextPos(paragraph, offset, [x, docY], COORDTYPE_SCREEN_RELATIVE);
+}
+
+/**
+ * Test caching of accessible object states
+ */
+addAccessibleTask(`
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br><hr>
+  <p id='paragraph'>
+    Пошел котик на торжок<br>
+    Купил котик пирожок<br>
+    Пошел котик на улочку<br>
+    Купил котик булочку<br>
+  </p>
+  <hr><br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br><hr>
+  <p id='paragraph2'>
+    Самому ли съесть<br>
+    Либо Сашеньке снесть<br>
+    Я и сам укушу<br>
+    Я и Сашеньке снесу<br>
+  </p>
+  <hr><br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>
+  <br><br><br><br><br><br><br><br><br><br>`,
+  runTests
+);
new file mode 100644
--- /dev/null
+++ b/accessible/tests/browser/scroll/head.js
@@ -0,0 +1,15 @@
+/* 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 events.js.
+loadScripts({ name: 'common.js', dir: MOCHITESTS_DIR }, 'events.js');
--- a/accessible/tests/browser/shared-head.js
+++ b/accessible/tests/browser/shared-head.js
@@ -3,19 +3,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 'use strict';
 
 /* import-globals-from ../mochitest/common.js */
 /* import-globals-from events.js */
 
 /* exported Logger, MOCHITESTS_DIR, invokeSetAttribute, invokeFocus,
-            invokeSetStyle, getAccessibleDOMNodeID,
+            invokeSetStyle, getAccessibleDOMNodeID, getAccessibleTagName,
             addAccessibleTask, findAccessibleChildByID, isDefunct,
-            CURRENT_CONTENT_DIR, loadScripts, loadFrameScripts, Cc, Cu */
+            CURRENT_CONTENT_DIR, loadScripts, loadFrameScripts, snippetToURL,
+            Cc, Cu, arrayFromChildren */
 
 const { interfaces: Ci, utils: Cu, classes: Cc } = Components;
 
 /**
  * Current browser test directory path used to load subscripts.
  */
 const CURRENT_DIR =
   'chrome://mochitests/content/browser/accessible/tests/browser/';
@@ -26,16 +27,18 @@ const CURRENT_DIR =
 const MOCHITESTS_DIR =
   'chrome://mochitests/content/a11y/accessible/tests/mochitest/';
 /**
  * A base URL for test files used in content.
  */
 const CURRENT_CONTENT_DIR =
   'http://example.com/browser/accessible/tests/browser/';
 
+const LOADED_FRAMESCRIPTS = new Map();
+
 /**
  * Used to dump debug information.
  */
 let Logger = {
   /**
    * Set up this variable to dump log messages into console.
    */
   dumpToConsole: false,
@@ -183,44 +186,71 @@ function loadFrameScripts(browser, ...sc
       } else {
         // Otherwise it is a serealized script.
         frameScript = `data:,${script}`;
       }
     } else {
       // Script is a object that has { dir, name } format.
       frameScript = `${script.dir}${script.name}`;
     }
+
+    let loadedScriptSet = LOADED_FRAMESCRIPTS.get(frameScript);
+    if (!loadedScriptSet) {
+      loadedScriptSet = new WeakSet();
+      LOADED_FRAMESCRIPTS.set(frameScript, loadedScriptSet);
+    } else if (loadedScriptSet.has(browser)) {
+      continue;
+    }
+
     mm.loadFrameScript(frameScript, false, true);
+    loadedScriptSet.add(browser);
   }
 }
 
 /**
+ * Takes an HTML snippet and returns an encoded URI for a full document
+ * with the snippet.
+ * @param {String} snippet   a markup snippet.
+ * @param {Object} bodyAttrs extra attributes to use in the body tag. Default is
+ *                           { id: "body "}.
+ * @return {String} a base64 encoded data url of the document container the
+ *                  snippet.
+ **/
+function snippetToURL(snippet, bodyAttrs={}) {
+  let attrs = Object.assign({}, { id: "body" }, bodyAttrs);
+  let attrsString = Object.entries(attrs).map(
+    ([attr, value]) => `${attr}=${JSON.stringify(value)}`).join(" ");
+  let encodedDoc = btoa(
+    `<html>
+      <head>
+        <meta charset="utf-8"/>
+        <title>Accessibility Test</title>
+      </head>
+      <body ${attrsString}>${snippet}</body>
+    </html>`);
+
+  return `data:text/html;charset=utf-8;base64,${encodedDoc}`;
+}
+
+/**
  * A wrapper around browser test add_task that triggers an accessible test task
  * as a new browser test task with given document, data URL or markup snippet.
  * @param  {String}                 doc  URL (relative to current directory) or
  *                                       data URL or markup snippet that is used
  *                                       to test content with
  * @param  {Function|AsyncFunction} task a generator or a function with tests to
  *                                       run
  */
 function addAccessibleTask(doc, task) {
   add_task(async function() {
     let url;
     if (doc.includes('doc_')) {
       url = `${CURRENT_CONTENT_DIR}e10s/${doc}`;
     } else {
-      // Assume it's a markup snippet.
-      url = `data:text/html,
-        <html>
-          <head>
-            <meta charset="utf-8"/>
-            <title>Accessibility Test</title>
-          </head>
-          <body id="body">${doc}</body>
-        </html>`;
+      url = snippetToURL(doc);
     }
 
     registerCleanupFunction(() => {
       let observers = Services.obs.enumerateObservers('accessible-event');
       while (observers.hasMoreElements()) {
         Services.obs.removeObserver(
           observers.getNext().QueryInterface(Ci.nsIObserver),
           'accessible-event');
@@ -275,25 +305,61 @@ function isDefunct(accessible) {
     if (defunct) {
       Logger.log(`Defunct accessible: ${prettyName(accessible)}`);
     }
   }
   return defunct;
 }
 
 /**
+ * Get the DOM tag name for a given accessible.
+ * @param  {nsIAccessible}  accessible accessible
+ * @return {String?}                   tag name of associated DOM node, or null.
+ */
+function getAccessibleTagName(acc) {
+  try {
+    return acc.attributes.getStringProperty("tag");
+  } catch (e) {
+    return null;
+  }
+}
+
+/**
  * Traverses the accessible tree starting from a given accessible as a root and
  * looks for an accessible that matches based on its DOMNode id.
  * @param  {nsIAccessible}  accessible root accessible
  * @param  {String}         id         id to look up accessible for
+ * @param  {Array?}         interfaces the interface or an array interfaces
+ *                                     to query it/them from obtained accessible
  * @return {nsIAccessible?}            found accessible if any
  */
-function findAccessibleChildByID(accessible, id) {
+function findAccessibleChildByID(accessible, id, interfaces) {
   if (getAccessibleDOMNodeID(accessible) === id) {
-    return accessible;
+    return queryInterfaces(accessible, interfaces);
   }
   for (let i = 0; i < accessible.children.length; ++i) {
     let found = findAccessibleChildByID(accessible.getChildAt(i), id);
     if (found) {
-      return found;
+      return queryInterfaces(found, interfaces);
     }
   }
 }
+
+function queryInterfaces(accessible, interfaces) {
+  if (!interfaces) {
+    return accessible;
+  }
+
+  for (let iface of interfaces.filter(i => !(accessible instanceof i))) {
+    try {
+      accessible.QueryInterface(iface);
+    } catch (e) {
+      ok(false, "Can't query " + iface);
+    }
+  }
+
+  return accessible;
+}
+
+function arrayFromChildren(accessible) {
+  return Array.from({ length: accessible.childCount }, (c, i) =>
+    accessible.getChildAt(i));
+}
new file mode 100644
--- /dev/null
+++ b/accessible/tests/browser/tree/browser.ini
@@ -0,0 +1,10 @@
+[DEFAULT]
+skip-if = e10s && os == 'win' && release_or_beta
+support-files =
+  head.js
+  !/accessible/tests/browser/events.js
+  !/accessible/tests/browser/shared-head.js
+  !/accessible/tests/mochitest/*.js
+
+[browser_test_aria_owns.js]
+[browser_test_aria_owns_select.js]
new file mode 100644
--- /dev/null
+++ b/accessible/tests/browser/tree/browser_test_aria_owns.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";
+
+function testChildrenIds(acc, expectedIds) {
+  let ids = arrayFromChildren(acc).map(child => getAccessibleDOMNodeID(child));
+  Assert.deepEqual(ids, expectedIds,
+    `Children for ${getAccessibleDOMNodeID(acc)} are wrong.`);
+}
+
+async function runTests(browser, accDoc) {
+  let one = findAccessibleChildByID(accDoc, "one");
+  let two = findAccessibleChildByID(accDoc, "two");
+  let three = findAccessibleChildByID(accDoc, "three");
+  let four = findAccessibleChildByID(accDoc, "four");
+
+  testChildrenIds(one, ["a"]);
+  testChildrenIds(two, ["b", "c", "d"]);
+  testChildrenIds(three, []);
+
+  let onReorders = waitForEvents({
+    expected: [
+      [EVENT_REORDER, "two"]], // children will be reordered via aria-owns
+    unexpected: [
+      [EVENT_REORDER, "one"],  // child will remain in place
+      [EVENT_REORDER, "three"], // none of its children will be reclaimed
+      [EVENT_REORDER, "four"]] // child will remain in place
+  });
+
+  await ContentTask.spawn(browser, null, async function() {
+    // aria-own ordinal child in place, should be a no-op.
+    document.getElementById("one").setAttribute("aria-owns", "a");
+    // remove aria-owned child that is already ordinal, should be no-op.
+    document.getElementById("four").removeAttribute("aria-owns");
+    // shuffle aria-owns with markup child.
+    document.getElementById("two").setAttribute("aria-owns", "d c");
+  });
+
+  await onReorders;
+
+  testChildrenIds(one, ["a"]);
+  testChildrenIds(two, ["b", "d", "c"]);
+  testChildrenIds(three, []);
+  testChildrenIds(four, ["e"]);
+
+  onReorders = waitForEvent(EVENT_REORDER, "one");
+
+  await ContentTask.spawn(browser, null, async function() {
+    let aa = document.createElement("li");
+    aa.id = "aa";
+    document.getElementById("one").appendChild(aa);
+  });
+
+  await onReorders;
+
+  testChildrenIds(one, ["aa", "a"]);
+
+  onReorders = waitForEvents([
+      [EVENT_REORDER, "two"],    // "b" will go to "three"
+      [EVENT_REORDER, "three"], // some children will be reclaimed and acquired
+      [EVENT_REORDER, "one"]]); // removing aria-owns will reorder native children
+
+  await ContentTask.spawn(browser, null, async function() {
+    // removing aria-owns should reorder the children
+    document.getElementById("one").removeAttribute("aria-owns");
+    // child order will be overridden by aria-owns
+    document.getElementById("three").setAttribute("aria-owns", "b d");
+  });
+
+  await onReorders;
+
+  testChildrenIds(one, ["a", "aa"]);
+  testChildrenIds(two, ["c"]);
+  testChildrenIds(three, ["b", "d"]);
+}
+
+/**
+ * Test caching of accessible object states
+ */
+addAccessibleTask(`
+    <ul id="one">
+      <li id="a">Test</li>
+    </ul>
+    <ul id="two" aria-owns="d">
+      <li id="b">Test 2</li>
+      <li id="c">Test 3</li>
+    </ul>
+    <ul id="three">
+      <li id="d">Test 4</li>
+    </ul>
+    <ul id="four" aria-owns="e">
+      <li id="e">Test 5</li>
+    </ul>
+    `, runTests);
new file mode 100644
--- /dev/null
+++ b/accessible/tests/browser/tree/browser_test_aria_owns_select.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";
+
+function testChildrenIds(acc, expectedIds) {
+  let ids = arrayFromChildren(acc).map(child => getAccessibleDOMNodeID(child));
+  Assert.deepEqual(ids, expectedIds,
+    `Children for ${getAccessibleDOMNodeID(acc)} are wrong.`);
+}
+
+async function runTests(browser, accDoc) {
+  let div = findAccessibleChildByID(accDoc, "div");
+  let select = findAccessibleChildByID(accDoc, "select");
+
+  testChildrenIds(div, ["b"]);
+  testChildrenIds(select.firstChild, ["a"]);
+
+  let onReorders = waitForEvents([
+    [EVENT_REORDER, "div"],
+    [EVENT_REORDER,
+      evt => getAccessibleDOMNodeID(evt.accessible.parent) == "select"]
+  ]);
+
+  await ContentTask.spawn(browser, null, async function() {
+    document.getElementById("div").removeAttribute("aria-owns");
+  });
+
+  await onReorders;
+
+  testChildrenIds(div, []);
+  testChildrenIds(select.firstChild, ["a", "b"]);
+}
+
+/**
+ * Test caching of accessible object states
+ */
+addAccessibleTask(`
+  <div id="div" role="group" aria-owns="b"></div>
+  <select id="select">
+    <option id="a"></option>
+    <option id="b"></option>
+  </select>
+    `, runTests);
new file mode 100644
--- /dev/null
+++ b/accessible/tests/browser/tree/head.js
@@ -0,0 +1,15 @@
+/* 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 events.js.
+loadScripts({ name: 'common.js', dir: MOCHITESTS_DIR }, 'events.js', 'layout.js');
--- a/accessible/tests/crashtests/448064.xhtml
+++ b/accessible/tests/crashtests/448064.xhtml
@@ -14,41 +14,41 @@
 </div>
 </div>
 
 <input id="mw_a"/>
 
 
 <script>
 function dumpAccessibleNode(aNode, level) {
-	var msg = "";
+  var msg = "";
 
-	try {
-		msg += "name=\"" + aNode.name + "\" ";
-	} catch (e) {
-		msg += " noName ";
-	}
+  try {
+    msg += "name=\"" + aNode.name + "\" ";
+  } catch (e) {
+    msg += " noName ";
+  }
 
-	dump(msg + '\n');
+  dump(msg + '\n');
 }
 
 
 function dumpAccessibleTree(aNode, level) {
-	level = level || 0;
+  level = level || 0;
 
-	dumpAccessibleNode(aNode, level);
-	try {
-		var child = aNode.firstChild;
-		while (child) {
-			dumpAccessibleTree(child, level + 1);
-			child = child.nextSibling;
-		}
-	} catch (e) {
-		dump("Error visiting child nodes: " + e + '\n');
-	}
+  dumpAccessibleNode(aNode, level);
+  try {
+    var child = aNode.firstChild;
+    while (child) {
+      dumpAccessibleTree(child, level + 1);
+      child = child.nextSibling;
+    }
+  } catch (e) {
+    dump("Error visiting child nodes: " + e + '\n');
+  }
 }
 
 function A(o) {
   var acc = SpecialPowers.Cc['@mozilla.org/accessibilityService;1']
                          .getService(SpecialPowers.Ci.nsIAccessibilityService);
   return acc.getAccessibleFor(o);
 }
 
--- a/accessible/tests/mochitest/aom/test_general.html
+++ b/accessible/tests/mochitest/aom/test_general.html
@@ -92,16 +92,16 @@
         'margin-left', 'text-align', 'text-indent', 'margin-right',
         'tag', 'margin-top', 'margin-bottom', 'display',
         'explicit-name'
       ];
     }
 
     is(anode.attributes.length, attrs.length, 'correct number of attributes');
     for (var i = 0; i < attrs.length; i++) {
-      is(anode.attributes[i], attrs[i],
-         `${attrs[i]} attribute is expected at ${i}th index`);
+      ok(attrs.indexOf(anode.attributes[i]) >= 0,
+         `${anode.attributes[i]} attribute is expected and found`);
     }
 
     finish();
   }
   </script>
 </head>
--- a/accessible/tests/mochitest/attributes.js
+++ b/accessible/tests/mochitest/attributes.js
@@ -91,17 +91,17 @@ function testGroupAttrs(aAccOrElmOrID, a
     };
     testAttrs(aAccOrElmOrID, attrs, true);
   }
 
   if (aLevel) {
     is(levelObj.value, aLevel,
        "Wrong group level for " + prettyName(aAccOrElmOrID));
 
-    var attrs = { "level" : String(aLevel) };
+    var attrs = { "level": String(aLevel) };
     testAttrs(aAccOrElmOrID, attrs, true);
   }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Text attributes.
 
 /**
@@ -154,17 +154,17 @@ function testTextAttrs(aID, aOffset, aAt
 
   for (var name in aDefAttrs) {
     if (!(name in expectedAttrs))
       expectedAttrs[name] = aDefAttrs[name];
   }
 
   attrs = getTextAttributes(aID, accessible, true, aOffset,
                             startOffset, endOffset);
-  
+
   if (!attrs)
     return;
 
   compareAttrs(errorMsg, attrs, expectedAttrs, aSkipUnexpectedAttrs);
 }
 
 /**
  * Test default text attributes.
@@ -176,28 +176,28 @@ function testTextAttrs(aID, aOffset, aAt
  * @param aSkipUnexpectedAttrs  [in] points the function doesn't fail if
  *                              unexpected attribute is encountered
  */
 function testDefaultTextAttrs(aID, aDefAttrs, aSkipUnexpectedAttrs)
 {
   var accessible = getAccessible(aID, [nsIAccessibleText]);
   if (!accessible)
     return;
-  
+
   var defAttrs = null;
-  try{
+  try {
     defAttrs = accessible.defaultTextAttributes;
   } catch (e) {
   }
-  
+
   if (!defAttrs) {
     ok(false, "Can't get default text attributes for " + aID);
     return;
   }
-  
+
   var errorMsg = ". Getting default text attributes for " + aID;
   compareAttrs(errorMsg, defAttrs, aDefAttrs, aSkipUnexpectedAttrs);
 }
 
 /**
  * Test text attributes for wrong offset.
  */
 function testTextAttrsWrongOffset(aID, aOffset)
@@ -313,22 +313,22 @@ function testAttrsInternal(aAccOrElmOrID
   var accessible = getAccessible(aAccOrElmOrID);
   if (!accessible)
     return;
 
   var attrs = null;
   try {
     attrs = accessible.attributes;
   } catch (e) { }
-  
+
   if (!attrs) {
     ok(false, "Can't get object attributes for " + prettyName(aAccOrElmOrID));
     return;
   }
-  
+
   var errorMsg = " for " + prettyName(aAccOrElmOrID);
   compareAttrs(errorMsg, attrs, aAttrs, aSkipUnexpectedAttrs, aAbsentAttrs);
 }
 
 function compareAttrs(aErrorMsg, aAttrs, aExpectedAttrs, aSkipUnexpectedAttrs,
                       aAbsentAttrs)
 {
   // Check if all obtained attributes are expected and have expected value.
@@ -351,17 +351,17 @@ function compareAttrs(aErrorMsg, aAttrs,
     }
   }
 
   // Check if all expected attributes are presented.
   for (var name in aExpectedAttrs) {
     var value = "";
     try {
       value = aAttrs.getStringProperty(name);
-    } catch(e) { }
+    } catch (e) { }
 
     if (!value)
       ok(false,
          "There is no expected attribute '" + name + "' " + aErrorMsg);
   }
 
   // Check if all unexpected attributes are absent.
   if (aAbsentAttrs) {
--- a/accessible/tests/mochitest/attributes/a11y.ini
+++ b/accessible/tests/mochitest/attributes/a11y.ini
@@ -1,12 +1,13 @@
 [DEFAULT]
 support-files =
   !/accessible/tests/mochitest/*.js
 
+[test_dpub_aria_xml-roles.html]
 [test_obj.html]
 [test_obj_css.html]
 [test_obj_css.xul]
 [test_obj_group.html]
 [test_obj_group.xul]
 [test_obj_group_tree.xul]
 [test_tag.html]
 [test_xml-roles.html]
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/attributes/test_dpub_aria_xml-roles.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>XML roles tests</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
+          src="../attributes.js"></script>
+
+  <script type="application/javascript">
+
+    function doTest()
+    {
+      // DPub ARIA roles should be exposed via the xml-roles object attribute.
+      let dpub_attrs = [
+        'doc-abstract',
+        'doc-acknowledgments',
+        'doc-afterword',
+        'doc-appendix',
+        'doc-backlink',
+        'doc-biblioentry',
+        'doc-bibliography',
+        'doc-biblioref',
+        'doc-chapter',
+        'doc-colophon',
+        'doc-conclusion',
+        'doc-cover',
+        'doc-credit',
+        'doc-credits',
+        'doc-dedication',
+        'doc-endnote',
+        'doc-endnotes',
+        'doc-epigraph',
+        'doc-epilogue',
+        'doc-errata',
+        'doc-example',
+        'doc-footnote',
+        'doc-foreword',
+        'doc-glossary',
+        'doc-glossref',
+        'doc-index',
+        'doc-introduction',
+        'doc-noteref',
+        'doc-notice',
+        'doc-pagebreak',
+        'doc-pagelist',
+        'doc-part',
+        'doc-preface',
+        'doc-prologue',
+        'doc-pullquote',
+        'doc-qna',
+        'doc-subtitle',
+        'doc-tip',
+        'doc-toc'
+      ];
+      for (let attr of dpub_attrs) {
+        testAttrs(attr, {"xml-roles": attr}, true);
+      }
+      SimpleTest.finish();
+    }
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=1343537"
+     title="implement ARIA DPUB extension">
+    Bug 1343537
+  </a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test"></pre>
+  <div id="doc-abstract" role="doc-abstract">abstract</div>
+  <div id="doc-acknowledgments" role="doc-acknowledgments">acknowledgments</div>
+  <div id="doc-afterword" role="doc-afterword">afterword</div>
+  <div id="doc-appendix" role="doc-appendix">appendix</div>
+  <div id="doc-backlink" role="doc-backlink">backlink</div>
+  <div id="doc-biblioentry" role="doc-biblioentry">biblioentry</div>
+  <div id="doc-bibliography" role="doc-bibliography">bibliography</div>
+  <div id="doc-biblioref" role="doc-biblioref">biblioref</div>
+  <div id="doc-chapter" role="doc-chapter">chapter</div>
+  <div id="doc-colophon" role="doc-colophon">colophon</div>
+  <div id="doc-conclusion" role="doc-conclusion">conclusion</div>
+  <div id="doc-cover" role="doc-cover">cover</div>
+  <div id="doc-credit" role="doc-credit">credit</div>
+  <div id="doc-credits" role="doc-credits">credits</div>
+  <div id="doc-dedication" role="doc-dedication">dedication</div>
+  <div id="doc-endnote" role="doc-endnote">endnote</div>
+  <div id="doc-endnotes" role="doc-endnotes">endnotes</div>
+  <div id="doc-epigraph" role="doc-epigraph">epigraph</div>
+  <div id="doc-epilogue" role="doc-epilogue">epilogue</div>
+  <div id="doc-errata" role="doc-errata">errata</div>
+  <div id="doc-example" role="doc-example">example</div>
+  <div id="doc-footnote" role="doc-footnote">footnote</div>
+  <div id="doc-foreword" role="doc-foreword">foreword</div>
+  <div id="doc-glossary" role="doc-glossary">glossary</div>
+  <div id="doc-glossref" role="doc-glossref">glossref</div>
+  <div id="doc-index" role="doc-index">index</div>
+  <div id="doc-introduction" role="doc-introduction">introduction</div>
+  <div id="doc-noteref" role="doc-noteref">noteref</div>
+  <div id="doc-notice" role="doc-notice">notice</div>
+  <div id="doc-pagebreak" role="doc-pagebreak">pagebreak</div>
+  <div id="doc-pagelist" role="doc-pagelist">pagelist</div>
+  <div id="doc-part" role="doc-part">part</div>
+  <div id="doc-preface" role="doc-preface">preface</div>
+  <div id="doc-prologue" role="doc-prologue">prologue</div>
+  <div id="doc-pullquote" role="doc-pullquote">pullquote</div>
+  <div id="doc-qna" role="doc-qna">qna</div>
+  <div id="doc-subtitle" role="doc-subtitle">subtitle</div>
+  <div id="doc-tip" role="doc-tip">tip</div>
+  <div id="doc-toc" role="doc-toc">toc</div>
+</body>
+</html>
--- a/accessible/tests/mochitest/attributes/test_obj.html
+++ b/accessible/tests/mochitest/attributes/test_obj.html
@@ -17,111 +17,115 @@ https://bugzilla.mozilla.org/show_bug.cg
           src="../common.js"></script>
   <script type="application/javascript"
           src="../attributes.js"></script>
 
   <script type="application/javascript">
     function doTest()
     {
       // aria
-      testAttrs("atomic", {"atomic" : "true", "container-atomic" : "true"}, true);
-      testAttrs(getNode("atomic").firstChild, {"container-atomic" : "true"}, true);
-      testAbsentAttrs("atomic_false", {"atomic" : "false", "container-atomic" : "false"});
-      testAbsentAttrs(getNode("atomic_false").firstChild, {"container-atomic" : "false"});
+      testAttrs("atomic", {"atomic": "true", "container-atomic": "true"}, true);
+      testAttrs(getNode("atomic").firstChild, {"container-atomic": "true"}, true);
+      testAbsentAttrs("atomic_false", {"atomic": "false", "container-atomic": "false"});
+      testAbsentAttrs(getNode("atomic_false").firstChild, {"container-atomic": "false"});
 
-      testAttrs("autocomplete", {"autocomplete" : "true"}, true);
-      testAttrs("checkbox", {"checkable" : "true"}, true);
-      testAttrs("checkedCheckbox", {"checkable" : "true"}, true);
-      testAttrs("checkedMenuitem", {"checkable" : "true"}, true);
-      testAttrs("checkedOption", {"checkable" : "true"}, true);
-      testAttrs("checkedRadio", {"checkable" : "true"}, true);
-      testAttrs("checkedTreeitem", {"checkable" : "true"}, true);
-      testAttrs("dropeffect", {"dropeffect" : "copy"}, true);
-      testAttrs("grabbed", {"grabbed" : "true"}, true);
-      testAbsentAttrs("haspopup", { "haspopup": "false" });
-      testAttrs("hidden", {"hidden" : "true"}, true);
+      testAttrs("autocomplete", {"autocomplete": "true"}, true);
+      testAttrs("checkbox", {"checkable": "true"}, true);
+      testAttrs("checkedCheckbox", {"checkable": "true"}, true);
+      testAbsentAttrs("checkedMenuitem", {"checkable": "true"}, true);
+      testAttrs("checkedMenuitemCheckbox", {"checkable": "true"}, true);
+      testAttrs("checkedMenuitemRadio", {"checkable": "true"}, true);
+      testAttrs("checkedOption", {"checkable": "true"}, true);
+      testAttrs("checkedRadio", {"checkable": "true"}, true);
+      testAttrs("checkedTreeitem", {"checkable": "true"}, true);
+      testAttrs("dropeffect", {"dropeffect": "copy"}, true);
+      testAttrs("grabbed", {"grabbed": "true"}, true);
+      testAttrs("haspopupTrue", { "haspopup": "true" }, true);
+      testAbsentAttrs("haspopupFalse", { "haspopup": "false" });
+      testAbsentAttrs("haspopupEmpty", { "haspopup": "" });
+      testAttrs("hidden", {"hidden": "true"}, true);
       testAbsentAttrs("hidden_false", { "hidden": "false" });
-      testAbsentAttrs("modal", {"modal" : "true"});
-      testAttrs("sortAscending", {"sort" : "ascending"}, true);
-      testAttrs("sortDescending", {"sort" : "descending"}, true);
-      testAttrs("sortNone", {"sort" : "none"}, true);
-      testAttrs("sortOther", {"sort" : "other"}, true);
-      testAttrs("roledescr", {"roledescription" : "spreadshit"}, true);
-      testAttrs("currentPage", {"current" : "page"}, true);
+      testAbsentAttrs("modal", {"modal": "true"});
+      testAttrs("sortAscending", {"sort": "ascending"}, true);
+      testAttrs("sortDescending", {"sort": "descending"}, true);
+      testAttrs("sortNone", {"sort": "none"}, true);
+      testAttrs("sortOther", {"sort": "other"}, true);
+      testAttrs("roledescr", {"roledescription": "spreadshit"}, true);
+      testAttrs("currentPage", {"current": "page"}, true);
 
       // inherited attributes by subdocuments
       var subdoc = getAccessible("iframe").firstChild;
-      testAttrs(subdoc, {"busy" : "true"}, true);
+      testAttrs(subdoc, {"busy": "true"}, true);
 
       // live object attribute
 
       // HTML
-      testAttrs("output", {"live" : "polite"}, true);
+      testAttrs("output", {"live": "polite"}, true);
 
       // ARIA
-      testAttrs("live", {"live" : "polite"}, true);
-      testAttrs("live2", {"live" : "polite"}, true);
-      testAbsentAttrs("live3", {"live" : ""});
-      testAttrs("log", {"live" : "polite"}, true);
-      testAttrs("logAssertive", {"live" : "assertive"}, true);
-      testAttrs("marquee", {"live" : "off"}, true);
-      testAttrs("status", {"live" : "polite"}, true);
-      testAttrs("timer", {"live" : "off"}, true);
-      testAbsentAttrs("tablist", {"live" : "polite"});
+      testAttrs("live", {"live": "polite"}, true);
+      testAttrs("live2", {"live": "polite"}, true);
+      testAbsentAttrs("live3", {"live": ""});
+      testAttrs("log", {"live": "polite"}, true);
+      testAttrs("logAssertive", {"live": "assertive"}, true);
+      testAttrs("marquee", {"live": "off"}, true);
+      testAttrs("status", {"live": "polite"}, true);
+      testAttrs("timer", {"live": "off"}, true);
+      testAbsentAttrs("tablist", {"live": "polite"});
 
       // container-live object attribute
-      testAttrs("liveChild", {"container-live" : "polite"}, true);
-      testAttrs("live2Child", {"container-live" : "polite"}, true);
-      testAttrs("logChild", {"container-live" : "polite"}, true);
-      testAttrs("logAssertiveChild", {"container-live" : "assertive"}, true);
-      testAttrs("marqueeChild", {"container-live" : "off"}, true);
-      testAttrs("statusChild", {"container-live" : "polite"}, true);
-      testAttrs("timerChild", {"container-live" : "off"}, true);
-      testAbsentAttrs("tablistChild", {"container-live" : "polite"});
+      testAttrs("liveChild", {"container-live": "polite"}, true);
+      testAttrs("live2Child", {"container-live": "polite"}, true);
+      testAttrs("logChild", {"container-live": "polite"}, true);
+      testAttrs("logAssertiveChild", {"container-live": "assertive"}, true);
+      testAttrs("marqueeChild", {"container-live": "off"}, true);
+      testAttrs("statusChild", {"container-live": "polite"}, true);
+      testAttrs("timerChild", {"container-live": "off"}, true);
+      testAbsentAttrs("tablistChild", {"container-live": "polite"});
 
       // container-live-role object attribute
-      testAttrs("log", {"container-live-role" : "log"}, true);
-      testAttrs("logAssertive", {"container-live-role" : "log"}, true);
-      testAttrs("marquee", {"container-live-role" : "marquee"}, true);
-      testAttrs("status", {"container-live-role" : "status"}, true);
-      testAttrs("timer", {"container-live-role" : "timer"}, true);
-      testAttrs("logChild", {"container-live-role" : "log"}, true);
-      testAttrs("logAssertive", {"container-live-role" : "log"}, true);
-      testAttrs("logAssertiveChild", {"container-live-role" : "log"}, true);
-      testAttrs("marqueeChild", {"container-live-role" : "marquee"}, true);
-      testAttrs("statusChild", {"container-live-role" : "status"}, true);
-      testAttrs("timerChild", {"container-live-role" : "timer"}, true);
-      testAbsentAttrs("tablistChild", {"container-live-role" : "tablist"});
+      testAttrs("log", {"container-live-role": "log"}, true);
+      testAttrs("logAssertive", {"container-live-role": "log"}, true);
+      testAttrs("marquee", {"container-live-role": "marquee"}, true);
+      testAttrs("status", {"container-live-role": "status"}, true);
+      testAttrs("timer", {"container-live-role": "timer"}, true);
+      testAttrs("logChild", {"container-live-role": "log"}, true);
+      testAttrs("logAssertive", {"container-live-role": "log"}, true);
+      testAttrs("logAssertiveChild", {"container-live-role": "log"}, true);
+      testAttrs("marqueeChild", {"container-live-role": "marquee"}, true);
+      testAttrs("statusChild", {"container-live-role": "status"}, true);
+      testAttrs("timerChild", {"container-live-role": "timer"}, true);
+      testAbsentAttrs("tablistChild", {"container-live-role": "tablist"});
 
       // absent aria-label and aria-labelledby object attribute
-      testAbsentAttrs("label", {"label" : "foo"});
-      testAbsentAttrs("labelledby", {"labelledby" : "label"});
+      testAbsentAttrs("label", {"label": "foo"});
+      testAbsentAttrs("labelledby", {"labelledby": "label"});
 
       // container that has no default live attribute
-      testAttrs("liveGroup", {"live" : "polite"}, true);
-      testAttrs("liveGroupChild", {"container-live" : "polite"}, true);
-      testAttrs("liveGroup", {"container-live-role" : "group"}, true);
-      testAttrs("liveGroupChild", {"container-live-role" : "group"}, true);
+      testAttrs("liveGroup", {"live": "polite"}, true);
+      testAttrs("liveGroupChild", {"container-live": "polite"}, true);
+      testAttrs("liveGroup", {"container-live-role": "group"}, true);
+      testAttrs("liveGroupChild", {"container-live-role": "group"}, true);
 
       // text input type
       testAbsentAttrs("button", { "text-input-type": "button"});
       testAbsentAttrs("checkbox", { "text-input-type": "checkbox"});
       testAbsentAttrs("radio", { "text-input-type": "radio"});
-      testAttrs("email", {"text-input-type" : "email"}, true);
-      testAttrs("search", {"text-input-type" : "search"}, true);
-      testAttrs("tel", {"text-input-type" : "tel"}, true);
-      testAttrs("url", {"text-input-type" : "url"}, true);
+      testAttrs("email", {"text-input-type": "email"}, true);
+      testAttrs("search", {"text-input-type": "search"}, true);
+      testAttrs("tel", {"text-input-type": "tel"}, true);
+      testAttrs("url", {"text-input-type": "url"}, true);
 
       // ARIA
-      testAttrs("searchbox", {"text-input-type" : "search"}, true);
+      testAttrs("searchbox", {"text-input-type": "search"}, true);
 
       // html
-      testAttrs("radio", {"checkable" : "true"}, true); 
-      testAttrs("checkbox", {"checkable" : "true"}, true); 
-      testAttrs("draggable", {"draggable" : "true"}, true);
+      testAttrs("radio", {"checkable": "true"}, true);
+      testAttrs("checkbox", {"checkable": "true"}, true);
+      testAttrs("draggable", {"draggable": "true"}, true);
       testAttrs("th1", { "abbr": "SS#" }, true);
       testAttrs("th2", { "abbr": "SS#" }, true);
       testAttrs("th2", { "axis": "social" }, true);
 
       // don't barf on an empty abbr element.
       testAbsentAttrs("th3", { "abbr": "" }, true);
 
       // application accessible
@@ -133,17 +137,17 @@ https://bugzilla.mozilla.org/show_bug.cg
         }
         testAttrs(getApplicationAccessible(), attrs, false);
       }
 
       // no object attributes
       testAbsentAttrs(getAccessible("listitem").firstChild, { "tag": "" });
 
       // experimental aria
-      testAttrs("experimental", {"blah" : "true"}, true);
+      testAttrs("experimental", {"blah": "true"}, true);
 
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
@@ -200,22 +204,26 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   <!-- aria -->
   <div id="atomic" aria-atomic="true">live region</div>
   <div id="atomic_false" aria-atomic="false">live region</div>
   <div id="autocomplete" role="textbox" aria-autocomplete="true"></div>
   <div id="checkbox" role="checkbox"></div>
   <div id="checkedCheckbox" role="checkbox" aria-checked="true"></div>
   <div id="checkedMenuitem" role="menuitem" aria-checked="true"></div>
+  <div id="checkedMenuitemCheckbox" role="menuitemcheckbox" aria-checked="true"></div>
+  <div id="checkedMenuitemRadio" role="menuitemradio" aria-checked="true"></div>
   <div id="checkedOption" role="option" aria-checked="true"></div>
   <div id="checkedRadio" role="radio" aria-checked="true"></div>
   <div id="checkedTreeitem" role="treeitem" aria-checked="true"></div>
   <div id="dropeffect" aria-dropeffect="copy"></div>
   <div id="grabbed" aria-grabbed="true"></div>
-  <div id="haspopup" aria-haspopup="true"></div>
+  <div id="haspopupTrue" aria-haspopup="true"></div>
+  <div id="haspopupFalse" aria-haspopup="false"></div>
+  <div id="haspopupEmpty" aria-haspopup=""></div>
   <div id="hidden" aria-hidden="true"></div>
   <div id="hidden_false" aria-hidden="false"></div>
   <div id="modal" aria-modal="true"></div>
   <div id="sortAscending" role="columnheader" aria-sort="ascending"></div>
   <div id="sortDescending" role="columnheader" aria-sort="descending"></div>
   <div id="sortNone" role="columnheader" aria-sort="none"></div>
   <div id="sortOther" role="columnheader" aria-sort="other"></div>
   <div id="roledescr" aria-roledescription="spreadshit"></div>
--- a/accessible/tests/mochitest/attributes/test_obj_group.html
+++ b/accessible/tests/mochitest/attributes/test_obj_group.html
@@ -144,36 +144,36 @@
       testGroupAttrs("tree3_ti1b", 2, 2, 2);
       testGroupAttrs("tree3_ti2", 2, 2, 1);
       testGroupAttrs("tree3_ti2a", 1, 2, 2);
       testGroupAttrs("tree3_ti2b", 2, 2, 2);
 
       //////////////////////////////////////////////////////////////////////////
       // ARIA grid
       testGroupAttrs("grid_row1", 1, 2);
-      testAbsentAttrs("grid_cell1", {"posinset":"", "setsize":""});
-      testAbsentAttrs("grid_cell2", {"posinset":"", "setsize":""});
+      testAbsentAttrs("grid_cell1", {"posinset": "", "setsize": ""});
+      testAbsentAttrs("grid_cell2", {"posinset": "", "setsize": ""});
 
       testGroupAttrs("grid_row2", 2, 2);
-      testAbsentAttrs("grid_cell3", {"posinset":"", "setsize":""});
-      testAbsentAttrs("grid_cell4", {"posinset":"", "setsize":""});
+      testAbsentAttrs("grid_cell3", {"posinset": "", "setsize": ""});
+      testAbsentAttrs("grid_cell4", {"posinset": "", "setsize": ""});
 
       //////////////////////////////////////////////////////////////////////////
       // ARIA treegrid
       testGroupAttrs("treegrid_row1", 1, 2, 1);
-      testAbsentAttrs("treegrid_cell1", {"posinset":"", "setsize":""});
-      testAbsentAttrs("treegrid_cell2", {"posinset":"", "setsize":""});
+      testAbsentAttrs("treegrid_cell1", {"posinset": "", "setsize": ""});
+      testAbsentAttrs("treegrid_cell2", {"posinset": "", "setsize": ""});
 
       testGroupAttrs("treegrid_row2", 1, 1, 2);
-      testAbsentAttrs("treegrid_cell3", {"posinset":"", "setsize":""});
-      testAbsentAttrs("treegrid_cell4", {"posinset":"", "setsize":""});
+      testAbsentAttrs("treegrid_cell3", {"posinset": "", "setsize": ""});
+      testAbsentAttrs("treegrid_cell4", {"posinset": "", "setsize": ""});
 
       testGroupAttrs("treegrid_row3", 2, 2, 1);
-      testAbsentAttrs("treegrid_cell5", {"posinset":"", "setsize":""});
-      testAbsentAttrs("treegrid_cell6", {"posinset":"", "setsize":""});
+      testAbsentAttrs("treegrid_cell5", {"posinset": "", "setsize": ""});
+      testAbsentAttrs("treegrid_cell6", {"posinset": "", "setsize": ""});
 
       //////////////////////////////////////////////////////////////////////////
       // HTML headings
       testGroupAttrs("h1", 0, 0, 1);
       testGroupAttrs("h2", 0, 0, 2);
       testGroupAttrs("h3", 0, 0, 3);
       testGroupAttrs("h4", 0, 0, 4);
       testGroupAttrs("h5", 0, 0, 5);
--- a/accessible/tests/mochitest/attributes/test_tag.html
+++ b/accessible/tests/mochitest/attributes/test_tag.html
@@ -15,24 +15,24 @@
   <script type="application/javascript"
           src="../attributes.js"></script>
 
   <script type="application/javascript">
 
     function doTest()
     {
       // And some AT may look for this
-      testAttrs("nav", {"tag" : "nav"}, true);
-      testAttrs("header", {"tag" : "header"}, true);
-      testAttrs("footer", {"tag" : "footer"}, true);
-      testAttrs("article", {"tag" : "article"}, true);
-      testAttrs("aside", {"tag" : "aside"}, true);
-      testAttrs("section", {"tag" : "section"}, true);
-      testAttrs("main", {"tag" : "article"}, true);
-      testAttrs("form", {"tag" : "article"}, true);
+      testAttrs("nav", {"tag": "nav"}, true);
+      testAttrs("header", {"tag": "header"}, true);
+      testAttrs("footer", {"tag": "footer"}, true);
+      testAttrs("article", {"tag": "article"}, true);
+      testAttrs("aside", {"tag": "aside"}, true);
+      testAttrs("section", {"tag": "section"}, true);
+      testAttrs("main", {"tag": "article"}, true);
+      testAttrs("form", {"tag": "article"}, true);
 
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
--- a/accessible/tests/mochitest/attributes/test_xml-roles.html
+++ b/accessible/tests/mochitest/attributes/test_xml-roles.html
@@ -15,86 +15,87 @@
   <script type="application/javascript"
           src="../attributes.js"></script>
 
   <script type="application/javascript">
 
     function doTest()
     {
       // Some AT may look for this
-      testAttrs("nav", {"xml-roles" : "navigation"}, true);
-      testAttrs("header", {"xml-roles" : "banner"}, true);
-      testAbsentAttrs("article_header", {"xml-roles" : "banner"});
-      testAbsentAttrs("section_header", {"xml-roles" : "banner"});
-      testAttrs("footer", {"xml-roles" : "contentinfo"}, true);
-      testAbsentAttrs("article_footer", {"xml-roles" : "contentinfo"});
-      testAbsentAttrs("section_footer", {"xml-roles" : "contentinfo"});
-      testAttrs("aside", {"xml-roles" : "complementary"}, true);
-      testAttrs("section", {"xml-roles" : "region"}, true);
-      testAttrs("main", {"xml-roles" : "main"}, true); // // ARIA override
-      testAttrs("form", {"xml-roles" : "form"}, true);
-      testAttrs("feed", {"xml-roles" : "feed"}, true);
-      testAttrs("article", {"xml-roles" : "article"}, true);
-      testAttrs("main_element", {"xml-roles" : "main"}, true);
+      testAttrs("nav", {"xml-roles": "navigation"}, true);
+      testAttrs("header", {"xml-roles": "banner"}, true);
+      testAbsentAttrs("article_header", {"xml-roles": "banner"});
+      testAbsentAttrs("section_header", {"xml-roles": "banner"});
+      testAttrs("footer", {"xml-roles": "contentinfo"}, true);
+      testAbsentAttrs("article_footer", {"xml-roles": "contentinfo"});
+      testAbsentAttrs("section_footer", {"xml-roles": "contentinfo"});
+      testAttrs("aside", {"xml-roles": "complementary"}, true);
+      testAttrs("section", {"xml-roles": "region"}, true);
+      testAttrs("main", {"xml-roles": "main"}, true); // // ARIA override
+      testAttrs("form", {"xml-roles": "form"}, true);
+      testAttrs("feed", {"xml-roles": "feed"}, true);
+      testAttrs("article", {"xml-roles": "article"}, true);
+      testAttrs("main_element", {"xml-roles": "main"}, true);
+      testAttrs("figure", {"xml-roles": "figure"}, true);
 
-      testAttrs("search", {"xml-roles" : "searchbox"}, true);
+      testAttrs("search", {"xml-roles": "searchbox"}, true);
 
-      testAttrs("open-1", {"xml-roles" : "open-fence"}, true);
-      testAttrs("open-2", {"xml-roles" : "open-fence"}, true);
-      testAttrs("open-3", {"xml-roles" : "open-fence"}, true);
-      testAttrs("open-4", {"xml-roles" : "open-fence"}, true);
-      testAttrs("open-5", {"xml-roles" : "open-fence"}, true);
-      testAttrs("open-6", {"xml-roles" : "open-fence"}, true);
-      testAttrs("open-7", {"xml-roles" : "open-fence"}, true);
+      testAttrs("open-1", {"xml-roles": "open-fence"}, true);
+      testAttrs("open-2", {"xml-roles": "open-fence"}, true);
+      testAttrs("open-3", {"xml-roles": "open-fence"}, true);
+      testAttrs("open-4", {"xml-roles": "open-fence"}, true);
+      testAttrs("open-5", {"xml-roles": "open-fence"}, true);
+      testAttrs("open-6", {"xml-roles": "open-fence"}, true);
+      testAttrs("open-7", {"xml-roles": "open-fence"}, true);
 
-      testAttrs("sep-1", {"xml-roles" : "separator"}, true);
-      testAttrs("sep-2", {"xml-roles" : "separator"}, true);
-      testAttrs("sep-3", {"xml-roles" : "separator"}, true);
-      testAttrs("sep-4", {"xml-roles" : "separator"}, true);
-      testAttrs("sep-5", {"xml-roles" : "separator"}, true);
-      testAttrs("sep-6", {"xml-roles" : "separator"}, true);
-      testAttrs("sep-7", {"xml-roles" : "separator"}, true);
+      testAttrs("sep-1", {"xml-roles": "separator"}, true);
+      testAttrs("sep-2", {"xml-roles": "separator"}, true);
+      testAttrs("sep-3", {"xml-roles": "separator"}, true);
+      testAttrs("sep-4", {"xml-roles": "separator"}, true);
+      testAttrs("sep-5", {"xml-roles": "separator"}, true);
+      testAttrs("sep-6", {"xml-roles": "separator"}, true);
+      testAttrs("sep-7", {"xml-roles": "separator"}, true);
 
-      testAttrs("close-1", {"xml-roles" : "close-fence"}, true);
-      testAttrs("close-2", {"xml-roles" : "close-fence"}, true);
-      testAttrs("close-3", {"xml-roles" : "close-fence"}, true);
-      testAttrs("close-4", {"xml-roles" : "close-fence"}, true);
-      testAttrs("close-5", {"xml-roles" : "close-fence"}, true);
-      testAttrs("close-6", {"xml-roles" : "close-fence"}, true);
-      testAttrs("close-7", {"xml-roles" : "close-fence"}, true);
+      testAttrs("close-1", {"xml-roles": "close-fence"}, true);
+      testAttrs("close-2", {"xml-roles": "close-fence"}, true);
+      testAttrs("close-3", {"xml-roles": "close-fence"}, true);
+      testAttrs("close-4", {"xml-roles": "close-fence"}, true);
+      testAttrs("close-5", {"xml-roles": "close-fence"}, true);
+      testAttrs("close-6", {"xml-roles": "close-fence"}, true);
+      testAttrs("close-7", {"xml-roles": "close-fence"}, true);
 
-      testAttrs("num", {"xml-roles" : "numerator"}, true);
-      testAttrs("den", {"xml-roles" : "denominator"}, true);
+      testAttrs("num", {"xml-roles": "numerator"}, true);
+      testAttrs("den", {"xml-roles": "denominator"}, true);
 
-      testAttrs("sub-1", {"xml-roles" : "subscript"}, true);
-      testAttrs("sub-2", {"xml-roles" : "subscript"}, true);
-      testAttrs("sub-3", {"xml-roles" : "subscript"}, true);
-      testAttrs("sup-1", {"xml-roles" : "superscript"}, true);
-      testAttrs("sup-2", {"xml-roles" : "superscript"}, true);
-      testAttrs("sup-3", {"xml-roles" : "superscript"}, true);
-      testAttrs("sup-4", {"xml-roles" : "superscript"}, true);
-      testAttrs("presub-1", {"xml-roles" : "presubscript"}, true);
-      testAttrs("presub-2", {"xml-roles" : "presubscript"}, true);
-      testAttrs("presup-1", {"xml-roles" : "presuperscript"}, true);
+      testAttrs("sub-1", {"xml-roles": "subscript"}, true);
+      testAttrs("sub-2", {"xml-roles": "subscript"}, true);
+      testAttrs("sub-3", {"xml-roles": "subscript"}, true);
+      testAttrs("sup-1", {"xml-roles": "superscript"}, true);
+      testAttrs("sup-2", {"xml-roles": "superscript"}, true);
+      testAttrs("sup-3", {"xml-roles": "superscript"}, true);
+      testAttrs("sup-4", {"xml-roles": "superscript"}, true);
+      testAttrs("presub-1", {"xml-roles": "presubscript"}, true);
+      testAttrs("presub-2", {"xml-roles": "presubscript"}, true);
+      testAttrs("presup-1", {"xml-roles": "presuperscript"}, true);
 
-      testAttrs("under-1", {"xml-roles" : "underscript"}, true);
-      testAttrs("under-2", {"xml-roles" : "underscript"}, true);
-      testAttrs("over-1", {"xml-roles" : "overscript"}, true);
-      testAttrs("over-2", {"xml-roles" : "overscript"}, true);
+      testAttrs("under-1", {"xml-roles": "underscript"}, true);
+      testAttrs("under-2", {"xml-roles": "underscript"}, true);
+      testAttrs("over-1", {"xml-roles": "overscript"}, true);
+      testAttrs("over-2", {"xml-roles": "overscript"}, true);
 
-      testAttrs("root-index-1", {"xml-roles" : "root-index"}, true);
+      testAttrs("root-index-1", {"xml-roles": "root-index"}, true);
 
-      testAttrs("base-1", {"xml-roles" : "base"}, true);
-      testAttrs("base-2", {"xml-roles" : "base"}, true);
-      testAttrs("base-3", {"xml-roles" : "base"}, true);
-      testAttrs("base-4", {"xml-roles" : "base"}, true);
-      testAttrs("base-5", {"xml-roles" : "base"}, true);
-      testAttrs("base-6", {"xml-roles" : "base"}, true);
-      testAttrs("base-7", {"xml-roles" : "base"}, true);
-      testAttrs("base-8", {"xml-roles" : "base"}, true);
+      testAttrs("base-1", {"xml-roles": "base"}, true);
+      testAttrs("base-2", {"xml-roles": "base"}, true);
+      testAttrs("base-3", {"xml-roles": "base"}, true);
+      testAttrs("base-4", {"xml-roles": "base"}, true);
+      testAttrs("base-5", {"xml-roles": "base"}, true);
+      testAttrs("base-6", {"xml-roles": "base"}, true);
+      testAttrs("base-7", {"xml-roles": "base"}, true);
+      testAttrs("base-8", {"xml-roles": "base"}, true);
 
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
@@ -135,16 +136,22 @@
      title="modify HTML5 header and footer accessibility API mapping">
     Bug 849624
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=1121518"
      title="ARIA 1.1: Support role 'searchbox'">
     Bug 1121518
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=1356049"
+     title="Map ARIA figure role">
+    Bug 1356049
+  </a>
+
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <nav id="nav">a nav</nav>
   <header id="header">a header</header>
   <footer id="footer">a footer</footer>
@@ -158,16 +165,17 @@
   </section>
   <aside id="aside">by the way I am an aside</aside>
   <section id="section">a section</section>
   <article id="main" role="main">a main area</article>
   <article id="form" role="form">a form area</article>
   <div id="feed" role="feed">a feed</div>
   <article id="article">article</article>
   <main id="main_element">another main area</main>
+  <div id="figure" role="figure">a figure</div>
 
   <input id="search" type="search"/>
 
   <!-- open-fence, separator, close-fence -->
   <math><mo id="open-1">(</mo><mi>x</mi><mo id="sep-1">,</mo><mi>y</mi><mo id="close-1">)</mo></math>
   <math><mrow><mo id="open-2">(</mo><mi>x</mi><mo id="sep-2">,</mo><mi>y</mi><mo id="close-2">)</mo></mrow></math>
   <math><mstyle><mo id="open-3">(</mo><mi>x</mi><mo id="sep-3">,</mo><mi>y</mi><mo id="close-3">)</mo></mstyle></math>
   <math><msqrt><mo id="open-4">(</mo><mi>x</mi><mo id="sep-4">,</mo><mi>y</mi><mo id="close-4">)</mo></msqrt></math>
--- a/accessible/tests/mochitest/bounds/a11y.ini
+++ b/accessible/tests/mochitest/bounds/a11y.ini
@@ -1,8 +1,6 @@
 [DEFAULT]
 support-files =
   !/accessible/tests/mochitest/*.js
 
 [test_list.html]
 [test_select.html]
-[test_zoom.html]
-[test_zoom_text.html]
deleted file mode 100644
--- a/accessible/tests/mochitest/bounds/test_zoom.html
+++ /dev/null
@@ -1,96 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <title>Accessible boundaries when page is zoomed</title>
-  <link rel="stylesheet" type="text/css"
-        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
-
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
-
-  <script type="application/javascript"
-          src="../common.js"></script>
-  <script type="application/javascript"
-          src="../role.js"></script>
-  <script type="application/javascript"
-          src="../events.js"></script>
-  <script type="application/javascript"
-          src="../layout.js"></script>
-  <script type="application/javascript"
-          src="../browser.js"></script>
-
-  <script type="application/javascript">
-    //gA11yEventDumpToConsole = true;
-    //enableLogging("tree,verbose");
-    function doPreTest()
-    {
-      var tabDocument = currentTabDocument();
-      var imgMap = tabDocument.getElementById("imgmap");
-      waitForImageMap(imgMap, doTest);
-    }
-
-    function doTest()
-    {
-      // Bug 746176: Failure of this whole test file on OS X.
-      if (MAC) {
-        todo(false, "Fix bug 746176 on Mac");
-        closeBrowserWindow();
-        SimpleTest.finish();
-        return;
-      }
-
-      var tabDocument = currentTabDocument();
-      var p1 = tabDocument.getElementById("p1");
-      var p2 = tabDocument.getElementById("p2");
-
-      var imgMap = tabDocument.getElementById("imgmap");
-      var imgMapAcc = getAccessible(imgMap);
-      var area = imgMapAcc.firstChild;
-
-      testBounds(p1);
-      testBounds(p2);
-      testBounds(area);
-
-      zoomDocument(tabDocument, 2.0);
-
-      testBounds(p1);
-      testBounds(p2);
-      testBounds(area);
-
-      closeBrowserWindow();
-      SimpleTest.finish();
-    }
-
-    var url = "data:text/html,<html><body>";
-    url += "<p id='p1'>para 1</p><p id='p2'>para 2</p>";
-    url += "<map name='atoz_map' id='map'>";
-    url += "  <area id='area1' href='http%3A%2F%2Fmozilla.org'";
-    url += "        coords=17,0,30,14' alt='mozilla.org' shape='rect'>";
-    url += "</map>";
-    url += "<img id='imgmap' width='447' height='15'";
-    url += "     usemap='%23atoz_map'";
-    url += "     src='chrome%3A%2F%2Fmochitests%2Fcontent%2Fa11y%2Faccessible%2Fletters.gif'>";
-    url += "</body></html>";
-
-    SimpleTest.waitForExplicitFinish();
-    openBrowserWindow(doPreTest,
-                      url,
-                      { left: 0, top: 0, width: 600, height: 600 });
-  </script>
-
-</head>
-<body>
-
-  <a target="_blank"
-     href="https://bugzilla.mozilla.org/show_bug.cgi?id=650241"
-     title="Location returned by accessibles incorrect when page zoomed">
-    Mozilla Bug 650241
-  </a>
-  <p id="display"></p>
-  <div id="content" style="display: none"></div>
-  <pre id="test">
-  </pre>
-</body>
-</html>
deleted file mode 100644
--- a/accessible/tests/mochitest/bounds/test_zoom_text.html
+++ /dev/null
@@ -1,77 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <title>The text range boundary when page is zoomed</title>
-  <meta http-equiv="Content-Type" content="text/html;charset=utf-8"></meta>
-  <link rel="stylesheet" type="text/css"
-        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
-
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
-
-  <script type="application/javascript"
-          src="../common.js"></script>
-  <script type="application/javascript"
-          src="../role.js"></script>
-  <script type="application/javascript"
-          src="../layout.js"></script>
-  <script type="application/javascript"
-          src="../browser.js"></script>
-
-  <script type="application/javascript">
-    function testTextNode(aDoc, aContainerID)
-    {
-      var hyperTextNode = aDoc.getElementById(aContainerID);
-      var textNode = hyperTextNode.firstChild;
-
-      var [x, y, width, height] = getBounds(textNode);
-      testTextBounds(hyperTextNode, 0, -1, [x, y, width, height],
-                     COORDTYPE_SCREEN_RELATIVE);
-    }
-
-    function doTest()
-    {
-      var tabDocument = currentTabDocument();
-      testTextNode(tabDocument, "p1");
-      testTextNode(tabDocument, "p2");
-
-      zoomDocument(tabDocument, 2.0);
-
-      testTextNode(tabDocument, "p1");
-
-      zoomDocument(tabDocument, 1.0);
-
-      closeBrowserWindow();
-      SimpleTest.finish();
-    }
-
-    var url = "data:text/html,<html>" +
-      "<meta http-equiv='Content-Type' content='text/html;charset=utf-8'>" +
-      "</meta><body>" +
-      "<p id='p1' style='font-family: monospace;'>Tilimilitryamdiya</p>" +
-      "<p id='p2'>ل</p>"
-      "</body></html>";
-
-    SimpleTest.waitForExplicitFinish();
-    openBrowserWindow(doTest,
-                      url,
-                      { left: 0, top: 0, width: 600, height: 600 });
-
-  </script>
-
-</head>
-<body>
-
-  <a target="_blank"
-     href="https://bugzilla.mozilla.org/show_bug.cgi?id=727942"
-     title="Text range boundaries are incorrect when page is zoomed">
-    Mozilla Bug 727942
-  </a>
-  <p id="display"></p>
-  <div id="content" style="display: none"></div>
-  <pre id="test">
-  </pre>
-</body>
-</html>
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -248,17 +248,17 @@ const DONOTFAIL_IF_NO_INTERFACE = 2;
 function getAccessible(aAccOrElmOrID, aInterfaces, aElmObj, aDoNotFailIf)
 {
   if (!aAccOrElmOrID)
     return null;
 
   var elm = null;
 
   if (aAccOrElmOrID instanceof nsIAccessible) {
-    try { elm = aAccOrElmOrID.DOMNode; } catch(e) { }
+    try { elm = aAccOrElmOrID.DOMNode; } catch (e) { }
 
   } else if (aAccOrElmOrID instanceof nsIDOMNode) {
     elm = aAccOrElmOrID;
 
   } else {
     elm = document.getElementById(aAccOrElmOrID);
     if (!elm) {
       ok(false, "Can't get DOM element for " + aAccOrElmOrID);
@@ -308,19 +308,18 @@ function getAccessible(aAccOrElmOrID, aI
 }
 
 /**
  * Return true if the given identifier has an accessible, or exposes the wanted
  * interfaces.
  */
 function isAccessible(aAccOrElmOrID, aInterfaces)
 {
-  return getAccessible(aAccOrElmOrID, aInterfaces, null,
-                       DONOTFAIL_IF_NO_ACC | DONOTFAIL_IF_NO_INTERFACE) ?
-    true : false;
+  return !!getAccessible(aAccOrElmOrID, aInterfaces, null,
+                         DONOTFAIL_IF_NO_ACC | DONOTFAIL_IF_NO_INTERFACE);
 }
 
 /**
  * Return an accessible that contains the DOM node for the given identifier.
  */
 function getContainerAccessible(aAccOrElmOrID)
 {
   var node = getNode(aAccOrElmOrID);
@@ -546,17 +545,17 @@ function testAccessibleTree(aAccOrElmOrI
 
         // nsIAccessible::parent
         var parent = null;
         try { parent = child.parent; } catch (e) {}
         is(parent, acc, "Wrong parent of " + prettyName(child));
 
         // nsIAccessible::indexInParent
         var indexInParent = -1;
-        try { indexInParent = child.indexInParent; } catch(e) {}
+        try { indexInParent = child.indexInParent; } catch (e) {}
         is(indexInParent, i,
            "Wrong index in parent of " + prettyName(child));
 
         // nsIAccessible::nextSibling
         var expectedNextSibling = (i < childCount - 1) ?
           children.queryElementAt(i + 1, nsIAccessible) : null;
         var nextSibling = null;
         try { nextSibling = child.nextSibling; } catch (e) {}
@@ -579,17 +578,17 @@ function testAccessibleTree(aAccOrElmOrI
 }
 
 /**
  * Return true if accessible for the given node is in cache.
  */
 function isAccessibleInCache(aNodeOrId)
 {
   var node = getNode(aNodeOrId);
-  return gAccService.getAccessibleFromCache(node) ? true : false;
+  return !!gAccService.getAccessibleFromCache(node);
 }
 
 /**
  * Test accessible tree for defunct accessible.
  *
  * @param  aAcc       [in] the defunct accessible
  * @param  aNodeOrId  [in] the DOM node identifier for the defunct accessible
  */
--- a/accessible/tests/mochitest/elm/a11y.ini
+++ b/accessible/tests/mochitest/elm/a11y.ini
@@ -9,8 +9,9 @@ skip-if = buildapp == 'mulet'
 [test_figure.html]
 [test_listbox.xul]
 [test_MathMLSpec.html]
 [test_nsApplicationAcc.html]
 [test_plugin.html]
 skip-if = buildapp == 'mulet'
 [test_canvas.html]
 [test_shadowroot.html]
+skip-if = stylo # bug 1293844
--- a/accessible/tests/mochitest/elm/test_HTMLSpec.html
+++ b/accessible/tests/mochitest/elm/test_HTMLSpec.html
@@ -106,17 +106,17 @@
         absentStates: STATE_LINKED,
         children: []
       };
       testElm(getAccessible("imgmap").lastChild, obj);
 
       //////////////////////////////////////////////////////////////////////////
       // HTML:article
       obj = {
-        role: ROLE_DOCUMENT,
+        role: ROLE_ARTICLE,
         states: STATE_READONLY,
         interfaces: [ nsIAccessibleText, nsIAccessibleHyperText ],
       };
       testElm("article", obj);
 
       //////////////////////////////////////////////////////////////////////////
       // HTML:aside
       obj = {
@@ -301,18 +301,18 @@
         ]
       };
       testElm("code_container", obj);
 
       //////////////////////////////////////////////////////////////////////////
       // HTML:col and HTML:colgroup under table
 
       obj =
-        { TABLE : [
-          { ROW :[
+        { TABLE: [
+          { ROW: [
             { role: ROLE_CELL },
             { role: ROLE_CELL },
             { role: ROLE_CELL }
           ] }
         ] };
       testElm("colNcolgroup_table", obj);
 
       //////////////////////////////////////////////////////////////////////////
@@ -854,17 +854,17 @@
       //////////////////////////////////////////////////////////////////////////
       // HTML:keygen
 
       obj = {
         role: ROLE_COMBOBOX,
         states: STATE_COLLAPSED | STATE_HASPOPUP,
         extraStates: EXT_STATE_EXPANDABLE,
         actions: "open",
-        children: [ 
+        children: [
           { COMBOBOX_LIST: [
             { role: ROLE_COMBOBOX_OPTION }, // high grade
             { role: ROLE_COMBOBOX_OPTION } // medium grade
           ] }
         ]
       };
       testElm("keygen", obj);
 
@@ -1267,17 +1267,17 @@
 
       //////////////////////////////////////////////////////////////////////////
       // HTML:u contained by paragraph
 
       obj = {
         role: ROLE_PARAGRAPH,
         textAttrs: {
           0: { },
-          6: { "text-underline-style" : "solid" }
+          6: { "text-underline-style": "solid" }
         },
         children: [
           { role: ROLE_TEXT_LEAF }, // plain text
           { role: ROLE_TEXT_LEAF } // HTML:u text
         ]
       };
       testElm("u_container", obj);
 
--- a/accessible/tests/mochitest/elm/test_figure.html
+++ b/accessible/tests/mochitest/elm/test_figure.html
@@ -28,17 +28,17 @@
 
       todo(false, "figure name gets extra whitespace in the end!");
       testName("figure", "figure caption ");
       testName("figcaption", null);
 
       testRelation("figure", RELATION_LABELLED_BY, "figcaption");
       testRelation("figcaption", RELATION_LABEL_FOR, "figure");
 
-      testAttrs("figure", {"xml-roles" : "figure"}, true);
+      testAttrs("figure", {"xml-roles": "figure"}, true);
 
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
--- a/accessible/tests/mochitest/elm/test_nsApplicationAcc.html
+++ b/accessible/tests/mochitest/elm/test_nsApplicationAcc.html
@@ -32,23 +32,23 @@
 
       // nsIAccessible::name
       var applicationName = "";
       if (LINUX || SOLARIS) {
         applicationName = appInfo.name;
       } else {
         try {
           applicationName = brandBundle.GetStringFromName("brandShortName");
-        } catch(e) {
+        } catch (e) {
         }
 
         if (applicationName == "")
           applicationName = "Gecko based application";
       }
-      is (accessible.name, applicationName, "wrong application accessible name");
+      is(accessible.name, applicationName, "wrong application accessible name");
 
       // nsIAccessibleApplication
       is(accessible.appName, appInfo.name, "Wrong application name");
       is(accessible.appVersion, appInfo.version, "Wrong application version");
       is(accessible.platformName, "Gecko", "Wrong platform name");
       is(accessible.platformVersion, appInfo.platformVersion,
          "Wrong platform version");
 
--- a/accessible/tests/mochitest/events/a11y.ini
+++ b/accessible/tests/mochitest/events/a11y.ini
@@ -15,30 +15,26 @@ support-files =
 [test_bug1322593.html]
 [test_bug1322593-2.html]
 [test_caretmove.html]
 [test_caretmove.xul]
 [test_coalescence.html]
 [test_contextmenu.html]
 [test_descrchange.html]
 [test_docload.html]
-[test_docload.xul]
-skip-if = buildapp == 'mulet'
 [test_docload_aria.html]
 [test_dragndrop.html]
 [test_flush.html]
 [test_focus_aria_activedescendant.html]
 [test_focus_autocomplete.xul]
 # Disabled on Linux and Windows due to frequent failures - bug 695019, bug 890795
 skip-if = os == 'win' || os == 'linux'
-[test_focus_browserui.xul]
 [test_focus_canvas.html]
 [test_focus_contextmenu.xul]
 [test_focus_controls.html]
-[test_focus_dialog.html]
 [test_focus_doc.html]
 [test_focus_general.html]
 [test_focus_general.xul]
 [test_focus_listcontrols.xul]
 [test_focus_menu.xul]
 [test_focus_name.html]
 [test_focus_selects.html]
 [test_focus_tabbox.xul]
--- a/accessible/tests/mochitest/events/test_aria_objattr.html
+++ b/accessible/tests/mochitest/events/test_aria_objattr.html
@@ -45,18 +45,18 @@
     function updateARIAHidden(aID, aIsDefined, aChildId)
     {
       this.__proto__ = new updateAttribute(aID, "aria-hidden",
                                            aIsDefined ? "true" : "false");
 
       this.finalCheck = function updateARIAHidden()
       {
         if (aIsDefined) {
-          testAttrs(aID, {"hidden" : "true"}, true);
-          testAttrs(aChildId, {"hidden" : "true"}, true);
+          testAttrs(aID, {"hidden": "true"}, true);
+          testAttrs(aChildId, {"hidden": "true"}, true);
         } else {
           testAbsentAttrs(aID, { "hidden": "true"});
           testAbsentAttrs(aChildId, { "hidden": "true"});
         }
       }
     }
 
     // Debug stuff.
--- a/accessible/tests/mochitest/events/test_aria_statechange.html
+++ b/accessible/tests/mochitest/events/test_aria_statechange.html
@@ -63,16 +63,35 @@
       };
 
       this.getID = function busyify_getID()
       {
         return prettyName(aID) + " aria-busy changed to '" + aIsBusy + "'";
       };
     }
 
+    function makeCurrent(aID, aIsCurrent, aValue)
+    {
+      this.DOMNode = getNode(aID);
+
+      this.eventSeq = [
+        new stateChangeChecker(EXT_STATE_CURRENT, true, aIsCurrent, this.DOMNode)
+      ];
+
+      this.invoke = function makeCurrent_invoke()
+      {
+        this.DOMNode.setAttribute("aria-current", aValue);
+      };
+
+      this.getID = function makeCurrent_getID()
+      {
+        return prettyName(aID) + " aria-current changed to " + aValue;
+      };
+    }
+
     function setAttrOfMixedType(aID, aAttr, aState, aValue)
     {
       this.DOMNode = getNode(aID);
 
       this.eventSeq = [
         new stateChangeChecker(aState, kOrdinalState,
                                aValue == "true", this.DOMNode)
       ];
@@ -143,16 +162,22 @@
       gQueue.push(new busyify("aria_doc", true));
       gQueue.push(new busyify("aria_doc", false));
 
       buildQueueForAttrOfMixedType(gQueue, "pressable", setPressed);
       buildQueueForAttrOfMixedType(gQueue, "pressable_native", setPressed);
       buildQueueForAttrOfMixedType(gQueue, "checkable", setChecked);
       buildQueueForAttrOfBoolType(gQueue, "checkableBool", setChecked);
 
+      gQueue.push(new makeCurrent("current_page_1", false, "false"));
+      gQueue.push(new makeCurrent("current_page_2", true, "page"));
+      gQueue.push(new makeCurrent("current_page_2", false, "false"));
+      gQueue.push(new makeCurrent("current_page_3", true, "true"));
+      gQueue.push(new makeCurrent("current_page_3", false, ""));
+
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTests);
   </script>
 </head>
 
@@ -178,16 +203,21 @@
      title="Pressed state is not exposed on a button element with aria-pressed attribute">
     Mozilla Bug 989958
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=1136563"
      title="Support ARIA 1.1 switch role">
     Mozilla Bug 1136563
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=1355921"
+     title="Elements with a defined, non-false value for aria-current should expose ATK_STATE_ACTIVE">
+    Mozilla Bug 1355921
+  </a>
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
   <div id="eventdump"></div>
 
   <!-- aria-expanded -->
@@ -199,10 +229,15 @@
 
   <!-- aria-pressed -->
   <div id="pressable" role="button"></div>
   <button id="pressable_native"></button>
 
   <!-- aria-checked -->
   <div id="checkable" role="checkbox"></div>
   <div id="checkableBool" role="switch"></div>
+
+  <!-- aria-current -->
+  <div id="current_page_1" role="link" aria-current="page">1</div>
+  <div id="current_page_2" role="link" aria-current="false">2</div>
+  <div id="current_page_3" role="link">3</div>
 </body>
 </html>
deleted file mode 100644
--- a/accessible/tests/mochitest/events/test_docload.xul
+++ /dev/null
@@ -1,243 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
-                 type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        title="Accessibility Loading Document Events Test.">
-
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
-
-  <script type="application/javascript"
-          src="../common.js"></script>
-  <script type="application/javascript"
-          src="../role.js"></script>
-  <script type="application/javascript"
-          src="../states.js"></script>
-  <script type="application/javascript"
-          src="../events.js"></script>
-  <script type="application/javascript"
-          src="../browser.js"></script>
-
-  <script type="application/javascript">
-  <![CDATA[
-    ////////////////////////////////////////////////////////////////////////////
-    // Invoker checkers.
-    function stateBusyChecker(aIsEnabled)
-    {
-      this.type = EVENT_STATE_CHANGE;
-      this.__defineGetter__("target", currentTabDocument);
-
-      this.check = function stateBusyChecker_check(aEvent)
-      {
-        var event = null;
-        try {
-          var event = aEvent.QueryInterface(nsIAccessibleStateChangeEvent);
-        } catch (e) {
-          ok(false, "State change event was expected");
-        }
-
-        if (!event)
-          return;
-
-        is(event.state, STATE_BUSY, "Wrong state of statechange event.");
-        is(event.isEnabled, aIsEnabled,
-           "Wrong value of state of statechange event");
-
-        testStates(event.accessible, (aIsEnabled ? STATE_BUSY : 0), 0,
-                   (aIsEnabled ? 0 : STATE_BUSY), 0);
-      }
-    }
-
-    function documentReloadChecker(aIsFromUserInput)
-    {
-      this.type = EVENT_DOCUMENT_RELOAD;
-      this.__defineGetter__("target", currentTabDocument);
-
-      this.check = function documentReloadChecker_check(aEvent)
-      {
-        is(aEvent.isFromUserInput, aIsFromUserInput,
-           "Wrong value of isFromUserInput");
-      }
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    // Invokers.
-
-    /**
-     * Load URI.
-     */
-    function loadURIInvoker(aURI)
-    {
-      this.invoke = function loadURIInvoker_invoke()
-      {
-        tabBrowser().loadURI(aURI);
-      }
-
-      this.eventSeq = [
-        // We don't expect state change event for busy true since things happen
-        // quickly and it's coalesced.
-        new asyncInvokerChecker(EVENT_REORDER, currentBrowser),
-        new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, currentTabDocument),
-        new stateBusyChecker(false)
-      ];
-
-      this.getID = function loadURIInvoker_getID()
-      {
-        return "load uri " + aURI;
-      }
-    }
-
-    /**
-     * Load the document having sub document. No document loading events for
-     * nested document.
-     */
-    function loadNestedDocURIInvoker(aNestedDocURI)
-    {
-      this.__proto__ = new loadURIInvoker(aNestedDocURI);
-
-      // Remove reorder event checker since the event is likely coalesced by
-      // reorder event on Firefox UI (refer to bug 759670 for details).
-      this.eventSeq.shift();
-
-      this.unexpectedEventSeq = [
-        new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, getNestedDoc),
-        new invokerChecker(EVENT_STATE_CHANGE, getNestedDoc)
-      ];
-
-      function getNestedDoc()
-      {
-        var iframeNodes = currentTabDocument().getElementsByTagName("iframe");
-        return iframeNodes && iframeNodes.length > 0 ?
-          iframeNodes[0].firstChild : null;
-      }
-    }
-
-    /**
-     * Reload the page by F5 (isFromUserInput flag is true).
-     */
-    function userReloadInvoker()
-    {
-      this.invoke = function userReloadInvoker_invoke()
-      {
-        synthesizeKey("VK_F5", {}, browserWindow());
-      }
-
-      this.eventSeq = [
-        new documentReloadChecker(true),
-        new asyncInvokerChecker(EVENT_REORDER, currentBrowser),
-        new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, currentTabDocument),
-        new stateBusyChecker(false)
-      ];
-
-      this.getID = function userReloadInvoker_getID()
-      {
-        return "user reload page";
-      }
-    }
-
-    /**
-     * Reload the page (isFromUserInput flag is false).
-     */
-    function reloadInvoker()
-    {
-      this.invoke = function reloadInvoker_invoke()
-      {
-        tabBrowser().reload();
-      }
-
-      this.eventSeq = [
-        new documentReloadChecker(false),
-        new asyncInvokerChecker(EVENT_REORDER, currentBrowser),
-        new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, currentTabDocument),
-        new stateBusyChecker(false)
-      ];
-
-      this.getID = function reloadInvoker_getID()
-      {
-        return "reload page";
-      }
-    }
-
-    /**
-     * Load wrong URI what results in error page loading.
-     */
-    function loadErrorPageInvoker(aURL, aURLDescr)
-    {
-      this.invoke = function loadErrorPageInvoker_invoke()
-      {
-        tabBrowser().loadURI(aURL);
-      }
-
-      this.eventSeq = [
-        // We don't expect state change for busy true, load stopped events since
-        // things happen quickly and it's coalesced.
-        new asyncInvokerChecker(EVENT_REORDER, currentBrowser),
-        new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, currentTabDocument),
-        new stateBusyChecker(false)
-      ];
-
-      this.getID = function loadErrorPageInvoker_getID()
-      {
-        return "load error page: '" + aURLDescr + "'";
-      }
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    // Tests
-
-    //gA11yEventDumpToConsole = true; // debug
-    //gA11yEventDumpFeature = "parentchain:reorder";
-
-    var gQueue = null;
-    function doTests()
-    {
-      gQueue = new eventQueue();
-
-      var dataURL =
-        "data:text/html,<html><body><iframe src='http://example.com'></iframe></body></html>";
-      gQueue.push(new loadNestedDocURIInvoker(dataURL));
-
-      gQueue.push(new loadURIInvoker("about:"));
-      gQueue.push(new userReloadInvoker());
-      gQueue.push(new loadURIInvoker("about:mozilla"));
-      gQueue.push(new reloadInvoker());
-      gQueue.push(new loadErrorPageInvoker("www.wronguri.wronguri",
-                                           "Server not found"));
-      gQueue.push(new loadErrorPageInvoker("https://nocert.example.com:443",
-                                          "Untrusted Connection"));
-
-      gQueue.onFinish = function() { closeBrowserWindow(); }
-      gQueue.invoke();
-    }
-
-    SimpleTest.waitForExplicitFinish();
-    openBrowserWindow(doTests);
-  ]]>
-  </script>
-
-  <vbox flex="1" style="overflow: auto;">
-  <body xmlns="http://www.w3.org/1999/xhtml">
-    <a target="_blank"
-       href="https://bugzilla.mozilla.org/show_bug.cgi?id=566103"
-       title=" reorganize accessible document handling">
-      Mozilla Bug 566103
-    </a>
-    <a target="_blank"
-       href="https://bugzilla.mozilla.org/show_bug.cgi?id=754165"
-       title="Fire document load events on iframes too">
-      Mozilla Bug 754165
-    </a>
-    <p id="display"></p>
-    <div id="content" style="display: none">
-    </div>
-    <pre id="test">
-    </pre>
-  </body>
-
-  <vbox id="eventdump"></vbox>
-  </vbox>
-</window>
--- a/accessible/tests/mochitest/events/test_dragndrop.html
+++ b/accessible/tests/mochitest/events/test_dragndrop.html
@@ -31,17 +31,17 @@
 
       this.invoke = function changeGrabbed_invoke() {
         if (aGrabValue != undefined) {
           this.DOMNode.setAttribute("aria-grabbed", aGrabValue);
         }
       }
 
       this.check = function changeGrabbed_check() {
-        testAttrs(aNodeOrID, {"grabbed" : aGrabValue}, true);
+        testAttrs(aNodeOrID, {"grabbed": aGrabValue}, true);
       }
 
       this.getID = function changeGrabbed_getID() {
         return prettyName(aNodeOrID) + " aria-grabbed changed";
       }
     }
 
     // aria dropeffect invoker
@@ -51,17 +51,17 @@
 
       this.invoke = function changeDropeffect_invoke() {
         if (aDropeffectValue != undefined) {
           this.DOMNode.setAttribute("aria-dropeffect", aDropeffectValue);
         }
       }
 
       this.check = function changeDropeffect_check() {
-        testAttrs(aNodeOrID, {"dropeffect" : aDropeffectValue}, true);
+        testAttrs(aNodeOrID, {"dropeffect": aDropeffectValue}, true);
       }
 
       this.getID = function changeDropeffect_getID() {
         return prettyName(aNodeOrID) + " aria-dropeffect changed";
       }
     }
 
     function doTests()
deleted file mode 100644
--- a/accessible/tests/mochitest/events/test_focus_browserui.xul
+++ /dev/null
@@ -1,149 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
-                 type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        title="Accessibility Loading Document Events Test.">
-
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
-
-  <script type="application/javascript"
-          src="../common.js"></script>
-  <script type="application/javascript"
-          src="../role.js"></script>
-  <script type="application/javascript"
-          src="../states.js"></script>
-  <script type="application/javascript"
-          src="../events.js"></script>
-  <script type="application/javascript"
-          src="../browser.js"></script>
-
-  <script type="application/javascript">
-  <![CDATA[
-    ////////////////////////////////////////////////////////////////////////////
-    // Helpers
-
-    function inputInDocument()
-    {
-      var tabdoc = currentTabDocument();
-      return tabdoc.getElementById("input");
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    // Invokers
-
-    function loadURI(aURI)
-    {
-      this.invoke = function loadURI_invoke()
-      {
-        tabBrowser().loadURI(aURI);
-      }
-
-      this.eventSeq = [
-        new focusChecker(currentTabDocument)
-      ];
-
-      this.getID = function loadURI_getID()
-      {
-        return "load uri " + aURI;
-      }
-    }
-
-    function goBack()
-    {
-      this.invoke = function goBack_invoke()
-      {
-        tabBrowser().goBack();
-      }
-
-      this.eventSeq = [
-        new focusChecker(inputInDocument)
-      ];
-
-      this.getID = function goBack_getID()
-      {
-        return "go back one page in history ";
-      }
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    // Testing
-
-    var gInputDocURI = "data:text/html,<html><input id='input'></html>";
-    var gButtonDocURI = "data:text/html,<html><input id='input' type='button' value='button'></html>";
-
-    //gA11yEventDumpToConsole = true; // debug
-
-    var gQueue = null;
-    function doTests()
-    {
-      gQueue = new eventQueue();
-
-      var tabDocument = currentTabDocument();
-      var input = inputInDocument();
-
-      // move focus to input inside tab document
-      gQueue.push(new synthTab(tabDocument, new focusChecker(input),
-                               browserWindow()));
-
-      // open new url, focus moves to new document
-      gQueue.push(new loadURI(gButtonDocURI));
-
-      // back one page in history, moves moves on input of tab document
-      gQueue.push(new goBack());
-
-      // open new tab, focus moves to urlbar
-      gQueue.push(new synthKey(tabDocument, "t", { accelKey: true, window: browserWindow() },
-                               new focusChecker(urlbarInput)));
-
-      // close open tab, focus goes on input of tab document
-      gQueue.push(new synthKey(tabDocument, "w", { accelKey: true, window: browserWindow() },
-                               new focusChecker(inputInDocument)));
-
-      gQueue.onFinish = function()
-      {
-        closeBrowserWindow();
-      }
-      gQueue.invoke();
-    }
-
-    if (navigator.oscpu.startsWith("Windows NT 6.1") || navigator.oscpu.startsWith("Windows NT 6.2")) {
-      todo(false, "fix the leak!");
-      } else {
-      SimpleTest.waitForExplicitFinish();
-      openBrowserWindow(doTests, gInputDocURI);
-    }
-  ]]>
-  </script>
-
-  <vbox flex="1" style="overflow: auto;">
-  <body xmlns="http://www.w3.org/1999/xhtml">
-    <a target="_blank"
-       href="https://bugzilla.mozilla.org/show_bug.cgi?id=644452"
-       title="Focus not set when switching to cached document with back or forward if anything other than the document was last focused">
-      Mozilla Bug 644452
-    </a>
-    <a target="_blank"
-       href="https://bugzilla.mozilla.org/show_bug.cgi?id=665412"
-       title="Broken focus when returning to editable text field after closing a tab while focused in the Navigation toolbar">
-      Mozilla Bug 665412
-    </a>
-    <a target="_blank"
-       href="https://bugzilla.mozilla.org/show_bug.cgi?id=673958"
-       title="Rework accessible focus handling">
-      Mozilla Bug 673958
-    </a>
-    <p id="display"></p>
-    <div id="content" style="display: none">
-    </div>
-    <pre id="test">
-    </pre>
-  </body>
-
-  <vbox id="eventdump"></vbox>
-  </vbox>
-</window>
deleted file mode 100644
--- a/accessible/tests/mochitest/events/test_focus_dialog.html
+++ /dev/null
@@ -1,164 +0,0 @@
-<html>
-
-<head>
-  <title>Accessible focus testing</title>
-
-  <link rel="stylesheet" type="text/css"
-        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
-
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
-
-  <script type="application/javascript"
-          src="../common.js"></script>
-  <script type="application/javascript"
-          src="../events.js"></script>
-  <script type="application/javascript"
-          src="../role.js"></script>
-  <script type="application/javascript"
-          src="../states.js"></script>
-
-  <script type="application/javascript">
-    function openCloseDialog(aID)
-    {
-      this.eventSeq = [
-        new focusChecker(getNode(aID))
-      ];
-
-      this.invoke = function openCloseDialog_invoke()
-      {
-        var wnd = window.open("focus.html");
-        wnd.close();
-      }
-
-      this.getID = function openCloseDialog_getID()
-      {
-        return "Open close dialog while focus on " + prettyName(aID);
-      }
-    }
-
-    var gDialogWnd = null;
-    function getDialogDocument()
-    {
-      return gDialogWnd.document;
-    }
-
-    function openDialog(aID)
-    {
-      this.eventSeq = [
-        new focusChecker(getDialogDocument)
-      ];
-
-      this.invoke = function openDialog_invoke()
-      {
-        gDialogWnd = window.open("focus.html");
-      }
-
-      this.getID = function openDialog_getID()
-      {
-        return "Open dialog while focus on " + prettyName(aID);
-      }
-    }
-
-    function closeDialog(aID)
-    {
-      this.eventSeq = [
-        new focusChecker(aID)
-      ];
-
-      this.invoke = function closeDialog_invoke()
-      {
-        gDialogWnd.close();
-      }
-
-      this.getID = function closeDialog_getID()
-      {
-        return "Close dialog while focus on " + prettyName(aID);
-      }
-    }
-
-    function showNFocusAlertDialog()
-    {
-      this.ID = "alertdialog";
-      this.DOMNode = getNode(this.ID);
-
-      this.invoke = function showNFocusAlertDialog_invoke()
-      {
-        document.getElementById(this.ID).style.display = 'block';
-        document.getElementById(this.ID).focus();
-      }
-
-      this.eventSeq = [
-        new invokerChecker(EVENT_SHOW, this.DOMNode),
-        new focusChecker(this.DOMNode)
-      ];
-
-      this.getID = function showNFocusAlertDialog_getID()
-      {
-        return "Show and focus alert dialog " + prettyName(this.ID);
-      }
-    }
-
-    /**
-     * Do tests.
-     */
-
-    //gA11yEventDumpID = "eventdump"; // debug stuff
-    //gA11yEventDumpToConsole = true;
-
-    var gQueue = null;
-
-    function doTests()
-    {
-      gQueue = new eventQueue(EVENT_FOCUS);
-
-      gQueue.push(new synthFocus("button"));
-      gQueue.push(new openDialog("button"));
-      gQueue.push(new closeDialog("button"));
-
-      var frameNode = getNode("editabledoc");
-      gQueue.push(new synthFocusOnFrame(frameNode));
-      gQueue.push(new openCloseDialog(frameNode.contentDocument));
-
-      gQueue.push(new showNFocusAlertDialog());
-
-      gQueue.invoke(); // Will call SimpleTest.finish();
-    }
-
-    SimpleTest.waitForExplicitFinish();
-    addA11yLoadEvent(doTests);
-  </script>
-</head>
-
-<body>
-
-  <a target="_blank"
-     href="https://bugzilla.mozilla.org/show_bug.cgi?id=551679"
-     title="focus is not fired for focused document when switching between windows">
-    Mozilla Bug 551679
-  </a>
-  <a target="_blank"
-     href="https://bugzilla.mozilla.org/show_bug.cgi?id=580464"
-     title="Accessible focus incorrect after JS focus() but correct after switching apps or using menu bar">
-    Mozilla Bug 580464
-  </a>
-  <p id="display"></p>
-  <div id="content" style="display: none"></div>
-  <pre id="test">
-  </pre>
-
-  <button id="button">button</button>
-  <iframe id="editabledoc" src="focus.html"></iframe>
-
-  <div id="alertdialog" style="display: none" tabindex="-1" role="alertdialog" aria-labelledby="title2" aria-describedby="desc2">
-    <div id="title2">Blah blah</div>
-    <div id="desc2">Woof woof woof.</div>
-    <button>Close</button>
-  </div>
-
-
-  <div id="eventdump"></div>
-</body>
-</html>
--- a/accessible/tests/mochitest/events/test_textselchange.html
+++ b/accessible/tests/mochitest/events/test_textselchange.html
@@ -22,17 +22,17 @@
     var gQueue = null;
 
     // gA11yEventDumpID = "eventdump"; // debug stuff
     //gA11yEventDumpToConsole = true;
 
     function getOnclickSeq(aID)
     {
       return [
-        new caretMoveChecker(0, aID), 
+        new caretMoveChecker(0, aID),
         new unexpectedInvokerChecker(EVENT_TEXT_SELECTION_CHANGED, aID)
       ];
     }
 
     function doTests()
     {
       // test caret move events and caret offsets
       gQueue = new eventQueue();
--- a/accessible/tests/mochitest/events/test_valuechange.html
+++ b/accessible/tests/mochitest/events/test_valuechange.html
@@ -35,28 +35,28 @@
         ];
 
       this.invoke = function changeARIAValue_invoke() {
 
         // Note: this should not fire an EVENT_VALUE_CHANGE when aria-valuetext
         // is not empty
         if (aValuenow != undefined)
           this.DOMNode.setAttribute("aria-valuenow", aValuenow);
- 
+
         // Note: this should always fire an EVENT_VALUE_CHANGE
         if (aValuetext != undefined)
           this.DOMNode.setAttribute("aria-valuetext", aValuetext);
       }
 
       this.check = function changeARIAValue_check() {
         var acc = getAccessible(aNodeOrID, [nsIAccessibleValue]);
         if (!acc)
           return;
 
-        // Note: always test against valuetext first because the existence of 
+        // Note: always test against valuetext first because the existence of
         // aria-valuetext takes precedence over aria-valuenow in gecko.
         is(acc.value, (aValuetext != undefined)? aValuetext : aValuenow,
             "Wrong value of " + prettyName(aNodeOrID));
       }
 
       this.getID = function changeARIAValue_getID() {
         return prettyName(aNodeOrID) + " value changed";
       }
@@ -156,26 +156,32 @@
     //gA11yEventDumpToConsole = true;
     function doTests()
     {
       // Test initial values
       testValue("slider_vn", "5", 5, 0, 1000, 0);
       testValue("slider_vnvt", "plain", 0, 0, 5, 0);
       testValue("slider_vt", "hi", 0, 0, 3, 0);
       testValue("scrollbar", "5", 5, 0, 1000, 0);
+      testValue("splitter", "5", 5, 0, 1000, 0);
       testValue("progress", "22%", 22, 0, 100, 0);
       testValue("range", "6", 6, 0, 10, 1);
 
+      // Test that elements which should not expose values do not
+      var accSeparator = getAccessible("separator", [nsIAccessibleValue], null, DONOTFAIL_IF_NO_INTERFACE);
+      ok(!accSeparator, "value interface is not exposed for separator");
+
       // Test value change events
       gQueue = new eventQueue();
 
       gQueue.push(new changeARIAValue("slider_vn", "6", undefined));
       gQueue.push(new changeARIAValue("slider_vt", undefined, "hey!"));
       gQueue.push(new changeARIAValue("slider_vnvt", "3", "sweet"));
       gQueue.push(new changeARIAValue("scrollbar", "6", undefined));
+      gQueue.push(new changeARIAValue("splitter", "6", undefined));
 
       gQueue.push(new changeValue("combobox", "hello"));
 
       gQueue.push(new changeProgressValue("progress", "50"));
       gQueue.push(new changeRangeValue("range"));
 
       gQueue.push(new changeSelectValue("select", "VK_DOWN", "2nd"));
       gQueue.push(new changeSelectValue("select", "3", "3rd"));
@@ -232,16 +238,24 @@
 
   <div id="slider_vnvt" role="slider" aria-valuenow="0" aria-valuetext="plain"
        aria-valuemin="0" aria-valuemax="5">sweetness slider</div>
 
   <!-- ARIA scrollbar -->
   <div id="scrollbar" role="scrollbar" aria-valuenow="5"
        aria-valuemin="0" aria-valuemax="1000">slider</div>
 
+  <!-- ARIA separator which is focusable (i.e. a splitter) -->
+  <div id="splitter" role="separator" tabindex="0" aria-valuenow="5"
+       aria-valuemin="0" aria-valuemax="1000">splitter</div>
+
+  <!-- ARIA separator which is not focusable and should not expose values -->
+  <div id="separator" role="separator" aria-valuenow="5"
+       aria-valuemin="0" aria-valuemax="1000">splitter</div>
+
   <!-- ARIA combobox -->
   <input id="combobox" role="combobox" aria-autocomplete="inline">
 
   <!-- progress bar -->
   <progress id="progress" value="22" max="100"></progress>
 
   <!-- input@type="range" -->
   <input type="range" id="range" min="0" max="10" value="6">
--- a/accessible/tests/mochitest/focus/a11y.ini
+++ b/accessible/tests/mochitest/focus/a11y.ini
@@ -1,9 +1,9 @@
 [DEFAULT]
 support-files =
   !/accessible/tests/mochitest/*.js
 
 [test_focusedChild.html]
-skip-if = (os == 'win' && (os_version == '6.2' || os_version == '6.3')) # bug 845134
+skip-if = (os == 'win' && os_version != '6.1') # bug 845134
 [test_takeFocus.html]
 skip-if = buildapp == 'mulet'
 [test_takeFocus.xul]
--- a/accessible/tests/mochitest/grid.js
+++ b/accessible/tests/mochitest/grid.js
@@ -76,17 +76,17 @@ function grid(aTableIdentifier)
   }
 
   this.handleKeyEvent = function handleKeyEvent(aEvent)
   {
     if (aEvent.target.localName != "td")
       return;
 
     var cell = aEvent.target;
-    switch(aEvent.keyCode) {
+    switch (aEvent.keyCode) {
       case nsIDOMKeyEvent.DOM_VK_UP:
         var colsCount = this.getColsCount();
         var idx = this.getIndexByCell(cell);
         var upidx = idx - colsCount;
         if (upidx >= 0) {
           cell.removeAttribute("tabindex");
           var upcell = this.getCellAtIndex(upidx);
           upcell.setAttribute("tabindex", "0");
--- a/accessible/tests/mochitest/hittest/test_browser.html
+++ b/accessible/tests/mochitest/hittest/test_browser.html
@@ -25,27 +25,27 @@
       var tgtX = hitX + hitWidth / 2;
       var tgtY = hitY + hitHeight / 2;
 
       var rootAcc = getRootAccessible();
       var docAcc = getAccessible(document);
       var outerDocAcc = docAcc.parent;
 
       var hitAcc = rootAcc.getDeepestChildAtPoint(tgtX, tgtY);
-      is(hitAcc, hititem, "Hit match at " + tgtX + "," + tgtY + 
+      is(hitAcc, hititem, "Hit match at " + tgtX + "," + tgtY +
                           ". Found: " + prettyName(hitAcc));
       var hitAcc2 = docAcc.getDeepestChildAtPoint(tgtX, tgtY);
-      is(hitAcc, hitAcc2, "Hit match at " + tgtX + "," + tgtY + 
+      is(hitAcc, hitAcc2, "Hit match at " + tgtX + "," + tgtY +
                           ". Found: " + prettyName(hitAcc2));
 
       hitAcc = outerDocAcc.getChildAtPoint(tgtX, tgtY);
-      is(hitAcc, docAcc, "Hit match at " + tgtX + "," + tgtY + 
+      is(hitAcc, docAcc, "Hit match at " + tgtX + "," + tgtY +
                          ". Found: " + prettyName(hitAcc));
       hitAcc = docAcc.getChildAtPoint(tgtX, tgtY);
-      is(hitAcc, hittest, "Hit match at " + tgtX + "," + tgtY + 
+      is(hitAcc, hittest, "Hit match at " + tgtX + "," + tgtY +
                           ". Found: " + prettyName(hitAcc));
 
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
--- a/accessible/tests/mochitest/hittest/test_shadowroot.html
+++ b/accessible/tests/mochitest/hittest/test_shadowroot.html
@@ -58,15 +58,16 @@
     // This routine adds the comment children of each 'component' to its
     // shadow root.
     var components = document.querySelectorAll('.components');
     for (var i = 0; i < components.length; i++) {
       var component = components[i];
       var shadow = component.createShadowRoot();
       for (var child = component.firstChild; child; child = child.nextSibling) {
         if (child.nodeType === 8)
+          // eslint-disable-next-line no-unsanitized/property
           shadow.innerHTML = child.data;
       }
     }
   </script>
 
 </body>
 </html>
--- a/accessible/tests/mochitest/jsat/output.js
+++ b/accessible/tests/mochitest/jsat/output.js
@@ -15,17 +15,17 @@ Cu.import("resource://gre/modules/access
  *                         output
  *
  * Note: if |aOldAccOrElmOrID| is not provided, the |aAccOrElmOrID| must be
  * scoped to the "root" element in markup.
  */
 function testContextOutput(expected, aAccOrElmOrID, aOldAccOrElmOrID, aGenerator) {
   var accessible = getAccessible(aAccOrElmOrID);
   var oldAccessible = aOldAccOrElmOrID !== null ?
-	getAccessible(aOldAccOrElmOrID || 'root') : null;
+    getAccessible(aOldAccOrElmOrID || 'root') : null;
   var context = new PivotContext(accessible, oldAccessible);
   var output = aGenerator.genForContext(context);
 
   // Create a version of the output that has null members where we have
   // null members in the expected output. Those are indexes that are not testable
   // because of the changing nature of the test (different window names), or strings
   // that are inaccessible to us, like the title of parent documents.
   var masked_output = [];
--- a/accessible/tests/mochitest/jsat/test_content_text.html
+++ b/accessible/tests/mochitest/jsat/test_content_text.html
@@ -120,17 +120,17 @@
            new ExpectedAnnouncement('navigating'),
            new ExpectedEditState({
             editing: false,
             multiline: false,
             atStart: true,
             atEnd: false })],
           [ContentMessages.simpleMoveNext,
            new ExpectedCursorChange(
-            [{ string : 'entry' }],
+            [{ string: 'entry' }],
             { focused: 'html'})],
           [ContentMessages.activateCurrent(0),
            new ExpectedClickAction(),
            new ExpectedAnnouncement('editing'),
            new ExpectedEditState({
             editing: true,
             multiline: false,
             atStart: true,
@@ -146,17 +146,17 @@
             editing: false,
             multiline: false,
             atStart: true,
             atEnd: false
            },{ focused: 'html' })
          ],
           [ContentMessages.simpleMoveNext,
            new ExpectedCursorChange(
-            [{ string : 'entry' }],
+            [{ string: 'entry' }],
             { focused: 'html'})],
           [ContentMessages.activateCurrent(0),
            new ExpectedClickAction(),
            new ExpectedAnnouncement('editing'),
            new ExpectedEditState({
             editing: true,
             multiline: false,
             atStart: true,
--- a/accessible/tests/mochitest/jsat/test_landmarks.html
+++ b/accessible/tests/mochitest/jsat/test_landmarks.html
@@ -57,21 +57,21 @@
         expectedUtterance: [
           [{"string": "footer"}, "a footer within an article"],
           ["a footer within an article", {"string": "footer"}]],
         expectedBraille: [
           [{"string": "footerAbbr"}, "a footer within an article"],
           ["a footer within an article", {"string": "footerAbbr"}]]
       }, {
         accOrElmOrID: "section_header",
-        expectedUtterance: [[{"string":"header"}, "a header within a section"],
-                            ["a header within a section", {"string":"header"}]],
+        expectedUtterance: [[{"string": "header"}, "a header within a section"],
+                            ["a header within a section", {"string": "header"}]],
         expectedBraille: [
-          [{"string":"headerAbbr"}, "a header within a section"],
-          ["a header within a section", {"string":"headerAbbr"}]]
+          [{"string": "headerAbbr"}, "a header within a section"],
+          ["a header within a section", {"string": "headerAbbr"}]]
       }, {
         accOrElmOrID: "section_footer",
         expectedUtterance: [
           [{"string": "footer"}, "a footer within a section"],
           ["a footer within a section", {"string": "footer"}]],
         expectedBraille: [
           [{"string": "footerAbbr"}, "a footer within a section"],
           ["a footer within a section", {"string": "footerAbbr"}]]
--- a/accessible/tests/mochitest/jsat/test_output.html
+++ b/accessible/tests/mochitest/jsat/test_output.html
@@ -60,19 +60,19 @@ https://bugzilla.mozilla.org/show_bug.cg
           expectedUtterance: [[{"string": "headingLevel", "args": [1]},
             "Test heading"], ["Test heading",
             {"string": "headingLevel", "args": [1]}]],
           expectedBraille: [[{"string": "headingAbbr"}, "Test heading"],
                             ["Test heading", {"string": "headingAbbr"}]]
         }, {
           accOrElmOrID: "list",
           expectedUtterance: [[{"string": "list"},
-            {"string": "listItemsCount", "count":1}, {"string": "listStart"},
+            {"string": "listItemsCount", "count": 1}, {"string": "listStart"},
             "1.", "list one"], ["1.", "list one", {"string": "listStart"},
-            {"string": "list"}, {"string": "listItemsCount", "count":1}]
+            {"string": "list"}, {"string": "listItemsCount", "count": 1}]
           ],
           expectedBraille: [[{"string": "listAbbr"}, "list one"],
             ["list one", {"string": "listAbbr"}]]
         }, {
           accOrElmOrID: "dlist",
           expectedUtterance: [[{"string": "definitionlist"},
             {"string": "listItemsCount", "count": 0.5}, "dd one"], ["dd one",
             {"string": "definitionlist"},
@@ -94,32 +94,32 @@ https://bugzilla.mozilla.org/show_bug.cg
           expectedUtterance: [[{"string": "list"},
             {"string": "listItemsCount", "count": 1}, {"string": "listStart"},
             "list two"], ["list two", {"string": "listStart"},
             {"string": "list"}, {"string": "listItemsCount", "count": 1}]
           ],
           expectedBraille: [["*", "list two"], ["*", "list two"]]
         }, {
           accOrElmOrID: "cell",
-          expectedUtterance: [[{"string":"table"},
+          expectedUtterance: [[{"string": "table"},
             {"string": "tblColumnInfo", "count": 1},
             {"string": "tblRowInfo", "count": 1}, "Fruits and vegetables",
             {"string": "columnInfo", "args": [1]},
             {"string": "rowInfo", "args": [1]}, {"string": "list"},
             {"string": "listItemsCount", "count": 4}, {"string": "listStart"},
             {"string": "link"}, "Apples", {"string": "link"}, "Bananas",
             {"string": "link"}, "Peaches", {"string": "listEnd"},
             {"string": "link"}, "Plums"], ["Apples", {"string": "link"},
             {"string": "listStart"}, "Bananas", {"string": "link"}, "Peaches",
             {"string": "link"}, "Plums", {"string": "link"},
             {"string": "listEnd"}, {"string": "list"},
             {"string": "listItemsCount", "count": 4},
             {"string": "columnInfo", "args": [1]},
             {"string": "rowInfo", "args": [1]}, "Fruits and vegetables",
-            {"string":"table"}, {"string": "tblColumnInfo", "count": 1},
+            {"string": "table"}, {"string": "tblColumnInfo", "count": 1},
             {"string": "tblRowInfo", "count": 1}]],
           expectedBraille: [[{"string": "cellInfoAbbr", "args": [ 1, 1]},
             {"string": "listAbbr"}, {"string": "linkAbbr"}, "Apples",
             {"string": "linkAbbr"}, "Bananas", {"string": "linkAbbr"},
             "Peaches", {"string": "linkAbbr"}, "Plums"], ["Apples",
             {"string": "linkAbbr"}, "Bananas", {"string": "linkAbbr"},
             "Peaches", {"string": "linkAbbr"}, "Plums", {"string": "linkAbbr"},
             {"string": "listAbbr"},
@@ -404,19 +404,19 @@ https://bugzilla.mozilla.org/show_bug.cg
           expectedUtterance: [[{"string": "listboxoption"}, "555-12345"],
                               ["555-12345", {"string": "listboxoption"}]],
           expectedBraille: [[{"string": "listboxoptionAbbr"}, "555-12345"],
                             ["555-12345", {"string": "listboxoptionAbbr"}]]
         }, {
           accOrElmOrID: "columnheader",
           oldAccOrElmOrID: "grid",
           expectedUtterance: [[{"string": "columnInfo", "args": [1]},
-            {"string": "rowInfo", "args" :[1]}, "Sunday"], ["Sunday",
+            {"string": "rowInfo", "args": [1]}, "Sunday"], ["Sunday",
             {"string": "columnInfo", "args": [1]},
-            {"string": "rowInfo", "args" :[1]}]],
+            {"string": "rowInfo", "args": [1]}]],
           expectedBraille: [[{"string": "cellInfoAbbr", "args": [1, 1]},
             "Sunday"], ["Sunday", {"string": "cellInfoAbbr", "args": [1, 1]}]]
         }, {
           accOrElmOrID: "rowheader",
           oldAccOrElmOrID: "grid",
           expectedUtterance: [[{"string": "columnInfo", "args": [1]},
             {"string": "rowInfo", "args": [2]}, "Sunday", "Week 1"], ["Week 1",
             {"string": "columnInfo", "args": [1]},
--- a/accessible/tests/mochitest/jsat/test_output_mathml.html
+++ b/accessible/tests/mochitest/jsat/test_output_mathml.html
@@ -14,162 +14,162 @@
           src="jsatcommon.js"></script>
   <script type="application/javascript">
 
     function doTest() {
       // Test the following accOrElmOrID.
       var tests = [{
           accOrElmOrID: "math-1",
           expectedUtterance: [
-            [{"string":"open-fence"},"(","x",",","y",{"string":"close-fence"},")"],
-            ["(",{"string":"open-fence"},"x",",","y",")",{"string":"close-fence"}]
+            [{"string": "open-fence"},"(","x",",","y",{"string": "close-fence"},")"],
+            ["(",{"string": "open-fence"},"x",",","y",")",{"string": "close-fence"}]
           ],
           expectedBraille: [
-            [{"string":"open-fenceAbbr"},"(","x",",","y",{"string":"close-fenceAbbr"},")"],
-            ["(",{"string":"open-fenceAbbr"},"x",",","y",")",{"string":"close-fenceAbbr"}]
+            [{"string": "open-fenceAbbr"},"(","x",",","y",{"string": "close-fenceAbbr"},")"],
+            ["(",{"string": "open-fenceAbbr"},"x",",","y",")",{"string": "close-fenceAbbr"}]
           ]
         }, {
           accOrElmOrID: "mfrac-1",
           expectedUtterance: [
-            [{"string":"mathmlfraction"},{"string":"numerator"},"a",{"string":"denominator"},"b"],
-            ["a",{"string":"numerator"},"b",{"string":"denominator"},{"string":"mathmlfraction"}]
+            [{"string": "mathmlfraction"},{"string": "numerator"},"a",{"string": "denominator"},"b"],
+            ["a",{"string": "numerator"},"b",{"string": "denominator"},{"string": "mathmlfraction"}]
           ],
           expectedBraille: [
-            [{"string":"mathmlfractionAbbr"},{"string":"numeratorAbbr"},"a",{"string":"denominatorAbbr"},"b"],
-            ["a",{"string":"numeratorAbbr"},"b",{"string":"denominatorAbbr"},{"string":"mathmlfractionAbbr"}]
+            [{"string": "mathmlfractionAbbr"},{"string": "numeratorAbbr"},"a",{"string": "denominatorAbbr"},"b"],
+            ["a",{"string": "numeratorAbbr"},"b",{"string": "denominatorAbbr"},{"string": "mathmlfractionAbbr"}]
           ]
         }, {
           accOrElmOrID: "mfrac-2",
           expectedUtterance: [
-            [{"string":"mathmlfractionwithoutbar"},{"string":"numerator"},"a",{"string":"denominator"},"b"],
-            ["a",{"string":"numerator"},"b",{"string":"denominator"},{"string":"mathmlfractionwithoutbar"}]
+            [{"string": "mathmlfractionwithoutbar"},{"string": "numerator"},"a",{"string": "denominator"},"b"],
+            ["a",{"string": "numerator"},"b",{"string": "denominator"},{"string": "mathmlfractionwithoutbar"}]
           ],
           expectedBraille: [
-            [{"string":"mathmlfractionwithoutbarAbbr"},{"string":"numeratorAbbr"},"a",{"string":"denominatorAbbr"},"b"],
-            ["a",{"string":"numeratorAbbr"},"b",{"string":"denominatorAbbr"},{"string":"mathmlfractionwithoutbarAbbr"}]
+            [{"string": "mathmlfractionwithoutbarAbbr"},{"string": "numeratorAbbr"},"a",{"string": "denominatorAbbr"},"b"],
+            ["a",{"string": "numeratorAbbr"},"b",{"string": "denominatorAbbr"},{"string": "mathmlfractionwithoutbarAbbr"}]
           ]
         }, {
           accOrElmOrID: "msub-1",
           expectedUtterance: [
-            [{"string":"mathmlscripted"},{"string":"base"},"a",{"string":"subscript"},"b"],
-            ["a",{"string":"base"},"b",{"string":"subscript"},{"string":"mathmlscripted"}]
+            [{"string": "mathmlscripted"},{"string": "base"},"a",{"string": "subscript"},"b"],
+            ["a",{"string": "base"},"b",{"string": "subscript"},{"string": "mathmlscripted"}]
           ],
           expectedBraille: [
-            [{"string":"mathmlscriptedAbbr"},{"string":"baseAbbr"},"a",{"string":"subscriptAbbr"},"b"],
-            ["a",{"string":"baseAbbr"},"b",{"string":"subscriptAbbr"},{"string":"mathmlscriptedAbbr"}]
+            [{"string": "mathmlscriptedAbbr"},{"string": "baseAbbr"},"a",{"string": "subscriptAbbr"},"b"],
+            ["a",{"string": "baseAbbr"},"b",{"string": "subscriptAbbr"},{"string": "mathmlscriptedAbbr"}]
           ]
         }, {
           accOrElmOrID: "msup-1",
           expectedUtterance: [
-            [{"string":"mathmlscripted"},{"string":"base"},"a",{"string":"superscript"},"b"],
-            ["a",{"string":"base"},"b",{"string":"superscript"},{"string":"mathmlscripted"}]
+            [{"string": "mathmlscripted"},{"string": "base"},"a",{"string": "superscript"},"b"],
+            ["a",{"string": "base"},"b",{"string": "superscript"},{"string": "mathmlscripted"}]
           ],
           expectedBraille: [
-            [{"string":"mathmlscriptedAbbr"},{"string":"baseAbbr"},"a",{"string":"superscriptAbbr"},"b"],
-            ["a",{"string":"baseAbbr"},"b",{"string":"superscriptAbbr"},{"string":"mathmlscriptedAbbr"}]
+            [{"string": "mathmlscriptedAbbr"},{"string": "baseAbbr"},"a",{"string": "superscriptAbbr"},"b"],
+            ["a",{"string": "baseAbbr"},"b",{"string": "superscriptAbbr"},{"string": "mathmlscriptedAbbr"}]
           ]
         }, {
           accOrElmOrID: "msubsup-1",
           expectedUtterance: [
-            [{"string":"mathmlscripted"},{"string":"base"},"a",{"string":"subscript"},"b",{"string":"superscript"},"c"],
-            ["a",{"string":"base"},"b",{"string":"subscript"},"c",{"string":"superscript"},{"string":"mathmlscripted"}]
+            [{"string": "mathmlscripted"},{"string": "base"},"a",{"string": "subscript"},"b",{"string": "superscript"},"c"],
+            ["a",{"string": "base"},"b",{"string": "subscript"},"c",{"string": "superscript"},{"string": "mathmlscripted"}]
           ],
           expectedBraille: [
-            [{"string":"mathmlscriptedAbbr"},{"string":"baseAbbr"},"a",{"string":"subscriptAbbr"},"b",{"string":"superscriptAbbr"},"c"],
-            ["a",{"string":"baseAbbr"},"b",{"string":"subscriptAbbr"},"c",{"string":"superscriptAbbr"},{"string":"mathmlscriptedAbbr"}]
+            [{"string": "mathmlscriptedAbbr"},{"string": "baseAbbr"},"a",{"string": "subscriptAbbr"},"b",{"string": "superscriptAbbr"},"c"],
+            ["a",{"string": "baseAbbr"},"b",{"string": "subscriptAbbr"},"c",{"string": "superscriptAbbr"},{"string": "mathmlscriptedAbbr"}]
           ]
         }, {
           accOrElmOrID: "mmultiscripts-1",
           expectedUtterance: [
-            [{"string":"mathmlscripted"},{"string":"base"},"a",{"string":"subscript"},"b",{"string":"superscript"},"c",{"string":"superscript"},"d",{"string":"presubscript"},"e",{"string":"presubscript"},"f",{"string":"presuperscript"},"g"],
-            ["a",{"string":"base"},"b",{"string":"subscript"},"c",{"string":"superscript"},"d",{"string":"superscript"},"e",{"string":"presubscript"},"f",{"string":"presubscript"},"g",{"string":"presuperscript"},{"string":"mathmlscripted"}]
+            [{"string": "mathmlscripted"},{"string": "base"},"a",{"string": "subscript"},"b",{"string": "superscript"},"c",{"string": "superscript"},"d",{"string": "presubscript"},"e",{"string": "presubscript"},"f",{"string": "presuperscript"},"g"],
+            ["a",{"string": "base"},"b",{"string": "subscript"},"c",{"string": "superscript"},"d",{"string": "superscript"},"e",{"string": "presubscript"},"f",{"string": "presubscript"},"g",{"string": "presuperscript"},{"string": "mathmlscripted"}]
           ],
           expectedBraille: [
-            [{"string":"mathmlscriptedAbbr"},{"string":"baseAbbr"},"a",{"string":"subscriptAbbr"},"b",{"string":"superscriptAbbr"},"c",{"string":"superscriptAbbr"},"d",{"string":"presubscriptAbbr"},"e",{"string":"presubscriptAbbr"},"f",{"string":"presuperscriptAbbr"},"g"],
-            ["a",{"string":"baseAbbr"},"b",{"string":"subscriptAbbr"},"c",{"string":"superscriptAbbr"},"d",{"string":"superscriptAbbr"},"e",{"string":"presubscriptAbbr"},"f",{"string":"presubscriptAbbr"},"g",{"string":"presuperscriptAbbr"},{"string":"mathmlscriptedAbbr"}]
+            [{"string": "mathmlscriptedAbbr"},{"string": "baseAbbr"},"a",{"string": "subscriptAbbr"},"b",{"string": "superscriptAbbr"},"c",{"string": "superscriptAbbr"},"d",{"string": "presubscriptAbbr"},"e",{"string": "presubscriptAbbr"},"f",{"string": "presuperscriptAbbr"},"g"],
+            ["a",{"string": "baseAbbr"},"b",{"string": "subscriptAbbr"},"c",{"string": "superscriptAbbr"},"d",{"string": "superscriptAbbr"},"e",{"string": "presubscriptAbbr"},"f",{"string": "presubscriptAbbr"},"g",{"string": "presuperscriptAbbr"},{"string": "mathmlscriptedAbbr"}]
           ]
         }, {
           accOrElmOrID: "munder-1",
           expectedUtterance: [
-            [{"string":"mathmlscripted"},{"string":"base"},"a",{"string":"underscript"},"b"],
-            ["a",{"string":"base"},"b",{"string":"underscript"},{"string":"mathmlscripted"}]
+            [{"string": "mathmlscripted"},{"string": "base"},"a",{"string": "underscript"},"b"],
+            ["a",{"string": "base"},"b",{"string": "underscript"},{"string": "mathmlscripted"}]
           ],
           expectedBraille: [
-            [{"string":"mathmlscriptedAbbr"},{"string":"baseAbbr"},"a",{"string":"underscriptAbbr"},"b"],
-            ["a",{"string":"baseAbbr"},"b",{"string":"underscriptAbbr"},{"string":"mathmlscriptedAbbr"}]
+            [{"string": "mathmlscriptedAbbr"},{"string": "baseAbbr"},"a",{"string": "underscriptAbbr"},"b"],
+            ["a",{"string": "baseAbbr"},"b",{"string": "underscriptAbbr"},{"string": "mathmlscriptedAbbr"}]
           ]
         }, {
           accOrElmOrID: "mover-1",
           expectedUtterance: [
-            [{"string":"mathmlscripted"},{"string":"base"},"a",{"string":"overscript"},"b"],
-            ["a",{"string":"base"},"b",{"string":"overscript"},{"string":"mathmlscripted"}]
+            [{"string": "mathmlscripted"},{"string": "base"},"a",{"string": "overscript"},"b"],
+            ["a",{"string": "base"},"b",{"string": "overscript"},{"string": "mathmlscripted"}]
           ],
           expectedBraille: [
-            [{"string":"mathmlscriptedAbbr"},{"string":"baseAbbr"},"a",{"string":"overscriptAbbr"},"b"],
-            ["a",{"string":"baseAbbr"},"b",{"string":"overscriptAbbr"},{"string":"mathmlscriptedAbbr"}]
+            [{"string": "mathmlscriptedAbbr"},{"string": "baseAbbr"},"a",{"string": "overscriptAbbr"},"b"],
+            ["a",{"string": "baseAbbr"},"b",{"string": "overscriptAbbr"},{"string": "mathmlscriptedAbbr"}]
           ]
         }, {
           accOrElmOrID: "munderover-1",
           expectedUtterance: [
-            [{"string":"mathmlscripted"},{"string":"base"},"a",{"string":"underscript"},"b",{"string":"overscript"},"c"],
-            ["a",{"string":"base"},"b",{"string":"underscript"},"c",{"string":"overscript"},{"string":"mathmlscripted"}]
+            [{"string": "mathmlscripted"},{"string": "base"},"a",{"string": "underscript"},"b",{"string": "overscript"},"c"],
+            ["a",{"string": "base"},"b",{"string": "underscript"},"c",{"string": "overscript"},{"string": "mathmlscripted"}]
           ],
           expectedBraille: [
-            [{"string":"mathmlscriptedAbbr"},{"string":"baseAbbr"},"a",{"string":"underscriptAbbr"},"b",{"string":"overscriptAbbr"},"c"],
-            ["a",{"string":"baseAbbr"},"b",{"string":"underscriptAbbr"},"c",{"string":"overscriptAbbr"},{"string":"mathmlscriptedAbbr"}]
+            [{"string": "mathmlscriptedAbbr"},{"string": "baseAbbr"},"a",{"string": "underscriptAbbr"},"b",{"string": "overscriptAbbr"},"c"],
+            ["a",{"string": "baseAbbr"},"b",{"string": "underscriptAbbr"},"c",{"string": "overscriptAbbr"},{"string": "mathmlscriptedAbbr"}]
           ]
         }, {
           accOrElmOrID: "mroot-1",
           expectedUtterance: [
-            [{"string":"mathmlroot"},{"string":"base"},"a",{"string":"root-index"},"b"],
-            ["a",{"string":"base"},"b",{"string":"root-index"},{"string":"mathmlroot"}]
+            [{"string": "mathmlroot"},{"string": "base"},"a",{"string": "root-index"},"b"],
+            ["a",{"string": "base"},"b",{"string": "root-index"},{"string": "mathmlroot"}]
           ],
           expectedBraille: [
-            [{"string":"mathmlrootAbbr"},{"string":"baseAbbr"},"a",{"string":"root-indexAbbr"},"b"],
-            ["a",{"string":"baseAbbr"},"b",{"string":"root-indexAbbr"},{"string":"mathmlrootAbbr"}]
+            [{"string": "mathmlrootAbbr"},{"string": "baseAbbr"},"a",{"string": "root-indexAbbr"},"b"],
+            ["a",{"string": "baseAbbr"},"b",{"string": "root-indexAbbr"},{"string": "mathmlrootAbbr"}]
           ]
         }, {
           accOrElmOrID: "mtable-1",
           expectedUtterance: [
-            [{"string":"mathmltable"},{"string":"tblColumnInfo","count":3},{"string":"tblRowInfo","count":2},{"string":"columnInfo","args":[1]},{"string":"rowInfo","args":[1]},"a",{"string":"columnInfo","args":[2]},{"string":"rowInfo","args":[1]},"b",{"string":"columnInfo","args":[3]},{"string":"rowInfo","args":[1]},"c",{"string":"columnInfo","args":[1]},{"string":"rowInfo","args":[2]},"d",{"string":"columnInfo","args":[2]},{"string":"rowInfo","args":[2]},"e",{"string":"columnInfo","args":[3]},{"string":"rowInfo","args":[2]},"f"],
-            ["a",{"string":"columnInfo","args":[1]},{"string":"rowInfo","args":[1]},"b",{"string":"columnInfo","args":[2]},{"string":"rowInfo","args":[1]},"c",{"string":"columnInfo","args":[3]},{"string":"rowInfo","args":[1]},"d",{"string":"columnInfo","args":[1]},{"string":"rowInfo","args":[2]},"e",{"string":"columnInfo","args":[2]},{"string":"rowInfo","args":[2]},"f",{"string":"columnInfo","args":[3]},{"string":"rowInfo","args":[2]},{"string":"mathmltable"},{"string":"tblColumnInfo","count":3},{"string":"tblRowInfo","count":2}]
+            [{"string": "mathmltable"},{"string": "tblColumnInfo","count": 3},{"string": "tblRowInfo","count": 2},{"string": "columnInfo","args": [1]},{"string": "rowInfo","args": [1]},"a",{"string": "columnInfo","args": [2]},{"string": "rowInfo","args": [1]},"b",{"string": "columnInfo","args": [3]},{"string": "rowInfo","args": [1]},"c",{"string": "columnInfo","args": [1]},{"string": "rowInfo","args": [2]},"d",{"string": "columnInfo","args": [2]},{"string": "rowInfo","args": [2]},"e",{"string": "columnInfo","args": [3]},{"string": "rowInfo","args": [2]},"f"],
+            ["a",{"string": "columnInfo","args": [1]},{"string": "rowInfo","args": [1]},"b",{"string": "columnInfo","args": [2]},{"string": "rowInfo","args": [1]},"c",{"string": "columnInfo","args": [3]},{"string": "rowInfo","args": [1]},"d",{"string": "columnInfo","args": [1]},{"string": "rowInfo","args": [2]},"e",{"string": "columnInfo","args": [2]},{"string": "rowInfo","args": [2]},"f",{"string": "columnInfo","args": [3]},{"string": "rowInfo","args": [2]},{"string": "mathmltable"},{"string": "tblColumnInfo","count": 3},{"string": "tblRowInfo","count": 2}]
           ],
           expectedBraille: [
-            [{"string":"mathmltableAbbr"},{"string":"tblColumnInfoAbbr","count":3},{"string":"tblRowInfoAbbr","count":2},{"string":"cellInfoAbbr","args":[1,1]},"a",{"string":"cellInfoAbbr","args":[2,1]},"b",{"string":"cellInfoAbbr","args":[3,1]},"c",{"string":"cellInfoAbbr","args":[1,2]},"d",{"string":"cellInfoAbbr","args":[2,2]},"e",{"string":"cellInfoAbbr","args":[3,2]},"f"],
-            ["a",{"string":"cellInfoAbbr","args":[1,1]},"b",{"string":"cellInfoAbbr","args":[2,1]},"c",{"string":"cellInfoAbbr","args":[3,1]},"d",{"string":"cellInfoAbbr","args":[1,2]},"e",{"string":"cellInfoAbbr","args":[2,2]},"f",{"string":"cellInfoAbbr","args":[3,2]},{"string":"mathmltableAbbr"},{"string":"tblColumnInfoAbbr","count":3},{"string":"tblRowInfoAbbr","count":2}]
+            [{"string": "mathmltableAbbr"},{"string": "tblColumnInfoAbbr","count": 3},{"string": "tblRowInfoAbbr","count": 2},{"string": "cellInfoAbbr","args": [1,1]},"a",{"string": "cellInfoAbbr","args": [2,1]},"b",{"string": "cellInfoAbbr","args": [3,1]},"c",{"string": "cellInfoAbbr","args": [1,2]},"d",{"string": "cellInfoAbbr","args": [2,2]},"e",{"string": "cellInfoAbbr","args": [3,2]},"f"],
+            ["a",{"string": "cellInfoAbbr","args": [1,1]},"b",{"string": "cellInfoAbbr","args": [2,1]},"c",{"string": "cellInfoAbbr","args": [3,1]},"d",{"string": "cellInfoAbbr","args": [1,2]},"e",{"string": "cellInfoAbbr","args": [2,2]},"f",{"string": "cellInfoAbbr","args": [3,2]},{"string": "mathmltableAbbr"},{"string": "tblColumnInfoAbbr","count": 3},{"string": "tblRowInfoAbbr","count": 2}]
           ]
       }, {
           accOrElmOrID: "menclose-1",
           expectedUtterance: [
-            [{"string":"mathmlenclosed"},{"string":"notation-longdiv"},"a"],
-            ["a",{"string":"notation-longdiv"},{"string":"mathmlenclosed"}]
+            [{"string": "mathmlenclosed"},{"string": "notation-longdiv"},"a"],
+            ["a",{"string": "notation-longdiv"},{"string": "mathmlenclosed"}]
           ],
           expectedBraille: [
-            [{"string":"mathmlenclosedAbbr"},{"string":"notation-longdivAbbr"},"a"],
-            ["a",{"string":"notation-longdivAbbr"},{"string":"mathmlenclosedAbbr"}]
+            [{"string": "mathmlenclosedAbbr"},{"string": "notation-longdivAbbr"},"a"],
+            ["a",{"string": "notation-longdivAbbr"},{"string": "mathmlenclosedAbbr"}]
           ]
         }, {
           accOrElmOrID: "menclose-2",
           expectedUtterance: [
-            [{"string":"mathmlenclosed"},{"string":"notation-circle"},"a"],
-            ["a",{"string":"notation-circle"},{"string":"mathmlenclosed"}]
+            [{"string": "mathmlenclosed"},{"string": "notation-circle"},"a"],
+            ["a",{"string": "notation-circle"},{"string": "mathmlenclosed"}]
           ],
           expectedBraille: [
-            [{"string":"mathmlenclosedAbbr"},{"string":"notation-circleAbbr"},"a"],
-            ["a",{"string":"notation-circleAbbr"},{"string":"mathmlenclosedAbbr"}]
+            [{"string": "mathmlenclosedAbbr"},{"string": "notation-circleAbbr"},"a"],
+            ["a",{"string": "notation-circleAbbr"},{"string": "mathmlenclosedAbbr"}]
           ]
         }, {
           accOrElmOrID: "menclose-3",
           expectedUtterance: [
-            [{"string":"mathmlenclosed"},{"string":"notation-left"},{"string":"notation-top"},{"string":"notation-bottom"},"a"],
-            ["a",{"string":"notation-left"},{"string":"notation-top"},{"string":"notation-bottom"},{"string":"mathmlenclosed"}]
+            [{"string": "mathmlenclosed"},{"string": "notation-left"},{"string": "notation-top"},{"string": "notation-bottom"},"a"],
+            ["a",{"string": "notation-left"},{"string": "notation-top"},{"string": "notation-bottom"},{"string": "mathmlenclosed"}]
           ],
           expectedBraille: [
-            [{"string":"mathmlenclosedAbbr"},{"string":"notation-leftAbbr"},{"string":"notation-topAbbr"},{"string":"notation-bottomAbbr"},"a"],
-            ["a",{"string":"notation-leftAbbr"},{"string":"notation-topAbbr"},{"string":"notation-bottomAbbr"},{"string":"mathmlenclosedAbbr"}]
+            [{"string": "mathmlenclosedAbbr"},{"string": "notation-leftAbbr"},{"string": "notation-topAbbr"},{"string": "notation-bottomAbbr"},"a"],
+            ["a",{"string": "notation-leftAbbr"},{"string": "notation-topAbbr"},{"string": "notation-bottomAbbr"},{"string": "mathmlenclosedAbbr"}]
           ]
         }];
 
       // Test all possible utterance order preference values.
       function testOutputOrder(aOutputOrder) {
         return function() {
           SpecialPowers.pushPrefEnv({
             "set": [[PREF_UTTERANCE_ORDER, aOutputOrder]]
--- a/accessible/tests/mochitest/name/markup.js
+++ b/accessible/tests/mochitest/name/markup.js
@@ -64,17 +64,17 @@ var gTestIterator =
 
     this.ruleIdx++;
     if (this.ruleIdx == this.ruleElms.length) {
       // When test is finished then name is empty and no explict-name.
       var defaultName = this.ruleSetElm.hasAttribute("defaultName") ?
         this.ruleSetElm.getAttribute("defaultName") : null;
       testName(this.elm, defaultName,
                "Default name test (" + gTestIterator.testID + "). ");
-      testAbsentAttrs(this.elm, {"explicit-name" : "true"});
+      testAbsentAttrs(this.elm, {"explicit-name": "true"});
 
       this.markupIdx++;
       if (this.markupIdx == this.markupElms.length) {
         //disableLogging("tree"); // debugging
         SimpleTest.finish();
         return;
       }
 
@@ -212,19 +212,19 @@ function testNameForAttrRule(aElm, aRule
       name += labelElm.getAttribute("textequiv");
     }
   }
 
   var msg = "Attribute '" + attr + "' test (" + gTestIterator.testID + "). ";
   testName(aElm, name, msg);
 
   if (aRule.getAttribute("explict-name") != "false")
-    testAttrs(aElm, {"explicit-name" : "true"}, true);
+    testAttrs(aElm, {"explicit-name": "true"}, true);
   else
-    testAbsentAttrs(aElm, {"explicit-name" : "true"});
+    testAbsentAttrs(aElm, {"explicit-name": "true"});
 
   // If @recreated attribute is used then this attribute change recreates an
   // accessible. Wait for reorder event in this case or otherwise proceed next
   // test immediately.
   if (aRule.hasAttribute("recreated")) {
     waitForEvent(EVENT_REORDER, aElm.parentNode,
                  gTestIterator.iterateNext, gTestIterator);
     aElm.removeAttribute(attr);
@@ -282,17 +282,17 @@ function testNameForElmRule(aElm, aRule)
   if (!labelElm) {
     ok(false, msg + " Failed to find '" + tagname + "' element.");
     gTestIterator.iterateNext();
     return;
   }
 
   var msg = "Element '" + tagname + "' test (" + gTestIterator.testID + ").";
   testName(aElm, labelElm.getAttribute("textequiv"), msg);
-  testAttrs(aElm, {"explicit-name" : "true"}, true);
+  testAttrs(aElm, {"explicit-name": "true"}, true);
 
   var parentNode = labelElm.parentNode;
 
   if (gDumpToConsole) {
     dump("\nProcessed elm rule. Wait for reorder event on " +
          prettyName(parentNode) + "\n");
   }
   waitForEvent(EVENT_REORDER, parentNode,
@@ -300,17 +300,17 @@ function testNameForElmRule(aElm, aRule)
 
   parentNode.removeChild(labelElm);
 }
 
 function testNameForSubtreeRule(aElm, aRule)
 {
   var msg = "From subtree test (" + gTestIterator.testID + ").";
   testName(aElm, aElm.getAttribute("textequiv"), msg);
-  testAbsentAttrs(aElm, {"explicit-name" : "true"});
+  testAbsentAttrs(aElm, {"explicit-name": "true"});
 
   if (gDumpToConsole) {
     dump("\nProcessed from subtree rule. Wait for reorder event on " +
          prettyName(aElm) + "\n");
   }
   waitForEvent(EVENT_REORDER, aElm, gTestIterator.iterateNext, gTestIterator);
 
   while (aElm.firstChild)
@@ -369,12 +369,12 @@ function evaluateXPath(aNode, aExpr, aRe
   while (res = result.iterateNext())
     found.push(res);
 
   return found;
 }
 
 function htmlDocResolver(aPrefix) {
   var ns = {
-    'html' : 'http://www.w3.org/1999/xhtml'
+    'html': 'http://www.w3.org/1999/xhtml'
   };
   return ns[aPrefix] || null;
 }
--- a/accessible/tests/mochitest/name/test_general.html
+++ b/accessible/tests/mochitest/name/test_general.html
@@ -22,41 +22,41 @@
       // Simple label provided via ARIA
       testName("btn_simple_aria_label", "I am a button");
 
       // aria-label and aria-labelledby, expect aria-labelledby
       testName("btn_both_aria_labels", "text I am a button, two");
 
       //////////////////////////////////////////////////////////////////////////
       // aria-labelledby
-      
+    
       // Single relation. The value of 'aria-labelledby' contains the ID of
       // an element. Gets the name from text node of that element.
       testName("btn_labelledby_text", "text");
 
       // Multiple relations. The value of 'aria-labelledby' contains the IDs
       // of elements. Gets the name from text nodes of those elements.
       testName("btn_labelledby_texts", "text1 text2");
 
       //////////////////////////////////////////////////////////////////////////
       // Name from named accessible
 
       testName("input_labelledby_namedacc", "Data");
 
       //////////////////////////////////////////////////////////////////////////
       // Name from subtree (single relation labelled_by).
-      
+    
       // Gets the name from text nodes contained by nested elements
       testName("btn_labelledby_mixed", "nomore text");
 
       // Gets the name from text nodes contained by nested elements, ignores
       // hidden elements (bug 443081).
       testName("btn_labelledby_mixed_hidden_child", "nomore text2");
 
-      // Gets the name from hidden text nodes contained by nested elements, 
+      // Gets the name from hidden text nodes contained by nested elements,
       // (label element is hidden entirely), (bug 443081).
       testName("btn_labelledby_mixed_hidden", "lala more hidden text");
 
       // Gets the name from text nodes contained by nested elements having block
       // representation (every text node value in the name should be devided by
       // spaces)
       testName("btn_labelledby_mixed_block", "text more text");
 
@@ -157,17 +157,17 @@
 
       //////////////////////////////////////////////////////////////////////////
       // textarea name
 
       // textarea's name should have the value, which initially is specified by
       // a text child.
       testName("textareawithchild", "Story Foo is ended.");
 
-      // new textarea name should reflect the value change. 
+      // new textarea name should reflect the value change.
       var elem = document.getElementById("textareawithchild");
       elem.value = "Bar";
 
       testName("textareawithchild", "Story Bar is ended.");
 
       //////////////////////////////////////////////////////////////////////////
       // controls having a value used as a part of computed name
 
--- a/accessible/tests/mochitest/pivot.js
+++ b/accessible/tests/mochitest/pivot.js
@@ -277,17 +277,17 @@ function setVCTextInvoker(aDocAcc, aPivo
                           aIdOrNameOrAcc, aIsFromUserInput)
 {
   var expectMove = (aIdOrNameOrAcc != false);
   this.invoke = function virtualCursorChangedInvoker_invoke()
   {
     VCChangedChecker.storePreviousPosAndOffset(aDocAcc.virtualCursor);
     SimpleTest.info(aDocAcc.virtualCursor.position);
     var moved = aDocAcc.virtualCursor[aPivotMoveMethod](aBoundary,
-      aIsFromUserInput === undefined ? true : false);
+      aIsFromUserInput === undefined);
     SimpleTest.is(!!moved, !!expectMove,
                   "moved pivot by text with " + aPivotMoveMethod +
                   " to " + aIdOrNameOrAcc);
   };
 
   this.getID = function setVCPosInvoker_getID()
   {
     return "Do " + (expectMove ? "" : "no-op ") + aPivotMoveMethod + " in " +
--- a/accessible/tests/mochitest/role.js
+++ b/accessible/tests/mochitest/role.js
@@ -1,12 +1,13 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Role constants
 
 const ROLE_ALERT = nsIAccessibleRole.ROLE_ALERT;
+const ROLE_ARTICLE = nsIAccessibleRole.ROLE_ARTICLE;
 const ROLE_ANIMATION = nsIAccessibleRole.ROLE_ANIMATION;
 const ROLE_APPLICATION = nsIAccessibleRole.ROLE_APPLICATION;
 const ROLE_APP_ROOT = nsIAccessibleRole.ROLE_APP_ROOT;
 const ROLE_AUTOCOMPLETE = nsIAccessibleRole.ROLE_AUTOCOMPLETE;
 const ROLE_BUTTONDROPDOWNGRID = nsIAccessibleRole.ROLE_BUTTONDROPDOWNGRID;
 const ROLE_CANVAS = nsIAccessibleRole.ROLE_CANVAS;
 const ROLE_CAPTION = nsIAccessibleRole.ROLE_CAPTION;
 const ROLE_CELL = nsIAccessibleRole.ROLE_CELL;
@@ -18,31 +19,34 @@ const ROLE_COMBOBOX_LIST = nsIAccessible
 const ROLE_COMBOBOX_OPTION = nsIAccessibleRole.ROLE_COMBOBOX_OPTION;
 const ROLE_COLUMNHEADER = nsIAccessibleRole.ROLE_COLUMNHEADER;
 const ROLE_DEFINITION = nsIAccessibleRole.ROLE_DEFINITION;
 const ROLE_DEFINITION_LIST = nsIAccessibleRole.ROLE_DEFINITION_LIST;
 const ROLE_DETAILS = nsIAccessibleRole.ROLE_DETAILS;
 const ROLE_DIAGRAM = nsIAccessibleRole.ROLE_DIAGRAM;
 const ROLE_DIALOG = nsIAccessibleRole.ROLE_DIALOG;
 const ROLE_DOCUMENT = nsIAccessibleRole.ROLE_DOCUMENT;
+const ROLE_EDITCOMBOBOX = nsIAccessibleRole.ROLE_EDITCOMBOBOX;
 const ROLE_EMBEDDED_OBJECT = nsIAccessibleRole.ROLE_EMBEDDED_OBJECT;
 const ROLE_ENTRY = nsIAccessibleRole.ROLE_ENTRY;
 const ROLE_EQUATION = nsIAccessibleRole.ROLE_EQUATION;
 const ROLE_FIGURE = nsIAccessibleRole.ROLE_FIGURE;
 const ROLE_FOOTER = nsIAccessibleRole.ROLE_FOOTER;
+const ROLE_FOOTNOTE = nsIAccessibleRole.ROLE_FOOTNOTE;
 const ROLE_FLAT_EQUATION = nsIAccessibleRole.ROLE_FLAT_EQUATION;
 const ROLE_FORM = nsIAccessibleRole.ROLE_FORM;
 const ROLE_GRAPHIC = nsIAccessibleRole.ROLE_GRAPHIC;
 const ROLE_GRID_CELL = nsIAccessibleRole.ROLE_GRID_CELL;
 const ROLE_GROUPING = nsIAccessibleRole.ROLE_GROUPING;
 const ROLE_HEADER = nsIAccessibleRole.ROLE_HEADER;
 const ROLE_HEADING = nsIAccessibleRole.ROLE_HEADING;
 const ROLE_IMAGE_MAP = nsIAccessibleRole.ROLE_IMAGE_MAP;
 const ROLE_INTERNAL_FRAME = nsIAccessibleRole.ROLE_INTERNAL_FRAME;
 const ROLE_LABEL = nsIAccessibleRole.ROLE_LABEL;
+const ROLE_LANDMARK = nsIAccessibleRole.ROLE_LANDMARK;
 const ROLE_LINK = nsIAccessibleRole.ROLE_LINK;
 const ROLE_LIST = nsIAccessibleRole.ROLE_LIST;
 const ROLE_LISTBOX = nsIAccessibleRole.ROLE_LISTBOX;
 const ROLE_LISTITEM = nsIAccessibleRole.ROLE_LISTITEM;
 const ROLE_MATHML_MATH = nsIAccessibleRole.ROLE_MATHML_MATH;
 const ROLE_MATHML_IDENTIFIER = nsIAccessibleRole.ROLE_MATHML_IDENTIFIER;
 const ROLE_MATHML_NUMBER = nsIAccessibleRole.ROLE_MATHML_NUMBER;
 const ROLE_MATHML_OPERATOR = nsIAccessibleRole.ROLE_MATHML_OPERATOR;
@@ -74,16 +78,17 @@ const ROLE_MATHML_LONG_DIVISION = nsIAcc
 const ROLE_MATHML_STACK_GROUP = nsIAccessibleRole.ROLE_MATHML_STACK_GROUP;
 const ROLE_MATHML_STACK_ROW = nsIAccessibleRole.ROLE_MATHML_STACK_ROW;
 const ROLE_MATHML_STACK_CARRIES = nsIAccessibleRole.ROLE_MATHML_STACK_CARRIES;
 const ROLE_MATHML_STACK_CARRY = nsIAccessibleRole.ROLE_MATHML_STACK_CARRY;
 const ROLE_MATHML_STACK_LINE = nsIAccessibleRole.ROLE_MATHML_STACK_LINE;
 const ROLE_MENUBAR = nsIAccessibleRole.ROLE_MENUBAR;
 const ROLE_MENUITEM = nsIAccessibleRole.ROLE_MENUITEM;
 const ROLE_MENUPOPUP = nsIAccessibleRole.ROLE_MENUPOPUP;
+const ROLE_NAVIGATION = nsIAccessibleRole.ROLE_NAVIGATION;
 const ROLE_NOTHING = nsIAccessibleRole.ROLE_NOTHING;
 const ROLE_NOTE = nsIAccessibleRole.ROLE_NOTE;
 const ROLE_OPTION = nsIAccessibleRole.ROLE_OPTION;
 const ROLE_OUTLINE = nsIAccessibleRole.ROLE_OUTLINE;
 const ROLE_OUTLINEITEM = nsIAccessibleRole.ROLE_OUTLINEITEM;
 const ROLE_PAGETAB = nsIAccessibleRole.ROLE_PAGETAB;
 const ROLE_PAGETABLIST = nsIAccessibleRole.ROLE_PAGETABLIST;
 const ROLE_PANE = nsIAccessibleRole.ROLE_PANE;
@@ -91,16 +96,17 @@ const ROLE_PARAGRAPH = nsIAccessibleRole
 const ROLE_PARENT_MENUITEM = nsIAccessibleRole.ROLE_PARENT_MENUITEM;
 const ROLE_PASSWORD_TEXT = nsIAccessibleRole.ROLE_PASSWORD_TEXT;
 const ROLE_PROGRESSBAR = nsIAccessibleRole.ROLE_PROGRESSBAR;
 const ROLE_PROPERTYPAGE = nsIAccessibleRole.ROLE_PROPERTYPAGE;
 const ROLE_PUSHBUTTON = nsIAccessibleRole.ROLE_PUSHBUTTON;
 const ROLE_RADIOBUTTON = nsIAccessibleRole.ROLE_RADIOBUTTON;
 const ROLE_RADIO_GROUP = nsIAccessibleRole.ROLE_RADIO_GROUP;
 const ROLE_RADIO_MENU_ITEM = nsIAccessibleRole.ROLE_RADIO_MENU_ITEM;
+const ROLE_REGION = nsIAccessibleRole.ROLE_REGION;
 const ROLE_RICH_OPTION = nsIAccessibleRole.ROLE_RICH_OPTION;
 const ROLE_ROW = nsIAccessibleRole.ROLE_ROW;
 const ROLE_ROWHEADER = nsIAccessibleRole.ROLE_ROWHEADER;
 const ROLE_SCROLLBAR = nsIAccessibleRole.ROLE_SCROLLBAR;
 const ROLE_SECTION = nsIAccessibleRole.ROLE_SECTION;
 const ROLE_SEPARATOR = nsIAccessibleRole.ROLE_SEPARATOR;
 const ROLE_SLIDER = nsIAccessibleRole.ROLE_SLIDER;
 const ROLE_SPINBUTTON = nsIAccessibleRole.ROLE_SPINBUTTON;
@@ -145,17 +151,17 @@ function getRole(aAccOrElmOrID)
 {
   var acc = getAccessible(aAccOrElmOrID);
   if (!acc)
     return -1;
 
   var role = -1;
   try {
     role = acc.role;
-  } catch(e) {
+  } catch (e) {
     ok(false, "Role for " + aAccOrElmOrID + " could not be retrieved!");
   }
 
   return role;
 }
 
 /**
  * Analogy of SimpleTest.is function used to check the role.
--- a/accessible/tests/mochitest/role/a11y.ini
+++ b/accessible/tests/mochitest/role/a11y.ini
@@ -1,10 +1,11 @@
 [DEFAULT]
 support-files =
   !/accessible/tests/mochitest/*.js
   !/accessible/tests/mochitest/moz.png
 
 [test_aria.html]
 [test_aria.xul]
+[test_dpub_aria.html]
 [test_general.html]
 [test_general.xul]
 [test_svg.html]
--- a/accessible/tests/mochitest/role/test_aria.html
+++ b/accessible/tests/mochitest/role/test_aria.html
@@ -16,26 +16,27 @@
   <script type="application/javascript">
 
     function doTest()
     {
       // ARIA role map.
       testRole("aria_alert", ROLE_ALERT);
       testRole("aria_alertdialog", ROLE_DIALOG);
       testRole("aria_application", ROLE_APPLICATION);
-      testRole("aria_article", ROLE_DOCUMENT);
+      testRole("aria_article", ROLE_ARTICLE);
       testRole("aria_button", ROLE_PUSHBUTTON);
       testRole("aria_checkbox", ROLE_CHECKBUTTON);
       testRole("aria_columnheader", ROLE_COLUMNHEADER);
-      testRole("aria_combobox", ROLE_COMBOBOX);
+      testRole("aria_combobox", ROLE_EDITCOMBOBOX);
       testRole("aria_dialog", ROLE_DIALOG);
       testRole("aria_directory", ROLE_LIST);
       testRole("aria_document", ROLE_DOCUMENT);
       testRole("aria_form", ROLE_FORM);
       testRole("aria_feed", ROLE_GROUPING);
+      testRole("aria_figure", ROLE_FIGURE);
       testRole("aria_grid", ROLE_TABLE);
       testRole("aria_gridcell", ROLE_GRID_CELL);
       testRole("aria_group", ROLE_GROUPING);
       testRole("aria_heading", ROLE_HEADING);
       testRole("aria_img", ROLE_GRAPHIC);
       testRole("aria_link", ROLE_LINK);
       testRole("aria_list", ROLE_LIST);
       testRole("aria_listbox", ROLE_LISTBOX);
@@ -48,47 +49,52 @@
       testRole("aria_menuitem", ROLE_MENUITEM);
       testRole("aria_menuitemcheckbox", ROLE_CHECK_MENU_ITEM);
       testRole("aria_menuitemradio", ROLE_RADIO_MENU_ITEM);
       testRole("aria_note", ROLE_NOTE);
       testRole("aria_presentation", ROLE_TEXT); // weak role
       testRole("aria_progressbar", ROLE_PROGRESSBAR);
       testRole("aria_radio", ROLE_RADIOBUTTON);
       testRole("aria_radiogroup", ROLE_RADIO_GROUP);
-      testRole("aria_region", ROLE_PANE);
+      testRole("aria_region_no_name", ROLE_TEXT);
+      testRole("aria_region_has_label", ROLE_REGION);
+      testRole("aria_region_has_labelledby", ROLE_REGION);
+      testRole("aria_region_has_title", ROLE_REGION);
+      testRole("aria_region_empty_name", ROLE_TEXT);
       testRole("aria_row", ROLE_ROW);
       testRole("aria_rowheader", ROLE_ROWHEADER);
       testRole("aria_scrollbar", ROLE_SCROLLBAR);
       testRole("aria_searchbox", ROLE_ENTRY);
       testRole("aria_separator", ROLE_SEPARATOR);
       testRole("aria_slider", ROLE_SLIDER);
       testRole("aria_spinbutton", ROLE_SPINBUTTON);
       testRole("aria_status", ROLE_STATUSBAR);
       testRole("aria_switch", ROLE_SWITCH);
       testRole("aria_tab", ROLE_PAGETAB);
       testRole("aria_tablist", ROLE_PAGETABLIST);
       testRole("aria_tabpanel", ROLE_PROPERTYPAGE);
+      testRole("aria_term", ROLE_TERM);
       testRole("aria_textbox", ROLE_ENTRY);
       testRole("aria_timer", ROLE_TEXT); // weak role
       testRole("aria_toolbar", ROLE_TOOLBAR);
       testRole("aria_tooltip", ROLE_TOOLTIP);
       testRole("aria_tree", ROLE_OUTLINE);
       testRole("aria_treegrid", ROLE_TREE_TABLE);
       testRole("aria_treeitem", ROLE_OUTLINEITEM);
 
       // Note:
       // The phrase "weak foo" here means that there is no good foo-to-platform
       // role mapping. Similarly "strong foo" means there is a good foo-to-
       // platform role mapping.
 
-      testRole("articlemain", ROLE_DOCUMENT);
+      testRole("articlemain", ROLE_ARTICLE);
       testRole("articleform", ROLE_FORM);
 
-      // Test article exposed as document
-      testRole("testArticle", ROLE_DOCUMENT);
+      // Test article exposed as article
+      testRole("testArticle", ROLE_ARTICLE);
 
       // weak roles that are forms of "live regions"
       testRole("log_table", ROLE_TABLE);
       testRole("timer_div", ROLE_SECTION);
 
       // other roles that are forms of "live regions"
       testRole("marquee_h1", ROLE_ANIMATION);
 
@@ -101,22 +107,21 @@
       var weak_landmarks = ["banner", "complementary", "contentinfo",
           "main", "navigation", "search"];
       for (l in weak_landmarks)
         testRole(weak_landmarks[l], ROLE_SECTION);
 
       for (l in weak_landmarks) {
         var id = weak_landmarks[l] + "_table";
         testRole(id, ROLE_TABLE);
-        
+    
         var accessibleTable = getAccessible(id, [nsIAccessibleTable], null,
                                             DONOTFAIL_IF_NO_INTERFACE);
-        ok(accessibleTable ? true : false,
-           "landmarked table should have nsIAccessibleTable");
-        
+        ok(!!accessibleTable, "landmarked table should have nsIAccessibleTable");
+    
         if (accessibleTable)
           is(accessibleTable.getCellAt(0,0).firstChild.name, "hi", "no cell");
       }
 
       //////////////////////////////////////////////////////////////////////////
       // test gEmptyRoleMap
       testRole("buttontable_row", ROLE_NOTHING);
       testRole("buttontable_cell", ROLE_NOTHING);
@@ -186,16 +191,21 @@
      title="Support ARIA 1.1 switch role">
     Bug 1136563
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=1121518"
      title="Support ARIA 1.1 searchbox role">
     Bug 1121518
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=1356049"
+     title="Map ARIA figure role">
+    Bug 1356049
+  </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <span id="aria_alert" role="alert"/>
   <span id="aria_alertdialog" role="alertdialog"/>
   <span id="aria_application" role="application"/>
@@ -204,16 +214,17 @@
   <span id="aria_checkbox" role="checkbox"/>
   <span id="aria_columnheader" role="columnheader"/>
   <span id="aria_combobox" role="combobox"/>
   <span id="aria_dialog" role="dialog"/>
   <span id="aria_directory" role="directory"/>
   <span id="aria_document" role="document"/>
   <span id="aria_form" role="form"/>
   <span id="aria_feed" role="feed"/>
+  <span id="aria_figure" role="figure"/>
   <span id="aria_grid" role="grid"/>
   <span id="aria_gridcell" role="gridcell"/>
   <span id="aria_group" role="group"/>
   <span id="aria_heading" role="heading"/>
   <span id="aria_img" role="img"/>
   <span id="aria_link" role="link"/>
   <span id="aria_list" role="list"/>
   <span id="aria_listbox" role="listbox"/>
@@ -226,29 +237,34 @@
   <span id="aria_menuitem" role="menuitem"/>
   <span id="aria_menuitemcheckbox" role="menuitemcheckbox"/>
   <span id="aria_menuitemradio" role="menuitemradio"/>
   <span id="aria_note" role="note"/>
   <span id="aria_presentation" role="presentation" tabindex="0"/>
   <span id="aria_progressbar" role="progressbar"/>
   <span id="aria_radio" role="radio"/>
   <span id="aria_radiogroup" role="radiogroup"/>
-  <span id="aria_region" role="region"/>
+  <span id="aria_region_no_name" role="region"/>
+  <span id="aria_region_has_label" role="region" aria-label="label"/>
+  <span id="aria_region_has_labelledby" role="region" aria-labelledby="label"/><span id="label" aria-label="label">
+  <span id="aria_region_has_title" role="region" title="title"/>
+  <span id="aria_region_empty_name" role="region" aria-label="" title="" aria-labelledby="empty"/><span id="empty"/>
   <span id="aria_row" role="row"/>
   <span id="aria_rowheader" role="rowheader"/>
   <span id="aria_scrollbar" role="scrollbar"/>
   <span id="aria_searchbox" role="textbox"/>
   <span id="aria_separator" role="separator"/>
   <span id="aria_slider" role="slider"/>
   <span id="aria_spinbutton" role="spinbutton"/>
   <span id="aria_status" role="status"/>
   <span id="aria_switch" role="switch"/>
   <span id="aria_tab" role="tab"/>
   <span id="aria_tablist" role="tablist"/>
   <span id="aria_tabpanel" role="tabpanel"/>
+  <span id="aria_term" role="term"/>
   <span id="aria_textbox" role="textbox"/>
   <span id="aria_timer" role="timer"/>
   <span id="aria_toolbar" role="toolbar"/>
   <span id="aria_tooltip" role="tooltip"/>
   <span id="aria_tree" role="tree"/>
   <span id="aria_treegrid" role="treegrid"/>
   <span id="aria_treeitem" role="treeitem"/>
 
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/role/test_dpub_aria.html
@@ -0,0 +1,116 @@
+<!DOCTYPE html>
+<html>
+<head>