Merge draft head draft
authorGregory Szorc <gps@mozilla.com>
Fri, 04 Aug 2017 14:18:00 -0700
changeset 629581 119e9f3fd97134f6b0407e0389f71f94f5327a85
parent 629580 8b48692f9f9ce0660f8be077184c3deb79604ea7 (diff)
parent 581420 6000261aa1c39498e93aa210cd2e3b3c9442e997 (current diff)
child 629582 6f4c9ec4ca58e356ab0c73734ee1ca977cc49e81
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,80 +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
-          triggered-by: nightly
-          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
-          triggered-by: nightly
           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
-          triggered-by: nightly
-          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
-          triggered-by: nightly
           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,89 @@
 
 # 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/**
-testing/**
 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 is imported as a system add-on and has its own lint rules currently.
+# 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
 !devtools/client/framework/selection.js
@@ -117,36 +119,33 @@ devtools/client/storage/test/*.html
 !devtools/client/storage/test/storage-cookies.html
 !devtools/client/storage/test/storage-overflow.html
 !devtools/client/storage/test/storage-search.html
 !devtools/client/storage/test/storage-unsecured-iframe.html
 !devtools/client/storage/test/storage-unsecured-iframe-usercontextid.html
 devtools/client/webaudioeditor/**
 devtools/client/webconsole/net/**
 devtools/client/webconsole/test/**
-devtools/client/webconsole/console-output.js
 devtools/client/webconsole/hudservice.js
 devtools/client/webconsole/webconsole-connection-proxy.js
 devtools/client/webconsole/webconsole.js
 devtools/client/webide/**
 !devtools/client/webide/components/webideCli.js
 devtools/server/tests/browser/storage-*.html
 !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/*
@@ -162,21 +161,24 @@ devtools/client/sourceeditor/tern/*
 devtools/client/sourceeditor/test/cm_mode_ruby.js
 devtools/client/sourceeditor/test/codemirror/*
 devtools/client/inspector/markup/test/lib_*
 devtools/client/jsonview/lib/require.js
 devtools/server/actors/utils/automation-timeline.js
 
 # Ignore devtools files testing sourcemaps / code style
 devtools/client/debugger/test/mochitest/code_binary_search.js
+devtools/client/debugger/test/mochitest/code_binary_search_absolute.js
 devtools/client/debugger/test/mochitest/code_math.min.js
 devtools/client/debugger/test/mochitest/code_math_bogus_map.js
 devtools/client/debugger/test/mochitest/code_ugly*
 devtools/client/debugger/test/mochitest/code_worker-source-map.js
 devtools/client/framework/test/code_ugly*
+devtools/client/inspector/markup/test/events_bundle.js
+devtools/client/netmonitor/test/xhr_bundle.js
 devtools/server/tests/unit/babel_and_browserify_script_with_source_map.js
 devtools/server/tests/unit/setBreakpoint*
 devtools/server/tests/unit/sourcemapped.js
 
 # dom/ exclusions
 dom/animation/**
 dom/archivereader/**
 dom/asmjscache/**
@@ -207,20 +209,22 @@ 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/**
 dom/power/**
 dom/presentation/**
 dom/promise/**
 dom/push/**
 dom/quota/**
@@ -242,62 +246,88 @@ 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
 
+# 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/**
+# 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/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
 
 # toolkit/ exclusions
 
 # Not part of the default build
@@ -305,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/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,36 +1,19 @@
 "use strict";
 
 module.exports = {
-  // When adding items to this file please check for effects on sub-directories.
+  // New rules and configurations should generally be added in
+  // tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js to
+  // allow external repositories that use the plugin to pick them up as well.
+  "extends": [
+    "plugin:mozilla/recommended"
+  ],
   "plugins": [
     "mozilla"
   ],
-  "rules": {
-    "mozilla/avoid-removeChild": "error",
-    "mozilla/avoid-nsISupportsString-preferences": "error",
-    "mozilla/import-browser-window-globals": "error",
-    "mozilla/import-globals": "warn",
-    "mozilla/no-import-into-var-and-global": "error",
-    "mozilla/no-useless-parameters": "error",
-    "mozilla/no-useless-removeEventListener": "error",
-    "mozilla/use-default-preference-values": "error",
-    "mozilla/use-ownerGlobal": "error",
-    // No (!foo in bar) or (!object instanceof Class)
-    "no-unsafe-negation": "error",
-    // No eval() and no strings in the first param of setTimeout or setInterval
-    "no-implied-eval": "error",
-    "no-eval": "error",
-  },
   // The html plugin is enabled via a command line option on eslint. To avoid
   // bad interactions with the xml preprocessor in eslint-plugin-mozilla, we
   // turn off processing of the html plugin for .xml files.
   "settings": {
     "html/xml-extensions": [ ".xhtml" ]
   },
-  "env": {
-    "es6": true
-  },
-  "parserOptions": {
-    "ecmaVersion": 8,
-  },
 };
--- a/.flake8
+++ b/.flake8
@@ -1,5 +1,4 @@
 [flake8]
 # See http://pep8.readthedocs.io/en/latest/intro.html#configuration
 ignore = E121, E123, E126, E129, E133, E226, E241, E242, E704, W503, E402
 max-line-length = 99
-filename = *.py, +.lint
--- a/.gdbinit_python
+++ b/.gdbinit_python
@@ -1,5 +1,5 @@
 python
 import sys
-sys.path.append('python/gdbpp/')
+sys.path.append('third_party/python/gdbpp/')
 import gdbpp
 end
--- a/.gitignore
+++ b/.gitignore
@@ -57,27 +57,29 @@ 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.
-python/psutil/**/*.so
-python/psutil/**/*.pyd
-python/psutil/build/
+third_party/python/psutil/**/*.so
+third_party/python/psutil/**/*.pyd
+third_party/python/psutil/build/
 
 # Ignore chrome.manifest files from the devtools loader
 devtools/client/chrome.manifest
 devtools/shared/chrome.manifest
 
 # Ignore node_modules directories in devtools
 devtools/**/node_modules
 
@@ -85,16 +87,19 @@ devtools/**/node_modules
 GTAGS
 GRTAGS
 GSYMS
 GPATH
 
 # Git clone directory for updating web-platform-tests
 testing/web-platform/sync/
 
+# Third party metadata for web-platform-tests
+testing/web-platform/products/
+
 # Android Gradle artifacts.
 mobile/android/gradle/.gradle
 
 # XCode project cruft
 embedding/ios/GeckoEmbed/GeckoEmbed.xcodeproj/project.xcworkspace/xcuserdata
 embedding/ios/GeckoEmbed/GeckoEmbed.xcodeproj/xcuserdata
 
 # Ignore mozharness execution files
