Merging mozilla-central to mozilla-qt.
authorOleg Romashin <romaxa@gmail.com>
Sun, 03 Aug 2008 20:30:10 +0300
changeset 16951 10b845068cff1bbfcc5421b0039dfdc1ab2f7733
parent 16950 814e972a6658d42410c23325df4e1222566283da (current diff)
parent 16338 d12488eef3f550053b0f3ecb4402c6eb13f8135b (diff)
child 16952 a8b558d55351a8ab4f0a064e95b4f8f766fb4db4
push idunknown
push userunknown
push dateunknown
milestone1.9.1a2pre
Merging mozilla-central to mozilla-qt.
.hgignore
browser/base/content/pageReport.js
browser/base/content/pageReport.xul
browser/locales/en-US/chrome/browser/pageReport.dtd
browser/locales/en-US/chrome/help/accessibility.xhtml
browser/locales/en-US/chrome/help/cookies.xhtml
browser/locales/en-US/chrome/help/customization.xhtml
browser/locales/en-US/chrome/help/download_manager.xhtml
browser/locales/en-US/chrome/help/firebird-toc.rdf
browser/locales/en-US/chrome/help/firebirdhelp.rdf
browser/locales/en-US/chrome/help/firefox_welcome.xhtml
browser/locales/en-US/chrome/help/forieusers.xhtml
browser/locales/en-US/chrome/help/glossary.xhtml
browser/locales/en-US/chrome/help/menu_reference.xhtml
browser/locales/en-US/chrome/help/mouse_shortcuts.xhtml
browser/locales/en-US/chrome/help/platformStrings.dtd
browser/locales/en-US/chrome/help/popup.xhtml
browser/locales/en-US/chrome/help/prefs.xhtml
browser/locales/en-US/chrome/help/search-db.rdf
browser/locales/en-US/chrome/help/shortcuts.xhtml
browser/locales/en-US/chrome/help/tabbed_browsing.xhtml
browser/locales/en-US/chrome/help/using_firebird.xhtml
browser/locales/en-US/extra-jar.mn
browser/themes/gnomestripe/browser/preferences/plugin.png
browser/themes/pinstripe/browser/preferences/plugin.png
browser/themes/winstripe/browser/Search-close-aero.png
browser/themes/winstripe/browser/Search-close.png
browser/themes/winstripe/browser/preferences/plugin.png
browser/themes/winstripe/browser/searchButtons-aero.png
browser/themes/winstripe/browser/searchButtons.png
browser/themes/winstripe/browser/siteButtons-aero.png
browser/themes/winstripe/browser/siteButtons.png
config/autoconf.mk.in
config/rules.mk
configure.in
content/svg/content/src/nsSVGAnimatedString.cpp
content/svg/content/src/nsSVGAnimatedString.h
content/xul/document/src/nsElementMap.cpp
content/xul/document/src/nsElementMap.h
editor/ui/composer/content/pref-publish.xul
editor/ui/locales/en-US/chrome/composer/pref-publish.dtd
extensions/canvas3d/Makefile.in
extensions/canvas3d/doc/glweb20spec.html
extensions/canvas3d/install.rdf
extensions/canvas3d/jar.mn
extensions/canvas3d/public/Makefile.in
extensions/canvas3d/public/nsICanvasGLPrivate.idl
extensions/canvas3d/public/nsICanvasRenderingContextGL.idl
extensions/canvas3d/public/nsICanvasRenderingContextGLBuffer.idl
extensions/canvas3d/public/nsICanvasRenderingContextGLES11.idl
extensions/canvas3d/public/nsICanvasRenderingContextGLWeb20.idl
extensions/canvas3d/resources/content/options.xul
extensions/canvas3d/src/Makefile.in
extensions/canvas3d/src/glew.c
extensions/canvas3d/src/glew.h
extensions/canvas3d/src/glewinfo.c
extensions/canvas3d/src/glxew.h
extensions/canvas3d/src/nsCanvas3DModule.cpp
extensions/canvas3d/src/nsCanvasRenderingContextGL.cpp
extensions/canvas3d/src/nsCanvasRenderingContextGL.h
extensions/canvas3d/src/nsCanvasRenderingContextGLES11.cpp
extensions/canvas3d/src/nsCanvasRenderingContextGLWeb20.cpp
extensions/canvas3d/src/nsGLPbuffer.cpp
extensions/canvas3d/src/nsGLPbuffer.h
extensions/canvas3d/src/visualinfo.c
extensions/canvas3d/src/wglew.h
extensions/canvas3d/test/3dtest1.html
extensions/canvas3d/test/3dtest2.html
extensions/canvas3d/test/3dtest3.html
extensions/canvas3d/test/3dtest4.html
extensions/canvas3d/test/3dtest5.html
extensions/canvas3d/test/tex.png
gfx/cairo/cairo/src/Makefile.in
gfx/cairo/cairo/src/cairo-debug.h
gfx/cairo/cairo/src/cairo.h
gfx/cairo/libpixman/src/pixman-combine.c
gfx/cairo/libpixman/src/pixman-remap.h
gfx/cairo/libpixman/src/pixman.h
gfx/public/nsWatchTask.h
gfx/src/shared/ignorable.x-ccmap
gfx/src/thebes/nsThebesDeviceContext.cpp
gfx/thebes/public/Makefile.in
gfx/thebes/src/gfxFont.cpp
gfx/thebes/src/gfxPlatform.cpp
intl/unicharutil/src/ignorables_abjadpoints.x-ccmap
js/src/fdlibm/Makefile.in
js/src/fdlibm/Makefile.ref
js/src/fdlibm/e_acos.c
js/src/fdlibm/e_acosh.c
js/src/fdlibm/e_asin.c
js/src/fdlibm/e_atan2.c
js/src/fdlibm/e_atanh.c
js/src/fdlibm/e_cosh.c
js/src/fdlibm/e_exp.c
js/src/fdlibm/e_fmod.c
js/src/fdlibm/e_gamma.c
js/src/fdlibm/e_gamma_r.c
js/src/fdlibm/e_hypot.c
js/src/fdlibm/e_j0.c
js/src/fdlibm/e_j1.c
js/src/fdlibm/e_jn.c
js/src/fdlibm/e_lgamma.c
js/src/fdlibm/e_lgamma_r.c
js/src/fdlibm/e_log.c
js/src/fdlibm/e_log10.c
js/src/fdlibm/e_pow.c
js/src/fdlibm/e_rem_pio2.c
js/src/fdlibm/e_remainder.c
js/src/fdlibm/e_scalb.c
js/src/fdlibm/e_sinh.c
js/src/fdlibm/e_sqrt.c
js/src/fdlibm/fdlibm.h
js/src/fdlibm/fdlibm.mak
js/src/fdlibm/fdlibm.mdp
js/src/fdlibm/k_cos.c
js/src/fdlibm/k_rem_pio2.c
js/src/fdlibm/k_sin.c
js/src/fdlibm/k_standard.c
js/src/fdlibm/k_tan.c
js/src/fdlibm/s_asinh.c
js/src/fdlibm/s_atan.c
js/src/fdlibm/s_cbrt.c
js/src/fdlibm/s_ceil.c
js/src/fdlibm/s_copysign.c
js/src/fdlibm/s_cos.c
js/src/fdlibm/s_erf.c
js/src/fdlibm/s_expm1.c
js/src/fdlibm/s_fabs.c
js/src/fdlibm/s_finite.c
js/src/fdlibm/s_floor.c
js/src/fdlibm/s_frexp.c
js/src/fdlibm/s_ilogb.c
js/src/fdlibm/s_isnan.c
js/src/fdlibm/s_ldexp.c
js/src/fdlibm/s_lib_version.c
js/src/fdlibm/s_log1p.c
js/src/fdlibm/s_logb.c
js/src/fdlibm/s_matherr.c
js/src/fdlibm/s_modf.c
js/src/fdlibm/s_nextafter.c
js/src/fdlibm/s_rint.c
js/src/fdlibm/s_scalbn.c
js/src/fdlibm/s_signgam.c
js/src/fdlibm/s_significand.c
js/src/fdlibm/s_sin.c
js/src/fdlibm/s_tan.c
js/src/fdlibm/s_tanh.c
js/src/fdlibm/w_acos.c
js/src/fdlibm/w_acosh.c
js/src/fdlibm/w_asin.c
js/src/fdlibm/w_atan2.c
js/src/fdlibm/w_atanh.c
js/src/fdlibm/w_cosh.c
js/src/fdlibm/w_exp.c
js/src/fdlibm/w_fmod.c
js/src/fdlibm/w_gamma.c
js/src/fdlibm/w_gamma_r.c
js/src/fdlibm/w_hypot.c
js/src/fdlibm/w_j0.c
js/src/fdlibm/w_j1.c
js/src/fdlibm/w_jn.c
js/src/fdlibm/w_lgamma.c
js/src/fdlibm/w_lgamma_r.c
js/src/fdlibm/w_log.c
js/src/fdlibm/w_log10.c
js/src/fdlibm/w_pow.c
js/src/fdlibm/w_remainder.c
js/src/fdlibm/w_scalb.c
js/src/fdlibm/w_sinh.c
js/src/fdlibm/w_sqrt.c
js/src/js.cpp
js/src/js.mak
js/src/jsapi.cpp
js/src/jsarena.cpp
js/src/jsarray.cpp
js/src/jsatom.cpp
js/src/jsbool.cpp
js/src/jscntxt.cpp
js/src/jscpucfg.cpp
js/src/jsdate.cpp
js/src/jsdbgapi.cpp
js/src/jsdhash.cpp
js/src/jsdtoa.cpp
js/src/jsemit.cpp
js/src/jsexn.cpp
js/src/jsfile.cpp
js/src/jsfun.cpp
js/src/jsgc.cpp
js/src/jshash.cpp
js/src/jsinterp.cpp
js/src/jsinvoke.cpp
js/src/jsiter.cpp
js/src/jskwgen.cpp
js/src/jslock.cpp
js/src/jslog2.cpp
js/src/jslong.cpp
js/src/jsmath.cpp
js/src/jsnum.cpp
js/src/jsobj.cpp
js/src/jsopcode.cpp
js/src/jsparse.cpp
js/src/jsprf.cpp
js/src/jsregexp.cpp
js/src/jsscan.cpp
js/src/jsscope.cpp
js/src/jsscript.cpp
js/src/jsstr.cpp
js/src/jsutil.cpp
js/src/jsxdrapi.cpp
js/src/jsxml.cpp
js/src/prmjtime.cpp
js/tests/create-patterns.pl
js/tests/test-browser.sh
js/tests/test-shell.sh
layout/base/nsICaret.h
layout/generic/punct_marks.ccmap
memory/jemalloc/tree.h
modules/oji/public/nsIJVMAuthTools.idl
modules/oji/src/nsJVMAuthTools.cpp
modules/oji/src/nsJVMAuthTools.h
testing/mochitest/runtests.pl.in
testing/sisyphus/data/download-check,firefox-1.5.0-ftp,mac.data
testing/sisyphus/data/download-check,firefox-1.5.0-ftp,win32.data
testing/sisyphus/data/download-check,firefox-2.0.0-ftp,mac.data
testing/sisyphus/data/download-check,firefox-2.0.0-ftp,win32.data
testing/sisyphus/data/download-check,firefox-all,mac.data
testing/sisyphus/data/download-check,firefox-all,win32.data
testing/sisyphus/data/download-check,firefox-all-older,mac.data
testing/sisyphus/data/download-check,firefox-all-older,win32.data
testing/sisyphus/data/download-check,thunderbird-1.5.0-ftp,mac.data
testing/sisyphus/data/download-check,thunderbird-1.5.0-ftp,win32.data
testing/sisyphus/data/download-check,thunderbird-2.0.0-ftp,mac.data
testing/sisyphus/data/download-check,thunderbird-2.0.0-ftp,win32.data
testing/sisyphus/data/download-check,thunderbird-all,mac.data
testing/sisyphus/data/download-check,thunderbird-all,win32.data
testing/sisyphus/data/download-check,thunderbird-all-older,mac.data
testing/sisyphus/data/download-check,thunderbird-all-older,win32.data
testing/sisyphus/data/firefox,1.8.0,nightly-mac.data
testing/sisyphus/data/firefox,1.8.0,nightly-win32.data
testing/sisyphus/data/firefox,1.8.1,nightly-mac.data
testing/sisyphus/data/firefox,1.8.1,nightly-win32.data
testing/sisyphus/data/firefox,1.9.0,nightly-mac.data
testing/sisyphus/data/firefox,1.9.0,nightly-win32.data
toolkit/Makefile.in
toolkit/content/tests/chrome/bug288254_window.xul
toolkit/content/tests/chrome/test_bug288254.xul
toolkit/library/Makefile.in
toolkit/library/libxul-config.mk
toolkit/library/nsStaticXULComponents.cpp
toolkit/mozapps/downloads/tests/browser/Makefile.in
toolkit/mozapps/downloads/tests/browser/browser_basic_functionality.js
toolkit/mozapps/downloads/tests/browser/browser_bug_394039.js
toolkit/mozapps/downloads/tests/browser/browser_bug_397935.js
toolkit/mozapps/downloads/tests/browser/browser_bug_406857.js
toolkit/mozapps/downloads/tests/browser/browser_bug_410289.js
toolkit/mozapps/downloads/tests/browser/browser_bug_411172.js
toolkit/mozapps/downloads/tests/browser/browser_bug_411172_mac.js
toolkit/mozapps/downloads/tests/browser/browser_bug_412360.js
toolkit/mozapps/downloads/tests/browser/browser_bug_413093.js
toolkit/mozapps/downloads/tests/browser/browser_bug_413985.js
toolkit/mozapps/downloads/tests/browser/browser_bug_416303.js
toolkit/mozapps/downloads/tests/browser/browser_cleanup_search.js
toolkit/mozapps/downloads/tests/browser/browser_multi_select.js
toolkit/mozapps/downloads/tests/browser/browser_multiword_search.js
toolkit/mozapps/downloads/tests/browser/browser_select_all.js
toolkit/themes/winstripe/mozapps/downloads/buttons-aero.png
toolkit/themes/winstripe/mozapps/downloads/buttons.png
toolkit/themes/winstripe/mozapps/extensions/searchIcons-aero.png
toolkit/themes/winstripe/mozapps/extensions/searchIcons.png
toolkit/toolkit-tiers.mk
toolkit/xre/nsAppRunner.cpp
tools/patcher/MozAUSConfig.pm
tools/patcher/MozAUSLib.pm
tools/patcher/patcher2.cfg
tools/patcher/patcher2.pl
tools/release/Bootstrap/Config.pm
tools/release/Bootstrap/Step.pm
tools/release/Bootstrap/Step/Build.pm
tools/release/Bootstrap/Step/PatcherConfig.pm
tools/release/Bootstrap/Step/Repack.pm
tools/release/Bootstrap/Step/Sign.pm
tools/release/Bootstrap/Step/Source.pm
tools/release/Bootstrap/Step/Stage.pm
tools/release/Bootstrap/Step/Tag.pm
tools/release/Bootstrap/Step/Tag/Bump.pm
tools/release/Bootstrap/Step/Tag/Mozilla.pm
tools/release/Bootstrap/Step/Tag/Talkback.pm
tools/release/Bootstrap/Step/Tag/l10n.pm
tools/release/Bootstrap/Step/TinderConfig.pm
tools/release/Bootstrap/Step/Updates.pm
tools/release/Bootstrap/Util.pm
tools/release/Makefile
tools/release/MozBuild/TinderLogParse.pm
tools/release/MozBuild/Util.pm
tools/release/README
tools/release/bin/backupsnip
tools/release/bin/pushsnip
tools/release/bin/verify-locales.pl
tools/release/bootstrap.cfg.example
tools/release/configs/fx-moz18-bootstrap.cfg
tools/release/configs/fx-moz18-nightly-bootstrap.cfg
tools/release/configs/fx-moz18-nightly-staging-bootstrap.cfg
tools/release/configs/fx-moz18-staging-bootstrap.cfg
tools/release/configs/fx-moz180-bootstrap.cfg
tools/release/configs/fx-moz19-bootstrap.cfg
tools/release/configs/fx-moz19-nightly-bootstrap.cfg
tools/release/configs/fx-moz19-nightly-staging-bootstrap.cfg
tools/release/configs/fx-moz19-staging-bootstrap.cfg
tools/release/configs/tb-moz18-bootstrap.cfg
tools/release/configs/tb-moz18-staging-bootstrap.cfg
tools/release/configs/tb-moz180-bootstrap.cfg
tools/release/configs/xr-moz19-bootstrap.cfg
tools/release/configs/xr-moz19-staging-bootstrap.cfg
tools/release/release
tools/release/t/Bootstrap/Step/Dummy.pm
tools/release/t/test.pl
tools/release/t/tinder-config.pl.orig
uriloader/exthandler/Makefile.in
widget/public/nsIKBStateControl.h
widget/public/nsIMenuBar.h
widget/src/cocoa/nsIMenu.h
widget/src/cocoa/nsIMenuItem.h
xpcom/static-checking.js
xpfe/components/alerts/Makefile.in
xpfe/components/alerts/public/Makefile.in
xpfe/components/alerts/public/nsIAlertsService.idl
xpfe/components/alerts/src/Makefile.in
xpfe/components/alerts/src/nsAlertsService.cpp
xpfe/components/alerts/src/nsAlertsService.h
xpfe/components/console/Makefile.in
xpfe/components/console/jsconsole-clhandler.js
xpfe/components/console/resources/content/console.css
xpfe/components/console/resources/content/console.js
xpfe/components/console/resources/content/console.xul
xpfe/components/console/resources/content/consoleBindings.xml
xpfe/components/console/resources/locale/en-US/console.dtd
xpfe/components/console/resources/locale/en-US/console.properties
xpfe/components/extensions/Makefile.in
xpfe/components/extensions/public/Makefile.in
xpfe/components/extensions/public/nsIExtensionManager.idl
xpfe/components/extensions/src/Makefile.in
xpfe/components/extensions/src/nsExtensionManager.js
xpfe/components/updates/Makefile.in
xpfe/components/updates/src/Makefile.in
xpfe/components/updates/src/README.html
xpfe/components/updates/src/nsUpdateNotifier.js
--- a/.hgignore
+++ b/.hgignore
@@ -1,29 +1,27 @@
 # .hgignore - List of filenames hg should ignore
 
 # Filenames that should be ignored wherever they appear
 ~$
 \.pyc$
+(^|/)TAGS$
 
 # User files that may appear at the root
 ^\.mozconfig$
+^mozconfig$
 ^\.mozconfig\.mk$
 ^\.mozconfig\.out$
 ^configure$
 ^config\.cache$
 ^config\.log$
+^ID$
 
-# subtrees from other repositories
-^nsprpub/
-^dbm/
-^security/nss/
-^security/coreconf/
-^security/dbm/
+# Empty marker file that's generated when we check out NSS
+^security/manager/\.nss\.checkout$
 
 # Build directories
-^obj-
-^objdir
+^obj
 
 # Build directories for js shell
 _DBG\.OBJ/
 _OPT\.OBJ/
 
--- a/.hgtags
+++ b/.hgtags
@@ -1,3 +1,10 @@
 df7a3c8ffeeaba229067efee5a20e21dae0dd877 MOZILLA_1_9_a4_BASE
 4209e16b58411750ac73f761023e46b76b793e2c MOZILLA_1_9_a6_BASE
 66a5c7bce7ee86a820d3c0d54fa07cb719be751c MOZILLA_1_9_a7_BASE
+caeba7562e495a9f604984df0b48b6f99bec3e2e FENNEC_M4
+9d9941eacb14827fdab4716710042fdde84eb60d FIREFOX_3_1a1_RELEASE
+9d9941eacb14827fdab4716710042fdde84eb60d FIREFOX_3_1a1_BUILD1
+c1d7e318a27574c995631fec166ad42672475702 FIREFOX_3_1a1_BUILD2
+c1d7e318a27574c995631fec166ad42672475702 FIREFOX_3_1a1_RELEASE
+afc4ee509d9ca3bb4031015c3c22963dcb4b7e7f FIREFOX_3_1a1_RELEASE
+afc4ee509d9ca3bb4031015c3c22963dcb4b7e7f FIREFOX_3_1a1_BUILD2
--- a/Makefile.in
+++ b/Makefile.in
@@ -61,16 +61,21 @@ tier_base_dirs = \
 	build \
 	probes \
 	$(NULL)
 
 ifdef MOZ_MEMORY
 tier_base_dirs += memory/jemalloc
 endif
 
+ifdef ENABLE_TESTS
+# Additional makefile targets to call automated test suites
+include $(topsrcdir)/testing/testsuite-targets.mk
+endif
+
 include $(topsrcdir)/$(MOZ_BUILD_APP)/build.mk
 
 TIERS += testharness
 
 # test harnesses
 ifdef ENABLE_TESTS
 tier_testharness_dirs += tools/test-harness
 endif
