Merge mozilla-central into Electrolysis
authorBenjamin Smedberg <benjamin@smedbergs.us>
Wed, 26 Aug 2009 12:15:27 -0400
changeset 35872 ef5eac530f6663ed097e63d78b36411157f662b3
parent 35871 5031157fc37803742c55ba45d84d48475784ff85 (current diff)
parent 31983 d25e72de30f1a518690f10499d5852d8a3713816 (diff)
child 35873 439cc0c773076b394c192f52a2588483b1821063
push idunknown
push userunknown
push dateunknown
milestone1.9.3a1pre
Merge mozilla-central into Electrolysis
.hgtags
accessible/src/atk/nsAppRootAccessible.cpp
accessible/src/atk/nsAppRootAccessible.h
browser/app/profile/firefox.js
browser/components/aboutRights.js
browser/components/aboutRobots.js
browser/components/certerror/aboutCertError.js
browser/components/feeds/src/nsAboutFeeds.cpp
browser/components/feeds/src/nsAboutFeeds.h
browser/components/privatebrowsing/src/aboutPrivateBrowsing.js
browser/components/sessionstore/src/aboutSessionRestore.js
browser/themes/pinstripe/browser/Toolbar-rtl.png
browser/themes/pinstripe/browser/places/selected-focused-gradient.png
browser/themes/pinstripe/browser/places/selected-gradient.png
config/autoconf.mk.in
config/javarules.mak
configure.in
content/base/src/Makefile.in
content/base/src/nsFrameLoader.cpp
content/base/src/nsFrameLoader.h
docshell/base/nsDocShell.cpp
dom/src/geolocation/MaemoLocationProvider.cpp
dom/src/geolocation/MaemoLocationProvider.h
embedding/config/readme.html
embedding/tests/os2Embed/Makefile.in
embedding/tests/os2Embed/SMALL.ICO
embedding/tests/os2Embed/WebBrowserChrome.cpp
embedding/tests/os2Embed/WebBrowserChrome.h
embedding/tests/os2Embed/WindowCreator.cpp
embedding/tests/os2Embed/WindowCreator.h
embedding/tests/os2Embed/os2Embed.ICO
embedding/tests/os2Embed/os2Embed.cpp
embedding/tests/os2Embed/os2Embed.h
embedding/tests/os2Embed/os2Embed.rc
embedding/tests/os2Embed/resource.h
extensions/layout-debug/ui/content/contents.rdf
extensions/layout-debug/ui/locale/en-US/contents.rdf
extensions/python/Makefile.in
extensions/python/dom/Makefile.in
extensions/python/dom/README.txt
extensions/python/dom/makefiles.sh
extensions/python/dom/nsdom/Makefile.in
extensions/python/dom/nsdom/__init__.py
extensions/python/dom/nsdom/context.py
extensions/python/dom/nsdom/domcompile.py
extensions/python/dom/nsdom/test/Makefile.in
extensions/python/dom/nsdom/test/regrtest.py
extensions/python/dom/nsdom/test/test_compile.py
extensions/python/dom/src/Makefile.in
extensions/python/dom/src/nsPyArgArray.cpp
extensions/python/dom/src/nsPyContext.cpp
extensions/python/dom/src/nsPyContext.h
extensions/python/dom/src/nsPyDOM.h
extensions/python/dom/src/nsPyDOMISupports.cpp
extensions/python/dom/src/nsPyDOMModule.cpp
extensions/python/dom/src/nsPyRuntime.cpp
extensions/python/dom/src/nsPyRuntime.h
extensions/python/dom/src/nsPyTimeout.cpp
extensions/python/dom/test/Makefile.in
extensions/python/dom/test/pyxultest/Makefile.in
extensions/python/dom/test/pyxultest/README.txt
extensions/python/dom/test/pyxultest/application.ini
extensions/python/dom/test/pyxultest/chrome/chrome.manifest
extensions/python/dom/test/pyxultest/chrome/content/dialog.xul
extensions/python/dom/test/pyxultest/chrome/content/document_write.xul
extensions/python/dom/test/pyxultest/chrome/content/html_content.html
extensions/python/dom/test/pyxultest/chrome/content/js_overlay.xul
extensions/python/dom/test/pyxultest/chrome/content/pytester.py
extensions/python/dom/test/pyxultest/chrome/content/pytester.xul
extensions/python/dom/test/pyxultest/chrome/content/python_overlay.xul
extensions/python/dom/test/pyxultest/chrome/content/pyxultest.css
extensions/python/dom/test/pyxultest/chrome/content/pyxultest.py
extensions/python/dom/test/pyxultest/chrome/content/pyxultest.xul
extensions/python/dom/test/pyxultest/jar.mn
extensions/python/dom/test/pyxultest/pyxultest-prefs.js
extensions/python/makefiles.sh
extensions/python/xpcom/Makefile.in
extensions/python/xpcom/__init__.py
extensions/python/xpcom/client/__init__.py
extensions/python/xpcom/components.py
extensions/python/xpcom/components/Makefile.in
extensions/python/xpcom/components/README.txt
extensions/python/xpcom/components/pyabout.py
extensions/python/xpcom/file.py
extensions/python/xpcom/makefiles.sh
extensions/python/xpcom/nsError.py
extensions/python/xpcom/primitives.py
extensions/python/xpcom/server/__init__.py
extensions/python/xpcom/server/enumerator.py
extensions/python/xpcom/server/factory.py
extensions/python/xpcom/server/loader.py
extensions/python/xpcom/server/module.py
extensions/python/xpcom/server/policy.py
extensions/python/xpcom/shutdown.py
extensions/python/xpcom/src/ErrorUtils.cpp
extensions/python/xpcom/src/Makefile.in
extensions/python/xpcom/src/PyGBase.cpp
extensions/python/xpcom/src/PyGInputStream.cpp
extensions/python/xpcom/src/PyGModule.cpp
extensions/python/xpcom/src/PyGStub.cpp
extensions/python/xpcom/src/PyGWeakReference.cpp
extensions/python/xpcom/src/PyIClassInfo.cpp
extensions/python/xpcom/src/PyIComponentManager.cpp
extensions/python/xpcom/src/PyIEnumerator.cpp
extensions/python/xpcom/src/PyIID.cpp
extensions/python/xpcom/src/PyIInputStream.cpp
extensions/python/xpcom/src/PyIInterfaceInfo.cpp
extensions/python/xpcom/src/PyIInterfaceInfoManager.cpp
extensions/python/xpcom/src/PyISimpleEnumerator.cpp
extensions/python/xpcom/src/PyISupports.cpp
extensions/python/xpcom/src/PyIVariant.cpp
extensions/python/xpcom/src/PyXPCOM.h
extensions/python/xpcom/src/PyXPCOM_std.h
extensions/python/xpcom/src/Pyxpt_info.cpp
extensions/python/xpcom/src/TypeObject.cpp
extensions/python/xpcom/src/VariantUtils.cpp
extensions/python/xpcom/src/dllmain.cpp
extensions/python/xpcom/src/loader/Makefile.in
extensions/python/xpcom/src/loader/pyloader.cpp
extensions/python/xpcom/src/module/Makefile.in
extensions/python/xpcom/src/module/_xpcom.cpp
extensions/python/xpcom/src/readme.html
extensions/python/xpcom/test/Makefile.in
extensions/python/xpcom/test/pyxpcom_test_tools.py
extensions/python/xpcom/test/regrtest.py
extensions/python/xpcom/test/test_com_exceptions.py
extensions/python/xpcom/test/test_comfile.py
extensions/python/xpcom/test/test_component/Makefile.in
extensions/python/xpcom/test/test_component/py_test_component.html
extensions/python/xpcom/test/test_component/py_test_component.idl
extensions/python/xpcom/test/test_component/py_test_component.py
extensions/python/xpcom/test/test_components.py
extensions/python/xpcom/test/test_isupports_primitives.py
extensions/python/xpcom/test/test_misc.py
extensions/python/xpcom/test/test_streams.py
extensions/python/xpcom/test/test_test_component.js
extensions/python/xpcom/test/test_test_component.py
extensions/python/xpcom/test/test_weakreferences.py
extensions/python/xpcom/tools/regxpcom.py
extensions/python/xpcom/tools/tracer_demo.py
extensions/python/xpcom/xpcom_consts.py
extensions/python/xpcom/xpt.py
gfx/thebes/src/gfxPlatform.cpp
gfx/thebes/src/gfxQuartzFontCache.h
gfx/thebes/src/gfxQuartzFontCache.mm
js/jsd/jsd.mak
js/jsd/jsdshell.mak
js/src/mandelbrot-results.js
js/src/math-trace-tests.js
js/src/trace-test.js
js/src/xpconnect/src/XPCDispParamPropJSClass.cpp
layout/build/nsLayoutStatics.cpp
layout/generic/nsIFrameDebug.h
layout/style/nsIInspectorCSSUtils.h
layout/style/nsInspectorCSSUtils.cpp
layout/style/nsInspectorCSSUtils.h
modules/plugin/base/src/Makefile.in
modules/plugin/base/src/nsNPAPIPlugin.cpp
modules/plugin/base/src/nsNPAPIPluginInstance.cpp
modules/plugin/base/src/nsPluginHost.cpp
modules/plugin/test/testplugin/nptest.cpp
modules/plugin/test/testplugin/nptest_gtk2.cpp
modules/plugin/test/testplugin/nptest_windows.cpp
netwerk/base/public/nsCPasswordManager.h
netwerk/base/public/nsCPasswordManagerInternal.h
netwerk/base/public/nsIPasswordManager.idl
netwerk/base/public/nsIPasswordManagerInternal.idl
netwerk/base/public/nsIPasswordManagerUtils.h
netwerk/base/public/nsISafeOutputStream.idl
testing/sisyphus/bin/hdiutil-expect.ex
testing/sisyphus/bin/set-msvc6-env.sh
testing/sisyphus/bin/set-msvc8-env.sh
testing/sisyphus/bin/smoke-build.sh
testing/sisyphus/bin/spider.pl
testing/sisyphus/bin/thunderbird.diff
testing/sisyphus/data/download-check,firefox-1.5.0-ftp,darwin.data
testing/sisyphus/data/download-check,firefox-1.5.0-ftp,linux.data
testing/sisyphus/data/download-check,firefox-1.5.0-ftp,nt.data
testing/sisyphus/data/download-check,firefox-2.0.0-ftp,darwin.data
testing/sisyphus/data/download-check,firefox-2.0.0-ftp,linux.data
testing/sisyphus/data/download-check,firefox-2.0.0-ftp,nt.data
testing/sisyphus/data/download-check,firefox-all,darwin.data
testing/sisyphus/data/download-check,firefox-all,linux.data
testing/sisyphus/data/download-check,firefox-all,nt.data
testing/sisyphus/data/download-check,firefox-all-older,darwin.data
testing/sisyphus/data/download-check,firefox-all-older,linux.data
testing/sisyphus/data/download-check,firefox-all-older,nt.data
testing/sisyphus/data/download-check,thunderbird-1.5.0-ftp,darwin.data
testing/sisyphus/data/download-check,thunderbird-1.5.0-ftp,linux.data
testing/sisyphus/data/download-check,thunderbird-1.5.0-ftp,nt.data
testing/sisyphus/data/download-check,thunderbird-2.0.0-ftp,darwin.data
testing/sisyphus/data/download-check,thunderbird-2.0.0-ftp,linux.data
testing/sisyphus/data/download-check,thunderbird-2.0.0-ftp,nt.data
testing/sisyphus/data/download-check,thunderbird-all,darwin.data
testing/sisyphus/data/download-check,thunderbird-all,linux.data
testing/sisyphus/data/download-check,thunderbird-all,nt.data
testing/sisyphus/data/download-check,thunderbird-all-older,darwin.data
testing/sisyphus/data/download-check,thunderbird-all-older,linux.data
testing/sisyphus/data/download-check,thunderbird-all-older,nt.data
testing/sisyphus/data/fennec,1.9.1,debug.data
testing/sisyphus/data/fennec,1.9.1,nightly-darwin.data
testing/sisyphus/data/fennec,1.9.1,nightly-linux.data
testing/sisyphus/data/fennec,1.9.1,nightly-nt.data
testing/sisyphus/data/fennec,1.9.1,opt.data
testing/sisyphus/data/fennec,1.9.1-test,debug.data
testing/sisyphus/data/fennec,1.9.1-test,opt.data
testing/sisyphus/data/fennec,1.9.2,debug.data
testing/sisyphus/data/fennec,1.9.2,opt.data
testing/sisyphus/data/fennec,1.9.2-test,debug.data
testing/sisyphus/data/fennec,1.9.2-test,opt.data
testing/sisyphus/data/firefox,1.8.0,nightly-darwin.data
testing/sisyphus/data/firefox,1.8.0,nightly-linux.data
testing/sisyphus/data/firefox,1.8.0,nightly-nt.data
testing/sisyphus/data/firefox,1.8.1,nightly-darwin.data
testing/sisyphus/data/firefox,1.8.1,nightly-linux.data
testing/sisyphus/data/firefox,1.8.1,nightly-nt.data
testing/sisyphus/data/firefox,1.9.0-jemalloc,debug.data
testing/sisyphus/data/firefox,1.9.0-jemalloc,opt.data
testing/sisyphus/data/firefox,1.9.0-jemalloc-test,debug.data
testing/sisyphus/data/firefox,1.9.0-jemalloc-test,opt.data
testing/sisyphus/data/firefox,1.9.1-actionmonkey,debug.data
testing/sisyphus/data/firefox,1.9.1-actionmonkey,opt.data
testing/sisyphus/data/firefox,1.9.1-jemalloc,debug.data
testing/sisyphus/data/firefox,1.9.1-jemalloc,opt.data
testing/sisyphus/data/firefox,1.9.1-jemalloc-test,debug.data
testing/sisyphus/data/firefox,1.9.1-jemalloc-test,opt.data
testing/sisyphus/data/firefox,1.9.1-tracemonkey,debug.data
testing/sisyphus/data/firefox,1.9.1-tracemonkey,opt.data
testing/sisyphus/data/firefox,1.9.1-tracemonkey-test,debug.data
testing/sisyphus/data/firefox,1.9.1-tracemonkey-test,opt.data
testing/sisyphus/data/js,1.9.1-actionmonkey,debug.data
testing/sisyphus/data/js,1.9.1-actionmonkey,opt.data
testing/sisyphus/data/js,1.9.1-tracemonkey,debug.data
testing/sisyphus/data/js,1.9.1-tracemonkey,opt.data
testing/sisyphus/data/js,1.9.1-tracemonkey-test,debug.data
testing/sisyphus/data/js,1.9.1-tracemonkey-test,opt.data
testing/sisyphus/data/thunderbird,1.8.0,debug.data
testing/sisyphus/data/thunderbird,1.8.0,opt.data
testing/sisyphus/data/thunderbird,1.8.0-test,debug.data
testing/sisyphus/data/thunderbird,1.8.1,debug.data
testing/sisyphus/data/thunderbird,1.8.1,opt.data
testing/sisyphus/data/thunderbird,1.8.1-test,debug.data
testing/sisyphus/data/thunderbird,1.9.0,debug.data
testing/sisyphus/data/thunderbird,1.9.0,opt.data
testing/sisyphus/data/thunderbird,1.9.0-test,debug.data
testing/sisyphus/data/thunderbird,1.9.1,debug.data
testing/sisyphus/data/thunderbird,1.9.1,opt.data
testing/sisyphus/data/thunderbird,1.9.1-test,debug.data
testing/xpcshell/tail.js
toolkit/components/autocomplete/public/nsIAutoCompleteResultTypes.idl
toolkit/components/autocomplete/src/nsAutoCompleteMdbResult.cpp
toolkit/components/autocomplete/src/nsAutoCompleteMdbResult.h
toolkit/components/places/tests/browser/399606-history.go-0.html
toolkit/components/places/tests/browser/399606-httprefresh.html
toolkit/components/places/tests/browser/399606-location.reload.html
toolkit/components/places/tests/browser/399606-location.replace.html
toolkit/components/places/tests/browser/399606-window.location.href.html
toolkit/components/places/tests/browser/399606-window.location.html
toolkit/components/places/tests/browser/browser_bug413985-history.go-0.js
toolkit/components/places/tests/browser/browser_bug413985-httprefresh.js
toolkit/components/places/tests/browser/browser_bug413985-location.reload.js
toolkit/components/places/tests/browser/browser_bug413985-location.replace.js
toolkit/components/places/tests/browser/browser_bug413985-window.location.href.js
toolkit/components/places/tests/browser/browser_bug413985-window.location.js
toolkit/content/tests/browser/bug471962_testpage_inner.sjs
toolkit/content/tests/browser/bug471962_testpage_outer.sjs
toolkit/mozapps/update/test/unit/head_update.js
toolkit/mozapps/update/test/unit/test_0040_general.js.in
toolkit/themes/pinstripe/global/icons/chevron-rtl.png
toolkit/themes/pinstripe/global/icons/find-bar-background.png
toolkit/themes/pinstripe/global/icons/white-gray-gradient-active.gif
toolkit/themes/pinstripe/global/icons/white-gray-gradient.gif
toolkit/themes/pinstripe/global/toolbar/white-transparent-gradient.png
toolkit/themes/winstripe/global/toolbar/chevron-rtl.gif
toolkit/xre/Makefile.in
toolkit/xre/nsAppRunner.cpp
tools/tests/LoadUrl.pl
tools/tests/SmokeTestLinux-1.pl
tools/tests/launchviewer.bat
tools/tests/mac/IntlSmoke.txt
tools/tests/mac/all_smoke.txt
tools/tests/mac/apFrame.inc
tools/tests/mac/i18n_smoketest.t
tools/tests/mac/smoketest.t
tools/tests/unix/smoke.pl
tools/tests/unix/url.txt
tools/tests/url.txt
tools/tests/win32/Copy.pm
tools/tests/win32/Intlurl.pl
tools/tests/win32/Intlurl.txt
tools/tests/win32/Process.pm
tools/tests/win32/apprunner.pl
tools/tests/win32/inbox
tools/tests/win32/inbox.snm
tools/tests/win32/mail.pl
tools/tests/win32/message.eml
tools/tests/win32/pop3.pl
tools/tests/win32/popresult.txt
tools/tests/win32/poptestdata.txt
tools/tests/win32/smoke.pl
tools/tests/win32/smtp.pl
tools/tests/win32/smtpresult.txt
tools/tests/win32/smtptestdata.txt
tools/tests/win32/test.pl
tools/tests/win32/url.pl
tools/tests/win32/url.txt
widget/src/os2/extradefs.os2
widget/src/os2/nsSwitchToUIThread.h
widget/src/windows/nsSwitchToUIThread.h
widget/src/xpwidgets/Makefile.in
xpcom/build/Makefile.in
xulrunner/app/document-os2.ico
--- a/.hgtags
+++ b/.hgtags
@@ -29,8 +29,9 @@ 8df5a90281cd4d75835e4b7696da200555eed15f
 8a601ed6bc4c7b3d1e35aa9e81f257512d984bd5 FENNEC_A2
 d7d64f68423b68a671f623f123e90057ebc49dac UPDATE_PACKAGING_R7
 fb32f6e1859c07846a01b4478a7b1678019e0b45 UPDATE_PACKAGING_R7
 f817a4378f32b1ad0a7c4b5a9949586dba816da5 FENNEC_M11
 5c1e7c779b6edc8ff912001990edc579f80597f4 FENNEC_B1
 fe9cc55b8db7f56f7e68a246acba363743854979 UPDATE_PACKAGING_R8
 6fd4bb500d425c406c1b52f66e5b195b20ae5e0a chromium-import-r15462
 6fd4bb500d425c406c1b52f66e5b195b20ae5e0a chromium-import-latest
+376b78fc72230aaf2ca4e279a8f4ef1efd4a1d9f GECKO_1_9_2_BASE
--- a/accessible/build/Makefile.in
+++ b/accessible/build/Makefile.in
@@ -49,18 +49,16 @@ EXPORT_LIBRARY = 1
 ifneq ($(OS_ARCH),WINNT)
 SHORT_LIBNAME	= access
 endif
 IS_COMPONENT	= 1
 MODULE_NAME	= nsAccessibilityModule
 GRE_MODULE	= 1
 LIBXUL_LIBRARY	= 1
 
-REQUIRES	= xpcom \
-		  $(NULL)
 
 CPPSRCS		= nsAccessibilityFactory.cpp
 
 LOCAL_INCLUDES	= -I$(srcdir)/../src
 
 SHARED_LIBRARY_LIBS = \
 	../src/base/$(LIB_PREFIX)accessibility_base_s.$(LIB_SUFFIX) \
 	../src/html/$(LIB_PREFIX)accessibility_html_s.$(LIB_SUFFIX) \
--- a/accessible/src/atk/Makefile.in
+++ b/accessible/src/atk/Makefile.in
@@ -40,40 +40,23 @@ srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = accessibility
 LIBRARY_NAME = accessibility_toolkit_s
 LIBXUL_LIBRARY = 1
 
-REQUIRES	= content \
-		  docshell \
-		  dom \
-		  editor \
-		  gfx \
-		  thebes \
-		  intl \
-		  layout \
-		  locale \
-		  necko \
-		  string \
-		  uriloader \
-		  view \
-		  webshell \
-		  widget \
-		  xpcom \
-		  $(NULL)
 
 CPPSRCS = \
   nsAccessNodeWrap.cpp \
   nsAccessibleWrap.cpp \
   nsDocAccessibleWrap.cpp \
   nsRootAccessibleWrap.cpp \
-  nsAppRootAccessible.cpp \
+  nsApplicationAccessibleWrap.cpp \
   nsMaiInterfaceComponent.cpp \
   nsMaiInterfaceAction.cpp \
   nsMaiInterfaceText.cpp \
   nsMaiInterfaceEditableText.cpp \
   nsMaiInterfaceSelection.cpp \
   nsMaiInterfaceValue.cpp \
   nsMaiHyperlink.cpp \
   nsMaiInterfaceHypertext.cpp \
--- a/accessible/src/atk/nsAccessNodeWrap.cpp
+++ b/accessible/src/atk/nsAccessNodeWrap.cpp
@@ -32,17 +32,17 @@
  * 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 ***** */
 
 #include "nsAccessNodeWrap.h"
-#include "nsAppRootAccessible.h"
+#include "nsApplicationAccessibleWrap.h"
 
 /* For documentation of the accessibility architecture, 
  * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
  */
 
 
 /*
  * Class nsAccessNodeWrap
--- a/accessible/src/atk/nsAccessibleWrap.cpp
+++ b/accessible/src/atk/nsAccessibleWrap.cpp
@@ -35,16 +35,17 @@
  * 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 ***** */
 
 #include "nsAccessibleWrap.h"
+#include "nsApplicationAccessibleWrap.h"
 #include "nsRootAccessible.h"
 #include "nsDocAccessibleWrap.h"
 #include "nsIAccessibleValue.h"
 #include "nsString.h"
 #include "nsAutoPtr.h"
 #include "prprf.h"
 #include "nsRoleMap.h"
 #include "nsStateMap.h"
@@ -58,19 +59,18 @@
 #include "nsMaiInterfaceHypertext.h"
 #include "nsMaiInterfaceHyperlinkImpl.h"
 #include "nsMaiInterfaceTable.h"
 #include "nsXPCOMStrings.h"
 #include "nsComponentManagerUtils.h"
 #include "nsMaiInterfaceDocument.h"
 #include "nsMaiInterfaceImage.h"
 
-#include "nsAppRootAccessible.h"
-
-extern "C" GType g_atk_hyperlink_impl_type; //defined in nsAppRootAccessible.cpp
+//defined in nsApplicationAccessibleWrap.cpp
+extern "C" GType g_atk_hyperlink_impl_type;
 
 /* MaiAtkObject */
 
 enum {
   ACTIVATE,
   CREATE,
   DEACTIVATE,
   DESTROY,
rename from accessible/src/atk/nsAppRootAccessible.cpp
rename to accessible/src/atk/nsApplicationAccessibleWrap.cpp
--- a/accessible/src/atk/nsAppRootAccessible.cpp
+++ b/accessible/src/atk/nsApplicationAccessibleWrap.cpp
@@ -34,24 +34,26 @@
  * 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 ***** */
 
+#include "nsApplicationAccessibleWrap.h"
+
 #include "nsCOMPtr.h"
 #include "nsMai.h"
-#include "nsAppRootAccessible.h"
 #include "prlink.h"
 #include "prenv.h"
 #include "nsIPrefBranch.h"
 #include "nsIServiceManager.h"
 #include "nsAutoPtr.h"
+#include "nsAccessibilityService.h"
 
 #include <gtk/gtk.h>
 #include <atk/atk.h>
 
 typedef GType (* AtkGetTypeType) (void);
 GType g_atk_hyperlink_impl_type = G_TYPE_INVALID;
 static PRBool sATKChecked = PR_FALSE;
 static PRLibrary *sATKLib = nsnull;
@@ -430,27 +432,31 @@ mai_util_remove_key_event_listener (guin
     if (g_hash_table_size(key_listener_list) == 0) {
         gtk_key_snooper_remove(key_snooper_id);
     }
 }
 
 AtkObject *
 mai_util_get_root(void)
 {
+    if (nsAccessibilityService::gIsShutdown) {
+        // We've shutdown, try to use gail instead
+        // (to avoid assert in spi_atk_tidy_windows())
+        if (gail_get_root)
+            return gail_get_root();
+
+        return nsnull;
+    }
+
     nsRefPtr<nsApplicationAccessibleWrap> root =
         nsAccessNode::GetApplicationAccessible();
 
     if (root)
         return root->GetAtkObject();
 
-    // We've shutdown, try to use gail instead
-    // (to avoid assert in spi_atk_tidy_windows())
-    if (gail_get_root)
-        return gail_get_root();
-
     return nsnull;
 }
 
 G_CONST_RETURN gchar *
 mai_util_get_toolkit_name(void)
 {
     return MAI_NAME;
 }
rename from accessible/src/atk/nsAppRootAccessible.h
rename to accessible/src/atk/nsApplicationAccessibleWrap.h
--- a/accessible/src/atk/nsXULTreeAccessibleWrap.cpp
+++ b/accessible/src/atk/nsXULTreeAccessibleWrap.cpp
@@ -40,411 +40,52 @@
 #include "nsIDOMElement.h"
 #include "nsITreeSelection.h"
 #include "nsITreeColumns.h"
 #include "nsXULTreeAccessibleWrap.h"
 
 // --------------------------------------------------------
 // nsXULTreeAccessibleWrap Accessible
 // --------------------------------------------------------
-NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeAccessibleWrap, nsXULTreeAccessible, nsIAccessibleTable)
 
-nsXULTreeAccessibleWrap::nsXULTreeAccessibleWrap(nsIDOMNode *aDOMNode, nsIWeakReference *aShell):
-nsXULTreeAccessible(aDOMNode, aShell)
+nsXULTreeGridAccessibleWrap::
+  nsXULTreeGridAccessibleWrap(nsIDOMNode *aDOMNode, nsIWeakReference *aShell):
+  nsXULTreeGridAccessible(aDOMNode, aShell)
 {
 }
 
