Bug 1249802 - Merge closed branch head into default
authorGregory Szorc <gps@mozilla.com>
Fri, 03 Jun 2016 14:28:20 -0700
changeset 379144 cad203729857344a36e9eb9c53af361ca474ee88
parent 379143 6b6397c6aa7918e3617d92f3062eace485829889 (diff)
parent 378961 b03691ff38b9d6bc63c1b5eb0c190e74f9546a8c (current diff)
child 379145 bad49d86f78f6b5aebfdfdeac2e02a12c8203bb3
push id21011
push usermak77@bonardo.net
push dateThu, 16 Jun 2016 13:40:45 +0000
bugs1249802
milestone47.0
Bug 1249802 - Merge closed branch head into default
--- a/.clang-format
+++ b/.clang-format
@@ -1,1 +1,4 @@
 BasedOnStyle: Mozilla
+
+# Ignore all comments because they aren't reflowed properly.
+CommentPragmas: "^"
new file mode 100644
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,189 @@
+# Always ignore node_modules.
+**/node_modules/**/*.*
+
+# 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.
+accessible/**
+addon-sdk/**
+build/**
+caps/**
+chrome/**
+config/**
+db/**
+docshell/**
+dom/**
+editor/**
+embedding/**
+extensions/**
+gfx/**
+gradle/**
+hal/**
+image/**
+intl/**
+ipc/**
+js/**
+layout/**
+media/**
+memory/**
+mfbt/**
+modules/**
+mozglue/**
+netwerk/**
+nsprpub/**
+other-licenses/**
+parser/**
+probes/**
+python/**
+rdf/**
+startupcache/**
+testing/**
+tools/**
+uriloader/**
+view/**
+webapprt/**
+widget/**
+xpcom/**
+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/base/content/browser-social.js
+browser/base/content/nsContextMenu.js
+browser/base/content/sanitizeDialog.js
+browser/base/content/test/**
+browser/base/content/newtab/**
+browser/components/downloads/**
+browser/components/feeds/**
+browser/components/preferences/**
+browser/components/privatebrowsing/**
+browser/components/sessionstore/**
+browser/components/shell/**
+browser/components/tabview/**
+browser/components/translation/**
+browser/extensions/pdfjs/**
+browser/extensions/pocket/content/panels/js/vendor/**
+browser/locales/**
+
+# Ignore all of loop since it is imported from github and checked at source.
+browser/extensions/loop/**
+
+# devtools/ exclusions
+devtools/*.js
+devtools/client/canvasdebugger/**
+devtools/client/commandline/**
+devtools/client/debugger/**
+devtools/client/eyedropper/**
+devtools/client/framework/**
+# devtools/client/inspector/shared/*.js files are eslint-clean, so they aren't
+# included in the ignore list.
+devtools/client/inspector/computed/**
+devtools/client/inspector/fonts/**
+devtools/client/inspector/shared/test/**
+devtools/client/inspector/test/**
+devtools/client/inspector/*.js
+devtools/client/jsonview/**
+devtools/client/memory/**
+devtools/client/netmonitor/**
+devtools/client/performance/**
+devtools/client/projecteditor/**
+devtools/client/promisedebugger/**
+devtools/client/responsivedesign/**
+devtools/client/scratchpad/**
+devtools/client/shadereditor/**
+devtools/client/shared/**
+devtools/client/sourceeditor/**
+devtools/client/webaudioeditor/**
+devtools/client/webconsole/**
+devtools/client/webide/**
+devtools/server/**
+devtools/shared/**
+
+# Ignore devtools pre-processed files
+devtools/client/framework/toolbox-process-window.js
+devtools/client/performance/system.js
+devtools/client/webide/webide-prefs.js
+devtools/client/preferences/**
+
+# Ignore devtools third-party libs
+devtools/shared/jsbeautify/*
+devtools/shared/acorn/*
+devtools/client/sourceeditor/tern/*
+devtools/shared/pretty-fast/*
+devtools/shared/sourcemap/*
+devtools/shared/qrcode/decoder/*
+devtools/shared/qrcode/encoder/*
+devtools/client/shared/vendor/*
+devtools/client/shared/d3.js
+devtools/client/webaudioeditor/lib/dagre-d3.js
+devtools/client/sourceeditor/codemirror/*.js
+devtools/client/sourceeditor/codemirror/**/*.js
+devtools/client/sourceeditor/test/codemirror/*
+devtools/client/inspector/markup/test/lib_*
+
+# mobile/android/ exclusions
+mobile/android/chrome/content
+mobile/android/tests/
+
+# 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/
+
+# Pretty sure we're disabling this one anyway
+mobile/android/modules/ContactService.jsm
+
+# Non-standard `(catch ex if ...)`
+mobile/android/components/Snippets.js
+
+# Bug 1178739: Ignore this file as a quick fix for "Illegal yield expression"
+mobile/android/modules/HomeProvider.jsm
+
+# services/ exclusions
+
+# Uses `#filter substitution`
+services/sync/modules/constants.js
+
+# toolkit/ exclusions
+
+# Not part of the default build
+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/**
+
+# Uses preprocessing
+toolkit/content/widgets/videocontrols.xml
+toolkit/content/widgets/wizard.xml
+toolkit/components/jsdownloads/src/DownloadIntegration.jsm
+toolkit/components/search/nsSearchService.js
+toolkit/components/url-classifier/**
+toolkit/components/urlformatter/nsURLFormatter.js
+toolkit/identity/FirefoxAccounts.jsm
+toolkit/modules/AppConstants.jsm
+toolkit/mozapps/downloads/nsHelperAppDlg.js
+toolkit/mozapps/extensions/internal/AddonConstants.jsm
+toolkit/mozapps/update/tests/data/xpcshellConstantsPP.js
+toolkit/webapps/**
new file mode 100644
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,12 @@
+{
+  // When adding items to this file please check for effects on sub-directories.
+  "plugins": [
+    "mozilla"
+  ],
+  "rules": {
+    "mozilla/import-globals": 1,
+  },
+  "env": {
+    "es6": true
+  },
+}
--- a/.gitignore
+++ b/.gitignore
@@ -3,67 +3,115 @@
 # Filenames that should be ignored wherever they appear
 *~
 *.pyc
 *.pyo
 TAGS
 tags
 ID
 .DS_Store*
+*.pdb
+*.egg-info
+
+# Allow the id locale directory for loop ('ID' matches this normally)
+!browser/extensions/loop/chrome/locale/id
 
 # Vim swap files.
 .*.sw[a-z]
 
 # Emacs directory variable files.
 **/.dir-locals.el
 
 # User files that may appear at the root
 /.mozconfig*
 /mozconfig
 /configure
+/old-configure
 /config.cache
 /config.log
 /.clang_complete
 /mach.ini
 
 # Empty marker file that's generated when we check out NSS
 security/manager/.nss.checkout
 
 # Build directories
 /obj*/
 
 # Build directories for js shell
-*/_DBG.OBJ/
-*/_OPT.OBJ/
+_DBG.OBJ/
+_OPT.OBJ/
 
 # SpiderMonkey configury
 js/src/configure
+js/src/old-configure
 js/src/autom4te.cache
 # SpiderMonkey test result logs
 js/src/tests/results-*.html
 js/src/tests/results-*.txt
 
 # Java HTML5 parser classes
 parser/html/java/htmlparser/
 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
+
+# Gradle cache.
+/.gradle/
+
+# Local Gradle configuration properties.
+/local.properties
+
 # Python virtualenv artifacts.
-python/psutil/*.so
-python/psutil/*.pyd
+python/psutil/**/*.so
+python/psutil/**/*.pyd
 python/psutil/build/
 
 # Ignore chrome.manifest files from the devtools loader
-browser/devtools/chrome.manifest
-toolkit/devtools/chrome.manifest
+devtools/client/chrome.manifest
+devtools/shared/chrome.manifest
 
 # Tag files generated by GNU Global
 GTAGS
 GRTAGS
 GSYMS
 GPATH
 
 # Git clone directory for updating web-platform-tests
 testing/web-platform/sync/
+
+# 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
+testing/mozharness/.tox/
+testing/mozharness/build/
+testing/mozharness/logs/
+testing/mozharness/.coverage
+testing/mozharness/nosetests.xml
+
+# Ignore node_modules from eslint-plugin-mozilla
+testing/eslint-plugin-mozilla/node_modules/
+
+# Ignore talos virtualenv and tp5n files.
+# The tp5n set is supposed to be decompressed at
+# testing/talos/talos/page_load_test/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
+testing/talos/talos/tests/devtools/damp.manifest.develop
--- a/.hgignore
+++ b/.hgignore
@@ -1,28 +1,31 @@
 # .hgignore - List of filenames hg should ignore
 
 # Filenames that should be ignored wherever they appear
 ~$
 \.py(c|o)$
 (?i)(^|/)TAGS$
 (^|/)ID$
 (^|/)\.DS_Store$
+\.pdb
+\.egg-info
 
 # Vim swap files.
 ^\.sw.$
 .[^/]*\.sw.$
 
 # Emacs directory variable files.
 \.dir-locals\.el
 
 # User files that may appear at the root
 ^\.mozconfig
 ^mozconfig*
 ^configure$
+^old-configure$
 ^config\.cache$
 ^config\.log$
 ^\.clang_complete
 ^mach.ini$
 
 # Empty marker file that's generated when we check out NSS
 ^security/manager/\.nss\.checkout$
 
@@ -31,65 +34,101 @@
 
 # Build directories for js shell
 _DBG\.OBJ/
 _OPT\.OBJ/
 ^js/src/.*-obj/
 
 # SpiderMonkey configury
 ^js/src/configure$
+^js/src/old-configure$
 ^js/src/autom4te.cache$
 # SpiderMonkey test result logs
 ^js/src/tests/results-.*\.(html|txt)$
 
 # Java HTML5 parser classes
 ^parser/html/java/(html|java)parser/
 
 # SVN directories
 \.svn/
 
 # Ignore the files and directory that Eclipse IDE creates
 \.project$
 \.cproject$
 \.settings/
 
-# Ignore the directory that JetBrains IDEs create
+# Ignore the files and directory that JetBrains IDEs create.
 \.idea/
+\.iml$
+
+# Gradle cache.
+^.gradle/
+
+# Local Gradle configuration properties.
+^local.properties$
 
 # Python stuff installed at build time.
 ^python/psutil/.*\.so
 ^python/psutil/.*\.pyd
 ^python/psutil/build/
 
 # Git repositories
 .git/
 
 # Ignore chrome.manifest files from the devtools loader
-^browser/devtools/chrome.manifest$
-^toolkit/devtools/chrome.manifest$
+^devtools/client/chrome.manifest$
+^devtools/shared/chrome.manifest$
 
 # git checkout of libstagefright
 ^media/libstagefright/android$
 
 # Tag files generated by GNU Global
 GTAGS
 GRTAGS
 GSYMS
 GPATH
 
-# Unit tests for Loop
+# Various items for Loop
 ^browser/components/loop/standalone/content/config\.js$
-^browser/components/loop/standalone/node_modules/
+^browser/extensions/loop/.*/node_modules/
+^browser/extensions/loop/.*\.module-cache
+^browser/extensions/loop/test/coverage/desktop
+^browser/extensions/loop/test/coverage/shared_standalone
+^browser/extensions/loop/test/visual-regression/diff
+^browser/extensions/loop/test/visual-regression/new
+^browser/extensions/loop/test/visual-regression/refs
 
 # Git clone directory for updating web-platform-tests
 ^testing/web-platform/sync/
 
-# Loop web client build/deploy dependencies
-^browser/components/loop/standalone/bower_components
+# Android Gradle artifacts.
+^mobile/android/gradle/.gradle
+
+# XCode project cruft
+^embedding/ios/GeckoEmbed/GeckoEmbed.xcodeproj/project.xcworkspace/xcuserdata
+^embedding/ios/GeckoEmbed/GeckoEmbed.xcodeproj/xcuserdata
 
-# Loop legal content build/deploy artifacts
+# Ignore mozharness execution files
+^testing/mozharness/.tox/
+^testing/mozharness/build/
+^testing/mozharness/logs/
+^testing/mozharness/.coverage
+^testing/mozharness/nosetests.xml
+
+# Ignore tox generated dir
+.tox/
 
-# XXX Once a grunt contrib-clean command has been added (bug 1066491), or
-# once legal has centralized their ToS and PP hosting infrastructure,
-# (expected Q4 2014) the legal doc build stuff for Loop can be removed,
-# including the following three lines
-^browser/components/loop/standalone/content/legal/styles/.*\.css$
-^browser/components/loop/standalone/content/legal/terms/en_US\.html$
+# Ignore node_modules from eslint-plugin-mozilla
+^testing/eslint-plugin-mozilla/node_modules/
+
+# Ignore talos virtualenv and tp5n files.
+# The tp5n set is supposed to be decompressed at
+# testing/talos/talos/page_load_test/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
+^testing/talos/talos/tests/devtools/damp.manifest.develop
--- a/.hgtags
+++ b/.hgtags
@@ -92,56 +92,192 @@ cf8750abee06cde395c659f8ecd8ae019d7512e3
 5bb309998e7050c9ee80b0147de1e473f008e221 FIREFOX_AURORA_20_BASE
 cc37417e2c284aed960f98ffa479de4ccdd5c7c3 FIREFOX_AURORA_21_BASE
 1c070ab0f9db59f13423b9c1db60419f7a9098f9 FIREFOX_AURORA_22_BASE
 d7ce9089999719d5186595d160f25123a4e63e39 FIREFOX_AURORA_23_BASE
 8d3810543edccf4fbe458178b88dd4a6e420b010 FIREFOX_AURORA_24_BASE
 ad0ae007aa9e03cd74e9005cd6652e544139b3b5 FIREFOX_AURORA_25_BASE
 2520866d58740851d862c7c59246a4e3f8b4a176 FIREFOX_AURORA_26_BASE
 05025f4889a0bf4dc99ce0c244c750adc002f015 FIREFOX_AURORA_27_BASE
+ba2cc1eda988a1614d8986ae145d28e1268409b9 FIREFOX_AURORA_29_BASE-m
+ba2cc1eda988a1614d8986ae145d28e1268409b9 Tagging for mozilla-central version bumps CLOSED TREE DONTBUILD
+ba2cc1eda988a1614d8986ae145d28e1268409b9 Tagging for mozilla-central version bumps CLOSED TREE DONTBUILD
+0000000000000000000000000000000000000000 Tagging for mozilla-central version bumps CLOSED TREE DONTBUILD
+ba2cc1eda988a1614d8986ae145d28e1268409b9 FIREFOX_AURORA_29_BASE-m
+0000000000000000000000000000000000000000 FIREFOX_AURORA_29_BASE-m
+ba2cc1eda988a1614d8986ae145d28e1268409b9 FIREFOX_AURORA_29_BASE
 9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
-ba2cc1eda988a1614d8986ae145d28e1268409b9 FIREFOX_AURORA_29_BASE
+07f5580d8a54e8311fa7641c907065a88de19e08 FIREFOX_AURORA_29_END
+3776f72f1967a7068879501eb7c08920032785b8 B2G_1_4_20140317_MERGEDAY
+aa70a6ce178a6839cd9e55761c4ac31d43ee7bd9 FIREFOX_BETA_29_END
+ba4a8f81efdcf000414f192342ccbd14c9626c36 RELEASE_BASE_20140602
+9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 83c9853e136451474dfa6d1aaa60a7fca7d2d83a FIREFOX_AURORA_30_BASE
 cfde3603b0206e119abea76fdd6e134b634348f1 FIREFOX_AURORA_31_BASE
 ab25447610b532eb4c32524a7dbc56a21eeaabb8 FIREFOX_BETA_30_BASE
 ab25447610b532eb4c32524a7dbc56a21eeaabb8 FIREFOX_AURORA_30_END
 6c18811bcd1b319801fd97aeb09c41b963863968 FIREFOX_BETA_30_END
 1772e55568e420f8c7fbf7b9434157e9f419c8f1 FIREFOX_RELEASE_31_BASE
+40b1b0712d7b53219a0404e78eec4e6a2796423e FIREFOX_RELEASE_30_END
+9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 16f3cac5e8fe471e12f76d6a94a477b14e78df7c FIREFOX_AURORA_32_BASE
 f11b164d75442617c4f046177d2ab913ed03a318 FIREFOX_BETA_31_BASE
 f11b164d75442617c4f046177d2ab913ed03a318 FIREFOX_AURORA_31_END
 dc2fd26b301375f15c935f00fe6283d3e3bc1efc B2G_2_0_20140609_MERGEDAY
 d69cd84b6824e018e0906cab0464e11e97a9bdca FIREFOX_BETA_32_BASE
 d69cd84b6824e018e0906cab0464e11e97a9bdca FIREFOX_BETA_32_BASE
 0000000000000000000000000000000000000000 FIREFOX_BETA_32_BASE
 0000000000000000000000000000000000000000 FIREFOX_BETA_32_BASE
 ac396ad5a32d60ae5b7eebe5416fdd46e9e12be1 FIREFOX_BETA_32_BASE
 6befadcaa68524d24960d8342e00503e4edc1869 FIREFOX_BETA_31_END
 92ad4cfa9435fbe136c61071041812f90bc8d89e FIREFOX_RELEASE_32_BASE
+cd52a7f8954809fd893196dc857f81b0cb61717c FIREFOX_RELEASE_31_END
+9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 dc23164ba2a289a8b22902e30990c77d9677c214 FIREFOX_AURORA_33_BASE
 a104ddcd4cdbf950f1755dfaf5a278d53570655f FIREFOX_AURORA_32_END
 114b010b6bf1a0efee03f003e54ed6fa00909972 FIREFOX_BETA_33_BASE
 ebd0ee3e97dc2756d979261b29f173638fe6aeb6 FIREFOX_BETA_32_END
 e8360a0c7d7483491e064c7cd445a94004af0a83 FIREFOX_RELEASE_33_BASE
+4641475ee1f3ec3e723e932e0f4f3f3fa7c55a5c FIREFOX_RELEASE_32_END
+9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 c360f3d1c00d73b0c1fb0a2c0da525cb55e58b83 FIREFOX_AURORA_34_BASE
 9f1aad8e807cc283aafbc14caa3d4775e8d0535c FIREFOX_AURORA_33_END
 5b8210dcf52a795646bf0c8a32082a2ed7c4f537 B2G_2_1_20140902_MERGEDAY
 e85828ce78a80e2ccda98972d69d5f750335c4ab FIREFOX_BETA_34_BASE
 8574e35b517785acc905327f4994e96576218fa8 FIREFOX_BETA_33_END
 e247a7f7c43842941bdb4207ca1b9d8881798997 FIREFOX_RELEASE_34_BASE
+a47b1b720b67b018a9cb106178de53a363641392 FIREFOX_RELEASE_33_END
+9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 cec1a116c4f9a3e887d52e9a26e8bbec200fe162 FIREFOX_AURORA_35_BASE
 2608561c091ae83cc85e38740feffa5bfc6b5ed4 FIREFOX_AURORA_34_END
 390a34a40ea4e7f4d24b3ed83778e0f408411fcc FIREFOX_BETA_35_BASE
 a3cc435fd3c315e5dfe9329d03d5943bb893cced FIREFOX_BETA_34_END
 fb06fa0600ab95db48212a237c79b650cac213c5 FIREFOX_RELEASE_35_BASE
+f4217563f1568c478c1ddf1647098946e51bc7f8 FIREFOX_RELEASE_34_END
+9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 ca89fe55717059e4e43040d16d260765ffa9dca7 FIREFOX_AURORA_36_BASE
 6047f510fb73c7dbe9866066fb01ddda3c170c9c FIREFOX_AURORA_37_BASE
 ca89fe55717059e4e43040d16d260765ffa9dca7 FIREFOX_AURORA_36_BASE
 0000000000000000000000000000000000000000 FIREFOX_AURORA_36_BASE
 6047f510fb73c7dbe9866066fb01ddda3c170c9c FIREFOX_AURORA_37_BASE
 0000000000000000000000000000000000000000 FIREFOX_AURORA_37_BASE
 0000000000000000000000000000000000000000 FIREFOX_AURORA_36_BASE
 b297a6727acfd21e757ddd38cd61894812666265 FIREFOX_AURORA_36_BASE
 0cf828669d5a0911b6f2b83d501eeef5bdf9905e FIREFOX_AURORA_35_END
 75177371cb85baaa9d623f56d849a5c21d18040f FIREFOX_BETA_36_BASE
 137baee3dda45c6a3b38be74f5709c24f7c7701a FIREFOX_BETA_35_END
-9e2391999085a47123017d76d336c3993640a8b3 FIREFOX_36_0b10_RELEASE
-9e2391999085a47123017d76d336c3993640a8b3 FIREFOX_36_0b10_BUILD1
+948a2c2e31d4b7eaa282ddeb327708605e3cc7fa FIREFOX_RELEASE_36_BASE
+d57ff45ca4fd7ccf1cb924030abf6c7d108eaab0 FIREFOX_RELEASE_35_END
+9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
+0000000000000000000000000000000000000000 FIREFOX_AURORA_37_BASE
+2c951493eef5b50b8085ef78ffe0d7902ff3d593 FIREFOX_AURORA_37_BASE
+1bc9beda018a42bdd5f63fc9fc46facf0c6f37ec FIREFOX_AURORA_36_END
+030fa1665346dfa94d1f72a1c7830644664ecf08 FIREFOX_BETA_37_BASE
+7d4016a05dd32bf2d726975ba9175bb13fc9ea97 FIREFOX_BETA_36_END
+196c6575593d6e8997402fb458bf8ed2f954fa4a FIREFOX_RELEASE_37_BASE
+58fe203296af528cc711dc314e4769a902e3852f FIREFOX_RELEASE_36_END
+9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
+98086da94ccdc88f6de86774ce3d1fa258dc7c44 FIREFOX_AURORA_38_BASE
+d55b99e8010728b0c802e75e967d2a853122dd30 FIREFOX_AURORA_37_END
+8bc9656cad94db48cd44f3947f1b3b1d8c57768a FIREFOX_BETA_38_BASE
+b41c57eefd69242fc9664a3e5c2dcaa46840051c FIREFOX_BETA_37_END
+fc98815acf5f041c6269fd256a68af8a92ba222a FIREFOX_RELEASE_38_BASE
+b95583c8e7e7a7ce629b4d4551747e818367d0a0 FIREFOX_RELEASE_37_END
+f33925facceefe32f6347faed2d805551d82e60b FIREFOX_RELEASE_38_END
+9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
+1b6bf6612c0f4d4fee81d18bf18016e692f874e1 FIREFOX_AURORA_39_BASE
+d92bf011e305a4a4ad6bb98192a53b86bd64b813 FIREFOX_AURORA_38_END
+5e851d50fb9b8d5a28e4fcd4731dd0f17e8fb4b9 FIREFOX_BETA_39_BASE
+85229fbaf01713caa9ad26c7d3afec271494113c FIREFOX_BETA_38_END
+5fecfbec2e3c934d4646a739bea60d3c93a35f9e FIREFOX_RELEASE_39_BASE
+9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
+66a95a483d2c77dfc387019336d18093acd6aac2 FIREFOX_AURORA_40_BASE
+eead3ccdf2d11feefc12907467cebbe07aa91ea9 FIREFOX_AURORA_39_END
+d77cf39268848f8a7e9b38082348b6cd4d1f3b5e FIREFOX_BETA_40_BASE
+0b0822cabbb95d8509852f90c0b7df5da0a4cabc FIREFOX_BETA_39_END
+34e00eb800c52e33059d37f6e41fb255b4bae6b8 FIREFOX_RELEASE_40_BASE
+9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
+312c68b16549de9cea1557f461d5d234bd5e0a7d FIREFOX_AURORA_41_BASE
+9d83ab013ab61c7f6e987bf0e7cbab1a1aed1ca8 FIREFOX_AURORA_40_END
+a019592053c4d93fbbafab8d0bd709529e3746de FIREFOX_BETA_41_BASE
+f147014ff61a12480d377c8bde1f90891772540f FIREFOX_BETA_40_END
+6c0329aacb73ab0510c6f1026ef066dfaed9139c FIREFOX_RELEASE_41_BASE
+9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
+7a19194812eb767bee7cdf8fc36ba9a383c1bead FIREFOX_AURORA_42_BASE
+d561dc208e61b2f2b4e82ab61710e14f56da4ddb FIREFOX_AURORA_41_END
+61bbc30704aa104e9929c719c0fd7957f96f00ea FIREFOX_BETA_42_BASE
+a5bf9cf6777519663e8e1db553727e59d3ad5681 FIREFOX_BETA_41_END
+3f2ff85b2f16c1fd161dc5ba77a5f3f2c52fd127 FIREFOX_RELEASE_42_BASE
+9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
+fcef8ded82219c89298b4e376cfbdfba79a1d35a FIREFOX_AURORA_43_BASE
+b0e20ff87b175424edec414215b325918ccb4792 FIREFOX_AURORA_42_END
+41fdefd640f368bccdeafe6446d42c0a5ad22797 FIREFOX_BETA_43_BASE
+0ec8472a93ac0c7ef0e98ebb91ac780bde12d5a5 FIREFOX_BETA_42_END
+38ffeba26f3e420312e04cb3afb408f4c66a6f2e FIREFOX_RELEASE_43_BASE
+9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
+67a788db9f07822cfef52351bbbe3745dff8bd7f FIREFOX_AURORA_44_BASE
+9d3bc275a924a84ab5f34df58c566af0f87479d0 FIREFOX_AURORA_43_END
+b717b80eec62a7ba9b8842487f157b68c1419edd FIREFOX_BETA_44_BASE
+366dd290472633b06f0942d7737c34e942e0916a FIREFOX_BETA_43_END
+ef3cfadfccb97588653ae06eefdac28ec447c1f6 FIREFOX_RELEASE_44_BASE
+9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
+99137d6d4061f408ae0869122649d8bdf489cc30 FIREFOX_AURORA_45_BASE
+4fbd53613240c431522521b953d5a62692909e65 FIREFOX_AURORA_44_END
+3bfa5bc61b626761d487b45c170b115259f69d6b FIREFOX_BETA_45_BASE
+6a7547e4a0f0e213bb8487c773e16543cbea8c73 FIREFOX_BETA_44_END
+3a9789adadcd0de9ee31b16a89a11985822c6a11 FENNEC_45_0b1_RELEASE
+6c0fd1f666e70f2b11f7083f9e7bf4c844a3716a FENNEC_45_0b1_RELEASE
+3a9789adadcd0de9ee31b16a89a11985822c6a11 FENNEC_45_0b1_BUILD1
+6c0fd1f666e70f2b11f7083f9e7bf4c844a3716a FENNEC_45_0b1_BUILD1
+5e1da6523e97d7f8b01004bbe33118ac784b40ea FIREFOX_45_0b1_RELEASE
+6c0fd1f666e70f2b11f7083f9e7bf4c844a3716a FIREFOX_45_0b1_RELEASE
+5e1da6523e97d7f8b01004bbe33118ac784b40ea FIREFOX_45_0b1_BUILD1
+6c0fd1f666e70f2b11f7083f9e7bf4c844a3716a FIREFOX_45_0b1_BUILD1
+bbe048ab30ad3321a6505697703e5fee20e91343 FIREFOX_RELEASE_45_BASE
+9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
+67c66c2878aed17ae3096d7db483ddbb2293c503 FIREFOX_AURORA_46_BASE
+d82221ba4219e4ac04ecfe2a5301703411e176fa FIREFOX_AURORA_45_END
+89effb961712d4a5f84e90bcdd4e421ed6645eea FIREFOX_BETA_46_BASE
+78fe98c670fcc9a1548ac655ae9a488d940fd9c8 FIREFOX_BETA_45_END
+fb3494d06dfb73e26df72ca7a4bc4ef5ebf8795c FIREFOX_46_0b1_RELEASE
+5904e3eb711dd263a6d2deb63b14e0c44e577054 FIREFOX_46_0b2_BUILD3
+5904e3eb711dd263a6d2deb63b14e0c44e577054 FIREFOX_46_0b2_RELEASE
+2f6f69a19150e03ad68062f2ac92342afb1ef787 FIREFOX_46_0b4_BUILD2
+2f6f69a19150e03ad68062f2ac92342afb1ef787 FIREFOX_46_0b4_RELEASE
+53d6e6648f97402a740687a82a297c66f5396548 FIREFOX_46_0b5_BUILD2
+53d6e6648f97402a740687a82a297c66f5396548 FIREFOX_46_0b5_RELEASE
+97b81104ac035d6a8f6ed59a1aad63fcc23e73c8 FIREFOX_46_0b6_BUILD1
+97b81104ac035d6a8f6ed59a1aad63fcc23e73c8 FIREFOX_46_0b6_RELEASE
+191f5eb4cbd72590277296cdb90d355adb347d45 FIREFOX_46_0b7_BUILD2
+191f5eb4cbd72590277296cdb90d355adb347d45 FIREFOX_46_0b7_RELEASE
+0334bcac4033f4f163476677165acd406e08fed8 FIREFOX_46_0b8_BUILD1
+0334bcac4033f4f163476677165acd406e08fed8 FIREFOX_46_0b8_RELEASE
+b007110e90053e58946b59765605bfca766c30d1 FIREFOX_46_0b9_BUILD1
+b007110e90053e58946b59765605bfca766c30d1 FIREFOX_46_0b9_RELEASE
+9ea83990839bd513869018e57bcbedb3454b63bb FIREFOX_46_0b10_BUILD1
+9ea83990839bd513869018e57bcbedb3454b63bb FIREFOX_46_0b10_RELEASE
+6c4646c7a6d6506e744c92a8170310191904c98e FIREFOX_RELEASE_46_BASE
+076bf6a0ac85ec6a4f3ee7c3efe653964d92b9f2 FIREFOX_46_0b11_BUILD1
+076bf6a0ac85ec6a4f3ee7c3efe653964d92b9f2 FIREFOX_46_0b11_RELEASE
+9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
+68d3781deda0d4d58ec9877862830db89669b3a5 FIREFOX_AURORA_47_BASE
+43d92f7052e7bab870c9b994d4b0a0f42d26b7a7 FIREFOX_AURORA_46_END
+8551b253f4061db31e4be7829c2f70c2610caf42 FIREFOX_BETA_47_BASE
+a2290938ee6cf794896a9347980bcb00ebb24c68 FIREFOX_BETA_46_END
+5bbf2e7c2fc6ff9010b1948e2f11477f48ee36e2 FIREFOX_47_0b1_BUILD2
+5bbf2e7c2fc6ff9010b1948e2f11477f48ee36e2 FIREFOX_47_0b1_RELEASE
+6f82d30fe05e1412e744cb76af86f0c9ffe509d4 FIREFOX_47_0b2_BUILD1
+6f82d30fe05e1412e744cb76af86f0c9ffe509d4 FIREFOX_47_0b2_RELEASE
+609000bcc11211d7c27ceea36fa2d2262fa0523f FIREFOX_47_0b3_BUILD1
+609000bcc11211d7c27ceea36fa2d2262fa0523f FIREFOX_47_0b3_RELEASE
+2991f214d4f4d8a3c5cfd95e6223f0660006767d FIREFOX_47_0b4_BUILD1
+2991f214d4f4d8a3c5cfd95e6223f0660006767d FIREFOX_47_0b4_RELEASE
+93a53170dedffdff45bf9eb8dac6e5ef7a13c4ba FIREFOX_47_0b5_BUILD1
+93a53170dedffdff45bf9eb8dac6e5ef7a13c4ba FIREFOX_47_0b5_RELEASE
+7d1f3450acc47025876964c1eca854ae027934f3 FIREFOX_47_0b6_BUILD1
+7d1f3450acc47025876964c1eca854ae027934f3 FIREFOX_47_0b6_RELEASE
+0723a0212f5e0b30d7532d4e35eba7759fb54507 FIREFOX_47_0b7_BUILD1
+0723a0212f5e0b30d7532d4e35eba7759fb54507 FIREFOX_47_0b7_RELEASE
+cb27eacbe04abc5f91a0379c23617715aab432ec FIREFOX_47_0b8_BUILD1
+cb27eacbe04abc5f91a0379c23617715aab432ec FIREFOX_47_0b8_RELEASE
+2ee4473c729acb2ba7dc723e7affe79ce14bff85 FIREFOX_47_0b9_BUILD1
+2ee4473c729acb2ba7dc723e7affe79ce14bff85 FIREFOX_47_0b9_RELEASE
+cf6ec12bd62001b93387ffb184a8841644255b5e FIREFOX_RELEASE_47_BASE
new file mode 100644
--- /dev/null
+++ b/.ycm_extra_conf.py
@@ -0,0 +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/.
+
+import imp
+import os
+from StringIO import StringIO
+import shlex
+import sys
+
+old_bytecode = sys.dont_write_bytecode
+sys.dont_write_bytecode = True
+
+path = os.path.join(os.path.dirname(__file__), 'mach')
+
+if not os.path.exists(path):
+    path = os.path.join(os.path.dirname(__file__), 'config.status')
+    config = imp.load_module('_buildconfig', open(path), path, ('', 'r', imp.PY_SOURCE))
+    path = os.path.join(config.topsrcdir, 'mach')
+mach_module = imp.load_module('_mach', open(path), path, ('', 'r', imp.PY_SOURCE))
+
+sys.dont_write_bytecode = old_bytecode
+
+def FlagsForFile(filename):
+    mach = mach_module.get_mach()
+    out = StringIO()
+    out.encoding = None
+    mach.run(['compileflags', filename], stdout=out, stderr=out)
+
+    flag_list = shlex.split(out.getvalue())
+
+    # This flag is added by Fennec for android build and causes ycmd to fail to parse the file.
+    # Removing this flag is a workaround until ycmd starts to handle this flag properly.
+    # https://github.com/Valloric/YouCompleteMe/issues/1490
+    final_flags = [x for x in flag_list if not x.startswith('-march=armv')]
+
+    return {
+        'flags': final_flags,
+        'do_cache': True
+    }
--- a/AUTHORS
+++ b/AUTHORS
@@ -9,16 +9,17 @@ contribution to Mozilla, see http://www.
 <1010mozilla@Ostermiller.com>
 Aaron Boodman <aa@google.com>
 Aaron Kaluszka <ask@swva.net>
 Aaron Leventhal <aaronleventhal@moonset.net>
 Aaron Nowack <anowack@mimiru.net>
 Aaron Reed <aaronr@us.ibm.com>
 Aaron Spangler <aaron@spangler.ods.org>
 Aaron Train <aaron.train@gmail.com>
+Abdelrhman Ahmed <a.ahmed1026@gmail.com>
 Achim Hasenmueller <achimha@innotek.de>
 ActiveState Tool Corp.
 Adam Barth <hk9565@gmail.com>
 Adam Christian <adam.christian@gmail.com>
 Adam Hauner
 Adam Lock <adamlock@netscape.com>
 Adam L. Peller
 Adam Souzis <adam@souzis.com>
@@ -353,16 +354,17 @@ Fernando Jimenez <ferjmoreno@gmail.com>
 Flock Inc.
 Florian Boesch <pyalot@gmail.com>
 Florian Hänel <heeen@gmx.de>
 Florian Queze <florian@queze.net>
 Florian Scholz <elchi3@elchi3.de>
 <flying@dom.natm.ru>
 France Telecom Research and Development
 Franck
+Francois Marier <francois@fmarier.org>
 Frank Tang <ftang@netscape.com>
 Frank Yan <fyan@mozilla.com>
 Franky Braem
 <franky@pacificconnections.com>
 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
 Frederic Plourde <frederic.plourde@polymtl.ca>
 Frederic Wang <fred.wang@free.fr>
 Fredrik Holmqvist <thesuckiestemail@yahoo.se>
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,10 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
+
 Merge day clobber
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/GNUmakefile
@@ -0,0 +1,14 @@
+# This Makefile is used as a shim to aid people with muscle memory
+# so that they can type "make".
+#
+# This file and all of its targets should not be used by anything important.
+
+all: build
+
+build:
+	./mach build
+
+clean:
+	./mach clobber
+
+.PHONY: all build clean
--- a/Makefile.in
+++ b/Makefile.in
@@ -10,166 +10,228 @@ make_min_ver := 3.81
 ifneq ($(make_min_ver),$(firstword $(sort $(make_min_ver) $(MAKE_VERSION))))
 $(error GNU Make $(make_min_ver) or higher is required)
 endif
 
 export TOPLEVEL_BUILD := 1
 
 default::
 
+ifndef TEST_MOZBUILD
 ifdef MOZ_BUILD_APP
 include $(topsrcdir)/$(MOZ_BUILD_APP)/build.mk
 endif
+endif
 
 include $(topsrcdir)/config/config.mk
 
-GARBAGE_DIRS += dist _javagen _profile staticlib
+GARBAGE_DIRS += _javagen _profile staticlib
 DIST_GARBAGE = config.cache config.log config.status* config-defs.h \
    config/autoconf.mk \
    mozilla-config.h \
    netwerk/necko-config.h xpcom/xpcom-config.h xpcom/xpcom-private.h \
    .mozconfig.mk
 
+ifndef MOZ_PROFILE_USE
+buildid.h source-repo.h: FORCE
+endif
+
 ifdef JS_STANDALONE
 configure_dir = $(topsrcdir)/js/src
 else
 configure_dir = $(topsrcdir)
 endif
 
+BUILD_BACKEND_FILES := $(addprefix backend.,$(addsuffix Backend,$(BUILD_BACKENDS)))
+
+ifndef TEST_MOZBUILD
 ifndef MOZ_PROFILE_USE
-# We need to explicitly put backend.RecursiveMakeBackend here
-# otherwise the rule in rules.mk doesn't run early enough.
-$(TIERS) binaries:: CLOBBER $(configure_dir)/configure config.status backend.RecursiveMakeBackend
+# We need to explicitly put BUILD_BACKEND_FILES here otherwise the rule in
+# rules.mk doesn't run early enough.
+$(TIERS) binaries:: CLOBBER $(configure_dir)/configure config.status $(BUILD_BACKEND_FILES)
 ifndef JS_STANDALONE
-ifndef LIBXUL_SDK
+ifdef COMPILE_ENVIRONMENT
 $(TIERS) binaries:: $(topsrcdir)/js/src/configure js/src/config.status
 endif
 endif
 endif
+endif
 
 ifdef JS_STANDALONE
 .PHONY: CLOBBER
 CLOBBER:
 else
 CLOBBER: $(topsrcdir)/CLOBBER
 	@echo 'STOP!  The CLOBBER file has changed.'
 	@echo 'Please run the build through a sanctioned build wrapper, such as'
 	@echo '"mach build" or client.mk.'
 	@exit 1
 endif
 
-$(topsrcdir)/configure: $(topsrcdir)/configure.in
-$(topsrcdir)/js/src/configure: $(topsrcdir)/js/src/configure.in
+$(topsrcdir)/configure: $(topsrcdir)/configure.in $(topsrcdir)/old-configure.in
+$(topsrcdir)/js/src/configure: $(topsrcdir)/js/src/configure.in $(topsrcdir)/js/src/old-configure.in
 $(topsrcdir)/configure $(topsrcdir)/js/src/configure:
-	@echo 'STOP!  $^ has changed, and your configure is out of date.'
+	@echo 'STOP!  $? has changed, and your configure is out of date.'
 	@echo 'Please rerun autoconf and re-configure your build directory.'
 	@echo 'To ignore this message, touch "$@",'
 	@echo 'but your build might not succeed.'
 	@exit 1
 
-config.status: $(configure_dir)/configure
-js/src/config.status: $(topsrcdir)/js/src/configure
+config.status: $(configure_dir)/configure $(configure_dir)/old-configure
+js/src/config.status: $(topsrcdir)/js/src/configure $(topsrcdir)/js/src/old-configure
 config.status js/src/config.status:
-	@echo 'STOP!  $^ has changed and needs to be run again.'
+	@echo 'STOP!  $? has changed and needs to be run again.'
 	@echo 'Please rerun it.'
 	@echo 'To ignore this message, touch "$(CURDIR)/$@",'
 	@echo 'but your build might not succeed.'
 	@exit 1
 
 # Regenerate the build backend if it is out of date. We only have this rule in
 # this main make file because having it in rules.mk and applied to partial tree
 # builds resulted in a world of hurt. Gory details are in bug 877308.
 #
 # The mach build driver will ensure the backend is up to date for partial tree
 # builds. This cleanly avoids most of the pain.
 
-backend.RecursiveMakeBackend:
+ifndef TEST_MOZBUILD
+
+.PHONY: backend
+backend: $(BUILD_BACKEND_FILES)
+
+# A traditional rule would look like this:
+#    backend.%:
+#        @echo do stuff
+#
+# But with -j<n>, and multiple items in BUILD_BACKEND_FILES, the command would
+# run multiple times in parallel.
+#
+# "Fortunately", make has some weird semantics for pattern rules: if there are
+# multiple targets in a pattern rule and each of them is matched at most once,
+# the command will only run once. So:
+#     backend%RecursiveMakeBackend backend%FasterMakeBackend:
+#         @echo do stuff
+#     backend: backend.RecursiveMakeBackend backend.FasterMakeBackend
+# would only execute the command once.
+#
+# Credit where due: http://stackoverflow.com/questions/2973445/gnu-makefile-rule-generating-a-few-targets-from-a-single-source-file/3077254#3077254
+$(subst .,%,$(BUILD_BACKEND_FILES)):
 	@echo 'Build configuration changed. Regenerating backend.'
 	$(PYTHON) config.status
 
-Makefile: backend.RecursiveMakeBackend
+Makefile: $(BUILD_BACKEND_FILES)
 	@$(TOUCH) $@
 
-include backend.RecursiveMakeBackend.pp
+define build_backend_rule
+$(1)_files := $$(shell cat $(1).in)
+$(1): $$($(1)_files)
+$$($(1)_files):
 
-default:: backend.RecursiveMakeBackend
+endef
+$(foreach file,$(BUILD_BACKEND_FILES),$(eval $(call build_backend_rule,$(file))))
+
+default:: $(BUILD_BACKEND_FILES)
+endif
 
 install_manifests := \
-  $(addprefix dist/,bin idl include public private sdk xpi-stage) \
+  $(addprefix dist/,branding idl include public private sdk xpi-stage) \
   _tests \
   $(NULL)
+# Skip the dist/bin install manifest when using the hybrid
+# FasterMake/RecursiveMake backend. This is a hack until bug 1241744 moves
+# xpidl handling to FasterMake in that case, mechanically making the dist/bin
+# install manifest non-existent (non-existent manifests being skipped)
+ifeq (,$(filter FasterMake+RecursiveMake,$(BUILD_BACKENDS)))
+install_manifests += dist/bin
+endif
 install_manifest_depends = \
   CLOBBER \
   $(configure_dir)/configure \
   config.status \
-  backend.RecursiveMakeBackend \
+  $(BUILD_BACKEND_FILES) \
   $(NULL)
 
 ifndef JS_STANDALONE
-ifndef LIBXUL_SDK
+ifdef COMPILE_ENVIRONMENT
 install_manifest_depends += \
   $(topsrcdir)/js/src/configure \
   js/src/config.status \
   $(NULL)
 endif
 endif
 
 .PHONY: install-manifests
 install-manifests: $(addprefix install-,$(install_manifests))
 
+# If we're using the hybrid FasterMake/RecursiveMake backend, we want
+# to recurse in the faster/ directory in parallel of install manifests.
+# But dist/idl needs to happen before (cf. dependencies in
+# config/faster/rules.mk)
+ifneq (,$(filter FasterMake+RecursiveMake,$(BUILD_BACKENDS)))
+install-manifests: faster
+.PHONY: faster
+faster: install-dist/idl
+	$(MAKE) -C faster FASTER_RECURSIVE_MAKE=1
+endif
+
 # process_install_manifest needs to be invoked with --no-remove when building
 # js as standalone because automated builds are building nspr separately and
 # that would remove the resulting files.
 # Eventually, a standalone js build would just be able to build nspr itself,
 # removing the need for the former.
 ifdef JS_STANDALONE
 NO_REMOVE=1
 endif
 
-.PHONY: $(addprefix install-,$(install_manifests))
-$(addprefix install-,$(filter dist/%,$(install_manifests))): install-dist/%: $(install_manifest_depends)
-	$(call py_action,process_install_manifest,$(if $(NO_REMOVE),--no-remove )$(DIST)/$* _build_manifests/install/dist_$*)
+.PHONY: $(addprefix install-,$(subst /,_,$(install_manifests)))
+$(addprefix install-,$(install_manifests)): install-%: $(install_manifest_depends)
+ifneq (,$(filter FasterMake+RecursiveMake,$(BUILD_BACKENDS)))
+	@# If we're using the hybrid FasterMake/RecursiveMake backend, we want
+	@# to ensure the FasterMake end doesn't have install manifests for the
+	@# same directory, because that would blow up
+	$(if $(wildcard _build_manifests/install/$(subst /,_,$*)),$(if $(wildcard faster/install_$(subst /,_,$*)*),$(error FasterMake and RecursiveMake ends of the hybrid build system want to handle $*)))
+endif
+	$(addprefix $(call py_action,process_install_manifest,$(if $(NO_REMOVE),--no-remove )$*) ,$(wildcard _build_manifests/install/$(subst /,_,$*)))
 
-install-_tests: $(install_manifest_depends)
-	$(call py_action,process_install_manifest,$(if $(NO_REMOVE),--no-remove )_tests _build_manifests/install/tests)
+# Dummy wrapper rule to allow the faster backend to piggy back
+$(addprefix install-,$(subst /,_,$(filter dist/%,$(install_manifests)))): install-dist_%: install-dist/% ;
 
 # For compatibility
 .PHONY: install-tests
 install-tests: install-_tests
 
 include $(topsrcdir)/build/moz-automation.mk
 
-# _tests should be purged during cleaning. However, we don't want it purged
-# during PGO builds because it contains some auto-generated files.
+# dist and _tests should be purged during cleaning. However, we don't want them
+# purged during PGO builds because they contain some auto-generated files.
 ifneq ($(filter-out maybe_clobber_profiledbuild,$(MAKECMDGOALS)),)
-GARBAGE_DIRS += _tests
+GARBAGE_DIRS += dist _tests
 endif
 
 # Windows PGO builds don't perform a clean before the 2nd pass. So, we want
 # to preserve content for the 2nd pass on Windows. Everywhere else, we always
 # process the install manifests as part of export.
 # For the binaries rule, not all the install manifests matter, so force only
 # the interesting ones to be done.
 ifdef MOZ_PROFILE_USE
 ifndef NO_PROFILE_GUIDED_OPTIMIZE
 ifneq ($(OS_ARCH)_$(GNU_CC), WINNT_)
-export:: install-manifests
+recurse_pre-export:: install-manifests
 binaries::
 	@$(MAKE) install-manifests NO_REMOVE=1 install_manifests=dist/include
 endif
 endif
 else # !MOZ_PROFILE_USE (normal build)
-export:: install-manifests
+recurse_pre-export:: install-manifests
 binaries::
 	@$(MAKE) install-manifests NO_REMOVE=1 install_manifests=dist/include
 endif
 
 # For historical reasons that are unknown, $(DIST)/sdk is always blown away
 # with no regard for PGO passes. This decision could probably be revisited.
-export:: install-dist/sdk
+recurse_pre-export:: install-dist/sdk
 
 ifndef JS_STANDALONE
 ifdef ENABLE_TESTS
 # Additional makefile targets to call automated test suites
 include $(topsrcdir)/testing/testsuite-targets.mk
 endif
 endif
 
@@ -206,17 +268,16 @@ ifeq (,$(filter-out Linux SunOS,$(OS_ARC
 MAKE_SYM_STORE_ARGS := -c --vcs-info
 DUMP_SYMS_BIN ?= $(DIST)/host/bin/dump_syms
 MAKE_SYM_STORE_PATH := $(DIST)/bin
 endif
 MAKE_SYM_STORE_ARGS += --install-manifest=$(DEPTH)/_build_manifests/install/dist_include,$(DIST)/include
 
 SYM_STORE_SOURCE_DIRS := $(topsrcdir)
 
-ifndef JS_STANDALONE
 include $(topsrcdir)/toolkit/mozapps/installer/package-name.mk
 
 ifdef MOZ_SYMBOLS_EXTRA_BUILDID
 EXTRA_BUILDID := -$(MOZ_SYMBOLS_EXTRA_BUILDID)
 endif
 
 SYMBOL_INDEX_NAME = \
   $(MOZ_APP_NAME)-$(MOZ_APP_VERSION)-$(OS_TARGET)-$(BUILDID)-$(CPU_ARCH)$(EXTRA_BUILDID)-symbols.txt
@@ -244,24 +305,21 @@ ifdef MOZ_CRASHREPORTER
 	grep 'sym' $(SYMBOL_INDEX_NAME) > $(SYMBOL_INDEX_NAME).tmp && \
 	  mv $(SYMBOL_INDEX_NAME).tmp $(SYMBOL_INDEX_NAME)
 	cd $(DIST)/crashreporter-symbols && \
           zip -r9D '../$(PKG_PATH)$(SYMBOL_ARCHIVE_BASENAME).zip' . -i '*.sym' -i '*.txt'  -x '*test*' -x '*Test*'
 endif # MOZ_CRASHREPORTER
 
 uploadsymbols:
 ifdef MOZ_CRASHREPORTER
+ifdef SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE
+	$(PYTHON) -u $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.py '$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip'
+else
 	$(SHELL) $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.sh $(SYMBOL_INDEX_NAME) '$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip'
 endif
-
-# MOZ_SOURCE_STAMP is defined in package-name.mk with a deferred assignment.
-# exporting it makes make run its $(shell) command for each invoked submake,
-# so transform it to an immediate assignment.
-MOZ_SOURCE_STAMP := $(MOZ_SOURCE_STAMP)
-export MOZ_SOURCE_STAMP
 endif
 
 .PHONY: update-packaging
 update-packaging:
 	$(MAKE) -C tools/update-packaging
 
 .PHONY: pretty-package
 pretty-package:
--- a/README.txt
+++ b/README.txt
@@ -17,12 +17,11 @@ If you have a question about developing 
 on http://developer.mozilla.org, you can try asking your question in a
 mozilla.* Usenet group, or on IRC at irc.mozilla.org. [The Mozilla news groups
 are accessible on Google Groups, or news.mozilla.org with a NNTP reader.]
 
 You can download nightly development builds from the Mozilla FTP server.
 Keep in mind that nightly builds, which are used by Mozilla developers for
 testing, may be buggy. Firefox nightlies, for example, can be found at:
 
-    ftp://ftp.mozilla.org/pub/firefox/nightly/latest-trunk/
+    https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central/
             - or -
     http://nightly.mozilla.org/
-
--- a/accessible/atk/AccessibleWrap.cpp
+++ b/accessible/atk/AccessibleWrap.cpp
@@ -6,18 +6,21 @@
 
 #include "AccessibleWrap.h"
 
 #include "Accessible-inl.h"
 #include "ApplicationAccessibleWrap.h"
 #include "InterfaceInitFuncs.h"
 #include "nsAccUtils.h"
 #include "mozilla/a11y/PDocAccessible.h"
+#include "OuterDocAccessible.h"
 #include "ProxyAccessible.h"
 #include "RootAccessible.h"
+#include "TableAccessible.h"
+#include "TableCellAccessible.h"
 #include "nsMai.h"
 #include "nsMaiHyperlink.h"
 #include "nsString.h"
 #include "nsAutoPtr.h"
 #include "prprf.h"
 #include "nsStateMap.h"
 #include "mozilla/a11y/Platform.h"
 #include "Relation.h"
@@ -28,17 +31,17 @@
 #include "mozilla/ArrayUtils.h"
 #include "nsXPCOMStrings.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIPersistentProperties2.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
-AccessibleWrap::EAvailableAtkSignals AccessibleWrap::gAvailableAtkSignals =
+MaiAtkObject::EAvailableAtkSignals MaiAtkObject::gAvailableAtkSignals =
   eUnknown;
 
 //defined in ApplicationAccessibleWrap.cpp
 extern "C" GType g_atk_hyperlink_impl_type;
 
 /* MaiAtkObject */
 
 enum {
@@ -91,17 +94,17 @@ static GType GetAtkTypeForMai(MaiInterfa
     case MAI_INTERFACE_DOCUMENT:
       return ATK_TYPE_DOCUMENT;
     case MAI_INTERFACE_IMAGE:
       return ATK_TYPE_IMAGE;
   }
   return G_TYPE_INVALID;
 }
 
-static const char* kNonUserInputEvent = ":system";
+#define NON_USER_EVENT ":system"
     
 static const GInterfaceInfo atk_if_infos[] = {
     {(GInterfaceInitFunc)componentInterfaceInitCB,
      (GInterfaceFinalizeFunc) nullptr, nullptr}, 
     {(GInterfaceInitFunc)actionInterfaceInitCB,
      (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)valueInterfaceInitCB,
      (GInterfaceFinalizeFunc) nullptr, nullptr},
@@ -118,32 +121,43 @@ static const GInterfaceInfo atk_if_infos
     {(GInterfaceInitFunc)textInterfaceInitCB,
      (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)documentInterfaceInitCB,
      (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)imageInterfaceInitCB,
      (GInterfaceFinalizeFunc) nullptr, nullptr}
 };
 
-/**
- * This MaiAtkObject is a thin wrapper, in the MAI namespace, for AtkObject
- */
-struct MaiAtkObject
+static GQuark quark_mai_hyperlink = 0;
+
+AtkHyperlink*
+MaiAtkObject::GetAtkHyperlink()
 {
-  AtkObject parent;
-  /*
-   * The AccessibleWrap whose properties and features are exported
-   * via this object instance.
-   */
-  uintptr_t accWrap;
-};
+  NS_ASSERTION(quark_mai_hyperlink, "quark_mai_hyperlink not initialized");
+  MaiHyperlink* maiHyperlink =
+    (MaiHyperlink*)g_object_get_qdata(G_OBJECT(this), quark_mai_hyperlink);
+  if (!maiHyperlink) {
+    maiHyperlink = new MaiHyperlink(accWrap);
+    g_object_set_qdata(G_OBJECT(this), quark_mai_hyperlink, maiHyperlink);
+  }
+
+  return maiHyperlink->GetAtkHyperlink();
+}
 
-// This is or'd with the pointer in MaiAtkObject::accWrap if the wrap-ee is a
-// proxy.
-static const uintptr_t IS_PROXY = 1;
+void
+MaiAtkObject::Shutdown()
+{
+  accWrap.SetBits(0);
+  MaiHyperlink* maiHyperlink =
+    (MaiHyperlink*)g_object_get_qdata(G_OBJECT(this), quark_mai_hyperlink);
+  if (maiHyperlink) {
+    delete maiHyperlink;
+    g_object_set_qdata(G_OBJECT(this), quark_mai_hyperlink, nullptr);
+  }
+}
 
 struct MaiAtkObjectClass
 {
     AtkObjectClass parent_class;
 };
 
 static guint mai_atk_object_signals [LAST_SIGNAL] = { 0, };
 
@@ -203,18 +217,16 @@ static AtkRelationSet*     refRelationSe
 */
 G_END_DECLS
 
 static GType GetMaiAtkType(uint16_t interfacesBits);
 static const char * GetUniqueMaiAtkTypeName(uint16_t interfacesBits);
 
 static gpointer parent_class = nullptr;
 
-static GQuark quark_mai_hyperlink = 0;
-
 GType
 mai_atk_object_get_type(void)
 {
     static GType type = 0;
 
     if (!type) {
         static const GTypeInfo tinfo = {
             sizeof(MaiAtkObjectClass),
@@ -245,69 +257,34 @@ AccessibleWrap::
 AccessibleWrap::~AccessibleWrap()
 {
     NS_ASSERTION(!mAtkObject, "ShutdownAtkObject() is not called");
 }
 
 void
 AccessibleWrap::ShutdownAtkObject()
 {
-    if (mAtkObject) {
-        if (IS_MAI_OBJECT(mAtkObject)) {
-            MAI_ATK_OBJECT(mAtkObject)->accWrap = 0;
-        }
-        SetMaiHyperlink(nullptr);
-        g_object_unref(mAtkObject);
-        mAtkObject = nullptr;
-    }
+  if (!mAtkObject)
+    return;
+
+  NS_ASSERTION(IS_MAI_OBJECT(mAtkObject), "wrong type of atk object");
+  if (IS_MAI_OBJECT(mAtkObject))
+    MAI_ATK_OBJECT(mAtkObject)->Shutdown();
+
+  g_object_unref(mAtkObject);
+  mAtkObject = nullptr;
 }
 
 void
 AccessibleWrap::Shutdown()
 {
   ShutdownAtkObject();
   Accessible::Shutdown();
 }
 
-MaiHyperlink*
-AccessibleWrap::GetMaiHyperlink(bool aCreate /* = true */)
-{
-    // make sure mAtkObject is created
-    GetAtkObject();
-
-    NS_ASSERTION(quark_mai_hyperlink, "quark_mai_hyperlink not initialized");
-    NS_ASSERTION(IS_MAI_OBJECT(mAtkObject), "Invalid AtkObject");
-    MaiHyperlink* maiHyperlink = nullptr;
-    if (quark_mai_hyperlink && IS_MAI_OBJECT(mAtkObject)) {
-        maiHyperlink = (MaiHyperlink*)g_object_get_qdata(G_OBJECT(mAtkObject),
-                                                         quark_mai_hyperlink);
-        if (!maiHyperlink && aCreate) {
-            maiHyperlink = new MaiHyperlink(this);
-            SetMaiHyperlink(maiHyperlink);
-        }
-    }
-    return maiHyperlink;
-}
-
-void
-AccessibleWrap::SetMaiHyperlink(MaiHyperlink* aMaiHyperlink)
-{
-    NS_ASSERTION(quark_mai_hyperlink, "quark_mai_hyperlink not initialized");
-    NS_ASSERTION(IS_MAI_OBJECT(mAtkObject), "Invalid AtkObject");
-    if (quark_mai_hyperlink && IS_MAI_OBJECT(mAtkObject)) {
-        MaiHyperlink* maiHyperlink = GetMaiHyperlink(false);
-        if (!maiHyperlink && !aMaiHyperlink) {
-            return; // Never set and we're shutting down
-        }
-        delete maiHyperlink;
-        g_object_set_qdata(G_OBJECT(mAtkObject), quark_mai_hyperlink,
-                           aMaiHyperlink);
-    }
-}
-
 void
 AccessibleWrap::GetNativeInterface(void** aOutAccessible)
 {
   *aOutAccessible = nullptr;
 
   if (!mAtkObject) {
     if (IsDefunct() || !nsAccUtils::IsEmbeddedObject(this)) {
       // We don't create ATK objects for node which has been shutdown or
@@ -577,25 +554,25 @@ initializeCB(AtkObject *aAtkObj, gpointe
     /* AtkObjectClass has not a "initialize" function now,
      * maybe it has later
      */
 
     if (ATK_OBJECT_CLASS(parent_class)->initialize)
         ATK_OBJECT_CLASS(parent_class)->initialize(aAtkObj, aData);
 
   /* initialize object */
-  MAI_ATK_OBJECT(aAtkObj)->accWrap = reinterpret_cast<uintptr_t>(aData);
+  MAI_ATK_OBJECT(aAtkObj)->accWrap.SetBits(reinterpret_cast<uintptr_t>(aData));
 }
 
 void
 finalizeCB(GObject *aObj)
 {
     if (!IS_MAI_OBJECT(aObj))
         return;
-    NS_ASSERTION(MAI_ATK_OBJECT(aObj)->accWrap == 0, "AccWrap NOT null");
+    NS_ASSERTION(MAI_ATK_OBJECT(aObj)->accWrap.IsNull(), "AccWrap NOT null");
 
     // call parent finalize function
     // finalize of GObjectClass will unref the accessible parent if has
     if (G_OBJECT_CLASS (parent_class)->finalize)
         G_OBJECT_CLASS (parent_class)->finalize(aObj);
 }
 
 const gchar*
@@ -615,17 +592,18 @@ getNameCB(AtkObject* aAtkObj)
 
   return aAtkObj->name;
 }
 
 static void
 MaybeFireNameChange(AtkObject* aAtkObj, const nsString& aNewName)
 {
   NS_ConvertUTF16toUTF8 newNameUTF8(aNewName);
-  if (aAtkObj->name && newNameUTF8.Equals(aAtkObj->name))
+  if (aAtkObj->name &&
+      !strncmp(aAtkObj->name, newNameUTF8.get(), newNameUTF8.Length()))
     return;
 
   // Below we duplicate the functionality of atk_object_set_name(),
   // but without calling atk_object_get_name(). Instead of
   // atk_object_get_name() we directly access aAtkObj->name. This is because
   // atk_object_get_name() would call getNameCB() which would call
   // MaybeFireNameChange() (or atk_object_set_name() before this problem was
   // fixed) and we would get an infinite recursion.
@@ -667,51 +645,53 @@ getDescriptionCB(AtkObject *aAtkObj)
 }
 
 AtkRole
 getRoleCB(AtkObject *aAtkObj)
 {
   if (aAtkObj->role != ATK_ROLE_INVALID)
     return aAtkObj->role;
 
-  AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
-  a11y::role role;
-  if (!accWrap) {
-    ProxyAccessible* proxy = GetProxy(aAtkObj);
-    if (!proxy)
-      return ATK_ROLE_INVALID;
+  AccessibleOrProxy acc = GetInternalObj(aAtkObj);
+  if (acc.IsNull()) {
+    return ATK_ROLE_INVALID;
+  }
 
-    role = proxy->Role();
-  } else {
 #ifdef DEBUG
+  if (AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj)) {
     NS_ASSERTION(nsAccUtils::IsTextInterfaceSupportCorrect(accWrap),
                  "Does not support Text interface when it should");
+  }
 #endif
 
-    role = accWrap->Role();
-  }
-
 #define ROLE(geckoRole, stringRole, atkRole, macRole, \
              msaaRole, ia2Role, nameRule) \
   case roles::geckoRole: \
     aAtkObj->role = atkRole; \
     break;
 
-  switch (role) {
+  switch (acc.Role()) {
 #include "RoleMap.h"
     default:
       MOZ_CRASH("Unknown role.");
-  };
+  }
 
 #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_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;
 }
 
 static AtkAttributeSet*
 ConvertToAtkAttributeSet(nsIPersistentProperties* aAttributes)
 {
     if (!aAttributes)
@@ -774,17 +754,17 @@ getAttributesCB(AtkObject *aAtkObj)
   AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
   if (accWrap)
     return GetAttributeSet(accWrap);
 
   ProxyAccessible* proxy = GetProxy(aAtkObj);
   if (!proxy)
     return nullptr;
 
-  nsAutoTArray<Attribute, 10> attrs;
+  AutoTArray<Attribute, 10> attrs;
   proxy->Attributes(&attrs);
   if (attrs.IsEmpty())
     return nullptr;
 
   AtkAttributeSet* objAttributeSet = nullptr;
   for (uint32_t i = 0; i < attrs.Length(); i++) {
     AtkAttribute *objAttr = (AtkAttribute *)g_malloc(sizeof(AtkAttribute));
     objAttr->name = g_strdup(attrs[i].Name().get());
@@ -814,71 +794,125 @@ getParentCB(AtkObject *aAtkObj)
     return aAtkObj->accessible_parent;
 
   AtkObject* atkParent = nullptr;
   if (AccessibleWrap* wrapper = GetAccessibleWrap(aAtkObj)) {
     Accessible* parent = wrapper->Parent();
     atkParent = parent ? AccessibleWrap::GetAtkObject(parent) : nullptr;
   } else if (ProxyAccessible* proxy = GetProxy(aAtkObj)) {
     ProxyAccessible* parent = proxy->Parent();
-    atkParent = parent ? GetWrapperFor(parent) : nullptr;
+    if (parent) {
+      atkParent = GetWrapperFor(parent);
+    } else {
+      // Otherwise this should be the proxy for the tab's top level document.
+      Accessible* outerDocParent = proxy->OuterDocOfRemoteBrowser();
+      NS_ASSERTION(outerDocParent, "this document should have an outerDoc as a parent");
+      if (outerDocParent) {
+        atkParent = AccessibleWrap::GetAtkObject(outerDocParent);
+      }
+    }
   }
 
   if (atkParent)
     atk_object_set_parent(aAtkObj, atkParent);
 
   return aAtkObj->accessible_parent;
 }
 
 gint
 getChildCountCB(AtkObject *aAtkObj)
 {
-    AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
-    if (!accWrap || nsAccUtils::MustPrune(accWrap)) {
-        return 0;
+  if (AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj)) {
+    if (nsAccUtils::MustPrune(accWrap)) {
+      return 0;
+    }
+
+    uint32_t count = accWrap->EmbeddedChildCount();
+    if (count) {
+      return static_cast<gint>(count);
     }
 
-    return static_cast<gint>(accWrap->EmbeddedChildCount());
+    OuterDocAccessible* outerDoc = accWrap->AsOuterDoc();
+    if (outerDoc && outerDoc->RemoteChildDoc()) {
+      return 1;
+    }
+  }
+
+  ProxyAccessible* proxy = GetProxy(aAtkObj);
+  if (proxy && !proxy->MustPruneChildren()) {
+    return proxy->EmbeddedChildCount();
+  }
+
+  return 0;
 }
 
 AtkObject *
 refChildCB(AtkObject *aAtkObj, gint aChildIndex)
 {
-    // aChildIndex should not be less than zero
-    if (aChildIndex < 0) {
+  // aChildIndex should not be less than zero
+  if (aChildIndex < 0) {
+    return nullptr;
+  }
+
+  AtkObject* childAtkObj = nullptr;
+  AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
+  if (accWrap) {
+    if (nsAccUtils::MustPrune(accWrap)) {
       return nullptr;
     }
 
-    AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
-    if (!accWrap || nsAccUtils::MustPrune(accWrap)) {
-        return nullptr;
+    Accessible* accChild = accWrap->GetEmbeddedChildAt(aChildIndex);
+    if (accChild) {
+      childAtkObj = AccessibleWrap::GetAtkObject(accChild);
+    } else {
+      OuterDocAccessible* docOwner = accWrap->AsOuterDoc();
+      if (docOwner) {
+        ProxyAccessible* proxyDoc = docOwner->RemoteChildDoc();
+        if (proxyDoc)
+          childAtkObj = GetWrapperFor(proxyDoc);
+      }
     }
+  } else if (ProxyAccessible* proxy = GetProxy(aAtkObj)) {
+    if (proxy->MustPruneChildren())
+      return nullptr;
 
-    Accessible* accChild = accWrap->GetEmbeddedChildAt(aChildIndex);
-    if (!accChild)
-        return nullptr;
+    ProxyAccessible* child = proxy->EmbeddedChildAt(aChildIndex);
+    if (child)
+      childAtkObj = GetWrapperFor(child);
+  } else {
+    return nullptr;
+  }
 
-    AtkObject* childAtkObj = AccessibleWrap::GetAtkObject(accChild);
+  NS_ASSERTION(childAtkObj, "Fail to get AtkObj");
+  if (!childAtkObj)
+    return nullptr;
 
-    NS_ASSERTION(childAtkObj, "Fail to get AtkObj");
-    if (!childAtkObj)
-        return nullptr;
-    g_object_ref(childAtkObj);
+  g_object_ref(childAtkObj);
 
   if (aAtkObj != childAtkObj->accessible_parent)
     atk_object_set_parent(childAtkObj, aAtkObj);
 
   return childAtkObj;
 }
 
 gint
 getIndexInParentCB(AtkObject* aAtkObj)
 {
   // We don't use Accessible::IndexInParent() because we don't include text
   // leaf nodes as children in ATK.
+  if (ProxyAccessible* proxy = GetProxy(aAtkObj)) {
+    if (ProxyAccessible* parent = proxy->Parent())
+      return parent->IndexOfEmbeddedChild(proxy);
+
+    if (proxy->OuterDocOfRemoteBrowser())
+      return 0;
+
+    return -1;
+  }
+
     AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
     if (!accWrap) {
         return -1;
     }
 
     Accessible* parent = accWrap->Parent();
     if (!parent)
         return -1; // No parent
@@ -942,30 +976,71 @@ UpdateAtkRelation(RelationType aType, Ac
     atk_relation_set_remove(aAtkSet, atkRelation);
 
   Relation rel(aAcc->RelationByType(aType));
   nsTArray<AtkObject*> targets;
   Accessible* tempAcc = nullptr;
   while ((tempAcc = rel.Next()))
     targets.AppendElement(AccessibleWrap::GetAtkObject(tempAcc));
 
+  if (aType == RelationType::EMBEDS && aAcc->IsRoot()) {
+    if (ProxyAccessible* proxyDoc =
+        aAcc->AsRoot()->GetPrimaryRemoteTopLevelContentDoc()) {
+      targets.AppendElement(GetWrapperFor(proxyDoc));
+    }
+  }
+
   if (targets.Length()) {
     atkRelation = atk_relation_new(targets.Elements(),
                                    targets.Length(), aAtkType);
     atk_relation_set_add(aAtkSet, atkRelation);
     g_object_unref(atkRelation);
   }
 }
 
 AtkRelationSet *
 refRelationSetCB(AtkObject *aAtkObj)
 {
   AtkRelationSet* relation_set =
     ATK_OBJECT_CLASS(parent_class)->ref_relation_set(aAtkObj);
 
+  const AtkRelationType typeMap[] = {
+#define RELATIONTYPE(gecko, s, atk, m, i) atk,
+#include "RelationTypeMap.h"
+#undef RELATIONTYPE
+  };
+
+  if (ProxyAccessible* proxy = GetProxy(aAtkObj)) {
+    nsTArray<RelationType> types;
+    nsTArray<nsTArray<ProxyAccessible*>> targetSets;
+    proxy->Relations(&types, &targetSets);
+
+    size_t relationCount = types.Length();
+    for (size_t i = 0; i < relationCount; i++) {
+      if (typeMap[static_cast<uint32_t>(types[i])] == ATK_RELATION_NULL)
+        continue;
+
+      size_t targetCount = targetSets[i].Length();
+      AutoTArray<AtkObject*, 5> wrappers;
+      for (size_t j = 0; j < targetCount; j++)
+        wrappers.AppendElement(GetWrapperFor(targetSets[i][j]));
+
+      AtkRelationType atkType = typeMap[static_cast<uint32_t>(types[i])];
+      AtkRelation* atkRelation =
+        atk_relation_set_get_relation_by_type(relation_set, atkType);
+      if (atkRelation)
+        atk_relation_set_remove(relation_set, atkRelation);
+
+      atkRelation = atk_relation_new(wrappers.Elements(), wrappers.Length(),
+                                     atkType);
+      atk_relation_set_add(relation_set, atkRelation);
+      g_object_unref(atkRelation);
+    }
+  }
+
   AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
   if (!accWrap)
     return relation_set;
 
 #define RELATIONTYPE(geckoType, geckoTypeName, atkType, msaaType, ia2Type) \
   UpdateAtkRelation(RelationType::geckoType, accWrap, atkType, relation_set);
 
 #include "RelationTypeMap.h"
@@ -975,24 +1050,27 @@ refRelationSetCB(AtkObject *aAtkObj)
   return relation_set;
 }
 
 // Check if aAtkObj is a valid MaiAtkObject, and return the AccessibleWrap
 // for it.
 AccessibleWrap*
 GetAccessibleWrap(AtkObject* aAtkObj)
 {
-  NS_ENSURE_TRUE(IS_MAI_OBJECT(aAtkObj), nullptr);
+  bool isMAIObject = IS_MAI_OBJECT(aAtkObj);
+  NS_ENSURE_TRUE(isMAIObject || MAI_IS_ATK_SOCKET(aAtkObj),
+                 nullptr);
 
-  // Make sure its native is an AccessibleWrap not a proxy.
-  if (MAI_ATK_OBJECT(aAtkObj)->accWrap & IS_PROXY)
-    return nullptr;
-
-    AccessibleWrap* accWrap =
-      reinterpret_cast<AccessibleWrap*>(MAI_ATK_OBJECT(aAtkObj)->accWrap);
+  AccessibleWrap* accWrap = nullptr;
+  if (isMAIObject) {
+    Accessible* acc = MAI_ATK_OBJECT(aAtkObj)->accWrap.AsAccessible();
+    accWrap = static_cast<AccessibleWrap*>(acc);
+  } else {
+    accWrap = MAI_ATK_SOCKET(aAtkObj)->accWrap;
+  }
 
   // Check if the accessible was deconstructed.
   if (!accWrap)
     return nullptr;
 
   NS_ENSURE_TRUE(accWrap->GetAtkObject() == aAtkObj, nullptr);
 
   AccessibleWrap* appAccWrap = ApplicationAcc();
@@ -1000,39 +1078,72 @@ GetAccessibleWrap(AtkObject* aAtkObj)
     return nullptr;
 
   return accWrap;
 }
 
 ProxyAccessible*
 GetProxy(AtkObject* aObj)
 {
-  if (!aObj || !(MAI_ATK_OBJECT(aObj)->accWrap & IS_PROXY))
+  return GetInternalObj(aObj).AsProxy();
+}
+
+AccessibleOrProxy
+GetInternalObj(AtkObject* aObj)
+{
+  if (!aObj || !IS_MAI_OBJECT(aObj))
     return nullptr;
 
-  return reinterpret_cast<ProxyAccessible*>(MAI_ATK_OBJECT(aObj)->accWrap
-      & ~IS_PROXY);
+  return MAI_ATK_OBJECT(aObj)->accWrap;
 }
 
 AtkObject*
 GetWrapperFor(ProxyAccessible* aProxy)
 {
   return reinterpret_cast<AtkObject*>(aProxy->GetWrapper() & ~IS_PROXY);
 }
 
 static uint16_t
-GetInterfacesForProxy(ProxyAccessible* aProxy)
+GetInterfacesForProxy(ProxyAccessible* aProxy, uint32_t aInterfaces)
 {
-  return MAI_INTERFACE_COMPONENT;
+  uint16_t interfaces = 1 << MAI_INTERFACE_COMPONENT;
+  if (aInterfaces & Interfaces::HYPERTEXT)
+    interfaces |= (1 << MAI_INTERFACE_HYPERTEXT) | (1 << MAI_INTERFACE_TEXT)
+        | (1 << MAI_INTERFACE_EDITABLE_TEXT);
+
+  if (aInterfaces & Interfaces::HYPERLINK)
+    interfaces |= 1 << MAI_INTERFACE_HYPERLINK_IMPL;
+
+  if (aInterfaces & Interfaces::VALUE)
+    interfaces |= 1 << MAI_INTERFACE_VALUE;
+
+  if (aInterfaces & Interfaces::TABLE)
+    interfaces |= 1 << MAI_INTERFACE_TABLE;
+
+  if (aInterfaces & Interfaces::IMAGE)
+    interfaces |= 1 << MAI_INTERFACE_IMAGE;
+
+  if (aInterfaces & Interfaces::DOCUMENT)
+    interfaces |= 1 << MAI_INTERFACE_DOCUMENT;
+
+  if (aInterfaces & Interfaces::SELECTION) {
+    interfaces |= 1 << MAI_INTERFACE_SELECTION;
+  }
+
+  if (aInterfaces & Interfaces::ACTION) {
+    interfaces |= 1 << MAI_INTERFACE_ACTION;
+  }
+
+  return interfaces;
 }
 
 void
-a11y::ProxyCreated(ProxyAccessible* aProxy)
+a11y::ProxyCreated(ProxyAccessible* aProxy, uint32_t aInterfaces)
 {
-  GType type = GetMaiAtkType(GetInterfacesForProxy(aProxy));
+  GType type = GetMaiAtkType(GetInterfacesForProxy(aProxy, aInterfaces));
   NS_ASSERTION(type, "why don't we have a type!");
 
   AtkObject* obj =
     reinterpret_cast<AtkObject *>
     (g_object_new(type, nullptr));
   if (!obj)
     return;
 
@@ -1042,27 +1153,31 @@ a11y::ProxyCreated(ProxyAccessible* aPro
   obj->layer = ATK_LAYER_INVALID;
   aProxy->SetWrapper(reinterpret_cast<uintptr_t>(obj) | IS_PROXY);
 }
 
 void
 a11y::ProxyDestroyed(ProxyAccessible* aProxy)
 {
   auto obj = reinterpret_cast<MaiAtkObject*>(aProxy->GetWrapper() & ~IS_PROXY);
-  obj->accWrap = 0;
+  obj->Shutdown();
   g_object_unref(obj);
   aProxy->SetWrapper(0);
 }
 
 nsresult
 AccessibleWrap::HandleAccEvent(AccEvent* aEvent)
 {
   nsresult rv = Accessible::HandleAccEvent(aEvent);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  if (IPCAccessibilityActive()) {
+    return NS_OK;
+  }
+
     Accessible* accessible = aEvent->GetAccessible();
     NS_ENSURE_TRUE(accessible, NS_ERROR_FAILURE);
 
     // The accessible can become defunct if we have an xpcom event listener
     // which decides it would be fun to change the DOM and flush layout.
     if (accessible->IsDefunct())
         return NS_OK;
 
@@ -1081,21 +1196,37 @@ AccessibleWrap::HandleAccEvent(AccEvent*
 
     AccessibleWrap* accWrap = GetAccessibleWrap(atkObj);
     if (!accWrap) {
         return NS_OK; // Node is shut down
     }
 
     switch (type) {
     case nsIAccessibleEvent::EVENT_STATE_CHANGE:
-        return FireAtkStateChangeEvent(aEvent, atkObj);
+      {
+        AccStateChangeEvent* event = downcast_accEvent(aEvent);
+        MAI_ATK_OBJECT(atkObj)->FireStateChangeEvent(event->GetState(),
+                                                     event->IsStateEnabled());
+        break;
+      }
 
     case nsIAccessibleEvent::EVENT_TEXT_REMOVED:
     case nsIAccessibleEvent::EVENT_TEXT_INSERTED:
-        return FireAtkTextChangedEvent(aEvent, atkObj);
+      {
+        AccTextChangeEvent* event = downcast_accEvent(aEvent);
+        NS_ENSURE_TRUE(event, NS_ERROR_FAILURE);
+
+        MAI_ATK_OBJECT(atkObj)-> FireTextChangeEvent(event->ModifiedText(),
+                                                     event->GetStartOffset(),
+                                                     event->GetLength(),
+                                                     event->IsTextInserted(),
+                                                     event->IsFromUserInput());
+
+        return NS_OK;
+      }
 
     case nsIAccessibleEvent::EVENT_FOCUS:
       {
         a11y::RootAccessible* rootAccWrap = accWrap->RootAccessible();
         if (rootAccWrap && rootAccWrap->mActivated) {
             atk_focus_tracker_notify(atkObj);
             // Fire state change event for focus
             atk_object_notify_state_change(atkObj, ATK_STATE_FOCUSED, true);
@@ -1109,16 +1240,17 @@ AccessibleWrap::HandleAccEvent(AccEvent*
         accessible->Name(newName);
 
         MaybeFireNameChange(atkObj, newName);
 
         break;
       }
 
   case nsIAccessibleEvent::EVENT_VALUE_CHANGE:
+  case nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE:
     if (accessible->HasNumericValue()) {
       // Make sure this is a numeric value. Don't fire for string value changes
       // (e.g. text editing) ATK values are always numeric.
       g_object_notify((GObject*)atkObj, "accessible-value");
     }
     break;
 
     case nsIAccessibleEvent::EVENT_SELECTION:
@@ -1133,16 +1265,21 @@ AccessibleWrap::HandleAccEvent(AccEvent*
     }
 
     case nsIAccessibleEvent::EVENT_SELECTION_WITHIN:
     {
       g_signal_emit_by_name(atkObj, "selection_changed");
       break;
     }
 
+    case nsIAccessibleEvent::EVENT_ALERT:
+      // A hack using state change showing events as alert events.
+      atk_object_notify_state_change(atkObj, ATK_STATE_SHOWING, true);
+      break;
+
     case nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED:
         g_signal_emit_by_name(atkObj, "text_selection_changed");
         break;
 
     case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED:
       {
         AccCaretMoveEvent* caretMoveEvent = downcast_accEvent(aEvent);
         NS_ASSERTION(caretMoveEvent, "Event needs event data");
@@ -1306,99 +1443,266 @@ AccessibleWrap::HandleAccEvent(AccEvent*
 
     return NS_OK;
 }
 
 void
 a11y::ProxyEvent(ProxyAccessible* aTarget, uint32_t aEventType)
 {
   AtkObject* wrapper = GetWrapperFor(aTarget);
-  if (aEventType == nsIAccessibleEvent::EVENT_FOCUS) {
+
+  switch (aEventType) {
+  case nsIAccessibleEvent::EVENT_FOCUS:
     atk_focus_tracker_notify(wrapper);
     atk_object_notify_state_change(wrapper, ATK_STATE_FOCUSED, true);
+    break;
+  case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE:
+    g_signal_emit_by_name(wrapper, "load_complete");
+    break;
+  case nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD:
+    g_signal_emit_by_name(wrapper, "reload");
+    break;
+  case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED:
+    g_signal_emit_by_name(wrapper, "load_stopped");
+    break;
+  case nsIAccessibleEvent::EVENT_MENUPOPUP_START:
+    atk_focus_tracker_notify(wrapper); // fire extra focus event
+    atk_object_notify_state_change(wrapper, ATK_STATE_VISIBLE, true);
+    atk_object_notify_state_change(wrapper, ATK_STATE_SHOWING, true);
+    break;
+  case nsIAccessibleEvent::EVENT_MENUPOPUP_END:
+    atk_object_notify_state_change(wrapper, ATK_STATE_VISIBLE, false);
+    atk_object_notify_state_change(wrapper, ATK_STATE_SHOWING, false);
+    break;
+  case nsIAccessibleEvent::EVENT_ALERT:
+    // A hack using state change showing events as alert events.
+    atk_object_notify_state_change(wrapper, ATK_STATE_SHOWING, true);
+    break;
+  case nsIAccessibleEvent::EVENT_VALUE_CHANGE:
+    g_object_notify((GObject*)wrapper, "accessible-value");
+    break;
   }
 }
 
-nsresult
-AccessibleWrap::FireAtkStateChangeEvent(AccEvent* aEvent,
-                                        AtkObject* aObject)
+void
+a11y::ProxyStateChangeEvent(ProxyAccessible* aTarget, uint64_t aState,
+                            bool aEnabled)
 {
-    AccStateChangeEvent* event = downcast_accEvent(aEvent);
-    NS_ENSURE_TRUE(event, NS_ERROR_FAILURE);
+  MaiAtkObject* atkObj = MAI_ATK_OBJECT(GetWrapperFor(aTarget));
+  atkObj->FireStateChangeEvent(aState, aEnabled);
+}
 
-    bool isEnabled = event->IsStateEnabled();
-    int32_t stateIndex = AtkStateMap::GetStateIndexFor(event->GetState());
+void
+a11y::ProxyCaretMoveEvent(ProxyAccessible* aTarget, int32_t aOffset)
+{
+  AtkObject* wrapper = GetWrapperFor(aTarget);
+  g_signal_emit_by_name(wrapper, "text_caret_moved", aOffset);
+}
+
+void
+MaiAtkObject::FireStateChangeEvent(uint64_t aState, bool aEnabled)
+{
+    int32_t stateIndex = AtkStateMap::GetStateIndexFor(aState);
     if (stateIndex >= 0) {
         NS_ASSERTION(gAtkStateMap[stateIndex].stateMapEntryType != kNoSuchState,
                      "No such state");
 
         if (gAtkStateMap[stateIndex].atkState != kNone) {
             NS_ASSERTION(gAtkStateMap[stateIndex].stateMapEntryType != kNoStateChange,
                          "State changes should not fired for this state");
 
             if (gAtkStateMap[stateIndex].stateMapEntryType == kMapOpposite)
-                isEnabled = !isEnabled;
+                aEnabled = !aEnabled;
 
             // Fire state change for first state if there is one to map
-            atk_object_notify_state_change(aObject,
+            atk_object_notify_state_change(&parent,
                                            gAtkStateMap[stateIndex].atkState,
-                                           isEnabled);
+                                           aEnabled);
         }
     }
+}
 
-    return NS_OK;
+void
+a11y::ProxyTextChangeEvent(ProxyAccessible* aTarget, const nsString& aStr,
+                           int32_t aStart, uint32_t aLen, bool aIsInsert,
+                           bool aFromUser)
+{
+  MaiAtkObject* atkObj = MAI_ATK_OBJECT(GetWrapperFor(aTarget));
+  atkObj->FireTextChangeEvent(aStr, aStart, aLen, aIsInsert, aFromUser);
 }
 
-nsresult
-AccessibleWrap::FireAtkTextChangedEvent(AccEvent* aEvent,
-                                        AtkObject* aObject)
-{
-    AccTextChangeEvent* event = downcast_accEvent(aEvent);
-    NS_ENSURE_TRUE(event, NS_ERROR_FAILURE);
+#define OLD_TEXT_INSERTED "text_changed::insert"
+#define OLD_TEXT_REMOVED "text_changed::delete"
+static const char* oldTextChangeStrings[2][2] = {
+  { OLD_TEXT_REMOVED NON_USER_EVENT, OLD_TEXT_INSERTED NON_USER_EVENT },
+  { OLD_TEXT_REMOVED, OLD_TEXT_INSERTED }
+};
 
-    int32_t start = event->GetStartOffset();
-    uint32_t length = event->GetLength();
-    bool isInserted = event->IsTextInserted();
-    bool isFromUserInput = aEvent->IsFromUserInput();
-    char* signal_name = nullptr;
+#define TEXT_INSERTED "text-insert"
+#define TEXT_REMOVED "text-remove"
+#define NON_USER_DETAIL "::system"
+static const char* textChangedStrings[2][2] = {
+  { TEXT_REMOVED NON_USER_DETAIL, TEXT_INSERTED NON_USER_DETAIL },
+  { TEXT_REMOVED, TEXT_INSERTED}
+};
 
+void
+MaiAtkObject::FireTextChangeEvent(const nsString& aStr, int32_t aStart,
+                                  uint32_t aLen, bool aIsInsert,
+                                  bool aFromUser)
+{
   if (gAvailableAtkSignals == eUnknown)
     gAvailableAtkSignals =
-      g_signal_lookup("text-insert", G_OBJECT_TYPE(aObject)) ?
+      g_signal_lookup("text-insert", G_OBJECT_TYPE(this)) ?
         eHaveNewAtkTextSignals : eNoNewAtkSignals;
 
   if (gAvailableAtkSignals == eNoNewAtkSignals) {
     // XXX remove this code and the gHaveNewTextSignals check when we can
     // stop supporting old atk since it doesn't really work anyway
     // see bug 619002
-    signal_name = g_strconcat(isInserted ? "text_changed::insert" :
-                              "text_changed::delete",
-                              isFromUserInput ? "" : kNonUserInputEvent, nullptr);
-    g_signal_emit_by_name(aObject, signal_name, start, length);
+    const char* signal_name =
+      oldTextChangeStrings[aFromUser][aIsInsert];
+    g_signal_emit_by_name(this, signal_name, aStart, aLen);
   } else {
-    nsAutoString text;
-    event->GetModifiedText(text);
-    signal_name = g_strconcat(isInserted ? "text-insert" : "text-remove",
-                              isFromUserInput ? "" : "::system", nullptr);
-    g_signal_emit_by_name(aObject, signal_name, start, length,
-                          NS_ConvertUTF16toUTF8(text).get());
+    const char* signal_name =
+      textChangedStrings[aFromUser][aIsInsert];
+    g_signal_emit_by_name(this, signal_name, aStart, aLen,
+                          NS_ConvertUTF16toUTF8(aStr).get());
   }
+}
 
-  g_free(signal_name);
-  return NS_OK;
-}
+#define ADD_EVENT "children_changed::add"
+#define HIDE_EVENT "children_changed::remove"
+
+static const char *kMutationStrings[2][2] = {
+  { HIDE_EVENT NON_USER_EVENT, ADD_EVENT NON_USER_EVENT },
+  { HIDE_EVENT, ADD_EVENT },
+};
 
 nsresult
 AccessibleWrap::FireAtkShowHideEvent(AccEvent* aEvent,
                                      AtkObject* aObject, bool aIsAdded)
 {
     int32_t indexInParent = getIndexInParentCB(aObject);
     AtkObject *parentObject = getParentCB(aObject);
     NS_ENSURE_STATE(parentObject);
 
     bool isFromUserInput = aEvent->IsFromUserInput();
-    char *signal_name = g_strconcat(aIsAdded ? "children_changed::add" :  "children_changed::remove",
-                                    isFromUserInput ? "" : kNonUserInputEvent, nullptr);
+    const char *signal_name = kMutationStrings[isFromUserInput][aIsAdded];
     g_signal_emit_by_name(parentObject, signal_name, indexInParent, aObject, nullptr);
-    g_free(signal_name);
 
     return NS_OK;
 }
+
+// static
+void
+AccessibleWrap::GetKeyBinding(Accessible* aAccessible, nsAString& aResult)
+{
+  // Return all key bindings including access key and keyboard shortcut.
+
+  // Get access key.
+  nsAutoString keyBindingsStr;
+  KeyBinding keyBinding = aAccessible->AccessKey();
+  if (!keyBinding.IsEmpty()) {
+    keyBinding.AppendToString(keyBindingsStr, KeyBinding::eAtkFormat);
+
+    Accessible* parent = aAccessible->Parent();
+    roles::Role role = parent ? parent->Role() : roles::NOTHING;
+    if (role == roles::PARENT_MENUITEM || role == roles::MENUITEM ||
+        role == roles::RADIO_MENU_ITEM || role == roles::CHECK_MENU_ITEM) {
+      // It is submenu, expose keyboard shortcuts from menu hierarchy like
+      // "s;<Alt>f:s"
+      nsAutoString keysInHierarchyStr = keyBindingsStr;
+      do {
+        KeyBinding parentKeyBinding = parent->AccessKey();
+        if (!parentKeyBinding.IsEmpty()) {
+          nsAutoString str;
+          parentKeyBinding.ToString(str, KeyBinding::eAtkFormat);
+          str.Append(':');
+
+          keysInHierarchyStr.Insert(str, 0);
+        }
+      } while ((parent = parent->Parent()) && parent->Role() != roles::MENUBAR);
+
+      keyBindingsStr.Append(';');
+      keyBindingsStr.Append(keysInHierarchyStr);
+    }
+  } else {
+    // No access key, add ';' to point this.
+    keyBindingsStr.Append(';');
+  }
+
+  // Get keyboard shortcut.
+  keyBindingsStr.Append(';');
+  keyBinding = aAccessible->KeyboardShortcut();
+  if (!keyBinding.IsEmpty()) {
+    keyBinding.AppendToString(keyBindingsStr, KeyBinding::eAtkFormat);
+  }
+  aResult = keyBindingsStr;
+}
+
+// static
+Accessible*
+AccessibleWrap::GetColumnHeader(TableAccessible* aAccessible, int32_t aColIdx)
+{
+  if (!aAccessible) {
+    return nullptr;
+  }
+
+  Accessible* cell = aAccessible->CellAt(0, aColIdx);
+  if (!cell) {
+    return nullptr;
+  }
+
+  // If the cell at the first row is column header then assume it is column
+  // header for all rows,
+  if (cell->Role() == roles::COLUMNHEADER) {
+    return cell;
+  }
+
+  // otherwise get column header for the data cell at the first row.
+  TableCellAccessible* tableCell = cell->AsTableCell();
+  if (!tableCell) {
+    return nullptr;
+  }
+
+  AutoTArray<Accessible*, 10> headerCells;
+  tableCell->ColHeaderCells(&headerCells);
+  if (headerCells.IsEmpty()) {
+    return nullptr;
+  }
+
+  return headerCells[0];
+}
+
+// static
+Accessible*
+AccessibleWrap::GetRowHeader(TableAccessible* aAccessible, int32_t aRowIdx)
+{
+  if (!aAccessible) {
+    return nullptr;
+  }
+
+  Accessible* cell = aAccessible->CellAt(aRowIdx, 0);
+  if (!cell) {
+    return nullptr;
+  }
+
+  // If the cell at the first column is row header then assume it is row
+  // header for all columns,
+  if (cell->Role() == roles::ROWHEADER) {
+    return cell;
+  }
+
+  // otherwise get row header for the data cell at the first column.
+  TableCellAccessible* tableCell = cell->AsTableCell();
+  if (!tableCell) {
+    return nullptr;
+  }
+
+  AutoTArray<Accessible*, 10> headerCells;
+  tableCell->RowHeaderCells(&headerCells);
+  if (headerCells.IsEmpty()) {
+    return nullptr;
+  }
+
+  return headerCells[0];
+}
--- a/accessible/atk/AccessibleWrap.h
+++ b/accessible/atk/AccessibleWrap.h
@@ -47,60 +47,48 @@ class MaiHyperlink;
  */
 class AccessibleWrap : public Accessible
 {
 public:
   AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc);
   virtual ~AccessibleWrap();
   void ShutdownAtkObject();
 
-  virtual void Shutdown();
+  virtual void Shutdown() override;
 
   // return the atk object for this AccessibleWrap
-  virtual void GetNativeInterface(void** aOutAccessible) MOZ_OVERRIDE;
-  virtual nsresult HandleAccEvent(AccEvent* aEvent);
+  virtual void GetNativeInterface(void** aOutAccessible) override;
+  virtual nsresult HandleAccEvent(AccEvent* aEvent) override;
 
   AtkObject * GetAtkObject(void);
   static AtkObject* GetAtkObject(Accessible* aAccessible);
 
   bool IsValidObject();
 
-  // get/set the MaiHyperlink object for this AccessibleWrap
-  MaiHyperlink* GetMaiHyperlink(bool aCreate = true);
-  void SetMaiHyperlink(MaiHyperlink* aMaiHyperlink);
-
   static const char * ReturnString(nsAString &aString) {
     static nsCString returnedString;
     returnedString = NS_ConvertUTF16toUTF8(aString);
     return returnedString.get();
   }
 
+  static void GetKeyBinding(Accessible* aAccessible, nsAString& aResult);
+
+  static Accessible* GetColumnHeader(TableAccessible* aAccessible,
+                                     int32_t aColIdx);
+  static Accessible* GetRowHeader(TableAccessible* aAccessible,
+                                  int32_t aRowIdx);
 protected:
 
   nsresult FireAtkStateChangeEvent(AccEvent* aEvent, AtkObject *aObject);
   nsresult FireAtkTextChangedEvent(AccEvent* aEvent, AtkObject *aObject);
   nsresult FireAtkShowHideEvent(AccEvent* aEvent, AtkObject *aObject,
                                 bool aIsAdded);
 
   AtkObject *mAtkObject;
 
 private:
-
-  /*
-   * do we have text-remove and text-insert signals if not we need to use
-   * text-changed see AccessibleWrap::FireAtkTextChangedEvent() and
-   * bug 619002
-   */
-  enum EAvailableAtkSignals {
-    eUnknown,
-    eHaveNewAtkTextSignals,
-    eNoNewAtkSignals
-  };
-
-  static EAvailableAtkSignals gAvailableAtkSignals;
-
   uint16_t CreateMaiInterfaces();
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif /* __NS_ACCESSIBLE_WRAP_H__ */
--- a/accessible/atk/ApplicationAccessibleWrap.h
+++ b/accessible/atk/ApplicationAccessibleWrap.h
@@ -14,22 +14,22 @@ namespace a11y {
 
 class ApplicationAccessibleWrap: public ApplicationAccessible
 {
 public:
   ApplicationAccessibleWrap();
   virtual ~ApplicationAccessibleWrap();
 
   // Accessible
-  virtual mozilla::a11y::ENameValueFlag Name(nsString& aName);
-  virtual bool InsertChildAt(uint32_t aIdx, Accessible* aChild) MOZ_OVERRIDE;
-  virtual bool RemoveChild(Accessible* aChild);
+  virtual mozilla::a11y::ENameValueFlag Name(nsString& aName) override;
+  virtual bool InsertChildAt(uint32_t aIdx, Accessible* aChild) override;
+  virtual bool RemoveChild(Accessible* aChild) override;
 
   /**
    * Return the atk object for app root accessible.
    */
-  virtual void GetNativeInterface(void** aOutAccessible) MOZ_OVERRIDE;
+  virtual void GetNativeInterface(void** aOutAccessible) override;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif   /* __NS_APP_ROOT_ACCESSIBLE_H__ */
--- a/accessible/atk/AtkSocketAccessible.cpp
+++ b/accessible/atk/AtkSocketAccessible.cpp
@@ -16,45 +16,16 @@ using namespace mozilla::a11y;
 AtkSocketEmbedType AtkSocketAccessible::g_atk_socket_embed = nullptr;
 GType AtkSocketAccessible::g_atk_socket_type = G_TYPE_INVALID;
 const char* AtkSocketAccessible::sATKSocketEmbedSymbol = "atk_socket_embed";
 const char* AtkSocketAccessible::sATKSocketGetTypeSymbol = "atk_socket_get_type";
 
 bool AtkSocketAccessible::gCanEmbed = FALSE;
 
 extern "C" void mai_atk_component_iface_init(AtkComponentIface* aIface);
-extern "C" GType mai_atk_socket_get_type(void);
-
-/* MaiAtkSocket */
-
-#define MAI_TYPE_ATK_SOCKET              (mai_atk_socket_get_type ())
-#define MAI_ATK_SOCKET(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj),\
-                                          MAI_TYPE_ATK_SOCKET, MaiAtkSocket))
-#define MAI_IS_ATK_SOCKET(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\
-                                          MAI_TYPE_ATK_SOCKET))
-#define MAI_ATK_SOCKET_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass),\
-                                          MAI_TYPE_ATK_SOCKET,\
-                                          MaiAtkSocketClass))
-#define MAI_IS_ATK_SOCKET_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass),\
-                                          MAI_TYPE_ATK_SOCKET))
-#define MAI_ATK_SOCKET_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj),\
-                                          MAI_TYPE_ATK_SOCKET,\
-                                          MaiAtkSocketClass))
-
-typedef struct _MaiAtkSocket
-{
-  AtkSocket parent;
-
-  AccessibleWrap* accWrap;
-} MaiAtkSocket;
-
-typedef struct _MaiAtkSocketClass
-{
-  AtkSocketClass parent_class;
-} MaiAtkSocketClass;
 
 G_DEFINE_TYPE_EXTENDED(MaiAtkSocket, mai_atk_socket,
                        AtkSocketAccessible::g_atk_socket_type, 0,
                        G_IMPLEMENT_INTERFACE(ATK_TYPE_COMPONENT,
                                              mai_atk_component_iface_init))
 
 void
 mai_atk_socket_class_init(MaiAtkSocketClass* aAcc)
@@ -81,30 +52,30 @@ mai_atk_socket_new(AccessibleWrap* aAccW
 
 extern "C" {
 static AtkObject*
 RefAccessibleAtPoint(AtkComponent* aComponent, gint aX, gint aY,
                      AtkCoordType aCoordType)
 {
   NS_ENSURE_TRUE(MAI_IS_ATK_SOCKET(aComponent), nullptr);
 
-  return refAccessibleAtPointHelper(MAI_ATK_SOCKET(aComponent)->accWrap,
+  return refAccessibleAtPointHelper(ATK_OBJECT(MAI_ATK_SOCKET(aComponent)),
                                     aX, aY, aCoordType);
 }
 
 static void
 GetExtents(AtkComponent* aComponent, gint* aX, gint* aY, gint* aWidth,
            gint* aHeight, AtkCoordType aCoordType)
 {
   *aX = *aY = *aWidth = *aHeight = 0;
 
   if (!MAI_IS_ATK_SOCKET(aComponent))
     return;
 
-  getExtentsHelper(MAI_ATK_SOCKET(aComponent)->accWrap,
+  getExtentsHelper(ATK_OBJECT(MAI_ATK_SOCKET(aComponent)),
                    aX, aY, aWidth, aHeight, aCoordType);
 }
 }
 
 void
 mai_atk_component_iface_init(AtkComponentIface* aIface)
 {
   NS_ASSERTION(aIface, "Invalid Interface");
--- a/accessible/atk/AtkSocketAccessible.h
+++ b/accessible/atk/AtkSocketAccessible.h
@@ -40,17 +40,17 @@ public:
    * True if the current Atk version supports AtkSocket and it was correctly
    * loaded.
    */
   static bool gCanEmbed;
 
   AtkSocketAccessible(nsIContent* aContent, DocAccessible* aDoc,
                       const nsCString& aPlugId);
 
-  virtual void Shutdown();
+  virtual void Shutdown() override;
 
-  virtual void GetNativeInterface(void** aOutAccessible) MOZ_OVERRIDE;
+  virtual void GetNativeInterface(void** aOutAccessible) override;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/atk/DocAccessibleWrap.cpp
+++ b/accessible/atk/DocAccessibleWrap.cpp
@@ -9,18 +9,17 @@
 
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // DocAccessibleWrap
 ////////////////////////////////////////////////////////////////////////////////
 
 DocAccessibleWrap::
-  DocAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
-                    nsIPresShell* aPresShell) :
-  DocAccessible(aDocument, aRootContent, aPresShell), mActivated(false)
+  DocAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell) :
+  DocAccessible(aDocument, aPresShell), mActivated(false)
 {
 }
 
 DocAccessibleWrap::~DocAccessibleWrap()
 {
 }
 
--- a/accessible/atk/DocAccessibleWrap.h
+++ b/accessible/atk/DocAccessibleWrap.h
@@ -14,18 +14,17 @@
 #include "DocAccessible.h"
 
 namespace mozilla {
 namespace a11y {
 
 class DocAccessibleWrap : public DocAccessible
 {
 public:
-  DocAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
-                    nsIPresShell* aPresShell);
+  DocAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell);
   virtual ~DocAccessibleWrap();
 
   bool mActivated;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
--- a/accessible/atk/InterfaceInitFuncs.h
+++ b/accessible/atk/InterfaceInitFuncs.h
@@ -12,18 +12,16 @@
 namespace mozilla {
 namespace a11y {
 
 class AccessibleWrap;
 
 } // namespace a11y
 } // namespace mozilla
 
-struct MaiUtilClass;
-
 extern "C" {
 void actionInterfaceInitCB(AtkActionIface* aIface);
 void componentInterfaceInitCB(AtkComponentIface* aIface);
 void documentInterfaceInitCB(AtkDocumentIface *aIface);
 void editableTextInterfaceInitCB(AtkEditableTextIface* aIface);
 void hyperlinkImplInterfaceInitCB(AtkHyperlinkImplIface *aIface);
 void hypertextInterfaceInitCB(AtkHypertextIface* aIface);
 void imageInterfaceInitCB(AtkImageIface* aIface);
@@ -31,15 +29,15 @@ void selectionInterfaceInitCB(AtkSelecti
 void tableInterfaceInitCB(AtkTableIface *aIface);
 void textInterfaceInitCB(AtkTextIface* aIface);
 void valueInterfaceInitCB(AtkValueIface *aIface);
 }
 
 /**
  * XXX these should live in a file of utils for atk.
  */
-AtkObject* refAccessibleAtPointHelper(mozilla::a11y::AccessibleWrap* aAccWrap,
+AtkObject* refAccessibleAtPointHelper(AtkObject* aAtkObj,
                                       gint aX, gint aY, AtkCoordType aCoordType);
-void getExtentsHelper(mozilla::a11y::AccessibleWrap* aAccWrap,
+void getExtentsHelper(AtkObject* aAtkObj,
                       gint* aX, gint* aY, gint* aWidth, gint* aHeight,
                       AtkCoordType aCoordType);
 
 #endif // ATK_INTERFACE_INIT_FUNCS_H_
--- a/accessible/atk/Platform.cpp
+++ b/accessible/atk/Platform.cpp
@@ -14,16 +14,20 @@
 #include "prenv.h"
 #include "prlink.h"
 
 #ifdef MOZ_ENABLE_DBUS
 #include <dbus/dbus.h>
 #endif
 #include <gtk/gtk.h>
 
+#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;
 
 extern "C" {
 typedef GType (* AtkGetTypeType) (void);
 typedef void (*GnomeAccessibilityInit) (void);
@@ -58,21 +62,23 @@ static GnomeAccessibilityModule sAtkBrid
     "libatk-bridge.a(libatk-bridge.so.0)", nullptr,
 #else
     "libatk-bridge.so", nullptr,
 #endif
     "gnome_accessibility_module_init", nullptr,
     "gnome_accessibility_module_shutdown", nullptr
 };
 
+#if (MOZ_WIDGET_GTK == 2)
 static GnomeAccessibilityModule sGail = {
     "libgail.so", nullptr,
     "gnome_accessibility_module_init", nullptr,
     "gnome_accessibility_module_shutdown", nullptr
 };
+#endif
 
 static nsresult
 LoadGtkModule(GnomeAccessibilityModule& aModule)
 {
     NS_ENSURE_ARG(aModule.libName);
 
     if (!(aModule.lib = PR_LoadLibrary(aModule.libName))) {
         //try to load the module with "gtk-2.0/modules" appended
@@ -89,17 +95,21 @@ LoadGtkModule(GnomeAccessibilityModule& 
         int16_t subLen = 0;
         while (loc2 >= 0) {
             loc2 = libPath.FindChar(':', loc1);
             if (loc2 < 0)
                 subLen = libPath.Length() - loc1;
             else
                 subLen = loc2 - loc1;
             nsAutoCString sub(Substring(libPath, loc1, subLen));
+#if (MOZ_WIDGET_GTK == 2)
             sub.AppendLiteral("/gtk-2.0/modules/");
+#else
+            sub.AppendLiteral("/gtk-3.0/modules/");
+#endif
             sub.Append(aModule.libName);
             aModule.lib = PR_LoadLibrary(sub.get());
             if (aModule.lib)
                 break;
 
             loc1 = loc2+1;
         }
         if (!aModule.lib)
@@ -153,29 +163,38 @@ a11y::PlatformInit()
     if (version) {
       char* endPtr = nullptr;
       atkMajorVersion = strtol(version, &endPtr, 10);
       if (*endPtr == '.')
         atkMinorVersion = 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)();
+#endif
 
   // Initialize the MAI Utility class, it will overwrite gail_util.
   g_type_class_unref(g_type_class_ref(mai_util_get_type()));
 
   // Init atk-bridge now
   PR_SetEnv("NO_AT_BRIDGE=0");
-  rv = LoadGtkModule(sAtkBridge);
-  if (NS_SUCCEEDED(rv)) {
-    (*sAtkBridge.init)();
+#if (MOZ_WIDGET_GTK == 3)
+  if (atk_bridge_adaptor_init) {
+    atk_bridge_adaptor_init(nullptr, nullptr);
+  } else
+#endif
+  {
+    nsresult rv = LoadGtkModule(sAtkBridge);
+    if (NS_SUCCEEDED(rv)) {
+      (*sAtkBridge.init)();
+    }
   }
 
   if (!sToplevel_event_hook_added) {
     sToplevel_event_hook_added = true;
     sToplevel_show_hook =
       g_signal_add_emission_hook(g_signal_lookup("show", GTK_TYPE_WINDOW),
                                  0, toplevel_event_watcher,
                                  reinterpret_cast<gpointer>(nsIAccessibleEvent::EVENT_SHOW),
@@ -204,27 +223,29 @@ a11y::PlatformShutdown()
         // an exit function registered will take care of it
         // if (sAtkBridge.shutdown)
         //     (*sAtkBridge.shutdown)();
         // PR_UnloadLibrary(sAtkBridge.lib);
         sAtkBridge.lib = nullptr;
         sAtkBridge.init = nullptr;
         sAtkBridge.shutdown = nullptr;
     }
+#if (MOZ_WIDGET_GTK == 2)
     if (sGail.lib) {
         // Do not shutdown gail because
         // 1) Maybe it's not init-ed by us. e.g. GtkEmbed
         // 2) We need it to avoid assert in spi_atk_tidy_windows
         // if (sGail.shutdown)
         //   (*sGail.shutdown)();
         // PR_UnloadLibrary(sGail.lib);
         sGail.lib = nullptr;
         sGail.init = nullptr;
         sGail.shutdown = nullptr;
     }
+#endif
     // if (sATKLib) {
     //     PR_UnloadLibrary(sATKLib);
     //     sATKLib = nullptr;
     // }
 }
 
   static const char sAccEnv [] = "GNOME_ACCESSIBILITY";
 #ifdef MOZ_ENABLE_DBUS
@@ -335,18 +356,17 @@ dbus_done:
   if (reply)
     dbus_message_unref(reply);
 
   if (dbusSuccess)
     return sShouldEnable;
 #endif
 
   //check gconf-2 setting
-static const char sGconfAccessibilityKey[] =
-    "/desktop/gnome/interface/accessibility";
+#define GCONF_A11Y_KEY "/desktop/gnome/interface/accessibility"
   nsresult rv = NS_OK;
   nsCOMPtr<nsIGConfService> gconf =
     do_GetService(NS_GCONFSERVICE_CONTRACTID, &rv);
   if (NS_SUCCEEDED(rv) && gconf)
-    gconf->GetBool(NS_LITERAL_CSTRING(sGconfAccessibilityKey), &sShouldEnable);
+    gconf->GetBool(NS_LITERAL_CSTRING(GCONF_A11Y_KEY), &sShouldEnable);
 
   return sShouldEnable;
 }
--- a/accessible/atk/RootAccessibleWrap.h
+++ b/accessible/atk/RootAccessibleWrap.h
@@ -15,17 +15,17 @@ namespace a11y {
 
 typedef RootAccessible RootAccessibleWrap;
 
 /* GtkWindowAccessible is the accessible class for gtk+ native window.
  * The instance of GtkWindowAccessible is a child of MaiAppRoot instance.
  * It is added into root when the toplevel window is created, and removed
  * from root when the toplevel window is destroyed.
  */
-class GtkWindowAccessible MOZ_FINAL : public DummyAccessible
+class GtkWindowAccessible final : public DummyAccessible
 {
 public:
   explicit GtkWindowAccessible(AtkObject* aAccessible);
   virtual ~GtkWindowAccessible();
 };
 
 } // namespace a11y
 } // namespace mozilla
--- a/accessible/atk/moz.build
+++ b/accessible/atk/moz.build
@@ -46,8 +46,13 @@ FINAL_LIBRARY = 'xul'
 if CONFIG['MOZ_ENABLE_GTK']:
     CFLAGS += CONFIG['TK_CFLAGS']
     CXXFLAGS += CONFIG['TK_CFLAGS']
 
 if CONFIG['MOZ_ENABLE_DBUS']:
     CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
 
 include('/ipc/chromium/chromium-config.mozbuild')
+
+if CONFIG['CLANG_CXX'] or CONFIG['GNU_CXX']:
+    # Used in G_DEFINE_TYPE_EXTENDED macro, probably fixed in newer glib /
+    # gobject headers. See bug 1243331 comment 3.
+    CXXFLAGS += ['-Wno-unused-local-typedefs']
--- a/accessible/atk/nsMai.h
+++ b/accessible/atk/nsMai.h
@@ -6,16 +6,17 @@
 
 #ifndef __NS_MAI_H__
 #define __NS_MAI_H__
 
 #include <atk/atk.h>
 #include <glib.h>
 #include <glib-object.h>
 
+#include "AccessibleOrProxy.h"
 #include "AccessibleWrap.h"
 
 namespace mozilla {
 namespace a11y {
 class ProxyAccessible;
 }
 }
 
@@ -29,26 +30,109 @@ class ProxyAccessible;
                                          MAI_TYPE_ATK_OBJECT))
 #define IS_MAI_OBJECT_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), \
                                          MAI_TYPE_ATK_OBJECT))
 #define MAI_ATK_OBJECT_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), \
                                          MAI_TYPE_ATK_OBJECT, \
                                          MaiAtkObjectClass))
 GType mai_atk_object_get_type(void);
 GType mai_util_get_type();
+extern "C" GType mai_atk_socket_get_type(void);
+
+/* MaiAtkSocket */
+
+#define MAI_TYPE_ATK_SOCKET              (mai_atk_socket_get_type ())
+#define MAI_ATK_SOCKET(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj),\
+                                          MAI_TYPE_ATK_SOCKET, MaiAtkSocket))
+#define MAI_IS_ATK_SOCKET(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\
+                                          MAI_TYPE_ATK_SOCKET))
+#define MAI_ATK_SOCKET_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass),\
+                                          MAI_TYPE_ATK_SOCKET,\
+                                          MaiAtkSocketClass))
+#define MAI_IS_ATK_SOCKET_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass),\
+                                          MAI_TYPE_ATK_SOCKET))
+#define MAI_ATK_SOCKET_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj),\
+                                          MAI_TYPE_ATK_SOCKET,\
+                                          MaiAtkSocketClass))
+
+typedef struct _MaiAtkSocket
+{
+  AtkSocket parent;
+
+  mozilla::a11y::AccessibleWrap* accWrap;
+} MaiAtkSocket;
+
+typedef struct _MaiAtkSocketClass
+{
+  AtkSocketClass parent_class;
+} MaiAtkSocketClass;
+
 mozilla::a11y::AccessibleWrap* GetAccessibleWrap(AtkObject* aAtkObj);
 mozilla::a11y::ProxyAccessible* GetProxy(AtkObject* aAtkObj);
+mozilla::a11y::AccessibleOrProxy GetInternalObj(AtkObject* aObj);
 AtkObject* GetWrapperFor(mozilla::a11y::ProxyAccessible* aProxy);
 
 extern int atkMajorVersion, atkMinorVersion;
 
 /**
  * Return true if the loaded version of libatk-1.0.so is at least
  * aMajor.aMinor.0.
  */
 static inline bool
 IsAtkVersionAtLeast(int aMajor, int aMinor)
 {
   return aMajor < atkMajorVersion ||
          (aMajor == atkMajorVersion && aMinor <= atkMinorVersion);
 }
 
+// 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
+ */
+struct MaiAtkObject
+{
+  AtkObject parent;
+  /*
+   * The AccessibleWrap whose properties and features are exported
+   * via this object instance.
+   */
+  mozilla::a11y::AccessibleOrProxy accWrap;
+
+  /*
+   * Get the AtkHyperlink for this atk object.
+   */
+  AtkHyperlink* GetAtkHyperlink();
+
+  /*
+   * Shutdown this AtkObject.
+   */
+  void Shutdown();
+
+  /*
+   * Notify atk of a state change on this AtkObject.
+   */
+  void FireStateChangeEvent(uint64_t aState, bool aEnabled);
+
+  /*
+   * Notify ATK of a text change within this ATK object.
+   */
+  void FireTextChangeEvent(const nsString& aStr, int32_t aStart, uint32_t aLen,
+                           bool aIsInsert, bool aIsFromUser);
+
+private:
+  /*
+   * do we have text-remove and text-insert signals if not we need to use
+   * text-changed see AccessibleWrap::FireAtkTextChangedEvent() and
+   * bug 619002
+   */
+  enum EAvailableAtkSignals {
+    eUnknown,
+    eHaveNewAtkTextSignals,
+    eNoNewAtkSignals
+  };
+
+  static EAvailableAtkSignals gAvailableAtkSignals;
+};
+
 #endif /* __NS_MAI_H__ */
--- a/accessible/atk/nsMaiHyperlink.cpp
+++ b/accessible/atk/nsMaiHyperlink.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 "nsIURI.h"
 #include "nsMaiHyperlink.h"
+#include "mozilla/a11y/ProxyAccessible.h"
 
 using namespace mozilla::a11y;
 
 /* MaiAtkHyperlink */
 
 #define MAI_TYPE_ATK_HYPERLINK      (mai_atk_hyperlink_get_type ())
 #define MAI_ATK_HYPERLINK(obj)      (G_TYPE_CHECK_INSTANCE_CAST ((obj),\
                                      MAI_TYPE_ATK_HYPERLINK, MaiAtkHyperlink))
@@ -56,18 +57,27 @@ static gchar *getUriCB(AtkHyperlink *aLi
 static AtkObject *getObjectCB(AtkHyperlink *aLink, gint aLinkIndex);
 static gint getEndIndexCB(AtkHyperlink *aLink);
 static gint getStartIndexCB(AtkHyperlink *aLink);
 static gboolean isValidCB(AtkHyperlink *aLink);
 static gint getAnchorCountCB(AtkHyperlink *aLink);
 G_END_DECLS
 
 static gpointer parent_class = nullptr;
-static Accessible*
-get_accessible_hyperlink(AtkHyperlink *aHyperlink);
+
+static MaiHyperlink*
+GetMaiHyperlink(AtkHyperlink *aHyperlink)
+{
+    NS_ENSURE_TRUE(MAI_IS_ATK_HYPERLINK(aHyperlink), nullptr);
+    MaiHyperlink * maiHyperlink =
+        MAI_ATK_HYPERLINK(aHyperlink)->maiHyperlink;
+    NS_ENSURE_TRUE(maiHyperlink != nullptr, nullptr);
+    NS_ENSURE_TRUE(maiHyperlink->GetAtkHyperlink() == aHyperlink, nullptr);
+    return maiHyperlink;
+}
 
 GType
 mai_atk_hyperlink_get_type(void)
 {
     static GType type = 0;
 
     if (!type) {
         static const GTypeInfo tinfo = {
@@ -85,69 +95,38 @@ mai_atk_hyperlink_get_type(void)
 
         type = g_type_register_static(ATK_TYPE_HYPERLINK,
                                       "MaiAtkHyperlink",
                                       &tinfo, GTypeFlags(0));
     }
     return type;
 }
 
-MaiHyperlink::MaiHyperlink(Accessible* aHyperLink) :
+MaiHyperlink::MaiHyperlink(AccessibleOrProxy aHyperLink) :
     mHyperlink(aHyperLink),
     mMaiAtkHyperlink(nullptr)
 {
+    mMaiAtkHyperlink =
+        reinterpret_cast<AtkHyperlink *>
+                        (g_object_new(mai_atk_hyperlink_get_type(), nullptr));
+    NS_ASSERTION(mMaiAtkHyperlink, "OUT OF MEMORY");
+    if (!mMaiAtkHyperlink)
+      return;
+
+    MAI_ATK_HYPERLINK(mMaiAtkHyperlink)->maiHyperlink = this;
 }
 
 MaiHyperlink::~MaiHyperlink()
 {
-    if (mMaiAtkHyperlink) {
-        MAI_ATK_HYPERLINK(mMaiAtkHyperlink)->maiHyperlink = nullptr;
-        g_object_unref(mMaiAtkHyperlink);
-    }
+  if (mMaiAtkHyperlink) {
+    MAI_ATK_HYPERLINK(mMaiAtkHyperlink)->maiHyperlink = nullptr;
+    g_object_unref(mMaiAtkHyperlink);
+  }
 }
 
-AtkHyperlink*
-MaiHyperlink::GetAtkHyperlink(void)
-{
-  NS_ENSURE_TRUE(mHyperlink, nullptr);
-
-  if (mMaiAtkHyperlink)
-    return mMaiAtkHyperlink;
-
-  if (!mHyperlink->IsLink())
-    return nullptr;
-
-    mMaiAtkHyperlink =
-        reinterpret_cast<AtkHyperlink *>
-                        (g_object_new(mai_atk_hyperlink_get_type(), nullptr));
-    NS_ASSERTION(mMaiAtkHyperlink, "OUT OF MEMORY");
-    NS_ENSURE_TRUE(mMaiAtkHyperlink, nullptr);
-
-    /* be sure to initialize it with "this" */
-    MaiHyperlink::Initialize(mMaiAtkHyperlink, this);
-
-    return mMaiAtkHyperlink;
-}
-
-/* static */
-
-/* remember to call this static function when a MaiAtkHyperlink
- * is created
- */
-
-nsresult
-MaiHyperlink::Initialize(AtkHyperlink *aObj, MaiHyperlink *aHyperlink)
-{
-    NS_ENSURE_ARG(MAI_IS_ATK_HYPERLINK(aObj));
-    NS_ENSURE_ARG(aHyperlink);
-
-    /* initialize hyperlink */
-    MAI_ATK_HYPERLINK(aObj)->maiHyperlink = aHyperlink;
-    return NS_OK;
-}
 
 /* static functions for ATK callbacks */
 
 void
 classInitCB(AtkHyperlinkClass *aClass)
 {
     GObjectClass *gobject_class = G_OBJECT_CLASS(aClass);
 
@@ -176,84 +155,107 @@ finalizeCB(GObject *aObj)
     /* call parent finalize function */
     if (G_OBJECT_CLASS (parent_class)->finalize)
         G_OBJECT_CLASS (parent_class)->finalize(aObj);
 }
 
 gchar *
 getUriCB(AtkHyperlink *aLink, gint aLinkIndex)
 {
-    Accessible* hyperlink = get_accessible_hyperlink(aLink);
-    NS_ENSURE_TRUE(hyperlink, nullptr);
+  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
+  if (!maiLink)
+    return nullptr;
 
+  nsAutoCString cautoStr;
+  if (Accessible* hyperlink = maiLink->GetAccHyperlink()) {
     nsCOMPtr<nsIURI> uri = hyperlink->AnchorURIAt(aLinkIndex);
     if (!uri)
-        return nullptr;
+      return nullptr;
 
-    nsAutoCString cautoStr;
     nsresult rv = uri->GetSpec(cautoStr);
     NS_ENSURE_SUCCESS(rv, nullptr);
 
     return g_strdup(cautoStr.get());
+  }
+
+  bool valid;
+  maiLink->Proxy()->AnchorURIAt(aLinkIndex, cautoStr, &valid);
+  if (!valid)
+    return nullptr;
+
+  return g_strdup(cautoStr.get());
 }
 
 AtkObject *
 getObjectCB(AtkHyperlink *aLink, gint aLinkIndex)
 {
-    Accessible* hyperlink = get_accessible_hyperlink(aLink);
-    NS_ENSURE_TRUE(hyperlink, nullptr);
+  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
+  if (!maiLink)
+    return nullptr;
 
-    Accessible* anchor = hyperlink->AnchorAt(aLinkIndex);
-    NS_ENSURE_TRUE(anchor, nullptr);
+    if (Accessible* hyperlink = maiLink->GetAccHyperlink()) {
+      Accessible* anchor = hyperlink->AnchorAt(aLinkIndex);
+      NS_ENSURE_TRUE(anchor, nullptr);
 
-    AtkObject* atkObj = AccessibleWrap::GetAtkObject(anchor);
-    //no need to add ref it, because it is "get" not "ref"
-    return atkObj;
+      return AccessibleWrap::GetAtkObject(anchor);
+    }
+
+    ProxyAccessible* anchor = maiLink->Proxy()->AnchorAt(aLinkIndex);
+    return anchor ? GetWrapperFor(anchor) : nullptr;
 }
 
 gint
 getEndIndexCB(AtkHyperlink *aLink)
 {
-    Accessible* hyperlink = get_accessible_hyperlink(aLink);
-    NS_ENSURE_TRUE(hyperlink, -1);
+  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
+  if (!maiLink)
+    return false;
 
+  if (Accessible* hyperlink = maiLink->GetAccHyperlink())
     return static_cast<gint>(hyperlink->EndOffset());
+
+  bool valid = false;
+  uint32_t endIdx = maiLink->Proxy()->EndOffset(&valid);
+  return valid ? static_cast<gint>(endIdx) : -1;
 }
 
 gint
 getStartIndexCB(AtkHyperlink *aLink)
 {
-    Accessible* hyperlink = get_accessible_hyperlink(aLink);
-    NS_ENSURE_TRUE(hyperlink, -1);
+  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
+  if (!maiLink)
+    return -1;
 
+  if (Accessible* hyperlink = maiLink->GetAccHyperlink())
     return static_cast<gint>(hyperlink->StartOffset());
+
+  bool valid = false;
+  uint32_t startIdx = maiLink->Proxy()->StartOffset(&valid);
+  return valid ? static_cast<gint>(startIdx) : -1;
 }
 
 gboolean
 isValidCB(AtkHyperlink *aLink)
 {
-    Accessible* hyperlink = get_accessible_hyperlink(aLink);
-    NS_ENSURE_TRUE(hyperlink, FALSE);
+  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
+  if (!maiLink)
+    return false;
 
+  if (Accessible* hyperlink = maiLink->GetAccHyperlink())
     return static_cast<gboolean>(hyperlink->IsLinkValid());
+
+  return static_cast<gboolean>(maiLink->Proxy()->IsLinkValid());
 }
 
 gint
 getAnchorCountCB(AtkHyperlink *aLink)
 {
-    Accessible* hyperlink = get_accessible_hyperlink(aLink);
-    NS_ENSURE_TRUE(hyperlink, -1);
-
-    return static_cast<gint>(hyperlink->AnchorCount());
-}
+  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
+  if (!maiLink)
+    return -1;
 
-// Check if aHyperlink is a valid MaiHyperlink, and return the
-// HyperLinkAccessible related.
-Accessible*
-get_accessible_hyperlink(AtkHyperlink *aHyperlink)
-{
-    NS_ENSURE_TRUE(MAI_IS_ATK_HYPERLINK(aHyperlink), nullptr);
-    MaiHyperlink * maiHyperlink =
-        MAI_ATK_HYPERLINK(aHyperlink)->maiHyperlink;
-    NS_ENSURE_TRUE(maiHyperlink != nullptr, nullptr);
-    NS_ENSURE_TRUE(maiHyperlink->GetAtkHyperlink() == aHyperlink, nullptr);
-    return maiHyperlink->GetAccHyperlink();
+  if (Accessible* hyperlink = maiLink->GetAccHyperlink())
+    return static_cast<gint>(hyperlink->AnchorCount());
+
+  bool valid = false;
+  uint32_t anchorCount = maiLink->Proxy()->AnchorCount(&valid);
+  return valid ? static_cast<gint>(anchorCount) : -1;
 }
--- a/accessible/atk/nsMaiHyperlink.h
+++ b/accessible/atk/nsMaiHyperlink.h
@@ -18,27 +18,38 @@ namespace a11y {
 
 /*
  * MaiHyperlink is a auxiliary class for MaiInterfaceHyperText.
  */
 
 class MaiHyperlink
 {
 public:
-  explicit MaiHyperlink(Accessible* aHyperLink);
+  explicit MaiHyperlink(AccessibleOrProxy aHyperLink);
   ~MaiHyperlink();
 
 public:
-  AtkHyperlink *GetAtkHyperlink(void);
+  AtkHyperlink* GetAtkHyperlink() const { return mMaiAtkHyperlink; }
   Accessible* GetAccHyperlink()
-    { return mHyperlink && mHyperlink->IsLink() ? mHyperlink : nullptr; }
+    {
+      if (!mHyperlink.IsAccessible())
+        return nullptr;
+
+      Accessible* link = mHyperlink.AsAccessible();
+      if (!link) {
+        return nullptr;
+      }
+
+      NS_ASSERTION(link->IsLink(), "Why isn't it a link!");
+      return link;
+    }
+
+  ProxyAccessible* Proxy() const { return mHyperlink.AsProxy(); }
 
 protected:
-  Accessible* mHyperlink;
+  AccessibleOrProxy mHyperlink;
   AtkHyperlink* mMaiAtkHyperlink;
-public:
-  static nsresult Initialize(AtkHyperlink *aObj, MaiHyperlink *aClass);
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif /* __MAI_HYPERLINK_H__ */
--- a/accessible/atk/nsMaiInterfaceAction.cpp
+++ b/accessible/atk/nsMaiInterfaceAction.cpp
@@ -5,107 +5,90 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "InterfaceInitFuncs.h"
 
 #include "Accessible-inl.h"
 #include "nsMai.h"
 #include "Role.h"
 #include "mozilla/Likely.h"
-
+#include "ProxyAccessible.h"
 #include "nsString.h"
 
 using namespace mozilla::a11y;
 
 extern "C" {
 
 static gboolean
 doActionCB(AtkAction *aAction, gint aActionIndex)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aAction));
-  return accWrap && accWrap->DoAction(aActionIndex);
+  if (accWrap) {
+    return accWrap->DoAction(aActionIndex);
+  }
+
+  ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aAction));
+  return proxy && proxy->DoAction(aActionIndex);
 }
 
 static gint
 getActionCountCB(AtkAction *aAction)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aAction));
-  return accWrap ? accWrap->ActionCount() : 0;
+  if (accWrap) {
+    return accWrap->ActionCount();
+  }
+
+  ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aAction));
+  return proxy ? proxy->ActionCount() : 0;
 }
 
 static const gchar*
 getActionDescriptionCB(AtkAction *aAction, gint aActionIndex)
 {
+  nsAutoString description;
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aAction));
-  if (!accWrap)
+  if (accWrap) {
+    accWrap->ActionDescriptionAt(aActionIndex, description);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aAction))) {
+    proxy->ActionDescriptionAt(aActionIndex, description);
+  } else {
     return nullptr;
+  }
 
-  nsAutoString description;
-  accWrap->ActionDescriptionAt(aActionIndex, description);
   return AccessibleWrap::ReturnString(description);
 }
 
 static const gchar*
 getActionNameCB(AtkAction *aAction, gint aActionIndex)
 {
+  nsAutoString autoStr;
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aAction));
-  if (!accWrap)
+  if (accWrap) {
+    accWrap->ActionNameAt(aActionIndex, autoStr);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aAction))) {
+    proxy->ActionNameAt(aActionIndex, autoStr);
+  } else {
     return nullptr;
+  }
 
-  nsAutoString autoStr;
-  accWrap->ActionNameAt(aActionIndex, autoStr);
   return AccessibleWrap::ReturnString(autoStr);
 }
 
 static const gchar*
 getKeyBindingCB(AtkAction *aAction, gint aActionIndex)
 {
+  nsAutoString keyBindingsStr;
   AccessibleWrap* acc = GetAccessibleWrap(ATK_OBJECT(aAction));
-  if (!acc)
+  if (acc) {
+    AccessibleWrap::GetKeyBinding(acc, keyBindingsStr);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aAction))) {
+    proxy->AtkKeyBinding(keyBindingsStr);
+  } else {
     return nullptr;
-
-  // Return all key bindings including access key and keyboard shortcut.
-  nsAutoString keyBindingsStr;
-
-  // Get access key.
-  KeyBinding keyBinding = acc->AccessKey();
-  if (!keyBinding.IsEmpty()) {
-    keyBinding.AppendToString(keyBindingsStr, KeyBinding::eAtkFormat);
-
-    Accessible* parent = acc->Parent();
-    roles::Role role = parent ? parent->Role() : roles::NOTHING;
-    if (role == roles::PARENT_MENUITEM || role == roles::MENUITEM ||
-        role == roles::RADIO_MENU_ITEM || role == roles::CHECK_MENU_ITEM) {
-      // It is submenu, expose keyboard shortcuts from menu hierarchy like
-      // "s;<Alt>f:s"
-      nsAutoString keysInHierarchyStr = keyBindingsStr;
-      do {
-        KeyBinding parentKeyBinding = parent->AccessKey();
-        if (!parentKeyBinding.IsEmpty()) {
-          nsAutoString str;
-          parentKeyBinding.ToString(str, KeyBinding::eAtkFormat);
-          str.Append(':');
-
-          keysInHierarchyStr.Insert(str, 0);
-        }
-      } while ((parent = parent->Parent()) && parent->Role() != roles::MENUBAR);
-
-      keyBindingsStr.Append(';');
-      keyBindingsStr.Append(keysInHierarchyStr);
-    }
-  } else {
-    // No access key, add ';' to point this.
-    keyBindingsStr.Append(';');
-  }
-
-  // Get keyboard shortcut.
-  keyBindingsStr.Append(';');
-  keyBinding = acc->KeyboardShortcut();
-  if (!keyBinding.IsEmpty()) {
-    keyBinding.AppendToString(keyBindingsStr, KeyBinding::eAtkFormat);
   }
 
   return AccessibleWrap::ReturnString(keyBindingsStr);
 }
 }
 
 void
 actionInterfaceInitCB(AtkActionIface* aIface)
--- a/accessible/atk/nsMaiInterfaceComponent.cpp
+++ b/accessible/atk/nsMaiInterfaceComponent.cpp
@@ -6,100 +6,137 @@
 
 #include "InterfaceInitFuncs.h"
 
 #include "AccessibleWrap.h"
 #include "nsAccUtils.h"
 #include "nsCoreUtils.h"
 #include "nsMai.h"
 #include "mozilla/Likely.h"
+#include "mozilla/a11y/ProxyAccessible.h"
 
 using namespace mozilla::a11y;
 
 extern "C" {
 
 static AtkObject*
 refAccessibleAtPointCB(AtkComponent* aComponent, gint aAccX, gint aAccY,
                        AtkCoordType aCoordType)
 {
-  return refAccessibleAtPointHelper(GetAccessibleWrap(ATK_OBJECT(aComponent)),
+  return refAccessibleAtPointHelper(ATK_OBJECT(aComponent),
                                     aAccX, aAccY, aCoordType);
 }
 
 static void
 getExtentsCB(AtkComponent* aComponent, gint* aX, gint* aY,
              gint* aWidth, gint* aHeight, AtkCoordType aCoordType)
 {
-  getExtentsHelper(GetAccessibleWrap(ATK_OBJECT(aComponent)),
+  getExtentsHelper(ATK_OBJECT(aComponent),
                    aX, aY, aWidth, aHeight, aCoordType);
 }
 
 static gboolean
 grabFocusCB(AtkComponent* aComponent)
 {
-  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aComponent));
-  if (!accWrap)
-    return FALSE;
+  AtkObject* atkObject = ATK_OBJECT(aComponent);
+  AccessibleWrap* accWrap = GetAccessibleWrap(atkObject);
+  if (accWrap) {
+    accWrap->TakeFocus();
+    return TRUE;
+  }
 
-  accWrap->TakeFocus();
-  return TRUE;
+  ProxyAccessible* proxy = GetProxy(atkObject);
+  if (proxy) {
+    proxy->TakeFocus();
+    return TRUE;
+  }
+
+  return FALSE;
 }
 }
 
 AtkObject*
-refAccessibleAtPointHelper(AccessibleWrap* aAccWrap, gint aX, gint aY,
+refAccessibleAtPointHelper(AtkObject* aAtkObj, gint aX, gint aY,
                            AtkCoordType aCoordType)
 {
-  if (!aAccWrap || aAccWrap->IsDefunct() || nsAccUtils::MustPrune(aAccWrap))
-    return nullptr;
+  AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
+  if (accWrap) {
+    if (accWrap->IsDefunct() || nsAccUtils::MustPrune(accWrap)) {
+      return nullptr;
+    }
 
-  // Accessible::ChildAtPoint(x,y) is in screen pixels.
-  if (aCoordType == ATK_XY_WINDOW) {
-    nsIntPoint winCoords =
-      nsCoreUtils::GetScreenCoordsForWindow(aAccWrap->GetNode());
-    aX += winCoords.x;
-    aY += winCoords.y;
+    // Accessible::ChildAtPoint(x,y) is in screen pixels.
+    if (aCoordType == ATK_XY_WINDOW) {
+      nsIntPoint winCoords =
+        nsCoreUtils::GetScreenCoordsForWindow(accWrap->GetNode());
+      aX += winCoords.x;
+      aY += winCoords.y;
+    }
+
+    Accessible* accAtPoint = accWrap->ChildAtPoint(aX, aY,
+                                                   Accessible::eDirectChild);
+    if (!accAtPoint) {
+      return nullptr;
+    }
+
+    AtkObject* atkObj = AccessibleWrap::GetAtkObject(accAtPoint);
+    if (atkObj) {
+      g_object_ref(atkObj);
+    }
+
+    return atkObj;
   }
 
-  Accessible* accAtPoint = aAccWrap->ChildAtPoint(aX, aY,
-                                                  Accessible::eDirectChild);
-  if (!accAtPoint)
-    return nullptr;
+  if (ProxyAccessible* proxy = GetProxy(aAtkObj)) {
+    ProxyAccessible* result =
+      proxy->AccessibleAtPoint(aX, aY, aCoordType == ATK_XY_WINDOW);
+    AtkObject* atkObj = result ? GetWrapperFor(result) : nullptr;
+    if (atkObj) {
+      g_object_ref(atkObj);
+    }
+    return atkObj;
+  }
 
-  AtkObject* atkObj = AccessibleWrap::GetAtkObject(accAtPoint);
-  if (atkObj)
-    g_object_ref(atkObj);
-  return atkObj;
+  return nullptr;
 }
 
 void
-getExtentsHelper(AccessibleWrap* aAccWrap,
+getExtentsHelper(AtkObject* aAtkObj,
                  gint* aX, gint* aY, gint* aWidth, gint* aHeight,
                  AtkCoordType aCoordType)
 {
+  AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
   *aX = *aY = *aWidth = *aHeight = 0;
 
-  if (!aAccWrap || aAccWrap->IsDefunct())
-    return;
+  if (accWrap) {
+    if (accWrap->IsDefunct()) {
+      return;
+    }
+
+    nsIntRect screenRect = accWrap->Bounds();
+    if (screenRect.IsEmpty())
+      return;
 
-  nsIntRect screenRect = aAccWrap->Bounds();
-  if (screenRect.IsEmpty())
+    if (aCoordType == ATK_XY_WINDOW) {
+      nsIntPoint winCoords =
+        nsCoreUtils::GetScreenCoordsForWindow(accWrap->GetNode());
+      screenRect.x -= winCoords.x;
+      screenRect.y -= winCoords.y;
+    }
+
+    *aX = screenRect.x;
+    *aY = screenRect.y;
+    *aWidth = screenRect.width;
+    *aHeight = screenRect.height;
     return;
-
-  if (aCoordType == ATK_XY_WINDOW) {
-    nsIntPoint winCoords =
-      nsCoreUtils::GetScreenCoordsForWindow(aAccWrap->GetNode());
-    screenRect.x -= winCoords.x;
-    screenRect.y -= winCoords.y;
   }
 
-  *aX = screenRect.x;
-  *aY = screenRect.y;
-  *aWidth = screenRect.width;
-  *aHeight = screenRect.height;
+  if (ProxyAccessible* proxy = GetProxy(aAtkObj)) {
+    proxy->Extents(aCoordType == ATK_XY_WINDOW, aX, aY, aWidth, aHeight);
+  }
 }
 
 void
 componentInterfaceInitCB(AtkComponentIface* aIface)
 {
   NS_ASSERTION(aIface, "Invalid Interface");
   if(MOZ_UNLIKELY(!aIface))
     return;
--- a/accessible/atk/nsMaiInterfaceDocument.cpp
+++ b/accessible/atk/nsMaiInterfaceDocument.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "InterfaceInitFuncs.h"
 
 #include "Accessible-inl.h"
 #include "AccessibleWrap.h"
 #include "DocAccessible.h"
 #include "nsMai.h"
+#include "ProxyAccessible.h"
 #include "mozilla/Likely.h"
 
 using namespace mozilla::a11y;
 
 static const char* const kDocTypeName = "W3C-doctype";
 static const char* const kDocUrlName = "DocURL";
 static const char* const kMimeTypeName = "MimeType";
 
@@ -41,22 +42,24 @@ documentInterfaceInitCB(AtkDocumentIface
     aIface->get_document_attributes = getDocumentAttributesCB;
     aIface->get_document_attribute_value = getDocumentAttributeValueCB;
     aIface->get_document_locale = getDocumentLocaleCB;
 }
 
 const gchar *
 getDocumentLocaleCB(AtkDocument *aDocument)
 {
+  nsAutoString locale;
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aDocument));
-  if (!accWrap)
-    return nullptr;
+  if (accWrap) {
+    accWrap->Language(locale);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aDocument))) {
+    proxy->Language(locale);
+  }
 
-  nsAutoString locale;
-  accWrap->Language(locale);
   return locale.IsEmpty() ? nullptr : AccessibleWrap::ReturnString(locale);
 }
 
 static inline GSList *
 prependToList(GSList *aList, const char *const aName, const nsAutoString &aValue)
 {
   if (aValue.IsEmpty())
     return aList;
@@ -66,52 +69,82 @@ prependToList(GSList *aList, const char 
     atkAttr->name = g_strdup(aName);
     atkAttr->value = g_strdup(NS_ConvertUTF16toUTF8(aValue).get());
     return g_slist_prepend(aList, atkAttr);
 }
 
 AtkAttributeSet *
 getDocumentAttributesCB(AtkDocument *aDocument)
 {
+  nsAutoString url;
+  nsAutoString w3cDocType;
+  nsAutoString mimeType;
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aDocument));
-  if (!accWrap || !accWrap->IsDoc())
+  if (accWrap) {
+    if (!accWrap->IsDoc()) {
+      return nullptr;
+    }
+
+    DocAccessible* document = accWrap->AsDoc();
+    document->URL(url);
+    document->DocType(w3cDocType);
+    document->MimeType(mimeType);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aDocument))) {
+    proxy->URLDocTypeMimeType(url, w3cDocType, mimeType);
+  } else {
     return nullptr;
+  }
 
   // according to atkobject.h, AtkAttributeSet is a GSList
   GSList* attributes = nullptr;
-  DocAccessible* document = accWrap->AsDoc();
-  nsAutoString aURL;
-  document->URL(aURL);
-  attributes = prependToList(attributes, kDocUrlName, aURL);
-
-  nsAutoString aW3CDocType;
-  document->DocType(aW3CDocType);
-  attributes = prependToList(attributes, kDocTypeName, aW3CDocType);
-
-  nsAutoString aMimeType;
-  document->MimeType(aMimeType);
-  attributes = prependToList(attributes, kMimeTypeName, aMimeType);
+  attributes = prependToList(attributes, kDocUrlName, url);
+  attributes = prependToList(attributes, kDocTypeName, w3cDocType);
+  attributes = prependToList(attributes, kMimeTypeName, mimeType);
 
   return attributes;
 }
 
 const gchar *
 getDocumentAttributeValueCB(AtkDocument *aDocument,
                             const gchar *aAttrName)
 {
+  ProxyAccessible* proxy = nullptr;
+  DocAccessible* document = nullptr;
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aDocument));
-  if (!accWrap || !accWrap->IsDoc())
-    return nullptr;
+  if (accWrap) {
+    if (!accWrap->IsDoc()) {
+      return nullptr;
+    }
 
-  DocAccessible* document = accWrap->AsDoc();
+    document = accWrap->AsDoc();
+  } else {
+    proxy = GetProxy(ATK_OBJECT(aDocument));
+    if (!proxy) {
+      return nullptr;
+    }
+  }
+
   nsAutoString attrValue;
-  if (!strcasecmp(aAttrName, kDocTypeName))
-    document->DocType(attrValue);
-  else if (!strcasecmp(aAttrName, kDocUrlName))
-    document->URL(attrValue);
-  else if (!strcasecmp(aAttrName, kMimeTypeName))
-    document->MimeType(attrValue);
-  else
+  if (!strcasecmp(aAttrName, kDocTypeName)) {
+    if (document) {
+      document->DocType(attrValue);
+    } else {
+      proxy->DocType(attrValue);
+    }
+  } else if (!strcasecmp(aAttrName, kDocUrlName)) {
+    if (document) {
+      document->URL(attrValue);
+    } else {
+      proxy->URL(attrValue);
+    }
+  } else if (!strcasecmp(aAttrName, kMimeTypeName)) {
+    if (document) {
+      document->MimeType(attrValue);
+    } else {
+      proxy->MimeType(attrValue);
+    }
+  } else {
     return nullptr;
+  }
 
   return attrValue.IsEmpty() ? nullptr : AccessibleWrap::ReturnString(attrValue);
 }
 }
--- a/accessible/atk/nsMaiInterfaceEditableText.cpp
+++ b/accessible/atk/nsMaiInterfaceEditableText.cpp
@@ -4,108 +4,122 @@
  * 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 "InterfaceInitFuncs.h"
 
 #include "Accessible-inl.h"
 #include "HyperTextAccessible-inl.h"
 #include "nsMai.h"
-
+#include "ProxyAccessible.h"
 #include "nsString.h"
 #include "mozilla/Likely.h"
 
 using namespace mozilla::a11y;
 
 extern "C" {
 static void
 setTextContentsCB(AtkEditableText *aText, const gchar *aString)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return;
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole()) {
+      return;
+    }
 
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
-    return;
-
-  NS_ConvertUTF8toUTF16 strContent(aString);
-  text->ReplaceText(strContent);
+    NS_ConvertUTF8toUTF16 strContent(aString);
+    text->ReplaceText(strContent);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    NS_ConvertUTF8toUTF16 strContent(aString);
+    proxy->ReplaceText(strContent);
+  }
 }
 
 static void
 insertTextCB(AtkEditableText *aText,
              const gchar *aString, gint aLength, gint *aPosition)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return;
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole()) {
+      return;
+    }
 
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
-    return;
-
-  NS_ConvertUTF8toUTF16 strContent(aString, aLength);
-  text->InsertText(strContent, *aPosition);
+    NS_ConvertUTF8toUTF16 strContent(aString);
+    text->InsertText(strContent, *aPosition);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    NS_ConvertUTF8toUTF16 strContent(aString);
+    proxy->InsertText(strContent, *aPosition);
+  }
 }
 
 static void
 copyTextCB(AtkEditableText *aText, gint aStartPos, gint aEndPos)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return;
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole()) {
+      return;
+    }
 
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
-    return;
-
-  text->CopyText(aStartPos, aEndPos);
+    text->CopyText(aStartPos, aEndPos);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    proxy->CopyText(aStartPos, aEndPos);
+  }
 }
 
 static void
 cutTextCB(AtkEditableText *aText, gint aStartPos, gint aEndPos)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return;
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole()) {
+      return;
+    }
 
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
-    return;
-
-  text->CutText(aStartPos, aEndPos);
+    text->CutText(aStartPos, aEndPos);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    proxy->CutText(aStartPos, aEndPos);
+  }
 }
 
 static void
 deleteTextCB(AtkEditableText *aText, gint aStartPos, gint aEndPos)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return;
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole()) {
+      return;
+    }
 
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
-    return;
-
-  text->DeleteText(aStartPos, aEndPos);
+    text->DeleteText(aStartPos, aEndPos);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    proxy->DeleteText(aStartPos, aEndPos);
+  }
 }
 
 static void
 pasteTextCB(AtkEditableText *aText, gint aPosition)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return;
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole()) {
+      return;
+    }
 
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
-    return;
-
-  text->PasteText(aPosition);
+    text->PasteText(aPosition);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    proxy->PasteText(aPosition);
+  }
 }
 }
 
 void
 editableTextInterfaceInitCB(AtkEditableTextIface* aIface)
 {
   NS_ASSERTION(aIface, "Invalid aIface");
   if (MOZ_UNLIKELY(!aIface))
--- a/accessible/atk/nsMaiInterfaceHyperlinkImpl.cpp
+++ b/accessible/atk/nsMaiInterfaceHyperlinkImpl.cpp
@@ -11,24 +11,23 @@
 
 using namespace mozilla::a11y;
 
 extern "C" {
 static AtkHyperlink*
 getHyperlinkCB(AtkHyperlinkImpl* aImpl)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aImpl));
-  if (!accWrap)
+  if (!accWrap && !GetProxy(ATK_OBJECT(aImpl)))
     return nullptr;
 
-  NS_ENSURE_TRUE(accWrap->IsLink(), nullptr);
+  if (accWrap)
+    NS_ASSERTION(accWrap->IsLink(), "why isn't it a link!");
 
-  MaiHyperlink* maiHyperlink = accWrap->GetMaiHyperlink();
-  NS_ENSURE_TRUE(maiHyperlink, nullptr);
-  return maiHyperlink->GetAtkHyperlink();
+  return MAI_ATK_OBJECT(aImpl)->GetAtkHyperlink();
 }
 }
 
 void
 hyperlinkImplInterfaceInitCB(AtkHyperlinkImplIface *aIface)
 {
   NS_ASSERTION(aIface, "no interface!");
   if (MOZ_UNLIKELY(!aIface))
--- a/accessible/atk/nsMaiInterfaceHypertext.cpp
+++ b/accessible/atk/nsMaiInterfaceHypertext.cpp
@@ -5,69 +5,84 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "InterfaceInitFuncs.h"
 
 #include "Accessible-inl.h"
 #include "HyperTextAccessible.h"
 #include "nsMai.h"
 #include "nsMaiHyperlink.h"
+#include "ProxyAccessible.h"
 #include "mozilla/Likely.h"
 
+
 using namespace mozilla::a11y;
 
 extern "C" {
 
 static AtkHyperlink*
 getLinkCB(AtkHypertext *aText, gint aLinkIndex)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return nullptr;
+  AtkObject* atkHyperLink = nullptr;
+  if (accWrap) {
+    HyperTextAccessible* hyperText = accWrap->AsHyperText();
+    NS_ENSURE_TRUE(hyperText, nullptr);
 
-  HyperTextAccessible* hyperText = accWrap->AsHyperText();
-  NS_ENSURE_TRUE(hyperText, nullptr);
+    Accessible* hyperLink = hyperText->LinkAt(aLinkIndex);
+    if (!hyperLink || !hyperLink->IsLink()) {
+      return nullptr;
+    }
 
-  Accessible* hyperLink = hyperText->LinkAt(aLinkIndex);
-  if (!hyperLink)
-    return nullptr;
+    atkHyperLink = AccessibleWrap::GetAtkObject(hyperLink);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    ProxyAccessible* proxyLink = proxy->LinkAt(aLinkIndex);
+    if (!proxyLink)
+      return nullptr;
 
-  AtkObject* hyperLinkAtkObj = AccessibleWrap::GetAtkObject(hyperLink);
-  AccessibleWrap* accChild = GetAccessibleWrap(hyperLinkAtkObj);
-  NS_ENSURE_TRUE(accChild, nullptr);
+    atkHyperLink = GetWrapperFor(proxyLink);
+  }
 
-  MaiHyperlink *maiHyperlink = accChild->GetMaiHyperlink();
-  NS_ENSURE_TRUE(maiHyperlink, nullptr);
-  return maiHyperlink->GetAtkHyperlink();
+    NS_ENSURE_TRUE(IS_MAI_OBJECT(atkHyperLink), nullptr);
+    return MAI_ATK_OBJECT(atkHyperLink)->GetAtkHyperlink();
 }
 
 static gint
 getLinkCountCB(AtkHypertext *aText)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return -1;
+  if (accWrap) {
+    HyperTextAccessible* hyperText = accWrap->AsHyperText();
+    NS_ENSURE_TRUE(hyperText, -1);
+    return hyperText->LinkCount();
+  }
 
-  HyperTextAccessible* hyperText = accWrap->AsHyperText();
-  NS_ENSURE_TRUE(hyperText, -1);
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    return proxy->LinkCount();
+  }
 
-  return hyperText->LinkCount();
+  return -1;
 }
 
 static gint
 getLinkIndexCB(AtkHypertext *aText, gint aCharIndex)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return -1;
+  if (accWrap) {
+    HyperTextAccessible* hyperText = accWrap->AsHyperText();
+    NS_ENSURE_TRUE(hyperText, -1);
 
-  HyperTextAccessible* hyperText = accWrap->AsHyperText();
-  NS_ENSURE_TRUE(hyperText, -1);
+    return hyperText->LinkIndexAtOffset(aCharIndex);
+  }
 
-  return hyperText->LinkIndexAtOffset(aCharIndex);
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    return proxy->LinkIndexAtOffset(aCharIndex);
+  }
+
+  return -1;
 }
 }
 
 void
 hypertextInterfaceInitCB(AtkHypertextIface* aIface)
 {
   NS_ASSERTION(aIface, "no interface!");
   if (MOZ_UNLIKELY(!aIface))
--- a/accessible/atk/nsMaiInterfaceImage.cpp
+++ b/accessible/atk/nsMaiInterfaceImage.cpp
@@ -7,54 +7,62 @@
 #include "InterfaceInitFuncs.h"
 
 #include "AccessibleWrap.h"
 #include "ImageAccessible.h"
 #include "mozilla/Likely.h"
 #include "nsMai.h"
 #include "nsIAccessibleTypes.h"
 #include "nsIURI.h"
+#include "ProxyAccessible.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 extern "C" {
 const gchar* getDescriptionCB(AtkObject* aAtkObj);
 
 static void
 getImagePositionCB(AtkImage* aImage, gint* aAccX, gint* aAccY,
                    AtkCoordType aCoordType)
 {
-  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aImage));
-  if (!accWrap || !accWrap->IsImage())
-    return;
-
-  ImageAccessible* image = accWrap->AsImage();
+  nsIntPoint pos;
   uint32_t geckoCoordType = (aCoordType == ATK_XY_WINDOW) ?
     nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE :
     nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE;
-  nsIntPoint pos = image->Position(geckoCoordType);
+
+  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aImage));
+  if (accWrap && accWrap->IsImage()) {
+    ImageAccessible* image = accWrap->AsImage();
+    pos = image->Position(geckoCoordType);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aImage))) {
+    pos = proxy->ImagePosition(geckoCoordType);
+  }
+
   *aAccX = pos.x;
   *aAccY = pos.y;
 }
 
 static const gchar*
 getImageDescriptionCB(AtkImage* aImage)
 {
   return getDescriptionCB(ATK_OBJECT(aImage));
 }
 
 static void
 getImageSizeCB(AtkImage* aImage, gint* aAccWidth, gint* aAccHeight)
 {
+  nsIntSize size;
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aImage));
-  if (!accWrap || !accWrap->IsImage())
-    return;
+  if (accWrap && accWrap->IsImage()) {
+    size = accWrap->AsImage()->Size();
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aImage))) {
+    size = proxy->ImageSize();
+  }
 
-  nsIntSize size = accWrap->AsImage()->Size();
   *aAccWidth = size.width;
   *aAccHeight = size.height;
 }
 
 } // extern "C"
 
 void
 imageInterfaceInitCB(AtkImageIface* aIface)
--- a/accessible/atk/nsMaiInterfaceSelection.cpp
+++ b/accessible/atk/nsMaiInterfaceSelection.cpp
@@ -4,100 +4,139 @@
  * 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 "InterfaceInitFuncs.h"
 
 #include "Accessible-inl.h"
 #include "AccessibleWrap.h"
 #include "nsMai.h"
+#include "ProxyAccessible.h"
 #include "mozilla/Likely.h"
 
 #include <atk/atk.h>
 
 using namespace mozilla::a11y;
 
 extern "C" {
 
 static gboolean
 addSelectionCB(AtkSelection *aSelection, gint i)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aSelection));
-  if (!accWrap || !accWrap->IsSelect())
-    return FALSE;
+  if (accWrap && accWrap->IsSelect()) {
+    return accWrap->AddItemToSelection(i);
+  }
 
-  return accWrap->AddItemToSelection(i);
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aSelection))) {
+    return proxy->AddItemToSelection(i);
+  }
+
+  return FALSE;
 }
 
 static gboolean
 clearSelectionCB(AtkSelection *aSelection)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aSelection));
-  if (!accWrap || !accWrap->IsSelect())
-    return FALSE;
+  if (accWrap && accWrap->IsSelect()) {
+    return accWrap->UnselectAll();
+  }
 
-  return accWrap->UnselectAll();
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aSelection))) {
+    return proxy->UnselectAll();
+  }
+
+  return FALSE;
 }
 
 static AtkObject*
 refSelectionCB(AtkSelection *aSelection, gint i)
 {
+  AtkObject* atkObj = nullptr;
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aSelection));
-  if (!accWrap || !accWrap->IsSelect())
-    return nullptr;
+  if (accWrap && accWrap->IsSelect()) {
+    Accessible* selectedItem = accWrap->GetSelectedItem(i);
+    if (!selectedItem) {
+      return nullptr;
+    }
 
-  Accessible* selectedItem = accWrap->GetSelectedItem(i);
-  if (!selectedItem)
-    return nullptr;
+    atkObj = AccessibleWrap::GetAtkObject(selectedItem);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aSelection))) {
+    ProxyAccessible* selectedItem = proxy->GetSelectedItem(i);
+    if (selectedItem) {
+      atkObj = GetWrapperFor(selectedItem);
+    }
+  }
 
-  AtkObject* atkObj = AccessibleWrap::GetAtkObject(selectedItem);
-  if (atkObj)
+  if (atkObj) {
     g_object_ref(atkObj);
+  }
 
   return atkObj;
 }
 
 static gint
 getSelectionCountCB(AtkSelection *aSelection)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aSelection));
-  if (!accWrap || !accWrap->IsSelect())
-    return -1;
+  if (accWrap && accWrap->IsSelect()) {
+    return accWrap->SelectedItemCount();
+  }
 
-  return accWrap->SelectedItemCount();
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aSelection))) {
+    return proxy->SelectedItemCount();
+  }
+
+  return -1;
 }
 
 static gboolean
 isChildSelectedCB(AtkSelection *aSelection, gint i)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aSelection));
-  if (!accWrap || !accWrap->IsSelect())
-    return FALSE;
+  if (accWrap && accWrap->IsSelect()) {
+    return accWrap->IsItemSelected(i);
+  }
 
-  return accWrap->IsItemSelected(i);
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aSelection))) {
+    return proxy->IsItemSelected(i);
+  }
+
+  return FALSE;
 }
 
 static gboolean
 removeSelectionCB(AtkSelection *aSelection, gint i)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aSelection));
-  if (!accWrap || !accWrap->IsSelect())
-    return FALSE;
+  if (accWrap && accWrap->IsSelect()) {
+    return accWrap->RemoveItemFromSelection(i);
+  }
 
-  return accWrap->RemoveItemFromSelection(i);
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aSelection))) {
+    return proxy->RemoveItemFromSelection(i);
+  }
+
+  return FALSE;
 }
 
 static gboolean
 selectAllSelectionCB(AtkSelection *aSelection)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aSelection));
-  if (!accWrap || !accWrap->IsSelect())
-    return FALSE;
+  if (accWrap && accWrap->IsSelect()) {
+    return accWrap->SelectAll();
+  }
 
-  return accWrap->SelectAll();
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aSelection))) {
+    return proxy->SelectAll();
+  }
+
+  return FALSE;
 }
 }
 
 void
 selectionInterfaceInitCB(AtkSelectionIface* aIface)
 {
   NS_ASSERTION(aIface, "Invalid aIface");
   if (MOZ_UNLIKELY(!aIface))
--- a/accessible/atk/nsMaiInterfaceTable.cpp
+++ b/accessible/atk/nsMaiInterfaceTable.cpp
@@ -7,205 +7,260 @@
 #include "InterfaceInitFuncs.h"
 
 #include "Accessible-inl.h"
 #include "AccessibleWrap.h"
 #include "nsAccUtils.h"
 #include "TableAccessible.h"
 #include "TableCellAccessible.h"
 #include "nsMai.h"
-
+#include "ProxyAccessible.h"
 #include "nsArrayUtils.h"
 
 #include "mozilla/Likely.h"
 
 using namespace mozilla::a11y;
 
 extern "C" {
 static AtkObject*
 refAtCB(AtkTable* aTable, gint aRowIdx, gint aColIdx)
 {
+  if (aRowIdx < 0 || aColIdx < 0) {
+    return nullptr;
+  }
+
+  AtkObject* cellAtkObj = nullptr;
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap || aRowIdx < 0 || aColIdx < 0)
-    return nullptr;
+  if (accWrap) {
+    Accessible* cell = accWrap->AsTable()->CellAt(aRowIdx, aColIdx);
+    if (!cell) {
+      return nullptr;
+    }
 
-  Accessible* cell = accWrap->AsTable()->CellAt(aRowIdx, aColIdx);
-  if (!cell)
-    return nullptr;
+    cellAtkObj = AccessibleWrap::GetAtkObject(cell);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
+    ProxyAccessible* cell = proxy->TableCellAt(aRowIdx, aColIdx);
+    if (!cell) {
+      return nullptr;
+    }
 
-  AtkObject* cellAtkObj = AccessibleWrap::GetAtkObject(cell);
-  if (cellAtkObj)
+    cellAtkObj = GetWrapperFor(cell);
+  }
+
+  if (cellAtkObj) {
     g_object_ref(cellAtkObj);
+  }
 
   return cellAtkObj;
 }
 
 static gint
 getIndexAtCB(AtkTable* aTable, gint aRowIdx, gint aColIdx)
 {
-  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap || aRowIdx < 0 || aColIdx < 0)
+  if (aRowIdx < 0 || aColIdx < 0) {
     return -1;
+  }
 
-  return static_cast<gint>(accWrap->AsTable()->CellIndexAt(aRowIdx, aColIdx));
+  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
+  if (accWrap) {
+    return static_cast<gint>(accWrap->AsTable()->CellIndexAt(aRowIdx, aColIdx));
+  }
+
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
+    return static_cast<gint>(proxy->TableCellIndexAt(aRowIdx, aColIdx));
+  }
+
+  return -1;
 }
 
 static gint
 getColumnAtIndexCB(AtkTable *aTable, gint aIdx)
 {
-  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap || aIdx < 0)
+  if (aIdx < 0) {
     return -1;
+  }
 
+  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
+  if (accWrap) {
     return static_cast<gint>(accWrap->AsTable()->ColIndexAt(aIdx));
+  }
+
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
+    return static_cast<gint>(proxy->TableColumnIndexAt(aIdx));
+  }
+
+  return -1;
 }
 
 static gint
 getRowAtIndexCB(AtkTable *aTable, gint aIdx)
 {
-  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap || aIdx < 0)
+  if (aIdx < 0) {
     return -1;
+  }
 
+  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
+  if (accWrap) {
     return static_cast<gint>(accWrap->AsTable()->RowIndexAt(aIdx));
+  }
+
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
+    return static_cast<gint>(proxy->TableRowIndexAt(aIdx));
+  }
+
+  return -1;
 }
 
 static gint
 getColumnCountCB(AtkTable *aTable)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap)
-    return -1;
+  if (accWrap) {
+    return static_cast<gint>(accWrap->AsTable()->ColCount());
+  }
 
-    return static_cast<gint>(accWrap->AsTable()->ColCount());
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
+    return static_cast<gint>(proxy->TableColumnCount());
+  }
+
+  return -1;
 }
 
 static gint
 getRowCountCB(AtkTable *aTable)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap)
-    return -1;
+  if (accWrap) {
+    return static_cast<gint>(accWrap->AsTable()->RowCount());
+  }
 
-    return static_cast<gint>(accWrap->AsTable()->RowCount());
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
+    return static_cast<gint>(proxy->TableRowCount());
+  }
+
+  return -1;
 }
 
 static gint
 getColumnExtentAtCB(AtkTable *aTable, gint aRowIdx, gint aColIdx)
 {
-  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap || aRowIdx < 0 || aColIdx < 0)
+  if (aRowIdx < 0 || aColIdx < 0) {
     return -1;
+  }
 
+  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
+  if (accWrap) {
     return static_cast<gint>(accWrap->AsTable()->ColExtentAt(aRowIdx, aColIdx));
+  }
+
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
+    return static_cast<gint>(proxy->TableColumnExtentAt(aRowIdx, aColIdx));
+  }
+
+  return -1;
 }
 
 static gint
 getRowExtentAtCB(AtkTable *aTable, gint aRowIdx, gint aColIdx)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap)
-    return -1;
+  if (accWrap) {
+    return static_cast<gint>(accWrap->AsTable()->RowExtentAt(aRowIdx, aColIdx));
+  }
 
-  return static_cast<gint>(accWrap->AsTable()->RowExtentAt(aRowIdx, aColIdx));
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
+    return static_cast<gint>(proxy->TableRowExtentAt(aRowIdx, aColIdx));
+  }
+
+  return -1;
 }
 
 static AtkObject*
 getCaptionCB(AtkTable* aTable)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap)
-    return nullptr;
+  if (accWrap) {
+    Accessible* caption = accWrap->AsTable()->Caption();
+    return caption ? AccessibleWrap::GetAtkObject(caption) : nullptr;
+  }
 
-  Accessible* caption = accWrap->AsTable()->Caption();
-  return caption ? AccessibleWrap::GetAtkObject(caption) : nullptr;
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
+    ProxyAccessible* caption = proxy->TableCaption();
+    return caption ? GetWrapperFor(caption) : nullptr;
+  }
+
+  return nullptr;
 }
 
 static const gchar*
 getColumnDescriptionCB(AtkTable *aTable, gint aColumn)
 {
+  nsAutoString autoStr;
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap)
+  if (accWrap) {
+    accWrap->AsTable()->ColDescription(aColumn, autoStr);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
+    proxy->TableColumnDescription(aColumn, autoStr);
+  } else {
     return nullptr;
-
-  nsAutoString autoStr;
-  accWrap->AsTable()->ColDescription(aColumn, autoStr);
+  }
 
   return AccessibleWrap::ReturnString(autoStr);
 }
 
 static AtkObject*
 getColumnHeaderCB(AtkTable *aTable, gint aColIdx)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap)
-    return nullptr;
-
-  Accessible* cell = accWrap->AsTable()->CellAt(0, aColIdx);
-  if (!cell)
-    return nullptr;
-
-  // If the cell at the first row is column header then assume it is column
-  // header for all rows,
-  if (cell->Role() == roles::COLUMNHEADER)
-    return AccessibleWrap::GetAtkObject(cell);
+  if (accWrap) {
+    Accessible* header =
+      AccessibleWrap::GetColumnHeader(accWrap->AsTable(), aColIdx);
+    return header ? AccessibleWrap::GetAtkObject(header) : nullptr;
+  }
 
-  // otherwise get column header for the data cell at the first row.
-  TableCellAccessible* tableCell = cell->AsTableCell();
-  if (!tableCell)
-    return nullptr;
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
+    ProxyAccessible* header = proxy->AtkTableColumnHeader(aColIdx);
+    return header ? GetWrapperFor(header) : nullptr;
+  }
 
-  nsAutoTArray<Accessible*, 10> headerCells;
-  tableCell->ColHeaderCells(&headerCells);
-  if (headerCells.IsEmpty())
-    return nullptr;
-
-  return AccessibleWrap::GetAtkObject(headerCells[0]);
+  return nullptr;
 }
 
 static const gchar*
 getRowDescriptionCB(AtkTable *aTable, gint aRow)
 {
+  nsAutoString autoStr;
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap)
+  if (accWrap) {
+    accWrap->AsTable()->RowDescription(aRow, autoStr);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
+    proxy->TableRowDescription(aRow, autoStr);
+  } else {
     return nullptr;
-
-  nsAutoString autoStr;
-  accWrap->AsTable()->RowDescription(aRow, autoStr);
+  }
 
   return AccessibleWrap::ReturnString(autoStr);
 }
 
 static AtkObject*
 getRowHeaderCB(AtkTable *aTable, gint aRowIdx)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap)
-    return nullptr;
-
-  Accessible* cell = accWrap->AsTable()->CellAt(aRowIdx, 0);
-  if (!cell)
-    return nullptr;
-
-  // If the cell at the first column is row header then assume it is row
-  // header for all columns,
-  if (cell->Role() == roles::ROWHEADER)
-    return AccessibleWrap::GetAtkObject(cell);
+  if (accWrap) {
+    Accessible* header =
+      AccessibleWrap::GetRowHeader(accWrap->AsTable(), aRowIdx);
+    return header ? AccessibleWrap::GetAtkObject(header) : nullptr;
+  }
 
-  // otherwise get row header for the data cell at the first column.
-  TableCellAccessible* tableCell = cell->AsTableCell();
-  if (!tableCell)
-    return nullptr;
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
+    ProxyAccessible* header = proxy->AtkTableRowHeader(aRowIdx);
+    return header ? GetWrapperFor(header) : nullptr;
+  }
 
-  nsAutoTArray<Accessible*, 10> headerCells;
-  tableCell->RowHeaderCells(&headerCells);
-  if (headerCells.IsEmpty())
-    return nullptr;
-
-  return AccessibleWrap::GetAtkObject(headerCells[0]);
+  return nullptr;
 }
 
 static AtkObject*
 getSummaryCB(AtkTable *aTable)
 {
   // Neither html:table nor xul:tree nor ARIA grid/tree have an ability to
   // link an accessible object to specify a summary. There is closes method
   // in TableAccessible::summary to get a summary as a string which is not
@@ -213,22 +268,26 @@ getSummaryCB(AtkTable *aTable)
   return nullptr;
 }
 
 static gint
 getSelectedColumnsCB(AtkTable *aTable, gint** aSelected)
 {
   *aSelected = nullptr;
 
+  AutoTArray<uint32_t, 10> cols;
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap)
+  if (accWrap) {
+    accWrap->AsTable()->SelectedColIndices(&cols);
+   } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
+    proxy->TableSelectedColumnIndices(&cols);
+  } else {
     return 0;
+  }
 
-  nsAutoTArray<uint32_t, 10> cols;
-  accWrap->AsTable()->SelectedColIndices(&cols);
   if (cols.IsEmpty())
     return 0;
 
   gint* atkColumns = g_new(gint, cols.Length());
   if (!atkColumns) {
     NS_WARNING("OUT OF MEMORY");
     return 0;
   }
@@ -236,63 +295,75 @@ getSelectedColumnsCB(AtkTable *aTable, g
   memcpy(atkColumns, cols.Elements(), cols.Length() * sizeof(uint32_t));
   *aSelected = atkColumns;
   return cols.Length();
 }
 
 static gint
 getSelectedRowsCB(AtkTable *aTable, gint **aSelected)
 {
+  AutoTArray<uint32_t, 10> rows;
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap)
+  if (accWrap) {
+    accWrap->AsTable()->SelectedRowIndices(&rows);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
+    proxy->TableSelectedRowIndices(&rows);
+  } else {
     return 0;
-
-  nsAutoTArray<uint32_t, 10> rows;
-  accWrap->AsTable()->SelectedRowIndices(&rows);
+  }
 
   gint* atkRows = g_new(gint, rows.Length());
   if (!atkRows) {
     NS_WARNING("OUT OF MEMORY");
     return 0;
   }
 
   memcpy(atkRows, rows.Elements(), rows.Length() * sizeof(uint32_t));
   *aSelected = atkRows;
   return rows.Length();
 }
 
 static gboolean
 isColumnSelectedCB(AtkTable *aTable, gint aColIdx)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap)
-    return FALSE;
+  if (accWrap) {
+    return static_cast<gboolean>(accWrap->AsTable()->IsColSelected(aColIdx));
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
+    return static_cast<gboolean>(proxy->TableColumnSelected(aColIdx));
+  }
 
-  return static_cast<gboolean>(accWrap->AsTable()->IsColSelected(aColIdx));
+  return FALSE;
 }
 
 static gboolean
 isRowSelectedCB(AtkTable *aTable, gint aRowIdx)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap)
-    return FALSE;
+  if (accWrap) {
+    return static_cast<gboolean>(accWrap->AsTable()->IsRowSelected(aRowIdx));
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
+    return static_cast<gboolean>(proxy->TableRowSelected(aRowIdx));
+  }
 
-  return static_cast<gboolean>(accWrap->AsTable()->IsRowSelected(aRowIdx));
+  return FALSE;
 }
 
 static gboolean
 isCellSelectedCB(AtkTable *aTable, gint aRowIdx, gint aColIdx)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-  if (!accWrap)
-    return FALSE;
-
+  if (accWrap) {
     return static_cast<gboolean>(accWrap->AsTable()->
       IsCellSelected(aRowIdx, aColIdx));
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aTable))) {
+    return static_cast<gboolean>(proxy->TableCellSelected(aRowIdx, aColIdx));
+  }
+
+  return FALSE;
 }
 }
 
 void
 tableInterfaceInitCB(AtkTableIface* aIface)
 {
   NS_ASSERTION(aIface, "no interface!");
   if (MOZ_UNLIKELY(!aIface))
--- a/accessible/atk/nsMaiInterfaceText.cpp
+++ b/accessible/atk/nsMaiInterfaceText.cpp
@@ -1,31 +1,93 @@
 /* -*- 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 "InterfaceInitFuncs.h"
-
+#include "mozilla/a11y/PDocAccessible.h"
 #include "Accessible-inl.h"
 #include "HyperTextAccessible-inl.h"
 #include "nsMai.h"
+#include "ProxyAccessible.h"
 
 #include "nsIAccessibleTypes.h"
 #include "nsIPersistentProperties2.h"
 #include "nsISimpleEnumerator.h"
 
 #include "mozilla/Likely.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 static const char* sAtkTextAttrNames[ATK_TEXT_ATTR_LAST_DEFINED];
 
+void
+ConvertTextAttributeToAtkAttribute(const nsACString& aName,
+                                   const nsAString& aValue,
+                                   AtkAttributeSet** aAttributeSet)
+{
+  // Handle attributes where atk has its own name.
+  const char* atkName = nullptr;
+  nsAutoString atkValue;
+  if (aName.EqualsLiteral("color")) {
+    // The format of the atk attribute is r,g,b and the gecko one is
+    // rgb(r, g, b).
+    atkValue = Substring(aValue, 4, aValue.Length() - 5);
+    atkValue.StripWhitespace();
+    atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_FG_COLOR];
+  } else if (aName.EqualsLiteral("background-color")) {
+    // The format of the atk attribute is r,g,b and the gecko one is
+    // rgb(r, g, b).
+    atkValue = Substring(aValue, 4, aValue.Length() - 5);
+    atkValue.StripWhitespace();
+    atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_BG_COLOR];
+  } else if (aName.EqualsLiteral("font-family")) {
+    atkValue = aValue;
+    atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_FAMILY_NAME];
+  } else if (aName.EqualsLiteral("font-size")) {
+    // ATK wants the number of pixels without px at the end.
+    atkValue = StringHead(aValue, aValue.Length() - 2);
+    atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_SIZE];
+  } else if (aName.EqualsLiteral("font-weight")) {
+    atkValue = aValue;
+    atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_WEIGHT];
+  } else if (aName.EqualsLiteral("invalid")) {
+    atkValue = aValue;
+    atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_INVALID];
+  }
+
+  if (atkName) {
+    AtkAttribute* objAttr =
+      static_cast<AtkAttribute*>(g_malloc(sizeof(AtkAttribute)));
+    objAttr->name = g_strdup(atkName);
+    objAttr->value = g_strdup(NS_ConvertUTF16toUTF8(atkValue).get());
+    *aAttributeSet = g_slist_prepend(*aAttributeSet, objAttr);
+  }
+}
+
+static AtkAttributeSet*
+ConvertToAtkTextAttributeSet(nsTArray<Attribute>& aAttributes)
+{
+  AtkAttributeSet* objAttributeSet = nullptr;
+  for (size_t i = 0; i < aAttributes.Length(); ++i) {
+    AtkAttribute* objAttr = (AtkAttribute *)g_malloc(sizeof(AtkAttribute));
+    objAttr->name = g_strdup(aAttributes[i].Name().get());
+    objAttr->value =
+      g_strdup(NS_ConvertUTF16toUTF8(aAttributes[i].Value()).get());
+    objAttributeSet = g_slist_prepend(objAttributeSet, objAttr);
+    ConvertTextAttributeToAtkAttribute(aAttributes[i].Name(),
+                                       aAttributes[i].Value(),
+                                       &objAttributeSet);
+  }
+  return objAttributeSet;
+}
+
 static AtkAttributeSet*
 ConvertToAtkTextAttributeSet(nsIPersistentProperties* aAttributes)
 {
   if (!aAttributes)
     return nullptr;
 
   AtkAttributeSet* objAttributeSet = nullptr;
   nsCOMPtr<nsISimpleEnumerator> propEnum;
@@ -49,50 +111,17 @@ ConvertToAtkTextAttributeSet(nsIPersiste
     rv = propElem->GetValue(value);
     NS_ENSURE_SUCCESS(rv, objAttributeSet);
 
     AtkAttribute* objAttr = (AtkAttribute*)g_malloc(sizeof(AtkAttribute));
     objAttr->name = g_strdup(name.get());
     objAttr->value = g_strdup(NS_ConvertUTF16toUTF8(value).get());
     objAttributeSet = g_slist_prepend(objAttributeSet, objAttr);
 
-    // Handle attributes where atk has its own name.
-    const char* atkName = nullptr;
-    nsAutoString atkValue;
-    if (name.EqualsLiteral("color")) {
-      // The format of the atk attribute is r,g,b and the gecko one is
-      // rgb(r,g,b).
-      atkValue = Substring(value, 5, value.Length() - 1);
-      atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_FG_COLOR];
-    } else if (name.EqualsLiteral("background-color")) {
-      // The format of the atk attribute is r,g,b and the gecko one is
-      // rgb(r,g,b).
-      atkValue = Substring(value, 5, value.Length() - 1);
-      atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_BG_COLOR];
-    } else if (name.EqualsLiteral("font-family")) {
-      atkValue = value;
-      atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_FAMILY_NAME];
-    } else if (name.EqualsLiteral("font-size")) {
-      // ATK wants the number of pixels without px at the end.
-      atkValue = StringHead(value, value.Length() - 2);
-      atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_SIZE];
-    } else if (name.EqualsLiteral("font-weight")) {
-      atkValue = value;
-      atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_WEIGHT];
-    } else if (name.EqualsLiteral("invalid")) {
-      atkValue = value;
-      atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_INVALID];
-    }
-
-    if (atkName) {
-      objAttr = static_cast<AtkAttribute*>(g_malloc(sizeof(AtkAttribute)));
-      objAttr->name = g_strdup(atkName);
-      objAttr->value = g_strdup(NS_ConvertUTF16toUTF8(atkValue).get());
-      objAttributeSet = g_slist_prepend(objAttributeSet, objAttr);
-    }
+    ConvertTextAttributeToAtkAttribute(name, value, &objAttributeSet);
   }
 
   // libatk-adaptor will free it
   return objAttributeSet;
 }
 
 static void
 ConvertTexttoAsterisks(AccessibleWrap* accWrap, nsAString& aString)
@@ -105,356 +134,468 @@ ConvertTexttoAsterisks(AccessibleWrap* a
 }
 
 extern "C" {
 
 static gchar*
 getTextCB(AtkText *aText, gint aStartOffset, gint aEndOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return nullptr;
+  nsAutoString autoStr;
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole())
+      return nullptr;
 
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
-    return nullptr;
-
-    nsAutoString autoStr;
     text->TextSubstring(aStartOffset, aEndOffset, autoStr);
 
     ConvertTexttoAsterisks(accWrap, autoStr);
-    NS_ConvertUTF16toUTF8 cautoStr(autoStr);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    proxy->TextSubstring(aStartOffset, aEndOffset, autoStr);
+  }
 
-    //copy and return, libspi will free it.
-    return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
+  NS_ConvertUTF16toUTF8 cautoStr(autoStr);
+
+  //copy and return, libspi will free it.
+  return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
 }
 
 static gchar*
 getTextAfterOffsetCB(AtkText *aText, gint aOffset,
                      AtkTextBoundary aBoundaryType,
                      gint *aStartOffset, gint *aEndOffset)
 {
+    nsAutoString autoStr;
+  int32_t startOffset = 0, endOffset = 0;
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return nullptr;
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole())
+      return nullptr;
 
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
-    return nullptr;
-
-  nsAutoString autoStr;
-  int32_t startOffset = 0, endOffset = 0;
-  text->TextAfterOffset(aOffset, aBoundaryType, &startOffset, &endOffset, autoStr);
+    text->TextAfterOffset(aOffset, aBoundaryType, &startOffset, &endOffset, autoStr);
+    ConvertTexttoAsterisks(accWrap, autoStr);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    proxy->GetTextAfterOffset(aOffset, aBoundaryType, autoStr, &startOffset,
+                              &endOffset);
+  }
 
   *aStartOffset = startOffset;
   *aEndOffset = endOffset;
 
-  ConvertTexttoAsterisks(accWrap, autoStr);
   NS_ConvertUTF16toUTF8 cautoStr(autoStr);
   return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
 }
 
 static gchar*
 getTextAtOffsetCB(AtkText *aText, gint aOffset,
                   AtkTextBoundary aBoundaryType,
                   gint *aStartOffset, gint *aEndOffset)
 {
+  nsAutoString autoStr;
+  int32_t startOffset = 0, endOffset = 0;
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return nullptr;
-
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
-    return nullptr;
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole())
+      return nullptr;
 
-    nsAutoString autoStr;
-    int32_t startOffset = 0, endOffset = 0;
     text->TextAtOffset(aOffset, aBoundaryType, &startOffset, &endOffset, autoStr);
-    *aStartOffset = startOffset;
-    *aEndOffset = endOffset;
+    ConvertTexttoAsterisks(accWrap, autoStr);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    proxy->GetTextAtOffset(aOffset, aBoundaryType, autoStr, &startOffset,
+                           &endOffset);
+  }
 
-    ConvertTexttoAsterisks(accWrap, autoStr);
-    NS_ConvertUTF16toUTF8 cautoStr(autoStr);
-    return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
+  *aStartOffset = startOffset;
+  *aEndOffset = endOffset;
+
+  NS_ConvertUTF16toUTF8 cautoStr(autoStr);
+  return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
 }
 
 static gunichar
 getCharacterAtOffsetCB(AtkText* aText, gint aOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return 0;
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole()) {
+      return 0;
+    }
 
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
-    return 0;
+    // char16_t is unsigned short in Mozilla, gnuichar is guint32 in glib.
+    return static_cast<gunichar>(text->CharAt(aOffset));
+  }
 
-  // char16_t is unsigned short in Mozilla, gnuichar is guint32 in glib.
-  return static_cast<gunichar>(text->CharAt(aOffset));
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    return static_cast<gunichar>(proxy->CharAt(aOffset));
+  }
+
+  return 0;
 }
 
 static gchar*
 getTextBeforeOffsetCB(AtkText *aText, gint aOffset,
                       AtkTextBoundary aBoundaryType,
                       gint *aStartOffset, gint *aEndOffset)
 {
-  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return nullptr;
-
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
-    return nullptr;
-
   nsAutoString autoStr;
   int32_t startOffset = 0, endOffset = 0;
-  text->TextBeforeOffset(aOffset, aBoundaryType,
-                         &startOffset, &endOffset, autoStr);
+  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole())
+      return nullptr;
+
+    text->TextBeforeOffset(aOffset, aBoundaryType,
+                           &startOffset, &endOffset, autoStr);
+    ConvertTexttoAsterisks(accWrap, autoStr);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    proxy->GetTextBeforeOffset(aOffset, aBoundaryType, autoStr, &startOffset,
+                               &endOffset);
+  }
+
   *aStartOffset = startOffset;
   *aEndOffset = endOffset;
 
-  ConvertTexttoAsterisks(accWrap, autoStr);
   NS_ConvertUTF16toUTF8 cautoStr(autoStr);
   return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
 }
 
 static gint
 getCaretOffsetCB(AtkText *aText)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return 0;
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole()) {
+      return 0;
+    }
 
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
-    return 0;
+    return static_cast<gint>(text->CaretOffset());
+  }
 
-  return static_cast<gint>(text->CaretOffset());
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    return static_cast<gint>(proxy->CaretOffset());
+  }
+
+  return 0;
 }
 
 static AtkAttributeSet*
 getRunAttributesCB(AtkText *aText, gint aOffset,
                    gint *aStartOffset,
                    gint *aEndOffset)
 {
   *aStartOffset = -1;
   *aEndOffset = -1;
+  int32_t startOffset = 0, endOffset = 0;
 
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return nullptr;
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole()) {
+      return nullptr;
+    }
+
+    nsCOMPtr<nsIPersistentProperties> attributes =
+      text->TextAttributes(false, aOffset, &startOffset, &endOffset);
 
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
+    *aStartOffset = startOffset;
+    *aEndOffset = endOffset;
+
+    return ConvertToAtkTextAttributeSet(attributes);
+  }
+
+  ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText));
+  if (!proxy) {
     return nullptr;
+  }
 
-  int32_t startOffset = 0, endOffset = 0;
-  nsCOMPtr<nsIPersistentProperties> attributes =
-    text->TextAttributes(false, aOffset, &startOffset, &endOffset);
-
+  AutoTArray<Attribute, 10> attrs;
+  proxy->TextAttributes(false, aOffset, &attrs, &startOffset, &endOffset);
   *aStartOffset = startOffset;
   *aEndOffset = endOffset;
-
-  return ConvertToAtkTextAttributeSet(attributes);
+  return ConvertToAtkTextAttributeSet(attrs);
 }
 
 static AtkAttributeSet*
 getDefaultAttributesCB(AtkText *aText)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return nullptr;
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole()) {
+      return nullptr;
+    }
 
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
+    nsCOMPtr<nsIPersistentProperties> attributes = text->DefaultTextAttributes();
+    return ConvertToAtkTextAttributeSet(attributes);
+  }
+
+  ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText));
+  if (!proxy) {
     return nullptr;
+  }
 
-  nsCOMPtr<nsIPersistentProperties> attributes = text->DefaultTextAttributes();
-  return ConvertToAtkTextAttributeSet(attributes);
+  AutoTArray<Attribute, 10> attrs;
+  proxy->DefaultTextAttributes(&attrs);
+  return ConvertToAtkTextAttributeSet(attrs);
 }
 
 static void
 getCharacterExtentsCB(AtkText *aText, gint aOffset,
                       gint *aX, gint *aY,
                       gint *aWidth, gint *aHeight,
                       AtkCoordType aCoords)
 {
-  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if(!accWrap || !aX || !aY || !aWidth || !aHeight)
+  if(!aX || !aY || !aWidth || !aHeight) {
     return;
+  }
 
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
-    return;
+  nsIntRect rect;
+  uint32_t geckoCoordType;
+  if (aCoords == ATK_XY_SCREEN) {
+    geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE;
+  } else {
+    geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE;
+  }
 
-    uint32_t geckoCoordType;
-    if (aCoords == ATK_XY_SCREEN)
-        geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE;
-    else
-        geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE;
+  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole()) {
+      return;
+    }
 
-  nsIntRect rect = text->CharBounds(aOffset, geckoCoordType);
+    rect = text->CharBounds(aOffset, geckoCoordType);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    rect = proxy->CharBounds(aOffset, geckoCoordType);
+  } else {
+    return;
+  }
+
   *aX = rect.x;
   *aY = rect.y;
   *aWidth = rect.width;
   *aHeight = rect.height;
 }
 
 static void
 getRangeExtentsCB(AtkText *aText, gint aStartOffset, gint aEndOffset,
                   AtkCoordType aCoords, AtkTextRectangle *aRect)
 {
-  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if(!accWrap || !aRect)
+  if (!aRect) {
     return;
+  }
 
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
-    return;
+  nsIntRect rect;
+  uint32_t geckoCoordType;
+  if (aCoords == ATK_XY_SCREEN) {
+    geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE;
+  } else {
+    geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE;
+  }
 
-    uint32_t geckoCoordType;
-    if (aCoords == ATK_XY_SCREEN)
-        geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE;
-    else
-        geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE;
+  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
+  if(accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole()) {
+      return;
+    }
 
-  nsIntRect rect = text->TextBounds(aStartOffset, aEndOffset, geckoCoordType);
+    rect = text->TextBounds(aStartOffset, aEndOffset, geckoCoordType);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    rect = proxy->TextBounds(aStartOffset, aEndOffset, geckoCoordType);
+  } else {
+    return;
+  }
+
   aRect->x = rect.x;
   aRect->y = rect.y;
   aRect->width = rect.width;
   aRect->height = rect.height;
 }
 
 static gint
 getCharacterCountCB(AtkText *aText)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return 0;
+  if (accWrap) {
+    HyperTextAccessible* textAcc = accWrap->AsHyperText();
+    return
+      textAcc->IsDefunct() ? 0 : static_cast<gint>(textAcc->CharacterCount());
+  }
 
-  HyperTextAccessible* textAcc = accWrap->AsHyperText();
-  return textAcc->IsDefunct() ?
-    0 : static_cast<gint>(textAcc->CharacterCount());
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    return proxy->CharacterCount();
+  }
+
+  return 0;
 }
 
 static gint
 getOffsetAtPointCB(AtkText *aText,
                    gint aX, gint aY,
                    AtkCoordType aCoords)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return -1;
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole()) {
+      return -1;
+    }
 
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
-    return -1;
+    return static_cast<gint>(
+      text->OffsetAtPoint(aX, aY,
+                          (aCoords == ATK_XY_SCREEN ?
+                           nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
+                           nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE)));
+  }
 
-  return static_cast<gint>(
-    text->OffsetAtPoint(aX, aY,
-                        (aCoords == ATK_XY_SCREEN ?
-                         nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
-                         nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE)));
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    return static_cast<gint>(
+      proxy->OffsetAtPoint(aX, aY,
+                           (aCoords == ATK_XY_SCREEN ?
+                            nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
+                            nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE)));
+  }
+
+  return -1;
 }
 
 static gint
 getTextSelectionCountCB(AtkText *aText)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return 0;
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole()) {
+      return 0;
+    }
 
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
-    return 0;
+    return text->SelectionCount();
+  }
 
-  return text->SelectionCount();
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    return proxy->SelectionCount();
+  }
+
+  return 0;
 }
 
 static gchar*
 getTextSelectionCB(AtkText *aText, gint aSelectionNum,
                    gint *aStartOffset, gint *aEndOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return nullptr;
+  int32_t startOffset = 0, endOffset = 0;
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole()) {
+      return nullptr;
+    }
 
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
-    return nullptr;
-
-  int32_t startOffset = 0, endOffset = 0;
-  text->SelectionBoundsAt(aSelectionNum, &startOffset, &endOffset);
-
+    text->SelectionBoundsAt(aSelectionNum, &startOffset, &endOffset);
     *aStartOffset = startOffset;
     *aEndOffset = endOffset;
 
     return getTextCB(aText, *aStartOffset, *aEndOffset);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    nsString data;
+    proxy->SelectionBoundsAt(aSelectionNum, data, &startOffset, &endOffset);
+    *aStartOffset = startOffset;
+    *aEndOffset = endOffset;
+
+    NS_ConvertUTF16toUTF8 dataAsUTF8(data);
+    return (dataAsUTF8.get()) ? g_strdup(dataAsUTF8.get()) : nullptr;
+  }
+  return nullptr;
 }
 
 // set methods
 static gboolean
 addTextSelectionCB(AtkText *aText,
                    gint aStartOffset,
                    gint aEndOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return FALSE;
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole()) {
+      return FALSE;
+    }
 
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
-    return FALSE;
+    return text->AddToSelection(aStartOffset, aEndOffset);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    return proxy->AddToSelection(aStartOffset, aEndOffset);
+  }
 
-  return text->AddToSelection(aStartOffset, aEndOffset);
+  return FALSE;
 }
 
 static gboolean
 removeTextSelectionCB(AtkText *aText,
                       gint aSelectionNum)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return FALSE;
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole()) {
+      return FALSE;
+    }
 
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
-    return FALSE;
+    return text->RemoveFromSelection(aSelectionNum);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    return proxy->RemoveFromSelection(aSelectionNum);
+  }
 
-  return text->RemoveFromSelection(aSelectionNum);
+  return FALSE;
 }
 
 static gboolean
 setTextSelectionCB(AtkText *aText, gint aSelectionNum,
                    gint aStartOffset, gint aEndOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return FALSE;
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole()) {
+      return FALSE;
+    }
 
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
-    return FALSE;
+    return text->SetSelectionBoundsAt(aSelectionNum, aStartOffset, aEndOffset);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    return proxy->SetSelectionBoundsAt(aSelectionNum, aStartOffset, aEndOffset);
+  }
 
-  return text->SetSelectionBoundsAt(aSelectionNum, aStartOffset, aEndOffset);
+  return FALSE;
 }
 
 static gboolean
 setCaretOffsetCB(AtkText *aText, gint aOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return FALSE;
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole() || !text->IsValidOffset(aOffset)) {
+      return FALSE;
+    }
 
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole() || !text->IsValidOffset(aOffset))
-    return FALSE;
+    text->SetCaretOffset(aOffset);
+    return TRUE;
+  }
 
-  text->SetCaretOffset(aOffset);
-  return TRUE;
+  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    proxy->SetCaretOffset(aOffset);
+    return TRUE;
+  }
+
+  return FALSE;
 }
 }
 
 void
 textInterfaceInitCB(AtkTextIface* aIface)
 {
   NS_ASSERTION(aIface, "Invalid aIface");
   if (MOZ_UNLIKELY(!aIface))
--- a/accessible/atk/nsMaiInterfaceValue.cpp
+++ b/accessible/atk/nsMaiInterfaceValue.cpp
@@ -3,98 +3,123 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "InterfaceInitFuncs.h"
 
 #include "AccessibleWrap.h"
 #include "nsMai.h"
-
+#include "ProxyAccessible.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/Likely.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 extern "C" {
 
 static void
 getCurrentValueCB(AtkValue *obj, GValue *value)
 {
+  ProxyAccessible* proxy = nullptr;
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj));
-  if (!accWrap)
-    return;
+  if (!accWrap) {
+    proxy = GetProxy(ATK_OBJECT(obj));
+    if (!proxy) {
+      return;
+    }
+  }
 
   memset (value,  0, sizeof (GValue));
-  double accValue = accWrap->CurValue();
+  double accValue = accWrap ? accWrap->CurValue() : proxy->CurValue();
   if (IsNaN(accValue))
     return;
 
   g_value_init (value, G_TYPE_DOUBLE);
   g_value_set_double (value, accValue);
 }
 
 static void
 getMaximumValueCB(AtkValue *obj, GValue *value)
 {
+  ProxyAccessible* proxy = nullptr;
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj));
-  if (!accWrap)
-    return;
+  if (!accWrap) {
+    proxy = GetProxy(ATK_OBJECT(obj));
+    if (!proxy) {
+      return;
+    }
+  }
 
   memset(value,  0, sizeof (GValue));
-  double accValue = accWrap->MaxValue();
+  double accValue = accWrap ? accWrap->MaxValue() : proxy->MaxValue();
   if (IsNaN(accValue))
     return;
 
   g_value_init(value, G_TYPE_DOUBLE);
   g_value_set_double(value, accValue);
 }
 
 static void
 getMinimumValueCB(AtkValue *obj, GValue *value)
 {
+  ProxyAccessible* proxy = nullptr;
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj));
-  if (!accWrap)
-    return;
+  if (!accWrap) {
+    proxy = GetProxy(ATK_OBJECT(obj));
+    if (!proxy) {
+      return;
+    }
+  }
 
   memset(value,  0, sizeof (GValue));
-  double accValue = accWrap->MinValue();
+  double accValue = accWrap ? accWrap->MinValue() : proxy->MinValue();
   if (IsNaN(accValue))
     return;
 
   g_value_init(value, G_TYPE_DOUBLE);
   g_value_set_double(value, accValue);
 }
 
 static void
 getMinimumIncrementCB(AtkValue *obj, GValue *minimumIncrement)
 {
+  ProxyAccessible* proxy = nullptr;
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj));
-  if (!accWrap)
-    return;
+  if (!accWrap) {
+    proxy = GetProxy(ATK_OBJECT(obj));
+    if (!proxy) {
+      return;
+    }
+  }
 
   memset(minimumIncrement,  0, sizeof (GValue));
-  double accValue = accWrap->Step();
+  double accValue = accWrap ? accWrap->Step() : proxy->Step();
   if (IsNaN(accValue))
     accValue = 0; // zero if the minimum increment is undefined
 
   g_value_init(minimumIncrement, G_TYPE_DOUBLE);
   g_value_set_double(minimumIncrement, accValue);
 }
 
 static gboolean
 setCurrentValueCB(AtkValue *obj, const GValue *value)
 {
+  ProxyAccessible* proxy = nullptr;
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj));
-  if (!accWrap)
-    return FALSE;
+  if (!accWrap) {
+    proxy = GetProxy(ATK_OBJECT(obj));
+    if (!proxy) {
+      return FALSE;
+    }
+  }
 
   double accValue =g_value_get_double(value);
-  return accWrap->SetCurValue(accValue);
+  return accWrap ? accWrap->SetCurValue(accValue) : proxy->SetCurValue(accValue);
 }
 }
 
 void
 valueInterfaceInitCB(AtkValueIface* aIface)
 {
   NS_ASSERTION(aIface, "Invalid aIface");
   if (MOZ_UNLIKELY(!aIface))
--- a/accessible/base/ARIAMap.cpp
+++ b/accessible/base/ARIAMap.cpp
@@ -11,48 +11,45 @@
 #include "nsCoreUtils.h"
 #include "Role.h"
 #include "States.h"
 
 #include "nsAttrName.h"
 #include "nsWhitespaceTokenizer.h"
 
 #include "mozilla/BinarySearch.h"
+#include "mozilla/dom/Element.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 using namespace mozilla::a11y::aria;
 
 static const uint32_t kGenericAccType = 0;
 
 /**
  *  This list of WAI-defined roles are currently hardcoded.
  *  Eventually we will most likely be loading an RDF resource that contains this information
  *  Using RDF will also allow for role extensibility. See bug 280138.
  *
  *  Definition of nsRoleMapEntry contains comments explaining this table.
  *
  *  When no Role enum mapping exists for an ARIA role, the role will be exposed
  *  via the object attribute "xml-roles".
- *
- *  There are no Role enums for the following landmark roles:
- *    banner, contentinfo, main, navigation, note, search, secondary,
- *    seealso, breadcrumbs.
  */
 
 static nsRoleMapEntry sWAIRoleMaps[] =
 {
   { // alert
     &nsGkAtoms::alert,
     roles::ALERT,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
-    kGenericAccType,
+    eAlert,
     kNoReqStates
   },
   { // alertdialog
     &nsGkAtoms::alertdialog,
     roles::DIALOG,
     kUseMapRole,
     eNoValue,
     eNoAction,
@@ -62,41 +59,61 @@ static nsRoleMapEntry sWAIRoleMaps[] =
   },
   { // application
     &nsGkAtoms::application,
     roles::APPLICATION,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
-    kGenericAccType,
+    eLandmark,
     kNoReqStates
   },
   { // article
     &nsGkAtoms::article,
     roles::DOCUMENT,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kGenericAccType,
     kNoReqStates,
     eReadonlyUntilEditable
   },
+  { // banner
+    &nsGkAtoms::banner,
+    roles::NOTHING,
+    kUseNativeRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
   { // button
     &nsGkAtoms::button,
     roles::PUSHBUTTON,
     kUseMapRole,
     eNoValue,
     ePressAction,
     eNoLiveAttr,
     eButton,
     kNoReqStates
     // eARIAPressed is auto applied on any button
   },
+  { // cell
+    &nsGkAtoms::cell,
+    roles::CELL,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eTableCell,
+    kNoReqStates
+  },
   { // checkbox
     &nsGkAtoms::checkbox,
     roles::CHECKBUTTON,
     kUseMapRole,
     eNoValue,
     eCheckUncheckAction,
     eNoLiveAttr,
     kGenericAccType,
@@ -124,16 +141,36 @@ static nsRoleMapEntry sWAIRoleMaps[] =
     eOpenCloseAction,
     eNoLiveAttr,
     kGenericAccType,
     states::COLLAPSED | states::HASPOPUP | states::VERTICAL,
     eARIAAutoComplete,
     eARIAReadonly,
     eARIAOrientation
   },
+  { // complementary
+    &nsGkAtoms::complementary,
+    roles::NOTHING,
+    kUseNativeRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
+  { // contentinfo
+    &nsGkAtoms::contentinfo,
+    roles::NOTHING,
+    kUseNativeRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
   { // dialog
     &nsGkAtoms::dialog,
     roles::DIALOG,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kGenericAccType,
@@ -162,17 +199,17 @@ static nsRoleMapEntry sWAIRoleMaps[] =
   },
   { // form
     &nsGkAtoms::form,
     roles::FORM,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
-    kGenericAccType,
+    eLandmark,
     kNoReqStates
   },
   { // grid
     &nsGkAtoms::grid,
     roles::TABLE,
     kUseMapRole,
     eNoValue,
     eNoAction,
@@ -285,16 +322,26 @@ static nsRoleMapEntry sWAIRoleMaps[] =
     roles::NOTHING,
     kUseNativeRole,
     eNoValue,
     eNoAction,
     ePoliteLiveAttr,
     kGenericAccType,
     kNoReqStates
   },
+  { // main
+    &nsGkAtoms::main,
+    roles::NOTHING,
+    kUseNativeRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
   { // marquee
     &nsGkAtoms::marquee,
     roles::ANIMATION,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eOffLiveAttr,
     kGenericAccType,
@@ -361,16 +408,36 @@ static nsRoleMapEntry sWAIRoleMaps[] =
     kUseMapRole,
     eNoValue,
     eClickAction,
     eNoLiveAttr,
     kGenericAccType,
     kNoReqStates,
     eARIACheckableBool
   },
+  { // navigation
+    &nsGkAtoms::navigation,
+    roles::NOTHING,
+    kUseNativeRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
+  { // none
+    &nsGkAtoms::none,
+    roles::NOTHING,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    kNoReqStates
+  },
   { // note
     &nsGkAtoms::note_,
     roles::NOTE,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kGenericAccType,
@@ -417,17 +484,17 @@ static nsRoleMapEntry sWAIRoleMaps[] =
     eSelectAction,
     eNoLiveAttr,
     kGenericAccType,
     kNoReqStates,
     eARIACheckableBool
   },
   { // radiogroup
     &nsGkAtoms::radiogroup,
-    roles::GROUPING,
+    roles::RADIO_GROUP,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kGenericAccType,
     kNoReqStates,
     eARIAOrientation
   },
@@ -481,16 +548,39 @@ static nsRoleMapEntry sWAIRoleMaps[] =
     eHasValueMinMax,
     eNoAction,
     eNoLiveAttr,
     kGenericAccType,
     states::VERTICAL,
     eARIAOrientation,
     eARIAReadonly
   },
+  { // search
+    &nsGkAtoms::search,
+    roles::NOTHING,
+    kUseNativeRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eLandmark,
+    kNoReqStates
+  },
+  { // searchbox
+    &nsGkAtoms::searchbox,
+    roles::ENTRY,
+    kUseMapRole,
+    eNoValue,
+    eActivateAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    kNoReqStates,
+    eARIAAutoComplete,
+    eARIAMultiline,
+    eARIAReadonlyOrEditable
+  },
   { // separator
     &nsGkAtoms::separator_,
     roles::SEPARATOR,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kGenericAccType,
@@ -525,27 +615,49 @@ static nsRoleMapEntry sWAIRoleMaps[] =
     roles::STATUSBAR,
     kUseMapRole,
     eNoValue,
     eNoAction,
     ePoliteLiveAttr,
     kGenericAccType,
     kNoReqStates
   },
+  { // switch
+    &nsGkAtoms::_switch,
+    roles::SWITCH,
+    kUseMapRole,
+    eNoValue,
+    eCheckUncheckAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    kNoReqStates,
+    eARIACheckableBool
+  },
   { // tab
     &nsGkAtoms::tab,
     roles::PAGETAB,
     kUseMapRole,
     eNoValue,
     eSwitchAction,
     eNoLiveAttr,
     kGenericAccType,
     kNoReqStates,
     eARIASelectable
   },
+  { // table
+    &nsGkAtoms::table,
+    roles::TABLE,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    eTable,
+    kNoReqStates,
+    eARIASelectable
+  },
   { // tablist
     &nsGkAtoms::tablist,
     roles::PAGETABLIST,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     eSelect,
@@ -676,16 +788,17 @@ nsRoleMapEntry aria::gEmptyRoleMap = {
  * whether there is an ARIA role or not:
  */
 static const EStateRule sWAIUnivStateMap[] = {
   eARIABusy,
   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
 };
 
 
 /**
  * ARIA attribute map for attribute characteristics.
  * @note ARIA attributes that don't have any flags are not included here.
@@ -705,22 +818,23 @@ static const AttrCharacteristics gWAIUni
   {&nsGkAtoms::aria_controls,          ATTR_BYPASSOBJ                 | ATTR_GLOBAL },
   {&nsGkAtoms::aria_describedby,       ATTR_BYPASSOBJ                 | ATTR_GLOBAL },
   {&nsGkAtoms::aria_disabled,          ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL },
   {&nsGkAtoms::aria_dropeffect,                         ATTR_VALTOKEN | ATTR_GLOBAL },
   {&nsGkAtoms::aria_expanded,          ATTR_BYPASSOBJ | ATTR_VALTOKEN               },
   {&nsGkAtoms::aria_flowto,            ATTR_BYPASSOBJ                 | ATTR_GLOBAL },
   {&nsGkAtoms::aria_grabbed,                            ATTR_VALTOKEN | ATTR_GLOBAL },
   {&nsGkAtoms::aria_haspopup,          ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL },
-  {&nsGkAtoms::aria_hidden,   ATTR_BYPASSOBJ_IF_FALSE | ATTR_VALTOKEN | ATTR_GLOBAL },
+  {&nsGkAtoms::aria_hidden,            ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL }, /* handled special way */
   {&nsGkAtoms::aria_invalid,           ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL },
   {&nsGkAtoms::aria_label,             ATTR_BYPASSOBJ                 | ATTR_GLOBAL },
   {&nsGkAtoms::aria_labelledby,        ATTR_BYPASSOBJ                 | ATTR_GLOBAL },
   {&nsGkAtoms::aria_level,             ATTR_BYPASSOBJ                               }, /* handled via groupPosition */
   {&nsGkAtoms::aria_live,                               ATTR_VALTOKEN | ATTR_GLOBAL },
+  {&nsGkAtoms::aria_modal,             ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL },
   {&nsGkAtoms::aria_multiline,         ATTR_BYPASSOBJ | ATTR_VALTOKEN               },
   {&nsGkAtoms::aria_multiselectable,   ATTR_BYPASSOBJ | ATTR_VALTOKEN               },
   {&nsGkAtoms::aria_owns,              ATTR_BYPASSOBJ                 | ATTR_GLOBAL },
   {&nsGkAtoms::aria_orientation,                        ATTR_VALTOKEN               },
   {&nsGkAtoms::aria_posinset,          ATTR_BYPASSOBJ                               }, /* handled via groupPosition */
   {&nsGkAtoms::aria_pressed,           ATTR_BYPASSOBJ | ATTR_VALTOKEN               },
   {&nsGkAtoms::aria_readonly,          ATTR_BYPASSOBJ | ATTR_VALTOKEN               },
   {&nsGkAtoms::aria_relevant,          ATTR_BYPASSOBJ                 | ATTR_GLOBAL },
@@ -743,22 +857,20 @@ struct RoleComparator
   int operator()(const nsRoleMapEntry& aEntry) const {
     return Compare(mRole, aEntry.ARIARoleString());
   }
 };
 
 }
 
 nsRoleMapEntry*
-aria::GetRoleMap(nsINode* aNode)
+aria::GetRoleMap(dom::Element* aEl)
 {
-  nsIContent* content = nsCoreUtils::GetRoleContent(aNode);
   nsAutoString roles;
-  if (!content ||
-      !content->GetAttr(kNameSpaceID_None, nsGkAtoms::role, roles) ||
+  if (!aEl || !aEl->GetAttr(kNameSpaceID_None, nsGkAtoms::role, roles) ||
       roles.IsEmpty()) {
     // We treat role="" as if the role attribute is absent (per aria spec:8.1.1)
     return nullptr;
   }
 
   nsWhitespaceTokenizer tokenizer(roles);
   while (tokenizer.hasMoreTokens()) {
     // Do a binary search through table for the next role in role list
@@ -791,16 +903,25 @@ aria::AttrCharacteristicsFor(nsIAtom* aA
 {
   for (uint32_t i = 0; i < ArrayLength(gWAIUnivAttrMap); i++)
     if (*gWAIUnivAttrMap[i].attributeName == aAtom)
       return gWAIUnivAttrMap[i].characteristics;
 
   return 0;
 }
 
+bool
+aria::HasDefinedARIAHidden(nsIContent* aContent)
+{
+  return aContent &&
+    nsAccUtils::HasDefinedARIAToken(aContent, nsGkAtoms::aria_hidden) &&
+    !aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_hidden,
+                           nsGkAtoms::_false, eCaseMatters);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // AttrIterator class
 
 bool
 AttrIterator::Next(nsAString& aAttrName, nsAString& aAttrValue)
 {
   while (mAttrIdx < mAttrCount) {
     const nsAttrName* attr = mContent->GetAttrNameAt(mAttrIdx);
--- a/accessible/base/ARIAMap.h
+++ b/accessible/base/ARIAMap.h
@@ -205,52 +205,57 @@ extern nsRoleMapEntry gEmptyRoleMap;
 /**
  * Get the role map entry for a given DOM node. This will use the first
  * ARIA role if the role attribute provides a space delimited list of roles.
  *
  * @param aNode  [in] the DOM node to get the role map entry for
  * @return        a pointer to the role map entry for the ARIA role, or nullptr
  *                if none
  */
-nsRoleMapEntry* GetRoleMap(nsINode* aNode);
+nsRoleMapEntry* GetRoleMap(dom::Element* aEl);
 
 /**
  * Return accessible state from ARIA universal states applied to the given
  * element.
  */
 uint64_t UniversalStatesFor(mozilla::dom::Element* aElement);
 
 /**
  * Get the ARIA attribute characteristics for a given ARIA attribute.
  *
  * @param aAtom  ARIA attribute
  * @return       A bitflag representing the attribute characteristics
  *               (see above for possible bit masks, prefixed "ATTR_")
  */
 uint8_t AttrCharacteristicsFor(nsIAtom* aAtom);
 
+/**
+ * Return true if the element has defined aria-hidden.
+ */
+bool HasDefinedARIAHidden(nsIContent* aContent);
+
  /**
-  * Represents a simple enumerator for iterating through ARIA attributes 
-  * exposed as object attributes on a given accessible. 
+  * Represents a simple enumerator for iterating through ARIA attributes
+  * exposed as object attributes on a given accessible.
   */
 class AttrIterator
 {
 public:
-  explicit AttrIterator(nsIContent* aContent) : 
-    mContent(aContent), mAttrIdx(0) 
-  { 
+  explicit AttrIterator(nsIContent* aContent) :
+    mContent(aContent), mAttrIdx(0)
+  {
     mAttrCount = mContent->GetAttrCount();
   }
 
   bool Next(nsAString& aAttrName, nsAString& aAttrValue);
 
 private:
-  AttrIterator() MOZ_DELETE;
-  AttrIterator(const AttrIterator&) MOZ_DELETE;
-  AttrIterator& operator= (const AttrIterator&) MOZ_DELETE;
+  AttrIterator() = delete;
+  AttrIterator(const AttrIterator&) = delete;
+  AttrIterator& operator= (const AttrIterator&) = delete;
 
   nsIContent* mContent;
   uint32_t mAttrIdx;
   uint32_t mAttrCount;
 };
 
 } // namespace aria
 } // namespace a11y
--- a/accessible/base/ARIAStateMap.cpp
+++ b/accessible/base/ARIAStateMap.cpp
@@ -180,16 +180,26 @@ aria::MapToState(EStateRule aRule, dom::
       static const TokenTypeData data(
         nsGkAtoms::aria_invalid, eBoolType,
         0, states::INVALID);
 
       MapTokenType(aElement, aState, data);
       return true;
     }
 
+    case eARIAModal:
+    {
+      static const TokenTypeData data(
+        nsGkAtoms::aria_modal, eBoolType,
+        0, states::MODAL);
+
+      MapTokenType(aElement, aState, data);
+      return true;
+    }
+
     case eARIAMultiline:
     {
       static const TokenTypeData data(
         nsGkAtoms::aria_multiline, eBoolType | eDefinedIfAbsent,
         0, states::MULTI_LINE, states::SINGLE_LINE);
 
       MapTokenType(aElement, aState, data);
       return true;
--- a/accessible/base/ARIAStateMap.h
+++ b/accessible/base/ARIAStateMap.h
@@ -28,16 +28,17 @@ enum EStateRule
   eARIABusy,
   eARIACheckableBool,
   eARIACheckableMixed,
   eARIACheckedMixed,
   eARIADisabled,
   eARIAExpanded,
   eARIAHasPopup,
   eARIAInvalid,
+  eARIAModal,
   eARIAMultiline,
   eARIAMultiSelectable,
   eARIAOrientation,
   eARIAPressed,
   eARIAReadonly,
   eARIAReadonlyOrEditable,
   eARIAReadonlyOrEditableIfDefined,
   eARIARequired,
--- a/accessible/base/AccCollector.cpp
+++ b/accessible/base/AccCollector.cpp
@@ -97,21 +97,23 @@ AccCollector::AppendObject(Accessible* a
 ////////////////////////////////////////////////////////////////////////////////
 
 int32_t
 EmbeddedObjCollector::GetIndexAt(Accessible* aAccessible)
 {
   if (aAccessible->mParent != mRoot)
     return -1;
 
-  if (aAccessible->mIndexOfEmbeddedChild != -1)
-    return aAccessible->mIndexOfEmbeddedChild;
+  MOZ_ASSERT(!aAccessible->IsProxy());
+  if (aAccessible->mInt.mIndexOfEmbeddedChild != -1)
+    return aAccessible->mInt.mIndexOfEmbeddedChild;
 
   return mFilterFunc(aAccessible) & filters::eMatch ?
     EnsureNGetIndex(aAccessible) : -1;
 }
 
 void
 EmbeddedObjCollector::AppendObject(Accessible* aAccessible)
 {
-  aAccessible->mIndexOfEmbeddedChild = mObjects.Length();
+  MOZ_ASSERT(!aAccessible->IsProxy());
+  aAccessible->mInt.mIndexOfEmbeddedChild = mObjects.Length();
   mObjects.AppendElement(aAccessible);
 }
--- a/accessible/base/AccCollector.h
+++ b/accessible/base/AccCollector.h
@@ -66,30 +66,30 @@ private:
   AccCollector(const AccCollector&);
   AccCollector& operator =(const AccCollector&);
 };
 
 /**
  * Collect embedded objects. Provide quick access to accessible by index and
  * vice versa.
  */
-class EmbeddedObjCollector MOZ_FINAL : public AccCollector
+class EmbeddedObjCollector final : public AccCollector
 {
 public:
   virtual ~EmbeddedObjCollector() { }
 
 public:
-  virtual int32_t GetIndexAt(Accessible* aAccessible);
+  virtual int32_t GetIndexAt(Accessible* aAccessible) override;
 
 protected:
   // Make sure it's used by Accessible class only.
   explicit EmbeddedObjCollector(Accessible* aRoot) :
     AccCollector(aRoot, filters::GetEmbeddedObject) { }
 
-  virtual void AppendObject(Accessible* aAccessible);
+  virtual void AppendObject(Accessible* aAccessible) override;
 
   friend class Accessible;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/base/AccEvent.cpp
+++ b/accessible/base/AccEvent.cpp
@@ -99,31 +99,32 @@ AccReorderEvent::IsShowHideEventTarget(c
   return 0;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccHideEvent
 ////////////////////////////////////////////////////////////////////////////////
 
 AccHideEvent::
-  AccHideEvent(Accessible* aTarget, nsINode* aTargetNode) :
-  AccMutationEvent(::nsIAccessibleEvent::EVENT_HIDE, aTarget, aTargetNode)
+  AccHideEvent(Accessible* aTarget, bool aNeedsShutdown) :
+  AccMutationEvent(::nsIAccessibleEvent::EVENT_HIDE, aTarget),
+  mNeedsShutdown(aNeedsShutdown)
 {
   mNextSibling = mAccessible->NextSibling();
   mPrevSibling = mAccessible->PrevSibling();
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccShowEvent
 ////////////////////////////////////////////////////////////////////////////////
 
 AccShowEvent::
-  AccShowEvent(Accessible* aTarget, nsINode* aTargetNode) :
-  AccMutationEvent(::nsIAccessibleEvent::EVENT_SHOW, aTarget, aTargetNode)
+  AccShowEvent(Accessible* aTarget) :
+  AccMutationEvent(::nsIAccessibleEvent::EVENT_SHOW, aTarget)
 {
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccTextSelChangeEvent
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -134,17 +135,17 @@ AccTextSelChangeEvent::AccTextSelChangeE
            eAutoDetect, eCoalesceTextSelChange),
   mSel(aSelection), mReason(aReason) {}
 
 AccTextSelChangeEvent::~AccTextSelChangeEvent() { }
 
 bool
 AccTextSelChangeEvent::IsCaretMoveOnly() const
 {
-  return mSel->GetRangeCount() == 1 && mSel->IsCollapsed() &&
+  return mSel->RangeCount() == 1 && mSel->IsCollapsed() &&
     ((mReason & (nsISelectionListener::COLLAPSETOSTART_REASON |
                  nsISelectionListener::COLLAPSETOEND_REASON)) == 0);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccSelChangeEvent
 ////////////////////////////////////////////////////////////////////////////////
 
--- a/accessible/base/AccEvent.h
+++ b/accessible/base/AccEvent.h
@@ -122,17 +122,17 @@ public:
   NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(AccEvent)
 
 protected:
   virtual ~AccEvent() {}
 
   bool mIsFromUserInput;
   uint32_t mEventType;
   EEventRule mEventRule;
-  nsRefPtr<Accessible> mAccessible;
+  RefPtr<Accessible> mAccessible;
 
   friend class EventQueue;
   friend class AccReorderEvent;
 };
 
 
 /**
  * Accessible state change event.
@@ -149,17 +149,17 @@ public:
 
   AccStateChangeEvent(Accessible* aAccessible, uint64_t aState) :
     AccEvent(::nsIAccessibleEvent::EVENT_STATE_CHANGE, aAccessible,
              eAutoDetect, eCoalesceStateChange), mState(aState)
     { mIsEnabled = (mAccessible->State() & mState) != 0; }
 
   // AccEvent
   static const EventGroup kEventGroup = eStateChangeEvent;
-  virtual unsigned int GetEventGroups() const
+  virtual unsigned int GetEventGroups() const override
   {
     return AccEvent::GetEventGroups() | (1U << eStateChangeEvent);
   }
 
   // AccStateChangeEvent
   uint64_t GetState() const { return mState; }
   bool IsStateEnabled() const { return mIsEnabled; }
 
@@ -178,27 +178,28 @@ class AccTextChangeEvent: public AccEven
 {
 public:
   AccTextChangeEvent(Accessible* aAccessible, int32_t aStart,
                      const nsAString& aModifiedText, bool aIsInserted,
                      EIsFromUserInput aIsFromUserInput = eAutoDetect);
 
   // AccEvent
   static const EventGroup kEventGroup = eTextChangeEvent;
-  virtual unsigned int GetEventGroups() const
+  virtual unsigned int GetEventGroups() const override
   {
     return AccEvent::GetEventGroups() | (1U << eTextChangeEvent);
   }
 
   // AccTextChangeEvent
   int32_t GetStartOffset() const { return mStart; }
   uint32_t GetLength() const { return mModifiedText.Length(); }
   bool IsTextInserted() const { return mIsInserted; }
   void GetModifiedText(nsAString& aModifiedText)
     { aModifiedText = mModifiedText; }
+  const nsString& ModifiedText() const { return mModifiedText; }
 
 private:
   int32_t mStart;
   bool mIsInserted;
   nsString mModifiedText;
 
   friend class EventQueue;
   friend class AccReorderEvent;
@@ -206,87 +207,88 @@ private:
 
 
 /**
  * Base class for show and hide accessible events.
  */
 class AccMutationEvent: public AccEvent
 {
 public:
-  AccMutationEvent(uint32_t aEventType, Accessible* aTarget,
-                   nsINode* aTargetNode) :
+  AccMutationEvent(uint32_t aEventType, Accessible* aTarget) :
     AccEvent(aEventType, aTarget, eAutoDetect, eCoalesceMutationTextChange)
   {
     // Don't coalesce these since they are coalesced by reorder event. Coalesce
     // contained text change events.
     mParent = mAccessible->Parent();
   }
   virtual ~AccMutationEvent() { }
 
   // Event
   static const EventGroup kEventGroup = eMutationEvent;
-  virtual unsigned int GetEventGroups() const
+  virtual unsigned int GetEventGroups() const override
   {
     return AccEvent::GetEventGroups() | (1U << eMutationEvent);
   }
 
   // MutationEvent
   bool IsShow() const { return mEventType == nsIAccessibleEvent::EVENT_SHOW; }
   bool IsHide() const { return mEventType == nsIAccessibleEvent::EVENT_HIDE; }
 
   Accessible* Parent() const { return mParent; }
 
 protected:
   nsCOMPtr<nsINode> mNode;
-  nsRefPtr<Accessible> mParent;
-  nsRefPtr<AccTextChangeEvent> mTextChangeEvent;
+  RefPtr<Accessible> mParent;
+  RefPtr<AccTextChangeEvent> mTextChangeEvent;
 
   friend class EventQueue;
 };
 
 
 /**
  * Accessible hide event.
  */
 class AccHideEvent: public AccMutationEvent
 {
 public:
-  AccHideEvent(Accessible* aTarget, nsINode* aTargetNode);
+  explicit AccHideEvent(Accessible* aTarget, bool aNeedsShutdown = true);
 
   // Event
   static const EventGroup kEventGroup = eHideEvent;
-  virtual unsigned int GetEventGroups() const
+  virtual unsigned int GetEventGroups() const override
   {
     return AccMutationEvent::GetEventGroups() | (1U << eHideEvent);
   }
 
   // AccHideEvent
   Accessible* TargetParent() const { return mParent; }
   Accessible* TargetNextSibling() const { return mNextSibling; }
   Accessible* TargetPrevSibling() const { return mPrevSibling; }
+  bool NeedsShutdown() const { return mNeedsShutdown; }
 
 protected:
-  nsRefPtr<Accessible> mNextSibling;
-  nsRefPtr<Accessible> mPrevSibling;
+  bool mNeedsShutdown;
+  RefPtr<Accessible> mNextSibling;
+  RefPtr<Accessible> mPrevSibling;
 
   friend class EventQueue;
 };
 
 
 /**
  * Accessible show event.
  */
 class AccShowEvent: public AccMutationEvent
 {
 public:
-  AccShowEvent(Accessible* aTarget, nsINode* aTargetNode);
+  explicit AccShowEvent(Accessible* aTarget);
 
   // Event
   static const EventGroup kEventGroup = eShowEvent;
-  virtual unsigned int GetEventGroups() const
+  virtual unsigned int GetEventGroups() const override
   {
     return AccMutationEvent::GetEventGroups() | (1U << eShowEvent);
   }
 };
 
 
 /**
  * Class for reorder accessible event. Takes care about
@@ -296,17 +298,17 @@ class AccReorderEvent : public AccEvent
 public:
   explicit AccReorderEvent(Accessible* aTarget) :
     AccEvent(::nsIAccessibleEvent::EVENT_REORDER, aTarget,
              eAutoDetect, eCoalesceReorder) { }
   virtual ~AccReorderEvent() { }
 
   // Event
   static const EventGroup kEventGroup = eReorderEvent;
-  virtual unsigned int GetEventGroups() const
+  virtual unsigned int GetEventGroups() const override
   {
     return AccEvent::GetEventGroups() | (1U << eReorderEvent);
   }
 
   /**
    * Get connected with mutation event.
    */
   void AddSubMutationEvent(AccMutationEvent* aEvent)
@@ -349,17 +351,17 @@ public:
                     EIsFromUserInput aIsFromUserInput = eAutoDetect) :
     AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aAccessible,
              aIsFromUserInput),
     mCaretOffset(aCaretOffset) { }
   virtual ~AccCaretMoveEvent() { }
 
   // AccEvent
   static const EventGroup kEventGroup = eCaretMoveEvent;
-  virtual unsigned int GetEventGroups() const
+  virtual unsigned int GetEventGroups() const override
   {
     return AccEvent::GetEventGroups() | (1U << eCaretMoveEvent);
   }
 
   // AccCaretMoveEvent
   int32_t GetCaretOffset() const { return mCaretOffset; }
 
 private:
@@ -375,30 +377,30 @@ class AccTextSelChangeEvent : public Acc
 public:
   AccTextSelChangeEvent(HyperTextAccessible* aTarget,
                         dom::Selection* aSelection,
                         int32_t aReason);
   virtual ~AccTextSelChangeEvent();
 
   // AccEvent
   static const EventGroup kEventGroup = eTextSelChangeEvent;
-  virtual unsigned int GetEventGroups() const
+  virtual unsigned int GetEventGroups() const override
   {
     return AccEvent::GetEventGroups() | (1U << eTextSelChangeEvent);
   }
 
   // AccTextSelChangeEvent
 
   /**
    * Return true if the text selection change wasn't caused by pure caret move.
    */
   bool IsCaretMoveOnly() const;
 
 private:
-  nsRefPtr<dom::Selection> mSel;
+  RefPtr<dom::Selection> mSel;
   int32_t mReason;
 
   friend class EventQueue;
   friend class SelectionManager;
 };
 
 
 /**
@@ -414,27 +416,27 @@ public:
 
   AccSelChangeEvent(Accessible* aWidget, Accessible* aItem,
                     SelChangeType aSelChangeType);
 
   virtual ~AccSelChangeEvent() { }
 
   // AccEvent
   static const EventGroup kEventGroup = eSelectionChangeEvent;
-  virtual unsigned int GetEventGroups() const
+  virtual unsigned int GetEventGroups() const override
   {
     return AccEvent::GetEventGroups() | (1U << eSelectionChangeEvent);
   }
 
   // AccSelChangeEvent
   Accessible* Widget() const { return mWidget; }
 
 private:
-  nsRefPtr<Accessible> mWidget;
-  nsRefPtr<Accessible> mItem;
+  RefPtr<Accessible> mWidget;
+  RefPtr<Accessible> mItem;
   SelChangeType mSelChangeType;
   uint32_t mPreceedingCount;
   AccSelChangeEvent* mPackedEvent;
 
   friend class EventQueue;
 };
 
 
@@ -444,17 +446,17 @@ private:
 class AccTableChangeEvent : public AccEvent
 {
 public:
   AccTableChangeEvent(Accessible* aAccessible, uint32_t aEventType,
                       int32_t aRowOrColIndex, int32_t aNumRowsOrCols);
 
   // AccEvent
   static const EventGroup kEventGroup = eTableChangeEvent;
-  virtual unsigned int GetEventGroups() const
+  virtual unsigned int GetEventGroups() const override
   {
     return AccEvent::GetEventGroups() | (1U << eTableChangeEvent);
   }
 
   // AccTableChangeEvent
   uint32_t GetIndex() const { return mRowOrColIndex; }
   uint32_t GetCount() const { return mNumRowsOrCols; }
 
@@ -474,29 +476,29 @@ public:
                    int32_t aOldStart, int32_t aOldEnd,
                    int16_t aReason,
                    EIsFromUserInput aIsFromUserInput = eFromUserInput);
 
   virtual ~AccVCChangeEvent() { }
 
   // AccEvent
   static const EventGroup kEventGroup = eVirtualCursorChangeEvent;
-  virtual unsigned int GetEventGroups() const
+  virtual unsigned int GetEventGroups() const override
   {
     return AccEvent::GetEventGroups() | (1U << eVirtualCursorChangeEvent);
   }
 
   // AccTableChangeEvent
   Accessible* OldAccessible() const { return mOldAccessible; }
   int32_t OldStartOffset() const { return mOldStart; }
   int32_t OldEndOffset() const { return mOldEnd; }
   int32_t Reason() const { return mReason; }
 
 private:
-  nsRefPtr<Accessible> mOldAccessible;
+  RefPtr<Accessible> mOldAccessible;
   int32_t mOldStart;
   int32_t mOldEnd;
   int16_t mReason;
 };
 
 /**
  * Accessible object attribute changed event.
  */
@@ -504,17 +506,17 @@ class AccObjectAttrChangedEvent: public 
 {
 public:
   AccObjectAttrChangedEvent(Accessible* aAccessible, nsIAtom* aAttribute) :
     AccEvent(::nsIAccessibleEvent::EVENT_OBJECT_ATTRIBUTE_CHANGED, aAccessible),
     mAttribute(aAttribute) { }
 
   // AccEvent
   static const EventGroup kEventGroup = eObjectAttrChangedEvent;
-  virtual unsigned int GetEventGroups() const
+  virtual unsigned int GetEventGroups() const override
   {
     return AccEvent::GetEventGroups() | (1U << eObjectAttrChangedEvent);
   }
 
   // AccObjectAttrChangedEvent
   nsIAtom* GetAttribute() const { return mAttribute; }
 
 private:
--- a/accessible/base/AccGroupInfo.cpp
+++ b/accessible/base/AccGroupInfo.cpp
@@ -59,20 +59,20 @@ AccGroupInfo::Update()
     }
 
     // Skip subset.
     if (siblingLevel > level)
       continue;
 
     // If the previous item in the group has calculated group information then
     // build group information for this item based on found one.
-    if (sibling->mGroupInfo) {
-      mPosInSet += sibling->mGroupInfo->mPosInSet;
-      mParent = sibling->mGroupInfo->mParent;
-      mSetSize = sibling->mGroupInfo->mSetSize;
+    if (sibling->mBits.groupInfo) {
+      mPosInSet += sibling->mBits.groupInfo->mPosInSet;
+      mParent = sibling->mBits.groupInfo->mParent;
+      mSetSize = sibling->mBits.groupInfo->mSetSize;
       return;
     }
 
     mPosInSet++;
   }
 
   // Compute set size.
   mSetSize = mPosInSet;
@@ -96,19 +96,19 @@ AccGroupInfo::Update()
       break;
 
     // Skip subset.
     if (siblingLevel > level)
       continue;
 
     // If the next item in the group has calculated group information then
     // build group information for this item based on found one.
-    if (sibling->mGroupInfo) {
-      mParent = sibling->mGroupInfo->mParent;
-      mSetSize = sibling->mGroupInfo->mSetSize;
+    if (sibling->mBits.groupInfo) {
+      mParent = sibling->mBits.groupInfo->mParent;
+      mSetSize = sibling->mBits.groupInfo->mSetSize;
       return;
     }
 
     mSetSize++;
   }
 
   if (mParent)
     return;
--- a/accessible/base/AccGroupInfo.h
+++ b/accessible/base/AccGroupInfo.h
@@ -73,19 +73,19 @@ public:
    * Return next item of the same group to the given item.
    */
   static Accessible* NextItemTo(Accessible* aItem);
 
 protected:
   AccGroupInfo(Accessible* aItem, a11y::role aRole);
 
 private:
-  AccGroupInfo() MOZ_DELETE;
-  AccGroupInfo(const AccGroupInfo&) MOZ_DELETE;
-  AccGroupInfo& operator =(const AccGroupInfo&) MOZ_DELETE;
+  AccGroupInfo() = delete;
+  AccGroupInfo(const AccGroupInfo&) = delete;
+  AccGroupInfo& operator =(const AccGroupInfo&) = delete;
 
   static mozilla::a11y::role BaseRole(mozilla::a11y::role aRole)
   {
     if (aRole == mozilla::a11y::roles::CHECK_MENU_ITEM ||
         aRole == mozilla::a11y::roles::PARENT_MENUITEM ||
         aRole == mozilla::a11y::roles::RADIO_MENU_ITEM)
       return mozilla::a11y::roles::MENUITEM;
 
--- a/accessible/base/AccIterator.cpp
+++ b/accessible/base/AccIterator.cpp
@@ -4,17 +4,17 @@
 
 #include "AccIterator.h"
 
 #include "AccGroupInfo.h"
 #ifdef MOZ_XUL
 #include "XULTreeAccessible.h"
 #endif
 
-#include "mozilla/dom/Element.h"
+#include "mozilla/dom/HTMLLabelElement.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccIterator
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -129,47 +129,54 @@ RelatedAccIterator::Next()
 HTMLLabelIterator::
   HTMLLabelIterator(DocAccessible* aDocument, const Accessible* aAccessible,
                     LabelFilter aFilter) :
   mRelIter(aDocument, aAccessible->GetContent(), nsGkAtoms::_for),
   mAcc(aAccessible), mLabelFilter(aFilter)
 {
 }
 
+bool
+HTMLLabelIterator::IsLabel(Accessible* aLabel)
+{
+  dom::HTMLLabelElement* labelEl =
+    dom::HTMLLabelElement::FromContent(aLabel->GetContent());
+  return labelEl && labelEl->GetControl() == mAcc->GetContent();
+}
+
 Accessible*
 HTMLLabelIterator::Next()
 {
   // Get either <label for="[id]"> element which explicitly points to given
   // element, or <label> ancestor which implicitly point to it.
   Accessible* label = nullptr;
   while ((label = mRelIter.Next())) {
-    if (label->GetContent()->Tag() == nsGkAtoms::label)
+    if (IsLabel(label)) {
       return label;
+    }
   }
 
   // Ignore ancestor label on not widget accessible.
   if (mLabelFilter == eSkipAncestorLabel || !mAcc->IsWidget())
     return nullptr;
 
   // Go up tree to get a name of ancestor label if there is one (an ancestor
   // <label> implicitly points to us). Don't go up farther than form or
   // document.
   Accessible* walkUp = mAcc->Parent();
   while (walkUp && !walkUp->IsDoc()) {
-    nsIContent* walkUpElm = walkUp->GetContent();
-    if (walkUpElm->IsHTML()) {
-      if (walkUpElm->Tag() == nsGkAtoms::label &&
-          !walkUpElm->HasAttr(kNameSpaceID_None, nsGkAtoms::_for)) {
-        mLabelFilter = eSkipAncestorLabel; // prevent infinite loop
-        return walkUp;
-      }
+    nsIContent* walkUpEl = walkUp->GetContent();
+    if (IsLabel(walkUp) &&
+        !walkUpEl->HasAttr(kNameSpaceID_None, nsGkAtoms::_for)) {
+      mLabelFilter = eSkipAncestorLabel; // prevent infinite loop
+      return walkUp;
+    }
 
-      if (walkUpElm->Tag() == nsGkAtoms::form)
-        break;
-    }
+    if (walkUpEl->IsHTMLElement(nsGkAtoms::form))
+      break;
 
     walkUp = walkUp->Parent();
   }
 
   return nullptr;
 }
 
 
@@ -183,17 +190,17 @@ HTMLOutputIterator(DocAccessible* aDocum
 {
 }
 
 Accessible*
 HTMLOutputIterator::Next()
 {
   Accessible* output = nullptr;
   while ((output = mRelIter.Next())) {
-    if (output->GetContent()->Tag() == nsGkAtoms::output)
+    if (output->GetContent()->IsHTMLElement(nsGkAtoms::output))
       return output;
   }
 
   return nullptr;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -206,17 +213,17 @@ XULLabelIterator::
 {
 }
 
 Accessible*
 XULLabelIterator::Next()
 {
   Accessible* label = nullptr;
   while ((label = mRelIter.Next())) {
-    if (label->GetContent()->Tag() == nsGkAtoms::label)
+    if (label->GetContent()->IsXULElement(nsGkAtoms::label))
       return label;
   }
 
   return nullptr;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -229,17 +236,17 @@ XULDescriptionIterator::
 {
 }
 
 Accessible*
 XULDescriptionIterator::Next()
 {
   Accessible* descr = nullptr;
   while ((descr = mRelIter.Next())) {
-    if (descr->GetContent()->Tag() == nsGkAtoms::description)
+    if (descr->GetContent()->IsXULElement(nsGkAtoms::description))
       return descr;
   }
 
   return nullptr;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // IDRefsIterator
@@ -321,31 +328,40 @@ IDRefsIterator::GetElem(const nsDependen
   }
 
   return nullptr;
 }
 
 Accessible*
 IDRefsIterator::Next()
 {
-  nsIContent* nextElm = NextElem();
-  return nextElm ? mDoc->GetAccessible(nextElm) : nullptr;
+  nsIContent* nextEl = nullptr;
+  while ((nextEl = NextElem())) {
+    Accessible* acc = mDoc->GetAccessible(nextEl);
+    if (acc) {
+      return acc;
+    }
+  }
+  return nullptr;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // SingleAccIterator
 ////////////////////////////////////////////////////////////////////////////////
 
 Accessible*
 SingleAccIterator::Next()
 {
-  nsRefPtr<Accessible> nextAcc;
+  RefPtr<Accessible> nextAcc;
   mAcc.swap(nextAcc);
-  return (nextAcc && !nextAcc->IsDefunct()) ? nextAcc : nullptr;
+  if (!nextAcc || nextAcc->IsDefunct()) {
+    return nullptr;
+  }
+  return nextAcc;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // ItemIterator
 ////////////////////////////////////////////////////////////////////////////////
 
 Accessible*
--- a/accessible/base/AccIterator.h
+++ b/accessible/base/AccIterator.h
@@ -38,17 +38,17 @@ class AccIterator : public AccIterable
 public:
   AccIterator(Accessible* aRoot, filters::FilterFuncPtr aFilterFunc);
   virtual ~AccIterator();
 
   /**
    * Return next accessible complying with filter function. Return the first
    * accessible for the first time.
    */
-  virtual Accessible* Next();
+  virtual Accessible* Next() override;
 
 private:
   AccIterator();
   AccIterator(const AccIterator&);
   AccIterator& operator =(const AccIterator&);
 
   struct IteratorState
   {
@@ -84,17 +84,17 @@ public:
   RelatedAccIterator(DocAccessible* aDocument, nsIContent* aDependentContent,
                      nsIAtom* aRelAttr);
 
   virtual ~RelatedAccIterator() { }
 
   /**
    * Return next related accessible for the given dependent accessible.
    */
-  virtual Accessible* Next();
+  virtual Accessible* Next() override;
 
 private:
   RelatedAccIterator();
   RelatedAccIterator(const RelatedAccIterator&);
   RelatedAccIterator& operator = (const RelatedAccIterator&);
 
   DocAccessible* mDocument;
   nsIAtom* mRelAttr;
@@ -118,23 +118,25 @@ public:
   HTMLLabelIterator(DocAccessible* aDocument, const Accessible* aAccessible,
                     LabelFilter aFilter = eAllLabels);
 
   virtual ~HTMLLabelIterator() { }
 
   /**
    * Return next label accessible associated with the given element.
    */
-  virtual Accessible* Next();
+  virtual Accessible* Next() override;
 
 private:
   HTMLLabelIterator();
   HTMLLabelIterator(const HTMLLabelIterator&);
   HTMLLabelIterator& operator = (const HTMLLabelIterator&);
 
+  bool IsLabel(Accessible* aLabel);
+
   RelatedAccIterator mRelIter;
   // XXX: replace it on weak reference (bug 678429), it's safe to use raw
   // pointer now because iterators life cycle is short.
   const Accessible* mAcc;
   LabelFilter mLabelFilter;
 };
 
 
@@ -145,17 +147,17 @@ class HTMLOutputIterator : public AccIte
 {
 public:
   HTMLOutputIterator(DocAccessible* aDocument, nsIContent* aElement);
   virtual ~HTMLOutputIterator() { }
 
   /**
    * Return next output accessible associated with the given element.
    */
-  virtual Accessible* Next();
+  virtual Accessible* Next() override;
 
 private:
   HTMLOutputIterator();
   HTMLOutputIterator(const HTMLOutputIterator&);
   HTMLOutputIterator& operator = (const HTMLOutputIterator&);
 
   RelatedAccIterator mRelIter;
 };
@@ -168,17 +170,17 @@ class XULLabelIterator : public AccItera
 {
 public:
   XULLabelIterator(DocAccessible* aDocument, nsIContent* aElement);
   virtual ~XULLabelIterator() { }
 
   /**
    * Return next label accessible associated with the given element.
    */
-  virtual Accessible* Next();
+  virtual Accessible* Next() override;
 
 private:
   XULLabelIterator();
   XULLabelIterator(const XULLabelIterator&);
   XULLabelIterator& operator = (const XULLabelIterator&);
 
   RelatedAccIterator mRelIter;
 };
@@ -191,17 +193,17 @@ class XULDescriptionIterator : public Ac
 {
 public:
   XULDescriptionIterator(DocAccessible* aDocument, nsIContent* aElement);
   virtual ~XULDescriptionIterator() { }
 
   /**
    * Return next description accessible associated with the given element.
    */
-  virtual Accessible* Next();
+  virtual Accessible* Next() override;
 
 private:
   XULDescriptionIterator();
   XULDescriptionIterator(const XULDescriptionIterator&);
   XULDescriptionIterator& operator = (const XULDescriptionIterator&);
 
   RelatedAccIterator mRelIter;
 };
@@ -229,88 +231,89 @@ public:
   nsIContent* NextElem();
 
   /**
    * Return the element with the given ID.
    */
   nsIContent* GetElem(const nsDependentSubstring& aID);
 
   // AccIterable
-  virtual Accessible* Next();
+  virtual Accessible* Next() override;
 
 private:
   IDRefsIterator();
   IDRefsIterator(const IDRefsIterator&);
   IDRefsIterator operator = (const IDRefsIterator&);
 
   nsString mIDs;
   nsIContent* mContent;
   DocAccessible* mDoc;
   nsAString::index_type mCurrIdx;
 };
 
+
 /**
  * Iterator that points to a single accessible returning it on the first call
  * to Next().
  */
 class SingleAccIterator : public AccIterable
 {
 public:
   explicit SingleAccIterator(Accessible* aTarget): mAcc(aTarget) { }
   virtual ~SingleAccIterator() { }
 
-  virtual Accessible* Next();
+  virtual Accessible* Next() override;
 
 private:
   SingleAccIterator();
   SingleAccIterator(const SingleAccIterator&);
   SingleAccIterator& operator = (const SingleAccIterator&);
 
-  nsRefPtr<Accessible> mAcc;
+  RefPtr<Accessible> mAcc;
 };
 
 
 /**
  * Used to iterate items of the given item container.
  */
 class ItemIterator : public AccIterable
 {
 public:
   explicit ItemIterator(Accessible* aItemContainer) :
     mContainer(aItemContainer), mAnchor(nullptr) { }
   virtual ~ItemIterator() { }
 
-  virtual Accessible* Next();
+  virtual Accessible* Next() override;
 
 private:
-  ItemIterator() MOZ_DELETE;
-  ItemIterator(const ItemIterator&) MOZ_DELETE;
-  ItemIterator& operator = (const ItemIterator&) MOZ_DELETE;
+  ItemIterator() = delete;
+  ItemIterator(const ItemIterator&) = delete;
+  ItemIterator& operator = (const ItemIterator&) = delete;
 
   Accessible* mContainer;
   Accessible* mAnchor;
 };
 
 
 /**
  * Used to iterate through XUL tree items of the same level.
  */
 class XULTreeItemIterator : public AccIterable
 {
 public:
   XULTreeItemIterator(XULTreeAccessible* aXULTree, nsITreeView* aTreeView,
                       int32_t aRowIdx);
   virtual ~XULTreeItemIterator() { }
 
-  virtual Accessible* Next();
+  virtual Accessible* Next() override;
 
 private:
-  XULTreeItemIterator() MOZ_DELETE;
-  XULTreeItemIterator(const XULTreeItemIterator&) MOZ_DELETE;
-  XULTreeItemIterator& operator = (const XULTreeItemIterator&) MOZ_DELETE;
+  XULTreeItemIterator() = delete;
+  XULTreeItemIterator(const XULTreeItemIterator&) = delete;
+  XULTreeItemIterator& operator = (const XULTreeItemIterator&) = delete;
 
   XULTreeAccessible* mXULTree;
   nsITreeView* mTreeView;
   int32_t mRowCount;
   int32_t mContainerLevel;
   int32_t mCurrRowIdx;
 };
 
--- a/accessible/base/AccTypes.h
+++ b/accessible/base/AccTypes.h
@@ -47,44 +47,47 @@ enum AccType {
 
   /**
    * Other accessible types.
    */
   eApplicationType,
   eHTMLOptGroupType,
   eImageMapType,
   eMenuPopupType,
+  eProxyType,
   eProgressType,
   eRootType,
   eXULLabelType,
   eXULListItemType,
   eXULTabpanelsType,
   eXULTreeType,
 
   eLastAccType = eXULTreeType
 };
 
 /**
  * Generic accessible type, different accessible classes can share the same
  * type, the same accessible class can have several types.
  */
 enum AccGenericType {
-  eAutoComplete = 1 << 0,
-  eAutoCompletePopup = 1 << 1,
-  eButton = 1 << 2,
-  eCombobox = 1 << 3,
-  eDocument = 1 << 4,
-  eHyperText = 1 << 5,
-  eList = 1 << 6,
-  eListControl = 1 << 7,
-  eMenuButton = 1 << 8,
-  eSelect = 1 << 9,
-  eTable = 1 << 10,
-  eTableCell = 1 << 11,
-  eTableRow = 1 << 12,
+  eAlert = 1 << 0,
+  eAutoComplete = 1 << 1,
+  eAutoCompletePopup = 1 << 2,
+  eButton = 1 << 3,
+  eCombobox = 1 << 4,
+  eDocument = 1 << 5,
+  eHyperText = 1 << 6,
+  eLandmark = 1 << 7,
+  eList = 1 << 8,
+  eListControl = 1 << 9,
+  eMenuButton = 1 << 10,
+  eSelect = 1 << 11,
+  eTable = 1 << 12,
+  eTableCell = 1 << 13,
+  eTableRow = 1 << 14,
 
   eLastAccGenericType = eTableRow
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif // mozilla_a11y_AccTypes_h
new file mode 100644
--- /dev/null
+++ b/accessible/base/AccessibleOrProxy.h
@@ -0,0 +1,121 @@
+/* -*- 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/. */
+
+#ifndef mozilla_a11y_AccessibleOrProxy_h
+#define mozilla_a11y_AccessibleOrProxy_h
+
+#include "mozilla/a11y/Accessible.h"
+#include "mozilla/a11y/ProxyAccessible.h"
+#include "mozilla/a11y/Role.h"
+
+#include <stdint.h>
+
+namespace mozilla {
+namespace a11y {
+
+/**
+ * This class stores an Accessible* or a ProxyAccessible* in a safe manner
+ * with size sizeof(void*).
+ */
+class AccessibleOrProxy
+{
+public:
+  MOZ_IMPLICIT AccessibleOrProxy(Accessible* aAcc) :
+    mBits(reinterpret_cast<uintptr_t>(aAcc)) {}
+  MOZ_IMPLICIT AccessibleOrProxy(ProxyAccessible* aProxy) :
+    mBits(reinterpret_cast<uintptr_t>(aProxy) | IS_PROXY) {}
+  MOZ_IMPLICIT AccessibleOrProxy(decltype(nullptr)) : mBits(0) {}
+
+  bool IsProxy() const { return mBits & IS_PROXY; }
+  ProxyAccessible* AsProxy() const
+  {
+    if (IsProxy()) {
+      return reinterpret_cast<ProxyAccessible*>(mBits & ~IS_PROXY);
+    }
+
+    return nullptr;
+  }
+
+  bool IsAccessible() const { return !IsProxy(); }
+  Accessible* AsAccessible() const
+  {
+    if (IsAccessible()) {
+      return reinterpret_cast<Accessible*>(mBits);
+    }
+
+    return nullptr;
+  }
+
+  bool IsNull() const { return mBits == 0; }
+
+  uint32_t ChildCount() const
+  {
+    if (IsProxy()) {
+      return AsProxy()->ChildrenCount();
+    }
+
+    return AsAccessible()->ChildCount();
+  }
+
+  /**
+   * Return the child object either an accessible or a proxied accessible at
+   * the given index.
+   */
+  AccessibleOrProxy ChildAt(uint32_t aIdx)
+  {
+    if (IsProxy()) {
+      return AsProxy()->ChildAt(aIdx);
+    }
+
+    return AsAccessible()->GetChildAt(aIdx);
+  }
+
+  /**
+   * Return the first child object.
+   */
+  AccessibleOrProxy FirstChild()
+  {
+    if (IsProxy()) {
+      return AsProxy()->FirstChild();
+    }
+
+    return AsAccessible()->FirstChild();
+  }
+
+  /**
+   * Return the first child object.
+   */
+  AccessibleOrProxy LastChild()
+  {
+    if (IsProxy()) {
+      return AsProxy()->LastChild();
+    }
+
+    return AsAccessible()->LastChild();
+  }
+
+  role Role() const
+  {
+    if (IsProxy()) {
+      return AsProxy()->Role();
+    }
+
+    return AsAccessible()->Role();
+  }
+
+  // XXX these are implementation details that ideally would not be exposed.
+  uintptr_t Bits() const { return mBits; }
+  void SetBits(uintptr_t aBits) { mBits = aBits; }
+
+private:
+  uintptr_t mBits;
+  static const uintptr_t IS_PROXY = 0x1;
+};
+
+}
+}
+
+#endif
--- a/accessible/base/DocManager.cpp
+++ b/accessible/base/DocManager.cpp
@@ -1,46 +1,52 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=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 "DocManager.h"
 
 #include "ApplicationAccessible.h"
 #include "ARIAMap.h"
 #include "DocAccessible-inl.h"
 #include "DocAccessibleChild.h"
+#include "DocAccessibleParent.h"
 #include "nsAccessibilityService.h"
+#include "Platform.h"
 #include "RootAccessibleWrap.h"
 #include "xpcAccessibleDocument.h"
 
 #ifdef A11Y_LOG
 #include "Logging.h"
 #endif
 
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
 #include "nsCURILoader.h"
 #include "nsDocShellLoadTypes.h"
 #include "nsIChannel.h"
 #include "nsIDOMDocument.h"
-#include "nsIDOMWindow.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIWebNavigation.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIWebProgress.h"
 #include "nsCoreUtils.h"
 #include "nsXULAppAPI.h"
-#include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/TabChild.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 using namespace mozilla::dom;
 
+StaticAutoPtr<nsTArray<DocAccessibleParent*>> DocManager::sRemoteDocuments;
+nsRefPtrHashtable<nsPtrHashKey<const DocAccessibleParent>, xpcAccessibleDocument>*
+DocManager::sRemoteXPCDocumentCache = nullptr;
+
 ////////////////////////////////////////////////////////////////////////////////
 // DocManager
 ////////////////////////////////////////////////////////////////////////////////
 
 DocManager::DocManager()
   : mDocAccessibleCache(2), mXPCDocumentCache(0)
 {
 }
@@ -62,62 +68,104 @@ DocManager::GetDocAccessible(nsIDocument
     return docAcc;
 
   return CreateDocOrRootAccessible(aDocument);
 }
 
 Accessible*
 DocManager::FindAccessibleInCache(nsINode* aNode) const
 {
-  nsSearchAccessibleInCacheArg arg;
-  arg.mNode = aNode;
+  for (auto iter = mDocAccessibleCache.ConstIter(); !iter.Done(); iter.Next()) {
+    DocAccessible* docAccessible = iter.UserData();
+    NS_ASSERTION(docAccessible,
+                 "No doc accessible for the object in doc accessible cache!");
 
-  mDocAccessibleCache.EnumerateRead(SearchAccessibleInDocCache,
-                                    static_cast<void*>(&arg));
-
-  return arg.mAccessible;
+    if (docAccessible) {
+      Accessible* accessible = docAccessible->GetAccessible(aNode);
+      if (accessible) {
+        return accessible;
+      }
+    }
+  }
+  return nullptr;
 }
 
 void
 DocManager::NotifyOfDocumentShutdown(DocAccessible* aDocument,
                                      nsIDocument* aDOMDocument)
 {
   xpcAccessibleDocument* xpcDoc = mXPCDocumentCache.GetWeak(aDocument);
   if (xpcDoc) {
     xpcDoc->Shutdown();
     mXPCDocumentCache.Remove(aDocument);
   }
 
   mDocAccessibleCache.Remove(aDOMDocument);
   RemoveListeners(aDOMDocument);
 }
 
+void
+DocManager::NotifyOfRemoteDocShutdown(DocAccessibleParent* aDoc)
+{
+  xpcAccessibleDocument* doc = GetCachedXPCDocument(aDoc);
+  if (doc) {
+    doc->Shutdown();
+    sRemoteXPCDocumentCache->Remove(aDoc);
+  }
+}
+
 xpcAccessibleDocument*
 DocManager::GetXPCDocument(DocAccessible* aDocument)
 {
   if (!aDocument)
     return nullptr;
 
   xpcAccessibleDocument* xpcDoc = mXPCDocumentCache.GetWeak(aDocument);
   if (!xpcDoc) {
     xpcDoc = new xpcAccessibleDocument(aDocument);
     mXPCDocumentCache.Put(aDocument, xpcDoc);
   }
   return xpcDoc;
 }
 
+xpcAccessibleDocument*
+DocManager::GetXPCDocument(DocAccessibleParent* aDoc)
+{
+  xpcAccessibleDocument* doc = GetCachedXPCDocument(aDoc);
+  if (doc) {
+    return doc;
+  }
+
+  if (!sRemoteXPCDocumentCache) {
+    sRemoteXPCDocumentCache =
+      new nsRefPtrHashtable<nsPtrHashKey<const DocAccessibleParent>, xpcAccessibleDocument>;
+  }
+
+  doc =
+    new xpcAccessibleDocument(aDoc, Interfaces::DOCUMENT | Interfaces::HYPERTEXT);
+  sRemoteXPCDocumentCache->Put(aDoc, doc);
+
+  return doc;
+}
+
 #ifdef DEBUG
 bool
 DocManager::IsProcessingRefreshDriverNotification() const
 {
-  bool isDocRefreshing = false;
-  mDocAccessibleCache.EnumerateRead(SearchIfDocIsRefreshing,
-                                    static_cast<void*>(&isDocRefreshing));
+  for (auto iter = mDocAccessibleCache.ConstIter(); !iter.Done(); iter.Next()) {
+    DocAccessible* docAccessible = iter.UserData();
+    NS_ASSERTION(docAccessible,
+                 "No doc accessible for the object in doc accessible cache!");
 
-  return isDocRefreshing;
+    if (docAccessible && docAccessible->mNotificationController &&
+        docAccessible->mNotificationController->IsUpdating()) {
+      return true;
+    }
+  }
+  return false;
 }
 #endif
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // DocManager protected
 
 bool
@@ -164,25 +212,25 @@ DocManager::OnStateChange(nsIWebProgress
                           nsresult aStatus)
 {
   NS_ASSERTION(aStateFlags & STATE_IS_DOCUMENT, "Other notifications excluded");
 
   if (nsAccessibilityService::IsShutdown() || !aWebProgress ||
       (aStateFlags & (STATE_START | STATE_STOP)) == 0)
     return NS_OK;
 
-  nsCOMPtr<nsIDOMWindow> DOMWindow;
+  nsCOMPtr<mozIDOMWindowProxy> DOMWindow;
   aWebProgress->GetDOMWindow(getter_AddRefs(DOMWindow));
   NS_ENSURE_STATE(DOMWindow);
 
-  nsCOMPtr<nsIDOMDocument> DOMDocument;
-  DOMWindow->GetDocument(getter_AddRefs(DOMDocument));
-  NS_ENSURE_STATE(DOMDocument);
+  nsPIDOMWindowOuter* piWindow = nsPIDOMWindowOuter::From(DOMWindow);
+  MOZ_ASSERT(piWindow);
 
-  nsCOMPtr<nsIDocument> document(do_QueryInterface(DOMDocument));
+  nsCOMPtr<nsIDocument> document = piWindow->GetDoc();
+  NS_ENSURE_STATE(document);
 
   // Document was loaded.
   if (aStateFlags & STATE_STOP) {
 #ifdef A11Y_LOG
     if (logging::IsEnabled(logging::eDocLoad))
       logging::DocLoad("document loaded", aWebProgress, aRequest, aStateFlags);
 #endif
 
@@ -349,17 +397,17 @@ DocManager::HandleDOMDocumentLoad(nsIDoc
 
   docAcc->NotifyOfLoad(aLoadEventType);
 }
 
 void
 DocManager::AddListeners(nsIDocument* aDocument,
                          bool aAddDOMContentLoadedListener)
 {
-  nsPIDOMWindow* window = aDocument->GetWindow();
+  nsPIDOMWindowOuter* window = aDocument->GetWindow();
   EventTarget* target = window->GetChromeEventHandler();
   EventListenerManager* elm = target->GetOrCreateListenerManager();
   elm->AddEventListenerByType(this, NS_LITERAL_STRING("pagehide"),
                               TrustedEventsAtCapture());
 
 #ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eDocCreate))
     logging::Text("added 'pagehide' listener");
@@ -373,17 +421,17 @@ DocManager::AddListeners(nsIDocument* aD
       logging::Text("added 'DOMContentLoaded' listener");
 #endif
   }
 }
 
 void
 DocManager::RemoveListeners(nsIDocument* aDocument)
 {
-  nsPIDOMWindow* window = aDocument->GetWindow();
+  nsPIDOMWindowOuter* window = aDocument->GetWindow();
   if (!window)
     return;
 
   EventTarget* target = window->GetChromeEventHandler();
   if (!target)
     return;
 
   EventListenerManager* elm = target->GetOrCreateListenerManager();
@@ -417,27 +465,25 @@ DocManager::CreateDocOrRootAccessible(ns
     NS_ASSERTION(parentDocAcc,
                  "Can't create an accessible for the document!");
     if (!parentDocAcc)
       return nullptr;
   }
 
   // We only create root accessibles for the true root, otherwise create a
   // doc accessible.
-  nsIContent *rootElm = nsCoreUtils::GetRoleContent(aDocument);
-  nsRefPtr<DocAccessible> docAcc = isRootDoc ?
-    new RootAccessibleWrap(aDocument, rootElm, presShell) :
-    new DocAccessibleWrap(aDocument, rootElm, presShell);
+  RefPtr<DocAccessible> docAcc = isRootDoc ?
+    new RootAccessibleWrap(aDocument, presShell) :
+    new DocAccessibleWrap(aDocument, presShell);
 
   // Cache the document accessible into document cache.
   mDocAccessibleCache.Put(aDocument, docAcc);
 
   // Initialize the document accessible.
   docAcc->Init();
-  docAcc->SetRoleMapEntry(aria::GetRoleMap(aDocument));
 
   // Bind the document to the tree.
   if (isRootDoc) {
     if (!ApplicationAcc()->AppendChild(docAcc)) {
       docAcc->Shutdown();
       return nullptr;
     }
 
@@ -446,20 +492,30 @@ DocManager::CreateDocOrRootAccessible(ns
     // constructed because event processing and tree construction are done by
     // the same document.
     // Note: don't use AccReorderEvent to avoid coalsecense and special reorder
     // events processing.
     docAcc->FireDelayedEvent(nsIAccessibleEvent::EVENT_REORDER,
                              ApplicationAcc());
 
     if (IPCAccessibilityActive()) {
-      DocAccessibleChild* ipcDoc = new DocAccessibleChild(docAcc);
-      docAcc->SetIPCDoc(ipcDoc);
-    auto contentChild = dom::ContentChild::GetSingleton();
-    contentChild->SendPDocAccessibleConstructor(ipcDoc, nullptr, 0);
+      nsIDocShell* docShell = aDocument->GetDocShell();
+      if (docShell) {
+        nsCOMPtr<nsITabChild> tabChild = do_GetInterface(docShell);
+
+        // XXX We may need to handle the case that we don't have a tab child
+        // differently.  It may be that this will cause us to fail to notify
+        // the parent process about important accessible documents.
+        if (tabChild) {
+          DocAccessibleChild* ipcDoc = new DocAccessibleChild(docAcc);
+          docAcc->SetIPCDoc(ipcDoc);
+          static_cast<TabChild*>(tabChild.get())->
+            SendPDocAccessibleConstructor(ipcDoc, nullptr, 0);
+        }
+      }
     }
   } else {
     parentDocAcc->BindChildDocument(docAcc);
   }
 
 #ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eDocCreate)) {
     logging::DocCreate("document creation finished", aDocument);
@@ -469,67 +525,39 @@ DocManager::CreateDocOrRootAccessible(ns
 
   AddListeners(aDocument, isRootDoc);
   return docAcc;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // DocManager static
 
-PLDHashOperator
-DocManager::GetFirstEntryInDocCache(const nsIDocument* aKey,
-                                    DocAccessible* aDocAccessible,
-                                    void* aUserArg)
-{
-  NS_ASSERTION(aDocAccessible,
-               "No doc accessible for the object in doc accessible cache!");
-  *reinterpret_cast<DocAccessible**>(aUserArg) = aDocAccessible;
-
-  return PL_DHASH_STOP;
-}
-
 void
 DocManager::ClearDocCache()
 {
-  DocAccessible* docAcc = nullptr;
-  while (mDocAccessibleCache.EnumerateRead(GetFirstEntryInDocCache, static_cast<void*>(&docAcc))) {
-    if (docAcc)
+  // This unusual do-one-element-per-iterator approach is required because each
+  // DocAccessible is removed elsewhere upon its Shutdown() method being
+  // called, which invalidates the existing iterator.
+  while (mDocAccessibleCache.Count() > 0) {
+    auto iter = mDocAccessibleCache.Iter();
+    MOZ_ASSERT(!iter.Done());
+    DocAccessible* docAcc = iter.UserData();
+    NS_ASSERTION(docAcc,
+                 "No doc accessible for the object in doc accessible cache!");
+    if (docAcc) {
       docAcc->Shutdown();
+    }
   }
 }
 
-PLDHashOperator
-DocManager::SearchAccessibleInDocCache(const nsIDocument* aKey,
-                                       DocAccessible* aDocAccessible,
-                                       void* aUserArg)
+void
+DocManager::RemoteDocAdded(DocAccessibleParent* aDoc)
 {
-  NS_ASSERTION(aDocAccessible,
-               "No doc accessible for the object in doc accessible cache!");
-
-  if (aDocAccessible) {
-    nsSearchAccessibleInCacheArg* arg =
-      static_cast<nsSearchAccessibleInCacheArg*>(aUserArg);
-    arg->mAccessible = aDocAccessible->GetAccessible(arg->mNode);
-    if (arg->mAccessible)
-      return PL_DHASH_STOP;
+  if (!sRemoteDocuments) {
+    sRemoteDocuments = new nsTArray<DocAccessibleParent*>;
+    ClearOnShutdown(&sRemoteDocuments);
   }
 
-  return PL_DHASH_NEXT;
+  MOZ_ASSERT(!sRemoteDocuments->Contains(aDoc),
+      "How did we already have the doc!");
+  sRemoteDocuments->AppendElement(aDoc);
+  ProxyCreated(aDoc, Interfaces::DOCUMENT | Interfaces::HYPERTEXT);
 }
-
-#ifdef DEBUG
-PLDHashOperator
-DocManager::SearchIfDocIsRefreshing(const nsIDocument* aKey,
-                                    DocAccessible* aDocAccessible,
-                                    void* aUserArg)
-{
-  NS_ASSERTION(aDocAccessible,
-               "No doc accessible for the object in doc accessible cache!");
-
-  if (aDocAccessible && aDocAccessible->mNotificationController &&
-      aDocAccessible->mNotificationController->IsUpdating()) {
-    *(static_cast<bool*>(aUserArg)) = true;
-    return PL_DHASH_STOP;
-  }
-
-  return PL_DHASH_NEXT;
-}
-#endif
--- a/accessible/base/DocManager.h
+++ b/accessible/base/DocManager.h
@@ -1,21 +1,23 @@
 /* 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_a11_DocManager_h_
 #define mozilla_a11_DocManager_h_
 
+#include "mozilla/ClearOnShutdown.h"
 #include "nsIDocument.h"
 #include "nsIDOMEventListener.h"
 #include "nsRefPtrHashtable.h"
 #include "nsIWebProgressListener.h"
 #include "nsWeakReference.h"
 #include "nsIPresShell.h"
+#include "mozilla/StaticPtr.h"
 
 namespace mozilla {
 namespace a11y {
 
 class Accessible;
 class DocAccessible;
 class xpcAccessibleDocument;
 class DocAccessibleParent;
@@ -69,30 +71,43 @@ public:
    */
   xpcAccessibleDocument* GetXPCDocument(DocAccessible* aDocument);
   xpcAccessibleDocument* GetCachedXPCDocument(DocAccessible* aDocument) const
     { return mXPCDocumentCache.GetWeak(aDocument); }
 
   /*
    * Notification that a top level document in a content process has gone away.
    */
-  void RemoteDocShutdown(DocAccessibleParent* aDoc)
+  static void RemoteDocShutdown(DocAccessibleParent* aDoc)
   {
-    DebugOnly<bool> result = mRemoteDocuments.RemoveElement(aDoc);
+    DebugOnly<bool> result = sRemoteDocuments->RemoveElement(aDoc);
     MOZ_ASSERT(result, "Why didn't we find the document!");
   }
 
   /*
    * Notify of a new top level document in a content process.
    */
-  void RemoteDocAdded(DocAccessibleParent* aDoc)
+  static void RemoteDocAdded(DocAccessibleParent* aDoc);
+
+  static const nsTArray<DocAccessibleParent*>* TopLevelRemoteDocs()
+    { return sRemoteDocuments; }
+
+  /**
+   * Remove the xpc document for a remote document if there is one.
+   */
+  static void NotifyOfRemoteDocShutdown(DocAccessibleParent* adoc);
+
+  /**
+   * Get a XPC document for a remote document.
+   */
+  static xpcAccessibleDocument* GetXPCDocument(DocAccessibleParent* aDoc);
+  static xpcAccessibleDocument* GetCachedXPCDocument(const DocAccessibleParent* aDoc)
   {
-    MOZ_ASSERT(!mRemoteDocuments.Contains(aDoc),
-               "How did we already have the doc!");
-    mRemoteDocuments.AppendElement(aDoc);
+    return sRemoteXPCDocumentCache ? sRemoteXPCDocumentCache->GetWeak(aDoc)
+      : nullptr;
   }
 
 #ifdef DEBUG
   bool IsProcessingRefreshDriverNotification() const;
 #endif
 
 protected:
   DocManager();
@@ -131,57 +146,34 @@ private:
   void RemoveListeners(nsIDocument* aDocument);
 
   /**
    * Create document or root accessible.
    */
   DocAccessible* CreateDocOrRootAccessible(nsIDocument* aDocument);
 
   /**
-   * Get first entry of the document accessible from cache.
-   */
-  static PLDHashOperator
-    GetFirstEntryInDocCache(const nsIDocument* aKey,
-                            DocAccessible* aDocAccessible,
-                            void* aUserArg);
-
-  /**
    * Clear the cache and shutdown the document accessibles.
    */
   void ClearDocCache();
 
-  struct nsSearchAccessibleInCacheArg
-  {
-    Accessible* mAccessible;
-    nsINode* mNode;
-  };
-
-  static PLDHashOperator
-    SearchAccessibleInDocCache(const nsIDocument* aKey,
-                               DocAccessible* aDocAccessible,
-                               void* aUserArg);
-
-#ifdef DEBUG
-  static PLDHashOperator
-    SearchIfDocIsRefreshing(const nsIDocument* aKey,
-                            DocAccessible* aDocAccessible, void* aUserArg);
-#endif
-
   typedef nsRefPtrHashtable<nsPtrHashKey<const nsIDocument>, DocAccessible>
     DocAccessibleHashtable;
   DocAccessibleHashtable mDocAccessibleCache;
 
   typedef nsRefPtrHashtable<nsPtrHashKey<const DocAccessible>, xpcAccessibleDocument>
     XPCDocumentHashtable;
   XPCDocumentHashtable mXPCDocumentCache;
+  static nsRefPtrHashtable<nsPtrHashKey<const DocAccessibleParent>, xpcAccessibleDocument>*
+    sRemoteXPCDocumentCache;
 
   /*
    * The list of remote top level documents.
    */
-  nsTArray<DocAccessibleParent*> mRemoteDocuments;
+  static StaticAutoPtr<nsTArray<DocAccessibleParent*>> sRemoteDocuments;
 };
 
 /**
  * Return the existing document accessible for the document if any.
  * Note this returns the doc accessible for the primary pres shell if there is
  * more than one.
  */
 inline DocAccessible*
--- a/accessible/base/EventQueue.cpp
+++ b/accessible/base/EventQueue.cpp
@@ -56,17 +56,17 @@ EventQueue::PushEvent(AccEvent* aEvent)
     while (parent &&
            nsTextEquivUtils::HasNameRule(parent, eNameFromSubtreeIfReqRule)) {
       // Test possible name dependent parent.
       if (nsTextEquivUtils::HasNameRule(parent, eNameFromSubtreeRule)) {
         nsAutoString name;
         ENameValueFlag nameFlag = parent->Name(name);
         // If name is obtained from subtree, fire name change event.
         if (nameFlag == eNameFromSubtree) {
-          nsRefPtr<AccEvent> nameChangeEvent =
+          RefPtr<AccEvent> nameChangeEvent =
             new AccEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, parent);
           PushEvent(nameChangeEvent);
         }
         break;
       }
       parent = parent->Parent();
     }
   }
@@ -243,22 +243,17 @@ EventQueue::CoalesceReorderEvents(AccEve
     if (!thisEvent->mAccessible->IsDoc() &&
         !thisEvent->mAccessible->IsInDocument()) {
       thisEvent->mEventRule = AccEvent::eDoNotEmit;
       continue;
     }
 
     // Coalesce earlier event of the same target.
     if (thisEvent->mAccessible == aTailEvent->mAccessible) {
-      if (thisEvent->mEventRule == AccEvent::eDoNotEmit) {
-        AccReorderEvent* tailReorder = downcast_accEvent(aTailEvent);
-        tailReorder->DoNotEmitAll();
-      } else {
-        thisEvent->mEventRule = AccEvent::eDoNotEmit;
-      }
+      thisEvent->mEventRule = AccEvent::eDoNotEmit;
 
       return;
     }
 
     // If tailEvent contains thisEvent
     // then
     //   if show or hide of tailEvent contains a grand parent of thisEvent
     //   then ignore thisEvent and its show and hide events
@@ -295,22 +290,26 @@ EventQueue::CoalesceReorderEvents(AccEve
     //   then assert
     //   otherwise ignore tailEvent but not its show and hide events
     Accessible* tailParent = aTailEvent->mAccessible;
     while (tailParent && tailParent != mDocument) {
       if (tailParent->Parent() == thisEvent->mAccessible) {
         AccReorderEvent* thisReorder = downcast_accEvent(thisEvent);
         AccReorderEvent* tailReorder = downcast_accEvent(aTailEvent);
         uint32_t eventType = thisReorder->IsShowHideEventTarget(tailParent);
-        if (eventType == nsIAccessibleEvent::EVENT_SHOW)
+        if (eventType == nsIAccessibleEvent::EVENT_SHOW) {
           tailReorder->DoNotEmitAll();
-        else if (eventType == nsIAccessibleEvent::EVENT_HIDE)
+        }
+        else if (eventType == nsIAccessibleEvent::EVENT_HIDE) {
           NS_ERROR("Accessible tree was modified after it was removed! Huh?");
-        else
+        }
+        else {
           aTailEvent->mEventRule = AccEvent::eDoNotEmit;
+          mEvents[index].swap(mEvents[count - 1]);
+        }
 
         return;
       }
 
       tailParent = tailParent->Parent();
     }
 
   } // for (index)
@@ -475,51 +474,24 @@ EventQueue::CreateTextChangeEventFor(Acc
   if (text.IsEmpty())
     return;
 
   aEvent->mTextChangeEvent =
     new AccTextChangeEvent(textAccessible, offset, text, aEvent->IsShow(),
                            aEvent->mIsFromUserInput ? eFromUserInput : eNoUserInput);
 }
 
-void
-EventQueue::SendIPCEvent(AccEvent* aEvent) const
-{
-  DocAccessibleChild* ipcDoc = mDocument->IPCDoc();
-  uint64_t id = aEvent->GetAccessible()->IsDoc() ? 0 :
-    reinterpret_cast<uintptr_t>(aEvent->GetAccessible());
-
-  switch(aEvent->GetEventType()) {
-    case nsIAccessibleEvent::EVENT_SHOW:
-      ipcDoc->ShowEvent(downcast_accEvent(aEvent));
-      break;
-
-    case nsIAccessibleEvent::EVENT_HIDE:
-      ipcDoc->SendHideEvent(id);
-      break;
-
-    case nsIAccessibleEvent::EVENT_REORDER:
-      // reorder events on the application acc aren't necessary to tell the parent
-      // about new top level documents.
-      if (!aEvent->GetAccessible()->IsApplication())
-        ipcDoc->SendEvent(id, aEvent->GetEventType());
-      break;
-    default:
-      ipcDoc->SendEvent(id, aEvent->GetEventType());
-  }
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // EventQueue: event queue
 
 void
 EventQueue::ProcessEventQueue()
 {
   // Process only currently queued events.
-  nsTArray<nsRefPtr<AccEvent> > events;
+  nsTArray<RefPtr<AccEvent> > events;
   events.SwapElements(mEvents);
 
   uint32_t eventCount = events.Length();
 #ifdef A11Y_LOG
   if (eventCount > 0 && logging::IsEnabled(logging::eEvents)) {
     logging::MsgBegin("EVENTS", "events processing");
     logging::Address("document", mDocument);
     logging::MsgEnd();
@@ -573,18 +545,17 @@ EventQueue::ProcessEventQueue()
       // Fire text change events.
       AccMutationEvent* mutationEvent = downcast_accEvent(event);
       if (mutationEvent) {
         if (mutationEvent->mTextChangeEvent)
           nsEventShell::FireEvent(mutationEvent->mTextChangeEvent);
       }
     }
 
-    if (event->mEventType == nsIAccessibleEvent::EVENT_HIDE)
+    AccHideEvent* hideEvent = downcast_accEvent(event);
+    if (hideEvent && hideEvent->NeedsShutdown()) {
       mDocument->ShutdownChildrenInSubtree(event->mAccessible);
+    }
 
     if (!mDocument)
       return;
-
-    if (IPCAccessibilityActive())
-      SendIPCEvent(event);
   }
 }
--- a/accessible/base/EventQueue.h
+++ b/accessible/base/EventQueue.h
@@ -27,18 +27,18 @@ protected:
   bool PushEvent(AccEvent* aEvent);
 
   /**
    * Process events from the queue and fires events.
    */
   void ProcessEventQueue();
 
 private:
-  EventQueue(const EventQueue&) MOZ_DELETE;
-  EventQueue& operator = (const EventQueue&) MOZ_DELETE;
+  EventQueue(const EventQueue&) = delete;
+  EventQueue& operator = (const EventQueue&) = delete;
 
   // Event queue processing
   /**
    * Coalesce redundant events from the queue.
    */
   void CoalesceEvents();
 
   /**
@@ -49,21 +49,16 @@ private:
   /**
    * Coalesce two selection change events within the same select control.
    */
   void CoalesceSelChangeEvents(AccSelChangeEvent* aTailEvent,
                                AccSelChangeEvent* aThisEvent,
                                uint32_t aThisIndex);
 
   /**
-   * Notify the parent process of events being fired by this event queue.
-   */
-  void SendIPCEvent(AccEvent* aEvent) const;
-
-  /**
    * Coalesce text change events caused by sibling hide events.
    */
   void CoalesceTextChangeEventsFor(AccHideEvent* aTailEvent,
                                    AccHideEvent* aThisEvent);
   void CoalesceTextChangeEventsFor(AccShowEvent* aTailEvent,
                                    AccShowEvent* aThisEvent);
 
   /**
@@ -76,18 +71,18 @@ private:
 protected:
 
   /**
    * The document accessible reference owning this queue.
    */
   DocAccessible* mDocument;
 
   /**
-   * Pending events array. Don't make this an nsAutoTArray; we use
+   * Pending events array. Don't make this an AutoTArray; we use
    * SwapElements() on it.
    */
-  nsTArray<nsRefPtr<AccEvent> > mEvents;
+  nsTArray<RefPtr<AccEvent> > mEvents;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif // mozilla_a11y_EventQueue_h_
--- a/accessible/base/Filters.cpp
+++ b/accessible/base/Filters.cpp
@@ -42,19 +42,17 @@ filters::GetRow(Accessible* aAccessible)
     return eSkip;
 
   return eSkipSubtree;
 }
 
 uint32_t
 filters::GetCell(Accessible* aAccessible)
 {
-  a11y::role role = aAccessible->Role();
-  return role == roles::GRID_CELL || role == roles::ROWHEADER ||
-    role == roles::COLUMNHEADER ? eMatch : eSkipSubtree;
+  return aAccessible->IsTableCell() ? eMatch : eSkipSubtree;
 }
 
 uint32_t
 filters::GetEmbeddedObject(Accessible* aAccessible)
 {
   return nsAccUtils::IsEmbeddedObject(aAccessible) ?
     eMatch | eSkipSubtree : eSkipSubtree;
 }
--- a/accessible/base/FocusManager.cpp
+++ b/accessible/base/FocusManager.cpp
@@ -213,17 +213,17 @@ FocusManager::ForceFocusEvent()
 }
 
 void
 FocusManager::DispatchFocusEvent(DocAccessible* aDocument,
                                  Accessible* aTarget)
 {
   NS_PRECONDITION(aDocument, "No document for focused accessible!");
   if (aDocument) {
-    nsRefPtr<AccEvent> event =
+    RefPtr<AccEvent> event =
       new AccEvent(nsIAccessibleEvent::EVENT_FOCUS, aTarget,
                    eAutoDetect, AccEvent::eCoalesceOfSameType);
     aDocument->FireDelayedEvent(event);
 
 #ifdef A11Y_LOG
     if (logging::IsEnabled(logging::eFocus))
       logging::FocusDispatched(aTarget);
 #endif
@@ -294,69 +294,52 @@ FocusManager::ProcessFocusEvent(AccEvent
       mActiveItem = activeItem;
       target = activeItem;
     }
   }
 
   // Fire menu start/end events for ARIA menus.
   if (target->IsARIARole(nsGkAtoms::menuitem)) {
     // The focus was moved into menu.
-    bool tryOwnsParent = true;
     Accessible* ARIAMenubar = nullptr;
-    Accessible* child = target;
-    Accessible* parent = child->Parent();
-    while (parent) {
-      nsRoleMapEntry* roleMap = parent->ARIARoleMap();
-      if (roleMap) {
-        if (roleMap->Is(nsGkAtoms::menubar)) {
-          ARIAMenubar = parent;
-          break;
-        }
-
-        // Go up in the parent chain of the menu hierarchy.
-        if (roleMap->Is(nsGkAtoms::menuitem) || roleMap->Is(nsGkAtoms::menu)) {
-          child = parent;
-          parent = child->Parent();
-          tryOwnsParent = true;
-          continue;
-        }
+    for (Accessible* parent = target->Parent(); parent; parent = parent->Parent()) {
+      if (parent->IsARIARole(nsGkAtoms::menubar)) {
+        ARIAMenubar = parent;
+        break;
       }
 
-      // If no required context role then check aria-owns relation.
-      if (!tryOwnsParent)
+      // Go up in the parent chain of the menu hierarchy.
+      if (!parent->IsARIARole(nsGkAtoms::menuitem) &&
+          !parent->IsARIARole(nsGkAtoms::menu)) {
         break;
-
-      RelatedAccIterator iter(child->Document(), child->GetContent(),
-                              nsGkAtoms::aria_owns);
-      parent = iter.Next();
-      tryOwnsParent = false;
+      }
     }
 
     if (ARIAMenubar != mActiveARIAMenubar) {
       // Leaving ARIA menu. Fire menu_end event on current menubar.
       if (mActiveARIAMenubar) {
-        nsRefPtr<AccEvent> menuEndEvent =
+        RefPtr<AccEvent> menuEndEvent =
           new AccEvent(nsIAccessibleEvent::EVENT_MENU_END, mActiveARIAMenubar,
                        aEvent->FromUserInput());
         nsEventShell::FireEvent(menuEndEvent);
       }
 
       mActiveARIAMenubar = ARIAMenubar;
 
       // Entering ARIA menu. Fire menu_start event.
       if (mActiveARIAMenubar) {
-        nsRefPtr<AccEvent> menuStartEvent =
+        RefPtr<AccEvent> menuStartEvent =
           new AccEvent(nsIAccessibleEvent::EVENT_MENU_START,
                        mActiveARIAMenubar, aEvent->FromUserInput());
         nsEventShell::FireEvent(menuStartEvent);
       }
     }
   } else if (mActiveARIAMenubar) {
     // Focus left a menu. Fire menu_end event.
-    nsRefPtr<AccEvent> menuEndEvent =
+    RefPtr<AccEvent> menuEndEvent =
       new AccEvent(nsIAccessibleEvent::EVENT_MENU_END, mActiveARIAMenubar,
                    aEvent->FromUserInput());
     nsEventShell::FireEvent(menuEndEvent);
 
     mActiveARIAMenubar = nullptr;
   }
 
 #ifdef A11Y_LOG
@@ -364,17 +347,17 @@ FocusManager::ProcessFocusEvent(AccEvent
     logging::FocusNotificationTarget("fire focus event", "Target", target);
 #endif
 
   // Reset cached caret value. The cache will be updated upon processing the
   // next caret move event. This ensures that we will return the correct caret
   // offset before the caret move event is handled.
   SelectionMgr()->ResetCaretOffset();
 
-  nsRefPtr<AccEvent> focusEvent =
+  RefPtr<AccEvent> focusEvent =
     new AccEvent(nsIAccessibleEvent::EVENT_FOCUS, target, aEvent->FromUserInput());
   nsEventShell::FireEvent(focusEvent);
 
   // Fire scrolling_start event when the document receives the focus if it has
   // an anchor jump. If an accessible within the document receive the focus
   // then null out the anchor jump because it no longer applies.
   DocAccessible* targetDocument = target->Document();
   Accessible* anchorJump = targetDocument->AnchorJump();
@@ -401,17 +384,17 @@ FocusManager::FocusedDOMNode() const
   if (focusedElm) {
     if (EventStateManager::IsRemoteTarget(focusedElm)) {
       return nullptr;
     }
     return focusedElm;
   }
 
   // Otherwise the focus can be on DOM document.
-  nsPIDOMWindow* focusedWnd = DOMFocusManager->GetFocusedWindow();
+  nsPIDOMWindowOuter* focusedWnd = DOMFocusManager->GetFocusedWindow();
   return focusedWnd ? focusedWnd->GetExtantDoc() : nullptr;
 }
 
 nsIDocument*
 FocusManager::FocusedDOMDocument() const
 {
   nsINode* focusedNode = FocusedDOMNode();
   return focusedNode ? focusedNode->OwnerDoc() : nullptr;
--- a/accessible/base/FocusManager.h
+++ b/accessible/base/FocusManager.h
@@ -119,16 +119,16 @@ private:
   nsINode* FocusedDOMNode() const;
 
   /**
    * Return DOM document having DOM focus.
    */
   nsIDocument* FocusedDOMDocument() const;
 
 private:
-  nsRefPtr<Accessible> mActiveItem;
-  nsRefPtr<Accessible> mActiveARIAMenubar;
+  RefPtr<Accessible> mActiveItem;
+  RefPtr<Accessible> mActiveARIAMenubar;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/base/Logging.cpp
+++ b/accessible/base/Logging.cpp
@@ -40,24 +40,26 @@ struct ModuleRep {
 static ModuleRep sModuleMap[] = {
   { "docload", logging::eDocLoad },
   { "doccreate", logging::eDocCreate },
   { "docdestroy", logging::eDocDestroy },
   { "doclifecycle", logging::eDocLifeCycle },
 
   { "events", logging::eEvents },
   { "platforms", logging::ePlatforms },
-  { "stack", logging::eStack },
   { "text", logging::eText },
   { "tree", logging::eTree },
 
   { "DOMEvents", logging::eDOMEvents },
   { "focus", logging::eFocus },
   { "selection", logging::eSelection },
-  { "notifications", logging::eNotifications }
+  { "notifications", logging::eNotifications },
+
+  { "stack", logging::eStack },
+  { "verbose", logging::eVerbose }
 };
 
 static void
 EnableLogging(const char* aModulesStr)
 {
   sModules = 0;
   if (!aModulesStr)
     return;
@@ -162,18 +164,22 @@ LogDocState(nsIDocument* aDocumentNode)
 
   printf("doc state: %s", docState);
   printf(", %sinitial", aDocumentNode->IsInitialDocument() ? "" : "not ");
   printf(", %sshowing", aDocumentNode->IsShowing() ? "" : "not ");
   printf(", %svisible", aDocumentNode->IsVisible() ? "" : "not ");
   printf(", %svisible considering ancestors", aDocumentNode->IsVisibleConsideringAncestors() ? "" : "not ");
   printf(", %sactive", aDocumentNode->IsActive() ? "" : "not ");
   printf(", %sresource", aDocumentNode->IsResourceDoc() ? "" : "not ");
-  printf(", has %srole content",
-         nsCoreUtils::GetRoleContent(aDocumentNode) ? "" : "no ");
+
+  dom::Element* rootEl = aDocumentNode->GetBodyElement();
+  if (!rootEl) {
+    rootEl = aDocumentNode->GetRootElement();
+  }
+  printf(", has %srole content", rootEl ? "" : "no ");
 }
 
 static void
 LogPresShell(nsIDocument* aDocumentNode)
 {
   nsIPresShell* ps = aDocumentNode->GetShell();
   printf("presshell: %p", static_cast<void*>(ps));
 
@@ -387,19 +393,19 @@ static const char* sDocEventTitle = "DOC
 static const char* sFocusTitle = "FOCUS";
 
 void
 logging::DocLoad(const char* aMsg, nsIWebProgress* aWebProgress,
                  nsIRequest* aRequest, uint32_t aStateFlags)
 {
   MsgBegin(sDocLoadTitle, aMsg);
 
-  nsCOMPtr<nsIDOMWindow> DOMWindow;
+  nsCOMPtr<mozIDOMWindowProxy> DOMWindow;
   aWebProgress->GetDOMWindow(getter_AddRefs(DOMWindow));
-  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(DOMWindow);
+  nsPIDOMWindowOuter* window = nsPIDOMWindowOuter::From(DOMWindow);
   if (!window) {
     MsgEnd();
     return;
   }
 
   nsCOMPtr<nsIDocument> documentNode = window->GetDoc();
   if (!documentNode) {
     MsgEnd();
@@ -602,16 +608,71 @@ logging::SelChange(nsISelection* aSelect
   bool isIgnored = !aDocument || !aDocument->IsContentLoaded();
   printf("\nSelection changed, selection type: %s, notification %s, reason: %d\n",
          strType, (isIgnored ? "ignored" : "pending"), aReason);
 
   Stack();
 }
 
 void
+logging::TreeInfo(const char* aMsg, uint32_t aExtraFlags, ...)
+{
+  if (IsEnabledAll(logging::eTree | aExtraFlags)) {
+    MsgBegin("TREE", aMsg);
+
+    va_list vl;
+    va_start(vl, aExtraFlags);
+    const char* descr = nullptr;
+    while ((descr = va_arg(vl, const char*))) {
+      AccessibleInfo(descr, va_arg(vl, Accessible*));
+    }
+    va_end(vl);
+
+    MsgEnd();
+
+    if (aExtraFlags & eStack) {
+      Stack();
+    }
+  }
+}
+
+void
+logging::TreeInfo(const char* aMsg, uint32_t aExtraFlags,
+                  const char* aMsg1, Accessible* aAcc,
+                  const char* aMsg2, nsINode* aNode)
+{
+  if (IsEnabledAll(logging::eTree | logging::eVerbose)) {
+    MsgBegin("TREE", aMsg);
+    AccessibleInfo(aMsg1, aAcc);
+    Accessible* acc = aAcc->Document()->GetAccessible(aNode);
+    if (acc) {
+      AccessibleInfo(aMsg2, acc);
+    }
+    else {
+      Node(aMsg2, aNode);
+    }
+    MsgEnd();
+  }
+}
+
+
+void
+logging::TreeInfo(const char* aMsg, uint32_t aExtraFlags, Accessible* aParent)
+{
+  if (IsEnabledAll(logging::eTree | aExtraFlags)) {
+    MsgBegin("TREE", aMsg);
+    AccessibleInfo("container", aParent);
+    for (uint32_t idx = 0; idx < aParent->ChildCount(); idx++) {
+      AccessibleInfo("child", aParent->GetChildAt(idx));
+    }
+    MsgEnd();
+  }
+}
+
+void
 logging::MsgBegin(const char* aTitle, const char* aMsgText, ...)
 {
   printf("\nA11Y %s: ", aTitle);
 
   va_list argptr;
   va_start(argptr, aMsgText);
   vprintf(aMsgText, argptr);
   va_end(argptr);
@@ -708,17 +769,17 @@ logging::Node(const char* aDescr, nsINod
     printf("%s: %p, not accessible node type, idx in parent: %d\n",
            aDescr, static_cast<void*>(aNode), idxInParent);
     return;
   }
 
   dom::Element* elm = aNode->AsElement();
 
   nsAutoCString tag;
-  elm->Tag()->ToUTF8String(tag);
+  elm->NodeInfo()->NameAtom()->ToUTF8String(tag);
 
   nsIAtom* idAtom = elm->GetID();
   nsAutoCString id;
   if (idAtom)
     idAtom->ToUTF8String(id);
 
   printf("%s: %p, %s@id='%s', idx in parent: %d\n",
          aDescr, static_cast<void*>(elm), tag.get(), id.get(), idxInParent);
@@ -732,16 +793,72 @@ logging::Document(DocAccessible* aDocume
          static_cast<void*>(aDocument->DocumentNode()));
 
   printf("    Document ");
   LogDocURI(aDocument->DocumentNode());
   printf("\n");
 }
 
 void
+logging::AccessibleInfo(const char* aDescr, Accessible* aAccessible)
+{
+  printf("    %s: %p; ", aDescr, static_cast<void*>(aAccessible));
+  if (!aAccessible) {
+    printf("\n");
+    return;
+  }
+  if (aAccessible->IsDefunct()) {
+    printf("defunct\n");
+    return;
+  }
+  if (!aAccessible->Document() || aAccessible->Document()->IsDefunct()) {
+    printf("document is shutting down, no info\n");
+    return;
+  }
+
+  nsAutoString role;
+  GetAccService()->GetStringRole(aAccessible->Role(), role);
+  printf("role: %s", NS_ConvertUTF16toUTF8(role).get());
+
+  nsAutoString name;
+  aAccessible->Name(name);
+  if (!name.IsEmpty()) {
+    printf(", name: '%s'", NS_ConvertUTF16toUTF8(name).get());
+  }
+
+  printf(", idx: %d", aAccessible->IndexInParent());
+
+  nsINode* node = aAccessible->GetNode();
+  if (!node) {
+    printf(", node: null\n");
+  }
+  else if (node->IsNodeOfType(nsINode::eDOCUMENT)) {
+    printf(", document node: %p\n", static_cast<void*>(node));
+  }
+  else if (node->IsNodeOfType(nsINode::eTEXT)) {
+    printf(", text node: %p\n", static_cast<void*>(node));
+  }
+  else if (node->IsElement()) {
+    dom::Element* el = node->AsElement();
+
+    nsAutoCString tag;
+    el->NodeInfo()->NameAtom()->ToUTF8String(tag);
+
+    nsIAtom* idAtom = el->GetID();
+    nsAutoCString id;
+    if (idAtom) {
+      idAtom->ToUTF8String(id);
+    }
+
+    printf(", element node: %p, %s@id='%s'\n",
+           static_cast<void*>(el), tag.get(), id.get());
+  }
+}
+
+void
 logging::AccessibleNNode(const char* aDescr, Accessible* aAccessible)
 {
   printf("    %s: %p; ", aDescr, static_cast<void*>(aAccessible));
   if (!aAccessible)
     return;
 
   nsAutoString role;
   GetAccService()->GetStringRole(aAccessible->Role(), role);
@@ -810,16 +927,22 @@ logging::Stack()
 
 bool
 logging::IsEnabled(uint32_t aModules)
 {
   return sModules & aModules;
 }
 
 bool
+logging::IsEnabledAll(uint32_t aModules)
+{
+  return (sModules & aModules) == aModules;
+}
+
+bool
 logging::IsEnabled(const nsAString& aModuleStr)
 {
   for (unsigned int idx = 0; idx < ArrayLength(sModuleMap); idx++) {
     if (aModuleStr.EqualsASCII(sModuleMap[idx].mStr))
       return sModules & sModuleMap[idx].mModule;
   }
 
   return false;
--- a/accessible/base/Logging.h
+++ b/accessible/base/Logging.h
@@ -30,32 +30,40 @@ namespace logging {
 enum EModules {
   eDocLoad = 1 << 0,
   eDocCreate = 1 << 1,
   eDocDestroy = 1 << 2,
   eDocLifeCycle = eDocLoad | eDocCreate | eDocDestroy,
 
   eEvents = 1 << 3,
   ePlatforms = 1 << 4,
-  eStack = 1 << 5,
-  eText = 1 << 6,
-  eTree = 1 << 7,
+  eText = 1 << 5,
+  eTree = 1 << 6,
 
-  eDOMEvents = 1 << 8,
-  eFocus = 1 << 9,
-  eSelection = 1 << 10,
-  eNotifications = eDOMEvents | eSelection | eFocus
+  eDOMEvents = 1 << 7,
+  eFocus = 1 << 8,
+  eSelection = 1 << 9,
+  eNotifications = eDOMEvents | eSelection | eFocus,
+
+  // extras
+  eStack = 1 << 10,
+  eVerbose = 1 << 11
 };
 
 /**
  * Return true if any of the given modules is logged.
  */
 bool IsEnabled(uint32_t aModules);
 
 /**
+ * Return true if all of the given modules are logged.
+ */
+bool IsEnabledAll(uint32_t aModules);
+
+/**
  * Return true if the given module is logged.
  */
 bool IsEnabled(const nsAString& aModules);
 
 /**
  * Log the document loading progress.
  */
 void DocLoad(const char* aMsg, nsIWebProgress* aWebProgress,
@@ -117,16 +125,25 @@ void FocusDispatched(Accessible* aTarget
 
 /**
  * Log the selection change.
  */
 void SelChange(nsISelection* aSelection, DocAccessible* aDocument,
                int16_t aReason);
 
 /**
+ * Log the given accessible elements info.
+ */
+void TreeInfo(const char* aMsg, uint32_t aExtraFlags, ...);
+void TreeInfo(const char* aMsg, uint32_t aExtraFlags,
+              const char* aMsg1, Accessible* aAcc,
+              const char* aMsg2, nsINode* aNode);
+void TreeInfo(const char* aMsg, uint32_t aExtraFlags, Accessible* aParent);
+
+/**
  * Log the message ('title: text' format) on new line. Print the start and end
  * boundaries of the message body designated by '{' and '}' (2 spaces indent for
  * body).
  */
 void MsgBegin(const char* aTitle, const char* aMsgText, ...);
 void MsgEnd();
 
 /**
@@ -159,16 +176,17 @@ void Node(const char* aDescr, nsINode* a
 /**
  * Log the document accessible info as message entry.
  */
 void Document(DocAccessible* aDocument);
 
 /**
  * Log the accessible and its DOM node as a message entry.
  */
+void AccessibleInfo(const char* aDescr, Accessible* aAccessible);
 void AccessibleNNode(const char* aDescr, Accessible* aAccessible);
 void AccessibleNNode(const char* aDescr, nsINode* aNode);
 
 /**
  * Log the DOM event.
  */
 void DOMEvent(const char* aDescr, nsINode* aOrigTarget,
               const nsAString& aEventType);
@@ -184,14 +202,15 @@ void Stack();
 void Enable(const nsAFlatCString& aModules);
 
 /**
  * Enable logging of modules specified by A11YLOG environment variable,
  * all other modules aren't logged.
  */
 void CheckEnv();
 
-} // namespace logs
+} // namespace logging
+
 } // namespace a11y
 } // namespace mozilla
 
 #endif
 
new file mode 100644
--- /dev/null
+++ b/accessible/base/MarkupMap.h
@@ -0,0 +1,332 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+MARKUPMAP(a,
+          New_HTMLLink,
+          roles::LINK)
+
+MARKUPMAP(abbr,
+          New_HyperText,
+          0)
+
+MARKUPMAP(acronym,
+          New_HyperText,
+          0)
+
+MARKUPMAP(article,
+          New_HyperText,
+          roles::DOCUMENT,
+          Attr(xmlroles, article))
+
+MARKUPMAP(aside,
+          New_HyperText,
+          roles::NOTE)
+
+MARKUPMAP(blockquote,
+          New_HyperText,
+          roles::SECTION)
+
+MARKUPMAP(dd,
+          New_HTMLDefinition,
+          roles::DEFINITION)
+
+MARKUPMAP(div,
+          nullptr,
+          roles::SECTION)
+
+MARKUPMAP(dl,
+          New_HTMLList,
+          roles::DEFINITION_LIST)
+
+MARKUPMAP(dt,
+          New_HTMLListitem,
+          roles::TERM)
+
+MARKUPMAP(figcaption,
+          New_HTMLFigcaption,
+          roles::CAPTION)
+
+MARKUPMAP(figure,
+          New_HTMLFigure,
+          roles::FIGURE,
+          Attr(xmlroles, figure))
+
+MARKUPMAP(form,
+          New_HyperText,
+          roles::FORM)
+
+MARKUPMAP(footer,
+          New_HyperText,
+          roles::FOOTER)
+
+MARKUPMAP(header,
+          New_HyperText,
+          roles::HEADER)
+
+MARKUPMAP(h1,
+          New_HyperText,
+          roles::HEADING)
+
+MARKUPMAP(h2,
+          New_HyperText,
+          roles::HEADING)
+
+MARKUPMAP(h3,
+          New_HyperText,
+          roles::HEADING)
+
+MARKUPMAP(h4,
+          New_HyperText,
+          roles::HEADING)
+
+MARKUPMAP(h5,
+          New_HyperText,
+          roles::HEADING)
+
+MARKUPMAP(h6,
+          New_HyperText,
+          roles::HEADING)
+
+MARKUPMAP(label,
+          New_HTMLLabel,
+          roles::LABEL)
+
+MARKUPMAP(legend,
+          New_HTMLLegend,
+          roles::LABEL)
+
+MARKUPMAP(li,
+          New_HTMLListitem,
+          0)
+
+MARKUPMAP(map,
+          nullptr,
+          roles::TEXT_CONTAINER)
+
+MARKUPMAP(math,
+          New_HyperText,
+          roles::MATHML_MATH)
+
+MARKUPMAP(mi_,
+          New_HyperText,
+          roles::MATHML_IDENTIFIER)
+
+MARKUPMAP(mn_,
+          New_HyperText,
+          roles::MATHML_NUMBER)
+
+MARKUPMAP(mo_,
+          New_HyperText,
+          roles::MATHML_OPERATOR,
+          AttrFromDOM(accent_, accent_),
+          AttrFromDOM(fence_, fence_),
+          AttrFromDOM(separator_, separator_),
+          AttrFromDOM(largeop_, largeop_))
+
+MARKUPMAP(mtext_,
+          New_HyperText,
+          roles::MATHML_TEXT)
+
+MARKUPMAP(ms_,
+          New_HyperText,
+          roles::MATHML_STRING_LITERAL)
+
+MARKUPMAP(mglyph_,
+          New_HyperText,
+          roles::MATHML_GLYPH)
+
+MARKUPMAP(mrow_,
+          New_HyperText,
+          roles::MATHML_ROW)
+
+MARKUPMAP(mfrac_,
+          New_HyperText,
+          roles::MATHML_FRACTION,
+          AttrFromDOM(bevelled_, bevelled_),
+          AttrFromDOM(linethickness_, linethickness_))
+
+MARKUPMAP(msqrt_,
+          New_HyperText,
+          roles::MATHML_SQUARE_ROOT)
+
+MARKUPMAP(mroot_,
+          New_HyperText,
+          roles::MATHML_ROOT)
+
+MARKUPMAP(mfenced_,
+          New_HyperText,
+          roles::MATHML_FENCED,
+          AttrFromDOM(close, close),
+          AttrFromDOM(open, open),
+          AttrFromDOM(separators_, separators_))
+
+MARKUPMAP(menclose_,
+          New_HyperText,
+          roles::MATHML_ENCLOSED,
+          AttrFromDOM(notation_, notation_))
+
+MARKUPMAP(mstyle_,
+          New_HyperText,
+          roles::MATHML_STYLE)
+
+MARKUPMAP(msub_,
+          New_HyperText,
+          roles::MATHML_SUB)
+
+MARKUPMAP(msup_,
+          New_HyperText,
+          roles::MATHML_SUP)
+
+MARKUPMAP(msubsup_,
+          New_HyperText,
+          roles::MATHML_SUB_SUP)
+
+MARKUPMAP(munder_,
+          New_HyperText,
+          roles::MATHML_UNDER,
+          AttrFromDOM(accentunder_, accentunder_),
+          AttrFromDOM(align, align))
+
+MARKUPMAP(mover_,
+          New_HyperText,
+          roles::MATHML_OVER,
+          AttrFromDOM(accent_, accent_),
+          AttrFromDOM(align, align))
+
+MARKUPMAP(munderover_,
+          New_HyperText,
+          roles::MATHML_UNDER_OVER,
+          AttrFromDOM(accent_, accent_),
+          AttrFromDOM(accentunder_, accentunder_),
+          AttrFromDOM(align, align))
+
+MARKUPMAP(mmultiscripts_,
+          New_HyperText,
+          roles::MATHML_MULTISCRIPTS)
+
+MARKUPMAP(mtable_,
+          New_HTMLTableAccessible,
+          roles::MATHML_TABLE,
+          AttrFromDOM(align, align),
+          AttrFromDOM(columnlines_, columnlines_),
+          AttrFromDOM(rowlines_, rowlines_))
+
+MARKUPMAP(mlabeledtr_,
+          New_HTMLTableRowAccessible,
+          roles::MATHML_LABELED_ROW)
+
+MARKUPMAP(mtr_,
+          New_HTMLTableRowAccessible,
+          roles::MATHML_TABLE_ROW)
+
+MARKUPMAP(mtd_,
+          New_HTMLTableCellAccessible,
+          roles::MATHML_CELL)
+
+MARKUPMAP(maction_,
+          New_HyperText,
+          roles::MATHML_ACTION,
+          AttrFromDOM(actiontype_, actiontype_),
+          AttrFromDOM(selection_, selection_))
+
+MARKUPMAP(merror_,
+          New_HyperText,
+          roles::MATHML_ERROR)
+
+MARKUPMAP(mstack_,
+          New_HyperText,
+          roles::MATHML_STACK,
+          AttrFromDOM(align, align),
+          AttrFromDOM(position, position))
+
+MARKUPMAP(mlongdiv_,
+          New_HyperText,
+          roles::MATHML_LONG_DIVISION,
+          AttrFromDOM(longdivstyle_, longdivstyle_))
+
+MARKUPMAP(msgroup_,
+          New_HyperText,
+          roles::MATHML_STACK_GROUP,
+          AttrFromDOM(position, position),
+          AttrFromDOM(shift_, shift_))
+
+MARKUPMAP(msrow_,
+          New_HyperText,
+          roles::MATHML_STACK_ROW,
+          AttrFromDOM(position, position))
+
+MARKUPMAP(mscarries_,
+          New_HyperText,
+          roles::MATHML_STACK_CARRIES,
+          AttrFromDOM(location_, location_),
+          AttrFromDOM(position, position))
+
+MARKUPMAP(mscarry_,
+          New_HyperText,
+          roles::MATHML_STACK_CARRY,
+          AttrFromDOM(crossout_, crossout_))
+
+MARKUPMAP(msline_,
+          New_HyperText,
+          roles::MATHML_STACK_LINE,
+          AttrFromDOM(position, position))
+
+MARKUPMAP(nav,
+          New_HyperText,
+          roles::SECTION)
+
+MARKUPMAP(ol,
+          New_HTMLList,
+          roles::LIST)
+
+MARKUPMAP(option,
+          New_HTMLOption,
+          0)
+
+MARKUPMAP(optgroup,
+          New_HTMLOptgroup,
+          0)
+
+MARKUPMAP(output,
+          New_HTMLOutput,
+          roles::SECTION,
+          Attr(live, polite))
+
+MARKUPMAP(p,
+          nullptr,
+          roles::PARAGRAPH)
+
+MARKUPMAP(progress,
+          New_HTMLProgress,
+          0)
+
+MARKUPMAP(q,
+          New_HyperText,
+          0)
+
+MARKUPMAP(section,
+          New_HyperText,
+          roles::SECTION,
+          Attr(xmlroles, region))
+
+MARKUPMAP(time,
+          New_HyperText,
+          0,
+          Attr(xmlroles, time),
+          AttrFromDOM(datetime, datetime))
+
+MARKUPMAP(td,
+          New_HTMLTableHeaderCellIfScope,
+          0)
+
+MARKUPMAP(th,
+          New_HTMLTableHeaderCell,
+          0)
+
+MARKUPMAP(ul,
+          New_HTMLList,
+          roles::LIST)
--- a/accessible/base/NotificationController.cpp
+++ b/accessible/base/NotificationController.cpp
@@ -5,17 +5,17 @@
 
 #include "NotificationController.h"
 
 #include "DocAccessible-inl.h"
 #include "DocAccessibleChild.h"
 #include "TextLeafAccessible.h"
 #include "TextUpdater.h"
 
-#include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/Telemetry.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // NotificationCollector
@@ -47,18 +47,28 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(Notificat
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(NotificationController)
   if (tmp->mDocument)
     tmp->Shutdown();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(NotificationController)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHangingChildDocuments)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContentInsertions)
+  for (auto it = tmp->mContentInsertions.ConstIter(); !it.Done(); it.Next()) {
+    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mContentInsertions key");
+    cb.NoteXPCOMChild(it.Key());
+    nsTArray<nsCOMPtr<nsIContent>>* list = it.UserData();
+    for (uint32_t i = 0; i < list->Length(); i++) {
+      NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
+                                         "mContentInsertions value item");
+      cb.NoteXPCOMChild(list->ElementAt(i));
+    }
+  }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvents)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRelocations)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(NotificationController, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(NotificationController, Release)
 
 ////////////////////////////////////////////////////////////////////////////////
 // NotificationCollector: public
 
@@ -81,69 +91,84 @@ NotificationController::Shutdown()
 
   mDocument = nullptr;
   mPresShell = nullptr;
 
   mTextHash.Clear();
   mContentInsertions.Clear();
   mNotifications.Clear();
   mEvents.Clear();
+  mRelocations.Clear();
 }
 
 void
 NotificationController::ScheduleChildDocBinding(DocAccessible* aDocument)
 {
   // Schedule child document binding to the tree.
   mHangingChildDocuments.AppendElement(aDocument);
   ScheduleProcessing();
 }
 
 void
 NotificationController::ScheduleContentInsertion(Accessible* aContainer,
                                                  nsIContent* aStartChildNode,
                                                  nsIContent* aEndChildNode)
 {
-  nsRefPtr<ContentInsertion> insertion = new ContentInsertion(mDocument,
-                                                              aContainer);
-  if (insertion && insertion->InitChildList(aStartChildNode, aEndChildNode) &&
-      mContentInsertions.AppendElement(insertion)) {
+  nsTArray<nsCOMPtr<nsIContent>>* list =
+    mContentInsertions.LookupOrAdd(aContainer);
+
+  bool needsProcessing = false;
+  nsIContent* node = aStartChildNode;
+  while (node != aEndChildNode) {
+    // Notification triggers for content insertion even if no content was
+    // actually inserted, check if the given content has a frame to discard
+    // this case early.
+    if (node->GetPrimaryFrame()) {
+      if (list->AppendElement(node))
+        needsProcessing = true;
+    }
+    node = node->GetNextSibling();
+  }
+
+  if (needsProcessing) {
     ScheduleProcessing();
   }
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// NotificationCollector: protected
-
 void
 NotificationController::ScheduleProcessing()
 {
   // If notification flush isn't planed yet start notification flush
   // asynchronously (after style and layout).
   if (mObservingState == eNotObservingRefresh) {
     if (mPresShell->AddRefreshObserver(this, Flush_Display))
       mObservingState = eRefreshObserving;
   }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// NotificationCollector: protected
+
 bool
 NotificationController::IsUpdatePending()
 {
   return mPresShell->IsLayoutFlushObserver() ||
     mObservingState == eRefreshProcessingForUpdate ||
-    mContentInsertions.Length() != 0 || mNotifications.Length() != 0 ||
+    mContentInsertions.Count() != 0 || mNotifications.Length() != 0 ||
     mTextHash.Count() != 0 ||
     !mDocument->HasLoadState(DocAccessible::eTreeConstructed);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // NotificationCollector: private
 
 void
 NotificationController::WillRefresh(mozilla::TimeStamp aTime)
 {
+  PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);
   Telemetry::AutoTimer<Telemetry::A11Y_UPDATE_TIME> updateTimer;
 
   // 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;
@@ -170,17 +195,17 @@ NotificationController::WillRefresh(mozi
       logging::MsgBegin("TREE", "initial tree created");
       logging::Address("document", mDocument);
       logging::MsgEnd();
     }
 #endif
 
     mDocument->DoInitialUpdate();
 
-    NS_ASSERTION(mContentInsertions.Length() == 0,
+    NS_ASSERTION(mContentInsertions.Count() == 0,
                  "Pending content insertions while initial accessible tree isn't created!");
   }
 
   // Initialize scroll support if needed.
   if (!(mDocument->mDocFlags & DocAccessible::eScrollInitialized))
     mDocument->AddScrollListener();
 
   // Process content inserted notifications to update the tree. Process other
@@ -188,56 +213,138 @@ NotificationController::WillRefresh(mozi
   // notifications are queued during this processing then they will be processed
   // on next refresh. If notification processing queues up new events then they
   // are processed in this refresh. If events processing queues up new events
   // then new events are processed on next refresh.
   // Note: notification processing or event handling may shut down the owning
   // document accessible.
 
   // Process only currently queued content inserted notifications.
-  nsTArray<nsRefPtr<ContentInsertion> > contentInsertions;
-  contentInsertions.SwapElements(mContentInsertions);
-
-  uint32_t insertionCount = contentInsertions.Length();
-  for (uint32_t idx = 0; idx < insertionCount; idx++) {
-    contentInsertions[idx]->Process();
-    if (!mDocument)
+  for (auto iter = mContentInsertions.ConstIter(); !iter.Done(); iter.Next()) {
+    mDocument->ProcessContentInserted(iter.Key(), iter.UserData());
+    if (!mDocument) {
       return;
+    }
   }
+  mContentInsertions.Clear();
 
   // Process rendered text change notifications.
-  mTextHash.EnumerateEntries(TextEnumerator, mDocument);
+  for (auto iter = mTextHash.Iter(); !iter.Done(); iter.Next()) {
+    nsCOMPtrHashKey<nsIContent>* entry = iter.Get();
+    nsIContent* textNode = entry->GetKey();
+    Accessible* textAcc = mDocument->GetAccessible(textNode);
+
+    // If the text node is not in tree or doesn't have frame then this case should
+    // have been handled already by content removal notifications.
+    nsINode* containerNode = textNode->GetParentNode();
+    if (!containerNode) {
+      NS_ASSERTION(!textAcc,
+                   "Text node was removed but accessible is kept alive!");
+      continue;
+    }
+
+    nsIFrame* textFrame = textNode->GetPrimaryFrame();
+    if (!textFrame) {
+      NS_ASSERTION(!textAcc,
+                   "Text node isn't rendered but accessible is kept alive!");
+      continue;
+    }
+
+    nsIContent* containerElm = containerNode->IsElement() ?
+      containerNode->AsElement() : nullptr;
+
+    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()) {
+  #ifdef A11Y_LOG
+        if (logging::IsEnabled(logging::eTree | logging::eText)) {
+          logging::MsgBegin("TREE", "text node lost its content");
+          logging::Node("container", containerElm);
+          logging::Node("content", textNode);
+          logging::MsgEnd();
+        }
+  #endif
+
+        mDocument->ContentRemoved(containerElm, textNode);
+        continue;
+      }
+
+      // Update text of the accessible and fire text change events.
+  #ifdef A11Y_LOG
+      if (logging::IsEnabled(logging::eText)) {
+        logging::MsgBegin("TEXT", "text may be changed");
+        logging::Node("container", containerElm);
+        logging::Node("content", textNode);
+        logging::MsgEntry("old text '%s'",
+                          NS_ConvertUTF16toUTF8(textAcc->AsTextLeaf()->Text()).get());
+        logging::MsgEntry("new text: '%s'",
+                          NS_ConvertUTF16toUTF8(text.mString).get());
+        logging::MsgEnd();
+      }
+  #endif
+
+      TextUpdater::Run(mDocument, textAcc->AsTextLeaf(), text.mString);
+      continue;
+    }
+
+    // Append an accessible if rendered text is not empty.
+    if (!text.mString.IsEmpty()) {
+  #ifdef A11Y_LOG
+      if (logging::IsEnabled(logging::eTree | logging::eText)) {
+        logging::MsgBegin("TREE", "text node gains new content");
+        logging::Node("container", containerElm);
+        logging::Node("content", textNode);
+        logging::MsgEnd();
+      }
+  #endif
+
+      // Make sure the text node is in accessible document still.
+      Accessible* container = mDocument->GetAccessibleOrContainer(containerNode);
+      NS_ASSERTION(container,
+                   "Text node having rendered text hasn't accessible document!");
+      if (container) {
+        nsTArray<nsCOMPtr<nsIContent> > insertedContents;
+        insertedContents.AppendElement(textNode);
+        mDocument->ProcessContentInserted(container, &insertedContents);
+      }
+    }
+  }
   mTextHash.Clear();
 
   // Bind hanging child documents.
   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;
 
     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;
         }
 
         outerDocAcc->RemoveChild(childDoc);
       }
 
       // Failed to bind the child document, destroy it.
       childDoc->Shutdown();
     }
   }
 
-  nsTArray<nsRefPtr<DocAccessible>> newChildDocs = Move(mHangingChildDocuments);
+  mHangingChildDocuments.Clear();
 
   // If the document is ready and all its subdocuments are completely loaded
   // then process the document load.
   if (mDocument->HasLoadState(DocAccessible::eReady) &&
       !mDocument->HasLoadState(DocAccessible::eCompletelyLoaded) &&
       hangingDocCnt == 0) {
     uint32_t childDocCnt = mDocument->ChildDocumentCount(), childDocIdx = 0;
     for (; childDocIdx < childDocCnt; childDocIdx++) {
@@ -249,199 +356,78 @@ NotificationController::WillRefresh(mozi
     if (childDocIdx == childDocCnt) {
       mDocument->ProcessLoad();
       if (!mDocument)
         return;
     }
   }
 
   // Process only currently queued generic notifications.
-  nsTArray < nsRefPtr<Notification> > notifications;
+  nsTArray < RefPtr<Notification> > notifications;
   notifications.SwapElements(mNotifications);
 
   uint32_t notificationCount = notifications.Length();
   for (uint32_t idx = 0; idx < notificationCount; idx++) {
     notifications[idx]->Process();
     if (!mDocument)
       return;
   }
 
   // Process invalidation list of the document after all accessible tree
   // modification are done.
   mDocument->ProcessInvalidationList();
 
+  // We cannot rely on DOM tree to keep aria-owns relations updated. Make
+  // a validation to remove dead links.
+  mDocument->ValidateARIAOwned();
+
+  // Process relocation list.
+  for (uint32_t idx = 0; idx < mRelocations.Length(); idx++) {
+    mDocument->DoARIAOwnsRelocation(mRelocations[idx]);
+  }
+  mRelocations.Clear();
+
   // If a generic notification occurs after this point then we may be allowed to
   // process it synchronously.  However we do not want to reenter if fireing
   // events causes script to run.
   mObservingState = eRefreshProcessing;
 
   ProcessEventQueue();
 
   if (IPCAccessibilityActive()) {
     size_t newDocCount = newChildDocs.Length();
     for (size_t i = 0; i < newDocCount; i++) {
       DocAccessible* childDoc = newChildDocs[i];
-      DocAccessibleChild* ipcDoc = new DocAccessibleChild(childDoc);
+      Accessible* parent = childDoc->Parent();
+      DocAccessibleChild* parentIPCDoc = mDocument->IPCDoc();
+      uint64_t id = reinterpret_cast<uintptr_t>(parent->UniqueID());
+      MOZ_ASSERT(id);
+      DocAccessibleChild* ipcDoc = childDoc->IPCDoc();
+      if (ipcDoc) {
+        parentIPCDoc->SendBindChildDoc(ipcDoc, id);
+        continue;
+      }
+
+      ipcDoc = new DocAccessibleChild(childDoc);
       childDoc->SetIPCDoc(ipcDoc);
-      auto contentChild = dom::ContentChild::GetSingleton();
-      DocAccessibleChild* parentIPCDoc = mDocument->IPCDoc();
-      uint64_t id = reinterpret_cast<uintptr_t>(childDoc->Parent()->UniqueID());
-      contentChild->SendPDocAccessibleConstructor(ipcDoc, parentIPCDoc, id);
+      nsCOMPtr<nsITabChild> tabChild =
+        do_GetInterface(mDocument->DocumentNode()->GetDocShell());
+      if (tabChild) {
+        static_cast<TabChild*>(tabChild.get())->
+          SendPDocAccessibleConstructor(ipcDoc, parentIPCDoc, id);
+      }
     }
   }
 
   mObservingState = eRefreshObserving;
   if (!mDocument)
     return;
 
   // Stop further processing if there are no new notifications of any kind or
   // events and document load is processed.
-  if (mContentInsertions.IsEmpty() && mNotifications.IsEmpty() &&
+  if (mContentInsertions.Count() == 0 && mNotifications.IsEmpty() &&
       mEvents.IsEmpty() && mTextHash.Count() == 0 &&
       mHangingChildDocuments.IsEmpty() &&
       mDocument->HasLoadState(DocAccessible::eCompletelyLoaded) &&
       mPresShell->RemoveRefreshObserver(this, Flush_Display)) {
     mObservingState = eNotObservingRefresh;
   }
 }
-
-////////////////////////////////////////////////////////////////////////////////
-// Notification controller: text leaf accessible text update
-
-PLDHashOperator
-NotificationController::TextEnumerator(nsCOMPtrHashKey<nsIContent>* aEntry,
-                                       void* aUserArg)
-{
-  DocAccessible* document = static_cast<DocAccessible*>(aUserArg);
-  nsIContent* textNode = aEntry->GetKey();
-  Accessible* textAcc = document->GetAccessible(textNode);
-
-  // If the text node is not in tree or doesn't have frame then this case should
-  // have been handled already by content removal notifications.
-  nsINode* containerNode = textNode->GetParentNode();
-  if (!containerNode) {
-    NS_ASSERTION(!textAcc,
-                 "Text node was removed but accessible is kept alive!");
-    return PL_DHASH_NEXT;
-  }
-
-  nsIFrame* textFrame = textNode->GetPrimaryFrame();
-  if (!textFrame) {
-    NS_ASSERTION(!textAcc,
-                 "Text node isn't rendered but accessible is kept alive!");
-    return PL_DHASH_NEXT;
-  }
-
-  nsIContent* containerElm = containerNode->IsElement() ?
-    containerNode->AsElement() : nullptr;
-
-  nsAutoString text;
-  textFrame->GetRenderedText(&text);
-
-  // Remove text accessible if rendered text is empty.
-  if (textAcc) {
-    if (text.IsEmpty()) {
-#ifdef A11Y_LOG
-      if (logging::IsEnabled(logging::eTree | logging::eText)) {
-        logging::MsgBegin("TREE", "text node lost its content");
-        logging::Node("container", containerElm);
-        logging::Node("content", textNode);
-        logging::MsgEnd();
-      }
-#endif
-
-      document->ContentRemoved(containerElm, textNode);
-      return PL_DHASH_NEXT;
-    }
-
-    // Update text of the accessible and fire text change events.
-#ifdef A11Y_LOG
-    if (logging::IsEnabled(logging::eText)) {
-      logging::MsgBegin("TEXT", "text may be changed");
-      logging::Node("container", containerElm);
-      logging::Node("content", textNode);
-      logging::MsgEntry("old text '%s'",
-                        NS_ConvertUTF16toUTF8(textAcc->AsTextLeaf()->Text()).get());
-      logging::MsgEntry("new text: '%s'",
-                        NS_ConvertUTF16toUTF8(text).get());
-      logging::MsgEnd();
-    }
-#endif
-
-    TextUpdater::Run(document, textAcc->AsTextLeaf(), text);
-    return PL_DHASH_NEXT;
-  }
-
-  // Append an accessible if rendered text is not empty.
-  if (!text.IsEmpty()) {
-#ifdef A11Y_LOG
-    if (logging::IsEnabled(logging::eTree | logging::eText)) {
-      logging::MsgBegin("TREE", "text node gains new content");
-      logging::Node("container", containerElm);
-      logging::Node("content", textNode);
-      logging::MsgEnd();
-    }
-#endif
-
-    // Make sure the text node is in accessible document still.
-    Accessible* container = document->GetAccessibleOrContainer(containerNode);
-    NS_ASSERTION(container,
-                 "Text node having rendered text hasn't accessible document!");
-    if (container) {
-      nsTArray<nsCOMPtr<nsIContent> > insertedContents;
-      insertedContents.AppendElement(textNode);
-      document->ProcessContentInserted(container, &insertedContents);
-    }
-  }
-
-  return PL_DHASH_NEXT;
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-// NotificationController: content inserted notification
-
-NotificationController::ContentInsertion::
-  ContentInsertion(DocAccessible* aDocument, Accessible* aContainer) :
-  mDocument(aDocument), mContainer(aContainer)
-{
-}
-
-bool
-NotificationController::ContentInsertion::
-  InitChildList(nsIContent* aStartChildNode, nsIContent* aEndChildNode)
-{
-  bool haveToUpdate = false;
-
-  nsIContent* node = aStartChildNode;
-  while (node != aEndChildNode) {
-    // Notification triggers for content insertion even if no content was
-    // actually inserted, check if the given content has a frame to discard
-    // this case early.
-    if (node->GetPrimaryFrame()) {
-      if (mInsertedContent.AppendElement(node))
-        haveToUpdate = true;
-    }
-
-    node = node->GetNextSibling();
-  }
-
-  return haveToUpdate;
-}
-
-NS_IMPL_CYCLE_COLLECTION(NotificationController::ContentInsertion,
-                         mContainer)
-
-NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(NotificationController::ContentInsertion,
-                                     AddRef)
-NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(NotificationController::ContentInsertion,
-                                       Release)
-
-void
-NotificationController::ContentInsertion::Process()
-{
-  mDocument->ProcessContentInserted(mContainer, &mInsertedContent);
-
-  mDocument = nullptr;
-  mContainer = nullptr;
-  mInsertedContent.Clear();
-}
-
--- a/accessible/base/NotificationController.h
+++ b/accessible/base/NotificationController.h
@@ -3,16 +3,18 @@
  * 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_NotificationController_h_
 #define mozilla_a11y_NotificationController_h_
 
 #include "EventQueue.h"
 
+#include "mozilla/IndexSequence.h"
+#include "mozilla/Tuple.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsRefreshDriver.h"
 
 #ifdef A11Y_LOG
 #include "Logging.h"
 #endif
 
 namespace mozilla {
@@ -49,55 +51,55 @@ private:
 
 /**
  * Template class for generic notification.
  *
  * @note  Instance is kept as a weak ref, the caller must guarantee it exists
  *        longer than the document accessible owning the notification controller
  *        that this notification is processed by.
  */
-template<class Class, class Arg>
+template<class Class, class ... Args>
 class TNotification : public Notification
 {
 public:
-  typedef void (Class::*Callback)(Arg*);
+  typedef void (Class::*Callback)(Args* ...);
 
-  TNotification(Class* aInstance, Callback aCallback, Arg* aArg) :
-    mInstance(aInstance), mCallback(aCallback), mArg(aArg) { }
+  TNotification(Class* aInstance, Callback aCallback, Args* ... aArgs) :
+    mInstance(aInstance), mCallback(aCallback), mArgs(aArgs...) { }
   virtual ~TNotification() { mInstance = nullptr; }
 
-  virtual void Process()
-  {
-    (mInstance->*mCallback)(mArg);
-
-    mInstance = nullptr;
-    mCallback = nullptr;
-    mArg = nullptr;
-  }
+  virtual void Process() override
+    { ProcessHelper(typename IndexSequenceFor<Args...>::Type()); }
 
 private:
   TNotification(const TNotification&);
   TNotification& operator = (const TNotification&);
 
+  template <size_t... Indices>
+    void ProcessHelper(IndexSequence<Indices...>)
+  {
+     (mInstance->*mCallback)(Get<Indices>(mArgs)...);
+  }
+
   Class* mInstance;
   Callback mCallback;
-  nsRefPtr<Arg> mArg;
+  Tuple<RefPtr<Args> ...> mArgs;
 };
 
 /**
  * Used to process notifications from core for the document accessible.
  */
-class NotificationController MOZ_FINAL : public EventQueue,
-                                         public nsARefreshObserver
+class NotificationController final : public EventQueue,
+                                     public nsARefreshObserver
 {
 public:
   NotificationController(DocAccessible* aDocument, nsIPresShell* aPresShell);
 
-  NS_IMETHOD_(MozExternalRefCountType) AddRef(void);
-  NS_IMETHOD_(MozExternalRefCountType) Release(void);
+  NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override;
+  NS_IMETHOD_(MozExternalRefCountType) Release(void) override;
 
   NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(NotificationController)
 
   /**
    * Shutdown the notification controller.
    */
   void Shutdown();
 
@@ -115,28 +117,51 @@ public:
    */
   void ScheduleChildDocBinding(DocAccessible* aDocument);
 
   /**
    * Schedule the accessible tree update because of rendered text changes.
    */
   inline void ScheduleTextUpdate(nsIContent* aTextNode)
   {
-    if (mTextHash.PutEntry(aTextNode))
-      ScheduleProcessing();
+    // Make sure we are not called with a node that is not in the DOM tree or
+    // not visible.
+    MOZ_ASSERT(aTextNode->GetParentNode(), "A text node is not in DOM");
+    MOZ_ASSERT(aTextNode->GetPrimaryFrame(), "A text node doesn't have a frame");
+    MOZ_ASSERT(aTextNode->GetPrimaryFrame()->StyleVisibility()->IsVisible(),
+               "A text node is not visible");
+
+    mTextHash.PutEntry(aTextNode);
+    ScheduleProcessing();
   }
 
   /**
    * Pend accessible tree update for content insertion.
    */
   void ScheduleContentInsertion(Accessible* aContainer,
                                 nsIContent* aStartChildNode,
                                 nsIContent* aEndChildNode);
 
   /**
+   * Pend an accessible subtree relocation.
+   */
+  void ScheduleRelocation(Accessible* aOwner)
+  {
+    if (!mRelocations.Contains(aOwner) && mRelocations.AppendElement(aOwner)) {
+      ScheduleProcessing();
+    }
+  }
+
+  /**
+   * Start to observe refresh to make notifications and events processing after
+   * layout.
+   */
+  void ScheduleProcessing();
+
+  /**
    * Process the generic notification synchronously if there are no pending
    * layout changes and no notifications are pending or being processed right
    * now. Otherwise, queue it up to process asynchronously.
    *
    * @note  The caller must guarantee that the given instance still exists when
    *        the notification is processed.
    */
   template<class Class, class Arg>
@@ -148,67 +173,60 @@ public:
 #ifdef A11Y_LOG
       if (mozilla::a11y::logging::IsEnabled(mozilla::a11y::logging::eNotifications))
         mozilla::a11y::logging::Text("sync notification processing");
 #endif
       (aInstance->*aMethod)(aArg);
       return;
     }
 
-    nsRefPtr<Notification> notification =
+    RefPtr<Notification> notification =
       new TNotification<Class, Arg>(aInstance, aMethod, aArg);
     if (notification && mNotifications.AppendElement(notification))
       ScheduleProcessing();
   }
 
   /**
    * Schedule the generic notification to process asynchronously.
    *
    * @note  The caller must guarantee that the given instance still exists when
    *        the notification is processed.
    */
-  template<class Class, class Arg>
+  template<class Class>
   inline void ScheduleNotification(Class* aInstance,
-                                   typename TNotification<Class, Arg>::Callback aMethod,
-                                   Arg* aArg)
+                                   typename TNotification<Class>::Callback aMethod)
   {
-    nsRefPtr<Notification> notification =
-      new TNotification<Class, Arg>(aInstance, aMethod, aArg);
+    RefPtr<Notification> notification =
+      new TNotification<Class>(aInstance, aMethod);
     if (notification && mNotifications.AppendElement(notification))
       ScheduleProcessing();
   }
 
 #ifdef DEBUG
   bool IsUpdating() const
     { return mObservingState == eRefreshProcessingForUpdate; }
 #endif
 
 protected:
   virtual ~NotificationController();
 
   nsCycleCollectingAutoRefCnt mRefCnt;
   NS_DECL_OWNINGTHREAD
 
   /**
-   * Start to observe refresh to make notifications and events processing after
-   * layout.
-   */
-  void ScheduleProcessing();
-
-  /**
    * Return true if the accessible tree state update is pending.
    */
   bool IsUpdatePending();
 
 private:
   NotificationController(const NotificationController&);
   NotificationController& operator = (const NotificationController&);
 
   // nsARefreshObserver
-  virtual void WillRefresh(mozilla::TimeStamp aTime);
+  virtual void WillRefresh(mozilla::TimeStamp aTime) override;
 
 private:
   /**
    * Indicates whether we're waiting on an event queue processing from our
    * notification controller to flush events.
    */
   enum eObservingState {
     eNotObservingRefresh,
@@ -221,57 +239,23 @@ private:
   /**
    * The presshell of the document accessible.
    */
   nsIPresShell* mPresShell;
 
   /**
    * Child documents that needs to be bound to the tree.
    */
-  nsTArray<nsRefPtr<DocAccessible> > mHangingChildDocuments;
+  nsTArray<RefPtr<DocAccessible> > mHangingChildDocuments;
 
   /**
-   * Storage for content inserted notification information.
+   * Pending accessible tree update notifications for content insertions.
    */
-  class ContentInsertion
-  {
-  public:
-    ContentInsertion(DocAccessible* aDocument, Accessible* aContainer);
-
-    NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(ContentInsertion)
-    NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(ContentInsertion)
-
-    bool InitChildList(nsIContent* aStartChildNode, nsIContent* aEndChildNode);
-    void Process();
-
-  protected:
-    virtual ~ContentInsertion() { mDocument = nullptr; }
-
-  private:
-    ContentInsertion();
-    ContentInsertion(const ContentInsertion&);
-    ContentInsertion& operator = (const ContentInsertion&);
-
-    // The document used to process content insertion, matched to document of
-    // the notification controller that this notification belongs to, therefore
-    // it's ok to keep it as weak ref.
-    DocAccessible* mDocument;
-
-    // The container accessible that content insertion occurs within.
-    nsRefPtr<Accessible> mContainer;
-
-    // Array of inserted contents.
-    nsTArray<nsCOMPtr<nsIContent> > mInsertedContent;
-  };
-
-  /**
-   * A pending accessible tree update notifications for content insertions.
-   * Don't make this an nsAutoTArray; we use SwapElements() on it.
-   */
-  nsTArray<nsRefPtr<ContentInsertion> > mContentInsertions;
+  nsClassHashtable<nsRefPtrHashKey<Accessible>,
+                   nsTArray<nsCOMPtr<nsIContent>>> mContentInsertions;
 
   template<class T>
   class nsCOMPtrHashKey : public PLDHashEntryHdr
   {
   public:
     typedef T* KeyType;
     typedef const T* KeyTypePointer;
 
@@ -288,29 +272,28 @@ private:
 
     enum { ALLOW_MEMMOVE = true };
 
    protected:
      nsCOMPtr<T> mKey;
   };
 
   /**
-   * A pending accessible tree update notifications for rendered text changes.
+   * Pending accessible tree update notifications for rendered text changes.
    */
   nsTHashtable<nsCOMPtrHashKey<nsIContent> > mTextHash;
 
   /**
-   * Update the accessible tree for pending rendered text change notifications.
+   * Other notifications like DOM events. Don't make this an AutoTArray; we
+   * use SwapElements() on it.
    */
-  static PLDHashOperator TextEnumerator(nsCOMPtrHashKey<nsIContent>* aEntry,
-                                        void* aUserArg);
+  nsTArray<RefPtr<Notification> > mNotifications;
 
   /**
-   * Other notifications like DOM events. Don't make this an nsAutoTArray; we
-   * use SwapElements() on it.
+   * Holds all scheduled relocations.
    */
-  nsTArray<nsRefPtr<Notification> > mNotifications;
+  nsTArray<RefPtr<Accessible> > mRelocations;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif // mozilla_a11y_NotificationController_h_
--- a/accessible/base/Platform.h
+++ b/accessible/base/Platform.h
@@ -1,16 +1,18 @@
 /* -*- 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 <stdint.h>
 
+class nsString;
+
 namespace mozilla {
 namespace a11y {
 
 class ProxyAccessible;
 
 enum EPlatformDisabledState {
   ePlatformIsForceEnabled = -1,
   ePlatformIsEnabled = 0,
@@ -50,23 +52,29 @@ void PlatformInit();
  * Note this is called before internal accessibility support is shutdown.
  */
 void PlatformShutdown();
 
 /**
  * called when a new ProxyAccessible is created, so the platform may setup a
  * wrapper for it, or take other action.
  */
-void ProxyCreated(ProxyAccessible*);
+void ProxyCreated(ProxyAccessible* aProxy, uint32_t aInterfaces);
 
 /**
  * Called just before a ProxyAccessible is destroyed so its wrapper can be
  * disposed of and other action taken.
  */
 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);
+void ProxyCaretMoveEvent(ProxyAccessible* aTarget, int32_t aOffset);
+void ProxyTextChangeEvent(ProxyAccessible* aTarget, const nsString& aStr,
+                          int32_t aStart, uint32_t aLen, bool aIsInsert,
+                          bool aFromUser);
 } // namespace a11y
 } // namespace mozilla
 
--- a/accessible/base/Relation.h
+++ b/accessible/base/Relation.h
@@ -90,18 +90,18 @@ public:
 
     if (!mFirstIter)
       mLastIter = nullptr;
 
     return target;
   }
 
 private:
-  Relation& operator = (const Relation&) MOZ_DELETE;
-  Relation(const Relation&) MOZ_DELETE;
+  Relation& operator = (const Relation&) = delete;
+  Relation(const Relation&) = delete;
 
   nsAutoPtr<AccIterable> mFirstIter;
   AccIterable* mLastIter;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
--- a/accessible/base/RelationType.h
+++ b/accessible/base/RelationType.h
@@ -2,22 +2,20 @@
 /* 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_relationtype_h_
 #define mozilla_a11y_relationtype_h_
 
-#include "mozilla/TypedEnum.h"
-
 namespace mozilla {
 namespace a11y {
 
-MOZ_BEGIN_ENUM_CLASS(RelationType)
+enum class RelationType {
 
   /**
    * This object is labelled by a target object.
    */
   LABELLED_BY = 0x00,
 
   /**
    * This object is label for a target object.
@@ -126,14 +124,14 @@ MOZ_BEGIN_ENUM_CLASS(RelationType)
 
   /**
    * The target object is the containing application object.
    */
   CONTAINING_APPLICATION = 0x14,
 
   LAST = CONTAINING_APPLICATION
 
-MOZ_END_ENUM_CLASS(RelationType)
+};
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/base/Role.h
+++ b/accessible/base/Role.h
@@ -711,37 +711,37 @@ enum Role {
    * A item of list that is shown by combobox.
    */
   COMBOBOX_OPTION = 115,
 
   /**
    * An image map -- has child links representing the areas
    */
   IMAGE_MAP = 116,
-  
+
   /**
    * An option in a listbox
    */
   OPTION = 117,
-  
+
   /**
    * A rich option in a listbox, it can have other widgets as children
    */
   RICH_OPTION = 118,
-  
+
   /**
    * A list of options
    */
   LISTBOX = 119,
 
   /**
    * Represents a mathematical equation in the accessible name
    */
   FLAT_EQUATION = 120,
-  
+
   /**
    * Represents a cell within a grid. It is used for role="gridcell". Unlike
    * CELL, it allows the calculation of the accessible name from subtree.
    * Also, see TABLE.
    */
   GRID_CELL = 121,
 
   /**
@@ -780,17 +780,204 @@ enum Role {
    */
   DEFINITION = 128,
 
   /**
    * Represent a keyboard or keypad key (ARIA role "key").
    */
   KEY = 129,
 
-  LAST_ROLE = KEY
+  /**
+   * Represent a switch control widget (ARIA role "switch").
+   */
+  SWITCH = 130,
+
+  /**
+   * A block of MathML code (math).
+   */
+  MATHML_MATH = 131,
+
+  /**
+   * A MathML identifier (mi in MathML).
+   */
+  MATHML_IDENTIFIER = 132,
+
+  /**
+   * A MathML number (mn in MathML).
+   */
+  MATHML_NUMBER = 133,
+
+  /**
+   * A MathML operator (mo in MathML).
+   */
+  MATHML_OPERATOR = 134,
+
+  /**
+   * A MathML text (mtext in MathML).
+   */
+  MATHML_TEXT = 135,
+
+  /**
+   * A MathML string literal (ms in MathML).
+   */
+  MATHML_STRING_LITERAL = 136,
+
+  /**
+   * A MathML glyph (mglyph in MathML).
+   */
+  MATHML_GLYPH = 137,
+
+  /**
+   * A MathML row (mrow in MathML).
+   */
+  MATHML_ROW = 138,
+
+  /**
+   * A MathML fraction (mfrac in MathML).
+   */
+  MATHML_FRACTION = 139,
+
+  /**
+   * A MathML square root (msqrt in MathML).
+   */
+  MATHML_SQUARE_ROOT = 140,
+
+  /**
+   * A MathML root (mroot in MathML).
+   */
+  MATHML_ROOT = 141,
+
+  /**
+   * A MathML fenced element (mfenced in MathML).
+   */
+  MATHML_FENCED = 142,
+
+  /**
+   * A MathML enclosed element (menclose in MathML).
+   */
+  MATHML_ENCLOSED = 143,
+
+  /**
+   * A MathML styling element (mstyle in MathML).
+   */
+  MATHML_STYLE = 144,
+
+  /**
+   * A MathML subscript (msub in MathML).
+   */
+  MATHML_SUB = 145,
+
+  /**
+   * A MathML superscript (msup in MathML).
+   */
+  MATHML_SUP = 146,
+
+  /**
+   * A MathML subscript and superscript (msubsup in MathML).
+   */
+  MATHML_SUB_SUP = 147,
+
+  /**
+   * A MathML underscript (munder in MathML).
+   */
+  MATHML_UNDER = 148,
+
+  /**
+   * A MathML overscript (mover in MathML).
+   */
+  MATHML_OVER = 149,
+
+  /**
+   * A MathML underscript and overscript (munderover in MathML).
+   */
+  MATHML_UNDER_OVER = 150,
+
+  /**
+   * A MathML multiple subscript and superscript element (mmultiscripts in
+   * MathML).
+   */
+  MATHML_MULTISCRIPTS = 151,
+
+  /**
+   * A MathML table (mtable in MathML).
+   */
+  MATHML_TABLE = 152,
+
+  /**
+   * A MathML labelled table row (mlabeledtr in MathML).
+   */
+  MATHML_LABELED_ROW = 153,
+
+  /**
+   * A MathML table row (mtr in MathML).
+   */
+  MATHML_TABLE_ROW = 154,
+
+  /**
+   * A MathML table entry or cell (mtd in MathML).
+   */
+  MATHML_CELL = 155,
+
+  /**
+   * A MathML interactive element (maction in MathML).
+   */
+  MATHML_ACTION = 156,
+
+  /**
+   * A MathML error message (merror in MathML).
+   */
+  MATHML_ERROR = 157,
+
+  /**
+   * A MathML stacked (rows of numbers) element (mstack in MathML).
+   */
+  MATHML_STACK = 158,
+
+  /**
+   * A MathML long division element (mlongdiv in MathML).
+   */
+  MATHML_LONG_DIVISION = 159,
+
+  /**
+   * A MathML stack group (msgroup in MathML).
+   */
+  MATHML_STACK_GROUP = 160,
+
+  /**
+   * A MathML stack row (msrow in MathML).
+   */
+  MATHML_STACK_ROW = 161,
+
+  /**
+   * MathML carries, borrows, or crossouts for a row (mscarries in MathML).
+   */
+  MATHML_STACK_CARRIES = 162,
+
+  /**
+   * A MathML carry, borrow, or crossout for a column (mscarry in MathML).
+   */
+  MATHML_STACK_CARRY = 163,
+
+  /**
+   * A MathML line in a stack (msline in MathML).
+   */
+  MATHML_STACK_LINE = 164,
+
+  /**
+   * A group containing radio buttons
+   */
+  RADIO_GROUP = 165,
+
+  /**
+   * A text container exposing brief amount of information. See related
+   * TEXT_CONTAINER role.
+   */
+  TEXT = 166,
+
+  LAST_ROLE = TEXT
 };
 
 } // namespace role
 
 typedef enum mozilla::a11y::roles::Role role;
 
 } // namespace a11y
 } // namespace mozilla
--- a/accessible/base/RoleMap.h
+++ b/accessible/base/RoleMap.h
@@ -69,17 +69,17 @@ ROLE(CARET,
      NSAccessibilityUnknownRole,  //Unused on OS X.
      ROLE_SYSTEM_CARET,
      ROLE_SYSTEM_CARET,
      eNoNameRule)
 
 ROLE(ALERT,
      "alert",
      ATK_ROLE_ALERT,
-     NSAccessibilityWindowRole,
+     NSAccessibilityGroupRole,
      ROLE_SYSTEM_ALERT,
      ROLE_SYSTEM_ALERT,
      eNoNameRule)
 
 ROLE(WINDOW,
      "window",
      ATK_ROLE_WINDOW,
      NSAccessibilityWindowRole,  //Irrelevant on OS X; all window a11y is handled by the system.
@@ -182,17 +182,17 @@ ROLE(GROUPING,
      NSAccessibilityGroupRole,
      ROLE_SYSTEM_GROUPING,
      ROLE_SYSTEM_GROUPING,
      eNoNameRule)
 
 ROLE(SEPARATOR,
      "separator",
      ATK_ROLE_SEPARATOR,
-     NSAccessibilityUnknownRole,
+     NSAccessibilitySplitterRole,
      ROLE_SYSTEM_SEPARATOR,
      ROLE_SYSTEM_SEPARATOR,
      eNoNameRule)
 
 ROLE(TOOLBAR,
      "toolbar",
      ATK_ROLE_TOOL_BAR,
      NSAccessibilityToolbarRole,
@@ -206,33 +206,33 @@ ROLE(STATUSBAR,
      NSAccessibilityUnknownRole,  //Doesn't exist on OS X (a status bar is its parts; a progressbar, a label, etc.)
      ROLE_SYSTEM_STATUSBAR,
      ROLE_SYSTEM_STATUSBAR,
      eNoNameRule)
 
 ROLE(TABLE,
      "table",
      ATK_ROLE_TABLE,
-     NSAccessibilityGroupRole,
+     NSAccessibilityTableRole,
      ROLE_SYSTEM_TABLE,
      ROLE_SYSTEM_TABLE,
      eNoNameRule)
 
 ROLE(COLUMNHEADER,
      "columnheader",
      ATK_ROLE_COLUMN_HEADER,
-     NSAccessibilityGroupRole,
+     NSAccessibilityCellRole,
      ROLE_SYSTEM_COLUMNHEADER,
      ROLE_SYSTEM_COLUMNHEADER,
      eNameFromSubtreeRule)
 
 ROLE(ROWHEADER,
      "rowheader",
      ATK_ROLE_ROW_HEADER,
-     NSAccessibilityGroupRole,
+     NSAccessibilityCellRole,
      ROLE_SYSTEM_ROWHEADER,
      ROLE_SYSTEM_ROWHEADER,
      eNameFromSubtreeRule)
 
 ROLE(COLUMN,
      "column",
      ATK_ROLE_UNKNOWN,
      NSAccessibilityColumnRole,
@@ -246,17 +246,17 @@ ROLE(ROW,
      NSAccessibilityRowRole,
      ROLE_SYSTEM_ROW,
      ROLE_SYSTEM_ROW,
      eNameFromSubtreeRule)
 
 ROLE(CELL,
      "cell",
      ATK_ROLE_TABLE_CELL,
-     NSAccessibilityGroupRole,
+     NSAccessibilityCellRole,
      ROLE_SYSTEM_CELL,
      ROLE_SYSTEM_CELL,
      eNameFromSubtreeIfReqRule)
 
 ROLE(LINK,
      "link",
      ATK_ROLE_LINK,
      @"AXLink",  //10.4+ the attr first define in SDK 10.4, so we define it here too. ROLE_LINK
@@ -749,17 +749,17 @@ ROLE(TERMINAL,
      ATK_ROLE_TERMINAL,
      NSAccessibilityUnknownRole,
      USE_ROLE_STRING,
      IA2_ROLE_TERMINAL,
      eNoNameRule)
 
 ROLE(TEXT_CONTAINER,
      "text container",
-     ATK_ROLE_TEXT,
+     ATK_ROLE_SECTION,
      NSAccessibilityGroupRole,
      USE_ROLE_STRING,
      IA2_ROLE_TEXT_FRAME,
      eNameFromSubtreeIfReqRule)
 
 ROLE(TOGGLE_BUTTON,
      "toggle button",
      ATK_ROLE_TOGGLE_BUTTON,
@@ -950,17 +950,17 @@ ROLE(IMAGE_MAP,
      NSAccessibilityUnknownRole,
      ROLE_SYSTEM_GRAPHIC,
      ROLE_SYSTEM_GRAPHIC,
      eNoNameRule)
 
 ROLE(OPTION,
      "listbox option",
      ATK_ROLE_LIST_ITEM,
-     NSAccessibilityRowRole,
+     NSAccessibilityStaticTextRole,
      ROLE_SYSTEM_LISTITEM,
      ROLE_SYSTEM_LISTITEM,
      eNameFromSubtreeRule)
 
 ROLE(RICH_OPTION,
      "listbox rich option",
      ATK_ROLE_LIST_ITEM,
      NSAccessibilityRowRole,
@@ -1050,8 +1050,305 @@ ROLE(DEFINITION,
 
 ROLE(KEY,
      "key",
      ATK_ROLE_PUSH_BUTTON,
      NSAccessibilityButtonRole,
      ROLE_SYSTEM_PUSHBUTTON,
      ROLE_SYSTEM_PUSHBUTTON,
      eNameFromSubtreeRule)
+
+ROLE(SWITCH,
+     "switch",
+     ATK_ROLE_TOGGLE_BUTTON,
+     NSAccessibilityCheckBoxRole,
+     ROLE_SYSTEM_CHECKBUTTON,
+     IA2_ROLE_TOGGLE_BUTTON,
+     eNameFromSubtreeRule)
+
+ROLE(MATHML_MATH,
+     "math",
+     ATK_ROLE_MATH,
+     NSAccessibilityGroupRole,
+     ROLE_SYSTEM_EQUATION,
+     ROLE_SYSTEM_EQUATION,
+     eNoNameRule)
+
+ROLE(MATHML_IDENTIFIER,
+     "mathml identifier",
+     ATK_ROLE_STATIC,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNameFromSubtreeRule)
+
+ROLE(MATHML_NUMBER,
+     "mathml number",
+     ATK_ROLE_STATIC,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNameFromSubtreeRule)
+
+ROLE(MATHML_OPERATOR,
+     "mathml operator",
+     ATK_ROLE_STATIC,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNameFromSubtreeRule)
+
+ROLE(MATHML_TEXT,
+     "mathml text",
+     ATK_ROLE_STATIC,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNameFromSubtreeRule)
+
+ROLE(MATHML_STRING_LITERAL,
+     "mathml string literal",
+     ATK_ROLE_STATIC,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNameFromSubtreeRule)
+
+ROLE(MATHML_GLYPH,
+     "mathml glyph",
+     ATK_ROLE_IMAGE,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNameFromSubtreeRule)
+
+ROLE(MATHML_ROW,
+     "mathml row",
+     ATK_ROLE_SECTION,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_FRACTION,
+     "mathml fraction",
+     ATK_ROLE_MATH_FRACTION,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_SQUARE_ROOT,
+     "mathml square root",
+     ATK_ROLE_MATH_ROOT,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_ROOT,
+     "mathml root",
+     ATK_ROLE_MATH_ROOT,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_FENCED,
+     "mathml fenced",
+     ATK_ROLE_SECTION,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_ENCLOSED,
+     "mathml enclosed",
+     ATK_ROLE_SECTION,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_STYLE,
+     "mathml style",
+     ATK_ROLE_SECTION,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_SUB,
+     "mathml sub",
+     ATK_ROLE_SECTION,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_SUP,
+     "mathml sup",
+     ATK_ROLE_SECTION,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_SUB_SUP,
+     "mathml sub sup",
+     ATK_ROLE_SECTION,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_UNDER,
+     "mathml under",
+     ATK_ROLE_SECTION,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_OVER,
+     "mathml over",
+     ATK_ROLE_SECTION,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_UNDER_OVER,
+     "mathml under over",
+     ATK_ROLE_SECTION,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_MULTISCRIPTS,
+     "mathml multiscripts",
+     ATK_ROLE_SECTION,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_TABLE,
+     "mathml table",
+     ATK_ROLE_TABLE,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_LABELED_ROW,
+     "mathml labeled row",
+     ATK_ROLE_TABLE_ROW,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_TABLE_ROW,
+     "mathml table row",
+     ATK_ROLE_TABLE_ROW,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_CELL,
+     "mathml cell",
+     ATK_ROLE_TABLE_CELL,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_ACTION,
+     "mathml action",
+     ATK_ROLE_SECTION,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_ERROR,
+     "mathml error",
+     ATK_ROLE_SECTION,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_STACK,
+     "mathml stack",
+     ATK_ROLE_UNKNOWN,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_LONG_DIVISION,
+     "mathml long division",
+     ATK_ROLE_UNKNOWN,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_STACK_GROUP,
+     "mathml stack group",
+     ATK_ROLE_UNKNOWN,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_STACK_ROW,
+     "mathml stack row",
+     ATK_ROLE_UNKNOWN,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_STACK_CARRIES,
+     "mathml stack carries",
+     ATK_ROLE_UNKNOWN,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_STACK_CARRY,
+     "mathml stack carry",
+     ATK_ROLE_UNKNOWN,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(MATHML_STACK_LINE,
+     "mathml stack line",
+     ATK_ROLE_UNKNOWN,
+     NSAccessibilityGroupRole,
+     0,
+     IA2_ROLE_UNKNOWN,
+     eNoNameRule)
+
+ROLE(RADIO_GROUP,
+     "grouping",
+     ATK_ROLE_PANEL,
+     NSAccessibilityRadioGroupRole,
+     ROLE_SYSTEM_GROUPING,
+     ROLE_SYSTEM_GROUPING,
+     eNoNameRule)
+
+ROLE(TEXT,
+     "text",
+     ATK_ROLE_STATIC,
+     NSAccessibilityGroupRole,
+     USE_ROLE_STRING,
+     IA2_ROLE_TEXT_FRAME,
+     eNameFromSubtreeIfReqRule)
+
--- a/accessible/base/SelectionManager.cpp
+++ b/accessible/base/SelectionManager.cpp
@@ -19,22 +19,22 @@
 #include "nsIPresShell.h"
 #include "mozilla/dom/Selection.h"
 #include "mozilla/dom/Element.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 using mozilla::dom::Selection;
 
-struct mozilla::a11y::SelData MOZ_FINAL
+struct mozilla::a11y::SelData final
 {
   SelData(Selection* aSel, int32_t aReason) :
     mSel(aSel), mReason(aReason) {}
 
-  nsRefPtr<Selection> mSel;
+  RefPtr<Selection> mSel;
   int16_t mReason;
 
   NS_INLINE_DECL_REFCOUNTING(SelData)
 
 private:
   // Private destructor, to discourage deletion outside of Release():
   ~SelData() {}
 };
@@ -159,17 +159,17 @@ SelectionManager::ProcessTextSelChangeEv
   // event->mSel is correct.
   if (!selection)
     selection = event->mSel;
 
   mCaretOffset = caretCntr->DOMPointToOffset(selection->GetFocusNode(),
                                              selection->FocusOffset());
   mAccWithCaret = caretCntr;
   if (mCaretOffset != -1) {
-    nsRefPtr<AccCaretMoveEvent> caretMoveEvent =
+    RefPtr<AccCaretMoveEvent> caretMoveEvent =
       new AccCaretMoveEvent(caretCntr, mCaretOffset, aEvent->FromUserInput());
     nsEventShell::FireEvent(caretMoveEvent);
   }
 }
 
 NS_IMETHODIMP
 SelectionManager::NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
                                          nsISelection* aSelection,
@@ -184,17 +184,17 @@ SelectionManager::NotifySelectionChanged
   if (logging::IsEnabled(logging::eSelection))
     logging::SelChange(aSelection, document, aReason);
 #endif
 
   if (document) {
     // Selection manager has longer lifetime than any document accessible,
     // so that we are guaranteed that the notification is processed before
     // the selection manager is destroyed.
-    nsRefPtr<SelData> selData =
+    RefPtr<SelData> selData =
       new SelData(static_cast<Selection*>(aSelection), aReason);
     document->HandleNotification<SelectionManager, SelData>
       (this, &SelectionManager::ProcessSelectionChanged, selData);
   }
 
   return NS_OK;
 }
 
@@ -221,17 +221,17 @@ SelectionManager::ProcessSelectionChange
 
   HyperTextAccessible* text = nsAccUtils::GetTextContainer(cntrNode);
   if (!text) {
     NS_NOTREACHED("We must reach document accessible implementing text interface!");
     return;
   }
 
   if (selection->GetType() == nsISelectionController::SELECTION_NORMAL) {
-    nsRefPtr<AccEvent> event =
+    RefPtr<AccEvent> event =
       new AccTextSelChangeEvent(text, selection, aSelData->mReason);
     text->Document()->FireDelayedEvent(event);
 
   } else if (selection->GetType() == nsISelectionController::SELECTION_SPELLCHECK) {
     // XXX: fire an event for container accessible of the focus/anchor range
     // of the spelcheck selection.
     text->Document()->FireDelayedEvent(nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED,
                                        text);
--- a/accessible/base/StyleInfo.cpp
+++ b/accessible/base/StyleInfo.cpp
@@ -53,16 +53,17 @@ StyleInfo::TextIndent(nsAString& aValue)
   switch (styleCoord.GetUnit()) {
     case eStyleUnit_Coord:
       coordVal = styleCoord.GetCoordValue();
       break;
 
     case eStyleUnit_Percent:
     {
       nsIFrame* frame = mElement->GetPrimaryFrame();
+      MOZ_ASSERT(frame, "frame must be a valid pointer.");
       nsIFrame* containerFrame = frame->GetContainingBlock();
       nscoord percentageBase = containerFrame->GetContentRect().width;
       coordVal = NSCoordSaturatingMultiply(percentageBase,
                                            styleCoord.GetPercentValue());
       break;
     }
 
     case eStyleUnit_Null:
@@ -83,16 +84,17 @@ StyleInfo::TextIndent(nsAString& aValue)
 
   aValue.AppendFloat(nsPresContext::AppUnitsToFloatCSSPixels(coordVal));
   aValue.AppendLiteral("px");
 }
 
 void
 StyleInfo::Margin(css::Side aSide, nsAString& aValue)
 {
+  MOZ_ASSERT(mElement->GetPrimaryFrame(), " mElement->GetPrimaryFrame() needs to be valid pointer");
   aValue.Truncate();
 
   nscoord coordVal = mElement->GetPrimaryFrame()->GetUsedMargin().Side(aSide);
   aValue.AppendFloat(nsPresContext::AppUnitsToFloatCSSPixels(coordVal));
   aValue.AppendLiteral("px");
 }
 
 void
--- a/accessible/base/StyleInfo.h
+++ b/accessible/base/StyleInfo.h
@@ -27,22 +27,22 @@ public:
   void MarginTop(nsAString& aValue) { Margin(eSideTop, aValue); }
   void MarginBottom(nsAString& aValue) { Margin(eSideBottom, aValue); }
 
   static void FormatColor(const nscolor& aValue, nsString& aFormattedValue);
   static void FormatFontStyle(const nscoord& aValue, nsAString& aFormattedValue);
   static void FormatTextDecorationStyle(uint8_t aValue, nsAString& aFormattedValue);
 
 private:
-  StyleInfo() MOZ_DELETE;
-  StyleInfo(const StyleInfo&) MOZ_DELETE;
-  StyleInfo& operator = (const StyleInfo&) MOZ_DELETE;
+  StyleInfo() = delete;
+  StyleInfo(const StyleInfo&) = delete;
+  StyleInfo& operator = (const StyleInfo&) = delete;
 
   void Margin(Side aSide, nsAString& aValue);
 
   dom::Element* mElement;
-  nsRefPtr<nsStyleContext> mStyleContext;
+  RefPtr<nsStyleContext> mStyleContext;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/base/TextAttrs.cpp
+++ b/accessible/base/TextAttrs.cpp
@@ -13,16 +13,20 @@
 #include "gfxFont.h"
 #include "nsFontMetrics.h"
 #include "nsLayoutUtils.h"
 #include "nsContainerFrame.h"
 #include "HyperTextAccessible.h"
 #include "mozilla/AppUnits.h"
 #include "mozilla/gfx/2D.h"
 
+#if defined(MOZ_WIDGET_GTK)
+#include "gfxPlatformGtk.h" // xxx - for UseFcFontList
+#endif
+
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // TextAttrsMgr
 ////////////////////////////////////////////////////////////////////////////////
 
 void
@@ -451,17 +455,17 @@ TextAttrsMgr::FontFamilyTextAttr::
 {
   nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::font_family, aValue);
 }
 
 bool
 TextAttrsMgr::FontFamilyTextAttr::
   GetFontFamily(nsIFrame* aFrame, nsString& aFamily)
 {
-  nsRefPtr<nsFontMetrics> fm;
+  RefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm));
 
   gfxFontGroup* fontGroup = fm->GetThebesFontGroup();
   gfxFont* font = fontGroup->GetFirstValidFont();
   gfxFontEntry* fontEntry = font->GetFontEntry();
   aFamily = fontEntry->FamilyName();
   return true;
 }
@@ -609,45 +613,54 @@ TextAttrsMgr::FontWeightTextAttr::
 }
 
 int32_t
 TextAttrsMgr::FontWeightTextAttr::
   GetFontWeight(nsIFrame* aFrame)
 {
   // nsFont::width isn't suitable here because it's necessary to expose real
   // value of font weight (used font might not have some font weight values).
-  nsRefPtr<nsFontMetrics> fm;
+  RefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm));
 
   gfxFontGroup *fontGroup = fm->GetThebesFontGroup();
   gfxFont *font = fontGroup->GetFirstValidFont();
 
   // When there doesn't exist a bold font in the family and so the rendering of
   // a non-bold font face is changed so that the user sees what looks like a
   // bold font, i.e. synthetic bolding is used. IsSyntheticBold method is only
   // needed on Mac, but it is "safe" to use on all platforms.  (For non-Mac
   // platforms it always return false.)
   if (font->IsSyntheticBold())
     return 700;
 
-#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)
-  // On Linux, font->GetStyle()->weight will give the absolute weight requested
-  // of the font face. The Linux code uses the gfxFontEntry constructor which
-  // doesn't initialize the weight field.
-  return font->GetStyle()->weight;
-#else
-  // On Windows, font->GetStyle()->weight will give the same weight as
-  // fontEntry->Weight(), the weight of the first font in the font group, which
-  // may not be the weight of the font face used to render the characters.
-  // On Mac, font->GetStyle()->weight will just give the same number as
-  // getComputedStyle(). fontEntry->Weight() will give the weight of the font
-  // face used.
-  gfxFontEntry *fontEntry = font->GetFontEntry();
-  return fontEntry->Weight();
+  bool useFontEntryWeight = true;
+
+  // Under Linux, when gfxPangoFontGroup code is used,
+  // font->GetStyle()->weight will give the absolute weight requested of the
+  // font face. The gfxPangoFontGroup code uses the gfxFontEntry constructor
+  // which doesn't initialize the weight field.
+#if defined(MOZ_WIDGET_QT)
+  useFontEntryWeight = false;
+#elif defined(MOZ_WIDGET_GTK)
+  useFontEntryWeight = gfxPlatformGtk::UseFcFontList();
 #endif
+
+  if (useFontEntryWeight) {
+    // On Windows, font->GetStyle()->weight will give the same weight as
+    // fontEntry->Weight(), the weight of the first font in the font group,
+    // which may not be the weight of the font face used to render the
+    // characters. On Mac, font->GetStyle()->weight will just give the same
+    // number as getComputedStyle(). fontEntry->Weight() will give the weight
+    // of the font face used.
+    gfxFontEntry *fontEntry = font->GetFontEntry();
+    return fontEntry->Weight();
+  } else {
+    return font->GetStyle()->weight;
+  }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // AutoGeneratedTextAttr
 ////////////////////////////////////////////////////////////////////////////////
 TextAttrsMgr::AutoGeneratedTextAttr::
   AutoGeneratedTextAttr(HyperTextAccessible* aHyperTextAcc,
                         Accessible* aAccessible) :
@@ -867,18 +880,17 @@ TextAttrsMgr::TextPosTextAttr::
     case eStyleUnit_Turn:
     case eStyleUnit_FlexFraction:
     case eStyleUnit_Integer:
     case eStyleUnit_Calc:
       break;
   }
 
   const nsIContent* content = aFrame->GetContent();
-  if (content && content->IsHTML()) {
-    const nsIAtom* tagName = content->Tag();
-    if (tagName == nsGkAtoms::sup)
+  if (content) {
+    if (content->IsHTMLElement(nsGkAtoms::sup))
       return eTextPosSuper;
-    if (tagName == nsGkAtoms::sub)
+    if (content->IsHTMLElement(nsGkAtoms::sub))
       return eTextPosSub;
   }
 
   return eTextPosNone;
 }
--- a/accessible/base/TextAttrs.h
+++ b/accessible/base/TextAttrs.h
@@ -125,17 +125,17 @@ protected:
   template<class T>
   class TTextAttr : public TextAttr
   {
   public:
     explicit TTextAttr(bool aGetRootValue) : mGetRootValue(aGetRootValue) {}
 
     // TextAttr
     virtual void Expose(nsIPersistentProperties* aAttributes,
-                        bool aIncludeDefAttrValue)
+                        bool aIncludeDefAttrValue) override
     {
       if (mGetRootValue) {
         if (mIsRootDefined)
           ExposeValue(aAttributes, mRootNativeValue);
         return;
       }
 
       if (mIsDefined) {
@@ -143,17 +143,17 @@ protected:
           ExposeValue(aAttributes, mNativeValue);
         return;
       }
 
       if (aIncludeDefAttrValue && mIsRootDefined)
         ExposeValue(aAttributes, mRootNativeValue);
     }
 
-    virtual bool Equal(Accessible* aAccessible)
+    virtual bool Equal(Accessible* aAccessible) override
     {
       T nativeValue;
       bool isDefined = GetValueFor(aAccessible, &nativeValue);
 
       if (!mIsDefined && !isDefined)
         return true;
 
       if (mIsDefined && isDefined)
@@ -198,19 +198,19 @@ protected:
   public:
     LangTextAttr(HyperTextAccessible* aRoot, nsIContent* aRootElm,
                  nsIContent* aElm);
     virtual ~LangTextAttr();
 
   protected:
 
     // TextAttr
-    virtual bool GetValueFor(Accessible* aAccessible, nsString* aValue);
+    virtual bool GetValueFor(Accessible* aAccessible, nsString* aValue) override;
     virtual void ExposeValue(nsIPersistentProperties* aAttributes,
-                             const nsString& aValue);
+                             const nsString& aValue) override;
 
   private:
     nsCOMPtr<nsIContent> mRootContent;
   };
 
 
   /**
    * Class is used for the 'invalid' text attribute. Note, it calculated
@@ -229,19 +229,19 @@ protected:
     enum {
       eFalse,
       eGrammar,
       eSpelling,
       eTrue
     };
 
     // TextAttr
-    virtual bool GetValueFor(Accessible* aAccessible, uint32_t* aValue);
+    virtual bool GetValueFor(Accessible* aAccessible, uint32_t* aValue) override;
     virtual void ExposeValue(nsIPersistentProperties* aAttributes,
-                             const uint32_t& aValue);
+                             const uint32_t& aValue) override;
 
   private:
     bool GetValue(nsIContent* aElm, uint32_t* aValue);
     nsIContent* mRootElm;
   };
 
 
   /**
@@ -251,19 +251,20 @@ protected:
   {
   public:
     BGColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame);
     virtual ~BGColorTextAttr() { }
 
   protected:
 
     // TextAttr
-    virtual bool GetValueFor(Accessible* aAccessible, nscolor* aValue);
+    virtual bool GetValueFor(Accessible* aAccessible, nscolor* aValue)
+      override;
     virtual void ExposeValue(nsIPersistentProperties* aAttributes,
-                             const nscolor& aValue);
+                             const nscolor& aValue) override;
 
   private:
     bool GetColor(nsIFrame* aFrame, nscolor* aColor);
     nsIFrame* mRootFrame;
   };
 
 
   /**
@@ -273,37 +274,39 @@ protected:
   {
   public:
     ColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame);
     virtual ~ColorTextAttr() { }
 
   protected:
 
     // TTextAttr
-    virtual bool GetValueFor(Accessible* aAccessible, nscolor* aValue);
+    virtual bool GetValueFor(Accessible* aAccessible, nscolor* aValue)
+      override;
     virtual void ExposeValue(nsIPersistentProperties* aAttributes,
-                             const nscolor& aValue);
+                             const nscolor& aValue) override;
   };
 
 
   /**
    * Class is used for the work with "font-family" text attribute.
    */
   class FontFamilyTextAttr : public TTextAttr<nsString>
   {
   public:
     FontFamilyTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame);
     virtual ~FontFamilyTextAttr() { }
 
   protected:
 
     // TTextAttr
-    virtual bool GetValueFor(Accessible* aAccessible, nsString* aValue);
+    virtual bool GetValueFor(Accessible* aAccessible, nsString* aValue)
+      override;
     virtual void ExposeValue(nsIPersistentProperties* aAttributes,
-                             const nsString& aValue);
+                             const nsString& aValue) override;
 
   private:
 
     bool GetFontFamily(nsIFrame* aFrame, nsString& aFamily);
   };
 
 
   /**
@@ -313,19 +316,20 @@ protected:
   {
   public:
     FontSizeTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame);
     virtual ~FontSizeTextAttr() { }
 
   protected:
 
     // TTextAttr
-    virtual bool GetValueFor(Accessible* aAccessible, nscoord* aValue);
+    virtual bool GetValueFor(Accessible* aAccessible, nscoord* aValue)
+      override;
     virtual void ExposeValue(nsIPersistentProperties* aAttributes,
-                             const nscoord& aValue);
+                             const nscoord& aValue) override;
 
   private:
     nsDeviceContext* mDC;
   };
 
 
   /**
    * Class is used for the work with "font-style" text attribute.
@@ -334,37 +338,39 @@ protected:
   {
   public:
     FontStyleTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame);
     virtual ~FontStyleTextAttr() { }
 
   protected:
 
     // TTextAttr
-    virtual bool GetValueFor(Accessible* aContent, nscoord* aValue);
+    virtual bool GetValueFor(Accessible* aContent, nscoord* aValue)
+      override;
     virtual void ExposeValue(nsIPersistentProperties* aAttributes,
-                             const nscoord& aValue);
+                             const nscoord& aValue) override;
   };
 
 
   /**
    * Class is used for the work with "font-weight" text attribute.
    */
   class FontWeightTextAttr : public TTextAttr<int32_t>
   {
   public:
     FontWeightTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame);
     virtual ~FontWeightTextAttr() { }
 
   protected:
 
     // TTextAttr
-    virtual bool GetValueFor(Accessible* aAccessible, int32_t* aValue);
+    virtual bool GetValueFor(Accessible* aAccessible, int32_t* aValue)
+      override;
     virtual void ExposeValue(nsIPersistentProperties* aAttributes,
-                             const int32_t& aValue);
+                             const int32_t& aValue) override;
 
   private:
     int32_t GetFontWeight(nsIFrame* aFrame);
   };
 
   /**
    * Class is used for the work with 'auto-generated' text attribute.
    */
@@ -372,19 +378,20 @@ protected:
   {
   public:
     AutoGeneratedTextAttr(HyperTextAccessible* aHyperTextAcc,
                           Accessible* aAccessible);
     virtual ~AutoGeneratedTextAttr() { }
 
   protected:
     // TextAttr
-    virtual bool GetValueFor(Accessible* aAccessible, bool* aValue);
+    virtual bool GetValueFor(Accessible* aAccessible, bool* aValue)
+      override;
     virtual void ExposeValue(nsIPersistentProperties* aAttributes,
-                             const bool& aValue);
+                             const bool& aValue) override;
   };
 
 
   /**
    * TextDecorTextAttr class is used for the work with
    * "text-line-through-style", "text-line-through-color",
    * "text-underline-style" and "text-underline-color" text attributes.
    */
@@ -423,19 +430,20 @@ protected:
   {
   public:
     TextDecorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame);
     virtual ~TextDecorTextAttr() { }
 
   protected:
 
     // TextAttr
-    virtual bool GetValueFor(Accessible* aAccessible, TextDecorValue* aValue);
+    virtual bool GetValueFor(Accessible* aAccessible, TextDecorValue* aValue)
+      override;
     virtual void ExposeValue(nsIPersistentProperties* aAttributes,
-                             const TextDecorValue& aValue);
+                             const TextDecorValue& aValue) override;
   };
 
   /**
    * Class is used for the work with "text-position" text attribute.
    */
 
   enum TextPosValue {
     eTextPosNone = 0,
@@ -448,19 +456,20 @@ protected:
   {
   public:
     TextPosTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame);
     virtual ~TextPosTextAttr() { }
 
   protected:
 
     // TextAttr
-    virtual bool GetValueFor(Accessible* aAccessible, TextPosValue* aValue);
+    virtual bool GetValueFor(Accessible* aAccessible, TextPosValue* aValue)
+      override;
     virtual void ExposeValue(nsIPersistentProperties* aAttributes,
-                             const TextPosValue& aValue);
+                             const TextPosValue& aValue) override;
 
   private:
     TextPosValue GetTextPosValue(nsIFrame* aFrame) const;
   };
 
 }; // TextAttrMgr
 
 } // namespace a11y
new file mode 100644
--- /dev/null
+++ b/accessible/base/TextRange-inl.h
@@ -0,0 +1,29 @@
+/* -*- 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/. */
+
+#ifndef mozilla_a11y_TextRange_inl_h__
+#define mozilla_a11y_TextRange_inl_h__
+
+#include "TextRange.h"
+#include "HyperTextAccessible.h"
+
+namespace mozilla {
+namespace a11y {
+
+inline Accessible*
+TextRange::Container() const
+{
+  uint32_t pos1 = 0, pos2 = 0;
+  AutoTArray<Accessible*, 30> parents1, parents2;
+  return CommonParent(mStartContainer, mEndContainer,
+                      &parents1, &pos1, &parents2, &pos2);
+}
+
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
--- a/accessible/base/TextRange.cpp
+++ b/accessible/base/TextRange.cpp
@@ -1,18 +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 "TextRange.h"
+#include "TextRange-inl.h"
 
 #include "Accessible-inl.h"
-#include "HyperTextAccessible.h"
 #include "nsAccUtils.h"
 
 namespace mozilla {
 namespace a11y {
 
 ////////////////////////////////////////////////////////////////////////////////
 // TextPoint
 
@@ -20,17 +19,17 @@ bool
 TextPoint::operator <(const TextPoint& aPoint) const
 {
   if (mContainer == aPoint.mContainer)
     return mOffset < aPoint.mOffset;
 
   // Build the chain of parents
   Accessible* p1 = mContainer;
   Accessible* p2 = aPoint.mContainer;
-  nsAutoTArray<Accessible*, 30> parents1, parents2;
+  AutoTArray<Accessible*, 30> parents1, parents2;
   do {
     parents1.AppendElement(p1);
     p1 = p1->Parent();
   } while (p1);
   do {
     parents2.AppendElement(p2);
     p2 = p2->Parent();
   } while (p2);
@@ -54,90 +53,37 @@ TextPoint::operator <(const TextPoint& a
 TextRange::TextRange(HyperTextAccessible* aRoot,
                      HyperTextAccessible* aStartContainer, int32_t aStartOffset,
                      HyperTextAccessible* aEndContainer, int32_t aEndOffset) :
   mRoot(aRoot), mStartContainer(aStartContainer), mEndContainer(aEndContainer),
   mStartOffset(aStartOffset), mEndOffset(aEndOffset)
 {
 }
 
-Accessible*
-TextRange::Container() const
-{
-  if (mStartContainer == mEndContainer)
-    return mStartContainer;
-
-  // Build the chain of parents
-  Accessible* p1 = mStartContainer;
-  Accessible* p2 = mEndContainer;
-  nsAutoTArray<Accessible*, 30> parents1, parents2;
-  do {
-    parents1.AppendElement(p1);
-    p1 = p1->Parent();
-  } while (p1);
-  do {
-    parents2.AppendElement(p2);
-    p2 = p2->Parent();
-  } while (p2);
-
-  // Find where the parent chain differs
-  uint32_t pos1 = parents1.Length();
-  uint32_t pos2 = parents2.Length();
-  Accessible* parent = nullptr;
-  uint32_t len = 0;
-  for (len = std::min(pos1, pos2); len > 0; --len) {
-    Accessible* child1 = parents1.ElementAt(--pos1);
-    Accessible* child2 = parents2.ElementAt(--pos2);
-    if (child1 != child2)
-      break;
-
-    parent = child1;
-  }
-
-  return parent;
-}
-
 void
 TextRange::EmbeddedChildren(nsTArray<Accessible*>* aChildren) const
 {
   if (mStartContainer == mEndContainer) {
     int32_t startIdx = mStartContainer->GetChildIndexAtOffset(mStartOffset);
     int32_t endIdx = mStartContainer->GetChildIndexAtOffset(mEndOffset);
     for (int32_t idx = startIdx; idx <= endIdx; idx++) {
       Accessible* child = mStartContainer->GetChildAt(idx);
       if (nsAccUtils::IsEmbeddedObject(child))
         aChildren->AppendElement(child);
     }
     return;
   }
 
   Accessible* p1 = mStartContainer->GetChildAtOffset(mStartOffset);
   Accessible* p2 = mEndContainer->GetChildAtOffset(mEndOffset);
-  nsAutoTArray<Accessible*, 30> parents1, parents2;
-  do {
-    parents1.AppendElement(p1);
-    p1 = p1->Parent();
-  } while (p1);
-  do {
-    parents2.AppendElement(p2);
-    p2 = p2->Parent();
-  } while (p2);
 
-  // Find deepest common container.
-  uint32_t pos1 = parents1.Length();
-  uint32_t pos2 = parents2.Length();
-  Accessible* container = nullptr;
-  for (uint32_t len = std::min(pos1, pos2); len > 0; --len) {
-    Accessible* child1 = parents1.ElementAt(--pos1);
-    Accessible* child2 = parents2.ElementAt(--pos2);
-    if (child1 != child2)
-      break;
-
-    container = child1;
-  }
+  uint32_t pos1 = 0, pos2 = 0;
+  AutoTArray<Accessible*, 30> parents1, parents2;
+  Accessible* container =
+    CommonParent(p1, p2, &parents1, &pos1, &parents2, &pos2);
 
   // Traverse the tree up to the container and collect embedded objects.
   for (uint32_t idx = 0; idx < pos1 - 1; idx++) {
     Accessible* parent = parents1[idx + 1];
     Accessible* child = parents1[idx];
     uint32_t childCount = parent->ChildCount();
     for (uint32_t childIdx = child->IndexInParent(); childIdx < childCount; childIdx++) {
       Accessible* next = parent->GetChildAt(childIdx);
@@ -191,16 +137,105 @@ TextRange::Bounds(nsTArray<nsIntRect> aR
 }
 
 void
 TextRange::Normalize(ETextUnit aUnit)
 {
 
 }
 
+bool
+TextRange::Crop(Accessible* aContainer)
+{
+  uint32_t boundaryPos = 0, containerPos = 0;
+  AutoTArray<Accessible*, 30> boundaryParents, containerParents;
+
+  // Crop the start boundary.
+  Accessible* container = nullptr;
+  Accessible* boundary = mStartContainer->GetChildAtOffset(mStartOffset);
+  if (boundary != aContainer) {
+    CommonParent(boundary, aContainer, &boundaryParents, &boundaryPos,
+                 &containerParents, &containerPos);
+
+    if (boundaryPos == 0) {
+      if (containerPos != 0) {
+        // The container is contained by the start boundary, reduce the range to
+        // the point starting at the container.
+        aContainer->ToTextPoint(mStartContainer.StartAssignment(), &mStartOffset);
+        static_cast<Accessible*>(mStartContainer)->AddRef();
+      }
+      else {
+        // The start boundary and the container are siblings.
+        container = aContainer;
+      }
+    }
+    else if (containerPos != 0) {
+      // The container does not contain the start boundary.
+      boundary = boundaryParents[boundaryPos];
+      container = containerParents[containerPos];
+    }
+
+    if (container) {
+      // If the range start is after the container, then make the range invalid.
+      if (boundary->IndexInParent() > container->IndexInParent()) {
+        return !!(mRoot = nullptr);
+      }
+
+      // If the range starts before the container, then reduce the range to
+      // the point starting at the container.
+      if (boundary->IndexInParent() < container->IndexInParent()) {
+        container->ToTextPoint(mStartContainer.StartAssignment(), &mStartOffset);
+        mStartContainer.get()->AddRef();
+      }
+    }
+
+    boundaryParents.SetLengthAndRetainStorage(0);
+    containerParents.SetLengthAndRetainStorage(0);
+  }
+
+  boundary = mEndContainer->GetChildAtOffset(mEndOffset);
+  if (boundary == aContainer) {
+    return true;
+  }
+
+  // Crop the end boundary.
+  container = nullptr;
+  CommonParent(boundary, aContainer, &boundaryParents, &boundaryPos,
+               &containerParents, &containerPos);
+
+  if (boundaryPos == 0) {
+    if (containerPos != 0) {
+      aContainer->ToTextPoint(mEndContainer.StartAssignment(), &mEndOffset, false);
+      static_cast<Accessible*>(mEndContainer)->AddRef();
+    }
+    else {
+      container = aContainer;
+    }
+  }
+  else if (containerPos != 0) {
+    boundary = boundaryParents[boundaryPos];
+    container = containerParents[containerPos];
+  }
+
+  if (!container) {
+    return true;
+  }
+
+  if (boundary->IndexInParent() < container->IndexInParent()) {
+    return !!(mRoot = nullptr);
+  }
+
+  if (boundary->IndexInParent() > container->IndexInParent()) {
+    container->ToTextPoint(mEndContainer.StartAssignment(), &mEndOffset, false);
+    static_cast<Accessible*>(mEndContainer)->AddRef();
+  }
+
+  return true;
+}
+
 void
 TextRange::FindText(const nsAString& aText, EDirection aDirection,
                     nsCaseTreatment aCaseSensitive, TextRange* aFoundRange) const
 {
 
 }
 
 void
@@ -291,10 +326,51 @@ TextRange::TextInternal(nsAString& aText
 void
 TextRange::MoveInternal(ETextUnit aUnit, int32_t aCount,
                         HyperTextAccessible& aContainer, int32_t aOffset,
                         HyperTextAccessible* aStopContainer, int32_t aStopOffset)
 {
 
 }
 
+Accessible*
+TextRange::CommonParent(Accessible* aAcc1, Accessible* aAcc2,
+                        nsTArray<Accessible*>* aParents1, uint32_t* aPos1,
+                        nsTArray<Accessible*>* aParents2, uint32_t* aPos2) const
+{
+  if (aAcc1 == aAcc2) {
+    return aAcc1;
+  }
+
+  MOZ_ASSERT(aParents1->Length() == 0 || aParents2->Length() == 0,
+             "Wrong arguments");
+
+  // Build the chain of parents.
+  Accessible* p1 = aAcc1;
+  Accessible* p2 = aAcc2;
+  do {
+    aParents1->AppendElement(p1);
+    p1 = p1->Parent();
+  } while (p1);
+  do {
+    aParents2->AppendElement(p2);
+    p2 = p2->Parent();