--- a/accessible/public/msaa/ISimpleDOMDocument.idl
+++ b/accessible/public/msaa/ISimpleDOMDocument.idl
@@ -87,40 +87,32 @@ cpp_quote("// * See latest W3C CSS specs
 cpp_quote("//")
 cpp_quote("//")
 cpp_quote("///////////////////////////////////////////////////////////////////////////////////////////////////////")
 cpp_quote("")
 cpp_quote("")
 
 import "objidl.idl";
 import "oaidl.idl";
-        
-        
-const long DISPID_DOC_URL         = -5904;
-const long DISPID_DOC_TITLE       = -5905;
-const long DISPID_DOC_MIMETYPE    = -5906;
-const long DISPID_DOC_DOCTYPE     = -5907;
-const long DISPID_DOC_NAMESPACE   = -5908;
-const long DISPID_DOC_MEDIATYPES  = -5909;
 
 [object, uuid(0D68D6D0-D93D-4d08-A30D-F00DD1F45B24)]
 interface ISimpleDOMDocument : IUnknown
 {
-  [propget, id(DISPID_DOC_URL)] HRESULT URL(
+  [propget] HRESULT URL(
     [out, retval] BSTR * url
   );
-  [propget, id(DISPID_DOC_TITLE)] HRESULT title(
+  [propget] HRESULT title(
     [out, retval] BSTR * title
   );
-  [propget, id(DISPID_DOC_MIMETYPE)] HRESULT mimeType(
+  [propget] HRESULT mimeType(
     [out, retval] BSTR * mimeType
   );
-  [propget, id(DISPID_DOC_DOCTYPE)] HRESULT docType(
+  [propget] HRESULT docType(
     [out, retval] BSTR * docType
   );
-  [propget, id(DISPID_DOC_NAMESPACE)] HRESULT nameSpaceURIForID(
+  [propget] HRESULT nameSpaceURIForID(
     [in]  short nameSpaceID,
     [out, retval] BSTR * nameSpaceURI
   );
-  [propput, id(DISPID_DOC_MEDIATYPES)] HRESULT alternateViewMediaTypes(
+  [propput] HRESULT alternateViewMediaTypes(
     [in] BSTR * commaSeparatedMediaTypes
 	);
 }
--- a/accessible/public/msaa/ISimpleDOMNode.idl
+++ b/accessible/public/msaa/ISimpleDOMNode.idl
@@ -128,23 +128,19 @@ cpp_quote("// Returns the computed langu
 cpp_quote("//")
 cpp_quote("//")
 cpp_quote("///////////////////////////////////////////////////////////////////////////////////////////////////////")
 cpp_quote("")
 cpp_quote("")
 
 import "objidl.idl";
 import "oaidl.idl";
-        
-const long DISPID_NODE_NODEINFO   = -5900;
-const long DISPID_NODE_ATTRIBUTES = -5901;
-const long DISPID_NODE_ATTRIBUTESFORNAMES = -5902;
-const long DISPID_NODE_COMPSTYLE  = -5903;
-const long DISPID_NODE_COMPSTYLEFORPROPS = -5904;
-const long DISPID_NODE_LANGUAGE = -5905;
+
+import "ISimpleDOMText.idl";
+import "ISimpleDOMDocument.idl";
 
 [object, uuid(1814ceeb-49e2-407f-af99-fa755a7d2607)]
 interface ISimpleDOMNode : IUnknown
 {
   const unsigned short NODETYPE_ELEMENT = 1;
   const unsigned short NODETYPE_ATTRIBUTE = 2;
   const unsigned short NODETYPE_TEXT = 3;
   const unsigned short NODETYPE_CDATA_SECTION = 4;
@@ -152,49 +148,49 @@ interface ISimpleDOMNode : IUnknown
   const unsigned short NODETYPE_ENTITY = 6;
   const unsigned short NODETYPE_PROCESSING_INSTRUCTION = 7;
   const unsigned short NODETYPE_COMMENT = 8;
   const unsigned short NODETYPE_DOCUMENT = 9;
   const unsigned short NODETYPE_DOCUMENT_TYPE = 10;
   const unsigned short NODETYPE_DOCUMENT_FRAGMENT = 11;
   const unsigned short NODETYPE_NOTATION = 12;
 
-  [propget, id(DISPID_NODE_NODEINFO)] HRESULT nodeInfo(
+  [propget] HRESULT nodeInfo(
     [out] BSTR *nodeName,   // for performance returns NULL for text nodes (true nodeName would be "#text")
     [out] short *nameSpaceID,
     [out] BSTR *nodeValue,
     [out] unsigned int *numChildren,
     [out] unsigned int *uniqueID, // In Win32 accessible events we generate, the target's childID matches to this
     [out, retval] unsigned short *nodeType
   );
 
-  [propget, id(DISPID_NODE_ATTRIBUTES)] HRESULT attributes(  
+  [propget] HRESULT attributes(  
     [in] unsigned short maxAttribs,
     [out, size_is(maxAttribs), length_is(*numAttribs)] BSTR *attribNames, 
     [out, size_is(maxAttribs), length_is(*numAttribs)] short *nameSpaceID,  
     [out, size_is(maxAttribs), length_is(*numAttribs)] BSTR *attribValues,
     [out, retval] unsigned short *numAttribs
   );
 
-  [propget, id(DISPID_NODE_ATTRIBUTESFORNAMES)] HRESULT attributesForNames(  
+  [propget] HRESULT attributesForNames(  
     [in] unsigned short numAttribs,
     [in, size_is(numAttribs), length_is(numAttribs)] BSTR *attribNames, 
     [in, size_is(numAttribs), length_is(numAttribs)] short *nameSpaceID,  
     [out, retval, size_is(numAttribs), length_is(numAttribs)] BSTR *attribValues
   );
 
-  [propget, id(DISPID_NODE_COMPSTYLE)] HRESULT computedStyle(  
+  [propget] HRESULT computedStyle(  
     [in] unsigned short maxStyleProperties,
     [in] boolean useAlternateView,  // If TRUE, returns properites for media as set in nsIDOMDocument::set_alternateViewMediaTypes
     [out, size_is(maxStyleProperties), length_is(*numStyleProperties)] BSTR *styleProperties, 
     [out, size_is(maxStyleProperties), length_is(*numStyleProperties)] BSTR *styleValues,
     [out, retval] unsigned short *numStyleProperties
   );
 
-  [propget, id(DISPID_NODE_COMPSTYLEFORPROPS)] HRESULT computedStyleForProperties(  
+  [propget] HRESULT computedStyleForProperties(  
     [in] unsigned short numStyleProperties, 
     [in] boolean useAlternateView,  // If TRUE, returns properites for media as set in nsIDOMDocument::set_alternateViewMediaTypes
     [in, size_is(numStyleProperties), length_is(numStyleProperties)] BSTR *styleProperties, 
     [out, retval, size_is(numStyleProperties), length_is(numStyleProperties)] BSTR *styleValues
   );
 
   HRESULT scrollTo([in] boolean placeTopLeft);
 
@@ -205,12 +201,23 @@ interface ISimpleDOMNode : IUnknown
   [propget] HRESULT nextSibling([out, retval] ISimpleDOMNode **node);
   [propget] HRESULT childAt([in] unsigned childIndex, 
                             [out, retval] ISimpleDOMNode **node);
 
   [propget] HRESULT innerHTML([out, retval] BSTR *innerHTML);
 
   [propget, local] HRESULT localInterface([out][retval] void **localInterface);
 
-  [propget, id(DISPID_NODE_LANGUAGE)] HRESULT language([out, retval] BSTR *language);
+  [propget] HRESULT language([out, retval] BSTR *language);
 }
 
 
+[
+    uuid(a6245497-9c0b-4449-85a5-bd6ad07df8ea), 
+    helpstring("ISimpleDOM Type Library")
+] 
+library ISimpleDOM 
+{
+  interface ISimpleDOMNode;
+  interface ISimpleDOMText;
+  interface ISimpleDOMDocument;
+};
+
--- a/accessible/public/msaa/Makefile.in
+++ b/accessible/public/msaa/Makefile.in
@@ -93,17 +93,17 @@ OS_LIBS = \
 	$(NULL)
 
 $(MIDL_GENERATED_FILES): done_gen
 
 done_gen: ISimpleDOMNode.idl \
           ISimpleDOMDocument.idl \
           ISimpleDOMText.idl
 
-	$(MIDL) $(MIDL_FLAGS) -Oicf $(srcdir)/ISimpleDOMNode.idl
+	$(MIDL) $(MIDL_FLAGS) -I $(srcdir) -Oicf $(srcdir)/ISimpleDOMNode.idl
 	$(MIDL) $(MIDL_FLAGS) -Oicf $(srcdir)/ISimpleDOMDocument.idl
 	$(MIDL) $(MIDL_FLAGS) -Oicf $(srcdir)/ISimpleDOMText.idl
 	touch $@
 
 EXPORTS = \
 	ISimpleDOMNode.h \
 	ISimpleDOMNode_i.c \
 	ISimpleDOMDocument.h \
--- a/accessible/public/nsIAccessibleText.idl
+++ b/accessible/public/nsIAccessibleText.idl
@@ -39,18 +39,19 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 
 typedef long nsAccessibleTextBoundary;
 
 interface nsIAccessible;
+interface nsIPersistentProperties;
 
-[scriptable, uuid(caa4f543-070e-4705-8428-2e53575c41bb)]
+[scriptable, uuid(0f4633b1-550c-4b50-8c04-0eb1005eef2f)]
 interface nsIAccessibleText : nsISupports
 {
   // In parameters for character offsets:
   //  -1 will be treated as the equal to the end of the text
   //  -2 will be treated as the caret position
   const PRInt32 TEXT_OFFSET_END_OF_TEXT = -1;
   const PRInt32 TEXT_OFFSET_CARET       = -2;
 
@@ -97,23 +98,34 @@ interface nsIAccessibleText : nsISupport
 
     /**
       * It would be better to return an unsigned long here,
       * to allow unicode chars > 16 bits
       */
   wchar getCharacterAtOffset (in long offset);
 
   /**
-   * Get the accessible and start/end offsets around the given offset.
-   * This accessible get return the DOM node and layout frame
-   * with the uniform attributes for this range of text
+   * Get the accessible start/end offsets around the given offset,
+   * return the text attributes for this range of text.
+   *
+   * @param  includeDefAttrs   [in] points whether text attributes applied to
+   *                           the entire accessible should be included or not.
+   * @param  offset            [in] text offset
+   * @param  rangeStartOffset  [out] start offset of the range of text
+   * @param  rangeEndOffset    [out] end offset of the range of text
    */
-  nsIAccessible getAttributeRange (in long offset,
-                                   out long rangeStartOffset,
-                                   out long rangeEndOffset);
+  nsIPersistentProperties getTextAttributes(in boolean includeDefAttrs,
+                                            in long offset,
+                                            out long rangeStartOffset,
+                                            out long rangeEndOffset);
+
+  /**
+   * Return the text attributes that apply to the entire accessible.
+   */
+  readonly attribute nsIPersistentProperties defaultTextAttributes;
 
   /**
    * Returns the bounding box of the specified position.
    *
    * The virtual character after the last character of the represented text,
    * i.e. the one at position length is a special case. It represents the
    * current input position and will therefore typically be queried by AT more
    * often than other positions. Because it does not represent an existing
@@ -218,19 +230,14 @@ interface nsIAccessibleText : nsISupport
  Using wstring (UCS2) instead of string encoded in UTF-8.
  Multibyte encodings (or at least potentially multi-byte
  encodings) would be preferred for the reasons cited above.
 
  The following methods will throw an exception on failure
  (since not every text component will allow every operation):
  setSelectionBounds, addSelection, removeSelection, setCaretOffset.
 
- getRangeAttributes defined to return an nsISupports
- interface instead of a pango specific data structure.
- It may be that some other return type is more appropriate
- for mozilla text attributes.
-
  we assume that all text components support the idea of
  a caret offset, whether visible or "virtual".  If this
  isn't the case, caretOffset can be made readonly and
  a setCaretOffset method provided which throws an exception
  on failure (as with *selection methods above).
 */
--- a/accessible/public/nsIAccessibleTreeCache.idl
+++ b/accessible/public/nsIAccessibleTreeCache.idl
@@ -42,17 +42,17 @@
 
 interface nsIAccessible;
 
 /**
  * A private interface to operate with tree accessible.
  *
  * @status UNDER_REVIEW
  */
-[uuid(7e0f50b0-6444-4372-b00f-4ce81c6b058a)]
+[uuid(1dde5c3b-bede-43d1-aabf-dabc461113bd)]
 interface nsIAccessibleTreeCache : nsISupports
 {
   /**
    * Get tree item from cache according to row and column, create if doesn't
    * exist in cache.
    *
    * @param aRow     the given row index
    * @param aColumn  the given column object. If is is nsnull then primary
@@ -77,16 +77,22 @@ interface nsIAccessibleTreeCache : nsISu
    * @param aStartRow  row index invalidation starts from
    * @param aEndRow    row index invalidation ends, -1 means last row index
    * @param aStartCol  column index invalidation starts from
    * @param aEndCol    column index invalidation ends, -1 mens last column
    *                   index
    */
   void treeViewInvalidated(in long aStartRow, in long aEndRow,
                            in long aStartCol, in long aEndCol);
+
+  /**
+   * Invalidates children created for previous tree view.
+   */
+  void treeViewChanged();
+
 };
 
 [uuid(b71532f9-53b2-4647-a5b2-1c5f57e9aed6)]
 interface nsPIAccessibleTreeItem : nsISupports
 {
   /**
    * Get/set cached name.
    */
--- a/accessible/src/atk/nsAccessibleWrap.cpp
+++ b/accessible/src/atk/nsAccessibleWrap.cpp
@@ -366,18 +366,19 @@ void nsAccessibleWrap::SetMaiHyperlink(M
     }
 }
 
 NS_IMETHODIMP nsAccessibleWrap::GetNativeInterface(void **aOutAccessible)
 {
     *aOutAccessible = nsnull;
 
     if (!mAtkObject) {
-        if (!IsEmbeddedObject(this)) {
-            // We don't create ATK objects for nsIAccessible plain text leaves
+        if (!mWeakShell || !IsEmbeddedObject(this)) {
+            // We don't create ATK objects for node which has been shutdown, or
+            // nsIAccessible plain text leaves
             return NS_ERROR_FAILURE;
         }
 
         GType type = GetMaiAtkType(CreateMaiInterfaces());
         NS_ENSURE_TRUE(type, NS_ERROR_FAILURE);
         mAtkObject =
             reinterpret_cast<AtkObject *>
                             (g_object_new(type, NULL));
@@ -780,61 +781,75 @@ getRoleCB(AtkObject *aAtkObj)
         atkRole = atkRoleMap[accRole]; // map to the actual value
         NS_ASSERTION(atkRoleMap[nsIAccessibleRole::ROLE_LAST_ENTRY] ==
                      kROLE_ATK_LAST_ENTRY, "ATK role map skewed");
         aAtkObj->role = static_cast<AtkRole>(atkRole);
     }
     return aAtkObj->role;
 }
 
+AtkAttributeSet*
+ConvertToAtkAttributeSet(nsIPersistentProperties* aAttributes)
+{
+    if (!aAttributes)
+        return nsnull;
+
+    AtkAttributeSet *objAttributeSet = nsnull;
+    nsCOMPtr<nsISimpleEnumerator> propEnum;
+    nsresult rv = aAttributes->Enumerate(getter_AddRefs(propEnum));
+    NS_ENSURE_SUCCESS(rv, nsnull);
+
+    PRBool hasMore;
+    while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) && hasMore) {
+        nsCOMPtr<nsISupports> sup;
+        rv = propEnum->GetNext(getter_AddRefs(sup));
+        NS_ENSURE_SUCCESS(rv, objAttributeSet);
+
+        nsCOMPtr<nsIPropertyElement> propElem(do_QueryInterface(sup));
+        NS_ENSURE_TRUE(propElem, objAttributeSet);
+
+        nsCAutoString name;
+        rv = propElem->GetKey(name);
+        NS_ENSURE_SUCCESS(rv, objAttributeSet);
+
+        nsAutoString value;
+        rv = propElem->GetValue(value);
+        NS_ENSURE_SUCCESS(rv, objAttributeSet);
+
+        AtkAttribute *objAttr = (AtkAttribute *)g_malloc(sizeof(AtkAttribute));
+        objAttr->name = g_strdup(name.get());
+        objAttr->value = g_strdup(NS_ConvertUTF16toUTF8(value).get());
+        objAttributeSet = g_slist_prepend(objAttributeSet, objAttr);
+    }
+
+    //libspi will free it
+    return objAttributeSet;
+}
+
 AtkAttributeSet *
 GetAttributeSet(nsIAccessible* aAccessible)
 {
-    AtkAttributeSet *objAttributeSet = nsnull;
     nsCOMPtr<nsIPersistentProperties> attributes;
     aAccessible->GetAttributes(getter_AddRefs(attributes));
-    
+
     if (attributes) {
         // Deal with attributes that we only need to expose in ATK
         PRUint32 state;
         aAccessible->GetFinalState(&state, nsnull);
         if (state & nsIAccessibleStates::STATE_HASPOPUP) {
           // There is no ATK state for haspopup, must use object attribute to expose the same info
           nsAutoString oldValueUnused;
           attributes->SetStringProperty(NS_LITERAL_CSTRING("haspopup"), NS_LITERAL_STRING("true"),
                                         oldValueUnused);
         }
 
-        nsCOMPtr<nsISimpleEnumerator> propEnum;
-        nsresult rv = attributes->Enumerate(getter_AddRefs(propEnum));
-        NS_ENSURE_SUCCESS(rv, nsnull);
-
-        PRBool hasMore;
-        while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) && hasMore) {
-            nsCOMPtr<nsISupports> sup;
-            rv = propEnum->GetNext(getter_AddRefs(sup));
-            nsCOMPtr<nsIPropertyElement> propElem(do_QueryInterface(sup));
-            NS_ENSURE_TRUE(propElem, nsnull);
-
-            nsCAutoString name;
-            rv = propElem->GetKey(name);
-            NS_ENSURE_SUCCESS(rv, nsnull);
-
-            nsAutoString value;
-            rv = propElem->GetValue(value);
-            NS_ENSURE_SUCCESS(rv, nsnull);
-
-            AtkAttribute *objAttribute = (AtkAttribute *)g_malloc(sizeof(AtkAttribute));
-            objAttribute->name = g_strdup(name.get());
-            objAttribute->value = g_strdup(NS_ConvertUTF16toUTF8(value).get());
-            objAttributeSet = g_slist_prepend(objAttributeSet, objAttribute);
-        }
+        return ConvertToAtkAttributeSet(attributes);
     }
 
-    return objAttributeSet;
+    return nsnull;
 }
 
 AtkAttributeSet *
 getAttributesCB(AtkObject *aAtkObj)
 {
     nsAccessibleWrap *accWrap = GetAccessibleWrap(aAtkObj);
 
     return accWrap ? GetAttributeSet(accWrap) : nsnull;
@@ -849,18 +864,19 @@ getParentCB(AtkObject *aAtkObj)
             return nsnull;
         }
 
         nsCOMPtr<nsIAccessible> accParent;
         nsresult rv = accWrap->GetParent(getter_AddRefs(accParent));
         if (NS_FAILED(rv) || !accParent)
             return nsnull;
 
-        atk_object_set_parent(aAtkObj,
-                              nsAccessibleWrap::GetAtkObject(accParent));
+        AtkObject *parent = nsAccessibleWrap::GetAtkObject(accParent);
+        if (parent)
+            atk_object_set_parent(aAtkObj, parent);
     }
     return aAtkObj->accessible_parent;
 }
 
 gint
 getChildCountCB(AtkObject *aAtkObj)
 {
     nsAccessibleWrap *accWrap = GetAccessibleWrap(aAtkObj);
@@ -1096,22 +1112,28 @@ nsAccessibleWrap *GetAccessibleWrap(AtkO
 }
 
 NS_IMETHODIMP
 nsAccessibleWrap::FireAccessibleEvent(nsIAccessibleEvent *aEvent)
 {
     nsresult rv = nsAccessible::FireAccessibleEvent(aEvent);
     NS_ENSURE_SUCCESS(rv, rv);
 
+    return FirePlatformEvent(aEvent);
+}
+
+nsresult
+nsAccessibleWrap::FirePlatformEvent(nsIAccessibleEvent *aEvent)
+{
     nsCOMPtr<nsIAccessible> accessible;
     aEvent->GetAccessible(getter_AddRefs(accessible));
     NS_ENSURE_TRUE(accessible, NS_ERROR_FAILURE);
 
     PRUint32 type = 0;
-    rv = aEvent->GetEventType(&type);
+    nsresult rv = aEvent->GetEventType(&type);
     NS_ENSURE_SUCCESS(rv, rv);
 
     AtkObject *atkObj = nsAccessibleWrap::GetAtkObject(accessible);
 
     // We don't create ATK objects for nsIAccessible plain text leaves,
     // just return NS_OK in such case
     if (!atkObj) {
         NS_ASSERTION(type == nsIAccessibleEvent::EVENT_ASYNCH_SHOW ||
@@ -1185,16 +1207,23 @@ nsAccessibleWrap::FireAccessibleEvent(ns
 
         MAI_LOG_DEBUG(("\n\nCaret postion: %d", caretOffset));
         g_signal_emit_by_name(atkObj,
                               "text_caret_moved",
                               // Curent caret position
                               caretOffset);
       } break;
 
+    case nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED:
+        MAI_LOG_DEBUG(("\n\nReceived: EVENT_TEXT_ATTRIBUTE_CHANGED\n"));
+
+        g_signal_emit_by_name(atkObj,
+                              "text-attributes-changed");
+        break;
+
     case nsIAccessibleEvent::EVENT_TABLE_MODEL_CHANGED:
         MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_MODEL_CHANGED\n"));
         g_signal_emit_by_name(atkObj, "model_changed");
         break;
 
     case nsIAccessibleEvent::EVENT_TABLE_ROW_INSERT:
       {
         MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_ROW_INSERT\n"));
@@ -1304,29 +1333,32 @@ nsAccessibleWrap::FireAccessibleEvent(ns
 
     case nsIAccessibleEvent::EVENT_MENU_END:
         MAI_LOG_DEBUG(("\n\nReceived: EVENT_MENU_END\n"));
         break;
 
     case nsIAccessibleEvent::EVENT_WINDOW_ACTIVATE:
       {
         MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_ACTIVATED\n"));
-        nsDocAccessibleWrap *accDocWrap =
-          static_cast<nsDocAccessibleWrap *>(accessible.get());
-        accDocWrap->mActivated = PR_TRUE;
+        nsRootAccessible *rootAcc =
+          static_cast<nsRootAccessible *>(accessible.get());
+        rootAcc->mActivated = PR_TRUE;
         guint id = g_signal_lookup ("activate", MAI_TYPE_ATK_OBJECT);
         g_signal_emit(atkObj, id, 0);
+
+        // Always fire a current focus event after activation.
+        rootAcc->FireCurrentFocusEvent();
       } break;
 
     case nsIAccessibleEvent::EVENT_WINDOW_DEACTIVATE:
       {
         MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_DEACTIVATED\n"));
-        nsDocAccessibleWrap *accDocWrap =
-          static_cast<nsDocAccessibleWrap *>(accessible.get());
-        accDocWrap->mActivated = PR_FALSE;
+        nsRootAccessible *rootAcc =
+          static_cast<nsRootAccessible *>(accessible.get());
+        rootAcc->mActivated = PR_FALSE;
         guint id = g_signal_lookup ("deactivate", MAI_TYPE_ATK_OBJECT);
         g_signal_emit(atkObj, id, 0);
       } break;
 
     case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE:
       {
         MAI_LOG_DEBUG(("\n\nReceived: EVENT_DOCUMENT_LOAD_COMPLETE\n"));
         g_signal_emit_by_name (atkObj, "load_complete");
--- a/accessible/src/atk/nsAccessibleWrap.h
+++ b/accessible/src/atk/nsAccessibleWrap.h
@@ -111,16 +111,18 @@ public:
 
     static const char * ReturnString(nsAString &aString) {
       static nsCString returnedString;
       returnedString = NS_ConvertUTF16toUTF8(aString);
       return returnedString.get();
     }
 
 protected:
+    virtual nsresult FirePlatformEvent(nsIAccessibleEvent *aEvent);
+
     nsresult FireAtkStateChangeEvent(nsIAccessibleEvent *aEvent,
                                      AtkObject *aObject);
     nsresult FireAtkTextChangedEvent(nsIAccessibleEvent *aEvent,
                                      AtkObject *aObject);
     nsresult FireAtkPropChangedEvent(nsIAccessibleEvent *aEvent,
                                      AtkObject *aObject);
     nsresult FireAtkShowHideEvent(nsIAccessibleEvent *aEvent,
                                   AtkObject *aObject, PRBool aIsAdded);
--- a/accessible/src/atk/nsMaiInterfaceText.cpp
+++ b/accessible/src/atk/nsMaiInterfaceText.cpp
@@ -36,18 +36,19 @@
  * 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 "nsMaiInterfaceText.h"
 #include "nsString.h"
+#include "nsIPersistentProperties2.h"
 
-AtkAttributeSet * GetAttributeSet(nsIAccessible* aAccessible);
+AtkAttributeSet* ConvertToAtkAttributeSet(nsIPersistentProperties* aAttributes);
 
 void
 textInterfaceInitCB(AtkTextIface *aIface)
 {
     NS_ASSERTION(aIface, "Invalid aIface");
     if (!aIface)
         return;
 
@@ -240,43 +241,59 @@ getCaretOffsetCB(AtkText *aText)
     return (NS_FAILED(rv)) ? 0 : static_cast<gint>(offset);
 }
 
 AtkAttributeSet *
 getRunAttributesCB(AtkText *aText, gint aOffset,
                    gint *aStartOffset,
                    gint *aEndOffset)
 {
+    *aStartOffset = -1;
+    *aEndOffset = -1;
+
     nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
     if (!accWrap)
         return nsnull;
 
     nsCOMPtr<nsIAccessibleText> accText;
     accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
                             getter_AddRefs(accText));
     NS_ENSURE_TRUE(accText, nsnull);
 
-    nsCOMPtr<nsIAccessible> accessibleWithAttrs;
+    nsCOMPtr<nsIPersistentProperties> attributes;
     PRInt32 startOffset = 0, endOffset = 0;
-    nsresult rv =
-        accText->GetAttributeRange(aOffset, &startOffset, &endOffset,
-                                   getter_AddRefs(accessibleWithAttrs));
+    nsresult rv = accText->GetTextAttributes(PR_FALSE, aOffset,
+                                             &startOffset, &endOffset,
+                                             getter_AddRefs(attributes));
+    NS_ENSURE_SUCCESS(rv, nsnull);
+
     *aStartOffset = startOffset;
     *aEndOffset = endOffset;
-    if (NS_FAILED(rv))
-        return nsnull;
 
-    return GetAttributeSet(accessibleWithAttrs);
+    return ConvertToAtkAttributeSet(attributes);
 }
 
 AtkAttributeSet *
 getDefaultAttributesCB(AtkText *aText)
 {
-    /* not supported ??? */
-    return nsnull;
+    nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
+    if (!accWrap)
+        return nsnull;
+
+    nsCOMPtr<nsIAccessibleText> accText;
+    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
+                            getter_AddRefs(accText));
+    NS_ENSURE_TRUE(accText, nsnull);
+
+    nsCOMPtr<nsIPersistentProperties> attributes;
+    nsresult rv = accText->GetDefaultTextAttributes(getter_AddRefs(attributes));
+    if (NS_FAILED(rv))
+        return nsnull;
+
+    return ConvertToAtkAttributeSet(attributes);
 }
 
 void
 getCharacterExtentsCB(AtkText *aText, gint aOffset,
                       gint *aX, gint *aY,
                       gint *aWidth, gint *aHeight,
                       AtkCoordType aCoords)
 {
--- a/accessible/src/base/Makefile.in
+++ b/accessible/src/base/Makefile.in
@@ -85,16 +85,17 @@ CPPSRCS = \
   nsAccessibleRelation.cpp \
   nsAccessibleTreeWalker.cpp \
   nsBaseWidgetAccessible.cpp \
   nsFormControlAccessible.cpp \
   nsRootAccessible.cpp \
   nsApplicationAccessible.cpp \
   nsCaretAccessible.cpp \
   nsTextAccessible.cpp \
+  nsTextUtils.cpp \
   $(NULL)
 
 EXPORTS = \
   nsRootAccessible.h \
   nsAccessibleEventData.h \
   nsAccessNode.h \
   $(NULL)
 
--- a/accessible/src/base/nsARIAMap.cpp
+++ b/accessible/src/base/nsARIAMap.cpp
@@ -58,16 +58,17 @@
 
 static const nsStateMapEntry kEndEntry = {nsnull, 0, 0};  // To fill in array of state mappings
 
 nsRoleMapEntry nsARIAMap::gWAIRoleMap[] = 
 {
   {"alert", nsIAccessibleRole::ROLE_ALERT, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"alertdialog", nsIAccessibleRole::ROLE_ALERT, eNameOkFromChildren, eNoValue, kNoReqStates, kEndEntry},
   {"application", nsIAccessibleRole::ROLE_APPLICATION, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
+  {"article", nsIAccessibleRole::ROLE_DOCUMENT, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"button", nsIAccessibleRole::ROLE_PUSHBUTTON, eNameOkFromChildren, eNoValue, kNoReqStates,
             {&nsAccessibilityAtoms::aria_pressed, kBoolState, nsIAccessibleStates::STATE_PRESSED},
             {&nsAccessibilityAtoms::aria_pressed, "mixed", nsIAccessibleStates::STATE_MIXED}, kEndEntry},
   {"checkbox", nsIAccessibleRole::ROLE_CHECKBUTTON, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_CHECKABLE,
             {&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED},
             {&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED},
             {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
   {"columnheader", nsIAccessibleRole::ROLE_COLUMNHEADER, eNameOkFromChildren, eNoValue, kNoReqStates,
--- a/accessible/src/base/nsAccessNode.cpp
+++ b/accessible/src/base/nsAccessNode.cpp
@@ -186,18 +186,17 @@ NS_IMETHODIMP nsAccessNode::Init()
     do_QueryInterface(docAccessible);
   NS_ASSERTION(privateDocAccessible, "No private docaccessible for docaccessible");
   privateDocAccessible->CacheAccessNode(uniqueID, this);
 
   // Make sure an ancestor in real content is cached
   // so that nsDocAccessible::RefreshNodes() can find the anonymous subtree to release when
   // the root node goes away
   nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
-  if (content && (content->IsNativeAnonymous() ||
-                  content->GetBindingParent())) {
+  if (content && content->IsInAnonymousSubtree()) {
     // Specific examples of where this is used: <input type="file"> and <xul:findbar>
     nsCOMPtr<nsIAccessible> parentAccessible;
     docAccessible->GetAccessibleInParentChain(mDOMNode, PR_TRUE, getter_AddRefs(parentAccessible));
     if (parentAccessible) {
       PRInt32 childCountUnused;
       parentAccessible->GetChildCount(&childCountUnused);
     }
   }
@@ -789,17 +788,17 @@ nsAccessNode::GetCacheEntry(nsAccessNode
                             void* aUniqueID,
                             nsIAccessNode **aAccessNode)
 {
   aCache.Get(aUniqueID, aAccessNode);  // AddRefs for us
 }
 
 PLDHashOperator nsAccessNode::ClearCacheEntry(const void* aKey, nsCOMPtr<nsIAccessNode>& aAccessNode, void* aUserArg)
 {
-  NS_ASSERTION(!aAccessNode, "Calling ClearCacheEntry with a NULL pointer!");
+  NS_ASSERTION(aAccessNode, "Calling ClearCacheEntry with a NULL pointer!");
   if (aAccessNode) {
     nsCOMPtr<nsPIAccessNode> privateAccessNode(do_QueryInterface(aAccessNode));
     privateAccessNode->Shutdown();
   }
 
   return PL_DHASH_REMOVE;
 }
 
@@ -871,20 +870,17 @@ nsAccessNode::GetLanguage(nsAString& aLa
         content = do_QueryInterface(docElement);
       }
     }
     if (!content) {
       return NS_ERROR_FAILURE;
     }
   }
 
-  nsIContent *walkUp = content;
-  while (walkUp && !walkUp->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::lang, aLanguage)) {
-    walkUp = walkUp->GetParent();
-  }
+  nsAccUtils::GetLanguageFor(content, nsnull, aLanguage);
 
   if (aLanguage.IsEmpty()) { // Nothing found, so use document's language
     nsIDocument *doc = content->GetOwnerDoc();
     if (doc) {
       doc->GetHeaderData(nsAccessibilityAtoms::headerContentLanguage, aLanguage);
     }
   }
  
--- a/accessible/src/base/nsAccessNode.h
+++ b/accessible/src/base/nsAccessNode.h
@@ -40,16 +40,18 @@
  * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
  */
 
 #ifndef _nsAccessNode_H_
 #define _nsAccessNode_H_
 
 #include "nsCOMPtr.h"
 #include "nsAccessibilityAtoms.h"
+#include "nsAccessibilityUtils.h"
+
 #include "nsIAccessibleTypes.h"
 #include "nsIAccessNode.h"
 #include "nsIContent.h"
 #include "nsPIAccessNode.h"
 #include "nsIDOMNode.h"
 #include "nsINameSpaceManager.h"
 #include "nsIStringBundle.h"
 #include "nsWeakReference.h"
--- a/accessible/src/base/nsAccessibilityAtomList.h
+++ b/accessible/src/base/nsAccessibilityAtomList.h
@@ -144,24 +144,25 @@ ACCESSIBILITY_ATOM(textbox, "textbox")  
 ACCESSIBILITY_ATOM(toolbaritem, "toolbaritem")   // XUL
 ACCESSIBILITY_ATOM(toolbarseparator, "toolbarseparator")   // XUL
 ACCESSIBILITY_ATOM(toolbarspring, "toolbarspring")   // XUL
 ACCESSIBILITY_ATOM(toolbarspacer, "toolbarspacer")   // XUL
 ACCESSIBILITY_ATOM(tooltip, "tooltip")   // XUL
 ACCESSIBILITY_ATOM(tr, "tr")
 ACCESSIBILITY_ATOM(ul, "ul")
 
-  // Alphabetical list of attributes
+  // Alphabetical list of attributes (DOM)
 ACCESSIBILITY_ATOM(acceltext, "acceltext")
 ACCESSIBILITY_ATOM(accesskey, "accesskey")
 ACCESSIBILITY_ATOM(alt, "alt")
 ACCESSIBILITY_ATOM(anonid, "anonid") // Used for ID's in XBL
 ACCESSIBILITY_ATOM(contenteditable, "contenteditable")
 ACCESSIBILITY_ATOM(control, "control")
 ACCESSIBILITY_ATOM(disabled, "disabled")
+ACCESSIBILITY_ATOM(display, "display")
 ACCESSIBILITY_ATOM(_class, "class")
 ACCESSIBILITY_ATOM(cycles, "cycles") // used for XUL cycler attribute
 ACCESSIBILITY_ATOM(curpos, "curpos") // XUL
 ACCESSIBILITY_ATOM(data, "data")
 ACCESSIBILITY_ATOM(droppable, "droppable")   // XUL combo box
 ACCESSIBILITY_ATOM(editable, "editable")
 ACCESSIBILITY_ATOM(_for, "for")
 ACCESSIBILITY_ATOM(hidden, "hidden")   // XUL tree columns
@@ -180,16 +181,20 @@ ACCESSIBILITY_ATOM(src, "src")
 ACCESSIBILITY_ATOM(selected, "selected")
 ACCESSIBILITY_ATOM(summary, "summary")
 ACCESSIBILITY_ATOM(tabindex, "tabindex")
 ACCESSIBILITY_ATOM(title, "title")
 ACCESSIBILITY_ATOM(tooltiptext, "tooltiptext")
 ACCESSIBILITY_ATOM(type, "type")
 ACCESSIBILITY_ATOM(value, "value")
 
+  // Alphabetical list of text attributes (AT API)
+ACCESSIBILITY_ATOM(invalid, "invalid")
+ACCESSIBILITY_ATOM(language, "language")
+
   // ARIA (DHTML accessibility) attributes
   // Also add to nsARIAMap.cpp and nsARIAMap.h
   // ARIA role attribute
 ACCESSIBILITY_ATOM(role, "role")
 ACCESSIBILITY_ATOM(aria_activedescendant, "aria-activedescendant")
 ACCESSIBILITY_ATOM(aria_atomic, "aria-atomic")
 ACCESSIBILITY_ATOM(aria_autocomplete, "aria-autocomplete")
 ACCESSIBILITY_ATOM(aria_busy, "aria-busy")
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -1323,39 +1323,36 @@ NS_IMETHODIMP nsAccessibilityService::Ge
   nsCOMPtr<nsIDOMElement> element(do_QueryInterface(aNode));
   if (element) {
     element->GetAttribute(NS_LITERAL_STRING("type"), attrib);
     if (attrib.EqualsLiteral("statusbarpanel"))
       printf("## aaronl debugging attribute\n");
   }
 #endif
 
-  nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
-  if (content && content->Tag() == nsAccessibilityAtoms::map) {
-    // Don't walk into maps, they take up no space.
-    // The nsHTMLAreaAccessible's they contain are attached as
-    // children of the appropriate nsHTMLImageAccessible.
-    *aIsHidden = PR_TRUE;
-    return NS_OK;
-  }
-
   // Check to see if we already have an accessible for this
   // node in the cache
   nsCOMPtr<nsIAccessNode> accessNode;
   GetCachedAccessNode(aNode, aWeakShell, getter_AddRefs(accessNode));
 
   nsCOMPtr<nsIAccessible> newAcc;
   if (accessNode) {
-    // Retrieved from cache
-    // QI might not succeed if it's a node that's not accessible
+    // Retrieved from cache. QI might not succeed if it's a node that's not
+    // accessible. In this case try to create new accessible because one and
+    // the same DOM node may be accessible or not in time (for example,
+    // when it is visible or hidden).
     newAcc = do_QueryInterface(accessNode);
-    NS_IF_ADDREF(*aAccessible = newAcc);
-    return NS_OK;
+    if (newAcc) {
+      NS_ADDREF(*aAccessible = newAcc);
+      return NS_OK;
+    }
   }
 
+  nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
+
   // No cache entry, so we must create the accessible
   // Check to see if hidden first
   nsCOMPtr<nsIDocument> nodeIsDoc;
   if (!content) {
     // This happens when we're on the document node, which will not QI to an
     // nsIContent.
     nodeIsDoc = do_QueryInterface(aNode);
     NS_ENSURE_TRUE(nodeIsDoc, NS_ERROR_FAILURE); // No content, and not doc node
@@ -1456,31 +1453,51 @@ NS_IMETHODIMP nsAccessibilityService::Ge
         *aIsHidden = PR_TRUE;
         return NS_OK;
       }
     }
     frame->GetAccessible(getter_AddRefs(newAcc));
     return InitAccessible(newAcc, aAccessible, nsnull);
   }
 
+  PRBool isHTML = content->IsNodeOfType(nsINode::eHTML);
+  if (isHTML && content->Tag() == nsAccessibilityAtoms::map) {
+    // Create hyper text accessible for HTML map if it is used to group links
+    // (see http://www.w3.org/TR/WCAG10-HTML-TECHS/#group-bypass). If the HTML
+    // map doesn't have 'name' attribute (or has empty name attribute) then we
+    // suppose it is used for links grouping. Otherwise we think it is used in
+    // conjuction with HTML image element and in this case we don't create any
+    // accessible for it and don't walk into it. The accessibles for HTML area
+    // (nsHTMLAreaAccessible) the map contains are attached as children of the
+    // appropriate accessible for HTML image (nsHTMLImageAccessible).
+    nsAutoString name;
+    content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::name, name);
+    if (!name.IsEmpty()) {
+      *aIsHidden = PR_TRUE;
+      return NS_OK;
+    }
+    
+    nsresult rv = CreateHyperTextAccessible(frame, getter_AddRefs(newAcc));
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
   nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(aNode);
   if (roleMapEntry && !nsCRT::strcmp(roleMapEntry->roleString, "presentation") &&
       !content->IsFocusable()) { // For presentation only
     // Only create accessible for role of "presentation" if it is focusable --
     // in that case we need an accessible in case it gets focused, we
     // don't want focus ever to be 'lost'
     return NS_OK;
   }
 
   // Elements may implement nsIAccessibleProvider via XBL. This allows them to
   // say what kind of accessible to create.
   nsresult rv = GetAccessibleByType(aNode, getter_AddRefs(newAcc));
   NS_ENSURE_SUCCESS(rv, rv);
-  
-  PRBool isHTML = content->IsNodeOfType(nsINode::eHTML);
+
   if (!newAcc && !isHTML) {
     if (content->GetNameSpaceID() == kNameSpaceID_SVG &&
              content->Tag() == nsAccessibilityAtoms::svg) {
       newAcc = new nsEnumRoleAccessible(aNode, aWeakShell,
                                         nsIAccessibleRole::ROLE_DIAGRAM);
     }
     else if (content->GetNameSpaceID() == kNameSpaceID_MathML &&
              content->Tag() == nsAccessibilityAtoms::math) {
@@ -1521,17 +1538,17 @@ NS_IMETHODIMP nsAccessibilityService::Ge
           }
           if (tableAccessible && nsAccessible::Role(tableAccessible) != nsIAccessibleRole::ROLE_TABLE) {
             NS_ASSERTION(!roleMapEntry, "Should not be changing ARIA role, just overriding impl class role");
             // Not in table: override role (roleMap entry was null).
             roleMapEntry = &nsARIAMap::gEmptyRoleMap;
           }
           break;
         }
-        else if (tableFrame->GetType() == nsAccessibilityAtoms::tableCellFrame) {
+        else if (tableContent->Tag() == nsAccessibilityAtoms::table) {
           // Stop before we are fooled by any additional table ancestors
           // This table cell frameis part of a separate ancestor table.
           tryTagNameOrFrame = PR_FALSE;
           break;
         }
       }
 
       if (!tableContent)
@@ -2044,24 +2061,25 @@ nsAccessibilityService::GetAccessibleFor
 
   if (frame && (frame->GetType() == nsAccessibilityAtoms::boxFrame ||
                 frame->GetType() == nsAccessibilityAtoms::scrollFrame)) { 
     parentFrame = frame->GetParent();
     if (parentFrame && parentFrame->GetType() == nsAccessibilityAtoms::deckFrame) {
       // If deck frame is for xul:tabpanels element then the given node has
       // tabpanel accessible.
       nsCOMPtr<nsIContent> parentContent = parentFrame->GetContent();
+#ifdef MOZ_XUL
       if (parentContent->NodeInfo()->Equals(nsAccessibilityAtoms::tabpanels,
                                             kNameSpaceID_XUL)) {
         *aAccessible = new nsXULTabpanelAccessible(aNode, weakShell);
-      } else {
+      } else
+#endif
         *aAccessible =
           new nsEnumRoleAccessible(aNode, weakShell,
                                    nsIAccessibleRole::ROLE_PROPERTYPAGE);
-      }
 
       NS_ENSURE_TRUE(*aAccessible, NS_ERROR_OUT_OF_MEMORY);
 
       NS_ADDREF(*aAccessible);
     }
   }
 
   return NS_OK;
--- a/accessible/src/base/nsAccessibilityUtils.cpp
+++ b/accessible/src/base/nsAccessibilityUtils.cpp
@@ -220,45 +220,70 @@ nsAccUtils::SetAccAttrsForXULContainerIt
 
   // Get item count.
   PRUint32 itemsCount = 0;
   container->GetItemCount(&itemsCount);
 
   // Get item index.
   PRInt32 indexOf = 0;
   container->GetIndexOfItem(item, &indexOf);
-  
-  PRUint32 setSize = itemsCount, posInSet = indexOf;
-  for (PRUint32 index = 0; index < itemsCount; index++) {
-    nsCOMPtr<nsIDOMXULElement> currItem;
-    container->GetItemAtIndex(index, getter_AddRefs(currItem));
-    nsCOMPtr<nsIDOMNode> currNode(do_QueryInterface(currItem));
+
+  // Calculate set size and position in the set.
+  PRUint32 setSize = 0, posInSet = 0;
+  for (PRInt32 index = indexOf; index >= 0; index--) {
+    nsCOMPtr<nsIDOMXULElement> item;
+    container->GetItemAtIndex(index, getter_AddRefs(item));
+
+    nsCOMPtr<nsIAccessible> itemAcc;
+    nsAccessNode::GetAccService()->GetAccessibleFor(item,
+                                                    getter_AddRefs(itemAcc));
+
+    if (itemAcc) {
+      PRUint32 itemRole = nsAccessible::Role(itemAcc);
+      if (itemRole == nsIAccessibleRole::ROLE_SEPARATOR)
+        break; // We reached the beginning of our group.
+
+      PRUint32 itemState = nsAccessible::State(itemAcc);
+      if (!(itemState & nsIAccessibleStates::STATE_INVISIBLE)) {
+        setSize++;
+        posInSet++;
+      }
+    }
+  }
+
+  for (PRInt32 index = indexOf + 1; index < itemsCount; index++) {
+    nsCOMPtr<nsIDOMXULElement> item;
+    container->GetItemAtIndex(index, getter_AddRefs(item));
     
     nsCOMPtr<nsIAccessible> itemAcc;
-    nsAccessNode::GetAccService()->GetAccessibleFor(currNode,
+    nsAccessNode::GetAccService()->GetAccessibleFor(item,
                                                     getter_AddRefs(itemAcc));
-    if (!itemAcc ||
-        nsAccessible::State(itemAcc) & nsIAccessibleStates::STATE_INVISIBLE) {
-      setSize--;
-      if (index < static_cast<PRUint32>(indexOf))
-        posInSet--;
+
+    if (itemAcc) {
+      PRUint32 itemRole = nsAccessible::Role(itemAcc);
+      if (itemRole == nsIAccessibleRole::ROLE_SEPARATOR)
+        break; // We reached the end of our group.
+
+      PRUint32 itemState = nsAccessible::State(itemAcc);
+      if (!(itemState & nsIAccessibleStates::STATE_INVISIBLE))
+        setSize++;
     }
   }
 
   // Get level of the item.
   PRInt32 level = -1;
   while (container) {
     level++;
 
     nsCOMPtr<nsIDOMXULContainerElement> parentContainer;
     container->GetParentContainer(getter_AddRefs(parentContainer));
     parentContainer.swap(container);
   }
   
-  SetAccGroupAttrs(aAttributes, level, posInSet + 1, setSize);
+  SetAccGroupAttrs(aAttributes, level, posInSet, setSize);
 }
 
 PRBool
 nsAccUtils::HasListener(nsIContent *aContent, const nsAString& aEventType)
 {
   NS_ENSURE_TRUE(aContent, PR_FALSE);
   nsCOMPtr<nsIEventListenerManager> listenerManager;
   aContent->GetListenerManager(PR_FALSE, getter_AddRefs(listenerManager));
@@ -310,16 +335,34 @@ nsAccUtils::FireAccEvent(PRUint32 aEvent
 
   nsCOMPtr<nsIAccessibleEvent> event =
     new nsAccEvent(aEventType, aAccessible, aIsAsynch);
   NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
 
   return pAccessible->FireAccessibleEvent(event);
 }
 
+already_AddRefed<nsIDOMElement>
+nsAccUtils::GetDOMElementFor(nsIDOMNode *aNode)
+{
+  nsCOMPtr<nsINode> node(do_QueryInterface(aNode));
+
+  nsIDOMElement *element = nsnull;
+  if (node->IsNodeOfType(nsINode::eELEMENT))
+    CallQueryInterface(node, &element);
+  else if (node->IsNodeOfType(nsINode::eTEXT))
+    CallQueryInterface(node->GetNodeParent(), &element);
+  else if (node->IsNodeOfType(nsINode::eDOCUMENT)) {
+    nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(node));
+    domDoc->GetDocumentElement(&element);
+  }
+
+  return element;
+}
+
 PRBool
 nsAccUtils::IsAncestorOf(nsIDOMNode *aPossibleAncestorNode,
                          nsIDOMNode *aPossibleDescendantNode)
 {
   NS_ENSURE_TRUE(aPossibleAncestorNode && aPossibleDescendantNode, PR_FALSE);
 
   nsCOMPtr<nsIDOMNode> loopNode = aPossibleDescendantNode;
   nsCOMPtr<nsIDOMNode> parentNode;
@@ -744,29 +787,28 @@ nsAccUtils::FindNeighbourPointingToNode(
 
 nsIContent*
 nsAccUtils::FindNeighbourPointingToNode(nsIContent *aForNode, 
                                         nsIAtom **aRelationAttrs,
                                         PRUint32 aAttrNum,
                                         nsIAtom *aTagName,
                                         PRUint32 aAncestorLevelsToSearch)
 {
-  nsCOMPtr<nsIContent> binding;
   nsAutoString controlID;
   if (!nsAccUtils::GetID(aForNode, controlID)) {
-    binding = aForNode->GetBindingParent();
-    if (binding == aForNode)
+    if (!aForNode->IsInAnonymousSubtree())
       return nsnull;
 
     aForNode->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::anonid, controlID);
     if (controlID.IsEmpty())
       return nsnull;
   }
 
   // Look for label in subtrees of nearby ancestors
+  nsCOMPtr<nsIContent> binding(aForNode->GetBindingParent());
   PRUint32 count = 0;
   nsIContent *labelContent = nsnull;
   nsIContent *prevSearched = nsnull;
 
   while (!labelContent && ++count <= aAncestorLevelsToSearch &&
          (aForNode = aForNode->GetParent()) != nsnull) {
 
     if (aForNode == binding) {
@@ -891,16 +933,29 @@ nsAccUtils::FindDescendantPointingToIDIm
       if (labelContent) {
         return labelContent;
       }
     }
   }
   return nsnull;
 }
 
+void
+nsAccUtils::GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent,
+                           nsAString& aLanguage)
+{
+  aLanguage.Truncate();
+
+  nsIContent *walkUp = aContent;
+  while (walkUp && walkUp != aRootContent &&
+         !walkUp->GetAttr(kNameSpaceID_None,
+                          nsAccessibilityAtoms::lang, aLanguage))
+    walkUp = walkUp->GetParent();
+}
+
 nsRoleMapEntry*
 nsAccUtils::GetRoleMapEntry(nsIDOMNode *aNode)
 {
   nsIContent *content = nsAccessible::GetRoleContent(aNode);
   nsAutoString roleString;
   if (!content || !content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::role, roleString)) {
     return nsnull;
   }
--- a/accessible/src/base/nsAccessibilityUtils.h
+++ b/accessible/src/base/nsAccessibilityUtils.h
@@ -134,16 +134,26 @@ public:
 
   /**
    * Fire accessible event of the given type for the given accessible.
    */
   static nsresult FireAccEvent(PRUint32 aEventType, nsIAccessible *aAccessible,
                                PRBool aIsAsynch = PR_FALSE);
 
   /**
+   * Return DOM element related with the given node, i.e.
+   * a) itself if it is DOM element
+   * b) parent element if it is text node
+   * c) document element if it is document node.
+   *
+   * @param aNode  [in] the given DOM node
+   */
+  static already_AddRefed<nsIDOMElement> GetDOMElementFor(nsIDOMNode *aNode);
+
+  /**
    * Is the first passed in node an ancestor of the second?
    * Note: A node is not considered to be the ancestor of itself.
    * @param aPossibleAncestorNode -- node to test for ancestor-ness of aPossibleDescendantNode
    * @param aPossibleDescendantNode -- node to test for descendant-ness of aPossibleAncestorNode
    * @return PR_TRUE if aPossibleAncestorNode is an ancestor of aPossibleDescendantNode
    */
    static PRBool IsAncestorOf(nsIDOMNode *aPossibleAncestorNode,
                               nsIDOMNode *aPossibleDescendantNode);
@@ -298,16 +308,26 @@ public:
    * Check if the given element is XLink.
    *
    * @param aContent  the given element
    * @return          PR_TRUE if the given element is XLink
    */
   static PRBool IsXLink(nsIContent *aContent);
 
   /**
+   * Returns language for the given node.
+   *
+   * @param aContent     [in] the given node
+   * @param aRootContent [in] container of the given node
+   * @param aLanguage    [out] language
+   */
+  static void GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent,
+                             nsAString& aLanguage);
+
+  /**
    * Get the role map entry for a given DOM node. This will use the first
    * ARIA role if the role attribute provides a space delimited list of roles.
    * @param aNode  The DOM node to get the role map entry for
    * @return       A pointer to the role map entry for the ARIA role, or nsnull if none
    */
    static nsRoleMapEntry* GetRoleMapEntry(nsIDOMNode *aNode);
 
   /**
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -1588,25 +1588,16 @@ nsresult nsAccessible::AppendFlatStringF
       }
     }
     return NS_OK;
   }
 
   nsAutoString textEquivalent;
   if (!aContent->IsNodeOfType(nsINode::eHTML)) {
     if (aContent->IsNodeOfType(nsINode::eXUL)) {
-      nsCOMPtr<nsIPresShell> shell = GetPresShell();
-      if (!shell) {
-        return NS_ERROR_FAILURE;  
-      }
-      nsIFrame *frame = shell->GetPrimaryFrameFor(aContent);
-      if (!frame || !frame->GetStyleVisibility()->IsVisible()) {
-        return NS_OK;
-      }
-
       nsCOMPtr<nsIDOMXULLabeledControlElement> labeledEl(do_QueryInterface(aContent));
       if (labeledEl) {
         labeledEl->GetLabel(textEquivalent);
       }
       else {
         if (aContent->NodeInfo()->Equals(nsAccessibilityAtoms::label, kNameSpaceID_XUL)) {
           aContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::value, textEquivalent);
         }
@@ -1656,18 +1647,27 @@ nsresult nsAccessible::AppendFlatStringF
 
 
 nsresult nsAccessible::AppendFlatStringFromSubtree(nsIContent *aContent, nsAString *aFlatString)
 {
   static PRBool isAlreadyHere; // Prevent recursion which can cause infinite loops
   if (isAlreadyHere) {
     return NS_OK;
   }
+
   isAlreadyHere = PR_TRUE;
-  nsresult rv = AppendFlatStringFromSubtreeRecurse(aContent, aFlatString);
+
+  nsCOMPtr<nsIPresShell> shell = GetPresShell();
+  NS_ENSURE_TRUE(shell, NS_ERROR_FAILURE);
+
+  nsIFrame *frame = shell->GetPrimaryFrameFor(aContent);
+  PRBool isHidden = (!frame || !frame->GetStyleVisibility()->IsVisible());
+  nsresult rv = AppendFlatStringFromSubtreeRecurse(aContent, aFlatString,
+                                                   isHidden);
+
   isAlreadyHere = PR_FALSE;
 
   if (NS_SUCCEEDED(rv) && !aFlatString->IsEmpty()) {
     nsAString::const_iterator start, end;
     aFlatString->BeginReading(start);
     aFlatString->EndReading(end);
 
     PRInt32 spacesToTruncate = 0;
@@ -1676,37 +1676,55 @@ nsresult nsAccessible::AppendFlatStringF
 
     if (spacesToTruncate > 0)
       aFlatString->Truncate(aFlatString->Length() - spacesToTruncate);
   }
 
   return rv;
 }
 
-nsresult nsAccessible::AppendFlatStringFromSubtreeRecurse(nsIContent *aContent, nsAString *aFlatString)
+nsresult
+nsAccessible::AppendFlatStringFromSubtreeRecurse(nsIContent *aContent,
+                                                 nsAString *aFlatString,
+                                                 PRBool aIsRootHidden)
 {
   // Depth first search for all text nodes that are decendants of content node.
   // Append all the text into one flat string
   PRUint32 numChildren = 0;
   nsCOMPtr<nsIDOMXULSelectControlElement> selectControlEl(do_QueryInterface(aContent));
   if (!selectControlEl) {  // Don't walk children of elements with options, just get label directly
     numChildren = aContent->GetChildCount();
   }
 
   if (numChildren == 0) {
     // There are no children or they are irrelvant: get the text from the current node
     AppendFlatStringFromContentNode(aContent, aFlatString);
     return NS_OK;
   }
 
   // There are relevant children: use them to get the text.
+  nsCOMPtr<nsIPresShell> shell = GetPresShell();
+  NS_ENSURE_TRUE(shell, NS_ERROR_FAILURE);
+
   PRUint32 index;
   for (index = 0; index < numChildren; index++) {
-    AppendFlatStringFromSubtreeRecurse(aContent->GetChildAt(index), aFlatString);
+    nsCOMPtr<nsIContent> childContent = aContent->GetChildAt(index);
+
+    // Walk into hidden subtree if the the root parent is also hidden. This
+    // happens when the author explictly uses a hidden label or description.
+    if (!aIsRootHidden) {
+      nsIFrame *childFrame = shell->GetPrimaryFrameFor(childContent);
+      if (!childFrame || !childFrame->GetStyleVisibility()->IsVisible())
+        continue;
+    }
+
+    AppendFlatStringFromSubtreeRecurse(childContent, aFlatString,
+                                       aIsRootHidden);
   }
+
   return NS_OK;
 }
 
 nsIContent *nsAccessible::GetLabelContent(nsIContent *aForNode)
 {
   if (aForNode->IsNodeOfType(nsINode::eXUL))
     return nsAccUtils::FindNeighbourPointingToNode(aForNode, nsAccessibilityAtoms::control,
                                                    nsAccessibilityAtoms::label);
@@ -2040,16 +2058,19 @@ NS_IMETHODIMP nsAccessible::GetFinalRole
   return mDOMNode ? GetRole(aRole) : NS_ERROR_FAILURE;  // Node already shut down
 }
 
 NS_IMETHODIMP
 nsAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
 {
   NS_ENSURE_ARG_POINTER(aAttributes);  // In/out param. Created if necessary.
   
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
   nsCOMPtr<nsIContent> content = GetRoleContent(mDOMNode);
   if (!content) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIPersistentProperties> attributes = *aAttributes;
   if (!attributes) {
     // Create only if an array wasn't already passed in
@@ -2109,46 +2130,72 @@ nsAccessible::GetAttributes(nsIPersisten
   if (!nsAccUtils::HasAccGroupAttrs(attributes)) {
     // The role of an accessible can be pointed by ARIA attribute but ARIA
     // posinset, level, setsize may be skipped. Therefore we calculate here
     // these properties to map them into description.
 
     // If accessible is invisible we don't want to calculate group ARIA
     // attributes for it.
     if ((role == nsIAccessibleRole::ROLE_LISTITEM ||
-        role == nsIAccessibleRole::ROLE_MENUITEM ||
-        role == nsIAccessibleRole::ROLE_RADIOBUTTON ||
-        role == nsIAccessibleRole::ROLE_PAGETAB ||
-        role == nsIAccessibleRole::ROLE_OPTION ||
-        role == nsIAccessibleRole::ROLE_RADIOBUTTON ||
-        role == nsIAccessibleRole::ROLE_OUTLINEITEM) &&
+         role == nsIAccessibleRole::ROLE_MENUITEM ||
+         role == nsIAccessibleRole::ROLE_CHECK_MENU_ITEM ||
+         role == nsIAccessibleRole::ROLE_RADIO_MENU_ITEM ||
+         role == nsIAccessibleRole::ROLE_RADIOBUTTON ||
+         role == nsIAccessibleRole::ROLE_PAGETAB ||
+         role == nsIAccessibleRole::ROLE_OPTION ||
+         role == nsIAccessibleRole::ROLE_RADIOBUTTON ||
+         role == nsIAccessibleRole::ROLE_OUTLINEITEM) &&
         0 == (State(this) & nsIAccessibleStates::STATE_INVISIBLE)) {
+
+      PRUint32 baseRole = role;
+      if (role == nsIAccessibleRole::ROLE_CHECK_MENU_ITEM ||
+          role == nsIAccessibleRole::ROLE_RADIO_MENU_ITEM)
+        baseRole = nsIAccessibleRole::ROLE_MENUITEM;
+
       nsCOMPtr<nsIAccessible> parent = GetParent();
       NS_ENSURE_TRUE(parent, NS_ERROR_FAILURE);
 
       PRInt32 positionInGroup = 0;
       PRInt32 setSize = 0;
 
       nsCOMPtr<nsIAccessible> sibling, nextSibling;
       parent->GetFirstChild(getter_AddRefs(sibling));
       NS_ENSURE_TRUE(sibling, NS_ERROR_FAILURE);
 
       PRBool foundCurrent = PR_FALSE;
-      PRUint32 siblingRole;
+      PRUint32 siblingRole, siblingBaseRole;
       while (sibling) {
         sibling->GetFinalRole(&siblingRole);
-        if (siblingRole == role &&
+
+        siblingBaseRole = siblingRole;
+        if (siblingRole == nsIAccessibleRole::ROLE_CHECK_MENU_ITEM ||
+            siblingRole == nsIAccessibleRole::ROLE_RADIO_MENU_ITEM)
+          siblingBaseRole = nsIAccessibleRole::ROLE_MENUITEM;
+
+        // If sibling is visible and has the same base role.
+        if (siblingBaseRole == baseRole &&
             !(State(sibling) & nsIAccessibleStates::STATE_INVISIBLE)) {
           ++ setSize;
           if (!foundCurrent) {
             ++ positionInGroup;
             if (sibling == this)
               foundCurrent = PR_TRUE;
           }
         }
+
+        // If the sibling is separator
+        if (siblingRole == nsIAccessibleRole::ROLE_SEPARATOR) {
+          if (foundCurrent) // the our group is ended
+            break;
+
+          // not our group, continue the searching
+          positionInGroup = 0;
+          setSize = 0;
+        }
+
         sibling->GetNextSibling(getter_AddRefs(nextSibling));
         sibling = nextSibling;
       }
 
       PRInt32 groupLevel = 0;
       if (role == nsIAccessibleRole::ROLE_OUTLINEITEM) {
         groupLevel = 1;
         nsCOMPtr<nsIAccessible> nextParent;
@@ -2245,16 +2292,24 @@ nsAccessible::GetAttributesInternal(nsIP
     if (!sameTypeParent || sameTypeParent == docShellTreeItem)
       break;
     nsIDocument *parentDoc = doc->GetParentDocument();
     if (!parentDoc)
       break;
     startContent = parentDoc->FindContentForSubDocument(doc);      
   }
 
+  // Expose 'display' attribute.
+  nsAutoString displayValue;
+  nsresult rv = GetComputedStyleValue(EmptyString(),
+                                      NS_LITERAL_STRING("display"),
+                                      displayValue);
+  if (NS_SUCCEEDED(rv))
+    nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::display,
+                           displayValue);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAccessible::GroupPosition(PRInt32 *aGroupLevel,
                             PRInt32 *aSimilarItemsInGroup,
                             PRInt32 *aPositionInGroup)
 {
@@ -2463,34 +2518,49 @@ nsAccessible::GetARIAState(PRUint32 *aSt
     return NS_OK;
   }
 
   PRUint32 index = 0;
   while (MappedAttrState(content, aState, &nsARIAMap::gWAIUnivStateMap[index])) {
     ++ index;
   }
 
-  if (!mRoleMapEntry)
-    return NS_OK;
-
-  // Once DHTML role is used, we're only readonly if DHTML readonly used
-  *aState &= ~nsIAccessibleStates::STATE_READONLY;
-
-  if (content->HasAttr(kNameSpaceID_None, content->GetIDAttributeName())) {
-    // If has a role & ID and aria-activedescendant on the container, assume focusable
-    nsIContent *ancestorContent = content;
-    while ((ancestorContent = ancestorContent->GetParent()) != nsnull) {
-      if (ancestorContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_activedescendant)) {
-          // ancestor has activedescendant property, this content could be active
-        *aState |= nsIAccessibleStates::STATE_FOCUSABLE;
-        break;
+  if (mRoleMapEntry) {
+    // Once DHTML role is used, we're only readonly if DHTML readonly used
+    *aState &= ~nsIAccessibleStates::STATE_READONLY;
+
+    if (content->HasAttr(kNameSpaceID_None, content->GetIDAttributeName())) {
+      // If has a role & ID and aria-activedescendant on the container, assume focusable
+      nsIContent *ancestorContent = content;
+      while ((ancestorContent = ancestorContent->GetParent()) != nsnull) {
+        if (ancestorContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_activedescendant)) {
+            // ancestor has activedescendant property, this content could be active
+          *aState |= nsIAccessibleStates::STATE_FOCUSABLE;
+          break;
+        }
       }
     }
   }
 
+  if (*aState & nsIAccessibleStates::STATE_FOCUSABLE) {
+    // Special case: aria-disabled propagates from ancestors down to any focusable descendant
+    nsIContent *ancestorContent = content;
+    while ((ancestorContent = ancestorContent->GetParent()) != nsnull) {
+      if (ancestorContent->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::aria_disabled,
+                                       nsAccessibilityAtoms::_true, eCaseMatters)) {
+          // ancestor has aria-disabled property, this is disabled
+        *aState |= nsIAccessibleStates::STATE_UNAVAILABLE;
+        break;
+      }
+    }    
+  }
+
+  if (!mRoleMapEntry)
+    return NS_OK;
+
   *aState |= mRoleMapEntry->state;
   if (MappedAttrState(content, aState, &mRoleMapEntry->attributeMap1) &&
       MappedAttrState(content, aState, &mRoleMapEntry->attributeMap2) &&
       MappedAttrState(content, aState, &mRoleMapEntry->attributeMap3) &&
       MappedAttrState(content, aState, &mRoleMapEntry->attributeMap4) &&
       MappedAttrState(content, aState, &mRoleMapEntry->attributeMap5) &&
       MappedAttrState(content, aState, &mRoleMapEntry->attributeMap6) &&
       MappedAttrState(content, aState, &mRoleMapEntry->attributeMap7)) {
@@ -2654,18 +2724,21 @@ NS_IMETHODIMP
 nsAccessible::GetNumActions(PRUint8 *aNumActions)
 {
   NS_ENSURE_ARG_POINTER(aNumActions);
   *aNumActions = 0;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
+  nsCOMPtr<nsIContent> content = GetRoleContent(mDOMNode);
+  if (!content)
+    return NS_OK;
+
   // Check if it's an simple xlink.
-  nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
   if (nsAccUtils::IsXLink(content)) {
     *aNumActions = 1;
     return NS_OK;
   }
 
   // Has registered 'click' event handler.
   PRBool isOnclick = nsAccUtils::HasListener(content,
                                              NS_LITERAL_STRING("click"));
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -35,17 +35,16 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef _nsAccessible_H_
 #define _nsAccessible_H_
 
 #include "nsAccessNodeWrap.h"
-#include "nsAccessibilityUtils.h"
 
 #include "nsIAccessible.h"
 #include "nsPIAccessible.h"
 #include "nsIAccessibleHyperLink.h"
 #include "nsIAccessibleSelectable.h"
 #include "nsIAccessibleValue.h"
 #include "nsIAccessibleRole.h"
 #include "nsIAccessibleStates.h"
@@ -192,17 +191,32 @@ protected:
   nsresult AppendNameFromAccessibleFor(nsIContent *aContent, nsAString *aFlatString,
                                        PRBool aFromValue = PR_FALSE);
   nsresult AppendFlatStringFromContentNode(nsIContent *aContent, nsAString *aFlatString);
   nsresult AppendStringWithSpaces(nsAString *aFlatString, const nsAString& textEquivalent);
 
   // helper method to verify frames
   static nsresult GetFullKeyName(const nsAString& aModifierName, const nsAString& aKeyName, nsAString& aStringOut);
   static nsresult GetTranslatedString(const nsAString& aKey, nsAString& aStringOut);
-  nsresult AppendFlatStringFromSubtreeRecurse(nsIContent *aContent, nsAString *aFlatString);
+
+  /**
+   * Walk into subtree and calculate the string which is used as the accessible
+   * name or description.
+   *
+   * @param aContent      [in] traversed content
+   * @param aFlatString   [in, out] result string
+   * @param aIsRootHidden [in] specifies whether root content (we started to
+   *                      traverse from) is hidden, in this case the result
+   *                      string is calculated from hidden children
+   *                      (this is used when hidden root content is explicitly
+   *                      specified as label or description by author)
+   */
+  nsresult AppendFlatStringFromSubtreeRecurse(nsIContent *aContent,
+                                              nsAString *aFlatString,
+                                              PRBool aIsRootHidden);
 
   // Helpers for dealing with children
   virtual void CacheChildren();
   
   // nsCOMPtr<>& is useful here, because getter_AddRefs() nulls the comptr's value, and NextChild
   // depends on the passed-in comptr being null or already set to a child (finding the next sibling).
   nsIAccessible *NextChild(nsCOMPtr<nsIAccessible>& aAccessible);
     
@@ -241,16 +255,26 @@ protected:
    *
    * @param aAriaProperty - the ARIA property we're using
    * @param aValue - value of the attribute
    *
    * @return - NS_OK_NO_ARIA_VALUE if there is no setted ARIA attribute
    */
   nsresult GetAttrValue(nsIAtom *aAriaProperty, double *aValue);
 
+  /**
+   * Fires platform accessible event. It's notification method only. It does
+   * change nothing on Gecko side. Mostly you should use
+   * nsIAccessible::FireAccessibleEvent excepting special cases like we have
+   * in xul:tree accessible to lie to AT. Must be overridden in wrap classes.
+   *
+   * @param aEvent  the accessible event to fire.
+   */
+  virtual nsresult FirePlatformEvent(nsIAccessibleEvent *aEvent) = 0;
+
   // Data Members
   nsCOMPtr<nsIAccessible> mParent;
   nsIAccessible *mFirstChild, *mNextSibling;
   nsRoleMapEntry *mRoleMapEntry; // Non-null indicates author-supplied role; possibly state & value as well
   PRInt32 mAccChildCount;
 };
 
 
--- a/accessible/src/base/nsCaretAccessible.cpp
+++ b/accessible/src/base/nsCaretAccessible.cpp
@@ -34,26 +34,26 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 // NOTE: alphabetically ordered
 #include "nsAccessibilityService.h"
 #include "nsCaretAccessible.h"
 #include "nsIAccessibleEvent.h"
-#include "nsICaret.h"
+#include "nsCaret.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMHTMLAnchorElement.h"
 #include "nsIDOMHTMLInputElement.h"
 #include "nsIDOMHTMLTextAreaElement.h"
 #include "nsIFrame.h"
 #include "nsIPresShell.h"
 #include "nsRootAccessible.h"
-#include "nsISelectionController.h"
 #include "nsISelectionPrivate.h"
+#include "nsISelection2.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIViewManager.h"
 #include "nsIWidget.h"
 
 NS_IMPL_ISUPPORTS1(nsCaretAccessible, nsISelectionListener)
   
 nsCaretAccessible::nsCaretAccessible( nsRootAccessible *aRootAccessible):
 mLastCaretOffset(-1), mRootAccessible(aRootAccessible)
@@ -73,104 +73,150 @@ void nsCaretAccessible::Shutdown()
   ClearControlSelectionListener(); // Clear the selection listener for the currently focused control
   mLastTextAccessible = nsnull;
   mLastUsedSelection = nsnull;
   mRootAccessible = nsnull;
 }
 
 nsresult nsCaretAccessible::ClearControlSelectionListener()
 {
+  nsCOMPtr<nsISelectionController> controller =
+    GetSelectionControllerForNode(mCurrentControl);
+
   mCurrentControl = nsnull;
-  mCurrentControlSelection = nsnull;
+
+  if (!controller)
+    return NS_OK;
 
-  nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryReferent(mCurrentControlSelection));
-  if (!selPrivate) {
-    return NS_OK;
-  }
+  // Remove 'this' registered as selection listener for the normal selection.
+  nsCOMPtr<nsISelection> normalSel;
+  controller->GetSelection(nsISelectionController::SELECTION_NORMAL,
+                           getter_AddRefs(normalSel));
+  nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(normalSel));
+  NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
+
+  nsresult rv = selPrivate->RemoveSelectionListener(this);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Remove 'this' registered as selection listener for the spellcheck
+  // selection.
+  nsCOMPtr<nsISelection> spellcheckSel;
+  controller->GetSelection(nsISelectionController::SELECTION_SPELLCHECK,
+                           getter_AddRefs(spellcheckSel));
+  selPrivate = do_QueryInterface(spellcheckSel);
+  NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
 
   return selPrivate->RemoveSelectionListener(this);
 }
 
 nsresult nsCaretAccessible::SetControlSelectionListener(nsIDOMNode *aCurrentNode)
 {
   NS_ENSURE_TRUE(mRootAccessible, NS_ERROR_FAILURE);
 
   ClearControlSelectionListener();
 
   mCurrentControl = aCurrentNode;
   mLastTextAccessible = nsnull;
 
   // When focus moves such that the caret is part of a new frame selection
-  // this removes the old selection listener and attaches a new one for the current focus
-  nsCOMPtr<nsIPresShell> presShell = 
-    mRootAccessible->GetPresShellFor(aCurrentNode);
-  if (!presShell)
-    return NS_ERROR_FAILURE;
-
-  nsCOMPtr<nsIDocument> doc = presShell->GetDocument();
-  NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
+  // this removes the old selection listener and attaches a new one for
+  // the current focus.
+  nsCOMPtr<nsISelectionController> controller =
+    GetSelectionControllerForNode(mCurrentControl);
+  NS_ENSURE_TRUE(controller, NS_ERROR_FAILURE);
 
-  nsCOMPtr<nsIContent> content(do_QueryInterface(aCurrentNode));
-  // The control selection listener is only for form controls, not for the document
-  // When there is no document, the content will be null
-  if (!content) {
-    return NS_OK;
-  }
-
-  nsIFrame *frame = presShell->GetPrimaryFrameFor(content);
-  NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
-
-  nsPresContext *presContext = presShell->GetPresContext();
-  NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
-
-  nsCOMPtr<nsISelectionController> selCon;
-  frame->GetSelectionController(presContext, getter_AddRefs(selCon));
-  NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
-  
-  nsCOMPtr<nsISelection> domSel;
-  selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSel));
-
-  nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(domSel));
+  // Register 'this' as selection listener for the normal selection.
+  nsCOMPtr<nsISelection> normalSel;
+  controller->GetSelection(nsISelectionController::SELECTION_NORMAL,
+                           getter_AddRefs(normalSel));
+  nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(normalSel));
   NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
 
-  mCurrentControlSelection = do_GetWeakReference(domSel);
+  nsresult rv = selPrivate->AddSelectionListener(this);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Register 'this' as selection listener for the spellcheck selection.
+  nsCOMPtr<nsISelection> spellcheckSel;
+  controller->GetSelection(nsISelectionController::SELECTION_SPELLCHECK,
+                           getter_AddRefs(spellcheckSel));
+  selPrivate = do_QueryInterface(spellcheckSel);
+  NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
+  
   return selPrivate->AddSelectionListener(this);
 }
 
 nsresult
 nsCaretAccessible::AddDocSelectionListener(nsIPresShell *aShell)
 {
   NS_ENSURE_TRUE(mRootAccessible, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsISelectionController> selCon = do_QueryInterface(aShell);
   NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsISelection> domSel;
   selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSel));
   nsCOMPtr<nsISelectionPrivate> selPrivate = do_QueryInterface(domSel);
   NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
 
+  nsresult rv = selPrivate->AddSelectionListener(this);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsISelection> spellcheckSel;
+  selCon->GetSelection(nsISelectionController::SELECTION_SPELLCHECK,
+                       getter_AddRefs(spellcheckSel));
+  selPrivate = do_QueryInterface(spellcheckSel);
+  NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
+  
   return selPrivate->AddSelectionListener(this);
 }
 
 nsresult
 nsCaretAccessible::RemoveDocSelectionListener(nsIPresShell *aShell)
 {
   nsCOMPtr<nsISelectionController> selCon = do_QueryInterface(aShell);
   NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsISelection> domSel;
   selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSel));
   nsCOMPtr<nsISelectionPrivate> selPrivate = do_QueryInterface(domSel);
   NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
 
+  selPrivate->RemoveSelectionListener(this);
+
+  nsCOMPtr<nsISelection> spellcheckSel;
+  selCon->GetSelection(nsISelectionController::SELECTION_SPELLCHECK,
+                       getter_AddRefs(spellcheckSel));
+  selPrivate = do_QueryInterface(spellcheckSel);
+  NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
+
   return selPrivate->RemoveSelectionListener(this);
 }
 
-NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel, PRInt16 aReason)
+NS_IMETHODIMP
+nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc,
+                                          nsISelection *aSel,
+                                          PRInt16 aReason)
+{
+  nsCOMPtr<nsISelection2> sel2(do_QueryInterface(aSel));
+
+  PRInt16 type = 0;
+  sel2->GetType(&type);
+
+  if (type == nsISelectionController::SELECTION_NORMAL)
+    return NormalSelectionChanged(aDoc, aSel);
+
+  if (type == nsISelectionController::SELECTION_SPELLCHECK)
+    return SpellcheckSelectionChanged(aDoc, aSel);
+
+  return NS_OK;
+}
+
+nsresult
+nsCaretAccessible::NormalSelectionChanged(nsIDOMDocument *aDoc,
+                                          nsISelection *aSel)
 {
   NS_ENSURE_TRUE(mRootAccessible, NS_ERROR_FAILURE);
 
   mLastUsedSelection = do_GetWeakReference(aSel);
 
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
   NS_ENSURE_TRUE(doc, NS_OK);
   nsIPresShell *presShell = doc->GetPrimaryShell();
@@ -242,16 +288,48 @@ NS_IMETHODIMP nsCaretAccessible::NotifyS
 
   nsCOMPtr<nsIAccessibleCaretMoveEvent> event =
     new nsAccCaretMoveEvent(focusNode);
   NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
 
   return mRootAccessible->FireDelayedAccessibleEvent(event);
 }
 
+nsresult
+nsCaretAccessible::SpellcheckSelectionChanged(nsIDOMDocument *aDoc,
+                                              nsISelection *aSel)
+{
+  // XXX: fire an event for accessible of focus node of the selection. If
+  // spellchecking is enabled then we will fire the number of events for
+  // the same accessible for newly appended range of the selection (for every
+  // misspelled word). If spellchecking is disabled (for example,
+  // @spellcheck="false" on html:body) then we won't fire any event.
+  nsCOMPtr<nsIDOMNode> targetNode;
+  aSel->GetFocusNode(getter_AddRefs(targetNode));
+  if (!targetNode)
+    return NS_OK;
+
+  nsCOMPtr<nsIAccessibleDocument> docAccessible =
+    nsAccessNode::GetDocAccessibleFor(targetNode);
+  NS_ENSURE_STATE(docAccessible);
+
+  nsCOMPtr<nsIAccessible> containerAccessible;
+  nsresult rv =
+    docAccessible->GetAccessibleInParentChain(targetNode, PR_TRUE,
+                                              getter_AddRefs(containerAccessible));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIAccessibleEvent> event =
+    new nsAccEvent(nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED,
+                   containerAccessible, nsnull);
+  NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
+
+  return mRootAccessible->FireAccessibleEvent(event);
+}
+
 nsRect
 nsCaretAccessible::GetCaretRect(nsIWidget **aOutWidget)
 {
   nsRect caretRect;
   NS_ENSURE_TRUE(aOutWidget, caretRect);
   *aOutWidget = nsnull;
   NS_ENSURE_TRUE(mRootAccessible, caretRect);
 
@@ -264,26 +342,26 @@ nsCaretAccessible::GetCaretRect(nsIWidge
 
   nsCOMPtr<nsIDOMNode> lastNodeWithCaret;
   lastAccessNode->GetDOMNode(getter_AddRefs(lastNodeWithCaret));
   NS_ENSURE_TRUE(lastNodeWithCaret, caretRect);
 
   nsCOMPtr<nsIPresShell> presShell = mRootAccessible->GetPresShellFor(lastNodeWithCaret);
   NS_ENSURE_TRUE(presShell, caretRect);
 
-  nsCOMPtr<nsICaret> caret;
+  nsRefPtr<nsCaret> caret;
   presShell->GetCaret(getter_AddRefs(caret));
   NS_ENSURE_TRUE(caret, caretRect);
 
   PRBool isCollapsed;
   nsIView *view;
   nsCOMPtr<nsISelection> caretSelection(do_QueryReferent(mLastUsedSelection));
   NS_ENSURE_TRUE(caretSelection, caretRect);
   
-  caret->GetCaretCoordinates(nsICaret::eRenderingViewCoordinates, caretSelection,
+  caret->GetCaretCoordinates(nsCaret::eRenderingViewCoordinates, caretSelection,
                              &caretRect, &isCollapsed, &view);
   if (!view || caretRect.IsEmpty()) {
     return nsRect(); // Return empty rect
   }
 
   PRBool isVisible;
   caret->GetCaretVisible(&isVisible);
   if (!isVisible) {
@@ -312,8 +390,40 @@ nsCaretAccessible::GetCaretRect(nsIWidge
                                                             nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE))) {
     caretRect.height -= charY - caretRect.y;
     caretRect.y = charY;
   }
 
   return caretRect;
 }
 
+already_AddRefed<nsISelectionController>
+nsCaretAccessible::GetSelectionControllerForNode(nsIDOMNode *aNode)
+{
+  if (!aNode)
+    return nsnull;
+
+  nsCOMPtr<nsIPresShell> presShell = mRootAccessible->GetPresShellFor(aNode);
+  if (!presShell)
+    return nsnull;
+
+  nsCOMPtr<nsIDocument> doc = presShell->GetDocument();
+  if (!doc)
+    return nsnull;
+
+  // Get selection controller only for form controls, not for the document.
+  nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
+  if (!content)
+    return nsnull;
+
+  nsIFrame *frame = presShell->GetPrimaryFrameFor(content);
+  if (!frame)
+    return nsnull;
+
+  nsPresContext *presContext = presShell->GetPresContext();
+  if (!presContext)
+    return nsnull;
+
+  nsISelectionController *controller = nsnull;
+  frame->GetSelectionController(presContext, &controller);
+  return controller;
+}
+
--- a/accessible/src/base/nsCaretAccessible.h
+++ b/accessible/src/base/nsCaretAccessible.h
@@ -35,23 +35,25 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __nsCaretAccessible_h__
 #define __nsCaretAccessible_h__
 
 #include "nsIWeakReference.h"
 #include "nsIAccessibleText.h"
-#include "nsICaret.h"
 #include "nsIDOMNode.h"
 #include "nsISelectionListener.h"
+#include "nsISelectionController.h"
 #include "nsRect.h"
 
 class nsRootAccessible;
 class nsIView;
+class nsIPresShell;
+class nsIWidget;
 
 /*
  * This special accessibility class is for the caret, which is really the currently focused selection.
  * There is only 1 visible caret per top level window (nsRootAccessible),
  * However, there may be several visible selections.
  *
  * The important selections are the one owned by each document, and the one in the currently focused control.
  *
@@ -114,27 +116,33 @@ public:
    * instead of document because it is more direct than getting it from
    * the document, and in any case it is unavailable from the doc after a pagehide.
    * @param aShell   PresShell for document to no longer listen to selection events from.
    */
   nsresult RemoveDocSelectionListener(nsIPresShell *aShell);
 
   nsRect GetCaretRect(nsIWidget **aOutWidget);
 
+protected:
+  nsresult NormalSelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel);
+  nsresult SpellcheckSelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel);
+
+  already_AddRefed<nsISelectionController>
+  GetSelectionControllerForNode(nsIDOMNode *aNode);
+
 private:
   // The currently focused control -- never a document.
   // We listen to selection for one control at a time (the focused one)
   // Document selection is handled separately via additional listeners on all active documents
   // The current control is set via SetControlSelectionListener()
   nsCOMPtr<nsIDOMNode> mCurrentControl;  // Selection controller for the currently focused control
-  nsCOMPtr<nsIWeakReference> mCurrentControlSelection;
 
-  // Info for the the last selection event
-  // If it was on a control, then mLastUsedSelection == mCurrentControlSelection
-  // Otherwise, it's for a document where the selection changed
+  // Info for the the last selection event.
+  // If it was on a control, then it's control's selection. Otherwise, it's for
+  // a document where the selection changed.
   nsCOMPtr<nsIWeakReference> mLastUsedSelection; // Weak ref to nsISelection
   nsCOMPtr<nsIAccessibleText> mLastTextAccessible;
   PRInt32 mLastCaretOffset;
 
   nsRootAccessible *mRootAccessible;
 };
 
 #endif
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -80,17 +80,18 @@
 PRUint32 nsDocAccessible::gLastFocusedAccessiblesState = 0;
 nsIAtom *nsDocAccessible::gLastFocusedFrameType = nsnull;
 
 //-----------------------------------------------------
 // construction
 //-----------------------------------------------------
 nsDocAccessible::nsDocAccessible(nsIDOMNode *aDOMNode, nsIWeakReference* aShell):
   nsHyperTextAccessibleWrap(aDOMNode, aShell), mWnd(nsnull),
-  mScrollPositionChangedTicks(0), mIsContentLoaded(PR_FALSE), mIsLoadCompleteFired(PR_FALSE)
+  mScrollPositionChangedTicks(0), mIsContentLoaded(PR_FALSE),
+  mIsLoadCompleteFired(PR_FALSE), mInFlushPendingEvents(PR_FALSE)
 {
   // 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
@@ -252,16 +253,19 @@ nsDocAccessible::GetState(PRUint32 *aSta
   nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocument));
   if (!xulDoc)
 #endif
   {
     // XXX Need to invent better check to see if doc is focusable,
     // which it should be if it is scrollable. A XUL document could be focusable.
     // See bug 376803.
     *aState |= nsIAccessibleStates::STATE_FOCUSABLE;
+    if (gLastFocusedNode == mDOMNode) {
+      *aState |= nsIAccessibleStates::STATE_FOCUSED;
+    }
   }
 
   if (!mIsContentLoaded) {
     *aState |= nsIAccessibleStates::STATE_BUSY;
     if (aExtraState) {
       *aExtraState |= nsIAccessibleStates::EXT_STATE_STALE;
     }
   }
@@ -508,18 +512,30 @@ NS_IMETHODIMP nsDocAccessible::GetCached
     if (privateParent) {
       privateParent->TestChildCache(accessible);
     }
   }
 #endif
   return NS_OK;
 }
 
