Merge draft head draft
authorGregory Szorc <gps@mozilla.com>
Fri, 04 Aug 2017 15:51:50 -0700
changeset 638860 d194080f1c24b079ae44826a64907824f60bd907
parent 638859 7038abb99fd7d775cdf968f6f61590cd12ba36ea (diff)
parent 614426 bc04dd2d65af4d0ce4a4c6160cb1fea0984f4ea9 (current diff)
child 638861 bd16809d9d8f19b49be6540616ce8931c65b8ae7
push id72398
push usergszorc@mozilla.com
push dateFri, 04 Aug 2017 23:14:39 +0000
milestone57.0a1
Merge draft head
--- 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
@@ -132,21 +133,19 @@ devtools/server/tests/browser/storage-*.
 !devtools/server/tests/browser/storage-unsecured-iframe.html
 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
+# Ignore devtools preferences files
 devtools/client/preferences/**
+devtools/shim/devtools-startup-prefs.js
 
 # Ignore devtools third-party libs
 devtools/shared/jsbeautify/*
 devtools/shared/acorn/*
 devtools/shared/gcli/source/*
 devtools/shared/node-properties/*
 devtools/shared/pretty-fast/*
 devtools/shared/sourcemap/*
@@ -210,16 +209,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 +246,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
@@ -320,30 +335,28 @@ 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/osfile/osfile.jsm
 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
@@ -92,463 +92,45 @@ cf8750abee06cde395c659f8ecd8ae019d7512e3
 5bb309998e7050c9ee80b0147de1e473f008e221 FIREFOX_AURORA_20_BASE
 cc37417e2c284aed960f98ffa479de4ccdd5c7c3 FIREFOX_AURORA_21_BASE
 1c070ab0f9db59f13423b9c1db60419f7a9098f9 FIREFOX_AURORA_22_BASE
 d7ce9089999719d5186595d160f25123a4e63e39 FIREFOX_AURORA_23_BASE
 8d3810543edccf4fbe458178b88dd4a6e420b010 FIREFOX_AURORA_24_BASE
 ad0ae007aa9e03cd74e9005cd6652e544139b3b5 FIREFOX_AURORA_25_BASE
 2520866d58740851d862c7c59246a4e3f8b4a176 FIREFOX_AURORA_26_BASE
 05025f4889a0bf4dc99ce0c244c750adc002f015 FIREFOX_AURORA_27_BASE
-ba2cc1eda988a1614d8986ae145d28e1268409b9 FIREFOX_AURORA_29_BASE-m
-ba2cc1eda988a1614d8986ae145d28e1268409b9 Tagging for mozilla-central version bumps CLOSED TREE DONTBUILD
-ba2cc1eda988a1614d8986ae145d28e1268409b9 Tagging for mozilla-central version bumps CLOSED TREE DONTBUILD
-0000000000000000000000000000000000000000 Tagging for mozilla-central version bumps CLOSED TREE DONTBUILD
-ba2cc1eda988a1614d8986ae145d28e1268409b9 FIREFOX_AURORA_29_BASE-m
-0000000000000000000000000000000000000000 FIREFOX_AURORA_29_BASE-m
+9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 ba2cc1eda988a1614d8986ae145d28e1268409b9 FIREFOX_AURORA_29_BASE
-9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
-07f5580d8a54e8311fa7641c907065a88de19e08 FIREFOX_AURORA_29_END
-3776f72f1967a7068879501eb7c08920032785b8 B2G_1_4_20140317_MERGEDAY
-aa70a6ce178a6839cd9e55761c4ac31d43ee7bd9 FIREFOX_BETA_29_END
-ba4a8f81efdcf000414f192342ccbd14c9626c36 RELEASE_BASE_20140602
-9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 83c9853e136451474dfa6d1aaa60a7fca7d2d83a FIREFOX_AURORA_30_BASE
 cfde3603b0206e119abea76fdd6e134b634348f1 FIREFOX_AURORA_31_BASE
-ab25447610b532eb4c32524a7dbc56a21eeaabb8 FIREFOX_BETA_30_BASE
-ab25447610b532eb4c32524a7dbc56a21eeaabb8 FIREFOX_AURORA_30_END
-6c18811bcd1b319801fd97aeb09c41b963863968 FIREFOX_BETA_30_END
-1772e55568e420f8c7fbf7b9434157e9f419c8f1 FIREFOX_RELEASE_31_BASE
-40b1b0712d7b53219a0404e78eec4e6a2796423e FIREFOX_RELEASE_30_END
-9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 16f3cac5e8fe471e12f76d6a94a477b14e78df7c FIREFOX_AURORA_32_BASE
-f11b164d75442617c4f046177d2ab913ed03a318 FIREFOX_BETA_31_BASE
-f11b164d75442617c4f046177d2ab913ed03a318 FIREFOX_AURORA_31_END
-dc2fd26b301375f15c935f00fe6283d3e3bc1efc B2G_2_0_20140609_MERGEDAY
-d69cd84b6824e018e0906cab0464e11e97a9bdca FIREFOX_BETA_32_BASE
-d69cd84b6824e018e0906cab0464e11e97a9bdca FIREFOX_BETA_32_BASE
-0000000000000000000000000000000000000000 FIREFOX_BETA_32_BASE
-0000000000000000000000000000000000000000 FIREFOX_BETA_32_BASE
-ac396ad5a32d60ae5b7eebe5416fdd46e9e12be1 FIREFOX_BETA_32_BASE
-6befadcaa68524d24960d8342e00503e4edc1869 FIREFOX_BETA_31_END
-92ad4cfa9435fbe136c61071041812f90bc8d89e FIREFOX_RELEASE_32_BASE
-cd52a7f8954809fd893196dc857f81b0cb61717c FIREFOX_RELEASE_31_END
-9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 dc23164ba2a289a8b22902e30990c77d9677c214 FIREFOX_AURORA_33_BASE
-a104ddcd4cdbf950f1755dfaf5a278d53570655f FIREFOX_AURORA_32_END
-114b010b6bf1a0efee03f003e54ed6fa00909972 FIREFOX_BETA_33_BASE
-ebd0ee3e97dc2756d979261b29f173638fe6aeb6 FIREFOX_BETA_32_END
-e8360a0c7d7483491e064c7cd445a94004af0a83 FIREFOX_RELEASE_33_BASE
-4641475ee1f3ec3e723e932e0f4f3f3fa7c55a5c FIREFOX_RELEASE_32_END
-9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 c360f3d1c00d73b0c1fb0a2c0da525cb55e58b83 FIREFOX_AURORA_34_BASE
-9f1aad8e807cc283aafbc14caa3d4775e8d0535c FIREFOX_AURORA_33_END
-5b8210dcf52a795646bf0c8a32082a2ed7c4f537 B2G_2_1_20140902_MERGEDAY
-e85828ce78a80e2ccda98972d69d5f750335c4ab FIREFOX_BETA_34_BASE
-8574e35b517785acc905327f4994e96576218fa8 FIREFOX_BETA_33_END
-e247a7f7c43842941bdb4207ca1b9d8881798997 FIREFOX_RELEASE_34_BASE
-a47b1b720b67b018a9cb106178de53a363641392 FIREFOX_RELEASE_33_END
-9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 cec1a116c4f9a3e887d52e9a26e8bbec200fe162 FIREFOX_AURORA_35_BASE
-2608561c091ae83cc85e38740feffa5bfc6b5ed4 FIREFOX_AURORA_34_END
-390a34a40ea4e7f4d24b3ed83778e0f408411fcc FIREFOX_BETA_35_BASE
-a3cc435fd3c315e5dfe9329d03d5943bb893cced FIREFOX_BETA_34_END
-fb06fa0600ab95db48212a237c79b650cac213c5 FIREFOX_RELEASE_35_BASE
-f4217563f1568c478c1ddf1647098946e51bc7f8 FIREFOX_RELEASE_34_END
-9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 ca89fe55717059e4e43040d16d260765ffa9dca7 FIREFOX_AURORA_36_BASE
 6047f510fb73c7dbe9866066fb01ddda3c170c9c FIREFOX_AURORA_37_BASE
 ca89fe55717059e4e43040d16d260765ffa9dca7 FIREFOX_AURORA_36_BASE
 0000000000000000000000000000000000000000 FIREFOX_AURORA_36_BASE
 6047f510fb73c7dbe9866066fb01ddda3c170c9c FIREFOX_AURORA_37_BASE
 0000000000000000000000000000000000000000 FIREFOX_AURORA_37_BASE
 0000000000000000000000000000000000000000 FIREFOX_AURORA_36_BASE
 b297a6727acfd21e757ddd38cd61894812666265 FIREFOX_AURORA_36_BASE
-0cf828669d5a0911b6f2b83d501eeef5bdf9905e FIREFOX_AURORA_35_END
-75177371cb85baaa9d623f56d849a5c21d18040f FIREFOX_BETA_36_BASE
-137baee3dda45c6a3b38be74f5709c24f7c7701a FIREFOX_BETA_35_END
-948a2c2e31d4b7eaa282ddeb327708605e3cc7fa FIREFOX_RELEASE_36_BASE
-d57ff45ca4fd7ccf1cb924030abf6c7d108eaab0 FIREFOX_RELEASE_35_END
-9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 0000000000000000000000000000000000000000 FIREFOX_AURORA_37_BASE
 2c951493eef5b50b8085ef78ffe0d7902ff3d593 FIREFOX_AURORA_37_BASE
-1bc9beda018a42bdd5f63fc9fc46facf0c6f37ec FIREFOX_AURORA_36_END
-030fa1665346dfa94d1f72a1c7830644664ecf08 FIREFOX_BETA_37_BASE
-7d4016a05dd32bf2d726975ba9175bb13fc9ea97 FIREFOX_BETA_36_END
-196c6575593d6e8997402fb458bf8ed2f954fa4a FIREFOX_RELEASE_37_BASE
-58fe203296af528cc711dc314e4769a902e3852f FIREFOX_RELEASE_36_END
-9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 98086da94ccdc88f6de86774ce3d1fa258dc7c44 FIREFOX_AURORA_38_BASE
-d55b99e8010728b0c802e75e967d2a853122dd30 FIREFOX_AURORA_37_END
-8bc9656cad94db48cd44f3947f1b3b1d8c57768a FIREFOX_BETA_38_BASE
-b41c57eefd69242fc9664a3e5c2dcaa46840051c FIREFOX_BETA_37_END
-fc98815acf5f041c6269fd256a68af8a92ba222a FIREFOX_RELEASE_38_BASE
-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
-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
-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
-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
-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
-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
-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
-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
-2f6f69a19150e03ad68062f2ac92342afb1ef787 FIREFOX_46_0b4_BUILD2
-2f6f69a19150e03ad68062f2ac92342afb1ef787 FIREFOX_46_0b4_RELEASE
-53d6e6648f97402a740687a82a297c66f5396548 FIREFOX_46_0b5_BUILD2
-53d6e6648f97402a740687a82a297c66f5396548 FIREFOX_46_0b5_RELEASE
-97b81104ac035d6a8f6ed59a1aad63fcc23e73c8 FIREFOX_46_0b6_BUILD1
-97b81104ac035d6a8f6ed59a1aad63fcc23e73c8 FIREFOX_46_0b6_RELEASE
-191f5eb4cbd72590277296cdb90d355adb347d45 FIREFOX_46_0b7_BUILD2
-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
-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
-5bbf2e7c2fc6ff9010b1948e2f11477f48ee36e2 FIREFOX_47_0b1_RELEASE
-6f82d30fe05e1412e744cb76af86f0c9ffe509d4 FIREFOX_47_0b2_BUILD1
-6f82d30fe05e1412e744cb76af86f0c9ffe509d4 FIREFOX_47_0b2_RELEASE
-609000bcc11211d7c27ceea36fa2d2262fa0523f FIREFOX_47_0b3_BUILD1
-609000bcc11211d7c27ceea36fa2d2262fa0523f FIREFOX_47_0b3_RELEASE
-2991f214d4f4d8a3c5cfd95e6223f0660006767d FIREFOX_47_0b4_BUILD1
-2991f214d4f4d8a3c5cfd95e6223f0660006767d FIREFOX_47_0b4_RELEASE
-93a53170dedffdff45bf9eb8dac6e5ef7a13c4ba FIREFOX_47_0b5_BUILD1
-93a53170dedffdff45bf9eb8dac6e5ef7a13c4ba FIREFOX_47_0b5_RELEASE
-7d1f3450acc47025876964c1eca854ae027934f3 FIREFOX_47_0b6_BUILD1
-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
-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
-9798772706750302d87a689cbbf056ae04244f80 FIREFOX_48_0b2_RELEASE
-13b02b96281e550c3cdbdf4eaed034aa1edefd69 FIREFOX_48_0b3_BUILD1
-13b02b96281e550c3cdbdf4eaed034aa1edefd69 FIREFOX_48_0b3_RELEASE
-676a32cdd41fd372f4c6df3a4954939f73a6ef02 FIREFOX_48_0b4_BUILD1
-676a32cdd41fd372f4c6df3a4954939f73a6ef02 FIREFOX_48_0b4_RELEASE
-dd7af1fa4ece1cb3158d08c80dfcbf1c6ca830fb FIREFOX_48_0b5_BUILD1
-dd7af1fa4ece1cb3158d08c80dfcbf1c6ca830fb FIREFOX_48_0b5_RELEASE
-d142c49033c015f67272562b37dbe2912cfc7f14 FIREFOX_48_0b6_BUILD1
-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
-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
-36af692196a1c92cc935cf6569e03fdf5dc5e426 FIREFOX_49_0b3_BUILD1
-36af692196a1c92cc935cf6569e03fdf5dc5e426 FIREFOX_49_0b3_RELEASE
-ab7b68014a1e20c423aa9b50ca76fd8edccb272c FIREFOX_49_0b4_BUILD1
-ab7b68014a1e20c423aa9b50ca76fd8edccb272c FIREFOX_49_0b4_RELEASE
-91505c2a68fb868bcab1e3dc03ffc2e89bf71cac FIREFOX_49_0b5_BUILD1
-91505c2a68fb868bcab1e3dc03ffc2e89bf71cac FIREFOX_49_0b5_RELEASE
-e6d6eb0ce3c42b4ebca91b1b1b64b716b2acb9fd FIREFOX_49_0b6_BUILD1
-e6d6eb0ce3c42b4ebca91b1b1b64b716b2acb9fd FIREFOX_49_0b6_RELEASE
-b44c72b85a800d9c6e719579d480bb2c3a87a753 FIREFOX_49_0b7_BUILD1
-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
-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
-865939f4946d80fa532aaa168515a2fe69f9a774 FIREFOX_50_0b2_BUILD1
-865939f4946d80fa532aaa168515a2fe69f9a774 FIREFOX_50_0b2_RELEASE
-6a7c1c8db5548d077c7fa36bce41af629ba52bd8 FIREFOX_50_0b3_BUILD1
-6a7c1c8db5548d077c7fa36bce41af629ba52bd8 FIREFOX_50_0b3_RELEASE
-f4b45ea3c0c836e5a457c8009bff423447e54803 FIREFOX_50_0b4_BUILD1
-f4b45ea3c0c836e5a457c8009bff423447e54803 FIREFOX_50_0b4_RELEASE
-49776d31766dd130969f9ec4ea3354a43e8e6d9d FIREFOX_50_0b5_BUILD1
-49776d31766dd130969f9ec4ea3354a43e8e6d9d FIREFOX_50_0b5_RELEASE
-70abfe99097824fd510544b188f24c588fd6d5a0 FIREFOX_50_0b6_BUILD1
-70abfe99097824fd510544b188f24c588fd6d5a0 FIREFOX_50_0b6_RELEASE
-6efc0964ec62bc4abfdc4cb1dc7cc461c3238634 FIREFOX_50_0b7_BUILD1
-6efc0964ec62bc4abfdc4cb1dc7cc461c3238634 FIREFOX_50_0b7_RELEASE
-b7adb2f10487f6f886e047670ba720a248edcb44 FIREFOX_50_0b8_BUILD1
-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
-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
-6296ed3dbefd133bba324230ec4f5a07d37041e1 FIREFOX_51_0b2_RELEASE
-f37e99ebc6e0c682003b52573f415e5fd78d425a FIREFOX_51_0b3_BUILD1
-f37e99ebc6e0c682003b52573f415e5fd78d425a FIREFOX_51_0b3_RELEASE
-1b954c82dd04faf1926804d89c0d130dc6b9ab93 FIREFOX_51_0b4_BUILD1
-1b954c82dd04faf1926804d89c0d130dc6b9ab93 FIREFOX_51_0b4_RELEASE
-9afe68360fa82c16b760b448b2156230a90caf11 FIREFOX_51_0b5_BUILD1
-9afe68360fa82c16b760b448b2156230a90caf11 FIREFOX_51_0b5_RELEASE
-2dec3c6c7c90e2e27093b8a3512c1b32a8263a8f FIREFOX_51_0b6_BUILD1
-2dec3c6c7c90e2e27093b8a3512c1b32a8263a8f FIREFOX_51_0b6_RELEASE
-829fcc7f60f04dffff4d29b007ef8015a1cd2c99 FIREFOX_51_0b7_BUILD1
-829fcc7f60f04dffff4d29b007ef8015a1cd2c99 FIREFOX_51_0b7_RELEASE
-ae5275b8c53ba76cb98576e4e2a3031b0d659ba3 FIREFOX_51_0b8_BUILD1
-ae5275b8c53ba76cb98576e4e2a3031b0d659ba3 FIREFOX_51_0b8_RELEASE
-6e4843d1510be426212d31fec03ad4f2d70b1977 FIREFOX_51_0b9_BUILD1
-6e4843d1510be426212d31fec03ad4f2d70b1977 FIREFOX_51_0b9_RELEASE
-4fbf5d14ce92bd45e0c7881dad20a66896402683 FIREFOX_51_0b10_BUILD1
-4fbf5d14ce92bd45e0c7881dad20a66896402683 FIREFOX_51_0b10_RELEASE
-0a17d39220700e742bf37a960967480b2f8159f1 FIREFOX_51_0b11_BUILD1
-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
-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
-0f339c1e154f75c484fe2fac507a9a225990d212 FIREFOX_52_0b2_RELEASE
-d171c36d484800b1bb00db1612460a7120dd2fdf FIREFOX_52_0b3_BUILD1
-d171c36d484800b1bb00db1612460a7120dd2fdf FIREFOX_52_0b3_RELEASE
-501a3fa83897af9598adfd6f794b5d5ea82fe237 FIREFOX_52_0b4_BUILD1
-501a3fa83897af9598adfd6f794b5d5ea82fe237 FIREFOX_52_0b4_RELEASE
-49b3ad9f467d48194dab8121f82e4c938b70b484 FIREFOX_52_0b5_BUILD1
-49b3ad9f467d48194dab8121f82e4c938b70b484 FIREFOX_52_0b5_RELEASE
-7b8aa893944b94d35e47314e52e0abff576c5ce2 FIREFOX_52_0b6_BUILD1
-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
-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
-615b84cd4c5f5923b78ffa1d335e51a6a74001f5 FIREFOX_BETA_52_END
-2b89485cf946cdfdd69e5d11aa6af2563fa7520d FIREFOX_53_0b1_BUILD1
-2b89485cf946cdfdd69e5d11aa6af2563fa7520d FIREFOX_53_0b1_RELEASE
-a4a198383638d54b6093b1caab16740cec21ebc2 FENNEC_53_0b1_BUILD3
-a4a198383638d54b6093b1caab16740cec21ebc2 FENNEC_53_0b1_RELEASE
-a5ccc32310c9a424ccb4f5106f5155ca20dd360a FIREFOX_53_0b2_BUILD1
-a5ccc32310c9a424ccb4f5106f5155ca20dd360a FIREFOX_53_0b2_RELEASE
-a5ccc32310c9a424ccb4f5106f5155ca20dd360a FENNEC_53_0b2_BUILD1
-a5ccc32310c9a424ccb4f5106f5155ca20dd360a FENNEC_53_0b2_RELEASE
-484f49860df6c257b06dac275d66651cc6f22867 FIREFOX_53_0b4_BUILD1
-484f49860df6c257b06dac275d66651cc6f22867 FIREFOX_53_0b4_RELEASE
-eb20f71a4f431d695b88ea5796a55d52cc9cf481 FIREFOX_53_0b5_BUILD1
-eb20f71a4f431d695b88ea5796a55d52cc9cf481 FIREFOX_53_0b5_RELEASE
-484f49860df6c257b06dac275d66651cc6f22867 FENNEC_53_0b4_BUILD1
-484f49860df6c257b06dac275d66651cc6f22867 FENNEC_53_0b4_RELEASE
-484f49860df6c257b06dac275d66651cc6f22867 FENNEC_53_0b4_BUILD1
-484f49860df6c257b06dac275d66651cc6f22867 FENNEC_53_0b4_BUILD1
-484f49860df6c257b06dac275d66651cc6f22867 FENNEC_53_0b4_RELEASE
-484f49860df6c257b06dac275d66651cc6f22867 FENNEC_53_0b4_RELEASE
-eb20f71a4f431d695b88ea5796a55d52cc9cf481 FENNEC_53_0b5_BUILD1
-eb20f71a4f431d695b88ea5796a55d52cc9cf481 FENNEC_53_0b5_RELEASE
-62467dd7218ffb48be7d4406d98ded5d0909fcfc FIREFOX_53_0b6_BUILD1
-62467dd7218ffb48be7d4406d98ded5d0909fcfc FIREFOX_53_0b6_RELEASE
-46d5fe92c82d36b922703faeb7dd3a17b5df55e1 FENNEC_53_0b7_BUILD1
-46d5fe92c82d36b922703faeb7dd3a17b5df55e1 FENNEC_53_0b7_RELEASE
-46d5fe92c82d36b922703faeb7dd3a17b5df55e1 FIREFOX_53_0b7_BUILD1
-46d5fe92c82d36b922703faeb7dd3a17b5df55e1 FIREFOX_53_0b7_RELEASE
-0a36cc120d6e7b8bc19176f5efac6b00dd9ad072 FIREFOX_53_0b8_BUILD1
-0a36cc120d6e7b8bc19176f5efac6b00dd9ad072 FIREFOX_53_0b8_RELEASE
-3a2e5c6e4ed33d9cb8b04b32f85b45a9aad4c8d8 FIREFOX_53_0b9_BUILD1
-3a2e5c6e4ed33d9cb8b04b32f85b45a9aad4c8d8 FIREFOX_53_0b9_RELEASE
-3a2e5c6e4ed33d9cb8b04b32f85b45a9aad4c8d8 FENNEC_53_0b9_BUILD1
-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
-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
-bfa8f90200d10fb26feb01967dc8a95736b6769a FENNEC_54_0b1_RELEASE
-cf76e00dcd6f142acf5b49f8beeb0ac95b2afa31 FIREFOX_54_0b1_BUILD1
-cf76e00dcd6f142acf5b49f8beeb0ac95b2afa31 FIREFOX_54_0b1_RELEASE
-ca3c6131b6eadf753445b3cd7a54e29b41ab11aa FIREFOX_54_0b2_BUILD1
-ca3c6131b6eadf753445b3cd7a54e29b41ab11aa FIREFOX_54_0b2_RELEASE
-ca3c6131b6eadf753445b3cd7a54e29b41ab11aa FENNEC_54_0b2_BUILD1
-ca3c6131b6eadf753445b3cd7a54e29b41ab11aa FENNEC_54_0b2_RELEASE
-0b1c079a2a4b826b217ec7d3c7446ef942e4fc0e FIREFOX_54_0b3_BUILD1
-0b1c079a2a4b826b217ec7d3c7446ef942e4fc0e FIREFOX_54_0b3_RELEASE
-8a7f650cff30f54e60e2a55f56c2e12222352f69 FIREFOX_54_0b4_BUILD1
-8a7f650cff30f54e60e2a55f56c2e12222352f69 FIREFOX_54_0b4_RELEASE
-06bf49fb579575e4813aa54127f67c22964c822b FIREFOX_54_0b5_BUILD1
-06bf49fb579575e4813aa54127f67c22964c822b FIREFOX_54_0b5_RELEASE
-8a7f650cff30f54e60e2a55f56c2e12222352f69 FENNEC_54_0b4_BUILD1
-8a7f650cff30f54e60e2a55f56c2e12222352f69 FENNEC_54_0b4_RELEASE
-798ee0e6f73eaed68e3f3968a20e9ae5c7a82718 FIREFOX_54_0b6_BUILD1
-798ee0e6f73eaed68e3f3968a20e9ae5c7a82718 FIREFOX_54_0b6_RELEASE
-798ee0e6f73eaed68e3f3968a20e9ae5c7a82718 FENNEC_54_0b6_BUILD1
-798ee0e6f73eaed68e3f3968a20e9ae5c7a82718 FENNEC_54_0b6_RELEASE
-8b7e2a303954352189cf0e9772f35aed06953fa5 FIREFOX_54_0b7_BUILD1
-8b7e2a303954352189cf0e9772f35aed06953fa5 FIREFOX_54_0b7_RELEASE
-9bef2dfbd584c0f3ae52953bfc3aed64e308960d FIREFOX_54_0b8_BUILD1
-9bef2dfbd584c0f3ae52953bfc3aed64e308960d FIREFOX_54_0b8_RELEASE
-9bef2dfbd584c0f3ae52953bfc3aed64e308960d FENNEC_54_0b8_BUILD1
-9bef2dfbd584c0f3ae52953bfc3aed64e308960d FENNEC_54_0b8_RELEASE
-54f218cec92ffcc2cc8160ed80c58ffe8b6c268d FIREFOX_54_0b9_BUILD1
-54f218cec92ffcc2cc8160ed80c58ffe8b6c268d FIREFOX_54_0b9_RELEASE
-a6edfa473c7dde50edc14a85374eb400e5ada494 FIREFOX_54_0b10_BUILD1
-a6edfa473c7dde50edc14a85374eb400e5ada494 FIREFOX_54_0b10_RELEASE
-a6edfa473c7dde50edc14a85374eb400e5ada494 FENNEC_54_0b10_BUILD2
-a6edfa473c7dde50edc14a85374eb400e5ada494 FENNEC_54_0b10_RELEASE
-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
-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
-803f16362c14a488b1923b184859f8265f63731f FIREFOX_55_0b2_RELEASE
-be4a0ad5d6cab12fb89495d020532040b91be1f4 FIREFOX_55_0b3_BUILD1
-be4a0ad5d6cab12fb89495d020532040b91be1f4 FIREFOX_55_0b3_RELEASE
-be4a0ad5d6cab12fb89495d020532040b91be1f4 FENNEC_55_0b3_BUILD1
-be4a0ad5d6cab12fb89495d020532040b91be1f4 FENNEC_55_0b3_RELEASE
-0a6a0148a61c5b2255f8b4272634efc1d1bd0c98 FIREFOX_55_0b4_BUILD2
-0a6a0148a61c5b2255f8b4272634efc1d1bd0c98 FIREFOX_55_0b4_RELEASE
-af94af58d1f315f475fbe831bb48aecbeb9a0c61 FIREFOX_55_0b5_BUILD1
-af94af58d1f315f475fbe831bb48aecbeb9a0c61 FIREFOX_55_0b5_RELEASE
-af94af58d1f315f475fbe831bb48aecbeb9a0c61 FENNEC_55_0b5_BUILD1
-af94af58d1f315f475fbe831bb48aecbeb9a0c61 FENNEC_55_0b5_RELEASE
-bfd96be70455cba0fdb82593d10395dd84dfa270 FIREFOX_55_0b6_BUILD1
-bfd96be70455cba0fdb82593d10395dd84dfa270 FIREFOX_55_0b6_RELEASE
-1ae7e516e5dae3c0b537251781e1adeb50783131 FIREFOX_55_0b7_BUILD1
-1ae7e516e5dae3c0b537251781e1adeb50783131 FIREFOX_55_0b7_RELEASE
-1ae7e516e5dae3c0b537251781e1adeb50783131 FENNEC_55_0b7_BUILD1
-1ae7e516e5dae3c0b537251781e1adeb50783131 FENNEC_55_0b7_RELEASE
-0a457907494285ecf2e1745b222436d775476d17 FIREFOX_55_0b8_BUILD1
-0a457907494285ecf2e1745b222436d775476d17 FIREFOX_55_0b8_RELEASE
-0a457907494285ecf2e1745b222436d775476d17 FENNEC_55_0b8_BUILD1
-0a457907494285ecf2e1745b222436d775476d17 FENNEC_55_0b8_RELEASE
-91e10e2411762dea81d5df70d9fefe96fe619353 FIREFOX_55_0b9_BUILD2
-91e10e2411762dea81d5df70d9fefe96fe619353 FIREFOX_55_0b9_RELEASE
-e26b1f5d635e2b62ba99f5ec90a0c10509a6eee9 FIREFOX_55_0b10_BUILD1
-e26b1f5d635e2b62ba99f5ec90a0c10509a6eee9 FIREFOX_55_0b10_RELEASE
-e26b1f5d635e2b62ba99f5ec90a0c10509a6eee9 FENNEC_55_0b10_BUILD1
-e26b1f5d635e2b62ba99f5ec90a0c10509a6eee9 FENNEC_55_0b10_RELEASE
-e5f14b9ae6c4c1e0ff1c430503671289120db203 FIREFOX_55_0b11_BUILD1
-e5f14b9ae6c4c1e0ff1c430503671289120db203 FIREFOX_55_0b11_RELEASE
+320642944e42a889db13c6c55b404e32319d4de6 FIREFOX_BETA_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
@@ -3,26 +3,15 @@
 module.exports = {
   "rules": {
     // 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
@@ -585,17 +585,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/SelectionManager.cpp
+++ b/accessible/base/SelectionManager.cpp
@@ -43,60 +43,59 @@ SelectionManager::SelectionManager() :
   mCaretOffset(-1), mAccWithCaret(nullptr)
 {
 
 }
 
 void
 SelectionManager::ClearControlSelectionListener()
 {
-  if (!mCurrCtrlFrame)
-    return;
-
-  const nsFrameSelection* frameSel = mCurrCtrlFrame->GetConstFrameSelection();
-  NS_ASSERTION(frameSel, "No frame selection for the element!");
-
-  mCurrCtrlFrame = nullptr;
-  if (!frameSel)
-    return;
 
   // Remove 'this' registered as selection listener for the normal selection.
-  Selection* normalSel = frameSel->GetSelection(SelectionType::eNormal);
-  normalSel->RemoveSelectionListener(this);
+  nsCOMPtr<nsISelection> normalSel = do_QueryReferent(mCurrCtrlNormalSel);
+  if (normalSel) {
+    normalSel->AsSelection()->RemoveSelectionListener(this);
+    mCurrCtrlNormalSel = nullptr;
+  }
 
   // Remove 'this' registered as selection listener for the spellcheck
   // selection.
-  Selection* spellSel = frameSel->GetSelection(SelectionType::eSpellCheck);
-  spellSel->RemoveSelectionListener(this);
+  nsCOMPtr<nsISelection> spellSel = do_QueryReferent(mCurrCtrlSpellSel);
+  if (spellSel) {
+    spellSel->AsSelection()->RemoveSelectionListener(this);
+    mCurrCtrlSpellSel = nullptr;
+  }
 }
 
 void
 SelectionManager::SetControlSelectionListener(dom::Element* aFocusedElm)
 {
   // When focus moves such that the caret is part of a new frame selection
   // this removes the old selection listener and attaches a new one for
   // the current focus.
   ClearControlSelectionListener();
 
-  mCurrCtrlFrame = aFocusedElm->GetPrimaryFrame();
-  if (!mCurrCtrlFrame)
+  nsIFrame* controlFrame = aFocusedElm->GetPrimaryFrame();
+  if (!controlFrame)
     return;
 
-  const nsFrameSelection* frameSel = mCurrCtrlFrame->GetConstFrameSelection();
+  const nsFrameSelection* frameSel = controlFrame->GetConstFrameSelection();
   NS_ASSERTION(frameSel, "No frame selection for focused element!");
   if (!frameSel)
     return;
 
   // Register 'this' as selection listener for the normal selection.
-  Selection* normalSel = frameSel->GetSelection(SelectionType::eNormal);
-  normalSel->AddSelectionListener(this);
+  nsCOMPtr<nsISelection> normalSel = frameSel->GetSelection(SelectionType::eNormal);
+  normalSel->AsSelection()->AddSelectionListener(this);
+  mCurrCtrlNormalSel = do_GetWeakReference(normalSel);
 
   // Register 'this' as selection listener for the spell check selection.
-  Selection* spellSel = frameSel->GetSelection(SelectionType::eSpellCheck);
-  spellSel->AddSelectionListener(this);
+  nsCOMPtr<nsISelection> spellSel = frameSel->GetSelection(SelectionType::eSpellCheck);
+  spellSel->AsSelection()->AddSelectionListener(this);
+  mCurrCtrlSpellSel = do_GetWeakReference(spellSel);
 }
 
 void
 SelectionManager::AddDocSelectionListener(nsIPresShell* aPresShell)
 {
   const nsFrameSelection* frameSel = aPresShell->ConstFrameSelection();
 
   // Register 'this' as selection listener for the normal selection.
--- a/accessible/base/SelectionManager.h
+++ b/accessible/base/SelectionManager.h
@@ -116,17 +116,18 @@ protected:
 
   /**
    * Process DOM selection change. Fire selection and caret move events.
    */
   void ProcessSelectionChanged(SelData* aSelData);
 
 private:
   // Currently focused control.