-// tree's children count is row count * col count + treecols count
-// override "children count = row count + treecols count" defined in
-// nsXULTreeAccessible
-NS_IMETHODIMP nsXULTreeAccessibleWrap::GetChildCount(PRInt32 *aAccChildCount)
-{
-  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
-
-  // get treecols count, which is cached by nsAccessibleTreeWalker
-  // by going through DOM structure of XUL tree
-  nsAccessible::GetChildCount(aAccChildCount);
-
-  if (*aAccChildCount != 0 && *aAccChildCount != eChildCountUninitialized) {
-    // add the count of table cell (or tree item) accessibles, which are
-    // created and appended by XUL tree accessible implementation
-    PRInt32 rowCount, colCount = 1;
-    mTreeView->GetRowCount(&rowCount);
-    GetColumns(&colCount);
-
-    *aAccChildCount += rowCount * colCount;
-  }
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsXULTreeAccessibleWrap::GetCaption(nsIAccessible **aCaption)
-{
-  *aCaption = nsnull;
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsXULTreeAccessibleWrap::GetSummary(nsAString &aSummary)
-{
-  aSummary.Truncate();
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsXULTreeAccessibleWrap::GetColumns(PRInt32 *aColumnCount)
-{
-  NS_ENSURE_ARG_POINTER(aColumnCount);
-  *aColumnCount = 0;
-
-  nsCOMPtr<nsITreeColumn> column;
-  column = GetFirstVisibleColumn(mTree);
-  if (!column)
-    return NS_ERROR_FAILURE;
-
-  do {
-    (*aColumnCount)++;
-  } while ((column = GetNextVisibleColumn(column)));
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsXULTreeAccessibleWrap::GetColumnHeader(nsIAccessibleTable **aColumnHeader)
+NS_IMETHODIMP
+nsXULTreeGridAccessibleWrap::GetColumnHeader(nsIAccessibleTable **aColumnHeader)
 {
   nsresult rv = NS_OK;
 
   nsCOMPtr<nsIAccessible> acc;
   nsAccessible::GetFirstChild(getter_AddRefs(acc));
   NS_ENSURE_TRUE(acc, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIAccessibleTable> accTable(do_QueryInterface(acc, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
   *aColumnHeader = accTable;
   NS_IF_ADDREF(*aColumnHeader);
 
   return rv;
 }
 
-NS_IMETHODIMP nsXULTreeAccessibleWrap::GetRows(PRInt32 *aRows)
-{
-  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
-
-  return mTreeView->GetRowCount(aRows);
-}
-
-NS_IMETHODIMP nsXULTreeAccessibleWrap::GetRowHeader(nsIAccessibleTable **aRowHeader)
-{
-  // Row header not supported
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
 NS_IMETHODIMP
-nsXULTreeAccessibleWrap::GetSelectedCellsCount(PRUint32* aCount)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsXULTreeAccessibleWrap::GetSelectedColumnsCount(PRUint32* aCount)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsXULTreeAccessibleWrap::GetSelectedRowsCount(PRUint32* aCount)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsXULTreeAccessibleWrap::GetSelectedCells(PRUint32 *aNumCells,
-                                          PRInt32 **aCells)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP nsXULTreeAccessibleWrap::GetSelectedColumns(PRUint32 *aNumColumns, PRInt32 **aColumns)
-{
-  // If all the row has been selected, then all the columns are selected.
-  // Because we can't select a column alone.
-  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
-  NS_ENSURE_ARG_POINTER(aNumColumns);
-
-  nsresult rv = NS_OK;
-
-  PRInt32 rows;
-  rv = GetRows(&rows);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  PRInt32 selectedRows;
-  rv = GetSelectionCount(&selectedRows);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (rows == selectedRows) {
-    PRInt32 columns;
-    rv = GetColumns(&columns);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    *aNumColumns = columns;
-  } else {
-    *aNumColumns = 0;
-    return rv;
-  }
-
-  PRInt32 *outArray = (PRInt32 *)nsMemory::Alloc((*aNumColumns) * sizeof(PRInt32));
-  NS_ENSURE_TRUE(outArray, NS_ERROR_OUT_OF_MEMORY);
-
-  for (PRUint32 index = 0; index < *aNumColumns; index++) {
-    outArray[index] = index;
-  }
-
-  *aColumns = outArray;
-  return rv;
-}
-
-NS_IMETHODIMP nsXULTreeAccessibleWrap::GetSelectedRows(PRUint32 *aNumRows, PRInt32 **aRows)
-{
-  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
-  NS_ENSURE_ARG_POINTER(aNumRows);
-
-  nsresult rv = NS_OK;
-
-  rv = GetSelectionCount((PRInt32 *)aNumRows);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  PRInt32 *outArray = (PRInt32 *)nsMemory::Alloc((*aNumRows) * sizeof(PRInt32));
-  NS_ENSURE_TRUE(outArray, NS_ERROR_OUT_OF_MEMORY);
-
-  nsCOMPtr<nsITreeView> view;
-  rv = mTree->GetView(getter_AddRefs(view));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsITreeSelection> selection;
-  rv = view->GetSelection(getter_AddRefs(selection));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  PRInt32 rowCount;
-  rv = GetRows(&rowCount);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  PRBool isSelected;
-  PRInt32 index, curr = 0;
-  for (index = 0; index < rowCount; index++) {
-    selection->IsSelected(index, &isSelected);
-    if (isSelected) {
-      outArray[curr++] = index;
-    }
-  }
-
-  *aRows = outArray;
-  return rv;
-}
-
-NS_IMETHODIMP nsXULTreeAccessibleWrap::CellRefAt(PRInt32 aRow, PRInt32 aColumn, nsIAccessible **aAccessibleCell)
-{
-  NS_ENSURE_TRUE(mDOMNode && mTree, NS_ERROR_FAILURE);
-
-  nsresult rv = NS_OK;
-
-  PRInt32 index;
-  rv = GetIndexAt(aRow, aColumn, &index);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return GetChildAt(index, aAccessibleCell);
-}
-
-NS_IMETHODIMP nsXULTreeAccessibleWrap::GetIndexAt(PRInt32 aRow, PRInt32 aColumn, PRInt32 *aIndex)
-{
-  NS_ENSURE_TRUE(mDOMNode, NS_ERROR_FAILURE);
-  NS_ENSURE_ARG_POINTER(aIndex);
-
-  nsresult rv = NS_OK;
-
-  PRInt32 columns;
-  rv = GetColumns(&columns);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  PRInt32 treeCols;
-  nsAccessible::GetChildCount(&treeCols);
-  *aIndex = aRow * columns + aColumn + treeCols;
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsXULTreeAccessibleWrap::GetColumnAtIndex(PRInt32 aIndex, PRInt32 *aColumn)
-{
-  NS_ENSURE_ARG_POINTER(aColumn);
-
-  *aColumn = -1;
-  nsresult rv = NS_OK;
-
-  PRInt32 columns;
-  rv = GetColumns(&columns);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  PRInt32 treeCols;
-  nsAccessible::GetChildCount(&treeCols);
-
-  if (aIndex >= treeCols) {
-    *aColumn = (aIndex - treeCols) % columns;
-  }
-  
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsXULTreeAccessibleWrap::GetRowAtIndex(PRInt32 aIndex, PRInt32 *aRow)
-{
-  NS_ENSURE_ARG_POINTER(aRow);
-
-  *aRow = -1;
-  nsresult rv = NS_OK;
-
-  PRInt32 columns;
-  rv = GetColumns(&columns);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  PRInt32 treeCols;
-  nsAccessible::GetChildCount(&treeCols);
-
-  if (aIndex >= treeCols) {
-    *aRow = (aIndex - treeCols) / columns;
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsXULTreeAccessibleWrap::GetColumnExtentAt(PRInt32 aRow, PRInt32 aColumn, PRInt32 *_retval)
-{
-  NS_ENSURE_ARG_POINTER(_retval);
-
-  *_retval = 1;
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsXULTreeAccessibleWrap::GetRowExtentAt(PRInt32 aRow, PRInt32 aColumn, PRInt32 *_retval)
-{
-  NS_ENSURE_ARG_POINTER(_retval);
-
-  *_retval = 1;
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsXULTreeAccessibleWrap::GetColumnDescription(PRInt32 aColumn, nsAString & _retval)
+nsXULTreeGridAccessibleWrap::GetColumnDescription(PRInt32 aColumn, nsAString & _retval)
 {
   nsCOMPtr<nsIAccessibleTable> columnHeader;
   nsresult rv = GetColumnHeader(getter_AddRefs(columnHeader));
   if (NS_SUCCEEDED(rv) && columnHeader) {
     return columnHeader->GetColumnDescription(aColumn, _retval);
   }
   return NS_ERROR_FAILURE;
 }
 
-NS_IMETHODIMP nsXULTreeAccessibleWrap::GetRowDescription(PRInt32 aRow, nsAString & _retval)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP nsXULTreeAccessibleWrap::IsColumnSelected(PRInt32 aColumn, PRBool *_retval)
-{
-  // If all the row has been selected, then all the columns are selected.
-  // Because we can't select a column alone.
-  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
-  NS_ENSURE_ARG_POINTER(_retval);
-
-  nsresult rv = NS_OK;
-
-  PRInt32 rows;
-  rv = GetRows(&rows);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  PRInt32 selectedRows;
-  rv = GetSelectionCount(&selectedRows);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  *_retval = rows == selectedRows;
-  return rv;
-}
-
-NS_IMETHODIMP nsXULTreeAccessibleWrap::IsRowSelected(PRInt32 aRow, PRBool *_retval)
-{
-  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
-
-  nsresult rv = NS_OK;
-
-  nsCOMPtr<nsITreeView> view;
-  rv = mTree->GetView(getter_AddRefs(view));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsITreeSelection> selection;
-  rv = view->GetSelection(getter_AddRefs(selection));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return selection->IsSelected(aRow, _retval);
-}
-
-NS_IMETHODIMP nsXULTreeAccessibleWrap::IsCellSelected(PRInt32 aRow, PRInt32 aColumn, PRBool *_retval)
-{
-  return IsRowSelected(aRow, _retval);
-}
-
-NS_IMETHODIMP
-nsXULTreeAccessibleWrap::SelectRow(PRInt32 aRow)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsXULTreeAccessibleWrap::SelectColumn(PRInt32 aColumn)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsXULTreeAccessibleWrap::UnselectRow(PRInt32 aRow)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsXULTreeAccessibleWrap::UnselectColumn(PRInt32 aColumn)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP nsXULTreeAccessibleWrap::ChangeSelection(PRInt32 aIndex, PRUint8 aMethod, PRBool *aSelState)
-{
-  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
-
-  PRInt32 rowIndex;
-  nsresult rv = GetRowAtIndex(aIndex, &rowIndex);
-
-  nsCOMPtr<nsITreeSelection> selection;
-  rv = mTreeView->GetSelection(getter_AddRefs(selection));
-  NS_ASSERTION(selection, "Can't get selection from mTreeView");
-
-  if (selection) {
-    selection->IsSelected(rowIndex, aSelState);
-    // XXX: Can move to nsXULTreeAccessible if this can be applied to cross-platform
-    if ((!(*aSelState) && eSelection_Add == aMethod)) {
-      nsresult rv = selection->Select(rowIndex);
-      mTree->EnsureRowIsVisible(aIndex);
-      return rv;
-    }
-    // XXX: Will eSelection_Remove happen for XULTree? Leave the original implementation here
-    if ((*aSelState) && eSelection_Remove == aMethod) {
-      return selection->ToggleSelect(rowIndex);
-    }
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsXULTreeAccessibleWrap::IsProbablyForLayout(PRBool *aIsProbablyForLayout)
-{
-  *aIsProbablyForLayout = PR_FALSE;
-  return NS_OK;
-}
-
 // --------------------------------------------------------
 // nsXULTreeColumnsAccessibleWrap Accessible
 // --------------------------------------------------------
 NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeColumnsAccessibleWrap, nsXULTreeColumnsAccessible, nsIAccessibleTable)
 
 nsXULTreeColumnsAccessibleWrap::nsXULTreeColumnsAccessibleWrap(nsIDOMNode *aDOMNode, nsIWeakReference *aShell):
 nsXULTreeColumnsAccessible(aDOMNode, aShell)
 {
--- a/accessible/src/atk/nsXULTreeAccessibleWrap.h
+++ b/accessible/src/atk/nsXULTreeAccessibleWrap.h
@@ -35,43 +35,31 @@
  * 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 __nsXULTreeAccessibleWrap_h__
 #define __nsXULTreeAccessibleWrap_h__
 
-#include "nsIAccessibleTable.h"
-#include "nsXULTreeAccessible.h"
+#include "nsXULTreeGridAccessible.h"
 
-typedef class nsXULTreeitemAccessible nsXULTreeitemAccessibleWrap;
-
-class nsXULTreeAccessibleWrap : public nsXULTreeAccessible,
-                                public nsIAccessibleTable
+class nsXULTreeGridAccessibleWrap : public nsXULTreeGridAccessible
 {
 public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIACCESSIBLETABLE
-
-  nsXULTreeAccessibleWrap(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
-  virtual ~nsXULTreeAccessibleWrap() {}
+  nsXULTreeGridAccessibleWrap(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
 
-  // nsIAccessible
-  NS_IMETHOD GetChildCount(PRInt32 *_retval);
-
-protected:
-  NS_IMETHOD ChangeSelection(PRInt32 aIndex, PRUint8 aMethod,
-                             PRBool *aSelState);
+  // nsIAccessibleTable
+  NS_IMETHOD GetColumnHeader(nsIAccessibleTable **aColumnHeader);
+  NS_IMETHOD GetColumnDescription(PRInt32 aColumn, nsAString& aDescription);
 };
 
 class nsXULTreeColumnsAccessibleWrap : public nsXULTreeColumnsAccessible,
                                        public nsIAccessibleTable
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIACCESSIBLETABLE
 
   nsXULTreeColumnsAccessibleWrap(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
-  virtual ~nsXULTreeColumnsAccessibleWrap() {}
 };
 
 #endif
--- a/accessible/src/base/Makefile.in
+++ b/accessible/src/base/Makefile.in
@@ -41,41 +41,16 @@ srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = accessibility
 LIBRARY_NAME = accessibility_base_s
 LIBXUL_LIBRARY = 1
 
-REQUIRES	= appshell \
-		  commandhandler \
-		  composer \
-		  content \
-		  docshell \
-		  dom \
-		  editor \
-		  gfx \
-		  thebes \
-		  intl \
-		  layout \
-		  locale \
-		  necko \
-		  plugin \
-		  pref \
-		  string \
-		  unicharutil \
-		  uriloader \
-		  view \
-		  webshell \
-		  widget \
-		  xpcom \
-		  xuldoc \
-		  imglib2 \
-		  $(NULL)
 
 CPPSRCS = \
   nsAccessNode.cpp \
   nsAccessibleEventData.cpp \
   nsARIAGridAccessible.cpp \
   nsARIAMap.cpp \
   nsDocAccessible.cpp \
   nsOuterDocAccessible.cpp \
--- a/accessible/src/base/nsAccUtils.cpp
+++ b/accessible/src/base/nsAccUtils.cpp
@@ -45,17 +45,17 @@
 #include "nsAccessibleEventData.h"
 #include "nsHyperTextAccessible.h"
 #include "nsHTMLTableAccessible.h"
 #include "nsDocAccessible.h"
 #include "nsAccessibilityAtoms.h"
 #include "nsAccessibleTreeWalker.h"
 #include "nsAccessible.h"
 #include "nsARIAMap.h"
-#include "nsXULTreeAccessible.h"
+#include "nsXULTreeGridAccessible.h"
 
 #include "nsIDOMXULContainerElement.h"
 #include "nsIDOMXULSelectCntrlEl.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
 #include "nsWhitespaceTokenizer.h"
 
 void
 nsAccUtils::GetAccAttr(nsIPersistentProperties *aAttributes,
@@ -774,26 +774,16 @@ already_AddRefed<nsXULTreeAccessible>
 nsAccUtils::QueryAccessibleTree(nsIAccessible *aAccessible)
 {
   nsXULTreeAccessible* accessible = nsnull;
   if (aAccessible)
     CallQueryInterface(aAccessible, &accessible);
 
   return accessible;
 }
-
-already_AddRefed<nsXULTreeitemAccessible>
-nsAccUtils::QueryAccessibleTreeitem(nsIAccessNode *aAccessNode)
-{
-  nsXULTreeitemAccessible* accessible = nsnull;
-  if (aAccessNode)
-    CallQueryInterface(aAccessNode, &accessible);
-
-  return accessible;
-}
 #endif
 
 #ifdef DEBUG_A11Y
 
 PRBool
 nsAccUtils::IsTextInterfaceSupportCorrect(nsIAccessible *aAccessible)
 {
   PRBool foundText = PR_FALSE;
--- a/accessible/src/base/nsAccUtils.h
+++ b/accessible/src/base/nsAccUtils.h
@@ -53,17 +53,16 @@
 #include "nsPoint.h"
 
 class nsAccessNode;
 class nsAccessible;
 class nsHTMLTableAccessible;
 class nsDocAccessible;
 #ifdef MOZ_XUL
 class nsXULTreeAccessible;
-class nsXULTreeitemAccessible;
 #endif
 
 class nsAccUtils
 {
 public:
   /**
    * Returns value of attribute from the given attributes container.
    *
@@ -285,16 +284,38 @@ public:
 
   /**
    * Return the 'live' or 'container-live' object attribute value from the given
    * ELiveAttrRule constant.
    */
   static void GetLiveAttrValue(PRUint32 aRule, nsAString& aValue);
 
   /**
+   * Query DestinationType from the given SourceType.
+   */
+  template<class DestinationType, class SourceType> static inline
+    already_AddRefed<DestinationType> QueryObject(SourceType *aObject)
+  {
+    DestinationType* object = nsnull;
+    if (aObject)
+      CallQueryInterface(aObject, &object);
+
+    return object;
+  }
+  template<class DestinationType, class SourceType> static inline
+    already_AddRefed<DestinationType> QueryObject(nsCOMPtr<SourceType>& aObject)
+  {
+    DestinationType* object = nsnull;
+    if (aObject)
+      CallQueryInterface(aObject, &object);
+
+    return object;
+  }
+
+  /**
    * Query nsAccessNode from the given nsIAccessible.
    */
   static already_AddRefed<nsAccessNode>
     QueryAccessNode(nsIAccessible *aAccessible)
   {
     nsAccessNode* accessNode = nsnull;
     if (aAccessible)
       CallQueryInterface(aAccessible, &accessNode);
@@ -359,22 +380,16 @@ public:
     QueryAccessibleDocument(nsIAccessibleDocument *aAccessibleDocument);
 
 #ifdef MOZ_XUL
   /**
    * Query nsXULTreeAccessible from the given nsIAccessible.
    */
   static already_AddRefed<nsXULTreeAccessible>
     QueryAccessibleTree(nsIAccessible *aAccessible);
-
-  /**
-   * Query nsXULTreeitemAccessible from the given nsIAccessNode.
-   */
-  static already_AddRefed<nsXULTreeitemAccessible>
-    QueryAccessibleTreeitem(nsIAccessNode *aAccessNode);
 #endif
 
 #ifdef DEBUG_A11Y
   /**
    * Detect whether the given accessible object implements nsIAccessibleText,
    * when it is text or has text child node.
    */
   static PRBool IsTextInterfaceSupportCorrect(nsIAccessible *aAccessible);
--- a/accessible/src/base/nsAccessNode.cpp
+++ b/accessible/src/base/nsAccessNode.cpp
@@ -36,16 +36,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsAccessNode.h"
 #include "nsIAccessible.h"
 #include "nsAccessibilityAtoms.h"
 #include "nsHashtable.h"
 #include "nsAccessibilityService.h"
+#include "nsApplicationAccessibleWrap.h"
 #include "nsIAccessibleDocument.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDocument.h"
 #include "nsIDOMCSSStyleDeclaration.h"
 #include "nsIDOMCSSPrimitiveValue.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMElement.h"
@@ -63,22 +64,16 @@
 #include "nsIPresShell.h"
 #include "nsIServiceManager.h"
 #include "nsIStringBundle.h"
 #include "nsITimer.h"
 #include "nsRootAccessible.h"
 #include "nsFocusManager.h"
 #include "nsIObserverService.h"
 
-#ifdef MOZ_ACCESSIBILITY_ATK
-#include "nsAppRootAccessible.h"
-#else
-#include "nsApplicationAccessibleWrap.h"
-#endif
-
 /* For documentation of the accessibility architecture, 
  * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
  */
 
 nsIStringBundle *nsAccessNode::gStringBundle = 0;
 nsIStringBundle *nsAccessNode::gKeyStringBundle = 0;
 nsITimer *nsAccessNode::gDoCommandTimer = 0;
 nsIDOMNode *nsAccessNode::gLastFocusedNode = 0;
--- a/accessible/src/base/nsAccessNode.h
+++ b/accessible/src/base/nsAccessNode.h
@@ -69,16 +69,28 @@ class nsApplicationAccessibleWrap;
 class nsIDocShellTreeItem;
 
 #define ACCESSIBLE_BUNDLE_URL "chrome://global-platform/locale/accessible.properties"
 #define PLATFORM_KEYS_BUNDLE_URL "chrome://global-platform/locale/platformKeys.properties"
 
 typedef nsInterfaceHashtable<nsVoidPtrHashKey, nsIAccessNode>
         nsAccessNodeHashtable;
 
+// What we want is: NS_INTERFACE_MAP_ENTRY(self) for static IID accessors,
+// but some of our classes have an ambiguous base class of nsISupports which
+// prevents this from working (the default macro converts it to nsISupports,
+// then addrefs it, then returns it). Therefore, we expand the macro here and
+// change it so that it works. Yuck.
+#define NS_INTERFACE_MAP_STATIC_AMBIGUOUS(_class) \
+  if (aIID.Equals(NS_GET_IID(_class))) { \
+  NS_ADDREF(this); \
+  *aInstancePtr = this; \
+  return NS_OK; \
+  } else
+
 #define NS_OK_DEFUNCT_OBJECT \
 NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_GENERAL, 0x22)
 
 #define NS_ENSURE_A11Y_SUCCESS(res, ret)                                  \
   PR_BEGIN_MACRO                                                          \
     nsresult __rv = res; /* Don't evaluate |res| more than once */        \
     if (NS_FAILED(__rv)) {                                                \
       NS_ENSURE_SUCCESS_BODY(res, ret)                                    \
--- a/accessible/src/base/nsAccessibilityAtomList.h
+++ b/accessible/src/base/nsAccessibilityAtomList.h
@@ -176,16 +176,17 @@ ACCESSIBILITY_ATOM(lang, "lang")
 ACCESSIBILITY_ATOM(linkedPanel, "linkedpanel") // XUL
 ACCESSIBILITY_ATOM(longDesc, "longdesc")
 ACCESSIBILITY_ATOM(max, "max") // XUL
 ACCESSIBILITY_ATOM(maxpos, "maxpos") // XUL
 ACCESSIBILITY_ATOM(minpos, "minpos") // XUL
 ACCESSIBILITY_ATOM(multiline, "multiline") // XUL
 ACCESSIBILITY_ATOM(name, "name")
 ACCESSIBILITY_ATOM(onclick, "onclick")
+ACCESSIBILITY_ATOM(popup, "popup")
 ACCESSIBILITY_ATOM(readonly, "readonly")
 ACCESSIBILITY_ATOM(scope, "scope") // HTML table
 ACCESSIBILITY_ATOM(simple, "simple") // XLink
 ACCESSIBILITY_ATOM(src, "src")
 ACCESSIBILITY_ATOM(selected, "selected")
 ACCESSIBILITY_ATOM(summary, "summary")
 ACCESSIBILITY_ATOM(tabindex, "tabindex")
 ACCESSIBILITY_ATOM(title, "title")
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -36,16 +36,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 // NOTE: alphabetically ordered
 #include "nsAccessibilityAtoms.h"
 #include "nsAccessibilityService.h"
 #include "nsCoreUtils.h"
 #include "nsAccUtils.h"
+#include "nsApplicationAccessibleWrap.h"
 #include "nsARIAGridAccessibleWrap.h"
 #include "nsARIAMap.h"
 #include "nsIContentViewer.h"
 #include "nsCURILoader.h"
 #include "nsDocAccessible.h"
 #include "nsHTMLImageAccessibleWrap.h"
 #include "nsHTMLLinkAccessible.h"
 #include "nsHTMLSelectAccessible.h"
@@ -101,22 +102,16 @@
 #include "nsHTMLWin32ObjectAccessible.h"
 #endif
 
 #ifndef DISABLE_XFORMS_HOOKS
 #include "nsXFormsFormControlsAccessible.h"
 #include "nsXFormsWidgetsAccessible.h"
 #endif
 
-#ifdef MOZ_ACCESSIBILITY_ATK
-#include "nsAppRootAccessible.h"
-#else
-#include "nsApplicationAccessibleWrap.h"
-#endif
-
 nsAccessibilityService *nsAccessibilityService::gAccessibilityService = nsnull;
 PRBool nsAccessibilityService::gIsShutdown = PR_TRUE;
 
 /**
   * nsAccessibilityService
   */
 
 nsAccessibilityService::nsAccessibilityService()
@@ -1907,18 +1902,17 @@ nsresult nsAccessibilityService::GetAcce
       break;
     case nsIAccessibleProvider::XULTextBox:
       *aAccessible = new nsXULTextFieldAccessible(aNode, weakShell);
       break;
     case nsIAccessibleProvider::XULThumb:
       *aAccessible = new nsXULThumbAccessible(aNode, weakShell);
       break;
     case nsIAccessibleProvider::XULTree:
-      *aAccessible = new nsXULTreeAccessibleWrap(aNode, weakShell);
-      break;
+      return GetAccessibleForXULTree(aNode, weakShell, aAccessible);
     case nsIAccessibleProvider::XULTreeColumns:
       *aAccessible = new nsXULTreeColumnsAccessibleWrap(aNode, weakShell);
       break;
     case nsIAccessibleProvider::XULTreeColumnItem:
       *aAccessible = new nsXULColumnItemAccessible(aNode, weakShell);
       break;
     case nsIAccessibleProvider::XULToolbar:
       *aAccessible = new nsXULToolbarAccessible(aNode, weakShell);
@@ -2142,8 +2136,39 @@ nsAccessibilityService::GetAccessibleFor
       NS_ENSURE_TRUE(*aAccessible, NS_ERROR_OUT_OF_MEMORY);
 
       NS_ADDREF(*aAccessible);
     }
   }
 
   return NS_OK;
 }
+
+#ifdef MOZ_XUL
+nsresult
+nsAccessibilityService::GetAccessibleForXULTree(nsIDOMNode *aNode,
+                                                nsIWeakReference *aWeakShell,
+                                                nsIAccessible **aAccessible)
+{
+  nsCOMPtr<nsITreeBoxObject> treeBoxObj;
+  nsCoreUtils::GetTreeBoxObject(aNode, getter_AddRefs(treeBoxObj));
+  if (!treeBoxObj)
+    return NS_ERROR_FAILURE;
+
+  nsCOMPtr<nsITreeColumns> treeColumns;
+  treeBoxObj->GetColumns(getter_AddRefs(treeColumns));
+  if (!treeColumns)
+    return NS_OK;
+
+  PRInt32 count = 0;
+  treeColumns->GetCount(&count);
+  if (count == 1) // outline of list accessible
+    *aAccessible = new nsXULTreeAccessible(aNode, aWeakShell);
+  else // table or tree table accessible
+    *aAccessible = new nsXULTreeGridAccessibleWrap(aNode, aWeakShell);
+
+  if (!*aAccessible)
+    return NS_ERROR_OUT_OF_MEMORY;
+
+  NS_ADDREF(*aAccessible);
+  return NS_OK;
+}
+#endif
--- a/accessible/src/base/nsAccessibilityService.h
+++ b/accessible/src/base/nsAccessibilityService.h
@@ -131,16 +131,25 @@ private:
   /**
    * Return accessible object if parent is a deck frame.
    *
    * @param aNode - DOMNode that accessible is returned for.
    */
   nsresult GetAccessibleForDeckChildren(nsIDOMNode *aNode,
                                         nsIAccessible **aAccessible);
 
+#ifdef MOZ_XUL
+  /**
+   * Create accessible for XUL tree element.
+   */
+  nsresult GetAccessibleForXULTree(nsIDOMNode *aNode,
+                                   nsIWeakReference *aWeakShell,
+                                   nsIAccessible **aAccessible);
+#endif
+  
   static nsAccessibilityService *gAccessibilityService;
 
   /**
    * Does this content node have a universal ARIA property set on it?
    * A universal ARIA property is one that can be defined on any element even if there is no role.
    *
    * @param aContent The content node to test
    * @param aWeakShell  A weak reference to the pres shell
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -89,17 +89,16 @@
 #include "nsIMutableArray.h"
 #include "nsIObserverService.h"
 #include "nsIServiceManager.h"
 #include "nsWhitespaceTokenizer.h"
 #include "nsAttrName.h"
 #include "nsNetUtil.h"
 
 #ifdef NS_DEBUG
-#include "nsIFrameDebug.h"
 #include "nsIDOMCharacterData.h"
 #endif
 
 /**
  * nsAccessibleDOMStringList implementation
  */
 nsAccessibleDOMStringList::nsAccessibleDOMStringList()
 {
@@ -1044,16 +1043,21 @@ nsAccessible::GetStateInternal(PRUint32 
   if (isOffscreen) {
     *aState |= nsIAccessibleStates::STATE_OFFSCREEN;
   }
 
   nsIFrame *frame = GetFrame();
   if (frame && (frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW))
     *aState |= nsIAccessibleStates::STATE_FLOATING;
 
+  // Check if a XUL element has the popup attribute (an attached popup menu).
+  if (content->IsNodeOfType(nsINode::eXUL))
+    if (content->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::popup))
+      *aState |= nsIAccessibleStates::STATE_HASPOPUP;
+
   // Add 'linked' state for simple xlink.
   if (nsCoreUtils::IsXLink(content))
     *aState |= nsIAccessibleStates::STATE_LINKED;
 
   return NS_OK;
 }
 
   /* readonly attribute boolean focusedChild; */
@@ -2695,73 +2699,75 @@ NS_IMETHODIMP nsAccessible::ExtendSelect
 }
 
 /* [noscript] void getNativeInterface(out voidPtr aOutAccessible); */
 NS_IMETHODIMP nsAccessible::GetNativeInterface(void **aOutAccessible)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-void nsAccessible::DoCommandCallback(nsITimer *aTimer, void *aClosure)
+nsresult
+nsAccessible::DoCommand(nsIContent *aContent, PRUint32 aActionIndex)
 {
-  NS_ASSERTION(gDoCommandTimer,
-               "How did we get here if there was no gDoCommandTimer?");
-  NS_RELEASE(gDoCommandTimer);
-
-  nsCOMPtr<nsIContent> content =
-    reinterpret_cast<nsIContent*>(aClosure);
-
-  nsIDocument *doc = content->GetDocument();
-  if (!doc)
-    return;
-
-  nsCOMPtr<nsIPresShell> presShell = doc->GetPrimaryShell();
-
-  // Scroll into view.
-  presShell->ScrollContentIntoView(content, NS_PRESSHELL_SCROLL_ANYWHERE,
-                                   NS_PRESSHELL_SCROLL_ANYWHERE);
-
-  // Fire mouse down and mouse up events.
-  PRBool res = nsCoreUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, presShell,
-                                               content);
-  if (!res)
-    return;
-
-  nsCoreUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_UP, presShell, content);
-}
-
-/*
- * Use Timer to execute "Click" command of XUL/HTML element (e.g. menuitem, button...).
- *
- * When "Click" is to open a "modal" dialog/window, it won't return untill the
- * dialog/window is closed. If executing "Click" command directly in
- * nsXXXAccessible::DoAction, it will block AT-Tools(e.g. GOK) that invoke
- * "action" of mozilla accessibles direclty.
- */
-nsresult nsAccessible::DoCommand(nsIContent *aContent)
-{
-  nsCOMPtr<nsIContent> content = aContent;
-  if (!content) {
-    content = do_QueryInterface(mDOMNode);
-  }
   if (gDoCommandTimer) {
     // Already have timer going for another command
     NS_WARNING("Doubling up on do command timers doesn't work. This wasn't expected.");
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1");
-  if (!timer) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  } 
+  NS_ENSURE_TRUE(timer, NS_ERROR_OUT_OF_MEMORY);
+
+  nsCOMPtr<nsIContent> content = aContent;
+  if (!content)
+    content = do_QueryInterface(mDOMNode);
+
+  // Command closure object memory will be free in DoCommandCallback().
+  nsCommandClosure *closure =
+    new nsCommandClosure(this, content, aActionIndex);
+  NS_ENSURE_TRUE(closure, NS_ERROR_OUT_OF_MEMORY);
 
   NS_ADDREF(gDoCommandTimer = timer);
   return gDoCommandTimer->InitWithFuncCallback(DoCommandCallback,
-                                               (void*)content, 0,
-                                               nsITimer::TYPE_ONE_SHOT);
+                                               static_cast<void*>(closure),
+                                               0, nsITimer::TYPE_ONE_SHOT);
+}
+
+void
+nsAccessible::DoCommandCallback(nsITimer *aTimer, void *aClosure)
+{
+  NS_ASSERTION(gDoCommandTimer,
+               "How did we get here if there was no gDoCommandTimer?");
+  NS_RELEASE(gDoCommandTimer);
+
+  nsCommandClosure *closure = static_cast<nsCommandClosure*>(aClosure);
+  closure->accessible->DispatchClickEvent(closure->content,
+                                          closure->actionIndex);
+  delete closure;
+}
+
+void
+nsAccessible::DispatchClickEvent(nsIContent *aContent, PRUint32 aActionIndex)
+{
+  if (IsDefunct())
+    return;
+
+  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
+
+  // Scroll into view.
+  presShell->ScrollContentIntoView(aContent, NS_PRESSHELL_SCROLL_ANYWHERE,
+                                   NS_PRESSHELL_SCROLL_ANYWHERE);
+
+  // Fire mouse down and mouse up events.
+  PRBool res = nsCoreUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, presShell,
+                                               aContent);
+  if (!res)
+    return;
+
+  nsCoreUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_UP, presShell, aContent);
 }
 
 already_AddRefed<nsIAccessible>
 nsAccessible::GetNextWithState(nsIAccessible *aStart, PRUint32 matchState)
 {
   // Return the next descendant that matches one of the states in matchState
   // Uses depth first search
   NS_ASSERTION(matchState, "GetNextWithState() not called with a state to match");
@@ -3216,16 +3222,21 @@ nsAccessible::GetActionRule(PRUint32 aSt
   nsIContent* content = nsCoreUtils::GetRoleContent(mDOMNode);
   if (!content)
     return eNoAction;
   
   // Check if it's simple xlink.
   if (nsCoreUtils::IsXLink(content))
     return eJumpAction;
 
+  // Return "click" action on elements that have an attached popup menu.
+  if (content->IsNodeOfType(nsINode::eXUL))
+    if (content->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::popup))
+      return eClickAction;
+
   // Has registered 'click' event handler.
   PRBool isOnclick = nsCoreUtils::HasListener(content,
                                               NS_LITERAL_STRING("click"));
 
   if (isOnclick)
     return eClickAction;
   
   // Get an action based on ARIA role.
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -333,19 +333,62 @@ protected:
    * @param aRequireLeaf, only accept leaf accessible nodes
    * @return the resulting accessible
    */   
   already_AddRefed<nsIAccessible> GetFirstAvailableAccessible(nsIDOMNode *aStartNode, PRBool aRequireLeaf = PR_FALSE);
 
   // Hyperlink helpers
   virtual nsresult GetLinkOffset(PRInt32* aStartOffset, PRInt32* aEndOffset);
 
-  // For accessibles that have actions
+  //////////////////////////////////////////////////////////////////////////////
+  // Action helpers
+
+  /**
+   * Used to describe click action target. See DoCommand() method.
+   */
+  struct nsCommandClosure
+  {
+    nsCommandClosure(nsAccessible *aAccessible, nsIContent *aContent,
+                     PRUint32 aActionIndex) :
+      accessible(aAccessible), content(aContent), actionIndex(aActionIndex) {}
+
+    nsRefPtr<nsAccessible> accessible;
+    nsCOMPtr<nsIContent> content;
+    PRUint32 actionIndex;
+  };
+
+  /**
+   * Prepares click action that will be invoked in timeout.
+   *
+   * @note  DoCommand() prepares an action in timeout because when action
+   *  command opens a modal dialog/window, it won't return until the
+   *  dialog/window is closed. If executing action command directly in
+   *  nsIAccessible::DoAction() method, it will block AT tools (e.g. GOK) that
+   *  invoke action of mozilla accessibles direclty (see bug 277888 for details).
+   *
+   * @param  aContent      [in, optional] element to click
+   * @param  aActionIndex  [in, optional] index of accessible action
+   */
+  nsresult DoCommand(nsIContent *aContent = nsnull, PRUint32 aActionIndex = 0);
+
+  /**
+   * Dispatch click event to target by calling DispatchClickEvent() method.
+   *
+   * @param  aTimer    [in] timer object
+   * @param  aClosure  [in] nsCommandClosure object describing a target.
+   */
   static void DoCommandCallback(nsITimer *aTimer, void *aClosure);
-  nsresult DoCommand(nsIContent *aContent = nsnull);
+
+  /**
+   * Dispatch click event.
+   */
+  virtual void DispatchClickEvent(nsIContent *aContent, PRUint32 aActionIndex);
+
+  //////////////////////////////////////////////////////////////////////////////
+  // Helpers
 
   // Check the visibility across both parent content and chrome
   PRBool CheckVisibilityInParentChain(nsIDocument* aDocument, nsIView* aView);
 
   /**
    *  Get the container node for an atomic region, defined by aria-atomic="true"
    *  @return the container node
    */
--- a/accessible/src/base/nsAccessibleEventData.cpp
+++ b/accessible/src/base/nsAccessibleEventData.cpp
@@ -33,16 +33,17 @@
  * 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 ***** */
 
 #include "nsAccessibleEventData.h"
 #include "nsAccessibilityAtoms.h"
+#include "nsApplicationAccessibleWrap.h"
 #include "nsCoreUtils.h"
 #include "nsIAccessibilityService.h"
 #include "nsIAccessNode.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "nsIEventStateManager.h"
 #include "nsIPersistentProperties2.h"
 #include "nsIServiceManager.h"
@@ -106,17 +107,27 @@ void nsAccEvent::GetLastEventAttributes(
   }
 }
 
 void nsAccEvent::CaptureIsFromUserInput(PRBool aIsAsynch)
 {
   nsCOMPtr<nsIDOMNode> eventNode;
   GetDOMNode(getter_AddRefs(eventNode));
   if (!eventNode) {
-    NS_NOTREACHED("There should always be a DOM node for an event");
+#ifdef DEBUG
+    // XXX: remove this hack during reorganization of 506907. Meanwhile we
+    // want to get rid an assertion for application accessible events which
+    // don't have DOM node (see bug 506206).
+    nsRefPtr<nsApplicationAccessibleWrap> applicationAcc =
+      nsAccessNode::GetApplicationAccessible();
+
+    if (mAccessible != static_cast<nsIAccessible*>(applicationAcc.get()))
+      NS_ASSERTION(eventNode, "There should always be a DOM node for an event");
+#endif
+
     return;
   }
 
   if (!aIsAsynch) {
     PrepareForEvent(eventNode);
     mIsFromUserInput = gLastEventFromUserInput;
   }
   // For asynch, cannot calculate if from user input.
@@ -261,45 +272,43 @@ nsAccEvent::GetAccessibleByNode()
   if (!mDOMNode)
     return nsnull;
 
   nsCOMPtr<nsIAccessibilityService> accService = 
     do_GetService("@mozilla.org/accessibilityService;1");
   if (!accService)
     return nsnull;
 
-  nsIAccessible *accessible = nsnull;
-  accService->GetAccessibleFor(mDOMNode, &accessible);
+  nsCOMPtr<nsIAccessible> accessible;
+  accService->GetAccessibleFor(mDOMNode, getter_AddRefs(accessible));
 
 #ifdef MOZ_XUL
   // hack for xul tree table. We need a better way for firing delayed event
   // against xul tree table. see bug 386821.
   // There will be problem if some day we want to fire delayed event against
   // the xul tree itself or an unselected treeitem.
   nsAutoString localName;
   mDOMNode->GetLocalName(localName);
   if (localName.EqualsLiteral("tree")) {
     nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelect =
       do_QueryInterface(mDOMNode);
     if (multiSelect) {
       PRInt32 treeIndex = -1;
       multiSelect->GetCurrentIndex(&treeIndex);
       if (treeIndex >= 0) {
-        nsRefPtr<nsXULTreeAccessible> treeCache =
+        nsRefPtr<nsXULTreeAccessible> treeAcc =
           nsAccUtils::QueryAccessibleTree(accessible);
-        if (treeCache) {
-          treeCache->GetCachedTreeitemAccessible(treeIndex, nsnull,
-                                                 &accessible);
-        }
+        if (treeAcc)
+          treeAcc->GetTreeItemAccessible(treeIndex, getter_AddRefs(accessible));
       }
     }
   }
 #endif
 
-  return accessible;
+  return accessible.forget();
 }
 
 /* static */
 void
 nsAccEvent::ApplyEventRules(nsCOMArray<nsIAccessibleEvent> &aEventsToFire)
 {
   PRUint32 numQueuedEvents = aEventsToFire.Count();
   for (PRInt32 tail = numQueuedEvents - 1; tail >= 0; tail --) {
--- a/accessible/src/base/nsApplicationAccessible.h
+++ b/accessible/src/base/nsApplicationAccessible.h
@@ -43,17 +43,17 @@
 #ifndef __NS_APPLICATION_ACCESSIBLE_H__
 #define __NS_APPLICATION_ACCESSIBLE_H__
 
 #include "nsAccessibleWrap.h"
 #include "nsIMutableArray.h"
 
 /**
  * nsApplicationAccessible is for the whole application of Mozilla.
- * Only one instance of nsAppRootAccessible exists for one Mozilla instance.
+ * Only one instance of nsApplicationAccessible exists for one Mozilla instance.
  * And this one should be created when Mozilla Startup (if accessibility
  * feature has been enabled) and destroyed when Mozilla Shutdown.
  *
  * All the accessibility objects for toplevel windows are direct children of
  * the nsApplicationAccessible instance.
  */
 
 class nsApplicationAccessible: public nsAccessibleWrap
--- a/accessible/src/base/nsCoreUtils.cpp
+++ b/accessible/src/base/nsCoreUtils.cpp
@@ -79,16 +79,79 @@ nsCoreUtils::HasListener(nsIContent *aCo
 {
   NS_ENSURE_TRUE(aContent, PR_FALSE);
   nsIEventListenerManager* listenerManager =
     aContent->GetListenerManager(PR_FALSE);
 
   return listenerManager && listenerManager->HasListenersFor(aEventType);  
 }
 
+void
+nsCoreUtils::DispatchClickEvent(nsITreeBoxObject *aTreeBoxObj,
+                                PRInt32 aRowIndex, nsITreeColumn *aColumn,
+                                const nsCString& aPseudoElt)
+{
+  nsCOMPtr<nsIDOMElement> tcElm;
+  aTreeBoxObj->GetTreeBody(getter_AddRefs(tcElm));
+  if (!tcElm)
+    return;
+
+  nsCOMPtr<nsIContent> tcContent(do_QueryInterface(tcElm));
+  nsIDocument *document = tcContent->GetCurrentDoc();
+  if (!document)
+    return;
+
+  nsIPresShell *presShell = nsnull;
+  presShell = document->GetPrimaryShell();
+  if (!presShell)
+    return;
+
+  // Ensure row is visible.
+  aTreeBoxObj->EnsureRowIsVisible(aRowIndex);
+
+  // Calculate x and y coordinates.
+  PRInt32 x = 0, y = 0, width = 0, height = 0;
+  nsresult rv = aTreeBoxObj->GetCoordsForCellItem(aRowIndex, aColumn,
+                                                  aPseudoElt,
+                                                  &x, &y, &width, &height);
+  if (NS_FAILED(rv))
+    return;
+
+  nsCOMPtr<nsIDOMXULElement> tcXULElm(do_QueryInterface(tcElm));
+  nsCOMPtr<nsIBoxObject> tcBoxObj;
+  tcXULElm->GetBoxObject(getter_AddRefs(tcBoxObj));
+
+  PRInt32 tcX = 0;
+  tcBoxObj->GetX(&tcX);
+
+  PRInt32 tcY = 0;
+  tcBoxObj->GetY(&tcY);
+
+  // Dispatch mouse events.
+  nsIFrame* tcFrame = presShell->GetPrimaryFrameFor(tcContent);  
+  nsIFrame* rootFrame = presShell->GetRootFrame();
+
+  nsPoint offset;
+  nsIWidget *rootWidget =
+    rootFrame->GetViewExternal()->GetNearestWidget(&offset);
+
+  nsPresContext* presContext = presShell->GetPresContext();
+
+  PRInt32 cnvdX = presContext->CSSPixelsToDevPixels(tcX + x + 1) +
+    presContext->AppUnitsToDevPixels(offset.x);
+  PRInt32 cnvdY = presContext->CSSPixelsToDevPixels(tcY + y + 1) +
+    presContext->AppUnitsToDevPixels(offset.y);
+
+  DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, cnvdX, cnvdY,
+                     tcContent, tcFrame, presShell, rootWidget);
+
+  DispatchMouseEvent(NS_MOUSE_BUTTON_UP, cnvdX, cnvdY,
+                     tcContent, tcFrame, presShell, rootWidget);
+}
+
 PRBool
 nsCoreUtils::DispatchMouseEvent(PRUint32 aEventType,
                                 nsIPresShell *aPresShell,
                                 nsIContent *aContent)
 {
   nsIFrame *frame = aPresShell->GetPrimaryFrameFor(aContent);
   if (!frame)
     return PR_FALSE;
@@ -104,31 +167,38 @@ nsCoreUtils::DispatchMouseEvent(PRUint32
   // Compute x and y coordinates.
   nsPoint point = frame->GetOffsetToExternal(rootFrame);
   nsSize size = frame->GetSize();
 
   nsPresContext* presContext = aPresShell->GetPresContext();
 
   PRInt32 x = presContext->AppUnitsToDevPixels(point.x + size.width / 2);
   PRInt32 y = presContext->AppUnitsToDevPixels(point.y + size.height / 2);
-  
+
   // Fire mouse event.
-  nsMouseEvent event(PR_TRUE, aEventType, rootWidget,
+  DispatchMouseEvent(aEventType, x, y, aContent, frame, aPresShell, rootWidget);
+  return PR_TRUE;
+}
+
+void
+nsCoreUtils::DispatchMouseEvent(PRUint32 aEventType, PRInt32 aX, PRInt32 aY,
+                                nsIContent *aContent, nsIFrame *aFrame,
+                                nsIPresShell *aPresShell, nsIWidget *aRootWidget)
+{
+  nsMouseEvent event(PR_TRUE, aEventType, aRootWidget,
                      nsMouseEvent::eReal, nsMouseEvent::eNormal);
 
-  event.refPoint = nsIntPoint(x, y);
-  
+  event.refPoint = nsIntPoint(aX, aY);
+
   event.clickCount = 1;
   event.button = nsMouseEvent::eLeftButton;
   event.time = PR_IntervalNow();
-  
+
   nsEventStatus status = nsEventStatus_eIgnore;
-  aPresShell->HandleEventWithTarget(&event, frame, aContent, &status);
-
-  return PR_TRUE;
+  aPresShell->HandleEventWithTarget(&event, aFrame, aContent, &status);
 }
 
 PRUint32
 nsCoreUtils::GetAccessKeyFor(nsIContent *aContent)
 {
   if (!aContent)
     return 0;
 
@@ -886,8 +956,154 @@ nsCoreUtils::GetTreeBodyBoxObject(nsITre
   nsCOMPtr<nsIDOMXULElement> tcXULElm(do_QueryInterface(tcElm));
   if (!tcXULElm)
     return nsnull;
 
   nsIBoxObject *boxObj = nsnull;
   tcXULElm->GetBoxObject(&boxObj);
   return boxObj;
 }
+
+void
+nsCoreUtils::GetTreeBoxObject(nsIDOMNode *aDOMNode,
+                              nsITreeBoxObject **aBoxObject)
+{
+  nsAutoString name;
+  nsCOMPtr<nsIDOMNode> parentNode, currentNode;
+  
+  // Find DOMNode's parents recursively until reach the <tree> tag
+  currentNode = aDOMNode;
+  while (currentNode) {
+    currentNode->GetLocalName(name);
+    if (name.EqualsLiteral("tree")) {
+      // We will get the nsITreeBoxObject from the tree node
+      nsCOMPtr<nsIDOMXULElement> xulElement(do_QueryInterface(currentNode));
+      if (xulElement) {
+        nsCOMPtr<nsIBoxObject> box;
+        xulElement->GetBoxObject(getter_AddRefs(box));
+        nsCOMPtr<nsITreeBoxObject> treeBox(do_QueryInterface(box));
+        if (treeBox) {
+          *aBoxObject = treeBox;
+          NS_ADDREF(*aBoxObject);
+          return;
+        }
+      }
+    }
+    currentNode->GetParentNode(getter_AddRefs(parentNode));
+    currentNode = parentNode;
+  }
+  
+  *aBoxObject = nsnull;
+}
+
+already_AddRefed<nsITreeColumn>
+nsCoreUtils::GetFirstSensibleColumn(nsITreeBoxObject *aTree)
+{
+  nsCOMPtr<nsITreeColumns> cols;
+  aTree->GetColumns(getter_AddRefs(cols));
+  if (!cols)
+    return nsnull;
+
+  nsCOMPtr<nsITreeColumn> column;
+  cols->GetFirstColumn(getter_AddRefs(column));
+  if (column && IsColumnHidden(column))
+    return GetNextSensibleColumn(column);
+
+  return column.forget();
+}
+
+already_AddRefed<nsITreeColumn>
+nsCoreUtils::GetLastSensibleColumn(nsITreeBoxObject *aTree)
+{
+  nsCOMPtr<nsITreeColumns> cols;
+  aTree->GetColumns(getter_AddRefs(cols));
+  if (!cols)
+    return nsnull;
+
+  nsCOMPtr<nsITreeColumn> column;
+  cols->GetLastColumn(getter_AddRefs(column));
+  if (column && IsColumnHidden(column))
+    return GetPreviousSensibleColumn(column);
+
+  return column.forget();
+}
+
+PRUint32
+nsCoreUtils::GetSensibleColumnsCount(nsITreeBoxObject *aTree)
+{
+  PRUint32 count = 0;
+
+  nsCOMPtr<nsITreeColumns> cols;
+  aTree->GetColumns(getter_AddRefs(cols));
+  if (!cols)
+    return count;
+
+  nsCOMPtr<nsITreeColumn> column;
+  cols->GetFirstColumn(getter_AddRefs(column));
+
+  while (column) {
+    if (!IsColumnHidden(column))
+      count++;
+
+    nsCOMPtr<nsITreeColumn> nextColumn;
+    column->GetNext(getter_AddRefs(nextColumn));
+    column.swap(nextColumn);
+  }
+
+  return count;
+}
+
+already_AddRefed<nsITreeColumn>
+nsCoreUtils::GetSensibleColumnAt(nsITreeBoxObject *aTree, PRUint32 aIndex)
+{
+  PRUint32 idx = aIndex;
+
+  nsCOMPtr<nsITreeColumn> column = GetFirstSensibleColumn(aTree);
+  while (column) {
+    if (idx == 0)
+      return column.forget();
+
+    idx--;
+    column = GetNextSensibleColumn(column);
+  }
+
+  return nsnull;
+}
+
+already_AddRefed<nsITreeColumn>
+nsCoreUtils::GetNextSensibleColumn(nsITreeColumn *aColumn)
+{
+  nsCOMPtr<nsITreeColumn> nextColumn;
+  aColumn->GetNext(getter_AddRefs(nextColumn));
+
+  while (nextColumn && IsColumnHidden(nextColumn)) {
+    nsCOMPtr<nsITreeColumn> tempColumn;
+    nextColumn->GetNext(getter_AddRefs(tempColumn));
+    nextColumn.swap(tempColumn);
+  }
+
+  return nextColumn.forget();
+}
+
+already_AddRefed<nsITreeColumn>
+nsCoreUtils::GetPreviousSensibleColumn(nsITreeColumn *aColumn)
+{
+  nsCOMPtr<nsITreeColumn> prevColumn;
+  aColumn->GetPrevious(getter_AddRefs(prevColumn));
+
+  while (prevColumn && IsColumnHidden(prevColumn)) {
+    nsCOMPtr<nsITreeColumn> tempColumn;
+    prevColumn->GetPrevious(getter_AddRefs(tempColumn));
+    prevColumn.swap(tempColumn);
+  }
+
+  return prevColumn.forget();
+}
+
+PRBool
+nsCoreUtils::IsColumnHidden(nsITreeColumn *aColumn)
+{
+  nsCOMPtr<nsIDOMElement> element;
+  aColumn->GetElement(getter_AddRefs(element));
+  nsCOMPtr<nsIContent> content = do_QueryInterface(element);
+  return content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::hidden,
+                              nsAccessibilityAtoms::_true, eCaseMatters);
+}
--- a/accessible/src/base/nsCoreUtils.h
+++ b/accessible/src/base/nsCoreUtils.h
@@ -40,16 +40,17 @@
 #define nsCoreUtils_h_
 
 #include "nsAccessibilityAtoms.h"
 
 #include "nsIDOMNode.h"
 #include "nsIContent.h"
 #include "nsIBoxObject.h"
 #include "nsITreeBoxObject.h"
+#include "nsITreeColumns.h"
 
 #include "nsIFrame.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIArray.h"
 #include "nsIMutableArray.h"
 #include "nsPoint.h"
 
 class nsCoreUtils
@@ -57,27 +58,56 @@ class nsCoreUtils
 public:
   /**
    * Return true if the given node has registered event listener of the given
    * type.
    */
   static PRBool HasListener(nsIContent *aContent, const nsAString& aEventType);
 
   /**
-   * Send mouse events to the given element.
+   * Dispatch click event to XUL tree cell.
    *
-   * @param aEventType  an event type (see nsGUIEvent.h for constants)
-   * @param aPresShell  the presshell for the given element
-   * @param aContent    the element element
+   * @param  aTreeBoxObj  [in] tree box object
+   * @param  aRowIndex    [in] row index
+   * @param  aColumn      [in] column object
+   * @param  aPseudoElm   [in] pseudo elemenet inside the cell, see
+   *                       nsITreeBoxObject for available values
+   */
+  static void DispatchClickEvent(nsITreeBoxObject *aTreeBoxObj,
+                                 PRInt32 aRowIndex, nsITreeColumn *aColumn,
+                                 const nsCString& aPseudoElt = EmptyCString());
+
+  /**
+   * Send mouse event to the given element.
+   *
+   * @param  aEventType  [in] an event type (see nsGUIEvent.h for constants)
+   * @param  aPresShell  [in] the presshell for the given element
+   * @param  aContent    [in] the element
    */
   static PRBool DispatchMouseEvent(PRUint32 aEventType,
                                    nsIPresShell *aPresShell,
                                    nsIContent *aContent);
 
   /**
+   * Send mouse event to the given element.
+   *
+   * @param aEventType   [in] an event type (see nsGUIEvent.h for constants)
+   * @param aX           [in] x coordinate in dev pixels
+   * @param aY           [in] y coordinate in dev pixels
+   * @param aContent     [in] the element
+   * @param aFrame       [in] frame of the element
+   * @param aPresShell   [in] the presshell for the element
+   * @param aRootWidget  [in] the root widget of the element
+   */
+  static void DispatchMouseEvent(PRUint32 aEventType, PRInt32 aX, PRInt32 aY,
+                                 nsIContent *aContent, nsIFrame *aFrame,
+                                 nsIPresShell *aPresShell,
+                                 nsIWidget *aRootWidget);
+
+  /**
    * Return an accesskey registered on the given element by
    * nsIEventStateManager or 0 if there is no registered accesskey.
    *
    * @param aContent - the given element.
    */
   static PRUint32 GetAccessKeyFor(nsIContent *aContent);
 
   /**
@@ -358,16 +388,62 @@ public:
 
   /**
    * Return box object for XUL treechildren element by tree box object.
    */
   static already_AddRefed<nsIBoxObject>
     GetTreeBodyBoxObject(nsITreeBoxObject *aTreeBoxObj);
 
   /**
+   * Return tree box object from any levels DOMNode under the XUL tree.
+   */
+  static void
+    GetTreeBoxObject(nsIDOMNode* aDOMNode, nsITreeBoxObject** aBoxObject);
+
+  /**
+   * Return first sensible column for the given tree box object.
+   */
+  static already_AddRefed<nsITreeColumn>
+    GetFirstSensibleColumn(nsITreeBoxObject *aTree);
+
+  /**
+   * Return last sensible column for the given tree box object.
+   */
+  static already_AddRefed<nsITreeColumn>
+    GetLastSensibleColumn(nsITreeBoxObject *aTree);
+
+  /**
+   * Return sensible columns count for the given tree box object.
+   */
+  static PRUint32 GetSensibleColumnsCount(nsITreeBoxObject *aTree);
+
+  /**
+   * Return sensible column at the given index for the given tree box object.
+   */
+  static already_AddRefed<nsITreeColumn>
+    GetSensibleColumnAt(nsITreeBoxObject *aTree, PRUint32 aIndex);
+
+  /**
+   * Return next sensible column for the given column.
+   */
+  static already_AddRefed<nsITreeColumn>
+    GetNextSensibleColumn(nsITreeColumn *aColumn);
+
+  /**
+   * Return previous sensible column for the given column.
+   */
+  static already_AddRefed<nsITreeColumn>
+    GetPreviousSensibleColumn(nsITreeColumn *aColumn);
+
+  /**
+   * Return true if the given column is hidden (i.e. not sensible).
+   */
+  static PRBool IsColumnHidden(nsITreeColumn *aColumn);
+
+  /**
    * Return true if the given node is table header element.
    */
   static PRBool IsHTMLTableHeader(nsIContent *aContent)
   {
     return aContent->NodeInfo()->Equals(nsAccessibilityAtoms::th) ||
       aContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::scope);
   }
 };
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -83,16 +83,19 @@ nsIAtom *nsDocAccessible::gLastFocusedFr
 //-----------------------------------------------------
 // construction
 //-----------------------------------------------------
 nsDocAccessible::nsDocAccessible(nsIDOMNode *aDOMNode, nsIWeakReference* aShell):
   nsHyperTextAccessibleWrap(aDOMNode, aShell), mWnd(nsnull),
   mScrollPositionChangedTicks(0), mIsContentLoaded(PR_FALSE),
   mIsLoadCompleteFired(PR_FALSE), mInFlushPendingEvents(PR_FALSE)
 {
+  // XXX aaronl should we use an algorithm for the initial cache size?
+  mAccessNodeCache.Init(kDefaultCacheSize);
+
   // For GTK+ native window, we do nothing here.
   if (!mDOMNode)
     return;
 
   // Because of the way document loading happens, the new nsIWidget is created before
   // the old one is removed. Since it creates the nsDocAccessible, for a brief moment
   // there can be 2 nsDocAccessible's for the content area, although for 2 different
   // pres shells.
@@ -108,19 +111,16 @@ nsDocAccessible::nsDocAccessible(nsIDOMN
       nsCOMPtr<nsIWidget> widget;
       vm->GetRootWidget(getter_AddRefs(widget));
       if (widget) {
         mWnd = widget->GetNativeData(NS_NATIVE_WINDOW);
       }
     }
   }
 
-  // XXX aaronl should we use an algorithm for the initial cache size?
-  mAccessNodeCache.Init(kDefaultCacheSize);
-
   nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
     nsCoreUtils::GetDocShellTreeItemFor(mDOMNode);
   nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(docShellTreeItem);
   if (docShell) {
     PRUint32 busyFlags;
     docShell->GetBusyFlags(&busyFlags);
     if (busyFlags == nsIDocShell::BUSY_FLAGS_NONE) {
       mIsContentLoaded = PR_TRUE;                                               
@@ -145,28 +145,16 @@ ElementTraverser(const void *aKey, nsIAc
   nsCycleCollectionTraversalCallback *cb = 
     static_cast<nsCycleCollectionTraversalCallback*>(aUserArg);
 
   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mAccessNodeCache entry");
   cb->NoteXPCOMChild(aAccessNode);
   return PL_DHASH_NEXT;
 }
 
-// What we want is: NS_INTERFACE_MAP_ENTRY(self) for static IID accessors,
-// but some of our classes have an ambiguous base class of nsISupports which
-// prevents this from working (the default macro converts it to nsISupports,
-// then addrefs it, then returns it). Therefore, we expand the macro here and
-// change it so that it works. Yuck.
-#define NS_INTERFACE_MAP_STATIC_AMBIGUOUS(_class) \
-  if (aIID.Equals(NS_GET_IID(_class))) { \
-    NS_ADDREF(this); \
-    *aInstancePtr = this; \
-    return NS_OK; \
-  } else
-
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocAccessible)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDocAccessible, nsAccessible)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mEventsToFire)
   tmp->mAccessNodeCache.EnumerateRead(ElementTraverser, &cb); 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDocAccessible, nsAccessible)
@@ -576,16 +564,27 @@ nsDocAccessible::CacheAccessNode(void *a
   if (accessNode) {
     nsRefPtr<nsAccessNode> accNode = nsAccUtils::QueryAccessNode(accessNode);
     accNode->Shutdown();
   }
 
   PutCacheEntry(mAccessNodeCache, aUniqueID, aAccessNode);
 }
 
+void
+nsDocAccessible::RemoveAccessNodeFromCache(nsIAccessNode *aAccessNode)
+{
+  if (!aAccessNode)
+    return;
+
+  void *uniqueID = nsnull;
+  aAccessNode->GetUniqueID(&uniqueID);
+  mAccessNodeCache.Remove(uniqueID);
+}
+
 NS_IMETHODIMP nsDocAccessible::GetParent(nsIAccessible **aParent)
 {
   // Hook up our new accessible with our parent
   *aParent = nsnull;
   NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE);
   if (!mParent) {
     nsIDocument *parentDoc = mDocument->GetParentDocument();
     NS_ENSURE_TRUE(parentDoc, NS_ERROR_FAILURE);
@@ -1346,16 +1345,25 @@ nsDocAccessible::ARIAAttributeChanged(ns
   }
 
   if (aAttribute == nsAccessibilityAtoms::aria_multiselectable &&
       aContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::role)) {
     // This affects whether the accessible supports nsIAccessibleSelectable.
     // 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, nsIAccessibleEvent::EVENT_DOM_SIGNIFICANT_CHANGE);
+    return;
+  }
+
+  // For aria drag and drop changes we fire a generic attribute change event;
+  // at least until native API comes up with a more meaningful event.
+  if (aAttribute == nsAccessibilityAtoms::aria_grabbed ||
+      aAttribute == nsAccessibilityAtoms::aria_dropeffect) {
+    FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_OBJECT_ATTRIBUTE_CHANGED,
+                           targetNode);
   }
 }
 
 void nsDocAccessible::ContentAppended(nsIDocument *aDocument,
                                       nsIContent* aContainer,
                                       PRInt32 aNewIndexInContainer)
 {
   if ((!mIsContentLoaded || !mDocument) && mAccessNodeCache.Count() <= 1) {
@@ -1792,22 +1800,21 @@ nsDocAccessible::FlushPendingEvents()
           if (hidingNode) {
             RefreshNodes(hidingNode); // Will this bite us with asynch events
           }
         }
       }
     }
   }
   mEventsToFire.Clear(); // Clear out array
+  mInFlushPendingEvents = PR_FALSE;
   NS_RELEASE_THIS(); // Release kung fu death grip
 
   // After a flood of events, reset so that user input flag is off
   nsAccEvent::ResetLastInputState();
-
-  mInFlushPendingEvents = PR_FALSE;
 }
 
 void nsDocAccessible::FlushEventsCallback(nsITimer *aTimer, void *aClosure)
 {
   nsDocAccessible *accessibleDoc = static_cast<nsDocAccessible*>(aClosure);
   NS_ASSERTION(accessibleDoc, "How did we get here without an accessible document?");
   if (accessibleDoc) {
     // A lot of crashes were happening here, so now we're reffing the doc
--- a/accessible/src/base/nsDocAccessible.h
+++ b/accessible/src/base/nsDocAccessible.h
@@ -51,21 +51,21 @@
 #include "nsCOMArray.h"
 #include "nsIDocShellTreeNode.h"
 
 class nsIScrollableView;
 
 const PRUint32 kDefaultCacheSize = 256;
 
 #define NS_DOCACCESSIBLE_IMPL_CID                       \
-{  /* 0ed1be1d-52a7-4bfd-b4f5-0de7caed4617 */           \
-  0x0ed1be1d,                                           \
-  0x52a7,                                               \
-  0x4bfd,                                               \
-  { 0xb4, 0xf5, 0x0d, 0xe7, 0xca, 0xed, 0x46, 0x17 }    \
+{  /* 9735bc5f-a4b6-4668-ab73-6f8434c8e750 */           \
+  0x9735bc5f,                                           \
+  0xa4b6,                                               \
+  0x4668,                                               \
+  { 0xab, 0x73, 0x6f, 0x84, 0x34, 0xc8, 0xe7, 0x50 }    \
 }
 
 class nsDocAccessible : public nsHyperTextAccessibleWrap,
                         public nsIAccessibleDocument,
                         public nsIDocumentObserver,
                         public nsIObserver,
                         public nsIScrollPositionListener,
                         public nsSupportsWeakReference
@@ -156,16 +156,21 @@ public:
    * Cache access node.
    *
    * @param  aUniquID     [in] the unique identifier of accessible
    * @param  aAccessNode  [in] accessible to cache
    */
   void CacheAccessNode(void *aUniqueID, nsIAccessNode *aAccessNode);
 
   /**
+   * Remove the given access node from document cache.
+   */
+  void RemoveAccessNodeFromCache(nsIAccessNode *aAccessNode);
+
+  /**
    * Fires pending events.
    */
   void FlushPendingEvents();
 
   /**
    * Fire document load events.
    *
    * @param  aEventType  [in] nsIAccessibleEvent constant
--- a/accessible/src/base/nsRelUtils.cpp
+++ b/accessible/src/base/nsRelUtils.cpp
@@ -37,16 +37,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsRelUtils.h"
 
 #include "nsAccessNode.h"
 
 #include "nsIDOMDocument.h"
 #include "nsIDOMElement.h"
+#include "nsIDOMDocumentXBL.h"
 
 #include "nsAutoPtr.h"
 #include "nsArrayUtils.h"
 
 already_AddRefed<nsIAccessible>
 nsRelUtils::GetRelatedAccessible(nsIAccessible *aAccessible,
                                  PRUint32 aRelationType)
 {
@@ -94,30 +95,42 @@ nsRelUtils::AddTargetFromContent(PRUint3
   nsCOMPtr<nsIAccessible> accessible;
   accService->GetAccessibleFor(node, getter_AddRefs(accessible));
   return AddTarget(aRelationType, aRelation, accessible);
 }
 
 nsresult
 nsRelUtils::AddTargetFromIDRefAttr(PRUint32 aRelationType,
                                    nsIAccessibleRelation **aRelation,
-                                   nsIContent *aContent, nsIAtom *aAttr)
+                                   nsIContent *aContent, nsIAtom *aAttr,
+                                   PRBool aMayBeAnon)
 {
   nsAutoString id;
   if (!aContent->GetAttr(kNameSpaceID_None, aAttr, id))
     return NS_OK_NO_RELATION_TARGET;
 
   nsCOMPtr<nsIDOMDocument> document =
     do_QueryInterface(aContent->GetOwnerDoc());
   NS_ASSERTION(document, "The given node is not in document!");
   if (!document)
     return NS_OK_NO_RELATION_TARGET;
 
   nsCOMPtr<nsIDOMElement> refElm;
-  document->GetElementById(id, getter_AddRefs(refElm));
+  if (aMayBeAnon && aContent->GetBindingParent()) {
+    nsCOMPtr<nsIDOMDocumentXBL> documentXBL(do_QueryInterface(document));
+    nsCOMPtr<nsIDOMElement> bindingParent =
+      do_QueryInterface(aContent->GetBindingParent());
+    documentXBL->GetAnonymousElementByAttribute(bindingParent,
+                                                NS_LITERAL_STRING("id"),
+                                                id,
+                                                getter_AddRefs(refElm));
+  }
+  else {
+    document->GetElementById(id, getter_AddRefs(refElm));
+  }
 
   nsCOMPtr<nsIContent> refContent(do_QueryInterface(refElm));
   return AddTargetFromContent(aRelationType, aRelation, refContent);
 }
 
 nsresult
 nsRelUtils::AddTargetFromIDRefsAttr(PRUint32 aRelationType,
                                     nsIAccessibleRelation **aRelation,
--- a/accessible/src/base/nsRelUtils.h
+++ b/accessible/src/base/nsRelUtils.h
@@ -92,20 +92,24 @@ public:
   /**
    * Create the relation if the given relation is null and add the target to it
    * pointed by IDRef attribute on the given node.
    *
    * @param  aRelationType  [in] relation type
    * @param  aRelation      [in, out] relation object
    * @param  aContent       [in] node having the given IDRef attribute
    * @param  aAttr          [in] IDRef attribute
+   * @param  aMayBeAnon     [in] true if the target may be anonymous; if so,
+   *                             we need to look for it under the binding
+   *                             parent of aContent.
    */
   static nsresult AddTargetFromIDRefAttr(PRUint32 aRelationType,
                                          nsIAccessibleRelation **aRelation,
-                                         nsIContent *aContent, nsIAtom *aAttr);
+                                         nsIContent *aContent, nsIAtom *aAttr,
+                                         PRBool aMayBeAnon = PR_FALSE);
 
   /**
    * Create the relation if the given relation is null and add the targets to it
    * that are pointed by IDRefs attribute on the given node.
    *
    * @param  aRelationType  [in] relation type
    * @param  aRelation      [in, out] relation object
    * @param  aContent       [in] node having the given IDRefs attribute
--- a/accessible/src/base/nsRootAccessible.cpp
+++ b/accessible/src/base/nsRootAccessible.cpp
@@ -33,31 +33,33 @@
  * 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 ***** */
 
 // NOTE: alphabetically ordered
 #include "nsAccessibilityService.h"
 #include "nsAccessibleEventData.h"
+#include "nsApplicationAccessibleWrap.h"
+
 #include "nsHTMLSelectAccessible.h"
-#include "nsIBaseWindow.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDocShellTreeNode.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMEventListener.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOMHTMLAnchorElement.h"
 #include "nsIDOMHTMLImageElement.h"
 #include "nsIDOMHTMLInputElement.h"
 #include "nsIDOMHTMLSelectElement.h"
 #include "nsIDOMDataContainerEvent.h"
+#include "nsIDOMNSDocument.h"
 #include "nsIDOMNSEvent.h"
 #include "nsIDOMXULMenuListElement.h"
 #include "nsIDOMXULMultSelectCntrlEl.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
 #include "nsIDOMXULPopupElement.h"
 #include "nsIDocument.h"
 #include "nsIEventListenerManager.h"
 #include "nsIFrame.h"
@@ -77,22 +79,16 @@
 #include "nsFocusManager.h"
 
 #ifdef MOZ_XUL
 #include "nsXULTreeAccessible.h"
 #include "nsIXULDocument.h"
 #include "nsIXULWindow.h"
 #endif
 
-#ifdef MOZ_ACCESSIBILITY_ATK
-#include "nsAppRootAccessible.h"
-#else
-#include "nsApplicationAccessibleWrap.h"
-#endif
-
 // Expanded version of NS_IMPL_ISUPPORTS_INHERITED2 
 // so we can QI directly to concrete nsRootAccessible
 NS_IMPL_QUERY_HEAD(nsRootAccessible)
 NS_IMPL_QUERY_BODY(nsIDOMEventListener)
 if (aIID.Equals(NS_GET_IID(nsRootAccessible)))
   foundInterface = reinterpret_cast<nsISupports*>(this);
 else
 NS_IMPL_QUERY_TAIL_INHERITING(nsDocAccessible)
@@ -110,17 +106,16 @@ nsRootAccessible::nsRootAccessible(nsIDO
 
 //-----------------------------------------------------
 // destruction
 //-----------------------------------------------------
 nsRootAccessible::~nsRootAccessible()
 {
 }
 
-// helpers
 /* readonly attribute AString name; */
 NS_IMETHODIMP
 nsRootAccessible::GetName(nsAString& aName)
 {
   aName.Truncate();
 
   if (!mDocument) {
     return NS_ERROR_FAILURE;
@@ -128,32 +123,18 @@ nsRootAccessible::GetName(nsAString& aNa
 
   if (mRoleMapEntry) {
     nsAccessible::GetName(aName);
     if (!aName.IsEmpty()) {
       return NS_OK;
     }
   }
 
-  nsCOMPtr<nsIDocShellTreeItem> docShellAsItem =
-    nsCoreUtils::GetDocShellTreeItemFor(mDOMNode);
-  NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
-
-  nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
-  docShellAsItem->GetTreeOwner(getter_AddRefs(treeOwner));
-
-  nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(treeOwner));
-  if (baseWindow) {
-    nsXPIDLString title;
-    baseWindow->GetTitle(getter_Copies(title));
-    aName.Assign(title);
-    return NS_OK;
-  }
-
-  return NS_ERROR_FAILURE;
+  nsCOMPtr<nsIDOMNSDocument> document(do_QueryInterface(mDocument));
+  return document->GetTitle(aName);
 }
 
 /* readonly attribute nsIAccessible accParent; */
 NS_IMETHODIMP nsRootAccessible::GetParent(nsIAccessible * *aParent) 
 {
   NS_ENSURE_ARG_POINTER(aParent);
   *aParent = nsnull;
 
@@ -731,21 +712,21 @@ nsresult nsRootAccessible::HandleEventWi
   // If it's a tree element, need the currently selected item
   if (isTree) {
     nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelect =
       do_QueryInterface(aTargetNode);
     if (multiSelect) {
       PRInt32 treeIndex = -1;
       multiSelect->GetCurrentIndex(&treeIndex);
       if (treeIndex >= 0) {
-        nsRefPtr<nsXULTreeAccessible> treeCache =
+        nsRefPtr<nsXULTreeAccessible> treeAcc =
           nsAccUtils::QueryAccessibleTree(accessible);
-        if (treeCache) {
-          treeCache->GetCachedTreeitemAccessible(treeIndex, nsnull,
-                                                 getter_AddRefs(treeItemAccessible));
+        if (treeAcc) {
+          treeAcc->GetTreeItemAccessible(treeIndex,
+                                         getter_AddRefs(treeItemAccessible));
           if (treeItemAccessible)
             accessible = treeItemAccessible;
         }
       }
     }
   }
 #endif
 
--- a/accessible/src/html/Makefile.in
+++ b/accessible/src/html/Makefile.in
@@ -42,36 +42,16 @@ srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = accessibility
 LIBRARY_NAME = accessibility_html_s
 LIBXUL_LIBRARY = 1
 
-REQUIRES	= composer \
-		  content \
-		  docshell \
-		  dom \
-		  editor \
-		  gfx \
-		  imglib2 \
-		  intl \
-		  js \
-		  layout \
-		  locale \
-		  necko \
-		  string \
-		  thebes \
-		  view \
-		  webshell \
-		  widget \
-		  xpcom \
-		  xpconnect \
-		  $(NULL)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 REQUIRES += editor
 endif
 
 CPPSRCS = \
   nsHTMLAreaAccessible.cpp \
   nsHTMLFormControlAccessible.cpp \
--- a/accessible/src/html/nsHTMLTableAccessible.h
+++ b/accessible/src/html/nsHTMLTableAccessible.h
@@ -217,17 +217,17 @@ protected:
    *
    * @param  aTagName     [in] tag name of searched element
    * @param  aAllowEmpty  [in, optional] points if found element can be empty
    *                       or contain whitespace text only.
    */
   PRBool HasDescendant(const nsAString& aTagName, PRBool aAllowEmpty = PR_TRUE);
 
 #ifdef SHOW_LAYOUT_HEURISTIC
-  nsAutoString mLayoutHeuristic;
+  nsString mLayoutHeuristic;
 #endif
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsHTMLTableAccessible,
                               NS_TABLEACCESSIBLE_IMPL_CID)
 
 
 class nsHTMLTableHeadAccessible : public nsHTMLTableAccessible
--- a/accessible/src/mac/Makefile.in
+++ b/accessible/src/mac/Makefile.in
@@ -40,32 +40,16 @@ srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = accessibility
 LIBRARY_NAME = accessibility_toolkit_s
 LIBXUL_LIBRARY = 1
 
-REQUIRES	= content \
-		  layout \
-		  docshell \
-		  dom \
-		  editor \
-		  gfx \
-		  thebes \
-		  intl \
-		  locale \
-		  string \
-		  uriloader \
-		  view \
-		  widget \
-		  xpcom \
-		  necko \
-		  $(NULL)
   
   
 CMMSRCS = nsAccessNodeWrap.mm \
           nsRootAccessibleWrap.mm \
           nsAccessibleWrap.mm \
           mozAccessible.mm \
           mozDocAccessible.mm \
           mozActionElements.mm \
--- a/accessible/src/mac/nsAccessibleWrap.mm
+++ b/accessible/src/mac/nsAccessibleWrap.mm
@@ -233,17 +233,17 @@ nsAccessibleWrap::GetUnignoredChildCount
     return 0;
   
   PRInt32 childCount = 0;
   GetChildCount(&childCount);
   
   nsCOMPtr<nsIAccessible> curAcc;
   
   while (NextChild(curAcc)) {
-    nsAccessibleWrap *childWrap = static_cast<nsAccessibleWrap*>((nsIAccessible*)curAcc.get());
+    nsAccessibleWrap *childWrap = static_cast<nsAccessibleWrap*>(curAcc.get());
     
     // if the current child is not ignored, count it.
     if (!childWrap->IsIgnored())
       ++childCount;
       
     // if it's flat, we don't care to inspect its children.
     if (nsAccUtils::MustPrune(childWrap))
       continue;
@@ -275,17 +275,17 @@ nsAccessibleWrap::GetUnignoredChildren(n
 {
   nsCOMPtr<nsIAccessible> curAcc;
   
   // we're flat; there are no children.
   if (nsAccUtils::MustPrune(this))
     return;
   
   while (NextChild(curAcc)) {
-    nsAccessibleWrap *childWrap = static_cast<nsAccessibleWrap*>((nsIAccessible*)curAcc.get());
+    nsAccessibleWrap *childWrap = static_cast<nsAccessibleWrap*>(curAcc.get());
     if (childWrap->IsIgnored()) {
       // element is ignored, so try adding its children as substitutes, if it has any.
       if (!nsAccUtils::MustPrune(childWrap)) {
         nsTArray<nsRefPtr<nsAccessibleWrap> > children;
         childWrap->GetUnignoredChildren(children);
         if (!children.IsEmpty()) {
           // add the found unignored descendants to the array.
           aChildrenArray.AppendElements(children);
@@ -296,17 +296,17 @@ nsAccessibleWrap::GetUnignoredChildren(n
       aChildrenArray.AppendElement(childWrap);
   }
 }
 
 already_AddRefed<nsIAccessible>
 nsAccessibleWrap::GetUnignoredParent()
 {
   nsCOMPtr<nsIAccessible> parent(GetParent());
-  nsAccessibleWrap *parentWrap = static_cast<nsAccessibleWrap*>((nsIAccessible*)parent.get());
+  nsAccessibleWrap *parentWrap = static_cast<nsAccessibleWrap*>(parent.get());
   if (!parentWrap)
     return nsnull;
     
   // recursively return the parent, until we find one that is not ignored.
   if (parentWrap->IsIgnored())
     return parentWrap->GetUnignoredParent();
   
   nsIAccessible *outValue = nsnull;
--- a/accessible/src/mac/nsXULTreeAccessibleWrap.h
+++ b/accessible/src/mac/nsXULTreeAccessibleWrap.h
@@ -33,14 +33,13 @@
  * 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 __nsXULTreeAccessibleWrap_h__
 #define __nsXULTreeAccessibleWrap_h__
 
-#include "nsXULTreeAccessible.h"
-typedef class nsXULTreeAccessible           nsXULTreeAccessibleWrap;
-typedef class nsXULTreeitemAccessible       nsXULTreeitemAccessibleWrap;
+#include "nsXULTreeGridAccessible.h"
+typedef class nsXULTreeGridAccessible       nsXULTreeGridAccessibleWrap;
 typedef class nsXULTreeColumnsAccessible    nsXULTreeColumnsAccessibleWrap;
 
 #endif
--- a/accessible/src/msaa/Makefile.in
+++ b/accessible/src/msaa/Makefile.in
@@ -40,37 +40,16 @@ srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = accessibility
 LIBRARY_NAME = accessibility_toolkit_s
 LIBXUL_LIBRARY = 1
 
-REQUIRES	= content \
-		  docshell \
-		  dom \
-		  editor \
-		  gfx \
-		  thebes \
-		  htmlparser \
-		  intl \
-		  layout \
-		  locale \
-		  necko \
-		  plugin \
-		  pref \
-		  string \
-		  uriloader \
-		  view \
-		  webshell \
-		  widget \
-		  xpcom \
-		  xuldoc \
-		  $(NULL)
 
 CPPSRCS = \
   nsAccessNodeWrap.cpp \
   nsAccessibleWrap.cpp \
   nsTextAccessibleWrap.cpp \
   nsDocAccessibleWrap.cpp \
   nsRootAccessibleWrap.cpp \
   nsHTMLWin32ObjectAccessible.cpp \
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -1289,16 +1289,25 @@ nsAccessibleWrap::role(long *aRole)
   nsresult rv = GetRole(&xpRole);
   if (NS_FAILED(rv))
     return GetHRESULT(rv);
 
   NS_ASSERTION(gWindowsRoleMap[nsIAccessibleRole::ROLE_LAST_ENTRY].ia2Role == ROLE_WINDOWS_LAST_ENTRY,
                "MSAA role map skewed");
 
   *aRole = gWindowsRoleMap[xpRole].ia2Role;
+
+  // Special case, if there is a ROLE_ROW inside of a ROLE_TREE_TABLE, then call
+  // the IA2 role a ROLE_OUTLINEITEM.
+  if (xpRole == nsIAccessibleRole::ROLE_ROW) {
+    nsCOMPtr<nsIAccessible> parent = GetParent();
+    if (nsAccUtils::Role(parent) == nsIAccessibleRole::ROLE_TREE_TABLE)
+      *aRole = ROLE_SYSTEM_OUTLINEITEM;
+  }
+
   return S_OK;
 
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return E_FAIL;
 }
 
 STDMETHODIMP
 nsAccessibleWrap::scrollTo(enum IA2ScrollType aScrollType)
--- a/accessible/src/msaa/nsXULTreeAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsXULTreeAccessibleWrap.cpp
@@ -15,17 +15,18 @@
  * The Original Code is mozilla.org code.
  *
  * The Initial Developer of the Original Code is
  * Netscape Corp.
  * Portions created by the Initial Developer are Copyright (C) 2003
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
- *   Aaron Leventhal
+ *   Aaron Leventhal <aaronleventhal@moonset.net> (original author)
+ *   Alexander Surkov <surkov.alexander@gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either 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
@@ -33,129 +34,24 @@
  * 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 ***** */
 
 #include "nsXULTreeAccessibleWrap.h"
 
-#include "nsTextFormatter.h"
-#include "nsIFrame.h"
-
-// --------------------------------------------------------
-// nsXULTreeAccessibleWrap
-// --------------------------------------------------------
-
-nsXULTreeAccessibleWrap::nsXULTreeAccessibleWrap(nsIDOMNode *aDOMNode, nsIWeakReference *aShell):
-nsXULTreeAccessible(aDOMNode, aShell)
-{
-}
-
-nsresult
-nsXULTreeAccessibleWrap::GetRoleInternal(PRUint32 *aRole)
-{
-  NS_ENSURE_STATE(mTree);
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeGridAccessibleWrap
+////////////////////////////////////////////////////////////////////////////////
 
-  nsCOMPtr<nsITreeColumns> cols;
-  mTree->GetColumns(getter_AddRefs(cols));
-  nsCOMPtr<nsITreeColumn> primaryCol;
-  if (cols) {
-    cols->GetPrimaryColumn(getter_AddRefs(primaryCol));
-  }
-  // No primary column means we're in a list
-  // In fact, history and mail turn off the primary flag when switching to a flat view
-  *aRole = primaryCol ? nsIAccessibleRole::ROLE_OUTLINE :
-                        nsIAccessibleRole::ROLE_LIST;
-
-  return NS_OK;
-}
-
-// --------------------------------------------------------
-// nsXULTreeitemAccessibleWrap Accessible
-// --------------------------------------------------------
-
-nsXULTreeitemAccessibleWrap::nsXULTreeitemAccessibleWrap(nsIAccessible *aParent, 
-                                                         nsIDOMNode *aDOMNode, 
-                                                         nsIWeakReference *aShell, 
-                                                         PRInt32 aRow, 
-                                                         nsITreeColumn* aColumn) :
-nsXULTreeitemAccessible(aParent, aDOMNode, aShell, aRow, aColumn)
+nsXULTreeGridAccessibleWrap::
+  nsXULTreeGridAccessibleWrap(nsIDOMNode *aDOMNode, nsIWeakReference *aShell) :
+  nsXULTreeGridAccessible(aDOMNode, aShell)
 {
 }
 
-nsresult
-nsXULTreeitemAccessibleWrap::GetRoleInternal(PRUint32 *aRole)
-{
-  // No primary column means we're in a list
-  // In fact, history and mail turn off the primary flag when switching to a flat view
-  NS_ENSURE_STATE(mColumn);
-  PRBool isPrimary = PR_FALSE;
-  mColumn->GetPrimary(&isPrimary);
-  *aRole = isPrimary ? nsIAccessibleRole::ROLE_OUTLINEITEM :
-                       nsIAccessibleRole::ROLE_LISTITEM;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXULTreeitemAccessibleWrap::GetBounds(PRInt32 *aX, PRInt32 *aY,
-                                       PRInt32 *aWidth, PRInt32 *aHeight)
-{
-  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;
-
-  // Get x coordinate and width from treechildren element, get y coordinate and
-  // height from tree cell.
-
-  nsCOMPtr<nsIBoxObject> boxObj = nsCoreUtils::GetTreeBodyBoxObject(mTree);
-  NS_ENSURE_STATE(boxObj);
+NS_IMPL_ISUPPORTS_INHERITED0(nsXULTreeGridAccessibleWrap,
+                             nsXULTreeGridAccessible)
 
-  PRInt32 cellStartX, cellWidth;
-  nsresult rv = mTree->GetCoordsForCellItem(mRow, mColumn, EmptyCString(),
-                                            &cellStartX, aY,
-                                            &cellWidth, aHeight);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  boxObj->GetWidth(aWidth);
-
-  PRInt32 tcX = 0, tcY = 0;
-  boxObj->GetScreenX(&tcX);
-  boxObj->GetScreenY(&tcY);
-
-  *aX = tcX;
-  *aY += tcY;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXULTreeitemAccessibleWrap::GetName(nsAString& aName)
-{
-  NS_ENSURE_STATE(mTree);
-  nsCOMPtr<nsITreeColumns> cols;
-  mTree->GetColumns(getter_AddRefs(cols));
-  if (!cols) {
-    return NS_OK;
-  }
-  nsCOMPtr<nsITreeColumn> column;
-  cols->GetFirstColumn(getter_AddRefs(column));
-  while (column) {
-    nsAutoString colText;
-    mTreeView->GetCellText(mRow, column, colText);
-    aName += colText + NS_LITERAL_STRING("  ");
-    nsCOMPtr<nsITreeColumn> nextColumn;
-    column->GetNext(getter_AddRefs(nextColumn));
-    column = nextColumn;
-  }
-
-  return NS_OK;
-}
-
+IMPL_IUNKNOWN_INHERITED1(nsXULTreeGridAccessibleWrap,
+                         nsAccessibleWrap,
+                         CAccessibleTable);
--- a/accessible/src/msaa/nsXULTreeAccessibleWrap.h
+++ b/accessible/src/msaa/nsXULTreeAccessibleWrap.h
@@ -15,17 +15,18 @@
  * The Original Code is mozilla.org code.
  *
  * The Initial Developer of the Original Code is
  * Netscape Corp.
  * Portions created by the Initial Developer are Copyright (C) 2003
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
- *   Pete Zha (pete.zha@sun.com)
+ *   Pete Zha <pete.zha@sun.com> (original author)
+ *   Alexander Surkov <surkov.alexander@gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either 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
@@ -34,38 +35,33 @@
  * 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 __nsXULTreeAccessibleWrap_h__
 #define __nsXULTreeAccessibleWrap_h__
 
-#include "nsXULTreeAccessible.h"
+#include "nsXULTreeGridAccessible.h"
+
+#include "CAccessibleTable.h"
 
 typedef class nsXULTreeColumnsAccessible   nsXULTreeColumnsAccessibleWrap;
 
-class nsXULTreeAccessibleWrap : public nsXULTreeAccessible
+/**
+ * IA2 wrapper of nsXULTreeGridAccessible class, implements IAccessibleTable
+ * interface.
+ */
+class nsXULTreeGridAccessibleWrap : public nsXULTreeGridAccessible,
+                                    public CAccessibleTable
 {
 public:
-  nsXULTreeAccessibleWrap(nsIDOMNode *aDOMNode, nsIWeakReference *aShell);
-  virtual ~nsXULTreeAccessibleWrap() {}
-
-  // nsAccessible
-  virtual nsresult GetRoleInternal(PRUint32 *aRole);
-};
+  nsXULTreeGridAccessibleWrap(nsIDOMNode *aDOMNode, nsIWeakReference *aShell);
+  virtual ~nsXULTreeGridAccessibleWrap() {}
 
-class nsXULTreeitemAccessibleWrap : public nsXULTreeitemAccessible
-{
-public:
-  nsXULTreeitemAccessibleWrap(nsIAccessible *aParent, nsIDOMNode *aDOMNode, nsIWeakReference *aShell, 
-    PRInt32 aRow, nsITreeColumn* aColumn);
-  virtual ~nsXULTreeitemAccessibleWrap() {}
+  // IUnknown
+  DECL_IUNKNOWN_INHERITED
 
-  // nsIAccessible
-  NS_IMETHOD GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
-  NS_IMETHOD GetName(nsAString &aName);
-
-  // nsAccessible
-  virtual nsresult GetRoleInternal(PRUint32 *aRole);
+  // nsISupports
+  NS_DECL_ISUPPORTS_INHERITED
 };
 
 #endif
--- a/accessible/src/other/Makefile.in
+++ b/accessible/src/other/Makefile.in
@@ -40,37 +40,16 @@ srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = accessibility
 LIBRARY_NAME = accessibility_toolkit_s
 LIBXUL_LIBRARY = 1
 
-REQUIRES	= content \
-		  docshell \
-		  dom \
-		  editor \
-		  gfx \
-		  thebes \
-		  htmlparser \
-		  intl \
-		  layout \
-		  locale \
-		  necko \
-		  plugin \
-		  pref \
-		  string \
-		  uriloader \
-		  view \
-		  webshell \
-		  widget \
-		  xpcom \
-		  xuldoc \
-		  $(NULL)
 
 CPPSRCS = \
   nsAccessNodeWrap.cpp \
   nsAccessibleWrap.cpp \
   nsRootAccessibleWrap.cpp \
   $(NULL)
 
 EXPORTS = \
--- a/accessible/src/other/nsXULTreeAccessibleWrap.h
+++ b/accessible/src/other/nsXULTreeAccessibleWrap.h
@@ -33,14 +33,13 @@
  * 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 __nsXULTreeAccessibleWrap_h__
 #define __nsXULTreeAccessibleWrap_h__
 
-#include "nsXULTreeAccessible.h"
-typedef class nsXULTreeAccessible           nsXULTreeAccessibleWrap;
-typedef class nsXULTreeitemAccessible       nsXULTreeitemAccessibleWrap;
+#include "nsXULTreeGridAccessible.h"
+typedef class nsXULTreeGridAccessible      nsXULTreeGridAccessibleWrap;
 typedef class nsXULTreeColumnsAccessible   nsXULTreeColumnsAccessibleWrap;
 
 #endif
--- a/accessible/src/xforms/Makefile.in
+++ b/accessible/src/xforms/Makefile.in
@@ -42,31 +42,16 @@ srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = accessibility
 LIBRARY_NAME = accessibility_xforms_s
 LIBXUL_LIBRARY = 1
 
-REQUIRES	= content \
-      docshell \
-      dom \
-      editor \
-      gfx \
-      thebes \
-      intl \
-      layout \
-      locale \
-      necko \
-      pref \
-      string \
-      widget \
-      xpcom \
-      $(NULL)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 REQUIRES += editor
 endif
 
 CPPSRCS = \
   nsXFormsAccessible.cpp \
   nsXFormsFormControlsAccessible.cpp \
--- a/accessible/src/xul/Makefile.in
+++ b/accessible/src/xul/Makefile.in
@@ -42,46 +42,32 @@ srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = accessibility
 LIBRARY_NAME = accessibility_xul_s
 LIBXUL_LIBRARY = 1
 
-REQUIRES	= content \
-		  docshell \
-		  dom \
-		  editor \
-		  gfx \
-		  thebes \
-		  intl \
-		  layout \
-		  locale \
-		  necko \
-		  pref \
-		  string \
-		  widget \
-		  xpcom \
-		  $(NULL)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 REQUIRES += editor
 endif
 
 CPPSRCS = \
   nsXULAlertAccessible.cpp \
   nsXULColorPickerAccessible.cpp \
   nsXULFormControlAccessible.cpp \
   nsXULMenuAccessible.cpp \
   nsXULSelectAccessible.cpp \
   nsXULSliderAccessible.cpp \
   nsXULTabAccessible.cpp \
   nsXULTextAccessible.cpp \
   nsXULTreeAccessible.cpp \
+  nsXULTreeGridAccessible.cpp \
   $(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES = \
--- a/accessible/src/xul/nsXULTabAccessible.cpp
+++ b/accessible/src/xul/nsXULTabAccessible.cpp
@@ -144,17 +144,18 @@ nsXULTabAccessible::GetRelationByType(PR
   // Expose 'LABEL_FOR' relation on tab accessible for tabpanel accessible.
   // XXX: It makes sense to require the interface from xul:tab to get linked
   // tabpanel element.
   nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
 
   // Check whether tab and tabpanel are related by 'linkedPanel' attribute on
   // xul:tab element.
   rv = nsRelUtils::AddTargetFromIDRefAttr(aRelationType, aRelation, content,
-                                          nsAccessibilityAtoms::linkedPanel);
+                                          nsAccessibilityAtoms::linkedPanel,
+                                          PR_TRUE);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (rv != NS_OK_NO_RELATION_TARGET)
     return NS_OK;
 
   // If there is no 'linkedPanel' attribute on xul:tab element then we
   // assume tab and tabpanels are related 1 to 1. We follow algorithm from
   // the setter 'selectedIndex' of tabbox.xml#tabs binding.
--- a/accessible/src/xul/nsXULTreeAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeAccessible.cpp
@@ -31,312 +31,304 @@
  * 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 ***** */
 
+#include "nsXULTreeAccessible.h"
+
+#include "nsDocAccessible.h"
+
 #include "nsIDOMXULElement.h"
 #include "nsIDOMXULMultSelectCntrlEl.h"
 #include "nsIDOMXULTreeElement.h"
 #include "nsITreeSelection.h"
-#include "nsXULTreeAccessibleWrap.h"
 #include "nsIMutableArray.h"
 #include "nsComponentManagerUtils.h"
 
-#ifdef MOZ_ACCESSIBILITY_ATK
-#include "nsIAccessibleTable.h"
-#endif
+////////////////////////////////////////////////////////////////////////////////
+// Internal static functions
+////////////////////////////////////////////////////////////////////////////////
 
-/* static */
-PRBool nsXULTreeAccessible::IsColumnHidden(nsITreeColumn *aColumn)
-{
-  nsCOMPtr<nsIDOMElement> element;
-  aColumn->GetElement(getter_AddRefs(element));
-  nsCOMPtr<nsIContent> content = do_QueryInterface(element);
-  return content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::hidden,
-                              nsAccessibilityAtoms::_true, eCaseMatters);
-}
-
-/* static */
-already_AddRefed<nsITreeColumn> nsXULTreeAccessible::GetNextVisibleColumn(nsITreeColumn *aColumn)
+static PLDHashOperator
+ElementTraverser(const void *aKey, nsIAccessNode *aAccessNode,
+                 void *aUserArg)
 {
-  // Skip hidden columns.
-  nsCOMPtr<nsITreeColumn> nextColumn;
-  aColumn->GetNext(getter_AddRefs(nextColumn));
-  while (nextColumn && IsColumnHidden(nextColumn)) {
-    nsCOMPtr<nsITreeColumn> tempColumn;
-    nextColumn->GetNext(getter_AddRefs(tempColumn));
-    nextColumn.swap(tempColumn);
-  }
-
-  nsITreeColumn *retCol = nsnull;
-  nextColumn.swap(retCol);
-  return retCol;
-}
+  nsCycleCollectionTraversalCallback *cb = 
+    static_cast<nsCycleCollectionTraversalCallback*>(aUserArg);
 
-/* static */
-already_AddRefed<nsITreeColumn> nsXULTreeAccessible::GetFirstVisibleColumn(nsITreeBoxObject *aTree)
-{
-  nsCOMPtr<nsITreeColumns> cols;
-  nsCOMPtr<nsITreeColumn> column;
-  aTree->GetColumns(getter_AddRefs(cols));
-  if (cols) {
-    cols->GetFirstColumn(getter_AddRefs(column));
-  }
-
-  if (column && IsColumnHidden(column)) {
-    column = GetNextVisibleColumn(column);
-  }
-  NS_ENSURE_TRUE(column, nsnull);
-
-  nsITreeColumn *retCol = nsnull;
-  column.swap(retCol);
-  return retCol;
+  NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mAccessNodeCache of XUL tree entry");
+  cb->NoteXPCOMChild(aAccessNode);
+  return PL_DHASH_NEXT;
 }
 
-/* static */
-already_AddRefed<nsITreeColumn> nsXULTreeAccessible::GetLastVisibleColumn(nsITreeBoxObject *aTree)
-{
-  nsCOMPtr<nsITreeColumns> cols;
-  nsCOMPtr<nsITreeColumn> column;
-  aTree->GetColumns(getter_AddRefs(cols));
-  if (cols) {
-    cols->GetLastColumn(getter_AddRefs(column));
-  }
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeAccessible
+////////////////////////////////////////////////////////////////////////////////
 
-  // Skip hidden columns.
-  while (column && IsColumnHidden(column)) {
-    nsCOMPtr<nsITreeColumn> tempColumn;
-    column->GetPrevious(getter_AddRefs(tempColumn));
-    column.swap(tempColumn);
-  }
-  NS_ENSURE_TRUE(column, nsnull);
-
-  nsITreeColumn *retCol = nsnull;
-  column.swap(retCol);
-  return retCol;
-}
-
-// ---------- nsXULTreeAccessible ----------
-
-nsXULTreeAccessible::nsXULTreeAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell):
-nsXULSelectableAccessible(aDOMNode, aShell),
-mAccessNodeCache(nsnull)
-
+nsXULTreeAccessible::
+  nsXULTreeAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell) :
+  nsXULSelectableAccessible(aDOMNode, aShell)
 {
-  GetTreeBoxObject(aDOMNode, getter_AddRefs(mTree));
+  nsCoreUtils::GetTreeBoxObject(aDOMNode, getter_AddRefs(mTree));
   if (mTree)
     mTree->GetView(getter_AddRefs(mTreeView));
+
   NS_ASSERTION(mTree && mTreeView, "Can't get mTree or mTreeView!\n");
-  mAccessNodeCache = new nsAccessNodeHashtable;
-  mAccessNodeCache->Init(kDefaultTreeCacheSize);
+
+  mAccessNodeCache.Init(kDefaultTreeCacheSize);
 }
 
-NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeAccessible,
-                             nsXULSelectableAccessible,
-                             nsXULTreeAccessible)
-                                                                                                       
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeAccessible: nsISupports and cycle collection implementation
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTreeAccessible)
 
-// Get the nsITreeBoxObject interface from any levels DOMNode under the <tree>
-void nsXULTreeAccessible::GetTreeBoxObject(nsIDOMNode *aDOMNode, nsITreeBoxObject **aBoxObject)
-{
-  nsAutoString name;
-  nsCOMPtr<nsIDOMNode> parentNode, currentNode;
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULTreeAccessible,
+                                                  nsAccessible)
+tmp->mAccessNodeCache.EnumerateRead(ElementTraverser, &cb);
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-  // Find DOMNode's parents recursively until reach the <tree> tag
-  currentNode = aDOMNode;
-  while (currentNode) {
-    currentNode->GetLocalName(name);
-    if (name.EqualsLiteral("tree")) {
-      // We will get the nsITreeBoxObject from the tree node
-      nsCOMPtr<nsIDOMXULElement> xulElement(do_QueryInterface(currentNode));
-      if (xulElement) {
-        nsCOMPtr<nsIBoxObject> box;
-        xulElement->GetBoxObject(getter_AddRefs(box));
-        nsCOMPtr<nsITreeBoxObject> treeBox(do_QueryInterface(box));
-        if (treeBox) {
-          *aBoxObject = treeBox;
-          NS_ADDREF(*aBoxObject);
-          return;
-        }
-      }
-    }
-    currentNode->GetParentNode(getter_AddRefs(parentNode));
-    currentNode = parentNode;
-  }
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULTreeAccessible,
+                                                nsAccessible)
+tmp->ClearCache(tmp->mAccessNodeCache);
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
-  *aBoxObject = nsnull;
-}
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXULTreeAccessible)
+NS_INTERFACE_MAP_STATIC_AMBIGUOUS(nsXULTreeAccessible)
+NS_INTERFACE_MAP_END_INHERITING(nsXULSelectableAccessible)
+
+NS_IMPL_ADDREF_INHERITED(nsXULTreeAccessible, nsXULSelectableAccessible)
+NS_IMPL_RELEASE_INHERITED(nsXULTreeAccessible, nsXULSelectableAccessible)
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeAccessible: nsAccessible implementation
 
 nsresult
 nsXULTreeAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
 {
-  // Get focus status from base class
+  // Get focus status from base class.
   nsresult rv = nsAccessible::GetStateInternal(aState, aExtraState);
   NS_ENSURE_A11Y_SUCCESS(rv, rv);
-  
-  // see if we are multiple select if so set ourselves as such
-  nsCOMPtr<nsIDOMElement> element (do_QueryInterface(mDOMNode));
-  if (element) {
-    // the default selection type is multiple
-    nsAutoString selType;
-    element->GetAttribute(NS_LITERAL_STRING("seltype"), selType);
-    if (selType.IsEmpty() || !selType.EqualsLiteral("single"))
-      *aState |= nsIAccessibleStates::STATE_MULTISELECTABLE;
-  }
+
+  // readonly state
+  *aState |= nsIAccessibleStates::STATE_READONLY;
+
+  // remove focusable and focused states since tree items are focusable for AT
+  *aState &= ~nsIAccessibleStates::STATE_FOCUSABLE;
+  *aState &= ~nsIAccessibleStates::STATE_FOCUSED;
 
-  *aState |= nsIAccessibleStates::STATE_READONLY |
-             nsIAccessibleStates::STATE_FOCUSABLE;
+  // multiselectable state.
+  nsCOMPtr<nsITreeSelection> selection;
+  mTreeView->GetSelection(getter_AddRefs(selection));
+  NS_ENSURE_STATE(selection);
+
+  PRBool isSingle = PR_FALSE;
+  rv = selection->GetSingle(&isSingle);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (!isSingle)
+    *aState |= nsIAccessibleStates::STATE_MULTISELECTABLE;
 
   return NS_OK;
 }
 
-// The value is the first selected child
-NS_IMETHODIMP nsXULTreeAccessible::GetValue(nsAString& _retval)
+NS_IMETHODIMP
+nsXULTreeAccessible::GetValue(nsAString& aValue)
 {
-  _retval.Truncate(0);
+  // Return the value is the first selected child.
 
-  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
+  aValue.Truncate();
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsITreeSelection> selection;
   mTreeView->GetSelection(getter_AddRefs(selection));
-  if (! selection)
+  if (!selection)
     return NS_ERROR_FAILURE;
 
   PRInt32 currentIndex;
   nsCOMPtr<nsIDOMElement> selectItem;
   selection->GetCurrentIndex(&currentIndex);
   if (currentIndex >= 0) {
     nsCOMPtr<nsITreeColumn> keyCol;
 
     nsCOMPtr<nsITreeColumns> cols;
     mTree->GetColumns(getter_AddRefs(cols));
     if (cols)
       cols->GetKeyColumn(getter_AddRefs(keyCol));
 
-    return mTreeView->GetCellText(currentIndex, keyCol, _retval);
+    return mTreeView->GetCellText(currentIndex, keyCol, aValue);
   }
 
   return NS_OK;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeAccessible: nsAccessNode implementation
+
 PRBool
 nsXULTreeAccessible::IsDefunct()
 {
   return nsXULSelectableAccessible::IsDefunct() || !mTree || !mTreeView;
 }
 
 nsresult
 nsXULTreeAccessible::Shutdown()
 {
+  // XXX: we don't remove accessible from document cache if shutdown wasn't
+  // initiated by document destroying. Note, we can't remove accessible from
+  // document cache here while document is going to be shutdown. Note, this is
+  // not unique place where we have similar problem.
+  ClearCache(mAccessNodeCache);
+
   mTree = nsnull;
   mTreeView = nsnull;
 
   nsXULSelectableAccessible::Shutdown();
+  return NS_OK;
+}
 
-  if (mAccessNodeCache) {
-    ClearCache(*mAccessNodeCache);
-    delete mAccessNodeCache;
-    mAccessNodeCache = nsnull;
-  }
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeAccessible: nsAccessible implementation (put methods here)
+
+nsresult
+nsXULTreeAccessible::GetRoleInternal(PRUint32 *aRole)
+{
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  // No primary column means we're in a list. In fact, history and mail turn off
+  // the primary flag when switching to a flat view.
+
+  nsCOMPtr<nsITreeColumns> cols;
+  mTree->GetColumns(getter_AddRefs(cols));
+  nsCOMPtr<nsITreeColumn> primaryCol;
+  if (cols)
+    cols->GetPrimaryColumn(getter_AddRefs(primaryCol));
+
+  *aRole = primaryCol ?
+    nsIAccessibleRole::ROLE_OUTLINE :
+    nsIAccessibleRole::ROLE_LIST;
 
   return NS_OK;
 }
 
-nsresult
-nsXULTreeAccessible::GetRoleInternal(PRUint32 *aRole)
-{
-  NS_ASSERTION(mTree, "No tree view");
-  PRInt32 colCount = 0;
-  if (NS_SUCCEEDED(GetColumnCount(mTree, &colCount)) && (colCount > 1))
-    *aRole = nsIAccessibleRole::ROLE_TREE_TABLE;
-  else
-    *aRole = nsIAccessibleRole::ROLE_OUTLINE;
-  return NS_OK;
-}
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeAccessible: nsIAccessible implementation
 
-NS_IMETHODIMP nsXULTreeAccessible::GetFirstChild(nsIAccessible **aFirstChild)
+NS_IMETHODIMP
+nsXULTreeAccessible::GetFirstChild(nsIAccessible **aFirstChild)
 {
   nsAccessible::GetFirstChild(aFirstChild);
 
   // in normal case, tree's first child should be treecols, if it is not here, 
   //   use the first row as tree's first child
   if (*aFirstChild == nsnull) {
-    NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
+    if (IsDefunct())
+      return NS_ERROR_FAILURE;
 
     PRInt32 rowCount;
     mTreeView->GetRowCount(&rowCount);
-    if (rowCount > 0) {
-      nsCOMPtr<nsITreeColumn> column = GetFirstVisibleColumn(mTree);
-      GetCachedTreeitemAccessible(0, column, aFirstChild);
-    }
+    if (rowCount > 0)
+      GetTreeItemAccessible(0, aFirstChild);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeAccessible::GetLastChild(nsIAccessible **aLastChild)
 {
   NS_ENSURE_ARG_POINTER(aLastChild);
   *aLastChild = nsnull;
 
-  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
 
   PRInt32 rowCount = 0;
   mTreeView->GetRowCount(&rowCount);
   if (rowCount > 0) {
-    nsCOMPtr<nsITreeColumn> column = GetLastVisibleColumn(mTree);
-    GetCachedTreeitemAccessible(rowCount - 1, column, aLastChild);
+    GetTreeItemAccessible(rowCount - 1, aLastChild);
 
     if (*aLastChild)
       return NS_OK;
   }
 
   // If there is not any rows, use treecols as tree's last child.
   return nsAccessible::GetLastChild(aLastChild);
 }
 
-// tree's children count is row count + treecols count
-NS_IMETHODIMP nsXULTreeAccessible::GetChildCount(PRInt32 *aAccChildCount)
+NS_IMETHODIMP
+nsXULTreeAccessible::GetChildCount(PRInt32 *aChildCount)
 {
-  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
+  // tree's children count is row count + treecols count.
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
 
-  nsAccessible::GetChildCount(aAccChildCount);
+  nsAccessible::GetChildCount(aChildCount);
 
-  if (*aAccChildCount != eChildCountUninitialized) {
-    PRInt32 rowCount;
+  if (*aChildCount != eChildCountUninitialized) {
+    PRInt32 rowCount = 0;
     mTreeView->GetRowCount(&rowCount);
-    *aAccChildCount += rowCount;
+    *aChildCount += rowCount;
   }
+
   return NS_OK;
 }
 
-NS_IMETHODIMP nsXULTreeAccessible::GetFocusedChild(nsIAccessible **aFocusedChild) 
+NS_IMETHODIMP
+nsXULTreeAccessible::GetChildAt(PRInt32 aChildIndex, nsIAccessible **aChild)
 {
+  NS_ENSURE_ARG_POINTER(aChild);
+  *aChild = nsnull;
+
+  PRInt32 childCount = 0;
+  nsresult rv = nsAccessible::GetChildCount(&childCount);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (aChildIndex < childCount)
+    return nsAccessible::GetChildAt(aChildIndex, aChild);
+
+  GetTreeItemAccessible(aChildIndex - childCount, aChild);
+  return *aChild ? NS_OK : NS_ERROR_INVALID_ARG;
+}
+
+NS_IMETHODIMP
+nsXULTreeAccessible::GetFocusedChild(nsIAccessible **aFocusedChild) 
+{
+  NS_ENSURE_ARG_POINTER(aFocusedChild);
+  *aFocusedChild = nsnull;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  if (gLastFocusedNode != mDOMNode)
+    return NS_OK;
+
   nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelect =
     do_QueryInterface(mDOMNode);
   if (multiSelect) {
-    PRInt32 row;
+    PRInt32 row = -1;
     multiSelect->GetCurrentIndex(&row);
-    if (row >= 0) {
-      GetCachedTreeitemAccessible(row, nsnull, aFocusedChild);
-      if (*aFocusedChild)
-        return NS_OK;
-    }
+    if (row >= 0)
+      GetTreeItemAccessible(row, aFocusedChild);
   }
-  NS_ADDREF(*aFocusedChild = this);
+
   return NS_OK;
 }
 
-// nsAccessible::GetChildAtPoint()
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeAccessible: nsAccessible implementation (DON'T put methods here)
+
 nsresult
 nsXULTreeAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
                                      PRBool aDeepestChild,
                                      nsIAccessible **aChild)
 {
   nsIFrame *frame = GetFrame();
   if (!frame)
     return NS_ERROR_FAILURE;
@@ -344,61 +336,73 @@ nsXULTreeAccessible::GetChildAtPoint(PRI
   nsPresContext *presContext = frame->PresContext();
   nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
 
   nsIFrame *rootFrame = presShell->GetRootFrame();
   NS_ENSURE_STATE(rootFrame);
 
   nsIntRect rootRect = rootFrame->GetScreenRectExternal();
 
-  PRInt32 clientX = presContext->AppUnitsToIntCSSPixels(
-    presContext->DevPixelsToAppUnits(aX - rootRect.x));
-  PRInt32 clientY = presContext->AppUnitsToIntCSSPixels(
-    presContext->DevPixelsToAppUnits(aY - rootRect.y));
+  PRInt32 clientX = presContext->DevPixelsToIntCSSPixels(aX - rootRect.x);
+  PRInt32 clientY = presContext->DevPixelsToIntCSSPixels(aY - rootRect.y);
 
   PRInt32 row = -1;
   nsCOMPtr<nsITreeColumn> column;
   nsCAutoString childEltUnused;
   mTree->GetCellAt(clientX, clientY, &row, getter_AddRefs(column),
                    childEltUnused);
 
   // If we failed to find tree cell for the given point then it might be
   // tree columns.
   if (row == -1 || !column)
     return nsXULSelectableAccessible::
       GetChildAtPoint(aX, aY, aDeepestChild, aChild);
 
-  GetCachedTreeitemAccessible(row, column, aChild);
+  GetTreeItemAccessible(row, aChild);
+  if (aDeepestChild && *aChild) {
+    // Look for accessible cell for the found item accessible.
+    nsRefPtr<nsXULTreeItemAccessibleBase> treeitemAcc =
+      nsAccUtils::QueryObject<nsXULTreeItemAccessibleBase>(*aChild);
+
+    nsCOMPtr<nsIAccessible> cellAccessible;
+    treeitemAcc->GetCellAccessible(column, getter_AddRefs(cellAccessible));
+    if (cellAccessible)
+      cellAccessible.swap(*aChild);
+  }
+
   return NS_OK;
 }
 
-// Ask treeselection to get all selected children
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeAccessible: nsAccessibleSelectable implementation
+
 NS_IMETHODIMP nsXULTreeAccessible::GetSelectedChildren(nsIArray **_retval)
 {
+  // Ask tree selection to get all selected children
   *_retval = nsnull;
 
-  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsITreeSelection> selection;
   mTreeView->GetSelection(getter_AddRefs(selection));
   if (!selection)
     return NS_ERROR_FAILURE;
   nsCOMPtr<nsIMutableArray> selectedAccessibles =
     do_CreateInstance(NS_ARRAY_CONTRACTID);
   NS_ENSURE_STATE(selectedAccessibles);
 
   PRInt32 rowIndex, rowCount;
   PRBool isSelected;
   mTreeView->GetRowCount(&rowCount);
   for (rowIndex = 0; rowIndex < rowCount; rowIndex++) {
     selection->IsSelected(rowIndex, &isSelected);
     if (isSelected) {
       nsCOMPtr<nsIAccessible> tempAccess;
-        GetCachedTreeitemAccessible(rowIndex, nsnull,
-                                    getter_AddRefs(tempAccess));
+      GetTreeItemAccessible(rowIndex, getter_AddRefs(tempAccess));
       NS_ENSURE_STATE(tempAccess);
 
       selectedAccessibles->AppendElement(tempAccess, PR_FALSE);
     }
   }
 
   PRUint32 length;
   selectedAccessibles->GetLength(&length);
@@ -409,29 +413,31 @@ NS_IMETHODIMP nsXULTreeAccessible::GetSe
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsXULTreeAccessible::GetSelectionCount(PRInt32 *aSelectionCount)
 {
   *aSelectionCount = 0;
 
-  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsITreeSelection> selection;
   mTreeView->GetSelection(getter_AddRefs(selection));
   if (selection)
     selection->GetCount(aSelectionCount);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsXULTreeAccessible::ChangeSelection(PRInt32 aIndex, PRUint8 aMethod, PRBool *aSelState)
 {
-  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsITreeSelection> selection;
   mTreeView->GetSelection(getter_AddRefs(selection));
   if (selection) {
     selection->IsSelected(aIndex, aSelState);
     if ((!(*aSelState) && eSelection_Add == aMethod) || 
         ((*aSelState) && eSelection_Remove == aMethod))
       return selection->ToggleSelect(aIndex);
@@ -454,62 +460,65 @@ NS_IMETHODIMP nsXULTreeAccessible::Remov
 
 NS_IMETHODIMP nsXULTreeAccessible::IsChildSelected(PRInt32 aIndex, PRBool *_retval)
 {
   return ChangeSelection(aIndex, eSelection_GetState, _retval);
 }
 
 NS_IMETHODIMP nsXULTreeAccessible::ClearSelection()
 {
-  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsITreeSelection> selection;
   mTreeView->GetSelection(getter_AddRefs(selection));
   if (selection)
     selection->ClearSelection();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeAccessible::RefSelection(PRInt32 aIndex, nsIAccessible **aAccessible)
 {
   NS_ENSURE_ARG_POINTER(aAccessible);
   *aAccessible = nsnull;
 
-  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsITreeSelection> selection;
   mTreeView->GetSelection(getter_AddRefs(selection));
   if (!selection)
     return NS_ERROR_FAILURE;
 
   PRInt32 rowIndex, rowCount;
   PRInt32 selCount = 0;
   PRBool isSelected;
   mTreeView->GetRowCount(&rowCount);
   for (rowIndex = 0; rowIndex < rowCount; rowIndex++) {
     selection->IsSelected(rowIndex, &isSelected);
     if (isSelected) {
       if (selCount == aIndex) {
-        GetCachedTreeitemAccessible(rowIndex, nsnull, aAccessible);
+        GetTreeItemAccessible(rowIndex, aAccessible);
         return NS_OK;
       }
       selCount++;
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsXULTreeAccessible::SelectAllSelection(PRBool *_retval)
 {
   *_retval = PR_FALSE;
 
-  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
 
   // see if we are multiple select if so set ourselves as such
   nsCOMPtr<nsIDOMElement> element (do_QueryInterface(mDOMNode));
   if (element) {
     nsAutoString selType;
     element->GetAttribute(NS_LITERAL_STRING("seltype"), selType);
     if (selType.IsEmpty() || !selType.EqualsLiteral("single")) {
       *_retval = PR_TRUE;
@@ -518,140 +527,125 @@ NS_IMETHODIMP nsXULTreeAccessible::Selec
       if (selection)
         selection->SelectAll();
     }
   }
 
   return NS_OK;
 }
 
-// nsXULTreeAccessible
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeAccessible: public implementation
 
 void
-nsXULTreeAccessible::GetCachedTreeitemAccessible(PRInt32 aRow,
-                                                 nsITreeColumn* aColumn,
-                                                 nsIAccessible** aAccessible)
+nsXULTreeAccessible::GetTreeItemAccessible(PRInt32 aRow,
+                                           nsIAccessible** aAccessible)
 {
   *aAccessible = nsnull;
 
-  NS_ASSERTION(mAccessNodeCache, "No accessibility cache for tree");
-  NS_ASSERTION(mTree && mTreeView, "Can't get mTree or mTreeView!\n");
-
-  nsCOMPtr<nsITreeColumn> col;
-#ifdef MOZ_ACCESSIBILITY_ATK
-  col = aColumn;
-#endif
-  PRInt32 columnIndex = -1;
+  if (aRow < 0)
+    return;
 
-  if (!col && mTree) {
-    nsCOMPtr<nsITreeColumns> cols;
-    mTree->GetColumns(getter_AddRefs(cols));
-    if (cols)
-      cols->GetKeyColumn(getter_AddRefs(col));
-  }
-
-  // Do not create accessible for treeitem if there is no column in the tree
-  // because it doesn't render treeitems properly.
-  if (!col)
+  PRInt32 rowCount = 0;
+  nsresult rv = mTreeView->GetRowCount(&rowCount);
+  if (NS_FAILED(rv) || aRow >= rowCount)
     return;
 
-  col->GetIndex(&columnIndex);
-
+  void *key = reinterpret_cast<void*>(aRow);
   nsCOMPtr<nsIAccessNode> accessNode;
-  GetCacheEntry(*mAccessNodeCache, (void*)(aRow * kMaxTreeColumns + columnIndex), getter_AddRefs(accessNode));
+  GetCacheEntry(mAccessNodeCache, key, getter_AddRefs(accessNode));
 
   if (!accessNode) {
-    nsRefPtr<nsAccessNode> treeItemAcc =
-      new nsXULTreeitemAccessibleWrap(this, mDOMNode, mWeakShell, aRow, col);
+    nsRefPtr<nsAccessNode> treeItemAcc;
+    CreateTreeItemAccessible(aRow, getter_AddRefs(treeItemAcc));
     if (!treeItemAcc)
       return;
 
     nsresult rv = treeItemAcc->Init();
     if (NS_FAILED(rv))
       return;
 
     accessNode = treeItemAcc;
-    PutCacheEntry(*mAccessNodeCache, (void*)(aRow * kMaxTreeColumns + columnIndex), accessNode);
+    PutCacheEntry(mAccessNodeCache, key, accessNode);
   }
 
   CallQueryInterface(accessNode, aAccessible);
 }
 
 void
 nsXULTreeAccessible::InvalidateCache(PRInt32 aRow, PRInt32 aCount)
 {
   if (IsDefunct())
     return;
 
   // Do not invalidate the cache if rows have been inserted.
   if (aCount > 0)
     return;
 
-  nsCOMPtr<nsITreeColumns> cols;
-  mTree->GetColumns(getter_AddRefs(cols));
-  if (!cols)
-    return;
+  // 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);
 
-#ifdef MOZ_ACCESSIBILITY_ATK
-  PRInt32 colsCount = 0;
-  nsresult rv = cols->GetCount(&colsCount);
-  if (NS_FAILED(rv))
-    return;
-#else
-  nsCOMPtr<nsITreeColumn> col;
-  cols->GetKeyColumn(getter_AddRefs(col));
-  if (!col)
-    return;
+    nsCOMPtr<nsIAccessNode> accessNode;
+    GetCacheEntry(mAccessNodeCache, key, getter_AddRefs(accessNode));
 
-  PRInt32 colIdx = 0;
-  nsresult rv = col->GetIndex(&colIdx);
-  if (NS_FAILED(rv))
-    return;
+    if (accessNode) {
+      nsRefPtr<nsAccessible> accessible =
+        nsAccUtils::QueryAccessible(accessNode);
 
-#endif
+      nsCOMPtr<nsIAccessibleEvent> event =
+        new nsAccEvent(nsIAccessibleEvent::EVENT_DOM_DESTROY,
+                       accessible, PR_FALSE);
+      FireAccessibleEvent(event);
 
-  for (PRInt32 rowIdx = aRow; rowIdx < aRow - aCount; rowIdx++) {
-#ifdef MOZ_ACCESSIBILITY_ATK
-    for (PRInt32 colIdx = 0; colIdx < colsCount; ++colIdx) {
-#else
-    {
-#endif
-
-      void *key = reinterpret_cast<void*>(rowIdx * kMaxTreeColumns + colIdx);
+      accessible->Shutdown();
 
-      nsCOMPtr<nsIAccessNode> accessNode;
-      GetCacheEntry(*mAccessNodeCache, key, getter_AddRefs(accessNode));
+      // Remove accessible from document cache and tree cache.
+      nsCOMPtr<nsIAccessibleDocument> docAccessible = GetDocAccessible();
+      if (docAccessible) { 
+        nsRefPtr<nsDocAccessible> docAcc =
+          nsAccUtils::QueryAccessibleDocument(docAccessible);
+        docAcc->RemoveAccessNodeFromCache(accessible);
+      }
 
-      if (accessNode) {
-        nsCOMPtr<nsIAccessible> accessible(do_QueryInterface(accessNode));
-        nsCOMPtr<nsIAccessibleEvent> event =
-          new nsAccEvent(nsIAccessibleEvent::EVENT_DOM_DESTROY,
-                         accessible, PR_FALSE);
-        FireAccessibleEvent(event);
-
-        mAccessNodeCache->Remove(key);
-      }
+      mAccessNodeCache.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.
   PRInt32 newRowCount = 0;
-  rv = mTreeView->GetRowCount(&newRowCount);
+  nsresult rv = mTreeView->GetRowCount(&newRowCount);
   if (NS_FAILED(rv))
     return;
 
   PRInt32 oldRowCount = newRowCount - aCount;
 
   for (PRInt32 rowIdx = newRowCount; rowIdx < oldRowCount; ++rowIdx) {
-#ifdef MOZ_ACCESSIBILITY_ATK
-    for (PRInt32 colIdx = 0; colIdx < colsCount; ++colIdx) {
-#else
-    {
-#endif
-      void *key = reinterpret_cast<void*>(rowIdx * kMaxTreeColumns + colIdx);
-      mAccessNodeCache->Remove(key);
+    void *key = reinterpret_cast<void*>(rowIdx);
+
+    nsCOMPtr<nsIAccessNode> accessNode;
+    GetCacheEntry(mAccessNodeCache, key, getter_AddRefs(accessNode));
+
+    if (accessNode) {
+      nsRefPtr<nsAccessNode> accNode =
+        nsAccUtils::QueryAccessNode(accessNode);
+
+      accNode->Shutdown();
+
+      // Remove accessible from document cache and tree cache.
+      nsCOMPtr<nsIAccessibleDocument> docAccessible = GetDocAccessible();
+      if (docAccessible) {
+        nsRefPtr<nsDocAccessible> docAcc =
+          nsAccUtils::QueryAccessibleDocument(docAccessible);
+        docAcc->RemoveAccessNodeFromCache(accNode);
+      }
+
+      mAccessNodeCache.Remove(key);
     }
   }
 }
 
 void
 nsXULTreeAccessible::TreeViewInvalidated(PRInt32 aStartRow, PRInt32 aEndRow,
                                          PRInt32 aStartCol, PRInt32 aEndCol)
 {
@@ -670,65 +664,39 @@ nsXULTreeAccessible::TreeViewInvalidated
     endRow = rowCount - 1;
   }
 
   nsCOMPtr<nsITreeColumns> treeColumns;
   mTree->GetColumns(getter_AddRefs(treeColumns));
   if (!treeColumns)
     return;
 
-#ifdef MOZ_ACCESSIBILITY_ATK
   PRInt32 endCol = aEndCol;
 
   if (endCol == -1) {
     PRInt32 colCount = 0;
     rv = treeColumns->GetCount(&colCount);
     if (NS_FAILED(rv))
       return;
 
     endCol = colCount - 1;
   }
-#else
-  nsCOMPtr<nsITreeColumn> col;
-  rv = treeColumns->GetKeyColumn(getter_AddRefs(col));
-  if (!col)
-    return;
-
-  PRInt32 colIdx = 0;
-  rv = col->GetIndex(&colIdx);
-  if (NS_FAILED(rv))
-    return;
-
-#endif
 
   for (PRInt32 rowIdx = aStartRow; rowIdx <= endRow; ++rowIdx) {
-#ifdef MOZ_ACCESSIBILITY_ATK
-    for (PRInt32 colIdx = aStartCol; colIdx <= endCol; ++colIdx)
-#endif
-    {
-      void *key = reinterpret_cast<void*>(rowIdx * kMaxTreeColumns + colIdx);
+    void *key = reinterpret_cast<void*>(rowIdx);
 
-      nsCOMPtr<nsIAccessNode> accessNode;
-      GetCacheEntry(*mAccessNodeCache, key, getter_AddRefs(accessNode));
+    nsCOMPtr<nsIAccessNode> accessNode;
+    GetCacheEntry(mAccessNodeCache, key, getter_AddRefs(accessNode));
 
-      if (accessNode) {
-        nsRefPtr<nsXULTreeitemAccessible> treeitemAcc(
-          nsAccUtils::QueryAccessibleTreeitem(accessNode));
-        NS_ASSERTION(treeitemAcc, "Wrong accessible at the given key!");
-
-        nsAutoString name, cachedName;
-        treeitemAcc->GetName(name);
+    if (accessNode) {
+      nsRefPtr<nsXULTreeItemAccessibleBase> treeitemAcc =
+        nsAccUtils::QueryObject<nsXULTreeItemAccessibleBase>(accessNode);
+      NS_ASSERTION(treeitemAcc, "Wrong accessible at the given key!");
 
-        treeitemAcc->GetCachedName(cachedName);
-        if (name != cachedName) {
-          nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE,
-                                   treeitemAcc);
-          treeitemAcc->SetCachedName(name);
-        }
-      }
+      treeitemAcc->RowInvalidated(aStartCol, endCol);
     }
   }
 }
 
 void
 nsXULTreeAccessible::TreeViewChanged()
 {
   if (IsDefunct())
@@ -740,627 +708,672 @@ nsXULTreeAccessible::TreeViewChanged()
   nsCOMPtr<nsIAccessibleEvent> eventDestroy =
     new nsAccEvent(nsIAccessibleEvent::EVENT_DOM_DESTROY,
                    this, PR_FALSE);
   if (!eventDestroy)
     return;
 
   FirePlatformEvent(eventDestroy);
 
-  ClearCache(*mAccessNodeCache);
+  ClearCache(mAccessNodeCache);
 
   mTree->GetView(getter_AddRefs(mTreeView));
 
   nsCOMPtr<nsIAccessibleEvent> eventCreate =
     new nsAccEvent(nsIAccessibleEvent::EVENT_DOM_CREATE,
                    this, PR_FALSE);
   if (!eventCreate)
     return;
 
   FirePlatformEvent(eventCreate);
 }
 
-nsresult nsXULTreeAccessible::GetColumnCount(nsITreeBoxObject* aBoxObject, PRInt32* aCount)
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeAccessible: protected implementation
+
+void
+nsXULTreeAccessible::CreateTreeItemAccessible(PRInt32 aRow,
+                                              nsAccessNode** aAccessNode)
 {
-  NS_ENSURE_TRUE(aBoxObject, NS_ERROR_FAILURE);
-  nsCOMPtr<nsITreeColumns> treeColumns;
-  aBoxObject->GetColumns(getter_AddRefs(treeColumns));
-  NS_ENSURE_TRUE(treeColumns, NS_ERROR_FAILURE);
-  return treeColumns->GetCount(aCount);
+  *aAccessNode = new nsXULTreeItemAccessible(mDOMNode, mWeakShell, this,
+                                             mTree, mTreeView, aRow);
+  NS_IF_ADDREF(*aAccessNode);
+}
+                             
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeItemAccessibleBase
+////////////////////////////////////////////////////////////////////////////////
+
+nsXULTreeItemAccessibleBase::
+  nsXULTreeItemAccessibleBase(nsIDOMNode *aDOMNode, nsIWeakReference *aShell,
+                              nsIAccessible *aParent, nsITreeBoxObject *aTree,
+                              nsITreeView *aTreeView, PRInt32 aRow) :
+  mTree(aTree), mTreeView(aTreeView), mRow(aRow),
+  nsAccessibleWrap(aDOMNode, aShell)
+{
+  mParent = aParent;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsXULTreeitemAccessible
-
-nsXULTreeitemAccessible::nsXULTreeitemAccessible(nsIAccessible *aParent, nsIDOMNode *aDOMNode, nsIWeakReference *aShell, PRInt32 aRow, nsITreeColumn* aColumn)
-  : nsLeafAccessible(aDOMNode, aShell)
-{
-  mParent = aParent;  // xxx todo: do we need this? We already have mParent on nsAccessible
-
-  nsXULTreeAccessible::GetTreeBoxObject(aDOMNode, getter_AddRefs(mTree));
-  if (mTree)
-    mTree->GetView(getter_AddRefs(mTreeView));
-  NS_ASSERTION(mTree && mTreeView, "Can't get mTree or mTreeView!\n");
-
-  // Since the real tree item does not correspond to any DOMNode, use the row index to distinguish each item
-  mRow = aRow;
-  mColumn = aColumn;
+// nsXULTreeItemAccessibleBase: nsISupports implementation
 
-  if (!mColumn && mTree) {
-    nsCOMPtr<nsITreeColumns> cols;
-    mTree->GetColumns(getter_AddRefs(cols));
-    if (cols)
-      cols->GetKeyColumn(getter_AddRefs(mColumn));
-  }
-}
-
-NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeitemAccessible,
-                             nsLeafAccessible,
-                             nsXULTreeitemAccessible)
+NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeItemAccessibleBase,
+                             nsAccessible,
+                             nsXULTreeItemAccessibleBase)
 
-// nsAccessNode
- 
-nsresult
-nsXULTreeitemAccessible::Shutdown()
-{
-  mTree = nsnull;
-  mTreeView = nsnull;
-  mColumn = nsnull;
-  return nsLeafAccessible::Shutdown();
-}
-
-// nsIAccessible
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeItemAccessibleBase: nsIAccessNode implementation
 
 NS_IMETHODIMP
-nsXULTreeitemAccessible::GetName(nsAString& aName)
+nsXULTreeItemAccessibleBase::GetUniqueID(void **aUniqueID)
 {
-  // XXX: we should take into account ARIA usage for content tree. 
-  aName.Truncate();
-
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  mTreeView->GetCellText(mRow, mColumn, aName);
-  
-  // If there is still no name try the cell value:
-  // This is for graphical cells. We need tree/table view implementors to implement
-  // FooView::GetCellValue to return a meaningful string for cases where there is
-  // something shown in the cell (non-text) such as a star icon; in which case
-  // GetCellValue for that cell would return "starred" or "flagged" for example.
-  if (aName.IsEmpty()) {
-    mTreeView->GetCellValue(mRow, mColumn, aName);
-  }
-  
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsXULTreeitemAccessible::GetUniqueID(void **aUniqueID)
-{
-  // Since mDOMNode is same for all tree item, use |this| pointer as the unique Id
+  // Since mDOMNode is same for all tree items and tree itself, use |this|
+  // pointer as the unique ID.
   *aUniqueID = static_cast<void*>(this);
   return NS_OK;
 }
 
-// nsAccessNode::Init()
-nsresult
-nsXULTreeitemAccessible::Init()
-{
-  nsresult rv = nsLeafAccessible::Init();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return GetName(mCachedName);
-}
-
-nsresult
-nsXULTreeitemAccessible::GetRoleInternal(PRUint32 *aRole)
-{
-  PRInt32 colCount = 0;
-  if (NS_SUCCEEDED(nsXULTreeAccessible::GetColumnCount(mTree, &colCount)) && colCount > 1)
-    *aRole = nsIAccessibleRole::ROLE_CELL;
-  else
-    *aRole = nsIAccessibleRole::ROLE_OUTLINEITEM;
-  return NS_OK;
-}
-
-// Possible states: focused, focusable, selected, checkable, checked, 
-// expanded/collapsed, invisible
-nsresult
-nsXULTreeitemAccessible::GetStateInternal(PRUint32 *aState,
-                                          PRUint32 *aExtraState)
-{
-  NS_ENSURE_ARG_POINTER(aState);
-
-  *aState = 0;
-  if (aExtraState)
-    *aExtraState = 0;
-
-  if (IsDefunct()) {
-    if (aExtraState)
-      *aExtraState = nsIAccessibleStates::EXT_STATE_DEFUNCT;
-    return NS_OK_DEFUNCT_OBJECT;
-  }
-
-  *aState = nsIAccessibleStates::STATE_FOCUSABLE |
-            nsIAccessibleStates::STATE_SELECTABLE;
-
-  // get expanded/collapsed state
-  if (IsExpandable()) {
-    PRBool isContainerOpen;
-    mTreeView->IsContainerOpen(mRow, &isContainerOpen);
-    *aState |= isContainerOpen? PRUint32(nsIAccessibleStates::STATE_EXPANDED):
-                                PRUint32(nsIAccessibleStates::STATE_COLLAPSED);
-  }
-
-  // get selected state
-  nsCOMPtr<nsITreeSelection> selection;
-  mTreeView->GetSelection(getter_AddRefs(selection));
-  if (selection) {
-    PRBool isSelected;
-    selection->IsSelected(mRow, &isSelected);
-    if (isSelected)
-      *aState |= nsIAccessibleStates::STATE_SELECTED;
-  }
-
-  nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelect =
-    do_QueryInterface(mDOMNode);
-  if (multiSelect) {
-    PRInt32 currentIndex;
-    multiSelect->GetCurrentIndex(&currentIndex);
-    if (currentIndex == mRow) {
-      *aState |= nsIAccessibleStates::STATE_FOCUSED;
-    }
-  }
-
-  PRInt32 firstVisibleRow, lastVisibleRow;
-  mTree->GetFirstVisibleRow(&firstVisibleRow);
-  mTree->GetLastVisibleRow(&lastVisibleRow);
-  if (mRow < firstVisibleRow || mRow > lastVisibleRow)
-    *aState |= nsIAccessibleStates::STATE_INVISIBLE;
-
-
-  PRInt16 type;
-  mColumn->GetType(&type);
-  if (type == nsITreeColumn::TYPE_CHECKBOX) {
-    *aState |= nsIAccessibleStates::STATE_CHECKABLE;
-    nsAutoString checked;
-    mTreeView->GetCellValue(mRow, mColumn, checked);
-    if (checked.EqualsIgnoreCase("true")) {
-      *aState |= nsIAccessibleStates::STATE_CHECKED;
-    }
-  }
-
-  return NS_OK;
-}
-
-PRBool
-nsXULTreeitemAccessible::IsDefunct()
-{
-  if (!mTree || !mTreeView || !mColumn || mRow < 0)
-    return PR_TRUE;
-
-  PRInt32 rowCount = 0;
-  nsresult rv = mTreeView->GetRowCount(&rowCount);
-  if (NS_FAILED(rv) || mRow >= rowCount)
-    return PR_TRUE;
-
-  // Call GetPresShell() since the accessible may be shut down in it.
-  nsCOMPtr<nsIPresShell> presShell(GetPresShell());
-  return !presShell;
-}
-
-PRBool nsXULTreeitemAccessible::IsExpandable()
-{
-  if (IsDefunct())
-    return PR_FALSE;
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeItemAccessibleBase: nsIAccessible implementation
 
-  PRBool isContainer;
-  mTreeView->IsContainer(mRow, &isContainer);
-  if (isContainer) {
-    PRBool isEmpty; 
-    mTreeView->IsContainerEmpty(mRow, &isEmpty);
-    if (!isEmpty) {
-      PRBool isPrimary;
-      mColumn->GetPrimary(&isPrimary);
-      if (isPrimary) {
-        return PR_TRUE;
-      }
-    }
-  }
-  return PR_FALSE;
-}
-
-// "activate" (xor "cycle") action is available for all treeitems
-// "expand/collapse" action is avaible for treeitem which is container
-NS_IMETHODIMP nsXULTreeitemAccessible::GetNumActions(PRUint8 *aNumActions)
-{
-  NS_ENSURE_ARG_POINTER(aNumActions);
-  *aNumActions = 0;
-
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  *aNumActions = IsExpandable() ? 2 : 1;
-  return NS_OK;
-}
-
-// Return the name of our actions
-NS_IMETHODIMP nsXULTreeitemAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
-{
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  if (aIndex == eAction_Click) {
-    PRBool isCycler;
-    mColumn->GetCycler(&isCycler);
-    if (isCycler) {
-      aName.AssignLiteral("cycle");
-    }
-    else {
-      aName.AssignLiteral("activate");
-    }
-    return NS_OK;
-  }
-  else if (aIndex == eAction_Expand && IsExpandable()) {
-    PRBool isContainerOpen;
-    mTreeView->IsContainerOpen(mRow, &isContainerOpen);
-    if (isContainerOpen)
-      aName.AssignLiteral("collapse");
-    else
-      aName.AssignLiteral("expand");
-    return NS_OK;
-  }
-
-  return NS_ERROR_INVALID_ARG;
-}
-
-nsresult
-nsXULTreeitemAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
-{
-  NS_ENSURE_ARG_POINTER(aAttributes);
-
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  nsresult rv = nsLeafAccessible::GetAttributesInternal(aAttributes);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIDOMXULTreeElement> tree(do_QueryInterface(mDOMNode));
-  NS_ENSURE_TRUE(tree, NS_OK);
-
-  nsCOMPtr<nsITreeView> view;
-  tree->GetView(getter_AddRefs(view));
-  NS_ENSURE_TRUE(view, NS_OK);
-
-  PRInt32 level;
-  rv = view->GetLevel(mRow, &level);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  PRInt32 topCount = 1;
-  for (PRInt32 index = mRow - 1; index >= 0; index--) {
-    PRInt32 lvl = -1;
-    if (NS_SUCCEEDED(view->GetLevel(index, &lvl))) {
-      if (lvl < level)
-        break;
-
-      if (lvl == level)
-        topCount++;
-    }
-  }
-
-  PRInt32 rowCount = 0;
-  rv = view->GetRowCount(&rowCount);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  PRInt32 bottomCount = 0;
-  for (PRInt32 index = mRow + 1; index < rowCount; index++) {
-    PRInt32 lvl = -1;
-    if (NS_SUCCEEDED(view->GetLevel(index, &lvl))) {
-      if (lvl < level)
-        break;
-
-      if (lvl == level)
-        bottomCount++;
-    }
-  }
-
-  PRInt32 setSize = topCount + bottomCount;
-  PRInt32 posInSet = topCount;
-
-  // set the group attributes
-  nsAccUtils::SetAccGroupAttrs(aAttributes, level + 1, posInSet, setSize);
-
-  // set the "cycles" attribute
-  PRBool isCycler;
-  mColumn->GetCycler(&isCycler);
-  if (isCycler) {
-    nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::cycles,
-                           NS_LITERAL_STRING("true"));
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsXULTreeitemAccessible::GetParent(nsIAccessible **aParent)
+NS_IMETHODIMP
+nsXULTreeItemAccessibleBase::GetParent(nsIAccessible **aParent)
 {
   NS_ENSURE_ARG_POINTER(aParent);
   *aParent = nsnull;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   if (mParent) {
     *aParent = mParent;
     NS_ADDREF(*aParent);
   }
 
   return NS_OK;
 }
 
-// Return the next row of tree if mColumn (if any),
-// otherwise return the next cell.
-NS_IMETHODIMP nsXULTreeitemAccessible::GetNextSibling(nsIAccessible **aNextSibling)
+NS_IMETHODIMP
+nsXULTreeItemAccessibleBase::GetNextSibling(nsIAccessible **aNextSibling)
 {
   NS_ENSURE_ARG_POINTER(aNextSibling);
   *aNextSibling = nsnull;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  nsRefPtr<nsXULTreeAccessible> treeCache =
+  nsRefPtr<nsXULTreeAccessible> treeAcc =
     nsAccUtils::QueryAccessibleTree(mParent);
-  NS_ENSURE_TRUE(treeCache, NS_ERROR_FAILURE);
-
-  PRInt32 rowCount;
-  mTreeView->GetRowCount(&rowCount);
-
-  if (!mColumn) {
-    if (mRow < rowCount - 1)
-      treeCache->GetCachedTreeitemAccessible(mRow + 1, nsnull, aNextSibling);
-
-    return NS_OK;
-  }
+  NS_ENSURE_STATE(treeAcc);
 
-  PRInt32 row = mRow;
-  nsCOMPtr<nsITreeColumn> column;
-#ifdef MOZ_ACCESSIBILITY_ATK
-  column = nsXULTreeAccessible::GetNextVisibleColumn(mColumn);
+  PRInt32 rowsCount = 0;
+  mTreeView->GetRowCount(&rowsCount);
+  if (mRow + 1 >= rowsCount)
+    return NS_OK;
 
-  if (!column) {
-    if (mRow < rowCount -1) {
-      row++;
-      column = nsXULTreeAccessible::GetFirstVisibleColumn(mTree);
-    } else {
-      // the next sibling of the last treeitem is null
-      return NS_OK;
-    }
-  }
-#else
-  if (++row >= rowCount) {
-    return NS_ERROR_FAILURE;
-  }
-#endif //MOZ_ACCESSIBILITY_ATK
-
-  treeCache->GetCachedTreeitemAccessible(row, column, aNextSibling);
+  treeAcc->GetTreeItemAccessible(mRow + 1, aNextSibling);
   return NS_OK;
 }
 
-// Return the previous row of tree if mColumn (if any),
-// otherwise return the previous cell.
-NS_IMETHODIMP nsXULTreeitemAccessible::GetPreviousSibling(nsIAccessible **aPreviousSibling)
+NS_IMETHODIMP
+nsXULTreeItemAccessibleBase::GetPreviousSibling(nsIAccessible **aPreviousSibling)
 {
   NS_ENSURE_ARG_POINTER(aPreviousSibling);
   *aPreviousSibling = nsnull;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  nsRefPtr<nsXULTreeAccessible> treeCache =
+  nsRefPtr<nsXULTreeAccessible> treeAcc =
     nsAccUtils::QueryAccessibleTree(mParent);
-  NS_ENSURE_TRUE(treeCache, NS_ERROR_FAILURE);
-
-  if (!mColumn && mRow > 0)
-    treeCache->GetCachedTreeitemAccessible(mRow - 1, nsnull, aPreviousSibling);
-
-  nsresult rv = NS_OK;
-
+  NS_ENSURE_STATE(treeAcc);
 
-  PRInt32 row = mRow;
-  nsCOMPtr<nsITreeColumn> column;
-#ifdef MOZ_ACCESSIBILITY_ATK
-  rv = mColumn->GetPrevious(getter_AddRefs(column));
-  NS_ENSURE_SUCCESS(rv, rv);
-  
-  if (!column && mRow > 0) {
-    row--;
-    column = nsXULTreeAccessible::GetLastVisibleColumn(mTree);
-  }
-#else
-  if (--row < 0) {
-    return NS_ERROR_FAILURE;
-  }
-#endif
+  // Get previous row accessible or tree columns accessible.
+  if (mRow > 0)
+    treeAcc->GetTreeItemAccessible(mRow - 1, aPreviousSibling);
+  else
+    treeAcc->GetFirstChild(aPreviousSibling);
 
-  treeCache->GetCachedTreeitemAccessible(row, column, aPreviousSibling);
   return NS_OK;
 }
 
-NS_IMETHODIMP nsXULTreeitemAccessible::DoAction(PRUint8 index)
+NS_IMETHODIMP
+nsXULTreeItemAccessibleBase::GetFocusedChild(nsIAccessible **aFocusedChild) 
 {
+  NS_ENSURE_ARG_POINTER(aFocusedChild);
+  *aFocusedChild = nsnull;
+
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  if (index == eAction_Click) {
-    nsresult rv = NS_OK;
-    PRBool isCycler;
-    mColumn->GetCycler(&isCycler);
-    if (isCycler) {
-      rv = mTreeView->CycleCell(mRow, mColumn);
-    } 
-    else {
-      nsCOMPtr<nsITreeSelection> selection;
-      mTreeView->GetSelection(getter_AddRefs(selection));
-      if (selection) {
-        rv = selection->Select(mRow);
-        mTree->EnsureRowIsVisible(mRow);
-      }
-    }
-    return rv;
-  }
-  else if (index == eAction_Expand && IsExpandable()) {
-    return mTreeView->ToggleOpenState(mRow);
+  if (gLastFocusedNode != mDOMNode)
+    return NS_OK;
+
+  nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelect =
+    do_QueryInterface(mDOMNode);
+
+  if (multiSelect) {
+    PRInt32 row = -1;
+    multiSelect->GetCurrentIndex(&row);
+    if (row == mRow)
+      NS_ADDREF(*aFocusedChild = this);
   }
 
-  return NS_ERROR_INVALID_ARG;
+  return NS_OK;
 }
 
 NS_IMETHODIMP
-nsXULTreeitemAccessible::GetBounds(PRInt32 *aX, PRInt32 *aY,
-                                   PRInt32 *aWidth, PRInt32 *aHeight)
+nsXULTreeItemAccessibleBase::GetBounds(PRInt32 *aX, PRInt32 *aY,
+                                       PRInt32 *aWidth, PRInt32 *aHeight)
 {
   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;
 
-  // Get bounds for tree cell and add x and y of treechildren element to
-  // x and y of the cell.
+  // Get x coordinate and width from treechildren element, get y coordinate and
+  // height from tree cell.
 
   nsCOMPtr<nsIBoxObject> boxObj = nsCoreUtils::GetTreeBodyBoxObject(mTree);
   NS_ENSURE_STATE(boxObj);
 
-  nsresult rv = mTree->GetCoordsForCellItem(mRow, mColumn, EmptyCString(),
-                                            aX, aY, aWidth, aHeight);
+  nsCOMPtr<nsITreeColumn> column = nsCoreUtils::GetFirstSensibleColumn(mTree);
+
+  PRInt32 x = 0, y = 0, width = 0, height = 0;
+  nsresult rv = mTree->GetCoordsForCellItem(mRow, column, EmptyCString(),
+                                            &x, &y, &width, &height);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  boxObj->GetWidth(&width);
+
   PRInt32 tcX = 0, tcY = 0;
   boxObj->GetScreenX(&tcX);
   boxObj->GetScreenY(&tcY);
-  *aX += tcX;
-  *aY += tcY;
+
+  x = tcX;
+  y += tcY;
+
+  nsPresContext *presContext = GetPresContext();
+  *aX = presContext->CSSPixelsToDevPixels(x);
+  *aY = presContext->CSSPixelsToDevPixels(y);
+  *aWidth = presContext->CSSPixelsToDevPixels(width);
+  *aHeight = presContext->CSSPixelsToDevPixels(height);
 
   return NS_OK;
 }
 
-NS_IMETHODIMP nsXULTreeitemAccessible::SetSelected(PRBool aSelect)
+NS_IMETHODIMP
+nsXULTreeItemAccessibleBase::SetSelected(PRBool aSelect)
 {
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsITreeSelection> selection;
   mTreeView->GetSelection(getter_AddRefs(selection));
   if (selection) {
     PRBool isSelected;
     selection->IsSelected(mRow, &isSelected);
     if (isSelected != aSelect)
       selection->ToggleSelect(mRow);
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP nsXULTreeitemAccessible::TakeFocus()
+NS_IMETHODIMP
+nsXULTreeItemAccessibleBase::TakeFocus()
 {
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsITreeSelection> selection;
   mTreeView->GetSelection(getter_AddRefs(selection));
   if (selection)
     selection->SetCurrentIndex(mRow);
 
   // focus event will be fired here
   return nsAccessible::TakeFocus();
 }
 
 NS_IMETHODIMP
-nsXULTreeitemAccessible::GetRelationByType(PRUint32 aRelationType,
-                                           nsIAccessibleRelation **aRelation)
+nsXULTreeItemAccessibleBase::GetRelationByType(PRUint32 aRelationType,
+                                               nsIAccessibleRelation **aRelation)
 {
   NS_ENSURE_ARG_POINTER(aRelation);
   *aRelation = nsnull;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   if (aRelationType == nsIAccessibleRelation::RELATION_NODE_CHILD_OF) {
-    PRInt32 columnIndex;
-    if (NS_SUCCEEDED(mColumn->GetIndex(&columnIndex)) && columnIndex == 0) {
-      PRInt32 parentIndex;
-      if (NS_SUCCEEDED(mTreeView->GetParentIndex(mRow, &parentIndex))) {
-        if (parentIndex == -1)
-          return nsRelUtils::AddTarget(aRelationType, aRelation, mParent);
-  
-        nsRefPtr<nsXULTreeAccessible> treeCache =
-          nsAccUtils::QueryAccessibleTree(mParent);
+    PRInt32 parentIndex;
+    if (NS_SUCCEEDED(mTreeView->GetParentIndex(mRow, &parentIndex))) {
+      if (parentIndex == -1)
+        return nsRelUtils::AddTarget(aRelationType, aRelation, mParent);
 
-        nsCOMPtr<nsIAccessible> accParent;
-        treeCache->GetCachedTreeitemAccessible(parentIndex, mColumn,
-                                               getter_AddRefs(accParent));
+      nsRefPtr<nsXULTreeAccessible> treeAcc =
+        nsAccUtils::QueryAccessibleTree(mParent);
 
-        return nsRelUtils::AddTarget(aRelationType, aRelation, accParent);
-      }
+      nsCOMPtr<nsIAccessible> logicalParent;
+      treeAcc->GetTreeItemAccessible(parentIndex, getter_AddRefs(logicalParent));
+      return nsRelUtils::AddTarget(aRelationType, aRelation, logicalParent);
     }
 
     return NS_OK;
   }
 
   return nsAccessible::GetRelationByType(aRelationType, aRelation);
 }
 
-// nsXULTreeitemAccessible
-void
-nsXULTreeitemAccessible::GetCachedName(nsAString &aName)
+NS_IMETHODIMP
+nsXULTreeItemAccessibleBase::GetNumActions(PRUint8 *aActionsCount)
 {
-  aName = mCachedName;
+  NS_ENSURE_ARG_POINTER(aActionsCount);
+  *aActionsCount = 0;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  // "activate" action is available for all treeitems, "expand/collapse" action
+  // is avaible for treeitem which is container.
+  *aActionsCount = IsExpandable() ? 2 : 1;
+  return NS_OK;
 }
 
-void
-nsXULTreeitemAccessible::SetCachedName(const nsAString &aName)
+NS_IMETHODIMP
+nsXULTreeItemAccessibleBase::GetActionName(PRUint8 aIndex, nsAString& aName)
+{
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  if (aIndex == eAction_Click) {
+    aName.AssignLiteral("activate");
+    return NS_OK;
+  }
+
+  if (aIndex == eAction_Expand && IsExpandable()) {
+    PRBool isContainerOpen;
+    mTreeView->IsContainerOpen(mRow, &isContainerOpen);
+    if (isContainerOpen)
+      aName.AssignLiteral("collapse");
+    else
+      aName.AssignLiteral("expand");
+
+    return NS_OK;
+  }
+
+  return NS_ERROR_INVALID_ARG;
+}
+
+NS_IMETHODIMP
+nsXULTreeItemAccessibleBase::DoAction(PRUint8 aIndex)
 {
-  mCachedName = aName;
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  if (aIndex != eAction_Click &&
+      (aIndex != eAction_Expand || !IsExpandable()))
+    return NS_ERROR_INVALID_ARG;
+
+  return DoCommand(nsnull, aIndex);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeItemAccessibleBase: nsAccessNode implementation
+
+PRBool
+nsXULTreeItemAccessibleBase::IsDefunct()
+{
+  if (nsAccessibleWrap::IsDefunct() || !mTree || !mTreeView || mRow < 0)
+    return PR_TRUE;
+
+  PRInt32 rowCount = 0;
+  nsresult rv = mTreeView->GetRowCount(&rowCount);
+  return NS_FAILED(rv) || mRow >= rowCount;
+}
+
+nsresult
+nsXULTreeItemAccessibleBase::Shutdown()
+{
+  mTree = nsnull;
+  mTreeView = nsnull;
+  mRow = -1;
+
+  return nsAccessibleWrap::Shutdown();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeItemAccessibleBase: nsAccessible implementation
+
+nsresult
+nsXULTreeItemAccessibleBase::GetAttributesInternal(nsIPersistentProperties *aAttributes)
+{
+  NS_ENSURE_ARG_POINTER(aAttributes);
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  PRInt32 level;
+  nsresult rv = mTreeView->GetLevel(mRow, &level);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRInt32 topCount = 1;
+  for (PRInt32 index = mRow - 1; index >= 0; index--) {
+    PRInt32 lvl = -1;
+    if (NS_SUCCEEDED(mTreeView->GetLevel(index, &lvl))) {
+      if (lvl < level)
+        break;
+
+      if (lvl == level)
+        topCount++;
+    }
+  }
+
+  PRInt32 rowCount = 0;
+  rv = mTreeView->GetRowCount(&rowCount);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRInt32 bottomCount = 0;
+  for (PRInt32 index = mRow + 1; index < rowCount; index++) {
+    PRInt32 lvl = -1;
+    if (NS_SUCCEEDED(mTreeView->GetLevel(index, &lvl))) {
+      if (lvl < level)
+        break;
+
+      if (lvl == level)
+        bottomCount++;
+    }
+  }
+
+  PRInt32 setSize = topCount + bottomCount;
+  PRInt32 posInSet = topCount;
+
+  // set the group attributes
+  nsAccUtils::SetAccGroupAttrs(aAttributes, level + 1, posInSet, setSize);
+  return NS_OK;
+}
+
+nsresult
+nsXULTreeItemAccessibleBase::GetStateInternal(PRUint32 *aState,
+                                              PRUint32 *aExtraState)
+{
+  NS_ENSURE_ARG_POINTER(aState);
+
+  *aState = 0;
+  if (aExtraState)
+    *aExtraState = 0;
+
+  if (IsDefunct()) {
+    if (aExtraState)
+      *aExtraState = nsIAccessibleStates::EXT_STATE_DEFUNCT;
+    return NS_OK_DEFUNCT_OBJECT;
+  }
+
+  // focusable and selectable states
+  *aState = nsIAccessibleStates::STATE_FOCUSABLE |
+    nsIAccessibleStates::STATE_SELECTABLE;
+
+  // expanded/collapsed state
+  if (IsExpandable()) {
+    PRBool isContainerOpen;
+    mTreeView->IsContainerOpen(mRow, &isContainerOpen);
+    *aState |= isContainerOpen ?
+      nsIAccessibleStates::STATE_EXPANDED:
+      nsIAccessibleStates::STATE_COLLAPSED;
+  }
+
+  // selected state
+  nsCOMPtr<nsITreeSelection> selection;
+  mTreeView->GetSelection(getter_AddRefs(selection));
+  if (selection) {
+    PRBool isSelected;
+    selection->IsSelected(mRow, &isSelected);
+    if (isSelected)
+      *aState |= nsIAccessibleStates::STATE_SELECTED;
+  }
+
+  // focused state
+  nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelect =
+  do_QueryInterface(mDOMNode);
+  if (multiSelect) {
+    PRInt32 currentIndex;
+    multiSelect->GetCurrentIndex(&currentIndex);
+    if (currentIndex == mRow) {
+      *aState |= nsIAccessibleStates::STATE_FOCUSED;
+    }
+  }
+
+  // invisible state
+  PRInt32 firstVisibleRow, lastVisibleRow;
+  mTree->GetFirstVisibleRow(&firstVisibleRow);
+  mTree->GetLastVisibleRow(&lastVisibleRow);
+  if (mRow < firstVisibleRow || mRow > lastVisibleRow)
+    *aState |= nsIAccessibleStates::STATE_INVISIBLE;
+
+  return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeItemAccessibleBase: protected implementation
+
+void
+nsXULTreeItemAccessibleBase::DispatchClickEvent(nsIContent *aContent,
+                                                PRUint32 aActionIndex)
+{
+  if (IsDefunct())
+    return;
+
+  nsCOMPtr<nsITreeColumns> columns;
+  mTree->GetColumns(getter_AddRefs(columns));
+  if (!columns)
+    return;
+
+  // Get column and pseudo element.
+  nsCOMPtr<nsITreeColumn> column;
+  nsCAutoString pseudoElm;
+
+  if (aActionIndex == eAction_Click) {
+    // Key column is visible and clickable.
+    columns->GetKeyColumn(getter_AddRefs(column));
+  } else {
+    // Primary column contains a twisty we should click on.
+    columns->GetPrimaryColumn(getter_AddRefs(column));
+    pseudoElm = NS_LITERAL_CSTRING("twisty");
+  }
+
+  if (column)
+    nsCoreUtils::DispatchClickEvent(mTree, mRow, column, pseudoElm);
+}
+
+PRBool
+nsXULTreeItemAccessibleBase::IsExpandable()
+{
+  PRBool isContainer = PR_FALSE;
+  mTreeView->IsContainer(mRow, &isContainer);
+  if (isContainer) {
+    PRBool isEmpty = PR_FALSE;
+    mTreeView->IsContainerEmpty(mRow, &isEmpty);
+    if (!isEmpty) {
+      nsCOMPtr<nsITreeColumns> columns;
+      mTree->GetColumns(getter_AddRefs(columns));
+      nsCOMPtr<nsITreeColumn> primaryColumn;
+      if (columns) {
+        columns->GetPrimaryColumn(getter_AddRefs(primaryColumn));
+        if (!nsCoreUtils::IsColumnHidden(primaryColumn))
+          return PR_TRUE;
+      }
+    }
+  }
+
+  return PR_FALSE;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeItemAccessible
+////////////////////////////////////////////////////////////////////////////////
+
+nsXULTreeItemAccessible::
+nsXULTreeItemAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell,
+                        nsIAccessible *aParent, nsITreeBoxObject *aTree,
+                        nsITreeView *aTreeView, PRInt32 aRow) :
+  nsXULTreeItemAccessibleBase(aDOMNode, aShell, aParent, aTree, aTreeView, aRow)
+{
+  mColumn = nsCoreUtils::GetFirstSensibleColumn(mTree);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeItemAccessible: nsIAccessible implementation
+
+NS_IMETHODIMP
+nsXULTreeItemAccessible::GetFirstChild(nsIAccessible **aFirstChild)
+{
+  NS_ENSURE_ARG_POINTER(aFirstChild);
+  *aFirstChild = nsnull;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeItemAccessible::GetLastChild(nsIAccessible **aLastChild)
+{
+  NS_ENSURE_ARG_POINTER(aLastChild);
+  *aLastChild = nsnull;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeItemAccessible::GetChildCount(PRInt32 *aChildCount)
+{
+  NS_ENSURE_ARG_POINTER(aChildCount);
+  *aChildCount = 0;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeItemAccessible::GetName(nsAString& aName)
+{
+  aName.Truncate();
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  mTreeView->GetCellText(mRow, mColumn, aName);
+
+  // If there is still no name try the cell value:
+  // This is for graphical cells. We need tree/table view implementors to implement
+  // FooView::GetCellValue to return a meaningful string for cases where there is
+  // something shown in the cell (non-text) such as a star icon; in which case
+  // GetCellValue for that cell would return "starred" or "flagged" for example.
+  if (aName.IsEmpty())
+    mTreeView->GetCellValue(mRow, mColumn, aName);
+
+  return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeItemAccessible: nsAccessNode implementation
+
+PRBool
+nsXULTreeItemAccessible::IsDefunct()
+{
+  return nsXULTreeItemAccessibleBase::IsDefunct() || !mColumn;
+}
+
+nsresult
+nsXULTreeItemAccessible::Init()
+{
+  nsresult rv = nsXULTreeItemAccessibleBase::Init();
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return GetName(mCachedName);
+}
+
+nsresult
+nsXULTreeItemAccessible::Shutdown()
+{
+  mColumn = nsnull;
+  return nsXULTreeItemAccessibleBase::Shutdown();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeItemAccessible: nsAccessible implementation
+
+nsresult
+nsXULTreeItemAccessible::GetRoleInternal(PRUint32 *aRole)
+{
+  nsCOMPtr<nsITreeColumn> column =
+    nsCoreUtils::GetFirstSensibleColumn(mTree);
+
+  PRBool isPrimary = PR_FALSE;
+  column->GetPrimary(&isPrimary);
+
+  *aRole = isPrimary ?
+    nsIAccessibleRole::ROLE_OUTLINEITEM :
+    nsIAccessibleRole::ROLE_LISTITEM;
+
+  return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeItemAccessible: nsXULTreeItemAccessibleBase implementation
+
+void
+nsXULTreeItemAccessible::RowInvalidated(PRInt32 aStartColIdx,
+                                        PRInt32 aEndColIdx)
+{
+  nsAutoString name;
+  GetName(name);
+
+  if (name != mCachedName) {
+    nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, this);
+    mCachedName = name;
+  }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
 //  nsXULTreeColumnsAccessible
+////////////////////////////////////////////////////////////////////////////////
+
 nsXULTreeColumnsAccessible::
   nsXULTreeColumnsAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell):
   nsXULColumnsAccessible(aDOMNode, aShell)
 {
 }
 
 NS_IMETHODIMP
 nsXULTreeColumnsAccessible::GetNextSibling(nsIAccessible **aNextSibling)
 {
   NS_ENSURE_ARG_POINTER(aNextSibling);
   *aNextSibling = nsnull;
 
   nsCOMPtr<nsITreeBoxObject> tree;
   nsCOMPtr<nsITreeView> treeView;
 
-  nsXULTreeAccessible::GetTreeBoxObject(mDOMNode, getter_AddRefs(tree));
+  nsCoreUtils::GetTreeBoxObject(mDOMNode, getter_AddRefs(tree));
   if (tree) {
     tree->GetView(getter_AddRefs(treeView));
     if (treeView) {
-      PRInt32 rowCount;
+      PRInt32 rowCount = 0;
       treeView->GetRowCount(&rowCount);
       if (rowCount > 0) {
-        nsCOMPtr<nsITreeColumn> column =
-          nsXULTreeAccessible::GetFirstVisibleColumn(tree);
+        nsRefPtr<nsXULTreeAccessible> treeAcc =
+          nsAccUtils::QueryAccessibleTree(mParent);
+        NS_ENSURE_STATE(treeAcc);
 
-        nsRefPtr<nsXULTreeAccessible> treeCache =
-          nsAccUtils::QueryAccessibleTree(mParent);
-        NS_ENSURE_TRUE(treeCache, NS_ERROR_FAILURE);
-
-        treeCache->GetCachedTreeitemAccessible(0, column, aNextSibling);
+        treeAcc->GetTreeItemAccessible(0, aNextSibling);
       }
     }
   }
 
   return NS_OK;
 }
 
--- a/accessible/src/xul/nsXULTreeAccessible.h
+++ b/accessible/src/xul/nsXULTreeAccessible.h
@@ -60,58 +60,58 @@ const PRUint32 kDefaultTreeCacheSize = 2
   0x42ee,                                               \
   { 0xb8, 0xe1, 0x2c, 0x44, 0xb0, 0x41, 0x85, 0xe3 }    \
 }
 
 class nsXULTreeAccessible : public nsXULSelectableAccessible
 {
 public:
   nsXULTreeAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
-  virtual ~nsXULTreeAccessible() {}
+
+  // nsISupports and cycle collection
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULTreeAccessible,
+                                           nsAccessible)
 
-  // nsISupports
-  NS_DECL_ISUPPORTS_INHERITED
+  // nsIAccessible
+  NS_IMETHOD GetValue(nsAString& aValue);
+
+  NS_IMETHOD GetFirstChild(nsIAccessible **aFirstChild);
+  NS_IMETHOD GetLastChild(nsIAccessible **aLastChild);
+  NS_IMETHOD GetChildCount(PRInt32 *aChildCount);
+  NS_IMETHOD GetChildAt(PRInt32 aChildIndex, nsIAccessible **aChild);
+
+  NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
 
   // nsIAccessibleSelectable
   NS_DECL_NSIACCESSIBLESELECTABLE
 
-  // nsIAccessible
-  NS_IMETHOD GetValue(nsAString& _retval);
-
-  NS_IMETHOD GetFirstChild(nsIAccessible **_retval);
-  NS_IMETHOD GetLastChild(nsIAccessible **_retval);
-  NS_IMETHOD GetChildCount(PRInt32 *_retval);
-  NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
-
   // nsAccessNode
   virtual PRBool IsDefunct();
   virtual nsresult Shutdown();
 
   // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
   virtual nsresult GetChildAtPoint(PRInt32 aX, PRInt32 aY,
                                    PRBool aDeepestChild,
                                    nsIAccessible **aChild);
 
   // nsXULTreeAccessible
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_XULTREEACCESSIBLE_IMPL_CID)
 
   /**
-   * Return tree item accessible at the givem row and column. If accessible
-   * doesn't exist in the cache then create it.
+   * Return tree item accessible at the givem row. If accessible doesn't exist
+   * in the cache then create and cache it.
    *
    * @param aRow         [in] the given row index
-   * @param aColumn      [in] the given column object. If is is nsnull then
-   *                      primary column is used
    * @param aAccessible  [out] tree item accessible
    */
-  void GetCachedTreeitemAccessible(PRInt32 aRow, nsITreeColumn *aColumn,
-                                   nsIAccessible **aAccessible);
+  void GetTreeItemAccessible(PRInt32 aRow, nsIAccessible **aAccessible);
 
   /**
    * Invalidates the number of cached treeitem accessibles.
    *
    * @param aRow    [in] row index the invalidation starts from
    * @param aCount  [in] the number of treeitem accessibles to invalidate,
    *                 the number sign specifies whether rows have been
    *                 inserted (plus) or removed (minus)
@@ -130,108 +130,157 @@ public:
   void TreeViewInvalidated(PRInt32 aStartRow, PRInt32 aEndRow,
                            PRInt32 aStartCol, PRInt32 aEndCol);
 
   /**
    * Invalidates children created for previous tree view.
    */
   void TreeViewChanged();
 
-  static void GetTreeBoxObject(nsIDOMNode* aDOMNode, nsITreeBoxObject** aBoxObject);
-  static nsresult GetColumnCount(nsITreeBoxObject* aBoxObject, PRInt32 *aCount);
+protected:
+  /**
+   * Creates tree item accessible for the given row index.
+   */
+  virtual void CreateTreeItemAccessible(PRInt32 aRowIndex,
+                                        nsAccessNode** aAccessNode);
 
-  static PRBool IsColumnHidden(nsITreeColumn *aColumn);
-  static already_AddRefed<nsITreeColumn> GetNextVisibleColumn(nsITreeColumn *aColumn);
-  static already_AddRefed<nsITreeColumn> GetFirstVisibleColumn(nsITreeBoxObject *aTree);
-  static already_AddRefed<nsITreeColumn> GetLastVisibleColumn(nsITreeBoxObject *aTree);
-
-protected:
   nsCOMPtr<nsITreeBoxObject> mTree;
   nsCOMPtr<nsITreeView> mTreeView;
-  nsAccessNodeHashtable *mAccessNodeCache;
+  nsAccessNodeHashtable mAccessNodeCache;
 
   NS_IMETHOD ChangeSelection(PRInt32 aIndex, PRUint8 aMethod, PRBool *aSelState);
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsXULTreeAccessible,
                               NS_XULTREEACCESSIBLE_IMPL_CID)
 
 /**
- * Accessible class for items for XUL tree.
+ * Base class for tree item accessibles.
  */
 
-#define NS_XULTREEITEMACCESSIBLE_IMPL_CID             \
-{  /* 7b1aa039-7270-4523-aeb3-61063a13ac3f */         \
-  0x7b1aa039,                                         \
-  0x7270,                                             \
-  0x4523,                                             \
-  { 0xae, 0xb3, 0x61, 0x06, 0x3a, 0x13, 0xac, 0x3f }  \
+#define NS_XULTREEITEMBASEACCESSIBLE_IMPL_CID         \
+{  /* 1ab79ae7-766a-443c-940b-b1e6b0831dfc */         \
+  0x1ab79ae7,                                         \
+  0x766a,                                             \
+  0x443c,                                             \
+  { 0x94, 0x0b, 0xb1, 0xe6, 0xb0, 0x83, 0x1d, 0xfc }  \
 }
 
-class nsXULTreeitemAccessible : public nsLeafAccessible
+class nsXULTreeItemAccessibleBase : public nsAccessibleWrap
 {
 public:
-  enum { eAction_Click = 0, eAction_Expand = 1 };
-
-  nsXULTreeitemAccessible(nsIAccessible *aParent, nsIDOMNode *aDOMNode, nsIWeakReference *aShell, PRInt32 aRow, nsITreeColumn* aColumn = nsnull);
-  virtual ~nsXULTreeitemAccessible() {}
+  nsXULTreeItemAccessibleBase(nsIDOMNode *aDOMNode, nsIWeakReference *aShell,
+                              nsIAccessible *aParent, nsITreeBoxObject *aTree,
+                              nsITreeView *aTreeView, PRInt32 aRow);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
+  // nsIAccessNode
+  NS_IMETHOD GetUniqueID(void **aUniqueID);
+
   // nsIAccessible
-  NS_IMETHOD GetName(nsAString& aName);
-  NS_IMETHOD GetNumActions(PRUint8 *_retval);
-  NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
+  NS_IMETHOD GetParent(nsIAccessible **aParent);
+  NS_IMETHOD GetNextSibling(nsIAccessible **aNextSibling);
+  NS_IMETHOD GetPreviousSibling(nsIAccessible **aPreviousSibling);
 
-  NS_IMETHOD GetParent(nsIAccessible **_retval);
-  NS_IMETHOD GetNextSibling(nsIAccessible **_retval);
-  NS_IMETHOD GetPreviousSibling(nsIAccessible **_retval);
+  NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
 
-  NS_IMETHOD DoAction(PRUint8 index);
-  NS_IMETHOD GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
+  NS_IMETHOD GetBounds(PRInt32 *aX, PRInt32 *aY,
+                       PRInt32 *aWidth, PRInt32 *aHeight);
+
   NS_IMETHOD SetSelected(PRBool aSelect); 
-  NS_IMETHOD TakeFocus(void); 
+  NS_IMETHOD TakeFocus();
 
   NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
                                nsIAccessibleRelation **aRelation);
 
-  // nsIAccessNode
-  NS_IMETHOD GetUniqueID(void **aUniqueID);
+  NS_IMETHOD GetNumActions(PRUint8 *aCount);
+  NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
+  NS_IMETHOD DoAction(PRUint8 aIndex);
+
+  // nsAccessNode
+  virtual PRBool IsDefunct();
+  virtual nsresult Shutdown();
+
+  // nsAccessible
+  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
+  virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
+
+  // nsXULTreeItemAccessibleBase
+  NS_DECLARE_STATIC_IID_ACCESSOR(NS_XULTREEITEMBASEACCESSIBLE_IMPL_CID)
+
+  /**
+   * Return cell accessible for the given column. If XUL tree accessible is not
+   * accessible table then return null.
+   */
+  virtual void GetCellAccessible(nsITreeColumn *aColumn,
+                                 nsIAccessible **aCellAcc)
+    { *aCellAcc = nsnull; }
+
+  /**
+   * Proccess row invalidation. Used to fires name change events.
+   */
+  virtual void RowInvalidated(PRInt32 aStartColIdx, PRInt32 aEndColIdx) = 0;
+
+protected:
+  enum { eAction_Click = 0, eAction_Expand = 1 };
+
+  // nsAccessible
+  virtual void DispatchClickEvent(nsIContent *aContent, PRUint32 aActionIndex);
+
+  // nsXULTreeItemAccessibleBase
+
+  /**
+   * Return true if the tree item accessible is expandable (contains subrows).
+   */
+  PRBool IsExpandable();
+
+  nsCOMPtr<nsITreeBoxObject> mTree;
+  nsCOMPtr<nsITreeView> mTreeView;
+  PRInt32 mRow;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsXULTreeItemAccessibleBase,
+                              NS_XULTREEITEMBASEACCESSIBLE_IMPL_CID)
+
+
+/**
+ * Accessible class for items for XUL tree.
+ */
+class nsXULTreeItemAccessible : public nsXULTreeItemAccessibleBase
+{
+public:
+  nsXULTreeItemAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell,
+                          nsIAccessible *aParent, nsITreeBoxObject *aTree,
+                          nsITreeView *aTreeView, PRInt32 aRow);
+
+  // nsIAccessible
+  NS_IMETHOD GetFirstChild(nsIAccessible **aFirstChild);
+  NS_IMETHOD GetLastChild(nsIAccessible **aLastChild);
+  NS_IMETHOD GetChildCount(PRInt32 *aChildCount);
+
+  NS_IMETHOD GetName(nsAString& aName);
 
   // nsAccessNode
   virtual PRBool IsDefunct();
   virtual nsresult Init();
   virtual nsresult Shutdown();
 
   // nsAccessible
-  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
-  virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
 
-  // nsXULTreeitemAccessible
-  NS_DECLARE_STATIC_IID_ACCESSOR(NS_XULTREEITEMACCESSIBLE_IMPL_CID)
-
-  /**
-   * Get/set cached name.
-   */
-  void GetCachedName(nsAString& aName);
-  void SetCachedName(const nsAString& aName);
+  // nsXULTreeItemAccessibleBase
+  virtual void RowInvalidated(PRInt32 aStartColIdx, PRInt32 aEndColIdx);
 
 protected:
-  PRBool IsExpandable();
-  nsCOMPtr<nsITreeBoxObject> mTree;
-  nsCOMPtr<nsITreeView> mTreeView;
-  PRInt32 mRow;
   nsCOMPtr<nsITreeColumn> mColumn;
   nsString mCachedName;
 };
 
-NS_DEFINE_STATIC_IID_ACCESSOR(nsXULTreeitemAccessible,
-                              NS_XULTREEITEMACCESSIBLE_IMPL_CID)
 
 /**
  * Accessible class for columns element of XUL tree.
  */
 class nsXULTreeColumnsAccessible : public nsXULColumnsAccessible
 {
 public:
   nsXULTreeColumnsAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
new file mode 100644
--- /dev/null
+++ b/accessible/src/xul/nsXULTreeGridAccessible.cpp
@@ -0,0 +1,1228 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** 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 Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * 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 ***** */
+
+#include "nsXULTreeGridAccessible.h"
+
+#include "nsITreeSelection.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// Internal static functions
+////////////////////////////////////////////////////////////////////////////////
+
+static PLDHashOperator
+ElementTraverser(const void *aKey, nsIAccessNode *aAccessNode,
+                 void *aUserArg)
+{
+  nsCycleCollectionTraversalCallback *cb = 
+    static_cast<nsCycleCollectionTraversalCallback*>(aUserArg);
+
+  NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
+                                     "mAccessNodeCache of XUL tree row entry");
+  cb->NoteXPCOMChild(aAccessNode);
+  return PL_DHASH_NEXT;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeGridAccessible
+////////////////////////////////////////////////////////////////////////////////
+
+nsXULTreeGridAccessible::
+  nsXULTreeGridAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell) :
+  nsXULTreeAccessible(aDOMNode, aShell)
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeGridAccessible: nsISupports implementation
+
+NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeGridAccessible,
+                             nsXULTreeAccessible,
+                             nsIAccessibleTable)
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeGridAccessible: nsIAccessibleTable implementation
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::GetCaption(nsIAccessible **aCaption)
+{
+  NS_ENSURE_ARG_POINTER(aCaption);
+  *aCaption = nsnull;
+
+  return IsDefunct() ? NS_ERROR_FAILURE : NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::GetSummary(nsAString &aSummary)
+{
+  aSummary.Truncate();
+  return IsDefunct() ? NS_ERROR_FAILURE : NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::GetColumns(PRInt32 *aColumnsCount)
+{
+  NS_ENSURE_ARG_POINTER(aColumnsCount);
+  *aColumnsCount = 0;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  *aColumnsCount = nsCoreUtils::GetSensibleColumnsCount(mTree);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::GetColumnHeader(nsIAccessibleTable **aColumnHeader)
+{
+  NS_ENSURE_ARG_POINTER(aColumnHeader);
+  *aColumnHeader = nsnull;
+
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::GetRows(PRInt32 *aRowsCount)
+{
+  NS_ENSURE_ARG_POINTER(aRowsCount);
+  *aRowsCount = nsnull;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  return mTreeView->GetRowCount(aRowsCount);
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::GetRowHeader(nsIAccessibleTable **aRowHeader)
+{
+  NS_ENSURE_ARG_POINTER(aRowHeader);
+  *aRowHeader = nsnull;
+
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::GetSelectedCellsCount(PRUint32* aCount)
+{
+  NS_ENSURE_ARG_POINTER(aCount);
+  *aCount = 0;
+
+  PRUint32 selectedRowsCount = 0;
+  nsresult rv = GetSelectedRowsCount(&selectedRowsCount);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRInt32 columnsCount = 0;
+  rv = GetColumns(&columnsCount);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  *aCount = selectedRowsCount * columnsCount;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::GetSelectedColumnsCount(PRUint32* aCount)
+{
+  NS_ENSURE_ARG_POINTER(aCount);
+  *aCount = 0;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  // If all the row has been selected, then all the columns are selected,
+  // because we can't select a column alone.
+
+  PRInt32 rowsCount = 0;
+  nsresult rv = GetRows(&rowsCount);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRInt32 selectedRowsCount = 0;
+  rv = GetSelectionCount(&selectedRowsCount);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (rowsCount == selectedRowsCount) {
+    PRInt32 columnsCount = 0;
+    rv = GetColumns(&columnsCount);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    *aCount = columnsCount;
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::GetSelectedRowsCount(PRUint32* aCount)
+{
+  NS_ENSURE_ARG_POINTER(aCount);
+  *aCount = 0;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  PRInt32 selectedRowsCount = 0;
+  nsresult rv = GetSelectionCount(&selectedRowsCount);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  *aCount = selectedRowsCount;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::GetSelectedCells(PRUint32 *aCellsCount,
+                                          PRInt32 **aCells)
+{
+  NS_ENSURE_ARG_POINTER(aCellsCount);
+  *aCellsCount = 0;
+  NS_ENSURE_ARG_POINTER(aCells);
+  *aCells = nsnull;
+
+  PRInt32 selectedRowsCount = 0;
+  nsresult rv = GetSelectionCount(&selectedRowsCount);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRInt32 columnsCount = 0;
+  rv = GetColumns(&columnsCount);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRInt32 selectedCellsCount = selectedRowsCount * columnsCount;
+  PRInt32* outArray = static_cast<PRInt32*>(
+    nsMemory::Alloc(selectedCellsCount * sizeof(PRInt32)));
+  NS_ENSURE_TRUE(outArray, NS_ERROR_OUT_OF_MEMORY);
+
+  nsCOMPtr<nsITreeSelection> selection;
+  rv = mTreeView->GetSelection(getter_AddRefs(selection));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRInt32 rowsCount = 0;
+  rv = GetRows(&rowsCount);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRBool isSelected;
+  for (PRInt32 rowIdx = 0, arrayIdx = 0; rowIdx < rowsCount; rowIdx++) {
+    selection->IsSelected(rowIdx, &isSelected);
+    if (isSelected) {
+      for (PRInt32 colIdx = 0; colIdx < columnsCount; colIdx++)
+        outArray[arrayIdx++] = rowIdx * columnsCount + colIdx;
+    }
+  }
+
+  *aCellsCount = selectedCellsCount;
+  *aCells = outArray;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::GetSelectedColumns(PRUint32 *aColumnsCount,
+                                            PRInt32 **aColumns)
+{
+  NS_ENSURE_ARG_POINTER(aColumnsCount);
+  *aColumnsCount = 0;
+  NS_ENSURE_ARG_POINTER(aColumns);
+  *aColumns = nsnull;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  // If all the row has been selected, then all the columns are selected.
+  // Because we can't select a column alone.
+
+  PRInt32 rowsCount = 0;
+  nsresult rv = GetRows(&rowsCount);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRInt32 selectedRowsCount = 0;
+  rv = GetSelectionCount(&selectedRowsCount);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (rowsCount != selectedRowsCount)
+    return NS_OK;
+
+  PRInt32 columnsCount = 0;
+  rv = GetColumns(&columnsCount);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRInt32* outArray = static_cast<PRInt32*>(
+    nsMemory::Alloc(columnsCount * sizeof(PRInt32)));
+  NS_ENSURE_TRUE(outArray, NS_ERROR_OUT_OF_MEMORY);
+
+  for (PRInt32 colIdx = 0; colIdx < columnsCount; colIdx++)
+    outArray[colIdx] = colIdx;
+
+  *aColumnsCount = columnsCount;
+  *aColumns = outArray;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::GetSelectedRows(PRUint32 *aRowsCount, PRInt32 **aRows)
+{
+  NS_ENSURE_ARG_POINTER(aRowsCount);
+  *aRowsCount = 0;
+  NS_ENSURE_ARG_POINTER(aRows);
+  *aRows = nsnull;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  PRInt32 selectedRowsCount = 0;
+  nsresult rv = GetSelectionCount(&selectedRowsCount);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRInt32* outArray = static_cast<PRInt32*>(
+    nsMemory::Alloc(selectedRowsCount * sizeof(PRInt32)));
+  NS_ENSURE_TRUE(outArray, NS_ERROR_OUT_OF_MEMORY);
+
+  nsCOMPtr<nsITreeSelection> selection;
+  rv = mTreeView->GetSelection(getter_AddRefs(selection));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRInt32 rowsCount = 0;
+  rv = GetRows(&rowsCount);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRBool isSelected;
+  for (PRInt32 rowIdx = 0, arrayIdx = 0; rowIdx < rowsCount; rowIdx++) {
+    selection->IsSelected(rowIdx, &isSelected);
+    if (isSelected)
+      outArray[arrayIdx++] = rowIdx;
+  }
+
+  *aRowsCount = selectedRowsCount;
+  *aRows = outArray;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::CellRefAt(PRInt32 aRowIndex, PRInt32 aColumnIndex,
+                                   nsIAccessible **aCell)
+{
+  NS_ENSURE_ARG_POINTER(aCell);
+  *aCell = nsnull;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  nsCOMPtr<nsIAccessible> rowAccessible;
+  GetTreeItemAccessible(aRowIndex, getter_AddRefs(rowAccessible));
+  if (!rowAccessible)
+    return NS_ERROR_INVALID_ARG;
+
+  nsCOMPtr<nsITreeColumn> column =
+  nsCoreUtils::GetSensibleColumnAt(mTree, aColumnIndex);
+  if (!column)
+    return NS_ERROR_INVALID_ARG;
+
+  nsRefPtr<nsXULTreeItemAccessibleBase> rowAcc =
+    nsAccUtils::QueryObject<nsXULTreeItemAccessibleBase>(rowAccessible);
+
+  rowAcc->GetCellAccessible(column, aCell);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::GetIndexAt(PRInt32 aRowIndex, PRInt32 aColumnIndex,
+                                    PRInt32 *aCellIndex)
+{
+  NS_ENSURE_ARG_POINTER(aCellIndex);
+  *aCellIndex = -1;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  PRInt32 columnsCount = 0;
+  nsresult rv = GetColumns(&columnsCount);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  *aCellIndex = aRowIndex * columnsCount + aColumnIndex;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::GetColumnAtIndex(PRInt32 aCellIndex,
+                                          PRInt32 *aColumnIndex)
+{
+  NS_ENSURE_ARG_POINTER(aColumnIndex);
+  *aColumnIndex = -1;
+
+  PRInt32 columnsCount = 0;
+  nsresult rv = GetColumns(&columnsCount);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  *aColumnIndex = aCellIndex % columnsCount;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::GetRowAtIndex(PRInt32 aCellIndex, PRInt32 *aRowIndex)
+{
+  NS_ENSURE_ARG_POINTER(aRowIndex);
+  *aRowIndex = -1;
+
+  PRInt32 columnsCount;
+  nsresult rv = GetColumns(&columnsCount);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  *aRowIndex = aCellIndex / columnsCount;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::GetColumnExtentAt(PRInt32 aRowIndex,
+                                           PRInt32 aColumnIndex,
+                                           PRInt32 *aExtentCount)
+{
+  NS_ENSURE_ARG_POINTER(aExtentCount);
+  *aExtentCount = 1;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::GetRowExtentAt(PRInt32 aRowIndex, PRInt32 aColumnIndex,
+                                        PRInt32 *aExtentCount)
+{
+  NS_ENSURE_ARG_POINTER(aExtentCount);
+  *aExtentCount = 1;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::GetColumnDescription(PRInt32 aColumnIndex,
+                                              nsAString& aDescription)
+{
+  aDescription.Truncate();
+
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::GetRowDescription(PRInt32 aRowIndex,
+                                           nsAString& aDescription)
+{
+  aDescription.Truncate();
+
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::IsColumnSelected(PRInt32 aColumnIndex,
+                                          PRBool *aIsSelected)
+{
+  NS_ENSURE_ARG_POINTER(aIsSelected);
+  *aIsSelected = PR_FALSE;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  // If all the row has been selected, then all the columns are selected.
+  // Because we can't select a column alone.
+  
+  PRInt32 rowsCount = 0;
+  nsresult rv = GetRows(&rowsCount);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRInt32 selectedRowsCount = 0;
+  rv = GetSelectionCount(&selectedRowsCount);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  *aIsSelected = rowsCount == selectedRowsCount;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::IsRowSelected(PRInt32 aRowIndex, PRBool *aIsSelected)
+{
+  NS_ENSURE_ARG_POINTER(aIsSelected);
+  *aIsSelected = PR_FALSE;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  nsCOMPtr<nsITreeSelection> selection;
+  nsresult rv = mTreeView->GetSelection(getter_AddRefs(selection));
+  NS_ENSURE_SUCCESS(rv, rv);
+  
+  return selection->IsSelected(aRowIndex, aIsSelected);
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::IsCellSelected(PRInt32 aRowIndex, PRInt32 aColumnIndex,
+                                        PRBool *aIsSelected)
+{
+  return IsRowSelected(aRowIndex, aIsSelected);
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::SelectRow(PRInt32 aRowIndex)
+{
+  nsCOMPtr<nsITreeSelection> selection;
+  mTreeView->GetSelection(getter_AddRefs(selection));
+  NS_ENSURE_STATE(selection);
+
+  return selection->Select(aRowIndex);
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::SelectColumn(PRInt32 aColumnIndex)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::UnselectRow(PRInt32 aRowIndex)
+{
+  nsCOMPtr<nsITreeSelection> selection;
+  mTreeView->GetSelection(getter_AddRefs(selection));
+  NS_ENSURE_STATE(selection);
+
+  return selection->ClearRange(aRowIndex, aRowIndex);
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::UnselectColumn(PRInt32 aColumnIndex)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridAccessible::IsProbablyForLayout(PRBool *aIsProbablyForLayout)
+{
+  NS_ENSURE_ARG_POINTER(aIsProbablyForLayout);
+  *aIsProbablyForLayout = PR_FALSE;
+
+  return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeGridAccessible: nsAccessible implementation
+
+nsresult
+nsXULTreeGridAccessible::GetRoleInternal(PRUint32 *aRole)
+{
+  nsCOMPtr<nsITreeColumns> treeColumns;
+  mTree->GetColumns(getter_AddRefs(treeColumns));
+  NS_ENSURE_STATE(treeColumns);
+
+  nsCOMPtr<nsITreeColumn> primaryColumn;
+  treeColumns->GetPrimaryColumn(getter_AddRefs(primaryColumn));
+
+  *aRole = primaryColumn ?
+    nsIAccessibleRole::ROLE_TREE_TABLE :
+    nsIAccessibleRole::ROLE_TABLE;
+
+  return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeGridAccessible: nsXULTreeAccessible implementation
+
+void
+nsXULTreeGridAccessible::CreateTreeItemAccessible(PRInt32 aRow,
+                                                  nsAccessNode** aAccessNode)
+{
+  *aAccessNode = new nsXULTreeGridRowAccessible(mDOMNode, mWeakShell, this,
+                                                mTree, mTreeView, aRow);
+  NS_IF_ADDREF(*aAccessNode);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeGridRowAccessible
+////////////////////////////////////////////////////////////////////////////////
+
+nsXULTreeGridRowAccessible::
+  nsXULTreeGridRowAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell,
+                             nsIAccessible *aTreeAcc, nsITreeBoxObject* aTree,
+                             nsITreeView *aTreeView, PRInt32 aRow) :
+  nsXULTreeItemAccessibleBase(aDOMNode, aShell, aTreeAcc, aTree, aTreeView, aRow)
+{
+  mAccessNodeCache.Init(kDefaultTreeCacheSize);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeGridRowAccessible: nsISupports and cycle collection implementation
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTreeGridRowAccessible)
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULTreeGridRowAccessible,
+                                                  nsAccessible)
+tmp->mAccessNodeCache.EnumerateRead(ElementTraverser, &cb);
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULTreeGridRowAccessible,
+                                                nsAccessible)
+tmp->ClearCache(tmp->mAccessNodeCache);
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXULTreeGridRowAccessible)
+NS_INTERFACE_MAP_STATIC_AMBIGUOUS(nsXULTreeGridRowAccessible)
+NS_INTERFACE_MAP_END_INHERITING(nsXULTreeItemAccessibleBase)
+
+NS_IMPL_ADDREF_INHERITED(nsXULTreeGridRowAccessible,
+                         nsXULTreeItemAccessibleBase)
+NS_IMPL_RELEASE_INHERITED(nsXULTreeGridRowAccessible,
+                          nsXULTreeItemAccessibleBase)
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeGridRowAccessible: nsIAccessible implementation
+
+NS_IMETHODIMP
+nsXULTreeGridRowAccessible::GetFirstChild(nsIAccessible **aFirstChild)
+{
+  NS_ENSURE_ARG_POINTER(aFirstChild);
+  *aFirstChild = nsnull;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  nsCOMPtr<nsITreeColumn> column = nsCoreUtils::GetFirstSensibleColumn(mTree);
+  NS_ASSERTION(column, "No column for table grid!");
+  if (!column)
+    return NS_ERROR_FAILURE;
+
+  GetCellAccessible(column, aFirstChild);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridRowAccessible::GetLastChild(nsIAccessible **aLastChild)
+{
+  NS_ENSURE_ARG_POINTER(aLastChild);
+  *aLastChild = nsnull;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  nsCOMPtr<nsITreeColumn> column = nsCoreUtils::GetLastSensibleColumn(mTree);
+  NS_ASSERTION(column, "No column for table grid!");
+  if (!column)
+    return NS_ERROR_FAILURE;
+
+  GetCellAccessible(column, aLastChild);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridRowAccessible::GetChildCount(PRInt32 *aChildCount)
+{
+  NS_ENSURE_ARG_POINTER(aChildCount);
+  *aChildCount = 0;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  *aChildCount = nsCoreUtils::GetSensibleColumnsCount(mTree);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridRowAccessible::GetChildAt(PRInt32 aChildIndex,
+                                       nsIAccessible **aChild)
+{
+  NS_ENSURE_ARG_POINTER(aChild);
+  *aChild = nsnull;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  nsCOMPtr<nsITreeColumn> column =
+    nsCoreUtils::GetSensibleColumnAt(mTree, aChildIndex);
+  if (!column)
+    return NS_ERROR_INVALID_ARG;
+
+  GetCellAccessible(column, aChild);
+  return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeGridRowAccessible: nsAccessNode implementation
+
+nsresult
+nsXULTreeGridRowAccessible::Shutdown()
+{
+  ClearCache(mAccessNodeCache);
+  return nsXULTreeItemAccessibleBase::Shutdown();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeGridRowAccessible: nsAccessible implementation
+
+nsresult
+nsXULTreeGridRowAccessible::GetRoleInternal(PRUint32 *aRole)
+{
+  *aRole = nsIAccessibleRole::ROLE_ROW;
+  return NS_OK;
+}
+
+nsresult
+nsXULTreeGridRowAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
+                                            PRBool aDeepestChild,
+                                            nsIAccessible **aChild)
+{
+  nsIFrame *frame = GetFrame();
+  if (!frame)
+    return NS_ERROR_FAILURE;
+
+  nsPresContext *presContext = frame->PresContext();
+  nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
+
+  nsIFrame *rootFrame = presShell->GetRootFrame();
+  NS_ENSURE_STATE(rootFrame);
+
+  nsIntRect rootRect = rootFrame->GetScreenRectExternal();
+
+  PRInt32 clientX = presContext->DevPixelsToIntCSSPixels(aX - rootRect.x);
+  PRInt32 clientY = presContext->DevPixelsToIntCSSPixels(aY - rootRect.y);
+
+  PRInt32 row = -1;
+  nsCOMPtr<nsITreeColumn> column;
+  nsCAutoString childEltUnused;
+  mTree->GetCellAt(clientX, clientY, &row, getter_AddRefs(column),
+                   childEltUnused);
+
+  // Return if we failed to find tree cell in the row for the given point.
+  if (row != mRow || !column)
+    return NS_OK;
+
+  GetCellAccessible(column, aChild);
+  return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeGridRowAccessible: nsXULTreeItemAccessibleBase implementation
+
+void
+nsXULTreeGridRowAccessible::GetCellAccessible(nsITreeColumn* aColumn,
+                                              nsIAccessible** aAccessible)
+{
+  NS_PRECONDITION(aColumn, "No tree column!");
+  *aAccessible = nsnull;
+
+  void* key = static_cast<void*>(aColumn);
+
+  nsCOMPtr<nsIAccessNode> accessNode;
+  GetCacheEntry(mAccessNodeCache, key, getter_AddRefs(accessNode));
+
+  if (!accessNode) {
+    nsRefPtr<nsAccessNode> cellAcc =
+      new nsXULTreeGridCellAccessible(mDOMNode, mWeakShell, this, mTree,
+                                      mTreeView, mRow, aColumn);
+    if (!cellAcc)
+      return;
+
+    nsresult rv = cellAcc->Init();
+    if (NS_FAILED(rv))
+      return;
+
+    accessNode = cellAcc;
+    PutCacheEntry(mAccessNodeCache, key, accessNode);
+  }
+
+  CallQueryInterface(accessNode, aAccessible);
+}
+
+void
+nsXULTreeGridRowAccessible::RowInvalidated(PRInt32 aStartColIdx,
+                                           PRInt32 aEndColIdx)
+{
+  nsCOMPtr<nsITreeColumns> treeColumns;
+  mTree->GetColumns(getter_AddRefs(treeColumns));
+  if (!treeColumns)
+    return;
+
+  for (PRInt32 colIdx = aStartColIdx; colIdx <= aEndColIdx; ++colIdx) {
+    nsCOMPtr<nsITreeColumn> column;
+    treeColumns->GetColumnAt(colIdx, getter_AddRefs(column));
+    if (column && !nsCoreUtils::IsColumnHidden(column)) {
+      nsCOMPtr<nsIAccessible> cellAccessible;
+      GetCellAccessible(column, getter_AddRefs(cellAccessible));
+      if (cellAccessible) {
+        nsRefPtr<nsXULTreeGridCellAccessible> cellAcc =
+          nsAccUtils::QueryObject<nsXULTreeGridCellAccessible>(cellAccessible);
+
+        cellAcc->CellInvalidated();
+      }
+    }
+  }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeGridCellAccessible
+////////////////////////////////////////////////////////////////////////////////
+
+nsXULTreeGridCellAccessible::
+nsXULTreeGridCellAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell,
+                            nsXULTreeGridRowAccessible *aRowAcc,
+                            nsITreeBoxObject *aTree, nsITreeView *aTreeView,
+                            PRInt32 aRow, nsITreeColumn* aColumn) :
+  nsLeafAccessible(aDOMNode, aShell), mTree(aTree),
+  mTreeView(aTreeView), mRow(aRow), mColumn(aColumn)
+{
+  mParent = aRowAcc;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeGridCellAccessible: nsISupports implementation
+
+NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeGridCellAccessible,
+                             nsLeafAccessible,
+                             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::GetParent(nsIAccessible **aParent)
+{
+  NS_ENSURE_ARG_POINTER(aParent);
+  *aParent = nsnull;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  if (mParent) {
+    *aParent = mParent;
+    NS_ADDREF(*aParent);
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridCellAccessible::GetNextSibling(nsIAccessible **aNextSibling)
+{
+  NS_ENSURE_ARG_POINTER(aNextSibling);
+  *aNextSibling = nsnull;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  nsCOMPtr<nsITreeColumn> nextColumn =
+    nsCoreUtils::GetNextSensibleColumn(mColumn);
+  if (!nextColumn)
+    return NS_OK;
+
+  nsRefPtr<nsXULTreeItemAccessibleBase> rowAcc =
+    nsAccUtils::QueryObject<nsXULTreeItemAccessibleBase>(mParent);
+  rowAcc->GetCellAccessible(nextColumn, aNextSibling);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridCellAccessible::GetPreviousSibling(nsIAccessible **aPreviousSibling)
+{
+  NS_ENSURE_ARG_POINTER(aPreviousSibling);
+  *aPreviousSibling = nsnull;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  nsCOMPtr<nsITreeColumn> nextColumn =
+    nsCoreUtils::GetPreviousSensibleColumn(mColumn);
+  if (!nextColumn)
+    return NS_OK;
+
+  nsRefPtr<nsXULTreeItemAccessibleBase> rowAcc =
+    nsAccUtils::QueryObject<nsXULTreeItemAccessibleBase>(mParent);
+  rowAcc->GetCellAccessible(nextColumn, aPreviousSibling);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridCellAccessible::GetFocusedChild(nsIAccessible **aFocusedChild) 
+{
+  NS_ENSURE_ARG_POINTER(aFocusedChild);
+  *aFocusedChild = nsnull;
+
+  return IsDefunct() ? NS_ERROR_FAILURE : NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridCellAccessible::GetName(nsAString& aName)
+{
+  aName.Truncate();
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  mTreeView->GetCellText(mRow, mColumn, aName);
+
+  // If there is still no name try the cell value:
+  // This is for graphical cells. We need tree/table view implementors to implement
+  // FooView::GetCellValue to return a meaningful string for cases where there is
+  // something shown in the cell (non-text) such as a star icon; in which case
+  // GetCellValue for that cell would return "starred" or "flagged" for example.
+  if (aName.IsEmpty())
+    mTreeView->GetCellValue(mRow, mColumn, aName);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridCellAccessible::GetBounds(PRInt32 *aX, PRInt32 *aY,
+                                       PRInt32 *aWidth, PRInt32 *aHeight)
+{
+  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;
+
+  // Get bounds for tree cell and add x and y of treechildren element to
+  // x and y of the cell.
+  nsCOMPtr<nsIBoxObject> boxObj = nsCoreUtils::GetTreeBodyBoxObject(mTree);
+  NS_ENSURE_STATE(boxObj);
+
+  PRInt32 x = 0, y = 0, width = 0, height = 0;
+  nsresult rv = mTree->GetCoordsForCellItem(mRow, mColumn,
+                                            NS_LITERAL_CSTRING("cell"),
+                                            &x, &y, &width, &height);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRInt32 tcX = 0, tcY = 0;
+  boxObj->GetScreenX(&tcX);
+  boxObj->GetScreenY(&tcY);
+  x += tcX;
+  y += tcY;
+
+  nsPresContext *presContext = GetPresContext();
+  *aX = presContext->CSSPixelsToDevPixels(x);
+  *aY = presContext->CSSPixelsToDevPixels(y);
+  *aWidth = presContext->CSSPixelsToDevPixels(width);
+  *aHeight = presContext->CSSPixelsToDevPixels(height);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridCellAccessible::GetNumActions(PRUint8 *aActionsCount)
+{
+  NS_ENSURE_ARG_POINTER(aActionsCount);
+  *aActionsCount = 0;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  PRBool isCycler = PR_FALSE;
+  mColumn->GetCycler(&isCycler);
+  if (isCycler) {
+    *aActionsCount = 1;
+    return NS_OK;
+  }
+
+  PRInt16 type;
+  mColumn->GetType(&type);
+  if (type == nsITreeColumn::TYPE_CHECKBOX && IsEditable())
+    *aActionsCount = 1;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridCellAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
+{
+  aName.Truncate();
+
+  if (aIndex != eAction_Click)
+    return NS_ERROR_INVALID_ARG;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  PRBool isCycler = PR_FALSE;
+  mColumn->GetCycler(&isCycler);
+  if (isCycler) {
+    aName.AssignLiteral("cycle");
+    return NS_OK;
+  }
+
+  PRInt16 type;
+  mColumn->GetType(&type);
+  if (type == nsITreeColumn::TYPE_CHECKBOX && IsEditable()) {
+    nsAutoString value;
+    mTreeView->GetCellValue(mRow, mColumn, value);
+    if (value.EqualsLiteral("true"))
+      aName.AssignLiteral("uncheck");
+    else
+      aName.AssignLiteral("check");
+    
+    return NS_OK;
+  }
+
+  return NS_ERROR_INVALID_ARG;
+}
+
+NS_IMETHODIMP
+nsXULTreeGridCellAccessible::DoAction(PRUint8 aIndex)
+{
+  if (aIndex != eAction_Click)
+    return NS_ERROR_INVALID_ARG;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  PRBool isCycler = PR_FALSE;
+  mColumn->GetCycler(&isCycler);
+  if (isCycler)
+    return DoCommand();
+
+  PRInt16 type;
+  mColumn->GetType(&type);
+  if (type == nsITreeColumn::TYPE_CHECKBOX && IsEditable())
+    return DoCommand();
+
+  return NS_ERROR_INVALID_ARG;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeGridCellAccessible: nsAccessNode implementation
+
+PRBool
+nsXULTreeGridCellAccessible::IsDefunct()
+{
+  return nsLeafAccessible::IsDefunct() || !mParent || !mTree || !mTreeView ||
+    !mColumn;
+}
+
+nsresult
+nsXULTreeGridCellAccessible::Init()
+{
+  nsresult rv = nsLeafAccessible::Init();
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRInt16 type;
+  mColumn->GetType(&type);
+  if (type == nsITreeColumn::TYPE_CHECKBOX)
+    mTreeView->GetCellValue(mRow, mColumn, mCachedTextEquiv);
+  else
+    mTreeView->GetCellText(mRow, mColumn, mCachedTextEquiv);
+
+  return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeGridCellAccessible: nsAccessible implementation
+
+nsresult
+nsXULTreeGridCellAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
+{
+  NS_ENSURE_ARG_POINTER(aAttributes);
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  // "table-cell-index" attribute
+  nsCOMPtr<nsIAccessible> accessible;
+  mParent->GetParent(getter_AddRefs(accessible));
+  nsCOMPtr<nsIAccessibleTable> tableAccessible = do_QueryInterface(accessible);
+
+  PRInt32 colIdx = GetColumnIndex();
+
+  PRInt32 cellIdx = -1;
+  tableAccessible->GetIndexAt(mRow, colIdx, &cellIdx);
+
+  nsAutoString stringIdx;
+  stringIdx.AppendInt(cellIdx);
+  nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::tableCellIndex,
+                         stringIdx);
+
+  // "cycles" attribute
+  PRBool isCycler = PR_FALSE;
+  nsresult rv = mColumn->GetCycler(&isCycler);
+  if (NS_SUCCEEDED(rv) && isCycler)
+    nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::cycles,
+                           NS_LITERAL_STRING("true"));
+
+  return NS_OK;
+}
+
+nsresult
+nsXULTreeGridCellAccessible::GetRoleInternal(PRUint32 *aRole)
+{
+  *aRole = nsIAccessibleRole::ROLE_GRID_CELL;
+  return NS_OK;
+}
+
+nsresult
+nsXULTreeGridCellAccessible::GetStateInternal(PRUint32 *aStates,
+                                              PRUint32 *aExtraStates)
+{
+  NS_ENSURE_ARG_POINTER(aStates);
+
+  *aStates = 0;
+  if (aExtraStates)
+    *aExtraStates = 0;
+
+  if (IsDefunct()) {
+    if (aExtraStates)
+      *aExtraStates = nsIAccessibleStates::EXT_STATE_DEFUNCT;
+    return NS_OK_DEFUNCT_OBJECT;
+  }
+
+  // selectable/selected state
+  *aStates |= nsIAccessibleStates::STATE_SELECTABLE;
+
+  nsCOMPtr<nsITreeSelection> selection;
+  mTreeView->GetSelection(getter_AddRefs(selection));
+  if (selection) {
+    PRBool isSelected = PR_FALSE;
+    selection->IsSelected(mRow, &isSelected);
+    if (isSelected)
+      *aStates |= nsIAccessibleStates::STATE_SELECTED;
+  }
+
+  // checked state
+  PRInt16 type;
+  mColumn->GetType(&type);
+  if (type == nsITreeColumn::TYPE_CHECKBOX) {
+    *aStates |= nsIAccessibleStates::STATE_CHECKABLE;
+    nsAutoString checked;
+    mTreeView->GetCellValue(mRow, mColumn, checked);
+    if (checked.EqualsIgnoreCase("true"))
+      *aStates |= nsIAccessibleStates::STATE_CHECKED;
+  }
+
+  return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeGridCellAccessible: public implementation
+
+PRInt32
+nsXULTreeGridCellAccessible::GetColumnIndex() const
+{
+  PRInt32 index = 0;
+  nsCOMPtr<nsITreeColumn> column = mColumn;
+  while (column = nsCoreUtils::GetPreviousSensibleColumn(column))
+    index++;
+
+  return index;
+}
+
+void
+nsXULTreeGridCellAccessible::CellInvalidated()
+{
+  nsAutoString textEquiv;
+
+  PRInt16 type;
+  mColumn->GetType(&type);
+  if (type == nsITreeColumn::TYPE_CHECKBOX) {
+    mTreeView->GetCellValue(mRow, mColumn, textEquiv);
+    if (mCachedTextEquiv != textEquiv) {
+      PRBool isEnabled = textEquiv.EqualsLiteral("true");
+      nsCOMPtr<nsIAccessibleStateChangeEvent> accEvent =
+        new nsAccStateChangeEvent(this, nsIAccessibleStates::STATE_CHECKED,
+                                  PR_FALSE, isEnabled);
+      if (accEvent)
+        FireAccessibleEvent(accEvent);
+
+      mCachedTextEquiv = textEquiv;
+    }
+
+    return;
+  }
+
+  mTreeView->GetCellText(mRow, mColumn, textEquiv);
+  if (mCachedTextEquiv != textEquiv) {
+    nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, this);
+    mCachedTextEquiv = textEquiv;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeGridCellAccessible: protected implementation
+
+void
+nsXULTreeGridCellAccessible::DispatchClickEvent(nsIContent *aContent,
+                                                PRUint32 aActionIndex)
+{
+  if (IsDefunct())
+    return;
+
+  nsCoreUtils::DispatchClickEvent(mTree, mRow, mColumn);
+}
+
+PRBool
+nsXULTreeGridCellAccessible::IsEditable() const
+{
+  // XXX: logic corresponds to tree.xml, it's preferable to have interface
+  // method to check it.
+  PRBool isEditable = PR_FALSE;
+  nsresult rv = mTreeView->IsEditable(mRow, mColumn, &isEditable);
+  if (NS_FAILED(rv) || !isEditable)
+    return PR_FALSE;
+
+  nsCOMPtr<nsIDOMElement> columnElm;
+  mColumn->GetElement(getter_AddRefs(columnElm));
+  if (!columnElm)
+    return PR_FALSE;
+
+  nsCOMPtr<nsIContent> columnContent(do_QueryInterface(columnElm));
+  if (!columnContent->AttrValueIs(kNameSpaceID_None,
+                                  nsAccessibilityAtoms::editable,
+                                  nsAccessibilityAtoms::_true,
+                                  eCaseMatters))
+    return PR_FALSE;
+
+  nsCOMPtr<nsIContent> treeContent(do_QueryInterface(mDOMNode));
+  return treeContent->AttrValueIs(kNameSpaceID_None,
+                                  nsAccessibilityAtoms::editable,
+                                  nsAccessibilityAtoms::_true,
+                                  eCaseMatters);
+}
new file mode 100644
--- /dev/null
+++ b/accessible/src/xul/nsXULTreeGridAccessible.h
@@ -0,0 +1,203 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** 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 Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * 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 ***** */
+
+#ifndef __nsXULTreeGridAccessible_h__
+#define __nsXULTreeGridAccessible_h__
+
+#include "nsIAccessibleTable.h"
+
+#include "nsXULTreeAccessible.h"
+
+/**
+ * Represents accessible for XUL tree in the case when it has multiple columns.
+ */
+class nsXULTreeGridAccessible : public nsXULTreeAccessible,
+                                public nsIAccessibleTable
+{
+public:
+  nsXULTreeGridAccessible(nsIDOMNode *aDOMNode,
+                          nsIWeakReference *aShell);
+
+  // nsISupports
+  NS_DECL_ISUPPORTS_INHERITED
+
+  // nsIAccessibleTable
+  NS_DECL_NSIACCESSIBLETABLE
+
+  // nsAccessible
+  virtual nsresult GetRoleInternal(PRUint32 *aRole);
+
+protected:
+
+  // nsXULTreeAccessible
+  virtual void CreateTreeItemAccessible(PRInt32 aRow,
+                                        nsAccessNode** aAccessNode);
+};
+
+
+/**
+ * Represents accessible for XUL tree item in the case when XUL tree has
+ * multiple columns.
+ */
+class nsXULTreeGridRowAccessible : public nsXULTreeItemAccessibleBase
+{
+public:
+  nsXULTreeGridRowAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell,
+                             nsIAccessible *aParent, nsITreeBoxObject *aTree,
+                             nsITreeView *aTreeView, PRInt32 aRow);
+
+  // nsISupports and cycle collection
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULTreeGridRowAccessible,
+                                           nsAccessible)
+
+  // nsIAccessible
+  NS_IMETHOD GetFirstChild(nsIAccessible **aFirstChild);
+  NS_IMETHOD GetLastChild(nsIAccessible **aLastChild);
+  NS_IMETHOD GetChildCount(PRInt32 *aChildCount);
+  NS_IMETHOD GetChildAt(PRInt32 aChildIndex, nsIAccessible **aChild);
+
+  // nsAccessNode
+  virtual nsresult Shutdown();
+
+  // nsAccessible
+  virtual nsresult GetRoleInternal(PRUint32 *aRole);
+  virtual nsresult GetChildAtPoint(PRInt32 aX, PRInt32 aY,
+                                   PRBool aDeepestChild,
+                                   nsIAccessible **aChild);
+
+  // nsXULTreeItemAccessibleBase
+  virtual void GetCellAccessible(nsITreeColumn *aColumn, nsIAccessible **aCell);
+  virtual void RowInvalidated(PRInt32 aStartColIdx, PRInt32 aEndColIdx);
+
+protected:
+  nsAccessNodeHashtable mAccessNodeCache;
+};
+
+
+/**
+ * Represents an accessible for XUL tree cell in the case when XUL tree has
+ * multiple columns.
+ */
+
+#define NS_XULTREEGRIDCELLACCESSIBLE_IMPL_CID         \
+{  /* 84588ad4-549c-4196-a932-4c5ca5de5dff */         \
+  0x84588ad4,                                         \
+  0x549c,                                             \
+  0x4196,                                             \
+  { 0xa9, 0x32, 0x4c, 0x5c, 0xa5, 0xde, 0x5d, 0xff }  \
+}
+
+class nsXULTreeGridCellAccessible : public nsLeafAccessible
+{
+public:
+  nsXULTreeGridCellAccessible(nsIDOMNode *aDOMNode, 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 GetParent(nsIAccessible **aParent);
+  NS_IMETHOD GetNextSibling(nsIAccessible **aNextSibling);
+  NS_IMETHOD GetPreviousSibling(nsIAccessible **aPrevSibling);
+
+  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);
+  NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
+  NS_IMETHOD DoAction(PRUint8 aIndex);
+
+  // nsAccessNode
+  virtual PRBool IsDefunct();
+  virtual nsresult Init();
+
+  // nsAccessible
+  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
+  virtual nsresult GetRoleInternal(PRUint32 *aRole);
+  virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
+
+  // nsXULTreeGridCellAccessible
+  NS_DECLARE_STATIC_IID_ACCESSOR(NS_XULTREEGRIDCELLACCESSIBLE_IMPL_CID)
+
+  /**
+   * Return index of the column.
+   */
+  PRInt32 GetColumnIndex() const;
+
+  /**
+   * Fire name or state change event if the accessible text or value has been
+   * changed.
+   */
+  void CellInvalidated();
+
+protected:
+  // nsAccessible
+  virtual void DispatchClickEvent(nsIContent *aContent, PRUint32 aActionIndex);
+
+  // nsXULTreeGridCellAccessible
+
+  /**
+   * Return true if value of cell can be modified.
+   */
+  PRBool IsEditable() const;
+
+  enum { eAction_Click = 0 };
+
+  nsCOMPtr<nsITreeBoxObject> mTree;
+  nsCOMPtr<nsITreeView> mTreeView;
+
+  PRInt32 mRow;
+  nsCOMPtr<nsITreeColumn> mColumn;
+
+  nsString mCachedTextEquiv;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsXULTreeGridCellAccessible,
+                              NS_XULTREEGRIDCELLACCESSIBLE_IMPL_CID)
+
+#endif
--- a/accessible/tests/mochitest/Makefile.in
+++ b/accessible/tests/mochitest/Makefile.in
@@ -54,57 +54,64 @@ include $(topsrcdir)/config/rules.mk
 		attributes.js \
 		common.js \
 		events.js \
 		grid.js \
 		layout.js \
 		name.css \
 		name.js \
 		name.xbl \
+		name_nsRootAcc_wnd.xul \
 		namerules.xml \
  		nsIAccessible_selects.js \
 		nsIAccessibleEditableText.js \
 		relations.js \
 		role.js \
 		states.js \
 		table.js \
 		value.js \
 		test_accessnode_invalidation.html \
+		test_actions.xul \
 		test_actions_aria.html \
 		test_actions_inputs.html \
-		test_actions.xul \
+		test_actions_tree.xul \
+		test_actions_treegrid.xul \
 		test_aria_activedescendant.html \
 		test_aria_role_article.html \
 		test_aria_role_equation.html \
 		test_aria_role_grid.html \
 		test_aria_roles.html \
 		test_aria_roles.xul \
 		test_aria_token_attrs.html \
+		test_attrs_elm_tree.xul \
 		test_bug420863.html \
 	$(warning   test_childAtPoint.html temporarily disabled) \
 	$(warning	test_childAtPoint.xul temporarily disabled) \
 		test_cssattrs.html \
 		test_descr.html \
 		test_elm_filectrl.html \
 	$(warning   test_elm_media.html temporarily disabled) \
 		test_elm_table.html \
+		test_elm_tree.xul \
 		test_elm_txtcntnr.html \
 		test_events_caretmove.html \
 		test_events_doc.html \
+		test_events_draganddrop.html \
 		test_events_focus.xul \
 		test_events_mutation.html \
 		test_events_tree.xul \
 		test_events_valuechange.html \
 		test_groupattrs.xul \
 		test_groupattrs.html \
 		test_name.html \
 		test_name.xul \
 		test_name_button.html \
 		test_name_link.html \
 		test_name_markup.html \
+		test_name_nsRootAcc.xul \
 		test_nsIAccessible_applicationAccessible.html \
 	$(warning test_nsIAccessible_comboboxes.xul temporarily disabled) \
  		test_nsIAccessible_selects.html \
 		test_nsIAccessible_focus.html \
 		test_nsIAccessibleDocument.html \
 		test_nsIAccessibleEditableText.html \
 		test_nsIAccessibleHyperLink.html \
 		test_nsIAccessibleHyperLink.xul \
@@ -112,36 +119,42 @@ include $(topsrcdir)/config/rules.mk
 		test_nsIAccessibleImage.html \
 		$(warning test_nsIAccessibleTable_listboxes.xul temporarily disabled) \
 		test_nsIAccessNode_utils.html \
 		test_nsOuterDocAccessible.html \
  		test_objectattrs.html \
 		test_relations.html \
 		test_relations.xul \
 		test_relations_table.html \
+		test_relations_tree.xul \
 		test_role_nsHyperTextAcc.html \
 		test_role_table_cells.html \
 		test_states.html \
-		test_states_editablebody.html \
 		test_states_doc.html \
 		test_states_docarticle.html \
+		test_states_editablebody.html \
 		test_states_frames.html \
+		test_states_popup.xul \
+		test_states_tree.xul \
 		test_table_1.html \
 		test_table_2.html \
 		test_table_4.html \
 		test_table_indexes.html \
 		test_table_indexes_ariagrid.html \
+		test_table_indexes_tree.xul \
 		test_table_layoutguess.html \
 		test_table_sels.html \
 		test_table_sels_ariagrid.html \
+		test_table_sels_tree.xul \
 		test_textattrs.html \
 		test_textboxes.html \
 		test_textboxes.xul \
 		test_value.xul \
 		testTextboxes.js \
+		treeview.css \
 		treeview.js \
 		z_states_frame.html \
 		z_states_framearticle.html \
 		z_states_framecheckbox.html \
 		z_states_frametextbox.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
--- a/accessible/tests/mochitest/actions.js
+++ b/accessible/tests/mochitest/actions.js
@@ -13,24 +13,35 @@ const ALL_EVENTS = CLICK_EVENTS | COMMAN
 // Public functions
 
 /**
  * Test default accessible actions.
  *
  * Action tester interface is:
  *
  *  var actionObj = {
- *    // identifier of accessible
+ *    // identifier of accessible to perform an action on
  *    get ID() {},
  *
- *    // name of default action
+ *    // index of the action
+ *    get actionIndex() {},
+ *
+ *    // name of the action
  *    get actionName() {},
  *
- *    // event constant defined above
- *    get events() {} 
+ *    // DOM events (see constants defined above)
+ *    get events() {},
+ *
+ *    // [optional] identifier of target DOM events listeners are registered on,
+ *    // used with 'events', if missing then 'ID' is used instead.
+ *    get targetID() {},
+ *
+ *    // [optional] perform checks when 'click' event is handled if 'events'
+ *    // is used.
+ *    checkOnClickEvent: function() {},
  *
  *    // [optional] an array of invoker's checker objects (see eventQueue
  *    // constructor events.js)
  *    get eventSeq() {} 
  *  };
  *
  *
  * @param  aArray [in] an array of action cheker objects
@@ -38,90 +49,95 @@ const ALL_EVENTS = CLICK_EVENTS | COMMAN
 function testActions(aArray)
 {
   gActionsQueue = new eventQueue();
 
   for (var idx = 0; idx < aArray.length; idx++) {
 
     var actionObj = aArray[idx];
     var accOrElmOrID = actionObj.ID;
+    var actionIndex = actionObj.actionIndex;
     var actionName = actionObj.actionName;
     var events = actionObj.events;
+    var accOrElmOrIDOfTarget = actionObj.targetID ?
+      actionObj.targetID : accOrElmOrID;
 
     var eventSeq = new Array();
     if (events) {
-      var elm = getNode(accOrElmOrID);
-      //alert(elm.QueryInterface(Components.interfaces.nsIDOMNode));
+      var elm = getNode(accOrElmOrIDOfTarget);
       if (events & MOUSEDOWN_EVENT)
         eventSeq.push(new checkerOfActionInvoker("mousedown", elm));
 
       if (events & MOUSEUP_EVENT)
         eventSeq.push(new checkerOfActionInvoker("mouseup", elm));
 
       if (events & CLICK_EVENT)
         eventSeq.push(new checkerOfActionInvoker("click", elm, actionObj));
 
       if (events & COMMAND_EVENT)
         eventSeq.push(new checkerOfActionInvoker("command", elm));
     }
 
     if (actionObj.eventSeq)
       eventSeq = eventSeq.concat(actionObj.eventSeq);
 
-    var invoker = new actionInvoker(accOrElmOrID, actionName, eventSeq);
+    var invoker = new actionInvoker(accOrElmOrID, actionIndex, actionName,
+                                    eventSeq);
     gActionsQueue.push(invoker);
   }
 
   gActionsQueue.invoke();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Private
 
 var gActionsQueue = null;
 
-function actionInvoker(aAccOrElmOrId, aActionName, aEventSeq)
+function actionInvoker(aAccOrElmOrId, aActionIndex, aActionName, aEventSeq)
 {
   this.invoke = function actionInvoker_invoke()
   {
     var acc = getAccessible(aAccOrElmOrId);
     if (!acc)
       return INVOKER_ACTION_FAILED;
 
     var isThereActions = acc.numActions > 0;
     ok(isThereActions,
        "No actions on the accessible for " + prettyName(aAccOrElmOrId));
 
     if (!isThereActions)
       return INVOKER_ACTION_FAILED;
 
-    is(acc.getActionName(0), aActionName,
+    is(acc.getActionName(aActionIndex), aActionName,
        "Wrong action name of the accessible for " + prettyName(aAccOrElmOrId));
 
     try {
-      acc.doAction(0);
+      acc.doAction(aActionIndex);
     }
     catch (e){
-      ok(false, "doAction(0) failed with: " + e.name);
+      ok(false, "doAction(" + aActionIndex + ") failed with: " + e.name);
       return INVOKER_ACTION_FAILED;
     }
   }
 
   this.eventSeq = aEventSeq;
 }
 
 function checkerOfActionInvoker(aType, aTarget, aActionObj)
 {
   this.type = aType;
 
   this.target = aTarget;
 
+  this.phase = false;
+
   this.getID = function getID()
   {
     return aType + " event handling";
   }
 
   this.check = function check(aEvent)
   {
-    if (aActionObj && "check" in aActionObj)
-      aActionObj.check(aEvent);
+    if (aActionObj && "checkOnClickEvent" in aActionObj)
+      aActionObj.checkOnClickEvent(aEvent);
   }
 }
--- a/accessible/tests/mochitest/attributes.js
+++ b/accessible/tests/mochitest/attributes.js
@@ -174,37 +174,37 @@ function testAttrsInternal(aAccOrElmOrID
     return;
 
   var attrs = null;
   try {
     attrs = accessible.attributes;
   } catch (e) { }
   
   if (!attrs) {
-    ok(false, "Can't get object attributes for " + aAccOrElmOrID);
+    ok(false, "Can't get object attributes for " + prettyName(aAccOrElmOrID));
     return;
   }
   
-  var errorMsg = " for " + aAccOrElmOrID;
+  var errorMsg = " for " + prettyName(aAccOrElmOrID);
   compareAttrs(errorMsg, attrs, aAttrs, aSkipUnexpectedAttrs, aAbsentAttrs);
 }
 
 function compareAttrs(aErrorMsg, aAttrs, aExpectedAttrs, aSkipUnexpectedAttrs,
                       aAbsentAttrs)
 {
   var enumerate = aAttrs.enumerate();
   while (enumerate.hasMoreElements()) {
     var prop = enumerate.getNext().QueryInterface(nsIPropertyElement);
 
     if (!(prop.key in aExpectedAttrs)) {
       if (!aSkipUnexpectedAttrs)
         ok(false, "Unexpected attribute '" + prop.key + "' having '" +
            prop.value + "'" + aErrorMsg);
     } else {
-      var msg = "Attribute '" + prop.key + " 'has wrong value" + aErrorMsg;
+      var msg = "Attribute '" + prop.key + "' has wrong value" + aErrorMsg;
       var expectedValue = aExpectedAttrs[prop.key];
 
       if (typeof expectedValue == "function")
         ok(expectedValue(prop.value), msg);
       else
         is(prop.value, expectedValue, msg);
     }
   }
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -158,31 +158,31 @@ const DONOTFAIL_IF_NO_ACC = 1;
 /**
  * Constants indicates getAccessible won't fail if accessible doesn't implement
  * the requested interfaces.
  */
 const DONOTFAIL_IF_NO_INTERFACE = 2;
 
 /**
  * Return accessible for the given identifier (may be ID attribute or DOM
- * element or accessible object).
+ * element or accessible object) or null.
  *
  * @param aAccOrElmOrID      [in] identifier to get an accessible implementing
  *                           the given interfaces
  * @param aInterfaces        [in, optional] the interface or an array interfaces
  *                           to query it/them from obtained accessible
  * @param aElmObj            [out, optional] object to store DOM element which
  *                           accessible is obtained for
  * @param aDoNotFailIf       [in, optional] no error for special cases (see
  *                            constants above)
  */
 function getAccessible(aAccOrElmOrID, aInterfaces, aElmObj, aDoNotFailIf)
 {
   if (!aAccOrElmOrID)
-    return;
+    return null;
 
   var elm = null;
 
   if (aAccOrElmOrID instanceof nsIAccessible) {
     aAccOrElmOrID.QueryInterface(nsIAccessNode);
     elm = aAccOrElmOrID.DOMNode;
 
   } else if (aAccOrElmOrID instanceof nsIDOMNode) {
@@ -248,16 +248,33 @@ function getAccessible(aAccOrElmOrID, aI
 function isAccessible(aAccOrElmOrID, aInterfaces)
 {
   return getAccessible(aAccOrElmOrID, aInterfaces, null,
                        DONOTFAIL_IF_NO_ACC | DONOTFAIL_IF_NO_INTERFACE) ?
     true : false;
 }
 
 /**
+ * Return root accessible for the given identifier.
+ */
+function getRootAccessible(aAccOrElmOrID)
+{
+  var acc = getAccessible(aAccOrElmOrID ? aAccOrElmOrID : document);
+  while (acc) {
+    var parent = acc.parent;
+    if (parent && !parent.parent)
+      return acc;
+
+    acc = parent;
+  }
+
+  return null;
+}
+
+/**
  * Run through accessible tree of the given identifier so that we ensure
  * accessible tree is created.
  */
 function ensureAccessibleTree(aAccOrElmOrID)
 {
   var acc = getAccessible(aAccOrElmOrID);
   if (!acc)
     return;
--- a/accessible/tests/mochitest/events.js
+++ b/accessible/tests/mochitest/events.js
@@ -1,16 +1,17 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Constants
 
 const EVENT_DOCUMENT_LOAD_COMPLETE =
   nsIAccessibleEvent.EVENT_DOCUMENT_LOAD_COMPLETE;
 const EVENT_DOM_DESTROY = nsIAccessibleEvent.EVENT_DOM_DESTROY;
 const EVENT_FOCUS = nsIAccessibleEvent.EVENT_FOCUS;
 const EVENT_NAME_CHANGE = nsIAccessibleEvent.EVENT_NAME_CHANGE;
+const EVENT_STATE_CHANGE = nsIAccessibleEvent.EVENT_STATE_CHANGE;
 const EVENT_REORDER = nsIAccessibleEvent.EVENT_REORDER;
 
 ////////////////////////////////////////////////////////////////////////////////
 // General
 
 /**
  * Set up this variable to dump events into DOM.
  */
@@ -128,16 +129,17 @@ function invokerChecker(aEventType, aTar
  *     // 1) an array consisted from two elements, the first element is DOM or
  *     // a11y event type, second element is event target (DOM node or
  *     // accessible).
  *     //
  *     // 2) object (invoker's checker object) like
  *     // var checker = {
  *     //   type getter: function() {}, // DOM or a11y event type
  *     //   target getter: function() {}, // DOM node or accessible
+ *     //   phase getter: function() {}, // DOM event phase (false - bubbling)
  *     //   check: function(aEvent) {},
  *     //   getID: function() {}
  *     // };
  *     eventSeq getter() {},
  *
  *     // [optional, used together with 'eventSeq'] Boolean indicates if events
  *     // specified by 'eventSeq' property shouldn't be triggerd by invoker.
  *     doNotExpectEvents getter() {},
@@ -170,16 +172,24 @@ function eventQueue(aEventType)
     gA11yEventApplicantsCount++;
 
     // XXX: Intermittent test_events_caretmove.html fails withouth timeout,
     // see bug 474952.
     window.setTimeout(function(aQueue) { aQueue.processNextInvoker(); }, 500,
                       this);
   }
 
+  /**
+   * This function is called when all events in the queue were handled.
+   * Override it if you need to be notified of this.
+   */
+  this.onFinish = function eventQueue_finish()
+  {
+  }
+
   // private
 
   /**
    * Process next invoker.
    */
   this.processNextInvoker = function eventQueue_processNextInvoker()
   {
     // Finish rocessing of the current invoker.
@@ -224,16 +234,17 @@ function eventQueue(aEventType)
 
     this.clearEventHandler();
 
     // Check if need to stop the test.
     if (testFailed || this.mIndex == this.mInvokers.length - 1) {
       gA11yEventApplicantsCount--;
       listenA11yEvents(false);
 
+      this.onFinish();
       SimpleTest.finish();
       return;
     }
 
     // Start processing of next invoker.
     invoker = this.getNextInvoker();
 
     this.setEventHandler(invoker);
@@ -276,36 +287,20 @@ function eventQueue(aEventType)
       for (var idx = 0; idx < this.mEventSeq.length; idx++) {
         if (this.compareEvents(idx, aEvent))
           invoker.wasCaught[idx] = true;
       }
     } else {
       // We wait for events in order specified by eventSeq variable.
       var idx = this.mEventSeqIdx + 1;
 
-      if (gA11yEventDumpID) { // debug stuff
-
-        if (aEvent instanceof nsIDOMEvent) {
-          var info = "Event type: " + aEvent.type;
-          info += ". Target: " + prettyName(aEvent.originalTarget);
-          dumpInfoToDOM(info);
-        }
+      var matched = this.compareEvents(idx, aEvent);
+      this.dumpEventToDOM(aEvent, idx, matched);
 
-        var currType = this.getEventType(idx);
-        var currTarget = this.getEventTarget(idx);
-
-        var info = "Event queue processing. Expected event type: ";
-        info += (typeof currType == "string") ?
-          currType : eventTypeToString(currType);
-        info += ". Target: " + prettyName(currTarget);
-
-        dumpInfoToDOM(info);
-      }
-
-      if (this.compareEvents(idx, aEvent)) {
+      if (matched) {
         this.checkEvent(idx, aEvent);
         invoker.wasCaught[idx] = true;
 
         if (idx == this.mEventSeq.length - 1) {
           // We need delay to avoid events coalesce from different invokers.
           var queue = this;
           SimpleTest.executeSoon(function() { queue.processNextInvoker(); });
           return;
@@ -335,49 +330,70 @@ function eventQueue(aEventType)
 
     this.mEventSeqIdx = -1;
 
     if (this.mEventSeq) {
       aInvoker.wasCaught = new Array(this.mEventSeq.length);
 
       for (var idx = 0; idx < this.mEventSeq.length; idx++) {
         var eventType = this.getEventType(idx);
-        if (typeof eventType == "string") // DOM event
-          document.addEventListener(eventType, this, true);
-        else // A11y event
+        if (typeof eventType == "string") {
+          // DOM event
+          var target = this.getEventTarget(idx);
+          var phase = this.getEventPhase(idx);
+          target.ownerDocument.addEventListener(eventType, this, phase);
+
+        } else {
+          // A11y event
           addA11yEventListener(eventType, this);
+        }
       }
     }
   }
 
   this.clearEventHandler = function eventQueue_clearEventHandler()
   {
     if (this.mEventSeq) {
       for (var idx = 0; idx < this.mEventSeq.length; idx++) {
         var eventType = this.getEventType(idx);
-        if (typeof eventType == "string") // DOM event
-          document.removeEventListener(eventType, this, true);
-        else // A11y event
+        if (typeof eventType == "string") {
+          // DOM event
+          var target = this.getEventTarget(idx);
+          var phase = this.getEventPhase(idx);
+          target.ownerDocument.removeEventListener(eventType, this, phase);
+
+        } else {
+          // A11y event
           removeA11yEventListener(eventType, this);
+        }
       }
 
       this.mEventSeq = null;
     }
   }
 
   this.getEventType = function eventQueue_getEventType(aIdx)
   {
     return this.mEventSeq[aIdx].type;
   }
 
   this.getEventTarget = function eventQueue_getEventTarget(aIdx)
   {
     return this.mEventSeq[aIdx].target;
   }
 
+  this.getEventPhase = function eventQueue_getEventPhase(aIdx)
+  {
+     var eventItem = this.mEventSeq[aIdx];
+    if ("phase" in eventItem)
+      return eventItem.phase;
+
+    return true;
+  }
+
   this.compareEvents = function eventQueue_compareEvents(aIdx, aEvent)
   {
     var eventType1 = this.getEventType(aIdx);
 
     var eventType2 = (aEvent instanceof nsIDOMEvent) ?
       aEvent.type : aEvent.eventType;
 
     if (eventType1 != eventType2)
@@ -414,16 +430,42 @@ function eventQueue(aEventType)
     var eventItem = this.mEventSeq[aIdx];
     if ("getID" in eventItem)
       return eventItem.getID();
 
     var invoker = this.getInvoker();
     return invoker.getID();
   }
 
+  this.dumpEventToDOM = function eventQueue_dumpEventToDOM(aOrigEvent,
+                                                           aExpectedEventIdx,
+                                                           aMatch)
+  {
+    if (!gA11yEventDumpID) // debug stuff
+      return;
+
+    // Dump DOM event information. Skip a11y event since it is dumped by
+    // gA11yEventObserver.
+    if (aOrigEvent instanceof nsIDOMEvent) {
+      var info = "Event type: " + aOrigEvent.type;
+      info += ". Target: " + prettyName(aOrigEvent.originalTarget);
+      dumpInfoToDOM(info);
+    }
+
+    var currType = this.getEventType(aExpectedEventIdx);
+    var currTarget = this.getEventTarget(aExpectedEventIdx);
+
+    var info = "EQ: " + (aMatch ? "matched" : "expected") + " event, type: ";
+    info += (typeof currType == "string") ?
+      currType : eventTypeToString(currType);
+    info += ". Target: " + prettyName(currTarget);
+
+    dumpInfoToDOM(info);
+  }
+
   this.mDefEventType = aEventType;
 
   this.mInvokers = new Array();
   this.mIndex = -1;
 
   this.mEventSeq = null;
   this.mEventSeqIdx = -1;
 }
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/name_nsRootAcc_wnd.xul
@@ -0,0 +1,103 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <script type="application/javascript">
+  <![CDATA[
+    var gOpenerWnd = window.opener.wrappedJSObject;
+
+    function ok(aCond, aMsg) {
+      gOpenerWnd.SimpleTest.ok(aCond, aMsg);
+    }
+
+    function is(aExpected, aActual, aMsg) {
+      gOpenerWnd.SimpleTest.is(aExpected, aActual, aMsg);
+    }
+
+    // Hack to make xul:tabbrowser work.
+    var XULBrowserWindow = {
+      isBusy: false,
+      setOverLink: function (link, b) {
+      }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Invoker implementation.
+
+    function switchTabSelectChecker(aInvoker)
+    {
+      this.type = "select";
+      this.target getter = function() { return aInvoker.getTabsElm(); }
+      this.getID = function() { return "switch tab, select event"; }
+    }
+
+    function switchTabFocusChecker(aInvoker)
+    {
+      this.type = gOpenerWnd.EVENT_FOCUS;
+      this.target getter = function() { return aInvoker.getContentDoc(); }
+      this.check = function(aEvent)
+      {
+        is(gOpenerWnd.getAccessible(document).name, "about:mozilla" + aEvent.accessible.name,
+           "Oops almost :)");
+      }
+      this.getID = function() { return "switch tab, focus event"; }
+    }
+
+    function switchTabInvoker(aTabBrowser)
+    {
+      this.invoke = function switchTabInvoker_invoke()
+      {
+        gOpenerWnd.synthesizeKey("VK_TAB", { ctrlKey: true });
+      }
+
+      this.eventSeq = [
+        new switchTabSelectChecker(this),
+        new switchTabFocusChecker(this)
+      ];
+
+      this.getContentDoc = function switchTabInvoker_getContentDoc()
+      {
+        return aTabBrowser.getBrowserAtIndex(1).contentDocument;
+      }
+      this.getTabsElm = function switchTabInvoker_getTabsElm()
+      {
+        return aTabBrowser.tabContainer;
+      }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Tests
+
+    var gQueue = null;
+
+    const Ci = Components.interfaces;
+
+    function onload()
+    {
+      var tabBrowser = document.getElementById("content");
+      tabBrowser.loadURI("about:");
+      tabBrowser.addTab("about:mozilla");
+
+      gQueue = new gOpenerWnd.eventQueue();
+      gQueue.push(new switchTabInvoker(tabBrowser));
+      gQueue.onFinish = function() { window.close(); }
+      gQueue.invoke();
+    }
+  ]]>
+  </script>
+
+  <!-- Hack to make xul:tabbrowser work -->
+  <menubar>
+    <menu label="menu">
+      <menupopup>
+        <menuitem label="close window hook" id="menu_closeWindow"/>
+        <menuitem label="close hook" id="menu_close"/>
+      </menupopup>
+    </menu>
+  </menubar>
+
+  <tabbrowser type="content-primary" flex="1" id="content"/>
+
+</window>
--- a/accessible/tests/mochitest/role.js
+++ b/accessible/tests/mochitest/role.js
@@ -19,29 +19,33 @@ const ROLE_GRID_CELL = nsIAccessibleRole
 const ROLE_GROUPING = nsIAccessibleRole.ROLE_GROUPING;
 const ROLE_HEADING = nsIAccessibleRole.ROLE_HEADING;
 const ROLE_IMAGE_MAP = nsIAccessibleRole.ROLE_IMAGE_MAP;
 const ROLE_INTERNAL_FRAME = nsIAccessibleRole.ROLE_INTERNAL_FRAME;
 const ROLE_LABEL = nsIAccessibleRole.ROLE_LABEL;
 const ROLE_LINK = nsIAccessibleRole.ROLE_LINK;
 const ROLE_LIST = nsIAccessibleRole.ROLE_LIST;
 const ROLE_LISTBOX = nsIAccessibleRole.ROLE_LISTBOX;
+const ROLE_LISTITEM = nsIAccessibleRole.ROLE_LISTITEM;
 const ROLE_NOTHING = nsIAccessibleRole.ROLE_NOTHING;
 const ROLE_OPTION = nsIAccessibleRole.ROLE_OPTION;
+const ROLE_OUTLINE = nsIAccessibleRole.ROLE_OUTLINE;
+const ROLE_OUTLINEITEM = nsIAccessibleRole.ROLE_OUTLINEITEM;
 const ROLE_PARAGRAPH = nsIAccessibleRole.ROLE_PARAGRAPH;
 const ROLE_PASSWORD_TEXT = nsIAccessibleRole.ROLE_PASSWORD_TEXT;
 const ROLE_PROGRESSBAR = nsIAccessibleRole.ROLE_PROGRESSBAR;
 const ROLE_PUSHBUTTON = nsIAccessibleRole.ROLE_PUSHBUTTON;
 const ROLE_ROW = nsIAccessibleRole.ROLE_ROW;
 const ROLE_SECTION = nsIAccessibleRole.ROLE_SECTION;
 const ROLE_SLIDER = nsIAccessibleRole.ROLE_SLIDER;
 const ROLE_TABLE = nsIAccessibleRole.ROLE_TABLE;
 const ROLE_TEXT_CONTAINER = nsIAccessibleRole.ROLE_TEXT_CONTAINER;
 const ROLE_TEXT_LEAF = nsIAccessibleRole.ROLE_TEXT_LEAF;
 const ROLE_TOGGLE_BUTTON = nsIAccessibleRole.ROLE_TOGGLE_BUTTON;
+const ROLE_TREE_TABLE = nsIAccessibleRole.ROLE_TREE_TABLE;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Public methods
 
 /**
  * Test that the role of the given accessible is the role passed in.
  *
  * @param aAccOrElmOrID  the accessible, DOM element or ID to be tested.
--- a/accessible/tests/mochitest/test_actions.xul
+++ b/accessible/tests/mochitest/test_actions.xul
@@ -45,16 +45,21 @@
           ID: "button",
           actionName: "press",
           events: ALL_EVENTS
         },
         {
           ID: "buttonmenu",
           actionName: "press",
           events: CLICK_EVENTS
+        },
+        {
+          ID: "labelWithPopup",
+          actionName: "click",
+          events: CLICK_EVENTS
         }/*, // XXX: bug 490288
         {
           ID: "buttonmenu_item",
           actionName: "click",
           events: CLICK_EVENTS
         }*/
       ];
 
@@ -68,16 +73,21 @@
 
   <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=410765"
          title="nsIAccessible actions testing">
         Mozilla Bug 410765
       </a>
+      <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=504252"
+         title="Expose STATE_HASPOPUP on XUL elements that have an @popup attribute">
+        Mozilla Bug 504252
+      </a><br/>
       <p id="display"></p>
       <div id="content" style="display: none">
       </div>
       <pre id="test">
       </pre>
     </body>
 
     <vbox flex="1">
@@ -97,12 +107,16 @@
       <button label="button" id="button"/>
 
       <button type="menu" id="buttonmenu" label="button">
         <menupopup>
           <menuitem label="item1" id="buttonmenu_item"/>
           <menuitem label="item1"/>
         </menupopup>
       </button>
+
+      <label id="labelWithPopup" value="file name"
+             popup="fileContext"
+             tabindex="0"/>
     </vbox>
   </hbox>
 </window>
 
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_actions_tree.xul
@@ -0,0 +1,139 @@
+<?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 tree actions 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="chrome://mochikit/content/a11y/accessible/treeview.js" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/common.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/states.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/events.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/actions.js" />
+
+  <script type="application/javascript">
+  <![CDATA[
+    ////////////////////////////////////////////////////////////////////////////
+    // Accessible tree testers
+
+    function focusChecker(aAcc, aStates)
+    {
+      this.type = EVENT_FOCUS;
+      this.target = aAcc;
+      this.getID = function focusChecker_getID()
+      {
+        return "focus handling";
+      }
+      this.check = function focusChecker_check(aEvent)
+      {
+        var states = aStates ? aStates : 0;
+        testStates(this.target, STATE_FOCUSED | STATE_SELECTED | states);
+      }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Test
+
+    // gA11yEventDumpID = "debug";
+
+    function doTestActions()
+    {
+      var treeNode = getNode("tree");
+      treeNode.removeEventListener("TreeViewChanged", doTestActions, false);
+
+      var treeBodyNode = treeNode.boxObject.treeBody;
+
+      var tree = getAccessible(treeNode);
+      var expandedTreeItem = tree.getChildAt(2);
+      var collapsedTreeItem = tree.getChildAt(5);
+
+      var actions = [
+        {
+          ID: expandedTreeItem,
+          actionName: "activate",
+          actionIndex: 0,
+          events: CLICK_EVENTS,
+          targetID: treeBodyNode,
+          eventSeq: [
+            new focusChecker(expandedTreeItem, STATE_EXPANDED)
+          ]
+        },
+        {
+          ID: collapsedTreeItem,
+          actionName: "expand",
+          actionIndex: 1,
+          events: CLICK_EVENTS,
+          targetID: treeBodyNode,
+          checkOnClickEvent: function check(aEvent)
+          {
+            testStates(this.ID, STATE_EXPANDED);
+          }
+        },
+        {
+          ID: collapsedTreeItem,
+          actionName: "collapse",
+          actionIndex: 1,
+          events: CLICK_EVENTS,
+          targetID: treeBodyNode,
+          checkOnClickEvent: function check(aEvent)
+          {
+            testStates(this.ID, STATE_COLLAPSED);
+          }
+        }
+      ];
+
+      testActions(actions); // Will call SimpleTest.finish();
+    }
+
+    function doTest()
+    {
+      var treeNode = getNode("tree");
+      treeNode.addEventListener("TreeViewChanged", doTestActions, false);
+      treeNode.view = new nsTreeTreeView();
+    }
+
+    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=503727"
+         title="Reorganize implementation of XUL tree accessibility">
+        Mozilla Bug 503727
+      </a><br/>
+      <p id="display"></p>
+      <div id="content" style="display: none">
+      </div>
+      <pre id="test">
+      </pre>
+    </body>
+
+    <vbox flex="1">
+      <tree id="tree" flex="1" minheight="100px">
+        <treecols>
+          <treecol id="col" flex="1" primary="true" label="column"/>
+        </treecols>
+        <treechildren/>
+      </tree>
+
+      <vbox id="debug"/>
+    </vbox>
+  </hbox>
+
+</window>
+
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_actions_treegrid.xul
@@ -0,0 +1,200 @@
+<?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"?>
+<?xml-stylesheet href="chrome://mochikit/content/a11y/accessible/treeview.css"
+                 type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="Accessible XUL tree actions 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="chrome://mochikit/content/a11y/accessible/treeview.js" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/common.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/states.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/events.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/actions.js" />
+
+  <script type="application/javascript">
+  <![CDATA[
+    ////////////////////////////////////////////////////////////////////////////
+    // Accessible tree testers
+
+    function focusChecker(aAcc, aStates)
+    {
+      this.type = EVENT_FOCUS;
+      this.target = aAcc;
+      this.getID = function focusChecker_getID()
+      {
+        return "focus handling";
+      }
+      this.check = function focusChecker_check(aEvent)
+      {
+        var states = aStates ? aStates : 0;
+        testStates(this.target, STATE_FOCUSED | STATE_SELECTED | states);
+      }
+    }
+
+    function stateChangeChecker(aAcc, aIsEnabled)
+    {
+      this.type = EVENT_STATE_CHANGE;
+      this.target = aAcc;
+      this.getID = function stateChangeChecker_getID()
+      {
+        return "state change handling";
+      }
+      this.check = function stateChangeChecker_check(aEvent)
+      {
+        if (aIsEnabled)
+          testStates(this.target, STATE_CHECKED);
+        else
+          testStates(this.target, STATE_CHECKABLE, 0, STATE_CHECKED);
+      }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Test
+
+    function doTestActions()
+    {
+      var treeNode = getNode("tabletree");
+      treeNode.removeEventListener("TreeViewChanged", doTestActions, false);
+
+      var treeBodyNode = treeNode.boxObject.treeBody;
+      treeNode.focus();
+
+      var tree = getAccessible(treeNode);
+
+      var expandedTreeItem = tree.getChildAt(2);
+      var collapsedTreeItem = tree.getChildAt(5);
+      var cycleCell = expandedTreeItem.getChildAt(0);
+      var checkableCell = expandedTreeItem.getChildAt(3);
+
+      var actions = [
+        {
+          ID: expandedTreeItem,
+          actionName: "activate",
+          actionIndex: 0,
+          events: CLICK_EVENTS,
+          targetID: treeBodyNode,
+          eventSeq: [
+            new focusChecker(expandedTreeItem, STATE_EXPANDED)
+          ]
+        },
+        {
+          ID: collapsedTreeItem,
+          actionName: "expand",
+          actionIndex: 1,
+          events: CLICK_EVENTS,
+          targetID: treeBodyNode,
+          check: function check(aEvent)
+          {
+            testStates(this.ID, STATE_EXPANDED);
+          }
+        },
+        {
+          ID: collapsedTreeItem,
+          actionName: "collapse",
+          actionIndex: 1,
+          events: CLICK_EVENTS,
+          targetID: treeBodyNode,
+          check: function check(aEvent)
+          {
+            testStates(this.ID, STATE_COLLAPSED);
+          }
+        },
+        {
+          ID: cycleCell,
+          actionName: "cycle",
+          actionIndex: 0,
+          events: CLICK_EVENTS,
+          targetID: treeBodyNode
+        },
+        {
+          ID: checkableCell,
+          actionName: "uncheck",
+          actionIndex: 0,
+          events: CLICK_EVENTS,
+          targetID: treeBodyNode,
+          eventSeq: [
+            new stateChangeChecker(checkableCell, false)
+          ]
+        },
+        {
+          ID: checkableCell,
+          actionName: "check",
+          actionIndex: 0,
+          events: CLICK_EVENTS,
+          targetID: treeBodyNode,
+          eventSeq: [
+            new stateChangeChecker(checkableCell, true)
+          ]
+        }
+      ];
+
+      testActions(actions); // Will call SimpleTest.finish();
+    }
+
+    // gA11yEventDumpID = "debug";
+
+    function doTest()
+    {
+      var treeNode = getNode("tabletree");
+      treeNode.addEventListener("TreeViewChanged", doTestActions, false);
+      treeNode.view = new nsTreeTreeView();
+    }
+
+    function test1()
+    {
+      var boxObj = getNode("tabletree").treeBoxObject;
+      boxObj.view.setCellValue(0, boxObj.columns.firstColumn, "false");
+    }
+
+    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=503727"
+         title="Reorganize implementation of XUL tree accessibility">
+        Mozilla Bug 503727
+      </a><br/>
+      <p id="display"></p>
+      <div id="content" style="display: none">
+      </div>
+      <pre id="test">
+      </pre>
+    </body>
+
+    <vbox flex="1">
+      <tree id="tabletree" flex="1" editable="true">
+        <treecols>
+          <treecol id="tabletree_col1" cycler="true" label="cycler"/>
+          <treecol id="tabletree_col2" flex="1" primary="true" label="column1"/>
+          <treecol id="tabletree_col3" flex="1" label="column2"/>
+          <treecol id="tabletree_col4" flex="1" label="checker"
+                   type="checkbox" editable="true"/>
+        </treecols>
+        <treechildren/>
+      </tree>
+
+      <vbox id="debug"/>
+      <button oncommand="test1();" label="uncheck"/>
+    </vbox>
+  </hbox>
+
+</window>
+
--- a/accessible/tests/mochitest/test_aria_roles.html
+++ b/accessible/tests/mochitest/test_aria_roles.html
@@ -1,12 +1,13 @@
 <!DOCTYPE html>
 <html>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=481114
+https://bugzilla.mozilla.org/show_bug.cgi?id=469688
 -->
 <head>
   <title>Test weak ARIA roles</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"
@@ -34,29 +35,43 @@ https://bugzilla.mozilla.org/show_bug.cg
       testRole("application", ROLE_APPLICATION);
 
       // weak landmarks
       var weak_landmarks = ["banner", "complementary", "contentinfo",
           "main", "navigation", "search"];
       for (l in weak_landmarks)
         testRole(weak_landmarks[l], ROLE_SECTION);
 
+      for (l in weak_landmarks) {
+        var id = weak_landmarks[l] + "_table";
+        testRole(id, ROLE_TABLE);
+        
+        var accessibleTable = getAccessible(id, [nsIAccessibleTable], null,
+                                            DONOTFAIL_IF_NO_INTERFACE);
+        ok(accessibleTable ? true : false,
+           "landmarked table should have nsIAccessibleTable");
+        
+        if (accessibleTable)
+          is(accessibleTable.cellRefAt(0,0).firstChild.name, "hi", "no cell");
+      }
+
       // test gEmptyRoleMap
       testRole("cell", ROLE_NOTHING);
 
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addLoadEvent(doTest);
   </script>
 </head>
 <body>
 
   <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=481114">Mozilla Bug 481114</a>
+  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=469688">Mozilla Bug 469688</a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
   
   <!-- "live" roles -->
   <table role="log" id="log_table">
     <tr><td>Table based log</td></tr>
@@ -68,16 +83,32 @@ https://bugzilla.mozilla.org/show_bug.cg
   <div role="application" id="application">application</div>
   <div role="banner" id="banner">banner</div>
   <div role="complementary" id="complementary">complementary</div>
   <div role="contentinfo" id="contentinfo">contentinfo</div>
   <div role="main" id="main">main</div>
   <div role="navigation" id="navigation">navigation</div>
   <div role="search" id="search">search</div>
 
+  <!-- landmarks are tables -->
+  <table role="application" id="application_table">application table
+    <tr><td>hi<td></tr></table>
+  <table role="banner" id="banner_table">banner table
+    <tr><td>hi<td></tr></table>
+  <table role="complementary" id="complementary_table">complementary table
+    <tr><td>hi<td></tr></table>
+  <table role="contentinfo" id="contentinfo_table">contentinfo table
+    <tr><td>hi<td></tr></table>
+  <table role="main" id="main_table">main table
+    <tr><td>hi<td></tr></table>
+  <table role="navigation" id="navigation_table">navigation table
+    <tr><td>hi<td></tr></table>
+  <table role="search" id="search_table">search table
+    <tr><td>hi<td></tr></table>
+
   <!-- test gEmptyRoleMap -->
   <table role="label">
     <tr>
       <td id="cell">cell</td>
     </tr>
   </table>
 
 </body>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_attrs_elm_tree.xul
@@ -0,0 +1,93 @@
+<?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 tree attributes 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="chrome://mochikit/content/a11y/accessible/treeview.js" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/common.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/attributes.js" />
+
+  <script type="application/javascript">
+  <![CDATA[
+    ////////////////////////////////////////////////////////////////////////////
+    // Test
+
+    function doTestAttrs()
+    {
+      var treeNode = getNode("tree");
+      treeNode.removeEventListener("TreeViewChanged", doTestAttrs, false);
+
+      var tree = getAccessible(treeNode);
+      var treeitem1 = tree.firstChild.nextSibling;
+      testGroupAttrs(treeitem1, "1", "4", "1");
+
+      var treeitem2 = treeitem1.nextSibling;
+      testGroupAttrs(treeitem2, "2", "4", "1");
+
+      var treeitem3 = treeitem2.nextSibling;
+      testGroupAttrs(treeitem3, "1", "2", "2");
+
+      var treeitem4 = treeitem3.nextSibling;
+      testGroupAttrs(treeitem4, "2", "2", "2");
+
+      var treeitem5 = treeitem4.nextSibling;
+      testGroupAttrs(treeitem5, "3", "4", "1");
+
+      var treeitem6 = treeitem5.nextSibling;
+      testGroupAttrs(treeitem6, "4", "4", "1");
+
+      SimpleTest.finish();
+    }
+
+    function doTest()
+    {
+      var treeNode = getNode("tree");
+      treeNode.addEventListener("TreeViewChanged", doTestAttrs, false);
+      treeNode.view = new nsTreeTreeView();
+    }
+
+    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=503727"
+         title="Reorganize implementation of XUL tree accessibility">
+        Mozilla Bug 503727
+      </a><br/>
+      <p id="display"></p>
+      <div id="content" style="display: none">
+      </div>
+      <pre id="test">
+      </pre>
+    </body>
+
+    <vbox flex="1">
+      <tree id="tree" flex="1">
+        <treecols>
+          <treecol id="col" flex="1" primary="true" label="column"/>
+        </treecols>
+        <treechildren/>
+      </tree>
+
+      <vbox id="debug"/>
+    </vbox>
+  </hbox>
+
+</window>
+
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_elm_tree.xul
@@ -0,0 +1,185 @@
+<?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 tree hierarchy 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="chrome://mochikit/content/a11y/accessible/treeview.js" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/common.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/role.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/events.js" />
+
+  <script type="application/javascript">
+  <![CDATA[
+    ////////////////////////////////////////////////////////////////////////////
+    // Accessible tree testers
+
+    function getTreeItemAccTree(aTableRole, aColumnsCount)
+    {
+      var treeItemRole;
+      switch (aTableRole) {
+        case ROLE_LIST:
+          treeItemRole = ROLE_LISTITEM;
+          break;
+        case ROLE_OUTLINE:
+          treeItemRole = ROLE_OUTLINEITEM;
+          break;
+        case ROLE_TABLE: case ROLE_TREE_TABLE:
+          treeItemRole = ROLE_ROW;
+          break;
+      }
+
+      var accTree = {
+        role: treeItemRole,
+        children: []
+      };
+
+      if (aTableRole == ROLE_TABLE || aTableRole == ROLE_TREE_TABLE) {
+        for (var idx = 0; idx < aColumnsCount; idx++) {
+          var cellAccTree = {
+            role: ROLE_GRID_CELL,
+            children: []
+          };
+          accTree.children.push(cellAccTree);
+        }
+      }
+
+      return accTree;
+    }
+
+    function testAccessibleTreeFor(aTree, aRole)
+    {
+      var accTreeForColumns = {
+        role: ROLE_LIST,
+        children: []
+      };
+
+      var accTreeForTree = {
+        role: aRole,
+        children: [
+          accTreeForColumns
+        ]
+      };
+
+      var treeBoxObject = aTree.treeBoxObject;
+      var view = treeBoxObject.view;
+      var columnsCount = treeBoxObject.columns.count;
+
+      for (var idx = 0; idx < columnsCount; idx++)
+        accTreeForColumns.children.push({ role: ROLE_COLUMNHEADER, children: []});
+      if (!aTree.hasAttribute("hidecolumnpicker"))
+        accTreeForColumns.children.push({ role: ROLE_PUSHBUTTON, children: []});
+
+      for (var idx = 0; idx < view.rowCount; idx++)
+        accTreeForTree.children.push(getTreeItemAccTree(aRole, columnsCount));
+
+      testAccessibleTree(aTree, accTreeForTree);
+    }
+
+    /**
+     * Event queue invoker object to test accessible tree for XUL tree element.
+     */
+    function treeChecker(aID, aView, aRole)
+    {
+      this.DOMNode = getNode(aID);
+
+      this.invoke = function invoke()
+      {
+        this.DOMNode.treeBoxObject.view = aView;
+      }
+      this.check = function check(aEvent)
+      {
+        testAccessibleTreeFor(this.DOMNode, aRole);
+      }
+      this.getID = function getID()
+      {
+        return "Tree testing of " + aID;
+      }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Test
+
+    // gA11yEventDumpID = "debug";
+    var gQueue = null;
+
+    function doTest()
+    {
+      var gQueue = new eventQueue("TreeViewChanged");
+
+      gQueue.push(new treeChecker("list", new nsTableTreeView(3), ROLE_LIST));
+      gQueue.push(new treeChecker("tree", new nsTreeTreeView(), ROLE_OUTLINE));
+      gQueue.push(new treeChecker("table", new nsTableTreeView(3), ROLE_TABLE));
+      gQueue.push(new treeChecker("treetable", new nsTreeTreeView(), ROLE_TREE_TABLE));
+
+      gQueue.invoke(); // Will call 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=503727"
+         title="Reorganize implementation of XUL tree accessibility">
+        Mozilla Bug 503727
+      </a><br/>
+      <p id="display"></p>
+      <div id="content" style="display: none">
+      </div>
+      <pre id="test">
+      </pre>
+    </body>
+
+    <vbox flex="1">
+      <tree id="list" flex="1" hidecolumnpicker="true">
+        <treecols>
+          <treecol id="col" flex="1" hideheader="true"/>
+        </treecols>
+        <treechildren/>
+      </tree>
+
+      <tree id="tree" flex="1">
+        <treecols>
+          <treecol id="col" flex="1" primary="true" label="column"/>
+        </treecols>
+        <treechildren/>
+      </tree>
+
+      <tree id="table" flex="1">
+        <treecols>
+          <treecol id="col1" flex="1" label="column"/>
+          <treecol id="col2" flex="1" label="column 2"/>
+        </treecols>
+        <treechildren/>
+      </tree>
+
+      <tree id="treetable" flex="1">
+        <treecols>
+          <treecol id="col1" flex="1" primary="true" label="column"/>
+          <treecol id="col2" flex="1" label="column 2"/>
+        </treecols>
+        <treechildren/>
+      </tree>
+
+      <vbox id="debug"/>
+    </vbox>
+  </hbox>
+
+</window>
+
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_events_draganddrop.html
@@ -0,0 +1,112 @@
+<html>
+
+<head>
+  <title>Accessible drag and drop event testing</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/a11y/accessible/common.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/events.js"></script>
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/attributes.js"></script>
+
+  <script type="application/javascript">
+
+    /**
+     * Do tests.
+     */
+    var gQueue = null;
+
+    // aria grabbed invoker
+    function changeGrabbed(aNodeOrID, aGrabValue)
+    {
+      this.DOMNode = getNode(aNodeOrID);
+
+      this.invoke = function changeGrabbed_invoke() {
+        if (aGrabValue != undefined) {
+          this.DOMNode.setAttribute("aria-grabbed", aGrabValue);
+        }
+      }
+
+      this.check = function changeGrabbed_check() {
+        testAttrs(aNodeOrID, {"grabbed" : aGrabValue}, true);
+      }
+
+      this.getID = function changeGrabbed_getID() {
+        return prettyName(aNodeOrID) + " aria-grabbed changed";
+      }
+    }
+
+    // aria dropeffect invoker
+    function changeDropeffect(aNodeOrID, aDropeffectValue)
+    {
+      this.DOMNode = getNode(aNodeOrID);
+
+      this.invoke = function changeDropeffect_invoke() {
+        if (aDropeffectValue != undefined) {
+          this.DOMNode.setAttribute("aria-dropeffect", aDropeffectValue);
+        }
+      }
+
+      this.check = function changeDropeffect_check() {
+        testAttrs(aNodeOrID, {"dropeffect" : aDropeffectValue}, true);
+      }
+
+      this.getID = function changeDropeffect_getID() {
+        return prettyName(aNodeOrID) + " aria-dropeffect changed";
+      }
+    }
+
+    function doTests()
+    {
+      // Test aria attribute mutation events
+      gQueue = new eventQueue(nsIAccessibleEvent.EVENT_OBJECT_ATTRIBUTE_CHANGED);
+
+      var id="grabbable";
+      gQueue.push(new changeGrabbed(id, "true"));
+      gQueue.push(new changeGrabbed(id, "false"));
+      todo(false, "uncomment this test when 472142 is fixed.");
+      //gQueue.push(new changeGrabbed(id, "undefined"));
+
+      var id="dropregion";
+      gQueue.push(new changeDropeffect(id, "copy"));
+      gQueue.push(new changeDropeffect(id, "execute"));
+
+      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=510441"
+     title="Add support for nsIAccessibleEvent::OBJECT_ATTRIBUTE_CHANGED">
+    Mozilla Bug 510441
+  </a>
+
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+  <div id="eventdump"></div>
+
+  <!-- ARIA grabbed -->
+  <div id="grabbable" role="button" aria-grabbed="foo">button</div>
+
+  <!-- ARIA dropeffect -->
+  <div id="dropregion" role="region" aria-dropeffect="none">button</div>
+</body>
+</html>
--- a/accessible/tests/mochitest/test_events_tree.xul
+++ b/accessible/tests/mochitest/test_events_tree.xul
@@ -26,16 +26,34 @@
 
   <script type="application/javascript">
   <![CDATA[
 
     ////////////////////////////////////////////////////////////////////////////
     // Invoker's checkers
 
     /**
+     * Check TreeViewChanged event and run through accessible tree to ensure
+     * it's created.
+     */
+    function treeViewChangedChecker(aMsg)
+    {
+      this.type = "TreeViewChanged";
+      this.target = gTree;
+      this.check = function check(aEvent)
+      {
+        ensureAccessibleTree(gTree);
+      }
+      this.getID = function getID()
+      {
+        return "TreeViewChanged";
+      }
+    }
+
+    /**
      * Check TreeRowCountChanged event.
      */
     function rowCountChangedChecker(aMsg, aIdx, aCount)
     {
       this.type = "TreeRowCountChanged";
       this.target = gTree;
       this.check = function check(aEvent)
       {
@@ -88,23 +106,18 @@
     function nameChangeChecker(aMsg, aRow, aCol)
     {
       this.type = EVENT_NAME_CHANGE;
 
       this.target getter = function()
       {
         var acc = getAccessible(gTree);
 
-        var tableAcc = getAccessible(acc, [nsIAccessibleTable], null,
-                                     DONOTFAIL_IF_NO_INTERFACE);
-
-        if (tableAcc)
-          return tableAcc.cellRefAt(aRow, aCol);
-
-        return acc.getChildAt(aRow + 1);
+        var tableAcc = getAccessible(acc, [nsIAccessibleTable]);
+        return tableAcc.cellRefAt(aRow, aCol);
       }
       this.getID = function getID()
       {
         return aMsg + "name changed";
       }
     }
 
     ////////////////////////////////////////////////////////////////////////////
@@ -117,28 +130,28 @@
     {
       this.invoke = function setTreeView_invoke()
       {
         gTreeBox.view = gView;
       }
 
       this.getID = function setTreeView_getID() { return "TreeViewChanged"; }
 
-      this.eventSeq = [ new invokerChecker("TreeViewChanged", gTree) ];
+      this.eventSeq = [ new treeViewChangedChecker() ];
     };
 
     /**
      * Insert row at 0 index and checks TreeRowCountChanged and TreeInvalidated
      * event.
      */
     function insertRow()
     {
       this.invoke = function insertRow_invoke()
       {
-        ++gView.mRowCount;
+        gView.appendItem("last");
         gTreeBox.rowCountChanged(0, 1);
       }
 
       this.eventSeq =
       [
         new rowCountChangedChecker("insertRow: ", 0, 1),
         new treeInvalidatedChecker("insertRow", 0, 5, null, null)
       ];
@@ -149,28 +162,24 @@
      * treeitem plus TreeInvalidated event.
      */
     function invalidateColumn()
     {
       this.invoke = function()
       {
         // Make sure accessibles for the tree is created because it makes
         // sure accessible events will be fired.
-        var treeAcc = getAccessible(gTree);
-
-        // Makes sure tree children accessibles are created otherwise they won't
+        // Make sure tree children accessibles are created otherwise they won't
         // be a cause of name changed events.
-        var children = treeAcc.children;
+        ensureAccessibleTree(gTree);
 
         // Fire 'TreeInvalidated' event by InvalidateColumn()
         var firstCol = gTree.columns.getFirstColumn();
-        for (var i = 0; i < gView.mRowCount; i++) {
-          var key = String(i) + firstCol.id;
-          gView.mData[key] = key + "_col";
-        }
+        for (var i = 0; i < gView.rowCount; i++)
+          gView.setCellText(i, firstCol, "hey " + String(i) + "x0");
 
         gTreeBox.invalidateColumn(firstCol);
       }
 
       this.eventSeq =
       [
         new nameChangeChecker("invalidateColumn: &quo