-NS_IMETHODIMP nsDocAccessible::CacheAccessNode(void *aUniqueID, nsIAccessNode *aAccessNode)
+NS_IMETHODIMP
+nsDocAccessible::CacheAccessNode(void *aUniqueID, nsIAccessNode *aAccessNode)
 {
+  // If there is an access node for the given unique ID then let's shutdown it.
+  // The unique ID may be presented in the cache if originally we created
+  // access node object and then we want to create accessible object when
+  // DOM node is changed.
+  nsCOMPtr<nsIAccessNode> accessNode;
+  GetCacheEntry(mAccessNodeCache, aUniqueID, getter_AddRefs(accessNode));
+  if (accessNode) {
+    nsCOMPtr<nsPIAccessNode> prAccessNode = do_QueryInterface(accessNode);
+    prAccessNode->Shutdown();
+  }
+
   PutCacheEntry(mAccessNodeCache, aUniqueID, aAccessNode);
   return NS_OK;
 }
 
 NS_IMETHODIMP nsDocAccessible::GetParent(nsIAccessible **aParent)
 {
   // Hook up our new accessible with our parent
   *aParent = nsnull;
@@ -581,17 +597,20 @@ NS_IMETHODIMP nsDocAccessible::Shutdown(
   if (mFireEventTimer) {
     // Doc being shut down before events fired,
     mFireEventTimer->Cancel();
     mFireEventTimer = nsnull;
     if (mEventsToFire.Count() > 0 ) {
       mEventsToFire.Clear();
       // Make sure we release the kung fu death grip which is always
       // there when there are still events left to be fired
-      NS_RELEASE_THIS();
+      // If FlushPendingEvents() is in call stack,
+      // kung fu death grip will be released there.
+      if (!mInFlushPendingEvents)
+        NS_RELEASE_THIS();
     }
   }
 
   // Remove from the cache after other parts of Shutdown(), so that Shutdown() procedures
   // can find the doc or root accessible in the cache if they need it.
   // We don't do this during ShutdownAccessibility() because that is already clearing the cache
   if (!gIsShuttingDownApp)
     gGlobalDocAccessibleCache.Remove(static_cast<void*>(kungFuDeathGripDoc));
@@ -849,18 +868,28 @@ NS_IMETHODIMP nsDocAccessible::FireDocLo
           nsCOMPtr<nsIAccessibleStateChangeEvent> accEvent =
             new nsAccStateChangeEvent(this, nsIAccessibleStates::STATE_BUSY, PR_FALSE, PR_FALSE);
           FireAccessibleEvent(accEvent);
           FireAnchorJumpEvent();
         }
       }
     }
   }
+
   if (sameTypeRoot == treeItem) {
     // Not a frame or iframe
+    if (!isFinished) {
+      // Fire state change event to set STATE_BUSY when document is loading. For
+      // example, Window-Eyes expects to get it.
+      nsCOMPtr<nsIAccessibleStateChangeEvent> accEvent =
+        new nsAccStateChangeEvent(this, nsIAccessibleStates::STATE_BUSY,
+                                  PR_FALSE, PR_TRUE);
+      FireAccessibleEvent(accEvent);
+    }
+
     nsAccUtils::FireAccEvent(aEventType, this);
   }
   return NS_OK;
 }
 
 void nsDocAccessible::ScrollTimerCallback(nsITimer *aTimer, void *aClosure)
 {
   nsDocAccessible *docAcc = reinterpret_cast<nsDocAccessible*>(aClosure);
@@ -1487,16 +1516,17 @@ nsDocAccessible::FireDelayedAccessibleEv
                                           0, nsITimer::TYPE_ONE_SHOT);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsDocAccessible::FlushPendingEvents()
 {
+  mInFlushPendingEvents = PR_TRUE;
   PRUint32 length = mEventsToFire.Count();
   NS_ASSERTION(length, "How did we get here without events to fire?");
   nsCOMPtr<nsIPresShell> presShell = GetPresShell();
   if (!presShell)
     length = 0; // The doc is now shut down, don't fire events in it anymore
   else
     nsAccEvent::ApplyEventRules(mEventsToFire);
   
@@ -1510,18 +1540,18 @@ NS_IMETHODIMP nsDocAccessible::FlushPend
     nsCOMPtr<nsIAccessible> accessible;
     accessibleEvent->GetAccessible(getter_AddRefs(accessible));
     nsCOMPtr<nsIDOMNode> domNode;
     accessibleEvent->GetDOMNode(getter_AddRefs(domNode));
     PRUint32 eventType = nsAccEvent::EventType(accessibleEvent);
     PRBool isFromUserInput = nsAccEvent::IsFromUserInput(accessibleEvent);
 
     if (domNode == gLastFocusedNode &&
-        eventType == nsIAccessibleEvent::EVENT_ASYNCH_HIDE || 
-        eventType == nsIAccessibleEvent::EVENT_ASYNCH_SHOW) {
+        (eventType == nsIAccessibleEvent::EVENT_ASYNCH_HIDE || 
+        eventType == nsIAccessibleEvent::EVENT_ASYNCH_SHOW)) {
       // If frame type didn't change for this event, then we don't actually need to invalidate
       // However, we only keep track of the old frame type for the focus, where it's very
       // important not to destroy and recreate the accessible for minor style changes,
       // such as a:focus { overflow: scroll; }
       nsCOMPtr<nsIContent> focusContent(do_QueryInterface(domNode));
       if (focusContent) {
         nsIFrame *focusFrame = presShell->GetRealPrimaryFrameFor(focusContent);
         nsIAtom *newFrameType =
@@ -1607,17 +1637,18 @@ NS_IMETHODIMP nsDocAccessible::FlushPend
           // Test caret line # -- fire an EVENT_ALERT on the focused node so we can watch the
           // line-number object attribute on it
           nsCOMPtr<nsIAccessible> accForFocus;
           GetAccService()->GetAccessibleFor(gLastFocusedNode, getter_AddRefs(accForFocus));
           nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_ALERT, accForFocus);
 #endif
           nsCOMPtr<nsIAccessibleCaretMoveEvent> caretMoveEvent =
             new nsAccCaretMoveEvent(accessible, caretOffset);
-          NS_ENSURE_TRUE(caretMoveEvent, NS_ERROR_OUT_OF_MEMORY);
+          if (!caretMoveEvent)
+            break; // Out of memory, break out to release kung fu death grip
 
           FireAccessibleEvent(caretMoveEvent);
 
           PRInt32 selectionCount;
           accessibleText->GetSelectionCount(&selectionCount);
           if (selectionCount) {  // There's a selection so fire selection change as well
             nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED,
                                      accessible, PR_TRUE);
@@ -1643,16 +1674,17 @@ NS_IMETHODIMP nsDocAccessible::FlushPend
     }
   }
   mEventsToFire.Clear(); // Clear out array
   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;
   return NS_OK;
 }
 
 void nsDocAccessible::FlushEventsCallback(nsITimer *aTimer, void *aClosure)
 {
   nsPIAccessibleDocument *accessibleDoc = static_cast<nsPIAccessibleDocument*>(aClosure);
   NS_ASSERTION(accessibleDoc, "How did we get here without an accessible document?");
   if (accessibleDoc) {
@@ -1723,19 +1755,18 @@ void nsDocAccessible::RefreshNodes(nsIDO
         children->GetLength(&childCount);
       nsCOMPtr<nsIDOMNode> possibleAnonNode;
       for (PRUint32 index = 0; index < childCount; index++) {
         nsCOMPtr<nsIAccessNode> childAccessNode;
         children->QueryElementAt(index, NS_GET_IID(nsIAccessNode),
                                  getter_AddRefs(childAccessNode));
         childAccessNode->GetDOMNode(getter_AddRefs(possibleAnonNode));
         nsCOMPtr<nsIContent> iterContent = do_QueryInterface(possibleAnonNode);
-        if (iterContent && (iterContent->IsNativeAnonymous() ||
-                            iterContent->GetBindingParent())) {
-          // GetBindingParent() check is a perf win -- make sure we don't
+        if (iterContent && iterContent->IsInAnonymousSubtree()) {
+          // IsInAnonymousSubtree() check is a perf win -- make sure we don't
           // shut down the same subtree twice since we'll reach non-anon content via
           // DOM traversal later in this method
           RefreshNodes(possibleAnonNode);
         }
       }
     }
   }
 
@@ -1965,27 +1996,24 @@ NS_IMETHODIMP nsDocAccessible::Invalidat
         break;
       }
       roleMapEntry = nsAccUtils::GetRoleMapEntry(ancestorNode);
     }
   }
 
   FireValueChangeForTextFields(containerAccessible);
 