--- a/.hgignore
+++ b/.hgignore
@@ -59,27 +59,29 @@
 # 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.
-^python/psutil/.*\.so
-^python/psutil/.*\.pyd
-^python/psutil/build/
+^third_party/python/psutil/.*\.so
+^third_party/python/psutil/.*\.pyd
+^third_party/python/psutil/build/
 
 # Git repositories
 .git/
 
 # Ignore chrome.manifest files from the devtools loader
 ^devtools/client/chrome.manifest$
 ^devtools/shared/chrome.manifest$
 
@@ -93,16 +95,19 @@
 GTAGS
 GRTAGS
 GSYMS
 GPATH
 
 # Git clone directory for updating web-platform-tests
 ^testing/web-platform/sync/
 
+# Third party metadata for web-platform-tests
+^testing/web-platform/products/
+
 # Android Gradle artifacts.
 ^mobile/android/gradle/.gradle
 
 # XCode project cruft
 ^embedding/ios/GeckoEmbed/GeckoEmbed.xcodeproj/project.xcworkspace/xcuserdata
 ^embedding/ios/GeckoEmbed/GeckoEmbed.xcodeproj/xcuserdata
 
 # Ignore mozharness execution files
@@ -112,32 +117,34 @@ 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
 ^testing/talos/bin/
 ^testing/talos/include/
 ^testing/talos/lib/
 ^testing/talos/talos/tests/tp5n.zip
 ^testing/talos/talos/tests/tp5n.tar.gz
 ^testing/talos/talos/tests/tp5n
 ^testing/talos/talos/tests/devtools/damp.manifest.develop
 ^talos-venv
+^py3venv
 
 # Ignore files created when running a reftest.
 ^lextab.py$
 
 # tup database
 ^\.tup
 
 # Ignore Visual Studio Code workspace files.
--- a/.hgtags
+++ b/.hgtags
@@ -127,8 +127,10 @@ 67c66c2878aed17ae3096d7db483ddbb2293c503
 68d3781deda0d4d58ec9877862830db89669b3a5 FIREFOX_AURORA_47_BASE
 1c6385ae1fe7e37d8f23f958ce14582f07af729e FIREFOX_AURORA_48_BASE
 d98f20c25feeac4dd7ebbd1c022957df1ef58af4 FIREFOX_AURORA_49_BASE
 465d150bc8be5bbf9f02a8607d4552b6a5e1697c FIREFOX_AURORA_50_BASE
 fc69febcbf6c0dcc4b3dfc7a346d8d348798a65f FIREFOX_AURORA_51_BASE
 1196bf3032e1bce1fb07a01fd9082a767426c5fb FIREFOX_AURORA_52_BASE
 f80dc9fc34680105b714a49b4704bb843f5f7004 FIREFOX_AURORA_53_BASE
 6583496f169cd8a13c531ed16e98e8bf313eda8e FIREFOX_AURORA_54_BASE
+f9605772a0c9098ed1bcaa98089b2c944ed69e9b FIREFOX_BETA_55_BASE
+320642944e42a889db13c6c55b404e32319d4de6 FIREFOX_BETA_56_BASE
--- a/.lldbinit
+++ b/.lldbinit
@@ -1,20 +1,20 @@
 # .lldbinit file for debugging Mozilla
 
 # -----------------------------------------------------------------------------
-# For documentation on all of the commands and type summaries defined here
-# and in the accompanying Python scripts, see python/lldbutils/README.txt.
+# For documentation on all of the commands and type summaries defined here and
+# in the accompanying Python scripts, see third_party/python/lldbutils/README.txt.
 # -----------------------------------------------------------------------------
 
 # Import the module that defines complex Gecko debugging commands.  This assumes
 # you are either running lldb from the top level source directory, the objdir,
 # or the dist/bin directory.  (.lldbinit files in the objdir and dist/bin set
 # topsrcdir appropriately.)
-script topsrcdir = topsrcdir if locals().has_key("topsrcdir") else os.getcwd(); sys.path.append(os.path.join(topsrcdir, "python/lldbutils")); import lldbutils; lldbutils.init()
+script topsrcdir = topsrcdir if locals().has_key("topsrcdir") else os.getcwd(); sys.path.append(os.path.join(topsrcdir, "third_party/python/lldbutils")); import lldbutils; lldbutils.init()
 
 # Mozilla's use of UNIFIED_SOURCES to include multiple source files into a
 # single compiled file breaks lldb breakpoint setting. This works around that.
 # See http://lldb.llvm.org/troubleshooting.html for more info.
 settings set target.inline-breakpoint-strategy always
 
 # Show the dynamic type of an object when using "expr".  This, for example,
 # will show a variable declared as "nsIFrame *" that points to an nsBlockFrame
--- 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/AUTHORS
+++ b/AUTHORS
@@ -285,16 +285,17 @@ David Rajchenbach-Teller <dteller@mozill
 David Savage
 David S. Miller <davem@redhat.com>
 David Woodhouse <dwmw2@infradead.org>
 David Zbarsky <dzbarsky@gmail.com>
 Dean Tessman <dean_tessman@hotmail.com>
 <deneen@alum.bucknell.edu>
 Denis Antrushin <adu@sparc.spb.su>
 Denis Issoupov <denis@macadamian.com>
+Dennis Ek <contact@dennisek.se>
 Dennis Handly
 Derrick Rice <derrick.rice@gmail.com>
 <desale@netscape.com>
 diablohn
 Diane Trout <diane@ghic.org>
 Dietrich Ayala <dietrich@mozilla.com>
 Digital Creations 2, Inc
 Disruptive Innovations
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +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.
 
-Bug 1340627 - clobber for Skia update
+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
 
@@ -259,25 +269,29 @@ prepsymbolsarchive:
 	$(NSINSTALL) -D $(DIST)/$(PKG_PATH)
 
 ifndef MOZ_AUTOMATION
 prepsymbolsarchive: recurse_syms
 endif
 
 .PHONY: symbolsfullarchive
 symbolsfullarchive: prepsymbolsarchive
-	$(RM) '$(DIST)/$(SYMBOL_FULL_ARCHIVE_BASENAME).zip'
-	cd $(DIST)/crashreporter-symbols && \
-          zip -r5D '../$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip' . -x '*test*' -x '*Test*'
+	$(RM) '$(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)/$(SYMBOL_ARCHIVE_BASENAME).zip'
-	cd $(DIST)/crashreporter-symbols && \
-          zip -r5D '../$(PKG_PATH)$(SYMBOL_ARCHIVE_BASENAME).zip' . -i '*.sym'
+	$(RM) '$(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
 
 uploadsymbols:
--- a/accessible/.eslintrc.js
+++ b/accessible/.eslintrc.js
@@ -1,31 +1,17 @@
 "use strict";
 
 module.exports = {
-  "extends": [
-    "plugin:mozilla/recommended"
-  ],
   "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/DocManager.cpp
+++ b/accessible/base/DocManager.cpp
@@ -87,20 +87,20 @@ DocManager::FindAccessibleInCache(nsINod
 
 void
 DocManager::RemoveFromXPCDocumentCache(DocAccessible* aDocument)
 {
   xpcAccessibleDocument* xpcDoc = mXPCDocumentCache.GetWeak(aDocument);
   if (xpcDoc) {
     xpcDoc->Shutdown();
     mXPCDocumentCache.Remove(aDocument);
-  }
 
-  if (!HasXPCDocuments()) {
-    MaybeShutdownAccService(nsAccessibilityService::eXPCOM);
+    if (!HasXPCDocuments()) {
+      MaybeShutdownAccService(nsAccessibilityService::eXPCOM);
+    }
   }
 }
 
 void
 DocManager::NotifyOfDocumentShutdown(DocAccessible* aDocument,
                                      nsIDocument* aDOMDocument)
 {
   // We need to remove listeners in both cases, when document is being shutdown
--- a/accessible/base/FocusManager.cpp
+++ b/accessible/base/FocusManager.cpp
@@ -10,16 +10,17 @@
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
 #include "nsEventShell.h"
 #include "Role.h"
 
 #include "nsFocusManager.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/dom/TabParent.h"
 
 namespace mozilla {
 namespace a11y {
 
 FocusManager::FocusManager()
 {
 }
 
@@ -30,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
@@ -53,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;
 }
 
@@ -185,22 +186,42 @@ 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 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 (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
   // DOM focus.
   Accessible* target = FocusedAccessible();
-  if (target)
+  if (target) {
     DispatchFocusEvent(target->Document(), target);
+  }
 }
 
 void
 FocusManager::ForceFocusEvent()
 {
   nsINode* focusedNode = FocusedDOMNode();
   if (focusedNode) {
     DocAccessible* document =
--- 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,
@@ -90,16 +90,20 @@ MARKUPMAP(h4,
 MARKUPMAP(h5,
           New_HyperText,
           roles::HEADING)
 
 MARKUPMAP(h6,
           New_HyperText,
           roles::HEADING)
 
+MARKUPMAP(input,
+          New_HTMLInput,
+          0)
+
 MARKUPMAP(label,
           New_HTMLLabel,
           roles::LABEL)
 
 MARKUPMAP(legend,
           New_HTMLLegend,
           roles::LABEL)
 
--- a/accessible/base/NotificationController.cpp
+++ b/accessible/base/NotificationController.cpp
@@ -585,18 +585,17 @@ NotificationController::ProcessMutationE
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // NotificationCollector: private
 
 void
 NotificationController::WillRefresh(mozilla::TimeStamp aTime)
 {
-  PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);
-  Telemetry::AutoTimer<Telemetry::A11Y_UPDATE_TIME> updateTimer;
+  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;
 
@@ -652,18 +651,20 @@ NotificationController::WillRefresh(mozi
 
     nsIFrame* textFrame = textNode->GetPrimaryFrame();
     if (!textFrame) {
       NS_ASSERTION(!textAcc,
                    "Text node isn't rendered but accessible is kept alive!");
       continue;
     }
 
+  #ifdef A11Y_LOG
     nsIContent* containerElm = containerNode->IsElement() ?
       containerNode->AsElement() : nullptr;
+  #endif
 
     nsIFrame::RenderedText text = textFrame->GetRenderedText(0,
         UINT32_MAX, nsIFrame::TextOffsetType::OFFSETS_IN_CONTENT_TEXT,
         nsIFrame::TrailingWhitespace::DONT_TRIM_TRAILING_WHITESPACE);
 
     // Remove text accessible if rendered text is empty.
     if (textAcc) {
       if (text.mString.IsEmpty()) {
@@ -725,24 +726,31 @@ NotificationController::WillRefresh(mozi
   for (auto iter = mContentInsertions.ConstIter(); !iter.Done(); iter.Next()) {
     mDocument->ProcessContentInserted(iter.Key(), iter.UserData());
     if (!mDocument) {
       return;
     }
   }
   mContentInsertions.Clear();
 
-  // Bind hanging child documents.
+  // Bind hanging child documents unless we are using IPC and the
+  // document has no IPC actor.  If we fail to bind the child doc then
+  // shut it down.
   uint32_t hangingDocCnt = mHangingChildDocuments.Length();
   nsTArray<RefPtr<DocAccessible>> newChildDocs;
   for (uint32_t idx = 0; idx < hangingDocCnt; idx++) {
     DocAccessible* childDoc = mHangingChildDocuments[idx];
     if (childDoc->IsDefunct())
       continue;
 
+    if (IPCAccessibilityActive() && !mDocument->IPCDoc()) {
+      childDoc->Shutdown();
+      continue;
+    }
+
     nsIContent* ownerContent = mDocument->DocumentNode()->
       FindContentForSubDocument(childDoc->DocumentNode());
     if (ownerContent) {
       Accessible* outerDocAcc = mDocument->GetAccessible(ownerContent);
       if (outerDocAcc && outerDocAcc->AppendChild(childDoc)) {
         if (mDocument->AppendChildDocument(childDoc)) {
           newChildDocs.AppendElement(Move(mHangingChildDocuments[idx]));
           continue;
@@ -750,16 +758,18 @@ NotificationController::WillRefresh(mozi
 
         outerDocAcc->RemoveChild(childDoc);
       }
 
       // Failed to bind the child document, destroy it.
       childDoc->Shutdown();
     }
   }
+
+  // Clear the hanging documents list, even if we didn't bind them.
   mHangingChildDocuments.Clear();
   MOZ_ASSERT(mDocument, "Illicit document shutdown");
   if (!mDocument) {
     return;
   }
 
   // If the document is ready and all its subdocuments are completely loaded
   // then process the document load.
--- 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.
@@ -69,17 +73,25 @@ void ProxyCreated(ProxyAccessible* aProx
 void ProxyDestroyed(ProxyAccessible*);
 
 /**
  * Callied when an event is fired on a proxied accessible.
  */
 void ProxyEvent(ProxyAccessible* aTarget, uint32_t aEventType);
 void ProxyStateChangeEvent(ProxyAccessible* aTarget, uint64_t aState,
                            bool aEnabled);
+
+#if defined(XP_WIN)
+void ProxyFocusEvent(ProxyAccessible* aTarget,
+                     const LayoutDeviceIntRect& aCaretRect);
+void ProxyCaretMoveEvent(ProxyAccessible* aTarget,
+                         const LayoutDeviceIntRect& aCaretRect);
+#else
 void ProxyCaretMoveEvent(ProxyAccessible* aTarget, int32_t aOffset);
+#endif
 void ProxyTextChangeEvent(ProxyAccessible* aTarget, const nsString& aStr,
                           int32_t aStart, uint32_t aLen, bool aIsInsert,
                           bool aFromUser);
 void ProxyShowHideEvent(ProxyAccessible* aTarget, ProxyAccessible* aParent,
                         bool aInsert, bool aFromUser);
 void ProxySelectionEvent(ProxyAccessible* aTarget, ProxyAccessible* aWidget,
                          uint32_t aType);
 } // namespace a11y
--- 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"
@@ -190,16 +191,29 @@ New_HTMLDefinition(nsIContent* aContent,
   if (aContext->IsList())
     return new HyperTextAccessibleWrap(aContent, aContext->Document());
   return nullptr;
 }
 
 static Accessible* New_HTMLLabel(nsIContent* aContent, Accessible* aContext)
   { return new HTMLLabelAccessible(aContent, aContext->Document()); }
 
+static Accessible* New_HTMLInput(nsIContent* aContent, Accessible* aContext)
+{
+  if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+                            nsGkAtoms::checkbox, eIgnoreCase)) {
+    return new HTMLCheckboxAccessible(aContent, aContext->Document());
+  }
+  if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+                            nsGkAtoms::radio, eIgnoreCase)) {
+    return new HTMLRadioButtonAccessible(aContent, aContext->Document());
+  }
+  return nullptr;
+}
+
 static Accessible* New_HTMLOutput(nsIContent* aContent, Accessible* aContext)
   { return new HTMLOutputAccessible(aContent, aContext->Document()); }
 
 static Accessible* New_HTMLProgress(nsIContent* aContent, Accessible* aContext)
   { return new HTMLProgressMeterAccessible(aContent, aContext->Document()); }
 
 static Accessible* New_HTMLSummary(nsIContent* aContent, Accessible* aContext)
   { return new HTMLSummaryAccessible(aContent, aContext->Document()); }
@@ -394,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
 
@@ -426,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
@@ -727,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,33 +313,39 @@ 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();
   if (!frame)
     return states::INVISIBLE;
 
   // Walk the parent frame chain to see if there's invisible parent or the frame
   // is in background tab.
   if (!frame->StyleVisibility()->IsVisible())
     return states::INVISIBLE;
 
+  // Offscreen state if the document's visibility state is not visible.
+  if (Document()->IsHidden())
+    return states::OFFSCREEN;
+
   nsIFrame* curFrame = frame;
   do {
     nsView* view = curFrame->GetView();
     if (view && view->GetVisibility() == nsViewVisibility_kHide)
       return states::INVISIBLE;
 
     if (nsLayoutUtils::IsPopup(curFrame))
       return 0;
@@ -886,16 +892,22 @@ Accessible::HandleAccEvent(AccEvent* aEv
         case nsIAccessibleEvent::EVENT_SELECTION_ADD:
         case nsIAccessibleEvent::EVENT_SELECTION_REMOVE: {
           AccSelChangeEvent* selEvent = downcast_accEvent(aEvent);
           uint64_t widgetID = selEvent->Widget()->IsDoc() ? 0 :
             reinterpret_cast<uintptr_t>(selEvent->Widget());
           ipcDoc->SendSelectionEvent(id, widgetID, aEvent->GetEventType());
           break;
         }
+#if defined(XP_WIN)
+        case nsIAccessibleEvent::EVENT_FOCUS: {
+          ipcDoc->SendFocusEvent(id);
+          break;
+        }
+#endif
         default:
           ipcDoc->SendEvent(id, aEvent->GetEventType());
       }
     }
   }
 
   if (nsCoreUtils::AccEventObserversExist()) {
     nsCoreUtils::DispatchAccEvent(MakeXPCEvent(aEvent));
@@ -930,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"));
     }
@@ -1395,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;
     }
@@ -1415,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) {
@@ -1784,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;
     }
@@ -2793,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!");
@@ -2048,72 +2060,90 @@ DocAccessible::RelocateARIAOwnedIfNeeded
   }
 
   return false;
 }
 
 void
 DocAccessible::DoARIAOwnsRelocation(Accessible* aOwner)
 {
-  nsTArray<RefPtr<Accessible> >* children = mARIAOwnsHash.LookupOrAdd(aOwner);
-
   MOZ_ASSERT(aOwner, "aOwner must be a valid pointer");
   MOZ_ASSERT(aOwner->Elm(), "aOwner->Elm() must be a valid pointer");
 
 #ifdef A11Y_LOG
   logging::TreeInfo("aria owns relocation", logging::eVerbose, aOwner);
 #endif
 
+  nsTArray<RefPtr<Accessible> >* owned = mARIAOwnsHash.LookupOrAdd(aOwner);
+
   IDRefsIterator iter(this, aOwner->Elm(), nsGkAtoms::aria_owns);
-  uint32_t arrayIdx = 0, insertIdx = aOwner->ChildCount() - children->Length();
+  uint32_t idx = 0;
   while (nsIContent* childEl = iter.NextElem()) {
     Accessible* child = GetAccessible(childEl);
+    auto insertIdx = aOwner->ChildCount() - owned->Length() + idx;
 
     // Make an attempt to create an accessible if it wasn't created yet.
     if (!child) {
       if (aOwner->IsAcceptableChild(childEl)) {
         child = GetAccService()->CreateAccessible(childEl, aOwner);
         if (child) {
           TreeMutation imut(aOwner);
           aOwner->InsertChildAt(insertIdx, child);
           imut.AfterInsertion(child);
           imut.Done();
 
           child->SetRelocated(true);
-          children->InsertElementAt(arrayIdx, child);
+          owned->InsertElementAt(idx, child);
+          idx++;
 
           // Create subtree before adjusting the insertion index, since subtree
           // creation may alter children in the container.
           CreateSubtree(child);
           FireEventsOnInsertion(aOwner);
-
-          insertIdx = child->IndexInParent() + 1;
-          arrayIdx++;
         }
       }
       continue;
     }
 
 #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)) {
-      NS_ASSERTION(child == children->ElementAt(arrayIdx), "Not in sync!");
-      insertIdx++; arrayIdx++;
-      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;
+      }
     }
 
-    NS_ASSERTION(children->SafeElementAt(arrayIdx) != child, "Already in place!");
+    MOZ_ASSERT(owned->SafeElementAt(idx) != child, "Already in place!");
 
-    nsTArray<RefPtr<Accessible> >::index_type idx = children->IndexOf(child);
-    if (idx < arrayIdx) {
+    if (owned->IndexOf(child) < idx) {
       continue; // ignore second entry of same ID
     }
 
     // A new child is found, check for loops.
     if (child->Parent() != aOwner) {
       Accessible* parent = aOwner;
       while (parent && parent != child && !parent->IsDoc()) {
         parent = parent->Parent();
@@ -2121,34 +2151,34 @@ DocAccessible::DoARIAOwnsRelocation(Acce
       // A referred child cannot be a parent of the owner.
       if (parent == child) {
         continue;
       }
     }
 
     if (MoveChild(child, aOwner, insertIdx)) {
       child->SetRelocated(true);
-      children->InsertElementAt(arrayIdx, child);
-      arrayIdx++;
-      insertIdx = child->IndexInParent() + 1;
+      owned->InsertElementAt(idx, child);
+      idx++;
     }
   }
 
   // Put back children that are not seized anymore.
-  PutChildrenBack(children, arrayIdx);
-  if (children->Length() == 0) {
+  PutChildrenBack(owned, idx);
+  if (owned->Length() == 0) {
     mARIAOwnsHash.Remove(aOwner);
   }
 }
 
 void
 DocAccessible::PutChildrenBack(nsTArray<RefPtr<Accessible> >* aChildren,
                                uint32_t aStartIdx)
 {
-  nsTArray<RefPtr<Accessible> > containers;
+  MOZ_ASSERT(aStartIdx <= aChildren->Length(), "Wrong removal index");
+
   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();
@@ -2160,55 +2190,76 @@ 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)
 {
   MOZ_ASSERT(aChild, "No child");
   MOZ_ASSERT(aChild->Parent(), "No parent");
+  MOZ_ASSERT(aIdxInParent <= static_cast<int32_t>(aNewParent->ChildCount()),
+             "Wrong insertion point for a moving child");
 
   Accessible* curParent = aChild->Parent();
 
 #ifdef A11Y_LOG
   logging::TreeInfo("move child", 0,
                     "old parent", curParent, "new parent", aNewParent,
                     "child", aChild, nullptr);
 #endif
 
-  // If the child was taken from from an ARIA owns element.
+  // Forget aria-owns info in case of ARIA owned element. The caller is expected
+  // to update it if needed.
   if (aChild->IsRelocated()) {
+    aChild->SetRelocated(false);
     nsTArray<RefPtr<Accessible> >* owned = mARIAOwnsHash.Get(curParent);
     MOZ_ASSERT(owned, "IsRelocated flag is out of sync with mARIAOwnsHash");
     owned->RemoveElement(aChild);
     if (owned->Length() == 0) {
       mARIAOwnsHash.Remove(curParent);
     }
   }
 
@@ -2315,16 +2366,17 @@ DocAccessible::UncacheChildrenInSubtree(
   for (uint32_t idx = 0; idx < count; idx++) {
     Accessible* child = aRoot->ContentChildAt(idx);
 
     if (child->IsRelocated()) {
       MOZ_ASSERT(owned, "IsRelocated flag is out of sync with mARIAOwnsHash");
       owned->RemoveElement(child);
       if (owned->Length() == 0) {
         mARIAOwnsHash.Remove(aRoot);
+        owned = nullptr;
       }
     }
 
     // Removing this accessible from the document doesn't mean anything about
     // accessibles for subdocuments, so skip removing those from the tree.
     if (!child->IsDoc()) {
       UncacheChildrenInSubtree(child);
     }
--- a/accessible/generic/DocAccessible.h
+++ b/accessible/generic/DocAccessible.h
@@ -132,16 +132,21 @@ public:
   {
     // eDOMLoaded flag check is used for error pages as workaround to make this
     // method return correct result since error pages do not receive 'pageshow'
     // event and as consequence nsIDocument::IsShowing() returns false.
     return mDocumentNode && mDocumentNode->IsVisible() &&
       (mDocumentNode->IsShowing() || HasLoadState(eDOMLoaded));
   }
 
+  bool IsHidden() const
+  {
+    return mDocumentNode->Hidden();
+  }
+
   /**
    * Document load states.
    */
   enum LoadState {
     // initial tree construction is pending
     eTreeConstructionPending = 0,
     // initial tree construction done
     eTreeConstructed = 1,
@@ -152,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();
   }
 
@@ -266,29 +264,37 @@ DocAccessibleParent::RecvStateChangeEven
     new xpcAccStateChangeEvent(type, xpcAcc, doc, node, fromUser, state, extra,
                                aEnabled);
   nsCoreUtils::DispatchAccEvent(Move(event));
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
-DocAccessibleParent::RecvCaretMoveEvent(const uint64_t& aID, const int32_t& aOffset)
+DocAccessibleParent::RecvCaretMoveEvent(const uint64_t& aID,
+#if defined(XP_WIN)
+                                        const LayoutDeviceIntRect& aCaretRect,
+#endif // defined (XP_WIN)
+                                        const int32_t& aOffset)
 {
   if (mShutdown) {
     return IPC_OK();
   }
 
   ProxyAccessible* proxy = GetAccessible(aID);
   if (!proxy) {
     NS_ERROR("unknown caret move event target!");
     return IPC_OK();
   }
 
+#if defined(XP_WIN)
+  ProxyCaretMoveEvent(proxy, aCaretRect);
+#else
   ProxyCaretMoveEvent(proxy, aOffset);
+#endif
 
   if (!nsCoreUtils::AccEventObserversExist()) {
     return IPC_OK();
   }
 
   xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(proxy);
   xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
   nsIDOMNode* node = nullptr;
@@ -384,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)
@@ -613,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()
 {
@@ -659,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);
   }
@@ -703,12 +719,43 @@ DocAccessibleParent::RecvGetWindowedPlug
   aPluginCOMProxy->Set(IAccessibleHolder::COMPtrType(rawAccPlugin));
 
   return IPC_OK();
 #else
   return IPC_FAIL(this, "Message unsupported in this build configuration");
 #endif
 }
 
+mozilla::ipc::IPCResult
+DocAccessibleParent::RecvFocusEvent(const uint64_t& aID,
+                                    const LayoutDeviceIntRect& aCaretRect)
+{
+  if (mShutdown) {
+    return IPC_OK();
+  }
+
+  ProxyAccessible* proxy = GetAccessible(aID);
+  if (!proxy) {
+    NS_ERROR("no proxy for event!");
+    return IPC_OK();
+  }
+
+  ProxyFocusEvent(proxy, aCaretRect);
+
+  if (!nsCoreUtils::AccEventObserversExist()) {
+    return IPC_OK();
+  }
+
+  xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(proxy);
+  xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
+  nsIDOMNode* node = nullptr;
+  bool fromUser = true; // XXX fix me
+  RefPtr<xpcAccEvent> event = new xpcAccEvent(nsIAccessibleEvent::EVENT_FOCUS,
+                                              xpcAcc, doc, node, fromUser);
+  nsCoreUtils::DispatchAccEvent(Move(event));
+
+  return IPC_OK();
+}
+
 #endif // defined(XP_WIN)
 
 } // a11y
 } // mozilla
--- a/accessible/ipc/DocAccessibleParent.h
+++ b/accessible/ipc/DocAccessibleParent.h
@@ -75,29 +75,35 @@ public:
   virtual mozilla::ipc::IPCResult RecvShowEvent(const ShowEventData& aData, const bool& aFromUser)
     override;
   virtual mozilla::ipc::IPCResult RecvHideEvent(const uint64_t& aRootID, const bool& aFromUser)
     override;
   virtual mozilla::ipc::IPCResult RecvStateChangeEvent(const uint64_t& aID,
                                                        const uint64_t& aState,
                                                        const bool& aEnabled) override final;
 
-  virtual mozilla::ipc::IPCResult RecvCaretMoveEvent(const uint64_t& aID, const int32_t& aOffset)
-    override final;
+  virtual mozilla::ipc::IPCResult RecvCaretMoveEvent(const uint64_t& aID,
+#if defined(XP_WIN)
+                                                     const LayoutDeviceIntRect& aCaretRect,
+#endif
+                                                     const int32_t& aOffset) override final;
 
   virtual mozilla::ipc::IPCResult RecvTextChangeEvent(const uint64_t& aID, const nsString& aStr,
                                                       const int32_t& aStart, const uint32_t& aLen,
                                                       const bool& aIsInsert,
                                                       const bool& aFromUser) override;
 
 #if defined(XP_WIN)
   virtual mozilla::ipc::IPCResult RecvSyncTextChangeEvent(const uint64_t& aID, const nsString& aStr,
                                                           const int32_t& aStart, const uint32_t& aLen,
                                                           const bool& aIsInsert,
                                                           const bool& aFromUser) override;
+
+  virtual mozilla::ipc::IPCResult RecvFocusEvent(const uint64_t& aID,
+                                                 const LayoutDeviceIntRect& aCaretRect) override;
 #endif // defined(XP_WIN)
 
   virtual mozilla::ipc::IPCResult RecvSelectionEvent(const uint64_t& aID,
                                                      const uint64_t& aWidgetID,
                                                      const uint32_t& aType) override;
 
   virtual mozilla::ipc::IPCResult RecvRoleChangedEvent(const uint32_t& aRole) override final;
 
@@ -144,17 +150,16 @@ public:
     ProxyAccessible* parent = aChildDoc->Parent();
     MOZ_ASSERT(parent);
     if (parent) {
       aChildDoc->Parent()->ClearChildDoc(aChildDoc);
     }
     DebugOnly<bool> result = mChildDocs.RemoveElement(aChildDoc->mActorID);
     aChildDoc->mParentDoc = kNoParentDoc;
     MOZ_ASSERT(result);
-    MOZ_ASSERT(aChildDoc->mChildDocs.Length() == 0);
   }
 
   void RemoveAccessible(ProxyAccessible* aAccessible)
   {
     MOZ_DIAGNOSTIC_ASSERT(mAccessibles.GetEntry(aAccessible->ID()));
     mAccessibles.RemoveEntry(aAccessible->ID());
   }
 
@@ -226,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/DocAccessibleChild.cpp
+++ b/accessible/ipc/other/DocAccessibleChild.cpp
@@ -1,16 +1,17 @@
 /* -*- 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 "DocAccessibleChild.h"
 
+#include "nsAccessibilityService.h"
 #include "Accessible-inl.h"
 #include "ProxyAccessible.h"
 #include "Relation.h"
 #include "HyperTextAccessible-inl.h"
 #include "TextLeafAccessible.h"
 #include "ImageAccessible.h"
 #include "TableAccessible.h"
 #include "TableCellAccessible.h"
@@ -1998,10 +1999,17 @@ DocAccessibleChild::RecvDOMNodeID(const 
   nsIAtom* id = content->GetID();
   if (id) {
     id->ToString(*aDOMNodeID);
   }
 
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult
+DocAccessibleChild::RecvRestoreFocus()
+{
+  FocusMgr()->ForceFocusEvent();
+  return IPC_OK();
+}
+
 }
 }
--- a/accessible/ipc/other/DocAccessibleChild.h
+++ b/accessible/ipc/other/DocAccessibleChild.h
@@ -33,16 +33,18 @@ public:
     SetManager(aManager);
   }
 
   ~DocAccessibleChild()
   {
     MOZ_COUNT_DTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase);
   }
 
+  virtual mozilla::ipc::IPCResult RecvRestoreFocus() override;
+
   /*
    * Return the state for the accessible with given ID.
    */
   virtual mozilla::ipc::IPCResult RecvState(const uint64_t& aID, uint64_t* aState) override;
 
   /*
    * Return the native state for the accessible with given ID.
    */
--- a/accessible/ipc/other/PDocAccessible.ipdl
+++ b/accessible/ipc/other/PDocAccessible.ipdl
@@ -68,16 +68,22 @@ parent:
    * Tell the parent document to bind the existing document as a new child
    * document.
    */
   async BindChildDoc(PDocAccessible aChildDoc, uint64_t aID);
 
 child:
   async __delete__();
 
+  /*
+   * Called as a result of focus shifting from chrome to content
+   * elements through keyboard navigation.
+   */
+  async RestoreFocus();
+
   // Accessible
   nested(inside_sync) sync State(uint64_t aID) returns(uint64_t states);
   nested(inside_sync) sync NativeState(uint64_t aID) returns(uint64_t states);
   nested(inside_sync) sync Name(uint64_t aID) returns(nsString name);
   nested(inside_sync) sync Value(uint64_t aID) returns(nsString value);
   nested(inside_sync) sync Help(uint64_t aID) returns(nsString help);
   nested(inside_sync) sync Description(uint64_t aID) returns(nsString desc);
   nested(inside_sync) sync Attributes(uint64_t aID) returns(Attribute[] attributes);
--- 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/DocAccessibleChild.cpp
+++ b/accessible/ipc/win/DocAccessibleChild.cpp
@@ -1,16 +1,17 @@
 /* -*- 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 "DocAccessibleChild.h"
 
+#include "nsAccessibilityService.h"
 #include "Accessible-inl.h"
 #include "mozilla/a11y/PlatformChild.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "RootAccessible.h"
 
 namespace mozilla {
 namespace a11y {
 
@@ -154,25 +155,74 @@ DocAccessibleChild::SendStateChangeEvent
     return PDocAccessibleChild::SendStateChangeEvent(aID, aState, aEnabled);
   }
 
   PushDeferredEvent(MakeUnique<SerializedStateChange>(this, aID, aState,
                                                       aEnabled));
   return true;
 }
 
+LayoutDeviceIntRect
+DocAccessibleChild::GetCaretRectFor(const uint64_t& aID)
+{
+  Accessible* target;
+
+  if (aID) {
+    target = reinterpret_cast<Accessible*>(aID);
+  } else {
+    target = mDoc;
+  }
+
+  MOZ_ASSERT(target);
+
+  HyperTextAccessible* text = target->AsHyperText();
+  if (!text) {
+    return LayoutDeviceIntRect();
+  }
+
+  nsIWidget* widget = nullptr;
+  return text->GetCaretRect(&widget);
+}
+
+bool
+DocAccessibleChild::SendFocusEvent(const uint64_t& aID)
+{
+  return SendFocusEvent(aID, GetCaretRectFor(aID));
+}
+
+bool
+DocAccessibleChild::SendFocusEvent(const uint64_t& aID,
+                                   const LayoutDeviceIntRect& aCaretRect)
+{
+  if (IsConstructedInParentProcess()) {
+    return PDocAccessibleChild::SendFocusEvent(aID, aCaretRect);
+  }
+
+  PushDeferredEvent(MakeUnique<SerializedFocus>(this, aID, aCaretRect));
+  return true;
+}
+
 bool
 DocAccessibleChild::SendCaretMoveEvent(const uint64_t& aID,
                                        const int32_t& aOffset)
 {
+  return SendCaretMoveEvent(aID, GetCaretRectFor(aID), aOffset);
+}
+
+bool
+DocAccessibleChild::SendCaretMoveEvent(const uint64_t& aID,
+                                       const LayoutDeviceIntRect& aCaretRect,
+                                       const int32_t& aOffset)
+{
   if (IsConstructedInParentProcess()) {
-    return PDocAccessibleChild::SendCaretMoveEvent(aID, aOffset);
+    return PDocAccessibleChild::SendCaretMoveEvent(aID, aCaretRect, aOffset);
   }
 
-  PushDeferredEvent(MakeUnique<SerializedCaretMove>(this, aID, aOffset));
+  PushDeferredEvent(MakeUnique<SerializedCaretMove>(this, aID, aCaretRect,
+                                                    aOffset));
   return true;
 }
 
 bool
 DocAccessibleChild::SendTextChangeEvent(const uint64_t& aID,
                                         const nsString& aStr,
                                         const int32_t& aStart,
                                         const uint32_t& aLen,
@@ -253,11 +303,18 @@ DocAccessibleChild::SendBindChildDoc(Doc
     return DocAccessibleChildBase::SendBindChildDoc(aChildDoc, aNewParentID);
   }
 
   PushDeferredEvent(MakeUnique<SerializedBindChildDoc>(this, aChildDoc,
                                                        aNewParentID));
   return true;
 }
 
+ipc::IPCResult
+DocAccessibleChild::RecvRestoreFocus()
+{
+  FocusMgr()->ForceFocusEvent();
+  return IPC_OK();
+}
+
 } // namespace a11y
 } // namespace mozilla
 
--- a/accessible/ipc/win/DocAccessibleChild.h
+++ b/accessible/ipc/win/DocAccessibleChild.h
@@ -23,31 +23,39 @@ class DocAccessibleChild : public DocAcc
 {
 public:
   DocAccessibleChild(DocAccessible* aDoc, IProtocol* aManager);
   ~DocAccessibleChild();
 
   virtual void Shutdown() override;
 
   virtual ipc::IPCResult
-  RecvParentCOMProxy(const IAccessibleHolder& aParentCOMProxy) override;
+    RecvParentCOMProxy(const IAccessibleHolder& aParentCOMProxy) override;
   virtual ipc::IPCResult
     RecvEmulatedWindow(const WindowsHandle& aEmulatedWindowHandle,
                        const IAccessibleHolder& aEmulatedWindowCOMProxy) override;
+  virtual ipc::IPCResult
+    RecvRestoreFocus() override;
 
   HWND GetNativeWindowHandle() const;
   IAccessible* GetEmulatedWindowIAccessible() const { return mEmulatedWindowProxy.get(); }
 
   IAccessible* GetParentIAccessible() const { return mParentProxy.get(); }
 
   bool SendEvent(const uint64_t& aID, const uint32_t& type);
   bool SendHideEvent(const uint64_t& aRootID, const bool& aFromUser);
   bool SendStateChangeEvent(const uint64_t& aID, const uint64_t& aState,
                             const bool& aEnabled);
   bool SendCaretMoveEvent(const uint64_t& aID, const int32_t& aOffset);
+  bool SendCaretMoveEvent(const uint64_t& aID,
+                          const LayoutDeviceIntRect& aCaretRect,
+                          const int32_t& aOffset);
+  bool SendFocusEvent(const uint64_t& aID);
+  bool SendFocusEvent(const uint64_t& aID,
+                      const LayoutDeviceIntRect& aCaretRect);
   bool SendTextChangeEvent(const uint64_t& aID, const nsString& aStr,
                            const int32_t& aStart, const uint32_t& aLen,
                            const bool& aIsInsert, const bool& aFromUser);
   bool SendSelectionEvent(const uint64_t& aID, const uint64_t& aWidgetID,
                           const uint32_t& aType);
   bool SendRoleChangedEvent(const uint32_t& aRole);
 
   bool ConstructChildDocInParentProcess(DocAccessibleChild* aNewChildDoc,
@@ -60,16 +68,18 @@ protected:
   virtual void MaybeSendShowEvent(ShowEventData& aData, bool aFromUser) override;
 
 private:
   void RemoveDeferredConstructor();
 
   bool IsConstructedInParentProcess() const { return mIsRemoteConstructed; }
   void SetConstructedInParentProcess() { mIsRemoteConstructed = true; }
 
+  LayoutDeviceIntRect GetCaretRectFor(const uint64_t& aID);
+
   /**
    * DocAccessibleChild should not fire events until it has asynchronously
    * received the COM proxy for its parent. OTOH, content a11y may still be
    * attempting to fire events during this window of time. If this object does
    * not yet have its parent proxy, instead of immediately sending the events to
    * our parent, we enqueue them to mDeferredEvents. As soon as
    * RecvParentCOMProxy is called, we play back mDeferredEvents.
    */
@@ -154,29 +164,49 @@ private:
     uint64_t  mID;
     uint64_t  mState;
     bool      mEnabled;
   };
 
   struct SerializedCaretMove final : public DeferredEvent
   {
     SerializedCaretMove(DocAccessibleChild* aTarget, uint64_t aID,
-                        int32_t aOffset)
+                        const LayoutDeviceIntRect& aCaretRect, int32_t aOffset)
       : DeferredEvent(aTarget)
       , mID(aID)
+      , mCaretRect(aCaretRect)
       , mOffset(aOffset)
     {}
 
     void Dispatch(DocAccessibleChild* aIPCDoc) override
     {
-      Unused << aIPCDoc->SendCaretMoveEvent(mID, mOffset);
+      Unused << aIPCDoc->SendCaretMoveEvent(mID, mCaretRect, mOffset);
     }
 
-    uint64_t  mID;
-    int32_t   mOffset;
+    uint64_t            mID;
+    LayoutDeviceIntRect mCaretRect;
+    int32_t             mOffset;
+  };
+
+  struct SerializedFocus final : public DeferredEvent
+  {
+    SerializedFocus(DocAccessibleChild* aTarget, uint64_t aID,
+                    const LayoutDeviceIntRect& aCaretRect)
+      : DeferredEvent(aTarget)
+      , mID(aID)
+      , mCaretRect(aCaretRect)
+    {}
+
+    void Dispatch(DocAccessibleChild* aIPCDoc) override
+    {
+      Unused << aIPCDoc->SendFocusEvent(mID, mCaretRect);
+    }
+
+    uint64_t            mID;
+    LayoutDeviceIntRect mCaretRect;
   };
 
   struct SerializedTextChange final : public DeferredEvent
   {
     SerializedTextChange(DocAccessibleChild* aTarget, uint64_t aID,
                          const nsString& aStr, int32_t aStart, uint32_t aLen,
                          bool aIsInsert, bool aFromUser)
       : DeferredEvent(aTarget)
--- 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/PDocAccessible.ipdl
+++ b/accessible/ipc/win/PDocAccessible.ipdl
@@ -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 protocol PFileDescriptorSet;
 include protocol PBrowser;
 
 using mozilla::a11y::IAccessibleHolder from "mozilla/a11y/IPCTypes.h";
 using mozilla::WindowsHandle from "ipc/IPCMessageUtils.h";
+using mozilla::LayoutDeviceIntRect from "Units.h";
 
 namespace mozilla {
 namespace a11y {
 
 struct AccessibleData
 {
   uint64_t ID;
   int32_t MsaaID;
@@ -45,35 +46,42 @@ parent:
   /*
    * Notify the parent process the document in the child process is firing an
    * event.
    */
   async Event(uint64_t aID, uint32_t type);
   async ShowEvent(ShowEventData data, bool aFromUser);
   async HideEvent(uint64_t aRootID, bool aFromUser);
   async StateChangeEvent(uint64_t aID, uint64_t aState, bool aEnabled);
-  async CaretMoveEvent(uint64_t aID, int32_t aOffset);
+  async CaretMoveEvent(uint64_t aID, LayoutDeviceIntRect aCaretRect,
+                       int32_t aOffset);
   async TextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart, uint32_t aLen,
                         bool aIsInsert, bool aFromUser);
   sync SyncTextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart,
                            uint32_t aLen, bool aIsInsert, bool aFromUser);
   async SelectionEvent(uint64_t aID, uint64_t aWidgetID, uint32_t aType);
   async RoleChangedEvent(uint32_t aRole);
+  async FocusEvent(uint64_t aID, LayoutDeviceIntRect aCaretRect);
 
   /*
    * Tell the parent document to bind the existing document as a new child
    * document.
    */
   async BindChildDoc(PDocAccessible aChildDoc, uint64_t aID);
 
   sync GetWindowedPluginIAccessible(WindowsHandle aHwnd)
     returns (IAccessibleHolder aPluginCOMProxy);
 
 child:
   async ParentCOMProxy(IAccessibleHolder aParentCOMProxy);
   async EmulatedWindow(WindowsHandle aEmulatedWindowHandle,
                        IAccessibleHolder aEmulatedWindowCOMProxy);
+  /*
+   * Called as a result of focus shifting from chrome to content
+   * elements through keyboard navigation.
+   */
+  async RestoreFocus();
 
   async __delete__();
 };
 
 }
 }
--- 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/handler/moz.build
+++ b/accessible/ipc/win/handler/moz.build
@@ -44,16 +44,17 @@ OS_LIBS += [
 
 RCINCLUDE = 'AccessibleHandler.rc'
 
 # Since we are defining our own COM entry points (DllRegisterServer et al),
 # but we still want to be able to delegate some work to the generated code,
 # we add the prefix "Proxy" to all of the generated counterparts.
 DEFINES['ENTRY_PREFIX'] = 'Proxy'
 DEFINES['REGISTER_PROXY_DLL'] = True
+LIBRARY_DEFINES['MOZ_MSCOM_REMARSHAL_NO_HANDLER'] = True
 
 # We want to generate distinct UUIDs on a per-channel basis, so we need
 # finer granularity than the standard preprocessor definitions offer.
 # These defines allow us to separate local builds from automated builds,
 # as well as separate beta from release.
 if CONFIG['MOZ_UPDATE_CHANNEL'] == 'default':
   DEFINES['USE_LOCAL_UUID'] = True
 elif CONFIG['MOZ_UPDATE_CHANNEL'] == 'beta':
--- 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.