about:startup - merge with trunk
authorDaniel Brooks <db48x@db48x.net>
Sun, 24 Oct 2010 16:24:58 -0500
changeset 58862 8ad67554aadd0e22451e6c740fd3061472d86655
parent 58861 ce8c23e52487d2c639a0d1f42f12c3399f324f94 (current diff)
parent 56418 df51ba69a839610b12a0e7b8d8f1504eba54287e (diff)
child 58863 bfc0fc174aa16ad0dac0ad68d2995ff8d0401a68
push id17440
push userdb48x@yahoo.com
push dateWed, 08 Dec 2010 04:15:54 +0000
treeherdermozilla-central@a89f24bf1798 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone2.0b8pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
about:startup - merge with trunk
accessible/tests/mochitest/tree/test_list_invalidate.html
browser/base/content/browser.js
browser/base/content/test/tabview/browser_tabview_bug587040.js
browser/base/jar.mn
browser/components/sessionstore/src/nsSessionStartup.js
browser/themes/pinstripe/browser/Popup-blocked.png
browser/themes/pinstripe/browser/Secure-statusbar-broken.png
browser/themes/pinstripe/browser/Secure-statusbar.png
browser/themes/winstripe/browser/Secure-aero.png
browser/themes/winstripe/browser/Secure.png
browser/themes/winstripe/browser/Security-broken-aero.png
browser/themes/winstripe/browser/Security-broken.png
content/base/crashtests/595606.html
content/base/test/file_bug543870_doc.html
content/base/test/file_bug543870_img.jpg
content/base/test/file_bug543870_inner.html
content/base/test/file_bug543870_text.txt
content/base/test/test_bug543870.html
content/html/content/test/583288_redirect_server.sjs
content/html/content/test/583288_submit_server.sjs
content/html/content/test/test_bug583288-1.html
content/html/content/test/test_bug583288-2.html
content/html/content/test/test_bug583288-3.html
content/html/document/public/nsIWyciwygChannel.idl
content/html/document/src/nsWyciwygChannel.cpp
content/html/document/src/nsWyciwygChannel.h
content/html/document/src/nsWyciwygProtocolHandler.cpp
content/html/document/src/nsWyciwygProtocolHandler.h
docshell/base/nsAboutRedirector.cpp
docshell/build/nsDocShellModule.cpp
dom/indexedDB/Savepoint.h
embedding/android/utils/Makefile.in
embedding/android/utils/nsGeckoUtils.cpp
js/narcissus/jsdefs.js
js/narcissus/jsexec.js
js/narcissus/jslex.js
js/narcissus/jsparse.js
js/narcissus/jsssa.js
js/src/methodjit/CompilerBase.h
js/src/shell/njs
js/src/tests/js1_5/extensions/regress-340199.js
js/src/tests/js1_5/extensions/regress-382509.js
js/src/tests/js1_6/Regress/regress-382509.js
js/src/tests/js1_8_1/trace/trace-test.js
js/src/trace-test/trace-test.py
js/src/xpconnect/src/XPCChromeObjectWrapper.cpp
js/src/xpconnect/src/XPCCrossOriginWrapper.cpp
js/src/xpconnect/src/XPCNativeWrapper.cpp
js/src/xpconnect/src/XPCNativeWrapper.h
js/src/xpconnect/src/XPCSafeJSObjectWrapper.cpp
js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp
js/src/xpconnect/tests/mochitest/test_bug448587.html
js/src/xpconnect/tests/mochitest/test_bug484459.html
js/src/xpconnect/tests/mochitest/test_bug517163.html
js/src/xpconnect/tests/mochitest/test_cows.html
js/src/xpconnect/tests/mochitest/test_wrappers.html
js/src/xpconnect/tests/unit/test_iterate.js
layout/base/crashtests/143862-1-inner.html
layout/base/crashtests/143862-1.html
layout/base/crashtests/311661-1-inner.xul
layout/base/crashtests/311661-1.html
layout/base/crashtests/311661-2-inner.xul
layout/base/crashtests/311661-2.html
layout/reftests/bugs/513318-3-ref.xul
layout/reftests/bugs/513318-3.xul
layout/reftests/css-optional/css-optional-button-ref.html
layout/reftests/forms/placeholder/placeholder-readonly-focus-ref.html
layout/reftests/svg/image-fill-01.svg
layout/reftests/svg/image-scaling-01.svg
layout/reftests/svg/image-scaling-02.svg
layout/reftests/svg/image/background-image-rect-1png.html
layout/reftests/svg/image/background-image-rect-1svg.html
layout/reftests/svg/image/background-image-rect-2.html
layout/reftests/svg/image/background-simple-1.html
layout/reftests/svg/image/background-simple-2.html
layout/reftests/svg/image/background-viewBox-1.html
layout/reftests/svg/image/border-image-simple-1.html
layout/reftests/svg/image/border-image-simple-2.html
layout/reftests/svg/image/content-outside-viewBox-1-helper.svg
layout/reftests/svg/image/img-content-outside-viewBox-1-ref.html
layout/reftests/svg/image/img-content-outside-viewBox-1.html
layout/reftests/svg/image/img-dyn-1-ref.html
layout/reftests/svg/image/img-dyn-1.html
layout/reftests/svg/image/img-height-meet-1-ref.html
layout/reftests/svg/image/img-height-meet-1.html
layout/reftests/svg/image/img-height-meet-2-ref.html
layout/reftests/svg/image/img-height-meet-2.html
layout/reftests/svg/image/img-height-slice-1-ref.html
layout/reftests/svg/image/img-height-slice-1.html
layout/reftests/svg/image/img-height-slice-2-ref.html
layout/reftests/svg/image/img-height-slice-2.html
layout/reftests/svg/image/img-simple-1.html
layout/reftests/svg/image/img-simple-2.html
layout/reftests/svg/image/img-simple-3.html
layout/reftests/svg/image/img-simple-4.html
layout/reftests/svg/image/img-simple-5.html
layout/reftests/svg/image/img-simple-6.html
layout/reftests/svg/image/img-simple-7.html
layout/reftests/svg/image/img-width-meet-1-ref.html
layout/reftests/svg/image/img-width-meet-1.html
layout/reftests/svg/image/img-width-meet-2-ref.html
layout/reftests/svg/image/img-width-meet-2.html
layout/reftests/svg/image/img-width-slice-1-ref.html
layout/reftests/svg/image/img-width-slice-1.html
layout/reftests/svg/image/img-width-slice-2-ref.html
layout/reftests/svg/image/img-width-slice-2.html
layout/reftests/svg/image/img-widthAndHeight-meet-1-ref.html
layout/reftests/svg/image/img-widthAndHeight-meet-1.html
layout/reftests/svg/image/img-widthAndHeight-meet-2-ref.html
layout/reftests/svg/image/img-widthAndHeight-meet-2.html
layout/reftests/svg/image/img-widthAndHeight-slice-1-ref.html
layout/reftests/svg/image/img-widthAndHeight-slice-1.html
layout/reftests/svg/image/img-widthAndHeight-slice-2-ref.html
layout/reftests/svg/image/img-widthAndHeight-slice-2.html
layout/reftests/svg/image/lime100x100-noSVGDimensions.svg
layout/reftests/svg/image/lime100x100-ref.html
layout/reftests/svg/image/lime100x100.png
layout/reftests/svg/image/lime100x100.svg
layout/reftests/svg/image/lime200x100.svg
layout/reftests/svg/image/lime200x200.svg
layout/reftests/svg/image/limeInRed100x100-viewBox.svg
layout/reftests/svg/image/limeInRed100x100.png
layout/reftests/svg/image/limeInRed100x100.svg
layout/reftests/svg/image/list-simple-1-ref.html
layout/reftests/svg/image/list-simple-1.html
layout/reftests/svg/image/squaredCircle-viewBox-noSize.svg
layout/reftests/svg/image/svg-image-util.css
layout/reftests/svg/image/svg-image-util.js
layout/reftests/svg/image/zoom/img-zoomIn-1.html
layout/reftests/svg/image/zoom/img-zoomOut-1.html
layout/reftests/svg/image/zoom/reftest.list
layout/reftests/svg/image/zoom/squaredCircle-150x150-ref.html
layout/reftests/svg/image/zoom/squaredCircle-50x50-ref.html
layout/reftests/svg/image/zoom/squaredCircle.svg
nsprpub/pr/src/memory/prgcleak.c
parser/htmlparser/tests/mochitest/html5lib_license.txt
parser/htmlparser/tests/mochitest/html5lib_tree_dat1.txt
parser/htmlparser/tests/mochitest/html5lib_tree_dat2.txt
parser/htmlparser/tests/mochitest/html5lib_tree_dat3.txt
services/crypto/WeaveCrypto.js
services/crypto/WeaveCrypto.manifest
services/sync/tests/unit/head_appinfo.js
services/sync/tests/unit/test_crypto_crypt.js
services/sync/tests/unit/test_crypto_keypair.js
services/sync/tests/unit/test_crypto_random.js
services/sync/tests/unit/test_crypto_rewrap.js
services/sync/tests/unit/test_crypto_verify.js
testing/mochitest/runtests.py.in
testing/mochitest/static/bug100533_iframe.html
testing/mochitest/static/bug100533_load.html
testing/mochitest/static/bug277724_iframe1.html
testing/mochitest/static/bug277724_iframe2.xhtml
testing/mochitest/static/bug340800_iframe.txt
testing/mochitest/static/bug344830_testembed.svg
testing/mochitest/static/nnc_lockup.gif
testing/mochitest/tests/MochiKit-1.4.2/tests/SimpleTest/SimpleTest.js
testing/mozmill/jsbridge-2.4.0/MANIFEST.in
testing/mozmill/jsbridge-2.4.0/PKG-INFO
testing/mozmill/jsbridge-2.4.0/jsbridge/__init__.py
testing/mozmill/jsbridge-2.4.0/jsbridge/extension/chrome.manifest
testing/mozmill/jsbridge-2.4.0/jsbridge/extension/chrome/content/overlay.js
testing/mozmill/jsbridge-2.4.0/jsbridge/extension/chrome/content/overlay.xul
testing/mozmill/jsbridge-2.4.0/jsbridge/extension/components/cmdarg.js
testing/mozmill/jsbridge-2.4.0/jsbridge/extension/install.rdf
testing/mozmill/jsbridge-2.4.0/jsbridge/extension/resource/modules/events.js
testing/mozmill/jsbridge-2.4.0/jsbridge/extension/resource/modules/init.js
testing/mozmill/jsbridge-2.4.0/jsbridge/extension/resource/modules/json2.js
testing/mozmill/jsbridge-2.4.0/jsbridge/extension/resource/modules/server.js
testing/mozmill/jsbridge-2.4.0/jsbridge/jsobjects.py
testing/mozmill/jsbridge-2.4.0/jsbridge/network.py
testing/mozmill/jsbridge-2.4.0/setup.cfg
testing/mozmill/jsbridge-2.4.0/setup.py
testing/mozmill/mozmill-1.5.0/MANIFEST.in
testing/mozmill/mozmill-1.5.0/PKG-INFO
testing/mozmill/mozmill-1.5.0/docs/Makefile
testing/mozmill/mozmill-1.5.0/docs/_build/doctrees/environment.pickle
testing/mozmill/mozmill-1.5.0/docs/_build/doctrees/index.doctree
testing/mozmill/mozmill-1.5.0/docs/_build/html/_sources/index.txt
testing/mozmill/mozmill-1.5.0/docs/_build/html/_static/contents.png
testing/mozmill/mozmill-1.5.0/docs/_build/html/_static/default.css
testing/mozmill/mozmill-1.5.0/docs/_build/html/_static/doctools.js
testing/mozmill/mozmill-1.5.0/docs/_build/html/_static/file.png
testing/mozmill/mozmill-1.5.0/docs/_build/html/_static/jquery.js
testing/mozmill/mozmill-1.5.0/docs/_build/html/_static/minus.png
testing/mozmill/mozmill-1.5.0/docs/_build/html/_static/navigation.png
testing/mozmill/mozmill-1.5.0/docs/_build/html/_static/plus.png
testing/mozmill/mozmill-1.5.0/docs/_build/html/_static/pygments.css
testing/mozmill/mozmill-1.5.0/docs/_build/html/_static/rightsidebar.css
testing/mozmill/mozmill-1.5.0/docs/_build/html/_static/searchtools.js
testing/mozmill/mozmill-1.5.0/docs/_build/html/_static/sphinxdoc.css
testing/mozmill/mozmill-1.5.0/docs/_build/html/_static/stickysidebar.css
testing/mozmill/mozmill-1.5.0/docs/_build/html/_static/traditional.css
testing/mozmill/mozmill-1.5.0/docs/_build/html/genindex.html
testing/mozmill/mozmill-1.5.0/docs/_build/html/index.html
testing/mozmill/mozmill-1.5.0/docs/_build/html/modindex.html
testing/mozmill/mozmill-1.5.0/docs/_build/html/objects.inv
testing/mozmill/mozmill-1.5.0/docs/_build/html/search.html
testing/mozmill/mozmill-1.5.0/docs/_build/html/searchindex.js
testing/mozmill/mozmill-1.5.0/docs/conf.py
testing/mozmill/mozmill-1.5.0/docs/index.rst
testing/mozmill/mozmill-1.5.0/mozmill/__init__.py
testing/mozmill/mozmill-1.5.0/mozmill/extension/build.xml
testing/mozmill/mozmill-1.5.0/mozmill/extension/chrome-jar.manifest
testing/mozmill/mozmill-1.5.0/mozmill/extension/chrome.manifest
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/chrome.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/css/fg.menu.css
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/css/mozmill.css
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/css/smoothness/images/ui-icons_222222_256x240.png
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/css/smoothness/images/ui-icons_2e83ff_256x240.png
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/css/smoothness/images/ui-icons_454545_256x240.png
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/css/smoothness/images/ui-icons_888888_256x240.png
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/css/smoothness/images/ui-icons_cd0a0a_256x240.png
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/css/smoothness/jquery-ui-1.7.1.custom.css
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/dx.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/dxwindow.xul
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/editor/bespin/BespinEmbedded.css
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/editor/bespin/BespinEmbedded.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/editor/bespin/BespinMain.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/editor/bespin/BespinWorker.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/editor/bespin/resources/screen_theme/theme.less
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/editor/editor.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/img/wmIcon.png
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/inspector.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/jquery/fg.menu.css
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/jquery/fg.menu.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/jquery/jquery-1.3.2.min.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/jquery/jquery-ui-1.7.1.custom.min.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/jquery/jquery.ui.core.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/jquery/jquery.ui.menu.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/menus.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/mozmill.html
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/mozmill.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/mozmill.xul
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/output.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/overlay.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/overlay.xul
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/overlay_tb.xul
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/prefs.xul
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/rec.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/shell.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/shortcuts.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/testwindow.xul
testing/mozmill/mozmill-1.5.0/mozmill/extension/content/ui.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/defaults/preferences/debug.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/install.rdf
testing/mozmill/mozmill-1.5.0/mozmill/extension/locale/en-US/mozmill.dtd
testing/mozmill/mozmill-1.5.0/mozmill/extension/locale/en-US/overlay.dtd
testing/mozmill/mozmill-1.5.0/mozmill/extension/mozmill-1.4.2b5.xpi
testing/mozmill/mozmill-1.5.0/mozmill/extension/readme.txt
testing/mozmill/mozmill-1.5.0/mozmill/extension/resource/modules/controller.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/resource/modules/elementslib.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/resource/modules/events.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/resource/modules/frame.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/resource/modules/init.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/resource/modules/inspection.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/resource/modules/jum.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/resource/modules/mozmill.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/resource/modules/utils.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/resource/stdlib/EventUtils.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/resource/stdlib/arrays.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/resource/stdlib/dom.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/resource/stdlib/httpd.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/resource/stdlib/json2.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/resource/stdlib/objects.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/resource/stdlib/os.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/resource/stdlib/strings.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/resource/stdlib/withs.js
testing/mozmill/mozmill-1.5.0/mozmill/extension/skin/chrome.css
testing/mozmill/mozmill-1.5.0/mozmill/extension/skin/overlay.css
testing/mozmill/mozmill-1.5.0/mozmill/extension/zipexclude.lst
testing/mozmill/mozmill-1.5.0/setup.cfg
testing/mozmill/mozmill-1.5.0/setup.py
testing/mozmill/mozmill-1.5.0/test/test_python_callbacks_callbacks.py
testing/mozmill/mozrunner-2.5.1/PKG-INFO
testing/mozmill/mozrunner-2.5.1/mozrunner/__init__.py
testing/mozmill/mozrunner-2.5.1/mozrunner/killableprocess.py
testing/mozmill/mozrunner-2.5.1/mozrunner/qijo.py
testing/mozmill/mozrunner-2.5.1/mozrunner/winprocess.py
testing/mozmill/mozrunner-2.5.1/mozrunner/wpk.py
testing/mozmill/mozrunner-2.5.1/setup.cfg
testing/mozmill/mozrunner-2.5.1/setup.py
testing/mozmill/tests/firefox/testPrivateBrowsing/testTabRestoration.js
toolkit/components/console/hudservice/tests/browser/browser_HUDServiceTestsAll.js
toolkit/mozapps/extensions/AddonManager.jsm
toolkit/mozapps/update/test/unit/data/empty.mar
toolkit/themes/pinstripe/global/jar.mn
toolkit/themes/winstripe/global/jar.mn
toolkit/xre/nsAppRunner.cpp
tools/update-packaging/unwrap_full_update.sh
xpfe/appshell/src/nsAbout.cpp
xpfe/appshell/src/nsAbout.h
--- a/Makefile.in
+++ b/Makefile.in
@@ -63,16 +63,20 @@ tier_base_dirs = \
 	build \
 	probes \
 	$(NULL)
 
 ifndef LIBXUL_SDK
 tier_base_dirs += \
 	memory \
 	$(NULL)
+ifeq ($(OS_TARGET),Android)
+tier_base_dirs += other-licenses/android
+endif
+
 endif
 
 ifdef COMPILE_ENVIRONMENT
 include $(topsrcdir)/$(MOZ_BUILD_APP)/build.mk
 endif
 
 
 include $(topsrcdir)/config/config.mk
@@ -115,19 +119,16 @@ config.status: $(topsrcdir)/configure
 export::
 	$(RM) -rf $(DIST)/sdk
 	$(MAKE) -C config export
 	$(MAKE) tier_nspr
 
 ifdef ENABLE_TESTS
 # Additional makefile targets to call automated test suites
 include $(topsrcdir)/testing/testsuite-targets.mk
-else
-# OS X Universal builds will want to call this, so stub it out
-package-tests:
 endif
 
 include $(topsrcdir)/config/rules.mk
 
 distclean::
 	cat unallmakefiles | $(XARGS) rm -f
 	rm -f unallmakefiles $(DIST_GARBAGE)
 
@@ -166,17 +167,17 @@ SYM_STORE_SOURCE_DIRS := $(topsrcdir)
 
 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_ARCH)-$(BUILDID)$(EXTRA_BUILDID)-symbols.txt
+  $(MOZ_APP_NAME)-$(MOZ_APP_VERSION)-$(OS_TARGET)-$(BUILDID)$(EXTRA_BUILDID)-symbols.txt
 
 buildsymbols:
 ifdef MOZ_CRASHREPORTER
 	echo building symbol store
 	$(RM) -rf $(DIST)/crashreporter-symbols
 	$(RM) -f "$(DIST)/$(SYMBOL_ARCHIVE_BASENAME).zip"
 	$(NSINSTALL) -D $(DIST)/crashreporter-symbols
 	$(PYTHON) $(topsrcdir)/toolkit/crashreporter/tools/symbolstore.py \
@@ -226,8 +227,15 @@ maybe_clobber_profiledbuild: clean
 else
 maybe_clobber_profiledbuild:
 endif
 else
 maybe_clobber_profiledbuild:
 endif
 
 .PHONY: maybe_clobber_profiledbuild
+
+# Look for R_386_PC32 relocations in shared libs, these
+# break x86_64 builds and SELinux users.
+ifeq ($(OS_TARGET)_$(TARGET_XPCOM_ABI),Linux_x86-gcc3)
+scheck::
+	@relcount=`find $(DIST)/bin -name "*.so" | xargs objdump -R | grep R_386_PC32 | wc -l` && if test $$relcount -gt 0; then echo "FAILED: R_386_PC32 relocations detected in a shared library.  Did you use a system header without adding it to config/system-headers?"; exit 1; else echo "PASSED"; fi
+endif
--- a/accessible/build/Makefile.in
+++ b/accessible/build/Makefile.in
@@ -86,13 +86,14 @@ EXTRA_DSO_LDOPTS =           \
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 EXTRA_DSO_LDOPTS += $(MOZ_GTK2_LIBS)
 endif
 
 ifeq ($(OS_ARCH),WINNT)
 OS_LIBS += \
 	oleaut32.lib \
 	version.lib \
+	ole32.lib \
 	$(NULL)
 endif
 
 include $(topsrcdir)/config/rules.mk
 
--- a/accessible/public/nsIAccessibilityService.h
+++ b/accessible/public/nsIAccessibilityService.h
@@ -104,18 +104,17 @@ public:
     CreateHTMLGroupboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
   virtual already_AddRefed<nsAccessible>
     CreateHTMLHRAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
   virtual already_AddRefed<nsAccessible>
     CreateHTMLImageAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
   virtual already_AddRefed<nsAccessible>
     CreateHTMLLabelAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
   virtual already_AddRefed<nsAccessible>
-    CreateHTMLLIAccessible(nsIContent* aContent, nsIPresShell* aPresShell,
-                           const nsAString& aBulletText) = 0;
+    CreateHTMLLIAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
   virtual already_AddRefed<nsAccessible>
     CreateHTMLListboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
   virtual already_AddRefed<nsAccessible>
     CreateHTMLMediaAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
   virtual already_AddRefed<nsAccessible>
     CreateHTMLObjectFrameAccessible(nsObjectFrame* aFrame, nsIContent* aContent,
                                     nsIPresShell* aPresShell) = 0;
   virtual already_AddRefed<nsAccessible>
@@ -136,51 +135,49 @@ public:
   /**
    * Adds/remove ATK root accessible for gtk+ native window to/from children
    * of the application accessible.
    */
   virtual nsAccessible* AddNativeRootAccessible(void* aAtkAccessible) = 0;
   virtual void RemoveNativeRootAccessible(nsAccessible* aRootAccessible) = 0;
 
   /**
-   * Used to describe sort of changes leading to accessible tree invalidation.
+   * Notification used to update the accessible tree when new content is
+   * inserted.
    */
-  enum {
-    NODE_APPEND = 0x01,
-    NODE_REMOVE = 0x02,
-    NODE_SIGNIFICANT_CHANGE = 0x03,
-    FRAME_SHOW = 0x04,
-    FRAME_HIDE = 0x05,
-    FRAME_SIGNIFICANT_CHANGE = 0x06
-  };
+  virtual void ContentRangeInserted(nsIPresShell* aPresShell,
+                                    nsIContent* aContainer,
+                                    nsIContent* aStartChild,
+                                    nsIContent* aEndChild) = 0;
 
   /**
-   * Invalidate the accessible tree when DOM tree or frame tree is changed.
-   *
-   * @param aPresShell   [in] the presShell where changes occurred
-   * @param aContent     [in] the affected DOM content
-   * @param aChangeType  [in] the change type (see constants declared above)
+   * Notification used to update the accessible tree when content is removed.
    */
-  virtual nsresult InvalidateSubtreeFor(nsIPresShell *aPresShell,
-                                        nsIContent *aContent,
-                                        PRUint32 aChangeType) = 0;
+  virtual void ContentRemoved(nsIPresShell* aPresShell, nsIContent* aContainer,
+                              nsIContent* aChild) = 0;
 
   /**
    * Notify accessibility that anchor jump has been accomplished to the given
    * target. Used by layout.
    */
   virtual void NotifyOfAnchorJumpTo(nsIContent *aTarget) = 0;
 
   /**
    * Notify the accessibility service that the given presshell is
    * being destroyed.
    */
   virtual void PresShellDestroyed(nsIPresShell *aPresShell) = 0;
 
   /**
+   * Recreate an accessible for the given content node in the presshell.
+   */
+  virtual void RecreateAccessible(nsIPresShell* aPresShell,
+                                  nsIContent* aContent) = 0;
+
+  /**
    * Fire accessible event of the given type for the given target.
    *
    * @param aEvent   [in] accessible event type
    * @param aTarget  [in] target of accessible event
    */
   virtual void FireAccessibleEvent(PRUint32 aEvent, nsAccessible* aTarget) = 0;
 };
 
--- a/accessible/src/Makefile.in
+++ b/accessible/src/Makefile.in
@@ -70,10 +70,12 @@ DIRS +=   xul
 endif
 
 ifndef DISABLE_XFORMS_HOOKS
 DIRS +=   xforms
 endif
 
 include $(topsrcdir)/config/rules.mk
 
+GARBAGE += $(LIB_PREFIX)accessibility_toolkit_s.$(LIB_SUFFIX)  $(LIB_PREFIX)accessibility_toolkit_s.$(LIB_SUFFIX).fake
+
 libs::
 	$(INSTALL) $(PLATFORM_DIR)/$(LIB_PREFIX)accessibility_toolkit_s.$(LIB_SUFFIX) $(wildcard $(PLATFORM_DIR)/$(LIB_PREFIX)accessibility_toolkit_s.$(LIB_SUFFIX).fake) .
--- a/accessible/src/base/AccEvent.cpp
+++ b/accessible/src/base/AccEvent.cpp
@@ -59,29 +59,25 @@
 ////////////////////////////////////////////////////////////////////////////////
 // AccEvent
 ////////////////////////////////////////////////////////////////////////////////
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccEvent constructors
 
 AccEvent::AccEvent(PRUint32 aEventType, nsAccessible* aAccessible,
-                   PRBool aIsAsync, EIsFromUserInput aIsFromUserInput,
-                   EEventRule aEventRule) :
-  mEventType(aEventType), mEventRule(aEventRule), mIsAsync(aIsAsync),
-  mAccessible(aAccessible)
+                   EIsFromUserInput aIsFromUserInput, EEventRule aEventRule) :
+  mEventType(aEventType), mEventRule(aEventRule), mAccessible(aAccessible)
 {
   CaptureIsFromUserInput(aIsFromUserInput);
 }
 
 AccEvent::AccEvent(PRUint32 aEventType, nsINode* aNode,
-                   PRBool aIsAsync, EIsFromUserInput aIsFromUserInput,
-                   EEventRule aEventRule) :
-  mEventType(aEventType), mEventRule(aEventRule), mIsAsync(aIsAsync),
-  mNode(aNode)
+                   EIsFromUserInput aIsFromUserInput, EEventRule aEventRule) :
+  mEventType(aEventType), mEventRule(aEventRule), mNode(aNode)
 {
   CaptureIsFromUserInput(aIsFromUserInput);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccEvent public methods
 
 nsAccessible *
@@ -213,58 +209,27 @@ AccEvent::CaptureIsFromUserInput(EIsFrom
     return;
   }
 
   mIsFromUserInput = esm->IsHandlingUserInputExternal();
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
-// AccReorderEvent
-////////////////////////////////////////////////////////////////////////////////
-
-AccReorderEvent::
-  AccReorderEvent(nsAccessible* aAccTarget, PRBool aIsAsynch,
-                  PRBool aIsUnconditional, nsINode* aReasonNode) :
-  AccEvent(::nsIAccessibleEvent::EVENT_REORDER, aAccTarget,
-           aIsAsynch, eAutoDetect, AccEvent::eCoalesceFromSameSubtree),
-  mUnconditionalEvent(aIsUnconditional), mReasonNode(aReasonNode)
-{
-}
-
-PRBool
-AccReorderEvent::IsUnconditionalEvent()
-{
-  return mUnconditionalEvent;
-}
-
-PRBool
-AccReorderEvent::HasAccessibleInReasonSubtree()
-{
-  if (!mReasonNode)
-    return PR_FALSE;
-
-  nsAccessible *accessible = GetAccService()->GetAccessible(mReasonNode);
-  return accessible || nsAccUtils::HasAccessibleChildren(mReasonNode);
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
 // AccStateChangeEvent
 ////////////////////////////////////////////////////////////////////////////////
 
 // Note: we pass in eAllowDupes to the base class because we don't currently
 // support correct state change coalescence (XXX Bug 569356). Also we need to
 // decide how to coalesce events created via accessible (instead of node).
 AccStateChangeEvent::
   AccStateChangeEvent(nsAccessible* aAccessible,
                       PRUint32 aState, PRBool aIsExtraState,
-                      PRBool aIsEnabled, PRBool aIsAsynch,
-                      EIsFromUserInput aIsFromUserInput):
-  AccEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE, aAccessible, aIsAsynch,
+                      PRBool aIsEnabled, EIsFromUserInput aIsFromUserInput):
+  AccEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE, aAccessible,
            aIsFromUserInput, eAllowDupes),
   mState(aState), mIsExtraState(aIsExtraState), mIsEnabled(aIsEnabled)
 {
 }
 
 AccStateChangeEvent::
   AccStateChangeEvent(nsINode* aNode, PRUint32 aState, PRBool aIsExtraState,
                       PRBool aIsEnabled):
@@ -310,67 +275,92 @@ AccStateChangeEvent::CreateXPCOMObject()
 // node. This means we won't try to create an accessible based on the node when
 // we are ready to fire the event and so we will no longer assert at that point
 // if the node was removed from the document. Either way, the AT won't work with
 // a defunct accessible so the behaviour should be equivalent.
 // XXX revisit this when coalescence is faster (eCoalesceFromSameSubtree)
 AccTextChangeEvent::
   AccTextChangeEvent(nsAccessible* aAccessible, PRInt32 aStart,
                      nsAString& aModifiedText, PRBool aIsInserted,
-                     PRBool aIsAsynch, EIsFromUserInput aIsFromUserInput)
+                     EIsFromUserInput aIsFromUserInput)
   : AccEvent(aIsInserted ?
              static_cast<PRUint32>(nsIAccessibleEvent::EVENT_TEXT_INSERTED) :
              static_cast<PRUint32>(nsIAccessibleEvent::EVENT_TEXT_REMOVED),
-             aAccessible, aIsAsynch, aIsFromUserInput, eAllowDupes)
+             aAccessible, aIsFromUserInput, eAllowDupes)
   , mStart(aStart)
   , mIsInserted(aIsInserted)
   , mModifiedText(aModifiedText)
 {
 }
 
 already_AddRefed<nsAccEvent>
 AccTextChangeEvent::CreateXPCOMObject()
 {
   nsAccEvent* event = new nsAccTextChangeEvent(this);
   NS_IF_ADDREF(event);
   return event;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
+// AccMutationEvent
+////////////////////////////////////////////////////////////////////////////////
+
+AccMutationEvent::
+  AccMutationEvent(PRUint32 aEventType, nsAccessible* aTarget,
+                   nsINode* aTargetNode, EIsFromUserInput aIsFromUserInput) :
+  AccEvent(aEventType, aTarget, aIsFromUserInput, eCoalesceFromSameSubtree)
+{
+  mNode = aTargetNode;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
 // AccHideEvent
 ////////////////////////////////////////////////////////////////////////////////
 
 AccHideEvent::
   AccHideEvent(nsAccessible* aTarget, nsINode* aTargetNode,
-               PRBool aIsAsynch, EIsFromUserInput aIsFromUserInput) :
-  AccEvent(nsIAccessibleEvent::EVENT_HIDE, aTarget, aIsAsynch,
-           aIsFromUserInput, eCoalesceFromSameSubtree)
+               EIsFromUserInput aIsFromUserInput) :
+  AccMutationEvent(::nsIAccessibleEvent::EVENT_HIDE, aTarget, aTargetNode,
+                   aIsFromUserInput)
 {
-  mNode = aTargetNode;
   mParent = mAccessible->GetCachedParent();
   mNextSibling = mAccessible->GetCachedNextSibling();
   mPrevSibling = mAccessible->GetCachedPrevSibling();
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
+// AccShowEvent
+////////////////////////////////////////////////////////////////////////////////
+
+AccShowEvent::
+  AccShowEvent(nsAccessible* aTarget, nsINode* aTargetNode,
+               EIsFromUserInput aIsFromUserInput) :
+  AccMutationEvent(::nsIAccessibleEvent::EVENT_SHOW, aTarget, aTargetNode,
+                   aIsFromUserInput)
+{
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
 // AccCaretMoveEvent
 ////////////////////////////////////////////////////////////////////////////////
 
 AccCaretMoveEvent::
   AccCaretMoveEvent(nsAccessible* aAccessible, PRInt32 aCaretOffset) :
-  AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aAccessible, PR_TRUE), // Currently always asynch
+  AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aAccessible),
   mCaretOffset(aCaretOffset)
 {
 }
 
 AccCaretMoveEvent::
   AccCaretMoveEvent(nsINode* aNode) :
-  AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aNode, PR_TRUE), // Currently always asynch
+  AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aNode),
   mCaretOffset(-1)
 {
 }
 
 already_AddRefed<nsAccEvent>
 AccCaretMoveEvent::CreateXPCOMObject()
 {
   nsAccEvent* event = new nsAccCaretMoveEvent(this);
@@ -380,19 +370,18 @@ AccCaretMoveEvent::CreateXPCOMObject()
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccTableChangeEvent
 ////////////////////////////////////////////////////////////////////////////////
 
 AccTableChangeEvent::
   AccTableChangeEvent(nsAccessible* aAccessible, PRUint32 aEventType,
-                      PRInt32 aRowOrColIndex, PRInt32 aNumRowsOrCols,
-                      PRBool aIsAsynch) :
-  AccEvent(aEventType, aAccessible, aIsAsynch),
+                      PRInt32 aRowOrColIndex, PRInt32 aNumRowsOrCols) :
+  AccEvent(aEventType, aAccessible),
   mRowOrColIndex(aRowOrColIndex), mNumRowsOrCols(aNumRowsOrCols)
 {
 }
 
 already_AddRefed<nsAccEvent>
 AccTableChangeEvent::CreateXPCOMObject()
 {
   nsAccEvent* event = new nsAccTableChangeEvent(this);
--- a/accessible/src/base/AccEvent.h
+++ b/accessible/src/base/AccEvent.h
@@ -36,16 +36,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef _AccEvent_H_
 #define _AccEvent_H_
 
+#include "nsIAccessibleEvent.h"
+
 #include "nsAccessible.h"
 
 class nsAccEvent;
 class nsDocAccessible;
 
 // Constants used to point whether the event is from user input.
 enum EIsFromUserInput
 {
@@ -85,49 +87,48 @@ public:
      eRemoveDupes,
 
      // eDoNotEmit : This event is confirmed as a duplicate, do not emit it.
      eDoNotEmit
   };
 
   // Initialize with an nsIAccessible
   AccEvent(PRUint32 aEventType, nsAccessible* aAccessible,
-           PRBool aIsAsynch = PR_FALSE,
            EIsFromUserInput aIsFromUserInput = eAutoDetect,
            EEventRule aEventRule = eRemoveDupes);
   // Initialize with an nsIDOMNode
-  AccEvent(PRUint32 aEventType, nsINode* aNode, PRBool aIsAsynch = PR_FALSE,
+  AccEvent(PRUint32 aEventType, nsINode* aNode,
            EIsFromUserInput aIsFromUserInput = eAutoDetect,
            EEventRule aEventRule = eRemoveDupes);
   virtual ~AccEvent() {}
 
   // AccEvent
   PRUint32 GetEventType() const { return mEventType; }
   EEventRule GetEventRule() const { return mEventRule; }
-  PRBool IsAsync() const { return mIsAsync; }
   PRBool IsFromUserInput() const { return mIsFromUserInput; }
 
   nsAccessible *GetAccessible();
   nsDocAccessible* GetDocAccessible();
   nsINode* GetNode();
 
   /**
    * Create and return an XPCOM object for accessible event object.
    */
   virtual already_AddRefed<nsAccEvent> CreateXPCOMObject();
 
   /**
    * Down casting.
    */
   enum EventGroup {
     eGenericEvent,
-    eReorderEvent,
     eStateChangeEvent,
     eTextChangeEvent,
+    eMutationEvent,
     eHideEvent,
+    eShowEvent,
     eCaretMoveEvent,
     eTableChangeEvent
   };
 
   static const EventGroup kEventGroup = eGenericEvent;
   virtual unsigned int GetEventGroups() const
   {
     return 1U << eGenericEvent;
@@ -149,66 +150,32 @@ protected:
    * Determine whether the event is from user input by event state manager if
    * it's not pointed explicetly.
    */
   void CaptureIsFromUserInput(EIsFromUserInput aIsFromUserInput);
 
   PRBool mIsFromUserInput;
   PRUint32 mEventType;
   EEventRule mEventRule;
-  PRPackedBool mIsAsync;
   nsRefPtr<nsAccessible> mAccessible;
   nsCOMPtr<nsINode> mNode;
 
   friend class nsAccEventQueue;
 };
 
 
 /**
- * Accessible reorder event.
- */
-class AccReorderEvent : public AccEvent
-{
-public:
-  AccReorderEvent(nsAccessible* aAccTarget, PRBool aIsAsynch,
-                  PRBool aIsUnconditional, nsINode* aReasonNode);
-
-  // AccEvent
-  static const EventGroup kEventGroup = eReorderEvent;
-  virtual unsigned int GetEventGroups() const
-  {
-    return AccEvent::GetEventGroups() | (1U << eReorderEvent);
-  }
-
-  // AccReorderEvent
-  /**
-   * Return true if event is unconditional, i.e. must be fired.
-   */
-  PRBool IsUnconditionalEvent();
-
-  /**
-   * Return true if changed DOM node has accessible in its tree.
-   */
-  PRBool HasAccessibleInReasonSubtree();
-
-private:
-  PRBool mUnconditionalEvent;
-  nsCOMPtr<nsINode> mReasonNode;
-};
-
-
-/**
  * Accessible state change event.
  */
 class AccStateChangeEvent: public AccEvent
 {
 public:
   AccStateChangeEvent(nsAccessible* aAccessible,
                       PRUint32 aState, PRBool aIsExtraState,
-                      PRBool aIsEnabled, PRBool aIsAsynch = PR_FALSE,
+                      PRBool aIsEnabled,
                       EIsFromUserInput aIsFromUserInput = eAutoDetect);
 
   AccStateChangeEvent(nsINode* aNode, PRUint32 aState, PRBool aIsExtraState,
                       PRBool aIsEnabled);
 
   AccStateChangeEvent(nsINode* aNode, PRUint32 aState, PRBool aIsExtraState);
 
   // AccEvent
@@ -234,18 +201,17 @@ private:
 
 /**
  * Accessible text change event.
  */
 class AccTextChangeEvent: public AccEvent
 {
 public:
   AccTextChangeEvent(nsAccessible* aAccessible, PRInt32 aStart,
-                     nsAString& aModifiedText,
-                     PRBool aIsInserted, PRBool aIsAsynch = PR_FALSE,
+                     nsAString& aModifiedText, PRBool aIsInserted,
                      EIsFromUserInput aIsFromUserInput = eAutoDetect);
 
   // AccEvent
   virtual already_AddRefed<nsAccEvent> CreateXPCOMObject();
 
   static const EventGroup kEventGroup = eTextChangeEvent;
   virtual unsigned int GetEventGroups() const
   {
@@ -264,42 +230,86 @@ private:
   PRBool mIsInserted;
   nsString mModifiedText;
 
   friend class nsAccEventQueue;
 };
 
 
 /**
- * Accessible hide events.
+ * Base class for show and hide accessible events.
  */
-class AccHideEvent : public AccEvent
+class AccMutationEvent: public AccEvent
+{
+public:
+  AccMutationEvent(PRUint32 aEventType, nsAccessible* aTarget,
+                   nsINode* aTargetNode, EIsFromUserInput aIsFromUserInput);
+
+  // Event
+  static const EventGroup kEventGroup = eMutationEvent;
+  virtual unsigned int GetEventGroups() const
+  {
+    return AccEvent::GetEventGroups() | (1U << eMutationEvent);
+  }
+
+  // MutationEvent
+  bool IsShow() const { return mEventType == nsIAccessibleEvent::EVENT_SHOW; }
+  bool IsHide() const { return mEventType == nsIAccessibleEvent::EVENT_HIDE; }
+
+protected:
+  nsRefPtr<AccTextChangeEvent> mTextChangeEvent;
+
+  friend class nsAccEventQueue;
+};
+
+
+/**
+ * Accessible hide event.
+ */
+class AccHideEvent: public AccMutationEvent
 {
 public:
   AccHideEvent(nsAccessible* aTarget, nsINode* aTargetNode,
-               PRBool aIsAsynch, EIsFromUserInput aIsFromUserInput);
+               EIsFromUserInput aIsFromUserInput);
 
   // Event
   static const EventGroup kEventGroup = eHideEvent;
   virtual unsigned int GetEventGroups() const
   {
-    return AccEvent::GetEventGroups() | (1U << eHideEvent);
+    return AccMutationEvent::GetEventGroups() | (1U << eHideEvent);
   }
 
 protected:
   nsRefPtr<nsAccessible> mParent;
   nsRefPtr<nsAccessible> mNextSibling;
   nsRefPtr<nsAccessible> mPrevSibling;
-  nsRefPtr<AccTextChangeEvent> mTextChangeEvent;
 
   friend class nsAccEventQueue;
 };
 
 
 /**
+ * Accessible show event.
+ */
+class AccShowEvent: public AccMutationEvent
+{
+public:
+  AccShowEvent(nsAccessible* aTarget, nsINode* aTargetNode,
+               EIsFromUserInput aIsFromUserInput);
+
+  // Event
+  static const EventGroup kEventGroup = eShowEvent;
+  virtual unsigned int GetEventGroups() const
+  {
+    return AccMutationEvent::GetEventGroups() | (1U << eShowEvent);
+  }
+};
+
+
+/**
  * Accessible caret move event.
  */
 class AccCaretMoveEvent: public AccEvent
 {
 public:
   AccCaretMoveEvent(nsAccessible* aAccessible, PRInt32 aCaretOffset);
   AccCaretMoveEvent(nsINode* aNode);
 
@@ -322,18 +332,17 @@ private:
 
 /**
  * Accessible table change event.
  */
 class AccTableChangeEvent : public AccEvent
 {
 public:
   AccTableChangeEvent(nsAccessible* aAccessible, PRUint32 aEventType,
-                      PRInt32 aRowOrColIndex, PRInt32 aNumRowsOrCols,
-                      PRBool aIsAsynch);
+                      PRInt32 aRowOrColIndex, PRInt32 aNumRowsOrCols);
 
   // AccEvent
   virtual already_AddRefed<nsAccEvent> CreateXPCOMObject();
 
   static const EventGroup kEventGroup = eTableChangeEvent;
   virtual unsigned int GetEventGroups() const
   {
     return AccEvent::GetEventGroups() | (1U << eTableChangeEvent);
--- a/accessible/src/base/nsAccDocManager.cpp
+++ b/accessible/src/base/nsAccDocManager.cpp
@@ -67,29 +67,28 @@ nsDocAccessible*
 nsAccDocManager::GetDocAccessible(nsIDocument *aDocument)
 {
   if (!aDocument)
     return nsnull;
 
   // Ensure CacheChildren is called before we query cache.
   nsAccessNode::GetApplicationAccessible()->EnsureChildren();
 
-  nsDocAccessible *docAcc =
-    mDocAccessibleCache.GetWeak(static_cast<void*>(aDocument));
+  nsDocAccessible* docAcc = mDocAccessibleCache.GetWeak(aDocument);
   if (docAcc)
     return docAcc;
 
   return CreateDocOrRootAccessible(aDocument);
 }
 
 nsAccessible*
-nsAccDocManager::FindAccessibleInCache(void *aUniqueID) const
+nsAccDocManager::FindAccessibleInCache(nsINode* aNode) const
 {
   nsSearchAccessibleInCacheArg arg;
-    arg.mUniqueID = aUniqueID;
+  arg.mNode = aNode;
 
   mDocAccessibleCache.EnumerateRead(SearchAccessibleInDocCache,
                                     static_cast<void*>(&arg));
 
   return arg.mAccessible;
 }
 
 void
@@ -131,27 +130,26 @@ nsAccDocManager::Shutdown()
     progress->RemoveProgressListener(static_cast<nsIWebProgressListener*>(this));
 
   ClearDocCache();
 }
 
 void
 nsAccDocManager::ShutdownDocAccessible(nsIDocument *aDocument)
 {
-  nsDocAccessible* docAccessible =
-    mDocAccessibleCache.GetWeak(static_cast<void*>(aDocument));
+  nsDocAccessible* docAccessible = mDocAccessibleCache.GetWeak(aDocument);
   if (!docAccessible)
     return;
 
   // We're allowed to not remove listeners when accessible document is shutdown
   // since we don't keep strong reference on chrome event target and listeners
   // are removed automatically when chrome event target goes away.
 
   docAccessible->Shutdown();
-  mDocAccessibleCache.Remove(static_cast<void*>(aDocument));
+  mDocAccessibleCache.Remove(aDocument);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
 NS_IMPL_THREADSAFE_ISUPPORTS3(nsAccDocManager,
                               nsIWebProgressListener,
                               nsIDOMEventListener,
@@ -210,18 +208,17 @@ nsAccDocManager::OnStateChange(nsIWebPro
 
   // Document loading was started.
   NS_LOG_ACCDOCLOAD("start document loading", aWebProgress, aRequest,
                     aStateFlags)
 
   if (!IsEventTargetDocument(document))
     return NS_OK;
 
-  nsDocAccessible *docAcc =
-    mDocAccessibleCache.GetWeak(static_cast<void*>(document));
+  nsDocAccessible* docAcc = mDocAccessibleCache.GetWeak(document);
   if (!docAcc)
     return NS_OK;
 
   nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(DOMWindow));
   nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(webNav));
   NS_ENSURE_STATE(docShell);
 
   // Fire reload and state busy events on existing document accessible while
@@ -341,45 +338,35 @@ nsAccDocManager::HandleEvent(nsIDOMEvent
 
 void
 nsAccDocManager::HandleDOMDocumentLoad(nsIDocument *aDocument,
                                        PRUint32 aLoadEventType,
                                        PRBool aMarkAsLoaded)
 {
   // Document accessible can be created before we were notified the DOM document
   // was loaded completely. However if it's not created yet then create it.
-  nsDocAccessible *docAcc =
-    mDocAccessibleCache.GetWeak(static_cast<void*>(aDocument));
-
+  nsDocAccessible* docAcc = mDocAccessibleCache.GetWeak(aDocument);
   if (!docAcc) {
     docAcc = CreateDocOrRootAccessible(aDocument);
     NS_ASSERTION(docAcc, "Can't create document accessible!");
     if (!docAcc)
       return;
   }
 
   if (aMarkAsLoaded)
     docAcc->MarkAsLoaded();
 
   // Do not fire document complete/stop events for root chrome document
   // accessibles and for frame/iframe documents because
   // a) screen readers start working on focus event in the case of root chrome
   // documents
   // b) document load event on sub documents causes screen readers to act is if
   // entire page is reloaded.
-  if (!IsEventTargetDocument(aDocument)) {
-    // XXX: AT doesn't update their virtual buffer once frame is loaded and it
-    // has dynamic content added after frame load. There's something wrong how
-    // we handle this changes.
-    if (!nsCoreUtils::IsRootDocument(aDocument)) {
-      docAcc->InvalidateCacheSubtree(nsnull,
-                                     nsIAccessibilityService::NODE_SIGNIFICANT_CHANGE);
-    }
+  if (!IsEventTargetDocument(aDocument))
     return;
-  }
 
   // Fire complete/load stopped if the load event type is given.
   if (aLoadEventType) {
     nsRefPtr<AccEvent> loadEvent = new AccEvent(aLoadEventType, aDocument);
     docAcc->FireDelayedAccessibleEvent(loadEvent);
   }
 
   // Fire busy state change event.
@@ -432,19 +419,20 @@ nsAccDocManager::AddListeners(nsIDocumen
                                 NS_EVENT_FLAG_CAPTURE, nsnull);
     NS_LOG_ACCDOCCREATE_TEXT("  added 'DOMContentLoaded' listener")
   }
 }
 
 nsDocAccessible*
 nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument)
 {
-  // Ignore temporary, hiding and svg resource documents.
+  // Ignore temporary, hiding, resource documents and documents without
+  // docshell.
   if (aDocument->IsInitialDocument() || !aDocument->IsVisible() ||
-      aDocument->GetDisplayDocument())
+      aDocument->IsResourceDoc() || !aDocument->IsActive())
     return nsnull;
 
   // Ignore documents without presshell.
   nsIPresShell *presShell = aDocument->GetShell();
   if (!presShell)
     return nsnull;
 
   // Do not create document accessible until role content is loaded, otherwise
@@ -487,27 +475,27 @@ nsAccDocManager::CreateDocOrRootAccessib
   nsDocAccessible *docAcc = isRootDoc ?
     new nsRootAccessibleWrap(aDocument, rootElm, weakShell) :
     new nsDocAccessibleWrap(aDocument, rootElm, weakShell);
 
   if (!docAcc)
     return nsnull;
 
   // Cache and addref document accessible.
-  if (!mDocAccessibleCache.Put(static_cast<void*>(aDocument), docAcc)) {
+  if (!mDocAccessibleCache.Put(aDocument, docAcc)) {
     delete docAcc;
     return nsnull;
   }
 
   // XXX: ideally we should initialize an accessible and then put it into tree,
   // we can't since document accessible fires reorder event on its container
   // while initialized.
   if (!outerDocAcc->AppendChild(docAcc) ||
       !GetAccService()->InitAccessible(docAcc, nsAccUtils::GetRoleMapEntry(aDocument))) {
-    mDocAccessibleCache.Remove(static_cast<void*>(aDocument));
+    mDocAccessibleCache.Remove(aDocument);
     return nsnull;
   }
 
   NS_LOG_ACCDOCCREATE("document creation finished", aDocument)
 
   AddListeners(aDocument, isRootDoc);
   return docAcc;
 }
@@ -540,39 +528,39 @@ nsAccDocManager::ShutdownDocAccessiblesI
 
   ShutdownDocAccessible(aDocument);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccDocManager static
 
 PLDHashOperator
-nsAccDocManager::ClearDocCacheEntry(const void* aKey,
+nsAccDocManager::ClearDocCacheEntry(const nsIDocument* aKey,
                                     nsRefPtr<nsDocAccessible>& aDocAccessible,
                                     void* aUserArg)
 {
   NS_ASSERTION(aDocAccessible,
                "Calling ClearDocCacheEntry with a NULL pointer!");
 
   if (aDocAccessible)
     aDocAccessible->Shutdown();
 
   return PL_DHASH_REMOVE;
 }
 
 PLDHashOperator
-nsAccDocManager::SearchAccessibleInDocCache(const void* aKey,
+nsAccDocManager::SearchAccessibleInDocCache(const nsIDocument* aKey,
                                             nsDocAccessible* aDocAccessible,
                                             void* aUserArg)
 {
   NS_ASSERTION(aDocAccessible,
                "No doc accessible for the object in doc accessible cache!");
 
   if (aDocAccessible) {
     nsSearchAccessibleInCacheArg* arg =
       static_cast<nsSearchAccessibleInCacheArg*>(aUserArg);
-    arg->mAccessible = aDocAccessible->GetCachedAccessible(arg->mUniqueID);
+    arg->mAccessible = aDocAccessible->GetCachedAccessible(arg->mNode);
     if (arg->mAccessible)
       return PL_DHASH_STOP;
   }
 
   return PL_DHASH_NEXT;
 }
--- a/accessible/src/base/nsAccDocManager.h
+++ b/accessible/src/base/nsAccDocManager.h
@@ -68,31 +68,31 @@ public:
    * Return document accessible for the given DOM node.
    */
   nsDocAccessible *GetDocAccessible(nsIDocument *aDocument);
 
   /**
    * Search through all document accessibles for an accessible with the given
    * unique id.
    */
-  nsAccessible *FindAccessibleInCache(void *aUniqueID) const;
+  nsAccessible* FindAccessibleInCache(nsINode* aNode) const;
 
   /**
    * Shutdown document accessibles in the tree starting from the given one.
    *
    * @param  aDocument  [in] the DOM document of start document accessible
    */
   void ShutdownDocAccessiblesInTree(nsIDocument *aDocument);
 
   /**
    * Return document accessible from the cache. Convenient method for testing.
    */
   inline nsDocAccessible* GetDocAccessibleFromCache(nsIDocument* aDocument) const
   {
-    return mDocAccessibleCache.GetWeak(static_cast<void*>(aDocument));
+    return mDocAccessibleCache.GetWeak(aDocument);
   }
 
 protected:
   nsAccDocManager() { };
 
   /**
    * Initialize the manager.
    */
@@ -157,43 +157,43 @@ private:
   nsDocAccessible *CreateDocOrRootAccessible(nsIDocument *aDocument);
 
   /**
    * Shutdown document accessibles in the tree starting from given tree item.
    */
   void ShutdownDocAccessiblesInTree(nsIDocShellTreeItem *aTreeItem,
                                     nsIDocument *aDocument);
 
-  typedef nsRefPtrHashtable<nsVoidPtrHashKey, nsDocAccessible>
+  typedef nsRefPtrHashtable<nsPtrHashKey<const nsIDocument>, nsDocAccessible>
     nsDocAccessibleHashtable;
 
   /**
    * Shutdown and remove the document accessible from cache.
    */
   static PLDHashOperator
-    ClearDocCacheEntry(const void* aKey,
+    ClearDocCacheEntry(const nsIDocument* aKey,
                        nsRefPtr<nsDocAccessible>& aDocAccessible,
                        void* aUserArg);
 
   /**
    * Clear the cache and shutdown the document accessibles.
    */
   void ClearDocCache()
   {
     mDocAccessibleCache.Enumerate(ClearDocCacheEntry, static_cast<void*>(this));
   }
 
   struct nsSearchAccessibleInCacheArg
   {
     nsAccessible *mAccessible;
-    void *mUniqueID;
+    nsINode* mNode;
   };
 
   static PLDHashOperator
-    SearchAccessibleInDocCache(const void* aKey,
+    SearchAccessibleInDocCache(const nsIDocument* aKey,
                                nsDocAccessible* aDocAccessible,
                                void* aUserArg);
 
   nsDocAccessibleHashtable mDocAccessibleCache;
 };
 
 /**
  * nsAccDocManager debugging macros.
--- a/accessible/src/base/nsAccTreeWalker.cpp
+++ b/accessible/src/base/nsAccTreeWalker.cpp
@@ -69,19 +69,21 @@ nsAccTreeWalker::
                   PRBool aWalkAnonContent) :
   mWeakShell(aShell), mState(nsnull)
 {
   NS_ASSERTION(aContent, "No node for the accessible tree walker!");
 
   if (aContent)
     mState = new WalkState(aContent);
 
-  mChildType = aWalkAnonContent ? nsIContent::eAllChildren :
+  mChildFilter = aWalkAnonContent ? nsIContent::eAllChildren :
                                   nsIContent::eAllButXBL;
 
+  mChildFilter |= nsIContent::eSkipPlaceholderContent;
+
   MOZ_COUNT_CTOR(nsAccTreeWalker);
 }
 
 nsAccTreeWalker::~nsAccTreeWalker()
 {
   // Clear state stack from memory
   while (mState)
     PopState();
@@ -94,17 +96,17 @@ nsAccTreeWalker::~nsAccTreeWalker()
 
 already_AddRefed<nsAccessible>
 nsAccTreeWalker::GetNextChildInternal(PRBool aNoWalkUp)
 {
   if (!mState || !mState->content)
     return nsnull;
 
   if (!mState->childList)
-    mState->childList = mState->content->GetChildren(mChildType);
+    mState->childList = mState->content->GetChildren(mChildFilter);
 
   nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
 
   PRUint32 length = 0;
   if (mState->childList)
     mState->childList->GetLength(&length);
 
   while (mState->childIdx < length) {
--- a/accessible/src/base/nsAccTreeWalker.h
+++ b/accessible/src/base/nsAccTreeWalker.h
@@ -86,13 +86,13 @@ private:
   PRBool PushState(nsIContent *aNode);
 
   /**
    * Pop state from stack.
    */
   void PopState();
 
   nsCOMPtr<nsIWeakReference> mWeakShell;
-  PRInt32 mChildType;
+  PRInt32 mChildFilter;
   WalkState* mState;
 };
 
 #endif 
--- a/accessible/src/base/nsAccessNode.cpp
+++ b/accessible/src/base/nsAccessNode.cpp
@@ -147,19 +147,22 @@ nsAccessNode::Init()
 void
 nsAccessNode::Shutdown()
 {
   mContent = nsnull;
   mWeakShell = nsnull;
 }
 
 // nsIAccessNode
-NS_IMETHODIMP nsAccessNode::GetUniqueID(void **aUniqueID)
+NS_IMETHODIMP
+nsAccessNode::GetUniqueID(void **aUniqueID)
 {
-  *aUniqueID = static_cast<void*>(GetNode());
+  NS_ENSURE_ARG_POINTER(aUniqueID);
+
+  *aUniqueID = UniqueID();
   return NS_OK;
 }
 
 // nsIAccessNode
 NS_IMETHODIMP
 nsAccessNode::GetOwnerWindow(void **aWindow)
 {
   NS_ENSURE_ARG_POINTER(aWindow);
@@ -305,16 +308,22 @@ already_AddRefed<nsRootAccessible> nsAcc
 }
 
 nsIFrame*
 nsAccessNode::GetFrame()
 {
   return mContent ? mContent->GetPrimaryFrame() : nsnull;
 }
 
+bool
+nsAccessNode::IsPrimaryForNode() const
+{
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessNode
 
 NS_IMETHODIMP
 nsAccessNode::GetDOMNode(nsIDOMNode **aDOMNode)
 {
   NS_ENSURE_ARG_POINTER(aDOMNode);
   *aDOMNode = nsnull;
--- a/accessible/src/base/nsAccessNode.h
+++ b/accessible/src/base/nsAccessNode.h
@@ -176,16 +176,30 @@ public:
    */
   already_AddRefed<nsIPresShell> GetPresShell();
 
   /**
    * Return presentation shell for the accessible.
    */
   nsIWeakReference* GetWeakShell() const { return mWeakShell; }
 
+  /**
+   * Return the unique identifier of the accessible.
+   */
+  void* UniqueID() { return static_cast<void*>(this); }
+
+  /**
+   * Return true if the accessible is primary accessible for the given DOM node.
+   *
+   * Accessible hierarchy may be complex for single DOM node, in this case
+   * these accessibles share the same DOM node. The primary accessible "owns"
+   * that DOM node in terms it gets stored in the accessible to node map.
+   */
+  virtual bool IsPrimaryForNode() const;
+
 protected:
     nsPresContext* GetPresContext();
 
     void LastRelease();
 
   nsCOMPtr<nsIContent> mContent;
   nsCOMPtr<nsIWeakReference> mWeakShell;
 
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -69,16 +69,17 @@
 #include "nsIObserverService.h"
 #include "nsIPluginInstance.h"
 #include "nsISupportsUtils.h"
 #include "nsObjectFrame.h"
 #include "nsOuterDocAccessible.h"
 #include "nsRootAccessibleWrap.h"
 #include "nsTextFragment.h"
 #include "mozilla/Services.h"
+#include "nsIEventStateManager.h"
 
 #ifdef MOZ_XUL
 #include "nsXULAlertAccessible.h"
 #include "nsXULColorPickerAccessible.h"
 #include "nsXULComboboxAccessible.h"
 #include "nsXULFormControlAccessible.h"
 #include "nsXULListboxAccessibleWrap.h"
 #include "nsXULMenuAccessibleWrap.h"
@@ -227,22 +228,20 @@ nsAccessibilityService::CreateHTMLButton
   nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(aPresShell));
   nsAccessible* accessible = new nsHTMLButtonAccessible(aContent, weakShell);
   NS_IF_ADDREF(accessible);
   return accessible;
 }
 
 already_AddRefed<nsAccessible>
 nsAccessibilityService::CreateHTMLLIAccessible(nsIContent* aContent,
-                                               nsIPresShell* aPresShell,
-                                               const nsAString& aBulletText)
+                                               nsIPresShell* aPresShell)
 {
   nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(aPresShell));
-  nsAccessible* accessible = new nsHTMLLIAccessible(aContent, weakShell,
-                                                    aBulletText);
+  nsAccessible* accessible = new nsHTMLLIAccessible(aContent, weakShell);
   NS_IF_ADDREF(accessible);
   return accessible;
 }
 
 already_AddRefed<nsAccessible>
 nsAccessibilityService::CreateHyperTextAccessible(nsIContent* aContent,
                                                   nsIPresShell* aPresShell)
 {
@@ -468,16 +467,72 @@ nsAccessibilityService::CreateHTMLCaptio
 {
   nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(aPresShell));
   nsAccessible* accessible = new nsHTMLCaptionAccessible(aContent, weakShell);
   NS_IF_ADDREF(accessible);
   return accessible;
 }
 
 void
+nsAccessibilityService::ContentRangeInserted(nsIPresShell* aPresShell,
+                                             nsIContent* aContainer,
+                                             nsIContent* aStartChild,
+                                             nsIContent* aEndChild)
+{
+#ifdef DEBUG_A11Y
+  nsAutoString tag;
+  aStartChild->Tag()->ToString(tag);
+  nsIAtom* id = aStartChild->GetID();
+  nsCAutoString strid;
+  if (id)
+    id->ToUTF8String(strid);
+  nsAutoString ctag;
+  aContainer->Tag()->ToString(ctag);
+  nsIAtom* cid = aContainer->GetID();
+  nsCAutoString strcid;
+  if (cid)
+    cid->ToUTF8String(strcid);
+  printf("\ncontent inserted: %s@id='%s', container: %s@id='%s', end node: %p\n\n",
+         NS_ConvertUTF16toUTF8(tag).get(), strid.get(),
+         NS_ConvertUTF16toUTF8(ctag).get(), strcid.get(), aEndChild);
+#endif
+
+  // XXX: bug 606082. aContainer is null when root element is inserted into
+  // document, we need to handle this and update the tree, also we need to
+  // update a content node of the document accessible.
+  if (aContainer) {
+    nsDocAccessible* docAccessible = GetDocAccessible(aPresShell->GetDocument());
+    if (docAccessible)
+      docAccessible->UpdateTree(aContainer, aStartChild, aEndChild, PR_TRUE);
+  }
+}
+
+void
+nsAccessibilityService::ContentRemoved(nsIPresShell* aPresShell,
+                                       nsIContent* aContainer,
+                                       nsIContent* aChild)
+{
+#ifdef DEBUG_A11Y
+  nsAutoString id;
+  aChild->Tag()->ToString(id);
+  printf("\ncontent removed: %s\n", NS_ConvertUTF16toUTF8(id).get());
+#endif
+
+  // XXX: bug 606082. aContainer is null when root element is inserted into
+  // document, we need to handle this and update the tree, perhaps destroy
+  // the document accessible.
+  if (aContainer) {
+    nsDocAccessible* docAccessible = GetDocAccessible(aPresShell->GetDocument());
+    if (docAccessible)
+      docAccessible->UpdateTree(aContainer, aChild, aChild->GetNextSibling(),
+                                PR_FALSE);
+  }
+}
+
+void
 nsAccessibilityService::PresShellDestroyed(nsIPresShell *aPresShell)
 {
   // Presshell destruction will automatically destroy shells for descendant
   // documents, so no need to worry about those. Just shut down the accessible
   // for this one document. That keeps us from having bad behavior in case of
   // deep bushy subtrees.
   // When document subtree containing iframe is hidden then we don't get
   // pagehide event for the iframe's underlying document and its presshell is
@@ -486,24 +541,32 @@ nsAccessibilityService::PresShellDestroy
   nsIDocument* doc = aPresShell->GetDocument();
   if (!doc)
     return;
 
   NS_LOG_ACCDOCDESTROY("presshell destroyed", doc)
   ShutdownDocAccessible(doc);
 }
 
+void
+nsAccessibilityService::RecreateAccessible(nsIPresShell* aPresShell,
+                                           nsIContent* aContent)
+{
+  nsDocAccessible* document = GetDocAccessible(aPresShell->GetDocument());
+  if (document)
+    document->RecreateAccessible(aContent);
+}
+
 // nsAccessibilityService protected
 nsAccessible *
 nsAccessibilityService::GetCachedAccessible(nsINode *aNode,
                                             nsIWeakReference *aWeakShell)
 {
   nsDocAccessible *docAccessible = GetDocAccessible(aNode->GetOwnerDoc());
-  return docAccessible ?
-    docAccessible->GetCachedAccessible(static_cast<void*>(aNode)) : nsnull;
+  return docAccessible ? docAccessible->GetCachedAccessible(aNode) : nsnull;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessibleRetrieval
 
 NS_IMETHODIMP
 nsAccessibilityService::GetApplicationAccessible(nsIAccessible **aAccessibleApplication)
 {
@@ -691,17 +754,17 @@ nsAccessibilityService::GetAccessibleFro
 
   // Search for an accessible in each of our per document accessible object
   // caches. If we don't find it, and the given node is itself a document, check
   // our cache of document accessibles (document cache). Note usually shutdown
   // document accessibles are not stored in the document cache, however an
   // "unofficially" shutdown document (i.e. not from nsAccDocManager) can still
   // exist in the document cache.
   nsCOMPtr<nsINode> node(do_QueryInterface(aNode));
-  nsAccessible* accessible = FindAccessibleInCache(static_cast<void*>(node));
+  nsAccessible* accessible = FindAccessibleInCache(node);
   if (!accessible) {
     nsCOMPtr<nsIDocument> document(do_QueryInterface(node));
     if (document)
       accessible = GetDocAccessibleFromCache(document);
   }
 
   NS_IF_ADDREF(*aAccessible = accessible);
   return NS_OK;
@@ -729,35 +792,35 @@ nsAccessibilityService::GetAccessible(ns
     nsCOMPtr<nsIWeakReference> weakShell(nsCoreUtils::GetWeakShellFor(aNode));
     if (weakShell)
       return GetAccessibleByRule(aNode, weakShell, eGetAccForNode);
   }
   return nsnull;
 }
 
 nsAccessible*
-nsAccessibilityService::GetCachedContainerAccessible(nsINode* aNode)
+nsAccessibilityService::GetCachedAccessibleOrContainer(nsINode* aNode)
 {
   if (!aNode)
     return nsnull;
 
   nsIDocument *document = aNode->GetCurrentDoc();
   if (!document)
     return nsnull;
 
   nsIPresShell *presShell = document->GetShell();
   if (!presShell)
     return nsnull;
 
   nsINode *currNode = aNode;
   nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell));
 
   nsAccessible *accessible = nsnull;
-  while ((currNode = currNode->GetNodeParent()) &&
-         !(accessible = GetCachedAccessible(currNode, weakShell)));
+  while (!(accessible = GetCachedAccessible(currNode, weakShell)) &&
+         (currNode = currNode->GetNodeParent()));
 
   return accessible;
 }
 
 PRBool
 nsAccessibilityService::InitAccessible(nsAccessible *aAccessible,
                                        nsRoleMapEntry *aRoleMapEntry)
 {
@@ -854,18 +917,17 @@ nsAccessibilityService::GetOrCreateAcces
 
   // Frames can be deallocated when we flush layout, or when we call into code
   // that can flush layout, either directly, or via DOM manipulation, or some
   // CSS styles like :hover. We use the weak frame checks to avoid calling
   // methods on a dead frame pointer.
   nsWeakFrame weakFrame = content->GetPrimaryFrame();
 
   // Check frame to see if it is hidden.
-  if (!weakFrame.GetFrame() ||
-      !weakFrame.GetFrame()->GetStyleVisibility()->IsVisible()) {
+  if (!weakFrame.GetFrame()) {
     if (aIsHidden)
       *aIsHidden = PR_TRUE;
 
     return nsnull;
   }
 
   if (weakFrame.GetFrame()->GetContent() != content) {
     // Not the main content for this frame. This happens because <area>
@@ -1192,33 +1254,34 @@ nsAccessibilityService::HasUniversalAria
 nsAccessible*
 nsAccessibilityService::GetAccessibleByRule(nsINode* aNode,
                                             nsIWeakReference* aWeakShell,
                                             EWhatAccToGet aWhatToGet)
 {
   if (!aNode || !aWeakShell)
     return nsnull;
 
-  nsAccessible* cachedAcc = GetCachedAccessible(aNode, aWeakShell);
-  if (cachedAcc) {
-    if (aWhatToGet & eGetAccForNode)
+  if (aWhatToGet & eGetAccForNode) {
+    nsAccessible* cachedAcc = GetCachedAccessible(aNode, aWeakShell);
+    if (cachedAcc && cachedAcc->IsBoundToParent())
       return cachedAcc;
-
-    // XXX: while nsAccessible::GetParent() tries to repair broken tree and
-    // may not return cached parent then we use GetAccessibleOrContainer().
-    return GetAccessibleByRule(aNode->GetNodeParent(), aWeakShell,
-                               eGetAccForNodeOrContainer);
   }
 
-  // Go up looking for the nearest accessible container stored in cache.
+  // Go up looking for the nearest accessible container having cached children.
   nsTArray<nsINode*> nodes;
+
   nsINode* node = aNode;
-  while ((node = node->GetNodeParent()) &&
-         !(cachedAcc = GetCachedAccessible(node, aWeakShell)))
+  nsAccessible* cachedAcc = nsnull;
+  while ((node = node->GetNodeParent())) {
+    cachedAcc = GetCachedAccessible(node, aWeakShell);
+    if (cachedAcc && cachedAcc->IsBoundToParent())
+      break;
+
     nodes.AppendElement(node);
+  }
 
   // Node is not in accessible document.
   if (!cachedAcc)
     return nsnull;
 
   // If children of the cached accessible weren't initialized then go down to
   // the given node and create accessible tree.
   nsAccessible* containerAcc = cachedAcc;
@@ -1629,18 +1692,17 @@ nsAccessibilityService::CreateHTMLAccess
   }
 
   if (tag == nsAccessibilityAtoms::dt ||
       (tag == nsAccessibilityAtoms::li &&
        aFrame->GetType() != nsAccessibilityAtoms::blockFrame)) {
     // Normally for li, it is created by the list item frame (in nsBlockFrame)
     // which knows about the bullet frame; however, in this case the list item
     // must have been styled using display: foo
-    nsAccessible* accessible = new nsHTMLLIAccessible(aContent, aWeakShell,
-                                                      EmptyString());
+    nsAccessible* accessible = new nsHTMLLIAccessible(aContent, aWeakShell);
     NS_IF_ADDREF(accessible);
     return accessible;
   }
 
   if (tag == nsAccessibilityAtoms::abbr ||
       tag == nsAccessibilityAtoms::acronym ||
       tag == nsAccessibilityAtoms::blockquote ||
       tag == nsAccessibilityAtoms::dd ||
@@ -1711,39 +1773,16 @@ nsAccessibilityService::RemoveNativeRoot
   nsApplicationAccessible* applicationAcc =
     nsAccessNode::GetApplicationAccessible();
 
   if (applicationAcc)
     applicationAcc->RemoveChild(aAccessible);
 #endif
 }
 
-// Called from layout when the frame tree owned by a node changes significantly
-nsresult
-nsAccessibilityService::InvalidateSubtreeFor(nsIPresShell *aShell,
-                                             nsIContent *aChangeContent,
-                                             PRUint32 aChangeType)
-{
-  NS_ASSERTION(aChangeType == nsIAccessibilityService::FRAME_SIGNIFICANT_CHANGE ||
-               aChangeType == nsIAccessibilityService::FRAME_SHOW ||
-               aChangeType == nsIAccessibilityService::FRAME_HIDE ||
-               aChangeType == nsIAccessibilityService::NODE_SIGNIFICANT_CHANGE ||
-               aChangeType == nsIAccessibilityService::NODE_APPEND ||
-               aChangeType == nsIAccessibilityService::NODE_REMOVE,
-               "Incorrect aEvent passed in");
-
-  NS_ENSURE_ARG_POINTER(aShell);
-
-  nsDocAccessible *docAccessible = GetDocAccessible(aShell->GetDocument());
-  if (docAccessible)
-    docAccessible->InvalidateCacheSubtree(aChangeContent, aChangeType);
-
-  return NS_OK;
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // NS_GetAccessibilityService
 ////////////////////////////////////////////////////////////////////////////////
 
 /**
  * Return accessibility service; creating one if necessary.
  */
 nsresult
--- a/accessible/src/base/nsAccessibilityService.h
+++ b/accessible/src/base/nsAccessibilityService.h
@@ -79,18 +79,17 @@ public:
     CreateHTMLGroupboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
   virtual already_AddRefed<nsAccessible>
     CreateHTMLHRAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
   virtual already_AddRefed<nsAccessible>
     CreateHTMLImageAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
   virtual already_AddRefed<nsAccessible>
     CreateHTMLLabelAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
   virtual already_AddRefed<nsAccessible>
-    CreateHTMLLIAccessible(nsIContent* aContent, nsIPresShell* aPresShell,
-                           const nsAString& aBulletText);
+    CreateHTMLLIAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
   virtual already_AddRefed<nsAccessible>
     CreateHTMLListboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
   virtual already_AddRefed<nsAccessible>
     CreateHTMLMediaAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
   virtual already_AddRefed<nsAccessible>
     CreateHTMLObjectFrameAccessible(nsObjectFrame* aFrame, nsIContent* aContent,
                                     nsIPresShell* aPresShell);
   virtual already_AddRefed<nsAccessible>
@@ -106,24 +105,31 @@ public:
   virtual already_AddRefed<nsAccessible>
     CreateHyperTextAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
   virtual already_AddRefed<nsAccessible>
     CreateOuterDocAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
 
   virtual nsAccessible* AddNativeRootAccessible(void* aAtkAccessible);
   virtual void RemoveNativeRootAccessible(nsAccessible* aRootAccessible);
 
-  virtual nsresult InvalidateSubtreeFor(nsIPresShell *aPresShell,
-                                        nsIContent *aContent,
-                                        PRUint32 aChangeType);
+  virtual void ContentRangeInserted(nsIPresShell* aPresShell,
+                                      nsIContent* aContainer,
+                                      nsIContent* aStartChild,
+                                      nsIContent* aEndChild);
+
+  virtual void ContentRemoved(nsIPresShell* aPresShell, nsIContent* aContainer,
+                              nsIContent* aChild);
 
   virtual void NotifyOfAnchorJumpTo(nsIContent *aTarget);
 
   virtual void PresShellDestroyed(nsIPresShell* aPresShell);
 
+  virtual void RecreateAccessible(nsIPresShell* aPresShell,
+                                  nsIContent* aContent);
+
   virtual void FireAccessibleEvent(PRUint32 aEvent, nsAccessible* aTarget);
 
   // nsAccessibiltiyService
 
   /**
    * Return true if accessibility service has been shutdown.
    */
   static PRBool IsShutdown() { return gIsShutdown; }
@@ -175,21 +181,31 @@ public:
    */
   inline nsAccessible* GetContainerAccessible(nsINode* aNode,
                                               nsIWeakReference* aWeakShell)
   {
     return GetAccessibleByRule(aNode, aWeakShell, eGetAccForContainer);
   }
 
   /**
+   * Return cached accessible for the given DOM node or cached container
+   * accessible if there's no cached accessible for the given node.
+   */
+  nsAccessible* GetCachedAccessibleOrContainer(nsINode* aNode);
+
+  /**
    * Return the first cached accessible parent of a DOM node.
    *
    * @param aDOMNode    [in] the DOM node to get an accessible for
    */
-  nsAccessible* GetCachedContainerAccessible(nsINode *aNode);
+  inline nsAccessible* GetCachedContainerAccessible(nsINode *aNode)
+  {
+    return aNode ?
+      GetCachedAccessibleOrContainer(aNode->GetNodeParent()) : nsnull;
+  }
 
   /**
    * Initialize an accessible and cache it. The method should be called for
    * every created accessible.
    *
    * @param  aAccessible    [in] accessible to initialize.
    * @param  aRoleMapEntry  [in] the role map entry role the ARIA role or nsnull
    *                          if none
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -94,16 +94,17 @@
 #include "nsIURI.h"
 #include "nsArrayUtils.h"
 #include "nsIMutableArray.h"
 #include "nsIObserverService.h"
 #include "nsIServiceManager.h"
 #include "nsWhitespaceTokenizer.h"
 #include "nsAttrName.h"
 #include "nsNetUtil.h"
+#include "nsIEventStateManager.h"
 
 #ifdef NS_DEBUG
 #include "nsIDOMCharacterData.h"
 #endif
 
 #include "mozilla/unused.h"
 
 
@@ -680,34 +681,33 @@ nsAccessible::GetStateInternal(PRUint32 
       *aExtraState = nsIAccessibleStates::EXT_STATE_DEFUNCT;
 
     return NS_OK_DEFUNCT_OBJECT;
   }
 
   if (aExtraState)
     *aExtraState = 0;
 
-  // Set STATE_UNAVAILABLE state based on disabled attribute
-  // The disabled attribute is mostly used in XUL elements and HTML forms, but
-  // if someone sets it on another attribute, 
-  // it seems reasonable to consider it unavailable
-  PRBool isDisabled;
-  if (mContent->IsHTML()) {
-    // In HTML, just the presence of the disabled attribute means it is disabled,
-    // therefore disabled="false" indicates disabled!
-    isDisabled = mContent->HasAttr(kNameSpaceID_None,
-                                   nsAccessibilityAtoms::disabled);
-  }
-  else {
-    isDisabled = mContent->AttrValueIs(kNameSpaceID_None,
-                                       nsAccessibilityAtoms::disabled,
-                                       nsAccessibilityAtoms::_true,
-                                       eCaseMatters);
-  }
-  if (isDisabled) {
+  nsEventStates intrinsicState = mContent->IntrinsicState();
+
+  if (intrinsicState.HasState(NS_EVENT_STATE_INVALID))
+    *aState |= nsIAccessibleStates::STATE_INVALID;
+
+  if (intrinsicState.HasState(NS_EVENT_STATE_REQUIRED))
+    *aState |= nsIAccessibleStates::STATE_REQUIRED;
+
+  PRBool disabled = mContent->IsHTML() ? 
+    (intrinsicState.HasState(NS_EVENT_STATE_DISABLED)) :
+    (mContent->AttrValueIs(kNameSpaceID_None,
+                           nsAccessibilityAtoms::disabled,
+                           nsAccessibilityAtoms::_true,
+                           eCaseMatters));
+
+  // Set unavailable state based on disabled state, otherwise set focus states
+  if (disabled) {
     *aState |= nsIAccessibleStates::STATE_UNAVAILABLE;
   }
   else if (mContent->IsElement()) {
     nsIFrame *frame = GetFrame();
     if (frame && frame->IsFocusable()) {
       *aState |= nsIAccessibleStates::STATE_FOCUSABLE;
     }
 
@@ -980,49 +980,59 @@ void nsAccessible::GetBoundsRect(nsRect&
     iterContent = nsnull;
     if (depth == 0)
       iterContent = iterFrame->GetContent();
   }
 }
 
 
 /* void getBounds (out long x, out long y, out long width, out long height); */
-NS_IMETHODIMP nsAccessible::GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height)
+NS_IMETHODIMP
+nsAccessible::GetBounds(PRInt32* aX, PRInt32* aY,
+                        PRInt32* aWidth, PRInt32* aHeight)
 {
-  // This routine will get the entire rectange for all the frames in this node
+  NS_ENSURE_ARG_POINTER(aX);
+  *aX = 0;
+  NS_ENSURE_ARG_POINTER(aY);
+  *aY = 0;
+  NS_ENSURE_ARG_POINTER(aWidth);
+  *aWidth = 0;
+  NS_ENSURE_ARG_POINTER(aHeight);
+  *aHeight = 0;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  // Flush layout so that all the frame construction, reflow, and styles are
+  // up-to-date since we rely on frames, and styles when calculating state.
+  // We don't flush the display because we don't care about painting.
+  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
+  presShell->FlushPendingNotifications(Flush_Layout);
+
+  // This routine will get the entire rectangle for all the frames in this node.
   // -------------------------------------------------------------------------
   //      Primary Frame for node
   //  Another frame, same node                <- Example
   //  Another frame, same node
 
-  nsPresContext *presContext = GetPresContext();
-  if (!presContext)
-  {
-    *x = *y = *width = *height = 0;
-    return NS_ERROR_FAILURE;
-  }
-
   nsRect unionRectTwips;
-  nsIFrame* aBoundingFrame = nsnull;
-  GetBoundsRect(unionRectTwips, &aBoundingFrame);   // Unions up all primary frames for this node and all siblings after it
-  if (!aBoundingFrame) {
-    *x = *y = *width = *height = 0;
-    return NS_ERROR_FAILURE;
-  }
-
-  *x      = presContext->AppUnitsToDevPixels(unionRectTwips.x); 
-  *y      = presContext->AppUnitsToDevPixels(unionRectTwips.y);
-  *width  = presContext->AppUnitsToDevPixels(unionRectTwips.width);
-  *height = presContext->AppUnitsToDevPixels(unionRectTwips.height);
+  nsIFrame* boundingFrame = nsnull;
+  GetBoundsRect(unionRectTwips, &boundingFrame);   // Unions up all primary frames for this node and all siblings after it
+  NS_ENSURE_STATE(boundingFrame);
+
+  nsPresContext* presContext = presShell->GetPresContext();
+  *aX = presContext->AppUnitsToDevPixels(unionRectTwips.x);
+  *aY = presContext->AppUnitsToDevPixels(unionRectTwips.y);
+  *aWidth = presContext->AppUnitsToDevPixels(unionRectTwips.width);
+  *aHeight = presContext->AppUnitsToDevPixels(unionRectTwips.height);
 
   // We have the union of the rectangle, now we need to put it in absolute screen coords
-
-  nsIntRect orgRectPixels = aBoundingFrame->GetScreenRectExternal();
-  *x += orgRectPixels.x;
-  *y += orgRectPixels.y;
+  nsIntRect orgRectPixels = boundingFrame->GetScreenRectExternal();
+  *aX += orgRectPixels.x;
+  *aY += orgRectPixels.y;
 
   return NS_OK;
 }
 
 // helpers
 
 nsIFrame* nsAccessible::GetBoundsFrame()
 {
@@ -2614,38 +2624,31 @@ nsAccessible::AppendTextTo(nsAString& aT
 // nsAccessNode public methods
 
 PRBool
 nsAccessible::Init()
 {
   if (!nsAccessNodeWrap::Init())
     return PR_FALSE;
 
-  nsDocAccessible *docAcc =
+  nsDocAccessible* document =
     GetAccService()->GetDocAccessible(mContent->GetOwnerDoc());
-  NS_ASSERTION(docAcc, "Cannot cache new nsAccessible!");
-  if (!docAcc)
-    return PR_FALSE;
-
-  void *uniqueID = nsnull;
-  GetUniqueID(&uniqueID);
-
-  return docAcc->CacheAccessible(uniqueID, this);
+  NS_ASSERTION(document, "Cannot cache new nsAccessible!");
+
+  return document ? document->CacheAccessible(this) : PR_FALSE;
 }
 
 void
 nsAccessible::Shutdown()
 {
   // Invalidate the child count and pointers to other accessibles, also make
   // sure none of its children point to this parent
   InvalidateChildren();
-  if (mParent) {
-    mParent->InvalidateChildren();
-    UnbindFromParent();
-  }
+  if (mParent)
+    mParent->RemoveChild(this);
 
   nsAccessNodeWrap::Shutdown();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessible public methods
 
 nsresult
@@ -2684,24 +2687,24 @@ nsAccessible::GetNameInternal(nsAString&
 }
 
 // nsAccessible protected
 void
 nsAccessible::BindToParent(nsAccessible* aParent, PRUint32 aIndexInParent)
 {
   NS_PRECONDITION(aParent, "This method isn't used to set null parent!");
 
-  if (mParent && mParent != aParent) {
-    // Adopt a child -- we allow this now. the new parent
-    // may be a dom node which wasn't previously accessible but now is.
-    // The old parent's children now need to be invalidated, since 
-    // it no longer owns the child, the new parent does
-    NS_ASSERTION(PR_FALSE, "Adopting child!");
-    if (mParent)
+  if (mParent) {
+    if (mParent != aParent) {
+      NS_ERROR("Adopting child!");
       mParent->InvalidateChildren();
+    } else {
+      NS_ERROR("Binding to the same parent!");
+      return;
+    }
   }
 
   mParent = aParent;
   mIndexInParent = aIndexInParent;
 }
 
 void
 nsAccessible::UnbindFromParent()
@@ -2727,17 +2730,17 @@ nsAccessible::InvalidateChildren()
 }
 
 PRBool
 nsAccessible::AppendChild(nsAccessible* aChild)
 {
   if (!mChildren.AppendElement(aChild))
     return PR_FALSE;
 
-  if (nsAccUtils::IsText(aChild))
+  if (!nsAccUtils::IsEmbeddedObject(aChild))
     mChildrenFlags = eMixedChildren;
 
   aChild->BindToParent(this, mChildren.Length() - 1);
   return PR_TRUE;
 }
 
 PRBool
 nsAccessible::InsertChildAt(PRUint32 aIndex, nsAccessible* aChild)
@@ -2892,23 +2895,20 @@ nsAccessible::GetIndexOfEmbeddedChild(ns
 }
 
 #ifdef DEBUG
 PRBool
 nsAccessible::IsInCache()
 {
   nsDocAccessible *docAccessible =
     GetAccService()->GetDocAccessible(mContent->GetOwnerDoc());
-  if (!docAccessible)
-    return nsnull;
-
-  void *uniqueID = nsnull;
-  GetUniqueID(&uniqueID);
-
-  return docAccessible->GetCachedAccessible(uniqueID) ? PR_TRUE : PR_FALSE;
+  if (docAccessible)
+    return docAccessible->GetCachedAccessibleByUniqueID(UniqueID()) ? PR_TRUE : PR_FALSE;
+
+  return PR_FALSE;
 }
 #endif
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // HyperLinkAccessible methods
 
 bool
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -46,31 +46,34 @@
 #include "nsIAccessibleSelectable.h"
 #include "nsIAccessibleValue.h"
 #include "nsIAccessibleRole.h"
 #include "nsIAccessibleStates.h"
 
 #include "nsStringGlue.h"
 #include "nsTArray.h"
 #include "nsRefPtrHashtable.h"
+#include "nsDataHashtable.h"
 
 class AccGroupInfo;
 class EmbeddedObjCollector;
 class nsAccessible;
 class AccEvent;
 struct nsRoleMapEntry;
 
 struct nsRect;
 class nsIContent;
 class nsIFrame;
 class nsIAtom;
 class nsIView;
 
 typedef nsRefPtrHashtable<nsVoidPtrHashKey, nsAccessible>
   nsAccessibleHashtable;
+typedef nsDataHashtable<nsPtrHashKey<const nsINode>, nsAccessible*>
+  NodeToAccessibleMap;
 
 // see nsAccessible::GetAttrValue
 #define NS_OK_NO_ARIA_VALUE \
 NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_GENERAL, 0x21)
 
 // see nsAccessible::GetNameInternal
 #define NS_OK_EMPTY_NAME \
 NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_GENERAL, 0x23)
@@ -201,16 +204,17 @@ public:
   /**
    * Set the ARIA role map entry for a new accessible.
    * For a newly created accessible, specify which role map entry should be used.
    *
    * @param aRoleMapEntry The ARIA nsRoleMapEntry* for the accessible, or 
    *                      nsnull if none.
    */
   virtual void SetRoleMapEntry(nsRoleMapEntry *aRoleMapEntry);
+  const nsRoleMapEntry* GetRoleMapEntry() const { return mRoleMapEntry; }
 
   /**
    * Cache children if necessary. Return true if the accessible is defunct.
    */
   PRBool EnsureChildren();
 
   /**
    * Set the child count to -1 (unknown) and null out cached child pointers.
@@ -285,17 +289,19 @@ public:
       mParent->mChildren.SafeElementAt(mIndexInParent + 1, nsnull).get() : nsnull;
   }
   nsAccessible* GetCachedPrevSibling() const
   {
     return mParent ?
       mParent->mChildren.SafeElementAt(mIndexInParent - 1, nsnull).get() : nsnull;
   }
   PRUint32 GetCachedChildCount() const { return mChildren.Length(); }
+  nsAccessible* GetCachedChildAt(PRUint32 aIndex) const { return mChildren.ElementAt(aIndex); }
   PRBool AreChildrenCached() const { return mChildrenFlags != eChildrenUninitialized; }
+  bool IsBoundToParent() const { return mParent; }
 
 #ifdef DEBUG
   /**
    * Return true if the access node is cached.
    */
   PRBool IsInCache();
 #endif
 
--- a/accessible/src/base/nsApplicationAccessible.cpp
+++ b/accessible/src/base/nsApplicationAccessible.cpp
@@ -358,16 +358,22 @@ nsApplicationAccessible::Init()
 }
 
 void
 nsApplicationAccessible::Shutdown()
 {
   mAppInfo = nsnull;
 }
 
+bool
+nsApplicationAccessible::IsPrimaryForNode() const
+{
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessible public methods
 
 nsresult
 nsApplicationAccessible::GetARIAState(PRUint32 *aState, PRUint32 *aExtraState)
 {
   return NS_OK;
 }
@@ -465,17 +471,17 @@ nsApplicationAccessible::GetSiblingAtOff
 
   if (aError)
     *aError = NS_OK; // fail peacefully
 
   return nsnull;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsIAccessNode
+// nsIAccessNode and nsAccessNode
 
 NS_IMETHODIMP
 nsApplicationAccessible::GetDOMNode(nsIDOMNode **aDOMNode)
 {
   NS_ENSURE_ARG_POINTER(aDOMNode);
   *aDOMNode = nsnull;
   return NS_OK;
 }
@@ -520,24 +526,16 @@ NS_IMETHODIMP
 nsApplicationAccessible::GetOwnerWindow(void **aOwnerWindow)
 {
   NS_ENSURE_ARG_POINTER(aOwnerWindow);
   *aOwnerWindow = nsnull;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsApplicationAccessible::GetUniqueID(void **aUniqueID)
-{
-  NS_ENSURE_ARG_POINTER(aUniqueID);
-  *aUniqueID = static_cast<void *>(this);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsApplicationAccessible::GetComputedStyleValue(const nsAString &aPseudoElt,
                                                const nsAString &aPropertyName,
                                                nsAString &aValue)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -551,8 +549,9 @@ nsApplicationAccessible::GetComputedStyl
 }
 
 NS_IMETHODIMP
 nsApplicationAccessible::GetLanguage(nsAString &aLanguage)
 {
   aLanguage.Truncate();
   return NS_OK;
 }
+
--- a/accessible/src/base/nsApplicationAccessible.h
+++ b/accessible/src/base/nsApplicationAccessible.h
@@ -66,17 +66,30 @@ public:
   using nsAccessible::GetChildAtPoint;
 
   nsApplicationAccessible();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessNode
-  NS_DECL_NSIACCESSNODE
+  NS_SCRIPTABLE NS_IMETHOD GetDOMNode(nsIDOMNode** aDOMNode);
+  NS_SCRIPTABLE NS_IMETHOD GetDocument(nsIAccessibleDocument** aDocument);
+  NS_SCRIPTABLE NS_IMETHOD GetRootDocument(nsIAccessibleDocument** aRootDocument);
+  NS_SCRIPTABLE NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML);
+  NS_SCRIPTABLE NS_IMETHOD ScrollTo(PRUint32 aScrollType);
+  NS_SCRIPTABLE NS_IMETHOD ScrollToPoint(PRUint32 aCoordinateType, PRInt32 aX, PRInt32 aY);
+  NS_IMETHOD GetOwnerWindow(void **aOwnerWindow);
+  NS_SCRIPTABLE NS_IMETHOD GetComputedStyleValue(const nsAString& aPseudoElt,
+                                                 const nsAString& aPropertyName,
+                                                 nsAString& aValue NS_OUTPARAM);
+  NS_SCRIPTABLE NS_IMETHOD GetComputedStyleCSSValue(const nsAString& aPseudoElt,
+                                                    const nsAString& aPropertyName,
+                                                    nsIDOMCSSPrimitiveValue** aValue NS_OUTPARAM);
+  NS_SCRIPTABLE NS_IMETHOD GetLanguage(nsAString& aLanguage);
 
   // nsIAccessible
   NS_IMETHOD GetParent(nsIAccessible **aParent);
   NS_IMETHOD GetNextSibling(nsIAccessible **aNextSibling);
   NS_IMETHOD GetPreviousSibling(nsIAccessible **aPreviousSibling);
   NS_IMETHOD GetName(nsAString &aName);
   NS_IMETHOD GetValue(nsAString &aValue);
   NS_IMETHOD GetDescription(nsAString &aDescription);
@@ -104,16 +117,17 @@ public:
 
   // nsIAccessibleApplication
   NS_DECL_NSIACCESSIBLEAPPLICATION
 
   // nsAccessNode
   virtual PRBool IsDefunct();
   virtual PRBool Init();
   virtual void Shutdown();
+  virtual bool IsPrimaryForNode() const;
 
   // nsAccessible
   virtual nsresult GetARIAState(PRUint32 *aState, PRUint32 *aExtraState);
   virtual PRUint32 Role();
   virtual PRUint32 NativeRole();
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
 
   virtual void InvalidateChildren();
--- a/accessible/src/base/nsCaretAccessible.cpp
+++ b/accessible/src/base/nsCaretAccessible.cpp
@@ -280,18 +280,17 @@ nsCaretAccessible::SpellcheckSelectionCh
   // misspelled word). If spellchecking is disabled (for example,
   // @spellcheck="false" on html:body) then we won't fire any event.
 
   nsRefPtr<nsHyperTextAccessible> textAcc =
     nsAccUtils::GetTextAccessibleFromSelection(aSel);
   NS_ENSURE_STATE(textAcc);
 
   nsRefPtr<AccEvent> event =
-    new AccEvent(nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED,
-                 textAcc, nsnull);
+    new AccEvent(nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED, textAcc);
 
   nsEventShell::FireEvent(event);
   return NS_OK;
 }
 
 nsIntRect
 nsCaretAccessible::GetCaretRect(nsIWidget **aOutWidget)
 {
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -79,30 +79,30 @@
 #endif
 
 namespace dom = mozilla::dom;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Static member initialization
 
 PRUint32 nsDocAccessible::gLastFocusedAccessiblesState = 0;
-nsIAtom *nsDocAccessible::gLastFocusedFrameType = nsnull;
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // Constructor/desctructor
 
 nsDocAccessible::
   nsDocAccessible(nsIDocument *aDocument, nsIContent *aRootContent,
                   nsIWeakReference *aShell) :
   nsHyperTextAccessibleWrap(aRootContent, aShell),
   mDocument(aDocument), mScrollPositionChangedTicks(0), mIsLoaded(PR_FALSE)
 {
   // XXX aaronl should we use an algorithm for the initial cache size?
   mAccessibleCache.Init(kDefaultCacheSize);
+  mNodeToAccessibleMap.Init(kDefaultCacheSize);
 
   // For GTK+ native window, we do nothing here.
   if (!mDocument)
     return;
 
   // nsAccDocManager creates document accessible when scrollable frame is
   // available already, it should be safe time to add scroll listener.
   AddScrollListener();
@@ -129,16 +129,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   }
 
   CycleCollectorTraverseCache(tmp->mAccessibleCache, &cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDocAccessible, nsAccessible)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mEventQueue)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSTARRAY(mChildDocuments)
+  tmp->mNodeToAccessibleMap.Clear();
   ClearCache(tmp->mAccessibleCache);
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDocAccessible)
   NS_INTERFACE_MAP_STATIC_AMBIGUOUS(nsDocAccessible)
   NS_INTERFACE_MAP_ENTRY(nsIAccessibleDocument)
   NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
   NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
@@ -563,26 +564,24 @@ NS_IMETHODIMP nsDocAccessible::GetAssoci
   if (isEditable) {
     NS_ADDREF(*aEditor = editor);
   }
   return NS_OK;
 }
 
 // nsDocAccessible public method
 nsAccessible *
-nsDocAccessible::GetCachedAccessible(void *aUniqueID)
+nsDocAccessible::GetCachedAccessible(nsINode *aNode)
 {
-  nsAccessible* accessible = mAccessibleCache.GetWeak(aUniqueID);
+  nsAccessible* accessible = mNodeToAccessibleMap.Get(aNode);
 
   // No accessible in the cache, check if the given ID is unique ID of this
   // document accessible.
   if (!accessible) {
-    void* thisUniqueID = nsnull;
-    GetUniqueID(&thisUniqueID);
-    if (thisUniqueID != aUniqueID)
+    if (GetNode() != aNode)
       return nsnull;
 
     accessible = this;
   }
 
 #ifdef DEBUG
   // All cached accessible nodes should be in the parent
   // It will assert if not all the children were created
@@ -593,39 +592,36 @@ nsDocAccessible::GetCachedAccessible(voi
     parent->TestChildCache(accessible);
 #endif
 
   return accessible;
 }
 
 // nsDocAccessible public method
 PRBool
-nsDocAccessible::CacheAccessible(void *aUniqueID, nsAccessible *aAccessible)
+nsDocAccessible::CacheAccessible(nsAccessible* aAccessible)
 {
-  // If there is already an accessible with the given unique ID, shut it down
-  // because the DOM node has changed.
-  nsAccessible *accessible = mAccessibleCache.GetWeak(aUniqueID);
-  NS_ASSERTION(!accessible,
-               "Caching new accessible for the DOM node while the old one is alive");
+  if (aAccessible->IsPrimaryForNode() &&
+      !mNodeToAccessibleMap.Put(aAccessible->GetNode(), aAccessible))
+    return PR_FALSE;
 
-  if (accessible)
-    accessible->Shutdown();
-
-  return mAccessibleCache.Put(aUniqueID, aAccessible);
+  return mAccessibleCache.Put(aAccessible->UniqueID(), aAccessible);
 }
 
 // nsDocAccessible public method
 void
-nsDocAccessible::RemoveAccessNodeFromCache(nsAccessible *aAccessible)
+nsDocAccessible::ShutdownAccessible(nsAccessible *aAccessible)
 {
-  if (!aAccessible)
-    return;
+  // Remove an accessible from node to accessible map if it is presented there.
+  if (aAccessible->IsPrimaryForNode() &&
+      mNodeToAccessibleMap.Get(aAccessible->GetNode()) == aAccessible)
+    mNodeToAccessibleMap.Remove(aAccessible->GetNode());
 
-  void *uniqueID = nsnull;
-  aAccessible->GetUniqueID(&uniqueID);
+  void* uniqueID = aAccessible->UniqueID();
+  aAccessible->Shutdown();
   mAccessibleCache.Remove(uniqueID);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessNode
 
 PRBool
 nsDocAccessible::Init()
@@ -641,22 +637,24 @@ nsDocAccessible::Init()
 
   nsDocAccessible* parentDocument = mParent->GetDocAccessible();
   if (parentDocument)
     parentDocument->AppendChildDocument(this);
 
   // Fire reorder event to notify new accessible document has been created and
   // attached to the tree.
   nsRefPtr<AccEvent> reorderEvent =
-    new AccReorderEvent(mParent, PR_FALSE, PR_TRUE, mDocument);
-  if (!reorderEvent)
-    return PR_FALSE;
+    new AccEvent(nsIAccessibleEvent::EVENT_REORDER, mParent, eAutoDetect,
+                 AccEvent::eCoalesceFromSameSubtree);
+  if (reorderEvent) {
+    FireDelayedAccessibleEvent(reorderEvent);
+    return PR_TRUE;
+  }
 
-  FireDelayedAccessibleEvent(reorderEvent);
-  return PR_TRUE;
+  return PR_FALSE;
 }
 
 void
 nsDocAccessible::Shutdown()
 {
   if (!mWeakShell) // already shutdown
     return;
 
@@ -676,16 +674,17 @@ nsDocAccessible::Shutdown()
 
     mParent->RemoveChild(this);
   }
 
   mChildDocuments.Clear();
 
   mWeakShell = nsnull;  // Avoid reentrancy
 
+  mNodeToAccessibleMap.Clear();
   ClearCache(mAccessibleCache);
 
   nsCOMPtr<nsIDocument> kungFuDeathGripDoc = mDocument;
   mDocument = nsnull;
 
   nsHyperTextAccessibleWrap::Shutdown();
 }
 
@@ -1039,18 +1038,17 @@ nsDocAccessible::AttributeChangedImpl(ns
   }
 
   if (aAttribute == nsAccessibilityAtoms::role ||
       aAttribute == nsAccessibilityAtoms::href ||
       aAttribute == nsAccessibilityAtoms::onclick) {
     // Not worth the expense to ensure which namespace these are in
     // It doesn't kill use to recreate the accessible even if the attribute was used
     // in the wrong namespace or an element that doesn't support it
-    InvalidateCacheSubtree(aContent,
-                           nsIAccessibilityService::NODE_SIGNIFICANT_CHANGE);
+    RecreateAccessible(aContent);
     return;
   }
   
   if (aAttribute == nsAccessibilityAtoms::alt ||
       aAttribute == nsAccessibilityAtoms::title ||
       aAttribute == nsAccessibilityAtoms::aria_label ||
       aAttribute == nsAccessibilityAtoms::aria_labelledby) {
     FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE,
@@ -1213,59 +1211,43 @@ nsDocAccessible::ARIAAttributeChanged(ns
     return;
   }
 
   if (aAttribute == nsAccessibilityAtoms::aria_multiselectable &&
       aContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::role)) {
     // This affects whether the accessible supports SelectAccessible.
     // COM says we cannot change what interfaces are supported on-the-fly,
     // so invalidate this object. A new one will be created on demand.
-    InvalidateCacheSubtree(aContent,
-                           nsIAccessibilityService::NODE_SIGNIFICANT_CHANGE);
+    RecreateAccessible(aContent);
     return;
   }
 }
 
 void nsDocAccessible::ContentAppended(nsIDocument *aDocument,
                                       nsIContent* aContainer,
                                       nsIContent* aFirstNewContent,
                                       PRInt32 /* unused */)
 {
-  if (!IsContentLoaded() && mAccessibleCache.Count() <= 1) {
-    // See comments in nsDocAccessible::InvalidateCacheSubtree
-    InvalidateChildren();
-    return;
-  }
-
-  // Does this need to be a strong ref?  If so, why?
-  for (nsIContent* cur = aFirstNewContent; cur; cur = cur->GetNextSibling()) {
-    // InvalidateCacheSubtree will not fire the EVENT_SHOW for the new node
-    // unless an accessible can be created for the passed in node, which it
-    // can't do unless the node is visible. The right thing happens there so
-    // no need for an extra visibility check here.
-    InvalidateCacheSubtree(cur, nsIAccessibilityService::NODE_APPEND);
-  }
 }
 
-
 void nsDocAccessible::ContentStatesChanged(nsIDocument* aDocument,
                                            nsIContent* aContent1,
                                            nsIContent* aContent2,
-                                           PRInt32 aStateMask)
+                                           nsEventStates aStateMask)
 {
-  if (0 == (aStateMask & NS_EVENT_STATE_CHECKED)) {
+  if (!aStateMask.HasState(NS_EVENT_STATE_CHECKED)) {
     return;
   }
 
   nsHTMLSelectOptionAccessible::SelectionChangedIfOption(aContent1);
   nsHTMLSelectOptionAccessible::SelectionChangedIfOption(aContent2);
 }
 
 void nsDocAccessible::DocumentStatesChanged(nsIDocument* aDocument,
-                                            PRInt32 aStateMask)
+                                            nsEventStates aStateMask)
 {
 }
 
 void nsDocAccessible::CharacterDataWillChange(nsIDocument *aDocument,
                                               nsIContent* aContent,
                                               CharacterDataChangeInfo* aInfo)
 {
   FireTextChangeEventForText(aContent, aInfo, PR_FALSE);
@@ -1277,34 +1259,23 @@ void nsDocAccessible::CharacterDataChang
 {
   FireTextChangeEventForText(aContent, aInfo, PR_TRUE);
 }
 
 void
 nsDocAccessible::ContentInserted(nsIDocument *aDocument, nsIContent* aContainer,
                                  nsIContent* aChild, PRInt32 /* unused */)
 {
-  // InvalidateCacheSubtree will not fire the EVENT_SHOW for the new node
-  // unless an accessible can be created for the passed in node, which it
-  // can't do unless the node is visible. The right thing happens there so
-  // no need for an extra visibility check here.
-  InvalidateCacheSubtree(aChild, nsIAccessibilityService::NODE_APPEND);
 }
 
 void
 nsDocAccessible::ContentRemoved(nsIDocument *aDocument, nsIContent* aContainer,
                                 nsIContent* aChild, PRInt32 /* unused */,
                                 nsIContent* aPreviousSibling)
 {
-  // It's no needed to invalidate the subtree of the removed element,
-  // because we get notifications directly from content (see
-  // nsGenericElement::doRemoveChildAt) *before* the frame for the content is
-  // destroyed, or any other side effects occur . That allows us to correctly
-  // calculate the TEXT_REMOVED event if there is one and coalesce events from
-  // the same subtree.
 }
 
 void
 nsDocAccessible::ParentChainChanged(nsIContent *aContent)
 {
 }
 
 
@@ -1335,46 +1306,190 @@ nsDocAccessible::GetNativeWindow() const
     vm->GetRootWidget(getter_AddRefs(widget));
     if (widget)
       return widget->GetNativeData(NS_NATIVE_WINDOW);
   }
   return nsnull;
 }
 
 nsAccessible*
-nsDocAccessible::GetCachedAccessibleInSubtree(void* aUniqueID)
+nsDocAccessible::GetCachedAccessibleByUniqueIDInSubtree(void* aUniqueID)
 {
-  nsAccessible* child = GetCachedAccessible(aUniqueID);
+  nsAccessible* child = GetCachedAccessibleByUniqueID(aUniqueID);
   if (child)
     return child;
 
   PRUint32 childDocCount = mChildDocuments.Length();
   for (PRUint32 childDocIdx= 0; childDocIdx < childDocCount; childDocIdx++) {
     nsDocAccessible* childDocument = mChildDocuments.ElementAt(childDocIdx);
-    child = childDocument->GetCachedAccessibleInSubtree(aUniqueID);
+    child = childDocument->GetCachedAccessibleByUniqueIDInSubtree(aUniqueID);
     if (child)
       return child;
   }
 
   return nsnull;
 }
 
+void
+nsDocAccessible::UpdateTree(nsIContent* aContainerNode,
+                            nsIContent* aStartNode,
+                            nsIContent* aEndNode,
+                            PRBool aIsInsert)
+{
+  // Content change notification mostly are async, thus we can't detect whether
+  // these actions are from user. This information is used to fire or do not
+  // fire events to avoid events that are generated because of document loading.
+  // Since this information may be not correct then we need to fire some events
+  // regardless the document loading state.
+
+  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
+  nsIEventStateManager* esm = presShell->GetPresContext()->EventStateManager();
+  PRBool fireAllEvents = PR_TRUE;//IsContentLoaded() || esm->IsHandlingUserInputExternal();
+
+  // We don't create new accessibles on content removal.
+  nsAccessible* container = aIsInsert ?
+    GetAccService()->GetAccessibleOrContainer(aContainerNode, mWeakShell) :
+    GetAccService()->GetCachedAccessibleOrContainer(aContainerNode);
+
+  if (aIsInsert) {
+    // XXX: Invalidate parent-child relations for container accessible and its
+    // children because there's no good way to find insertion point of new child
+    // accessibles into accessible tree. We need to invalidate children even
+    // there's no inserted accessibles in the end because accessible children
+    // are created while parent recaches child accessibles.
+    container->InvalidateChildren();
+  }
+
+  EIsFromUserInput fromUserInput = esm->IsHandlingUserInputExternal() ?
+    eFromUserInput : eNoUserInput;
+
+  // Update the accessible tree in the case of content removal and fire events
+  // if allowed.
+  PRUint32 updateFlags =
+    UpdateTreeInternal(container, aStartNode, aEndNode,
+                       aIsInsert, fireAllEvents, fromUserInput);
+
+  // Content insertion/removal is not cause of accessible tree change.
+  if (updateFlags == eNoAccessible)
+    return;
+
+  // Check to see if change occurred inside an alert, and fire an EVENT_ALERT
+  // if it did.
+  if (aIsInsert && !(updateFlags & eAlertAccessible)) {
+    // XXX: tree traversal is perf issue, accessible should know if they are
+    // children of alert accessible to avoid this.
+    nsAccessible* ancestor = container;
+    while (ancestor) {
+      const nsRoleMapEntry* roleMapEntry = ancestor->GetRoleMapEntry();
+      if (roleMapEntry && roleMapEntry->role == nsIAccessibleRole::ROLE_ALERT) {
+        FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_ALERT,
+                                   ancestor->GetNode(), AccEvent::eRemoveDupes,
+                                   fromUserInput);
+        break;
+      }
+
+      // Don't climb above this document.
+      if (ancestor == this)
+        break;
+
+      ancestor = ancestor->GetParent();
+    }
+  }
+
+  // Fire nether value change nor reorder events if action is not from user
+  // input and document is loading. We are notified about changes in editor
+  // synchronously, so from user input flag is correct for value change events.
+  if (!fireAllEvents)
+    return;
+
+  // Fire value change event.
+  if (container->Role() == nsIAccessibleRole::ROLE_ENTRY) {
+    nsRefPtr<AccEvent> valueChangeEvent =
+      new AccEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, container,
+                   fromUserInput, AccEvent::eRemoveDupes);
+    FireDelayedAccessibleEvent(valueChangeEvent);
+  }
+
+  // Fire reorder event so the MSAA clients know the children have changed. Also
+  // the event is used internally by MSAA part.
+  nsRefPtr<AccEvent> reorderEvent =
+    new AccEvent(nsIAccessibleEvent::EVENT_REORDER, container->GetNode(),
+                 fromUserInput, AccEvent::eCoalesceFromSameSubtree);
+  if (reorderEvent)
+    FireDelayedAccessibleEvent(reorderEvent);
+}
+
+void
+nsDocAccessible::RecreateAccessible(nsINode* aNode)
+{
+  // XXX: we shouldn't recreate whole accessible subtree that happens when
+  // hide event is handled, instead we should subclass hide and show events
+  // to handle them separately and implement their coalescence with normal hide
+  // and show events.
+
+  nsAccessible* parent = nsnull;
+
+  // Fire hide event for old accessible.
+  nsAccessible* oldAccessible =
+    GetAccService()->GetAccessibleInWeakShell(aNode, mWeakShell);
+  if (oldAccessible) {
+    parent = oldAccessible->GetParent();
+
+    nsRefPtr<AccEvent> hideEvent = new AccHideEvent(oldAccessible, aNode,
+                                                    eAutoDetect);
+    if (hideEvent)
+      FireDelayedAccessibleEvent(hideEvent);
+
+    // Unbind old accessible from tree.
+    parent->RemoveChild(oldAccessible);
+
+    if (oldAccessible->IsPrimaryForNode() &&
+        mNodeToAccessibleMap.Get(oldAccessible->GetNode()) == oldAccessible)
+      mNodeToAccessibleMap.Remove(oldAccessible->GetNode());
+
+  } else {
+    parent = GetAccService()->GetContainerAccessible(aNode, mWeakShell);
+  }
+
+  // Get new accessible and fire show event.
+  parent->InvalidateChildren();
+
+  nsAccessible* newAccessible =
+    GetAccService()->GetAccessibleInWeakShell(aNode, mWeakShell);
+  if (newAccessible) {
+    nsRefPtr<AccEvent> showEvent = new AccShowEvent(newAccessible, aNode,
+                                                    eAutoDetect);
+    if (showEvent)
+      FireDelayedAccessibleEvent(showEvent);
+  }
+
+  // Fire reorder event.
+  if (oldAccessible || newAccessible) {
+    nsRefPtr<AccEvent> reorderEvent =
+      new AccEvent(nsIAccessibleEvent::EVENT_REORDER, parent->GetNode(),
+                   eAutoDetect, AccEvent::eCoalesceFromSameSubtree);
+
+    if (reorderEvent)
+      FireDelayedAccessibleEvent(reorderEvent);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Protected members
 
 void
 nsDocAccessible::FireValueChangeForTextFields(nsAccessible *aAccessible)
 {
   if (aAccessible->Role() != nsIAccessibleRole::ROLE_ENTRY)
     return;
 
   // Dependent value change event for text changes in textfields
   nsRefPtr<AccEvent> valueChangeEvent =
     new AccEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, aAccessible,
-                 PR_FALSE, eAutoDetect, AccEvent::eRemoveDupes);
+                 eAutoDetect, AccEvent::eRemoveDupes);
   FireDelayedAccessibleEvent(valueChangeEvent);
 }
 
 void
 nsDocAccessible::FireTextChangeEventForText(nsIContent *aContent,
                                             CharacterDataChangeInfo* aInfo,
                                             PRBool aIsInserted)
 {
@@ -1421,106 +1536,30 @@ nsDocAccessible::FireTextChangeEventForT
   if (text.IsEmpty())
     return;
 
   // Normally we only fire delayed events created from the node, not an
   // accessible object. See the AccTextChangeEvent constructor for details
   // about this exceptional case.
   nsRefPtr<AccEvent> event =
     new AccTextChangeEvent(textAccessible, offset + textOffset, text,
-                           aIsInserted, PR_FALSE);
+                          aIsInserted);
   FireDelayedAccessibleEvent(event);
 
   FireValueChangeForTextFields(textAccessible);
 }
 
-already_AddRefed<AccEvent>
-nsDocAccessible::CreateTextChangeEventForNode(nsAccessible *aContainerAccessible,
-                                              nsIContent *aChangeNode,
-                                              nsAccessible *aChangeChild,
-                                              PRBool aIsInserting,
-                                              PRBool aIsAsynch,
-                                              EIsFromUserInput aIsFromUserInput)
-{
-  nsRefPtr<nsHyperTextAccessible> textAccessible =
-    do_QueryObject(aContainerAccessible);
-  if (!textAccessible) {
-    return nsnull;
-  }
-
-  nsAutoString text;
-  PRInt32 offset = 0;
-  if (aChangeChild) {
-    // Don't fire event for the first html:br in an editor.
-    if (aChangeChild->Role() == nsIAccessibleRole::ROLE_WHITESPACE) {
-      nsCOMPtr<nsIEditor> editor;
-      textAccessible->GetAssociatedEditor(getter_AddRefs(editor));
-      if (editor) {
-        PRBool isEmpty = PR_FALSE;
-        editor->GetDocumentIsEmpty(&isEmpty);
-        if (isEmpty) {
-          return nsnull;
-        }
-      }
-    }
-
-    offset = textAccessible->GetChildOffset(aChangeChild);
-    aChangeChild->AppendTextTo(text, 0, PR_UINT32_MAX);
-
-  } else {
-    // A span-level object or something else without an accessible is being
-    // added, where it has no accessible but it has descendant content which is
-    // aggregated as text into the parent hypertext. In this case, changed text
-    // is compounded from all accessible contained in changed node.
-    nsAccTreeWalker walker(mWeakShell, aChangeNode,
-                           GetAllowsAnonChildAccessibles());
-    nsRefPtr<nsAccessible> child = walker.GetNextChild();
-
-    // No descendant content that represents any text in the hypertext parent.
-    if (!child)
-      return nsnull;
-
-    offset = textAccessible->GetChildOffset(child);
-    child->AppendTextTo(text, 0, PR_UINT32_MAX);
-
-    nsINode* containerNode = textAccessible->GetNode();
-    PRInt32 childCount = textAccessible->GetChildCount();
-    PRInt32 childIdx = child->GetIndexInParent();
-
-    for (PRInt32 idx = childIdx + 1; idx < childCount; idx++) {
-      nsAccessible* nextChild = textAccessible->GetChildAt(idx);
-      // We only want accessibles with DOM nodes as children of this node.
-      if (!nsCoreUtils::IsAncestorOf(aChangeNode, nextChild->GetNode(),
-                                     containerNode))
-        break;
-
-      nextChild->AppendTextTo(text, 0, PR_UINT32_MAX);
-    }
-  }
-
-  if (text.IsEmpty())
-    return nsnull;
-
-  AccEvent* event = new AccTextChangeEvent(aContainerAccessible, offset, text,
-                                           aIsInserting, aIsAsynch,
-                                           aIsFromUserInput);
-  NS_IF_ADDREF(event);
-
-  return event;
-}
-
 // nsDocAccessible public member
 nsresult
 nsDocAccessible::FireDelayedAccessibleEvent(PRUint32 aEventType, nsINode *aNode,
                                             AccEvent::EEventRule aAllowDupes,
-                                            PRBool aIsAsynch,
                                             EIsFromUserInput aIsFromUserInput)
 {
   nsRefPtr<AccEvent> event =
-    new AccEvent(aEventType, aNode, aIsAsynch, aIsFromUserInput, aAllowDupes);
+    new AccEvent(aEventType, aNode, aIsFromUserInput, aAllowDupes);
   NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
 
   return FireDelayedAccessibleEvent(event);
 }
 
 // nsDocAccessible public member
 nsresult
 nsDocAccessible::FireDelayedAccessibleEvent(AccEvent* aEvent)
@@ -1529,509 +1568,174 @@ nsDocAccessible::FireDelayedAccessibleEv
   NS_LOG_ACCDOCLOAD_FIREEVENT(aEvent)
 
   if (mEventQueue)
     mEventQueue->Push(aEvent);
 
   return NS_OK;
 }
 
+// nsDocAccessible public member
 void
 nsDocAccessible::ProcessPendingEvent(AccEvent* aEvent)
-{  
-  nsAccessible *accessible = aEvent->GetAccessible();
-  nsINode *node = aEvent->GetNode();
-
-  PRUint32 eventType = aEvent->GetEventType();
-  EIsFromUserInput isFromUserInput =
-    aEvent->IsFromUserInput() ? eFromUserInput : eNoUserInput;
-
-  PRBool isAsync = aEvent->IsAsync();
-
-  if (node == gLastFocusedNode && isAsync &&
-      (eventType == nsIAccessibleEvent::EVENT_SHOW ||
-       eventType == nsIAccessibleEvent::EVENT_HIDE)) {
-    // If frame type didn't change for this event, then we don't actually need to invalidate
-    // However, we only keep track of the old frame type for the focus, where it's very
-    // important not to destroy and recreate the accessible for minor style changes,
-    // such as a:focus { overflow: scroll; }
-    nsCOMPtr<nsIContent> focusContent(do_QueryInterface(node));
-    if (focusContent) {
-      nsIFrame *focusFrame = focusContent->GetPrimaryFrame();
-      nsIAtom *newFrameType =
-        (focusFrame && focusFrame->GetStyleVisibility()->IsVisible()) ?
-        focusFrame->GetType() : nsnull;
-
-      if (newFrameType == gLastFocusedFrameType) {
-        // Don't need to invalidate this current accessible, but can
-        // just invalidate the children instead
-        FireShowHideEvents(node, PR_TRUE, eventType, eNormalEvent,
-                           isAsync, isFromUserInput);
-        return;
-      }
-      gLastFocusedFrameType = newFrameType;
-    }
-  }
-
-  if (eventType == nsIAccessibleEvent::EVENT_SHOW) {
-
-    nsAccessible* containerAccessible = nsnull;
-    if (accessible) {
-      containerAccessible = accessible->GetParent();
-    } else {
-      nsCOMPtr<nsIWeakReference> weakShell(nsCoreUtils::GetWeakShellFor(node));
-      containerAccessible = GetAccService()->GetContainerAccessible(node,
-                                                                    weakShell);
-    }
-
-    if (!containerAccessible)
-      containerAccessible = this;
-
-    if (isAsync) {
-      // For asynch show, delayed invalidatation of parent's children
-      containerAccessible->InvalidateChildren();
-
-      // Some show events in the subtree may have been removed to 
-      // avoid firing redundant events. But, we still need to make sure any
-      // accessibles parenting those shown nodes lose their child references.
-      InvalidateChildrenInSubtree(node);
-    }
-
-    // Also fire text changes if the node being created could affect the text in an nsIAccessibleText parent.
-    // When a node is being made visible or is inserted, the text in an ancestor hyper text will gain characters
-    // At this point we now have the frame and accessible for this node if there is one. That is why we
-    // wait to fire this here, instead of in InvalidateCacheSubtree(), where we wouldn't be able to calculate
-    // the offset, length and text for the text change.
-    if (node && node != mDocument) {
-      nsCOMPtr<nsIContent> content(do_QueryInterface(node));
-      nsRefPtr<AccEvent> textChangeEvent =
-        CreateTextChangeEventForNode(containerAccessible, content, accessible,
-                                     PR_TRUE, PR_TRUE, isFromUserInput);
-      if (textChangeEvent) {
-        // XXX Queue them up and merge the text change events
-        // XXX We need a way to ignore SplitNode and JoinNode() when they
-        // do not affect the text within the hypertext
-        nsEventShell::FireEvent(textChangeEvent);
-      }
-    }
-
-    // Fire show/create events for this node or first accessible descendants of it
-    FireShowHideEvents(node, PR_FALSE, eventType, eNormalEvent, isAsync,
-                       isFromUserInput); 
-    return;
-  }
-
-  if (accessible) {
-    if (eventType == nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED) {
-      nsCOMPtr<nsIAccessibleText> accessibleText = do_QueryObject(accessible);
-      PRInt32 caretOffset;
-      if (accessibleText && NS_SUCCEEDED(accessibleText->GetCaretOffset(&caretOffset))) {
-#ifdef DEBUG_A11Y
-        PRUnichar chAtOffset;
-        accessibleText->GetCharacterAtOffset(caretOffset, &chAtOffset);
-        printf("\nCaret moved to %d with char %c", caretOffset, chAtOffset);
-#endif
-#ifdef DEBUG_CARET
-        // Test caret line # -- fire an EVENT_ALERT on the focused node so we can watch the
-        // line-number object attribute on it
-        nsAccessible *focusedAcc =
-          GetAccService()->GetAccessible(gLastFocusedNode);
-        nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_ALERT, focusedAcc);
-#endif
-        nsRefPtr<AccEvent> caretMoveEvent =
-          new AccCaretMoveEvent(accessible, caretOffset);
-        if (!caretMoveEvent)
-          return;
-
-        nsEventShell::FireEvent(caretMoveEvent);
-
-        PRInt32 selectionCount;
-        accessibleText->GetSelectionCount(&selectionCount);
-        if (selectionCount) {  // There's a selection so fire selection change as well
-          nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED,
-                                  accessible, PR_TRUE);
-        }
-      } 
-    }
-    else if (eventType == nsIAccessibleEvent::EVENT_REORDER) {
-      // Fire reorder event if it's unconditional (see InvalidateCacheSubtree
-      // method) or if changed node (that is the reason of this reorder event)
-      // is accessible or has accessible children.
-      AccReorderEvent* reorderEvent = downcast_accEvent(aEvent);
-      if (reorderEvent->IsUnconditionalEvent() ||
-          reorderEvent->HasAccessibleInReasonSubtree()) {
-        nsEventShell::FireEvent(aEvent);
-      }
-    }
-    else {
-      nsEventShell::FireEvent(aEvent);
-
-      // Post event processing
-      if (eventType == nsIAccessibleEvent::EVENT_HIDE && node) {
-        // Shutdown nsIAccessNode's or nsIAccessibles for any DOM nodes in
-        // this subtree.
-        // XXX: Will this bite us with asynch events.
-        RefreshNodes(node);
-      }
-    }
-  }
-}
-
-void
-nsDocAccessible::InvalidateChildrenInSubtree(nsINode *aStartNode)
 {
-  nsAccessible *accessible = GetCachedAccessible(aStartNode);
-  if (accessible)
-    accessible->InvalidateChildren();
-
-  // Invalidate accessible children in the DOM subtree 
-  PRInt32 index, numChildren = aStartNode->GetChildCount();
-  for (index = 0; index < numChildren; index ++) {
-    nsINode *childNode = aStartNode->GetChildAt(index);
-    InvalidateChildrenInSubtree(childNode);
-  }
-}
-
-void
-nsDocAccessible::RefreshNodes(nsINode *aStartNode)
-{
-  if (mAccessibleCache.Count() <= 1) {
-    return; // All we have is a doc accessible. There is nothing to invalidate, quit early
-  }
-
-  // Shut down accessible subtree, which may have been created for anonymous
-  // content subtree.
-  nsAccessible *accessible = GetCachedAccessible(aStartNode);
-  if (accessible) {
-    // Fire menupopup end if a menu goes away
-    if (accessible->Role() == nsIAccessibleRole::ROLE_MENUPOPUP) {
-      nsCOMPtr<nsIDOMXULPopupElement> popup(do_QueryInterface(aStartNode));
-      if (!popup) {
-        // Popup elements already fire these via DOMMenuInactive
-        // handling in nsRootAccessible::HandleEvent
-        nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_END,
-                                accessible);
-      }
-    }
-
-    // We only need to shutdown the accessibles here if one of them has been
-    // created.
-    if (accessible->GetCachedChildCount() > 0) {
-      nsCOMPtr<nsIArray> children;
-      // use GetChildren() to fetch all children at once, because after shutdown
-      // the child references are cleared.
-      accessible->GetChildren(getter_AddRefs(children));
-      PRUint32 childCount =0;
-      if (children)
-        children->GetLength(&childCount);
-      nsINode *possibleAnonNode = nsnull;
-      for (PRUint32 index = 0; index < childCount; index++) {
-        nsRefPtr<nsAccessNode> childAccessNode;
-        children->QueryElementAt(index, NS_GET_IID(nsAccessNode),
-                                 getter_AddRefs(childAccessNode));
-        possibleAnonNode = childAccessNode->GetNode();
-        nsCOMPtr<nsIContent> iterContent = do_QueryInterface(possibleAnonNode);
-        if (iterContent && iterContent->IsInAnonymousSubtree()) {
-          // IsInAnonymousSubtree() check is a perf win -- make sure we don't
-          // shut down the same subtree twice since we'll reach non-anon content via
-          // DOM traversal later in this method
-          RefreshNodes(possibleAnonNode);
-        }
-      }
-    }
-  }
-
-  // Shutdown ordinary content subtree as well -- there may be
-  // access node children which are not full accessible objects
-  PRUint32 childCount = aStartNode->GetChildCount();
-  for (PRUint32 childIdx = 0; childIdx < childCount; childIdx++) {
-    nsIContent *childContent = aStartNode->GetChildAt(childIdx);
-    RefreshNodes(childContent);
-  }
-
+  nsAccessible* accessible = aEvent->GetAccessible();
   if (!accessible)
     return;
 
-  if (accessible == this) {
-    // Don't shutdown our doc object -- this may just be from the finished loading.
-    // We will completely shut it down when the pagehide event is received
-    // However, we must invalidate the doc accessible's children in order to be sure
-    // all pointers to them are correct
-    InvalidateChildren();
-    return;
+  PRUint32 eventType = aEvent->GetEventType();
+
+  if (eventType == nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED) {
+    nsCOMPtr<nsIAccessibleText> accessibleText = do_QueryObject(accessible);
+    PRInt32 caretOffset;
+    if (accessibleText &&
+        NS_SUCCEEDED(accessibleText->GetCaretOffset(&caretOffset))) {
+#ifdef DEBUG_A11Y
+      PRUnichar chAtOffset;
+      accessibleText->GetCharacterAtOffset(caretOffset, &chAtOffset);
+      printf("\nCaret moved to %d with char %c", caretOffset, chAtOffset);
+#endif
+#ifdef DEBUG_CARET
+      // Test caret line # -- fire an EVENT_ALERT on the focused node so we can watch the
+      // line-number object attribute on it
+      nsAccessible* focusedAcc =
+        GetAccService()->GetAccessible(gLastFocusedNode);
+      nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_ALERT, focusedAcc);
+#endif
+      nsRefPtr<AccEvent> caretMoveEvent =
+          new AccCaretMoveEvent(accessible, caretOffset);
+      if (!caretMoveEvent)
+        return;
+
+      nsEventShell::FireEvent(caretMoveEvent);
+
+      PRInt32 selectionCount;
+      accessibleText->GetSelectionCount(&selectionCount);
+      if (selectionCount) {  // There's a selection so fire selection change as well
+        nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED,
+                                accessible);
+      }
+    }
   }
+  else {
+    nsEventShell::FireEvent(aEvent);
 
-  // Shut down the actual accessible or access node
-  void *uniqueID;
-  accessible->GetUniqueID(&uniqueID);
-  accessible->Shutdown();
-
-  // Remove from hash table as well
-  mAccessibleCache.Remove(uniqueID);
+    // Post event processing
+    if (eventType == nsIAccessibleEvent::EVENT_HIDE)
+      ShutdownChildrenInSubtree(accessible);
+  }
 }
 
-// nsDocAccessible public member
-void
-nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild,
-                                        PRUint32 aChangeType)
+PRUint32
+nsDocAccessible::UpdateTreeInternal(nsAccessible* aContainer,
+                                    nsIContent* aStartNode,
+                                    nsIContent* aEndNode,
+                                    PRBool aIsInsert,
+                                    PRBool aFireAllEvents,
+                                    EIsFromUserInput aFromUserInput)
 {
-  PRBool isHiding =
-    aChangeType == nsIAccessibilityService::FRAME_HIDE ||
-    aChangeType == nsIAccessibilityService::NODE_REMOVE;
-
-  PRBool isShowing =
-    aChangeType == nsIAccessibilityService::FRAME_SHOW ||
-    aChangeType == nsIAccessibilityService::NODE_APPEND;
-
-#ifdef DEBUG
-  PRBool isChanging =
-    aChangeType == nsIAccessibilityService::NODE_SIGNIFICANT_CHANGE ||
-    aChangeType == nsIAccessibilityService::FRAME_SIGNIFICANT_CHANGE;
-#endif
-
-  NS_ASSERTION(isChanging || isHiding || isShowing,
-               "Incorrect aChangeEventType passed in");
-
-  PRBool isAsynch =
-    aChangeType == nsIAccessibilityService::FRAME_HIDE ||
-    aChangeType == nsIAccessibilityService::FRAME_SHOW ||
-    aChangeType == nsIAccessibilityService::FRAME_SIGNIFICANT_CHANGE;
+  PRUint32 updateFlags = eNoAccessible;
+  for (nsIContent* node = aStartNode; node != aEndNode;
+       node = node->GetNextSibling()) {
 
-  // Invalidate cache subtree
-  // We have to check for accessibles for each dom node by traversing DOM tree
-  // instead of just the accessible tree, although that would be faster
-  // Otherwise we might miss the nsAccessNode's that are not nsAccessible's.
-
-  NS_ENSURE_TRUE(mDocument,);
-
-  nsINode *childNode = aChild;
-  if (!childNode)
-    childNode = mDocument;
+    // Tree update triggers for content insertion even if no content was
+    // inserted actually, check if the given content has a frame to discard
+    // this case early.
+    if (aIsInsert && !node->GetPrimaryFrame())
+      continue;
 
-  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
-  NS_ENSURE_TRUE(presShell,);
-  
-  if (!IsContentLoaded()) {
-    // Still loading document
-    if (mAccessibleCache.Count() <= 1) {
-      // Still loading and no accessibles has yet been created other than this
-      // doc accessible. In this case we optimize
-      // by not firing SHOW/HIDE/REORDER events for every document mutation
-      // caused by page load, since AT is not going to want to grab the
-      // document and listen to these changes until after the page is first loaded
-      // Leave early, and ensure mAccChildCount stays uninitialized instead of 0,
-      // which it is if anyone asks for its children right now.
-      InvalidateChildren();
-      return;
+    nsAccessible* accessible = aIsInsert ?
+      GetAccService()->GetAccessibleInWeakShell(node, mWeakShell) :
+      GetCachedAccessible(node);
+
+    if (!accessible) {
+      updateFlags |= UpdateTreeInternal(aContainer, node->GetFirstChild(),
+                                        nsnull, aIsInsert, aFireAllEvents,
+                                        aFromUserInput);
+      continue;
     }
 
-    nsIEventStateManager *esm = presShell->GetPresContext()->EventStateManager();
-    NS_ENSURE_TRUE(esm,);
+    updateFlags |= eAccessible;
+
+    // Fire show/hide event.
+    if (aFireAllEvents) {
+      nsRefPtr<AccEvent> event;
+      if (aIsInsert)
+        event = new AccShowEvent(accessible, node, aFromUserInput);
+      else
+        event = new AccHideEvent(accessible, node, aFromUserInput);
+
+      if (event)
+        FireDelayedAccessibleEvent(event);
+    }
 
-    if (!esm->IsHandlingUserInputExternal()) {
-      // Changes during page load, but not caused by user input
-      // Just invalidate accessible hierarchy and return,
-      // otherwise the page load time slows down way too much
-      nsAccessible *containerAccessible =
-        GetAccService()->GetCachedContainerAccessible(childNode);
-      if (!containerAccessible) {
-        containerAccessible = this;
+    if (aIsInsert) {
+      const nsRoleMapEntry* roleMapEntry = accessible->GetRoleMapEntry();
+      if (roleMapEntry) {
+        if (roleMapEntry->role == nsIAccessibleRole::ROLE_MENUPOPUP) {
+          // Fire EVENT_MENUPOPUP_START if ARIA menu appears.
+          FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START,
+                                     node, AccEvent::eRemoveDupes, aFromUserInput);
+
+        } else if (roleMapEntry->role == nsIAccessibleRole::ROLE_ALERT) {
+          // Fire EVENT_ALERT if ARIA alert appears.
+          updateFlags = eAlertAccessible;
+          FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_ALERT, node,
+                                     AccEvent::eRemoveDupes, aFromUserInput);
+        }
       }
 
-      containerAccessible->InvalidateChildren();
-      return;
-    }     
-    // else: user input, so we must fall through and for full handling,
-    // e.g. fire the mutation events. Note: user input could cause DOM_CREATE
-    // during page load if user typed into an input field or contentEditable area
-  }
-
-  // Update last change state information
-  nsAccessible *childAccessible = GetCachedAccessible(childNode);
-
-#ifdef DEBUG_A11Y
-  nsAutoString localName;
-  if (aChild)
-    aChild->NodeInfo()->GetName(localName);
-  const char *hasAccessible = childAccessible ? " (acc)" : "";
-  if (aChangeType == nsIAccessibilityService::FRAME_HIDE)
-    printf("[Hide %s %s]\n", NS_ConvertUTF16toUTF8(localName).get(), hasAccessible);
-  else if (aChangeType == nsIAccessibilityService::FRAME_SHOW)
-    printf("[Show %s %s]\n", NS_ConvertUTF16toUTF8(localName).get(), hasAccessible);
-  else if (aChangeType == nsIAccessibilityService::FRAME_SIGNIFICANT_CHANGE)
-    printf("[Layout change %s %s]\n", NS_ConvertUTF16toUTF8(localName).get(), hasAccessible);
-  else if (aChangeType == nsIAccessibilityService::NODE_APPEND)
-    printf("[Create %s %s]\n", NS_ConvertUTF16toUTF8(localName).get(), hasAccessible);
-  else if (aChangeType == nsIAccessibilityService::NODE_REMOVE)
-    printf("[Destroy  %s %s]\n", NS_ConvertUTF16toUTF8(localName).get(), hasAccessible);
-  else if (aChangeType == nsIAccessibilityService::NODE_SIGNIFICANT_CHANGE)
-    printf("[Type change %s %s]\n", NS_ConvertUTF16toUTF8(localName).get(), hasAccessible);
-#endif
-
-  nsAccessible *containerAccessible =
-    GetAccService()->GetCachedContainerAccessible(childNode);
-  if (!containerAccessible) {
-    containerAccessible = this;
-  }
-
-  if (!isShowing) {
-    // Fire EVENT_HIDE.
-    if (isHiding) {
-      if (aChild) {
-        nsIFrame *frame = aChild->GetPrimaryFrame();
-        if (frame) {
-          nsIFrame *frameParent = frame->GetParent();
-          if (!frameParent || !frameParent->GetStyleVisibility()->IsVisible()) {
-            // Ancestor already hidden or being hidden at the same time:
-            // don't process redundant hide event
-            // This often happens when visibility is cleared for node,
-            // which hides an entire subtree -- we get notified for each
-            // node in the subtree and need to collate the hide events ourselves.
-            return;
-          }
-        }
+      // If focused node has been shown then it means its frame was recreated
+      // while it's focused. Fire focus event on new focused accessible. If
+      // the queue contains focus event for this node then it's suppressed by
+      // this one.
+      if (node == gLastFocusedNode) {
+        FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_FOCUS,
+                                   node, AccEvent::eCoalesceFromSameDocument,
+                                   aFromUserInput);
       }
-    }
-
-    // Fire an event if the accessible existed for node being hidden, otherwise
-    // for the first line accessible descendants. Fire before the accessible(s)
-    // away.
-    nsresult rv = FireShowHideEvents(childNode, PR_FALSE,
-                                     nsIAccessibleEvent::EVENT_HIDE,
-                                     eDelayedEvent, isAsynch);
-    if (NS_FAILED(rv))
-      return;
-  }
-
-  // We need to get an accessible for the mutation event's container node
-  // If there is no accessible for that node, we need to keep moving up the parent
-  // chain so there is some accessible.
-  // We will use this accessible to fire the accessible mutation event.
-  // We're guaranteed success, because we will eventually end up at the doc accessible,
-  // and there is always one of those.
-
-  if (aChild && !isHiding) {
-    if (!isAsynch) {
-      // DOM already updated with new objects -- invalidate parent's children now
-      // For asynch we must wait until layout updates before we invalidate the children
-      containerAccessible->InvalidateChildren();
-    }
-
-    // Fire EVENT_SHOW, EVENT_MENUPOPUP_START for newly visible content.
-
-    // Fire after a short timer, because we want to make sure the view has been
-    // updated to make this accessible content visible. If we don't wait,
-    // the assistive technology may receive the event and then retrieve
-    // nsIAccessibleStates::STATE_INVISIBLE for the event's accessible object.
-
-    FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_SHOW, childNode,
-                               AccEvent::eCoalesceFromSameSubtree,
-                               isAsynch);
-
-    // Check to see change occurred in an ARIA menu, and fire
-    // an EVENT_MENUPOPUP_START if it did.
-    nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(childNode);
-    if (roleMapEntry && roleMapEntry->role == nsIAccessibleRole::ROLE_MENUPOPUP) {
-      FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START,
-                                 childNode, AccEvent::eRemoveDupes,
-                                 isAsynch);
-    }
-
-    // Check to see if change occurred inside an alert, and fire an EVENT_ALERT if it did
-    nsIContent *ancestor = aChild;
-    while (PR_TRUE) {
-      if (roleMapEntry && roleMapEntry->role == nsIAccessibleRole::ROLE_ALERT) {
-        FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_ALERT, ancestor,
-                                   AccEvent::eRemoveDupes, isAsynch);
-        break;
-      }
-      ancestor = ancestor->GetParent();
-      if (!ancestor)
-        break;
-
-      roleMapEntry = nsAccUtils::GetRoleMapEntry(ancestor);
+    } else {
+      // Update the tree for content removal.
+      aContainer->RemoveChild(accessible);
+      UncacheChildrenInSubtree(accessible);
     }
   }
 
-  FireValueChangeForTextFields(containerAccessible);
-
-  // Fire an event so the MSAA clients know the children have changed. Also
-  // the event is used internally by MSAA part.
+  return updateFlags;
+}
 
-  // We need to fire a delayed reorder event for the accessible parent of the
-  // changed node. We fire an unconditional reorder event if the changed node or
-  // one of its children is already accessible. In the case of show events, the
-  // accessible object might not be created yet for an otherwise accessible
-  // changed node (because its frame might not be constructed yet). In this case
-  // we fire a conditional reorder event, so that we will later check whether
-  // the changed node is accessible or has accessible children.
-  // Filtering/coalescing of these events happens during the queue flush.
+void
+nsDocAccessible::UncacheChildrenInSubtree(nsAccessible* aRoot)
+{
+  PRUint32 count = aRoot->GetCachedChildCount();
+  for (PRUint32 idx = 0; idx < count; idx++)
+    UncacheChildrenInSubtree(aRoot->GetCachedChildAt(idx));
 
-  PRBool isUnconditionalEvent = childAccessible ||
-    aChild && nsAccUtils::HasAccessibleChildren(childNode);
-
-  nsRefPtr<AccEvent> reorderEvent =
-    new AccReorderEvent(containerAccessible, isAsynch, isUnconditionalEvent,
-                        aChild ? aChild : nsnull);
-  NS_ENSURE_TRUE(reorderEvent,);
-
-  FireDelayedAccessibleEvent(reorderEvent);
+  if (aRoot->IsPrimaryForNode() &&
+      mNodeToAccessibleMap.Get(aRoot->GetNode()) == aRoot)
+    mNodeToAccessibleMap.Remove(aRoot->GetNode());
 }
 
-nsresult
-nsDocAccessible::FireShowHideEvents(nsINode *aNode,
-                                    PRBool aAvoidOnThisNode,
-                                    PRUint32 aEventType,
-                                    EEventFiringType aDelayedOrNormal,
-                                    PRBool aIsAsyncChange,
-                                    EIsFromUserInput aIsFromUserInput)
+void
+nsDocAccessible::ShutdownChildrenInSubtree(nsAccessible* aAccessible)
 {
-  NS_ENSURE_ARG(aNode);
+#ifdef DEBUG
+  nsAccessible* incache = mAccessibleCache.GetWeak(aAccessible->UniqueID());
+#endif
 
-  nsAccessible *accessible = nsnull;
-  if (!aAvoidOnThisNode) {
-    if (aEventType == nsIAccessibleEvent::EVENT_HIDE) {
-      // Don't allow creation for accessibles when nodes going away
-      accessible = GetCachedAccessible(aNode);
-    } else {
-      // Allow creation of new accessibles for show events
-      accessible = GetAccService()->GetAccessible(aNode);
+  // Traverse through children and shutdown them before this accessible. When
+  // child gets shutdown then it removes itself from children array of its
+  //parent. Use jdx index to process the cases if child is not attached to the
+  // parent and as result doesn't remove itself from its children.
+  PRUint32 count = aAccessible->GetCachedChildCount();
+  for (PRUint32 idx = 0, jdx = 0; idx < count; idx++) {
+    nsAccessible* child = aAccessible->GetCachedChildAt(jdx);
+    if (!child->IsBoundToParent()) {
+      NS_ERROR("Parent refers to a child, child doesn't refer to parent!");
+      jdx++;
     }
+
+    ShutdownChildrenInSubtree(child);
   }
 
-  if (accessible) {
-    // Found an accessible, so fire the show/hide on it and don't look further
-    // into this subtree.
-    nsRefPtr<AccEvent> event;
-    if (aDelayedOrNormal == eDelayedEvent &&
-        aEventType == nsIAccessibleEvent::EVENT_HIDE) {
-      // Use AccHideEvent for delayed hide events to coalesce text change events
-      // caused by these hide events.
-      event = new AccHideEvent(accessible, accessible->GetNode(),
-                               aIsAsyncChange, aIsFromUserInput);
-
-    } else {
-      event = new AccEvent(aEventType, accessible, aIsAsyncChange,
-                           aIsFromUserInput,
-                           AccEvent::eCoalesceFromSameSubtree);
-    }
-    NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
+  ShutdownAccessible(aAccessible);
+}
 
-    if (aDelayedOrNormal == eDelayedEvent)
-      return FireDelayedAccessibleEvent(event);
-
-    nsEventShell::FireEvent(event);
-    return NS_OK;
-  }
-
-  // Could not find accessible to show hide yet, so fire on any
-  // accessible descendants in this subtree
-  PRUint32 count = aNode->GetChildCount();
-  for (PRUint32 index = 0; index < count; index++) {
-    nsINode *childNode = aNode->GetChildAt(index);
-    nsresult rv = FireShowHideEvents(childNode, PR_FALSE, aEventType,
-                                     aDelayedOrNormal, aIsAsyncChange,
-                                     aIsFromUserInput);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  return NS_OK;
-}
--- a/accessible/src/base/nsDocAccessible.h
+++ b/accessible/src/base/nsDocAccessible.h
@@ -165,84 +165,86 @@ public:
     { return mChildDocuments.SafeElementAt(aIndex, nsnull); }
 
   /**
    * Non-virtual method to fire a delayed event after a 0 length timeout.
    *
    * @param aEventType   [in] the nsIAccessibleEvent event type
    * @param aDOMNode     [in] DOM node the accesible event should be fired for
    * @param aAllowDupes  [in] rule to process an event (see EEventRule constants)
-   * @param aIsAsynch    [in] set to PR_TRUE if this is not being called from
-   *                      code synchronous with a DOM event
    */
   nsresult FireDelayedAccessibleEvent(PRUint32 aEventType, nsINode *aNode,
                                       AccEvent::EEventRule aAllowDupes = AccEvent::eRemoveDupes,
-                                      PRBool aIsAsynch = PR_FALSE,
                                       EIsFromUserInput aIsFromUserInput = eAutoDetect);
 
   /**
    * Fire accessible event after timeout.
    *
    * @param aEvent  [in] the event to fire
    */
   nsresult FireDelayedAccessibleEvent(AccEvent* aEvent);
 
   /**
-   * Find the accessible object in the accessibility cache that corresponds to
-   * the given node or the first ancestor of it that has an accessible object
-   * associated with it. Clear that accessible object's parent's cache of
-   * accessible children and remove the accessible object and any descendants
-   * from the accessible cache. Fires proper events. New accessible objects will
-   * be created and cached again on demand.
-   *
-   * @param aContent  [in] the child that is changing
-   * @param aEvent    [in] the event from nsIAccessibleEvent that caused
-   *                   the change.
-   */
-  void InvalidateCacheSubtree(nsIContent *aContent, PRUint32 aEvent);
-
-  /**
-   * Return the cached accessible by the given unique ID if it's in subtree of
+   * Return the cached accessible by the given DOM node if it's in subtree of
    * this document accessible or the document accessible itself, otherwise null.
    *
-   * @note   the unique ID matches with the uniqueID attribute on nsIAccessNode
-   *
-   * @param  aUniqueID  [in] the unique ID used to cache the node.
-   *
    * @return the accessible object
    */
-  nsAccessible* GetCachedAccessible(void *aUniqueID);
+  nsAccessible* GetCachedAccessible(nsINode* aNode);
+
+  /**
+   * Return the cached accessible by the given unique ID within this document.
+   *
+   * @note   the unique ID matches with the uniqueID() of nsAccessNode
+   *
+   * @param  aUniqueID  [in] the unique ID used to cache the node.
+   */
+  nsAccessible* GetCachedAccessibleByUniqueID(void* aUniqueID)
+  {
+    return UniqueID() == aUniqueID ?
+      this : mAccessibleCache.GetWeak(aUniqueID);
+  }
 
   /**
    * Return the cached accessible by the given unique ID looking through
    * this and nested documents.
    */
-  nsAccessible* GetCachedAccessibleInSubtree(void* aUniqueID);
+  nsAccessible* GetCachedAccessibleByUniqueIDInSubtree(void* aUniqueID);
 
   /**
    * Cache the accessible.
    *
-   * @param  aUniquID     [in] the unique identifier of accessible
    * @param  aAccessible  [in] accessible to cache
    *
    * @return true if accessible being cached, otherwise false
    */
-  PRBool CacheAccessible(void *aUniqueID, nsAccessible *aAccessible);
+  PRBool CacheAccessible(nsAccessible *aAccessible);
 
   /**
-   * Remove the given accessible from document cache.
+   * Shutdown the accessible and remove it from document cache.
    */
-  void RemoveAccessNodeFromCache(nsAccessible *aAccessible);
+  void ShutdownAccessible(nsAccessible *aAccessible);
 
   /**
    * Process the event when the queue of pending events is untwisted. Fire
    * accessible events as result of the processing.
    */
   void ProcessPendingEvent(AccEvent* aEvent);
 
+  /**
+   * Update the accessible tree.
+   */
+  void UpdateTree(nsIContent* aContainerNode, nsIContent* aStartChildNode,
+                  nsIContent* aEndChildNode, PRBool aIsInsert);
+
+  /**
+   * Recreate an accessible, results in hide/show events pair.
+   */
+  void RecreateAccessible(nsINode* aNode);
+
 protected:
 
     virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
     virtual nsresult AddEventListeners();
     virtual nsresult RemoveEventListeners();
     void AddScrollListener();
     void RemoveScrollListener();
 
@@ -259,30 +261,16 @@ protected:
    * Remove the given document accessible from this document's child document
    * accessibles.
    */
   void RemoveChildDocument(nsDocAccessible* aChildDocument)
   {
     mChildDocuments.RemoveElement(aChildDocument);
   }
 
-  /**
-   * Invalidate parent-child relations for any cached accessible in the DOM
-   * subtree. Accessible objects aren't destroyed.
-   *
-   * @param aStartNode  [in] the root of the subrtee to invalidate accessible
-   *                      child/parent refs in
-   */
-  void InvalidateChildrenInSubtree(nsINode *aStartNode);
-
-  /**
-   * Traverse through DOM tree and shutdown accessible objects.
-   */
-  void RefreshNodes(nsINode *aStartNode);
-
     static void ScrollTimerCallback(nsITimer *aTimer, void *aClosure);
 
     /**
      * Fires accessible events when attribute is changed.
      *
      * @param aContent - node that attribute is changed for
      * @param aNameSpaceID - namespace of changed attribute
      * @param aAttribute - changed attribute
@@ -306,72 +294,64 @@ protected:
      * @param aIsInserted  the flag pointed whether removed or inserted
      *                     characters should be cause of event
      */
     void FireTextChangeEventForText(nsIContent *aContent,
                                     CharacterDataChangeInfo* aInfo,
                                     PRBool aIsInserted);
 
   /**
-   * Create a text change event for a changed node.
-   *
-   * @param  aContainerAccessible  [in] the parent accessible for the node
-   * @param  aChangeNode           [in] the node that is being inserted or
-   *                                 removed, or shown/hidden
-   * @param  aAccessible           [in] the accessible for that node, or nsnull
-   *                                 if none exists
-   * @param  aIsInserting          [in] is aChangeNode being created or shown
-   *                                 (vs. removed or hidden)
-   * @param  aIsAsync              [in] whether casual change is async
-   * @param  aIsFromUserInput      [in] the event is known to be from user input
-   */
-  already_AddRefed<AccEvent>
-    CreateTextChangeEventForNode(nsAccessible *aContainerAccessible,
-                                 nsIContent *aChangeNode,
-                                 nsAccessible *aAccessible,
-                                 PRBool aIsInserting,
-                                 PRBool aIsAsynch,
-                                 EIsFromUserInput aIsFromUserInput = eAutoDetect);
-
-  /**
    * Used to define should the event be fired on a delay.
    */
   enum EEventFiringType {
     eNormalEvent,
     eDelayedEvent
   };
 
   /**
-   * Fire show/hide events for either the current node if it has an accessible,
-   * or the first-line accessible descendants of the given node.
-   *
-   * @param  aDOMNode          [in] the given node
-   * @param  aAvoidOnThisNode  [in] call with PR_TRUE the first time to
-   *                             prevent event firing on root node for change
-   * @param  aEventType        [in] event type to fire an event
-   * @param  aDelayedOrNormal  [in] whether to fire the event on a delay
-   * @param  aIsAsyncChange    [in] whether casual change is async
-   * @param  aIsFromUserInput  [in] the event is known to be from user input
-   */
-  nsresult FireShowHideEvents(nsINode *aDOMNode, PRBool aAvoidOnThisNode,
-                              PRUint32 aEventType,
-                              EEventFiringType aDelayedOrNormal,
-                              PRBool aIsAsyncChange,
-                              EIsFromUserInput aIsFromUserInput = eAutoDetect);
-
-  /**
    * Fire a value change event for the the given accessible if it is a text
    * field (has a ROLE_ENTRY).
    */
   void FireValueChangeForTextFields(nsAccessible *aAccessible);
 
   /**
+   * Helper for UpdateTree() method. Go down to DOM subtree and updates
+   * accessible tree. Return one of these flags.
+   */
+  enum EUpdateTreeFlags {
+    eNoAccessible = 0,
+    eAccessible = 1,
+    eAlertAccessible = 2
+  };
+
+  PRUint32 UpdateTreeInternal(nsAccessible* aContainer,
+                              nsIContent* aStartNode,
+                              nsIContent* aEndNode,
+                              PRBool aIsInsert,
+                              PRBool aFireEvents,
+                              EIsFromUserInput aFromUserInput);
+
+  /**
+   * Remove accessibles in subtree from node to accessible map.
+   */
+  void UncacheChildrenInSubtree(nsAccessible* aRoot);
+
+  /**
+   * Shutdown any cached accessible in the subtree.
+   *
+   * @param aAccessible  [in] the root of the subrtee to invalidate accessible
+   *                      child/parent refs in
+   */
+  void ShutdownChildrenInSubtree(nsAccessible *aAccessible);
+
+  /**
    * Cache of accessibles within this document accessible.
    */
   nsAccessibleHashtable mAccessibleCache;
+  NodeToAccessibleMap mNodeToAccessibleMap;
 
     nsCOMPtr<nsIDocument> mDocument;
     nsCOMPtr<nsITimer> mScrollWatchTimer;
     PRUint16 mScrollPositionChangedTicks; // Used for tracking scroll events
 
 protected:
 
   nsRefPtr<nsAccEventQueue> mEventQueue;
--- a/accessible/src/base/nsEventShell.cpp
+++ b/accessible/src/base/nsEventShell.cpp
@@ -63,22 +63,22 @@ nsEventShell::FireEvent(AccEvent* aEvent
 
   accessible->HandleAccEvent(aEvent);
 
   sEventTargetNode = nsnull;
 }
 
 void
 nsEventShell::FireEvent(PRUint32 aEventType, nsAccessible *aAccessible,
-                        PRBool aIsAsynch, EIsFromUserInput aIsFromUserInput)
+                        EIsFromUserInput aIsFromUserInput)
 {
   NS_ENSURE_TRUE(aAccessible,);
 
   nsRefPtr<AccEvent> event = new AccEvent(aEventType, aAccessible,
-                                          aIsAsynch, aIsFromUserInput);
+                                          aIsFromUserInput);
 
   FireEvent(event);
 }
 
 void 
 nsEventShell::GetEventAttributes(nsINode *aNode,
                                  nsIPersistentProperties *aAttributes)
 {
@@ -142,19 +142,19 @@ nsAccEventQueue::Push(AccEvent* aEvent)
 {
   mEvents.AppendElement(aEvent);
 
   // Filter events.
   CoalesceEvents();
 
   // Associate text change with hide event if it wasn't stolen from hiding
   // siblings during coalescence.
-  AccHideEvent* hideEvent = downcast_accEvent(aEvent);
-  if (hideEvent && !hideEvent->mTextChangeEvent)
-    CreateTextChangeEventFor(hideEvent);
+  AccMutationEvent* showOrHideEvent = downcast_accEvent(aEvent);
+  if (showOrHideEvent && !showOrHideEvent->mTextChangeEvent)
+    CreateTextChangeEventFor(showOrHideEvent);
 
   // Process events.
   PrepareFlush();
 }
 
 void
 nsAccEventQueue::Shutdown()
 {
@@ -204,20 +204,20 @@ nsAccEventQueue::WillRefresh(mozilla::Ti
   NS_ASSERTION(length, "How did we get here without events to fire?");
 
   for (PRUint32 index = 0; index < length; index ++) {
 
     AccEvent* accEvent = events[index];
     if (accEvent->mEventRule != AccEvent::eDoNotEmit) {
       mDocument->ProcessPendingEvent(accEvent);
 
-      AccHideEvent* hideEvent = downcast_accEvent(accEvent);
-      if (hideEvent) {
-        if (hideEvent->mTextChangeEvent)
-          mDocument->ProcessPendingEvent(hideEvent->mTextChangeEvent);
+      AccMutationEvent* showOrhideEvent = downcast_accEvent(accEvent);
+      if (showOrhideEvent) {
+        if (showOrhideEvent->mTextChangeEvent)
+          mDocument->ProcessPendingEvent(showOrhideEvent->mTextChangeEvent);
       }
     }
 
     // No document means it was shut down during event handling by AT
     if (!mDocument)
       return;
   }
 
@@ -262,156 +262,88 @@ nsAccEventQueue::CoalesceEvents()
         // that is sibling of target of newly appended event then apply its
         // event rule to the newly appended event.
 
         // XXX: deal with show events separately because they can't be
         // coalesced by accessible tree the same as hide events since target
         // accessibles can't be created at this point because of lazy frame
         // construction (bug 570275).
 
-        // Coalesce hide events for sibling targets.
+        // Coalesce hide and show events for sibling targets.
         if (tailEvent->mEventType == nsIAccessibleEvent::EVENT_HIDE) {
           AccHideEvent* tailHideEvent = downcast_accEvent(tailEvent);
           AccHideEvent* thisHideEvent = downcast_accEvent(thisEvent);
           if (thisHideEvent->mParent == tailHideEvent->mParent) {
             tailEvent->mEventRule = thisEvent->mEventRule;
 
             // Coalesce text change events for hide events.
             if (tailEvent->mEventRule != AccEvent::eDoNotEmit)
               CoalesceTextChangeEventsFor(tailHideEvent, thisHideEvent);
 
             return;
           }
+        } else if (tailEvent->mEventType == nsIAccessibleEvent::EVENT_SHOW) {
+          if (thisEvent->mAccessible->GetParent() ==
+              tailEvent->mAccessible->GetParent()) {
+            tailEvent->mEventRule = thisEvent->mEventRule;
+
+            // Coalesce text change events for show events.
+            if (tailEvent->mEventRule != AccEvent::eDoNotEmit) {
+              AccShowEvent* tailShowEvent = downcast_accEvent(tailEvent);
+              AccShowEvent* thisShowEvent = downcast_accEvent(thisEvent);
+              CoalesceTextChangeEventsFor(tailShowEvent, thisShowEvent);
+            }
+
+            return;
+          }
         }
 
         // Ignore events unattached from DOM since we don't coalesce them.
         if (!thisEvent->mNode->IsInDoc())
           continue;
 
-        // Coalesce show and reorder events by sibling targets.
+        // Coalesce earlier event for the same target.
+        if (thisEvent->mNode == tailEvent->mNode) {
+          thisEvent->mEventRule = AccEvent::eDoNotEmit;
+          return;
+        }
+
+        // Coalesce events by sibling targets (this is a case for reorder
+        // events).
         if (thisEvent->mNode->GetNodeParent() ==
             tailEvent->mNode->GetNodeParent()) {
           tailEvent->mEventRule = thisEvent->mEventRule;
           return;
         }
 
-        // Specifies if this event target can be descendant of tail node.
-        PRBool thisCanBeDescendantOfTail = PR_FALSE;
-
-        // Coalesce depending on whether this event was coalesced or not.
-        if (thisEvent->mEventRule == AccEvent::eDoNotEmit) {
-          // If this event was coalesced then do not emit tail event iff tail
-          // event has the same target or its target is contained by this event
-          // target. Note, we don't need to check whether tail event target
-          // contains this event target since this event was coalesced already.
-
-          // As well we don't need to apply the calculated rule for siblings of
-          // tail node because tail event rule was applied to possible tail
-          // node siblings while this event was coalesced.
-
-          if (thisEvent->mNode == tailEvent->mNode) {
-            thisEvent->mEventRule = AccEvent::eDoNotEmit;
-            return;
-          }
-
-        } else {
-          // If this event wasn't coalesced already then try to coalesce it or
-          // tail event. If this event is coalesced by tail event then continue
-          // search through events other events that can be coalesced by tail
-          // event.
-
-          // If tail and this events have the same target then coalesce tail
-          // event because more early event we should fire early and then stop
-          // processing.
-          if (thisEvent->mNode == tailEvent->mNode) {
-            // Coalesce reorder events by special way since reorder events can
-            // be conditional events (be or not be fired in the end).
-            if (thisEvent->mEventType == nsIAccessibleEvent::EVENT_REORDER) {
-              CoalesceReorderEventsFromSameSource(thisEvent, tailEvent);
-              if (tailEvent->mEventRule != AccEvent::eDoNotEmit)
-                continue;
-            }
-            else {
-              tailEvent->mEventRule = AccEvent::eDoNotEmit;
-            }
-
-            return;
-          }
-
-          // This and tail events can be anywhere in the tree, make assumptions
-          // for mutation events.
-
-          // More older show event target (thisNode) can't be contained by
-          // recent.
-          // show event target (tailNode), i.e be a descendant of tailNode.
-          // XXX: target of older show event caused by DOM node appending can be
-          // contained by target of recent show event caused by style change.
-          // XXX: target of older show event caused by style change can be
-          // contained by target of recent show event caused by style change.
-          thisCanBeDescendantOfTail =
-            tailEvent->mEventType != nsIAccessibleEvent::EVENT_SHOW ||
-            tailEvent->mIsAsync;
-        }
+        // This and tail events can be anywhere in the tree, make assumptions
+        // for mutation events.
 
         // Coalesce tail event if tail node is descendant of this node. Stop
         // processing if tail event is coalesced since all possible descendants
         // of this node was coalesced before.
         // Note: more older hide event target (thisNode) can't contain recent
         // hide event target (tailNode), i.e. be ancestor of tailNode. Skip
         // this check for hide events.
         if (tailEvent->mEventType != nsIAccessibleEvent::EVENT_HIDE &&
             nsCoreUtils::IsAncestorOf(thisEvent->mNode, tailEvent->mNode)) {
-
-          if (thisEvent->mEventType == nsIAccessibleEvent::EVENT_REORDER) {
-            CoalesceReorderEventsFromSameTree(thisEvent, tailEvent);
-            if (tailEvent->mEventRule != AccEvent::eDoNotEmit)
-              continue;
-
-            return;
-          }
-
           tailEvent->mEventRule = AccEvent::eDoNotEmit;
           return;
         }
 
-#ifdef DEBUG
-        if (tailEvent->mEventType == nsIAccessibleEvent::EVENT_HIDE &&
-            nsCoreUtils::IsAncestorOf(thisEvent->mNode, tailEvent->mNode)) {
-          NS_NOTREACHED("More older hide event target is an ancestor of recent hide event target!");
-        }
-#endif
-
         // If this node is a descendant of tail node then coalesce this event,
-        // check other events in the queue.
-        if (thisCanBeDescendantOfTail &&
-            nsCoreUtils::IsAncestorOf(tailEvent->mNode, thisEvent->mNode)) {
-
-          if (thisEvent->mEventType == nsIAccessibleEvent::EVENT_REORDER) {
-            CoalesceReorderEventsFromSameTree(tailEvent, thisEvent);
-            if (tailEvent->mEventRule != AccEvent::eDoNotEmit)
-              continue;
-
-            return;
-          }
-
-          // Do not emit thisEvent, also apply this result to sibling nodes of
-          // thisNode.
+        // check other events in the queue. Do not emit thisEvent, also apply
+        // this result to sibling nodes of thisNode.
+        if (nsCoreUtils::IsAncestorOf(tailEvent->mNode, thisEvent->mNode)) {
           thisEvent->mEventRule = AccEvent::eDoNotEmit;
           ApplyToSiblings(0, index, thisEvent->mEventType,
                           thisEvent->mNode, AccEvent::eDoNotEmit);
           continue;
         }
 
-#ifdef DEBUG
-        if (!thisCanBeDescendantOfTail &&
-            nsCoreUtils::IsAncestorOf(tailEvent->mNode, thisEvent->mNode)) {
-          NS_NOTREACHED("Older event target is a descendant of recent event target!");
-        }
-#endif
-
       } // for (index)
 
     } break; // case eCoalesceFromSameSubtree
 
     case AccEvent::eCoalesceFromSameDocument:
     {
       // Used for focus event, coalesce more older event since focus event
       // for accessible can be duplicated by event for its document, we are
@@ -450,59 +382,24 @@ nsAccEventQueue::CoalesceEvents()
 void
 nsAccEventQueue::ApplyToSiblings(PRUint32 aStart, PRUint32 aEnd,
                                  PRUint32 aEventType, nsINode* aNode,
                                  AccEvent::EEventRule aEventRule)
 {
   for (PRUint32 index = aStart; index < aEnd; index ++) {
     AccEvent* accEvent = mEvents[index];
     if (accEvent->mEventType == aEventType &&
-        accEvent->mEventRule != AccEvent::eDoNotEmit &&
+        accEvent->mEventRule != AccEvent::eDoNotEmit && accEvent->mNode &&
         accEvent->mNode->GetNodeParent() == aNode->GetNodeParent()) {
       accEvent->mEventRule = aEventRule;
     }
   }
 }
 
 void
-nsAccEventQueue::CoalesceReorderEventsFromSameSource(AccEvent* aAccEvent1,
-                                                     AccEvent* aAccEvent2)
-{
-  // Do not emit event2 if event1 is unconditional.
-  AccReorderEvent* reorderEvent1 = downcast_accEvent(aAccEvent1);
-  if (reorderEvent1->IsUnconditionalEvent()) {
-    aAccEvent2->mEventRule = AccEvent::eDoNotEmit;
-    return;
-  }
-
-  // Do not emit event1 if event2 is unconditional.
-  AccReorderEvent* reorderEvent2 = downcast_accEvent(aAccEvent2);
-  if (reorderEvent2->IsUnconditionalEvent()) {
-    aAccEvent1->mEventRule = AccEvent::eDoNotEmit;
-    return;
-  }
-
-  // Do not emit event2 if event1 is valid, otherwise do not emit event1.
-  if (reorderEvent1->HasAccessibleInReasonSubtree())
-    aAccEvent2->mEventRule = AccEvent::eDoNotEmit;
-  else
-    aAccEvent1->mEventRule = AccEvent::eDoNotEmit;
-}
-
-void
-nsAccEventQueue::CoalesceReorderEventsFromSameTree(AccEvent* aAccEvent,
-                                                   AccEvent* aDescendantAccEvent)
-{
-  // Do not emit descendant event if this event is unconditional.
-  AccReorderEvent* reorderEvent = downcast_accEvent(aAccEvent);
-  if (reorderEvent->IsUnconditionalEvent())
-    aDescendantAccEvent->mEventRule = AccEvent::eDoNotEmit;
-}
-
-void
 nsAccEventQueue::CoalesceTextChangeEventsFor(AccHideEvent* aTailEvent,
                                              AccHideEvent* aThisEvent)
 {
   // XXX: we need a way to ignore SplitNode and JoinNode() when they do not
   // affect the text within the hypertext.
 
   AccTextChangeEvent* textEvent = aThisEvent->mTextChangeEvent;
   if (!textEvent)
@@ -518,17 +415,45 @@ nsAccEventQueue::CoalesceTextChangeEvent
                                           0, PR_UINT32_MAX);
     textEvent->mStart -= textEvent->GetLength() - oldLen;
   }
 
   aTailEvent->mTextChangeEvent.swap(aThisEvent->mTextChangeEvent);
 }
 
 void
-nsAccEventQueue::CreateTextChangeEventFor(AccHideEvent* aEvent)
+nsAccEventQueue::CoalesceTextChangeEventsFor(AccShowEvent* aTailEvent,
+                                             AccShowEvent* aThisEvent)
+{
+  AccTextChangeEvent* textEvent = aThisEvent->mTextChangeEvent;
+  if (!textEvent)
+    return;
+
+  if (aTailEvent->mAccessible->GetIndexInParent() ==
+      aThisEvent->mAccessible->GetIndexInParent() + 1) {
+    // If tail target was inserted after this target, i.e. tail target is next
+    // sibling of this target.
+    aTailEvent->mAccessible->AppendTextTo(textEvent->mModifiedText,
+                                          0, PR_UINT32_MAX);
+
+  } else if (aTailEvent->mAccessible->GetIndexInParent() ==
+             aThisEvent->mAccessible->GetIndexInParent() -1) {
+    // If tail target was inserted before this target, i.e. tail target is
+    // previous sibling of this target.
+    nsAutoString startText;
+    aTailEvent->mAccessible->AppendTextTo(startText, 0, PR_UINT32_MAX);
+    textEvent->mModifiedText = startText + textEvent->mModifiedText;
+    textEvent->mStart -= startText.Length();
+  }
+
+  aTailEvent->mTextChangeEvent.swap(aThisEvent->mTextChangeEvent);
+}
+
+void
+nsAccEventQueue::CreateTextChangeEventFor(AccMutationEvent* aEvent)
 {
   nsRefPtr<nsHyperTextAccessible> textAccessible = do_QueryObject(
     GetAccService()->GetContainerAccessible(aEvent->mNode,
                                             aEvent->mAccessible->GetWeakShell()));
   if (!textAccessible)
     return;
 
   // Don't fire event for the first html:br in an editor.
@@ -546,12 +471,11 @@ nsAccEventQueue::CreateTextChangeEventFo
   PRInt32 offset = textAccessible->GetChildOffset(aEvent->mAccessible);
 
   nsAutoString text;
   aEvent->mAccessible->AppendTextTo(text, 0, PR_UINT32_MAX);
   if (text.IsEmpty())
     return;
 
   aEvent->mTextChangeEvent =
-    new AccTextChangeEvent(textAccessible, offset, text, PR_FALSE,
-                           aEvent->mIsAsync,
+    new AccTextChangeEvent(textAccessible, offset, text, aEvent->IsShow(),
                            aEvent->mIsFromUserInput ? eFromUserInput : eNoUserInput);
 }
--- a/accessible/src/base/nsEventShell.h
+++ b/accessible/src/base/nsEventShell.h
@@ -61,21 +61,18 @@ public:
    */
   static void FireEvent(AccEvent* aEvent);
 
   /**
    * Fire accessible event of the given type for the given accessible.
    *
    * @param  aEventType   [in] the event type
    * @param  aAccessible  [in] the event target
-   * @param  aIsAsync     [in, optional] specifies whether the origin change
-   *                        this event is fired owing to is async.
    */
   static void FireEvent(PRUint32 aEventType, nsAccessible *aAccessible,
-                        PRBool aIsAsynch = PR_FALSE,
                         EIsFromUserInput aIsFromUserInput = eAutoDetect);
 
   /**
    * Append 'event-from-input' object attribute if the accessible event has
    * been fired just now for the given node.
    *
    * @param  aNode        [in] the DOM node
    * @param  aAttributes  [in, out] the attributes
@@ -140,41 +137,36 @@ private:
    * @param aEventRule       the event rule to be applied
    *                         (should be eDoNotEmit or eAllowDupes)
    */
   void ApplyToSiblings(PRUint32 aStart, PRUint32 aEnd,
                        PRUint32 aEventType, nsINode* aNode,
                        AccEvent::EEventRule aEventRule);
 
   /**
-   * Do not emit one of two given reorder events fired for the same DOM node.
-   */
-  void CoalesceReorderEventsFromSameSource(AccEvent* aAccEvent1,
-                                           AccEvent* aAccEvent2);
-
-  /**
    * Do not emit one of two given reorder events fired for DOM nodes in the case
    * when one DOM node is in parent chain of second one.
    */
   void CoalesceReorderEventsFromSameTree(AccEvent* aAccEvent,
                                          AccEvent* aDescendantAccEvent);
 
   /**
    * Coalesce text change events caused by sibling hide events.
    */
   void CoalesceTextChangeEventsFor(AccHideEvent* aTailEvent,
                                    AccHideEvent* aThisEvent);
+  void CoalesceTextChangeEventsFor(AccShowEvent* aTailEvent,
+                                   AccShowEvent* aThisEvent);
 
   /**
-   * Create text change event caused by hide event. When a node is hidden or
-   * removed, the text in an ancestor hyper text will lose characters. Create
-   * text change event unless the node is being removed or frame is being
-   * destroyed.
+   * Create text change event caused by hide or show event. When a node is
+   * hidden/removed or shown/appended, the text in an ancestor hyper text will
+   * lose or get new characters.
    */
-  void CreateTextChangeEventFor(AccHideEvent* aEvent);
+  void CreateTextChangeEventFor(AccMutationEvent* aEvent);
 
   /**
    * Indicates whether we're waiting on a refresh notification from our
    * presshell to flush events
    */
   PRBool mObservingRefresh;
 
   /**
--- a/accessible/src/base/nsRootAccessible.cpp
+++ b/accessible/src/base/nsRootAccessible.cpp
@@ -314,17 +314,16 @@ nsRootAccessible::GetCaretAccessible()
   return mCaretAccessible;
 }
 
 PRBool
 nsRootAccessible::FireAccessibleFocusEvent(nsAccessible *aAccessible,
                                            nsINode *aNode,
                                            nsIDOMEvent *aFocusEvent,
                                            PRBool aForceEvent,
-                                           PRBool aIsAsynch,
                                            EIsFromUserInput aIsFromUserInput)
 {
   // Implementors: only fire delayed/async events from this method.
 
   if (mCaretAccessible) {
     nsCOMPtr<nsIDOMNSEvent> nsevent(do_QueryInterface(aFocusEvent));
     if (nsevent) {
       // Use the originally focused node where the selection lives.
@@ -393,30 +392,30 @@ nsRootAccessible::FireAccessibleFocusEve
         nsAccessible *menuBarAccessible =
           nsAccUtils::GetAncestorWithRole(finalFocusAccessible,
                                           nsIAccessibleRole::ROLE_MENUBAR);
         if (menuBarAccessible) {
           mCurrentARIAMenubar = menuBarAccessible->GetNode();
           if (mCurrentARIAMenubar) {
             nsRefPtr<AccEvent> menuStartEvent =
               new AccEvent(nsIAccessibleEvent::EVENT_MENU_START,
-                           menuBarAccessible, PR_FALSE, aIsFromUserInput,
+                           menuBarAccessible, aIsFromUserInput,
                            AccEvent::eAllowDupes);
             if (menuStartEvent) {
               FireDelayedAccessibleEvent(menuStartEvent);
             }
           }
         }
       }
     }
   }
   else if (mCurrentARIAMenubar) {
     nsRefPtr<AccEvent> menuEndEvent =
       new AccEvent(nsIAccessibleEvent::EVENT_MENU_END, mCurrentARIAMenubar,
-                   PR_FALSE, aIsFromUserInput, AccEvent::eAllowDupes);
+                   aIsFromUserInput, AccEvent::eAllowDupes);
     if (menuEndEvent) {
       FireDelayedAccessibleEvent(menuEndEvent);
     }
     mCurrentARIAMenubar = nsnull;
   }
 
   nsCOMPtr<nsIContent> focusContent = do_QueryInterface(finalFocusNode);
   nsIFrame *focusFrame = nsnull;
@@ -429,23 +428,21 @@ nsRootAccessible::FireAccessibleFocusEve
 
     focusFrame = focusContent->GetPrimaryFrame();
   }
 
   NS_IF_RELEASE(gLastFocusedNode);
   gLastFocusedNode = finalFocusNode;
   NS_IF_ADDREF(gLastFocusedNode);
 
-  gLastFocusedFrameType = (focusFrame && focusFrame->GetStyleVisibility()->IsVisible()) ? focusFrame->GetType() : 0;
-
   // Coalesce focus events from the same document, because DOM focus event might
   // be fired for the document node and then for the focused DOM element.
   FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_FOCUS,
                              finalFocusNode, AccEvent::eCoalesceFromSameDocument,
-                             aIsAsynch, aIsFromUserInput);
+                             aIsFromUserInput);
 
   return PR_TRUE;
 }
 
 void
 nsRootAccessible::FireCurrentFocusEvent()
 {
   if (IsDefunct())
@@ -658,17 +655,16 @@ nsRootAccessible::HandleEvent(nsIDOMEven
             return NS_OK;
         }
       }
     }
     FireAccessibleFocusEvent(accessible, focusedItem, aEvent);
   }
   else if (eventType.EqualsLiteral("blur")) {
     NS_IF_RELEASE(gLastFocusedNode);
-    gLastFocusedFrameType = nsnull;
     gLastFocusedAccessiblesState = 0;
   }
   else if (eventType.EqualsLiteral("AlertActive")) { 
     nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_ALERT, accessible);
   }
   else if (eventType.EqualsLiteral("popupshown")) {
     HandlePopupShownEvent(accessible);
   }
@@ -727,26 +723,26 @@ nsRootAccessible::HandleEvent(nsIDOMEven
           break;
         }
         containerContent = containerContent->GetParent();
       }
     }
     if (fireFocus) {
       // Always asynch, always from user input.
       FireAccessibleFocusEvent(accessible, targetNode, aEvent, PR_TRUE,
-                               PR_TRUE, eFromUserInput);
+                               eFromUserInput);
     }
   }
-  else if (eventType.EqualsLiteral("DOMMenuBarActive")) {  // Always asynch, always from user input
+  else if (eventType.EqualsLiteral("DOMMenuBarActive")) {  // Always from user input
     nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENU_START,
-                            accessible, PR_TRUE, eFromUserInput);
+                            accessible, eFromUserInput);
   }
-  else if (eventType.EqualsLiteral("DOMMenuBarInactive")) {  // Always asynch, always from user input
+  else if (eventType.EqualsLiteral("DOMMenuBarInactive")) {  // Always from user input
     nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENU_END,
-                            accessible, PR_TRUE, eFromUserInput);
+                            accessible, eFromUserInput);
     FireCurrentFocusEvent();
   }
   else if (eventType.EqualsLiteral("ValueChange")) {
     FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
                                targetNode, AccEvent::eRemoveDupes);
   }
 #ifdef DEBUG
   else if (eventType.EqualsLiteral("mouseover")) {
--- a/accessible/src/base/nsRootAccessible.h
+++ b/accessible/src/base/nsRootAccessible.h
@@ -101,17 +101,16 @@ public:
    * @param  aForceEvent       [in] fire a focus event even if the last focused
    *                             item was the same
    * @return                    boolean -- was a focus event actually fired
    */
   PRBool FireAccessibleFocusEvent(nsAccessible *aFocusAccessible,
                                   nsINode *aFocusNode,
                                   nsIDOMEvent *aFocusEvent,
                                   PRBool aForceEvent = PR_FALSE,
-                                  PRBool aIsAsynch = PR_FALSE,
                                   EIsFromUserInput aIsFromUserInput = eAutoDetect);
 
     /**
       * Fire an accessible focus event for the current focused node,
       * if there is a focus.
       */
     void FireCurrentFocusEvent();
 
--- a/accessible/src/base/nsTextEquivUtils.cpp
+++ b/accessible/src/base/nsTextEquivUtils.cpp
@@ -232,16 +232,21 @@ nsTextEquivUtils::AppendFromAccessibleCh
 
   return rv;
 }
 
 nsresult
 nsTextEquivUtils::AppendFromAccessible(nsAccessible *aAccessible,
                                        nsAString *aString)
 {
+  // Ignore hidden accessible for name computation.
+  nsIFrame* frame = aAccessible->GetFrame();
+  if (!frame || !frame->GetStyleVisibility()->IsVisible())
+    return NS_OK;
+
   //XXX: is it necessary to care the accessible is not a document?
   if (aAccessible->IsContent()) {
     nsresult rv = AppendTextEquivFromTextContent(aAccessible->GetContent(),
                                                  aString);
     if (rv != NS_OK_NO_NAME_CLAUSE_HANDLED)
       return rv;
   }
 
--- a/accessible/src/html/nsHTMLLinkAccessible.cpp
+++ b/accessible/src/html/nsHTMLLinkAccessible.cpp
@@ -36,17 +36,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsHTMLLinkAccessible.h"
 
 #include "nsCoreUtils.h"
 
-#include "nsILink.h"
+#include "nsIEventStateManager.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLLinkAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsHTMLLinkAccessible::
   nsHTMLLinkAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
   nsHyperTextAccessibleWrap(aContent, aShell)
@@ -77,30 +77,32 @@ nsHTMLLinkAccessible::GetStateInternal(P
 
   if (mContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::name)) {
     // This is how we indicate it is a named anchor
     // In other words, this anchor can be selected as a location :)
     // There is no other better state to use to indicate this.
     *aState |= nsIAccessibleStates::STATE_SELECTABLE;
   }
 
-  nsLinkState linkState = mContent->GetLinkState();
-  if (linkState == eLinkState_NotLink || linkState == eLinkState_Unknown) {
-    // This is a either named anchor (a link with also a name attribute) or
-    // it doesn't have any attributes. Check if 'click' event handler is
-    // registered, otherwise bail out.
-    PRBool isOnclick = nsCoreUtils::HasClickListener(mContent);
-    if (!isOnclick)
-      return NS_OK;
+  nsEventStates state = mContent->IntrinsicState();
+  if (state.HasAtLeastOneOfStates(NS_EVENT_STATE_VISITED |
+                                  NS_EVENT_STATE_UNVISITED)) {
+    *aState |= nsIAccessibleStates::STATE_LINKED;
+
+    if (state.HasState(NS_EVENT_STATE_VISITED))
+      *aState |= nsIAccessibleStates::STATE_TRAVERSED;
+
+    return NS_OK;
   }
 
-  *aState |= nsIAccessibleStates::STATE_LINKED;
-
-  if (linkState == eLinkState_Visited)
-    *aState |= nsIAccessibleStates::STATE_TRAVERSED;
+  // This is a either named anchor (a link with also a name attribute) or
+  // it doesn't have any attributes. Check if 'click' event handler is
+  // registered, otherwise bail out.
+  if (nsCoreUtils::HasClickListener(mContent))
+    *aState |= nsIAccessibleStates::STATE_LINKED;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLLinkAccessible::GetValue(nsAString& aValue)
 {
   aValue.Truncate();
@@ -181,11 +183,12 @@ nsHTMLLinkAccessible::GetAnchorURI(PRUin
 // Protected members
 
 PRBool
 nsHTMLLinkAccessible::IsLinked()
 {
   if (IsDefunct())
     return PR_FALSE;
 
-  nsLinkState linkState = mContent->GetLinkState();
-  return linkState != eLinkState_NotLink && linkState != eLinkState_Unknown;
+  nsEventStates state = mContent->IntrinsicState();
+  return state.HasAtLeastOneOfStates(NS_EVENT_STATE_VISITED |
+                                     NS_EVENT_STATE_UNVISITED);
 }
--- a/accessible/src/html/nsHTMLSelectAccessible.cpp
+++ b/accessible/src/html/nsHTMLSelectAccessible.cpp
@@ -75,33 +75,28 @@ nsHTMLSelectListAccessible::GetStateInte
 {
   nsresult rv = nsAccessibleWrap::GetStateInternal(aState, aExtraState);
   NS_ENSURE_A11Y_SUCCESS(rv, rv);
 
   // As a nsHTMLSelectListAccessible we can have the following states:
   //   nsIAccessibleStates::STATE_MULTISELECTABLE
   //   nsIAccessibleStates::STATE_EXTSELECTABLE
 
-  nsCOMPtr<nsIDOMHTMLSelectElement> select(do_QueryInterface(mContent));
-  if (select) {
-    if (*aState & nsIAccessibleStates::STATE_FOCUSED) {
-      // Treat first focusable option node as actual focus, in order
-      // to avoid confusing JAWS, which needs focus on the option
-      nsCOMPtr<nsIContent> focusedOption =
-        nsHTMLSelectOptionAccessible::GetFocusedOption(mContent);
-      if (focusedOption) { // Clear focused state since it is on option
-        *aState &= ~nsIAccessibleStates::STATE_FOCUSED;
-      }
+  if (*aState & nsIAccessibleStates::STATE_FOCUSED) {
+    // Treat first focusable option node as actual focus, in order
+    // to avoid confusing JAWS, which needs focus on the option
+    nsCOMPtr<nsIContent> focusedOption =
+      nsHTMLSelectOptionAccessible::GetFocusedOption(mContent);
+    if (focusedOption) { // Clear focused state since it is on option
+      *aState &= ~nsIAccessibleStates::STATE_FOCUSED;
     }
-    PRBool multiple;
-    select->GetMultiple(&multiple);
-    if ( multiple )
-      *aState |= nsIAccessibleStates::STATE_MULTISELECTABLE |
-                 nsIAccessibleStates::STATE_EXTSELECTABLE;
   }
+  if (mContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::multiple))
+    *aState |= nsIAccessibleStates::STATE_MULTISELECTABLE |
+               nsIAccessibleStates::STATE_EXTSELECTABLE;
 
   return NS_OK;
 }
 
 PRUint32
 nsHTMLSelectListAccessible::NativeRole()
 {
   if (mParent && mParent->Role() == nsIAccessibleRole::ROLE_COMBOBOX)
@@ -117,29 +112,25 @@ bool
 nsHTMLSelectListAccessible::IsSelect()
 {
   return true;
 }
 
 bool
 nsHTMLSelectListAccessible::SelectAll()
 {
-  nsCOMPtr<nsIDOMHTMLSelectElement> selectElm(do_QueryInterface(mContent));
-  PRBool isMultiple = PR_FALSE;
-  selectElm->GetMultiple(&isMultiple);
-  return isMultiple ? nsAccessibleWrap::SelectAll() : false;
+  return mContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::multiple) ?
+           nsAccessibleWrap::SelectAll() : false;
 }
 
 bool
 nsHTMLSelectListAccessible::UnselectAll()
 {
-  nsCOMPtr<nsIDOMHTMLSelectElement> selectElm(do_QueryInterface(mContent));
-  PRBool isMultiple = PR_FALSE;
-  selectElm->GetMultiple(&isMultiple);
-  return isMultiple ? nsAccessibleWrap::UnselectAll() : false;
+  return mContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::multiple) ?
+           nsAccessibleWrap::UnselectAll() : false;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLSelectListAccessible: nsAccessible protected
 
 void
 nsHTMLSelectListAccessible::CacheChildren()
 {
@@ -669,16 +660,19 @@ nsHTMLSelectOptGroupAccessible::CacheChi
 ////////////////////////////////////////////////////////////////////////////////
 
 nsHTMLComboboxAccessible::
   nsHTMLComboboxAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
   nsAccessibleWrap(aContent, aShell)
 {
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// nsHTMLComboboxAccessible: nsAccessible
+
 PRUint32
 nsHTMLComboboxAccessible::NativeRole()
 {
   return nsIAccessibleRole::ROLE_COMBOBOX;
 }
 
 void
 nsHTMLComboboxAccessible::CacheChildren()
@@ -863,31 +857,43 @@ NS_IMETHODIMP nsHTMLComboboxAccessible::
 
 nsHTMLComboboxListAccessible::
   nsHTMLComboboxListAccessible(nsIAccessible *aParent, nsIContent *aContent,
                                nsIWeakReference *aShell) :
   nsHTMLSelectListAccessible(aContent, aShell)
 {
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// nsHTMLComboboxAccessible: nsAccessNode
+
 nsIFrame*
 nsHTMLComboboxListAccessible::GetFrame()
 {
   nsIFrame* frame = nsHTMLSelectListAccessible::GetFrame();
 
   if (frame) {
     nsIComboboxControlFrame* comboBox = do_QueryFrame(frame);
     if (comboBox) {
       return comboBox->GetDropDown();
     }
   }
 
   return nsnull;
 }
 
+bool
+nsHTMLComboboxListAccessible::IsPrimaryForNode() const
+{
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsHTMLComboboxAccessible: nsAccessible
+
 /**
   * As a nsHTMLComboboxListAccessible we can have the following states:
   *     STATE_FOCUSED
   *     STATE_FOCUSABLE
   *     STATE_INVISIBLE
   *     STATE_FLOATING
   */
 nsresult
@@ -903,24 +909,16 @@ nsHTMLComboboxListAccessible::GetStateIn
   if (comboFrame && comboFrame->IsDroppedDown())
     *aState |= nsIAccessibleStates::STATE_FLOATING;
   else
     *aState |= nsIAccessibleStates::STATE_INVISIBLE;
 
   return NS_OK;
 }
 
-NS_IMETHODIMP nsHTMLComboboxListAccessible::GetUniqueID(void **aUniqueID)
-{
-  // Since mContent is same for all tree item, use |this| pointer as the unique
-  // Id.
-  *aUniqueID = static_cast<void*>(this);
-  return NS_OK;
-}
-
 /**
   * Gets the bounds for the areaFrame.
   *     Walks the Frame tree and checks for proper frames.
   */
 void nsHTMLComboboxListAccessible::GetBoundsRect(nsRect& aBounds, nsIFrame** aBoundingFrame)
 {
   *aBoundingFrame = nsnull;
 
--- a/accessible/src/html/nsHTMLSelectAccessible.h
+++ b/accessible/src/html/nsHTMLSelectAccessible.h
@@ -221,20 +221,18 @@ class nsHTMLComboboxListAccessible : pub
 {
 public:
 
   nsHTMLComboboxListAccessible(nsIAccessible *aParent, 
                                nsIContent *aContent, 
                                nsIWeakReference* aShell);
   virtual ~nsHTMLComboboxListAccessible() {}
 
-  // nsIAccessible
-  NS_IMETHOD GetUniqueID(void **aUniqueID);
-
   // nsAccessNode
   virtual nsIFrame* GetFrame();
+  virtual bool IsPrimaryForNode() const;
 
   // nsAccessible
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
   virtual void GetBoundsRect(nsRect& aBounds, nsIFrame** aBoundingFrame);
 };
 
 #endif
--- a/accessible/src/html/nsHTMLTextAccessible.cpp
+++ b/accessible/src/html/nsHTMLTextAccessible.cpp
@@ -41,16 +41,17 @@
 
 #include "nsDocAccessible.h"
 #include "nsAccUtils.h"
 #include "nsRelUtils.h"
 #include "nsTextEquivUtils.h"
 
 #include "nsIFrame.h"
 #include "nsPresContext.h"
+#include "nsBlockFrame.h"
 #include "nsISelection.h"
 #include "nsISelectionController.h"
 #include "nsComponentManagerUtils.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLTextAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -247,23 +248,22 @@ nsHTMLOutputAccessible::GetAttributesInt
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLLIAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsHTMLLIAccessible::
-  nsHTMLLIAccessible(nsIContent *aContent, nsIWeakReference *aShell,
-                     const nsAString& aBulletText) :
+  nsHTMLLIAccessible(nsIContent* aContent, nsIWeakReference* aShell) :
   nsHyperTextAccessibleWrap(aContent, aShell)
 {
-  if (!aBulletText.IsEmpty()) {
-    mBulletAccessible = new nsHTMLListBulletAccessible(mContent, mWeakShell, 
-                                                       aBulletText);
+  nsBlockFrame* blockFrame = do_QueryFrame(GetFrame());
+  if (blockFrame && !blockFrame->BulletIsEmptyExternal()) {
+    mBulletAccessible = new nsHTMLListBulletAccessible(mContent, mWeakShell);
     if (mBulletAccessible)
       mBulletAccessible->Init();
   }
 }
 
 NS_IMPL_ISUPPORTS_INHERITED0(nsHTMLLIAccessible, nsHyperTextAccessible)
 
 void
@@ -324,44 +324,58 @@ nsHTMLLIAccessible::CacheChildren()
   nsAccessibleWrap::CacheChildren();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLListBulletAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsHTMLListBulletAccessible::
-  nsHTMLListBulletAccessible(nsIContent *aContent, nsIWeakReference *aShell,
-                             const nsAString& aBulletText) :
-    nsLeafAccessible(aContent, aShell), mBulletText(aBulletText)
+  nsHTMLListBulletAccessible(nsIContent* aContent, nsIWeakReference* aShell) :
+    nsLeafAccessible(aContent, aShell)
 {
   mBulletText += ' '; // Otherwise bullets are jammed up against list text
 }
 
-NS_IMETHODIMP
-nsHTMLListBulletAccessible::GetUniqueID(void **aUniqueID)
-{
-  // Since mContent is same as for list item, use |this| pointer as the unique
-  // id.
-  *aUniqueID = static_cast<void*>(this);
-  return NS_OK;
-}
+////////////////////////////////////////////////////////////////////////////////
+// nsHTMLListBulletAccessible: nsAccessNode
 
 void
 nsHTMLListBulletAccessible::Shutdown()
 {
   mBulletText.Truncate();
   nsLeafAccessible::Shutdown();
 }
 
+bool
+nsHTMLListBulletAccessible::IsPrimaryForNode() const
+{
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsHTMLListBulletAccessible: nsAccessible
+
 NS_IMETHODIMP
 nsHTMLListBulletAccessible::GetName(nsAString &aName)
 {
-  // Native anonymous content, ARIA can't be used.
-  aName = mBulletText;
+  aName.Truncate();
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  // Native anonymous content, ARIA can't be used. Get list bullet text.
+  nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame());
+  if (blockFrame) {
+    blockFrame->GetBulletText(aName);
+
+    // Append space otherwise bullets are jammed up against list text.
+    aName.Append(' ');
+  }
+
   return NS_OK;
 }
 
 PRUint32
 nsHTMLListBulletAccessible::NativeRole()
 {
   return nsIAccessibleRole::ROLE_STATICTEXT;
 }
@@ -376,21 +390,27 @@ nsHTMLListBulletAccessible::GetStateInte
   *aState |= nsIAccessibleStates::STATE_READONLY;
   return NS_OK;
 }
 
 nsresult
 nsHTMLListBulletAccessible::AppendTextTo(nsAString& aText, PRUint32 aStartOffset,
                                          PRUint32 aLength)
 {
-  PRUint32 maxLength = mBulletText.Length() - aStartOffset;
-  if (aLength > maxLength) {
-    aLength = maxLength;
+  nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame());
+  if (blockFrame) {
+    nsAutoString bulletText;
+    blockFrame->GetBulletText(bulletText);
+
+    PRUint32 maxLength = bulletText.Length() - aStartOffset;
+    if (aLength > maxLength)
+      aLength = maxLength;
+
+    aText += Substring(bulletText, aStartOffset, aLength);
   }
-  aText += Substring(mBulletText, aStartOffset, aLength);
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLListAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsHTMLListAccessible::
--- a/accessible/src/html/nsHTMLTextAccessible.h
+++ b/accessible/src/html/nsHTMLTextAccessible.h
@@ -125,27 +125,24 @@ public:
 };
 
 /**
  * Used for bullet of HTML list item element (for example, HTML li).
  */
 class nsHTMLListBulletAccessible : public nsLeafAccessible
 {
 public:
-  nsHTMLListBulletAccessible(nsIContent *aContent, nsIWeakReference *aShell,
-                             const nsAString& aBulletText);
-
-  // nsIAccessNode
-  NS_IMETHOD GetUniqueID(void **aUniqueID);
+  nsHTMLListBulletAccessible(nsIContent* aContent, nsIWeakReference* aShell);
 
   // nsIAccessible
   NS_IMETHOD GetName(nsAString& aName);
 
   // nsAccessNode
   virtual void Shutdown();
+  virtual bool IsPrimaryForNode() const;
 
   // nsAccessible
   virtual PRUint32 NativeRole();
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
   virtual nsresult AppendTextTo(nsAString& aText, PRUint32 aStartOffset,
                                 PRUint32 aLength);
 
 protected:
@@ -175,18 +172,17 @@ public:
 };
 
 /**
  * Used for HTML list item (e.g. HTML li).
  */
 class nsHTMLLIAccessible : public nsHyperTextAccessibleWrap
 {
 public:
-  nsHTMLLIAccessible(nsIContent *aContent, nsIWeakReference *aShell,
-                     const nsAString& aBulletText);
+  nsHTMLLIAccessible(nsIContent* aContent, nsIWeakReference* aShell);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessible
   NS_IMETHOD GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
 
   // nsAccessNode
--- a/accessible/src/msaa/nsAccessNodeWrap.cpp
+++ b/accessible/src/msaa/nsAccessNodeWrap.cpp
@@ -129,23 +129,69 @@ STDMETHODIMP nsAccessNodeWrap::QueryInte
    
   (reinterpret_cast<IUnknown*>(*ppv))->AddRef(); 
   return S_OK;
 }
 
 STDMETHODIMP
 nsAccessNodeWrap::QueryService(REFGUID guidService, REFIID iid, void** ppv)
 {
+  *ppv = nsnull;
+
   static const GUID IID_SimpleDOMDeprecated = {0x0c539790,0x12e4,0x11cf,0xb6,0x61,0x00,0xaa,0x00,0x4c,0xd6,0xd8};
+
+  // Provide a special service ID for getting the accessible for the browser tab
+  // document that contains this accessible object. If this accessible object
+  // is not inside a browser tab then the service fails with E_NOINTERFACE.
+  // A use case for this is for screen readers that need to switch context or
+  // 'virtual buffer' when focus moves from one browser tab area to another.
+  static const GUID SID_IAccessibleContentDocument = {0xa5d8e1f3,0x3571,0x4d8f,0x95,0x21,0x07,0xed,0x28,0xfb,0x07,0x2e};
+
   if (guidService != IID_ISimpleDOMNode &&
       guidService != IID_SimpleDOMDeprecated &&
       guidService != IID_IAccessible &&  guidService != IID_IAccessible2 &&
-      guidService != IID_IAccessibleApplication)
+      guidService != IID_IAccessibleApplication &&
+      guidService != SID_IAccessibleContentDocument)
     return E_INVALIDARG;
 
+  if (guidService == SID_IAccessibleContentDocument) {
+    if (iid != IID_IAccessible)
+      return E_NOINTERFACE;
+
+    nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = 
+      nsCoreUtils::GetDocShellTreeItemFor(mContent);
+    if (!docShellTreeItem)
+      return E_UNEXPECTED;
+
+    // Walk up the parent chain without crossing the boundary at which item
+    // types change, preventing us from walking up out of tab content.
+    nsCOMPtr<nsIDocShellTreeItem> root;
+    docShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(root));
+    if (!root)
+      return E_UNEXPECTED;
+
+
+    // If the item type is typeContent, we assume we are in browser tab content.
+    // Note this includes content such as about:addons, for consistency.
+    PRInt32 itemType;
+    root->GetItemType(&itemType);
+    if (itemType != nsIDocShellTreeItem::typeContent)
+      return E_NOINTERFACE;
+
+    // Make sure this is a document.
+    nsDocAccessible* docAcc = nsAccUtils::GetDocAccessibleFor(root);
+    if (!docAcc)
+      return E_UNEXPECTED;
+
+    *ppv = static_cast<IAccessible*>(docAcc);
+
+    (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
+    return NS_OK;
+  }
+
   // Can get to IAccessibleApplication from any node via QS
   if (iid == IID_IAccessibleApplication) {
     nsApplicationAccessible *applicationAcc = GetApplicationAccessible();
     if (!applicationAcc)
       return E_NOINTERFACE;
 
     nsresult rv = applicationAcc->QueryNativeInterface(iid, ppv);
     return NS_SUCCEEDED(rv) ? S_OK : E_NOINTERFACE;
@@ -206,19 +252,17 @@ STDMETHODIMP nsAccessNodeWrap::get_nodeI
 
   *aNameSpaceID = IsContent() ?
     static_cast<short>(mContent->GetNameSpaceID()) : 0;
 
   // This is a unique ID for every content node.  The 3rd party
   // accessibility application can compare this to the childID we
   // return for events such as focus events, to correlate back to
   // data nodes in their internal object model.
-  void *uniqueID;
-  GetUniqueID(&uniqueID);
-  *aUniqueID = - NS_PTR_TO_INT32(uniqueID);
+  *aUniqueID = - NS_PTR_TO_INT32(UniqueID());
 
   *aNumChildren = GetNode()->GetChildCount();
 
 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return S_OK;
 }
 
 
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -1349,22 +1349,17 @@ nsAccessibleWrap::get_localizedExtendedS
 
   return E_NOTIMPL;
 }
 
 STDMETHODIMP
 nsAccessibleWrap::get_uniqueID(long *uniqueID)
 {
 __try {
-  void *id = nsnull;
-  nsresult rv = GetUniqueID(&id);
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
-
-  *uniqueID = - reinterpret_cast<long>(id);
+  *uniqueID = - reinterpret_cast<long>(UniqueID());
   return S_OK;
 
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return E_FAIL;
 }
 
 STDMETHODIMP
 nsAccessibleWrap::get_windowHandle(HWND *aWindowHandle)
@@ -1570,70 +1565,63 @@ nsAccessibleWrap::FirePlatformEvent(AccE
 
   nsAccessible *accessible = aEvent->GetAccessible();
   if (!accessible)
     return NS_OK;
 
   if (eventType == nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED ||
       eventType == nsIAccessibleEvent::EVENT_FOCUS) {
     UpdateSystemCaret();
+
+  } else if (eventType == nsIAccessibleEvent::EVENT_REORDER) {
+    // If the accessible children are changed then drop the IEnumVariant current
+    // position of the accessible.
+    UnattachIEnumVariant();
   }
- 
+
   PRInt32 childID = GetChildIDFor(accessible); // get the id for the accessible
   if (!childID)
     return NS_OK; // Can't fire an event without a child ID
 
-  // See if we're in a scrollable area with its own window
-  nsAccessible *newAccessible = nsnull;
-  if (eventType == nsIAccessibleEvent::EVENT_HIDE) {
-    // Don't use frame from current accessible when we're hiding that
-    // accessible.
-    newAccessible = accessible->GetCachedParent();
-  } else {
-    newAccessible = accessible;
+  HWND hWnd = GetHWNDFor(accessible);
+  NS_ENSURE_TRUE(hWnd, NS_ERROR_FAILURE);
+
+  nsAutoString tag;
+  nsCAutoString id;
+  nsIContent* cnt = accessible->GetContent();
+  if (cnt) {
+    cnt->Tag()->ToString(tag);
+    nsIAtom* aid = cnt->GetID();
+    if (aid)
+      aid->ToUTF8String(id);
   }
 
-  HWND hWnd = GetHWNDFor(newAccessible);
-  NS_ENSURE_TRUE(hWnd, NS_ERROR_FAILURE);
-
-  // Gecko uses two windows for every scrollable area. One window contains
-  // scrollbars and the child window contains only the client area.
-  // Details of the 2 window system:
-  // * Scrollbar window: caret drawing window & return value for WindowFromAccessibleObject()
-  // * Client area window: text drawing window & MSAA event window
+#ifdef DEBUG_A11Y
+  printf("\n\nMSAA event: event: %d, target: %s@id='%s', childid: %d, hwnd: %d\n\n",
+         eventType, NS_ConvertUTF16toUTF8(tag).get(), id.get(),
+         childID, hWnd);
+#endif
 
   // Fire MSAA event for client area window.
   NotifyWinEvent(winEvent, hWnd, OBJID_CLIENT, childID);
-
-  // If the accessible children are changed then drop the IEnumVariant current
-  // position of the accessible.
-  if (eventType == nsIAccessibleEvent::EVENT_REORDER)
-    UnattachIEnumVariant();
-
   return NS_OK;
 }
 
 //------- Helper methods ---------
 
-PRInt32 nsAccessibleWrap::GetChildIDFor(nsIAccessible* aAccessible)
+PRInt32 nsAccessibleWrap::GetChildIDFor(nsAccessible* aAccessible)
 {
   // A child ID of the window is required, when we use NotifyWinEvent,
   // so that the 3rd party application can call back and get the IAccessible
   // the event occurred on.
 
-  void *uniqueID = nsnull;
-  nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(aAccessible));
-  if (!accessNode) {
-    return 0;
-  }
-  accessNode->GetUniqueID(&uniqueID);
-
   // Yes, this means we're only compatibible with 32 bit
   // MSAA is only available for 32 bit windows, so it's okay
-  return - NS_PTR_TO_INT32(uniqueID);
+  // XXX: bug 606080
+  return aAccessible ? - NS_PTR_TO_INT32(aAccessible->UniqueID()) : 0;
 }
 
 HWND
 nsAccessibleWrap::GetHWNDFor(nsAccessible *aAccessible)
 {
   if (!aAccessible)
     return 0;
 
--- a/accessible/src/msaa/nsAccessibleWrap.h
+++ b/accessible/src/msaa/nsAccessibleWrap.h
@@ -305,17 +305,17 @@ public: // construction, destruction
                                            VARIANT *pVarResult,
                                            EXCEPINFO *pExcepInfo,
                                            UINT *puArgErr);
 
   // nsAccessible
   virtual nsresult HandleAccEvent(AccEvent* aEvent);
 
   // Helper methods
-  static PRInt32 GetChildIDFor(nsIAccessible* aAccessible);
+  static PRInt32 GetChildIDFor(nsAccessible* aAccessible);
   static HWND GetHWNDFor(nsAccessible *aAccessible);
   static HRESULT ConvertToIA2Attributes(nsIPersistentProperties *aAttributes,
                                         BSTR *aIA2Attributes);
 
   /**
    * System caret support: update the Windows caret position. 
    * The system caret works more universally than the MSAA caret
    * For example, Window-Eyes, JAWS, ZoomText and Windows Tablet Edition use it
--- a/accessible/src/msaa/nsDocAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsDocAccessibleWrap.cpp
@@ -104,17 +104,17 @@ nsDocAccessibleWrap::GetXPAccessibleFor(
 {
   // If lVal negative then it is treated as child ID and we should look for
   // accessible through whole accessible subtree including subdocuments.
   // Otherwise we treat lVal as index in parent.
 
   if (aVarChild.vt == VT_I4 && aVarChild.lVal < 0) {
     // Convert child ID to unique ID.
     void* uniqueID = reinterpret_cast<void*>(-aVarChild.lVal);
-    return GetCachedAccessibleInSubtree(uniqueID);
+    return GetCachedAccessibleByUniqueIDInSubtree(uniqueID);
   }
 
   return nsAccessibleWrap::GetXPAccessibleFor(aVarChild);
 }
 
 STDMETHODIMP nsDocAccessibleWrap::get_URL(/* [out] */ BSTR __RPC_FAR *aURL)
 {
 __try {
--- a/accessible/src/msaa/nsWinUtils.cpp
+++ b/accessible/src/msaa/nsWinUtils.cpp
@@ -59,17 +59,17 @@ nsWinUtils::ConvertToIA2Array(nsIArray *
   nsresult rv = aGeckoArray->GetLength(&length);
   if (NS_FAILED(rv))
     return GetHRESULT(rv);
 
   if (length == 0)
     return S_FALSE;
 
   *aIA2Array =
-    static_cast<IUnknown**>(nsMemory::Alloc((length) * sizeof(IUnknown*)));
+    static_cast<IUnknown**>(::CoTaskMemAlloc((length) * sizeof(IUnknown*)));
   if (!*aIA2Array)
     return E_OUTOFMEMORY;
 
   PRUint32 idx = 0;
   for (; idx < length; ++idx) {
     nsCOMPtr<nsIWinAccessNode> winAccessNode =
       do_QueryElementAt(aGeckoArray, idx, &rv);
     if (NS_FAILED(rv))
@@ -85,17 +85,17 @@ nsWinUtils::ConvertToIA2Array(nsIArray *
   }
 
   if (NS_FAILED(rv)) {
     for (PRUint32 idx2 = 0; idx2 < idx; idx2++) {
       (*aIA2Array)[idx2]->Release();
       (*aIA2Array)[idx2] = NULL;
     }
 
-    nsMemory::Free(*aIA2Array);
+    ::CoTaskMemFree(*aIA2Array);
     return GetHRESULT(rv);
   }
 
   *aIA2ArrayLen = length;
   return S_OK;
 }
 
 void
--- a/accessible/src/xul/nsXULTreeAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeAccessible.cpp
@@ -504,25 +504,23 @@ nsXULTreeAccessible::InvalidateCache(PRI
   // Fire destroy event for removed tree items and delete them from caches.
   for (PRInt32 rowIdx = aRow; rowIdx < aRow - aCount; rowIdx++) {
 
     void* key = reinterpret_cast<void*>(rowIdx);
     nsAccessible *accessible = mAccessibleCache.GetWeak(key);
 
     if (accessible) {
       nsRefPtr<AccEvent> event =
-        new AccEvent(nsIAccessibleEvent::EVENT_HIDE, accessible, PR_FALSE);
+        new AccEvent(nsIAccessibleEvent::EVENT_HIDE, accessible);
       nsEventShell::FireEvent(event);
 
-      accessible->Shutdown();
-
-      // Remove accessible from document cache and tree cache.
+      // Shutdown and remove accessible from document cache and tree cache.
       nsDocAccessible *docAccessible = GetDocAccessible();
       if (docAccessible)
-        docAccessible->RemoveAccessNodeFromCache(accessible);
+        docAccessible->ShutdownAccessible(accessible);
 
       mAccessibleCache.Remove(key);
     }
   }
 
   // We dealt with removed tree items already however we may keep tree items
   // having row indexes greater than row count. We should remove these dead tree
   // items silently from caches.
@@ -534,22 +532,20 @@ nsXULTreeAccessible::InvalidateCache(PRI
   PRInt32 oldRowCount = newRowCount - aCount;
 
   for (PRInt32 rowIdx = newRowCount; rowIdx < oldRowCount; ++rowIdx) {
 
     void *key = reinterpret_cast<void*>(rowIdx);
     nsAccessible *accessible = mAccessibleCache.GetWeak(key);
 
     if (accessible) {
-      accessible->Shutdown();
-
-      // Remove accessible from document cache and tree cache.
+      // Shutdown and remove accessible from document cache and tree cache.
       nsDocAccessible *docAccessible = GetDocAccessible();
       if (docAccessible)
-        docAccessible->RemoveAccessNodeFromCache(accessible);
+        docAccessible->ShutdownAccessible(accessible);
 
       mAccessibleCache.Remove(key);
     }
   }
 }
 
 void
 nsXULTreeAccessible::TreeViewInvalidated(PRInt32 aStartRow, PRInt32 aEndRow,
@@ -605,28 +601,28 @@ nsXULTreeAccessible::TreeViewChanged()
 {
   if (IsDefunct())
     return;
 
   // Fire only notification destroy/create events on accessible tree to lie to
   // AT because it should be expensive to fire destroy events for each tree item
   // in cache.
   nsRefPtr<AccEvent> eventDestroy =
-    new AccEvent(nsIAccessibleEvent::EVENT_HIDE, this, PR_FALSE);
+    new AccEvent(nsIAccessibleEvent::EVENT_HIDE, this);
   if (!eventDestroy)
     return;
 
   FirePlatformEvent(eventDestroy);
 
   ClearCache(mAccessibleCache);
 
   mTree->GetView(getter_AddRefs(mTreeView));
 
   nsRefPtr<AccEvent> eventCreate =
-    new AccEvent(nsIAccessibleEvent::EVENT_SHOW, this, PR_FALSE);
+    new AccEvent(nsIAccessibleEvent::EVENT_SHOW, this);
   if (!eventCreate)
     return;
 
   FirePlatformEvent(eventCreate);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeAccessible: protected implementation
@@ -658,28 +654,16 @@ nsXULTreeItemAccessibleBase::
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeItemAccessibleBase: nsISupports implementation
 
 NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeItemAccessibleBase,
                              nsAccessible,
                              nsXULTreeItemAccessibleBase)
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsXULTreeItemAccessibleBase: nsIAccessNode implementation
-
-NS_IMETHODIMP
-nsXULTreeItemAccessibleBase::GetUniqueID(void **aUniqueID)
-{
-  // Since mContent is same for all tree items and tree itself, use |this|
-  // pointer as the unique ID.
-  *aUniqueID = static_cast<void*>(this);
-  return NS_OK;
-}
-
-////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeItemAccessibleBase: nsIAccessible implementation
 
 NS_IMETHODIMP
 nsXULTreeItemAccessibleBase::GetFocusedChild(nsIAccessible **aFocusedChild) 
 {
   NS_ENSURE_ARG_POINTER(aFocusedChild);
   *aFocusedChild = nsnull;
 
@@ -883,16 +867,22 @@ nsXULTreeItemAccessibleBase::Shutdown()
 {
   mTree = nsnull;
   mTreeView = nsnull;
   mRow = -1;
 
   nsAccessibleWrap::Shutdown();
 }
 
+bool
+nsXULTreeItemAccessibleBase::IsPrimaryForNode() const
+{
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeItemAccessibleBase: nsAccessible public methods
 
 // nsIAccessible::groupPosition
 nsresult
 nsXULTreeItemAccessibleBase::GroupPosition(PRInt32 *aGroupLevel,
                                            PRInt32 *aSimilarItemsInGroup,
                                            PRInt32 *aPositionInGroup)
--- a/accessible/src/xul/nsXULTreeAccessible.h
+++ b/accessible/src/xul/nsXULTreeAccessible.h
@@ -176,19 +176,16 @@ public:
 
   nsXULTreeItemAccessibleBase(nsIContent *aContent, nsIWeakReference *aShell,
                               nsAccessible *aParent, nsITreeBoxObject *aTree,
                               nsITreeView *aTreeView, PRInt32 aRow);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
-  // nsIAccessNode
-  NS_IMETHOD GetUniqueID(void **aUniqueID);
-
   // nsIAccessible
   NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
 
   NS_IMETHOD GetBounds(PRInt32 *aX, PRInt32 *aY,
                        PRInt32 *aWidth, PRInt32 *aHeight);
 
   NS_IMETHOD SetSelected(PRBool aSelect); 
   NS_IMETHOD TakeFocus();
@@ -202,16 +199,17 @@ public:
 
   NS_IMETHOD GetNumActions(PRUint8 *aCount);
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD DoAction(PRUint8 aIndex);
 
   // nsAccessNode
   virtual PRBool IsDefunct();
   virtual void Shutdown();
+  virtual bool IsPrimaryForNode() const;
 
   // nsAccessible
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
   virtual PRInt32 GetIndexInParent()
     { return mParent ? mParent->GetCachedChildCount() + mRow : -1; }
 
   // nsXULTreeItemAccessibleBase
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_XULTREEITEMBASEACCESSIBLE_IMPL_CID)
--- a/accessible/src/xul/nsXULTreeGridAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeGridAccessible.cpp
@@ -800,28 +800,16 @@ nsXULTreeGridCellAccessible(nsIContent *
 // nsXULTreeGridCellAccessible: nsISupports implementation
 
 NS_IMPL_ISUPPORTS_INHERITED2(nsXULTreeGridCellAccessible,
                              nsLeafAccessible,
                              nsIAccessibleTableCell,
                              nsXULTreeGridCellAccessible)
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsXULTreeGridCellAccessible: nsIAccessNode implementation
-
-NS_IMETHODIMP
-nsXULTreeGridCellAccessible::GetUniqueID(void **aUniqueID)
-{
-  NS_ENSURE_ARG_POINTER(aUniqueID);
-  *aUniqueID = static_cast<void*>(this);
-
-  return NS_OK;
-}
-
-////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeGridCellAccessible: nsIAccessible implementation
 
 NS_IMETHODIMP
 nsXULTreeGridCellAccessible::GetFocusedChild(nsIAccessible **aFocusedChild) 
 {
   NS_ENSURE_ARG_POINTER(aFocusedChild);
   *aFocusedChild = nsnull;
 
@@ -1119,16 +1107,22 @@ nsXULTreeGridCellAccessible::Init()
   if (type == nsITreeColumn::TYPE_CHECKBOX)
     mTreeView->GetCellValue(mRow, mColumn, mCachedTextEquiv);
   else
     mTreeView->GetCellText(mRow, mColumn, mCachedTextEquiv);
 
   return PR_TRUE;
 }
 
+bool
+nsXULTreeGridCellAccessible::IsPrimaryForNode() const
+{
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeGridCellAccessible: nsAccessible public implementation
 
 nsresult
 nsXULTreeGridCellAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
   NS_ENSURE_ARG_POINTER(aAttributes);
 
--- a/accessible/src/xul/nsXULTreeGridAccessible.h
+++ b/accessible/src/xul/nsXULTreeGridAccessible.h
@@ -136,19 +136,16 @@ public:
   nsXULTreeGridCellAccessible(nsIContent *aContent, nsIWeakReference *aShell,
                               nsXULTreeGridRowAccessible *aRowAcc,
                               nsITreeBoxObject *aTree, nsITreeView *aTreeView,
                               PRInt32 aRow, nsITreeColumn* aColumn);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
-  // nsIAccessNode
-  NS_IMETHOD GetUniqueID(void **aUniqueID);
-
   // nsIAccessible
   NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
 
   NS_IMETHOD GetName(nsAString& aName);
   NS_IMETHOD GetBounds(PRInt32 *aX, PRInt32 *aY,
                        PRInt32 *aWidth, PRInt32 *aHeight);
 
   NS_IMETHOD GetNumActions(PRUint8 *aCount);
@@ -156,16 +153,17 @@ public:
   NS_IMETHOD DoAction(PRUint8 aIndex);
 
   // nsIAccessibleTableCell
   NS_DECL_NSIACCESSIBLETABLECELL
 
   // nsAccessNode
   virtual PRBool IsDefunct();
   virtual PRBool Init();
+  virtual bool IsPrimaryForNode() const;
 
   // nsAccessible
   virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
   virtual PRUint32 NativeRole();
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
   virtual PRInt32 GetIndexInParent() { return GetColumnIndex(); }
 
   // nsXULTreeGridCellAccessible
--- a/accessible/tests/mochitest/Makefile.in
+++ b/accessible/tests/mochitest/Makefile.in
@@ -47,16 +47,17 @@ DIRS	= \
   attributes \
   events \
   hyperlink \
   relations \
   selectable \
   states \
   table \
   tree \
+  treeupdate \
   $(null)
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =\
 		formimage.png \
 		letters.gif \
--- a/accessible/tests/mochitest/actions/Makefile.in
+++ b/accessible/tests/mochitest/actions/Makefile.in
@@ -46,14 +46,15 @@ include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =\
 		test_anchors.html \
 		test_aria.html \
 		test_general.html \
 		test_general.xul \
 		test_inputs.html \
+		test_link.html \
 		test_tree.xul \
 		test_treegrid.xul \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
--- a/accessible/tests/mochitest/actions/test_link.html
+++ b/accessible/tests/mochitest/actions/test_link.html
@@ -14,57 +14,97 @@
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
   <script type="application/javascript"
           src="../actions.js"></script>
 
   <script type="application/javascript">
+    function getAnchorTargetDocumentAcc()
+    {
+      var thisTabDocAcc = getTabDocAccessible();
+      var thisDocTabPanelAcc = thisTabDocAcc.parent.parent;
+      var tabPanelsAcc = thisDocTabPanelAcc.parent;
+      var newDocTabPanelAcc = tabPanelsAcc.lastChild.firstChild;
+      return newDocTabPanelAcc.firstChild;
+    }
+
+    function linkChecker(aID)
+    {
+      this.type = EVENT_DOCUMENT_LOAD_COMPLETE;
+      this.__defineGetter__("target", getAnchorTargetDocumentAcc);
+
+      this.check = function linkChecker_check()
+      {
+        var anchorTargetWindow =
+          getAccessible(getAnchorTargetDocumentAcc(), [nsIAccessibleDocument]).
+          window;
+        anchorTargetWindow.close();
+      }
+
+      this.getID = function linkChecker_getID()
+      {
+        return "link '" + aID + "' states check ";
+      }
+    }
+
+    //gA11yEventDumpID = "eventdump"; // debug stuff
+
     function doTest()
     {
       var actionsArray = [
         {
           ID: "link1",
           actionName: "jump",
-          events: CLICK_EVENTS
+          events: CLICK_EVENTS,
+          eventSeq: [
+            new linkChecker("link1")
+          ]
         },
         {
           ID: "img1",
-          actionName: "click",
-          events: CLICK_EVENTS
+          targetID: "link1",
+          actionName: "jump",
+          events: CLICK_EVENTS,
+          eventSeq: [
+            new linkChecker("link1")
+          ]
         },
         {
           ID: "link2",
           actionName: "click",
           events: CLICK_EVENTS
         },
         {
           ID: "img2",
-          actionName: "click",
+          targetID: "link2",
+          actionName: "jump",
           events: CLICK_EVENTS
         },
         {
           ID: "link3",
           actionName: "click",
           events: CLICK_EVENTS
         },
         {
           ID: "img3",
-          actionName: "click",
+          targetID: "link3",
+          actionName: "jump",
           events: CLICK_EVENTS
         },
         {
           ID: "link4",
           actionName: "click",
           events: CLICK_EVENTS
         },
         {
           ID: "img4",
-          actionName: "click",
+          targetID: "link4",
+          actionName: "jump",
           events: CLICK_EVENTS
         }
       ];
       testActions(actionsArray);
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
@@ -78,22 +118,24 @@
      title="Expose click action if mouseup and mousedown are registered">
     Mozilla Bug 423409
   </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
-  <a href="http://mozilla.org" id="link1">
+  <a href="about:mozilla" id="link1" target="_blank">
     <img src="../moz.png" id="img1">
   </a>
   <a id="link2" onmousedown="">
     <img src="../moz.png" id="img2">
   </a>
   <a id="link3" onclick="">
     <img src="../moz.png" id="img3">
   </a>
   <a id="link4" onmouseup="">
     <img src="../moz.png" id="img4">
   </a>
+
+  <div id="eventdump"></div>
 </body>
 </html>
--- a/accessible/tests/mochitest/attributes/test_text.html
+++ b/accessible/tests/mochitest/attributes/test_text.html
@@ -424,21 +424,18 @@
       ID = "area13";
       defAttrs = buildDefaultTextAttrs(ID, "12pt");
       attrs = { };
       testTextAttrs(ID, 0, attrs, defAttrs, 0, 0);
 
       ID = "area14";
       defAttrs = buildDefaultTextAttrs(ID, kInputFontSize);
 
-      // XXX: While we expose text leaf accessibles for placeholder we grab its
-      // style, bug 545817.
-      // attrs = { color: "rgb(109, 109, 109)" };
-      //testTextAttrs(ID, 0, attrs, defAttrs, 0, 0);
-      todo(false, "enable commented tests when bug 545817 is fixed");
+      attrs = { };
+      testTextAttrs(ID, 0, attrs, defAttrs, 0, 0);
 
       //////////////////////////////////////////////////////////////////////////
       // area15, embed char tests, "*plain*plain**bold*bold*"
       ID = "area15";
       defAttrs = buildDefaultTextAttrs(ID, "12pt");
 
       // p
       testTextAttrs(ID, 0, { }, { }, 0, 1);
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -46,61 +46,27 @@ const nsIDOMHTMLDocument = Components.in
 const nsIDOMNode = Components.interfaces.nsIDOMNode;
 const nsIDOMNSHTMLElement = Components.interfaces.nsIDOMNSHTMLElement;
 const nsIDOMWindow = Components.interfaces.nsIDOMWindow;
 const nsIDOMXULElement = Components.interfaces.nsIDOMXULElement;
 
 const nsIPropertyElement = Components.interfaces.nsIPropertyElement;
 
 ////////////////////////////////////////////////////////////////////////////////
-// States
-
-const STATE_BUSY = nsIAccessibleStates.STATE_BUSY;
-const STATE_CHECKED = nsIAccessibleStates.STATE_CHECKED;
-const STATE_CHECKABLE = nsIAccessibleStates.STATE_CHECKABLE;
-const STATE_COLLAPSED = nsIAccessibleStates.STATE_COLLAPSED;
-const STATE_EXPANDED = nsIAccessibleStates.STATE_EXPANDED;
-const STATE_EXTSELECTABLE = nsIAccessibleStates.STATE_EXTSELECTABLE;
-const STATE_FOCUSABLE = nsIAccessibleStates.STATE_FOCUSABLE;
-const STATE_FOCUSED = nsIAccessibleStates.STATE_FOCUSED;
-const STATE_HASPOPUP = nsIAccessibleStates.STATE_HASPOPUP;
-const STATE_INVALID = nsIAccessibleStates.STATE_INVALID;
-const STATE_LINKED = nsIAccessibleStates.STATE_LINKED;
-const STATE_MIXED = nsIAccessibleStates.STATE_MIXED;
-const STATE_MULTISELECTABLE = nsIAccessibleStates.STATE_MULTISELECTABLE;
-const STATE_OFFSCREEN = nsIAccessibleStates.STATE_OFFSCREEN;
-const STATE_PRESSED = nsIAccessibleStates.STATE_PRESSED;
-const STATE_READONLY = nsIAccessibleStates.STATE_READONLY;
-const STATE_REQUIRED = nsIAccessibleStates.STATE_REQUIRED;
-const STATE_SELECTABLE = nsIAccessibleStates.STATE_SELECTABLE;
-const STATE_SELECTED = nsIAccessibleStates.STATE_SELECTED;
-const STATE_TRAVERSED = nsIAccessibleStates.STATE_TRAVERSED;
-const STATE_UNAVAILABLE = nsIAccessibleStates.STATE_UNAVAILABLE;
-
-const EXT_STATE_ACTIVE = nsIAccessibleStates.EXT_STATE_ACTIVE;
-const EXT_STATE_DEFUNCT = nsIAccessibleStates.EXT_STATE_DEFUNCT;
-const EXT_STATE_EDITABLE = nsIAccessibleStates.EXT_STATE_EDITABLE;
-const EXT_STATE_EXPANDABLE = nsIAccessibleStates.EXT_STATE_EXPANDABLE;
-const EXT_STATE_HORIZONTAL = nsIAccessibleStates.EXT_STATE_HORIZONTAL;
-const EXT_STATE_MULTI_LINE = nsIAccessibleStates.EXT_STATE_MULTI_LINE;
-const EXT_STATE_SINGLE_LINE = nsIAccessibleStates.EXT_STATE_SINGLE_LINE;
-const EXT_STATE_SUPPORTS_AUTOCOMPLETION = 
-      nsIAccessibleStates.EXT_STATE_SUPPORTS_AUTOCOMPLETION;
-const EXT_STATE_VERTICAL = nsIAccessibleStates.EXT_STATE_VERTICAL;
-
-////////////////////////////////////////////////////////////////////////////////
 // OS detect
 const MAC = (navigator.platform.indexOf("Mac") != -1)? true : false;
 const LINUX = (navigator.platform.indexOf("Linux") != -1)? true : false;
 const SOLARIS = (navigator.platform.indexOf("SunOS") != -1)? true : false;
 const WIN = (navigator.platform.indexOf("Win") != -1)? true : false;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Accessible general
 
+const STATE_BUSY = nsIAccessibleStates.STATE_BUSY;
+
 const kEmbedChar = String.fromCharCode(0xfffc);
 
 /**
  * nsIAccessibleRetrieval, initialized when test is loaded.
  */
 var gAccRetrieval = null;
 
 /**
@@ -260,26 +226,58 @@ function getAccessible(aAccOrElmOrID, aI
 function isAccessible(aAccOrElmOrID, aInterfaces)
 {
   return getAccessible(aAccOrElmOrID, aInterfaces, null,
                        DONOTFAIL_IF_NO_ACC | DONOTFAIL_IF_NO_INTERFACE) ?
     true : false;
 }
 
 /**
+ * Return an accessible that contains the DOM node for the given identifier.
+ */
+function getContainerAccessible(aAccOrElmOrID)
+{
+  var node = getNode(aAccOrElmOrID);
+  if (!node)
+    return null;
+
+  while ((node = node.parentNode) && !isAccessible(node));
+  return node ? getAccessible(node) : null;
+}
+
+/**
  * Return root accessible for the given identifier.
  */
 function getRootAccessible(aAccOrElmOrID)
 {
   var acc = getAccessible(aAccOrElmOrID ? aAccOrElmOrID : document,
                           [nsIAccessNode]);
   return acc ? acc.rootDocument.QueryInterface(nsIAccessible) : null;
 }
 
 /**
+ * Return tab document accessible the given accessible is contained by.
+ */
+function getTabDocAccessible(aAccOrElmOrID)
+{
+  var acc = getAccessible(aAccOrElmOrID ? aAccOrElmOrID : document,
+                          [nsIAccessNode]);
+
+  var docAcc = acc.document.QueryInterface(nsIAccessible);
+  var containerDocAcc = docAcc.parent.QueryInterface(nsIAccessNode).document;
+
+  // Test is running is stand-alone mode.
+  if (acc.rootDocument == containerDocAcc)
+    return docAcc;
+
+  // In the case of running all tests together.
+  return containerDocAcc.QueryInterface(nsIAccessible);
+}
+
+/**
  * Return application accessible.
  */
 function getApplicationAccessible()
 {
   return gAccRetrieval.getApplicationAccessible().
     QueryInterface(nsIAccessibleApplication);
 }
 
@@ -537,16 +535,25 @@ function prettyName(aIdentifier)
     var msg = "[" + getNodePrettyName(acc.DOMNode);
     try {
       msg += ", role: " + roleToString(acc.role);
       if (acc.name)
         msg += ", name: '" + acc.name + "'";
     } catch (e) {
       msg += "defunct";
     }
+
+    if (acc) {
+      var exp = /native\s*@\s*(0x[a-f0-9]+)/g;
+      var match = exp.exec(acc.valueOf());
+      if (match)
+        msg += ", address: " + match[1];
+      else
+        msg += ", address: " + acc.valueOf();
+    }
     msg += "]";
 
     return msg;
   }
 
   if (aIdentifier instanceof nsIDOMNode)
     return getNodePrettyName(aIdentifier);
 
@@ -566,19 +573,21 @@ function initialize()
     getService(nsIAccessibleRetrieval);
 }
 
 addLoadEvent(initialize);
 
 function getNodePrettyName(aNode)
 {
   try {
-    if (aNode.nodeType == nsIDOMNode.ELEMENT_NODE && aNode.hasAttribute("id"))
-      return " '" + aNode.getAttribute("id") + "' ";
-
     if (aNode.nodeType == nsIDOMNode.DOCUMENT_NODE)
       return " 'document node' ";
 
-    return " '" + aNode.localName + " node' ";
+    var name = " '" + aNode.localName;
+    if (aNode.nodeType == nsIDOMNode.ELEMENT_NODE && aNode.hasAttribute("id"))
+      name += "@id='" + aNode.getAttribute("id") + "'";
+
+    name += " node' "
+    return name;
   } catch (e) {
-    return "no node info";
+    return "' no node info '";
   }
 }
--- a/accessible/tests/mochitest/events.js
+++ b/accessible/tests/mochitest/events.js
@@ -3,16 +3,18 @@
 
 const EVENT_ALERT = nsIAccessibleEvent.EVENT_ALERT;
 const EVENT_DOCUMENT_LOAD_COMPLETE = nsIAccessibleEvent.EVENT_DOCUMENT_LOAD_COMPLETE;
 const EVENT_DOCUMENT_RELOAD = nsIAccessibleEvent.EVENT_DOCUMENT_RELOAD;
 const EVENT_DOCUMENT_LOAD_STOPPED = nsIAccessibleEvent.EVENT_DOCUMENT_LOAD_STOPPED;
 const EVENT_HIDE = nsIAccessibleEvent.EVENT_HIDE;
 const EVENT_FOCUS = nsIAccessibleEvent.EVENT_FOCUS;
 const EVENT_NAME_CHANGE = nsIAccessibleEvent.EVENT_NAME_CHANGE;
+const EVENT_MENUPOPUP_START = nsIAccessibleEvent.EVENT_MENUPOPUP_START;
+const EVENT_MENUPOPUP_END = nsIAccessibleEvent.EVENT_MENUPOPUP_END;
 const EVENT_REORDER = nsIAccessibleEvent.EVENT_REORDER;
 const EVENT_SCROLLING_START = nsIAccessibleEvent.EVENT_SCROLLING_START;
 const EVENT_SELECTION_ADD = nsIAccessibleEvent.EVENT_SELECTION_ADD;
 const EVENT_SELECTION_WITHIN = nsIAccessibleEvent.EVENT_SELECTION_WITHIN;
 const EVENT_SHOW = nsIAccessibleEvent.EVENT_SHOW;
 const EVENT_STATE_CHANGE = nsIAccessibleEvent.EVENT_STATE_CHANGE;
 const EVENT_TEXT_CARET_MOVED = nsIAccessibleEvent.EVENT_TEXT_CARET_MOVED;
 const EVENT_TEXT_INSERTED = nsIAccessibleEvent.EVENT_TEXT_INSERTED;
@@ -549,17 +551,19 @@ function eventQueue(aEventType)
     container.appendChild(text1);
 
     var styledNode = document.createElement(inlineTagName);
     if (aMatch) {
       styledNode.setAttribute("style", "color: blue;");
       styledNode.textContent = "matched";
 
       // Dump matched events into console.
-      dump("\n*****\nEQ matched: " + eventTypeToString(currType) + "\n*****\n");
+      if (gA11yEventDumpToConsole)
+        dump("\n*****\nEQ matched: " + eventTypeToString(currType) + "\n*****\n");
+
     } else {
       styledNode.textContent = "expected";
     }
     container.appendChild(styledNode);
 
     var info = " event, type: ";
     info += (typeof currType == "string") ?
       currType : eventTypeToString(currType);
@@ -927,16 +931,19 @@ var gA11yEventObserver =
         }
 
         info += ". Target: " + prettyName(event.accessible);
 
         if (listenersArray)
           info += ". Listeners count: " + listenersArray.length;
 
         eventFromDumpArea = false;
+
+        if (gA11yEventDumpToConsole)
+          dump("\n" + info + "\n");
         dumpInfoToDOM(info);
       }
     }
 
     // Do not notify listeners if event is result of event log changes.
     if (!listenersArray || eventFromDumpArea)
       return;
 
--- a/accessible/tests/mochitest/events/Makefile.in
+++ b/accessible/tests/mochitest/events/Makefile.in
@@ -49,17 +49,18 @@ include $(topsrcdir)/config/rules.mk
 		docload_wnd.html \
 		docload_wnd.xul \
 		focus.html \
 		scroll.html \
 		test_aria_alert.html \
 		test_aria_statechange.html \
 		test_attrs.html \
 		test_caretmove.html \
-	$(warning	test_coalescence.html temporarily disabled) \
+		test_coalescence.html \
+		test_contextmenu.html \
 		test_docload.html \
 		test_docload.xul \
 		test_dragndrop.html \
 		test_flush.html \
 		test_focus.html \
 		test_focus.xul \
 		test_focus_name.html \
 		test_focusdoc.html \
--- a/accessible/tests/mochitest/events/test_coalescence.html
+++ b/accessible/tests/mochitest/events/test_coalescence.html
@@ -359,16 +359,21 @@
 </head>
 
 <body>
 
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=513213"
      title="coalesce events when new event is appended to the queue">
     Mozilla Bug 513213
+  </a><br>
+  <a target="_blank"
+     title="Rework accessible tree update code"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275">
+    Mozilla Bug 570275
   </a>
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
   <div id="eventdump"></div>
 
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/events/test_contextmenu.html
@@ -0,0 +1,141 @@
+<html>
+
+<head>
+  <title>Context menu tests</title>
+
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
+          src="../states.js"></script>
+  <script type="application/javascript"
+          src="../events.js"></script>
+
+  <script type="application/javascript">
+    ////////////////////////////////////////////////////////////////////////////
+    // Invokers
+
+    function showContextMenu(aID)
+    {
+      this.DOMNode = getNode(aID);
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_MENUPOPUP_START, getContextMenuNode()),
+      ];
+
+      this.invoke = function showContextMenu_invoke()
+      {
+        synthesizeMouse(this.DOMNode, 4, 4, { type: "contextmenu", button: 2 });
+      }
+
+      this.getID = function showContextMenu_getID()
+      {
+        return "show context menu";
+      }
+    }
+
+    function selectMenuItem()
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_FOCUS, getFocusedMenuItem)
+      ];
+
+      this.invoke = function selectMenuItem_invoke()
+      {
+        synthesizeKey("VK_DOWN", { });
+      }
+
+      this.getID = function selectMenuItem_getID()
+      {
+        return "select first menuitem";
+      }
+    }
+
+    function closeContextMenu(aID)
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_MENUPOPUP_END,
+                           getAccessible(getContextMenuNode()))
+      ];
+
+      this.invoke = function closeContextMenu_invoke()
+      {
+        synthesizeKey("VK_ESCAPE", { });
+      }
+
+      this.getID = function closeContextMenu_getID()
+      {
+        return "close context menu";
+      }
+    }
+
+    function getContextMenuNode()
+    {
+      return getRootAccessible().DOMDocument.
+        getElementById("contentAreaContextMenu");
+    }
+
+    function getFocusedMenuItem()
+    {
+      var menu = getAccessible(getAccessible(getContextMenuNode()));
+      for (var idx = 0; idx < menu.childCount; idx++) {
+        var item = menu.getChildAt(idx);
+
+        if (hasState(item, STATE_FOCUSED))
+          return getAccessible(item, [nsIAccessNode]);
+      }
+      return null;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Do tests
+
+    var gQueue = null;
+    //gA11yEventDumpID = "eventdump"; // debug stuff
+    //gA11yEventDumpToConsole = true;
+
+    function doTests()
+    {
+      gQueue = new eventQueue();
+
+      gQueue.push(new showContextMenu("input"));
+      gQueue.push(new selectMenuItem());
+      gQueue.push(new closeContextMenu());
+
+      gQueue.invoke(); // Will call SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTests);
+  </script>
+</head>
+
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=580535"
+     title="Broken accessibility in context menus">
+    Mozilla Bug 580535
+  </a><br>
+
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <input id="input">
+
+  <div id="eventdump"></div>
+</body>
+</html>
--- a/accessible/tests/mochitest/events/test_focus.html
+++ b/accessible/tests/mochitest/events/test_focus.html
@@ -53,21 +53,44 @@
       ];
 
       this.getID = function focusElmWhileSubdocIsFocused_getID()
       {
         return "Focus element while subdocument is focused " + prettyName(aID);
       }
     }
 
+    function showNFocusAlertDialog()
+    {
+      this.ID = "alertdialog";
+      this.DOMNode = getNode(this.ID);
+
+      this.invoke = function showNFocusAlertDialog_invoke()
+      {
+        document.getElementById(this.ID).style.display = 'block';
+        document.getElementById(this.ID).focus();
+        todo(false, "Enable show event handling when bug 422744 is fixed.");
+      }
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_FOCUS, this.DOMNode),
+        // new invokerChecker(EVENT_SHOW, this.DOMNode)
+      ];
+
+      this.getID = function showNFocusAlertDialog_getID()
+      {
+        return "Show and focus alert dialog " + prettyName(this.ID);
+      }
+    }
+
     /**
      * Do tests.
      */
 
-    // gA11yEventDumpID = "eventdump"; // debug stuff
+    //gA11yEventDumpID = "eventdump"; // debug stuff
 
     var gQueue = null;
 
     function doTests()
     {
       gQueue = new eventQueue(EVENT_FOCUS);
 
       gQueue.push(new synthFocus("editablearea"));
@@ -77,16 +100,18 @@
       gQueue.push(new openCloseDialog("button"));
 
       var frameNode = getNode("editabledoc");
       gQueue.push(new synthFocusOnFrame(frameNode));
       gQueue.push(new openCloseDialog(frameNode.contentDocument));
 
       gQueue.push(new focusElmWhileSubdocIsFocused("button"));
 
+      gQueue.push(new showNFocusAlertDialog());
+
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTests);
   </script>
 </head>
 
@@ -97,21 +122,33 @@
      title="focus is not fired for focused document when switching between windows">
     Mozilla Bug 551679
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=352220"
      title=" Inconsistent focus events when returning to a document frame">
     Mozilla Bug 352220
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=580464"
+     title="Accessible focus incorrect after JS focus() but correct after switching apps or using menu bar">
+    Mozilla Bug 580464
+  </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <div id="editablearea" contentEditable="true">editable area</div>
   <input id="textbox">
   <button id="button">button</button>
   <iframe id="editabledoc" src="focus.html"></iframe>
 
+  <div id="alertdialog" style="display: none" tabindex="-1" role="alertdialog" aria-labelledby="title2" aria-describedby="desc2">
+    <div id="title2">Blah blah</div>
+    <div id="desc2">Woof woof woof.</div>
+    <button>Close</button>
+  </div>
+
+
   <div id="eventdump"></div>
 </body>
 </html>
--- a/accessible/tests/mochitest/events/test_focus.xul
+++ b/accessible/tests/mochitest/events/test_focus.xul
@@ -36,17 +36,17 @@
         return prettyName(aNodeOrID) + " click menu item";
       }
     }
     
     /**
      * Do tests.
      */
 
-    // gA11yEventDumpID = "eventdump"; // debug stuff
+    //gA11yEventDumpID = "eventdump"; // debug stuff
 
     var gQueue = null;
 
     function doTests()
     {
       // Test focus events.
       gQueue = new eventQueue(nsIAccessibleEvent.EVENT_FOCUS);
 
--- a/accessible/tests/mochitest/events/test_mutation.html
+++ b/accessible/tests/mochitest/events/test_mutation.html
@@ -225,26 +225,27 @@
      */
     function cloneAndReplaceInDOM(aNodeOrID)
     {
       this.__proto__ = new mutateA11yTree(aNodeOrID, kHideAndShowEvents,
                                           false);
 
       this.invoke = function cloneAndReplaceInDOM_invoke()
       {
-        var newElm = this.DOMNode.cloneNode(true);
-        newElm.removeAttribute('id');
-        this.eventSeq[1][1] = newElm;
-        this.DOMNode.parentNode.replaceChild(newElm, this.DOMNode);
+        this.DOMNode.parentNode.replaceChild(this.newElm, this.DOMNode);
       }
 
       this.getID = function cloneAndReplaceInDOM_getID()
       {
         return aNodeOrID + " clone and replace in DOM.";
       }
+
+      this.newElm = this.DOMNode.cloneNode(true);
+      this.newElm.removeAttribute('id');
+      this.setTarget(kShowEvent, this.newElm);
     }
 
     /**
      * Target getters.
      */
     function getFirstChild(aNode)
     {
       return [aNode.firstChild];
@@ -274,49 +275,36 @@
     {
       return aNode.parentNode;
     }
 
     /**
      * Do tests.
      */
     var gQueue = null;
-    // gA11yEventDumpID = "eventdump"; // debug stuff
+    //gA11yEventDumpID = "eventdump"; // debug stuff
 
     function doTests()
     {
       gQueue = new eventQueue();
 
       // Show/hide events by changing of display style of accessible DOM node
       // from 'inline' to 'none', 'none' to 'inline'.
       var id = "link1";
       getAccessible(id); // ensure accessible is created
       gQueue.push(new changeStyle(id, "display", "none", kHideEvents));
       gQueue.push(new changeStyle(id, "display", "inline", kShowEvents));
 
-      // Show/hide events by changing of visibility style of accessible DOM node
-      // from 'visible' to 'hidden', 'hidden' to 'visible'.
-      var id = "link2";
-      getAccessible(id);
-      gQueue.push(new changeStyle(id, "visibility", "hidden", kHideEvents));
-      gQueue.push(new changeStyle(id, "visibility", "visible", kShowEvents));
-
       // Show/hide events by changing of display style of accessible DOM node
       // from 'inline' to 'block', 'block' to 'inline'.
       var id = "link3";
       getAccessible(id); // ensure accessible is created
       gQueue.push(new changeStyle(id, "display", "block", kHideAndShowEvents));
       gQueue.push(new changeStyle(id, "display", "inline", kHideAndShowEvents));
 
-      // Show/hide events by changing of visibility style of accessible DOM node
-      // from 'collapse' to 'visible', 'visible' to 'collapse'.
-      var id = "link4";
-      gQueue.push(new changeStyle(id, "visibility", "visible", kShowEvents));
-      gQueue.push(new changeStyle(id, "visibility", "collapse", kHideEvents));
-
       // Show/hide events by adding new accessible DOM node and removing old one.
       var id = "link5";
       gQueue.push(new cloneAndAppendToDOM(id));
       gQueue.push(new removeFromDOM(id));
 
       // No show/hide events by adding new not accessible DOM node and removing
       // old one, no reorder event for their parent.
       var id = "child1";
@@ -342,46 +330,48 @@
 
       // Hide events for accessible children of unaccessible removed DOM node
       // and reorder event for its parent.
       gQueue.push(new removeFromDOM("child4", kHideEvents,
                                     getNEnsureChildren, getParent));
 
       // Show/hide events by creating new accessible DOM node and replacing
       // old one.
-      // XXX: bug 472810
-      // gQueue.push(new cloneAndReplaceInDOM("link6"));
+      getAccessible("link6"); // ensure accessible is created
+      gQueue.push(new cloneAndReplaceInDOM("link6"));
 
       // Show/hide events by changing class name on the parent node.
       gQueue.push(new changeClass("container2", "link7", "", kShowEvents));
       gQueue.push(new changeClass("container2", "link7", "displayNone",
                                   kHideEvents));
-      gQueue.push(new changeClass("container3", "link8", "", kShowEvents));
-      gQueue.push(new changeClass("container3", "link8", "visibilityHidden",
-                                  kHideEvents));
 
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTests);
   </script>
 </head>
 
 <body>
 
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=469985"
      title=" turn the test from bug 354745 into mochitest">
     Mozilla Bug 469985
-  </a>
+  </a><br>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=472662"
      title="no reorder event when html:link display property is changed from 'none' to 'inline'">
     Mozilla Bug 472662
+  </a><br>
+  <a target="_blank"
+     title="Rework accessible tree update code"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275">
+    Mozilla Bug 570275
   </a>
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
   <div id="eventdump"></div>
 
--- a/accessible/tests/mochitest/events/test_scroll.xul
+++ b/accessible/tests/mochitest/events/test_scroll.xul
@@ -68,20 +68,20 @@
       /*
        * When tests are packed in a .jar, we need to extract them so we 
        * can access the specific url with a file:// protocol which appears
        * to be required by loadURI() (at least a file without an embedded .jar)
        */
       var jar = getJar(rootDir);
       if (jar) {
         var tmpdir = extractJarToTmp(jar);
-        rootDir = "file://" + tmpdir.path;
+        rootDir = "file://" + tmpdir.path + '/';
       }
 
-      var url = rootDir + "/scroll.html#link1";
+      var url = rootDir + "scroll.html#link1";
       var tabBrowser = document.getElementById("tabBrowser");
       tabBrowser.loadURI(url);
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   ]]>
   </script>
--- a/accessible/tests/mochitest/events/test_text.html
+++ b/accessible/tests/mochitest/events/test_text.html
@@ -79,32 +79,46 @@
       {
         return "Remove inaccessible span containing accessible nodes" + prettyName(aID);
       }
     }
 
     /**
      * Insert inaccessible child node containing accessibles.
      */
-    function insertChildSpan(aID)
+    function insertChildSpan(aID, aInsertAllTogether)
     {
       this.__proto__ = new textInsertInvoker(aID, 0, 5, "33322");
 
       this.invoke = function insertChildSpan_invoke()
       {
         // <span><span>333</span><span>22</span></span>
-        var topSpan = document.createElement("span");
-        var fSpan = document.createElement("span");
-        fSpan.textContent = "333";
-        topSpan.appendChild(fSpan);
-        var sSpan = document.createElement("span");
-        sSpan.textContent = "22";
-        topSpan.appendChild(sSpan);
+        if (aInsertAllTogether) {
+          var topSpan = document.createElement("span");
+          var fSpan = document.createElement("span");
+          fSpan.textContent = "333";
+          topSpan.appendChild(fSpan);
+          var sSpan = document.createElement("span");
+          sSpan.textContent = "22";
+          topSpan.appendChild(sSpan);
+
+          this.DOMNode.insertBefore(topSpan, this.DOMNode.childNodes[0]);
 
-        this.DOMNode.insertBefore(topSpan, this.DOMNode.childNodes[0]);
+        } else {
+          var topSpan = document.createElement("span");
+          this.DOMNode.insertBefore(topSpan, this.DOMNode.childNodes[0]);
+
+          var fSpan = document.createElement("span");
+          fSpan.textContent = "333";
+          topSpan.appendChild(fSpan);
+
+          var sSpan = document.createElement("span");
+          sSpan.textContent = "22";
+          topSpan.appendChild(sSpan);
+        }
       }
 
       this.getID = function insertChildSpan_getID()
       {
        return "Insert inaccessible span containing accessibles" +
           prettyName(aID);
       }
     }
@@ -266,17 +280,18 @@
 
     function doTests()
     {
       gQueue = new eventQueue();
 
       // Text remove event on inaccessible child HTML span removal containing
       // accessible text nodes.
       gQueue.push(new removeChildSpan("p"));
-      gQueue.push(new insertChildSpan("p"));
+      gQueue.push(new insertChildSpan("p"), true);
+      gQueue.push(new insertChildSpan("p"), false);
 
       // Remove embedded character.
       gQueue.push(new removeChildDiv("div"));
       gQueue.push(new insertChildDiv("div"));
 
       // Remove all children.
       var text = kEmbedChar + "txt" + kEmbedChar;
       gQueue.push(new removeChildren("div2", true, 0, 5, text));
@@ -318,16 +333,21 @@
      title="Coalesce text events on nodes removal">
     Mozilla Bug 574003
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=575052"
      title="Cache text offsets within hypertext accessible">
     Mozilla Bug 575052
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275"
+     title="Rework accessible tree update code">
+    Mozilla Bug 570275
+  </a>
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
   <div id="eventdump"></div>
 
   <p id="p"><span><span>333</span><span>22</span></span>1111</p>
--- a/accessible/tests/mochitest/role.js
+++ b/accessible/tests/mochitest/role.js
@@ -10,16 +10,17 @@ const ROLE_BUTTONDROPDOWNGRID = nsIAcces
 const ROLE_CAPTION = nsIAccessibleRole.ROLE_CAPTION;
 const ROLE_CELL = nsIAccessibleRole.ROLE_CELL;
 const ROLE_CHECKBUTTON = nsIAccessibleRole.ROLE_CHECKBUTTON;
 const ROLE_CHROME_WINDOW = nsIAccessibleRole.ROLE_CHROME_WINDOW;
 const ROLE_COMBOBOX = nsIAccessibleRole.ROLE_COMBOBOX;
 const ROLE_COMBOBOX_LIST = nsIAccessibleRole.ROLE_COMBOBOX_LIST;
 const ROLE_COMBOBOX_OPTION = nsIAccessibleRole.ROLE_COMBOBOX_OPTION;
 const ROLE_COLUMNHEADER = nsIAccessibleRole.ROLE_COLUMNHEADER;
+const ROLE_DIALOG = nsIAccessibleRole.ROLE_DIALOG;
 const ROLE_DOCUMENT = nsIAccessibleRole.ROLE_DOCUMENT;
 const ROLE_EMBEDDED_OBJECT = nsIAccessibleRole.ROLE_EMBEDDED_OBJECT;
 const ROLE_ENTRY = nsIAccessibleRole.ROLE_ENTRY;
 const ROLE_FLAT_EQUATION = nsIAccessibleRole.ROLE_FLAT_EQUATION;
 const ROLE_FORM = nsIAccessibleRole.ROLE_FORM;
 const ROLE_GRAPHIC = nsIAccessibleRole.ROLE_GRAPHIC;
 const ROLE_GRID_CELL = nsIAccessibleRole.ROLE_GRID_CELL;
 const ROLE_GROUPING = nsIAccessibleRole.ROLE_GROUPING;
@@ -95,8 +96,28 @@ function getRole(aAccOrElmOrID)
   try {
     role = acc.role;
   } catch(e) {
     ok(false, "Role for " + aAccOrElmOrID + " could not be retrieved!");
   }
 
   return role;
 }
+
+/**
+ * Analogy of SimpleTest.is function used to check the role.
+ */
+function isRole(aIdentifier, aRole, aMsg)
+{
+  var role = getRole(aIdentifier);
+  if (role == - 1)
+    return;
+
+  if (role == aRole) {
+    ok(true, aMsg);
+    return;
+  }
+
+  var got = roleToString(role);
+  var expected = roleToString(aRole);
+
+  ok(false, aMsg + "got '" + got + "', expected '" + expected + "'");
+}
--- a/accessible/tests/mochitest/states.js
+++ b/accessible/tests/mochitest/states.js
@@ -1,16 +1,56 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Helper functions for accessible states testing.
 //
 // requires:
 //   common.js
 //
 ////////////////////////////////////////////////////////////////////////////////
 
+////////////////////////////////////////////////////////////////////////////////
+// State constants
+
+// const STATE_BUSY is defined in common.js
+const STATE_CHECKED = nsIAccessibleStates.STATE_CHECKED;
+const STATE_CHECKABLE = nsIAccessibleStates.STATE_CHECKABLE;
+const STATE_COLLAPSED = nsIAccessibleStates.STATE_COLLAPSED;
+const STATE_EXPANDED = nsIAccessibleStates.STATE_EXPANDED;
+const STATE_EXTSELECTABLE = nsIAccessibleStates.STATE_EXTSELECTABLE;
+const STATE_FOCUSABLE = nsIAccessibleStates.STATE_FOCUSABLE;
+const STATE_FOCUSED = nsIAccessibleStates.STATE_FOCUSED;
+const STATE_HASPOPUP = nsIAccessibleStates.STATE_HASPOPUP;
+const STATE_INVALID = nsIAccessibleStates.STATE_INVALID;
+const STATE_LINKED = nsIAccessibleStates.STATE_LINKED;
+const STATE_MIXED = nsIAccessibleStates.STATE_MIXED;
+const STATE_MULTISELECTABLE = nsIAccessibleStates.STATE_MULTISELECTABLE;
+const STATE_OFFSCREEN = nsIAccessibleStates.STATE_OFFSCREEN;
+const STATE_PRESSED = nsIAccessibleStates.STATE_PRESSED;
+const STATE_READONLY = nsIAccessibleStates.STATE_READONLY;
+const STATE_REQUIRED = nsIAccessibleStates.STATE_REQUIRED;
+const STATE_SELECTABLE = nsIAccessibleStates.STATE_SELECTABLE;
+const STATE_SELECTED = nsIAccessibleStates.STATE_SELECTED;
+const STATE_TRAVERSED = nsIAccessibleStates.STATE_TRAVERSED;
+const STATE_UNAVAILABLE = nsIAccessibleStates.STATE_UNAVAILABLE;
+
+const EXT_STATE_ACTIVE = nsIAccessibleStates.EXT_STATE_ACTIVE;
+const EXT_STATE_DEFUNCT = nsIAccessibleStates.EXT_STATE_DEFUNCT;
+const EXT_STATE_EDITABLE = nsIAccessibleStates.EXT_STATE_EDITABLE;
+const EXT_STATE_EXPANDABLE = nsIAccessibleStates.EXT_STATE_EXPANDABLE;
+const EXT_STATE_HORIZONTAL = nsIAccessibleStates.EXT_STATE_HORIZONTAL;
+const EXT_STATE_MULTI_LINE = nsIAccessibleStates.EXT_STATE_MULTI_LINE;
+const EXT_STATE_SINGLE_LINE = nsIAccessibleStates.EXT_STATE_SINGLE_LINE;
+const EXT_STATE_SUPPORTS_AUTOCOMPLETION =
+  nsIAccessibleStates.EXT_STATE_SUPPORTS_AUTOCOMPLETION;
+const EXT_STATE_VERTICAL = nsIAccessibleStates.EXT_STATE_VERTICAL;
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Test functions
+
 /**
  * Tests the states and extra states of the given accessible.
  * Also tests for unwanted states and extra states.
  * In addition, the function performs a few plausibility checks derived from the
  * sstates and extra states passed in.
  *
  * @param aAccOrElmOrID      The accessible, DOM element or ID to be tested.
  * @param aState             The state bits that are wanted.
@@ -87,24 +127,16 @@ function testStates(aAccOrElmOrID, aStat
     isState(state & STATE_CHECKED, 0, false,
             "Mixed element cannot be state checked!");
 
   // selected/selectable
   if (state & STATE_SELECTED) {
     isState(state & STATE_SELECTABLE, STATE_SELECTABLE, false,
             "Selected element should be selectable!");
   }
-
-  // unavailable
-  if (state & STATE_UNAVAILABLE) {
-    var role = getRole(aAccOrElmOrID);
-    if (role != ROLE_GROUPING && role != ROLE_EMBEDDED_OBJECT)
-      isState(state & STATE_FOCUSABLE, STATE_FOCUSABLE, false,
-              "Disabled " + id + " must be focusable!");
-  }
 }
 
 /**
  * Tests an acessible and its sub tree for the passed in state bits.
  * Used to make sure that states are propagated to descendants, for example the
  * STATE_UNAVAILABLE from a container to its children.
  *
  * @param aAccOrElmOrID  The accessible, DOM element or ID to be tested.
@@ -152,16 +184,26 @@ function getStates(aAccOrElmOrID)
     return [0, 0];
   
   var state = {}, extraState = {};
   acc.getState(state, extraState);
 
   return [state.value, extraState.value];
 }
 
+/**
+ * Return true if the accessible has given states.
+ */
+function hasState(aAccOrElmOrID, aState, aExtraState)
+{
+  var [state, exstate] = getStates(aAccOrElmOrID);
+  return (aState ? state & aState : true) &&
+    (aExtraState ? exstate & aExtraState : true);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Private implementation details
 
 /**
  * Analogy of SimpleTest.is function used to compare states.
  */
 function isState(aState1, aState2, aIsExtraStates, aMsg)
 {
--- a/accessible/tests/mochitest/states/Makefile.in
+++ b/accessible/tests/mochitest/states/Makefile.in
@@ -49,16 +49,18 @@ include $(topsrcdir)/config/rules.mk
 #  test_frames.html \
 
 _TEST_FILES =\
 		test_aria.html \
 		test_aria_imgmap.html \
 		test_doc.html \
 		test_docarticle.html \
 		test_editablebody.html \
+		test_inputs.html \
+		test_inputs.xul \
 		test_link.html \
 		test_popup.xul \
 		test_tree.xul \
 		z_frames.html \
 		z_frames_article.html \
 		z_frames_checkbox.html \
 		z_frames_textbox.html \
 		$(NULL)
--- a/accessible/tests/mochitest/states/test_aria.html
+++ b/accessible/tests/mochitest/states/test_aria.html
@@ -24,16 +24,46 @@
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../role.js"></script>
   <script type="application/javascript"
           src="../states.js"></script>
 
   <script type="application/javascript">
+    function testAriaDisabledTree(aAccOrElmOrID)
+    {
+      // test accessible and its subtree for propagated state.
+      var acc = getAccessible(aAccOrElmOrID);
+      if (!acc)
+        return;
+
+      var [state, extraState] = getStates(aAccOrElmOrID);
+      if (state & STATE_UNAVAILABLE) {
+        var role = getRole(acc);
+        if (role != ROLE_GROUPING) {
+          testStates(acc, STATE_FOCUSABLE);
+        }
+      }
+
+      // Iterate over its children to see if the state got propagated.
+      var children = null;
+      try {
+        children = acc.children;
+      } catch(e) {}
+      ok(children, "Could not get children for " + aAccOrElmOrID +"!");
+  
+      if (children) {
+        for (var i = 0; i < children.length; i++) {
+          var childAcc = children.queryElementAt(i, nsIAccessible);
+          testAriaDisabledTree(childAcc);
+        }
+      }
+    }
+
     function doTest()
     {
       // aria_autocomplete
       testStates("textbox_autocomplete_inline", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
       testStates("textbox_autocomplete_list", STATE_HASPOPUP, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
       testStates("textbox_autocomplete_both", STATE_HASPOPUP, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
       testStates("combobox_autocomplete_inline", STATE_HASPOPUP, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
       testStates("combobox_autocomplete_list", STATE_HASPOPUP, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
@@ -59,17 +89,17 @@
       }
 
       // aria-checked
       testStates("aria_checked_checkbox", STATE_CHECKED);
       testStates("aria_mixed_checkbox", STATE_MIXED);
 
       // test disabled group and all its descendants to see if they are
       // disabled, too. See bug 429285.
-      testStatesInSubtree("group", STATE_UNAVAILABLE);
+      testAriaDisabledTree("group");
 
       // offscreen test
       testStates("aria_offscreen_textbox", STATE_OFFSCREEN);
 
       //
       // This section tests aria roles on links/anchors for underlying
       // nsHTMLLinkAccessible creation. (see closed bug 494807)
       //
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/states/test_inputs.html
@@ -0,0 +1,148 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>HTML input states</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../states.js"></script>
+
+  <script type="application/javascript">
+  function doTest()
+  {
+    // 'required' state. Also piggyback 'unavailable' testing here.
+    var maybe_required = ["input","search","radio","checkbox","textarea"];
+    var never_required = ["submit","button","reset","image"];
+
+    var i;
+    for (i in maybe_required) {
+      testStates(maybe_required[i], STATE_REQUIRED, 0, STATE_UNAVAILABLE);
+      testStates(maybe_required[i] + "2", 0, 0, STATE_REQUIRED);
+      testStates(maybe_required[i] + "3", STATE_UNAVAILABLE);
+    }
+
+    for (i in never_required) {
+      testStates(never_required[i], 0, 0, STATE_REQUIRED);
+    }
+
+    // inherited 'unavailable' state
+    testStates("f", STATE_UNAVAILABLE);
+    testStates("f_input", STATE_UNAVAILABLE);
+    testStates("f_input_disabled", STATE_UNAVAILABLE);
+
+    // invalid/valid state
+    var invalid = ["maxlength","pattern","email","url"];
+    document.getElementById("maxlength").value = "i am too long";
+    for (i in invalid) {
+      testStates(invalid[i], STATE_INVALID);
+      testStates(invalid[i] + "2", 0, 0, STATE_INVALID);
+    }
+
+    // invalid/valid state
+    var invalid = ["maxlength","pattern","email","url"];
+    document.getElementById("maxlength").value = "i am too long";
+    for (i in invalid) {
+      testStates(invalid[i], STATE_INVALID);
+      testStates(invalid[i] + "2", 0, 0, STATE_INVALID);
+    }
+
+    SimpleTest.finish();
+  }
+
+  SimpleTest.waitForExplicitFinish();
+  addA11yLoadEvent(doTest);
+  </script>
+</head>
+
+<body>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=559275"
+     title="map attribute required to STATE_REQUIRED">
+    Mozilla Bug 559275
+  </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=389238"
+     title="Support disabled state on fieldset">
+    Mozilla Bug 389238
+  </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=599163"
+     title="check disabled state instead of attribute">
+    Mozilla Bug 599163
+  </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=601205"
+     title="Expose intrinsic invalid state to accessibility API">
+    Mozilla Bug 601205
+  </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=601205"
+     title="Expose intrinsic invalid state to accessibility API">
+    Mozilla Bug 601205
+  </a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+
+  <form>
+    <input id="input" type="input" required>
+    <input id="input2" type="input">
+    <input id="input3" type="input" disabled>
+    <input id="search" type="search" required>
+    <input id="search2" type="search">
+    <input id="search3" type="search" disabled>
+    <input id="radio" type="radio" required>
+    <input id="radio2" type="radio">
+    <input id="radio3" type="radio" disabled>
+    <input id="checkbox" type="checkbox" required>
+    <input id="checkbox2" type="checkbox">
+    <input id="checkbox3" type="checkbox" disabled>
+    <textarea id="textarea" required></textarea>
+    <textarea id="textarea2"></textarea>
+    <textarea id="textarea3" disabled></textarea>
+  </form>
+
+  <!-- bogus required usage -->
+  <input id="submit" type="submit" required>
+  <input id="button" type="button" required>
+  <input id="reset" type="reset" required>
+  <input id="image" type="image" required>
+
+  <!-- disabled -->
+  <fieldset id="f" disabled>
+    <input id="f_input">
+    <input id="f_input_disabled" disabled>
+  </fieldset>
+
+  <!-- invalid/valid -->
+  <input id="maxlength" maxlength="1">
+  <input id="maxlength2" maxlength="100" value="foo">
+  <input id="pattern" pattern="bar" value="foo">
+  <input id="pattern2" pattern="bar" value="bar">
+  <input id="email" type="email" value="foo">
+  <input id="email2" type="email" value="foo@bar.com">
+  <input id="url" type="url" value="foo">
+  <input id="url2" type="url" value="http://mozilla.org/">
+
+  <!-- invalid/valid -->
+  <input id="maxlength" maxlength="1">
+  <input id="maxlength2" maxlength="100" value="foo">
+  <input id="pattern" pattern="bar" value="foo">
+  <input id="pattern2" pattern="bar" value="bar">
+  <input id="email" type="email" value="foo">
+  <input id="email2" type="email" value="foo@bar.com">
+  <input id="url" type="url" value="foo">
+  <input id="url2" type="url" value="http://mozilla.org/">
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/states/test_inputs.xul
@@ -0,0 +1,84 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="Accessible XUL input control state tests">
+
+  <script type="application/javascript" 
+          src="chrome://mochikit/content/MochiKit/packed.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+
+  <script type="application/javascript"
+          src="../common.js" />
+  <script type="application/javascript"
+          src="../states.js" />
+
+  <script type="application/javascript">
+  <![CDATA[
+
+    function doTest()
+    {
+      testStates("some-text", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE);
+      testStates("some-text2", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
+      testStates("some-password", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE);
+      testStates("some-password2", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
+      testStates("checkbox", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE);
+      testStates("checkbox2", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
+      testStates("radio-group", 0, 0, STATE_UNAVAILABLE);
+      testStates("orange", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
+      testStates("violet", 0, 0, STATE_UNAVAILABLE);
+      testStates("radio-group2", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
+      testStates("orange2", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
+
+      SimpleTest.finish()
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  ]]>
+  </script>
+
+  <hbox flex="1" style="overflow: auto;">
+    <body xmlns="http://www.w3.org/1999/xhtml">
+     <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=599163"
+         title="check disabled state instead of attribute">
+        Mozilla Bug 599163
+     </a><br/>
+      <p id="display"></p>
+      <div id="content" style="display: none">
+      </div>
+      <pre id="test">
+      </pre>
+    </body>
+
+    <vbox flex="1">
+
+    <textbox id="some-text"/>
+    <textbox id="some-text2" disabled="true"/>
+    <textbox id="some-password" type="password" maxlength="8"/>
+    <textbox id="some-password2" type="password" maxlength="8" disabled="true"/>
+
+    <checkbox id="checkbox" checked="true" label="Steak"/>
+    <checkbox id="checkbox2" checked="true" label="Salad" disabled="true"/>
+
+    <radiogroup id="radio-group">
+      <radio id="orange" label="Orange" disabled="true"/>
+      <radio id="violet" selected="true" label="Violet"/>
+      <radio id="yellow" label="Yellow"/>
+    </radiogroup>
+
+    <radiogroup id="radio-group2" disabled="true">
+      <radio id="orange2" label="Orange"/>
+      <radio id="violet2" selected="true" label="Violet"/>
+      <radio id="yellow2" label="Yellow"/>
+    </radiogroup>
+
+    </vbox>
+  </hbox>
+
+</window>
+
--- a/accessible/tests/mochitest/states/test_link.html
+++ b/accessible/tests/mochitest/states/test_link.html
@@ -16,21 +16,21 @@
   <script type="application/javascript"
           src="../role.js"></script>
   <script type="application/javascript"
           src="../states.js"></script>
 
   <script type="application/javascript">
     function doTest()
     {
-      // strong roles
       testStates("link1", STATE_LINKED);
       testStates("link2", STATE_LINKED);
       testStates("link3", STATE_LINKED);
       testStates("link4", STATE_LINKED);
+      testStates("link5", 0, 0, STATE_LINKED);
 
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 
@@ -47,11 +47,12 @@
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <a id="link1" href="http://mozilla.org">link</a>
   <a id="link2" onclick="">link</a>
   <a id="link3" onmousedown="">link</a>
   <a id="link4" onmouseup="">link</a>
+  <a id="link5">not link</a>
 
 </body>
 </html>
--- a/accessible/tests/mochitest/test_editabletext_1.html
+++ b/accessible/tests/mochitest/test_editabletext_1.html
@@ -63,17 +63,17 @@ https://bugzilla.mozilla.org/show_bug.cg
     function doTest()
     {
       testEditable("input");
       // testEditable("div"); XXX: bug 452599
 
       var frame = document.getElementById("frame");
       frame.contentDocument.designMode = "on";
       testEditable(frame.contentDocument);
-      
+
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 <body>
--- a/accessible/tests/mochitest/test_nsIAccessible_selects.html
+++ b/accessible/tests/mochitest/test_nsIAccessible_selects.html
@@ -8,16 +8,18 @@
           src="chrome://mochikit/content/MochiKit/packed.js"></script>
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript"
           src="common.js"></script>
   <script type="application/javascript"
           src="role.js"></script>
   <script type="application/javascript"
+          src="states.js"></script>
+  <script type="application/javascript"
           src="nsIAccessible_selects.js"></script>
 
   <script type="application/javascript">
     function doTest()
     {
       // Label and combo, separate tags
       var names = [
         "Foo:", // combobox
--- a/accessible/tests/mochitest/test_value.html
+++ b/accessible/tests/mochitest/test_value.html
@@ -34,17 +34,17 @@
       {
         var acc = getAccessible(aID);
         if (!acc)
           return;
         is(acc.value, aValue, "Wrong value for " + aID + "!");
       }
 
       var rootDir = getRootDirectory(window.location.href);
-      var href = rootDir.path + "/foo";
+      var href = rootDir.path + "foo";
 
       // roles that can't live as nsHTMLLinkAccessibles
       testValue("aria_menuitem_link", "");
       testValue("aria_button_link", "");
       testValue("aria_checkbox_link", "");
       testValue("aria_application_link", "");
 
       // roles that can live as nsHTMLLinkAccessibles
--- a/accessible/tests/mochitest/tree/Makefile.in
+++ b/accessible/tests/mochitest/tree/Makefile.in
@@ -57,17 +57,16 @@ include $(topsrcdir)/config/rules.mk
 		test_filectrl.html \
 		test_formctrl.html \
 		test_formctrl.xul \
 		test_gencontent.html \
 		test_groupbox.xul \
 		test_iframe.html \
 		test_img.html \
 		test_list.html \
-		test_list_invalidate.html \
 		test_media.html \
 		test_menu.xul \
 		test_select.html \
 		test_tabbox.xul \
 		test_tabbrowser.xul \
 		test_table.html \
 		test_tree.xul \
 		test_txtcntr.html \
--- a/accessible/tests/mochitest/tree/test_combobox.xul
+++ b/accessible/tests/mochitest/tree/test_combobox.xul
@@ -49,19 +49,16 @@
 
       accTree = {
         role: ROLE_COMBOBOX,
         children: [
           {
             role: ROLE_ENTRY,
             children: [
               {
-                role: ROLE_TEXT_LEAF // HTML 5 placeholder attribute value
-              },
-              {
                 role: ROLE_TEXT_LEAF // Text node for the node's value
               }
             ]
           },
           {
             role: ROLE_COMBOBOX_LIST, // context menu
             children: []
           },
@@ -122,19 +119,16 @@
                 role: ROLE_COMBOBOX_OPTION
               }
             ]
           },
           {
             role: ROLE_ENTRY,
             children: [
               {
-                role: ROLE_TEXT_LEAF // HTML 5 placeholder attribute value
-              },
-              {
                 role: ROLE_TEXT_LEAF // Text node for the node's value
               }
             ]
           },
           {
             role: ROLE_COMBOBOX_LIST, // context menu popup
             children: [ ]
           }
--- a/accessible/tests/mochitest/tree/test_cssoverflow.html
+++ b/accessible/tests/mochitest/tree/test_cssoverflow.html
@@ -25,111 +25,105 @@
           src="../events.js"></script>
 
   <script type="application/javascript">
     ////////////////////////////////////////////////////////////////////////////
     // Invokers
 
     function focusAnchor(aID)
     {
-      this.DOMNode = getNode(aID);
-      this.link = getAccessible(this.DOMNode);
-      this.linkChild = this.link.firstChild;
-      this.linkChildNode = getAccessible(this.linkChild, [nsIAccessNode]).DOMNode;
+      this.linkNode = getNode(aID);
+      this.link = getAccessible(this.linkNode);
 
       this.eventSeq = [
-//        new invokerChecker(EVENT_HIDE, this.linkChild),
-//        new invokerChecker(EVENT_SHOW, getAccessible, this.linkChildNode),
-        new invokerChecker(EVENT_FOCUS, this.link)
-      ];
-
-      this.unexpectedEventSeq = [
-        new invokerChecker(EVENT_HIDE, this.link),
-        new invokerChecker(EVENT_SHOW, getAccessible, this.DOMNode)
+        new invokerChecker(EVENT_FOCUS, getAccessible, this.linkNode)
       ];
 
       this.invoke = function focusAnchor_invoke()
       {
-        todo(false, "enable event hide/show events");
-        getNode(aID).focus();
+        this.linkNode.focus();
+      }
+
+      this.check = function focusAnchor_check(aEvent)
+      {
+        isnot(this.link, aEvent.accessible,
+              "Focus should be fired against new link accessible!");
       }
 
       this.getID = function focusAnchor_getID()
       {
         return "focus a:focus{overflow:scroll} #1";
       }
     }
 
-    function tabAnchor(aID, aPrevID)
+    function tabAnchor(aID)
     {
-      this.DOMNode = getNode(aID);
-      this.link = getAccessible(this.DOMNode);
-      this.linkChild = this.link.firstChild;
-      this.linkChildNode = getAccessible(this.linkChild, [nsIAccessNode]).DOMNode;
-      this.prevLink = getAccessible(aPrevID);
-      this.prevLinkNode = getAccessible(this.prevLink, [nsIAccessNode]).DOMNode;
+      this.linkNode = getNode(aID);
+      this.link = getAccessible(this.linkNode);
 
       this.eventSeq = [
-        new invokerChecker(EVENT_HIDE, this.prevLink),
-        new invokerChecker(EVENT_SHOW, getAccessible, this.prevLinkNode),
-        new invokerChecker(EVENT_HIDE, this.linkChild),
-        new invokerChecker(EVENT_SHOW, getAccessible, this.linkChildNode),
-        new invokerChecker(EVENT_FOCUS, this.link)
+        new invokerChecker(EVENT_FOCUS, getAccessible, this.linkNode)
       ];
 
-      this.unexpectedEventSeq = [
-        new invokerChecker(EVENT_HIDE, this.link),
-        new invokerChecker(EVENT_SHOW, getAccessible, this.DOMNode)
-      ];
-
-      this.invoke = function focusAnchor_invoke()
+      this.invoke = function tabAnchor_invoke()
       {
         synthesizeKey("VK_TAB", { shiftKey: false });
       }
 
-      this.getID = function focusAnchor_getID()
+      this.check = function tabAnchor_check(aEvent)
+      {
+        isnot(this.link, aEvent.accessible,
+              "Focus should be fired against new link accessible!");
+      }
+
+      this.getID = function tabAnchor_getID()
       {
         return "focus a:focus{overflow:scroll} #2";
       }
     }
 
     ////////////////////////////////////////////////////////////////////////////
     // Do tests
 
     var gQueue = null;
-    // gA11yEventDumpID = "eventdump"; // debug stuff
+    //gA11yEventDumpID = "eventdump"; // debug stuff
+    //gA11yEventDumpToConsole = true;
 
     function doTests()
     {
       gQueue = new eventQueue();
 
       // CSS 'overflow: scroll' property setting and unsetting causes accessible
-      // recreation (and fire show/hide events) if the accessible is not
-      // focused. If it's focused its children are recreated. For example,
-      // focusing the HTML:a with ':focus {overflow: scroll; }' CSS style
-      // shouldn't cause of HTML:a accessible recreation. The same time blur
-      // makes its accessible to be recreated.
-      gQueue.push(new focusAnchor("a"))
-      gQueue.push(new tabAnchor("a2", "a"));
+      // recreation (and fire show/hide events). For example, the focus and
+      // blur of HTML:a with ':focus {overflow: scroll; }' CSS style causes its
+      // accessible recreation. The focus event should be fired on new
+      // accessible.
+      gQueue.push(new focusAnchor("a"));
+      gQueue.push(new tabAnchor("a2"));
 
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTests);
   </script>
 </head>
 
 <body>
 
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=591163"
      title="mochitest for bug 413777: focus the a:focus {overflow: scroll;} shouldn't recreate HTML a accessible">
     Mozilla Bug 591163
   </a><br>
+  <a target="_blank"
+     title="Rework accessible tree update code"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275">
+    Mozilla Bug 570275
+  </a><br>
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
   <div id="eventdump"></div>
 
   <div>
--- a/accessible/tests/mochitest/tree/test_list.html
+++ b/accessible/tests/mochitest/tree/test_list.html
@@ -35,68 +35,111 @@
       if (aSubtree)
         obj.children.push(aSubtree);
 
       return obj;
     }
 
     function doTest()
     {
-      var bulletText = String.fromCharCode(0x2022) + " ";
+      const discBulletText = String.fromCharCode(0x2022) + " ";
+      const circleBulletText = String.fromCharCode(0x25e6) + " ";
+      const squareBulletText = String.fromCharCode(0x25aa) + " ";
 
       // list1
-      var accTree = {
+      var discAccTree = {
         role: ROLE_LIST,
         children: [
-          new listItemTree(bulletText, "Oranges"),
-          new listItemTree(bulletText, "Apples"),
-          new listItemTree(bulletText, "Bananas")
+          new listItemTree(discBulletText, "Oranges"),
+          new listItemTree(discBulletText, "Apples"),
+          new listItemTree(discBulletText, "Bananas")
         ]
       };
 
-      testAccessibleTree("list1", accTree);
+      testAccessibleTree("list1", discAccTree);
 
       // list2
-      accTree = {
+      var circleAccTree = {
+        role: ROLE_LIST,
+        children: [
+          new listItemTree(circleBulletText, "Oranges"),
+          new listItemTree(circleBulletText, "Apples"),
+          new listItemTree(circleBulletText, "Bananas")
+        ]
+      };
+
+      testAccessibleTree("list2", circleAccTree);
+
+      // list3
+      var squareAccTree = {
+        role: ROLE_LIST,
+        children: [
+          new listItemTree(squareBulletText, "Oranges"),
+          new listItemTree(squareBulletText, "Apples"),
+          new listItemTree(squareBulletText, "Bananas")
+        ]
+      };
+
+      testAccessibleTree("list3", squareAccTree);
+
+      // list4
+      var nestedAccTree = {
         role: ROLE_LIST,
         children: [
           new listItemTree("1. ", "Oranges"),
           new listItemTree("2. ", "Apples"),
-          new listItemTree("3. ", "Bananas", accTree)
+          new listItemTree("3. ", "Bananas", circleAccTree)
         ]
       };
 
-      testAccessibleTree("list2", accTree);
+      testAccessibleTree("list4", nestedAccTree);
 
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 <body>
 
   <a target="_blank"
      title="Fix O(n^2) access to all the children of a container"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=342045">
     Mozilla Bug 342045
   </a>
+  <a target="_blank"
+     title="Bullets of nested not ordered lists have one and the same character."
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=604587">
+    Mozilla Bug 604587
+  </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <ul id="list1">
-    <li id="li1">Oranges</li>
-    <li id="li2">Apples</li>
-    <li id="li3">Bananas</li>
+    <li id="l1_li1">Oranges</li>
+    <li id="l1_li2">Apples</li>
+    <li id="l1_li3">Bananas</li>
   </ul>
 
-  <ol id="list2">
+  <ul id="list2" style="list-style-type: circle">
+    <li id="l2_li1">Oranges</li>
+    <li id="l2_li2">Apples</li>
+    <li id="l2_li3">Bananas</li>
+  </ul>
+
+  <ul id="list3" style="list-style-type: square">
+    <li id="l3_li1">Oranges</li>
+    <li id="l3_li2">Apples</li>
+    <li id="l3_li3">Bananas</li>
+  </ul>
+
+  <ol id="list4">
     <li id="li4">Oranges</li>
     <li id="li5">Apples</li>
     <li id="li6">Bananas<ul>
         <li id="n_li4">Oranges</li>
         <li id="n_li5">Apples</li>
         <li id="n_li6">Bananas</li>
       </ul>
     </li>
--- a/accessible/tests/mochitest/tree/test_tabbrowser.xul
+++ b/accessible/tests/mochitest/tree/test_tabbrowser.xul
@@ -66,16 +66,19 @@
     }
 
     function testAccTree()
     {
       var tabsAccTree = {
         role: ROLE_PAGETABLIST,
         children: [
           {
+            role: ROLE_PUSHBUTTON // tab scroll up button
+          },
+          {
             role: ROLE_PAGETAB,
             children: [
               {
                 role: ROLE_PUSHBUTTON
               }
             ]
           },
           {
@@ -83,16 +86,19 @@
             children: [
               {
                 role: ROLE_PUSHBUTTON
               }
             ]
           },
           {
             role: ROLE_PUSHBUTTON
+          },
+          {
+            role: ROLE_PUSHBUTTON // tab scroll down button
           }
         ]
       };
       testAccessibleTree(getNode("tabbrowser").tabContainer, tabsAccTree);
 
       var tabboxAccTree = {
         role: ROLE_PANE,
         children: [
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/treeupdate/Makefile.in
@@ -0,0 +1,56 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2010
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Alexander Surkov <surkov.alexander@gmail.com> (original author)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir  = accessible/treeupdate
+
+include $(DEPTH)/config/autoconf.mk
+include $(topsrcdir)/config/rules.mk
+
+_TEST_FILES =\
+		test_list_editabledoc.html \
+		test_list.html \
+		test_recreation.html \
+		test_tableinsubtree.html \
+		$(NULL)
+
+libs:: $(_TEST_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
rename from accessible/tests/mochitest/tree/test_list_invalidate.html
rename to accessible/tests/mochitest/treeupdate/test_list.html
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/treeupdate/test_list_editabledoc.html
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <title>Test HTML li and listitem bullet accessible insertion into editable document</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
+          src="../events.js"></script>
+
+  <script type="application/javascript">
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Invokers
+
+    function addLi(aID)
+    {
+      this.listNode = getNode(aID);
+      this.liNode = document.createElement("li");
+      this.liNode.textContent = "item";
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_SHOW, getAccessible, this.liNode),
+        new invokerChecker(EVENT_REORDER, this.listNode)
+      ];
+
+      this.invoke = function addLi_invoke()
+      {
+        this.listNode.appendChild(this.liNode);
+      }
+
+      this.finalCheck = function addLi_finalCheck()
+      {
+        var tree = {
+          role: ROLE_LIST,
+          children: [
+            {
+              role: ROLE_LISTITEM,
+              children: [
+                {
+                  role: ROLE_STATICTEXT,
+                  name: "1. ",
+                  children: []
+                },
+                {
+                  role: ROLE_TEXT_LEAF,
+                  children: []
+                }
+              ]
+            }
+          ]
+        };
+        testAccessibleTree(aID, tree);
+      }
+
+      this.getID = function addLi_getID()
+      {
+        return "add li";
+      }
+    };
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Test
+
+    //gA11yEventDumpID = "eventdump"; // debug stuff
+
+    var gQueue = null;
+
+    function doTest()
+    {
+      gQueue = new eventQueue();
+
+      gQueue.push(new addLi("list"));
+
+      gQueue.invoke(); // SimpleTest.finish() will be called in the end
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body contentEditable="true">
+
+  <a target="_blank"
+     title="Wrong list bullet text of accessible for the first numbered HTML:li in CKEditor"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=557795">Mozilla Bug 557795</a>
+
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <ol id="list">
+  </ol>
+
+  <div id="eventdump"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/treeupdate/test_recreation.html
@@ -0,0 +1,166 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <title>Test accessible recreation</title>
+
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
+          src="../events.js"></script>
+
+  <script type="application/javascript">
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Invokers
+
+    function recreateAccessible(aID, aWontBeAccessible)
+    {
+      this.node = getNode(aID);
+      this.accessible =
+        isAccessible(this.node) ? getAccessible(this.node) : null;
+
+      this.eventSeq = [ ];
+
+      if (this.accessible)
+        this.eventSeq.push(new invokerChecker(EVENT_HIDE,
+                                              this.accessible));
+
+      if (!aWontBeAccessible)
+        this.eventSeq.push(new invokerChecker(EVENT_SHOW, getAccessible,
+                                              this.node));
+
+      this.eventSeq.push(new invokerChecker(EVENT_REORDER,
+                                            getContainerAccessible(this.node)));
+
+      if (this.accessible) {
+        this.unexpectedEventSeq = [
+          new invokerChecker(EVENT_SHOW, this.accessible)
+        ];
+      }
+    }
+
+    function changeAttr(aID, aAttr, aValue)
+    {
+      this.__proto__ = new recreateAccessible(aID);
+
+      this.invoke = function changeAttr_invoke()
+      {
+        this.node.setAttribute(aAttr, aValue);
+      }
+
+      this.getID = function changeAttr_getID()
+      {
+        return "change " + aAttr + "attribute for " + aID;
+      }
+    }
+
+    function removeAttr(aID, aAttr)
+    {
+      this.__proto__ = new recreateAccessible(aID, true);
+
+      this.invoke = function remvoeAttr_invoke()
+      {
+        this.node.removeAttribute(aAttr);
+      }
+
+      this.getID = function remvoeAttr_getID()
+      {
+        return "remove " + aAttr + "attribute for " + aID;
+      }
+    }
+
+    function changeRole(aID, aHasAccessible)
+    {
+      this.__proto__ = new changeAttr(aID, "role", "button");
+    }
+
+    function removeRole(aID)
+    {
+      this.__proto__ = new removeAttr(aID, "role");
+    }
+
+    function changeOnclick(aID)
+    {
+      this.__proto__ = new changeAttr(aID, "onclick", "alert(3);");
+    }
+
+    function changeHref(aID)
+    {
+      this.__proto__ = new changeAttr(aID, "href", "www");
+    }
+
+    function changeMultiselectable(aID)
+    {
+      this.__proto__ = new changeAttr(aID, "aria-multiselectable", "true");
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Test
+
+    //gA11yEventDumpID = "eventdump"; // debug stuff
+    //gA11yEventDumpToConsole = true;
+
+    var gQueue = null;
+
+    function doTest()
+    {
+      gQueue = new eventQueue();
+
+      // make the accessible an inaccessible
+      gQueue.push(new changeRole("span"));
+
+      // make the inaccessible an accessible
+      gQueue.push(new removeRole("span"));
+
+      // recreate an accessible by role change
+      gQueue.push(new changeRole("div1"));
+
+      // recreate an accessible by onclick change
+      gQueue.push(new changeOnclick("div2"));
+
+      // recreate an accessible by href change
+      gQueue.push(new changeHref("anchor"));
+
+      // recreate an accessible by aria-multiselectable change
+      gQueue.push(new changeMultiselectable("div3"));
+
+      gQueue.invoke(); // SimpleTest.finish() will be called in the end
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     title="Rework accessible tree update code"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275">
+    Mozilla Bug 570275
+  </a>
+
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <span id="span">span</span>
+  <div id="div1">div</div>
+  <div id="div2">div</div>
+  <a id="anchor">anchor</a>
+  <div id="div3" role="listbox">list</div>
+
+  <div id="eventdump"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/treeupdate/test_tableinsubtree.html
@@ -0,0 +1,120 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <title>Table creation in ARIA dialog test</title>
+
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
+          src="../events.js"></script>
+
+  <script type="application/javascript">
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Invokers
+
+    function showARIADialog(aID)
+    {
+      this.node = getNode(aID);
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_SHOW, this.node)
+      ];
+
+      this.invoke = function showARIADialog_invoke()
+      {
+        this.node.style.display = "block";
+        getNode("input").value = "hello";
+        getNode("cell").textContent = "cell1";
+        getNode("input").focus();
+      }
+
+      this.finalCheck = function showARIADialog_finalCheck()
+      {
+        var tree = {
+          role: ROLE_DIALOG,
+          children: [
+            {
+              role: ROLE_TABLE,
+              children: [
+                {
+                  role: ROLE_ROW,
+                  children: [
+                    {
+                      role: ROLE_CELL,
+                      children: [ { role: ROLE_TEXT_LEAF } ]
+                    },
+                    {
+                      role: ROLE_CELL,
+                      children: [ { role: ROLE_ENTRY } ]
+                    }
+                  ]
+                }
+              ]
+            }
+          ]
+        };
+        testAccessibleTree(aID, tree);
+      }
+
+      this.getID = function showARIADialog_getID()
+      {
+        return "show ARIA dialog";
+      }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Test
+
+    //gA11yEventDumpID = "eventdump"; // debug stuff
+    //gA11yEventDumpToConsole = true;
+
+    var gQueue = null;
+
+    function doTest()
+    {
+      gQueue = new eventQueue();
+
+      // make the accessible an inaccessible
+      gQueue.push(new showARIADialog("dialog"));
+
+      gQueue.invoke(); // SimpleTest.finish() will be called in the end
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     title="Rework accessible tree update code"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275">
+    Mozilla Bug 570275
+  </a>
+
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <div id="dialog" role="dialog" style="display: none;">
+    <table>
+      <tr><td id="cell"></td><td><input id="input"></td>
+    </table>
+  </div>
+
+  <div id="eventdump"></div>
+</body>
+</html>
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -325,16 +325,17 @@ pref("browser.search.searchEnginesURL", 
 pref("browser.search.defaultenginename",      "chrome://browser-region/locale/region.properties");
 
 // disable logging for the search service by default
 pref("browser.search.log", false);
 
 // Ordering of Search Engines in the Engine list. 
 pref("browser.search.order.1",                "chrome://browser-region/locale/region.properties");
 pref("browser.search.order.2",                "chrome://browser-region/locale/region.properties");
+pref("browser.search.order.3",                "chrome://browser-region/locale/region.properties");
 
 // search bar results always open in a new tab
 pref("browser.search.openintab", false);
 
 // send ping to the server to update
 pref("browser.search.update", true);
 
 // disable logging for the search service update system by default
@@ -485,18 +486,18 @@ pref("intl.charset.detector", "chrome://
 pref("intl.charset.default",  "chrome://global-platform/locale/intl.properties");
 pref("font.language.group", "chrome://global/locale/intl.properties");
 pref("intl.menuitems.alwaysappendaccesskeys","chrome://global/locale/intl.properties");
 pref("intl.menuitems.insertseparatorbeforeaccesskeys","chrome://global/locale/intl.properties");
 
 // simple gestures support
 pref("browser.gesture.swipe.left", "Browser:BackOrBackDuplicate");
 pref("browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate");
-pref("browser.gesture.swipe.up", "cmd_scrollTop");
-pref("browser.gesture.swipe.down", "cmd_scrollBottom");
+pref("browser.gesture.swipe.up", "Browser:HideTabView");
+pref("browser.gesture.swipe.down", "Browser:ShowTabView");
 #ifdef XP_MACOSX
 pref("browser.gesture.pinch.latched", true);
 pref("browser.gesture.pinch.threshold", 150);
 #else
 pref("browser.gesture.pinch.latched", false);
 pref("browser.gesture.pinch.threshold", 25);
 #endif
 pref("browser.gesture.pinch.out", "cmd_fullZoomEnlarge");
@@ -786,28 +787,32 @@ pref("browser.sessionstore.resume_sessio
 
 // minimal interval between two save operations in milliseconds
 pref("browser.sessionstore.interval", 15000);
 // maximum amount of POSTDATA to be saved in bytes per history entry (-1 = all of it)
 // (NB: POSTDATA will be saved either entirely or not at all)
 pref("browser.sessionstore.postdata", 0);
 // on which sites to save text data, POSTDATA and cookies
 // 0 = everywhere, 1 = unencrypted sites, 2 = nowhere
-pref("browser.sessionstore.privacy_level", 1);
+pref("browser.sessionstore.privacy_level", 0);
 // the same as browser.sessionstore.privacy_level, but for saving deferred session data
-pref("browser.sessionstore.privacy_level_deferred", 2);
+pref("browser.sessionstore.privacy_level_deferred", 0);
 // how many tabs can be reopened (per window)
 pref("browser.sessionstore.max_tabs_undo", 10);
 // how many windows can be reopened (per session) - on non-OS X platforms this
 // pref may be ignored when dealing with pop-up windows to ensure proper startup
 pref("browser.sessionstore.max_windows_undo", 3);
 // number of crashes that can occur before the about:sessionrestore page is displayed
 // (this pref has no effect if more than 6 hours have passed since the last crash)
 pref("browser.sessionstore.max_resumed_crashes", 1);
-// number of tabs to restore concurrently
+// The number of tabs that can restore concurrently:
+// < 0 = All tabs can restore at the same time
+//   0 = Only the selected tab in each window will be restored
+//       Other tabs won't be restored until they are selected
+//   N = The number of tabs to restore at the same time
 pref("browser.sessionstore.max_concurrent_tabs", 3);
 
 // allow META refresh by default
 pref("accessibility.blockautorefresh", false);
 
 // Whether history is enabled or not.
 pref("places.history.enabled", true);
 
@@ -933,41 +938,39 @@ pref("browser.sessionstore.interval", 60
 pref("toolbar.customization.usesheet", true);
 #else
 pref("toolbar.customization.usesheet", false);
 #endif
 
 // The default for this pref reflects whether the build is capable of IPC.
 // (Turning it on in a no-IPC build will have no effect.)
 #ifdef XP_MACOSX
-// OSX still has only partial support for IPC.  Note that the PowerPC
-// and x86 builds must generate identical copies of this file, so we
-// can't make the prefs indicate that IPC is not available at all in
-// PowerPC builds.
-pref("dom.ipc.plugins.enabled", false);
-// These plug-ins will run OOP by default
-pref("dom.ipc.plugins.enabled.flash player.plugin", true);
-pref("dom.ipc.plugins.enabled.javaplugin2_npapi.plugin", true);
+// i386 ipc preferences
+pref("dom.ipc.plugins.enabled.i386", false);
+pref("dom.ipc.plugins.enabled.i386.flash player.plugin", true);
+pref("dom.ipc.plugins.enabled.i386.javaplugin2_npapi.plugin", true);
+// x86_64 ipc preferences
+pref("dom.ipc.plugins.enabled.x86_64", true);
 #elifdef MOZ_IPC
 pref("dom.ipc.plugins.enabled", true);
 #else
 pref("dom.ipc.plugins.enabled", false);
 #endif
 
 #ifdef XP_WIN
 #ifndef WINCE
 pref("browser.taskbar.previews.enable", true);
 pref("browser.taskbar.previews.max", 20);
 pref("browser.taskbar.previews.cachetime", 5);
 pref("browser.taskbar.lists.enabled", true);
 pref("browser.taskbar.lists.frequent.enabled", true);
 pref("browser.taskbar.lists.recent.enabled", false);
 pref("browser.taskbar.lists.maxListItemCount", 7);
 pref("browser.taskbar.lists.tasks.enabled", true);
-pref("browser.taskbar.lists.refreshInSeconds", 30);
+pref("browser.taskbar.lists.refreshInSeconds", 120);
 #endif
 #endif
 
 #ifdef MOZ_SERVICES_SYNC
 // The sync engines to use.
 pref("services.sync.registerEngines", "Bookmarks,Form,History,Password,Prefs,Tab");
 // Preferences to be synced by default
 pref("services.sync.prefs.sync.accessibility.blockautorefresh", true);
@@ -1038,18 +1041,18 @@ pref("services.sync.prefs.sync.security.
 pref("services.sync.prefs.sync.security.warn_leaving_secure", true);
 pref("services.sync.prefs.sync.security.warn_submit_insecure", true);
 pref("services.sync.prefs.sync.security.warn_viewing_mixed", true);
 pref("services.sync.prefs.sync.signon.rememberSignons", true);
 pref("services.sync.prefs.sync.spellchecker.dictionary", true);
 pref("services.sync.prefs.sync.xpinstall.whitelist.required", true);
 #endif
 
-// Disable the Error Console
+// Disable the error console and inspector
 pref("devtools.errorconsole.enabled", false);
-
-// disable the Inspector
 pref("devtools.inspector.enabled", false);
 
 // Whether the character encoding menu is under the main Firefox button. This
 // preference is a string so that localizers can alter it.
 pref("browser.menu.showCharacterEncoding", "chrome://browser/locale/browser.properties");
 
+// Whether the Panorama should animate going in/out of tabs
+pref("browser.panorama.animate_zoom", true);
--- a/browser/base/content/aboutHome.js
+++ b/browser/base/content/aboutHome.js
@@ -166,17 +166,17 @@ function showSnippets()
     let snippetsElt = document.getElementById("snippets");
     snippetsElt.innerHTML = snippets;
     // Scripts injected by innerHTML are inactive, so we have to relocate them
     // through DOM manipulation to activate their contents.
     Array.forEach(snippetsElt.getElementsByTagName("script"), function(elt) {
       let relocatedScript = document.createElement("script");
       relocatedScript.type = "text/javascript;version=1.8";
       relocatedScript.text = elt.text;
-      snippetsElt.replaceChild(relocatedScript, elt);
+      elt.parentNode.replaceChild(relocatedScript, elt);
     });
     snippetsElt.hidden = false;
   } else {
     // If there are no saved snippets, show one of the default ones.
     let defaultSnippetsElt = document.getElementById("defaultSnippets");
     let entries = defaultSnippetsElt.querySelectorAll("span");
     // Choose a random snippet.  Assume there is always at least one.
     let randIndex = Math.round(Math.random() * (entries.length - 1));
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -205,16 +205,17 @@
 #endif
               </menupopup>
             </menu>
 
             <menu id="view-menu" label="&viewMenu.label;"
                   accesskey="&viewMenu.accesskey;">
               <menupopup id="menu_viewPopup">
                 <menuitem id="menu_tabview"
+                          key="key_tabview"
                           label="&viewTabGroups.label;"
                           accesskey="&viewTabGroups.accesskey;"
                           command="Browser:ToggleTabView"/>
                 <menu id="viewToolbarsMenu"
                       label="&viewToolbarsMenu.label;"
                       accesskey="&viewToolbarsMenu.accesskey;">
                   <menupopup onpopupshowing="onViewToolbarsPopupShowing(event);">
                     <menuseparator/>
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -91,23 +91,43 @@ var StarUI = {
 
   // nsIDOMEventListener
   handleEvent: function SU_handleEvent(aEvent) {
     switch (aEvent.type) {
       case "popuphidden":
         if (aEvent.originalTarget == this.panel) {
           if (!this._element("editBookmarkPanelContent").hidden)
             this.quitEditMode();
+
           this._restoreCommandsState();
           this._itemId = -1;
-          this._uri = null;
           if (this._batching) {
             PlacesUIUtils.ptm.endBatch();
             this._batching = false;
           }
+
+          switch (this._actionOnHide) {
+            case "cancel": {
+              PlacesUIUtils.ptm.undoTransaction();
+              break;
+            }
+            case "remove": {
+              // Remove all bookmarks for the bookmark's url, this also removes
+              // the tags for the url.
+              PlacesUIUtils.ptm.beginBatch();
+              let itemIds = PlacesUtils.getBookmarksForURI(this._uriForRemoval);
+              for (let i = 0; i < itemIds.length; i++) {
+                let txn = PlacesUIUtils.ptm.removeItem(itemIds[i]);
+                PlacesUIUtils.ptm.doTransaction(txn);
+              }
+              PlacesUIUtils.ptm.endBatch();
+              break;
+            }
+          }
+          this._actionOnHide = "";
         }
         break;
       case "keypress":
         if (aEvent.getPreventDefault()) {
           // The event has already been consumed inside of the panel.
           break;
         }
         switch (aEvent.keyCode) {
@@ -180,22 +200,19 @@ var StarUI = {
     // then show Page Bookmarked, else if the bookmark did already exist,
     // we are about editing it, then use Edit This Bookmark.
     this._element("editBookmarkPanelTitle").value =
       this._batching ?
         gNavigatorBundle.getString("editBookmarkPanel.pageBookmarkedTitle") :
         gNavigatorBundle.getString("editBookmarkPanel.editBookmarkTitle");
 
     // No description; show the Done, Cancel;
-    // hide the Edit, Undo buttons
     this._element("editBookmarkPanelDescription").textContent = "";
     this._element("editBookmarkPanelBottomButtons").hidden = false;
     this._element("editBookmarkPanelContent").hidden = false;
-    this._element("editBookmarkPanelEditButton").hidden = true;
-    this._element("editBookmarkPanelUndoRemoveButton").hidden = true;
 
     // The remove button is shown only if we're not already batching, i.e.
     // if the cancel button/ESC does not remove the bookmark.
     this._element("editBookmarkPanelRemoveButton").hidden = this._batching;
 
     // The label of the remove button differs if the URI is bookmarked
     // multiple times.
     var bookmarks = PlacesUtils.getBookmarksForURI(gBrowser.currentURI);
@@ -232,138 +249,42 @@ var StarUI = {
       else {
         // Note this isn't actually used anymore, we should remove this
         // once we decide not to bring back the page bookmarked notification
         this.panel.focus();
       }
     }
   },
 
-  showPageBookmarkedNotification:
-  function PCH_showPageBookmarkedNotification(aItemId, aAnchorElement, aPosition) {
-    this._blockCommands(); // un-done in the popuphiding handler
-
-    var brandBundle = this._element("bundle_brand");
-    var brandShortName = brandBundle.getString("brandShortName");
-
-    // "Page Bookmarked" title
-    this._element("editBookmarkPanelTitle").value =
-      gNavigatorBundle.getString("editBookmarkPanel.pageBookmarkedTitle");
-
-    // description
-    this._element("editBookmarkPanelDescription").textContent =
-      gNavigatorBundle.getFormattedString("editBookmarkPanel.pageBookmarkedDescription",
-                                          [brandShortName]);
-
-    // show the "Edit.." button and the Remove Bookmark button, hide the
-    // undo-remove-bookmark button.
-    this._element("editBookmarkPanelEditButton").hidden = false;
-    this._element("editBookmarkPanelRemoveButton").hidden = false;
-    this._element("editBookmarkPanelUndoRemoveButton").hidden = true;
-
-    // unset the unstarred state, if set
-    this._element("editBookmarkPanelStarIcon").removeAttribute("unstarred");
-
-    this._itemId = aItemId !== undefined ? aItemId : this._itemId;
-    if (this.panel.state == "closed") {
-      // Consume dismiss clicks, see bug 400924
-      this.panel.popupBoxObject
-          .setConsumeRollupEvent(Ci.nsIPopupBoxObject.ROLLUP_CONSUME);
-      this.panel.openPopup(aAnchorElement, aPosition, -1, -1);
-    }
-    else
-      this.panel.focus();
-  },
-
   quitEditMode: function SU_quitEditMode() {
     this._element("editBookmarkPanelContent").hidden = true;
     this._element("editBookmarkPanelBottomButtons").hidden = true;
     gEditItemOverlay.uninitPanel(true);
   },
 
   editButtonCommand: function SU_editButtonCommand() {
     this.showEditBookmarkPopup();
   },
 
   cancelButtonOnCommand: function SU_cancelButtonOnCommand() {
-    // The order here is important! We have to hide the panel first, otherwise
-    // changes done as part of Undo may change the panel contents and by
-    // that force it to commit more transactions
+    this._actionOnHide = "cancel";
     this.panel.hidePopup();
-    this.endBatch();
-    PlacesUIUtils.ptm.undoTransaction();
   },
 
   removeBookmarkButtonCommand: function SU_removeBookmarkButtonCommand() {
-#ifdef ADVANCED_STARRING_UI
-    // In minimal mode ("page bookmarked" notification), the bookmark
-    // is removed and the panel is hidden immediately. In full edit mode,
-    // a "Bookmark Removed" notification along with an Undo button is
-    // shown
-    if (this._batching) {
-      PlacesUIUtils.ptm.endBatch();
-      PlacesUIUtils.ptm.beginBatch(); // allow undo from within the notification
-
-      // "Bookmark Removed" title (the description field is already empty in
-      // this mode)
-      this._element("editBookmarkPanelTitle").value =
-        gNavigatorBundle.getString("editBookmarkPanel.bookmarkedRemovedTitle");
-
-      // hide the edit panel
-      this.quitEditMode();
-
-      // Hide the remove bookmark button, show the undo-remove-bookmark
-      // button.
-      this._element("editBookmarkPanelUndoRemoveButton").hidden = false;
-      this._element("editBookmarkPanelRemoveButton").hidden = true;
-      this._element("editBookmarkPanelStarIcon").setAttribute("unstarred", "true");
-      this.panel.focus();
-    }
-#endif
-
-    // cache its uri so we can get the new itemId in the case of undo
-    this._uri = PlacesUtils.bookmarks.getBookmarkURI(this._itemId);
-
-    // remove all bookmarks for the bookmark's url, this also removes
-    // the tags for the url
-    var itemIds = PlacesUtils.getBookmarksForURI(this._uri);
-    for (var i=0; i < itemIds.length; i++) {
-      var txn = PlacesUIUtils.ptm.removeItem(itemIds[i]);
-      PlacesUIUtils.ptm.doTransaction(txn);
-    }
-
-#ifdef ADVANCED_STARRING_UI
-    // hidePopup resets our itemId, thus we call it only after removing
-    // the bookmark
-    if (!this._batching)
-#endif
-      this.panel.hidePopup();
-  },
-
-  undoRemoveBookmarkCommand: function SU_undoRemoveBookmarkCommand() {
-    // restore the bookmark by undoing the last transaction and go back
-    // to the edit state
-    this.endBatch();
-    PlacesUIUtils.ptm.undoTransaction();
-    this._itemId = PlacesUtils.getMostRecentBookmarkForURI(this._uri);
-    this.showEditBookmarkPopup();
+    this._uriForRemoval = PlacesUtils.bookmarks.getBookmarkURI(this._itemId);
+    this._actionOnHide = "remove";
+    this.panel.hidePopup();
   },
 
   beginBatch: function SU_beginBatch() {
     if (!this._batching) {
       PlacesUIUtils.ptm.beginBatch();
       this._batching = true;
     }
-  },
-
-  endBatch: function SU_endBatch() {
-    if (this._batching) {
-      PlacesUIUtils.ptm.endBatch();
-      this._batching = false;
-    }
   }
 }
 
 var PlacesCommandHook = {
   /**
    * Adds a bookmark to the page loaded in the given browser.
    *
    * @param aBrowser
@@ -424,20 +345,16 @@ var PlacesCommandHook = {
     if (aBrowser.contentWindow == window.content) {
       var starIcon = aBrowser.ownerDocument.getElementById("star-button");
       if (starIcon && isElementVisible(starIcon)) {
         // Make sure the bookmark properties dialog hangs toward the middle of
         // the location bar in RTL builds
         var position = (getComputedStyle(gNavToolbox, "").direction == "rtl") ? 'after_start' : 'after_end';
         if (aShowEditUI)
           StarUI.showEditBookmarkPopup(itemId, starIcon, position);
-#ifdef ADVANCED_STARRING_UI
-        else
-          StarUI.showPageBookmarkedNotification(itemId, starIcon, position);
-#endif
         return;
       }
     }
 
     StarUI.showEditBookmarkPopup(itemId, aBrowser, "overlap");
   },
 
   /**
@@ -545,25 +462,16 @@ var PlacesCommandHook = {
       // No currently open places window, so open one with the specified mode.
       openDialog("chrome://browser/content/places/places.xul", 
                  "", "chrome,toolbar=yes,dialog=no,resizable", aLeftPaneRoot);
     }
     else {
       organizer.PlacesOrganizer.selectLeftPaneQuery(aLeftPaneRoot);
       organizer.focus();
     }
-  },
-
-  deleteButtonOnCommand: function PCH_deleteButtonCommand() {
-    PlacesUtils.bookmarks.removeItem(gEditItemOverlay.itemId);
-
-    // remove all tags for the associated url
-    PlacesUtils.tagging.untagURI(gEditItemOverlay._uri, null);
-
-    this.panel.hidePopup();
   }
 };
 
 // View for the history menu.
 function HistoryMenu(aPopupShowingEvent) {
   XPCOMUtils.defineLazyServiceGetter(this, "_ss",
                                      "@mozilla.org/browser/sessionstore;1",
                                      "nsISessionStore");
@@ -1148,49 +1056,59 @@ let BookmarksMenuButton = {
 
   init: function BMB_init() {
     this.updatePosition();
 
     // Any other stuff that does not regard the button itself should be
     // handled in the onPopupShowing handler, so it does not hit Ts.
   },
 
-  _popupInitialized: false,
-  _popupNeedsUpdating: true,
+  _popupNeedsUpdate: {},
   onPopupShowing: function BMB_onPopupShowing(event) {
-    if (!this._popupNeedsUpdating)
+    // Don't handle events for submenus.
+    if (event.target != event.currentTarget)
       return;
-    this._popupNeedsUpdating = false;
+
+    let popup = event.target;
+    let needsUpdate = this._popupNeedsUpdate[popup.id];
 
-    let viewToolbar = document.getElementById("BMB_viewBookmarksToolbar");
-    if (!this._popupInitialized) {
-      // First popupshowing event, initialize immutable attributes.
-      this._popupInitialized = true;
+    // Check if popup contents need to be updated.  Note that if needsUpdate is
+    // undefined we have never seen the popup, thus it should be updated.
+    if (needsUpdate === false)
+      return;
+    this._popupNeedsUpdate[popup.id] = false;
+
+    function getPlacesAnonymousElement(aAnonId)
+      document.getAnonymousElementByAttribute(popup.parentNode,
+                                              "placesanonid",
+                                              aAnonId);
+
+    let viewToolbarMenuitem = getPlacesAnonymousElement("view-toolbar");
+    if (viewToolbarMenuitem) {
       // Update View bookmarks toolbar checkbox menuitem.
-      viewToolbar.setAttribute("toolbarId", this.personalToolbar.id);
-
-      // Need to set the label on Unsorted Bookmarks menu.
-      let unsortedBookmarksElt =
-        document.getElementById("BMB_unsortedBookmarksFolderMenu");
-      unsortedBookmarksElt.label =
-        PlacesUtils.getString("UnsortedBookmarksFolderTitle");
+      viewToolbarMenuitem.setAttribute("checked",
+                                       !this.personalToolbar.collapsed);
     }
 
-    // Update View Bookmarks Toolbar checkbox menuitem.
-    viewToolbar.setAttribute("checked", !this.personalToolbar.collapsed);
-
-    // Hide Bookmarks Toolbar menu if the button is next to the bookmarks
-    // toolbar item, show them otherwise.
-    let button = this.button;
-    document.getElementById("BMB_bookmarksToolbarFolderMenu").collapsed =
-      button && button.parentNode == this.bookmarksToolbarItem;
+    let toolbarMenuitem = getPlacesAnonymousElement("toolbar-autohide");
+    if (toolbarMenuitem) {
+      // If bookmarks items are visible, hide Bookmarks Toolbar menu and the
+      // separator after it.
+      toolbarMenuitem.collapsed = toolbarMenuitem.nextSibling.collapsed =
+        isElementVisible(this.bookmarksToolbarItem);
+    }
   },
 
   updatePosition: function BMB_updatePosition() {
-    this._popupNeedsUpdating = true;
+    // Popups will have to be updated when the user customizes the UI, or
+    // changes personal toolbar collapsed status.  Both of those location call
+    // updatePosition(), so this is the only point asking for popup updates.
+    for (let popupId in this._popupNeedsUpdate) {
+      this._popupNeedsUpdate[popupId] = true;
+    }
 
     let button = this.button;
     if (!button)
       return;
 
     // If the toolbar containing bookmarks is visible, we want to move the
     // button to bookmarksToolbarItem.
     let bookmarksToolbarItem = this.bookmarksToolbarItem;
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -112,16 +112,18 @@
     </command>
     <command id="Browser:ReloadSkipCache" oncommand="BrowserReloadSkipCache()" disabled="true">
       <observes element="Browser:Reload" attribute="disabled"/>
     </command>
     <command id="Browser:NextTab" oncommand="gBrowser.tabContainer.advanceSelectedTab(1, true);"/>
     <command id="Browser:PrevTab" oncommand="gBrowser.tabContainer.advanceSelectedTab(-1, true);"/>
     <command id="Browser:ShowAllTabs" oncommand="allTabs.open();"/>
     <command id="Browser:ToggleTabView" oncommand="TabView.toggle();"/>
+    <command id="Browser:ShowTabView" oncommand="TabView.show();"/>
+    <command id="Browser:HideTabView" oncommand="TabView.hide();"/>    
     <command id="cmd_fullZoomReduce"  oncommand="FullZoom.reduce()"/>
     <command id="cmd_fullZoomEnlarge" oncommand="FullZoom.enlarge()"/>
     <command id="cmd_fullZoomReset"   oncommand="FullZoom.reset()"/>
     <command id="cmd_fullZoomToggle"  oncommand="ZoomManager.toggleZoom();"/>
     <command id="Browser:OpenLocation" oncommand="openLocation();"/>
 
     <command id="Tools:Search" oncommand="BrowserSearch.webSearch();"/>
     <command id="Tools:Downloads" oncommand="BrowserDownloadsUI();"/>
@@ -211,34 +213,31 @@
          modifiers="alt"/>
 #endif
 
 #
 # Search Command Key Logic works like this:
 # 
 # Unix: Ctrl+K (cross platform binding)
 #       Ctrl+J (in case of emacs Ctrl-K conflict)
-# Mac:  Ctrl+K (cross platform binding)
+# Mac:  Cmd+K (cross platform binding)
+#       Cmd+Opt+F (platform convention)
 # Win:  Ctrl+K (cross platform binding)
-#       Ctrl+E (IE compat)
 #
 # We support Ctrl+K on all platforms now and advertise it in the menu since it is
 # our standard - it is a "safe" choice since it is near no harmful keys like "W" as
 # "E" is. People mourning the loss of Ctrl+K for emacs compat can switch their GTK
 # system setting to use emacs emulation, and we should respect it. Focus-Search-Box
 # is a fundamental keybinding and we are maintaining a XP binding so that it is easy
 # for people to switch to Linux.
 #
     <key id="key_search" key="&searchFocus.commandkey;" command="Tools:Search" modifiers="accel"/>
 #ifdef XP_MACOSX
     <key id="key_search2" key="&findOnCmd.commandkey;" command="Tools:Search" modifiers="accel,alt"/>
 #endif
-#ifdef XP_WIN
-    <key id="key_search2" key="&searchFocus.commandkey2;" command="Tools:Search" modifiers="accel"/>
-#endif
 #ifdef XP_GNOME
     <key id="key_search2" key="&searchFocusUnix.commandkey;" command="Tools:Search" modifiers="accel"/>
     <key id="key_openDownloads" key="&downloadsUnix.commandkey;" command="Tools:Downloads" modifiers="accel,shift"/>
 #else
     <key id="key_openDownloads" key="&downloads.commandkey;" command="Tools:Downloads" modifiers="accel"/>
 #endif
     <key id="key_openAddons" key="&addons.commandkey;" command="Tools:Addons" modifiers="accel,shift"/>
     <key id="key_errorConsole" key="&errorConsoleCmd.commandkey;" oncommand="toJavaScriptConsole();" modifiers="accel,shift" disabled="true"/>
@@ -343,16 +342,18 @@
     <key                          key="&fullZoomEnlargeCmd.commandkey3;" command="cmd_fullZoomEnlarge" modifiers="accel"/>
     <key id="key_fullZoomReset"   key="&fullZoomResetCmd.commandkey;"    command="cmd_fullZoomReset"   modifiers="accel"/>
     <key                          key="&fullZoomResetCmd.commandkey2;"   command="cmd_fullZoomReset"   modifiers="accel"/>
 
     <key id="key_showAllTabs" command="Browser:ShowAllTabs" keycode="VK_TAB" modifiers="control,shift"/>
 
     <key id="key_switchTextDirection" key="&bidiSwitchTextDirectionItem.commandkey;" command="cmd_switchTextDirection" modifiers="accel,shift" />
 
+    <key id="key_tabview" key="&tabView.commandkey;" command="Browser:ToggleTabView" modifiers="accel"/>
+
     <key id="key_privatebrowsing" command="Tools:PrivateBrowsing" key="&privateBrowsingCmd.commandkey;" modifiers="accel,shift"/>
     <key id="key_sanitize" command="Tools:Sanitize" keycode="VK_DELETE" modifiers="accel,shift"/>
 #ifdef XP_MACOSX
     <key id="key_sanitize_mac" command="Tools:Sanitize" keycode="VK_BACK" modifiers="accel,shift"/>
 #endif
 #ifdef XP_UNIX
     <key id="key_quitApplication" key="&quitApplicationCmdMac.key;" command="cmd_quitApplication" modifiers="accel"/>
 #endif
--- a/browser/base/content/browser-syncui.js
+++ b/browser/base/content/browser-syncui.js
@@ -190,17 +190,17 @@ let gSyncUI = {
 
   onSyncDelay: function SUI_onSyncDelay() {
     // basically, we want to just inform users that stuff is going to take a while
     let title = this._stringBundle.GetStringFromName("error.sync.no_node_found.title");
     let description = this._stringBundle.GetStringFromName("error.sync.no_node_found");
     let buttons = [new Weave.NotificationButton(
       this._stringBundle.GetStringFromName("error.sync.serverStatusButton.label"),
       this._stringBundle.GetStringFromName("error.sync.serverStatusButton.accesskey"),
-      function() { gWeaveWin.openServerStatus(); return true; }
+      function() { gSyncUI.openServerStatus(); return true; }
     )];
     let notification = new Weave.Notification(
       title, description, null, Weave.Notifications.PRIORITY_INFO, buttons);
     Weave.Notifications.replaceTitle(notification);
     this._wasDelayed = true;
   },
 
   onLoginFinish: function SUI_onLoginFinish() {
--- a/browser/base/content/browser-tabview.js
+++ b/browser/base/content/browser-tabview.js
@@ -207,57 +207,16 @@ let TabView = {
   _setBrowserKeyHandlers : function() {
     let self = this;
 
     window.addEventListener("keypress", function(event) {
       if (self.isVisible())
         return;
 
       let charCode = event.charCode;
-#ifdef XP_MACOSX
-      // if a text box in a webpage has the focus, the event.altKey would
-      // return false so we are depending on the charCode here.
-      if (!event.ctrlKey && !event.metaKey && !event.shiftKey &&
-          charCode == 160) { // alt + space
-#else
-      if (event.ctrlKey && !event.metaKey && !event.shiftKey && !event.altKey && 
-          charCode == KeyEvent.DOM_VK_SPACE) { // ctrl + space
-#endif
-
-        // Don't handle this event if it's coming from a node that might allow
-        // multiple keyboard selection like selects or trees
-        let node = event.target;
-        switch (node.namespaceURI) {
-          case "http://www.w3.org/1999/xhtml":
-            // xhtml:select only allows multiple when the attr is set
-            if (node.localName == "select" && node.hasAttribute("multiple"))
-              return;
-            break;
-
-          case "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul":
-            switch (node.localName) {
-              case "listbox":
-                // xul:listbox is by default single
-                if (node.getAttribute("seltype") == "multiple")
-                  return;
-                break;
-              case "tree":
-                // xul:tree is by default multiple
-                if (node.getAttribute("seltype") != "single")
-                  return;
-                break;
-            }
-        }
-
-        event.stopPropagation();
-        event.preventDefault();
-        self.show();
-        return;
-      }
-
       // Control (+ Shift) + `
       if (event.ctrlKey && !event.metaKey && !event.altKey &&
           (charCode == 96 || charCode == 126)) {
         event.stopPropagation();
         event.preventDefault();
 
         self._initFrame(function() {
           let tabItem = self._window.GroupItems.getNextGroupItemTab(event.shiftKey);
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -32,24 +32,24 @@ tabbrowser {
   -moz-transition: min-width .2s ease-out, max-width .25s ease-out;
 }
 
 .tabbrowser-tab:not([pinned]):not([fadein]) {
   max-width: 1px;
   min-width: 1px;
 }
 
-.tab-progress:not([fadein]):not([pinned]),
+.tab-throbber:not([fadein]):not([pinned]),
 .tab-label:not([fadein]):not([pinned]),
 .tab-icon-image:not([fadein]):not([pinned]),
 .tab-close-button:not([fadein]):not([pinned]) {
   opacity: 0 !important;
 }
 
-.tab-progress,
+.tab-throbber,
 .tab-label,
 .tab-icon-image,
 .tab-close-button {
   -moz-transition: opacity .25s;
 }
 
 .tabbrowser-tab[pinned] {
   position: fixed;
@@ -101,16 +101,24 @@ toolbarpaletteitem[place="palette"] > to
 toolbar:not([mode="icons"]) > #urlbar-container > #urlbar > toolbarbutton,
 toolbar[mode="icons"] > #urlbar-container > #urlbar > #urlbar-reload-button:not([displaystop]) + #urlbar-stop-button,
 toolbar[mode="icons"] > #urlbar-container > #urlbar > #urlbar-reload-button[displaystop],
 toolbar[mode="icons"] > #reload-button:not([displaystop]) + #stop-button,
 toolbar[mode="icons"] > #reload-button[displaystop] {
   visibility: collapse;
 }
 
+#feed-button > .toolbarbutton