-  if (!isShowing) {
-    // Fire an event so the assistive technology knows the children have changed
-    // This is only used by older MSAA clients. Newer ones should derive this
-    // from SHOW and HIDE so that they don't fetch extra objects
-    if (childAccessible) {
-      nsCOMPtr<nsIAccessibleEvent> reorderEvent =
-        new nsAccEvent(nsIAccessibleEvent::EVENT_REORDER, containerAccessible,
-                       isAsynch, nsAccEvent::eCoalesceFromSameSubtree);
-      NS_ENSURE_TRUE(reorderEvent, NS_ERROR_OUT_OF_MEMORY);
-      FireDelayedAccessibleEvent(reorderEvent);
-    }
+  if (childAccessible) {
+    // Fire an event so the MSAA clients know the children have changed. Also
+    // the event is used internally by MSAA part.
+    nsCOMPtr<nsIAccessibleEvent> reorderEvent =
+      new nsAccEvent(nsIAccessibleEvent::EVENT_REORDER, containerAccessible,
+                     isAsynch, nsAccEvent::eCoalesceFromSameSubtree);
+    NS_ENSURE_TRUE(reorderEvent, NS_ERROR_OUT_OF_MEMORY);
+    FireDelayedAccessibleEvent(reorderEvent);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocAccessible::GetAccessibleInParentChain(nsIDOMNode *aNode,
                                             PRBool aCanCreate,
--- a/accessible/src/base/nsDocAccessible.h
+++ b/accessible/src/base/nsDocAccessible.h
@@ -216,13 +216,14 @@ class nsDocAccessible : public nsHyperTe
     PRUint16 mScrollPositionChangedTicks; // Used for tracking scroll events
     PRPackedBool mIsContentLoaded;
     PRPackedBool mIsLoadCompleteFired;
     nsCOMArray<nsIAccessibleEvent> mEventsToFire;
 
 protected:
     PRBool mIsAnchor;
     PRBool mIsAnchorJumped;
+    PRBool mInFlushPendingEvents;
     static PRUint32 gLastFocusedAccessiblesState;
     static nsIAtom *gLastFocusedFrameType;
 };
 
 #endif  
--- a/accessible/src/base/nsOuterDocAccessible.cpp
+++ b/accessible/src/base/nsOuterDocAccessible.cpp
@@ -143,8 +143,40 @@ nsOuterDocAccessible::GetAttributesInter
   aAttributes->GetStringProperty(NS_LITERAL_CSTRING("tag"), tag);
   if (!tag.IsEmpty()) {
     // We're overriding the ARIA attributes on an sub document, but we don't want to
     // override the other attributes
     return NS_OK;
   }
   return nsAccessible::GetAttributesInternal(aAttributes);
 }
+
+// Internal frame, which is the doc's parent, should not have a click action
+NS_IMETHODIMP
+nsOuterDocAccessible::GetNumActions(PRUint8 *aNumActions)
+{
+  NS_ENSURE_ARG_POINTER(aNumActions);
+  *aNumActions = 0;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsOuterDocAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
+{
+  aName.Truncate();
+
+  return NS_ERROR_INVALID_ARG;
+}
+
+NS_IMETHODIMP
+nsOuterDocAccessible::GetActionDescription(PRUint8 aIndex, nsAString& aDescription)
+{
+  aDescription.Truncate();
+
+  return NS_ERROR_INVALID_ARG;
+}
+
+NS_IMETHODIMP
+nsOuterDocAccessible::DoAction(PRUint8 aIndex)
+{
+  return NS_ERROR_INVALID_ARG;
+}
--- a/accessible/src/base/nsOuterDocAccessible.h
+++ b/accessible/src/base/nsOuterDocAccessible.h
@@ -53,11 +53,15 @@ class nsOuterDocAccessible : public nsAc
                          nsIWeakReference* aShell);
 
     NS_IMETHOD GetRole(PRUint32 *aRole);
     NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
     NS_IMETHOD GetChildAtPoint(PRInt32 aX, PRInt32 aY,
                                nsIAccessible **aAccessible);
     void CacheChildren();
     nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
+    NS_IMETHOD GetNumActions(PRUint8 *aNumActions);
+    NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
+    NS_IMETHODIMP GetActionDescription(PRUint8 aIndex, nsAString& aDescription);
+    NS_IMETHOD DoAction(PRUint8 aIndex);
 };
 
 #endif  
--- a/accessible/src/base/nsRootAccessible.cpp
+++ b/accessible/src/base/nsRootAccessible.cpp
@@ -35,17 +35,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 // NOTE: alphabetically ordered
 #include "nsAccessibilityService.h"
 #include "nsAccessibleEventData.h"
 #include "nsHTMLSelectAccessible.h"
 #include "nsIBaseWindow.h"
-#include "nsICaret.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"
@@ -638,28 +637,16 @@ nsresult nsRootAccessible::HandleEventWi
   if (eventType.EqualsLiteral("DOMContentLoaded")) {
     // Don't create the doc accessible until load scripts have a chance to set
     // role attribute for <body> or <html> element, because the value of 
     // role attribute will be cached when the doc accessible is Init()'d
     TryFireEarlyLoadEvent(aTargetNode);
     return NS_OK;
   }
 
-#ifdef MOZ_XUL
-  if (eventType.EqualsLiteral("TreeViewChanged")) { // Always asynch, always from user input
-    if (!isTree)
-      return NS_OK;
-
-    nsCOMPtr<nsIContent> treeContent = do_QueryInterface(aTargetNode);
-    nsAccEvent::PrepareForEvent(aTargetNode, PR_TRUE);
-    return accService->InvalidateSubtreeFor(eventShell, treeContent,
-                                            nsIAccessibleEvent::EVENT_DOM_SIGNIFICANT_CHANGE);
-  }
-#endif
-
   if (eventType.EqualsLiteral("popuphiding")) {
     // If accessible focus was on or inside popup that closes,
     // then restore it to true current focus.
     // This is the case when we've been getting DOMMenuItemActive events
     // inside of a combo box that closes. The real focus is on the combo box.
     // It's also the case when a popup gets focus in ATK -- when it closes
     // we need to fire an event to restore focus to where it was
     if (!gLastFocusedNode ||
@@ -673,21 +660,32 @@ nsresult nsRootAccessible::HandleEventWi
   nsCOMPtr<nsIAccessible> accessible;
   accService->GetAccessibleInShell(aTargetNode, eventShell,
                                    getter_AddRefs(accessible));
   nsCOMPtr<nsPIAccessible> privAcc(do_QueryInterface(accessible));
   if (!privAcc)
     return NS_OK;
 
 #ifdef MOZ_XUL
-  if (eventType.EqualsLiteral("TreeRowCountChanged"))
-    return HandleTreeRowCountChangedEvent(aEvent, accessible, localName);
-  
-  if (eventType.EqualsLiteral("TreeInvalidated"))
-    return HandleTreeInvalidatedEvent(aEvent, accessible, localName);
+  if (isTree) {
+    nsCOMPtr<nsIAccessibleTreeCache> treeAcc(do_QueryInterface(accessible));
+    NS_ASSERTION(treeAcc,
+                 "Accessible for xul:tree doesn't implement nsIAccessibleTreeCache interface.");
+
+    if (treeAcc) {
+      if (eventType.EqualsLiteral("TreeViewChanged"))
+        return treeAcc->TreeViewChanged();
+
+      if (eventType.EqualsLiteral("TreeRowCountChanged"))
+        return HandleTreeRowCountChangedEvent(aEvent, treeAcc);
+      
+      if (eventType.EqualsLiteral("TreeInvalidated"))
+        return HandleTreeInvalidatedEvent(aEvent, treeAcc);
+    }
+  }
 #endif
 
   if (eventType.EqualsLiteral("RadioStateChange")) {
     PRUint32 state = State(accessible);
 
     // radiogroup in prefWindow is exposed as a list,
     // and panebutton is exposed as XULListitem in A11y.
     // nsXULListitemAccessible::GetState uses STATE_SELECTED in this case,
@@ -1090,22 +1088,18 @@ NS_IMETHODIMP nsRootAccessible::FireDocL
   mIsContentLoaded = (aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE ||
                       aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED);
 
   return NS_OK;
 }
 
 nsresult
 nsRootAccessible::HandleTreeRowCountChangedEvent(nsIDOMEvent *aEvent,
-                                                 nsIAccessible *aAccessible,
-                                                 const nsAString& aTargetName)
+                                                 nsIAccessibleTreeCache *aAccessible)
 {
-  if (!aTargetName.EqualsLiteral("tree"))
-    return NS_OK;
-
   nsCOMPtr<nsIDOMDataContainerEvent> dataEvent(do_QueryInterface(aEvent));
   if (!dataEvent)
     return NS_OK;
 
   nsCOMPtr<nsIVariant> indexVariant;
   dataEvent->GetData(NS_LITERAL_STRING("index"),
                      getter_AddRefs(indexVariant));
   if (!indexVariant)
@@ -1116,30 +1110,23 @@ nsRootAccessible::HandleTreeRowCountChan
                      getter_AddRefs(countVariant));
   if (!countVariant)
     return NS_OK;
 
   PRInt32 index, count;
   indexVariant->GetAsInt32(&index);
   countVariant->GetAsInt32(&count);
 
-  nsCOMPtr<nsIAccessibleTreeCache> treeAccCache(do_QueryInterface(aAccessible));
-  NS_ENSURE_STATE(treeAccCache);
-
-  return treeAccCache->InvalidateCache(index, count);
+  return aAccessible->InvalidateCache(index, count);
 }
 
 nsresult
 nsRootAccessible::HandleTreeInvalidatedEvent(nsIDOMEvent *aEvent,
-                                             nsIAccessible *aAccessible,
-                                             const nsAString& aTargetName)
+                                             nsIAccessibleTreeCache *aAccessible)
 {
-  if (!aTargetName.EqualsLiteral("tree"))
-    return NS_OK;
-
   nsCOMPtr<nsIDOMDataContainerEvent> dataEvent(do_QueryInterface(aEvent));
   if (!dataEvent)
     return NS_OK;
 
   PRInt32 startRow = 0, endRow = -1, startCol = 0, endCol = -1;
 
   nsCOMPtr<nsIVariant> startRowVariant;
   dataEvent->GetData(NS_LITERAL_STRING("startrow"),
@@ -1160,14 +1147,11 @@ nsRootAccessible::HandleTreeInvalidatedE
     startColVariant->GetAsInt32(&startCol);
 
   nsCOMPtr<nsIVariant> endColVariant;
   dataEvent->GetData(NS_LITERAL_STRING("endcolumn"),
                      getter_AddRefs(endColVariant));
   if (endColVariant)
     endColVariant->GetAsInt32(&endCol);
 
-  nsCOMPtr<nsIAccessibleTreeCache> treeAcc(do_QueryInterface(aAccessible));
-  NS_ENSURE_STATE(treeAcc);
-
-  return treeAcc->TreeViewInvalidated(startRow, endRow, startCol, endCol);
+  return aAccessible->TreeViewInvalidated(startRow, endRow, startCol, endCol);
 }
 
--- a/accessible/src/base/nsRootAccessible.h
+++ b/accessible/src/base/nsRootAccessible.h
@@ -33,19 +33,23 @@
  * 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 _nsRootAccessible_H_
 #define _nsRootAccessible_H_
 
+#include "nsCaretAccessible.h"
 #include "nsDocAccessibleWrap.h"
+
+#include "nsIAccessibleDocument.h"
+#include "nsIAccessibleTreeCache.h"
+
 #include "nsHashtable.h"
-#include "nsIAccessibleDocument.h"
 #include "nsCaretAccessible.h"
 #include "nsIDocument.h"
 #include "nsIDOMFocusListener.h"
 #include "nsIDOMFormListener.h"
 #include "nsIDOMXULListener.h"
 #include "nsITimer.h"
 
 #define NS_ROOTACCESSIBLE_IMPL_CID                      \
@@ -98,46 +102,48 @@ class nsRootAccessible : public nsDocAcc
       * @param aForceEvent       Fire a focus event even if the last focused item was the same
       * @return                  Boolean -- was a focus event actually fired
       */
     PRBool FireAccessibleFocusEvent(nsIAccessible *aFocusAccessible,
                                     nsIDOMNode *aFocusNode,
                                     nsIDOMEvent *aFocusEvent,
                                     PRBool aForceEvent = PR_FALSE,
                                     PRBool aIsAsynch = PR_FALSE);
+    /**
+      * Fire an accessible focus event for the current focused node,
+      * if there is a focus.
+      */
+    void FireCurrentFocusEvent();
 
     nsCaretAccessible *GetCaretAccessible();
 
   private:
     nsCOMPtr<nsITimer> mFireFocusTimer;
     static void FireFocusCallback(nsITimer *aTimer, void *aClosure);
     
   protected:
     nsresult AddEventListeners();
     nsresult RemoveEventListeners();
     nsresult HandleEventWithTarget(nsIDOMEvent* aEvent,
                                    nsIDOMNode* aTargetNode);
     static void GetTargetNode(nsIDOMEvent *aEvent, nsIDOMNode **aTargetNode);
     void TryFireEarlyLoadEvent(nsIDOMNode *aDocNode);
-    void FireCurrentFocusEvent();
     void GetChromeEventHandler(nsIDOMEventTarget **aChromeTarget);
 
     /**
      * Handles 'TreeRowCountChanged' event. Used in HandleEventWithTarget().
      */
     nsresult HandleTreeRowCountChangedEvent(nsIDOMEvent *aEvent,
-                                            nsIAccessible *aAccessible,
-                                            const nsAString& aTargetName);
+                                            nsIAccessibleTreeCache *aAccessible);
 
     /**
      * Handles 'TreeInvalidated' event. Used in HandleEventWithTarget().
      */
     nsresult HandleTreeInvalidatedEvent(nsIDOMEvent *aEvent,
-                                        nsIAccessible *aAccessible,
-                                        const nsAString& aTargetName);
+                                        nsIAccessibleTreeCache *aAccessible);
 
 #ifdef MOZ_XUL
     PRUint32 GetChromeFlags();
 #endif
     already_AddRefed<nsIDocShellTreeItem>
            GetContentDocShell(nsIDocShellTreeItem *aStart);
     nsRefPtr<nsCaretAccessible> mCaretAccessible;
     nsCOMPtr<nsIDOMNode> mCurrentARIAMenubar;
new file mode 100644
--- /dev/null
+++ b/accessible/src/base/nsTextUtils.cpp
@@ -0,0 +1,181 @@
+/* -*- 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 Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * 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 "nsTextUtils.h"
+
+#include "nsAccessNode.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// nsLangTextAttr
+
+PRBool
+nsLangTextAttr::equal(nsIDOMElement *aElm)
+{
+  nsCOMPtr<nsIContent> content(do_QueryInterface(aElm));
+  if (!content)
+    return PR_FALSE;
+
+  nsAutoString lang;
+  nsAccUtils::GetLanguageFor(content, mRootContent, lang);
+
+  return lang == mLang;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsCSSTextAttr
+
+/**
+ * Item of the gCSSTextAttrsMap map.
+ */
+struct nsCSSTextAttrMapItem
+{
+  const char* mCSSName;
+  const char* mCSSValue;
+  const char* mAttrName;
+  const char* mAttrValue;
+};
+
+/**
+ * The map of CSS properties to text attributes.
+ */
+
+const char* const kAnyValue = nsnull;
+const char* const kCopyName = nsnull;
+const char* const kCopyValue = nsnull;
+
+static nsCSSTextAttrMapItem gCSSTextAttrsMap[] = {
+  // CSS name            CSS value        Attribute name              Attribute name
+  { "background-color",  kAnyValue,       kCopyName,                  kCopyValue },
+  { "color",             kAnyValue,       kCopyName,                  kCopyValue },
+  { "font-family",       kAnyValue,       kCopyName,                  kCopyValue },
+  { "font-size",         kAnyValue,       kCopyName,                  kCopyValue },
+  { "font-style",        kAnyValue,       kCopyName,                  kCopyValue },
+  { "font-weight",       kAnyValue,       kCopyName,                  kCopyValue },
+  { "text-decoration",   "line-through",  "text-line-through-style",  "solid" },
+  { "text-decoration",   "underline",     "text-underline-style",     "solid" },
+  { "text-align",        kAnyValue,       kCopyName,                  kCopyValue },
+  { "text-indent",       kAnyValue,       kCopyName,                  kCopyValue },
+  { "vertical-align",    kAnyValue,       "text-position",            kCopyValue }
+};
+
+nsCSSTextAttr::nsCSSTextAttr(PRBool aIncludeDefAttrValue, nsIDOMElement *aElm,
+                             nsIDOMElement *aRootElm) :
+  mIndex(-1), mIncludeDefAttrValue(aIncludeDefAttrValue)
+{
+  nsAccessNode::GetComputedStyleDeclaration(EmptyString(), aElm,
+                                            getter_AddRefs(mStyleDecl));
+
+  if (!mIncludeDefAttrValue)
+    nsAccessNode::GetComputedStyleDeclaration(EmptyString(), aRootElm,
+                                              getter_AddRefs(mDefStyleDecl));
+}
+
+PRBool
+nsCSSTextAttr::equal(nsIDOMElement *aElm)
+{
+  if (!aElm || !mStyleDecl)
+    return PR_FALSE;
+
+  nsCOMPtr<nsIDOMCSSStyleDeclaration> currStyleDecl;
+  nsAccessNode::GetComputedStyleDeclaration(EmptyString(), aElm,
+                                            getter_AddRefs(currStyleDecl));
+  if (!currStyleDecl)
+    return PR_FALSE;
+
+  NS_ConvertASCIItoUTF16 cssName(gCSSTextAttrsMap[mIndex].mCSSName);
+
+  nsAutoString currValue;
+  nsresult rv = currStyleDecl->GetPropertyValue(cssName, currValue);
+  if (NS_FAILED(rv))
+    return PR_FALSE;
+
+  nsAutoString value;
+  rv = mStyleDecl->GetPropertyValue(cssName, value);
+  return NS_SUCCEEDED(rv) && value == currValue;
+}
+
+PRBool
+nsCSSTextAttr::iterate()
+{
+  return ++mIndex < static_cast<PRInt32>(NS_ARRAY_LENGTH(gCSSTextAttrsMap));
+}
+
+PRBool
+nsCSSTextAttr::get(nsACString& aName, nsAString& aValue)
+{
+  if (!mStyleDecl)
+    return PR_FALSE;
+
+  NS_ConvertASCIItoUTF16 cssName(gCSSTextAttrsMap[mIndex].mCSSName);
+  nsresult rv = mStyleDecl->GetPropertyValue(cssName, aValue);
+  if (NS_FAILED(rv))
+    return PR_FALSE;
+
+  // Don't expose text attribute if corresponding CSS value on the element
+  // equals to CSS value on the root element and we don't want to include
+  // default values.
+  if (!mIncludeDefAttrValue) {
+    if (!mDefStyleDecl)
+      return PR_FALSE;
+
+    nsAutoString defValue;
+    mDefStyleDecl->GetPropertyValue(cssName, defValue);
+    if (defValue == aValue)
+      return PR_FALSE;
+  }
+
+  // Don't expose text attribute if its required specific CSS value isn't
+  // matched with the CSS value we got.
+  const char *cssValue = gCSSTextAttrsMap[mIndex].mCSSValue;
+  if (cssValue != kAnyValue && !aValue.EqualsASCII(cssValue))
+    return PR_FALSE;
+
+  // Get the name of text attribute.
+  if (gCSSTextAttrsMap[mIndex].mAttrName != kCopyName)
+    aName = gCSSTextAttrsMap[mIndex].mAttrName;
+  else
+    aName = gCSSTextAttrsMap[mIndex].mCSSName;
+
+  // Get the value of text attribute.
+  const char *attrValue = gCSSTextAttrsMap[mIndex].mAttrValue;
+  if (attrValue != kCopyValue)
+    AppendASCIItoUTF16(attrValue, aValue);
+
+  return PR_TRUE;
+}
+
new file mode 100644
--- /dev/null
+++ b/accessible/src/base/nsTextUtils.h
@@ -0,0 +1,112 @@
+/* -*- 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 Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * 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 nsTextUtils_h_
+#define nsTextUtils_h_
+
+#include "nsIDOMElement.h"
+#include "nsIDOMCSSStyleDeclaration.h"
+
+#include "nsIContent.h"
+
+#include "nsCOMPtr.h"
+#include "nsString.h"
+
+/**
+ * Base class to work with text attributes. See derived classes below.
+ */
+class nsTextAttr
+{
+public:
+  /**
+   * Return true if the text attribute for the given element equals with
+   * predefined attribute.
+   */
+  virtual PRBool equal(nsIDOMElement *aElm) = 0;
+};
+
+/**
+ * Class is used for the work with 'lang' text attributes. Used in
+ * nsHyperTextAccessible.
+ */
+class nsLangTextAttr : public nsTextAttr
+{
+public:
+  nsLangTextAttr(nsAString& aLang, nsIContent *aRootContent) :
+    mLang(aLang), mRootContent(aRootContent) { }
+
+  virtual PRBool equal(nsIDOMElement *aElm);
+
+private:
+  nsString mLang;
+  nsCOMPtr<nsIContent> mRootContent;
+};
+
+/**
+ * Class is used for the work with CSS based text attributes. Used in
+ * nsHyperTextAccessible.
+ */
+class nsCSSTextAttr : public nsTextAttr
+{
+public:
+  nsCSSTextAttr(PRBool aIncludeDefAttrValue, nsIDOMElement *aElm,
+                nsIDOMElement *aRootElm);
+
+  // nsTextAttr
+  virtual PRBool equal(nsIDOMElement *aElm);
+
+  // nsCSSTextAttr
+  /**
+   * Interates through attributes.
+   */
+  PRBool iterate();
+
+  /**
+   * Get name and value of attribute.
+   */
+  PRBool get(nsACString& aName, nsAString& aValue);
+
+private:
+  PRInt32 mIndex;
+  PRBool mIncludeDefAttrValue;
+
+  nsCOMPtr<nsIDOMCSSStyleDeclaration> mStyleDecl;
+  nsCOMPtr<nsIDOMCSSStyleDeclaration> mDefStyleDecl;
+};
+
+#endif
--- a/accessible/src/html/nsHTMLFormControlAccessible.cpp
+++ b/accessible/src/html/nsHTMLFormControlAccessible.cpp
@@ -278,25 +278,28 @@ NS_IMETHODIMP nsHTMLButtonAccessible::Ge
 NS_IMETHODIMP nsHTMLButtonAccessible::GetName(nsAString& aName)
 {
   nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
   if (!content) {
     return NS_ERROR_FAILURE; // Node shut down
   }
 
   nsAutoString name;
-  if (!content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::value,
-                        name) &&
-      !content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::alt,
-                        name)) {
-    if (mRoleMapEntry) {
-      // Use HTML label or DHTML accessibility's labelledby attribute for name
-      GetHTMLName(name, PR_FALSE);
-    }
-    if (name.IsEmpty()) {
+  // Prefer aria-labelledby attribute for name
+  if (content->HasAttr(kNameSpaceID_None,
+                       nsAccessibilityAtoms::aria_labelledby)) {
+    GetHTMLName(name, PR_FALSE);
+  }
+
+  if (name.IsEmpty()) {
+    // no label from HTML or ARIA
+    if (!content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::value,
+                          name) &&
+        !content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::alt,
+                          name)) {
       // Use the button's (default) label if nothing else works
       nsIFrame* frame = GetFrame();
       if (frame) {
         nsIFormControlFrame* fcFrame;
         CallQueryInterface(frame, &fcFrame);
         if (fcFrame)
           fcFrame->GetFormProperty(nsAccessibilityAtoms::defaultLabel, name);
       }
@@ -458,28 +461,31 @@ nsHTMLTextFieldAccessible::GetState(PRUi
       *aState |= nsIAccessibleStates::STATE_HASPOPUP;
     }
   }
 
   if (content->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::readonly)) {
     *aState |= nsIAccessibleStates::STATE_READONLY;
   }
 
-  if (!aExtraState || !(*aExtraState & nsIAccessibleStates::EXT_STATE_EDITABLE))
+  if (!aExtraState)
     return NS_OK;
 
   nsCOMPtr<nsIDOMHTMLInputElement> htmlInput(do_QueryInterface(mDOMNode));
   // Is it an <input> or a <textarea> ?
   if (htmlInput) {
     *aExtraState |= nsIAccessibleStates::EXT_STATE_SINGLE_LINE;
   }
   else {
     *aExtraState |= nsIAccessibleStates::EXT_STATE_MULTI_LINE;
   }
 