-  WeakFrame mCurrCtrlFrame;
   int32_t mCaretOffset;
   HyperTextAccessible* mAccWithCaret;
+  nsWeakPtr mCurrCtrlNormalSel;
+  nsWeakPtr mCurrCtrlSpellSel;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- 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
@@ -439,17 +439,17 @@ nsCoreUtils::IsErrorPage(nsIDocument *aD
 {
   nsIURI *uri = aDocument->GetDocumentURI();
   bool isAboutScheme = false;
   uri->SchemeIs("about", &isAboutScheme);
   if (!isAboutScheme)
     return false;
 
   nsAutoCString path;
-  uri->GetPath(path);
+  uri->GetPathQueryRef(path);
 
   NS_NAMED_LITERAL_CSTRING(neterror, "neterror");
   NS_NAMED_LITERAL_CSTRING(certerror, "certerror");
 
   return StringBeginsWith(path, neterror) || StringBeginsWith(path, certerror);
 }
 
 bool
@@ -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)
 {
@@ -1323,16 +1333,18 @@ DocAccessible::UnbindFromDocument(Access
 #endif
   }
 
   // Remove an accessible from node-to-accessible map if it exists there.
   if (aAccessible->IsNodeMapEntry() &&
       mNodeToAccessibleMap.Get(aAccessible->GetNode()) == aAccessible)
     mNodeToAccessibleMap.Remove(aAccessible->GetNode());
 
+  aAccessible->mStateFlags |= eIsNotInDocument;
+
   // Update XPCOM part.
   xpcAccessibleDocument* xpcDoc = GetAccService()->GetCachedXPCDocument(this);
   if (xpcDoc)
     xpcDoc->NotifyOfShutdown(aAccessible);
 
   void* uniqueID = aAccessible->UniqueID();
 
   NS_ASSERTION(!aAccessible->IsDefunct(), "Shutdown the shutdown accessible!");
@@ -2092,21 +2104,41 @@ DocAccessible::DoARIAOwnsRelocation(Acce
     }
 
 #ifdef A11Y_LOG
   logging::TreeInfo("aria owns traversal", logging::eVerbose,
                     "candidate", child, nullptr);
 #endif
 
     // 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
     }
 
@@ -2137,17 +2169,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();
@@ -2159,33 +2190,50 @@ 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) {
+      MoveChild(child, origContainer, idxInParent);
+    } 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)
--- 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
@@ -1,65 +1,65 @@
 /* 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/. */
 
 /* exported AccessFu */
 
-'use strict';
+"use strict";
 
 const {utils: Cu, interfaces: Ci} = Components;
 
-this.EXPORTED_SYMBOLS = ['AccessFu']; // jshint ignore:line
+this.EXPORTED_SYMBOLS = ["AccessFu"]; // jshint ignore:line
 
-Cu.import('resource://gre/modules/Services.jsm');
-Cu.import('resource://gre/modules/accessibility/Utils.jsm');
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/accessibility/Utils.jsm");
 