+  if (!(*aExtraState & nsIAccessibleStates::EXT_STATE_EDITABLE))
+    return NS_OK;
+
   nsCOMPtr<nsIContent> bindingContent = content->GetBindingParent();
   if (bindingContent &&
       bindingContent->NodeInfo()->Equals(nsAccessibilityAtoms::textbox,
                                          kNameSpaceID_XUL) &&
       bindingContent->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::type,
                                   nsAccessibilityAtoms::autocomplete,
                                   eIgnoreCase)) {
     // If parent is XUL textbox and value of @type attribute is "autocomplete",
--- a/accessible/src/html/nsHTMLLinkAccessible.cpp
+++ b/accessible/src/html/nsHTMLLinkAccessible.cpp
@@ -61,17 +61,26 @@ NS_IMETHODIMP
 nsHTMLLinkAccessible::GetName(nsAString& aName)
 { 
   aName.Truncate();
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
-  return AppendFlatStringFromSubtree(content, &aName);
+  nsresult rv = AppendFlatStringFromSubtree(content, &aName);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (aName.IsEmpty()) {
+    // Probably an image without alt or title inside, try to get the name on
+    // the link by usual way.
+    return GetHTMLName(aName, PR_FALSE);
+  }
+
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLLinkAccessible::GetRole(PRUint32 *aRole)
 {
   NS_ENSURE_ARG_POINTER(aRole);
 
   *aRole = nsIAccessibleRole::ROLE_LINK;
@@ -97,19 +106,24 @@ nsHTMLLinkAccessible::GetState(PRUint32 
     *aState |= nsIAccessibleStates::STATE_SELECTABLE;
   }
 
   nsCOMPtr<nsILink> link = do_QueryInterface(mDOMNode);
   NS_ENSURE_STATE(link);
 
   nsLinkState linkState;
   link->GetLinkState(linkState);
-  if (linkState == eLinkState_NotLink) {
-    // This is a named anchor, not a link with also a name attribute. bail out.
-    return NS_OK;
+  if (linkState == eLinkState_NotLink || linkState == eLinkState_Unknown) {
+    // This is a either named anchor (a link with also a name attribute) or
+    // it doesn't have any attributes. Check if 'click' event handler is
+    // registered, otherwise bail out.
+    PRBool isOnclick = nsAccUtils::HasListener(content,
+                                               NS_LITERAL_STRING("click"));
+    if (!isOnclick)
+      return NS_OK;
   }
 
   *aState |= nsIAccessibleStates::STATE_LINKED;
 
   if (linkState == eLinkState_Visited)
     *aState |= nsIAccessibleStates::STATE_TRAVERSED;
 
   return NS_OK;
@@ -133,35 +147,45 @@ nsHTMLLinkAccessible::GetValue(nsAString
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLLinkAccessible::GetNumActions(PRUint8 *aNumActions)
 {
   NS_ENSURE_ARG_POINTER(aNumActions);
 
+  if (!IsLinked())
+    return nsHyperTextAccessible::GetNumActions(aNumActions);
+
   *aNumActions = 1;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLLinkAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
 {
+  aName.Truncate();
+
+  if (!IsLinked())
+    return nsHyperTextAccessible::GetActionName(aIndex, aName);
+
   // Action 0 (default action): Jump to link
-  aName.Truncate();
   if (aIndex != eAction_Jump)
     return NS_ERROR_INVALID_ARG;
 
   aName.AssignLiteral("jump");
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLLinkAccessible::DoAction(PRUint8 aIndex)
 {
+  if (!IsLinked())
+    return nsHyperTextAccessible::DoAction(aIndex);
+
   // Action 0 (default action): Jump to link
   if (aIndex != eAction_Jump)
     return NS_ERROR_INVALID_ARG;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
@@ -180,8 +204,25 @@ nsHTMLLinkAccessible::GetURI(PRInt32 aIn
   if (aIndex != 0)
     return NS_ERROR_INVALID_ARG;
 
   nsCOMPtr<nsILink> link(do_QueryInterface(mDOMNode));
   NS_ENSURE_STATE(link);
 
   return link->GetHrefURI(aURI);
 }
+
+////////////////////////////////////////////////////////////////////////////////
+// Protected members
+
+PRBool
+nsHTMLLinkAccessible::IsLinked()
+{
+  nsCOMPtr<nsILink> link(do_QueryInterface(mDOMNode));
+  if (!link)
+    return PR_FALSE;
+
+  nsLinkState linkState;
+  nsresult rv = link->GetLinkState(linkState);
+
+  return NS_SUCCEEDED(rv) && linkState != eLinkState_NotLink &&
+         linkState != eLinkState_Unknown;
+}
--- a/accessible/src/html/nsHTMLLinkAccessible.h
+++ b/accessible/src/html/nsHTMLLinkAccessible.h
@@ -59,11 +59,16 @@ public:
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD DoAction(PRUint8 aIndex);
 
   // nsIAccessibleHyperLink
   NS_IMETHOD GetURI(PRInt32 aIndex, nsIURI **aURI);
 
 protected:
   enum { eAction_Jump = 0 };
+
+  /**
+   * Returns true if the link has href attribute.
+   */
+  PRBool IsLinked();
 };
 
 #endif  
--- a/accessible/src/html/nsHTMLSelectAccessible.cpp
+++ b/accessible/src/html/nsHTMLSelectAccessible.cpp
@@ -330,17 +330,17 @@ nsHTMLSelectListAccessible::GetState(PRU
 {
   nsresult rv = nsHTMLSelectableAccessible::GetState(aState, aExtraState);
   NS_ENSURE_SUCCESS(rv, rv);
   if (!mDOMNode)
     return NS_OK;
 
   nsCOMPtr<nsIDOMHTMLSelectElement> select (do_QueryInterface(mDOMNode));
   if (select) {
-    if (*aState | nsIAccessibleStates::STATE_FOCUSED) {
+    if (*aState & nsIAccessibleStates::STATE_FOCUSED) {
       // Treat first focusable option node as actual focus, in order
       // to avoid confusing JAWS, which needs focus on the option
       nsCOMPtr<nsIDOMNode> focusedOption;
       nsHTMLSelectOptionAccessible::GetFocusedOptionNode(mDOMNode, 
                                                          getter_AddRefs(focusedOption));
       if (focusedOption) { // Clear focused state since it is on option
         *aState &= ~nsIAccessibleStates::STATE_FOCUSED;
       }
@@ -616,17 +616,17 @@ nsIFrame* nsHTMLSelectOptionAccessible::
   *     STATE_OFFSCREEN
   */
 NS_IMETHODIMP
 nsHTMLSelectOptionAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
 {
   // Upcall to nsAccessible, but skip nsHyperTextAccessible impl
   // because we don't want EXT_STATE_EDITABLE or EXT_STATE_SELECTABLE_TEXT
   nsresult rv = nsAccessible::GetState(aState, aExtraState);
-  NS_ENSURE_TRUE(rv, rv);
+  NS_ENSURE_SUCCESS(rv, rv);
   if (!mDOMNode)
     return NS_OK;
 
   PRUint32 selectState, selectExtState;
   nsCOMPtr<nsIContent> selectContent = GetSelectState(&selectState,
                                                       &selectExtState);
   if (selectState & nsIAccessibleStates::STATE_INVISIBLE) {
     return NS_OK;
--- a/accessible/src/html/nsHTMLTableAccessible.cpp
+++ b/accessible/src/html/nsHTMLTableAccessible.cpp
@@ -1166,21 +1166,23 @@ NS_IMETHODIMP nsHTMLTableAccessible::IsP
     NS_ENSURE_TRUE(tableFrame , NS_ERROR_FAILURE);
     nsSize tableSize  = tableFrame->GetSize();
     nsCOMPtr<nsIAccessibleDocument> docAccessible = GetDocAccessible();
     nsCOMPtr<nsPIAccessNode> docAccessNode(do_QueryInterface(docAccessible));
     NS_ENSURE_TRUE(docAccessNode, NS_ERROR_FAILURE);
     nsIFrame *docFrame = docAccessNode->GetFrame();
     NS_ENSURE_TRUE(docFrame , NS_ERROR_FAILURE);
     nsSize docSize = docFrame->GetSize();
-    PRInt32 percentageOfDocWidth = (100 * tableSize.width) / docSize.width;
-    if (percentageOfDocWidth > 95) {
-      // 3-4 columns, no borders, not a lot of rows, and 95% of the doc's width
-      // Probably for layout
-      RETURN_LAYOUT_ANSWER(PR_TRUE, "<=4 columns, width hardcoded in pixels and 95% of document width");
+    if (docSize.width > 0) {
+      PRInt32 percentageOfDocWidth = (100 * tableSize.width) / docSize.width;
+      if (percentageOfDocWidth > 95) {
+        // 3-4 columns, no borders, not a lot of rows, and 95% of the doc's width
+        // Probably for layout
+        RETURN_LAYOUT_ANSWER(PR_TRUE, "<=4 columns, width hardcoded in pixels and 95% of document width");
+      }
     }
   }
 
   // Two column rules
   if (rows * columns <= 10) {
     RETURN_LAYOUT_ANSWER(PR_TRUE, "2-4 columns, 10 cells or less, non-bordered");
   }
 
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -36,25 +36,28 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsHyperTextAccessible.h"
 #include "nsAccessibilityAtoms.h"
 #include "nsAccessibilityService.h"
 #include "nsAccessibleTreeWalker.h"
+#include "nsTextUtils.h"
+
 #include "nsPIAccessNode.h"
 #include "nsIClipboard.h"
 #include "nsContentCID.h"
 #include "nsIDOMAbstractView.h"
 #include "nsIDOMCharacterData.h"
 #include "nsIDOMDocument.h"
 #include "nsPIDOMWindow.h"        
 #include "nsIDOMDocumentView.h"
 #include "nsIDOMRange.h"
+#include "nsIDOMNSRange.h"
 #include "nsIDOMWindowInternal.h"
 #include "nsIDOMXULDocument.h"
 #include "nsIEditingSession.h"
 #include "nsIEditor.h"
 #include "nsIFontMetrics.h"
 #include "nsIFrame.h"
 #include "nsFrameSelection.h"
 #include "nsILineIterator.h"
@@ -632,17 +635,19 @@ nsresult nsHyperTextAccessible::DOMPoint
   // Get accessible for this findNode, or if that node isn't accessible, use the
   // accessible for the next DOM node which has one (based on forward depth first search)
   nsCOMPtr<nsIAccessible> descendantAccessible;
   if (findNode) {
     nsCOMPtr<nsIContent> findContent = do_QueryInterface(findNode);
     if (findContent->IsNodeOfType(nsINode::eHTML) && 
         findContent->NodeInfo()->Equals(nsAccessibilityAtoms::br)) {
       nsIContent *parent = findContent->GetParent();
-      if (parent && parent->IsNativeAnonymous() && parent->GetChildCount() == 1) {
+      if (parent &&
+          parent->IsRootOfNativeAnonymousSubtree() &&
+          parent->GetChildCount() == 1) {
         // This <br> is the only node in a text control, therefore it is the hacky
         // "bogus node" used when there is no text in a control
         *aHyperTextOffset = 0;
         return NS_OK;
       }
     }
     descendantAccessible = GetFirstAvailableAccessible(findNode);
   }
@@ -666,17 +671,17 @@ nsresult nsHyperTextAccessible::DOMPoint
     // addTextOffset, to put us after the embedded object char. We'll only treat the offset as
     // before the embedded object char if we end at the very beginning of the child.
     addTextOffset = addTextOffset > 0;
     }
     else {
       // Start offset, inclusive
       // Make sure the offset lands on the embedded object character in order to indicate
       // the true inner offset is inside the subtree for that link
-      addTextOffset = (TextLength(descendantAccessible) == addTextOffset) ? 1 : 0;
+      addTextOffset = (TextLength(descendantAccessible) == static_cast<PRInt32>(addTextOffset)) ? 1 : 0;
     }
     descendantAccessible = parentAccessible;
   }  
 
   // Loop through, adding offsets until we reach childAccessible
   // If childAccessible is null we will end up adding up the entire length of
   // the hypertext, which is good -- it just means our offset node
   // came after the last accessible child's node
@@ -694,16 +699,28 @@ nsresult nsHyperTextAccessible::DOMPoint
       NS_ADDREF(*aFinalAccessible = childAccessible);
     }
   }
 
   return NS_OK;
 }
 
 nsresult
+nsHyperTextAccessible::HypertextOffsetToDOMPoint(PRInt32 aHTOffset,
+                                                 nsIDOMNode **aNode,
+                                                 PRInt32 *aOffset)
+{
+  nsCOMPtr<nsIDOMNode> endNode;
+  PRInt32 endOffset;
+
+  return HypertextOffsetsToDOMRange(aHTOffset, aHTOffset, aNode, aOffset,
+                                    getter_AddRefs(endNode), &endOffset);
+}
+
+nsresult
 nsHyperTextAccessible::HypertextOffsetsToDOMRange(PRInt32 aStartHTOffset,
                                                   PRInt32 aEndHTOffset,
                                                   nsIDOMNode **aStartNode,
                                                   PRInt32 *aStartOffset,
                                                   nsIDOMNode **aEndNode,
                                                   PRInt32 *aEndOffset)
 {
   NS_ENSURE_ARG_POINTER(aStartNode);
@@ -864,16 +881,19 @@ BOUNDARY_LINE_START       From the line 
 BOUNDARY_LINE_END         From the line end before/at/after the offset to the next line start.
 */
 
 nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTextBoundary aBoundaryType,
                                               PRInt32 aOffset, PRInt32 *aStartOffset, PRInt32 *aEndOffset,
                                               nsAString &aText)
 {
   aText.Truncate();
+
+  NS_ENSURE_ARG_POINTER(aStartOffset);
+  NS_ENSURE_ARG_POINTER(aEndOffset);
   *aStartOffset = *aEndOffset = 0;
 
   nsCOMPtr<nsIPresShell> presShell = GetPresShell();
   if (!presShell) {
     return NS_ERROR_FAILURE;
   }
 
   if (aOffset == nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT) {
@@ -883,30 +903,80 @@ nsresult nsHyperTextAccessible::GetTextH
     GetCaretOffset(&aOffset);
     if (aOffset > 0 && (aBoundaryType == BOUNDARY_LINE_START ||
                         aBoundaryType == BOUNDARY_LINE_END)) {
       // It is the same character offset when the caret is visually at the very end of a line
       // or the start of a new line. Getting text at the line should provide the line with the visual caret,
       // otherwise screen readers will announce the wrong line as the user presses up or down arrow and land
       // at the end of a line.
       nsCOMPtr<nsISelection> domSel;
-      nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
+      nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL,
+                                  nsnull, getter_AddRefs(domSel));
+      NS_ENSURE_SUCCESS(rv, rv);
+
       nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSel));
       nsCOMPtr<nsFrameSelection> frameSelection;
       rv = privateSelection->GetFrameSelection(getter_AddRefs(frameSelection));
       NS_ENSURE_SUCCESS(rv, rv);
+
       if (frameSelection->GetHint() == nsFrameSelection::HINTLEFT) {
         -- aOffset;  // We are at the start of a line
       }
     }
   }
   else if (aOffset < 0) {
     return NS_ERROR_FAILURE;
   }
 
+  nsSelectionAmount amount;
+  PRBool needsStart = PR_FALSE;
+  switch (aBoundaryType) {
+    case BOUNDARY_CHAR:
+      amount = eSelectCharacter;
+      if (aType == eGetAt)
+        aType = eGetAfter; // Avoid returning 2 characters
+      break;
+
+    case BOUNDARY_WORD_START:
+      needsStart = PR_TRUE;
+      amount = eSelectWord;
+      break;
+
+    case BOUNDARY_WORD_END:
+      amount = eSelectWord;
+      break;
+
+    case BOUNDARY_LINE_START:
+      // Newlines are considered at the end of a line. Since getting
+      // the BOUNDARY_LINE_START gets the text from the line-start to the next
+      // line-start, the newline is included at the end of the string.
+      needsStart = PR_TRUE;
+      amount = eSelectLine;
+      break;
+
+    case BOUNDARY_LINE_END:
+      // Newlines are considered at the end of a line. Since getting
+      // the BOUNDARY_END_START gets the text from the line-end to the next
+      //line-end, the newline is included at the beginning of the string.
+      amount = eSelectLine;
+      break;
+
+    case BOUNDARY_ATTRIBUTE_RANGE:
+    {
+      nsresult rv = GetTextAttributes(PR_FALSE, aOffset,
+                                      aStartOffset, aEndOffset, nsnull);
+      NS_ENSURE_SUCCESS(rv, rv);
+      
+      return GetText(*aStartOffset, *aEndOffset, aText);
+    }
+
+    default:  // Note, sentence support is deprecated and falls through to here
+      return NS_ERROR_INVALID_ARG;
+  }
+
   PRInt32 startOffset = aOffset + (aBoundaryType == BOUNDARY_LINE_END);  // Avoid getting the previous line
   PRInt32 endOffset = startOffset;
 
   // Convert offsets to frame-relative
   nsCOMPtr<nsIAccessible> startAcc;
   nsIFrame *startFrame = GetPosAndText(startOffset, endOffset, nsnull, nsnull,
                                        nsnull, getter_AddRefs(startAcc));
 
@@ -924,70 +994,16 @@ nsresult nsHyperTextAccessible::GetTextH
       return aOffset > textLength ? NS_ERROR_FAILURE : NS_OK;
     }
     else {
       // We're on the last continuation since we're on the last character
       startFrame = startFrame->GetLastContinuation();
     }
   }
 
-  nsSelectionAmount amount;
-  PRBool needsStart = PR_FALSE;
-  switch (aBoundaryType)
-  {
-  case BOUNDARY_CHAR:
-    amount = eSelectCharacter;
-    if (aType == eGetAt) {
-      aType = eGetAfter; // Avoid returning 2 characters
-    }
-    break;
-  case BOUNDARY_WORD_START:
-    needsStart = PR_TRUE;
-    amount = eSelectWord;
-    break;
-  case BOUNDARY_WORD_END:
-    amount = eSelectWord;
-    break;
-  case BOUNDARY_LINE_START:
-    // Newlines are considered at the end of a line,
-    // Since getting the BOUNDARY_LINE_START gets the text from the line-start
-    // to the next line-start, the newline is included at the end of the string
-    needsStart = PR_TRUE;
-    amount = eSelectLine;
-    break;
-  case BOUNDARY_LINE_END:
-    // Newlines are considered at the end of a line,
-    // Since getting the BOUNDARY_END_START gets the text from the line-end
-    // to the next line-end, the newline is included at the beginning of the string
-    amount = eSelectLine;
-    break;
-  case BOUNDARY_ATTRIBUTE_RANGE:
-    {
-      // XXX We should merge identically formatted frames
-      // XXX deal with static text case
-      // XXX deal with boundary type
-      nsIContent *textContent = startFrame->GetContent();
-      // If not text, then it's represented by an embedded object char 
-      // (length of 1)
-      // XXX did this mean to check for eTEXT?
-      // XXX This is completely wrong, needs to be reimplemented
-      PRInt32 textLength = textContent ? textContent->TextLength() : 1;
-      if (textLength < 0) {
-        return NS_ERROR_FAILURE;
-      }
-      *aStartOffset = aOffset - startOffset;
-      *aEndOffset = *aStartOffset + textLength;
-      startOffset = *aStartOffset;
-      endOffset = *aEndOffset;
-      return GetText(startOffset, endOffset, aText);
-    }
-  default:  // Note, sentence support is deprecated and falls through to here
-    return NS_ERROR_INVALID_ARG;
-  }
-
   PRInt32 finalStartOffset, finalEndOffset;
 
   // If aType == eGetAt we'll change both the start and end offset from
   // the original offset
   if (aType == eGetAfter) {
     finalStartOffset = aOffset;
   }
   else {
@@ -1066,41 +1082,116 @@ NS_IMETHODIMP nsHyperTextAccessible::Get
 }
 
 NS_IMETHODIMP nsHyperTextAccessible::GetTextAfterOffset(PRInt32 aOffset, nsAccessibleTextBoundary aBoundaryType,
                                                         PRInt32 *aStartOffset, PRInt32 *aEndOffset, nsAString & aText)
 {
   return GetTextHelper(eGetAfter, aBoundaryType, aOffset, aStartOffset, aEndOffset, aText);
 }
 
-NS_IMETHODIMP nsHyperTextAccessible::GetAttributeRange(PRInt32 aOffset, PRInt32 *aRangeStartOffset, 
-                                                       PRInt32 *aRangeEndOffset, nsIAccessible **aAccessibleWithAttrs)
+// nsIPersistentProperties
+// nsIAccessibleText::getTextAttributes(in boolean includeDefAttrs,
+//                                      in long offset,
+//                                      out long rangeStartOffset,
+//                                      out long rangeEndOffset);
+NS_IMETHODIMP
+nsHyperTextAccessible::GetTextAttributes(PRBool aIncludeDefAttrs,
+                                         PRInt32 aOffset,
+                                         PRInt32 *aStartOffset,
+                                         PRInt32 *aEndOffset,
+                                         nsIPersistentProperties **aAttributes)
 {
-  // Return the range of text with common attributes around aOffset
-  *aRangeStartOffset = *aRangeEndOffset = 0;
-  *aAccessibleWithAttrs = nsnull;
+  // 1. First we get spell check, then language, then the set of CSS-based
+  //    attributes.
+  // 2. As we get each new attribute, we pass the current start and end offsets
+  //    as in/out parameters. In other words, as attributes are collected,
+  //    the attribute range itself can only stay the same or get smaller.
+  //
+  // Example:
+  //  Current: range 5-10
+  //  Adding:  range 7-12
+  //  Result:  range 7-10
 
-  if (!mDOMNode) {
-    return NS_ERROR_FAILURE;
+  NS_ENSURE_ARG_POINTER(aStartOffset);
+  *aStartOffset = 0;
+
+  NS_ENSURE_ARG_POINTER(aEndOffset);
+  nsresult rv = GetCharacterCount(aEndOffset);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (aAttributes) {
+    *aAttributes = nsnull;
+
+    nsCOMPtr<nsIPersistentProperties> attributes =
+      do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
+    NS_ENSURE_TRUE(attributes, NS_ERROR_OUT_OF_MEMORY);
+
+    NS_ADDREF(*aAttributes = attributes);
   }
 
-  nsCOMPtr<nsIAccessible> accessible;
-  
-  while (NextChild(accessible)) {
-    PRInt32 length = TextLength(accessible);
-    NS_ENSURE_TRUE(length >= 0, NS_ERROR_FAILURE);
-    if (*aRangeStartOffset + length > aOffset) {
-      *aRangeEndOffset = *aRangeStartOffset + length;
-      NS_ADDREF(*aAccessibleWithAttrs = accessible);
-      return NS_OK;
-    }
-    *aRangeStartOffset += length;
+  if (!mDOMNode)
+    return NS_ERROR_FAILURE;
+
+  nsCOMPtr<nsIDOMNode> node;
+  PRInt32 nodeOffset = 0;
+  rv = HypertextOffsetToDOMPoint(aOffset, getter_AddRefs(node), &nodeOffset);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Set 'misspelled' text attribute.
+  rv = GetSpellTextAttribute(node, nodeOffset, aStartOffset, aEndOffset,
+                             aAttributes ? *aAttributes : nsnull);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIContent> content(do_QueryInterface(node));
+  if (content && content->IsNodeOfType(nsINode::eELEMENT))
+    node = do_QueryInterface(content->GetChildAt(nodeOffset));
+
+  if (!node)
+    return NS_OK;
+
+  // Set 'lang' text attribute.
+  rv =  GetLangTextAttributes(aIncludeDefAttrs, node,
+                              aStartOffset, aEndOffset,
+                              aAttributes ? *aAttributes : nsnull);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Set CSS based text attributes.
+  rv = GetCSSTextAttributes(aIncludeDefAttrs, node,
+                            aStartOffset, aEndOffset,
+                            aAttributes ? *aAttributes : nsnull);
+  return rv;
+}
+
+// nsIPersistentProperties
+// nsIAccessibleText::defaultTextAttributes
+NS_IMETHODIMP
+nsHyperTextAccessible::GetDefaultTextAttributes(nsIPersistentProperties **aAttributes)
+{
+  NS_ENSURE_ARG_POINTER(aAttributes);
+  *aAttributes = nsnull;
+
+  nsCOMPtr<nsIPersistentProperties> attributes =
+    do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
+  NS_ENSURE_TRUE(attributes, NS_ERROR_OUT_OF_MEMORY);
+
+  NS_ADDREF(*aAttributes = attributes);
+
+  if (!mDOMNode)
+    return NS_ERROR_FAILURE;
+
+  nsCOMPtr<nsIDOMElement> element = nsAccUtils::GetDOMElementFor(mDOMNode);
+
+  nsCSSTextAttr textAttr(PR_TRUE, element, nsnull);
+  while (textAttr.iterate()) {
+    nsCAutoString name;
+    nsAutoString value, oldValue;
+    if (textAttr.get(name, value))
+      attributes->SetStringProperty(name, value, oldValue);
   }
-
-  return NS_ERROR_FAILURE;
+  return NS_OK;
 }
 
 nsresult
 nsHyperTextAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
   if (!mDOMNode) {
     return NS_ERROR_FAILURE;  // Node already shut down
   }
@@ -1130,16 +1221,18 @@ nsHyperTextAccessible::GetAttributesInte
     nsAutoString strHeadLevel;
     strHeadLevel.AppendInt(headLevel);
     nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::level,
                            strHeadLevel);
   }
   
   // Indicate when the current object uses block-level formatting
   // via formatting: block
+  // XXX: 'formatting' attribute is deprecated and will be removed in Mozilla2,
+  // use 'display' attribute instead.
   nsIFrame *frame = GetFrame();
   if (frame && frame->GetType() == nsAccessibilityAtoms::blockFrame) {
     nsAutoString oldValueUnused;
     aAttributes->SetStringProperty(NS_LITERAL_CSTRING("formatting"), NS_LITERAL_STRING("block"),
                                    oldValueUnused);
   }
 
   if (gLastFocusedNode == mDOMNode) {
@@ -1467,17 +1560,18 @@ nsresult nsHyperTextAccessible::SetSelec
   // Set the selection
   nsresult rv = SetSelectionBounds(0, aStartPos, aEndPos);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // If range 0 was successfully set, clear any additional selection 
   // ranges remaining from previous selection
   nsCOMPtr<nsISelection> domSel;
   nsCOMPtr<nsISelectionController> selCon;
-  GetSelections(getter_AddRefs(selCon), getter_AddRefs(domSel));
+  GetSelections(nsISelectionController::SELECTION_NORMAL,
+                getter_AddRefs(selCon), getter_AddRefs(domSel));
   if (domSel) {
     PRInt32 numRanges;
     domSel->GetRangeCount(&numRanges);
 
     for (PRInt32 count = 0; count < numRanges - 1; count ++) {
       nsCOMPtr<nsIDOMRange> range;
       domSel->GetRangeAt(1, getter_AddRefs(range));
       domSel->RemoveRange(range);
@@ -1502,17 +1596,18 @@ NS_IMETHODIMP nsHyperTextAccessible::Set
 /*
  * Gets the offset position of the caret (cursor).
  */
 NS_IMETHODIMP nsHyperTextAccessible::GetCaretOffset(PRInt32 *aCaretOffset)
 {
   *aCaretOffset = 0;
 
   nsCOMPtr<nsISelection> domSel;
-  nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
+  nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL,
+                              nsnull, getter_AddRefs(domSel));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIDOMNode> caretNode;
   rv = domSel->GetFocusNode(getter_AddRefs(caretNode));
   NS_ENSURE_SUCCESS(rv, rv);
 
   PRInt32 caretOffset;
   domSel->GetFocusOffset(&caretOffset);
@@ -1520,17 +1615,18 @@ NS_IMETHODIMP nsHyperTextAccessible::Get
   return DOMPointToHypertextOffset(caretNode, caretOffset, aCaretOffset);
 }
 
 PRInt32 nsHyperTextAccessible::GetCaretLineNumber()
 {
   // Provide the line number for the caret, relative to the
   // currently focused node. Use a 1-based index
   nsCOMPtr<nsISelection> domSel;
-  GetSelections(nsnull, getter_AddRefs(domSel));
+  GetSelections(nsISelectionController::SELECTION_NORMAL, nsnull,
+                getter_AddRefs(domSel));
   nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSel));
   NS_ENSURE_TRUE(privateSelection, -1);
   nsCOMPtr<nsFrameSelection> frameSelection;
   privateSelection->GetFrameSelection(getter_AddRefs(frameSelection));
   NS_ENSURE_TRUE(frameSelection, -1);
 
   nsCOMPtr<nsIDOMNode> caretNode;
   domSel->GetFocusNode(getter_AddRefs(caretNode));
@@ -1583,19 +1679,21 @@ PRInt32 nsHyperTextAccessible::GetCaretL
 
     caretFrame = parentFrame;
   }
 
   NS_NOTREACHED("DOM ancestry had this hypertext but frame ancestry didn't");
   return lineNumber;
 }
 
-nsresult nsHyperTextAccessible::GetSelections(nsISelectionController **aSelCon,
-                                              nsISelection **aDomSel,
-                                              nsCOMArray<nsIDOMRange>* aRanges)
+nsresult
+nsHyperTextAccessible::GetSelections(PRInt16 aType,
+                                     nsISelectionController **aSelCon,
+                                     nsISelection **aDomSel,
+                                     nsCOMArray<nsIDOMRange>* aRanges)
 {
   if (!mDOMNode) {
     return NS_ERROR_FAILURE;
   }
   if (aSelCon) {
     *aSelCon = nsnull;
   }
   if (aDomSel) {
@@ -1603,65 +1701,60 @@ nsresult nsHyperTextAccessible::GetSelec
   }
   if (aRanges) {
     aRanges->Clear();
   }
   
   nsCOMPtr<nsISelection> domSel;
   nsCOMPtr<nsISelectionController> selCon;
 
-  nsCOMPtr<nsIDOMNode> startNode;
   nsCOMPtr<nsIEditor> editor;
   GetAssociatedEditor(getter_AddRefs(editor));
   nsCOMPtr<nsIPlaintextEditor> peditor(do_QueryInterface(editor));
   if (peditor) {
     // Case 1: plain text editor
     // This is for form controls which have their own
     // selection controller separate from the document, for example
     // HTML:input, HTML:textarea, XUL:textbox, etc.
-    if (aSelCon) {
-      editor->GetSelectionController(getter_AddRefs(selCon));
-      NS_ENSURE_TRUE(*aSelCon, NS_ERROR_FAILURE);
-    }
-
-    editor->GetSelection(getter_AddRefs(domSel));
-    NS_ENSURE_TRUE(domSel, NS_ERROR_FAILURE);
-
-    nsCOMPtr<nsIDOMElement> editorRoot;
-    editor->GetRootElement(getter_AddRefs(editorRoot));
-    startNode = do_QueryInterface(editorRoot);
-    NS_ENSURE_STATE(startNode);
+    editor->GetSelectionController(getter_AddRefs(selCon));
   }
   else {
     // Case 2: rich content subtree (can be rich editor)
     // This uses the selection controller from the entire document
     nsIFrame *frame = GetFrame();
     NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
 
     // Get the selection and selection controller
     frame->GetSelectionController(GetPresContext(),
                                   getter_AddRefs(selCon));
-    NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
-    selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
-                         getter_AddRefs(domSel));
-    NS_ENSURE_TRUE(domSel, NS_ERROR_FAILURE);
+  }
+  NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
 
-    startNode = mDOMNode;
-  }
+  selCon->GetSelection(aType, getter_AddRefs(domSel));
+  NS_ENSURE_TRUE(domSel, NS_ERROR_FAILURE);
 
   if (aSelCon) {
     NS_ADDREF(*aSelCon = selCon);
   }
   if (aDomSel) {
     NS_ADDREF(*aDomSel = domSel);
   }
+
   if (aRanges) {
     nsCOMPtr<nsISelection2> selection2(do_QueryInterface(domSel));
     NS_ENSURE_TRUE(selection2, NS_ERROR_FAILURE);
 
+    nsCOMPtr<nsIDOMNode> startNode(mDOMNode);
+    if (peditor) {
+      nsCOMPtr<nsIDOMElement> editorRoot;
+      editor->GetRootElement(getter_AddRefs(editorRoot));
+      startNode = do_QueryInterface(editorRoot);
+    }
+    NS_ENSURE_STATE(startNode);
+
     nsCOMPtr<nsIDOMNodeList> childNodes;
     nsresult rv = startNode->GetChildNodes(getter_AddRefs(childNodes));
     NS_ENSURE_SUCCESS(rv, rv);
     PRUint32 numChildren; 
     rv = childNodes->GetLength(&numChildren);
     NS_ENSURE_SUCCESS(rv, rv);
     rv = selection2->GetRangesForIntervalCOMArray(startNode, 0,
                                                   startNode, numChildren,
@@ -1685,34 +1778,36 @@ nsresult nsHyperTextAccessible::GetSelec
 
 /*
  * Gets the number of selected regions.
  */
 NS_IMETHODIMP nsHyperTextAccessible::GetSelectionCount(PRInt32 *aSelectionCount)
 {
   nsCOMPtr<nsISelection> domSel;
   nsCOMArray<nsIDOMRange> ranges;
-  nsresult rv = GetSelections(nsnull, nsnull, &ranges);
+  nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL,
+                              nsnull, nsnull, &ranges);
   NS_ENSURE_SUCCESS(rv, rv);
 
   *aSelectionCount = ranges.Count();
 
   return NS_OK;
 }
 
 /*
  * Gets the start and end offset of the specified selection.
  */
 NS_IMETHODIMP nsHyperTextAccessible::GetSelectionBounds(PRInt32 aSelectionNum, PRInt32 *aStartOffset, PRInt32 *aEndOffset)
 {
   *aStartOffset = *aEndOffset = 0;
 
   nsCOMPtr<nsISelection> domSel;
   nsCOMArray<nsIDOMRange> ranges;
-  nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel), &ranges);
+  nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL,
+                              nsnull, getter_AddRefs(domSel), &ranges);
   NS_ENSURE_SUCCESS(rv, rv);
 
   PRInt32 rangeCount = ranges.Count();
   if (aSelectionNum < 0 || aSelectionNum >= rangeCount)
     return NS_ERROR_INVALID_ARG;
 
   nsCOMPtr<nsIDOMRange> range = ranges[aSelectionNum];
 
@@ -1755,17 +1850,18 @@ NS_IMETHODIMP nsHyperTextAccessible::Get
  * Changes the start and end offset of the specified selection.
  */
 NS_IMETHODIMP
 nsHyperTextAccessible::SetSelectionBounds(PRInt32 aSelectionNum,
                                           PRInt32 aStartOffset,
                                           PRInt32 aEndOffset)
 {
   nsCOMPtr<nsISelection> domSel;
-  nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
+  nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL,
+                              nsnull, getter_AddRefs(domSel));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Caret is a collapsed selection
   PRBool isOnlyCaret = (aStartOffset == aEndOffset);
 
   PRInt32 rangeCount;
   domSel->GetRangeCount(&rangeCount);
   nsCOMPtr<nsIDOMRange> range;
@@ -1803,32 +1899,34 @@ nsHyperTextAccessible::SetSelectionBound
 }
 
 /*
  * Adds a selection bounded by the specified offsets.
  */
 NS_IMETHODIMP nsHyperTextAccessible::AddSelection(PRInt32 aStartOffset, PRInt32 aEndOffset)
 {
   nsCOMPtr<nsISelection> domSel;
-  nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
+  nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL,
+                              nsnull, getter_AddRefs(domSel));
   NS_ENSURE_SUCCESS(rv, rv);
 
   PRInt32 rangeCount;
   domSel->GetRangeCount(&rangeCount);
 
   return SetSelectionBounds(rangeCount, aStartOffset, aEndOffset);
 }
 
 /*
  * Removes the specified selection.
  */
 NS_IMETHODIMP nsHyperTextAccessible::RemoveSelection(PRInt32 aSelectionNum)
 {
   nsCOMPtr<nsISelection> domSel;
-  nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
+  nsresult rv = GetSelections(nsISelectionController::SELECTION_NORMAL,
+                              nsnull, getter_AddRefs(domSel));
   NS_ENSURE_SUCCESS(rv, rv);
 
   PRInt32 rangeCount;
   domSel->GetRangeCount(&rangeCount);
   if (aSelectionNum < 0 || aSelectionNum >= rangeCount)
     return NS_ERROR_INVALID_ARG;
 
   nsCOMPtr<nsIDOMRange> range;
@@ -2030,8 +2128,361 @@ nsHyperTextAccessible::GetDOMPointByFram
     *aNodeOffset = parent->IndexOf(content);
     node = do_QueryInterface(parent);
   }
 
   NS_IF_ADDREF(*aNode = node);
   return NS_OK;
 }
 
+// nsHyperTextAccessible
+nsresult
+nsHyperTextAccessible::DOMRangeBoundToHypertextOffset(nsIDOMRange *aRange,
+                                                      PRBool aIsStartBound,
+                                                      PRBool aIsStartHTOffset,
+                                                      PRInt32 *aHTOffset)
+{
+  nsCOMPtr<nsIDOMNode> node;
+  PRInt32 nodeOffset = 0;
+
+  nsresult rv;
+  if (aIsStartBound) {
+    rv = aRange->GetStartContainer(getter_AddRefs(node));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = aRange->GetStartOffset(&nodeOffset);
+    NS_ENSURE_SUCCESS(rv, rv);
+  } else {
+    rv = aRange->GetEndContainer(getter_AddRefs(node));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = aRange->GetEndOffset(&nodeOffset);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  nsCOMPtr<nsIAccessible> startAcc;
+  rv = DOMPointToHypertextOffset(node, nodeOffset, aHTOffset,
+                                 getter_AddRefs(startAcc));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (aIsStartHTOffset && !startAcc)
+    *aHTOffset = 0;
+
+  return NS_OK;
+}
+
+// nsHyperTextAccessible
+nsresult
+nsHyperTextAccessible::GetSpellTextAttribute(nsIDOMNode *aNode,
+                                             PRInt32 aNodeOffset,
+                                             PRInt32 *aHTStartOffset,
+                                             PRInt32 *aHTEndOffset,
+                                             nsIPersistentProperties *aAttributes)
+{
+  nsCOMArray<nsIDOMRange> ranges;
+  nsresult rv = GetSelections(nsISelectionController::SELECTION_SPELLCHECK,
+                              nsnull, nsnull, &ranges);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRInt32 rangeCount = ranges.Count();
+  if (!rangeCount)
+    return NS_OK;
+
+  for (PRInt32 index = 0; index < rangeCount; index++) {
+    nsCOMPtr<nsIDOMRange> range = ranges[index];
+    nsCOMPtr<nsIDOMNSRange> nsrange(do_QueryInterface(range));
+    NS_ENSURE_STATE(nsrange);
+
+    PRInt16 result;
+    rv = nsrange->ComparePoint(aNode, aNodeOffset, &result);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    if (result == 1) { // range is before point
+      PRInt32 startHTOffset = 0;
+      rv = DOMRangeBoundToHypertextOffset(range, PR_FALSE, PR_TRUE,
+                                          &startHTOffset);
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      if (startHTOffset > *aHTStartOffset)
+        *aHTStartOffset = startHTOffset;
+
+    } else if (result == -1) { // range is after point
+      PRInt32 endHTOffset = 0;
+      rv = DOMRangeBoundToHypertextOffset(range, PR_TRUE, PR_FALSE,
+                                          &endHTOffset);
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      if (endHTOffset < *aHTEndOffset)
+        *aHTEndOffset = endHTOffset;
+
+    } else { // point is in range
+      PRInt32 startHTOffset = 0;
+      rv = DOMRangeBoundToHypertextOffset(range, PR_TRUE, PR_TRUE,
+                                          &startHTOffset);
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      PRInt32 endHTOffset = 0;
+      rv = DOMRangeBoundToHypertextOffset(range, PR_FALSE, PR_FALSE,
+                                          &endHTOffset);
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      if (startHTOffset > *aHTStartOffset)
+        *aHTStartOffset = startHTOffset;
+      if (endHTOffset < *aHTEndOffset)
+        *aHTEndOffset = endHTOffset;
+
+      if (aAttributes) {
+        nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::invalid,
+                               NS_LITERAL_STRING("spelling"));
+      }
+
+      return NS_OK;
+    }
+  }
+
+  return NS_OK;
+}
+
+// nsHyperTextAccessible
+nsresult
+nsHyperTextAccessible::GetLangTextAttributes(PRBool aIncludeDefAttrs,
+                                             nsIDOMNode *aSourceNode,
+                                             PRInt32 *aStartHTOffset,
+                                             PRInt32 *aEndHTOffset,
+                                             nsIPersistentProperties *aAttributes)
+{
+  nsCOMPtr<nsIDOMElement> sourceElm(nsAccUtils::GetDOMElementFor(aSourceNode));
+
+  nsCOMPtr<nsIContent> content(do_QueryInterface(sourceElm));
+  nsCOMPtr<nsIContent> rootContent(do_QueryInterface(mDOMNode));
+
+  nsAutoString lang;
+  nsAccUtils::GetLanguageFor(content, rootContent, lang);
+
+  nsAutoString rootLang;
+  nsresult rv = GetLanguage(rootLang);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (aAttributes) {
+    // Expose 'language' text attribute if the DOM 'lang' attribute is
+    // presented and it's different from the 'lang' attribute on the root
+    // element or we should include default values of text attribute.
+    const nsAString& resultLang = lang.IsEmpty() ? rootLang : lang;
+    if (!resultLang.IsEmpty() && (aIncludeDefAttrs || lang != rootLang))
+      nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::language,
+                             resultLang);
+  }
+
+  nsLangTextAttr textAttr(lang, rootContent);
+  return GetRangeForTextAttr(aSourceNode, &textAttr,
+                             aStartHTOffset, aEndHTOffset);
+}
+
+// nsHyperTextAccessible
+nsresult
+nsHyperTextAccessible::GetCSSTextAttributes(PRBool aIncludeDefAttrs,
+                                            nsIDOMNode *aSourceNode,
+                                            PRInt32 *aStartHTOffset,
+                                            PRInt32 *aEndHTOffset,
+                                            nsIPersistentProperties *aAttributes)
+{
+  nsCOMPtr<nsIDOMElement> sourceElm(nsAccUtils::GetDOMElementFor(aSourceNode));
+  nsCOMPtr<nsIDOMElement> rootElm(nsAccUtils::GetDOMElementFor(mDOMNode));
+
+  nsCSSTextAttr textAttr(aIncludeDefAttrs, sourceElm, rootElm);
+  while (textAttr.iterate()) {
+    nsCAutoString name;
+    nsAutoString value, oldValue;
+    if (aAttributes && textAttr.get(name, value))
+      aAttributes->SetStringProperty(name, value, oldValue);
+
+    nsresult rv = GetRangeForTextAttr(aSourceNode, &textAttr,
+                                      aStartHTOffset, aEndHTOffset);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  return NS_OK;
+}
+
+// nsHyperTextAccessible
+nsresult
+nsHyperTextAccessible::GetRangeForTextAttr(nsIDOMNode *aNode,
+                                           nsTextAttr *aComparer,
+                                           PRInt32 *aStartHTOffset,
+                                           PRInt32 *aEndHTOffset)
+{
+  nsCOMPtr<nsIDOMElement> rootElm(nsAccUtils::GetDOMElementFor(mDOMNode));
+  NS_ENSURE_STATE(rootElm);
+
+  nsCOMPtr<nsIDOMNode> tmpNode(aNode);
+  nsCOMPtr<nsIDOMNode> currNode(aNode);
+
+  // Navigate backwards and forwards from current node to the root node to
+  // calculate range bounds for the text attribute. Navigation sequence is the
+  // following:
+  // 1. Navigate through the siblings.
+  // 2. If the traversed sibling has children then navigate from its leaf child
+  //    to it through whole tree of the traversed sibling.
+  // 3. Get the parent and cycle algorithm until the root node.
+
+  // Navigate backwards (find the start offset).
+  while (currNode && currNode != rootElm) {
+    nsCOMPtr<nsIDOMElement> currElm(nsAccUtils::GetDOMElementFor(currNode));
+    NS_ENSURE_STATE(currElm);
+
+    if (currNode != aNode && !aComparer->equal(currElm)) {
+      PRInt32 startHTOffset = 0;
+      nsCOMPtr<nsIAccessible> startAcc;
+      nsresult rv = DOMPointToHypertextOffset(tmpNode, -1, &startHTOffset,
+                                              getter_AddRefs(startAcc));
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      if (!startAcc)
+        startHTOffset = 0;
+
+      if (startHTOffset > *aStartHTOffset)
+        *aStartHTOffset = startHTOffset;
+
+      break;
+    }
+
+    currNode->GetPreviousSibling(getter_AddRefs(tmpNode));
+    if (tmpNode) {
+      // Navigate through the subtree of traversed children to calculate
+      // left bound of the range.
+      FindStartOffsetInSubtree(tmpNode, currNode, aComparer, aStartHTOffset);
+    }
+
+    currNode->GetParentNode(getter_AddRefs(tmpNode));
+    currNode.swap(tmpNode);
+  }
+
+  // Navigate forwards (find the end offset).
+  PRBool moveIntoSubtree = PR_TRUE;
+  currNode = aNode;
+  while (currNode && currNode != rootElm) {
+    nsCOMPtr<nsIDOMElement> currElm(nsAccUtils::GetDOMElementFor(currNode));
+    NS_ENSURE_STATE(currElm);
+
+    // Stop new end offset searching if the given text attribute changes its
+    // value.
+    if (!aComparer->equal(currElm)) {
+      PRInt32 endHTOffset = 0;
+      nsresult rv = DOMPointToHypertextOffset(currNode, -1, &endHTOffset);
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      if (endHTOffset < *aEndHTOffset)
+        *aEndHTOffset = endHTOffset;
+
+      break;
+    }
+
+    if (moveIntoSubtree) {
+      // Navigate through subtree of traversed node. We use 'moveIntoSubtree'
+      // flag to avoid traversing the same subtree twice.
+      currNode->GetFirstChild(getter_AddRefs(tmpNode));
+      if (tmpNode)
+        FindEndOffsetInSubtree(tmpNode, aComparer, aEndHTOffset);
+    }
+
+    currNode->GetNextSibling(getter_AddRefs(tmpNode));
+    moveIntoSubtree = PR_TRUE;
+    if (!tmpNode) {
+      currNode->GetParentNode(getter_AddRefs(tmpNode));
+      moveIntoSubtree = PR_FALSE;
+    }
+
+    currNode.swap(tmpNode);
+  }
+
+  return NS_OK;
+}
+
+
+PRBool
+nsHyperTextAccessible::FindEndOffsetInSubtree(nsIDOMNode *aCurrNode,
+                                              nsTextAttr *aComparer,
+                                              PRInt32 *aHTOffset)
+{
+  if (!aCurrNode)
+    return PR_FALSE;
+
+  nsCOMPtr<nsIDOMElement> currElm(nsAccUtils::GetDOMElementFor(aCurrNode));
+  NS_ENSURE_STATE(currElm);
+
+  // If the given text attribute (pointed by nsTextAttr object) changes its
+  // value on the traversed element then fit the end of range.
+  if (!aComparer->equal(currElm)) {
+    PRInt32 endHTOffset = 0;
+    nsresult rv = DOMPointToHypertextOffset(aCurrNode, -1, &endHTOffset);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    if (endHTOffset < *aHTOffset)
+      *aHTOffset = endHTOffset;
+
+    return PR_TRUE;
+  }
+
+  // Deeply traverse into the tree to fit the end of range.
+  nsCOMPtr<nsIDOMNode> nextNode;
+  aCurrNode->GetFirstChild(getter_AddRefs(nextNode));
+  if (nextNode) {
+    PRBool res = FindEndOffsetInSubtree(nextNode, aComparer, aHTOffset);
+    if (res)
+      return res;
+  }
+
+  aCurrNode->GetNextSibling(getter_AddRefs(nextNode));
+  if (nextNode) {
+    if (FindEndOffsetInSubtree(nextNode, aComparer, aHTOffset))
+      return PR_TRUE;
+  }
+
+  return PR_FALSE;
+}
+
+PRBool
+nsHyperTextAccessible::FindStartOffsetInSubtree(nsIDOMNode *aCurrNode,
+                                                nsIDOMNode *aPrevNode,
+                                                nsTextAttr *aComparer,
+                                                PRInt32 *aHTOffset)
+{
+  if (!aCurrNode)
+    return PR_FALSE;
+
+  // Find the closest element back to the traversed element.
+  nsCOMPtr<nsIDOMNode> nextNode;
+  aCurrNode->GetLastChild(getter_AddRefs(nextNode));
+  if (nextNode) {
+    if (FindStartOffsetInSubtree(nextNode, aPrevNode, aComparer, aHTOffset))
+      return PR_TRUE;
+  }
+
+  nsCOMPtr<nsIDOMElement> currElm(nsAccUtils::GetDOMElementFor(aCurrNode));
+  NS_ENSURE_STATE(currElm);
+
+  // If the given text attribute (pointed by nsTextAttr object) changes its
+  // value on the traversed element then fit the start of range.
+  if (!aComparer->equal(currElm)) {
+    PRInt32 startHTOffset = 0;
+    nsCOMPtr<nsIAccessible> startAcc;
+    nsresult rv = DOMPointToHypertextOffset(aPrevNode, -1, &startHTOffset,
+                                            getter_AddRefs(startAcc));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    if (!startAcc)
+      startHTOffset = 0;
+
+    if (startHTOffset > *aHTOffset)
+      *aHTOffset = startHTOffset;
+
+    return PR_TRUE;
+  }
+
+  // Moving backwards to find the start of range.
+  aCurrNode->GetPreviousSibling(getter_AddRefs(nextNode));
+  if (nextNode) {
+    if (FindStartOffsetInSubtree(nextNode, aCurrNode, aComparer, aHTOffset))
+      return PR_TRUE;
+  }
+
+  return PR_FALSE;
+}
--- a/accessible/src/html/nsHyperTextAccessible.h
+++ b/accessible/src/html/nsHyperTextAccessible.h
@@ -40,16 +40,18 @@
 #ifndef _nsHyperTextAccessible_H_
 #define _nsHyperTextAccessible_H_
 
 #include "nsAccessibleWrap.h"
 #include "nsIAccessibleText.h"
 #include "nsIAccessibleHyperText.h"
 #include "nsIAccessibleEditableText.h"
 #include "nsAccessibleEventData.h"
+#include "nsTextUtils.h"
+
 #include "nsFrameSelection.h"
 #include "nsISelectionController.h"
 
 enum EGetTextType { eGetBefore=-1, eGetAt=0, eGetAfter=1 };
 
 // This character marks where in the text returned via nsIAccessibleText(),
 // that embedded object characters exist
 const PRUnichar kEmbeddedObjectChar = 0xfffc;
@@ -59,35 +61,37 @@ const PRUnichar kForcedNewLineChar = '\n
 #define NS_HYPERTEXTACCESSIBLE_IMPL_CID                 \
 {  /* 245f3bc9-224f-4839-a92e-95239705f30b */           \
   0x245f3bc9,                                           \
   0x224f,                                               \
   0x4839,                                               \
   { 0xa9, 0x2e, 0x95, 0x23, 0x97, 0x05, 0xf3, 0x0b }    \
 }
 
-
 /**
   * Special Accessible that knows how contain both text and embedded objects
   */
 class nsHyperTextAccessible : public nsAccessibleWrap,
                               public nsIAccessibleText,
                               public nsIAccessibleHyperText,
                               public nsIAccessibleEditableText
 {
 public:
   nsHyperTextAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIACCESSIBLETEXT
   NS_DECL_NSIACCESSIBLEHYPERTEXT
   NS_DECL_NSIACCESSIBLEEDITABLETEXT
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_HYPERTEXTACCESSIBLE_IMPL_CID)
 
+  // nsIAccessible
   NS_IMETHOD GetRole(PRUint32 *aRole);
   NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
+
+  // nsAccessible
   virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
   void CacheChildren();
 
   // Convert content offset to rendered text offset  
   static nsresult ContentToRenderedOffset(nsIFrame *aFrame, PRInt32 aContentOffset,
                                           PRUint32 *aRenderedOffset);
   
   // Convert rendered text offset to content offset
@@ -120,16 +124,27 @@ public:
     *                       descendant, then the returned offset will be on the relevant embedded object char.
     */
   nsresult DOMPointToHypertextOffset(nsIDOMNode* aNode, PRInt32 aNodeOffset,
                                      PRInt32 *aHypertextOffset,
                                      nsIAccessible **aFinalAccessible = nsnull,
                                      PRBool aIsEndOffset = PR_FALSE);
 
   /**
+   * Turn a hypertext offsets into DOM point.
+   *
+   * @param  aHTOffset  [in] the given start hypertext offset
+   * @param  aNode      [out] start node
+   * @param  aOffset    [out] offset inside the start node
+   */
+  nsresult HypertextOffsetToDOMPoint(PRInt32 aHTOffset,
+                                     nsIDOMNode **aNode,
+                                     PRInt32 *aOffset);
+
+  /**
    * Turn a start and end hypertext offsets into DOM range.
    *
    * @param  aStartHTOffset  [in] the given start hypertext offset
    * @param  aEndHTOffset    [in] the given end hypertext offset
    * @param  aStartNode      [out] start node of the range
    * @param  aStartOffset    [out] start offset of the range
    * @param  aEndNode        [out] end node of the range
    * @param  aEndOffset      [out] end offset of the range
@@ -206,37 +221,164 @@ protected:
                           nsIntRect *aBoundsRect = nsnull,
                           nsIAccessible **aStartAcc = nsnull,
                           nsIAccessible **aEndAcc = nsnull);
 
   nsIntRect GetBoundsForString(nsIFrame *aFrame, PRUint32 aStartRenderedOffset, PRUint32 aEndRenderedOffset);
 
   // Selection helpers
 
-  /**
-   * Get the relevant selection interfaces and ranges for the current hyper text
-   * @param aSelCon      The selection controller for the current hyper text, or nsnull if not needed
-   * @param aDomSel      The selection interface for the current hyper text, or nsnull if not needed
-   * @param aRanges      The selected ranges within the current subtree, or nsnull if not needed
+    /**
+   * Get the relevant selection interfaces and ranges for the current hyper
+   * text.
+   *
+   * @param aType    [in] the selection type
+   * @param aSelCon  [out, optional] the selection controller for the current
+   *                 hyper text
+   * @param aDomSel  [out, optional] the selection interface for the current
+   *                 hyper text
+   * @param aRanges  [out, optional] the selected ranges within the current
+   *                 subtree
    */
-  nsresult GetSelections(nsISelectionController **aSelCon,
+  nsresult GetSelections(PRInt16 aType,
+                         nsISelectionController **aSelCon,
                          nsISelection **aDomSel = nsnull,
                          nsCOMArray<nsIDOMRange>* aRanges = nsnull);
+
   nsresult SetSelectionRange(PRInt32 aStartPos, PRInt32 aEndPos);
 
   /**
    * Provide the line number for the caret, relative to the
    * current DOM node.
    * @return 1-based index for the line number with the caret
    */
   PRInt32 GetCaretLineNumber();
 
   // Helpers
   nsresult GetDOMPointByFrameOffset(nsIFrame *aFrame, PRInt32 aOffset,
                                     nsIAccessible *aAccessible,
                                     nsIDOMNode **aNode, PRInt32 *aNodeOffset);
+
+  
+  /**
+   * Return hyper text offset for the specified bound of the given DOM range.
+   * If the bound is outside of the hyper text then offset value is either
+   * 0 or number of characters of hyper text, it depends on type of requested
+   * offset. The method is a wrapper for DOMPointToHypertextOffset.
+   *
+   * @param aRange          [in] the given range
+   * @param aIsStartBound   [in] specifies whether the required range bound is
+   *                        start bound
+   * @param aIsStartOffset  [in] the offset type, used when the range bound is
+   *                        outside of hyper text
+   * @param aHTOffset       [out] the result offset
+   */
+  nsresult DOMRangeBoundToHypertextOffset(nsIDOMRange *aRange,
+                                          PRBool aIsStartBound,
+                                          PRBool aIsStartOffset,
+                                          PRInt32 *aHTOffset);
+
+  /**
+   * Set 'misspelled' text attribute and return range offsets where the
+   * attibute is stretched. If the text is not misspelled at the given offset
+   * then we expose only range offsets where text is not misspelled. The method
+   * is used by GetTextAttributes() method.
+   *
+   * @param aIncludeDefAttrs  [in] points whether text attributes having default
+   *                          values of attributes should be included
+   * @param aSourceNode       [in] the node we start to traverse from
+   * @param aStartOffset      [in, out] the start offset
+   * @param aEndOffset        [in, out] the end offset
+   * @param aAttributes       [out, optional] result attributes
+   */
+  nsresult GetSpellTextAttribute(nsIDOMNode *aNode, PRInt32 aNodeOffset,
+                                 PRInt32 *aStartOffset,
+                                 PRInt32 *aEndOffset,
+                                 nsIPersistentProperties *aAttributes);
+
+  /**
+   * Set 'lang' text attribute and return range offsets where attibute is
+   * stretched. The method is used by GetTextAttributes() method.
+   *
+   * @param aIncludeDefAttrs  [in] points whether text attributes having default
+   *                          values of attributes should be included
+   * @param aSourceNode       [in] the node we start to traverse from
+   * @param aStartOffset      [in, out] the start offset
+   * @param aEndOffset        [in, out] the end offset
+   * @param aAttributes       [out, optional] result attributes
+   */
+  nsresult GetLangTextAttributes(PRBool aIncludeDefAttrs,
+                                 nsIDOMNode *aSourceNode,
+                                 PRInt32 *aStartOffset,
+                                 PRInt32 *aEndOffset,
+                                 nsIPersistentProperties *aAttributes);
+
+  /**
+   * Set CSS based text attribute and return range offsets where attibutes are
+   * stretched. The method is used by GetTextAttributes() method.
+   *
+   * @param aIncludeDefAttrs  [in] points whether text attributes having default
+   *                          values of attributes should be included
+   * @param aSourceNode       [in] the node we start to traverse from
+   * @param aStartOffset      [in, out] the start offset
+   * @param aEndOffset        [in, out] the end offset
+   * @param aAttributes       [out, optional] result attributes
+   */
+  nsresult GetCSSTextAttributes(PRBool aIncludeDefAttrs,
+                                nsIDOMNode *aSourceNode,
+                                PRInt32 *aStartOffset,
+                                PRInt32 *aEndOffset,
+                                nsIPersistentProperties *aAttributes);
+
+  /**
+   * Calculates range (start and end offsets) of text where the text attribute
+   * (pointed by nsTextAttr object) is stretched. New offsets may be smaller if
+   * the given text attribute changes its value before or after the given
+   * offsets.
+   *
+   * @param aNode          [in] the node we start to traverse from
+   * @param aComparer      [in] object used to describe the text attribute
+   * @param aStartHTOffset [in, out] the start offset
+   * @param aEndHTOffset   [in, out] the end offset
+   */
+  nsresult GetRangeForTextAttr(nsIDOMNode *aNode,
+                               nsTextAttr *aComparer,
+                               PRInt32 *aStartHTOffset,
+                               PRInt32 *aEndHTOffset);
+
+  /**
+   * Find new end offset for text attributes navigating through the tree. New
+   * end offset may be smaller if the given text attribute (pointed by
+   * nsTextAttr object) changes its value before the given end offset.
+   *
+   * @param  aCurrNode  [in] the first node of the tree
+   * @param  aComparer  [in] object used to describe the text attribute
+   * @param  aHTOffset  [in, out] the end offset
+   * @return            true if the end offset has been changed
+   */
+  PRBool FindEndOffsetInSubtree(nsIDOMNode *aCurrNode,
+                                nsTextAttr *aComparer,
+                                PRInt32 *aHTOffset);
+
+  /**
+   * Find the start offset for text attributes navigating through the tree. New
+   * start offset may be bigger if the given text attribute (pointed by
+   * nsTextAttr object) changes its value after the given start offset.
+   *
+   * @param  aCurrNode  [in] the node navigating through thee thee is started
+   *                    from
+   * @param  aPrevNode  [in] the previous node placed before the start node
+   * @param  aComparer  [in] object used to describe the text attribute
+   * @param  aHTOffset  [in, out] the start offset
+   * @return            true if the start offset has been changed
+   */
+  PRBool FindStartOffsetInSubtree(nsIDOMNode *aCurrNode,
+                                  nsIDOMNode *aPrevNode,
+                                  nsTextAttr *aComparer,
+                                  PRInt32 *aHTOffset);
+
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsHyperTextAccessible,
                               NS_HYPERTEXTACCESSIBLE_IMPL_CID)
 
 #endif  // _nsHyperTextAccessible_H_
 
--- a/accessible/src/mac/nsAccessibleWrap.h
+++ b/accessible/src/mac/nsAccessibleWrap.h
@@ -91,17 +91,19 @@ class nsAccessibleWrap : public nsAccess
       return (state & nsIAccessibleStates::STATE_HASPOPUP);
     }
     
     // return this accessible's all children, adhering to "flat" accessibles by not returning their children.
     void GetUnignoredChildren(nsTArray<nsRefPtr<nsAccessibleWrap> > &aChildrenArray);
     virtual already_AddRefed<nsIAccessible> GetUnignoredParent();
     
   protected:
-    
+
+    virtual nsresult FirePlatformEvent(nsIAccessibleEvent *aEvent);
+
     PRBool AncestorIsFlat() {
       // we don't create a native object if we're child of a "flat" accessible; for example, on OS X buttons 
       // shouldn't have any children, because that makes the OS confused. 
       //
       // to maintain a scripting environment where the XPCOM accessible hierarchy look the same 
       // on all platforms, we still let the C++ objects be created though.
       
       nsCOMPtr<nsIAccessible> curParent = GetParent();
--- a/accessible/src/mac/nsAccessibleWrap.mm
+++ b/accessible/src/mac/nsAccessibleWrap.mm
@@ -164,18 +164,28 @@ nsAccessibleWrap::FireAccessibleEvent(ns
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   NS_ENSURE_ARG_POINTER(aEvent);
 
   nsresult rv = nsAccessible::FireAccessibleEvent(aEvent);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  return FirePlatformEvent(aEvent);
+
+  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
+}
+
+nsresult
+nsAccessibleWrap::FirePlatformEvent(nsIAccessibleEvent *aEvent)
+{
+  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
   PRUint32 eventType;
-  rv = aEvent->GetEventType(&eventType);
+  nsresult rv = aEvent->GetEventType(&eventType);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // ignore everything but focus-changed and value-changed events for now.
   if (eventType != nsIAccessibleEvent::EVENT_FOCUS &&
       eventType != nsIAccessibleEvent::EVENT_VALUE_CHANGE)
     return NS_OK;
 
   nsCOMPtr<nsIAccessible> accessible;
--- a/accessible/src/msaa/CAccessibleText.cpp
+++ b/accessible/src/msaa/CAccessibleText.cpp
@@ -43,16 +43,17 @@
 #include "Accessible2.h"
 #include "AccessibleText_i.c"
 
 #include "nsIAccessible.h"
 #include "nsIAccessibleText.h"
 #include "nsIAccessibleTypes.h"
 #include "nsIWinAccessNode.h"
 #include "nsAccessNodeWrap.h"
+#include "nsAccessibleWrap.h"
 
 #include "nsCOMPtr.h"
 #include "nsString.h"
 
 #define GET_NSIACCESSIBLETEXT \
 nsCOMPtr<nsIAccessibleText> textAcc(do_QueryInterface(this));\
 NS_ASSERTION(textAcc,\
              "Subclass of CAccessibleText doesn't implement nsIAccessibleText");\
@@ -103,42 +104,36 @@ CAccessibleText::get_attributes(long aOf
     return E_INVALIDARG;
 
   *aStartOffset = 0;
   *aEndOffset = 0;
   *aTextAttributes = NULL;
 
   GET_NSIACCESSIBLETEXT
 
-  nsCOMPtr<nsIAccessible> accessible;
   PRInt32 startOffset = 0, endOffset = 0;
-  textAcc->GetAttributeRange(aOffset, &startOffset, &endOffset,
-                             getter_AddRefs(accessible));
-  if (!accessible)
-    return E_FAIL;
-
-  nsCOMPtr<nsIWinAccessNode> winAccessNode(do_QueryInterface(accessible));
-  if (!winAccessNode)
-    return E_FAIL;
-
-  void *instancePtr = 0;
-  winAccessNode->QueryNativeInterface(IID_IAccessible2, &instancePtr);
-  if (!instancePtr)
-    return E_FAIL;
-
-  IAccessible2 *pAccessible2 = static_cast<IAccessible2*>(instancePtr);
-  HRESULT hr = pAccessible2->get_attributes(aTextAttributes);
-  pAccessible2->Release();
+  nsCOMPtr<nsIPersistentProperties> attributes;
+  nsresult rv = textAcc->GetTextAttributes(PR_TRUE, aOffset,
+                                           &startOffset, &endOffset,
+                                           getter_AddRefs(attributes));
+  if (NS_FAILED(rv))
+    return GetHRESULT(rv);
+  
+  HRESULT hr = nsAccessibleWrap::ConvertToIA2Attributes(attributes,
+                                                        aTextAttributes);
+  if (FAILED(hr))
+    return hr;
 
   *aStartOffset = startOffset;
   *aEndOffset = endOffset;
-  return hr;
+
+  return S_OK;
 
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
-  return E_NOTIMPL;
+  return E_FAIL;
 }
 
 STDMETHODIMP
 CAccessibleText::get_caretOffset(long *aOffset)
 {
 __try {
   *aOffset = -1;
 
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -70,16 +70,18 @@
 
 #ifdef DEBUG_LEAKS
 static gAccessibles = 0;
 #endif
 
 EXTERN_C GUID CDECL CLSID_Accessible =
 { 0x61044601, 0xa811, 0x4e2b, { 0xbb, 0xba, 0x17, 0xbf, 0xab, 0xd3, 0x29, 0xd7 } };
 
+static const PRInt32 kIEnumVariantDisconnected = -1;
+
 /*
  * Class nsAccessibleWrap
  */
 
 //-----------------------------------------------------
 // construction
 //-----------------------------------------------------
 nsAccessibleWrap::nsAccessibleWrap(nsIDOMNode* aNode, nsIWeakReference *aShell):
@@ -328,16 +330,22 @@ STDMETHODIMP nsAccessibleWrap::get_accVa
   *pszValue = NULL;
   nsCOMPtr<nsIAccessible> xpAccessible;
   GetXPAccessibleFor(varChild, getter_AddRefs(xpAccessible));
   if (xpAccessible) {
     nsAutoString value;
     if (NS_FAILED(xpAccessible->GetValue(value)))
       return E_FAIL;
 
+    // see bug 438784: Need to expose URL on doc's value attribute.
+    // For this, reverting part of fix for bug 425693 to make this MSAA method 
+    // behave IAccessible2-style.
+    if (value.IsEmpty())
+      return S_FALSE;
+
     *pszValue = ::SysAllocStringLen(value.get(), value.Length());
     if (!*pszValue)
       return E_OUTOFMEMORY;
   }
 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return S_OK;
 }
 
@@ -1075,68 +1083,68 @@ STDMETHODIMP nsAccessibleWrap::put_accVa
       /* [optional][in] */ VARIANT varChild,
       /* [in] */ BSTR szValue)
 {
   return E_NOTIMPL;
 }
 
 #include "mshtml.h"
 
+////////////////////////////////////////////////////////////////////////////////
+// nsAccessibleWrap. IEnumVariant
+
 STDMETHODIMP
-nsAccessibleWrap::Next(ULONG aNumElementsRequested, VARIANT FAR* pvar, ULONG FAR* aNumElementsFetched)
+nsAccessibleWrap::Next(ULONG aNumElementsRequested, VARIANT FAR* aPVar,
+                       ULONG FAR* aNumElementsFetched)
 {
-  // If there are two clients using this at the same time, and they are
-  // each using a different mEnumVariant position it would be bad, because
-  // we have only 1 object and can only keep of mEnumVARIANT position once
-
   // Children already cached via QI to IEnumVARIANT
 __try {
   *aNumElementsFetched = 0;
 
-  PRInt32 numChildren;
-  GetChildCount(&numChildren);
+  if (aNumElementsRequested <= 0 || !aPVar)
+    return E_INVALIDARG;
+
+  if (mEnumVARIANTPosition == kIEnumVariantDisconnected)
+    return CO_E_OBJNOTCONNECTED;
+
+  nsCOMPtr<nsIAccessible> traversedAcc;
+  nsresult rv = GetChildAt(mEnumVARIANTPosition, getter_AddRefs(traversedAcc));
+  if (!traversedAcc)
+    return S_FALSE;
 
-  if (aNumElementsRequested <= 0 || !pvar ||
-      mEnumVARIANTPosition >= numChildren) {
-    return E_FAIL;
+  for (PRUint32 i = 0; i < aNumElementsRequested; i++) {
+    VariantInit(&aPVar[i]);
+
+    aPVar[i].pdispVal = NativeAccessible(traversedAcc);
+    aPVar[i].vt = VT_DISPATCH;
+    (*aNumElementsFetched)++;
+
+    nsCOMPtr<nsIAccessible> nextAcc;
+    traversedAcc->GetNextSibling(getter_AddRefs(nextAcc));
+    if (!nextAcc)
+      break;
+
+    traversedAcc = nextAcc;
   }
 
-  VARIANT varStart;
-  VariantInit(&varStart);
-  varStart.lVal = CHILDID_SELF;
-  varStart.vt = VT_I4;
-
-  accNavigate(NAVDIR_FIRSTCHILD, varStart, &pvar[0]);
+  mEnumVARIANTPosition += *aNumElementsFetched;
+  return (*aNumElementsFetched) < aNumElementsRequested ? S_FALSE : S_OK;
 
-  for (long childIndex = 0; pvar[*aNumElementsFetched].vt == VT_DISPATCH; ++childIndex) {
-    PRBool wasAccessibleFetched = PR_FALSE;
-    nsAccessibleWrap *msaaAccessible =
-      static_cast<nsAccessibleWrap*>(pvar[*aNumElementsFetched].pdispVal);
-    if (!msaaAccessible)
-      break;
-    if (childIndex >= mEnumVARIANTPosition) {
-      if (++*aNumElementsFetched >= aNumElementsRequested)
-        break;
-      wasAccessibleFetched = PR_TRUE;
-    }
-    msaaAccessible->accNavigate(NAVDIR_NEXT, varStart, &pvar[*aNumElementsFetched] );
-    if (!wasAccessibleFetched)
-      msaaAccessible->nsAccessNode::Release(); // this accessible will not be received by the caller
-  }
-
-  mEnumVARIANTPosition += static_cast<PRUint16>(*aNumElementsFetched);
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
-  return NOERROR;
+  return E_FAIL;
 }
 
 STDMETHODIMP
 nsAccessibleWrap::Skip(ULONG aNumElements)
 {
 __try {
-  mEnumVARIANTPosition += static_cast<PRUint16>(aNumElements);
+  if (mEnumVARIANTPosition == kIEnumVariantDisconnected)
+    return CO_E_OBJNOTCONNECTED;
+
+  mEnumVARIANTPosition += aNumElements;
 
   PRInt32 numChildren;
   GetChildCount(&numChildren);
 
   if (mEnumVARIANTPosition > numChildren)
   {
     mEnumVARIANTPosition = numChildren;
     return S_FALSE;
@@ -1147,18 +1155,36 @@ nsAccessibleWrap::Skip(ULONG aNumElement
 
 STDMETHODIMP
 nsAccessibleWrap::Reset(void)
 {
   mEnumVARIANTPosition = 0;
   return NOERROR;
 }
 
+STDMETHODIMP
+nsAccessibleWrap::Clone(IEnumVARIANT FAR* FAR* ppenum)
+{
+__try {
+  *ppenum = nsnull;
+  
+  nsCOMPtr<nsIArray> childArray;
+  nsresult rv = GetChildren(getter_AddRefs(childArray));
 
-// IAccessible2
+  *ppenum = new AccessibleEnumerator(childArray);
+  if (!*ppenum)
+    return E_OUTOFMEMORY;
+  NS_ADDREF(*ppenum);
+
+} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
+  return NOERROR;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsAccessibleWrap. IAccessible2
 
 STDMETHODIMP
 nsAccessibleWrap::get_nRelations(long *aNRelations)
 {
 __try {
   PRUint32 count = 0;
   nsresult rv = GetRelationsCount(&count);
   *aNRelations = count;
@@ -1553,99 +1579,22 @@ nsAccessibleWrap::get_attributes(BSTR *a
 __try {
   *aAttributes = NULL;
 
   nsCOMPtr<nsIPersistentProperties> attributes;
   nsresult rv = GetAttributes(getter_AddRefs(attributes));
   if (NS_FAILED(rv))
     return GetHRESULT(rv);
 
-  if (!attributes)
-    return S_FALSE;
-
-  nsCOMPtr<nsISimpleEnumerator> propEnum;
-  attributes->Enumerate(getter_AddRefs(propEnum));
-  if (!propEnum)
-    return E_FAIL;
-
-  nsAutoString strAttrs;
-
-  const char kCharsToEscape[] = ":;=,\\";
-
-  PRBool hasMore = PR_FALSE;
-  while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) && hasMore) {
-    nsCOMPtr<nsISupports> propSupports;
-    propEnum->GetNext(getter_AddRefs(propSupports));
-
-    nsCOMPtr<nsIPropertyElement> propElem(do_QueryInterface(propSupports));
-    if (!propElem)
-      return E_FAIL;
-
-    nsCAutoString name;
-    rv = propElem->GetKey(name);
-    if (NS_FAILED(rv))
-      return GetHRESULT(rv);
-
-    PRUint32 offset = 0;
-    while ((offset = name.FindCharInSet(kCharsToEscape, offset)) != kNotFound) {
-      name.Insert('\\', offset);
-      offset += 2;
-    }
-
-    nsAutoString value;
-    rv = propElem->GetValue(value);
-    if (NS_FAILED(rv))
-      return E_FAIL;
-
-    offset = 0;
-    while ((offset = value.FindCharInSet(kCharsToEscape, offset)) != kNotFound) {
-      value.Insert('\\', offset);
-      offset += 2;
-    }
-
-    AppendUTF8toUTF16(name, strAttrs);
-    strAttrs.Append(':');
-    strAttrs.Append(value);
-    strAttrs.Append(';');
-  }
-
-  if (strAttrs.IsEmpty())
-    return S_FALSE;
-
-  *aAttributes = ::SysAllocStringLen(strAttrs.get(), strAttrs.Length());
-  return *aAttributes ? S_OK : E_OUTOFMEMORY;
+  return ConvertToIA2Attributes(attributes, aAttributes);
 
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return E_FAIL;
 }
 
-STDMETHODIMP
-nsAccessibleWrap::Clone(IEnumVARIANT FAR* FAR* ppenum)
-{
-__try {
-  // Clone could be bad, the cloned items aren't tracked for shutdown
-  // Then again, as long as the client releases the items in time, we're okay
-  *ppenum = nsnull;
-
-  nsAccessibleWrap *accessibleWrap = new nsAccessibleWrap(mDOMNode, mWeakShell);
-  if (!accessibleWrap)
-    return E_FAIL;
-
-  IAccessible *msaaAccessible = static_cast<IAccessible*>(accessibleWrap);
-  msaaAccessible->AddRef();
-  QueryInterface(IID_IEnumVARIANT, (void**)ppenum);
-  if (*ppenum)
-    (*ppenum)->Skip(mEnumVARIANTPosition); // QI addrefed
-  msaaAccessible->Release();
-
-} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
-  return NOERROR;
-}
-
-
 // For IDispatch support
 STDMETHODIMP
 nsAccessibleWrap::GetTypeInfoCount(UINT *p)
 {
   *p = 0;
   return E_NOTIMPL;
 }
 
@@ -1685,16 +1634,22 @@ NS_IMETHODIMP nsAccessibleWrap::GetNativ
 NS_IMETHODIMP
 nsAccessibleWrap::FireAccessibleEvent(nsIAccessibleEvent *aEvent)
 {
   NS_ENSURE_ARG(aEvent);
 
   nsresult rv = nsAccessible::FireAccessibleEvent(aEvent);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  return FirePlatformEvent(aEvent);
+}
+
+nsresult
+nsAccessibleWrap::FirePlatformEvent(nsIAccessibleEvent *aEvent)
+{
   PRUint32 eventType = 0;
   aEvent->GetEventType(&eventType);
 
   NS_ENSURE_TRUE(eventType > 0 &&
                  eventType < nsIAccessibleEvent::EVENT_LAST_ENTRY,
                  NS_ERROR_FAILURE);
 
   PRUint32 winLastEntry = gWinEventMap[nsIAccessibleEvent::EVENT_LAST_ENTRY];
@@ -1740,16 +1695,21 @@ nsAccessibleWrap::FireAccessibleEvent(ns
   // scrollbars and the child window contains only the client area.
   // Details of the 2 window system:
   // * Scrollbar window: caret drawing window & return value for WindowFromAccessibleObject()
   // * Client area window: text drawing window & MSAA event window
 
   // Fire MSAA event for client area window.
   NotifyWinEvent(winEvent, hWnd, OBJID_CLIENT, childID);
 
+  // If the accessible children are changed then drop the IEnumVariant current
+  // position of the accessible.
+  if (eventType == nsIAccessibleEvent::EVENT_REORDER)
+    UnattachIEnumVariant();
+
   return NS_OK;
 }
 
 //------- Helper methods ---------
 
 PRInt32 nsAccessibleWrap::GetChildIDFor(nsIAccessible* aAccessible)
 {
   // A child ID of the window is required, when we use NotifyWinEvent,
@@ -1811,16 +1771,79 @@ nsAccessibleWrap::GetHWNDFor(nsIAccessib
 
     accessibleDoc->GetWindowHandle(&handle);
     hWnd = (HWND)handle;
   }
 
   return hWnd;
 }
 
+HRESULT
+nsAccessibleWrap::ConvertToIA2Attributes(nsIPersistentProperties *aAttributes,
+                                         BSTR *aIA2Attributes)
+{
+  *aIA2Attributes = NULL;
+
+  // The format is name:value;name:value; with \ for escaping these
+  // characters ":;=,\".
+
+  if (!aAttributes)
+    return S_FALSE;
+
+  nsCOMPtr<nsISimpleEnumerator> propEnum;
+  aAttributes->Enumerate(getter_AddRefs(propEnum));
+  if (!propEnum)
+    return E_FAIL;
+
+  nsAutoString strAttrs;
+
+  const char kCharsToEscape[] = ":;=,\\";
+
+  PRBool hasMore = PR_FALSE;
+  while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) && hasMore) {
+    nsCOMPtr<nsISupports> propSupports;
+    propEnum->GetNext(getter_AddRefs(propSupports));
+
+    nsCOMPtr<nsIPropertyElement> propElem(do_QueryInterface(propSupports));
+    if (!propElem)
+      return E_FAIL;
+
+    nsCAutoString name;
+    if (NS_FAILED(propElem->GetKey(name)))
+      return E_FAIL;
+
+    PRUint32 offset = 0;
+    while ((offset = name.FindCharInSet(kCharsToEscape, offset)) != kNotFound) {
+      name.Insert('\\', offset);
+      offset += 2;
+    }
+
+    nsAutoString value;
+    if (NS_FAILED(propElem->GetValue(value)))
+      return E_FAIL;
+
+    offset = 0;
+    while ((offset = value.FindCharInSet(kCharsToEscape, offset)) != kNotFound) {
+      value.Insert('\\', offset);
+      offset += 2;
+    }
+
+    AppendUTF8toUTF16(name, strAttrs);
+    strAttrs.Append(':');
+    strAttrs.Append(value);
+    strAttrs.Append(';');
+  }
+
+  if (strAttrs.IsEmpty())
+    return S_FALSE;
+
+  *aIA2Attributes = ::SysAllocStringLen(strAttrs.get(), strAttrs.Length());
+  return *aIA2Attributes ? S_OK : E_OUTOFMEMORY;
+}
+
 IDispatch *nsAccessibleWrap::NativeAccessible(nsIAccessible *aXPAccessible)
 {
   if (!aXPAccessible) {
    NS_WARNING("Not passing in an aXPAccessible");
    return NULL;
   }
 
   nsCOMPtr<nsIAccessibleWin32Object> accObject(do_QueryInterface(aXPAccessible));
@@ -1836,16 +1859,22 @@ IDispatch *nsAccessibleWrap::NativeAcces
   }
 
   IAccessible *msaaAccessible;
   aXPAccessible->GetNativeInterface((void**)&msaaAccessible);
 
   return static_cast<IDispatch*>(msaaAccessible);
 }
 
+void
+nsAccessibleWrap::UnattachIEnumVariant()
+{
+  if (mEnumVARIANTPosition > 0)
+    mEnumVARIANTPosition = kIEnumVariantDisconnected;
+}
 
 void nsAccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild, nsIAccessible **aXPAccessible)
 {
   *aXPAccessible = nsnull;
   if (!mWeakShell)
     return; // Fail, we don't want to do anything after we've shut down
 
   // if its us real easy - this seems to always be the case
--- a/accessible/src/msaa/nsAccessibleWrap.h
+++ b/accessible/src/msaa/nsAccessibleWrap.h
@@ -256,17 +256,21 @@ class nsAccessibleWrap : public nsAccess
         /* [retval][out] */ long *indexInParent);
 
     virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_locale(
         /* [retval][out] */ IA2Locale *locale);
 
     virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_attributes(
         /* [retval][out] */ BSTR *attributes);
 
-  public:   // IEnumVariantMethods
+  public: // IEnumVariant
+    // If there are two clients using this at the same time, and they are
+    // each using a different mEnumVariant position it would be bad, because
+    // we have only 1 object and can only keep of mEnumVARIANT position once.
+
     virtual /* [local] */ HRESULT STDMETHODCALLTYPE Next( 
         /* [in] */ ULONG celt,
         /* [length_is][size_is][out] */ VARIANT __RPC_FAR *rgVar,
         /* [out] */ ULONG __RPC_FAR *pCeltFetched);
   
     virtual HRESULT STDMETHODCALLTYPE Skip( 
         /* [in] */ ULONG celt);
   
@@ -287,16 +291,18 @@ class nsAccessibleWrap : public nsAccess
         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);
 
   // nsPIAccessible
   NS_IMETHOD FireAccessibleEvent(nsIAccessibleEvent *aEvent);
 
   // Helper methods
   static PRInt32 GetChildIDFor(nsIAccessible* aAccessible);
   static HWND GetHWNDFor(nsIAccessible *aAccessible);
+  static HRESULT ConvertToIA2Attributes(nsIPersistentProperties *aAttributes,
+                                        BSTR *aIA2Attributes);
 
   /**
    * System caret support: update the Windows caret position. 
    * The system caret works more universally than the MSAA caret
    * For example, Window-Eyes, JAWS, ZoomText and Windows Tablet Edition use it
    * We will use an invisible system caret.
    * Gecko is still responsible for drawing its own caret
    */
@@ -307,21 +313,30 @@ class nsAccessibleWrap : public nsAccess
 
   // NT4 does not have the oleacc that defines these methods. So we define copies here that automatically
   // load the library only if needed.
   static STDMETHODIMP AccessibleObjectFromWindow(HWND hwnd,DWORD dwObjectID,REFIID riid,void **ppvObject);
   static STDMETHODIMP NotifyWinEvent(DWORD event,HWND hwnd,LONG idObjectType,LONG idObject);
 
   static IDispatch *NativeAccessible(nsIAccessible *aXPAccessible);
 
+  /**
+   * Drops the IEnumVariant current position so that navigation methods
+   * Next() and Skip() doesn't work until Reset() method is called. The method
+   * is used when children of the accessible are changed.
+   */
+  void UnattachIEnumVariant();
+
 protected:
+  virtual nsresult FirePlatformEvent(nsIAccessibleEvent *aEvent);
+
   // mEnumVARIANTPosition not the current accessible's position, but a "cursor" of 
   // where we are in the current list of children, with respect to
   // nsIEnumVariant::Reset(), Skip() and Next().
-  PRUint16 mEnumVARIANTPosition;
+  PRInt32 mEnumVARIANTPosition;
 
   enum navRelations {
     NAVRELATION_CONTROLLED_BY = 0x1000,
     NAVRELATION_CONTROLLER_FOR = 0x1001,
     NAVRELATION_LABEL_FOR = 0x1002,
     NAVRELATION_LABELLED_BY = 0x1003,
     NAVRELATION_MEMBER_OF = 0x1004,
     NAVRELATION_NODE_CHILD_OF = 0x1005,
--- a/accessible/src/other/nsAccessibleWrap.h
+++ b/accessible/src/other/nsAccessibleWrap.h
@@ -46,11 +46,16 @@
 #include "nsCOMPtr.h"
 #include "nsAccessible.h"
 
 class nsAccessibleWrap : public nsAccessible
 {
   public: // construction, destruction
     nsAccessibleWrap(nsIDOMNode*, nsIWeakReference *aShell);
     virtual ~nsAccessibleWrap();
+
+  protected:
+    virtual nsresult FirePlatformEvent(nsIAccessibleEvent *aEvent) {
+      return NS_OK;
+    }
 };
 
 #endif
--- a/accessible/src/xul/nsXULSelectAccessible.cpp
+++ b/accessible/src/xul/nsXULSelectAccessible.cpp
@@ -835,21 +835,23 @@ nsXULListitemAccessible::GetListAccessib
   
   nsCOMPtr<nsIDOMXULSelectControlItemElement> listItem =
     do_QueryInterface(mDOMNode);
   if (!listItem)
     return nsnull;
 
   nsCOMPtr<nsIDOMXULSelectControlElement> list;
   listItem->GetControl(getter_AddRefs(list));
-  if (!list)
+
+  nsCOMPtr<nsIDOMNode> listNode(do_QueryInterface(list));
+  if (!listNode)
     return nsnull;
 
   nsIAccessible *listAcc = nsnull;
-  GetAccService()->GetAccessibleInWeakShell(list, mWeakShell, &listAcc);
+  GetAccService()->GetAccessibleInWeakShell(listNode, mWeakShell, &listAcc);
   return listAcc;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULListitemAccessible. nsIAccessible
 
 /**
   * If there is a Listcell as a child ( not anonymous ) use it, otherwise
--- a/accessible/src/xul/nsXULTreeAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeAccessible.cpp
@@ -631,32 +631,34 @@ nsXULTreeAccessible::InvalidateCache(PRI
 //   treeViewInvalidated(in long aStartRow, in long aEndRow,
 //                       in long aStartCol, in long aEndCol);
 NS_IMETHODIMP
 nsXULTreeAccessible::TreeViewInvalidated(PRInt32 aStartRow, PRInt32 aEndRow,
                                          PRInt32 aStartCol, PRInt32 aEndCol)
 {
   NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
 
-  PRInt32 endRow = aEndRow, endCol = aEndCol;
+  PRInt32 endRow = aEndRow;
 
   nsresult rv;
   if (endRow == -1) {
     PRInt32 rowCount = 0;
     rv = mTreeView->GetRowCount(&rowCount);
     NS_ENSURE_SUCCESS(rv, rv);
 
     endRow = rowCount - 1;
   }
 
   nsCOMPtr<nsITreeColumns> treeColumns;
   mTree->GetColumns(getter_AddRefs(treeColumns));
   NS_ENSURE_STATE(treeColumns);
 
 #ifdef MOZ_ACCESSIBILITY_ATK
+  PRInt32 endCol = aEndCol;
+
   if (endCol == -1) {
     PRInt32 colCount = 0;
     rv = treeColumns->GetCount(&colCount);
     NS_ENSURE_SUCCESS(rv, rv);
 
     endCol = colCount - 1;
   }
 #else
@@ -700,26 +702,58 @@ nsXULTreeAccessible::TreeViewInvalidated
         }
       }
     }
   }
 
   return NS_OK;
 }
 
+// void nsIAccessibleTreeCache::treeViewChanged();
+NS_IMETHODIMP
+nsXULTreeAccessible::TreeViewChanged()
+{
+  if (!mTree)
+    return NS_ERROR_FAILURE;
+
+  // Fire only notification destroy/create events on accessible tree to lie to
+  // AT because it should be expensive to fire destroy events for each tree item
+  // in cache.
+  nsCOMPtr<nsIAccessibleEvent> eventDestroy =
+    new nsAccEvent(nsIAccessibleEvent::EVENT_DOM_DESTROY,
+                   this, PR_FALSE);
+  NS_ENSURE_TRUE(eventDestroy, NS_ERROR_OUT_OF_MEMORY);
+
+  nsresult rv = FirePlatformEvent(eventDestroy);
+
+  ClearCache(*mAccessNodeCache);
+
+  mTree->GetView(getter_AddRefs(mTreeView));
+
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIAccessibleEvent> eventCreate =
+    new nsAccEvent(nsIAccessibleEvent::EVENT_DOM_CREATE,
+                   this, PR_FALSE);
+  NS_ENSURE_TRUE(eventCreate, NS_ERROR_OUT_OF_MEMORY);
+
+  return FirePlatformEvent(eventCreate);
+}
+
 nsresult nsXULTreeAccessible::GetColumnCount(nsITreeBoxObject* aBoxObject, PRInt32* aCount)
 {
   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);
 }
 
-// ---------- nsXULTreeitemAccessible ---------- 
+////////////////////////////////////////////////////////////////////////////////
+// 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)
--- a/accessible/tests/mochitest/Makefile.in
+++ b/accessible/tests/mochitest/Makefile.in
@@ -42,27 +42,40 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = accessible
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =\
 		moz.png \
+		nsIAccessible_name.css \
+		nsIAccessible_name.xbl \
 		test_aria_activedescendant.html \
+		test_aria_role_article.html \
 		test_bug368835.xul \
 		test_bug420863.html \
+		test_cssattrs.html \
 		test_groupattrs.xul \
-		test_table_indexes.html \
+	$(warning test_table_indexes.html temporarily disabled) \
+		test_nsIAccessible_name.html \
+		test_nsIAccessible_name.xul \
 		test_nsIAccessibleTable_1.html \
 		test_nsIAccessibleTable_2.html \
 		test_nsIAccessibleTable_3.html \
 		test_nsIAccessibleTable_4.html \
 		test_nsIAccessibleTable_listboxes.xul \
+		test_nsIAccessibleDocument.html \
 		test_nsIAccessibleHyperLink.html \
 		test_nsIAccessibleHyperLink.xul \
 		test_nsIAccessibleHyperText.html \
 		test_nsIAccessibleImage.html \
+		test_nsOuterDocAccessible.html \
+		test_textattrs.html \
+		test_textboxes.html \
+		test_textboxes.xul \
+		testTextboxes.js \
 		test_bug428479.html \
+		test_bug429285.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/nsIAccessible_name.css
@@ -0,0 +1,11 @@
+box.first {
+  -moz-binding: url('chrome://mochikit/content/a11y/accessible/nsIAccessible_name.xbl#first');
+}
+
+.second {
+  -moz-binding: url('chrome://mochikit/content/a11y/accessible/nsIAccessible_name.xbl#second');
+}
+
+.third {
+  -moz-binding: url('chrome://mochikit/content/a11y/accessible/nsIAccessible_name.xbl#third');
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/nsIAccessible_name.xbl
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+
+<bindings xmlns="http://www.mozilla.org/xbl"
+          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <binding id="first">
+    <content>
+      <xul:textbox anonid="labeled" class="bottom"/>
+      <xul:label control="labeled" value="Label"/>
+      <children/>
+    </content>
+  </binding>
+
+  <binding id="second">
+    <content>
+      <xul:box class="first">
+        <xul:label control="toplabeled" value="Top textbox"/>
+        <xul:textbox anonid="toplabeled" class="top"/>
+      </xul:box>
+      <children/>
+    </content>
+  </binding>
+
+</bindings>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/testTextboxes.js
@@ -0,0 +1,93 @@
+const nsIAccessibleRetrieval = Components.interfaces.nsIAccessibleRetrieval;
+
+// Mapping needed state flags for easier handling.
+const state_focusable = 
+      Components.interfaces.nsIAccessibleStates.STATE_FOCUSABLE;
+const state_focused = 
+      Components.interfaces.nsIAccessibleStates.STATE_FOCUSED;
+const state_readonly = 
+      Components.interfaces.nsIAccessibleStates.STATE_READONLY;
+
+const ext_state_multi_line = 
+      Components.interfaces.nsIAccessibleStates.EXT_STATE_MULTI_LINE;
+const ext_state_editable = 
+      Components.interfaces.nsIAccessibleStates.EXT_STATE_EDITABLE;
+const ext_state_required = 
+      Components.interfaces.nsIAccessibleStates.STATE_REQUIRED;
+const ext_state_invalid = 
+      Components.interfaces.nsIAccessibleStates.STATE_INVALID;
+
+// Mapping needed final roles
+const role_entry = Components.interfaces.nsIAccessibleRole.ROLE_ENTRY;
+const role_password_text =
+      Components.interfaces.nsIAccessibleRole.ROLE_PASSWORD_TEXT;
+
+var gAccRetrieval = null;
+
+function testValue(aID, aAcc, aValue, aRole)
+{
+  if (aRole == role_password_text) {
+    var value;
+    try {
+      value = aAcc.value;
+      do_throw("We do not want a value on " + aID + "!");
+    } catch(e) {
+      is(e.result, Components.results.NS_ERROR_FAILURE,
+         "Wrong return value for getValue on " + aID + "!");
+    }
+  } else
+    is(aAcc.value, aValue, "Wrong value for " + aID + "!");
+}
+
+function testStates(aID, aAcc, aState, aExtraState, aAbsentState)
+{
+  var state = {}, extraState = {};
+  aAcc.getFinalState(state, extraState);
+  is(state.value & aState, aState, "wrong state bits for " + aID + "!");
+  is(extraState.value & aExtraState, aExtraState,
+     "wrong extraState bits for " + aID + "!");
+  if (aAbsentState != 0)
+    is(state.value & aAbsentState, 0, "state bits should not be present in ID "
+       + aID + "!");
+  if (state.value & state_readonly)
+    // if state is readonly, ext state must not be ext_state_editable.
+    is(extraState.value & ext_state_editable, 0,
+       "Read-only " + aID + " cannot be editable!");
+}
+
+function testAction(aID, aAcc, aNumActions, aActionName, aActionDescription)
+{
+  var numActions = aAcc.numActions;
+  is(numActions, aNumActions, "Wrong number of actions for " + aID + "!");
+
+  if (numActions != 0) {
+    // Test first action. Normally only 1 should be present.
+    is(aAcc.getActionName(0), aActionName,
+       "Wrong name of action for " + aID + "!");
+    is(aAcc.getActionDescription(0), aActionDescription,
+       "Wrong description of action for " + aID + "!");
+  }
+}
+
+function testThis(aID, aName, aValue, aDescription, aRole, aState,
+                  aExtraState, aAbsentState, aNumActions, aActionName,
+                  aActionDescription)
+{
+  var elem = document.getElementById(aID);
+  var acc = null;
+  try {
+    acc = gAccRetrieval.getAccessibleFor(elem);
+  } catch(e) {}
+  ok(acc, "No accessible for " + aID + "!");
+
+  if (acc) {
+    is(acc.name, aName, "Wrong name for " + aID + "!");
+    testValue(aID, acc, aValue, aRole);
+    is(acc.description, aDescription, "Wrong description for " + aID + "!");
+    is(acc.role, aRole, "Wrong role for " + aID + "!");
+
+    testStates(aID, acc, aState, aExtraState, aAbsentState);
+
+    testAction(aID, acc, aNumActions, aActionName, aActionDescription);
+  }
+}
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_aria_role_article.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=429666
+-->
+<head>
+  <title>Expose ROLE_DOCUMENT for ARIA landmarks that inherit from document chrome tests</title>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript">
+    function doTest()
+    {
+      var accRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
+                       getService(Components.interfaces.nsIAccessibleRetrieval);
+
+      // Test article exposed as document
+      var articleElement = document.getElementById("testArticle");
+      var articleAcc = null;
+      try {
+        articleAcc = accRetrieval.getAccessibleFor(articleElement);
+      } catch(e) { }
+      ok(articleAcc, "no accessible for article!");
+      if (articleAcc) {
+        is(articleAcc.finalRole,
+           Components.interfaces.nsIAccessibleRole.ROLE_DOCUMENT,
+           "Wrong role for article!");
+        is(articleAcc.name, "Test article", "Wrong name for article!");
+      }
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=429666">Mozilla Bug 429666</a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+  <div id="testArticle" role="article" title="Test article">
+    <p>This is a paragraph inside the article.</p>
+  </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_bug429285.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=429285
+-->
+<head>
+  <title>Propagate aria-disabled state to descendants chrome tests</title>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript">
+    // Mapping needed state flags for easier handling.
+    const state_disabled = 
+          Components.interfaces.nsIAccessibleStates.STATE_UNAVAILABLE;
+    const state_focusable = 
+          Components.interfaces.nsIAccessibleStates.STATE_FOCUSABLE;
+
+    const nsIAccessibleRetrieval = Components.interfaces.nsIAccessibleRetrieval;
+    const nsIAccessible = Components.interfaces.nsIAccessible;
+
+    var gAccRetrieval = null;
+
+    function testChildren(aID, aAcc)
+    {
+      // Check state of aAcc first.
+      var state = {}, extraState = {};
+      aAcc.getFinalState(state, extraState);
+      if (state.value & state_focusable) {
+        is(state.value & state_disabled, state_disabled,
+           "Wrong disabled state bit for " + aID + "!");
+      }
+
+      // Iterate over its children to see if they are disabled, too.
+      var children = null;
+      try {
+        children = aAcc.children;
+      } catch(e) {}
+      ok(children, "Could not get children for " + aID +"!");
+
+      if (children) {
+        for (var i=0; i<children.length; i++) {
+          var childAcc = children.queryElementAt(i, nsIAccessible);
+          // Test and recurse over its children as well.
+          testChildren(childAcc.name, childAcc);
+        }
+      }
+    }
+
+    function doTest()
+    {
+      gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
+                      getService(nsIAccessibleRetrieval);
+
+      var groupItem = document.getElementById("group");
+      var groupAcc = null;
+      try {
+        groupAcc = gAccRetrieval.getAccessibleFor(groupItem);
+      } catch (e) {}
+      ok (groupAcc,
+          "No accessible for group element!");
+
+      if (groupAcc) {
+        var state = {}, extraState = {};
+        groupAcc.getFinalState(state, extraState);
+        is(state.value & state_disabled, state_disabled,
+          "Wrong disabled state bit for Group element!");
+        testChildren("group", groupAcc);
+      }
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=429285"
+     title="Propagate aria-disabled to descendants">
+    Mozilla Bug 429285
+  </a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <div id="group" role="group" aria-disabled="true">
+    <button>hi</button>
+    <div tabindex="0" role="listbox" aria-activedescendant="item1">
+      <div role="option" id="item1">Item 1</div>
+      <div role="option" id="item2">Item 2</div>
+      <div role="option" id="item3">Item 3</div>
+      <div role="option" id="item4">Item 4</div>
+    </div>
+    <div role="slider" tabindex="0">A slider</div>
+  </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_cssattrs.html
@@ -0,0 +1,85 @@
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=439566
+-->
+<head>
+  <title>CSS-like attributes tests</title>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript">
+    const nsIAccessibleRetrieval = Components.interfaces.nsIAccessibleRetrieval;
+
+    var gAccRetrieval = null;
+
+    function testAttr(aID, aName, aValue)
+    {
+      var acc = null;
+      try {
+        acc = gAccRetrieval.getAccessibleFor(document.getElementById(aID));
+      } catch(e) { }
+
+      if (!acc) {
+        ok(false, "Can't get accessible object for " + aID);
+        return;
+      }
+
+      var attrs = null;
+      try {
+        attrs = acc.attributes;
+      } catch(e) { }
+
+      if (!attrs) {
+        ok(false, "Can't get accessible attributes for " + aID);
+        return;
+      }
+      
+      is(attrs.getStringProperty(aName), aValue,
+         "Accessible with ID " + aID + " has wrong attribute value");
+    }
+
+    function doTest()
+    {
+      gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
+                      getService(nsIAccessibleRetrieval);
+
+      testAttr("span", "display", "inline");
+      testAttr("div", "display", "block");
+      testAttr("p", "display", "block");
+      testAttr("input", "display", "inline");
+      testAttr("table", "display", "table");
+      testAttr("tr", "display", "table-row");
+      testAttr("td", "display", "table-cell");
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=439566"
+     title="Include the css display property as an IAccessible2 object attribute">
+    Mozilla Bug 439566
+  </a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <span id="span" role="group">It's span</span>
+  <div id="div">It's div</div>
+  <p id="p">It's paragraph"</p>
+  <input id="input"/>
+  <table id="table">
+    <tr id="tr" role="group">
+      <td id="td">td</td>
+    </tr>
+  </table>
+</body>
+</html>
--- a/accessible/tests/mochitest/test_groupattrs.xul
+++ b/accessible/tests/mochitest/test_groupattrs.xul
@@ -16,58 +16,135 @@
 
     function accAttributes(aId)
     {
       this.getAttribute = function getAttribute(aName)
       {
         try {
           return this.mAttrs.getStringProperty(aName);
         } catch (e) {
-          alert(e);
           return "";
         }
       }
 
       this.mAcc = gAccService.getAccessibleFor(document.getElementById(aId));
-      this.mAttrs = this.mAcc.attributes;
+      ok(this.mAcc, "Can't get accessible for " + aId);
+
+      if (this.mAcc)
+        this.mAttrs = this.mAcc.attributes;
+    }
+
+    function testGroupAttrs(aID, aPosInSet, aSetSize, aLevel)
+    {
+      var attrs = new accAttributes(aID);
+      is(attrs.getAttribute("posinset"), aPosInSet, "Wrong posinset on " + aID);
+      is(attrs.getAttribute("setsize"), aSetSize, "Wrong setsize on " + aID);
+      if (aLevel)
+        is(attrs.getAttribute("level"), aLevel, "Wrong level on " + aID);
     }
 
     function doTest()
     {
       // Activate accessibility, otherwise events aren't fired.
       gAccService = Components.classes["@mozilla.org/accessibleRetrieval;1"].
                     getService(Components.interfaces.nsIAccessibleRetrieval);
 
-      var attrs = new accAttributes("item1");
-      is(attrs.getAttribute("posinset"), "1", "Wrong posinset on item1.");
-      is(attrs.getAttribute("setsize"), "2", "Wrong setsize on item1.");
+      //////////////////////////////////////////////////////////////////////////
+      // xul:listbox (bug 417317)
+      testGroupAttrs("item1", "1", "2");
+      testGroupAttrs("item2", "2", "2");
+
+      //////////////////////////////////////////////////////////////////////////
+      // xul:menu (bug 443881)
+      var menu1 = document.getElementById("menu_item1");
+      menu1.open = true;
+
+      window.setTimeout(function() {
+        var menu2 = document.getElementById("menu_item2");
+        menu2.open = true;
 
-      attrs = new accAttributes("item2");
-      is(attrs.getAttribute("posinset"), "2", "Wrong posinset on item2.");
-      is(attrs.getAttribute("setsize"), "2", "Wrong setsize on item2.");
+        window.setTimeout(function() {
+          testGroupAttrs("menu_item1.1", "1", "1");
+          testGroupAttrs("menu_item1.2", "1", "3");
+          testGroupAttrs("menu_item1.4", "2", "3");
+          testGroupAttrs("menu_item2", "3", "3");
+          testGroupAttrs("menu_item2.1", "1", "2", "1");
+          testGroupAttrs("menu_item2.2", "2", "2", "1");
 
-      SimpleTest.finish();
+          SimpleTest.finish();
+        }, 0);
+      }, 0);
+
+      //////////////////////////////////////////////////////////////////////////
+      // ARIA menu (bug 441888)
+      testGroupAttrs("aria-menuitem", "1", "3");
+      testGroupAttrs("aria-menuitemcheckbox", "2", "3");
+      testGroupAttrs("aria-menuitemradio", "3", "3");
+      testGroupAttrs("aria-menuitem2", "1", "1");
     }
 
     SimpleTest.waitForExplicitFinish();
     addLoadEvent(doTest);
   ]]>
   </script>
 
   <body xmlns="http://www.w3.org/1999/xhtml">
     <a target="_blank"
        href="https://bugzilla.mozilla.org/show_bug.cgi?id=417317"
        title="Certain types of LISTITEM accessibles no longer get attributes set like 'x of y', regression from fix for bug 389926">
       Mozilla Bug 417317
-    </a>
+    </a><br/>
+    <a target="_blank"
+       href="https://bugzilla.mozilla.org/show_bug.cgi?id=443881"
+       title="take into account separators in xul menus when group attributes are calculating">
+      Mozilla Bug 443881
+    </a><br/>
+    <a target="_blank"
+       href="https://bugzilla.mozilla.org/show_bug.cgi?id=441888"
+       title="ARIA checked menu items are not included in the total list of menu items">
+      Mozilla Bug 441888
+    </a><br/>
+
     <p id="display"></p>
     <div id="content" style="display: none">
     </div>
     <pre id="test">
     </pre>
   </body>
 
   <listbox>
     <listitem label="item1" id="item1"/>
     <listitem label="item2" id="item2"/>
   </listbox>
+
+  <menubar>
+    <menu label="item1" id="menu_item1">
+      <menupopup>
+        <menuitem label="item1.1" id="menu_item1.1"/>
+        <menuseparator/>
+        <menuitem label="item1.2" id="menu_item1.2"/>
+        <menuitem label="item1.3" hidden="true"/>
+        <menuitem label="item1.4" id="menu_item1.4"/>
+        <menu label="item2" id="menu_item2">
+          <menupopup>
+            <menuitem label="item2.1" id="menu_item2.1"/>
+            <menuitem label="item2.2" id="menu_item2.2"/>
+          </menupopup>
+        </menu>
+      </menupopup>
+    </menu>
+  </menubar>
+
+  <vbox>
+    <description role="menuitem" id="aria-menuitem"
+                 value="conventional menuitem"/>
+    <description role="menuitemcheckbox" id="aria-menuitemcheckbox"
+                 value="conventional checkbox menuitem"/>
+    <description role="menuitem" hidden="true"/>
+    <description role="menuitemradio" id="aria-menuitemradio"
+                 value="conventional radio menuitem"/>
+    <description role="separator"
+                 value="conventional separator"/>
+    <description role="menuitem" id="aria-menuitem2"
+                 value="conventional menuitem"/>
+  </vbox>
 </window>
 
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_nsIAccessibleDocument.html
@@ -0,0 +1,111 @@
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=441737
+-->
+<head>
+  <title>nsIAccessibleDocument chrome tests</title>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript">
+    const nsIAccessibleRetrieval = Components.interfaces.nsIAccessibleRetrieval;
+    const nsIAccessibleRole = Components.interfaces.nsIAccessibleRole;
+    const nsIAccessibleDocument = Components.interfaces.nsIAccessibleDocument;
+    const nsIDOMDocument = Components.interfaces.nsIDOMDocument;
+    const nsIDOMWindow = Components.interfaces.nsIDOMWindow;
+
+    // needed state flag
+    const state_focusable =
+          Components.interfaces.nsIAccessibleStates.STATE_FOCUSABLE;
+    const state_readonly =
+          Components.interfaces.nsIAccessibleStates.STATE_READONLY;
+
+    var gAccRetrieval = null;
+
+    function doTest()
+    {
+      gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
+                      getService(nsIAccessibleRetrieval);
+
+      // Get accessible for body tag.
+      var docAcc = null;
+      try {
+        docAcc = gAccRetrieval.getAccessibleFor(document).
+                 QueryInterface(nsIAccessibleDocument);
+      } catch(e) {}
+      ok(docAcc, "No accessible with interface for document!");
+
+      if (docAcc) {
+        // nsIAccessible
+        is(docAcc.name, "nsIAccessibleDocument chrome tests",
+           "Name for document accessible not correct!");
+        is(docAcc.role, nsIAccessibleRole.ROLE_DOCUMENT,
+           "Wrong role for document!");
+
+        // check if it is focusable, read-only.
+        var state = {}, extraState = {}
+        docAcc.getFinalState(state, extraState);
+        var desiredStates = (state_focusable | state_readonly);
+        is(state.value & desiredStates, desiredStates,
+           "Wrong state bits for document!");
+
+        // No actions wanted on doc
+        is(docAcc.numActions, 0, "Wrong number of actions for document!");
+
+        // attributes should contain tag:body
+        attributes = docAcc.attributes;
+        is(attributes.getStringProperty("tag"), "BODY",
+           "Wrong attribute on document!");
+
+        // nsIAccessibleDocument
+        is(docAcc.URL, "chrome://mochikit/content/a11y/accessible/test_nsIAccessibleDocument.html",
+           "Wrong URL for document!");
+        is(docAcc.title, "nsIAccessibleDocument chrome tests",        
+           "Wrong title for document!");
+        is(docAcc.mimeType, "text/html",
+           "Wrong mime type for document!");
+        // nsDocAccessible::getDocType currently returns NS_ERROR_FAILURE.
+        // See bug 442005. After fixing, please remove this comment and
+        // uncomment the below two lines to enable the test.
+//        is(docAcc.docType, "HTML",
+//           "Wrong type of document!");
+
+        // Test for correct nsIDOMDocument retrieval.
+        var domDoc = null;
+        try {
+          domDoc = docAcc.document.QueryInterface(nsIDOMDocument);
+        } catch(e) {}
+        ok(domDoc, "no nsIDOMDocument for this doc accessible!");
+        is(domDoc, document, "Document nodes do not match!");
+
+        // Test for correct nsIDOMWindow retrieval.
+        var domWindow = null;
+        try {
+          domWindow = docAcc.window.QueryInterface(nsIDOMWindow);
+        } catch(e) {}
+        ok(domWindow, "no nsIDOMWindow for this doc accessible!");
+        is(domWindow, window, "Window nodes do not match!");
+      }
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=441737"
+     title="nsAccessibleDocument chrome tests">
+    Mozilla Bug 441737
+  </a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+</body>
+</html>
--- a/accessible/tests/mochitest/test_nsIAccessibleHyperLink.html
+++ b/accessible/tests/mochitest/test_nsIAccessibleHyperLink.html
@@ -6,16 +6,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <head>
   <title>nsIHyperLinkAccessible chrome tests</title>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript">
+    var gAccRetrieval = null;
+
     function testThis(aID, aAcc, aRole, aAnchors, aName, aValid, aStartIndex,
                       aEndIndex)
     {
       is(aAcc.finalRole, aRole, "Wrong role for ID " + aID + "!");
       is(aAcc.anchorCount, aAnchors, "Wrong number of anchors for ID "
                                       + aID + "!");
       is(aAcc.getAnchor(0).name, aName, "Wrong name for ID "
                                         + aID + "!");
@@ -31,28 +33,56 @@ https://bugzilla.mozilla.org/show_bug.cg
     {
       is(aAcc.selected, aSelectedBefore,
          "Wrong selected state before focus for ID " + aID + "!");
       document.getElementById(aID).focus();
       is(aAcc.selected, aSelectedAfter,
          "Wrong seleccted state after focus for ID " + aID + "!");
     }
 
-    function testStates(aID, aAcc, aState, aExtraState, aAbsentState)
+    function testStates(aID, aAcc, aState, aExtraState, aAbsentState,
+                        aShowStateDebugFlag)
     {
       var state = {}, extraState = {};
       aAcc.getFinalState(state, extraState);
+
+      if (aShowStateDebugFlag) {
+        var list = gAccRetrieval.getStringStates(state.value, 0);
+
+        var str = "";
+        for (var i = 0; i < list.length; i++)
+          str += list.item(i) + "\n";
+
+        alert(str);
+      }
+
       is(state.value & aState, aState, "Wrong state bits for ID " + aID + "!");
       is(extraState.value & aExtraState, aExtraState, 
          "Wrong extra state bits for ID " + aID + "!");
       if (aAbsentState != 0)
         is(state.value & aAbsentState, 0, "state bits should not be present in ID "
            + aID + "!");
     }
-      
+
+    function testAction(aId, aAcc, aActionName)
+    {
+      var numActions = aActionName ? 1 : 0;
+      is(aAcc.numActions, numActions,
+         "Wrong actions number for ID " + aId);
+      try {
+        is(aAcc.getActionName(0), aActionName,
+           "Wrong action name for ID " + aId);
+      } catch (e) {
+        if (numActions)
+          ok(false, "Exception on action name getting for ID " + aId);
+        else
+          ok(true, "Correct action name for ID " + aId);
+      }
+    }
+
     function doTest()
     {
       // Mapping needed state flags for easier handling.
       const state_focusable = 
             Components.interfaces.nsIAccessibleStates.STATE_FOCUSABLE;
       const state_focused = 
             Components.interfaces.nsIAccessibleStates.STATE_FOCUSED;
       const state_selectable = 
@@ -66,25 +96,25 @@ https://bugzilla.mozilla.org/show_bug.cg
             Components.interfaces.nsIAccessibleStates.EXT_STATE_MULTI_LINE;
       const ext_state_horizontal = 
             Components.interfaces.nsIAccessibleStates.EXT_STATE_HORIZONTAL;
       const ext_state_required = 
             Components.interfaces.nsIAccessibleStates.STATE_REQUIRED;
       const ext_state_invalid = 
             Components.interfaces.nsIAccessibleStates.STATE_INVALID;
 
-      var accService = Components.classes["@mozilla.org/accessibleRetrieval;1"].
-                       getService(Components.interfaces.nsIAccessibleRetrieval);
+      gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
+                      getService(Components.interfaces.nsIAccessibleRetrieval);
 
       //////////////////////////////////////////////////////////////////////////
       // normal hyperlink
       var normalHyperlinkElement = document.getElementById("NormalHyperlink");
       var normalHyperlinkAcc;
       try {
-        normalHyperlinkAcc = accService.getAccessibleFor(normalHyperlinkElement).
+        normalHyperlinkAcc = gAccRetrieval.getAccessibleFor(normalHyperlinkElement).
               QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
       } catch(e) {
         ok(normalHyperlinkAcc, "no interface for normal hyperlink!");
       }
       testThis("NormalHyperlink", normalHyperlinkAcc,
                Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1, 
                "Mozilla Foundation", true, 18, 19);
       is(normalHyperlinkAcc.getURI(0).spec, "http://www.mozilla.org/", 
@@ -97,40 +127,41 @@ https://bugzilla.mozilla.org/show_bug.cg
                  (state_focusable | state_focused | state_linked),
                  (ext_state_horizontal), (0));
 
       //////////////////////////////////////////////////////////////////////////
       // ARIA hyperlink
       var ariaHyperlinkElement = document.getElementById("AriaHyperlink");
       var ariaHyperlinkAcc;
       try {
-        ariaHyperlinkAcc = accService.getAccessibleFor(ariaHyperlinkElement).
+        ariaHyperlinkAcc = gAccRetrieval.getAccessibleFor(ariaHyperlinkElement).
             QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
       } catch(e) {
         ok(ariaHyperlinkAcc, "no interface for ARIA Hyperlink!");
       }
       testThis("AriaHyperlink", ariaHyperlinkAcc,
                Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1,
                "Mozilla Foundation Home", true, 32, 33);
       testStates("AriaHyperlink", ariaHyperlinkAcc,
                  (state_focusable | state_linked),
                  (ext_state_horizontal), (0));
       testFocus("AriaHyperlink", ariaHyperlinkAcc, false, true);
       testStates("AriaHyperlink", ariaHyperlinkAcc,
                  (state_focusable | state_focused | state_linked),
                  (ext_state_horizontal), (0));
+      testAction("AriaHyperlink", ariaHyperlinkAcc, "click");
 
       //////////////////////////////////////////////////////////////////////////
       // ARIA hyperlink with status invalid
       var invalidAriaHyperlinkElement =
           document.getElementById("InvalidAriaHyperlink");
       var invalidAriaHyperlinkAcc;
       try {
         invalidAriaHyperlinkAcc =
-               accService.getAccessibleFor(invalidAriaHyperlinkElement).
+               gAccRetrieval.getAccessibleFor(invalidAriaHyperlinkElement).
                QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
       } catch(e) {
         ok(invalidAriaHyperlinkAcc, "no interface for invalid ARIA hyperlink!");
       }
       is(invalidAriaHyperlinkAcc.valid, false, "Should not be valid!");
       testStates("InvalidAriaHyperlink", invalidAriaHyperlinkAcc,
                  (state_linked),
                  (ext_state_horizontal), (state_focusable));
@@ -139,17 +170,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 
       //////////////////////////////////////////////////////////////////////////
       // image map and its link children
       var imageMapHyperlinkElement =
           document.getElementById("imgmap");
       var imageMapHyperlinkAcc;
       try {
         imageMapHyperlinkAcc =
-             accService.getAccessibleFor(imageMapHyperlinkElement).
+             gAccRetrieval.getAccessibleFor(imageMapHyperlinkElement).
               QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
       } catch(e) {
         ok(imageMapHyperlinkAcc, "no Image Map interface!");
       }
       testThis("imgmap", imageMapHyperlinkAcc,
                Components.interfaces.nsIAccessibleRole.ROLE_IMAGE_MAP, 2, 
                "b", true, 83, 84);
       is(imageMapHyperlinkAcc.getURI(0).spec,
@@ -197,83 +228,212 @@ https://bugzilla.mozilla.org/show_bug.cg
                  (0), (0));
 
       //////////////////////////////////////////////////////////////////////////
       // empty hyperlink
       var emptyLinkElement = document.getElementById("emptyLink");
       var EmptyHLAcc;
       try {
         EmptyHLAcc =
-             accService.getAccessibleFor(emptyLinkElement).
+             gAccRetrieval.getAccessibleFor(emptyLinkElement).
              QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
       } catch (e) {
         ok(EmptyHLAcc, "no interface for empty link!");
       }
       testThis("emptyLink", EmptyHLAcc,
                Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1,
-               "", true, 98, 99);
+               null, true, 98, 99);
       testStates("emptyLink", EmptyHLAcc,
                  (state_focusable | state_linked),
                  (ext_state_horizontal), (0));
+      testAction("emptyLink", EmptyHLAcc, "jump");
 
       //////////////////////////////////////////////////////////////////////////
       // normal hyperlink with embedded span
       var hyperlinkElementWithSpan = document.getElementById("LinkWithSpan");
       var hyperlinkWithSpanAcc;
       try {
         hyperlinkWithSpanAcc =
-              accService.getAccessibleFor(hyperlinkElementWithSpan).
+              gAccRetrieval.getAccessibleFor(hyperlinkElementWithSpan).
               QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
       } catch(e) {
         ok(hyperlinkWithSpanAcc, "no interface for hyperlink with span!");
       }
       testThis("LinkWithSpan", hyperlinkWithSpanAcc,
                Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1, 
                "Heise Online", true, 124, 125);
       is(hyperlinkWithSpanAcc.getURI(0).spec, "http://www.heise.de/", 
          "URI wrong for hyperlinkElementWithSpan!");
       testStates("LinkWithSpan", hyperlinkWithSpanAcc,
                  (state_focusable | state_linked),
                  (ext_state_horizontal), (0));
       testFocus("LinkWithSpan", hyperlinkWithSpanAcc, false, true);
       testStates("LinkWithSpan", hyperlinkWithSpanAcc,
                  (state_focusable | state_focused | state_linked),
                  (ext_state_horizontal), (0));
+      testAction("LinkWithSpan", hyperlinkWithSpanAcc, "jump");
 
       //////////////////////////////////////////////////////////////////////////
       // Named anchor, should never have state_linked
       var namedAnchorElement = document.getElementById("namedAnchor");
       var namedAnchorAcc;
       try {
-        namedAnchorAcc = accService.getAccessibleFor(namedAnchorElement).
+        namedAnchorAcc = gAccRetrieval.getAccessibleFor(namedAnchorElement).
               QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
       } catch(e) {
         ok(namedAnchorAcc, "no interface for named anchor!");
       }
       testThis("namedAnchor", namedAnchorAcc,
                Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1, 
                "This should never be of state_linked", true, 202, 203);
       testStates("namedAnchor", namedAnchorAcc,
                  (state_selectable),
                  (ext_state_horizontal), (state_focusable | state_linked));
+      testAction("namedAnchor", namedAnchorAcc, "");
 
+      //////////////////////////////////////////////////////////////////////////
+      // No link (hasn't any attribute), should never have state_linked
+      var noLinkElement = document.getElementById("noLink");
+      var noLinkAcc;
+      try {
+        noLinkAcc = gAccRetrieval.getAccessibleFor(noLinkElement).
+              QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
+      } catch(e) {
+        ok(noLinkAcc, "no interface for named anchor!");
+      }
+      testThis("noLink", noLinkAcc,
+               Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1, 
+               "This should never be of state_linked", true, 262, 263);
+      testStates("noLink", noLinkAcc,
+                 0,
+                 (ext_state_horizontal), (state_focusable | state_linked));
+      testAction("noLink", noLinkAcc, "");
+
+      //////////////////////////////////////////////////////////////////////////
+      // Link with registered 'click' event, should have state_linked
+      var linkWithClickElement = document.getElementById("linkWithClick");
+      var linkWithClickAcc;
+      try {
+        linkWithClickAcc = gAccRetrieval.getAccessibleFor(linkWithClickElement).
+              QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
+      } catch(e) {
+        ok(linkWithClickAcc, "no interface for named anchor!");
+      }
+      testThis("linkWithClick", linkWithClickAcc,
+               Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1, 
+               "This should have state_linked", true, 301, 302);
+      testStates("linkWithClick", linkWithClickAcc,
+                 (state_linked),
+                 (ext_state_horizontal), 0);
+      testAction("linkWithClick", linkWithClickAcc, "click");
+
+      //////////////////////////////////////////////////////////////////////////
+      // Maps to group links (bug 431615).
+      var linksMapElement = document.getElementById("linksmap");
+      var linksMapAcc;
+      try {
+        linksMapAcc = gAccRetrieval.getAccessibleFor(linksMapElement);
+      } catch(e) { }
+
+      ok(linksMapAcc, "no accessible for map grouping links!");
+
+      //////////////////////////////////////////////////////////////////////////
+      // Link with title attribute, no name from the subtree (bug 438325).
+      var id = "linkWithTitleNoNameFromSubtree";
+      var linkElement = document.getElementById(id);
+      var linkAcc;
+      try {
+        linkAcc = gAccRetrieval.getAccessibleFor(linkElement).
+              QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
+      } catch(e) {
+        ok(linkAcc, "no interface for link with ID " + id + "!");
+      }
+      testThis(id, linkAcc,
+               Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1, 
+               "Link with title", true, 354, 355);
+      testStates(id, linkAcc,
+                 (state_linked),
+                 (ext_state_horizontal), 0);
+      testAction(id, linkAcc, "jump");
+
+      //////////////////////////////////////////////////////////////////////////
+      // Link with title attribute, name from the subtree - onsreen name
+      // (bug 438325).
+      id = "linkWithTitleNameFromSubtree";
+      linkElement = document.getElementById(id);
+      linkAcc;
+      try {
+        linkAcc = gAccRetrieval.getAccessibleFor(linkElement).
+              QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
+      } catch(e) {
+        ok(linkAcc, "no interface for link with ID " + id + "!");
+      }
+      testThis(id, linkAcc,
+               Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1, 
+               "the name from subtree", true, 403, 404);
+      testStates(id, linkAcc,
+                 (state_linked),
+                 (ext_state_horizontal), 0);
+      testAction(id, linkAcc, "jump");
+
+      //////////////////////////////////////////////////////////////////////////
+      // Link with title attribute, name from the nested html:img (bug 438325).
+      id = "linkWithTitleNameFromImg";
+      linkElement = document.getElementById(id);
+      linkAcc;
+      try {
+        linkAcc = gAccRetrieval.getAccessibleFor(linkElement).
+              QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
+      } catch(e) {
+        ok(linkAcc, "no interface for link with ID " + id + "!");
+      }
+      testThis(id, linkAcc,
+               Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1, 
+               "The title for link", true, 458, 459);
+      testStates(id, linkAcc,
+                 (state_linked),
+                 (ext_state_horizontal), 0);
+      testAction(id, linkAcc, "jump");
+
+      //////////////////////////////////////////////////////////////////////////
+      // Link with label, no name from the subtree (bug 438325).
+      id = "linkWithLabelNoNameFromSubtree";
+      linkElement = document.getElementById(id);
+      linkAcc;
+      try {
+        linkAcc = gAccRetrieval.getAccessibleFor(linkElement).
+              QueryInterface(Components.interfaces.nsIAccessibleHyperLink);
+      } catch(e) {
+        ok(linkAcc, "no interface for link with ID " + id + "!");
+      }
+      testThis(id, linkAcc,
+               Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1, 
+               "Link with label and nested image:", true, 462, 463);
+      testStates(id, linkAcc,
+                 (state_linked),
+                 (ext_state_horizontal), 0);
+      testAction(id, linkAcc, "jump");
+
+      //////////////////////////////////////////////////////////////////////////
+      //
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addLoadEvent(doTest);
   </script>
 </head>
 <body>
 
   <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=418368">Mozilla Bug 418368</a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
+
   <br>Simple link:<br>
   <a id="NormalHyperlink" href="http://www.mozilla.org">Mozilla Foundation</a>
   <br>ARIA link:<br>
   <span id="AriaHyperlink" role="link"
          onclick="window.open('http://www.mozilla.org/');"
          tabindex="0">Mozilla Foundation Home</span>
   <br>Invalid, non-focusable hyperlink:<br>
   <span id="InvalidAriaHyperlink" role="link" aria-invalid="true"
@@ -288,16 +448,51 @@ https://bugzilla.mozilla.org/show_bug.cg
           coords="0,0,13,14"
           alt="a"
           shape="rect"></area>
   </map>
   <img width="447" id="imgmap"
        height="15"
        usemap="#atoz_map"
        src="http://www.bbc.co.uk/radio4/images/letters.gif"></img>
+
   <br>Empty link:<br>
   <a id="emptyLink" href=""><img src=""></img></a>
+
   <br>Link with embedded span<br>
   <a id="LinkWithSpan" href="http://www.heise.de/"><span lang="de">Heise Online</span></a>
+
   <br>Named anchor, must not have "linked" state for it to be exposed correctly:<br>
   <a id="namedAnchor" name="named_anchor">This should never be of state_linked</a>
+
+  <br>Link having no attributes, must not have "linked" state:</br>
+  <a id="noLink">This should never be of state_linked</a>
+
+  <br>Link with registered 'click' event: </br>
+  <a id="linkWithClick" onclick="var clicked = true;">This should have state_linked</a>
+
+  <br>Link with title attribute (no name from subtree): </br>
+  <a id="linkWithTitleNoNameFromSubtree" href="http://www.heise.de/"
+     title="Link with title"><img src=""/></a>
+
+  <br>Link with title attribute (name from subtree): </br>
+  <a id="linkWithTitleNameFromSubtree" href="http://www.heise.de/"
+     title="Link with title">the name from subtree</a>
+
+  <br>Link with title attribute (name from nested image): </br>
+  <a id="linkWithTitleNameFromImg" href="http://www.heise.de/"
+     title="Link with title"><img src="" alt="The title for link"/></a>
+
+  <br><label for="linkWithLabelNoNameFromSubtree">Link with label and nested image: </label></br>
+  <a id="linkWithLabelNoNameFromSubtree"
+     href="http://www.heise.de/"><img src=""/></a>
+
+  <br>Map that is used to group links (www.w3.org/TR/WCAG10-HTML-TECHS/#group-bypass),
+   also see the bug 431615:<br>
+  <map id="linksmap" title="Site navigation">
+    <ul>
+      <li><a href="http://mozilla.org">About the project</a></li>
+      <li><a href="http://mozilla.org">Sites and sounds</a></li>
+    </ul>
+  </map>
+
 </body>
 </html>
--- a/accessible/tests/mochitest/test_nsIAccessibleImage.html
+++ b/accessible/tests/mochitest/test_nsIAccessibleImage.html
@@ -12,65 +12,100 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   <script type="application/javascript">
     const nsIAccessibleImage = Components.interfaces.nsIAccessibleImage;
     const nsIAccessibleCoordinateType = 
           Components.interfaces.nsIAccessibleCoordinateType;
 
     var gAccRetrieval;
 
-    function testCords(aID, aImageAcc, aCordType, aXCoordinate, aYCoordinate,
-                       aCoordTypeString)
+    function testCoordinates(aID, aAcc, aWidth, aHeight)
     {
-      var x = {}, y = {};
-      aImageAcc.getImagePosition(aCordType, x, y);
-      is(x.value, aXCoordinate,
-         "Wrong " + aCoordTypeString + " x offset for " + aID + "!");
-      is(y.value, aYCoordinate,
-         "Wrong " + aCoordTypeString + " y offset for " + aID + "!");
-    }
+      var screenX = {}, screenY = {}, windowX = {}, windowY = {}, parentX = {},
+          parentY = {};
 
-    function testCoordinates(aID, aAcc, aXCoordinates, aYCoordinates, aWidth,
-                             aHeight)
-    {
-      var imageAcc;
+      var imageAcc = null;
       try {
         imageAcc = aAcc.QueryInterface(nsIAccessibleImage);
       } catch(e) {}
       ok(imageAcc, "no image interface for " + aID + "!");
 
-      testCords(aID, imageAcc,
-                nsIAccessibleCoordinateType.COORDTYPE_SCREEN_RELATIVE,
-                aXCoordinates[0], aYCoordinates[0], "screen");
-      testCords(aID, imageAcc,
-                nsIAccessibleCoordinateType.COORDTYPE_WINDOW_RELATIVE,
-                aXCoordinates[1], aYCoordinates[1], "window");
-      testCords(aID, imageAcc,
-                nsIAccessibleCoordinateType.COORDTYPE_PARENT_RELATIVE,
-                aXCoordinates[2], aYCoordinates[2], "parent");
+      if (!imageAcc)
+        return;
+
+      // get screen coordinates.
+      imageAcc.getImagePosition(
+               nsIAccessibleCoordinateType.COORDTYPE_SCREEN_RELATIVE,
+               screenX, screenY);
+      // get window coordinates.
+      imageAcc.getImagePosition(
+               nsIAccessibleCoordinateType.COORDTYPE_WINDOW_RELATIVE,
+               windowX, windowY);
+      // get parent related coordinates.
+      imageAcc.getImagePosition(
+               nsIAccessibleCoordinateType.COORDTYPE_PARENT_RELATIVE,
+               parentX, parentY);
+      // XXX For linked images, a negative parentY value is returned, and the
+      // screenY coordinate is the link's screenY coordinate minus 1.
+      // Until this is fixed, set parentY to -1 if it's negative.
+      if (parentY.value < 0) {
+        parentY.value = -1;
+      }
+
+      // See if asking image for child at image's screen coordinates gives
+      // correct accessible. getChildAtPoint operates on screen coordinates.
+      var tempAcc = null;
+      try {
+        tempAcc = imageAcc.getChildAtPoint(screenX.value, screenY.value);
+      } catch(e) {}
+      is(tempAcc, imageAcc,
+         "Wrong accessible returned for position of " + aID + "!");
+
+      // get image's parent.
+      var imageParentAcc = null;
+      try {
+        imageParentAcc = imageAcc.parent;
+      } catch(e) {}
+      ok(imageParentAcc, "no parent accessible for " + aID + "!");
+
+      if (imageParentAcc) {
+        // See if parent's screen coordinates plus image's parent relative
+        // coordinates equal to image's screen coordinates.
+        var parentAccX = {}, parentAccY = {}, parentAccWidth = {},
+            parentAccHeight = {};
+        imageParentAcc.getBounds(parentAccX, parentAccY, parentAccWidth,
+                                 parentAccHeight);
+        is(parentAccX.value + parentX.value, screenX.value,
+           "Wrong screen x coordinate for " + aID + "!");
+        is(parentAccY.value + parentY.value, screenY.value,
+           "Wrong screen y coordinate for " + aID + "!");
+      }
 
       var width = {}, height = {};
       imageAcc.getImageSize(width, height);
       is(width.value, aWidth, "Wrong width for " + aID + "!");
       is(height.value, aHeight, "wrong height for " + aID + "!");
     }
 
-    function testThis(aID, aName, aSRC, aXCoordinates, aYCoordinates, aWidth,
-                      aHeight)
+    function testThis(aID, aName, aSRC, aWidth, aHeight)
     {
       var elem = document.getElementById(aID);
       var acc;
       try {
         acc = gAccRetrieval.getAccessibleFor(elem);
       } catch(e) {}
       ok(acc, "No accessible for " + aID + "!");
+
+      if (!acc)
+        return;
+
       is(acc.name, aName, "wrong name for " + aID + "!");
 
       // test coordinates and size
-      testCoordinates(aID, acc, aXCoordinates, aYCoordinates, aWidth, aHeight);
+      testCoordinates(aID, acc, aWidth, aHeight);
 
       // bug 429659: Make sure the SRC attribute is set for any image
       var attributes;
       try {
         attributes = acc.attributes;
       } catch(e) {}
       ok(attributes, "no attributes on " + aID + "!");
       is(attributes.getStringProperty("src"), aSRC,
@@ -78,64 +113,44 @@ https://bugzilla.mozilla.org/show_bug.cg
     }
 
     function doTest()
     {
       gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
                        getService(Components.interfaces.nsIAccessibleRetrieval);
 
       // Test non-linked image
-      var xCords = [16, 12, 8];
-      var yCords = [227, 223, 113];
-      testThis("nonLinkedImage", null, "moz.png", xCords, yCords, 89, 38);
+      testThis("nonLinkedImage", null, "moz.png", 89, 38);
 
       // Test linked image
-      xCords = [16, 12, 0];
-      yCords = [289, 285, -27];
-      testThis("linkedImage", null, "moz.png", xCords, yCords, 93, 42);
+      testThis("linkedImage", null, "moz.png", 93, 42);
 
       // Test non-linked image with alt attribute
-      xCords = [16, 12, 8];
-      yCords = [356, 352, 242];
-      testThis("nonLinkedImageWithAlt", "MoFo", "moz.png", xCords, yCords, 89, 38);
+      testThis("nonLinkedImageWithAlt", "MoFo", "moz.png", 89, 38);
 
       // Test linked image with alt attribute
-      xCords = [16, 12, 0];
-      yCords = [418, 414, -27];
-      testThis("linkedImageWithAlt", "MoFo link", "moz.png", xCords, yCords, 93, 42);
+      testThis("linkedImageWithAlt", "MoFo link", "moz.png", 93, 42);
 
       // Test non-linked image with title attribute
-      xCords = [16, 12, 8];
-      yCords = [485, 481, 371];
-      testThis("nonLinkedImageWithTitle", "MoFo logo", "moz.png", xCords, yCords, 89, 38);
+      testThis("nonLinkedImageWithTitle", "MoFo logo", "moz.png", 89, 38);
 
       // Test linked image with title attribute
-      xCords = [16, 12, 0];
-      yCords = [547, 543, -27];
-      testThis("linkedImageWithTitle", "Link to MoFo", "moz.png", xCords, yCords, 93, 42);
+      testThis("linkedImageWithTitle", "Link to MoFo", "moz.png", 93, 42);
 
       // Test simple image with empty alt attribute
-      xCords = [16, 12, 8];
-      yCords = [614, 610, 500];
-      testThis("nonLinkedImageEmptyAlt", "", "moz.png", xCords, yCords, 89, 38);
+      testThis("nonLinkedImageEmptyAlt", "", "moz.png", 89, 38);
 
       // Test linked image with empty alt attribute
-      xCords = [16, 12, 0];
-      yCords = [676, 672, -27];
-      testThis("linkedImageEmptyAlt", "", "moz.png", xCords, yCords, 93, 42);
+      testThis("linkedImageEmptyAlt", "", "moz.png", 93, 42);
 
       // Test simple image with empty alt attribute and title
-      xCords = [16, 12, 8];
-      yCords = [743, 739, 629];
-      testThis("nonLinkedImageEmptyAltAndTitle", "MozillaFoundation", "moz.png", xCords, yCords, 89, 38);
+      testThis("nonLinkedImageEmptyAltAndTitle", "MozillaFoundation", "moz.png", 89, 38);
 
       // Test linked image with empty alt attribute and title
-      xCords = [16, 12, 0];
-      yCords = [805, 801, -27];
-      testThis("linkedImageEmptyAltAndTitle", "Link to Mozilla Foundation", "moz.png", xCords, yCords, 93, 42);
+      testThis("linkedImageEmptyAltAndTitle", "Link to Mozilla Foundation", "moz.png", 93, 42);
 
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addLoadEvent(doTest);
   </script>
 </head>
--- a/accessible/tests/mochitest/test_nsIAccessibleTable_4.html
+++ b/accessible/tests/mochitest/test_nsIAccessibleTable_4.html
@@ -95,16 +95,36 @@ function doTest()
     is(accTable4.role, Ci.nsIAccessibleRole.ROLE_TABLE, "wrong role");
 
     is(accTable4.cellRefAt(0,0).firstChild.name, "cell0", "wrong cell");
     is(accTable4.cellRefAt(0,1).firstChild.name, "cell1", "wrong cell");
     is(accTable4.cellRefAt(1,0).firstChild.name, "cell2", "wrong cell");
     is(accTable4.cellRefAt(1,1).firstChild.name, "cell3", "wrong cell");
   }
 
+  // Test table with display:inline and an outside table. We shouldn't be fooled
+  // by the outside table and shouldn't create table accessible and table cell
+  // accessible in this case
+  var table5 = document.getElementById("table5");
+  accNotCreated = false;
+  try {
+    var accTable1 = accService.getAccessibleFor(table1);
+  } catch (e) {
+    accNotCreated = true;
+  }
+  ok(accNotCreated, "wrongly created table accessible");
+  var t5Cell = document.getElementById("t5_cell");
+  accNotCreated = false;
+  try {
+    var accCell = accService.getAccessibleFor(t5Cell);
+  } catch (e) {
+    accNotCreated = true;
+  }
+  ok(accNotCreated, "wrongly created table cell accessible");
+
   SimpleTest.finish();
 }
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(doTest);
   </script>
  </head>
 
  <body >
@@ -145,11 +165,23 @@ addLoadEvent(doTest);
      <td>cell0</td>
      <td>cell1</td>
     </tr>
     <tr>
      <td>cell2</td>
      <td>cell3</td>
     </tr>
    </table>
+
+   <table>
+   <tr>
+   <td style="display:block">
+     <table style="display:inline" id="table5">
+       <tr><td id="t5_cell">cell0</td></tr>
+     </table>
+   </td>
+   <td>cell1</td>
+   </tr>
+   </table>
+
   </center>
  </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_nsIAccessible_name.html
@@ -0,0 +1,273 @@
+<html>
+
+<head>
+  <title>nsIAccessible::name calculation</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">
+    const nsIAccessibleRetrieval = Components.interfaces.nsIAccessibleRetrieval;
+    const nsIAccessibleRole = Components.interfaces.nsIAccessibleRole;
+
+    var gAccRetrieval = null;
+
+    function testName(aID, aName)
+    {
+      var elm = document.getElementById(aID);
+      if (!elm) {
+        ok(false, "There is no element with ID " + aID);
+        return;
+      }
+
+      var acc = null;
+      try {
+        acc = gAccRetrieval.getAccessibleFor(elm);
+      } catch(e) {
+      }
+
+      if (!acc) {
+        ok(false, "There is no accessible for " + aID);
+        return;
+      }
+
+      is(acc.name, aName, "Wrong name of the accessible for " + aID);
+    }
+
+    function doTest()
+    {
+      gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
+                      getService(nsIAccessibleRetrieval);
+
+
+      //////////////////////////////////////////////////////////////////////////
+      // aria-labelledby
+      
+      // Single relation. The value of 'aria-labelledby' contains the ID of
+      // an element. Gets the name from text node of that element.
+      testName("btn_labelledby_text", "text");
+
+      // Multiple relations. The value of 'aria-labelledby' contains the IDs
+      // of elements. Gets the name from text nodes of those elements.
+      testName("btn_labelledby_texts", "text1 text2");
+
+
+      //////////////////////////////////////////////////////////////////////////
+      // Name from subtree (single relation labelled_by).
+      
+      // Gets the name from text nodes contained by nested elements
+      testName("btn_labelledby_mixed", "nomore text");
+
+      // Gets the name from text nodes contained by nested elements, ignores
+      // hidden elements (bug 443081).
+      testName("btn_labelledby_mixed_hidden_child", "nomore text2");
+
+      // Gets the name from hidden text nodes contained by nested elements, 
+      // (label element is hidden entirely), (bug 443081).
+      testName("btn_labelledby_mixed_hidden", "lala more hidden text");
+
+      // Gets the name from text nodes contained by nested elements having block
+      // representation (every text node value in the name should be devided by
+      // spaces)
+      testName("btn_labelledby_mixed_block", "text more text");
+
+      // Gets the name from text nodes contained by html:td (every text node
+      // value in the name should be devided by spaces).
+      // XXX: this case is rather a feature than strong wanted behaviour.
+      testName("btn_labelledby_mixed_table", "text space text");
+
+      // Gets the name from image accessible.
+      testName("btn_labelledby_mixed_img", "text image");
+
+      // Gets the name from input accessibles
+      // Note: if input have label elements then the name isn't calculated
+      // from them.
+      testName("btn_labelledby_mixed_input",
+               "input button Submit Query Reset input image");
+
+      // Gets the name from the title of object element.
+      testName("btn_labelledby_mixed_object", "object");
+
+      // Gets the name from text nodes. Element br adds space between them.
+      testName("btn_labelledby_mixed_br", "text text");
+
+
+      //////////////////////////////////////////////////////////////////////////
+      // label element
+
+      // The label element contains the button. The name is calculated from
+      // this button.
+      // Note: the name contains the content of the button.
+      testName("btn_label_inside", "text10text");
+
+      // The label element and the button are placed in the same form. Gets
+      // the name from the label subtree.
+      testName("btn_label_inform", "in form");
+
+      // The label element is placed outside of form where the button is.
+      // Do not take into account the label.
+      testName("btn_label_outform", "12");
+
+      // The label element and the button are in the same document. Gets the
+      // name from the label subtree.
+      testName("btn_label_indocument", "in document");
+
+
+      //////////////////////////////////////////////////////////////////////////
+      // name from children
+
+      // ARIA role button is presented allowing the name calculation from
+      // children.
+      testName("btn_children", "14");
+
+      // ARIA role option is presented allowing the name calculation from
+      // visible children (bug 443081).
+      testName("lb_opt1_children_hidden", "i am visible");
+
+
+      //////////////////////////////////////////////////////////////////////////
+      // title attribute
+
+      // If nothing is left. Let's try title attribute.
+      testName("btn_title", "title");
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addLoadEvent(doTest);
+  </script>
+
+</head>
+
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=444279"
+     title="mochitest for accessible name calculating">
+    Mozilla Bug 444279
+  </a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <!-- aria-labelledby, single relation -->
+  <span id="labelledby_text">text</span>
+  <button id="btn_labelledby_text"
+          aria-labelledby="labelledby_text">1</button>
+  <br/>
+
+  <!-- aria-labelledby, multiple relations -->
+  <span id="labelledby_text1">text1</span>
+  <span id="labelledby_text2">text2</span>
+  <button id="btn_labelledby_texts"
+          aria-labelledby="labelledby_text1 labelledby_text2">2</button>
+  <br/>
+
+  <!-- the name from subtree, mixed content -->
+  <span id="labelledby_mixed">no<span>more text</span></span>
+  <button id="btn_labelledby_mixed"
+          aria-labelledby="labelledby_mixed">3</button>
+  <br/>
+
+  <!-- the name from subtree, mixed/hidden content -->
+  <span id="labelledby_mixed_hidden_child">
+    no<span>more 
+      <span style="display: none;">hidden</span>
+      text2
+      <span style="visibility: hidden">hidden2</span>
+    </span>
+  </span>
+  <button id="btn_labelledby_mixed_hidden_child"
+          aria-labelledby="labelledby_mixed_hidden_child">3.1</button>
+  <br/>
+
+  <!-- the name from subtree, mixed/completely hidden content -->
+  <span id="labelledby_mixed_hidden"
+        style="display: none;">lala <span>more hidden </span>text</span></span>
+  <button id="btn_labelledby_mixed_hidden"
+          aria-labelledby="labelledby_mixed_hidden">3.2</button>
+  <br/>
+
+  <!-- the name from subtree, mixed content, block structure -->
+  <div id="labelledby_mixed_block"><div>text</div>more text</div></div>
+  <button id="btn_labelledby_mixed_block"
+          aria-labelledby="labelledby_mixed_block">4</button>
+  <br/>
+
+  <!-- the name from subtree, mixed content, table structure -->
+  <table><tr>
+    <td id="labelledby_mixed_table">text<span>space</span>text</td>
+  </tr></table>
+  <button id="btn_labelledby_mixed_table"
+          aria-labelledby="labelledby_mixed_table">5</button>
+  <br/>
+
+  <!-- the name from subtree, child img -->
+  <span id="labelledby_mixed_img">text<img alt="image"/></span>
+  <button id="btn_labelledby_mixed_img"
+          aria-labelledby="labelledby_mixed_img">6</button>
+  <br/>
+
+  <!-- the name from subtree, child inputs -->
+  <span id="labelledby_mixed_input">
+    <input type="button" id="input_button" title="input button"/>
+    <input type="submit" id="input_submit"/>
+    <input type="reset" id="input_reset"/>
+    <input type="image" id="input_image" title="input image"/>
+  </span>
+  <button id="btn_labelledby_mixed_input"
+          aria-labelledby="labelledby_mixed_input">7</button>
+  <br/>
+
+  <!-- the name from subtree, child object -->
+  <span id="labelledby_mixed_object">
+    <object data="about:blank" title="object"></object>
+  </span>
+  <button id="btn_labelledby_mixed_object"
+          aria-labelledby="labelledby_mixed_object">8</button>
+  <br/>
+
+  <!-- the name from subtree, child br -->
+  <span id="labelledby_mixed_br">text<br/>text</span>
+  <button id="btn_labelledby_mixed_br"
+          aria-labelledby="labelledby_mixed_br">9</button>
+  <br/>
+
+  <!-- label element, label contains the button -->
+  <label>text<button id="btn_label_inside">10</button>text</label>
+  <br/>
+
+  <!-- label element, label and the button are in the same form -->
+  <form>
+    <label for="btn_label_inform">in form</label>
+    <button id="btn_label_inform">11</button>
+  </form>
+
+  <!-- label element, label is outside of the form of the button -->
+  <label for="btn_label_outform">out form</label>
+  <form>
+    <button id="btn_label_outform">12</button>
+  </form>
+
+  <!-- label element, label and the button are in the same document -->
+  <label for="btn_label_indocument">in document</label>
+  <button id="btn_label_indocument">13</button>
+
+  <!-- name from children -->
+  <span id="btn_children" role="button">14</span>
+
+  <!-- name from children, hidden children -->
+  <div role="listbox" tabindex="0">
+    <div id="lb_opt1_children_hidden" role="option" tabindex="0">
+      <span>i am visible</span>
+      <span style="display:none">i am hidden</span>
+    </div>
+  </div>
+
+  <!-- name from title attribute -->
+  <span id="btn_title" role="group" title="title">15</span>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_nsIAccessible_name.xul
@@ -0,0 +1,318 @@
+<?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/nsIAccessible_name.css"
+                 type="text/css"?>
+
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="Accessibility Name Calculating Test.">
+
+  <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 type="application/javascript">
+  <![CDATA[
+    const nsIAccessibleRetrieval = Components.interfaces.nsIAccessibleRetrieval;
+    const nsIAccessibleRole = Components.interfaces.nsIAccessibleRole;
+
+    var gAccRetrieval = null;
+
+    function testName(aID, aName)
+    {
+      var elm = document.getElementById(aID);
+      if (!elm) {
+        ok(false, "There is no element with ID " + aID);
+        return null;
+      }
+
+      var acc = null;
+      try {
+        acc = gAccRetrieval.getAccessibleFor(elm);
+      } catch(e) {
+      }
+
+      if (!acc) {
+        ok(false, "There is no accessible for " + aID);
+        return null;
+      }
+
+      is(acc.name, aName, "Wrong name of the accessible for " + aID);
+      return acc;
+    }
+
+    function doTest()
+    {
+      gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
+                      getService(nsIAccessibleRetrieval);
+
+
+      //////////////////////////////////////////////////////////////////////////
+      // aria-labelledby
+      
+      // Single relation. The value of 'aria-labelledby' contains the ID of
+      // an element. Gets the name from text node of that element.
+      testName("btn_labelledby_text", "text");
+
+      // Multiple relations. The value of 'aria-labelledby' contains the IDs
+      // of elements. Gets the name from text nodes of those elements.
+      testName("btn_labelledby_texts", "text1 text2");
+
+
+      //////////////////////////////////////////////////////////////////////////
+      // Name from subtree (single relation labelled_by).
+      
+      // Gets the name from text nodes contained by nested elements.
+      testName("btn_labelledby_mixed", "nomore text");
+
+      // Gets the name from text nodes and selected item of menulist
+      // (other items are ignored).
+      testName("btn_labelledby_mixed_menulist",
+               "nomore text selected item more text");
+      
+      // Gets the name from text nodes contained by nested elements, ignores
+      // hidden elements (bug 443081).
+      testName("btn_labelledby_mixed_hidden_child", "nomore text2");
+
+      // Gets the name from hidden text nodes contained by nested elements, 
+      // (label element is hidden entirely), (bug 443081)
+      testName("btn_labelledby_mixed_hidden", "lala more hidden text");
+
+
+      //////////////////////////////////////////////////////////////////////////
+      // Name for nsIDOMXULLabeledControlElement.
+
+      // Gets the name from @label attribute.
+      testName("btn_nsIDOMXULLabeledControlElement", "labeled element");
+
+
+      //////////////////////////////////////////////////////////////////////////
+      // Name for nsIDOMXULSelectControlItemElement.
+
+      // Gets the name from @label attribute.
+      testName("li_nsIDOMXULSelectControlItemElement", "select control item");
+
+
+      //////////////////////////////////////////////////////////////////////////
+      // Name if the XUL element doesn't implement nsIDOMXULSelectControlElement
+      // and has @label attribute.
+
+      testName("box_not_nsIDOMXULSelectControlElement", "box");
+
+
+      //////////////////////////////////////////////////////////////////////////
+      // Name from the label element.
+
+      // The label and button are placed on 2nd level relative common parent.
+      testName("btn_label_1", "label1");
+
+      // The label is on 1st, the button is on 5th level relative common parent.
+      testName("btn_label_2", "label2");
+
+      // The label and button are siblings.
+      testName("btn_label_3", "label3");
+
+
+      //////////////////////////////////////////////////////////////////////////
+      // Name from the label element in anonymous content (see bug 362365).
+
+      // Get the name from anonymous label element for anonymous textbox
+      // (@anonid is used).
+      var ID = "box_label_anon1";
+      var box1Acc = testName(ID, "");
+      if (box1Acc) {
+        var textboxAcc = box1Acc.firstChild;
+        is(textboxAcc.name, "Label",
+           "Wrong label for anonymous textbox of " + ID);
+      }
+
+      // Get the name from anonymous label element for anonymous textbox
+      // (@anonid is used). Nested bindings.
+      ID = "box_label_anon2";
+      var box2Acc = testName(ID, "");
+      if (box2Acc) {
+        var textboxAcc = box2Acc.firstChild;
+        is(textboxAcc.name, "Label",
+           "Wrong label for anonymous textbox of " + ID);
+
+        var topTextboxAcc = box2Acc.lastChild;
+        is(topTextboxAcc.name, "Top textbox",
+           "Wrong label for anonymous textbox of " + ID);
+      }
+
+
+      //////////////////////////////////////////////////////////////////////////
+      // tooltiptext (if nothing above isn't presented then tooltiptext is used)
+      testName("box_tooltiptext", "tooltiptext label");
+
+
+      //////////////////////////////////////////////////////////////////////////
+      // Name from the @title attribute of <toolbaritem/> (original bug 237249).
+
+      // Direct child of toolbaritem.
+      var textboxAcc = testName("toolbaritem_textbox", "ooospspss");
+
+      // Element from anonymous content of direct child of toolbaritem.
+      var dropmarkerAcc = textboxAcc.lastChild;
+      is(dropmarkerAcc.finalRole, nsIAccessibleRole.ROLE_PUSHBUTTON,
+         "The last child of autocomplete textbox 'toolbaritem_textbox' should be dropmarker.");
+      is(dropmarkerAcc.name, "ooospspss",
+         "Wrong name for dropmarker of autocomplete textbox 'toolbaritem_textbox'.");
+
+      // Child from subtree of toolbaritem.
+      testName("toolbaritem_hboxbutton", "ooospspss");
+
+
+      //////////////////////////////////////////////////////////////////////////
+      // Name from children
+
+      // ARIA role button is presented allowing the name calculation from
+      // children.
+      testName("box_children", "14");
+
+      // ARIA role option is presented allowing the name calculation from
+      // the visible children (bug 443081)
+      testName("lb_opt1_children_hidden", "i am visible");
+
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addLoadEvent(doTest);
+  ]]>
+  </script>
+
+  <body xmlns="http://www.w3.org/1999/xhtml">
+    <a target="_blank"
+       href="https://bugzilla.mozilla.org/show_bug.cgi?id=444279"
+       title="mochitest for accessible name calculating">
+      Mozilla Bug 444279
+    </a>
+    <p id="display"></p>
+    <div id="content" style="display: none">
+    </div>
+    <pre id="test">
+    </pre>
+  </body>
+
+  <!-- aria-labelledby, single relation -->
+  <description id="labelledby_text">text</description>
+  <button id="btn_labelledby_text"
+          aria-labelledby="labelledby_text"/>
+
+  <!-- aria-labelledby, multiple relations -->
+  <description id="labelledby_text1">text1</description>
+  <description id="labelledby_text2">text2</description>
+  <button id="btn_labelledby_texts"
+          aria-labelledby="labelledby_text1 labelledby_text2"/>
+
+  <!-- the name from subtree, mixed content -->
+  <description id="labelledby_mixed">
+    no<description>more text</description>
+  </description>
+  <button id="btn_labelledby_mixed"
+          aria-labelledby="labelledby_mixed"/>
+
+  <!-- the name from subtree, mixed/hidden content -->
+  <description id="labelledby_mixed_hidden_child">no<description>more <description hidden="true">hidden</description>text2</description></description>
+  <button id="btn_labelledby_mixed_hidden_child"
+          aria-labelledby="labelledby_mixed_hidden_child"/>
+
+  <!-- the name from subtree, mixed/completely hidden content -->
+  <description id="labelledby_mixed_hidden"
+               hidden="true">lala <description>more hidden </description>text</description>
+  <button id="btn_labelledby_mixed_hidden"
+          aria-labelledby="labelledby_mixed_hidden"/>
+  <br/>
+
+  <!-- the name from subtree, mixed content, ignore items of menulist -->
+  <description id="labelledby_mixed_menulist">
+    no<description>more text</description>
+    <menulist>
+      <menupopup>
+        <menuitem label="selected item"/>
+        <menuitem label="item"/>
+      </menupopup>
+    </menulist>
+    more text
+  </description>
+  <button id="btn_labelledby_mixed_menulist"
+          aria-labelledby="labelledby_mixed_menulist"/>
+
+  <!-- nsIDOMXULLabeledControlElement -->
+  <button id="btn_nsIDOMXULLabeledControlElement"
+          label="labeled element"/>
+
+  <!-- nsIDOMXULSelectControlItemElement -->
+  <listbox>
+    <listitem id="li_nsIDOMXULSelectControlItemElement"
+              label="select control item"/>
+  </listbox>
+
+  <!-- not nsIDOMXULSelectControlElement -->
+  <box id="box_not_nsIDOMXULSelectControlElement" role="group" label="box"/>
+
+  <!-- label element  -->
+  <hbox>
+    <box>
+      <label control="btn_label_1">label1</label>
+    </box>
+    <label control="btn_label_2">label2</label>
+    <box>
+      <button id="btn_label_1"/>
+      <box>
+        <box>
+          <box>
+            <button id="btn_label_2"/>
+          </box>
+        </box>
+      </box>
+    </box>
+    <label control="btn_label_3">label3</label>
+    <button id="btn_label_3"/>
+  </hbox>
+
+  <!-- label element, anonymous content -->
+  <box id="box_label_anon1"
+       class="first"
+       role="group"/>
+
+  <box id="box_label_anon2" 
+       class="second" 
+       role="group"/>
+
+  <!-- tooltiptext -->
+  <box id="box_tooltiptext"
+       role="group"
+       tooltiptext="tooltiptext label"/>
+
+  <!-- the name from @title of toolbaritem -->
+  <toolbar>
+    <toolbaritem title="ooospspss">
+      <textbox id="toolbaritem_textbox"
+               flex="1"
+               type="autocomplete"
+               enablehistory="true">
+        <hbox role="button" id="toolbaritem_hboxbutton">
+           <description value="button"/>
+        </hbox>
+      </textbox>
+    </toolbaritem>
+  </toolbar>
+
+  <!-- name from children -->
+  <box id="box_children" role="button">14</box>
+
+  <!-- name from children, hidden children -->
+  <vbox role="listbox" tabindex="0">
+    <hbox id="lb_opt1_children_hidden" role="option" tabindex="0">
+      <description>i am visible</description>
+      <description style="display:none">i am hidden</description>
+    </hbox>
+  </vbox>
+
+</window>
+
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_nsOuterDocAccessible.html
@@ -0,0 +1,106 @@
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=441519
+-->
+<head>
+  <title>nsOuterDocAccessible chrome tests</title>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript">
+    const nsIAccessibleRetrieval = Components.interfaces.nsIAccessibleRetrieval;
+    const nsIAccessibleRole = Components.interfaces.nsIAccessibleRole;
+
+    // needed state flag
+    const state_focusable =
+          Components.interfaces.nsIAccessibleStates.STATE_FOCUSABLE;
+
+    // needed error return value
+    const ns_error_invalid_arg = Components.results.NS_ERROR_INVALID_ARG;
+
+    var gAccRetrieval = null;
+
+    function doTest()
+    {
+      gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
+                      getService(nsIAccessibleRetrieval);
+
+      // Get accessible for body tag.
+      var docAcc = null;
+      try {
+        docAcc = gAccRetrieval.getAccessibleFor(document);
+      } catch(e) {}
+      ok(docAcc, "No accessible for document!");
+
+      if (docAcc) {
+        var outerDocAcc = null;
+        try {
+          outerDocAcc = docAcc.parent;
+        } catch(e) {}
+        ok(outerDocAcc, "No internal frame parent for document!");
+
+        if (outerDocAcc) {
+          is(outerDocAcc.role, nsIAccessibleRole.ROLE_INTERNAL_FRAME,
+             "Wrong role for internal frame!");
+
+          // check if it is focusable, not desired.
+          var state = {}, extraState = {}
+          outerDocAcc.getFinalState(state, extraState);
+          is(state.value & state_focusable, 0,
+             "Wrong focusable state bit for internal frame!");
+
+          // see bug 428954: No name wanted for internal frame
+          is(outerDocAcc.name, "", "Wrong name for internal frame!");
+
+          // see bug 440770, no actions wanted on outer doc
+          is(outerDocAcc.numActions, 0,
+             "Wrong number of actions for internal frame!");
+          var actionTempStr; // not really used, just needs to receive a value
+          try {
+            actionTempStr = outerDocAcc.getActionName(0);
+            do_throw("No exception thrown for actionName!");
+          } catch(e) {
+            ok(e.result, ns_error_invalid_arg,
+               "Wrong return value for actionName call!");
+          }
+
+          try {
+            actionTempStr = outerDocAcc.getActionDescription(0);
+            do_throw("No exception thrown for actionDescription!");
+          } catch(e) {
+            ok(e.result, ns_error_invalid_arg,
+               "Wrong return value for actionDescription call!");
+          }
+
+          try {
+            outerDocAcc.doAction(0);
+            do_throw("No exception thrown for doAction!");
+          } catch(e) {
+            ok(e.result, ns_error_invalid_arg,
+               "Wrong return value for doAction call!");
+          }
+        }
+      }
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=441519"
+     title="nsOuterDocAccessible chrome tests">
+    Mozilla Bug 441519
+  </a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_textattrs.html
@@ -0,0 +1,476 @@
+<html>
+
+<head>
+  <title>Text attributes tests</title>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript">
+    const nsIAccessibleRetrieval = Components.interfaces.nsIAccessibleRetrieval;
+    const nsIAccessibleText = Components.interfaces.nsIAccessibleText;
+    const nsIAccessibleEvent = Components.interfaces.nsIAccessibleEvent;
+
+    const nsIDOMNSEditableElement =
+      Components.interfaces.nsIDOMNSEditableElement;
+    const nsIObserverService = Components.interfaces.nsIObserverService;
+
+    var gAccRetrieval = null;
+
+    /**
+     * Test text attributes.
+     *
+     * @param aID               the ID of DOM element having text accessible
+     * @param aOffset           the offset inside text accessible to fetch
+     *                          text attributes
+     * @param aAttrs            the map of text attributes (name/value pairs)
+     * @param aStartOffset      the start offset where text attributes are
+     *                          applied
+     * @param aEndOffset        the end offset where text attribute are applied
+     * @param aDefAttrs         the list of default text attributes (name/value
+     *                          pairs)
+     */
+    function testTextAttrs(aID, aOffset,
+                           aAttrs, aStartOffset, aEndOffset, aDefAttrs)
+    {
+      var node = document.getElementById(aID);
+      if (!node) {
+        ok(false, "Can't get the element with ID " + aID);
+        return;
+      }
+
+      var accessible = null;
+      try {
+        accessible = gAccRetrieval.getAccessibleFor(node);
+        accessible.QueryInterface(nsIAccessibleText);
+      } catch (e) {
+      }
+
+      if (!accessible) {
+        ok(false, "Can't query nsIAccessibleText interface for " + aID);
+        return;
+      }
+
+      var startOffset = { value: -1 };
+      var endOffset = { value: -1 };
+      var attrs = null;
+      try {
+        attrs = accessible.getTextAttributes(false,
+                                             aOffset,
+                                             startOffset, endOffset);
+      } catch (e) {
+      }
+
+      if (!attrs) {
+        ok(false, "Can't get text attributes for " + aID);
+        return;
+      }
+
+      var errorMsg = " for " + aID + "at offset " + aOffset;
+      is(startOffset.value, aStartOffset,
+         "Wrong start offset" + errorMsg);
+      is(endOffset.value, aEndOffset,
+          "Wrong end offset" + errorMsg);
+
+      compareTextAttrs(errorMsg, attrs, aAttrs);
+
+      var defAttrs = null;
+      try{
+        defAttrs = accessible.defaultTextAttributes;
+      } catch (e) {
+      }
+
+      if (!defAttrs) {
+        ok(false, "Can't get default attributes for " + aID);
+        return;
+      }
+
+      compareTextAttrs(errorMsg, defAttrs, aDefAttrs);
+    }
+
+    function compareTextAttrs(aErrorMsg, aAttrs, aExpectedAttrs)
+    {
+      var enumerate = aAttrs.enumerate();
+      while (enumerate.hasMoreElements()) {
+        var prop = enumerate.getNext().
+          QueryInterface(Components.interfaces.nsIPropertyElement);
+
+        if (!(prop.key in aExpectedAttrs))
+          ok(false,
+             "Unexpected attribute '" + prop.key + "'" + aErrorMsg);
+        else
+          is(prop.value, aExpectedAttrs[prop.key],
+             "Attribute '" + prop.key + "' has wrong value" + aErrorMsg);
+      }
+
+      for (var name in aExpectedAttrs) {
+        var value = "";
+        try {
+          value = aAttrs.getStringProperty(name);
+        } catch(e) {
+        }
+
+        if (!value)
+          ok(false,
+             "There is no expected attribute '" + name + "'" + aErrorMsg);
+      }
+    }
+
+    var gObserverService = null;
+    var gA11yEventObserver = null;
+
+    function testSpellTextAttrs()
+    {
+      gA11yEventObserver = {
+        observe: function observe(aSubject, aTopic, aData)
+        {
+          if (aTopic != "accessible-event")
+            return;
+
+          
+          var event = aSubject.QueryInterface(nsIAccessibleEvent);
+
+          if (event.eventType == nsIAccessibleEvent.EVENT_TEXT_ATTRIBUTE_CHANGED)
+            this.mTextAttrChangedEventCounter++;
+        },
+
+        mTextAttrChangedEventCounter: 0
+      };
+
+      // Add accessibility event listeners
+      var gObserverService = Components.classes["@mozilla.org/observer-service;1"].
+                            getService(nsIObserverService);
+
+      gObserverService.addObserver(gA11yEventObserver, "accessible-event",
+                                  false);
+
+      ID = "area8";
+  
+      var node = document.getElementById(ID);
+      node.focus();
+
+      var editor = node.QueryInterface(nsIDOMNSEditableElement).editor;
+      var spellchecker = editor.getInlineSpellChecker(true);
+      spellchecker.enableRealTimeSpell = true;
+
+      window.setTimeout(function()
+        {
+          var defAttrs = {
+            "font-style": "normal",
+            "text-align": "start",
+            "font-size": "11px",
+            "background-color": "rgb(255, 255, 255)",
+            "font-weight": "400",
+            "text-indent": "0px",
+            "color": "rgb(0, 0, 0)",
+            "font-family": "Lucida Grande",
+            "text-position": "baseline"
+          };
+
+          var attrs = { "background-color": "transparent" };
+          var misspelledAttrs = {
+            "background-color": "transparent",
+            "invalid": "spelling"
+          };
+
+          testTextAttrs(ID, 0, attrs, 0, 11, defAttrs);
+          testTextAttrs(ID, 11, misspelledAttrs, 11, 17, defAttrs);
+          testTextAttrs(ID, 18, misspelledAttrs, 18, 22, defAttrs);
+
+          is(gA11yEventObserver.mTextAttrChangedEventCounter, 2,
+             "Wrong count of 'text attribute changed' events for " + ID);
+
+          // Remove a11y events listener
+          gObserverService.removeObserver(gA11yEventObserver,
+                                          "accessible-event");
+
+          SimpleTest.finish();
+        }, 0);
+    }
+
+    function doTest()
+    {
+      gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
+                      getService(nsIAccessibleRetrieval);
+
+      //////////////////////////////////////////////////////////////////////////
+      // area1
+      var ID = "area1";
+      var defAttrs = {
+        "font-style": "normal",
+        "text-align": "start",
+        "font-size": "16px",
+        "background-color": "transparent",
+        "font-weight": "400",
+        "text-indent": "0px",
+        "color": "rgb(0, 0, 0)",
+        "font-family": "serif",
+        "text-position": "baseline"
+      };
+
+      var attrs = {};
+      testTextAttrs(ID, 0, attrs, 0, 7, defAttrs);
+
+      attrs = {"font-weight": "401"};
+      testTextAttrs(ID, 7, attrs, 7, 11, defAttrs);
+
+      attrs = {};
+      testTextAttrs(ID, 12, attrs, 11, 18, defAttrs);
+
+      //////////////////////////////////////////////////////////////////////////
+      // area2
+      ID = "area2";
+      defAttrs = {
+        "font-style": "normal",
+        "text-align": "start",
+        "font-size": "16px",
+        "background-color": "transparent",
+        "font-weight": "400",
+        "text-indent": "0px",
+        "color": "rgb(0, 0, 0)",
+        "font-family": "serif",
+        "text-position": "baseline"
+      };
+
+      attrs = {};
+      testTextAttrs(ID, 0, attrs, 0, 7, defAttrs);
+
+      attrs = {"font-weight": "401"};
+      testTextAttrs(ID, 7, attrs, 7, 12, defAttrs);
+
+      attrs = {"font-style": "italic", "font-weight": "401"};
+      testTextAttrs(ID, 13, attrs, 12, 19, defAttrs);
+
+      attrs = {"font-weight": "401"};
+      testTextAttrs(ID, 20, attrs, 19, 23, defAttrs);
+
+      attrs = {};
+      testTextAttrs(ID, 24, attrs, 23, 30, defAttrs);
+
+      //////////////////////////////////////////////////////////////////////////
+      // area3
+      ID = "area3";
+      defAttrs = {
+        "font-style": "normal",
+        "text-align": "start",
+        "font-size": "16px",
+        "background-color": "transparent",
+        "font-weight": "400",
+        "text-indent": "0px",
+        "color": "rgb(0, 0, 0)",
+        "font-family": "serif",
+        "text-position": "baseline"
+      };
+
+      attrs = {"color": "rgb(0, 128, 0)"};
+      testTextAttrs(ID, 0, attrs, 0, 6, defAttrs);
+
+      attrs = {"color": "rgb(255, 0, 0)"};
+      testTextAttrs(ID, 6, attrs, 6, 26, defAttrs);
+
+      attrs = {"color": "rgb(0, 128, 0)"};
+      testTextAttrs(ID, 26, attrs, 26, 50, defAttrs);
+
+      //////////////////////////////////////////////////////////////////////////
+      // area4
+      ID = "area4";
+      defAttrs = {
+        "font-style": "normal",
+        "text-align": "start",
+        "font-size": "16px",
+        "background-color": "transparent",
+        "font-weight": "400",
+        "text-indent": "0px",
+        "color": "rgb(0, 0, 0)",
+        "font-family": "serif",
+        "text-position": "baseline"
+      };
+
+      attrs = {"color": "rgb(0, 128, 0)"};
+      testTextAttrs(ID, 0, attrs, 0, 16, defAttrs);
+
+      attrs = {"color": "rgb(255, 0, 0)"};
+      testTextAttrs(ID, 16, attrs, 16, 33, defAttrs);
+
+      attrs = {"color": "rgb(0, 128, 0)"};
+      testTextAttrs(ID, 34, attrs, 33, 46, defAttrs);
+
+      //////////////////////////////////////////////////////////////////////////
+      // area5
+      ID = "area5";
+      defAttrs = {
+        "font-style": "normal",
+        "text-align": "start",
+        "font-size": "16px",
+        "background-color": "transparent",
+        "font-weight": "400",
+        "text-indent": "0px",
+        "color": "rgb(0, 0, 0)",
+        "font-family": "serif",
+        "text-position": "baseline"
+      };
+
+      attrs = {"color": "rgb(0, 128, 0)"};
+      testTextAttrs(ID, 0, attrs, 0, 5, defAttrs);
+
+      attrs = {};
+      testTextAttrs(ID, 7, attrs, 5, 8, defAttrs);
+
+      attrs = {"color": "rgb(255, 0, 0)"};
+      testTextAttrs(ID, 9, attrs, 8, 11, defAttrs);
+