-if (Utils.MozBuildApp === 'mobile/android') {
-  Cu.import('resource://gre/modules/Messaging.jsm');
+if (Utils.MozBuildApp === "mobile/android") {
+  Cu.import("resource://gre/modules/Messaging.jsm");
 }
 
 const ACCESSFU_DISABLE = 0; // jshint ignore:line
 const ACCESSFU_ENABLE = 1;
 const ACCESSFU_AUTO = 2;
 
-const SCREENREADER_SETTING = 'accessibility.screenreader';
-const QUICKNAV_MODES_PREF = 'accessibility.accessfu.quicknav_modes';
-const QUICKNAV_INDEX_PREF = 'accessibility.accessfu.quicknav_index';
+const SCREENREADER_SETTING = "accessibility.screenreader";
+const QUICKNAV_MODES_PREF = "accessibility.accessfu.quicknav_modes";
+const QUICKNAV_INDEX_PREF = "accessibility.accessfu.quicknav_index";
 
 this.AccessFu = { // jshint ignore:line
   /**
    * Initialize chrome-layer accessibility functionality.
    * If accessibility is enabled on the platform, then a special accessibility
    * mode is started.
    */
   attach: function attach(aWindow) {
     Utils.init(aWindow);
 
-    if (Utils.MozBuildApp === 'mobile/android') {
-      EventDispatcher.instance.dispatch('Accessibility:Ready');
-      EventDispatcher.instance.registerListener(this, 'Accessibility:Settings');
+    if (Utils.MozBuildApp === "mobile/android") {
+      EventDispatcher.instance.dispatch("Accessibility:Ready");
+      EventDispatcher.instance.registerListener(this, "Accessibility:Settings");
     }
 
     this._activatePref = new PrefCache(
-      'accessibility.accessfu.activate', this._enableOrDisable.bind(this));
+      "accessibility.accessfu.activate", this._enableOrDisable.bind(this));
 
     this._enableOrDisable();
   },
 
   /**
    * Shut down chrome-layer accessibility functionality from the outside.
    */
   detach: function detach() {
     // Avoid disabling twice.
     if (this._enabled) {
       this._disable();
     }
-    if (Utils.MozBuildApp === 'mobile/android') {
-      EventDispatcher.instance.unregisterListener(this, 'Accessibility:Settings');
+    if (Utils.MozBuildApp === "mobile/android") {
+      EventDispatcher.instance.unregisterListener(this, "Accessibility:Settings");
     }
     delete this._activatePref;
     Utils.uninit();
   },
 
   /**
    * A lazy getter for event handler that binds the scope to AccessFu object.
    */
@@ -74,29 +74,29 @@ this.AccessFu = { // jshint ignore:line
    * with arrow keys.
    */
   _enable: function _enable() {
     if (this._enabled) {
       return;
     }
     this._enabled = true;
 
-    Cu.import('resource://gre/modules/accessibility/Utils.jsm');
-    Cu.import('resource://gre/modules/accessibility/PointerAdapter.jsm');
-    Cu.import('resource://gre/modules/accessibility/Presentation.jsm');
+    Cu.import("resource://gre/modules/accessibility/Utils.jsm");
+    Cu.import("resource://gre/modules/accessibility/PointerAdapter.jsm");
+    Cu.import("resource://gre/modules/accessibility/Presentation.jsm");
 
     for (let mm of Utils.AllMessageManagers) {
       this._addMessageListeners(mm);
       this._loadFrameScript(mm);
     }
 
     // Add stylesheet
-    let stylesheetURL = 'chrome://global/content/accessibility/AccessFu.css';
+    let stylesheetURL = "chrome://global/content/accessibility/AccessFu.css";
     let stylesheet = Utils.win.document.createProcessingInstruction(
-      'xml-stylesheet', 'href="' + stylesheetURL + '" type="text/css"');
+      "xml-stylesheet", `href="${stylesheetURL}" type="text/css"`);
     Utils.win.document.insertBefore(stylesheet, Utils.win.document.firstChild);
     this.stylesheet = Cu.getWeakReference(stylesheet);
 
 
     // Populate quicknav modes
     this._quicknavModesPref =
       new PrefCache(QUICKNAV_MODES_PREF, (aName, aValue, aFirstRun) => {
         this.Input.quickNavMode.updateModes(aValue);
@@ -108,139 +108,139 @@ this.AccessFu = { // jshint ignore:line
 
     this._quicknavCurrentModePref =
       new PrefCache(QUICKNAV_INDEX_PREF, (aName, aValue) => {
         this.Input.quickNavMode.updateCurrentMode(Number(aValue));
       }, true);
 
     // Check for output notification
     this._notifyOutputPref =
-      new PrefCache('accessibility.accessfu.notify_output');
+      new PrefCache("accessibility.accessfu.notify_output");
 
 
     this.Input.start();
     Output.start();
     PointerAdapter.start();
 
-    if (Utils.MozBuildApp === 'mobile/android') {
+    if (Utils.MozBuildApp === "mobile/android") {
       EventDispatcher.instance.registerListener(this, [
-        'Accessibility:ActivateObject',
-        'Accessibility:Focus',
-        'Accessibility:LongPress',
-        'Accessibility:MoveByGranularity',
-        'Accessibility:NextObject',
-        'Accessibility:PreviousObject',
-        'Accessibility:ScrollBackward',
-        'Accessibility:ScrollForward',
+        "Accessibility:ActivateObject",
+        "Accessibility:Focus",
+        "Accessibility:LongPress",
+        "Accessibility:MoveByGranularity",
+        "Accessibility:NextObject",
+        "Accessibility:PreviousObject",
+        "Accessibility:ScrollBackward",
+        "Accessibility:ScrollForward",
       ]);
     }
 
-    Services.obs.addObserver(this, 'remote-browser-shown');
-    Services.obs.addObserver(this, 'inprocess-browser-shown');
-    Utils.win.addEventListener('TabOpen', this);
-    Utils.win.addEventListener('TabClose', this);
-    Utils.win.addEventListener('TabSelect', this);
+    Services.obs.addObserver(this, "remote-browser-shown");
+    Services.obs.addObserver(this, "inprocess-browser-shown");
+    Utils.win.addEventListener("TabOpen", this);
+    Utils.win.addEventListener("TabClose", this);
+    Utils.win.addEventListener("TabSelect", this);
 
     if (this.readyCallback) {
       this.readyCallback();
       delete this.readyCallback;
     }
 
-    Logger.info('AccessFu:Enabled');
+    Logger.info("AccessFu:Enabled");
   },
 
   /**
    * Disable AccessFu and return to default interaction mode.
    */
   _disable: function _disable() {
     if (!this._enabled) {
       return;
     }
 
     this._enabled = false;
 
     Utils.win.document.removeChild(this.stylesheet.get());
 
     for (let mm of Utils.AllMessageManagers) {
-      mm.sendAsyncMessage('AccessFu:Stop');
+      mm.sendAsyncMessage("AccessFu:Stop");
       this._removeMessageListeners(mm);
     }
 
     this.Input.stop();
     Output.stop();
     PointerAdapter.stop();
 
-    Utils.win.removeEventListener('TabOpen', this);
-    Utils.win.removeEventListener('TabClose', this);
-    Utils.win.removeEventListener('TabSelect', this);
+    Utils.win.removeEventListener("TabOpen", this);
+    Utils.win.removeEventListener("TabClose", this);
+    Utils.win.removeEventListener("TabSelect", this);
 
-    Services.obs.removeObserver(this, 'remote-browser-shown');
-    Services.obs.removeObserver(this, 'inprocess-browser-shown');
+    Services.obs.removeObserver(this, "remote-browser-shown");
+    Services.obs.removeObserver(this, "inprocess-browser-shown");
 
-    if (Utils.MozBuildApp === 'mobile/android') {
+    if (Utils.MozBuildApp === "mobile/android") {
       EventDispatcher.instance.unregisterListener(this, [
-        'Accessibility:ActivateObject',
-        'Accessibility:Focus',
-        'Accessibility:LongPress',
-        'Accessibility:MoveByGranularity',
-        'Accessibility:NextObject',
-        'Accessibility:PreviousObject',
-        'Accessibility:ScrollBackward',
-        'Accessibility:ScrollForward',
+        "Accessibility:ActivateObject",
+        "Accessibility:Focus",
+        "Accessibility:LongPress",
+        "Accessibility:MoveByGranularity",
+        "Accessibility:NextObject",
+        "Accessibility:PreviousObject",
+        "Accessibility:ScrollBackward",
+        "Accessibility:ScrollForward",
       ]);
     }
 
     delete this._quicknavModesPref;
     delete this._notifyOutputPref;
 
     if (this.doneCallback) {
       this.doneCallback();
       delete this.doneCallback;
     }
 
-    Logger.info('AccessFu:Disabled');
+    Logger.info("AccessFu:Disabled");
   },
 
   _enableOrDisable: function _enableOrDisable() {
     try {
       if (!this._activatePref) {
         return;
       }
       let activatePref = this._activatePref.value;
       if (activatePref == ACCESSFU_ENABLE ||
           this._systemPref && activatePref == ACCESSFU_AUTO) {
         this._enable();
       } else {
         this._disable();
       }
     } catch (x) {
-      dump('Error ' + x.message + ' ' + x.fileName + ':' + x.lineNumber);
+      dump("Error " + x.message + " " + x.fileName + ":" + x.lineNumber);
     }
   },
 
   receiveMessage: function receiveMessage(aMessage) {
     Logger.debug(() => {
-      return ['Recieved', aMessage.name, JSON.stringify(aMessage.json)];
+      return ["Recieved", aMessage.name, JSON.stringify(aMessage.json)];
     });
 
     switch (aMessage.name) {
-      case 'AccessFu:Ready':
+      case "AccessFu:Ready":
         let mm = Utils.getMessageManager(aMessage.target);
         if (this._enabled) {
-          mm.sendAsyncMessage('AccessFu:Start',
-                              {method: 'start', buildApp: Utils.MozBuildApp});
+          mm.sendAsyncMessage("AccessFu:Start",
+                              {method: "start", buildApp: Utils.MozBuildApp});
         }
         break;
-      case 'AccessFu:Present':
+      case "AccessFu:Present":
         this._output(aMessage.json, aMessage.target);
         break;
-      case 'AccessFu:Input':
+      case "AccessFu:Input":
         this.Input.setEditState(aMessage.json);
         break;
-      case 'AccessFu:DoScroll':
+      case "AccessFu:DoScroll":
         this.Input.doScroll(aMessage.json);
         break;
     }
   },
 
   _output: function _output(aPresentationData, aBrowser) {
     if (!Utils.isAliveAndVisible(
       Utils.AccService.getAccessibleFor(aBrowser))) {
@@ -254,139 +254,139 @@ this.AccessFu = { // jshint ignore:line
       try {
         Output[presenter.type](presenter.details, aBrowser);
       } catch (x) {
         Logger.logException(x);
       }
     }
 
     if (this._notifyOutputPref.value) {
-      Services.obs.notifyObservers(null, 'accessibility-output',
+      Services.obs.notifyObservers(null, "accessibility-output",
                                    JSON.stringify(aPresentationData));
     }
   },
 
   _loadFrameScript: function _loadFrameScript(aMessageManager) {
     if (this._processedMessageManagers.indexOf(aMessageManager) < 0) {
       aMessageManager.loadFrameScript(
-        'chrome://global/content/accessibility/content-script.js', true);
+        "chrome://global/content/accessibility/content-script.js", true);
       this._processedMessageManagers.push(aMessageManager);
     } else if (this._enabled) {
       // If the content-script is already loaded and AccessFu is enabled,
       // send an AccessFu:Start message.
-      aMessageManager.sendAsyncMessage('AccessFu:Start',
-        {method: 'start', buildApp: Utils.MozBuildApp});
+      aMessageManager.sendAsyncMessage("AccessFu:Start",
+        {method: "start", buildApp: Utils.MozBuildApp});
     }
   },
 
   _addMessageListeners: function _addMessageListeners(aMessageManager) {
-    aMessageManager.addMessageListener('AccessFu:Present', this);
-    aMessageManager.addMessageListener('AccessFu:Input', this);
-    aMessageManager.addMessageListener('AccessFu:Ready', this);
-    aMessageManager.addMessageListener('AccessFu:DoScroll', this);
+    aMessageManager.addMessageListener("AccessFu:Present", this);
+    aMessageManager.addMessageListener("AccessFu:Input", this);
+    aMessageManager.addMessageListener("AccessFu:Ready", this);
+    aMessageManager.addMessageListener("AccessFu:DoScroll", this);
   },
 
   _removeMessageListeners: function _removeMessageListeners(aMessageManager) {
-    aMessageManager.removeMessageListener('AccessFu:Present', this);
-    aMessageManager.removeMessageListener('AccessFu:Input', this);
-    aMessageManager.removeMessageListener('AccessFu:Ready', this);
-    aMessageManager.removeMessageListener('AccessFu:DoScroll', this);
+    aMessageManager.removeMessageListener("AccessFu:Present", this);
+    aMessageManager.removeMessageListener("AccessFu:Input", this);
+    aMessageManager.removeMessageListener("AccessFu:Ready", this);
+    aMessageManager.removeMessageListener("AccessFu:DoScroll", this);
   },
 
   _handleMessageManager: function _handleMessageManager(aMessageManager) {
     if (this._enabled) {
       this._addMessageListeners(aMessageManager);
     }
     this._loadFrameScript(aMessageManager);
   },
 
-  onEvent: function (event, data, callback) {
+  onEvent: function(event, data, callback) {
     switch (event) {
-      case 'Accessibility:Settings':
+      case "Accessibility:Settings":
         this._systemPref = data.enabled;
         this._enableOrDisable();
         break;
-      case 'Accessibility:NextObject':
-      case 'Accessibility:PreviousObject': {
+      case "Accessibility:NextObject":
+      case "Accessibility:PreviousObject": {
         let rule = data ?
           data.rule.substr(0, 1).toUpperCase() + data.rule.substr(1).toLowerCase() :
-          'Simple';
-        let method = event.replace(/Accessibility:(\w+)Object/, 'move$1');
-        this.Input.moveCursor(method, rule, 'gesture');
+          "Simple";
+        let method = event.replace(/Accessibility:(\w+)Object/, "move$1");
+        this.Input.moveCursor(method, rule, "gesture");
         break;
       }
-      case 'Accessibility:ActivateObject':
+      case "Accessibility:ActivateObject":
         this.Input.activateCurrent(data);
         break;
-      case 'Accessibility:LongPress':
+      case "Accessibility:LongPress":
         this.Input.sendContextMenuMessage();
         break;
-      case 'Accessibility:ScrollForward':
-        this.Input.androidScroll('forward');
+      case "Accessibility:ScrollForward":
+        this.Input.androidScroll("forward");
         break;
-      case 'Accessibility:ScrollBackward':
-        this.Input.androidScroll('backward');
+      case "Accessibility:ScrollBackward":
+        this.Input.androidScroll("backward");
         break;
-      case 'Accessibility:Focus':
+      case "Accessibility:Focus":
         this._focused = data.gainFocus;
         if (this._focused) {
           this.autoMove({ forcePresent: true, noOpIfOnScreen: true });
         }
         break;
-      case 'Accessibility:MoveByGranularity':
+      case "Accessibility:MoveByGranularity":
         this.Input.moveByGranularity(data);
         break;
     }
   },
 
   observe: function observe(aSubject, aTopic, aData) {
     switch (aTopic) {
-      case 'remote-browser-shown':
-      case 'inprocess-browser-shown':
+      case "remote-browser-shown":
+      case "inprocess-browser-shown":
       {
         // Ignore notifications that aren't from a Browser
         let frameLoader = aSubject.QueryInterface(Ci.nsIFrameLoader);
         if (!frameLoader.ownerIsMozBrowserFrame) {
           return;
         }
         this._handleMessageManager(frameLoader.messageManager);
         break;
       }
     }
   },
 
   _handleEvent: function _handleEvent(aEvent) {
     switch (aEvent.type) {
-      case 'TabOpen':
+      case "TabOpen":
       {
         let mm = Utils.getMessageManager(aEvent.target);
         this._handleMessageManager(mm);
         break;
       }
-      case 'TabClose':
+      case "TabClose":
       {
         let mm = Utils.getMessageManager(aEvent.target);
         let mmIndex = this._processedMessageManagers.indexOf(mm);
         if (mmIndex > -1) {
           this._removeMessageListeners(mm);
           this._processedMessageManagers.splice(mmIndex, 1);
         }
         break;
       }
-      case 'TabSelect':
+      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;
@@ -394,17 +394,17 @@ this.AccessFu = { // jshint ignore:line
         }
         break;
       }
     }
   },
 
   autoMove: function autoMove(aOptions) {
     let mm = Utils.getMessageManager(Utils.CurrentBrowser);
-    mm.sendAsyncMessage('AccessFu:AutoMove', aOptions);
+    mm.sendAsyncMessage("AccessFu:AutoMove", aOptions);
   },
 
   announce: function announce(aAnnouncement) {
     this._output(Presentation.announce(aAnnouncement), Utils.CurrentBrowser);
   },
 
   // So we don't enable/disable twice
   _enabled: false,
@@ -445,61 +445,61 @@ this.AccessFu = { // jshint ignore:line
       return bounds.expandToIntegers();
     }
 };
 
 var Output = {
   brailleState: {
     startOffset: 0,
     endOffset: 0,
-    text: '',
+    text: "",
     selectionStart: 0,
     selectionEnd: 0,
 
     init: function init(aOutput) {
-      if (aOutput && 'output' in aOutput) {
+      if (aOutput && "output" in aOutput) {
         this.startOffset = aOutput.startOffset;
         this.endOffset = aOutput.endOffset;
         // We need to append a space at the end so that the routing key
         // corresponding to the end of the output (i.e. the space) can be hit to
         // move the caret there.
-        this.text = aOutput.output + ' ';
-        this.selectionStart = typeof aOutput.selectionStart === 'number' ?
+        this.text = aOutput.output + " ";
+        this.selectionStart = typeof aOutput.selectionStart === "number" ?
                               aOutput.selectionStart : this.selectionStart;
-        this.selectionEnd = typeof aOutput.selectionEnd === 'number' ?
+        this.selectionEnd = typeof aOutput.selectionEnd === "number" ?
                             aOutput.selectionEnd : this.selectionEnd;
 
         return { text: this.text,
                  selectionStart: this.selectionStart,
                  selectionEnd: this.selectionEnd };
       }
 
       return null;
     },
 
     adjustText: function adjustText(aText) {
       let newBraille = [];
       let braille = {};
 
       let prefix = this.text.substring(0, this.startOffset).trim();
       if (prefix) {
-        prefix += ' ';
+        prefix += " ";
         newBraille.push(prefix);
       }
 
       newBraille.push(aText);
 
       let suffix = this.text.substring(this.endOffset).trim();
       if (suffix) {
-        suffix = ' ' + suffix;
+        suffix = " " + suffix;
         newBraille.push(suffix);
       }
 
       this.startOffset = braille.startOffset = prefix.length;
-      this.text = braille.text = newBraille.join('') + ' ';
+      this.text = braille.text = newBraille.join("") + " ";
       this.endOffset = braille.endOffset = braille.text.length - suffix.length;
       braille.selectionStart = this.selectionStart;
       braille.selectionEnd = this.selectionEnd;
 
       return braille;
     },
 
     adjustSelection: function adjustSelection(aSelection) {
@@ -513,93 +513,93 @@ var Output = {
       this.selectionEnd = braille.selectionEnd =
         aSelection.selectionEnd + this.startOffset;
 
       return braille;
     }
   },
 
   start: function start() {
-    Cu.import('resource://gre/modules/Geometry.jsm');
+    Cu.import("resource://gre/modules/Geometry.jsm");
   },
 
   stop: function stop() {
     if (this.highlightBox) {
       let highlightBox = this.highlightBox.get();
       if (highlightBox) {
         highlightBox.remove();
       }
       delete this.highlightBox;
     }
   },
 
   B2G: function B2G(aDetails) {
-    Utils.dispatchChromeEvent('accessibility-output', aDetails);
+    Utils.dispatchChromeEvent("accessibility-output", aDetails);
   },
 
   Visual: function Visual(aDetail, aBrowser) {
     switch (aDetail.eventType) {
-      case 'viewport-change':
-      case 'vc-change':
+      case "viewport-change":
+      case "vc-change":
       {
         let highlightBox = null;
         if (!this.highlightBox) {
           let doc = Utils.win.document;
           // Add highlight box
           highlightBox = Utils.win.document.
-            createElementNS('http://www.w3.org/1999/xhtml', 'div');
+            createElementNS("http://www.w3.org/1999/xhtml", "div");
           let parent = doc.body || doc.documentElement;
           parent.appendChild(highlightBox);
-          highlightBox.id = 'virtual-cursor-box';
+          highlightBox.id = "virtual-cursor-box";
 
           // Add highlight inset for inner shadow
           highlightBox.appendChild(
-            doc.createElementNS('http://www.w3.org/1999/xhtml', 'div'));
+            doc.createElementNS("http://www.w3.org/1999/xhtml", "div"));
 
           this.highlightBox = Cu.getWeakReference(highlightBox);
         } else {
           highlightBox = this.highlightBox.get();
         }
 
         let padding = aDetail.padding;
         let r = AccessFu.adjustContentBounds(aDetail.bounds, aBrowser, true);
 
         // First hide it to avoid flickering when changing the style.
-        highlightBox.classList.remove('show');
-        highlightBox.style.top = (r.top - padding) + 'px';
-        highlightBox.style.left = (r.left - padding) + 'px';
-        highlightBox.style.width = (r.width + padding*2) + 'px';
-        highlightBox.style.height = (r.height + padding*2) + 'px';
-        highlightBox.classList.add('show');
+        highlightBox.classList.remove("show");
+        highlightBox.style.top = (r.top - padding) + "px";
+        highlightBox.style.left = (r.left - padding) + "px";
+        highlightBox.style.width = (r.width + padding * 2) + "px";
+        highlightBox.style.height = (r.height + padding * 2) + "px";
+        highlightBox.classList.add("show");
 
         break;
       }
-      case 'tabstate-change':
+      case "tabstate-change":
       {
         let highlightBox = this.highlightBox ? this.highlightBox.get() : null;
         if (highlightBox) {
-          highlightBox.classList.remove('show');
+          highlightBox.classList.remove("show");
         }
         break;
       }
     }
   },
 
   Android: function Android(aDetails, aBrowser) {
     const ANDROID_VIEW_TEXT_CHANGED = 0x10;
     const ANDROID_VIEW_TEXT_SELECTION_CHANGED = 0x2000;
 
     for (let androidEvent of aDetails) {
-      androidEvent.type = 'Accessibility:Event';
+      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;
@@ -609,140 +609,140 @@ var Output = {
           break;
       }
 
       Utils.win.WindowEventDispatcher.sendRequest(androidEvent);
     }
   },
 
   Braille: function Braille(aDetails) {
-    Logger.debug('Braille output: ' + aDetails.output);
+    Logger.debug("Braille output: " + aDetails.output);
   }
 };
 
 var Input = {
   editState: {},
 
   start: function start() {
     // XXX: This is too disruptive on desktop for now.
     // Might need to add special modifiers.
-    if (Utils.MozBuildApp != 'browser') {
-      Utils.win.document.addEventListener('keypress', this, true);
+    if (Utils.MozBuildApp != "browser") {
+      Utils.win.document.addEventListener("keypress", this, true);
     }
-    Utils.win.addEventListener('mozAccessFuGesture', this, true);
+    Utils.win.addEventListener("mozAccessFuGesture", this, true);
   },
 
   stop: function stop() {
-    if (Utils.MozBuildApp != 'browser') {
-      Utils.win.document.removeEventListener('keypress', this, true);
+    if (Utils.MozBuildApp != "browser") {
+      Utils.win.document.removeEventListener("keypress", this, true);
     }
-    Utils.win.removeEventListener('mozAccessFuGesture', this, true);
+    Utils.win.removeEventListener("mozAccessFuGesture", this, true);
   },
 
   handleEvent: function Input_handleEvent(aEvent) {
     try {
       switch (aEvent.type) {
-      case 'keypress':
+      case "keypress":
         this._handleKeypress(aEvent);
         break;
-      case 'mozAccessFuGesture':
+      case "mozAccessFuGesture":
         this._handleGesture(aEvent.detail);
         break;
       }
     } catch (x) {
       Logger.logException(x);
     }
   },
 
   _handleGesture: function _handleGesture(aGesture) {
     let gestureName = aGesture.type + aGesture.touches.length;
-    Logger.debug('Gesture', aGesture.type,
-                 '(fingers: ' + aGesture.touches.length + ')');
+    Logger.debug("Gesture", aGesture.type,
+                 "(fingers: " + aGesture.touches.length + ")");
 
     switch (gestureName) {
-      case 'dwell1':
-      case 'explore1':
-        this.moveToPoint('Simple', aGesture.touches[0].x,
+      case "dwell1":
+      case "explore1":
+        this.moveToPoint("Simple", aGesture.touches[0].x,
           aGesture.touches[0].y);
         break;
-      case 'doubletap1':
+      case "doubletap1":
         this.activateCurrent();
         break;
-      case 'doubletaphold1':
-        Utils.dispatchChromeEvent('accessibility-control', 'quicknav-menu');
+      case "doubletaphold1":
+        Utils.dispatchChromeEvent("accessibility-control", "quicknav-menu");
         break;
-      case 'swiperight1':
-        this.moveCursor('moveNext', 'Simple', 'gestures');
+      case "swiperight1":
+        this.moveCursor("moveNext", "Simple", "gestures");
         break;
-      case 'swipeleft1':
-        this.moveCursor('movePrevious', 'Simple', 'gesture');
+      case "swipeleft1":
+        this.moveCursor("movePrevious", "Simple", "gesture");
         break;
-      case 'swipeup1':
+      case "swipeup1":
         this.moveCursor(
-          'movePrevious', this.quickNavMode.current, 'gesture', true);
+          "movePrevious", this.quickNavMode.current, "gesture", true);
         break;
-      case 'swipedown1':
-        this.moveCursor('moveNext', this.quickNavMode.current, 'gesture', true);
+      case "swipedown1":
+        this.moveCursor("moveNext", this.quickNavMode.current, "gesture", true);
         break;
-      case 'exploreend1':
-      case 'dwellend1':
+      case "exploreend1":
+      case "dwellend1":
         this.activateCurrent(null, true);
         break;
-      case 'swiperight2':
+      case "swiperight2":
         if (aGesture.edge) {
-          Utils.dispatchChromeEvent('accessibility-control',
-            'edge-swipe-right');
+          Utils.dispatchChromeEvent("accessibility-control",
+            "edge-swipe-right");
           break;
         }
         this.sendScrollMessage(-1, true);
         break;
-      case 'swipedown2':
+      case "swipedown2":
         if (aGesture.edge) {
-          Utils.dispatchChromeEvent('accessibility-control', 'edge-swipe-down');
+          Utils.dispatchChromeEvent("accessibility-control", "edge-swipe-down");
           break;
         }
         this.sendScrollMessage(-1);
         break;
-      case 'swipeleft2':
+      case "swipeleft2":
         if (aGesture.edge) {
-          Utils.dispatchChromeEvent('accessibility-control', 'edge-swipe-left');
+          Utils.dispatchChromeEvent("accessibility-control", "edge-swipe-left");
           break;
         }
         this.sendScrollMessage(1, true);
         break;
-      case 'swipeup2':
+      case "swipeup2":
         if (aGesture.edge) {
-          Utils.dispatchChromeEvent('accessibility-control', 'edge-swipe-up');
+          Utils.dispatchChromeEvent("accessibility-control", "edge-swipe-up");
           break;
         }
         this.sendScrollMessage(1);
         break;
-      case 'explore2':
+      case "explore2":
         Utils.CurrentBrowser.contentWindow.scrollBy(
           -aGesture.deltaX, -aGesture.deltaY);
         break;
-      case 'swiperight3':
-        this.moveCursor('moveNext', this.quickNavMode.current, 'gesture');
+      case "swiperight3":
+        this.moveCursor("moveNext", this.quickNavMode.current, "gesture");
         break;
-      case 'swipeleft3':
-        this.moveCursor('movePrevious', this.quickNavMode.current, 'gesture');
+      case "swipeleft3":
+        this.moveCursor("movePrevious", this.quickNavMode.current, "gesture");
         break;
-      case 'swipedown3':
+      case "swipedown3":
         this.quickNavMode.next();
-        AccessFu.announce('quicknav_' + this.quickNavMode.current);
+        AccessFu.announce("quicknav_" + this.quickNavMode.current);
         break;
-      case 'swipeup3':
+      case "swipeup3":
         this.quickNavMode.previous();
-        AccessFu.announce('quicknav_' + this.quickNavMode.current);
+        AccessFu.announce("quicknav_" + this.quickNavMode.current);
         break;
-      case 'tripletap3':
-        Utils.dispatchChromeEvent('accessibility-control', 'toggle-shade');
+      case "tripletap3":
+        Utils.dispatchChromeEvent("accessibility-control", "toggle-shade");
         break;
-      case 'tap2':
-        Utils.dispatchChromeEvent('accessibility-control', 'toggle-pause');
+      case "tap2":
+        Utils.dispatchChromeEvent("accessibility-control", "toggle-pause");
         break;
     }
   },
 
   _handleKeypress: function _handleKeypress(aEvent) {
     let target = aEvent.target;
 
     // Ignore keys with modifiers so the content could take advantage of them.
@@ -757,60 +757,60 @@ var Input = {
         // If it was pressed with meta, pass the key on without the meta.
         if (this.editState.editing) {
           return;
         }
 
         let key = String.fromCharCode(aEvent.charCode);
         try {
           let [methodName, rule] = this.keyMap[key];
-          this.moveCursor(methodName, rule, 'keyboard');
+          this.moveCursor(methodName, rule, "keyboard");
         } catch (x) {
           return;
         }
         break;
       case aEvent.DOM_VK_RIGHT:
         if (this.editState.editing) {
           if (!this.editState.atEnd) {
             // Don't move forward if caret is not at end of entry.
             // XXX: Fix for rtl
             return;
-          } else {
-            target.blur();
           }
+          target.blur();
+
         }
         this.moveCursor(aEvent.shiftKey ?
-          'moveLast' : 'moveNext', 'Simple', 'keyboard');
+          "moveLast" : "moveNext", "Simple", "keyboard");
         break;
       case aEvent.DOM_VK_LEFT:
         if (this.editState.editing) {
           if (!this.editState.atStart) {
             // Don't move backward if caret is not at start of entry.
             // XXX: Fix for rtl
             return;
-          } else {
-            target.blur();
           }
+          target.blur();
+
         }
         this.moveCursor(aEvent.shiftKey ?
-          'moveFirst' : 'movePrevious', 'Simple', 'keyboard');
+          "moveFirst" : "movePrevious", "Simple", "keyboard");
         break;
       case aEvent.DOM_VK_UP:
         if (this.editState.multiline) {
           if (!this.editState.atStart) {
             // Don't blur content if caret is not at start of text area.
             return;
-          } else {
-            target.blur();
           }
+          target.blur();
+
         }
 
-        if (Utils.MozBuildApp == 'mobile/android') {
+        if (Utils.MozBuildApp == "mobile/android") {
           // Return focus to native Android browser chrome.
-          Utils.win.WindowEventDispatcher.dispatch('ToggleChrome:Focus');
+          Utils.win.WindowEventDispatcher.dispatch("ToggleChrome:Focus");
         }
         break;
       case aEvent.DOM_VK_RETURN:
         if (this.editState.editing) {
           return;
         }
         this.activateCurrent();
         break;
@@ -821,137 +821,137 @@ var Input = {
     aEvent.preventDefault();
     aEvent.stopPropagation();
   },
 
   moveToPoint: function moveToPoint(aRule, aX, aY) {
     // XXX: Bug 1013408 - There is no alignment between the chrome window's
     // viewport size and the content viewport size in Android. This makes
     // sending mouse events beyond its bounds impossible.
-    if (Utils.MozBuildApp === 'mobile/android') {
+    if (Utils.MozBuildApp === "mobile/android") {
       let mm = Utils.getMessageManager(Utils.CurrentBrowser);
-      mm.sendAsyncMessage('AccessFu:MoveToPoint',
-        {rule: aRule, x: aX, y: aY, origin: 'top'});
+      mm.sendAsyncMessage("AccessFu:MoveToPoint",
+        {rule: aRule, x: aX, y: aY, origin: "top"});
     } else {
       let win = Utils.win;
-      Utils.winUtils.sendMouseEvent('mousemove',
+      Utils.winUtils.sendMouseEvent("mousemove",
         aX - win.mozInnerScreenX, aY - win.mozInnerScreenY, 0, 0, 0);
     }
   },
 
   moveCursor: function moveCursor(aAction, aRule, aInputType, aAdjustRange) {
     let mm = Utils.getMessageManager(Utils.CurrentBrowser);
-    mm.sendAsyncMessage('AccessFu:MoveCursor',
+    mm.sendAsyncMessage("AccessFu:MoveCursor",
                         { action: aAction, rule: aRule,
-                          origin: 'top', inputType: aInputType,
+                          origin: "top", inputType: aInputType,
                           adjustRange: aAdjustRange });
   },
 
   androidScroll: function androidScroll(aDirection) {
     let mm = Utils.getMessageManager(Utils.CurrentBrowser);
-    mm.sendAsyncMessage('AccessFu:AndroidScroll',
-                        { direction: aDirection, origin: 'top' });
+    mm.sendAsyncMessage("AccessFu:AndroidScroll",
+                        { direction: aDirection, origin: "top" });
   },
 
   moveByGranularity: function moveByGranularity(aDetails) {
     const GRANULARITY_PARAGRAPH = 8;
     const GRANULARITY_LINE = 4;
 
     if (!this.editState.editing) {
       if (aDetails.granularity & (GRANULARITY_PARAGRAPH | GRANULARITY_LINE)) {
-        this.moveCursor('move' + aDetails.direction, 'Simple', 'gesture');
+        this.moveCursor("move" + aDetails.direction, "Simple", "gesture");
         return;
       }
     } else {
       aDetails.atStart = this.editState.atStart;
       aDetails.atEnd = this.editState.atEnd;
     }
 
     let mm = Utils.getMessageManager(Utils.CurrentBrowser);
-    let type = this.editState.editing ? 'AccessFu:MoveCaret' :
-                                        'AccessFu:MoveByGranularity';
+    let type = this.editState.editing ? "AccessFu:MoveCaret" :
+                                        "AccessFu:MoveByGranularity";
     mm.sendAsyncMessage(type, aDetails);
   },
 
   activateCurrent: function activateCurrent(aData, aActivateIfKey = false) {
     let mm = Utils.getMessageManager(Utils.CurrentBrowser);
-    let offset = aData && typeof aData.keyIndex === 'number' ?
+    let offset = aData && typeof aData.keyIndex === "number" ?
                  aData.keyIndex - Output.brailleState.startOffset : -1;
 
-    mm.sendAsyncMessage('AccessFu:Activate',
+    mm.sendAsyncMessage("AccessFu:Activate",
                         {offset: offset, activateIfKey: aActivateIfKey});
   },
 
   sendContextMenuMessage: function sendContextMenuMessage() {
     let mm = Utils.getMessageManager(Utils.CurrentBrowser);
-    mm.sendAsyncMessage('AccessFu:ContextMenu', {});
+    mm.sendAsyncMessage("AccessFu:ContextMenu", {});
   },
 
   setEditState: function setEditState(aEditState) {
-    Logger.debug(() => { return ['setEditState', JSON.stringify(aEditState)] });
+    Logger.debug(() => { return ["setEditState", JSON.stringify(aEditState)] });
     this.editState = aEditState;
   },
 
   // XXX: This is here for backwards compatability with screen reader simulator
   // it should be removed when the extension is updated on amo.
   scroll: function scroll(aPage, aHorizontal) {
     this.sendScrollMessage(aPage, aHorizontal);
   },
 
   sendScrollMessage: function sendScrollMessage(aPage, aHorizontal) {
     let mm = Utils.getMessageManager(Utils.CurrentBrowser);
-    mm.sendAsyncMessage('AccessFu:Scroll',
-      {page: aPage, horizontal: aHorizontal, origin: 'top'});
+    mm.sendAsyncMessage("AccessFu:Scroll",
+      {page: aPage, horizontal: aHorizontal, origin: "top"});
   },
 
   doScroll: function doScroll(aDetails) {
     let horizontal = aDetails.horizontal;
     let page = aDetails.page;
     let p = AccessFu.adjustContentBounds(
       aDetails.bounds, Utils.CurrentBrowser, true).center();
     Utils.winUtils.sendWheelEvent(p.x, p.y,
       horizontal ? page : 0, horizontal ? 0 : page, 0,
       Utils.win.WheelEvent.DOM_DELTA_PAGE, 0, 0, 0, 0);
   },
 
   get keyMap() {
     delete this.keyMap;
     this.keyMap = {
-      a: ['moveNext', 'Anchor'],
-      A: ['movePrevious', 'Anchor'],
-      b: ['moveNext', 'Button'],
-      B: ['movePrevious', 'Button'],
-      c: ['moveNext', 'Combobox'],
-      C: ['movePrevious', 'Combobox'],
-      d: ['moveNext', 'Landmark'],
-      D: ['movePrevious', 'Landmark'],
-      e: ['moveNext', 'Entry'],
-      E: ['movePrevious', 'Entry'],
-      f: ['moveNext', 'FormElement'],
-      F: ['movePrevious', 'FormElement'],
-      g: ['moveNext', 'Graphic'],
-      G: ['movePrevious', 'Graphic'],
-      h: ['moveNext', 'Heading'],
-      H: ['movePrevious', 'Heading'],
-      i: ['moveNext', 'ListItem'],
-      I: ['movePrevious', 'ListItem'],
-      k: ['moveNext', 'Link'],
-      K: ['movePrevious', 'Link'],
-      l: ['moveNext', 'List'],
-      L: ['movePrevious', 'List'],
-      p: ['moveNext', 'PageTab'],
-      P: ['movePrevious', 'PageTab'],
-      r: ['moveNext', 'RadioButton'],
-      R: ['movePrevious', 'RadioButton'],
-      s: ['moveNext', 'Separator'],
-      S: ['movePrevious', 'Separator'],
-      t: ['moveNext', 'Table'],
-      T: ['movePrevious', 'Table'],
-      x: ['moveNext', 'Checkbox'],
-      X: ['movePrevious', 'Checkbox']
+      a: ["moveNext", "Anchor"],
+      A: ["movePrevious", "Anchor"],
+      b: ["moveNext", "Button"],
+      B: ["movePrevious", "Button"],
+      c: ["moveNext", "Combobox"],
+      C: ["movePrevious", "Combobox"],
+      d: ["moveNext", "Landmark"],
+      D: ["movePrevious", "Landmark"],
+      e: ["moveNext", "Entry"],
+      E: ["movePrevious", "Entry"],
+      f: ["moveNext", "FormElement"],
+      F: ["movePrevious", "FormElement"],
+      g: ["moveNext", "Graphic"],
+      G: ["movePrevious", "Graphic"],
+      h: ["moveNext", "Heading"],
+      H: ["movePrevious", "Heading"],
+      i: ["moveNext", "ListItem"],
+      I: ["movePrevious", "ListItem"],
+      k: ["moveNext", "Link"],
+      K: ["movePrevious", "Link"],
+      l: ["moveNext", "List"],
+      L: ["movePrevious", "List"],
+      p: ["moveNext", "PageTab"],
+      P: ["movePrevious", "PageTab"],
+      r: ["moveNext", "RadioButton"],
+      R: ["movePrevious", "RadioButton"],
+      s: ["moveNext", "Separator"],
+      S: ["movePrevious", "Separator"],
+      t: ["moveNext", "Table"],
+      T: ["movePrevious", "Table"],
+      x: ["moveNext", "Checkbox"],
+      X: ["movePrevious", "Checkbox"]
     };
 
     return this.keyMap;
   },
 
   quickNavMode: {
     get current() {
       return this.modes[this._currentIndex];
@@ -966,21 +966,21 @@ var Input = {
     next: function quickNavMode_next() {
       Services.prefs.setIntPref(QUICKNAV_INDEX_PREF,
         this._currentIndex + 1 >= this.modes.length ?
           0 : this._currentIndex + 1);
     },
 
     updateModes: function updateModes(aModes) {
       if (aModes) {
-        this.modes = aModes.split(',');
+        this.modes = aModes.split(",");
       } else {
         this.modes = [];
       }
     },
 
     updateCurrentMode: function updateCurrentMode(aModeIndex) {
-      Logger.debug('Quicknav mode:', this.modes[aModeIndex]);
+      Logger.debug("Quicknav mode:", this.modes[aModeIndex]);
       this._currentIndex = aModeIndex;
     }
   }
 };
 AccessFu.Input = Input;
--- a/accessible/jsat/Constants.jsm
+++ b/accessible/jsat/Constants.jsm
@@ -1,59 +1,59 @@
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
-this.EXPORTED_SYMBOLS = ['Roles', 'Events', 'Relations',
-                         'Filters', 'States', 'Prefilters'];
+this.EXPORTED_SYMBOLS = ["Roles", "Events", "Relations",
+                         "Filters", "States", "Prefilters"];
 
-function ConstantsMap (aObject, aPrefix, aMap = {}, aModifier = null) {
+function ConstantsMap(aObject, aPrefix, aMap = {}, aModifier = null) {
   let offset = aPrefix.length;
   for (var name in aObject) {
     if (name.indexOf(aPrefix) === 0) {
       aMap[name.slice(offset)] = aModifier ?
         aModifier(aObject[name]) : aObject[name];
     }
   }
 
   return aMap;
 }
 
 XPCOMUtils.defineLazyGetter(
-  this, 'Roles',
+  this, "Roles",
   function() {
-    return ConstantsMap(Ci.nsIAccessibleRole, 'ROLE_');
+    return ConstantsMap(Ci.nsIAccessibleRole, "ROLE_");
   });
 
 XPCOMUtils.defineLazyGetter(
-  this, 'Events',
+  this, "Events",
   function() {
-    return ConstantsMap(Ci.nsIAccessibleEvent, 'EVENT_');
+    return ConstantsMap(Ci.nsIAccessibleEvent, "EVENT_");
   });
 
 XPCOMUtils.defineLazyGetter(
-  this, 'Relations',
+  this, "Relations",
   function() {
-    return ConstantsMap(Ci.nsIAccessibleRelation, 'RELATION_');
+    return ConstantsMap(Ci.nsIAccessibleRelation, "RELATION_");
   });
 
 XPCOMUtils.defineLazyGetter(
-  this, 'Prefilters',
+  this, "Prefilters",
   function() {
-    return ConstantsMap(Ci.nsIAccessibleTraversalRule, 'PREFILTER_');
+    return ConstantsMap(Ci.nsIAccessibleTraversalRule, "PREFILTER_");
   });
 
 XPCOMUtils.defineLazyGetter(
-  this, 'Filters',
+  this, "Filters",
   function() {
-    return ConstantsMap(Ci.nsIAccessibleTraversalRule, 'FILTER_');
+    return ConstantsMap(Ci.nsIAccessibleTraversalRule, "FILTER_");
   });
 
 XPCOMUtils.defineLazyGetter(
-  this, 'States',
+  this, "States",
   function() {
-    let statesMap = ConstantsMap(Ci.nsIAccessibleStates, 'STATE_', {},
+    let statesMap = ConstantsMap(Ci.nsIAccessibleStates, "STATE_", {},
                                  (val) => { return { base: val, extended: 0 }; });
-    ConstantsMap(Ci.nsIAccessibleStates, 'EXT_STATE_', statesMap,
+    ConstantsMap(Ci.nsIAccessibleStates, "EXT_STATE_", statesMap,
                  (val) => { return { base: 0, extended: val }; });
     return statesMap;
   });
--- a/accessible/jsat/ContentControl.jsm
+++ b/accessible/jsat/ContentControl.jsm
@@ -1,175 +1,175 @@
 /* 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/. */
 
 var Ci = Components.interfaces;
 var Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, 'Services',
-  'resource://gre/modules/Services.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Utils',
-  'resource://gre/modules/accessibility/Utils.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Logger',
-  'resource://gre/modules/accessibility/Utils.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Roles',
-  'resource://gre/modules/accessibility/Constants.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'TraversalRules',
-  'resource://gre/modules/accessibility/Traversal.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'TraversalHelper',
-  'resource://gre/modules/accessibility/Traversal.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Presentation',
-  'resource://gre/modules/accessibility/Presentation.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, "Services",
+  "resource://gre/modules/Services.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Utils",
+  "resource://gre/modules/accessibility/Utils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Logger",
+  "resource://gre/modules/accessibility/Utils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Roles",
+  "resource://gre/modules/accessibility/Constants.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "TraversalRules",
+  "resource://gre/modules/accessibility/Traversal.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "TraversalHelper",
+  "resource://gre/modules/accessibility/Traversal.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Presentation",
+  "resource://gre/modules/accessibility/Presentation.jsm");
 
-this.EXPORTED_SYMBOLS = ['ContentControl'];
+this.EXPORTED_SYMBOLS = ["ContentControl"];
 
 const MOVEMENT_GRANULARITY_CHARACTER = 1;
 const MOVEMENT_GRANULARITY_WORD = 2;
 const MOVEMENT_GRANULARITY_PARAGRAPH = 8;
 
 this.ContentControl = function ContentControl(aContentScope) {
   this._contentScope = Cu.getWeakReference(aContentScope);
   this._childMessageSenders = new WeakMap();
 };
 
 this.ContentControl.prototype = {
-  messagesOfInterest: ['AccessFu:MoveCursor',
-                       'AccessFu:ClearCursor',
-                       'AccessFu:MoveToPoint',
-                       'AccessFu:AutoMove',
-                       'AccessFu:Activate',
-                       'AccessFu:MoveCaret',
-                       'AccessFu:MoveByGranularity',
-                       'AccessFu:AndroidScroll'],
+  messagesOfInterest: ["AccessFu:MoveCursor",
+                       "AccessFu:ClearCursor",
+                       "AccessFu:MoveToPoint",
+                       "AccessFu:AutoMove",
+                       "AccessFu:Activate",
+                       "AccessFu:MoveCaret",
+                       "AccessFu:MoveByGranularity",
+                       "AccessFu:AndroidScroll"],
 
   start: function cc_start() {
     let cs = this._contentScope.get();
     for (let message of this.messagesOfInterest) {
       cs.addMessageListener(message, this);
     }
-    cs.addEventListener('mousemove', this);
+    cs.addEventListener("mousemove", this);
   },
 
   stop: function cc_stop() {
     let cs = this._contentScope.get();
     for (let message of this.messagesOfInterest) {
       cs.removeMessageListener(message, this);
     }
-    cs.removeEventListener('mousemove', this);
+    cs.removeEventListener("mousemove", this);
   },
 
   get document() {
     return this._contentScope.get().content.document;
   },
 
   get window() {
     return this._contentScope.get().content;
   },
 
   get vc() {
     return Utils.getVirtualCursor(this.document);
   },
 
   receiveMessage: function cc_receiveMessage(aMessage) {
     Logger.debug(() => {
-      return ['ContentControl.receiveMessage',
+      return ["ContentControl.receiveMessage",
         aMessage.name,
         JSON.stringify(aMessage.json)];
     });
 
     // If we get an explicit message, we should immediately cancel any autoMove
     this.cancelAutoMove();
 
     try {
-      let func = this['handle' + aMessage.name.slice(9)]; // 'AccessFu:'.length
+      let func = this["handle" + aMessage.name.slice(9)]; // 'AccessFu:'.length
       if (func) {
         func.bind(this)(aMessage);
       } else {
-        Logger.warning('ContentControl: Unhandled message:', aMessage.name);
+        Logger.warning("ContentControl: Unhandled message:", aMessage.name);
       }
     } catch (x) {
       Logger.logException(
-        x, 'Error handling message: ' + JSON.stringify(aMessage.json));
+        x, "Error handling message: " + JSON.stringify(aMessage.json));
     }
   },
 
   handleAndroidScroll: function cc_handleAndroidScroll(aMessage) {
     let vc = this.vc;
     let position = vc.position;
 
-    if (aMessage.json.origin != 'child' && this.sendToChild(vc, aMessage)) {
+    if (aMessage.json.origin != "child" && this.sendToChild(vc, aMessage)) {
       // Forwarded succesfully to child cursor.
       return;
     }
 
     // Counter-intuitive, but scrolling backward (ie. up), actually should
     // increase range values.
-    if (this.adjustRange(position, aMessage.json.direction === 'backward')) {
+    if (this.adjustRange(position, aMessage.json.direction === "backward")) {
       return;
     }
 
-    this._contentScope.get().sendAsyncMessage('AccessFu:DoScroll',
+    this._contentScope.get().sendAsyncMessage("AccessFu:DoScroll",
       { bounds: Utils.getBounds(position, true),
-        page: aMessage.json.direction === 'forward' ? 1 : -1,
+        page: aMessage.json.direction === "forward" ? 1 : -1,
         horizontal: false });
   },
 
   handleMoveCursor: function cc_handleMoveCursor(aMessage) {
     let origin = aMessage.json.origin;
     let action = aMessage.json.action;
     let adjustRange = aMessage.json.adjustRange;
     let vc = this.vc;
 
-    if (origin != 'child' && this.sendToChild(vc, aMessage)) {
+    if (origin != "child" && this.sendToChild(vc, aMessage)) {
       // Forwarded succesfully to child cursor.
       return;
     }
 
-    if (adjustRange && this.adjustRange(vc.position, action === 'moveNext')) {
+    if (adjustRange && this.adjustRange(vc.position, action === "moveNext")) {
       return;
     }
 
     let moved = TraversalHelper.move(vc, action, aMessage.json.rule);
 
     if (moved) {
-      if (origin === 'child') {
+      if (origin === "child") {
         // We just stepped out of a child, clear child cursor.
         Utils.getMessageManager(aMessage.target).sendAsyncMessage(
-          'AccessFu:ClearCursor', {});
+          "AccessFu:ClearCursor", {});
       } else {
         // We potentially landed on a new child cursor. If so, we want to
         // either be on the first or last item in the child doc.
         let childAction = action;
-        if (action === 'moveNext') {
-          childAction = 'moveFirst';
-        } else if (action === 'movePrevious') {
-          childAction = 'moveLast';
+        if (action === "moveNext") {
+          childAction = "moveFirst";
+        } else if (action === "movePrevious") {
+          childAction = "moveLast";
         }
 
         // Attempt to forward move to a potential child cursor in our
         // new position.
         this.sendToChild(vc, aMessage, { action: childAction }, true);
       }
     } else if (!this._childMessageSenders.has(aMessage.target) &&
-               origin !== 'top') {
+               origin !== "top") {
       // We failed to move, and the message is not from a parent, so forward
       // to it.
       this.sendToParent(aMessage);
     } else {
-      this._contentScope.get().sendAsyncMessage('AccessFu:Present',
+      this._contentScope.get().sendAsyncMessage("AccessFu:Present",
         Presentation.noMove(action));
     }
   },
 
   handleEvent: function cc_handleEvent(aEvent) {
-    if (aEvent.type === 'mousemove') {
+    if (aEvent.type === "mousemove") {
       this.handleMoveToPoint(
-        { json: { x: aEvent.screenX, y: aEvent.screenY, rule: 'Simple' } });
+        { json: { x: aEvent.screenX, y: aEvent.screenY, rule: "Simple" } });
     }
     if (!Utils.getMessageManager(aEvent.target)) {
       aEvent.preventDefault();
     } else {
       aEvent.target.focus();
     }
   },
 
@@ -180,29 +180,29 @@ this.ContentControl.prototype = {
     let dpr = this.window.devicePixelRatio;
     this.vc.moveToPoint(rule, x * dpr, y * dpr, true);
   },
 
   handleClearCursor: function cc_handleClearCursor(aMessage) {
     let forwarded = this.sendToChild(this.vc, aMessage);
     this.vc.position = null;
     if (!forwarded) {
-      this._contentScope.get().sendAsyncMessage('AccessFu:CursorCleared');
+      this._contentScope.get().sendAsyncMessage("AccessFu:CursorCleared");
     }
     this.document.activeElement.blur();
   },
 
   handleAutoMove: function cc_handleAutoMove(aMessage) {
     this.autoMove(null, aMessage.json);
   },
 
   handleActivate: function cc_handleActivate(aMessage) {
     let activateAccessible = (aAccessible) => {
       Logger.debug(() => {
-        return ['activateAccessible', Logger.accessibleToString(aAccessible)];
+        return ["activateAccessible", Logger.accessibleToString(aAccessible)];
       });
       try {
         if (aMessage.json.activateIfKey &&
           !Utils.isActivatableOnFingerUp(aAccessible)) {
           // Only activate keys, don't do anything on other objects.
           return;
         }
       } catch (e) {
@@ -229,28 +229,28 @@ this.ContentControl.prototype = {
         let objX = {}, objY = {}, objW = {}, objH = {};
         aAccessible.getBounds(objX, objY, objW, objH);
 
         let x = Math.round((objX.value - docX.value) + objW.value / 2);
         let y = Math.round((objY.value - docY.value) + objH.value / 2);
 
         let node = aAccessible.DOMNode || aAccessible.parent.DOMNode;
 
-        for (let eventType of ['mousedown', 'mouseup']) {
-          let evt = this.document.createEvent('MouseEvents');
+        for (let eventType of ["mousedown", "mouseup"]) {
+          let evt = this.document.createEvent("MouseEvents");
           evt.initMouseEvent(eventType, true, true, this.window,
             x, y, 0, 0, 0, false, false, false, false, 0, null);
           node.dispatchEvent(evt);
         }
       }
 
       if (!Utils.isActivatableOnFingerUp(aAccessible)) {
         // Keys will typically have a sound of their own.
-        this._contentScope.get().sendAsyncMessage('AccessFu:Present',
-          Presentation.actionInvoked(aAccessible, 'click'));
+        this._contentScope.get().sendAsyncMessage("AccessFu:Present",
+          Presentation.actionInvoked(aAccessible, "click"));
       }
     };
 
     let focusedAcc = Utils.AccService.getAccessibleFor(
       this.document.activeElement);
     if (focusedAcc && this.vc.position === focusedAcc
         && focusedAcc.role === Roles.ENTRY) {
       let accText = focusedAcc.QueryInterface(Ci.nsIAccessibleText);
@@ -298,116 +298,116 @@ this.ContentControl.prototype = {
       return false;
     }
 
     let elem = acc.DOMNode;
     if (!elem) {
       return false;
     }
 
-    if (elem.tagName === 'INPUT' && elem.type === 'range') {
-      elem[aStepUp ? 'stepDown' : 'stepUp']();
-      let evt = this.document.createEvent('UIEvent');
-      evt.initEvent('change', true, true);
+    if (elem.tagName === "INPUT" && elem.type === "range") {
+      elem[aStepUp ? "stepDown" : "stepUp"]();
+      let evt = this.document.createEvent("UIEvent");
+      evt.initEvent("change", true, true);
       elem.dispatchEvent(evt);
     } else {
-      let evt = this.document.createEvent('KeyboardEvent');
+      let evt = this.document.createEvent("KeyboardEvent");
       let keycode = aStepUp ? evt.DOM_VK_DOWN : evt.DOM_VK_UP;
       evt.initKeyEvent(
         "keypress", false, true, null, false, false, false, false, keycode, 0);
       elem.dispatchEvent(evt);
     }
 
     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;
     }
 
-    if (direction === 'Previous') {
+    if (direction === "Previous") {
       this.vc.movePreviousByText(granularity);
-    } else if (direction === 'Next') {
+    } else if (direction === "Next") {
       this.vc.moveNextByText(granularity);
     }
   },
 
   presentCaretChange: function cc_presentCaretChange(
     aText, aOldOffset, aNewOffset) {
     if (aOldOffset !== aNewOffset) {
       let msg = Presentation.textSelectionChanged(aText, aNewOffset, aNewOffset,
         aOldOffset, aOldOffset, true);
-      this._contentScope.get().sendAsyncMessage('AccessFu:Present', msg);
+      this._contentScope.get().sendAsyncMessage("AccessFu:Present", msg);
     }
   },
 
   handleMoveCaret: function cc_handleMoveCaret(aMessage) {
     let direction = aMessage.json.direction;
     let granularity = aMessage.json.granularity;
     let accessible = this.vc.position;
     let accText = accessible.QueryInterface(Ci.nsIAccessibleText);
     let oldOffset = accText.caretOffset;
     let text = accText.getText(0, accText.characterCount);
 
     let start = {}, end = {};
-    if (direction === 'Previous' && !aMessage.json.atStart) {
+    if (direction === "Previous" && !aMessage.json.atStart) {
       switch (granularity) {
         case MOVEMENT_GRANULARITY_CHARACTER:
           accText.caretOffset--;
           break;
         case MOVEMENT_GRANULARITY_WORD:
           accText.getTextBeforeOffset(accText.caretOffset,
             Ci.nsIAccessibleText.BOUNDARY_WORD_START, start, end);
           accText.caretOffset = end.value === accText.caretOffset ?
             start.value : end.value;
           break;
         case MOVEMENT_GRANULARITY_PARAGRAPH:
-          let startOfParagraph = text.lastIndexOf('\n', accText.caretOffset - 1);
+          let startOfParagraph = text.lastIndexOf("\n", accText.caretOffset - 1);
           accText.caretOffset = startOfParagraph !== -1 ? startOfParagraph : 0;
           break;
       }
-    } else if (direction === 'Next' && !aMessage.json.atEnd) {
+    } else if (direction === "Next" && !aMessage.json.atEnd) {
       switch (granularity) {
         case MOVEMENT_GRANULARITY_CHARACTER:
           accText.caretOffset++;
           break;
         case MOVEMENT_GRANULARITY_WORD:
           accText.getTextAtOffset(accText.caretOffset,
                                   Ci.nsIAccessibleText.BOUNDARY_WORD_END, start, end);
           accText.caretOffset = end.value;
           break;
         case MOVEMENT_GRANULARITY_PARAGRAPH:
-          accText.caretOffset = text.indexOf('\n', accText.caretOffset + 1);
+          accText.caretOffset = text.indexOf("\n", accText.caretOffset + 1);
           break;
       }
     }
 
     this.presentCaretChange(text, oldOffset, accText.caretOffset);
   },
 
   getChildCursor: function cc_getChildCursor(aAccessible) {
     let acc = aAccessible || this.vc.position;
     if (Utils.isAliveAndVisible(acc) && acc.role === Roles.INTERNAL_FRAME) {
       let domNode = acc.DOMNode;
       let mm = this._childMessageSenders.get(domNode, null);
       if (!mm) {
         mm = Utils.getMessageManager(domNode);
-        mm.addWeakMessageListener('AccessFu:MoveCursor', this);
+        mm.addWeakMessageListener("AccessFu:MoveCursor", this);
         this._childMessageSenders.set(domNode, mm);
       }
 
       return mm;
     }
 
     return null;
   },
@@ -421,29 +421,29 @@ this.ContentControl.prototype = {
     }
 
     if (aFocus) {
       position.takeFocus();
     }
 
     // XXX: This is a silly way to make a deep copy
     let newJSON = JSON.parse(JSON.stringify(aMessage.json));
-    newJSON.origin = 'parent';
+    newJSON.origin = "parent";
     for (let attr in aReplacer) {
       newJSON[attr] = aReplacer[attr];
     }
 
     mm.sendAsyncMessage(aMessage.name, newJSON);
     return true;
   },
 
   sendToParent: function cc_sendToParent(aMessage) {
     // XXX: This is a silly way to make a deep copy
     let newJSON = JSON.parse(JSON.stringify(aMessage.json));
-    newJSON.origin = 'child';
+    newJSON.origin = "child";
     aMessage.target.sendAsyncMessage(aMessage.name, newJSON);
   },
 
   /**
    * Move cursor and/or present its location.
    * aOptions could have any of these fields:
    * - delay: in ms, before actual move is performed. Another autoMove call
    *    would cancel it. Useful if we want to wait for a possible trailing
@@ -460,17 +460,17 @@ this.ContentControl.prototype = {
     let moveFunc = () => {
       let vc = this.vc;
       let acc = aAnchor;
       let rule = aOptions.onScreenOnly ?
         TraversalRules.SimpleOnScreen : TraversalRules.Simple;
       let forcePresentFunc = () => {
         if (aOptions.forcePresent) {
           this._contentScope.get().sendAsyncMessage(
-            'AccessFu:Present', Presentation.pivotChanged(
+            "AccessFu:Present", Presentation.pivotChanged(
               vc.position, null, Ci.nsIAccessiblePivot.REASON_NONE,
               vc.startOffset, vc.endOffset, false));
         }
       };
 
       if (aOptions.noOpIfOnScreen &&
         Utils.isAliveAndVisible(vc.position, true)) {
         forcePresentFunc();
@@ -478,30 +478,30 @@ this.ContentControl.prototype = {
       }
 
       if (aOptions.moveToFocused) {
         acc = Utils.AccService.getAccessibleFor(
           this.document.activeElement) || acc;
       }
 
       let moved = false;
-      let moveMethod = aOptions.moveMethod || 'moveNext'; // default is moveNext
-      let moveFirstOrLast = moveMethod in ['moveFirst', 'moveLast'];
+      let moveMethod = aOptions.moveMethod || "moveNext"; // default is moveNext
+      let moveFirstOrLast = moveMethod in ["moveFirst", "moveLast"];
       if (!moveFirstOrLast || acc) {
         // We either need next/previous or there is an anchor we need to use.
-        moved = vc[moveFirstOrLast ? 'moveNext' : moveMethod](rule, acc, true,
+        moved = vc[moveFirstOrLast ? "moveNext" : moveMethod](rule, acc, true,
                                                               false);
       }
       if (moveFirstOrLast && !moved) {
         // We move to first/last after no anchor move happened or succeeded.
         moved = vc[moveMethod](rule, false);
       }
 
       let sentToChild = this.sendToChild(vc, {
-        name: 'AccessFu:AutoMove',
+        name: "AccessFu:AutoMove",
         json: {
           moveMethod: aOptions.moveMethod,
           moveToFocused: aOptions.moveToFocused,
           noOpIfOnScreen: true,
           forcePresent: true
         }
       }, null, true);
 
--- a/accessible/jsat/EventManager.jsm
+++ b/accessible/jsat/EventManager.jsm
@@ -1,36 +1,36 @@
 /* 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';
+"use strict";
 
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 const TEXT_NODE = 3;
 
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Services',
-  'resource://gre/modules/Services.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Utils',
-  'resource://gre/modules/accessibility/Utils.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Logger',
-  'resource://gre/modules/accessibility/Utils.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Presentation',
-  'resource://gre/modules/accessibility/Presentation.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Roles',
-  'resource://gre/modules/accessibility/Constants.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Events',
-  'resource://gre/modules/accessibility/Constants.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'States',
-  'resource://gre/modules/accessibility/Constants.jsm');
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Services",
+  "resource://gre/modules/Services.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Utils",
+  "resource://gre/modules/accessibility/Utils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Logger",
+  "resource://gre/modules/accessibility/Utils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Presentation",
+  "resource://gre/modules/accessibility/Presentation.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Roles",
+  "resource://gre/modules/accessibility/Constants.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Events",
+  "resource://gre/modules/accessibility/Constants.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "States",
+  "resource://gre/modules/accessibility/Constants.jsm");
 
-this.EXPORTED_SYMBOLS = ['EventManager'];
+this.EXPORTED_SYMBOLS = ["EventManager"];
 
 this.EventManager = function EventManager(aContentScope, aContentControl) {
   this.contentScope = aContentScope;
   this.contentControl = aContentControl;
   this.addEventListener = this.contentScope.addEventListener.bind(
     this.contentScope);
   this.removeEventListener = this.contentScope.removeEventListener.bind(
     this.contentScope);
@@ -42,108 +42,108 @@ this.EventManager = function EventManage
 };
 
 this.EventManager.prototype = {
   editState: { editing: false },
 
   start: function start() {
     try {
       if (!this._started) {
-        Logger.debug('EventManager.start');
+        Logger.debug("EventManager.start");
 
         this._started = true;
 
         AccessibilityEventObserver.addListener(this);
 
         this.webProgress.addProgressListener(this,
           (Ci.nsIWebProgress.NOTIFY_STATE_ALL |
            Ci.nsIWebProgress.NOTIFY_LOCATION));
-        this.addEventListener('wheel', this, true);
-        this.addEventListener('scroll', this, true);
-        this.addEventListener('resize', this, true);
+        this.addEventListener("wheel", this, true);
+        this.addEventListener("scroll", this, true);
+        this.addEventListener("resize", this, true);
         this._preDialogPosition = new WeakMap();
       }
-      this.present(Presentation.tabStateChanged(null, 'newtab'));
+      this.present(Presentation.tabStateChanged(null, "newtab"));
 
     } catch (x) {
-      Logger.logException(x, 'Failed to start EventManager');
+      Logger.logException(x, "Failed to start EventManager");
     }
   },
 
   // XXX: Stop is not called when the tab is closed (|TabClose| event is too
   // late). It is only called when the AccessFu is disabled explicitly.
   stop: function stop() {
     if (!this._started) {
       return;
     }
-    Logger.debug('EventManager.stop');
+    Logger.debug("EventManager.stop");
     AccessibilityEventObserver.removeListener(this);
     try {
       this._preDialogPosition = new WeakMap();
       this.webProgress.removeProgressListener(this);
-      this.removeEventListener('wheel', this, true);
-      this.removeEventListener('scroll', this, true);
-      this.removeEventListener('resize', this, true);
+      this.removeEventListener("wheel", this, true);
+      this.removeEventListener("scroll", this, true);
+      this.removeEventListener("resize", this, true);
     } catch (x) {
       // contentScope is dead.
     } finally {
       this._started = false;
     }
   },
 
   handleEvent: function handleEvent(aEvent) {
     Logger.debug(() => {
-      return ['DOMEvent', aEvent.type];
+      return ["DOMEvent", aEvent.type];
     });
 
     try {
       switch (aEvent.type) {
-      case 'wheel':
+      case "wheel":
       {
         let delta = aEvent.deltaX || aEvent.deltaY;
         this.contentControl.autoMove(
          null,
-         { moveMethod: delta > 0 ? 'moveNext' : 'movePrevious',
+         { moveMethod: delta > 0 ? "moveNext" : "movePrevious",
            onScreenOnly: true, noOpIfOnScreen: true, delay: 500 });
         break;
       }
-      case 'scroll':
-      case 'resize':
+      case "scroll":
+      case "resize":
       {
         // the target could be an element, document or window
         let window = null;
         if (aEvent.target instanceof Ci.nsIDOMWindow)
           window = aEvent.target;
         else if (aEvent.target instanceof Ci.nsIDOMDocument)
           window = aEvent.target.defaultView;
         else if (aEvent.target instanceof Ci.nsIDOMElement)
           window = aEvent.target.ownerGlobal;
         this.present(Presentation.viewportChanged(window));
         break;
       }
       }
     } catch (x) {
-      Logger.logException(x, 'Error handling DOM event');
+      Logger.logException(x, "Error handling DOM event");
     }
   },
 
   handleAccEvent: function handleAccEvent(aEvent) {
     Logger.debug(() => {
-      return ['A11yEvent', Logger.eventToString(aEvent),
+      return ["A11yEvent", Logger.eventToString(aEvent),
               Logger.accessibleToString(aEvent.accessible)];
     });
 
     // Don't bother with non-content events in firefox.
-    if (Utils.MozBuildApp == 'browser' &&
+    if (Utils.MozBuildApp == "browser" &&
         aEvent.eventType != Events.VIRTUALCURSOR_CHANGED &&
         // XXX Bug 442005 results in DocAccessible::getDocType returning
         // NS_ERROR_FAILURE. Checking for aEvent.accessibleDocument.docType ==
         // 'window' does not currently work.
         (aEvent.accessibleDocument.DOMDocument.doctype &&
-         aEvent.accessibleDocument.DOMDocument.doctype.name === 'window')) {
+         aEvent.accessibleDocument.DOMDocument.doctype.name === "window")) {
       return;
     }
 
     switch (aEvent.eventType) {
       case Events.VIRTUALCURSOR_CHANGED:
       {
         let pivot = aEvent.accessible.
           QueryInterface(Ci.nsIAccessibleDocument).virtualCursor;
@@ -170,39 +170,39 @@ this.EventManager.prototype = {
       {
         let event = aEvent.QueryInterface(Ci.nsIAccessibleStateChangeEvent);
         let state = Utils.getState(event);
         if (state.contains(States.CHECKED)) {
           if (aEvent.accessible.role === Roles.SWITCH) {
             this.present(
               Presentation.
                 actionInvoked(aEvent.accessible,
-                              event.isEnabled ? 'on' : 'off'));
+                              event.isEnabled ? "on" : "off"));
           } else {
             this.present(
               Presentation.
                 actionInvoked(aEvent.accessible,
-                              event.isEnabled ? 'check' : 'uncheck'));
+                              event.isEnabled ? "check" : "uncheck"));
           }
         } else if (state.contains(States.SELECTED)) {
           this.present(
             Presentation.
               actionInvoked(aEvent.accessible,
-                            event.isEnabled ? 'select' : 'unselect'));
+                            event.isEnabled ? "select" : "unselect"));
         }
         break;
       }
       case Events.NAME_CHANGE:
       {
         let acc = aEvent.accessible;
         if (acc === this.contentControl.vc.position) {
           this.present(Presentation.nameChanged(acc));
         } else {
           let {liveRegion, isPolite} = this._handleLiveRegion(aEvent,
-            ['text', 'all']);
+            ["text", "all"]);
           if (liveRegion) {
             this.present(Presentation.nameChanged(acc, isPolite));
           }
         }
         break;
       }
       case Events.SCROLLING_START:
       {
@@ -227,22 +227,22 @@ this.EventManager.prototype = {
           }
         }
         break;
       }
       case Events.OBJECT_ATTRIBUTE_CHANGED:
       {
         let evt = aEvent.QueryInterface(
           Ci.nsIAccessibleObjectAttributeChangedEvent);
-        if (evt.changedAttribute.toString() !== 'aria-hidden') {
+        if (evt.changedAttribute.toString() !== "aria-hidden") {
           // Only handle aria-hidden attribute change.
           break;
         }
         let hidden = Utils.isHidden(aEvent.accessible);
-        this[hidden ? '_handleHide' : '_handleShow'](evt);
+        this[hidden ? "_handleHide" : "_handleShow"](evt);
         if (this.inTest) {
           this.sendMsgFunc("AccessFu:AriaHidden", { hidden: hidden });
         }
         break;
       }
       case Events.SHOW:
       {
         this._handleShow(aEvent);
@@ -253,17 +253,17 @@ this.EventManager.prototype = {
         let evt = aEvent.QueryInterface(Ci.nsIAccessibleHideEvent);
         this._handleHide(evt);
         break;
       }
       case Events.TEXT_INSERTED:
       case Events.TEXT_REMOVED:
       {
         let {liveRegion, isPolite} = this._handleLiveRegion(aEvent,
-          ['text', 'all']);
+          ["text", "all"]);
         if (aEvent.isFromUserInput || liveRegion) {
           // Handle all text mutations coming from the user or if they happen
           // on a live region.
           this._handleText(aEvent, liveRegion, isPolite);
         }
         break;
       }
       case Events.FOCUS:
@@ -304,17 +304,17 @@ this.EventManager.prototype = {
       {
         let position = this.contentControl.vc.position;
         let target = aEvent.accessible;
         if (position === target ||
             Utils.getEmbeddedControl(position) === target) {
           this.present(Presentation.valueChanged(target));
         } else {
           let {liveRegion, isPolite} = this._handleLiveRegion(aEvent,
-            ['text', 'all']);
+            ["text", "all"]);
           if (liveRegion) {
             this.present(Presentation.valueChanged(target, isPolite));
           }
         }
       }
     }
   },
 
@@ -363,32 +363,32 @@ this.EventManager.prototype = {
       this.sendMsgFunc("AccessFu:Input", editState);
     }
 
     this.editState = editState;
   },
 
   _handleShow: function _handleShow(aEvent) {
     let {liveRegion, isPolite} = this._handleLiveRegion(aEvent,
-      ['additions', 'all']);
+      ["additions", "all"]);
     // Only handle show if it is a relevant live region.
     if (!liveRegion) {
       return;
     }
     // Show for text is handled by the EVENT_TEXT_INSERTED handler.
     if (aEvent.accessible.role === Roles.TEXT_LEAF) {
       return;
     }
     this._dequeueLiveEvent(Events.HIDE, liveRegion);
     this.present(Presentation.liveRegion(liveRegion, isPolite, false));
   },
 
   _handleHide: function _handleHide(aEvent) {
     let {liveRegion, isPolite} = this._handleLiveRegion(
-      aEvent, ['removals', 'all']);
+      aEvent, ["removals", "all"]);
     let acc = aEvent.accessible;
     if (liveRegion) {
       // Hide for text is handled by the EVENT_TEXT_REMOVED handler.
       if (acc.role === Roles.TEXT_LEAF) {
         return;
       }
       this._queueLiveEvent(Events.HIDE, liveRegion, isPolite);
     } else {
@@ -412,30 +412,30 @@ this.EventManager.prototype = {
     }
   },
 
   _handleText: function _handleText(aEvent, aLiveRegion, aIsPolite) {
     let event = aEvent.QueryInterface(Ci.nsIAccessibleTextChangeEvent);
     let isInserted = event.isInserted;
     let txtIface = aEvent.accessible.QueryInterface(Ci.nsIAccessibleText);
 
-    let text = '';
+    let text = "";
     try {
       text = txtIface.getText(0, Ci.nsIAccessibleText.TEXT_OFFSET_END_OF_TEXT);
     } catch (x) {
       // XXX we might have gotten an exception with of a
       // zero-length text. If we did, ignore it (bug #749810).
       if (txtIface.characterCount) {
         throw x;
       }
     }
     // If there are embedded objects in the text, ignore them.
     // Assuming changes to the descendants would already be handled by the
     // show/hide event.
-    let modifiedText = event.modifiedText.replace(/\uFFFC/g, '');
+    let modifiedText = event.modifiedText.replace(/\uFFFC/g, "");
     if (modifiedText != event.modifiedText && !modifiedText.trim()) {
       return;
     }
 
     if (aLiveRegion) {
       if (aEvent.eventType === Events.TEXT_REMOVED) {
         this._queueLiveEvent(Events.TEXT_REMOVED, aLiveRegion, aIsPolite,
           modifiedText);
@@ -451,23 +451,23 @@ this.EventManager.prototype = {
   },
 
   _handleLiveRegion: function _handleLiveRegion(aEvent, aRelevant) {
     if (aEvent.isFromUserInput) {
       return {};
     }
     let parseLiveAttrs = function parseLiveAttrs(aAccessible) {
       let attrs = Utils.getAttributes(aAccessible);
-      if (attrs['container-live']) {
+      if (attrs["container-live"]) {
         return {
-          live: attrs['container-live'],
-          relevant: attrs['container-relevant'] || 'additions text',
-          busy: attrs['container-busy'],
-          atomic: attrs['container-atomic'],
-          memberOf: attrs['member-of']
+          live: attrs["container-live"],
+          relevant: attrs["container-relevant"] || "additions text",
+          busy: attrs["container-busy"],
+          atomic: attrs["container-atomic"],
+          memberOf: attrs["member-of"]
         };
       }
       return null;
     };
     // XXX live attributes are not set for hidden accessibles yet. Need to
     // climb up the tree to check for them.
     let getLiveAttributes = function getLiveAttributes(aEvent) {
       let liveAttrs = parseLiveAttrs(aEvent.accessible);
@@ -481,30 +481,30 @@ this.EventManager.prototype = {
           return liveAttrs;
         }
         parent = parent.parent
       }
       return {};
     };
     let {live, relevant, /* busy, atomic, memberOf */ } = getLiveAttributes(aEvent);
     // If container-live is not present or is set to |off| ignore the event.
-    if (!live || live === 'off') {
+    if (!live || live === "off") {
       return {};
     }
     // XXX: support busy and atomic.
 
     // Determine if the type of the mutation is relevant. Default is additions
     // and text.
     let isRelevant = Utils.matchAttributeValue(relevant, aRelevant);
     if (!isRelevant) {
       return {};
     }
     return {
       liveRegion: aEvent.accessible,
-      isPolite: live === 'polite'
+      isPolite: live === "polite"
     };
   },
 
   _dequeueLiveEvent: function _dequeueLiveEvent(aEventType, aLiveRegion) {
     let domNode = aLiveRegion.DOMNode;
     if (this._liveEventQueue && this._liveEventQueue.has(domNode)) {
       let queue = this._liveEventQueue.get(domNode);
       let nextEvent = queue[0];
@@ -537,39 +537,39 @@ this.EventManager.prototype = {
     }
   },
 
   present: function present(aPresentationData) {
     this.sendMsgFunc("AccessFu:Present", aPresentationData);
   },
 
   onStateChange: function onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
-    let tabstate = '';
+    let tabstate = "";
 
     let loadingState = Ci.nsIWebProgressListener.STATE_TRANSFERRING |
       Ci.nsIWebProgressListener.STATE_IS_DOCUMENT;
     let loadedState = Ci.nsIWebProgressListener.STATE_STOP |
       Ci.nsIWebProgressListener.STATE_IS_NETWORK;
 
     if ((aStateFlags & loadingState) == loadingState) {
-      tabstate = 'loading';
+      tabstate = "loading";
     } else if ((aStateFlags & loadedState) == loadedState &&
                !aWebProgress.isLoadingDocument) {
-      tabstate = 'loaded';
+      tabstate = "loaded";
     }
 
     if (tabstate) {
       let docAcc = Utils.AccService.getAccessibleFor(aWebProgress.DOMWindow.document);
       this.present(Presentation.tabStateChanged(docAcc, tabstate));
     }
   },
 
   onLocationChange: function onLocationChange(aWebProgress, aRequest, aLocation, aFlags) {
     let docAcc = Utils.AccService.getAccessibleFor(aWebProgress.DOMWindow.document);
-    this.present(Presentation.tabStateChanged(docAcc, 'newdoc'));
+    this.present(Presentation.tabStateChanged(docAcc, "newdoc"));
   },
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
                                          Ci.nsISupportsWeakReference,
                                          Ci.nsISupports,
                                          Ci.nsIObserver])
 };
 
@@ -592,28 +592,28 @@ const AccessibilityEventObserver = {
 
   /**
    * Start an AccessibilityEventObserver.
    */
   start: function start() {
     if (this.started || this.listenerCount === 0) {
       return;
     }
-    Services.obs.addObserver(this, 'accessible-event');
+    Services.obs.addObserver(this, "accessible-event");
     this.started = true;
   },
 
   /**
    * Stop an AccessibilityEventObserver.
    */
   stop: function stop() {
     if (!this.started) {
       return;
     }
-    Services.obs.removeObserver(this, 'accessible-event');
+    Services.obs.removeObserver(this, "accessible-event");
     // Clean up all registered event managers.
     this.eventManagers = new WeakMap();
     this.listenerCount = 0;
     this.started = false;
   },
 
   /**
    * Register an EventManager and start listening to the
@@ -624,17 +624,17 @@ const AccessibilityEventObserver = {
    */
   addListener: function addListener(aEventManager) {
     let content = aEventManager.contentScope.content;
     if (!this.eventManagers.has(content)) {
       this.listenerCount++;
     }
     this.eventManagers.set(content, aEventManager);
     // Since at least one EventManager was registered, start listening.
-    Logger.debug('AccessibilityEventObserver.addListener. Total:',
+    Logger.debug("AccessibilityEventObserver.addListener. Total:",
       this.listenerCount);
     this.start();
   },
 
   /**
    * Unregister an EventManager and, optionally, stop listening to the
    * 'accessible-event' messages.
    *
@@ -642,17 +642,17 @@ const AccessibilityEventObserver = {
    *        An EventManager object that was stopped in the specific content.
    */
   removeListener: function removeListener(aEventManager) {
     let content = aEventManager.contentScope.content;
     if (!this.eventManagers.delete(content)) {
       return;
     }
     this.listenerCount--;
-    Logger.debug('AccessibilityEventObserver.removeListener. Total:',
+    Logger.debug("AccessibilityEventObserver.removeListener. Total:",
       this.listenerCount);
     if (this.listenerCount === 0) {
       // If there are no EventManagers registered at the moment, stop listening
       // to the 'accessible-event' messages.
       this.stop();
     }
   },
 
@@ -674,42 +674,42 @@ const AccessibilityEventObserver = {
     }
     return this.getListener(parent);
   },
 
   /**
    * Handle the 'accessible-event' message.
    */
   observe: function observe(aSubject, aTopic, aData) {
-    if (aTopic !== 'accessible-event') {
+    if (aTopic !== "accessible-event") {
       return;
     }
     let event = aSubject.QueryInterface(Ci.nsIAccessibleEvent);
     if (!event.accessibleDocument) {
       Logger.warning(
-        'AccessibilityEventObserver.observe: no accessible document:',
+        "AccessibilityEventObserver.observe: no accessible document:",
         Logger.eventToString(event), "accessible:",
         Logger.accessibleToString(event.accessible));
       return;
     }
     let content = event.accessibleDocument.window;
     // Match the content window to its EventManager.
     let eventManager = this.getListener(content);
     if (!eventManager || !eventManager._started) {
-      if (Utils.MozBuildApp === 'browser' &&
+      if (Utils.MozBuildApp === "browser" &&
           !(content instanceof Ci.nsIDOMChromeWindow)) {
         Logger.warning(
-          'AccessibilityEventObserver.observe: ignored event:',
+          "AccessibilityEventObserver.observe: ignored event:",
           Logger.eventToString(event), "accessible:",
           Logger.accessibleToString(event.accessible), "document:",
           Logger.accessibleToString(event.accessibleDocument));
       }
       return;
     }
     try {
       eventManager.handleAccEvent(event);
     } catch (x) {
-      Logger.logException(x, 'Error handing accessible event');
+      Logger.logException(x, "Error handing accessible event");
     } finally {
       return;
     }
   }
 };
--- a/accessible/jsat/Gestures.jsm
+++ b/accessible/jsat/Gestures.jsm
@@ -1,15 +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/. */
 
 /* exported GestureSettings, GestureTracker */
 
-/******************************************************************************
+/** ****************************************************************************
   All gestures have the following pathways when being resolved(v)/rejected(x):
                Tap -> DoubleTap        (x)
                    -> Dwell            (x)
                    -> Swipe            (x)
 
          DoubleTap -> TripleTap        (x)
                    -> TapHold          (x)
 
@@ -29,34 +29,34 @@
 
   DoubleTapHoldEnd -> Explore          (x)
 
         ExploreEnd -> Explore          (x)
 
            Explore -> ExploreEnd       (v)
 ******************************************************************************/
 
-'use strict';
+"use strict";
 
 const Cu = Components.utils;
 
-this.EXPORTED_SYMBOLS = ['GestureSettings', 'GestureTracker']; // jshint ignore:line
+this.EXPORTED_SYMBOLS = ["GestureSettings", "GestureTracker"]; // jshint ignore:line
 
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
-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, "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, "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;
@@ -70,17 +70,17 @@ const TAP_MAX_RADIUS = 0.2;
 // consequent pointer move lines.
 const DIRECTNESS_COEFF = 1.44;
 // Amount in inches from the edges of the screen for it to be an edge swipe
 const EDGE = 0.1;
 // Multiply timeouts by this constant, x2 works great too for slower users.
 const TIMEOUT_MULTIPLIER = 1;
 // A single pointer down/up sequence periodically precedes the tripple swipe
 // gesture on Android. This delay acounts for that.
-const IS_ANDROID = Utils.MozBuildApp === 'mobile/android' &&
+const IS_ANDROID = Utils.MozBuildApp === "mobile/android" &&
   Utils.AndroidSdkVersion >= 14;
 
 /**
  * A point object containing distance travelled data.
  * @param {Object} aPoint A point object that looks like: {
  *   x: x coordinate in pixels,
  *   y: y coordinate in pixels
  * }
@@ -197,35 +197,35 @@ this.GestureTracker = { // jshint ignore
    * Create a new gesture object and attach resolution handler to it as well as
    * handle the incoming pointer event.
    * @param  {Object} aDetail A new pointer event detail.
    * @param  {Number} aTimeStamp A new pointer event timeStamp.
    * @param  {Function} aGesture A gesture constructor (default: Tap).
    */
   _init: function GestureTracker__init(aDetail, aTimeStamp, aGesture) {
     // Only create a new gesture on |pointerdown| event.
-    if (aDetail.type !== 'pointerdown') {
+    if (aDetail.type !== "pointerdown") {
       return;
     }
     let GestureConstructor = aGesture || (IS_ANDROID ? DoubleTap : Tap);
     this._create(GestureConstructor);
     this._update(aDetail, aTimeStamp);
   },
 
   /**
    * Handle the incoming pointer event with the existing gesture object(if
    * present) or with the newly created one.
    * @param  {Object} aDetail A new pointer event detail.
    * @param  {Number} aTimeStamp A new pointer event timeStamp.
    */
   handle: function GestureTracker_handle(aDetail, aTimeStamp) {
     Logger.gesture(() => {
-      return ['Pointer event', Utils.dpi, 'at:', aTimeStamp, JSON.stringify(aDetail)];
+      return ["Pointer event", Utils.dpi, "at:", aTimeStamp, JSON.stringify(aDetail)];
     });
-    this[this.current ? '_update' : '_init'](aDetail, aTimeStamp);
+    this[this.current ? "_update" : "_init"](aDetail, aTimeStamp);
   },
 
   /**
    * Create a new gesture object and attach resolution handler to it.
    * @param  {Function} aGesture A gesture constructor.
    * @param  {Number} aTimeStamp An original pointer event timeStamp.
    * @param  {Array} aPoints All changed points associated with the new pointer
    * event.
@@ -274,17 +274,17 @@ this.GestureTracker = { // jshint ignore
  * @param  {String} aType A gesture type.
  * @param  {Object} aPoints Gesture's points.
  * @param  {String} xKey A default key for the x coordinate. Default is
  * 'startX'.
  * @param  {String} yKey A default key for the y coordinate. Default is
  * 'startY'.
  * @return {Object} a mozAccessFuGesture detail structure.
  */
-function compileDetail(aType, aPoints, keyMap = {x: 'startX', y: 'startY'}) {
+function compileDetail(aType, aPoints, keyMap = {x: "startX", y: "startY"}) {
   let touches = [];
   let maxDeltaX = 0;
   let maxDeltaY = 0;
   for (let identifier in aPoints) {
     let point = aPoints[identifier];
     let touch = {};
     for (let key in keyMap) {
       touch[key] = point[keyMap[key]];
@@ -316,20 +316,20 @@ function compileDetail(aType, aPoints, k
  * @param {Number} aTimeStamp An original pointer event's timeStamp that started
  * the gesture resolution sequence.
  * @param {Object} aPoints An existing set of points (from previous events).
  * 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.');
+  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 = {
@@ -344,32 +344,32 @@ Gesture.prototype = {
     // reject this gesture promise.
     return GestureSettings.maxConsecutiveGestureDelay;
   },
 
   /**
    * Clear the existing timer.
    */
   clearTimer: function Gesture_clearTimer() {
-    Logger.gesture('clearTimeout', this.type);
+    Logger.gesture("clearTimeout", this.type);
     clearTimeout(this._timer);
     delete this._timer;
   },
 
   /**
    * Start the timer for gesture timeout.
    * @param {Number} aTimeStamp An original pointer event's timeStamp that
    * started the gesture resolution sequence.
    */
   startTimer: function Gesture_startTimer(aTimeStamp) {
-    Logger.gesture('startTimer', this.type);
+    Logger.gesture("startTimer", this.type);
     this.clearTimer();
     let delay = this._getDelay(aTimeStamp);
     let handler = () => {
-      Logger.gesture('timer handler');
+      Logger.gesture("timer handler");
       this.clearTimer();
       if (!this._inProgress) {
         this._deferred.reject();
       } else if (this._rejectToOnWait) {
         this._deferred.reject(this._rejectToOnWait);
       }
     };
     if (delay <= 0) {
@@ -403,17 +403,17 @@ Gesture.prototype = {
    */
   _update: function Gesture__update(aPoints, aType, aCanCreate = false, aNeedComplete = false) {
     let complete;
     let lastEvent;
     for (let point of aPoints) {
       let identifier = point.identifier;
       let gesturePoint = this.points[identifier];
       if (gesturePoint) {
-        if (aType === 'pointerdown' && aCanCreate) {
+        if (aType === "pointerdown" && aCanCreate) {
           // scratch the previous pointer with that id.
           this.points[identifier] = new Point(point);
         } else {
           gesturePoint.update(point);
         }
         if (aNeedComplete) {
           // Since the gesture is completing and at least one of the gesture
           // points is updated, set the return value to true.
@@ -435,49 +435,49 @@ Gesture.prototype = {
     return complete;
   },
 
   /**
    * Emit a mozAccessFuGesture (when the gesture is resolved).
    * @param  {Object} aDetail a compiled mozAccessFuGesture detail structure.
    */
   _emit: function Gesture__emit(aDetail) {
-    let evt = new Utils.win.CustomEvent('mozAccessFuGesture', {
+    let evt = new Utils.win.CustomEvent("mozAccessFuGesture", {
       bubbles: true,
       cancelable: true,
       detail: aDetail
     });
     Utils.win.dispatchEvent(evt);
   },
 
   /**
    * Handle the pointer down event.
    * @param  {Array} aPoints A new pointer down points.
    * @param  {Number} aTimeStamp A new pointer down timeStamp.
    */
   pointerdown: function Gesture_pointerdown(aPoints, aTimeStamp) {
     this._inProgress = true;
-    this._update(aPoints, 'pointerdown',
+    this._update(aPoints, "pointerdown",
       aTimeStamp - this.startTime < GestureSettings.maxMultitouch);
   },
 
   /**
    * Handle the pointer move event.
    * @param  {Array} aPoints A new pointer move points.
    */
   pointermove: function Gesture_pointermove(aPoints) {
-    this._update(aPoints, 'pointermove');
+    this._update(aPoints, "pointermove");
   },
 
   /**
    * Handle the pointer up event.
    * @param  {Array} aPoints A new pointer up points.
    */
   pointerup: function Gesture_pointerup(aPoints) {
-    let complete = this._update(aPoints, 'pointerup', false, true);
+    let complete = this._update(aPoints, "pointerup", false, true);
     if (complete) {
       this._deferred.resolve();
     }
   },
 
   /**
    * A subsequent gesture constructor to resolve the current one to. E.g.
    * tap->doubletap, dwell->dwellend, etc.
@@ -501,17 +501,17 @@ Gesture.prototype = {
    *   id: current gesture id,
    *   gestureType: an optional subsequent gesture constructor.
    * }
    */
   _handleResolve: function Gesture__handleResolve() {
     if (this.isComplete) {
       return;
     }
-    Logger.gesture('Resolving', this.id, 'gesture.');
+    Logger.gesture("Resolving", this.id, "gesture.");
     this.isComplete = true;
     this.clearTimer();
     let detail = this.compile();
     if (detail) {
       this._emit(detail);
     }
     return {
       id: this.id,
@@ -526,17 +526,17 @@ Gesture.prototype = {
    *   id: current gesture id,
    *   gestureType: an optional subsequent gesture constructor.
    * }
    */
   _handleReject: function Gesture__handleReject(aRejectTo) {
     if (this.isComplete) {
       return;
     }
-    Logger.gesture('Rejecting', this.id, 'gesture.');
+    Logger.gesture("Rejecting", this.id, "gesture.");
     this.isComplete = true;
     this.clearTimer();
     return {
       id: this.id,
       gestureType: aRejectTo
     };
   },
 
@@ -553,26 +553,26 @@ Gesture.prototype = {
 
 /**
  * A mixin for an explore related object.
  */
 function ExploreGesture() {
   this.compile = () => {
     // Unlike most of other gestures explore based gestures compile using the
     // current point position and not the start one.
-    return compileDetail(this.type, this.points, {x: 'x', y: 'y'});
+    return compileDetail(this.type, this.points, {x: "x", y: "y"});
   };
 }
 
 /**
  * Check the in progress gesture for completion.
  */
 function checkProgressGesture(aGesture) {
   aGesture._inProgress = true;
-  if (aGesture.lastEvent === 'pointerup') {
+  if (aGesture.lastEvent === "pointerup") {
     if (aGesture.test) {
       aGesture.test(true);
     }
     aGesture._deferred.resolve();
   }
 }
 
 /**
@@ -624,17 +624,17 @@ TravelGesture.prototype.test = function 
 function DwellEnd(aTimeStamp, aPoints, aLastEvent) {
   this._inProgress = true;
   // If the pointer travels, reject to Explore.
   TravelGesture.call(this, aTimeStamp, aPoints, aLastEvent);
   checkProgressGesture(this);
 }
 
 DwellEnd.prototype = Object.create(TravelGesture.prototype);
-DwellEnd.prototype.type = 'dwellend';
+DwellEnd.prototype.type = "dwellend";
 
 /**
  * TapHoldEnd gesture. This gesture can be represented as the following diagram:
  * pointerdown-pointerup-pointerdown-*wait*-pointerup.
  * @param {Number} aTimeStamp An original pointer event's timeStamp that started
  * the gesture resolution sequence.
  * @param {Object} aPoints An existing set of points (from previous events).
  * @param {?String} aLastEvent Last pointer event type.
@@ -642,17 +642,17 @@ DwellEnd.prototype.type = 'dwellend';
 function TapHoldEnd(aTimeStamp, aPoints, aLastEvent) {
   this._inProgress = true;
   // If the pointer travels, reject to Explore.
   TravelGesture.call(this, aTimeStamp, aPoints, aLastEvent);
   checkProgressGesture(this);
 }
 
 TapHoldEnd.prototype = Object.create(TravelGesture.prototype);
-TapHoldEnd.prototype.type = 'tapholdend';
+TapHoldEnd.prototype.type = "tapholdend";
 
 /**
  * DoubleTapHoldEnd gesture. This gesture can be represented as the following
  * diagram:
  * pointerdown-pointerup-pointerdown-pointerup-pointerdown-*wait*-pointerup.
  * @param {Number} aTimeStamp An original pointer event's timeStamp that started
  * the gesture resolution sequence.
  * @param {Object} aPoints An existing set of points (from previous events).
@@ -661,17 +661,17 @@ TapHoldEnd.prototype.type = 'tapholdend'
 function DoubleTapHoldEnd(aTimeStamp, aPoints, aLastEvent) {
   this._inProgress = true;
   // If the pointer travels, reject to Explore.
   TravelGesture.call(this, aTimeStamp, aPoints, aLastEvent);
   checkProgressGesture(this);
 }
 
 DoubleTapHoldEnd.prototype = Object.create(TravelGesture.prototype);
-DoubleTapHoldEnd.prototype.type = 'doubletapholdend';
+DoubleTapHoldEnd.prototype.type = "doubletapholdend";
 
 /**
  * A common tap gesture object.
  * @param {Number} aTimeStamp An original pointer event's timeStamp that started
  * the gesture resolution sequence.
  * @param {Object} aPoints An existing set of points (from previous events).
  * @param {?String} aLastEvent Last pointer event type.
  * @param {Function} aRejectToOnWait A constructor for the next gesture to
@@ -695,17 +695,17 @@ TapGesture.prototype._getDelay = functio
   // If, for TapGesture, no pointermove or pointerup happens within the
   // GestureSettings.dwellThreshold, reject.
   // Note: the original pointer event's timeStamp is irrelevant here.
   return GestureSettings.dwellThreshold;
 };
 
 TapGesture.prototype.pointerup = function TapGesture_pointerup(aPoints) {
     if (this._rejectToOnPointerDown) {
-      let complete = this._update(aPoints, 'pointerup', false, true);
+      let complete = this._update(aPoints, "pointerup", false, true);
       if (complete) {
         this.clearTimer();
         if (GestureSettings.maxGestureResolveTimeout) {
           this._pointerUpTimer = setTimeout(() => {
             clearTimeout(this._pointerUpTimer);
             delete this._pointerUpTimer;
             this._deferred.resolve();
           }, GestureSettings.maxGestureResolveTimeout);
@@ -737,48 +737,48 @@ TapGesture.prototype.pointerdown = funct
  * @param {?String} aLastEvent Last pointer event type.
  */
 function Tap(aTimeStamp, aPoints, aLastEvent) {
   // If the pointer travels, reject to Swipe.
   TapGesture.call(this, aTimeStamp, aPoints, aLastEvent, Dwell, Swipe, DoubleTap);
 }
 
 Tap.prototype = Object.create(TapGesture.prototype);
-Tap.prototype.type = 'tap';
+Tap.prototype.type = "tap";
 
 
 /**
  * Double Tap gesture.
  * @param {Number} aTimeStamp An original pointer event's timeStamp that started
  * the gesture resolution sequence.
  * @param {Object} aPoints An existing set of points (from previous events).
  * @param {?String} aLastEvent Last pointer event type.
  */
 function DoubleTap(aTimeStamp, aPoints, aLastEvent) {
   this._inProgress = true;
   TapGesture.call(this, aTimeStamp, aPoints, aLastEvent, TapHold, null, TripleTap);
 }
 
 DoubleTap.prototype = Object.create(TapGesture.prototype);
-DoubleTap.prototype.type = 'doubletap';
+DoubleTap.prototype.type = "doubletap";
 
 /**
  * Triple Tap gesture.
  * @param {Number} aTimeStamp An original pointer event's timeStamp that started
  * the gesture resolution sequence.
  * @param {Object} aPoints An existing set of points (from previous events).
  * @param {?String} aLastEvent Last pointer event type.
  */
 function TripleTap(aTimeStamp, aPoints, aLastEvent) {
   this._inProgress = true;
   TapGesture.call(this, aTimeStamp, aPoints, aLastEvent, DoubleTapHold, null, null);
 }
 
 TripleTap.prototype = Object.create(TapGesture.prototype);
-TripleTap.prototype.type = 'tripletap';
+TripleTap.prototype.type = "tripletap";
 
 /**
  * Common base object for gestures that are created as resolved.
  * @param {Number} aTimeStamp An original pointer event's timeStamp that started
  * the gesture resolution sequence.
  * @param {Object} aPoints An existing set of points (from previous events).
  * @param {?String} aLastEvent Last pointer event type.
  */
@@ -797,63 +797,63 @@ ResolvedGesture.prototype = Object.creat
  * @param {Object} aPoints An existing set of points (from previous events).
  * @param {?String} aLastEvent Last pointer event type.
  */
 function Dwell(aTimeStamp, aPoints, aLastEvent) {
   ResolvedGesture.call(this, aTimeStamp, aPoints, aLastEvent);
 }
 
 Dwell.prototype = Object.create(ResolvedGesture.prototype);
-Dwell.prototype.type = 'dwell';
+Dwell.prototype.type = "dwell";
 Dwell.prototype.resolveTo = DwellEnd;
 
 /**
  * TapHold gesture
  * @param {Number} aTimeStamp An original pointer event's timeStamp that started
  * the gesture resolution sequence.
  * @param {Object} aPoints An existing set of points (from previous events).
  * @param {?String} aLastEvent Last pointer event type.
  */
 function TapHold(aTimeStamp, aPoints, aLastEvent) {
   ResolvedGesture.call(this, aTimeStamp, aPoints, aLastEvent);
 }
 
 TapHold.prototype = Object.create(ResolvedGesture.prototype);
-TapHold.prototype.type = 'taphold';
+TapHold.prototype.type = "taphold";
 TapHold.prototype.resolveTo = TapHoldEnd;
 
 /**
  * DoubleTapHold gesture
  * @param {Number} aTimeStamp An original pointer event's timeStamp that started
  * the gesture resolution sequence.
  * @param {Object} aPoints An existing set of points (from previous events).
  * @param {?String} aLastEvent Last pointer event type.
  */
 function DoubleTapHold(aTimeStamp, aPoints, aLastEvent) {
   ResolvedGesture.call(this, aTimeStamp, aPoints, aLastEvent);
 }
 
 DoubleTapHold.prototype = Object.create(ResolvedGesture.prototype);
-DoubleTapHold.prototype.type = 'doubletaphold';
+DoubleTapHold.prototype.type = "doubletaphold";
 DoubleTapHold.prototype.resolveTo = DoubleTapHoldEnd;
 
 /**
  * Explore gesture
  * @param {Number} aTimeStamp An original pointer event's timeStamp that started
  * the gesture resolution sequence.
  * @param {Object} aPoints An existing set of points (from previous events).
  * @param {?String} aLastEvent Last pointer event type.
  */
 function Explore(aTimeStamp, aPoints, aLastEvent) {
   ExploreGesture.call(this);
   ResolvedGesture.call(this, aTimeStamp, aPoints, aLastEvent);
 }
 
 Explore.prototype = Object.create(ResolvedGesture.prototype);
-Explore.prototype.type = 'explore';
+Explore.prototype.type = "explore";
 Explore.prototype.resolveTo = ExploreEnd;
 
 /**
  * ExploreEnd gesture.
  * @param {Number} aTimeStamp An original pointer event's timeStamp that started
  * the gesture resolution sequence.
  * @param {Object} aPoints An existing set of points (from previous events).
  * @param {?String} aLastEvent Last pointer event type.
@@ -862,34 +862,34 @@ function ExploreEnd(aTimeStamp, aPoints,
   this._inProgress = true;
   ExploreGesture.call(this);
   // If the pointer travels, reject to Explore.
   TravelGesture.call(this, aTimeStamp, aPoints, aLastEvent);
   checkProgressGesture(this);
 }
 
 ExploreEnd.prototype = Object.create(TravelGesture.prototype);
-ExploreEnd.prototype.type = 'exploreend';
+ExploreEnd.prototype.type = "exploreend";
 
 /**
  * Swipe gesture.
  * @param {Number} aTimeStamp An original pointer event's timeStamp that started
  * the gesture resolution sequence.
  * @param {Object} aPoints An existing set of points (from previous events).
  * @param {?String} aLastEvent Last pointer event type.
  */
 function Swipe(aTimeStamp, aPoints, aLastEvent) {
   this._inProgress = true;
   this._rejectToOnWait = Explore;
   Gesture.call(this, aTimeStamp, aPoints, aLastEvent);
   checkProgressGesture(this);
 }
 
 Swipe.prototype = Object.create(Gesture.prototype);
-Swipe.prototype.type = 'swipe';
+Swipe.prototype.type = "swipe";
 Swipe.prototype._getDelay = function Swipe__getDelay(aTimeStamp) {
   // Swipe should be completed within the GestureSettings.swipeMaxDuration from
   // the initial pointer down event.
   return GestureSettings.swipeMaxDuration - this.startTime + aTimeStamp;
 };
 
 /**
  * Determine wither the gesture was Swipe or Explore.
@@ -919,37 +919,37 @@ Swipe.prototype.test = function Swipe_te
 
 /**
  * Compile a swipe related mozAccessFuGesture event detail.
  * @return {Object} A mozAccessFuGesture detail object.
  */
 Swipe.prototype.compile = function Swipe_compile() {
   let type = this.type;
   let detail = compileDetail(type, this.points,
-    {x1: 'startX', y1: 'startY', x2: 'x', y2: 'y'});
+    {x1: "startX", y1: "startY", x2: "x", y2: "y"});
   let deltaX = detail.deltaX;
   let deltaY = detail.deltaY;
   let edge = EDGE * Utils.dpi;
   if (Math.abs(deltaX) > Math.abs(deltaY)) {
     // Horizontal swipe.
     let startPoints = detail.touches.map(touch => touch.x1);
     if (deltaX > 0) {
-      detail.type = type + 'right';
+      detail.type = type + "right";
       detail.edge = Math.min.apply(null, startPoints) <= edge;
     } else {
-      detail.type = type + 'left';
+      detail.type = type + "left";
       detail.edge =
         Utils.win.screen.width - Math.max.apply(null, startPoints) <= edge;
     }
   } else {
     // Vertical swipe.
     let startPoints = detail.touches.map(touch => touch.y1);
     if (deltaY > 0) {
-      detail.type = type + 'down';
+      detail.type = type + "down";
       detail.edge = Math.min.apply(null, startPoints) <= edge;
     } else {
-      detail.type = type + 'up';
+      detail.type = type + "up";
       detail.edge =
         Utils.win.screen.height - Math.max.apply(null, startPoints) <= edge;
     }
   }
   return detail;
 };
--- a/accessible/jsat/OutputGenerator.jsm
+++ b/accessible/jsat/OutputGenerator.jsm
@@ -1,40 +1,40 @@
 /* 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/. */
 
 /* exported UtteranceGenerator, BrailleGenerator */
 
-'use strict';
+"use strict";
 
 const {utils: Cu, interfaces: Ci} = Components;
 
 const INCLUDE_DESC = 0x01;
 const INCLUDE_NAME = 0x02;
 const INCLUDE_VALUE = 0x04;
 const NAME_FROM_SUBTREE_RULE = 0x10;
 const IGNORE_EXPLICIT_NAME = 0x20;
 
 const OUTPUT_DESC_FIRST = 0;
 const OUTPUT_DESC_LAST = 1;
 
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Utils', // jshint ignore:line
-  'resource://gre/modules/accessibility/Utils.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'PrefCache', // 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, 'Roles', // jshint ignore:line
-  'resource://gre/modules/accessibility/Constants.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'States', // jshint ignore:line
-  'resource://gre/modules/accessibility/Constants.jsm');
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Utils", // jshint ignore:line
+  "resource://gre/modules/accessibility/Utils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PrefCache", // 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, "Roles", // jshint ignore:line
+  "resource://gre/modules/accessibility/Constants.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "States", // jshint ignore:line
+  "resource://gre/modules/accessibility/Constants.jsm");
 
-this.EXPORTED_SYMBOLS = ['UtteranceGenerator', 'BrailleGenerator']; // jshint ignore:line
+this.EXPORTED_SYMBOLS = ["UtteranceGenerator", "BrailleGenerator"]; // jshint ignore:line
 
 var OutputGenerator = {
 
   defaultOutputOrder: OUTPUT_DESC_LAST,
 
   /**
    * Generates output for a PivotContext.
    * @param {PivotContext} aContext object that generates and caches
@@ -52,17 +52,17 @@ var OutputGenerator = {
     };
     let ignoreSubtree = function ignoreSubtree(aAccessible) {
       let roleString = Utils.AccService.getStringRole(aAccessible.role);
       let nameRule = self.roleRuleMap[roleString] || 0;
       // Ignore subtree if the name is explicit and the role's name rule is the
       // NAME_FROM_SUBTREE_RULE.
       return (((nameRule & INCLUDE_VALUE) && aAccessible.value) ||
               ((nameRule & NAME_FROM_SUBTREE_RULE) &&
-               (Utils.getAttributes(aAccessible)['explicit-name'] === 'true' &&
+               (Utils.getAttributes(aAccessible)["explicit-name"] === "true" &&
                !(nameRule & IGNORE_EXPLICIT_NAME))));
     };
 
     let contextStart = this._getContextStart(aContext);
 
     if (this.outputOrder === OUTPUT_DESC_FIRST) {
       contextStart.forEach(addOutput);
       addOutput(aContext.accessible);
@@ -161,65 +161,65 @@ var OutputGenerator = {
   /**
    * Adds an accessible name and description to the output if available.
    * @param {Array} aOutput Output array.
    * @param {nsIAccessible} aAccessible current accessible object.
    * @param {Number} aFlags output flags.
    */
   _addName: function _addName(aOutput, aAccessible, aFlags) {
     let name;
-    if ((Utils.getAttributes(aAccessible)['explicit-name'] === 'true' &&
+    if ((Utils.getAttributes(aAccessible)["explicit-name"] === "true" &&
          !(aFlags & IGNORE_EXPLICIT_NAME)) || (aFlags & INCLUDE_NAME)) {
       name = aAccessible.name;
     }
 
     let description = aAccessible.description;
     if (description) {
       // Compare against the calculated name unconditionally, regardless of name rule,
       // so we can make sure we don't speak duplicated descriptions
       let tmpName = name || aAccessible.name;
       if (tmpName && (description !== tmpName)) {
-        name = name || '';
+        name = name || "";
         name = this.outputOrder === OUTPUT_DESC_FIRST ?
-          description + ' - ' + name :
-          name + ' - ' + description;
+          description + " - " + name :
+          name + " - " + description;
       }
     }
 
     if (!name || !name.trim()) {
       return;
     }
-    aOutput[this.outputOrder === OUTPUT_DESC_FIRST ? 'push' : 'unshift'](name);
+    aOutput[this.outputOrder === OUTPUT_DESC_FIRST ? "push" : "unshift"](name);
   },
 
   /**
    * Adds a landmark role to the output if available.
    * @param {Array} aOutput Output array.
    * @param {nsIAccessible} aAccessible current accessible object.
    */
   _addLandmark: function _addLandmark(aOutput, aAccessible) {
     let landmarkName = Utils.getLandmarkName(aAccessible);
     if (!landmarkName) {
       return;
     }
-    aOutput[this.outputOrder === OUTPUT_DESC_FIRST ? 'unshift' : 'push']({
+    aOutput[this.outputOrder === OUTPUT_DESC_FIRST ? "unshift" : "push"]({
       string: landmarkName
     });
   },
 
   /**
    * 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.
@@ -227,198 +227,198 @@ var OutputGenerator = {
       case Roles.MATHML_MULTISCRIPTS:
       case Roles.MATHML_OVER:
       case Roles.MATHML_SUB:
       case Roles.MATHML_SUB_SUP:
       case Roles.MATHML_SUP:
       case Roles.MATHML_UNDER:
       case Roles.MATHML_UNDER_OVER:
         // For scripted accessibles, use the string 'mathmlscripted'.
-        roleStr = 'mathmlscripted';
+        roleStr = "mathmlscripted";
         break;
       case Roles.MATHML_FRACTION:
         // From a semantic point of view, the only important point is to
         // distinguish between fractions that have a bar and those that do not.
         // Per the MathML 3 spec, the latter happens iff the linethickness
         // attribute is of the form [zero-float][optional-unit]. In that case,
         // we use the string 'mathmlfractionwithoutbar'.
         let linethickness = Utils.getAttributes(aAccessible).linethickness;
         if (linethickness) {
             let numberMatch = linethickness.match(/^(?:\d|\.)+/);
             if (numberMatch && !parseFloat(numberMatch[0])) {
-                roleStr += 'withoutbar';
+                roleStr += "withoutbar";
             }
         }
         break;
       default:
         // Otherwise, do not output the actual role.
         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.
    */
   _addMencloseNotations: function _addMencloseNotations(aOutput, aAccessible) {
-    let notations = Utils.getAttributes(aAccessible).notation || 'longdiv';
-    aOutput[this.outputOrder === OUTPUT_DESC_FIRST ? 'push' : 'unshift'].apply(
-      aOutput, notations.split(' ').map(notation => {
-        return { string: this._getOutputName('notation-' + notation) };
+    let notations = Utils.getAttributes(aAccessible).notation || "longdiv";
+    aOutput[this.outputOrder === OUTPUT_DESC_FIRST ? "push" : "unshift"].apply(
+      aOutput, notations.split(" ").map(notation => {
+        return { string: this._getOutputName("notation-" + notation) };
       }));
   },
 
   /**
    * Adds an entry type attribute to the description if available.
    * @param {Array} aOutput Output array.
    * @param {nsIAccessible} aAccessible current accessible object.
    * @param {String} aRoleStr aAccessible's role string.
    */
   _addType: function _addType(aOutput, aAccessible, aRoleStr) {
-    if (aRoleStr !== 'entry') {
+    if (aRoleStr !== "entry") {
       return;
     }
 
-    let typeName = Utils.getAttributes(aAccessible)['text-input-type'];
+    let typeName = Utils.getAttributes(aAccessible)["text-input-type"];
     // Ignore the the input type="text" case.
-    if (!typeName || typeName === 'text') {
+    if (!typeName || typeName === "text") {
       return;
     }
-    aOutput.push({string: 'textInputType_' + typeName});
+    aOutput.push({string: "textInputType_" + typeName});
   },
 
   _addState: function _addState(aOutput, aState, aRoleStr) {}, // jshint ignore:line
 
   _addRole: function _addRole(aOutput, aAccessible, aRoleStr) {}, // jshint ignore:line
 
   get outputOrder() {
     if (!this._utteranceOrder) {
-      this._utteranceOrder = new PrefCache('accessibility.accessfu.utterance');
+      this._utteranceOrder = new PrefCache("accessibility.accessfu.utterance");
     }
-    return typeof this._utteranceOrder.value === 'number' ?
+    return typeof this._utteranceOrder.value === "number" ?
       this._utteranceOrder.value : this.defaultOutputOrder;
   },
 
   _getOutputName: function _getOutputName(aName) {
-    return aName.replace(/\s/g, '');
+    return aName.replace(/\s/g, "");
   },
 
   roleRuleMap: {
-    'menubar': INCLUDE_DESC,
-    'scrollbar': INCLUDE_DESC,
-    'grip': INCLUDE_DESC,
-    'alert': INCLUDE_DESC | INCLUDE_NAME,
-    'menupopup': INCLUDE_DESC,
-    'menuitem': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
-    'tooltip': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
-    'columnheader': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
-    'rowheader': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
-    'column': NAME_FROM_SUBTREE_RULE,
-    'row': NAME_FROM_SUBTREE_RULE,
-    'cell': INCLUDE_DESC | INCLUDE_NAME,
-    'application': INCLUDE_NAME,
-    'document': INCLUDE_NAME,
-    'grouping': INCLUDE_DESC | INCLUDE_NAME,
-    'toolbar': INCLUDE_DESC,
-    'table': INCLUDE_DESC | INCLUDE_NAME,
-    'link': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
-    'helpballoon': NAME_FROM_SUBTREE_RULE,
-    'list': INCLUDE_DESC | INCLUDE_NAME,
-    'listitem': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
-    'outline': INCLUDE_DESC,
-    'outlineitem': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
-    'pagetab': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
-    'graphic': INCLUDE_DESC,
-    'switch': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
-    'pushbutton': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
-    'checkbutton': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
-    'radiobutton': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
-    'buttondropdown': NAME_FROM_SUBTREE_RULE,
-    'combobox': INCLUDE_DESC | INCLUDE_VALUE,
-    'droplist': INCLUDE_DESC,
-    'progressbar': INCLUDE_DESC | INCLUDE_VALUE,
-    'slider': INCLUDE_DESC | INCLUDE_VALUE,
-    'spinbutton': INCLUDE_DESC | INCLUDE_VALUE,
-    'diagram': INCLUDE_DESC,
-    'animation': INCLUDE_DESC,
-    'equation': INCLUDE_DESC,
-    'buttonmenu': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
-    'buttondropdowngrid': NAME_FROM_SUBTREE_RULE,
-    'pagetablist': INCLUDE_DESC,
-    'canvas': INCLUDE_DESC,
-    'check menu item': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
-    'label': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
-    'password text': INCLUDE_DESC,
-    'popup menu': INCLUDE_DESC,
-    'radio menu item': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
-    'table column header': NAME_FROM_SUBTREE_RULE,
-    'table row header': NAME_FROM_SUBTREE_RULE,
-    'tear off menu item': NAME_FROM_SUBTREE_RULE,
-    'toggle button': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
-    'parent menuitem': NAME_FROM_SUBTREE_RULE,
-    'header': INCLUDE_DESC,
-    'footer': INCLUDE_DESC,
-    'entry': INCLUDE_DESC | INCLUDE_NAME | INCLUDE_VALUE,
-    'caption': INCLUDE_DESC,
-    'document frame': INCLUDE_DESC,
-    'heading': INCLUDE_DESC,
-    'calendar': INCLUDE_DESC | INCLUDE_NAME,
-    'combobox option': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
-    'listbox option': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
-    'listbox rich option': NAME_FROM_SUBTREE_RULE,
-    'gridcell': NAME_FROM_SUBTREE_RULE,
-    'check rich option': NAME_FROM_SUBTREE_RULE,
-    'term': NAME_FROM_SUBTREE_RULE,
-    'definition': NAME_FROM_SUBTREE_RULE,
-    'key': NAME_FROM_SUBTREE_RULE,
-    'image map': INCLUDE_DESC,
-    'option': INCLUDE_DESC,
-    'listbox': INCLUDE_DESC,
-    'definitionlist': INCLUDE_DESC | INCLUDE_NAME,
-    'dialog': INCLUDE_DESC | INCLUDE_NAME,
-    'chrome window': IGNORE_EXPLICIT_NAME,
-    'app root': IGNORE_EXPLICIT_NAME,
-    'statusbar': NAME_FROM_SUBTREE_RULE,
-    'mathml table': INCLUDE_DESC | INCLUDE_NAME,
-    'mathml labeled row': NAME_FROM_SUBTREE_RULE,
-    'mathml table row': NAME_FROM_SUBTREE_RULE,
-    'mathml cell': INCLUDE_DESC | INCLUDE_NAME,
-    'mathml fraction': INCLUDE_DESC,
-    'mathml square root': INCLUDE_DESC,
-    'mathml root': INCLUDE_DESC,
-    'mathml enclosed': INCLUDE_DESC,
-    'mathml sub': INCLUDE_DESC,
-    'mathml sup': INCLUDE_DESC,
-    'mathml sub sup': INCLUDE_DESC,
-    'mathml under': INCLUDE_DESC,
-    'mathml over': INCLUDE_DESC,
-    'mathml under over': INCLUDE_DESC,
-    'mathml multiscripts': INCLUDE_DESC,
-    'mathml identifier': INCLUDE_DESC,
-    'mathml number': INCLUDE_DESC,
-    'mathml operator': INCLUDE_DESC,
-    'mathml text': INCLUDE_DESC,
-    'mathml string literal': INCLUDE_DESC,
-    'mathml row': INCLUDE_DESC,
-    'mathml style': INCLUDE_DESC,
-    'mathml error': INCLUDE_DESC },
+    "menubar": INCLUDE_DESC,
+    "scrollbar": INCLUDE_DESC,
+    "grip": INCLUDE_DESC,
+    "alert": INCLUDE_DESC | INCLUDE_NAME,
+    "menupopup": INCLUDE_DESC,
+    "menuitem": INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
+    "tooltip": INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
+    "columnheader": INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
+    "rowheader": INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
+    "column": NAME_FROM_SUBTREE_RULE,
+    "row": NAME_FROM_SUBTREE_RULE,
+    "cell": INCLUDE_DESC | INCLUDE_NAME,
+    "application": INCLUDE_NAME,
+    "document": INCLUDE_NAME,
+    "grouping": INCLUDE_DESC | INCLUDE_NAME,
+    "toolbar": INCLUDE_DESC,
+    "table": INCLUDE_DESC | INCLUDE_NAME,
+    "link": INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
+    "helpballoon": NAME_FROM_SUBTREE_RULE,
+    "list": INCLUDE_DESC | INCLUDE_NAME,
+    "listitem": INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
+    "outline": INCLUDE_DESC,
+    "outlineitem": INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
+    "pagetab": INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
+    "graphic": INCLUDE_DESC,
+    "switch": INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
+    "pushbutton": INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
+    "checkbutton": INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
+    "radiobutton": INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
+    "buttondropdown": NAME_FROM_SUBTREE_RULE,
+    "combobox": INCLUDE_DESC | INCLUDE_VALUE,
+    "droplist": INCLUDE_DESC,
+    "progressbar": INCLUDE_DESC | INCLUDE_VALUE,
+    "slider": INCLUDE_DESC | INCLUDE_VALUE,
+    "spinbutton": INCLUDE_DESC | INCLUDE_VALUE,
+    "diagram": INCLUDE_DESC,
+    "animation": INCLUDE_DESC,
+    "equation": INCLUDE_DESC,
+    "buttonmenu": INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
+    "buttondropdowngrid": NAME_FROM_SUBTREE_RULE,
+    "pagetablist": INCLUDE_DESC,
+    "canvas": INCLUDE_DESC,
+    "check menu item": INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
+    "label": INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
+    "password text": INCLUDE_DESC,
+    "popup menu": INCLUDE_DESC,
+    "radio menu item": INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
+    "table column header": NAME_FROM_SUBTREE_RULE,
+    "table row header": NAME_FROM_SUBTREE_RULE,
+    "tear off menu item": NAME_FROM_SUBTREE_RULE,
+    "toggle button": INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
+    "parent menuitem": NAME_FROM_SUBTREE_RULE,
+    "header": INCLUDE_DESC,
+    "footer": INCLUDE_DESC,
+    "entry": INCLUDE_DESC | INCLUDE_NAME | INCLUDE_VALUE,
+    "caption": INCLUDE_DESC,
+    "document frame": INCLUDE_DESC,
+    "heading": INCLUDE_DESC,
+    "calendar": INCLUDE_DESC | INCLUDE_NAME,
+    "combobox option": INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
+    "listbox option": INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
+    "listbox rich option": NAME_FROM_SUBTREE_RULE,
+    "gridcell": NAME_FROM_SUBTREE_RULE,
+    "check rich option": NAME_FROM_SUBTREE_RULE,
+    "term": NAME_FROM_SUBTREE_RULE,
+    "definition": NAME_FROM_SUBTREE_RULE,
+    "key": NAME_FROM_SUBTREE_RULE,
+    "image map": INCLUDE_DESC,
+    "option": INCLUDE_DESC,
+    "listbox": INCLUDE_DESC,
+    "definitionlist": INCLUDE_DESC | INCLUDE_NAME,
+    "dialog": INCLUDE_DESC | INCLUDE_NAME,
+    "chrome window": IGNORE_EXPLICIT_NAME,
+    "app root": IGNORE_EXPLICIT_NAME,
+    "statusbar": NAME_FROM_SUBTREE_RULE,
+    "mathml table": INCLUDE_DESC | INCLUDE_NAME,
+    "mathml labeled row": NAME_FROM_SUBTREE_RULE,
+    "mathml table row": NAME_FROM_SUBTREE_RULE,
+    "mathml cell": INCLUDE_DESC | INCLUDE_NAME,
+    "mathml fraction": INCLUDE_DESC,
+    "mathml square root": INCLUDE_DESC,
+    "mathml root": INCLUDE_DESC,
+    "mathml enclosed": INCLUDE_DESC,
+    "mathml sub": INCLUDE_DESC,
+    "mathml sup": INCLUDE_DESC,
+    "mathml sub sup": INCLUDE_DESC,
+    "mathml under": INCLUDE_DESC,
+    "mathml over": INCLUDE_DESC,
+    "mathml under over": INCLUDE_DESC,
+    "mathml multiscripts": INCLUDE_DESC,
+    "mathml identifier": INCLUDE_DESC,
+    "mathml number": INCLUDE_DESC,
+    "mathml operator": INCLUDE_DESC,
+    "mathml text": INCLUDE_DESC,
+    "mathml string literal": INCLUDE_DESC,
+    "mathml row": INCLUDE_DESC,
+    "mathml style": INCLUDE_DESC,
+    "mathml error": INCLUDE_DESC },
 
   mathmlRolesSet: new Set([
     Roles.MATHML_MATH,
     Roles.MATHML_IDENTIFIER,
     Roles.MATHML_NUMBER,
     Roles.MATHML_OPERATOR,
     Roles.MATHML_TEXT,
     Roles.MATHML_STRING_LITERAL,
@@ -459,17 +459,17 @@ var OutputGenerator = {
 
         if (aFlags & INCLUDE_DESC) {
           this._addState(output, aState, aRoleStr);
           this._addType(output, aAccessible, aRoleStr);
           this._addRole(output, aAccessible, aRoleStr);
         }
 
         if (aFlags & INCLUDE_VALUE && aAccessible.value.trim()) {
-          output[this.outputOrder === OUTPUT_DESC_FIRST ? 'push' : 'unshift'](
+          output[this.outputOrder === OUTPUT_DESC_FIRST ? "push" : "unshift"](
             aAccessible.value);
         }
 
         this._addName(output, aAccessible, aFlags);
         this._addLandmark(output, aAccessible);
 
         return output;
       },
@@ -481,30 +481,30 @@ var OutputGenerator = {
         // we don't need the context.
         return [];
       }
 
       return this.objectOutputFunctions.defaultFunc.apply(this, arguments);
     },
 
     entry: function entry(aAccessible, aRoleStr, aState, aFlags) {
-      let rolestr = aState.contains(States.MULTI_LINE) ? 'textarea' : 'entry';
+      let rolestr = aState.contains(States.MULTI_LINE) ? "textarea" : "entry";
       return this.objectOutputFunctions.defaultFunc.apply(
         this, [aAccessible, rolestr, aState, aFlags]);
     },
 
     pagetab: function pagetab(aAccessible, aRoleStr, aState, aFlags) {
       let itemno = {};
       let itemof = {};
       aAccessible.groupPosition({}, itemof, itemno);
       let output = [];
       this._addState(output, aState);
       this._addRole(output, aAccessible, aRoleStr);
       output.push({
-        string: 'objItemOfN',
+        string: "objItemOfN",
         args: [itemno.value, itemof.value]
       });
 
       this._addName(output, aAccessible, aFlags);
       this._addLandmark(output, aAccessible);
 
       return output;
     },
@@ -520,20 +520,20 @@ var OutputGenerator = {
       } finally {
         // Check if it's a layout table, and bail out if true.
         // We don't want to speak any table information for layout tables.
         if (table.isProbablyForLayout()) {
           return output;
         }
         this._addRole(output, aAccessible, aRoleStr);
         output.push.call(output, {
-          string: this._getOutputName('tblColumnInfo'),
+          string: this._getOutputName("tblColumnInfo"),
           count: table.columnCount
         }, {
-          string: this._getOutputName('tblRowInfo'),
+          string: this._getOutputName("tblRowInfo"),
           count: table.rowCount
         });
         this._addName(output, aAccessible, aFlags);
         this._addLandmark(output, aAccessible);
         return output;
       }
     },
 
@@ -579,124 +579,123 @@ var OutputGenerator = {
  * For example {@link genForAction} might return ['button', 'clicked'] for a
  * clicked event. Speaking only 'clicked' makes sense. Speaking 'button' does
  * not.
  */
 this.UtteranceGenerator = {  // jshint ignore:line
   __proto__: OutputGenerator, // jshint ignore:line
 
   gActionMap: {
-    jump: 'jumpAction',
-    press: 'pressAction',
-    check: 'checkAction',
-    uncheck: 'uncheckAction',
-    on: 'onAction',
-    off: 'offAction',
-    select: 'selectAction',
-    unselect: 'unselectAction',
-    open: 'openAction',
-    close: 'closeAction',
-    switch: 'switchAction',
-    click: 'clickAction',
-    collapse: 'collapseAction',
-    expand: 'expandAction',
-    activate: 'activateAction',
-    cycle: 'cycleAction'
+    jump: "jumpAction",
+    press: "pressAction",
+    check: "checkAction",
+    uncheck: "uncheckAction",
+    on: "onAction",
+    off: "offAction",
+    select: "selectAction",
+    unselect: "unselectAction",
+    open: "openAction",
+    close: "closeAction",
+    switch: "switchAction",
+    click: "clickAction",
+    collapse: "collapseAction",
+    expand: "expandAction",
+    activate: "activateAction",
+    cycle: "cycleAction"
   },
 
-  //TODO: May become more verbose in the future.
+  // TODO: May become more verbose in the future.
   genForAction: function genForAction(aObject, aActionName) {
     return [{string: this.gActionMap[aActionName]}];
   },
 
   genForLiveRegion:
     function genForLiveRegion(aContext, aIsHide, aModifiedText) {
       let utterance = [];
       if (aIsHide) {
-        utterance.push({string: 'hidden'});
+        utterance.push({string: "hidden"});
       }
       return utterance.concat(aModifiedText || this.genForContext(aContext));
     },
 
   genForAnnouncement: function genForAnnouncement(aAnnouncement) {
     return [{
       string: aAnnouncement
     }];
   },
 
   genForTabStateChange: function genForTabStateChange(aObject, aTabState) {
     switch (aTabState) {
-      case 'newtab':
-        return [{string: 'tabNew'}];
-      case 'loading':
-        return [{string: 'tabLoading'}];
-      case 'loaded':
-        return [aObject.name, {string: 'tabLoaded'}];
-      case 'loadstopped':
-        return [{string: 'tabLoadStopped'}];
-      case 'reload':
-        return [{string: 'tabReload'}];
+      case "newtab":
+        return [{string: "tabNew"}];
+      case "loading":
+        return [{string: "tabLoading"}];
+      case "loaded":
+        return [aObject.name, {string: "tabLoaded"}];
+      case "loadstopped":
+        return [{string: "tabLoadStopped"}];
+      case "reload":
+        return [{string: "tabReload"}];
       default:
         return [];
     }
   },
 
   genForEditingMode: function genForEditingMode(aIsEditing) {
-    return [{string: aIsEditing ? 'editingMode' : 'navigationMode'}];
+    return [{string: aIsEditing ? "editingMode" : "navigationMode"}];
   },
 
   objectOutputFunctions: {
 
     __proto__: OutputGenerator.objectOutputFunctions, // jshint ignore:line
 
     defaultFunc: function defaultFunc() {
       return this.objectOutputFunctions._generateBaseOutput.apply(
         this, arguments);
     },
 
     heading: function heading(aAccessible, aRoleStr, aState, aFlags) {
       let level = {};
       aAccessible.groupPosition(level, {}, {});
-      let utterance = [{string: 'headingLevel', args: [level.value]}];
+      let utterance = [{string: "headingLevel", args: [level.value]}];
 
       this._addName(utterance, aAccessible, aFlags);
       this._addLandmark(utterance, aAccessible);
 
       return utterance;
     },
 
     listitem: function listitem(aAccessible, aRoleStr, aState, aFlags) {
       let itemno = {};
       let itemof = {};
       aAccessible.groupPosition({}, itemof, itemno);
       let utterance = [];
       if (itemno.value == 1) {
         // Start of list
-        utterance.push({string: 'listStart'});
-      }
-      else if (itemno.value == itemof.value) {
+        utterance.push({string: "listStart"});
+      } else if (itemno.value == itemof.value) {
         // last item
-        utterance.push({string: 'listEnd'});
+        utterance.push({string: "listEnd"});
       }
 
       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]);
       }
@@ -720,22 +719,22 @@ this.UtteranceGenerator = {  // jshint i
           }
         };
         let addHeaders = function addHeaders(aUtterance, aHeaders) {
           if (aHeaders.length > 0) {
             aUtterance.push.apply(aUtterance, aHeaders);
           }
         };
 
-        addCellChanged(utterance, cell.columnChanged, 'columnInfo',
+        addCellChanged(utterance, cell.columnChanged, "columnInfo",
           cell.columnIndex);
-        addCellChanged(utterance, cell.rowChanged, 'rowInfo', cell.rowIndex);
+        addCellChanged(utterance, cell.rowChanged, "rowInfo", cell.rowIndex);
 
-        addExtent(utterance, cell.columnExtent, 'spansColumns');
-        addExtent(utterance, cell.rowExtent, 'spansRows');
+        addExtent(utterance, cell.columnExtent, "spansColumns");
+        addExtent(utterance, cell.rowExtent, "spansRows");
 
         addHeaders(utterance, cell.columnHeaders);
         addHeaders(utterance, cell.rowHeaders);
       }
 
       this._addName(utterance, aAccessible, aFlags);
       this._addLandmark(utterance, aAccessible);
 
@@ -769,72 +768,72 @@ this.UtteranceGenerator = {  // jshint i
     } else {
       aOutput.push({string: this._getOutputName(aRoleStr)});
     }
   },
 
   _addState: function _addState(aOutput, aState, aRoleStr) {
 
     if (aState.contains(States.UNAVAILABLE)) {
-      aOutput.push({string: 'stateUnavailable'});
+      aOutput.push({string: "stateUnavailable"});
     }
 
     if (aState.contains(States.READONLY)) {
-      aOutput.push({string: 'stateReadonly'});
+      aOutput.push({string: "stateReadonly"});
     }
 
     // Don't utter this in Jelly Bean, we let TalkBack do it for us there.
     // This is because we expose the checked information on the node itself.
     // XXX: this means the checked state is always appended to the end,
     // regardless of the utterance ordering preference.
-    if ((Utils.AndroidSdkVersion < 16 || Utils.MozBuildApp === 'browser') &&
+    if ((Utils.AndroidSdkVersion < 16 || Utils.MozBuildApp === "browser") &&
       aState.contains(States.CHECKABLE)) {
       let checked = aState.contains(States.CHECKED);
       let statetr;
-      if (aRoleStr === 'switch') {
-        statetr = checked ? 'stateOn' : 'stateOff';
+      if (aRoleStr === "switch") {
+        statetr = checked ? "stateOn" : "stateOff";
       } else {
-        statetr = checked ? 'stateChecked' : 'stateNotChecked';
+        statetr = checked ? "stateChecked" : "stateNotChecked";
       }
       aOutput.push({string: statetr});
     }
 
     if (aState.contains(States.PRESSED)) {
-      aOutput.push({string: 'statePressed'});
+      aOutput.push({string: "statePressed"});
     }
 
     if (aState.contains(States.EXPANDABLE)) {
       let statetr = aState.contains(States.EXPANDED) ?
-        'stateExpanded' : 'stateCollapsed';
+        "stateExpanded" : "stateCollapsed";
       aOutput.push({string: statetr});
     }
 
     if (aState.contains(States.REQUIRED)) {
-      aOutput.push({string: 'stateRequired'});
+      aOutput.push({string: "stateRequired"});
     }
 
     if (aState.contains(States.TRAVERSED)) {
-      aOutput.push({string: 'stateTraversed'});
+      aOutput.push({string: "stateTraversed"});
     }
 
     if (aState.contains(States.HASPOPUP)) {
-      aOutput.push({string: 'stateHasPopup'});
+      aOutput.push({string: "stateHasPopup"});
     }
 
     if (aState.contains(States.SELECTED)) {
-      aOutput.push({string: 'stateSelected'});
+      aOutput.push({string: "stateSelected"});
     }
   },
 
   _getListUtterance:
     function _getListUtterance(aAccessible, aRoleStr, aFlags, aItemCount) {
       let utterance = [];
       this._addRole(utterance, aAccessible, aRoleStr);
       utterance.push({
-        string: this._getOutputName('listItemsCount'),
+        string: this._getOutputName("listItemsCount"),
         count: aItemCount
       });
 
       this._addName(utterance, aAccessible, aFlags);
       this._addLandmark(utterance, aAccessible);
 
       return utterance;
     }
@@ -846,32 +845,32 @@ this.BrailleGenerator = {  // jshint ign
   genForContext: function genForContext(aContext) {
     let output = OutputGenerator.genForContext.apply(this, arguments);
 
     let acc = aContext.accessible;
 
     // add the static text indicating a list item; do this for both listitems or
     // direct first children of listitems, because these are both common
     // browsing scenarios
-    let addListitemIndicator = function addListitemIndicator(indicator = '*') {
+    let addListitemIndicator = function addListitemIndicator(indicator = "*") {
       output.unshift(indicator);
     };
 
     if (acc.indexInParent === 1 &&
         acc.parent.role == Roles.LISTITEM &&
         acc.previousSibling.role == Roles.STATICTEXT) {
       if (acc.parent.parent && acc.parent.parent.DOMNode &&
-          acc.parent.parent.DOMNode.nodeName == 'UL') {
+          acc.parent.parent.DOMNode.nodeName == "UL") {
         addListitemIndicator();
       } else {
         addListitemIndicator(acc.previousSibling.name.trim());
       }
     } else if (acc.role == Roles.LISTITEM && acc.firstChild &&
                acc.firstChild.role == Roles.STATICTEXT) {
-      if (acc.parent.DOMNode.nodeName == 'UL') {
+      if (acc.parent.DOMNode.nodeName == "UL") {
         addListitemIndicator();
       } else {
         addListitemIndicator(acc.firstChild.name.trim());
       }
     }
 
     return output;
   },
@@ -900,17 +899,17 @@ this.BrailleGenerator = {  // jshint ign
       if (cell) {
         let addHeaders = function addHeaders(aBraille, aHeaders) {
           if (aHeaders.length > 0) {
             aBraille.push.apply(aBraille, aHeaders);
           }
         };
 
         braille.push({
-          string: this._getOutputName('cellInfo'),
+          string: this._getOutputName("cellInfo"),
           args: [cell.columnIndex + 1, cell.rowIndex + 1]
         });
 
         addHeaders(braille, cell.columnHeaders);
         addHeaders(braille, cell.rowHeaders);
       }
 
       this._addName(braille, aAccessible, aFlags);
@@ -967,36 +966,36 @@ this.BrailleGenerator = {  // jshint ign
     if (aContext.accessible.parent.role == Roles.LINK) {
       return [aContext.accessible.parent];
     }
 
     return [];
   },
 
   _getOutputName: function _getOutputName(aName) {
-    return OutputGenerator._getOutputName(aName) + 'Abbr';
+    return OutputGenerator._getOutputName(aName) + "Abbr";
   },
 
   _addRole: function _addRole(aBraille, aAccessible, aRoleStr) {
     if (this.mathmlRolesSet.has(aAccessible.role)) {
       this._addMathRoles(aBraille, aAccessible, aRoleStr);
     } else {
       aBraille.push({string: this._getOutputName(aRoleStr)});
     }
   },
 
   _addState: function _addState(aBraille, aState, aRoleStr) {
     if (aState.contains(States.CHECKABLE)) {
       aBraille.push({
         string: aState.contains(States.CHECKED) ?
-          this._getOutputName('stateChecked') :
-          this._getOutputName('stateUnchecked')
+          this._getOutputName("stateChecked") :
+          this._getOutputName("stateUnchecked")
       });
     }
-    if (aRoleStr === 'toggle button') {
+    if (aRoleStr === "toggle button") {
       aBraille.push({
         string: aState.contains(States.PRESSED) ?
-          this._getOutputName('statePressed') :
-          this._getOutputName('stateUnpressed')
+          this._getOutputName("statePressed") :
+          this._getOutputName("stateUnpressed")
       });
     }
   }
 };
--- a/accessible/jsat/PointerAdapter.jsm
+++ b/accessible/jsat/PointerAdapter.jsm
@@ -1,130 +1,130 @@
 /* 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/. */
 
 /* exported PointerRelay, PointerAdapter */
 
-'use strict';
+"use strict";
 
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
-this.EXPORTED_SYMBOLS = ['PointerRelay', 'PointerAdapter']; // jshint ignore:line
+this.EXPORTED_SYMBOLS = ["PointerRelay", "PointerAdapter"]; // jshint ignore:line
 
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
-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, 'GestureSettings', // jshint ignore:line
-  'resource://gre/modules/accessibility/Gestures.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'GestureTracker', // jshint ignore:line
-  'resource://gre/modules/accessibility/Gestures.jsm');
+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, "GestureSettings", // jshint ignore:line
+  "resource://gre/modules/accessibility/Gestures.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "GestureTracker", // jshint ignore:line
+  "resource://gre/modules/accessibility/Gestures.jsm");
 
 // The virtual touch ID generated by a mouse event.
-const MOUSE_ID = 'mouse';
+const MOUSE_ID = "mouse";
 // Synthesized touch ID.
 const SYNTH_ID = -1;
 
 var PointerRelay = { // jshint ignore:line
   /**
    * A mapping of events we should be intercepting. Entries with a value of
    * |true| are used for compiling high-level gesture events. Entries with a
    * value of |false| are cancelled and do not propogate to content.
    */
   get _eventsOfInterest() {
     delete this._eventsOfInterest;
 
     switch (Utils.widgetToolkit) {
-      case 'android':
+      case "android":
         this._eventsOfInterest = {
-          'touchstart' : true,
-          'touchmove' : true,
-          'touchend' : true };
+          "touchstart": true,
+          "touchmove": true,
+          "touchend": true };
         break;
 
-      case 'gonk':
+      case "gonk":
         this._eventsOfInterest = {
-          'touchstart' : true,
-          'touchmove' : true,
-          'touchend' : true,
-          'mousedown' : false,
-          'mousemove' : false,
-          'mouseup': false,
-          'click': false };
+          "touchstart": true,
+          "touchmove": true,
+          "touchend": true,
+          "mousedown": false,
+          "mousemove": false,
+          "mouseup": false,
+          "click": false };
         break;
 
       default:
         // Desktop.
         this._eventsOfInterest = {
-          'mousemove' : true,
-          'mousedown' : true,
-          'mouseup': true,
-          'click': false
+          "mousemove": true,
+          "mousedown": true,
+          "mouseup": true,
+          "click": false
         };
-        if ('ontouchstart' in Utils.win) {
-          for (let eventType of ['touchstart', 'touchmove', 'touchend']) {
+        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',
-    'mouseup': 'pointerup'
+    "touchstart": "pointerdown",
+    "mousedown": "pointerdown",
+    "touchmove": "pointermove",
+    "mousemove": "pointermove",
+    "touchend": "pointerup",
+    "mouseup": "pointerup"
   },
 
   start: function PointerRelay_start(aOnPointerEvent) {
-    Logger.debug('PointerRelay.start');
+    Logger.debug("PointerRelay.start");
     this.onPointerEvent = aOnPointerEvent;
     for (let eventType in this._eventsOfInterest) {
       Utils.win.addEventListener(eventType, this, true, true);
     }
   },
 
   stop: function PointerRelay_stop() {
-    Logger.debug('PointerRelay.stop');
+    Logger.debug("PointerRelay.stop");
     delete this.lastPointerMove;
     delete this.onPointerEvent;
     for (let eventType in this._eventsOfInterest) {
       Utils.win.removeEventListener(eventType, this, true, true);
     }
   },
 
   handleEvent: function PointerRelay_handleEvent(aEvent) {
     // Don't bother with chrome mouse events.
-    if (Utils.MozBuildApp === 'browser' &&
+    if (Utils.MozBuildApp === "browser" &&
       aEvent.view.top instanceof Ci.nsIDOMChromeWindow) {
       return;
     }
     if (aEvent.mozInputSource === Ci.nsIDOMMouseEvent.MOZ_SOURCE_UNKNOWN ||
         aEvent.isSynthesized) {
       // Ignore events that are scripted or clicks from the a11y API.
       return;
     }
 
     let changedTouches = aEvent.changedTouches || [{
       identifier: MOUSE_ID,
       screenX: aEvent.screenX,
       screenY: aEvent.screenY,
       target: aEvent.target
     }];
 
-    if (Utils.widgetToolkit === 'android' &&
+    if (Utils.widgetToolkit === "android" &&
       changedTouches.length === 1 && changedTouches[0].identifier === 1) {
       return;
     }
 
     if (changedTouches.length === 1 &&
         changedTouches[0].identifier === SYNTH_ID) {
       return;
     }
@@ -149,23 +149,23 @@ var PointerRelay = { // jshint ignore:li
         }
       )
     });
   }
 };
 
 this.PointerAdapter = { // jshint ignore:line
   start: function PointerAdapter_start() {
-    Logger.debug('PointerAdapter.start');
+    Logger.debug("PointerAdapter.start");
     GestureTracker.reset();
     PointerRelay.start(this.handleEvent);
   },
 
   stop: function PointerAdapter_stop() {
-    Logger.debug('PointerAdapter.stop');
+    Logger.debug("PointerAdapter.stop");
     PointerRelay.stop();
     GestureTracker.reset();
   },
 
   handleEvent: function PointerAdapter_handleEvent(aDetail) {
     let timeStamp = Date.now();
     GestureTracker.handle(aDetail, timeStamp);
   }
--- a/accessible/jsat/Presentation.jsm
+++ b/accessible/jsat/Presentation.jsm
@@ -1,46 +1,46 @@
 /* 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/. */
 
 /* exported Presentation */
 
-'use strict';
+"use strict";
 
 const {utils: Cu, interfaces: Ci} = Components;
 
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-Cu.import('resource://gre/modules/accessibility/Utils.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Logger', // jshint ignore:line
-  'resource://gre/modules/accessibility/Utils.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'PivotContext', // jshint ignore:line
-  'resource://gre/modules/accessibility/Utils.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'UtteranceGenerator', // jshint ignore:line
-  'resource://gre/modules/accessibility/OutputGenerator.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'BrailleGenerator', // jshint ignore:line
-  'resource://gre/modules/accessibility/OutputGenerator.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Roles', // jshint ignore:line
-  'resource://gre/modules/accessibility/Constants.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'States', // jshint ignore:line
-  'resource://gre/modules/accessibility/Constants.jsm');
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/accessibility/Utils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Logger", // jshint ignore:line
+  "resource://gre/modules/accessibility/Utils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PivotContext", // jshint ignore:line
+  "resource://gre/modules/accessibility/Utils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "UtteranceGenerator", // jshint ignore:line
+  "resource://gre/modules/accessibility/OutputGenerator.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "BrailleGenerator", // jshint ignore:line
+  "resource://gre/modules/accessibility/OutputGenerator.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Roles", // jshint ignore:line
+  "resource://gre/modules/accessibility/Constants.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "States", // jshint ignore:line
+  "resource://gre/modules/accessibility/Constants.jsm");
 
-this.EXPORTED_SYMBOLS = ['Presentation']; // jshint ignore:line
+this.EXPORTED_SYMBOLS = ["Presentation"]; // jshint ignore:line
 
 /**
  * The interface for all presenter classes. A presenter could be, for example,
  * a speech output module, or a visual cursor indicator.
  */
 function Presenter() {}
 
 Presenter.prototype = {
   /**
    * The type of presenter. Used for matching it with the appropriate output method.
    */
-  type: 'Base',
+  type: "Base",
 
   /**
    * The virtual cursor's position changed.
    * @param {PivotContext} aContext the context object for the new pivot
    *   position.
    * @param {int} aReason the reason for the pivot change.
    *   See nsIAccessiblePivot.
    * @param {bool} aIsFromUserInput the pivot change was invoked by the user
@@ -140,17 +140,17 @@ Presenter.prototype = {
 
 /**
  * Visual presenter. Draws a box around the virtual cursor's position.
  */
 function VisualPresenter() {}
 
 VisualPresenter.prototype = Object.create(Presenter.prototype);
 
-VisualPresenter.prototype.type = 'Visual';
+VisualPresenter.prototype.type = "Visual";
 
 /**
  * The padding in pixels between the object and the highlight border.
  */
 VisualPresenter.prototype.BORDER_PADDING = 2;
 
 VisualPresenter.prototype.viewportChanged =
   function VisualPresenter_viewportChanged(aWindow, aCurrentContext) {
@@ -163,17 +163,17 @@ VisualPresenter.prototype.viewportChange
     let end = aCurrentContext.endOffset;
     if (Utils.isAliveAndVisible(currentAcc)) {
       let bounds = (start === -1 && end === -1) ? Utils.getBounds(currentAcc) :
                    Utils.getTextBounds(currentAcc, start, end);
 
       return {
         type: this.type,
         details: {
-          eventType: 'viewport-change',
+          eventType: "viewport-change",
           bounds: bounds,
           padding: this.BORDER_PADDING
         }
       };
     }
 
     return null;
   };
@@ -192,49 +192,49 @@ VisualPresenter.prototype.pivotChanged =
       let bounds = (aContext.startOffset === -1 && aContext.endOffset === -1) ?
             aContext.bounds : Utils.getTextBounds(aContext.accessibleForBounds,
                                                   aContext.startOffset,
                                                   aContext.endOffset);
 
       return {
         type: this.type,
         details: {
-          eventType: 'vc-change',
+          eventType: "vc-change",
           bounds: bounds,
           padding: this.BORDER_PADDING
         }
       };
     } catch (e) {
-      Logger.logException(e, 'Failed to get bounds');
+      Logger.logException(e, "Failed to get bounds");
       return null;
     }
   };
 
 VisualPresenter.prototype.tabSelected =
   function VisualPresenter_tabSelected(aDocContext, aVCContext) {
     return this.pivotChanged(aVCContext, Ci.nsIAccessiblePivot.REASON_NONE);
   };
 
 VisualPresenter.prototype.tabStateChanged =
   function VisualPresenter_tabStateChanged(aDocObj, aPageState) {
-    if (aPageState == 'newdoc') {
-      return {type: this.type, details: {eventType: 'tabstate-change'}};
+    if (aPageState == "newdoc") {
+      return {type: this.type, details: {eventType: "tabstate-change"}};
     }
 
     return null;
   };
 
 /**
  * Android presenter. Fires Android a11y events.
  */
 function AndroidPresenter() {}
 
 AndroidPresenter.prototype = Object.create(Presenter.prototype);
 
-AndroidPresenter.prototype.type = 'Android';
+AndroidPresenter.prototype.type = "Android";
 
 // Android AccessibilityEvent type constants.
 AndroidPresenter.prototype.ANDROID_VIEW_CLICKED = 0x01;
 AndroidPresenter.prototype.ANDROID_VIEW_LONG_CLICKED = 0x02;
 AndroidPresenter.prototype.ANDROID_VIEW_SELECTED = 0x04;
 AndroidPresenter.prototype.ANDROID_VIEW_FOCUSED = 0x08;
 AndroidPresenter.prototype.ANDROID_VIEW_TEXT_CHANGED = 0x10;
 AndroidPresenter.prototype.ANDROID_WINDOW_STATE_CHANGED = 0x20;
@@ -436,17 +436,17 @@ AndroidPresenter.prototype.viewportChang
 
 AndroidPresenter.prototype.editingModeChanged =
   function AndroidPresenter_editingModeChanged(aIsEditing) {
     return this.announce(UtteranceGenerator.genForEditingMode(aIsEditing));
   };
 
 AndroidPresenter.prototype.announce =
   function AndroidPresenter_announce(aAnnouncement) {
-    let localizedAnnouncement = Utils.localize(aAnnouncement).join(' ');
+    let localizedAnnouncement = Utils.localize(aAnnouncement).join(" ");
     return {
       type: this.type,
       details: [{
         eventType: (Utils.AndroidSdkVersion >= 16) ?
           this.ANDROID_ANNOUNCEMENT : this.ANDROID_VIEW_TEXT_CHANGED,
         text: [localizedAnnouncement],
         addedCount: localizedAnnouncement.length,
         removedCount: 0,
@@ -464,60 +464,60 @@ AndroidPresenter.prototype.liveRegion =
 
 AndroidPresenter.prototype.noMove =
   function AndroidPresenter_noMove(aMoveMethod) {
     return {
       type: this.type,
       details: [
       { eventType: this.ANDROID_VIEW_ACCESSIBILITY_FOCUSED,
         exitView: aMoveMethod,
-        text: ['']
+        text: [""]
       }]
     };
   };
 
 /**
  * A B2G presenter for Gaia.
  */
 function B2GPresenter() {}
 
 B2GPresenter.prototype = Object.create(Presenter.prototype);
 
-B2GPresenter.prototype.type = 'B2G';
+B2GPresenter.prototype.type = "B2G";
 
 B2GPresenter.prototype.keyboardEchoSetting =
-  new PrefCache('accessibility.accessfu.keyboard_echo');
+  new PrefCache("accessibility.accessfu.keyboard_echo");
 B2GPresenter.prototype.NO_ECHO = 0;
 B2GPresenter.prototype.CHARACTER_ECHO = 1;
 B2GPresenter.prototype.WORD_ECHO = 2;
 B2GPresenter.prototype.CHARACTER_AND_WORD_ECHO = 3;
 
 /**
  * A pattern used for haptic feedback.
  * @type {Array}
  */
 B2GPresenter.prototype.PIVOT_CHANGE_HAPTIC_PATTERN = [40];
 
 /**
  * Pivot move reasons.
  * @type {Array}
  */
-B2GPresenter.prototype.pivotChangedReasons = ['none', 'next', 'prev', 'first',
-                                              'last', 'text', 'point'];
+B2GPresenter.prototype.pivotChangedReasons = ["none", "next", "prev", "first",
+                                              "last", "text", "point"];
 
 B2GPresenter.prototype.pivotChanged =
   function B2GPresenter_pivotChanged(aContext, aReason, aIsUserInput) {
     if (!aContext.accessible) {
       return null;
     }
 
     return {
       type: this.type,
       details: {
-        eventType: 'vc-change',
+        eventType: "vc-change",
         data: UtteranceGenerator.genForContext(aContext),
         options: {
           pattern: this.PIVOT_CHANGE_HAPTIC_PATTERN,
           isKey: Utils.isActivatableOnFingerUp(aContext.accessible),
           reason: this.pivotChangedReasons[aReason],
           isUserInput: aIsUserInput,
           hints: aContext.interactionHints
         }
@@ -525,17 +525,17 @@ B2GPresenter.prototype.pivotChanged =
     };
   };
 
 B2GPresenter.prototype.nameChanged =
   function B2GPresenter_nameChanged(aAccessible, aIsPolite = true) {
     return {
       type: this.type,
       details: {
-        eventType: 'name-change',
+        eventType: "name-change",
         data: aAccessible.name,
         options: {enqueue: aIsPolite}
       }
     };
   };
 
 B2GPresenter.prototype.valueChanged =
   function B2GPresenter_valueChanged(aAccessible, aIsPolite = true) {
@@ -543,27 +543,27 @@ B2GPresenter.prototype.valueChanged =
     // the editable value changes are handled in the text changed presenter
     if (Utils.getState(aAccessible).contains(States.EDITABLE)) {
       return null;
     }
 
     return {
       type: this.type,
       details: {
-        eventType: 'value-change',
+        eventType: "value-change",
         data: aAccessible.value,
         options: {enqueue: aIsPolite}
       }
     };
   };
 
 B2GPresenter.prototype.textChanged = function B2GPresenter_textChanged(
   aAccessible, aIsInserted, aStart, aLength, aText, aModifiedText) {
     let echoSetting = this.keyboardEchoSetting.value;
-    let text = '';
+    let text = "";
 
     if (echoSetting == this.CHARACTER_ECHO ||
         echoSetting == this.CHARACTER_AND_WORD_ECHO) {
       text = aModifiedText;
     }
 
     // add word if word boundary is added
     if ((echoSetting == this.WORD_ECHO ||
@@ -579,89 +579,89 @@ B2GPresenter.prototype.textChanged = fun
       if (endBefore.value !== endAfter.value) {
         text += maybeWord;
       }
     }
 
     return {
       type: this.type,
       details: {
-        eventType: 'text-change',
+        eventType: "text-change",
         data: text
       }
     };
 
   };
 
 B2GPresenter.prototype.actionInvoked =
   function B2GPresenter_actionInvoked(aObject, aActionName) {
     return {
       type: this.type,
       details: {
-        eventType: 'action',
+        eventType: "action",
         data: UtteranceGenerator.genForAction(aObject, aActionName)
       }
     };
   };
 
 B2GPresenter.prototype.liveRegion = function B2GPresenter_liveRegion(aContext,
   aIsPolite, aIsHide, aModifiedText) {
     return {
       type: this.type,
       details: {
-        eventType: 'liveregion-change',
+        eventType: "liveregion-change",
         data: UtteranceGenerator.genForLiveRegion(aContext, aIsHide,
           aModifiedText),
         options: {enqueue: aIsPolite}
       }
     };
   };
 
 B2GPresenter.prototype.announce =
   function B2GPresenter_announce(aAnnouncement) {
     return {
       type: this.type,
       details: {
-        eventType: 'announcement',
+        eventType: "announcement",
         data: aAnnouncement
       }
     };
   };
 
 B2GPresenter.prototype.noMove =
   function B2GPresenter_noMove(aMoveMethod) {
     return {
       type: this.type,
       details: {
-        eventType: 'no-move',
+        eventType: "no-move",
         data: aMoveMethod
       }
     };
   };
 
 /**
  * A braille presenter
  */
 function BraillePresenter() {}
 
 BraillePresenter.prototype = Object.create(Presenter.prototype);
 
-BraillePresenter.prototype.type = 'Braille';
+BraillePresenter.prototype.type = "Braille";
 
 BraillePresenter.prototype.pivotChanged =
   function BraillePresenter_pivotChanged(aContext) {
     if (!aContext.accessible) {
       return null;
     }
 
     return {
       type: this.type,
       details: {
         output: Utils.localize(BrailleGenerator.genForContext(aContext)).join(
-          ' '),
+          " "),
         selectionStart: 0,
         selectionEnd: 0
       }
     };
   };
 
 BraillePresenter.prototype.textSelectionChanged =
   function BraillePresenter_textSelectionChanged(aText, aStart, aEnd) {
@@ -673,19 +673,19 @@ BraillePresenter.prototype.textSelection
       }
     };
   };
 
 this.Presentation = { // jshint ignore:line
   get presenters() {
     delete this.presenters;
     let presenterMap = {
-      'mobile/android': [VisualPresenter, AndroidPresenter],
-      'b2g': [VisualPresenter, B2GPresenter],
-      'browser': [VisualPresenter, B2GPresenter, AndroidPresenter]
+      "mobile/android": [VisualPresenter, AndroidPresenter],
+      "b2g": [VisualPresenter, B2GPresenter],
+      "browser": [VisualPresenter, B2GPresenter, AndroidPresenter]
     };
     this.presenters = presenterMap[Utils.MozBuildApp].map(P => new P());
     return this.presenters;
   },
 
   get displayedAccessibles() {
     delete this.displayedAccessibles;
     this.displayedAccessibles = new WeakMap();
@@ -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/Traversal.jsm
+++ b/accessible/jsat/Traversal.jsm
@@ -1,33 +1,33 @@
 /* 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/. */
 
 /* exported TraversalRules, TraversalHelper */
 
-'use strict';
+"use strict";
 
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
-this.EXPORTED_SYMBOLS = ['TraversalRules', 'TraversalHelper']; // jshint ignore:line
+this.EXPORTED_SYMBOLS = ["TraversalRules", "TraversalHelper"]; // jshint ignore:line
 
-Cu.import('resource://gre/modules/accessibility/Utils.jsm');
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Roles',  // jshint ignore:line
-  'resource://gre/modules/accessibility/Constants.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Filters',  // jshint ignore:line
-  'resource://gre/modules/accessibility/Constants.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'States',  // jshint ignore:line
-  'resource://gre/modules/accessibility/Constants.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Prefilters',  // jshint ignore:line
-  'resource://gre/modules/accessibility/Constants.jsm');
+Cu.import("resource://gre/modules/accessibility/Utils.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Roles",  // jshint ignore:line
+  "resource://gre/modules/accessibility/Constants.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Filters",  // jshint ignore:line
+  "resource://gre/modules/accessibility/Constants.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "States",  // jshint ignore:line
+  "resource://gre/modules/accessibility/Constants.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Prefilters",  // jshint ignore:line
+  "resource://gre/modules/accessibility/Constants.jsm");
 
-var gSkipEmptyImages = new PrefCache('accessibility.accessfu.skip_empty_images');
+var gSkipEmptyImages = new PrefCache("accessibility.accessfu.skip_empty_images");
 
 function BaseTraversalRule(aRoles, aMatchFunc, aPreFilter, aContainerRule) {
   this._explicitMatchRoles = new Set(aRoles);
   this._matchRoles = aRoles;
   if (aRoles.length) {
     if (aRoles.indexOf(Roles.LABEL) < 0) {
       this._matchRoles.push(Roles.LABEL);
     }
@@ -42,22 +42,21 @@ function BaseTraversalRule(aRoles, aMatc
 }
 
 BaseTraversalRule.prototype = {
     getMatchRoles: function BaseTraversalRule_getmatchRoles(aRoles) {
       aRoles.value = this._matchRoles;
       return aRoles.value.length;
     },
 
-    match: function BaseTraversalRule_match(aAccessible)
-    {
+    match: function BaseTraversalRule_match(aAccessible) {
       let role = aAccessible.role;
       if (role == Roles.INTERNAL_FRAME) {
         return (Utils.getMessageManager(aAccessible.DOMNode)) ?
-          Filters.MATCH  | Filters.IGNORE_SUBTREE : Filters.IGNORE;
+          Filters.MATCH | Filters.IGNORE_SUBTREE : Filters.IGNORE;
       }
 
       let matchResult =
         (this._explicitMatchRoles.has(role) || !this._explicitMatchRoles.size) ?
         this._matchFunc(aAccessible) : Filters.IGNORE;
 
       // If we are on a label that nests a checkbox/radio we should land on it.
       // It is a bigger touch target, and it reduces clutter.
@@ -189,24 +188,23 @@ this.TraversalRules = { // jshint ignore
 
   SimpleOnScreen: new BaseTraversalRule(
     gSimpleTraversalRoles, gSimpleMatchFunc,
     Prefilters.DEFUNCT | Prefilters.INVISIBLE | Prefilters.ARIA_HIDDEN |
     Prefilters.TRANSPARENT | Prefilters.OFFSCREEN),
 
   Anchor: new BaseTraversalRule(
     [Roles.LINK],
-    function Anchor_match(aAccessible)
-    {
+    function Anchor_match(aAccessible) {
       // We want to ignore links, only focus named anchors.
       if (Utils.getState(aAccessible).contains(States.LINKED)) {
         return Filters.IGNORE;
-      } else {
-        return Filters.MATCH;
       }
+      return Filters.MATCH;
+
     }),
 
   Button: new BaseTraversalRule(
     [Roles.PUSHBUTTON,
      Roles.SPINBUTTON,
      Roles.TOGGLE_BUTTON,
      Roles.BUTTONDROPDOWN,
      Roles.BUTTONDROPDOWNGRID]),
@@ -227,23 +225,23 @@ this.TraversalRules = { // jshint ignore
   Section: new BaseTraversalRule(
     [],
     function Section_match(aAccessible) {
       if (aAccessible.role === Roles.HEADING) {
         return Filters.MATCH;
       }
 
       let matchedRole = Utils.matchRoles(aAccessible, [
-        'banner',
-        'complementary',
-        'contentinfo',
-        'main',
-        'navigation',
-        'search',
-        'region'
+        "banner",
+        "complementary",
+        "contentinfo",
+        "main",
+        "navigation",
+        "search",
+        "region"
         ]);
 
       return matchedRole ? Filters.MATCH : Filters.IGNORE;
     }, null, true),
 
   Entry: new BaseTraversalRule(
     [Roles.ENTRY,
      Roles.PASSWORD_TEXT]),
@@ -279,24 +277,23 @@ this.TraversalRules = { // jshint ignore
     }),
 
   ListItem: new BaseTraversalRule(
     [Roles.LISTITEM,
      Roles.TERM]),
 
   Link: new BaseTraversalRule(
     [Roles.LINK],
-    function Link_match(aAccessible)
-    {
+    function Link_match(aAccessible) {
       // We want to ignore anchors, only focus real links.
       if (Utils.getState(aAccessible).contains(States.LINKED)) {
         return Filters.MATCH;
-      } else {
-        return Filters.IGNORE;
       }
+      return Filters.IGNORE;
+
     }),
 
   /* For TalkBack's "Control" granularity. Form conrols and links */
   Control: new BaseTraversalRule(
     [Roles.PUSHBUTTON,
      Roles.SPINBUTTON,
      Roles.TOGGLE_BUTTON,
      Roles.BUTTONDROPDOWN,
@@ -309,18 +306,17 @@ this.TraversalRules = { // jshint ignore
      Roles.RADIOBUTTON,
      Roles.RADIO_MENU_ITEM,
      Roles.SLIDER,
      Roles.CHECKBUTTON,
      Roles.CHECK_MENU_ITEM,
      Roles.SWITCH,
      Roles.LINK,
      Roles.MENUITEM],
-    function Control_match(aAccessible)
-    {
+    function Control_match(aAccessible) {
       // We want to ignore anchors, only focus real links.
       if (aAccessible.role == Roles.LINK &&
           !Utils.getState(aAccessible).contains(States.LINKED)) {
         return Filters.IGNORE;
       }
       return Filters.MATCH;
     }),
 
@@ -356,17 +352,17 @@ this.TraversalRules = { // jshint ignore
     [Roles.TABLE]),
 
   Checkbox: new BaseTraversalRule(
     [Roles.CHECKBUTTON,
      Roles.CHECK_MENU_ITEM,
      Roles.SWITCH /* A type of checkbox that represents on/off values */]),
 
   _shouldSkipImage: function _shouldSkipImage(aAccessible) {
-    if (gSkipEmptyImages.value && aAccessible.name === '') {
+    if (gSkipEmptyImages.value && aAccessible.name === "") {
       return Filters.IGNORE;
     }
     return Filters.MATCH;
   }
 };
 
 this.TraversalHelper = {
   _helperPivotCache: null,
@@ -404,14 +400,14 @@ this.TraversalHelper = {
           aVirtualCursor.modalRoot = null;
         } else {
           // If we failed to step to another container, break and return false.
           break;
         }
       }
 
       return moved;
-    } else {
-      return aVirtualCursor[aMethod](rule);
     }
+    return aVirtualCursor[aMethod](rule);
+
   }
 
 };
--- a/accessible/jsat/Utils.jsm
+++ b/accessible/jsat/Utils.jsm
@@ -1,49 +1,49 @@
 /* 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/. */
 
 /* exported Utils, Logger, PivotContext, PrefCache */
 
-'use strict';
+"use strict";
 
 const {classes: Cc, utils: Cu, interfaces: Ci} = Components;
 
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Services', // jshint ignore:line
-  'resource://gre/modules/Services.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Rect', // jshint ignore:line
-  'resource://gre/modules/Geometry.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Roles', // jshint ignore:line
-  'resource://gre/modules/accessibility/Constants.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Events', // jshint ignore:line
-  'resource://gre/modules/accessibility/Constants.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Relations', // jshint ignore:line
-  'resource://gre/modules/accessibility/Constants.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'States', // jshint ignore:line
-  'resource://gre/modules/accessibility/Constants.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'PluralForm', // jshint ignore:line
-  'resource://gre/modules/PluralForm.jsm');
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Services", // jshint ignore:line
+  "resource://gre/modules/Services.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Rect", // jshint ignore:line
+  "resource://gre/modules/Geometry.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Roles", // jshint ignore:line
+  "resource://gre/modules/accessibility/Constants.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Events", // jshint ignore:line
+  "resource://gre/modules/accessibility/Constants.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Relations", // jshint ignore:line
+  "resource://gre/modules/accessibility/Constants.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "States", // jshint ignore:line
+  "resource://gre/modules/accessibility/Constants.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PluralForm", // jshint ignore:line
+  "resource://gre/modules/PluralForm.jsm");
 
-this.EXPORTED_SYMBOLS = ['Utils', 'Logger', 'PivotContext', 'PrefCache']; // jshint ignore:line
+this.EXPORTED_SYMBOLS = ["Utils", "Logger", "PivotContext", "PrefCache"]; // jshint ignore:line
 
 this.Utils = { // jshint ignore:line
   _buildAppMap: {
-    '{3c2e2abc-06d4-11e1-ac3b-374f68613e61}': 'b2g',
-    '{d1bfe7d9-c01e-4237-998b-7b5f960a4314}': 'graphene',
-    '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}': 'browser',
-    '{aa3c5121-dab2-40e2-81ca-7ea25febc110}': 'mobile/android',
-    '{a23983c0-fd0e-11dc-95ff-0800200c9a66}': 'mobile/xul'
+    "{3c2e2abc-06d4-11e1-ac3b-374f68613e61}": "b2g",
+    "{d1bfe7d9-c01e-4237-998b-7b5f960a4314}": "graphene",
+    "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}": "browser",
+    "{aa3c5121-dab2-40e2-81ca-7ea25febc110}": "mobile/android",
+    "{a23983c0-fd0e-11dc-95ff-0800200c9a66}": "mobile/xul"
   },
 
   init: function Utils_init(aWindow) {
     if (this._win) {
       // XXX: only supports attaching to one window now.
-      throw new Error('Only one top-level window could used with AccessFu');
+      throw new Error("Only one top-level window could used with AccessFu");
     }
     this._win = Cu.getWeakReference(aWindow);
   },
 
   uninit: function Utils_uninit() {
     if (!this._win) {
       return;
     }
@@ -63,17 +63,17 @@ this.Utils = { // jshint ignore:line
       return null;
     }
     return win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(
       Ci.nsIDOMWindowUtils);
   },
 
   get AccService() {
     if (!this._AccService) {
-      this._AccService = Cc['@mozilla.org/accessibilityService;1'].
+      this._AccService = Cc["@mozilla.org/accessibilityService;1"].
         getService(Ci.nsIAccessibilityService);
     }
 
     return this._AccService;
   },
 
   set MozBuildApp(value) {
     this._buildApp = value;
@@ -98,26 +98,26 @@ this.Utils = { // jshint ignore:line
       this._widgetToolkit = Services.appinfo.widgetToolkit;
     }
     return this._widgetToolkit;
   },
 
   get ScriptName() {
     if (!this._ScriptName) {
       this._ScriptName =
-        (Services.appinfo.processType == 2) ? 'AccessFuContent' : 'AccessFu';
+        (Services.appinfo.processType == 2) ? "AccessFuContent" : "AccessFu";
     }
     return this._ScriptName;
   },
 
   get AndroidSdkVersion() {
     if (!this._AndroidSdkVersion) {
-      if (Services.appinfo.OS == 'Android') {
+      if (Services.appinfo.OS == "Android") {
         this._AndroidSdkVersion = Services.sysinfo.getPropertyAsInt32(
-          'version');
+          "version");
       } else {
         // Most useful in desktop debugging.
         this._AndroidSdkVersion = 16;
       }
     }
     return this._AndroidSdkVersion;
   },
 
@@ -126,32 +126,32 @@ this.Utils = { // jshint ignore:line
     this._AndroidSdkVersion = value;
   },
 
   get BrowserApp() {
     if (!this.win) {
       return null;
     }
     switch (this.MozBuildApp) {
-      case 'mobile/android':
+      case "mobile/android":
         return this.win.BrowserApp;
-      case 'browser':
+      case "browser":
         return this.win.gBrowser;
-      case 'b2g':
+      case "b2g":
         return this.win.shell;
       default:
         return null;
     }
   },
 
   get CurrentBrowser() {
     if (!this.BrowserApp) {
       return null;
     }
-    if (this.MozBuildApp == 'b2g') {
+    if (this.MozBuildApp == "b2g") {
       return this.BrowserApp.contentBrowser;
     }
     return this.BrowserApp.selectedBrowser;
   },
 
   get CurrentContentDoc() {
     let browser = this.CurrentBrowser;
     return browser ? browser.contentDocument : null;
@@ -159,37 +159,37 @@ this.Utils = { // jshint ignore:line
 
   get AllMessageManagers() {
     let messageManagers = new Set();
 
     function collectLeafMessageManagers(mm) {
       for (let i = 0; i < mm.childCount; i++) {
         let childMM = mm.getChildAt(i);
 
-        if ('sendAsyncMessage' in childMM) {
+        if ("sendAsyncMessage" in childMM) {
           messageManagers.add(childMM);
         } else {
           collectLeafMessageManagers(childMM);
         }
       }
     }
 
     collectLeafMessageManagers(this.win.messageManager);
 
     let document = this.CurrentContentDoc;
 
     if (document) {
-      if (document.location.host === 'b2g') {
+      if (document.location.host === "b2g") {
         // The document is a b2g app chrome (ie. Mulet).
         let contentBrowser = this.win.content.shell.contentBrowser;
         messageManagers.add(this.getMessageManager(contentBrowser));
         document = contentBrowser.contentDocument;
       }
 
-      let remoteframes = document.querySelectorAll('iframe');
+      let remoteframes = document.querySelectorAll("iframe");
 
       for (let i = 0; i < remoteframes.length; ++i) {
         let mm = this.getMessageManager(remoteframes[i]);
         if (mm) {
           messageManagers.add(mm);
         }
       }
 
@@ -212,41 +212,41 @@ this.Utils = { // jshint ignore:line
     // Clean up the white space.
     return localized.filter(word => word).map(word => word.trim()).
       filter(trimmed => trimmed);
   },
 
   get stringBundle() {
     delete this.stringBundle;
     let bundle = Services.strings.createBundle(
-      'chrome://global/locale/AccessFu.properties');
+      "chrome://global/locale/AccessFu.properties");
     this.stringBundle = {
       get: function stringBundle_get(aDetails = {}) {
-        if (!aDetails || typeof aDetails === 'string') {
+        if (!aDetails || typeof aDetails === "string") {
           return aDetails;
         }
-        let str = '';
+        let str = "";
         let string = aDetails.string;
         if (!string) {
           return str;
         }
         try {
           let args = aDetails.args;
           let count = aDetails.count;
           if (args) {
             str = bundle.formatStringFromName(string, args, args.length);
           } else {
             str = bundle.GetStringFromName(string);
           }
           if (count) {
             str = PluralForm.get(count, str);
-            str = str.replace('#1', count);
+            str = str.replace("#1", count);
           }
         } catch (e) {
-          Logger.debug('Failed to get a string from a bundle for', string);
+          Logger.debug("Failed to get a string from a bundle for", string);
         } finally {
           return str;
         }
       }
     };
     return this.stringBundle;
   },
 
@@ -259,22 +259,22 @@ this.Utils = { // jshint ignore:line
     }
   },
 
   getState: function getState(aAccessibleOrEvent) {
     if (aAccessibleOrEvent instanceof Ci.nsIAccessibleStateChangeEvent) {
       return new State(
         aAccessibleOrEvent.isExtraState ? 0 : aAccessibleOrEvent.state,
         aAccessibleOrEvent.isExtraState ? aAccessibleOrEvent.state : 0);
-    } else {
+    }
       let state = {};
       let extState = {};
       aAccessibleOrEvent.getState(state, extState);
       return new State(state.value, extState.value);
-    }
+
   },
 
   getAttributes: function getAttributes(aAccessible) {
     let attributes = {};
 
     if (aAccessible && aAccessible.attributes) {
       let attributesEnum = aAccessible.attributes.enumerate();
 
@@ -359,43 +359,43 @@ this.Utils = { // jshint ignore:line
     while (acc) {
       if (acc == aSubTreeRoot) {
         return true;
       }
 
       try {
         acc = acc.parent;
       } catch (x) {
-        Logger.debug('Failed to get parent:', x);
+        Logger.debug("Failed to get parent:", x);
         acc = null;
       }
     }
 
     return false;
   },
 
   isHidden: function isHidden(aAccessible) {
     // Need to account for aria-hidden, so can't just check for INVISIBLE
     // state.
     let hidden = Utils.getAttributes(aAccessible).hidden;
-    return hidden && hidden === 'true';
+    return hidden && hidden === "true";
   },
 
   visibleChildCount: function visibleChildCount(aAccessible) {
     let count = 0;
     for (let child = aAccessible.firstChild; child; child = child.nextSibling) {
       if (!this.isHidden(child)) {
         ++count;
       }
     }
     return count;
   },
 
   inHiddenSubtree: function inHiddenSubtree(aAccessible) {
-    for (let acc=aAccessible; acc; acc=acc.parent) {
+    for (let acc = aAccessible; acc; acc = acc.parent) {
       if (this.isHidden(acc)) {
         return true;
       }
     }
     return false;
   },
 
   isAliveAndVisible: function isAliveAndVisible(aAccessible, aIsOnScreen) {
@@ -413,54 +413,54 @@ this.Utils = { // jshint ignore:line
     } catch (x) {
       return false;
     }
 
     return true;
   },
 
   matchAttributeValue: function matchAttributeValue(aAttributeValue, values) {
-    let attrSet = new Set(aAttributeValue.split(' '));
+    let attrSet = new Set(aAttributeValue.split(" "));
     for (let value of values) {
       if (attrSet.has(value)) {
         return value;
       }
     }
   },
 
   getLandmarkName: function getLandmarkName(aAccessible) {
     return this.matchRoles(aAccessible, [
-      'banner',
-      'complementary',
-      'contentinfo',
-      'main',
-      'navigation',
-      'search'
+      "banner",
+      "complementary",
+      "contentinfo",
+      "main",
+      "navigation",
+      "search"
     ]);
   },
 
   getMathRole: function getMathRole(aAccessible) {
     return this.matchRoles(aAccessible, [
-      'base',
-      'close-fence',
-      'denominator',
-      'numerator',
-      'open-fence',
-      'overscript',
-      'presubscript',
-      'presuperscript',
-      'root-index',
-      'subscript',
-      'superscript',
-      'underscript'
+      "base",
+      "close-fence",
+      "denominator",
+      "numerator",
+      "open-fence",
+      "overscript",
+      "presubscript",
+      "presuperscript",
+      "root-index",
+      "subscript",
+      "superscript",
+      "underscript"
     ]);
   },
 
   matchRoles: function matchRoles(aAccessible, aRoles) {
-    let roles = this.getAttributes(aAccessible)['xml-roles'];
+    let roles = this.getAttributes(aAccessible)["xml-roles"];
     if (!roles) {
       return;
     }
 
     // Looking up a role that would match any in the provided roles.
     return this.matchAttributeValue(roles, aRoles);
   },
 
@@ -476,29 +476,29 @@ this.Utils = { // jshint ignore:line
     }
 
     return null;
   },
 
   isListItemDecorator: function isListItemDecorator(aStaticText,
                                                     aExcludeOrdered) {
     let parent = aStaticText.parent;
-    if (aExcludeOrdered && parent.parent.DOMNode.nodeName === 'OL') {
+    if (aExcludeOrdered && parent.parent.DOMNode.nodeName === "OL") {
       return false;
     }
 
     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
@@ -511,17 +511,17 @@ this.Utils = { // jshint ignore:line
     }
 
   },
 
   isActivatableOnFingerUp: function isActivatableOnFingerUp(aAccessible) {
     if (aAccessible.role === Roles.KEY) {
       return true;
     }
-    let quick_activate = this.getAttributes(aAccessible)['moz-quick-activate'];
+    let quick_activate = this.getAttributes(aAccessible)["moz-quick-activate"];
     return quick_activate && JSON.parse(quick_activate);
   }
 };
 
 /**
  * State object used internally to process accessible's states.
  * @param {Number} aBase     Base state.
  * @param {Number} aExtended Extended state.
@@ -537,41 +537,41 @@ State.prototype = {
   },
   toString: function State_toString() {
     let stateStrings = Utils.AccService.
       getStringStates(this.base, this.extended);
     let statesArray = new Array(stateStrings.length);
     for (let i = 0; i < statesArray.length; i++) {
       statesArray[i] = stateStrings.item(i);
     }
-    return '[' + statesArray.join(', ') + ']';
+    return "[" + statesArray.join(", ") + "]";
   }
 };
 
 this.Logger = { // jshint ignore:line
   GESTURE: -1,
   DEBUG: 0,
   INFO: 1,
   WARNING: 2,
   ERROR: 3,
-  _LEVEL_NAMES: ['GESTURE', 'DEBUG', 'INFO', 'WARNING', 'ERROR'],
+  _LEVEL_NAMES: ["GESTURE", "DEBUG", "INFO", "WARNING", "ERROR"],
 
   logLevel: 1, // INFO;
 
   test: false,
 
   log: function log(aLogLevel) {
     if (aLogLevel < this.logLevel) {
       return;
     }
 
     let args = Array.prototype.slice.call(arguments, 1);
-    let message = (typeof(args[0]) === 'function' ? args[0]() : args).join(' ');
-    message = '[' + Utils.ScriptName + '] ' + this._LEVEL_NAMES[aLogLevel + 1] +
-      ' ' + message + '\n';
+    let message = (typeof(args[0]) === "function" ? args[0]() : args).join(" ");
+    message = "[" + Utils.ScriptName + "] " + this._LEVEL_NAMES[aLogLevel + 1] +
+      " " + message + "\n";
     dump(message);
     // Note: used for testing purposes. If |this.test| is true, also log to
     // the console service.
     if (this.test) {
       try {
         Services.console.logStringMessage(message);
       } catch (ex) {
         // There was an exception logging to the console service.
@@ -600,72 +600,72 @@ this.Logger = { // jshint ignore:line
   },
 
   error: function error() {
     this.log.apply(
       this, [this.ERROR].concat(Array.prototype.slice.call(arguments)));
   },
 
   logException: function logException(
-    aException, aErrorMessage = 'An exception has occured') {
+    aException, aErrorMessage = "An exception has occured") {
     try {
-      let stackMessage = '';
+      let stackMessage = "";
       if (aException.stack) {
-        stackMessage = '  ' + aException.stack.replace(/\n/g, '\n  ');
+        stackMessage = "  " + aException.stack.replace(/\n/g, "\n  ");
       } else if (aException.location) {
         let frame = aException.location;
         let stackLines = [];
         while (frame && frame.lineNumber) {
           stackLines.push(
-            '  ' + frame.name + '@' + frame.filename + ':' + frame.lineNumber);
+            "  " + frame.name + "@" + frame.filename + ":" + frame.lineNumber);
           frame = frame.caller;
         }
-        stackMessage = stackLines.join('\n');
+        stackMessage = stackLines.join("\n");
       } else {
         stackMessage =
-          '(' + aException.fileName + ':' + aException.lineNumber + ')';
+          "(" + aException.fileName + ":" + aException.lineNumber + ")";
       }
-      this.error(aErrorMessage + ':\n ' +
-                 aException.message + '\n' +
+      this.error(aErrorMessage + ":\n " +
+                 aException.message + "\n" +
                  stackMessage);
     } catch (x) {
       this.error(x);
     }
   },
 
   accessibleToString: function accessibleToString(aAccessible) {
     if (!aAccessible) {
-      return '[ null ]';
+      return "[ null ]";
     }
 
     try {
-      return'[ ' + Utils.AccService.getStringRole(aAccessible.role) +
-        ' | ' + aAccessible.name + ' ]';
+      return "[ " + Utils.AccService.getStringRole(aAccessible.role) +
+        " | " + aAccessible.name + " ]";
     } catch (x) {
-      return '[ defunct ]';
+      return "[ defunct ]";
     }
   },
 
   eventToString: function eventToString(aEvent) {
     let str = Utils.AccService.getStringEventType(aEvent.eventType);
     if (aEvent.eventType == Events.STATE_CHANGE) {
       let event = aEvent.QueryInterface(Ci.nsIAccessibleStateChangeEvent);
       let stateStrings = event.isExtraState ?
         Utils.AccService.getStringStates(0, event.state) :
         Utils.AccService.getStringStates(event.state, 0);
-      str += ' (' + stateStrings.item(0) + ')';
+      str += " (" + stateStrings.item(0) + ")";
     }
 
     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) + ')';
+      str += " (" + this.accessibleToString(event.oldAccessible) + " -> " +
+        this.accessibleToString(pivot.position) + ")";
     }
 
     return str;
   },
 
   statesToString: function statesToString(aAccessible) {
     return Utils.getState(aAccessible).toString();
   },
@@ -675,23 +675,23 @@ this.Logger = { // jshint ignore:line
       return;
     }
 
     this._dumpTreeInternal(aLogLevel, aRootAccessible, 0);
   },
 
   _dumpTreeInternal:
     function _dumpTreeInternal(aLogLevel, aAccessible, aIndent) {
-      let indentStr = '';
+      let indentStr = "";
       for (let i = 0; i < aIndent; i++) {
-        indentStr += ' ';
+        indentStr += " ";
       }
       this.log(aLogLevel, indentStr,
                this.accessibleToString(aAccessible),
-               '(' + this.statesToString(aAccessible) + ')');
+               "(" + this.statesToString(aAccessible) + ")");
       for (let i = 0; i < aAccessible.childCount; i++) {
         this._dumpTreeInternal(aLogLevel, aAccessible.getChildAt(i),
           aIndent + 1);
       }
     }
 };
 
 /**
@@ -749,26 +749,26 @@ PivotContext.prototype = {
                             Ci.nsIAccessibleText.TEXT_OFFSET_END_OF_TEXT)};
       let hypertextAcc = this._accessible.QueryInterface(
         Ci.nsIAccessibleHyperText);
 
       // Iterate through the links in backwards order so text replacements don't
       // affect the offsets of links yet to be processed.
       for (let i = hypertextAcc.linkCount - 1; i >= 0; i--) {
         let link = hypertextAcc.getLinkAt(i);
-        let linkText = '';
+        let linkText = "";
         if (link instanceof Ci.nsIAccessibleText) {
           linkText = link.QueryInterface(Ci.nsIAccessibleText).
                           getText(0,
                             Ci.nsIAccessibleText.TEXT_OFFSET_END_OF_TEXT);
         }
 
         let start = link.startIndex;
         let end = link.endIndex;
-        for (let offset of ['startOffset', 'endOffset']) {
+        for (let offset of ["startOffset", "endOffset"]) {
           if (this[offset] >= end) {
             result[offset] += linkText.length - (end - start);
           }
         }
         result.text = result.text.substring(0, start) + linkText +
                       result.text.substring(end);
       }
 
@@ -787,17 +787,17 @@ PivotContext.prototype = {
     let ancestry = [];
     let parent = aAccessible;
     try {
       while (parent && (parent = parent.parent)) {
        ancestry.push(parent);
       }
     } catch (x) {
       // A defunct accessible will raise an exception geting parent.
-      Logger.debug('Failed to get parent:', x);
+      Logger.debug("Failed to get parent:", x);
     }
     return ancestry.reverse();
   },
 
   /**
    * A list of the old accessible's ancestry.
    */
   get oldAncestry() {
@@ -874,23 +874,23 @@ PivotContext.prototype = {
 
   /**
    * Get interaction hints for the context ancestry.
    * @return {Array} Array of interaction hints.
    */
   get interactionHints() {
     let hints = [];
     this.newAncestry.concat(this.accessible).reverse().forEach(aAccessible => {
-      let hint = Utils.getAttributes(aAccessible)['moz-hint'];
+      let hint = Utils.getAttributes(aAccessible)["moz-hint"];
       if (hint) {
         hints.push(hint);
       } else if (aAccessible.actionCount > 0) {
         hints.push({
           string: Utils.AccService.getStringRole(
-            aAccessible.role).replace(/\s/g, '') + '-hint'
+            aAccessible.role).replace(/\s/g, "") + "-hint"
         });
       }
     });
     return hints;
   },
 
   /*
    * A subtree generator function, used to generate a flattened
@@ -941,17 +941,17 @@ PivotContext.prototype = {
         yield enumerator.getNext().QueryInterface(Ci.nsIAccessible).name;
       }
     };
 
     cellInfo.current = getAccessibleCell(aAccessible);
 
     if (!cellInfo.current) {
       Logger.warning(aAccessible,
-        'does not support nsIAccessibleTableCell interface.');
+        "does not support nsIAccessibleTableCell interface.");
       this._cells.set(domNode, null);
       return null;
     }
 
     let table = cellInfo.current.table;
     if (table.isProbablyForLayout()) {
       this._cells.set(domNode, null);
       return null;
@@ -1053,21 +1053,21 @@ PrefCache.prototype = {
     } catch (x) {
       // Pref does not exist.
       return null;
     }
   },
 
   observe: function observe(aSubject) {
     this.value = this._getValue(aSubject.QueryInterface(Ci.nsIPrefBranch));
-    Logger.info('pref changed', this.name, this.value);
+    Logger.info("pref changed", this.name, this.value);
     if (this.callback) {
       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/jsat/content-script.js
+++ b/accessible/jsat/content-script.js
@@ -2,152 +2,152 @@
  * 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/. */
 
 /* eslint-env mozilla/frame-script */
 
 var Ci = Components.interfaces;
 var Cu = Components.utils;
 
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Logger',
-  'resource://gre/modules/accessibility/Utils.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Presentation',
-  'resource://gre/modules/accessibility/Presentation.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Utils',
-  'resource://gre/modules/accessibility/Utils.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'EventManager',
-  'resource://gre/modules/accessibility/EventManager.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'ContentControl',
-  'resource://gre/modules/accessibility/ContentControl.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Roles',
-  'resource://gre/modules/accessibility/Constants.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'States',
-  'resource://gre/modules/accessibility/Constants.jsm');
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Logger",
+  "resource://gre/modules/accessibility/Utils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Presentation",
+  "resource://gre/modules/accessibility/Presentation.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Utils",
+  "resource://gre/modules/accessibility/Utils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "EventManager",
+  "resource://gre/modules/accessibility/EventManager.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "ContentControl",
+  "resource://gre/modules/accessibility/ContentControl.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Roles",
+  "resource://gre/modules/accessibility/Constants.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "States",
+  "resource://gre/modules/accessibility/Constants.jsm");
 
-Logger.info('content-script.js', content.document.location);
+Logger.info("content-script.js", content.document.location);
 
 var eventManager = null;
 var contentControl = null;
 
 function forwardToParent(aMessage) {
   // XXX: This is a silly way to make a deep copy
   let newJSON = JSON.parse(JSON.stringify(aMessage.json));
-  newJSON.origin = 'child';
+  newJSON.origin = "child";
   sendAsyncMessage(aMessage.name, newJSON);
 }
 
 function forwardToChild(aMessage, aListener, aVCPosition) {
   let acc = aVCPosition || Utils.getVirtualCursor(content.document).position;
 
   if (!Utils.isAliveAndVisible(acc) || acc.role != Roles.INTERNAL_FRAME) {
     return false;
   }
 
   Logger.debug(() => {
-    return ['forwardToChild', Logger.accessibleToString(acc),
-            aMessage.name, JSON.stringify(aMessage.json, null, '  ')];
+    return ["forwardToChild", Logger.accessibleToString(acc),
+            aMessage.name, JSON.stringify(aMessage.json, null, "  ")];
   });
 
   let mm = Utils.getMessageManager(acc.DOMNode);
 
   if (aListener) {
     mm.addMessageListener(aMessage.name, aListener);
   }
 
   // XXX: This is a silly way to make a deep copy
   let newJSON = JSON.parse(JSON.stringify(aMessage.json));
-  newJSON.origin = 'parent';
+  newJSON.origin = "parent";
   if (Utils.isContentProcess) {
     // XXX: OOP content's screen offset is 0,
     // so we remove the real screen offset here.
     newJSON.x -= content.mozInnerScreenX;
     newJSON.y -= content.mozInnerScreenY;
   }
   mm.sendAsyncMessage(aMessage.name, newJSON);
   return true;
 }
 
 function activateContextMenu(aMessage) {
   let position = Utils.getVirtualCursor(content.document).position;
   if (!forwardToChild(aMessage, activateContextMenu, position)) {
     let center = Utils.getBounds(position, true).center();
 
-    let evt = content.document.createEvent('HTMLEvents');
-    evt.initEvent('contextmenu', true, true);
+    let evt = content.document.createEvent("HTMLEvents");
+    evt.initEvent("contextmenu", true, true);
     evt.clientX = center.x;
     evt.clientY = center.y;
     position.DOMNode.dispatchEvent(evt);
   }
 }
 
 function presentCaretChange(aText, aOldOffset, aNewOffset) {
   if (aOldOffset !== aNewOffset) {
     let msg = Presentation.textSelectionChanged(aText, aNewOffset, aNewOffset,
                                                 aOldOffset, aOldOffset, true);
-    sendAsyncMessage('AccessFu:Present', msg);
+    sendAsyncMessage("AccessFu:Present", msg);
   }
 }
 
 function scroll(aMessage) {
   let position = Utils.getVirtualCursor(content.document).position;
   if (!forwardToChild(aMessage, scroll, position)) {
-    sendAsyncMessage('AccessFu:DoScroll',
+    sendAsyncMessage("AccessFu:DoScroll",
                      { bounds: Utils.getBounds(position, true),
                        page: aMessage.json.page,
                        horizontal: aMessage.json.horizontal });
   }
 }
 
 addMessageListener(
-  'AccessFu:Start',
+  "AccessFu:Start",
   function(m) {
     if (m.json.logLevel) {
       Logger.logLevel = Logger[m.json.logLevel];
     }
 
-    Logger.debug('AccessFu:Start');
+    Logger.debug("AccessFu:Start");
     if (m.json.buildApp)
       Utils.MozBuildApp = m.json.buildApp;
 
-    addMessageListener('AccessFu:ContextMenu', activateContextMenu);
-    addMessageListener('AccessFu:Scroll', scroll);
+    addMessageListener("AccessFu:ContextMenu", activateContextMenu);
+    addMessageListener("AccessFu:Scroll", scroll);
 
     if (!contentControl) {
       contentControl = new ContentControl(this);
     }
     contentControl.start();
 
     if (!eventManager) {
       eventManager = new EventManager(this, contentControl);
     }
     eventManager.inTest = m.json.inTest;
     eventManager.start();
 
     function contentStarted() {
       let accDoc = Utils.AccService.getAccessibleFor(content.document);
       if (accDoc && !Utils.getState(accDoc).contains(States.BUSY)) {
-        sendAsyncMessage('AccessFu:ContentStarted');
+        sendAsyncMessage("AccessFu:ContentStarted");
       } else {
         content.setTimeout(contentStarted, 0);
       }
     }
 
     if (m.json.inTest) {
       // During a test we want to wait for the document to finish loading for
       // consistency.
       contentStarted();
     }
   });
 
 addMessageListener(
-  'AccessFu:Stop',
+  "AccessFu:Stop",
   function(m) {
-    Logger.debug('AccessFu:Stop');
+    Logger.debug("AccessFu:Stop");
 
-    removeMessageListener('AccessFu:ContextMenu', activateContextMenu);
-    removeMessageListener('AccessFu:Scroll', scroll);
+    removeMessageListener("AccessFu:ContextMenu", activateContextMenu);
+    removeMessageListener("AccessFu:Scroll", scroll);
 
     eventManager.stop();
     contentControl.stop();
   });
 
-sendAsyncMessage('AccessFu:Ready');
+sendAsyncMessage("AccessFu:Ready");
--- a/accessible/mac/AccessibleWrap.mm
+++ b/accessible/mac/AccessibleWrap.mm
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "DocAccessible.h"
 #include "nsObjCExceptions.h"
 
 #include "Accessible-inl.h"
 #include "nsAccUtils.h"
 #include "Role.h"
+#include "gfxPlatform.h"
 
 #import "mozAccessible.h"
 #import "mozActionElements.h"
 #import "mozHTMLAccessible.h"
 #import "mozTableAccessible.h"
 #import "mozTextAccessible.h"
 
 using namespace mozilla;
@@ -181,16 +182,22 @@ AccessibleWrap::AncestorIsFlat()
   return false;
 }
 
 void
 a11y::FireNativeEvent(mozAccessible* aNativeAcc, uint32_t aEventType)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
+  // Under headless mode we don't have access to a native window, so we skip
+  // dispatching native events.
+  if (gfxPlatform::IsHeadless()) {
+    return;
+  }
+
   switch (aEventType) {
     case nsIAccessibleEvent::EVENT_FOCUS:
       [aNativeAcc didReceiveFocus];
       break;
     case nsIAccessibleEvent::EVENT_VALUE_CHANGE:
     case nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE:
       [aNativeAcc valueDidChange];
       break;
--- 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
  *