Merge mozilla-central to tracemonkey.
authorRobert Sayre <sayrer@gmail.com>
Wed, 24 Jun 2009 13:16:16 -0700
changeset 29881 8ff867fdc1f4b8e4dfa1fe7e598bedd5ec7e1bf1
parent 29880 6d41b2eaaae16af67a9190a5e70f767792727b68 (current diff)
parent 29551 e482ed88939c5f1bcae9b77f9ceef1de6bcbc373 (diff)
child 29882 147d92057b26826f8c048bdc41971279c7bc185b
push id7810
push userrsayre@mozilla.com
push dateTue, 30 Jun 2009 19:21:13 +0000
treeherdermozilla-central@83e105e5f0db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9.2a1pre
Merge mozilla-central to tracemonkey.
accessible/public/nsPIAccessible.idl
browser/installer/windows/msi/dept.mmh
browser/themes/pinstripe/browser/urlbar/endcap-focused-rtl.png
browser/themes/pinstripe/browser/urlbar/endcap-focused.png
browser/themes/pinstripe/browser/urlbar/endcap-rtl.png
browser/themes/pinstripe/browser/urlbar/endcap-secure.png
browser/themes/pinstripe/browser/urlbar/endcap.png
browser/themes/pinstripe/browser/urlbar/startcap-active-focused-rtl.png
browser/themes/pinstripe/browser/urlbar/startcap-active-focused.png
browser/themes/pinstripe/browser/urlbar/startcap-active-rtl.png
browser/themes/pinstripe/browser/urlbar/startcap-active.png
browser/themes/pinstripe/browser/urlbar/startcap-focused-rtl.png
browser/themes/pinstripe/browser/urlbar/startcap-focused.png
browser/themes/pinstripe/browser/urlbar/startcap-rtl.png
browser/themes/pinstripe/browser/urlbar/startcap-secure-active.png
browser/themes/pinstripe/browser/urlbar/startcap-secure-end-active.png
browser/themes/pinstripe/browser/urlbar/startcap-secure-end-focused.png
browser/themes/pinstripe/browser/urlbar/startcap-secure-end.png
browser/themes/pinstripe/browser/urlbar/startcap-secure-mid-active.png
browser/themes/pinstripe/browser/urlbar/startcap-secure-mid-focused.png
browser/themes/pinstripe/browser/urlbar/startcap-secure-mid.png
browser/themes/pinstripe/browser/urlbar/startcap-secure-start-active.png
browser/themes/pinstripe/browser/urlbar/startcap-secure-start-focused.png
browser/themes/pinstripe/browser/urlbar/startcap-secure-start.png
browser/themes/pinstripe/browser/urlbar/startcap-secure.png
browser/themes/pinstripe/browser/urlbar/startcap-verified-end-active.png
browser/themes/pinstripe/browser/urlbar/startcap-verified-end-focused.png
browser/themes/pinstripe/browser/urlbar/startcap-verified-end.png
browser/themes/pinstripe/browser/urlbar/startcap-verified-mid-active.png
browser/themes/pinstripe/browser/urlbar/startcap-verified-mid-focused.png
browser/themes/pinstripe/browser/urlbar/startcap-verified-mid.png
browser/themes/pinstripe/browser/urlbar/startcap-verified-start-active.png
browser/themes/pinstripe/browser/urlbar/startcap-verified-start-focused.png
browser/themes/pinstripe/browser/urlbar/startcap-verified-start.png
browser/themes/pinstripe/browser/urlbar/startcap.png
browser/themes/pinstripe/browser/urlbar/textfield-mid-focused.png
browser/themes/pinstripe/browser/urlbar/textfield-mid.png
content/svg/content/src/nsIDOMSVGListener.h
content/svg/content/src/nsIDOMSVGZoomListener.h
content/svg/content/src/nsISVGTextContentMetrics.h
content/xul/templates/src/crashtests/441785-1.rdf
content/xul/templates/src/crashtests/441785-1.xul
content/xul/templates/src/crashtests/441785-2.rdf
dom/public/coreEvents/nsIDOMDragListener.h
dom/src/geolocation/test/Makefile.in
dom/src/geolocation/test/TestGeolocationProvider.js
editor/libeditor/text/nsWrapUtils.cpp
editor/libeditor/text/nsWrapUtils.h
gfx/src/thebes/nsSystemFontsMac.cpp
js/makefile.win
js/src/jstracer.cpp
js/src/jstracer.h
layout/base/nsFocusEventSuppressor.cpp
layout/base/nsIFocusEventSuppressor.h
layout/reftests/backgrounds/fallback-color-1.xhtml
layout/reftests/backgrounds/fallback-color-2.xhtml
layout/reftests/backgrounds/fallback-color-3.xhtml
layout/reftests/backgrounds/fallback-color-4.xhtml
layout/reftests/backgrounds/fallback-color-5.xhtml
layout/reftests/backgrounds/fallback-color-6.xhtml
layout/reftests/backgrounds/fallback-color-7.xhtml
layout/reftests/backgrounds/fallback-color-8.xhtml
layout/reftests/backgrounds/fallback-color-9.xhtml
layout/reftests/backgrounds/fallback-color-ref.xhtml
modules/plugin/base/public/nsIClassicPluginFactory.idl
modules/plugin/base/public/nsICookieStorage.idl
modules/plugin/base/public/nsIEventHandler.idl
modules/plugin/base/public/nsIFileUtilities.idl
modules/plugin/base/public/nsIJRILiveConnectPIPeer.idl
modules/plugin/base/public/nsIJRILiveConnectPlugin.idl
modules/plugin/base/public/nsILegacyPluginWrapperOS2.idl
modules/plugin/base/public/nsIScriptablePlugin.idl
modules/plugin/os2wrapper/Makefile.in
modules/plugin/os2wrapper/README.txt
modules/plugin/os2wrapper/moz_IDs.cmd
modules/plugin/os2wrapper/moz_IDs_Generated.h
modules/plugin/os2wrapper/moz_IDs_Input.lst
modules/plugin/os2wrapper/nsInnoTekPluginWrapper.h
modules/plugin/os2wrapper/nsInnoTekPluginWrapperModule.cpp
modules/plugin/os2wrapper/util_debug.c
modules/plugin/os2wrapper/wrap_VFTs.h
modules/plugin/os2wrapper/wrap_XPCOM.cpp
modules/plugin/os2wrapper/wrap_XPCOM_3rdparty.h
netwerk/testserver/Connection.java
netwerk/testserver/Makefile.in
netwerk/testserver/ScriptFile.java
netwerk/testserver/TestServer.java
netwerk/testserver/docs/bar.html
netwerk/testserver/docs/foo.html
netwerk/testserver/docs/generic.res
netwerk/testserver/docs/help.html
netwerk/testserver/docs/post.html
netwerk/testserver/docs/urlmap
storage/src/Variant.cpp
storage/test/unit/test_storage_statement_executeAsync.js
toolkit/mozapps/update/test/unit/data/aus-0110_general-1.mar
toolkit/mozapps/update/test/unit/data/aus-0110_general-2.mar
toolkit/mozapps/update/test/unit/data/aus-0110_general_ref_image1.png
toolkit/mozapps/update/test/unit/data/aus-0110_general_ref_image2.png
toolkit/mozapps/update/test/unit/test_0051_general.js
toolkit/themes/pinstripe/global/closetab.png
toolkit/themes/pinstripe/tests/Makefile.in
toolkit/themes/pinstripe/tests/test_bug371080.xul
toolkit/themes/winstripe/global/icons/close-button.gif
tools/tests/viewer/mtbf/makefile.win
tools/tests/viewer/mtbf/mtbf.cpp
tools/tests/viewer/mtbf/mtbf.dsp
tools/tests/viewer/mtbf/mtbf.dsw
tools/tests/viewer/mtbf/urls.txt
tools/testserver/Connection.java
tools/testserver/Makefile.in
tools/testserver/ScriptFile.java
tools/testserver/TestServer.java
tools/testserver/docs/bar.html
tools/testserver/docs/foo.html
tools/testserver/docs/generic.res
tools/testserver/docs/help.html
tools/testserver/docs/post.html
tools/testserver/docs/urlmap
uriloader/exthandler/mac/nsInternetConfig.h
uriloader/exthandler/mac/nsInternetConfig.mm
uriloader/exthandler/mac/nsInternetConfigService.h
uriloader/exthandler/mac/nsInternetConfigService.mm
uriloader/exthandler/nsIInternetConfigService.idl
xpcom/stub/nsOS2VACLegacy.cpp
--- a/accessible/Makefile.in
+++ b/accessible/Makefile.in
@@ -38,12 +38,16 @@
 DEPTH   = ..
 topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH   = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE	= accessibility
-DIRS    = public src build tests
+DIRS    = public src build
+
+ifdef ENABLE_TESTS
+DIRS    += tests
+endif
 
 include $(topsrcdir)/config/rules.mk
 
--- a/accessible/public/Makefile.in
+++ b/accessible/public/Makefile.in
@@ -53,17 +53,16 @@ GRE_MODULE	= 1
 XPIDLSRCS = \
       nsIAccessibleTypes.idl \
       nsIAccessibilityService.idl \
       nsIAccessibleRetrieval.idl \
       nsIAccessible.idl \
       nsIAccessibleRelation.idl \
       nsIAccessibleRole.idl \
       nsIAccessibleStates.idl \
-      nsPIAccessible.idl \
       nsIAccessibleDocument.idl \
       nsPIAccessibleDocument.idl \
       nsIAccessibleProvider.idl \
       nsIAccessibleSelectable.idl \
       nsIAccessNode.idl \
       nsIAccessibleEvent.idl \
       nsIAccessibleEditableText.idl \
       nsIAccessibleHyperLink.idl \
deleted file mode 100644
--- a/accessible/public/nsPIAccessible.idl
+++ /dev/null
@@ -1,119 +0,0 @@
-/* -*- 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
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2003
- * the Initial Developer. All Rights Reserved.
- *
- * Original Author: Aaron Leventhal (aaronl@netscape.com)
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * 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 "nsISupports.idl"
-
-interface nsIAccessible;
-interface nsIAccessibleEvent;
-%{C++
-   struct nsRoleMapEntry;
-%}
-[ptr] native nsRoleMapEntryPtr(nsRoleMapEntry);
-
-[uuid(ed61e5cd-283a-42df-9599-765e0e27f4d9)]
-interface nsPIAccessible : nsISupports
-{
-  /**
-   * Set accessible parent.
-   */
-  void setParent(in nsIAccessible aAccParent);
-
-  /**
-   * Set first accessible child.
-   */
-  void setFirstChild(in nsIAccessible aAccFirstChild);
-
-  /**
-   * Set next sibling accessible.
-   */
-  void setNextSibling(in nsIAccessible aAccNextSibling);
-
-  /**
-   * Return parent accessible only if cached.
-   */
-  void getCachedParent(out nsIAccessible aAccParent);
-
-  /**
-   * Return first child accessible only if cached.
-   */
-  void getCachedFirstChild(out nsIAccessible aAccFirstChild);
-
-  /**
-   * Set the child count to -1 (unknown) and null out cached child pointers
-   */
-  void invalidateChildren();
-
-  /**
-   * Fire accessible event.
-   */
-  void fireAccessibleEvent(in nsIAccessibleEvent aAccEvent);
-
-  /**
-   * Return true if there are accessible children in anonymous content
-   */
-  readonly attribute boolean allowsAnonChildAccessibles;
-
-  /**
-   * Assert if child not in parent's cache.
-   */
-  void testChildCache(in nsIAccessible aCachedChild);
-
-  /**
-   * Returns text of accessible if accessible has text role otherwise empty
-   * string.
-   */
-  void appendTextTo(out AString aString, in unsigned long aStartOffset,
-                    in unsigned long aLength);
-                    
-  /**
-   * Set the ARIA role map entry for a new accessible.
-   * For a newly created accessible, specify which role map entry should be used.
-   * @param aRoleMapEntry The ARIA nsRoleMapEntry* for the accessible, or 
-   *                      nsnull if none.
-   */
-   void setRoleMapEntry(in nsRoleMapEntryPtr aRoleMapEntry);
-
-  /**
-   * Maps ARIA state attributes to state of accessible. Note the given state
-   * argument should hold states for accessible before you pass it into this
-   * method.
-   * @param  in/out where to fill the states into.
-   */
-   void getARIAState(out unsigned long aState);
-};
-
--- a/accessible/src/Makefile.in
+++ b/accessible/src/Makefile.in
@@ -70,9 +70,9 @@ endif
 
 ifndef DISABLE_XFORMS_HOOKS
 DIRS +=   xforms
 endif
 
 include $(topsrcdir)/config/rules.mk
 
 libs::
-	$(NSINSTALL) $(PLATFORM_DIR)/$(LIB_PREFIX)accessibility_toolkit_s.$(LIB_SUFFIX) .
+	$(INSTALL) $(PLATFORM_DIR)/$(LIB_PREFIX)accessibility_toolkit_s.$(LIB_SUFFIX) .
--- a/accessible/src/atk/Makefile.in
+++ b/accessible/src/atk/Makefile.in
@@ -86,16 +86,17 @@ CPPSRCS = \
 ifdef MOZ_XUL
 CPPSRCS += \
   nsXULTreeAccessibleWrap.cpp \
   $(NULL)
 endif
 
 EXPORTS = \
   nsAccessNodeWrap.h \
+  nsARIAGridAccessibleWrap.h \
   nsAccessibleWrap.h \
   nsDocAccessibleWrap.h \
   nsRootAccessibleWrap.h \
   nsTextAccessibleWrap.h \
   nsXULMenuAccessibleWrap.h \
   nsXULTreeAccessibleWrap.h \
   nsHyperTextAccessibleWrap.h \
   nsHTMLImageAccessibleWrap.h \
new file mode 100644
--- /dev/null
+++ b/accessible/src/atk/nsARIAGridAccessibleWrap.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 _NSARIAGRIDACCESSIBLEWRAP_H
+#define _NSARIAGRIDACCESSIBLEWRAP_H
+
+#include "nsARIAGridAccessible.h"
+
+typedef class nsARIAGridAccessible nsARIAGridAccessibleWrap;
+
+#endif
+
--- a/accessible/src/atk/nsAccessibleWrap.cpp
+++ b/accessible/src/atk/nsAccessibleWrap.cpp
@@ -257,36 +257,16 @@ mai_atk_object_get_type(void)
 
         type = g_type_register_static(ATK_TYPE_OBJECT,
                                       "MaiAtkObject", &tinfo, GTypeFlags(0));
         quark_mai_hyperlink = g_quark_from_static_string("MaiHyperlink");
     }
     return type;
 }
 
-/*
- * Must keep sychronization with enumerate AtkProperty in 
- * accessible/src/base/nsAccessibleEventData.h
- */
-static char * sAtkPropertyNameArray[PROP_LAST] = {
-    0,
-    "accessible-name",
-    "accessible-description",
-    "accessible-parent",
-    "accessible-role",
-    "accessible-layer",
-    "accessible-mdi-zorder",
-    "accessible-table-caption",
-    "accessible-table-column-description",
-    "accessible-table-column-header",
-    "accessible-table-row-description",
-    "accessible-table-row-header",
-    "accessible-table-summary"
-};
-
 #ifdef MAI_LOGGING
 PRInt32 nsAccessibleWrap::mAccWrapCreated = 0;
 PRInt32 nsAccessibleWrap::mAccWrapDeleted = 0;
 #endif
 
 nsAccessibleWrap::nsAccessibleWrap(nsIDOMNode* aNode,
                                    nsIWeakReference *aShell)
     : nsAccessible(aNode, aShell),
@@ -1121,17 +1101,17 @@ nsAccessibleWrap *GetAccessibleWrap(AtkO
         static_cast<nsAccessibleWrap*>(appAccWrap.get());
 
     if (tmpAppAccWrap != tmpAccWrap && !tmpAccWrap->IsValidObject())
         return nsnull;
 
     return tmpAccWrap;
 }
 
-NS_IMETHODIMP
+nsresult
 nsAccessibleWrap::FireAccessibleEvent(nsIAccessibleEvent *aEvent)
 {
     nsresult rv = nsAccessible::FireAccessibleEvent(aEvent);
     NS_ENSURE_SUCCESS(rv, rv);
 
     return FirePlatformEvent(aEvent);
 }
 
--- a/accessible/src/base/nsARIAGridAccessible.cpp
+++ b/accessible/src/base/nsARIAGridAccessible.cpp
@@ -92,38 +92,20 @@ NS_IMETHODIMP
 nsARIAGridAccessible::GetColumns(PRInt32 *aColumns)
 {
   NS_ENSURE_ARG_POINTER(aColumns);
   *aColumns = 0;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  nsCOMPtr<nsIAccessible> row, nextChild;
-  GetFirstChild(getter_AddRefs(row));
-  while (row && nsAccUtils::Role(row) != nsIAccessibleRole::ROLE_ROW) {
-    row->GetNextSibling(getter_AddRefs(nextChild));
-    row.swap(nextChild);
-  }
-
-  if (!row)
-    return NS_OK;
-
+  nsCOMPtr<nsIAccessible> row = GetNextRow();
   nsCOMPtr<nsIAccessible> cell;
-  row->GetFirstChild(getter_AddRefs(cell));
-  while (cell) {
-    PRUint32 role = nsAccUtils::Role(cell);
-    if (role == nsIAccessibleRole::ROLE_GRID_CELL ||
-        role == nsIAccessibleRole::ROLE_ROWHEADER ||
-        role == nsIAccessibleRole::ROLE_COLUMNHEADER)
-      (*aColumns)++;
-
-    cell->GetNextSibling(getter_AddRefs(nextChild));
-    cell.swap(nextChild);
-  }
+  while ((cell = GetNextCellInRow(row, cell)))
+    (*aColumns)++;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsARIAGridAccessible::GetColumnHeader(nsIAccessibleTable **aColumnHeader)
 {
   NS_ENSURE_ARG_POINTER(aColumnHeader);
@@ -140,25 +122,19 @@ NS_IMETHODIMP
 nsARIAGridAccessible::GetRows(PRInt32 *aRows)
 {
   NS_ENSURE_ARG_POINTER(aRows);
   *aRows = 0;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  nsCOMPtr<nsIAccessible> row, nextRow;
-  GetFirstChild(getter_AddRefs(row));
-  while (row) {
-    if (nsAccUtils::Role(row) == nsIAccessibleRole::ROLE_ROW)
-      (*aRows)++;
-
-    row->GetNextSibling(getter_AddRefs(nextRow));
-    row.swap(nextRow);
-  }
+  nsCOMPtr<nsIAccessible> row;
+  while ((row = GetNextRow(row)))
+    (*aRows)++;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsARIAGridAccessible::GetRowHeader(nsIAccessibleTable **aRowHeader)
 {
   NS_ENSURE_ARG_POINTER(aRowHeader);
@@ -176,50 +152,21 @@ nsARIAGridAccessible::CellRefAt(PRInt32 
                                 nsIAccessible **aAccessible)
 {
   NS_ENSURE_ARG_POINTER(aAccessible);
   *aAccessible = nsnull;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  PRInt32 rowIdx = aRow + 1;
-  nsCOMPtr<nsIAccessible> row, nextChild;
-  GetFirstChild(getter_AddRefs(row));
-  while (row) {
-    if (nsAccUtils::Role(row) == nsIAccessibleRole::ROLE_ROW)
-      rowIdx--;
-
-    if (rowIdx == 0)
-      break;
-
-    row->GetNextSibling(getter_AddRefs(nextChild));
-    row.swap(nextChild);
-  }
-
-  NS_ENSURE_ARG(row && rowIdx == 0);
+  nsCOMPtr<nsIAccessible> row = GetRowAt(aRow);
+  NS_ENSURE_ARG(row);
 
-  PRInt32 colIdx = aColumn + 1;
-  nsCOMPtr<nsIAccessible> cell;
-  row->GetFirstChild(getter_AddRefs(cell));
-  while (cell) {
-    PRUint32 role = nsAccUtils::Role(cell);
-    if (role == nsIAccessibleRole::ROLE_GRID_CELL ||
-        role == nsIAccessibleRole::ROLE_ROWHEADER ||
-        role == nsIAccessibleRole::ROLE_COLUMNHEADER)
-      colIdx--;
-
-    if (colIdx == 0)
-      break;
-
-    cell->GetNextSibling(getter_AddRefs(nextChild));
-    cell.swap(nextChild);
-  }
-
-  NS_ENSURE_ARG(cell && colIdx == 0);
+  nsCOMPtr<nsIAccessible> cell = GetCellInRowAt(row, aColumn);
+  NS_ENSURE_ARG(cell);
 
   NS_ADDREF(*aAccessible = cell);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsARIAGridAccessible::GetIndexAt(PRInt32 aRow, PRInt32 aColumn, PRInt32 *aIndex)
 {
@@ -356,182 +303,335 @@ nsARIAGridAccessible::IsColumnSelected(P
   NS_ENSURE_ARG_POINTER(aIsSelected);
   *aIsSelected = PR_FALSE;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   NS_ENSURE_ARG(IsValidColumn(aColumn));
 
-  // XXX: should we rely on aria-selected or DOM selection?
-  return NS_ERROR_NOT_IMPLEMENTED;
+  nsCOMPtr<nsIAccessible> row = GetNextRow();
+  if (!row)
+    return NS_OK;
+
+  do {
+    if (!IsARIASelected(row)) {
+      nsCOMPtr<nsIAccessible> cell = GetCellInRowAt(row, aColumn);
+      if (!cell) // Do not fail due to wrong markup
+        return NS_OK;
+      
+      if (!IsARIASelected(cell))
+        return NS_OK;
+    }
+  } while ((row = GetNextRow(row)));
+
+  *aIsSelected = PR_TRUE;
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsARIAGridAccessible::IsRowSelected(PRInt32 aRow, PRBool *aIsSelected)
 {
   NS_ENSURE_ARG_POINTER(aIsSelected);
   *aIsSelected = PR_FALSE;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  NS_ENSURE_ARG(IsValidRow(aRow));
+  nsCOMPtr<nsIAccessible> row = GetRowAt(aRow);
+  NS_ENSURE_ARG(row);
 
-  // XXX: should we rely on aria-selected or DOM selection?
-  return NS_ERROR_NOT_IMPLEMENTED;
+  if (!IsARIASelected(row)) {
+    nsCOMPtr<nsIAccessible> cell;
+    while ((cell = GetNextCellInRow(row, cell))) {
+      if (!IsARIASelected(cell))
+        return NS_OK;
+    }
+  }
+
+  *aIsSelected = PR_TRUE;
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsARIAGridAccessible::IsCellSelected(PRInt32 aRow, PRInt32 aColumn,
                                      PRBool *aIsSelected)
 {
   NS_ENSURE_ARG_POINTER(aIsSelected);
   *aIsSelected = PR_FALSE;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  NS_ENSURE_ARG(IsValidRowNColumn(aRow, aColumn));
+  nsCOMPtr<nsIAccessible> row(GetRowAt(aRow));
+  NS_ENSURE_ARG(row);
+
+  if (!IsARIASelected(row)) {
+    nsCOMPtr<nsIAccessible> cell(GetCellInRowAt(row, aColumn));
+    NS_ENSURE_ARG(cell);
 
-  // XXX: should we rely on aria-selected or DOM selection?
-  return NS_ERROR_NOT_IMPLEMENTED;
+    if (!IsARIASelected(cell))
+      return NS_OK;
+  }
+
+  *aIsSelected = PR_TRUE;
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsARIAGridAccessible::GetSelectedCellsCount(PRUint32* aCount)
 {
   NS_ENSURE_ARG_POINTER(aCount);
   *aCount = 0;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  // XXX: should we rely on aria-selected or DOM selection?
-  return NS_ERROR_NOT_IMPLEMENTED;
+  PRInt32 colCount = 0;
+  GetColumns(&colCount);
+  
+  nsCOMPtr<nsIAccessible> row;
+  while ((row = GetNextRow(row))) {
+    if (IsARIASelected(row)) {
+      (*aCount) += colCount;
+      continue;
+    }
+
+    nsCOMPtr<nsIAccessible> cell;
+    while ((cell = GetNextCellInRow(row, cell))) {
+      if (IsARIASelected(cell))
+        (*aCount)++;
+    }
+  }
+
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsARIAGridAccessible::GetSelectedColumnsCount(PRUint32* aCount)
 {
-  NS_ENSURE_ARG_POINTER(aCount);
-  *aCount = 0;
-
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  // XXX: should we rely on aria-selected or DOM selection?
-  return NS_ERROR_NOT_IMPLEMENTED;
+  return GetSelectedColumnsArray(aCount);
 }
 
 NS_IMETHODIMP
 nsARIAGridAccessible::GetSelectedRowsCount(PRUint32* aCount)
 {
   NS_ENSURE_ARG_POINTER(aCount);
   *aCount = 0;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  // XXX: should we rely on aria-selected or DOM selection?
-  return NS_ERROR_NOT_IMPLEMENTED;
+  nsCOMPtr<nsIAccessible> row;
+  while ((row = GetNextRow(row))) {
+    if (IsARIASelected(row)) {
+      (*aCount)++;
+      continue;
+    }
+
+    nsCOMPtr<nsIAccessible> cell = GetNextCellInRow(row);
+    if (!cell)
+      continue;
+
+    PRBool isRowSelected = PR_TRUE;
+    do {
+      if (!IsARIASelected(cell)) {
+        isRowSelected = PR_FALSE;
+        break;
+      }
+    } while ((cell = GetNextCellInRow(row, cell)));
+
+    if (isRowSelected)
+      (*aCount)++;
+  }
+
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsARIAGridAccessible::GetSelectedCells(PRUint32 *aCellsCount, PRInt32 **aCells)
 {
   NS_ENSURE_ARG_POINTER(aCellsCount);
   *aCellsCount = 0;
   NS_ENSURE_ARG_POINTER(aCells);
   *aCells = nsnull;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  // XXX: should we rely on aria-selected or DOM selection?
-  return NS_ERROR_NOT_IMPLEMENTED;
+  PRInt32 rowCount = 0;
+  GetRows(&rowCount);
+
+  PRInt32 colCount = 0;
+  GetColumns(&colCount);
+
+  nsTArray<PRInt32> selCells(rowCount * colCount);
+
+  nsCOMPtr<nsIAccessible> row;
+  for (PRInt32 rowIdx = 0; row = GetNextRow(row); rowIdx++) {
+    if (IsARIASelected(row)) {
+      for (PRInt32 colIdx = 0; colIdx < colCount; colIdx++)
+        selCells.AppendElement(rowIdx * colCount + colIdx);
+
+      continue;
+    }
+
+    nsCOMPtr<nsIAccessible> cell;
+    for (PRInt32 colIdx = 0; cell = GetNextCellInRow(row, cell); colIdx++) {
+      if (IsARIASelected(cell))
+        selCells.AppendElement(rowIdx * colCount + colIdx);
+    }
+  }
+
+  PRUint32 selCellsCount = selCells.Length();
+  if (!selCellsCount)
+    return NS_OK;
+
+  *aCells = static_cast<PRInt32*>(
+    nsMemory::Clone(selCells.Elements(), selCellsCount * sizeof(PRInt32)));
+  NS_ENSURE_TRUE(*aCells, NS_ERROR_OUT_OF_MEMORY);
+
+  *aCellsCount = selCellsCount;
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsARIAGridAccessible::GetSelectedColumns(PRUint32 *aColumnsCount,
                                          PRInt32 **aColumns)
 {
-  NS_ENSURE_ARG_POINTER(aColumnsCount);
-  *aColumnsCount = 0;
   NS_ENSURE_ARG_POINTER(aColumns);
-  *aColumns = nsnull;
 
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  // XXX: should we rely on aria-selected or DOM selection?
-  return NS_ERROR_NOT_IMPLEMENTED;
+  return GetSelectedColumnsArray(aColumnsCount, aColumns);
 }
 
 NS_IMETHODIMP
 nsARIAGridAccessible::GetSelectedRows(PRUint32 *aRowsCount, PRInt32 **aRows)
 {
   NS_ENSURE_ARG_POINTER(aRowsCount);
   *aRowsCount = 0;
   NS_ENSURE_ARG_POINTER(aRows);
   *aRows = nsnull;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  // XXX: should we rely on aria-selected or DOM selection?
-  return NS_ERROR_NOT_IMPLEMENTED;
+  PRInt32 rowCount = 0;
+  GetRows(&rowCount);
+  if (!rowCount)
+    return NS_OK;
+
+  nsTArray<PRInt32> selRows(rowCount);
+
+  nsCOMPtr<nsIAccessible> row;
+  for (PRInt32 rowIdx = 0; row = GetNextRow(row); rowIdx++) {
+    if (IsARIASelected(row)) {
+      selRows.AppendElement(rowIdx);
+      continue;
+    }
+
+    nsCOMPtr<nsIAccessible> cell = GetNextCellInRow(row);
+    if (!cell)
+      continue;
+
+    PRBool isRowSelected = PR_TRUE;
+    do {
+      if (!IsARIASelected(cell)) {
+        isRowSelected = PR_FALSE;
+        break;
+      }
+    } while ((cell = GetNextCellInRow(row, cell)));
+
+    if (isRowSelected)
+      selRows.AppendElement(rowIdx);
+  }
+
+  PRUint32 selRowsCount = selRows.Length();
+  if (!selRowsCount)
+    return NS_OK;
+
+  *aRows = static_cast<PRInt32*>(
+    nsMemory::Clone(selRows.Elements(), selRowsCount * sizeof(PRInt32)));
+  NS_ENSURE_TRUE(*aRows, NS_ERROR_OUT_OF_MEMORY);
+
+  *aRowsCount = selRowsCount;
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsARIAGridAccessible::SelectRow(PRInt32 aRow)
 {
   NS_ENSURE_ARG(IsValidRow(aRow));
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  // XXX: should we rely on aria-selected or DOM selection?
-  return NS_ERROR_NOT_IMPLEMENTED;
+  nsCOMPtr<nsIAccessible> row;
+  for (PRInt32 rowIdx = 0; row = GetNextRow(row); rowIdx++) {
+    nsresult rv = SetARIASelected(row, rowIdx == aRow);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsARIAGridAccessible::SelectColumn(PRInt32 aColumn)
 {
   NS_ENSURE_ARG(IsValidColumn(aColumn));
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  // XXX: should we rely on aria-selected or DOM selection?
-  return NS_ERROR_NOT_IMPLEMENTED;
+  nsCOMPtr<nsIAccessible> row;
+  while ((row = GetNextRow(row))) {
+    // Unselect all cells in the row.
+    nsresult rv = SetARIASelected(row, PR_FALSE);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    // Select cell at the column index.
+    nsCOMPtr<nsIAccessible> cell = GetCellInRowAt(row, aColumn);
+    if (cell) {
+      rv = SetARIASelected(cell, PR_TRUE);
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
+  }
+
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsARIAGridAccessible::UnselectRow(PRInt32 aRow)
 {
-  NS_ENSURE_ARG(IsValidRow(aRow));
-
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  // XXX: should we rely on aria-selected or DOM selection?
-  return NS_ERROR_NOT_IMPLEMENTED;
+  nsCOMPtr<nsIAccessible> row = GetRowAt(aRow);
+  NS_ENSURE_ARG(row);
+
+  return SetARIASelected(row, PR_FALSE);
 }
 
 NS_IMETHODIMP
 nsARIAGridAccessible::UnselectColumn(PRInt32 aColumn)
 {
   NS_ENSURE_ARG(IsValidColumn(aColumn));
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  // XXX: should we rely on aria-selected or DOM selection?
-  return NS_ERROR_NOT_IMPLEMENTED;
+  nsCOMPtr<nsIAccessible> row;
+  while ((row = GetNextRow(row))) {
+    nsCOMPtr<nsIAccessible> cell = GetCellInRowAt(row, aColumn);
+    if (cell) {
+      nsresult rv = SetARIASelected(cell, PR_FALSE);
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
+  }
+
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsARIAGridAccessible::IsProbablyForLayout(PRBool *aIsProbablyForLayout)
 {
   NS_ENSURE_ARG_POINTER(aIsProbablyForLayout);
   *aIsProbablyForLayout = PR_FALSE;
 
@@ -574,16 +674,238 @@ nsARIAGridAccessible::IsValidRowNColumn(
   if (aRow >= rowCount)
     return PR_FALSE;
 
   PRInt32 colCount = 0;
   GetColumns(&colCount);
   return aColumn < colCount;
 }
 
+already_AddRefed<nsIAccessible>
+nsARIAGridAccessible::GetRowAt(PRInt32 aRow)
+{
+  PRInt32 rowIdx = aRow;
+  nsCOMPtr<nsIAccessible> row(GetNextRow());
+  while (rowIdx != 0 && (row = GetNextRow(row)))
+    rowIdx--;
+
+  return row.forget();
+}
+
+already_AddRefed<nsIAccessible>
+nsARIAGridAccessible::GetCellInRowAt(nsIAccessible *aRow, PRInt32 aColumn)
+{
+  PRInt32 colIdx = aColumn;
+  nsCOMPtr<nsIAccessible> cell(GetNextCellInRow(aRow));
+  while (colIdx != 0 && (cell = GetNextCellInRow(aRow, cell)))
+    colIdx--;
+
+  return cell.forget();
+}
+
+already_AddRefed<nsIAccessible>
+nsARIAGridAccessible::GetNextRow(nsIAccessible *aRow)
+{
+  nsCOMPtr<nsIAccessible> nextRow, tmpAcc;
+  if (!aRow)
+    GetFirstChild(getter_AddRefs(nextRow));
+  else
+    aRow->GetNextSibling(getter_AddRefs(nextRow));
+
+  while (nextRow) {
+    if (nsAccUtils::Role(nextRow) == nsIAccessibleRole::ROLE_ROW)
+      return nextRow.forget();
+
+    nextRow->GetNextSibling(getter_AddRefs(tmpAcc));
+    tmpAcc.swap(nextRow);
+  }
+
+  return nsnull;
+}
+
+already_AddRefed<nsIAccessible>
+nsARIAGridAccessible::GetNextCellInRow(nsIAccessible *aRow, nsIAccessible *aCell)
+{
+  if (!aRow)
+    return nsnull;
+
+  nsCOMPtr<nsIAccessible> nextCell, tmpAcc;
+  if (!aCell)
+    aRow->GetFirstChild(getter_AddRefs(nextCell));
+  else
+    aCell->GetNextSibling(getter_AddRefs(nextCell));
+
+  while (nextCell) {
+    PRUint32 role = nsAccUtils::Role(nextCell);
+    if (role == nsIAccessibleRole::ROLE_GRID_CELL ||
+        role == nsIAccessibleRole::ROLE_ROWHEADER ||
+        role == nsIAccessibleRole::ROLE_COLUMNHEADER)
+      return nextCell.forget();
+
+    nextCell->GetNextSibling(getter_AddRefs(tmpAcc));
+    tmpAcc.swap(nextCell);
+  }
+
+  return nsnull;
+}
+
+PRBool
+nsARIAGridAccessible::IsARIASelected(nsIAccessible *aAccessible)
+{
+  nsRefPtr<nsAccessible> acc = nsAccUtils::QueryAccessible(aAccessible);
+  nsCOMPtr<nsIDOMNode> node;
+  acc->GetDOMNode(getter_AddRefs(node));
+  NS_ASSERTION(node, "No DOM node!");
+
+  if (node) {
+    nsCOMPtr<nsIContent> content(do_QueryInterface(node));
+    if (content->AttrValueIs(kNameSpaceID_None,
+                             nsAccessibilityAtoms::aria_selected,
+                             nsAccessibilityAtoms::_true, eCaseMatters))
+      return PR_TRUE;
+  }
+
+  return PR_FALSE;
+}
+
+nsresult
+nsARIAGridAccessible::SetARIASelected(nsIAccessible *aAccessible,
+                                      PRBool aIsSelected, PRBool aNotify)
+{
+  nsRefPtr<nsAccessible> acc = nsAccUtils::QueryAccessible(aAccessible);
+  nsCOMPtr<nsIDOMNode> node;
+  acc->GetDOMNode(getter_AddRefs(node));
+  NS_ENSURE_STATE(node);
+
+  nsCOMPtr<nsIContent> content(do_QueryInterface(node));
+
+  nsresult rv = NS_OK;
+  if (aIsSelected)
+    rv = content->SetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_selected,
+                          NS_LITERAL_STRING("true"), aNotify);
+  else
+    rv = content->UnsetAttr(kNameSpaceID_None,
+                            nsAccessibilityAtoms::aria_selected, aNotify);
+
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // No "smart" select/unselect for internal call.
+  if (!aNotify)
+    return NS_OK;
+
+  // If row or cell accessible was selected then we're able to not bother about
+  // selection of its cells or its row because our algorithm is row oriented,
+  // i.e. we check selection on row firstly and then on cells.
+  if (aIsSelected)
+    return NS_OK;
+
+  PRUint32 role = nsAccUtils::Role(aAccessible);
+
+  // If the given accessible is row that was unselected then remove
+  // aria-selected from cell accessible.
+  if (role == nsIAccessibleRole::ROLE_ROW) {
+    nsCOMPtr<nsIAccessible> cell;
+    while ((cell = GetNextCellInRow(aAccessible, cell))) {
+      rv = SetARIASelected(cell, PR_FALSE, PR_FALSE);
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
+    return NS_OK;
+  }
+
+  // If the given accessible is cell that was unselected and its row is selected
+  // then remove aria-selected from row and put aria-selected on
+  // siblings cells.
+  if (role == nsIAccessibleRole::ROLE_GRID_CELL ||
+      role == nsIAccessibleRole::ROLE_ROWHEADER ||
+      role == nsIAccessibleRole::ROLE_COLUMNHEADER) {
+    nsCOMPtr<nsIAccessible> row;
+    aAccessible->GetParent(getter_AddRefs(row));
+
+    if (nsAccUtils::Role(row) == nsIAccessibleRole::ROLE_ROW &&
+        IsARIASelected(row)) {
+      rv = SetARIASelected(row, PR_FALSE, PR_FALSE);
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      nsCOMPtr<nsIAccessible> cell;
+      while ((cell = GetNextCellInRow(row, cell))) {
+        if (cell != aAccessible) {
+          rv = SetARIASelected(cell, PR_TRUE, PR_FALSE);
+          NS_ENSURE_SUCCESS(rv, rv);
+        }
+      }
+    }
+  }
+
+  return NS_OK;
+}
+
+nsresult
+nsARIAGridAccessible::GetSelectedColumnsArray(PRUint32 *aColumnsCount,
+                                              PRInt32 **aColumns)
+{
+  NS_ENSURE_ARG_POINTER(aColumnsCount);
+  *aColumnsCount = 0;
+  if (aColumns)
+    *aColumns = nsnull;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  nsCOMPtr<nsIAccessible> row = GetNextRow();
+  if (!row)
+    return NS_OK;
+
+  PRInt32 colCount = 0;
+  GetColumns(&colCount);
+  if (!colCount)
+    return NS_OK;
+
+  PRInt32 selColCount = colCount;
+
+  nsTArray<PRBool> isColSelArray(selColCount);
+  isColSelArray.AppendElements(selColCount);
+  for (PRInt32 i = 0; i < selColCount; i++)
+    isColSelArray[i] = PR_TRUE;
+
+  do {
+    if (IsARIASelected(row))
+      continue;
+
+    PRInt32 colIdx = 0;
+    nsCOMPtr<nsIAccessible> cell;
+    for (colIdx = 0; cell = GetNextCellInRow(row, cell); colIdx++) {
+      if (isColSelArray.SafeElementAt(colIdx, PR_FALSE) &&
+          !IsARIASelected(cell)) {
+        isColSelArray[colIdx] = PR_FALSE;
+        selColCount--;
+      }
+    }
+  } while ((row = GetNextRow(row)));
+
+  if (!selColCount)
+    return NS_OK;
+
+  if (!aColumns) {
+    *aColumnsCount = selColCount;
+    return NS_OK;
+  }
+
+  *aColumns = static_cast<PRInt32*>(
+    nsMemory::Alloc(selColCount * sizeof(PRInt32)));
+  NS_ENSURE_TRUE(*aColumns, NS_ERROR_OUT_OF_MEMORY);
+
+  *aColumnsCount = selColCount;
+  for (PRInt32 colIdx = 0, idx = 0; colIdx < colCount; colIdx++) {
+    if (isColSelArray[colIdx])
+      (*aColumns)[idx++] = colIdx;
+  }
+
+  return NS_OK;
+}
+
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsARIAGridCellAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // Constructor
--- a/accessible/src/base/nsARIAGridAccessible.h
+++ b/accessible/src/base/nsARIAGridAccessible.h
@@ -54,21 +54,85 @@ public:
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessibleTable
   NS_DECL_NSIACCESSIBLETABLE
 
 protected:
+  /**
+   * Return true if the given row index is valid.
+   */
   PRBool IsValidRow(PRInt32 aRow);
+
+  /**
+   * Retrn true if the given column index is valid.
+   */
   PRBool IsValidColumn(PRInt32 aColumn);
+
+  /**
+   * Retrun true if given row and column indexes are valid.
+   */
   PRBool IsValidRowNColumn(PRInt32 aRow, PRInt32 aColumn);
+
+  /**
+   * Return row accessible at the given row index.
+   */
+  already_AddRefed<nsIAccessible> GetRowAt(PRInt32 aRow);
+
+  /**
+   * Return cell accessible at the given column index in the row.
+   */
+  already_AddRefed<nsIAccessible> GetCellInRowAt(nsIAccessible *aRow,
+                                                 PRInt32 aColumn);
+
+  /**
+   * Return next row accessible relative given row accessible or first row
+   * accessible if it is null.
+   *
+   * @param  aRow  [in, optional] row accessible
+   */
+  already_AddRefed<nsIAccessible> GetNextRow(nsIAccessible *aRow = nsnull);
+
+  /**
+   * Return next cell accessible relative given cell accessible or first cell
+   * in the given row accessible if given cell accessible is null.
+   *
+   * @param  aRow   [in] row accessible
+   * @param  aCell  [in, optional] cell accessible
+   */
+  already_AddRefed<nsIAccessible> GetNextCellInRow(nsIAccessible *aRow,
+                                                   nsIAccessible *aCell = nsnull);
+
+  /**
+   * Return true if the DOM node of given accessible has aria-selected="true"
+   * attribute.
+   */
+  PRBool IsARIASelected(nsIAccessible *aAccessible);
+
+  /**
+   * Set aria-selected attribute value on DOM node of the given accessible.
+   *
+   * @param  aAccessible  [in] accessible
+   * @param  aIsSelected  [in] new value of aria-selected attribute
+   * @param  aNotify      [in, optional] specifies if DOM should be notified
+   *                       about attribute change (used internally).
+   */
+  nsresult SetARIASelected(nsIAccessible *aAccessible, PRBool aIsSelected,
+                           PRBool aNotify = PR_TRUE);
+
+  /**
+   * Helper method for GetSelectedColumnsCount and GetSelectedColumns.
+   */
+  nsresult GetSelectedColumnsArray(PRUint32 *aColumnsCount,
+                                   PRInt32 **aColumns = nsnull);
 };
 
+
 /**
  * Accessible for ARIA gridcell and rowheader/columnheader.
  */
 class nsARIAGridCellAccessible : public nsHyperTextAccessibleWrap
 {
 public:
   nsARIAGridCellAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
 
--- a/accessible/src/base/nsARIAMap.cpp
+++ b/accessible/src/base/nsARIAMap.cpp
@@ -58,518 +58,569 @@
 
 static const nsStateMapEntry kEndEntry = {nsnull, 0, 0};  // To fill in array of state mappings
 
 nsRoleMapEntry nsARIAMap::gWAIRoleMap[] = 
 {
   {
     "alert",
     nsIAccessibleRole::ROLE_ALERT,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "alertdialog",
     nsIAccessibleRole::ROLE_DIALOG,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "application",
     nsIAccessibleRole::ROLE_APPLICATION,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "article",
     nsIAccessibleRole::ROLE_DOCUMENT,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     nsIAccessibleStates::STATE_READONLY,
     kEndEntry
   },
   {
     "button",
     nsIAccessibleRole::ROLE_PUSHBUTTON,
+    kUseMapRole,
     eNoValue,
     eClickAction,
     eNoLiveAttr,
     kNoReqStates,
     {&nsAccessibilityAtoms::aria_pressed, kBoolState, nsIAccessibleStates::STATE_PRESSED | nsIAccessibleStates::STATE_CHECKABLE},
     {&nsAccessibilityAtoms::aria_pressed, "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
     kEndEntry
   },
   {
     "checkbox",
     nsIAccessibleRole::ROLE_CHECKBUTTON,
+    kUseMapRole,
     eNoValue,
     eCheckUncheckAction,
     eNoLiveAttr,
     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,
+    kUseMapRole,
     eNoValue,
     eSortAction,
     eNoLiveAttr,
     kNoReqStates,
     {&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
     {&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
     {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
     kEndEntry
   },
   {
     "combobox",
     nsIAccessibleRole::ROLE_COMBOBOX,
+    kUseMapRole,
     eHasValueMinMax,
     eOpenCloseAction,
     eNoLiveAttr,
     nsIAccessibleStates::STATE_COLLAPSED | nsIAccessibleStates::STATE_HASPOPUP,
     // Manually map EXT_STATE_SUPPORTS_AUTOCOMPLETION aria-autocomplete
     {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
     kEndEntry
   },
   {
     "dialog",
     nsIAccessibleRole::ROLE_DIALOG,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "document",
     nsIAccessibleRole::ROLE_DOCUMENT,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     nsIAccessibleStates::STATE_READONLY,
     kEndEntry
   },
   {
     "grid",
     nsIAccessibleRole::ROLE_TABLE,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     nsIAccessibleStates::STATE_FOCUSABLE,
     {&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
     {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
     kEndEntry
   },
   {
     "gridcell",
     nsIAccessibleRole::ROLE_GRID_CELL,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     {&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
     {&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
     {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
     kEndEntry
   },
   {
     "group",
     nsIAccessibleRole::ROLE_GROUPING,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "heading",
     nsIAccessibleRole::ROLE_HEADING,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "img",
     nsIAccessibleRole::ROLE_GRAPHIC,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "label",
     nsIAccessibleRole::ROLE_LABEL,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "link",
     nsIAccessibleRole::ROLE_LINK,
+    kUseMapRole,
     eNoValue,
     eJumpAction,
     eNoLiveAttr,
     nsIAccessibleStates::STATE_LINKED,
     kEndEntry
   },
   {
     "list",
     nsIAccessibleRole::ROLE_LIST,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     nsIAccessibleStates::STATE_READONLY,
     {&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
     kEndEntry
   },
   {
     "listbox",
     nsIAccessibleRole::ROLE_LISTBOX,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
     {&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
     kEndEntry
   },
   {
     "listitem",
     nsIAccessibleRole::ROLE_LISTITEM,
+    kUseMapRole,
     eNoValue,
     eNoAction, // XXX: should depend on state, parent accessible
     eNoLiveAttr,
     nsIAccessibleStates::STATE_READONLY,
     {&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
     {&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
     {&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
     {&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
     {&nsAccessibilityAtoms::aria_checked, "false", nsIAccessibleStates::STATE_CHECKABLE},
     kEndEntry
   },
   {
     "log",
     nsIAccessibleRole::ROLE_NOTHING,
+    kUseNativeRole,
     eNoValue,
     eNoAction,
     ePoliteLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "marquee",
     nsIAccessibleRole::ROLE_NOTHING,
+    kUseNativeRole,
     eNoValue,
     eNoAction,
     eOffLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "math",
     nsIAccessibleRole::ROLE_FLAT_EQUATION,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "menu",
     nsIAccessibleRole::ROLE_MENUPOPUP,
+    kUseMapRole,
     eNoValue,
     eNoAction, // XXX: technically accessibles of menupopup role haven't
                // any action, but menu can be open or close.
     eNoLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "menubar",
     nsIAccessibleRole::ROLE_MENUBAR,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "menuitem",
     nsIAccessibleRole::ROLE_MENUITEM,
+    kUseMapRole,
     eNoValue,
     eClickAction,
     eNoLiveAttr,
     kNoReqStates,
     {&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
     {&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
     {&nsAccessibilityAtoms::aria_checked, "false", nsIAccessibleStates::STATE_CHECKABLE},
     kEndEntry
   },
   {
     "menuitemcheckbox",
     nsIAccessibleRole::ROLE_CHECK_MENU_ITEM,
+    kUseMapRole,
     eNoValue,
     eClickAction,
     eNoLiveAttr,
     nsIAccessibleStates::STATE_CHECKABLE,
     {&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED },
     {&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED},
     kEndEntry
   },
   {
     "menuitemradio",
     nsIAccessibleRole::ROLE_RADIO_MENU_ITEM,
+    kUseMapRole,
     eNoValue,
     eClickAction,
     eNoLiveAttr,
     nsIAccessibleStates::STATE_CHECKABLE,
     {&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED },
     kEndEntry
   },
   {
     "option",
     nsIAccessibleRole::ROLE_OPTION,
+    kUseMapRole,
     eNoValue,
     eSelectAction,
     eNoLiveAttr,
     kNoReqStates,
     {&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
     {&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
     {&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
     {&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
     {&nsAccessibilityAtoms::aria_checked, "false", nsIAccessibleStates::STATE_CHECKABLE},
     kEndEntry
   },
   {
     "presentation",
     nsIAccessibleRole::ROLE_NOTHING,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "progressbar",
     nsIAccessibleRole::ROLE_PROGRESSBAR,
+    kUseMapRole,
     eHasValueMinMax,
     eNoAction,
     eNoLiveAttr,
     nsIAccessibleStates::STATE_READONLY,
     kEndEntry
   },
   {
     "radio",
     nsIAccessibleRole::ROLE_RADIOBUTTON,
+    kUseMapRole,
     eNoValue,
     eSelectAction,
     eNoLiveAttr,
     nsIAccessibleStates::STATE_CHECKABLE,
     {&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED},
     kEndEntry
   },
   {
     "radiogroup",
     nsIAccessibleRole::ROLE_GROUPING,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "region",
     nsIAccessibleRole::ROLE_PANE,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "row",
     nsIAccessibleRole::ROLE_ROW,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     {&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
     {&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
     kEndEntry
   },
   {
     "rowheader",
     nsIAccessibleRole::ROLE_ROWHEADER,
+    kUseMapRole,
     eNoValue,
     eSortAction,
     eNoLiveAttr,
     kNoReqStates,
     {&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
     {&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
     {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
     kEndEntry
   },
   {
     "section",
     nsIAccessibleRole::ROLE_SECTION,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "separator",
     nsIAccessibleRole::ROLE_SEPARATOR,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "slider",
     nsIAccessibleRole::ROLE_SLIDER,
+    kUseMapRole,
     eHasValueMinMax,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
     kEndEntry
   },
   {
     "spinbutton",
     nsIAccessibleRole::ROLE_SPINBUTTON,
+    kUseMapRole,
     eHasValueMinMax,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
     kEndEntry
   },
   {
     "status",
     nsIAccessibleRole::ROLE_STATUSBAR,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     ePoliteLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "tab",
     nsIAccessibleRole::ROLE_PAGETAB,
+    kUseMapRole,
     eNoValue,
     eSwitchAction,
     eNoLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "tablist",
     nsIAccessibleRole::ROLE_PAGETABLIST,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     ePoliteLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "tabpanel",
     nsIAccessibleRole::ROLE_PROPERTYPAGE,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "textbox",
     nsIAccessibleRole::ROLE_ENTRY,
+    kUseMapRole,
     eNoValue,
     eActivateAction,
     eNoLiveAttr,
     kNoReqStates,
     // Manually map EXT_STATE_SINGLE_LINE and EXT_STATE_MULTI_LINE FROM aria-multiline
     // Manually map EXT_STATE_SUPPORTS_AUTOCOMPLETION aria-autocomplete
     {&nsAccessibilityAtoms::aria_autocomplete, "list", nsIAccessibleStates::STATE_HASPOPUP},
     {&nsAccessibilityAtoms::aria_autocomplete, "both", nsIAccessibleStates::STATE_HASPOPUP},
     {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
     kEndEntry
   },
   {
     "timer",
     nsIAccessibleRole::ROLE_NOTHING,
+    kUseNativeRole,
     eNoValue,
     eNoAction,
     eOffLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "toolbar",
     nsIAccessibleRole::ROLE_TOOLBAR,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "tooltip",
     nsIAccessibleRole::ROLE_TOOLTIP,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     kEndEntry
   },
   {
     "tree",
     nsIAccessibleRole::ROLE_OUTLINE,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
     {&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
     kEndEntry
   },
   {
     "treegrid",
     nsIAccessibleRole::ROLE_TREE_TABLE,
+    kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
     {&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
     kEndEntry
   },
   {
     "treeitem",
     nsIAccessibleRole::ROLE_OUTLINEITEM,
+    kUseMapRole,
     eNoValue,
     eActivateAction, // XXX: should expose second 'expand/collapse' action based
                      // on states
     eNoLiveAttr,
     kNoReqStates,
     {&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
     {&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
     {&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
@@ -579,26 +630,28 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] 
   }
 };
 
 PRUint32 nsARIAMap::gWAIRoleMapLength = NS_ARRAY_LENGTH(nsARIAMap::gWAIRoleMap);
 
 nsRoleMapEntry nsARIAMap::gLandmarkRoleMap = {
   "",
   nsIAccessibleRole::ROLE_NOTHING,
+  kUseNativeRole,
   eNoValue,
   eNoAction,
   eNoLiveAttr,
   kNoReqStates,
   kEndEntry
 };
 
 nsRoleMapEntry nsARIAMap::gEmptyRoleMap = {
   "",
   nsIAccessibleRole::ROLE_NOTHING,
+  kUseMapRole,
   eNoValue,
   eNoAction,
   eNoLiveAttr,
   kNoReqStates,
   kEndEntry
 };
 
 /**
--- a/accessible/src/base/nsARIAMap.h
+++ b/accessible/src/base/nsARIAMap.h
@@ -67,16 +67,20 @@ enum EActionRule
 
 enum ELiveAttrRule
 {
   eNoLiveAttr,
   eOffLiveAttr,
   ePoliteLiveAttr
 };
 
+// Role mapping rule
+const PRBool kUseMapRole = PR_TRUE;
+const PRBool kUseNativeRole = PR_FALSE;
+
 // ARIA attribute characteristic masks, grow as needed
 
 /**
  * This mask indicates the attribute should not be exposed as an object
  * attribute via the catch-all logic in nsAccessible::GetAttributes.
  * This means it either isn't mean't to be exposed as an object attribute, or
  * that it should, but is already handled in other code.
  */
@@ -114,16 +118,19 @@ struct nsAttributeCharacteristics
 struct nsRoleMapEntry
 {
   // ARIA role: string representation such as "button"
   const char *roleString;
   
   // Role mapping rule: maps to this nsIAccessibleRole
   PRUint32 role;
   
+  // Role rule: whether to use mapped role or native semantics
+  PRBool roleRule;
+  
   // Value mapping rule: how to compute nsIAccessible value
   EValueRule valueRule;
 
   // Action mapping rule, how to expose nsIAccessible action
   EActionRule actionRule;
 
   // 'live' and 'container-live' object attributes mapping rule: how to expose
   // these object attributes if ARIA 'live' attribute is missed.
--- a/accessible/src/base/nsAccUtils.cpp
+++ b/accessible/src/base/nsAccUtils.cpp
@@ -36,17 +36,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsCoreUtils.h"
 #include "nsAccUtils.h"
 
 #include "nsIAccessibleStates.h"
 #include "nsIAccessibleTypes.h"
-#include "nsPIAccessible.h"
 
 #include "nsAccessibleEventData.h"
 #include "nsHyperTextAccessible.h"
 #include "nsHTMLTableAccessible.h"
 #include "nsAccessibilityAtoms.h"
 #include "nsAccessibleTreeWalker.h"
 #include "nsAccessible.h"
 #include "nsARIAMap.h"
@@ -275,30 +274,33 @@ nsAccUtils::SetLiveContainerAttributes(n
   while (ancestor) {
 
     // container-relevant attribute
     if (relevant.IsEmpty() &&
         nsAccUtils::HasDefinedARIAToken(ancestor, nsAccessibilityAtoms::aria_relevant) &&
         ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_relevant, relevant))
       SetAccAttr(aAttributes, nsAccessibilityAtoms::containerRelevant, relevant);
 
-    // container-live attribute
+    // container-live, and container-live-role attributes
     if (live.IsEmpty()) {
+      nsCOMPtr<nsIDOMNode> node(do_QueryInterface(ancestor));
+      nsRoleMapEntry *role = GetRoleMapEntry(node);
       if (nsAccUtils::HasDefinedARIAToken(ancestor,
                                           nsAccessibilityAtoms::aria_live)) {
         ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_live,
                           live);
+      } else if (role) {
+        GetLiveAttrValue(role->liveAttRule, live);
+      }
+      if (!live.IsEmpty()) {
         SetAccAttr(aAttributes, nsAccessibilityAtoms::containerLive, live);
-      } else {
-        nsCOMPtr<nsIDOMNode> node(do_QueryInterface(ancestor));
-        nsRoleMapEntry *role = GetRoleMapEntry(node);
         if (role) {
-          nsAutoString live;
-          GetLiveAttrValue(role->liveAttRule, live);
-          SetAccAttr(aAttributes, nsAccessibilityAtoms::containerLive, live);
+          nsAccUtils::SetAccAttr(aAttributes,
+                                 nsAccessibilityAtoms::containerLiveRole,
+                                 NS_ConvertASCIItoUTF16(role->roleString));
         }
       }
     }
 
     // container-atomic attribute
     if (atomic.IsEmpty() &&
         nsAccUtils::HasDefinedARIAToken(ancestor, nsAccessibilityAtoms::aria_atomic) &&
         ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_atomic, atomic))
@@ -335,24 +337,23 @@ nsAccUtils::HasDefinedARIAToken(nsIConte
 }
 
 nsresult
 nsAccUtils::FireAccEvent(PRUint32 aEventType, nsIAccessible *aAccessible,
                          PRBool aIsAsynch)
 {
   NS_ENSURE_ARG(aAccessible);
 
-  nsCOMPtr<nsPIAccessible> pAccessible(do_QueryInterface(aAccessible));
-  NS_ASSERTION(pAccessible, "Accessible doesn't implement nsPIAccessible");
+  nsRefPtr<nsAccessible> acc(nsAccUtils::QueryAccessible(aAccessible));
 
   nsCOMPtr<nsIAccessibleEvent> event =
     new nsAccEvent(aEventType, aAccessible, aIsAsynch);
   NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
 
-  return pAccessible->FireAccessibleEvent(event);
+  return acc->FireAccessibleEvent(event);
 }
 
 PRBool
 nsAccUtils::HasAccessibleChildren(nsIDOMNode *aNode)
 {
   if (!aNode)
     return PR_FALSE;
 
@@ -714,21 +715,31 @@ nsAccUtils::GetLiveAttrValue(PRUint32 aR
       aValue = NS_LITERAL_STRING("polite");
       break;
   }
 }
 
 already_AddRefed<nsAccessible>
 nsAccUtils::QueryAccessible(nsIAccessible *aAccessible)
 {
-  nsAccessible* accessible = nsnull;
+  nsAccessible* acc = nsnull;
   if (aAccessible)
-    CallQueryInterface(aAccessible, &accessible);
-  
-  return accessible;
+    CallQueryInterface(aAccessible, &acc);
+
+  return acc;
+}
+
+already_AddRefed<nsAccessible>
+nsAccUtils::QueryAccessible(nsIAccessNode *aAccessNode)
+{
+  nsAccessible* acc = nsnull;
+  if (aAccessNode)
+    CallQueryInterface(aAccessNode, &acc);
+
+  return acc;
 }
 
 already_AddRefed<nsHTMLTableAccessible>
 nsAccUtils::QueryAccessibleTable(nsIAccessibleTable *aAccessibleTable)
 {
   nsHTMLTableAccessible* accessible = nsnull;
   if (aAccessibleTable)
     CallQueryInterface(aAccessibleTable, &accessible);
@@ -792,20 +803,20 @@ nsAccUtils::TextLength(nsIAccessible *aA
       return NS_SUCCEEDED(rv) ? static_cast<PRInt32>(length) : -1;
     }
   }
   
   // For list bullets (or anything other accessible which would compute its own
   // text. They don't have their own frame.
   // XXX In the future, list bullets may have frame and anon content, so 
   // we should be able to remove this at that point
-  nsCOMPtr<nsPIAccessible> pAcc(do_QueryInterface(aAccessible));
-  
+  nsRefPtr<nsAccessible> acc(nsAccUtils::QueryAccessible(aAccessible));
+
   nsAutoString text;
-  pAcc->AppendTextTo(text, 0, PR_UINT32_MAX); // Get all the text
+  acc->AppendTextTo(text, 0, PR_UINT32_MAX); // Get all the text
   return text.Length();
 }
 
 PRBool
 nsAccUtils::MustPrune(nsIAccessible *aAccessible)
 { 
   PRUint32 role = nsAccUtils::Role(aAccessible);
 
--- a/accessible/src/base/nsAccUtils.h
+++ b/accessible/src/base/nsAccUtils.h
@@ -325,16 +325,22 @@ public:
 
   /**
    * Query nsAccessible from the given nsIAccessible.
    */
   static already_AddRefed<nsAccessible>
     QueryAccessible(nsIAccessible *aAccessible);
 
   /**
+   * Query nsAccessible from the given nsIAccessNode.
+   */
+  static already_AddRefed<nsAccessible>
+    QueryAccessible(nsIAccessNode *aAccessNode);
+
+  /**
    * Query nsHTMLTableAccessible from the given nsIAccessibleTable.
    */
   static already_AddRefed<nsHTMLTableAccessible>
     QueryAccessibleTable(nsIAccessibleTable *aAccessibleTable);
   
 #ifdef DEBUG_A11Y
   /**
    * Detect whether the given accessible object implements nsIAccessibleText,
--- a/accessible/src/base/nsAccessNode.cpp
+++ b/accessible/src/base/nsAccessNode.cpp
@@ -61,17 +61,17 @@
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
 #include "nsIServiceManager.h"
 #include "nsIStringBundle.h"
 #include "nsITimer.h"
 #include "nsRootAccessible.h"
-#include "nsIFocusController.h"
+#include "nsFocusManager.h"
 #include "nsIObserverService.h"
 
 #ifdef MOZ_ACCESSIBILITY_ATK
 #include "nsAppRootAccessible.h"
 #else
 #include "nsApplicationAccessibleWrap.h"
 #endif
 
@@ -771,43 +771,34 @@ nsAccessNode::ClearCache(nsAccessNodeHas
 
 already_AddRefed<nsIDOMNode> nsAccessNode::GetCurrentFocus()
 {
   nsCOMPtr<nsIPresShell> shell = nsCoreUtils::GetPresShellFor(mDOMNode);
   NS_ENSURE_TRUE(shell, nsnull);
   nsCOMPtr<nsIDocument> doc = shell->GetDocument();
   NS_ENSURE_TRUE(doc, nsnull);
 
-  nsCOMPtr<nsPIDOMWindow> privateDOMWindow(do_QueryInterface(doc->GetWindow()));
-  if (!privateDOMWindow) {
-    return nsnull;
-  }
-  nsIFocusController *focusController = privateDOMWindow->GetRootFocusController();
-  if (!focusController) {
-    return nsnull;
-  }
+  nsIDOMWindow* win = doc->GetWindow();
+
+  nsCOMPtr<nsIDOMWindow> focusedWindow;
   nsCOMPtr<nsIDOMElement> focusedElement;
-  focusController->GetFocusedElement(getter_AddRefs(focusedElement));
+  nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
+  if (fm)
+    fm->GetFocusedElementForWindow(win, PR_TRUE, getter_AddRefs(focusedWindow),
+                                   getter_AddRefs(focusedElement));
+
   nsIDOMNode *focusedNode = nsnull;
-  if (!focusedElement) {
-    // Document itself has focus
-    nsCOMPtr<nsIDOMWindowInternal> focusedWinInternal;
-    focusController->GetFocusedWindow(getter_AddRefs(focusedWinInternal));
-    if (!focusedWinInternal) {
-      return nsnull;
-    }
-    nsCOMPtr<nsIDOMDocument> focusedDOMDocument;
-    focusedWinInternal->GetDocument(getter_AddRefs(focusedDOMDocument));
-    if (!focusedDOMDocument) {
-      return nsnull;
-    }
-    focusedDOMDocument->QueryInterface(NS_GET_IID(nsIDOMNode), (void**)&focusedNode);
+  if (focusedElement) {
+    CallQueryInterface(focusedElement, &focusedNode);
   }
-  else {
-    focusedElement->QueryInterface(NS_GET_IID(nsIDOMNode), (void**)&focusedNode);
+  else if (focusedWindow) {
+    nsCOMPtr<nsIDOMDocument> doc;
+    focusedWindow->GetDocument(getter_AddRefs(doc));
+    if (doc)
+      CallQueryInterface(doc, &focusedNode);
   }
 
   return focusedNode;
 }
 
 NS_IMETHODIMP
 nsAccessNode::GetLanguage(nsAString& aLanguage)
 {
--- a/accessible/src/base/nsAccessibilityAtomList.h
+++ b/accessible/src/base/nsAccessibilityAtomList.h
@@ -159,16 +159,17 @@ 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(_class, "class")
 ACCESSIBILITY_ATOM(cycles, "cycles") // used for XUL cycler attribute
 ACCESSIBILITY_ATOM(curpos, "curpos") // XUL
 ACCESSIBILITY_ATOM(data, "data")
+ACCESSIBILITY_ATOM(draggable, "draggable")
 ACCESSIBILITY_ATOM(droppable, "droppable")   // XUL combo box
 ACCESSIBILITY_ATOM(editable, "editable")
 ACCESSIBILITY_ATOM(_for, "for")
 ACCESSIBILITY_ATOM(headers, "headers")   // HTML table
 ACCESSIBILITY_ATOM(hidden, "hidden")   // XUL tree columns
 ACCESSIBILITY_ATOM(href, "href") // XUL, XLink
 ACCESSIBILITY_ATOM(increment, "increment") // XUL
 ACCESSIBILITY_ATOM(lang, "lang")
@@ -254,14 +255,15 @@ ACCESSIBILITY_ATOM(aria_valuetext, "aria
 // of an HTML button from the button frame
 ACCESSIBILITY_ATOM(defaultLabel, "defaultLabel")
 
 // Object attributes
 ACCESSIBILITY_ATOM(tableCellIndex, "table-cell-index")
 ACCESSIBILITY_ATOM(containerAtomic, "container-atomic")
 ACCESSIBILITY_ATOM(containerBusy, "container-busy")
 ACCESSIBILITY_ATOM(containerLive, "container-live")
+ACCESSIBILITY_ATOM(containerLiveRole, "container-live-role")
 ACCESSIBILITY_ATOM(containerRelevant, "container-relevant")
 ACCESSIBILITY_ATOM(level, "level")
 ACCESSIBILITY_ATOM(live, "live")
 ACCESSIBILITY_ATOM(lineNumber, "line-number")
 ACCESSIBILITY_ATOM(posinset, "posinset") 
 ACCESSIBILITY_ATOM(setsize, "setsize")
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -36,17 +36,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 // NOTE: alphabetically ordered
 #include "nsAccessibilityAtoms.h"
 #include "nsAccessibilityService.h"
 #include "nsCoreUtils.h"
 #include "nsAccUtils.h"
-#include "nsARIAGridAccessible.h"
+#include "nsARIAGridAccessibleWrap.h"
 #include "nsARIAMap.h"
 #include "nsIContentViewer.h"
 #include "nsCURILoader.h"
 #include "nsDocAccessible.h"
 #include "nsHTMLImageAccessibleWrap.h"
 #include "nsHTMLLinkAccessible.h"
 #include "nsHTMLSelectAccessible.h"
 #include "nsHTMLTableAccessibleWrap.h"
@@ -453,22 +453,21 @@ nsAccessibilityService::CreateRootAccess
     *aRootAcc = new nsDocAccessibleWrap(rootNode, weakShell);
   }
   else {
     *aRootAcc = new nsRootAccessibleWrap(rootNode, weakShell);
   }
   if (!*aRootAcc)
     return NS_ERROR_OUT_OF_MEMORY;
 
-  nsRefPtr<nsAccessNode> rootAcc = nsAccUtils::QueryAccessNode(*aRootAcc);
+  nsRefPtr<nsAccessible> rootAcc = nsAccUtils::QueryAccessible(*aRootAcc);
   rootAcc->Init();
 
   nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(rootNode);
-  nsCOMPtr<nsPIAccessible> privateAccessible(do_QueryInterface(*aRootAcc));
-  privateAccessible->SetRoleMapEntry(roleMapEntry);
+  rootAcc->SetRoleMapEntry(roleMapEntry);
 
   NS_ADDREF(*aRootAcc);
 
   return NS_OK;
 }
 
  /**
    * HTML widget creation
@@ -553,16 +552,20 @@ nsAccessibilityService::CreateHTMLAccess
 #ifndef MOZ_ACCESSIBILITY_ATK
            tag == nsAccessibilityAtoms::tbody ||
            tag == nsAccessibilityAtoms::tfoot ||
            tag == nsAccessibilityAtoms::thead ||
 #endif
            tag == nsAccessibilityAtoms::q) {
     return CreateHyperTextAccessible(aFrame, aAccessible);
   }
+  else if (tag == nsAccessibilityAtoms::tr) {
+    *aAccessible = new nsEnumRoleAccessible(aNode, aWeakShell,
+                                            nsIAccessibleRole::ROLE_ROW);
+  }
   else if (nsCoreUtils::IsHTMLTableHeader(content)) {
     *aAccessible = new nsHTMLTableHeaderAccessible(aNode, aWeakShell);
   }
 
   NS_IF_ADDREF(*aAccessible);
   return NS_OK;
 }
 
@@ -1257,23 +1260,21 @@ nsresult nsAccessibilityService::InitAcc
                                                 nsIAccessible **aAccessibleOut,
                                                 nsRoleMapEntry *aRoleMapEntry)
 {
   if (!aAccessibleIn) {
     return NS_ERROR_FAILURE; // No accessible to init
   }
   NS_ASSERTION(aAccessibleOut && !*aAccessibleOut, "Out param should already be cleared out");
 
-  nsRefPtr<nsAccessNode> acc = nsAccUtils::QueryAccessNode(aAccessibleIn);
+  nsRefPtr<nsAccessible> acc = nsAccUtils::QueryAccessible(aAccessibleIn);
   nsresult rv = acc->Init(); // Add to cache, etc.
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsPIAccessible> privateAccessible =
-    do_QueryInterface(aAccessibleIn);
-  privateAccessible->SetRoleMapEntry(aRoleMapEntry);
+  acc->SetRoleMapEntry(aRoleMapEntry);
   NS_ADDREF(*aAccessibleOut = aAccessibleIn);
 
   return NS_OK;
 }
 
 static PRBool HasRelatedContent(nsIContent *aContent)
 {
   nsAutoString id;
@@ -1545,26 +1546,31 @@ NS_IMETHODIMP nsAccessibilityService::Ge
           break;
         }
       }
 
       if (!tableContent)
         tryTagNameOrFrame = PR_FALSE;
     }
 
-    if (roleMapEntry && (!partOfHTMLTable || !tryTagNameOrFrame ||
-        frameType != nsAccessibilityAtoms::tableOuterFrame)) {
-      // Try to create ARIA grid/treegrid accessibles.
-      if (roleMapEntry->role == nsIAccessibleRole::ROLE_TABLE ||
-          roleMapEntry->role == nsIAccessibleRole::ROLE_TREE_TABLE) {
-        newAcc = new nsARIAGridAccessible(aNode, aWeakShell);
-      } else if (roleMapEntry->role == nsIAccessibleRole::ROLE_GRID_CELL ||
-                 roleMapEntry->role == nsIAccessibleRole::ROLE_ROWHEADER ||
-                 roleMapEntry->role == nsIAccessibleRole::ROLE_COLUMNHEADER) {
-        newAcc = new nsARIAGridCellAccessible(aNode, aWeakShell);
+    if (roleMapEntry) {
+      // Create ARIA grid/treegrid accessibles if node is not of a child or
+      // valid child of HTML table and is not a HTML table.
+      if ((!partOfHTMLTable || !tryTagNameOrFrame) &&
+          frameType != nsAccessibilityAtoms::tableOuterFrame) {
+
+        if (roleMapEntry->role == nsIAccessibleRole::ROLE_TABLE ||
+            roleMapEntry->role == nsIAccessibleRole::ROLE_TREE_TABLE) {
+          newAcc = new nsARIAGridAccessibleWrap(aNode, aWeakShell);
+
+        } else if (roleMapEntry->role == nsIAccessibleRole::ROLE_GRID_CELL ||
+            roleMapEntry->role == nsIAccessibleRole::ROLE_ROWHEADER ||
+            roleMapEntry->role == nsIAccessibleRole::ROLE_COLUMNHEADER) {
+          newAcc = new nsARIAGridCellAccessible(aNode, aWeakShell);
+        }
       }
     }
 
     if (!newAcc && tryTagNameOrFrame) {
       // Prefer to use markup (mostly tag name, perhaps attributes) to
       // decide if and what kind of accessible to create.
       // The method creates accessibles for table related content too therefore
       // we do not call it if accessibles for table related content are
@@ -1710,20 +1716,19 @@ nsAccessibilityService::GetRelevantConte
       nsCOMPtr<nsIDOMNode> bindingNode(do_QueryInterface(bindingParent));
       if (bindingNode) {
         // Try to get an accessible by type since XBL widget can be accessible
         // only if it implements nsIAccessibleProvider interface.
         nsCOMPtr<nsIAccessible> accessible;
         rv = GetAccessibleByType(bindingNode, getter_AddRefs(accessible));
 
         if (NS_SUCCEEDED(rv)) {
-          nsCOMPtr<nsPIAccessible> paccessible(do_QueryInterface(accessible));
-          if (paccessible) {
-            PRBool allowsAnonChildren = PR_FALSE;
-            paccessible->GetAllowsAnonChildAccessibles(&allowsAnonChildren);
+          nsRefPtr<nsAccessible> acc(nsAccUtils::QueryAccessible(accessible));
+          if (acc) {
+            PRBool allowsAnonChildren = acc->GetAllowsAnonChildAccessibles();
             if (!allowsAnonChildren) {
               NS_ADDREF(*aRelevantNode = bindingNode);
               return NS_OK;
             }
           }
         }
       }
     }
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -69,16 +69,17 @@
 #include "nsIFormControl.h"
 
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsIFrame.h"
 #include "nsIViewManager.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIScrollableFrame.h"
+#include "nsFocusManager.h"
 
 #include "nsXPIDLString.h"
 #include "nsUnicharUtils.h"
 #include "nsReadableUtils.h"
 #include "prdtoa.h"
 #include "nsIAtom.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
@@ -174,22 +175,16 @@ nsresult nsAccessible::QueryInterface(RE
   }
 
   if (aIID.Equals(NS_GET_IID(nsIAccessible))) {
     *aInstancePtr = static_cast<nsIAccessible*>(this);
     NS_ADDREF_THIS();
     return NS_OK;
   }
 
-  if(aIID.Equals(NS_GET_IID(nsPIAccessible))) {
-    *aInstancePtr = static_cast<nsPIAccessible*>(this);
-    NS_ADDREF_THIS();
-    return NS_OK;
-  }
-
   if (aIID.Equals(NS_GET_IID(nsAccessible))) {
     *aInstancePtr = static_cast<nsAccessible*>(this);
     NS_ADDREF_THIS();
     return NS_OK;
   }
 
   if (aIID.Equals(NS_GET_IID(nsIAccessibleSelectable))) {
     nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
@@ -261,20 +256,20 @@ nsAccessible::nsAccessible(nsIDOMNode* a
 
 //-----------------------------------------------------
 // destruction
 //-----------------------------------------------------
 nsAccessible::~nsAccessible()
 {
 }
 
-NS_IMETHODIMP nsAccessible::SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry)
+void
+nsAccessible::SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry)
 {
   mRoleMapEntry = aRoleMapEntry;
-  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAccessible::GetName(nsAString& aName)
 {
   aName.Truncate();
 
   if (IsDefunct())
@@ -483,118 +478,119 @@ nsAccessible::GetKeyboardShortcut(nsAStr
     propertyKey.AssignLiteral("VK_CONTROL");
     nsAccessible::GetFullKeyName(propertyKey, accesskey, accesskey);
   }
 
   aAccessKey = accesskey;
   return NS_OK;
 }
 
-NS_IMETHODIMP nsAccessible::SetParent(nsIAccessible *aParent)
+void
+nsAccessible::SetParent(nsIAccessible *aParent)
 {
   if (mParent != aParent) {
     // Adopt a child -- we allow this now. the new parent
     // may be a dom node which wasn't previously accessible but now is.
     // The old parent's children now need to be invalidated, since 
     // it no longer owns the child, the new parent does
-    nsCOMPtr<nsPIAccessible> privOldParent = do_QueryInterface(mParent);
-    if (privOldParent) {
-      privOldParent->InvalidateChildren();
-    }
+    nsRefPtr<nsAccessible> oldParent = nsAccUtils::QueryAccessible(mParent);
+    if (oldParent)
+      oldParent->InvalidateChildren();
   }
 
   mParent = aParent;
-  return NS_OK;
 }
 
-NS_IMETHODIMP nsAccessible::SetFirstChild(nsIAccessible *aFirstChild)
+void
+nsAccessible::SetFirstChild(nsIAccessible *aFirstChild)
 {
   mFirstChild = aFirstChild;
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP nsAccessible::SetNextSibling(nsIAccessible *aNextSibling)
+void
+nsAccessible::SetNextSibling(nsIAccessible *aNextSibling)
 {
   mNextSibling = aNextSibling;
-  return NS_OK;
 }
 
 nsresult
 nsAccessible::Shutdown()
 {
   mNextSibling = nsnull;
 
   // Invalidate the child count and pointers to other accessibles, also make
   // sure none of its children point to this parent
   InvalidateChildren();
   if (mParent) {
-    nsCOMPtr<nsPIAccessible> privateParent(do_QueryInterface(mParent));
-    privateParent->InvalidateChildren();
+    nsRefPtr<nsAccessible> parent(nsAccUtils::QueryAccessible(mParent));
+    parent->InvalidateChildren();
     mParent = nsnull;
   }
 
   return nsAccessNodeWrap::Shutdown();
 }
 
-NS_IMETHODIMP nsAccessible::InvalidateChildren()
+void
+nsAccessible::InvalidateChildren()
 {
   // Document has transformed, reset our invalid children and child count
 
   // Reset the sibling pointers, they will be set up again the next time
   // CacheChildren() is called.
   // Note: we don't want to start creating accessibles at this point,
   // so don't use GetNextSibling() here. (bug 387252)
-  nsAccessible* child = static_cast<nsAccessible*>(mFirstChild.get());
+  nsRefPtr<nsAccessible> child = nsAccUtils::QueryAccessible(mFirstChild);
   while (child) {
     child->mParent = nsnull;
 
     nsCOMPtr<nsIAccessible> next = child->mNextSibling;
     child->mNextSibling = nsnull;
-    child = static_cast<nsAccessible*>(next.get());
+    child = nsAccUtils::QueryAccessible(next);
   }
 
   mAccChildCount = eChildCountUninitialized;
   mFirstChild = nsnull;
-  return NS_OK;
 }
 
-NS_IMETHODIMP nsAccessible::GetParent(nsIAccessible **  aParent)
+NS_IMETHODIMP
+nsAccessible::GetParent(nsIAccessible **aParent)
 {
-  nsresult rv = GetCachedParent(aParent);
-  if (NS_FAILED(rv) || *aParent) {
-    return rv;
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  nsCOMPtr<nsIAccessible> cachedParent = GetCachedParent();
+  if (cachedParent) {
+    cachedParent.swap(*aParent);
+    return NS_OK;
   }
 
   nsCOMPtr<nsIAccessibleDocument> docAccessible(GetDocAccessible());
   NS_ENSURE_TRUE(docAccessible, NS_ERROR_FAILURE);
 
   return docAccessible->GetAccessibleInParentChain(mDOMNode, PR_TRUE, aParent);
 }
 
-NS_IMETHODIMP nsAccessible::GetCachedParent(nsIAccessible **  aParent)
+already_AddRefed<nsIAccessible>
+nsAccessible::GetCachedParent()
 {
-  *aParent = nsnull;
-  if (!mWeakShell) {
-    // This node has been shut down
-    return NS_ERROR_FAILURE;
-  }
-  NS_IF_ADDREF(*aParent = mParent);
-  return NS_OK;
+  if (IsDefunct())
+    return nsnull;
+
+  nsCOMPtr<nsIAccessible> cachedParent = mParent;
+  return cachedParent.forget();
 }
 
-NS_IMETHODIMP nsAccessible::GetCachedFirstChild(nsIAccessible **  aFirstChild)
+already_AddRefed<nsIAccessible>
+nsAccessible::GetCachedFirstChild()
 {
-  *aFirstChild = nsnull;
-  if (!mWeakShell) {
-    // This node has been shut down
-    return NS_ERROR_FAILURE;
-  }
-  NS_IF_ADDREF(*aFirstChild = mFirstChild);
-  return NS_OK;
+  if (IsDefunct())
+    return nsnull;
+
+  nsCOMPtr<nsIAccessible> cachedFirstChild = mFirstChild;
+  return cachedFirstChild.forget();
 }
 
   /* readonly attribute nsIAccessible nextSibling; */
 NS_IMETHODIMP nsAccessible::GetNextSibling(nsIAccessible * *aNextSibling) 
 { 
   *aNextSibling = nsnull; 
   if (!mWeakShell) {
     // This node has been shut down
@@ -654,20 +650,19 @@ NS_IMETHODIMP nsAccessible::GetFirstChil
 {  
   if (gIsCacheDisabled) {
     InvalidateChildren();
   }
   PRInt32 numChildren;
   GetChildCount(&numChildren);  // Make sure we cache all of the children
 
 #ifdef DEBUG
-  nsCOMPtr<nsPIAccessible> firstChild(do_QueryInterface(mFirstChild));
+  nsRefPtr<nsAccessible> firstChild(nsAccUtils::QueryAccessible(mFirstChild));
   if (firstChild) {
-    nsCOMPtr<nsIAccessible> realParent;
-    firstChild->GetCachedParent(getter_AddRefs(realParent));
+    nsCOMPtr<nsIAccessible> realParent = firstChild->GetCachedParent();
     NS_ASSERTION(!realParent || realParent == this,
                  "Two accessibles have the same first child accessible.");
   }
 #endif
 
   NS_IF_ADDREF(*aFirstChild = mFirstChild);
 
   return NS_OK;  
@@ -746,44 +741,43 @@ void nsAccessible::CacheChildren()
   if (!mWeakShell) {
     // This node has been shut down
     mAccChildCount = eChildCountUninitialized;
     return;
   }
 
   if (mAccChildCount == eChildCountUninitialized) {
     mAccChildCount = 0;// Prevent reentry
-    PRBool allowsAnonChildren = PR_FALSE;
-    GetAllowsAnonChildAccessibles(&allowsAnonChildren);
+    PRBool allowsAnonChildren = GetAllowsAnonChildAccessibles();
     nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, allowsAnonChildren);
     // Seed the frame hint early while we're still on a container node.
     // This is better than doing the GetPrimaryFrameFor() later on
     // a text node, because text nodes aren't in the frame map.
     walker.mState.frame = GetFrame();
 
-    nsCOMPtr<nsPIAccessible> privatePrevAccessible;
+    nsRefPtr<nsAccessible> prevAcc;
     PRInt32 childCount = 0;
     walker.GetFirstChild();
     SetFirstChild(walker.mState.accessible);
 
     while (walker.mState.accessible) {
       ++ childCount;
-      privatePrevAccessible = do_QueryInterface(walker.mState.accessible);
-      privatePrevAccessible->SetParent(this);
+      prevAcc = nsAccUtils::QueryAccessible(walker.mState.accessible);
+      prevAcc->SetParent(this);
       walker.GetNextSibling();
-      privatePrevAccessible->SetNextSibling(walker.mState.accessible);
+      prevAcc->SetNextSibling(walker.mState.accessible);
     }
     mAccChildCount = childCount;
   }
 }
 
-NS_IMETHODIMP nsAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
+PRBool
+nsAccessible::GetAllowsAnonChildAccessibles()
 {
-  *aAllowsAnonChildren = PR_TRUE;
-  return NS_OK;
+  return PR_TRUE;
 }
 
 /* readonly attribute long childCount; */
 NS_IMETHODIMP nsAccessible::GetChildCount(PRInt32 *aAccChildCount) 
 {
   CacheChildren();
   *aAccChildCount = mAccChildCount;
   return NS_OK;  
@@ -820,40 +814,39 @@ NS_IMETHODIMP nsAccessible::GetIndexInPa
     nsCOMPtr<nsIAccessible> tempAccessible;
     sibling->GetNextSibling(getter_AddRefs(tempAccessible));
     sibling = tempAccessible;
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP nsAccessible::TestChildCache(nsIAccessible *aCachedChild)
+void
+nsAccessible::TestChildCache(nsIAccessible *aCachedChild)
 {
-#ifndef DEBUG_A11Y
-  return NS_OK;
-#else
+#ifdef DEBUG_A11Y
   // All cached accessible nodes should be in the parent
   // It will assert if not all the children were created
   // when they were first cached, and no invalidation
   // ever corrected parent accessible's child cache.
-  if (mAccChildCount <= 0) {
-    return NS_OK;
-  }
+  if (mAccChildCount <= 0)
+    return;
+
   nsCOMPtr<nsIAccessible> sibling = mFirstChild;
 
   while (sibling != aCachedChild) {
     NS_ASSERTION(sibling, "[TestChildCache] Never ran into the same child that we started from");
     if (!sibling)
-      return NS_ERROR_FAILURE;
+      return;
 
     nsCOMPtr<nsIAccessible> tempAccessible;
     sibling->GetNextSibling(getter_AddRefs(tempAccessible));
     sibling = tempAccessible;
   }
-  return NS_OK;
+
 #endif
 }
 
 nsresult nsAccessible::GetTranslatedString(const nsAString& aKey, nsAString& aStringOut)
 {
   nsXPIDLString xsValue;
 
   if (!gStringBundle || 
@@ -1464,24 +1457,21 @@ nsAccessible::TakeFocus()
                              nsAccessibilityAtoms::aria_activedescendant,
                              id, PR_TRUE);
           }
         }
       }
     }
   }
 
-  nsCOMPtr<nsIDOMNSHTMLElement> htmlElement(do_QueryInterface(content));
-  if (htmlElement) {
-    // HTML Elements also set the caret position
-    // in order to affect tabbing order
-    return htmlElement->Focus();
-  }
-
-  content->SetFocus(GetPresContext());
+  nsCOMPtr<nsIDOMElement> element(do_QueryInterface(content));
+  nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
+  if (fm)
+    fm->SetFocus(element, 0);
+
   return NS_OK;
 }
 
 nsresult
 nsAccessible::GetHTMLName(nsAString& aLabel)
 {
   nsCOMPtr<nsIContent> content = nsCoreUtils::GetRoleContent(mDOMNode);
   if (!content) {
@@ -1586,17 +1576,17 @@ nsAccessible::GetXULName(nsAString& aLab
       return NS_OK;
     }
     parent = parent->GetParent();
   }
 
   return nsTextEquivUtils::GetNameFromSubtree(this, aLabel);
 }
 
-NS_IMETHODIMP
+nsresult
 nsAccessible::FireAccessibleEvent(nsIAccessibleEvent *aEvent)
 {
   NS_ENSURE_ARG_POINTER(aEvent);
   nsCOMPtr<nsIDOMNode> eventNode;
   aEvent->GetDOMNode(getter_AddRefs(eventNode));
   NS_ENSURE_TRUE(nsAccUtils::IsNodeRelevant(eventNode), NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIObserverService> obsService =
@@ -1605,18 +1595,22 @@ nsAccessible::FireAccessibleEvent(nsIAcc
 
   return obsService->NotifyObservers(aEvent, NS_ACCESSIBLE_EVENT_TOPIC, nsnull);
 }
 
 NS_IMETHODIMP
 nsAccessible::GetRole(PRUint32 *aRole)
 {
   NS_ENSURE_ARG_POINTER(aRole);
+
   *aRole = nsIAccessibleRole::ROLE_NOTHING;
 
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
   if (mRoleMapEntry) {
     *aRole = mRoleMapEntry->role;
 
     // These unfortunate exceptions don't fit into the ARIA table
     // This is where the nsIAccessible role depends on both the role and ARIA state
     if (*aRole == nsIAccessibleRole::ROLE_PUSHBUTTON) {
       nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
       if (content) {
@@ -1648,31 +1642,22 @@ nsAccessible::GetRole(PRUint32 *aRole)
     }
     else if (*aRole == nsIAccessibleRole::ROLE_OPTION) {
       nsCOMPtr<nsIAccessible> parent;
       GetParent(getter_AddRefs(parent));
       if (nsAccUtils::Role(parent) == nsIAccessibleRole::ROLE_COMBOBOX_LIST)
         *aRole = nsIAccessibleRole::ROLE_COMBOBOX_OPTION;
     }
 
-    // gLandmarkRoleMap: can use role of accessible class impl
-    // gEmptyRoleMap and all others: cannot use role of accessible class impl
-    if (mRoleMapEntry != &nsARIAMap::gLandmarkRoleMap) {
-      // We can now expose ROLE_NOTHING when there is a role map entry or used
-      // role is nothing, which
-      // will cause ATK to use ROLE_UNKNOWN and MSAA to use a BSTR role with
-      // the ARIA role or element's tag. In either case the AT can also use
-      // the object attributes tag and xml-roles to find out more.
+    // We are done if the mapped role trumps native semantics
+    if (mRoleMapEntry->roleRule == kUseMapRole)
       return NS_OK;
-    }
   }
 
-  return mDOMNode ?
-    GetRoleInternal(aRole) :
-    NS_ERROR_FAILURE;  // Node already shut down
+  return GetRoleInternal(aRole);
 }
 
 NS_IMETHODIMP
 nsAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
 {
   NS_ENSURE_ARG_POINTER(aAttributes);  // In/out param. Created if necessary.
   
   if (IsDefunct())
@@ -1847,16 +1832,27 @@ nsAccessible::GetAttributesInternal(nsIP
 
   // Expose 'text-indent' attribute.
   rv = GetComputedStyleValue(EmptyString(), NS_LITERAL_STRING("text-indent"),
                              value);
   if (NS_SUCCEEDED(rv))
     nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::textIndent,
                            value);
 
+  // Expose draggable object attribute?
+  nsCOMPtr<nsIDOMNSHTMLElement> htmlElement = do_QueryInterface(content);
+  if (htmlElement) {
+    PRBool draggable = PR_FALSE;
+    htmlElement->GetDraggable(&draggable);
+    if (draggable) {
+      nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::draggable,
+                             NS_LITERAL_STRING("true"));
+    }
+  }
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAccessible::GroupPosition(PRInt32 *aGroupLevel,
                             PRInt32 *aSimilarItemsInGroup,
                             PRInt32 *aPositionInGroup)
 {
@@ -1934,16 +1930,24 @@ PRBool nsAccessible::MappedAttrState(nsI
   return PR_TRUE;
 }
 
 NS_IMETHODIMP
 nsAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
 {
   NS_ENSURE_ARG_POINTER(aState);
 
+  if (!IsDefunct()) {
+    // Flush layout so that all the frame construction, reflow, and styles are
+    // up-to-date since we rely on frames, and styles when calculating state.
+    // We don't flush the display because we don't care about painting.
+    nsCOMPtr<nsIPresShell> presShell = GetPresShell();
+    presShell->FlushPendingNotifications(Flush_Layout);
+  }
+
   nsresult rv = GetStateInternal(aState, aExtraState);
   NS_ENSURE_A11Y_SUCCESS(rv, rv);
 
   // Apply ARIA states to be sure accessible states will be overriden.
   GetARIAState(aState);
 
   if (mRoleMapEntry && mRoleMapEntry->role == nsIAccessibleRole::ROLE_PAGETAB) {
     if (*aState & nsIAccessibleStates::STATE_FOCUSED) {
@@ -3106,17 +3110,17 @@ nsresult nsAccessible::GetLinkOffset(PRI
     }
     accessible->GetNextSibling(getter_AddRefs(nextSibling));
     accessible.swap(nextSibling);
   }
 
   return NS_ERROR_FAILURE;
 }
 
-NS_IMETHODIMP
+nsresult
 nsAccessible::AppendTextTo(nsAString& aText, PRUint32 aStartOffset, PRUint32 aLength)
 {
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessible public methods
 
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -41,17 +41,16 @@
 
 #include "nsAccessNodeWrap.h"
 
 #include "nsARIAMap.h"
 #include "nsRelUtils.h"
 #include "nsTextEquivUtils.h"
 
 #include "nsIAccessible.h"
-#include "nsPIAccessible.h"
 #include "nsIAccessibleHyperLink.h"
 #include "nsIAccessibleSelectable.h"
 #include "nsIAccessibleValue.h"
 #include "nsIAccessibleRole.h"
 #include "nsIAccessibleStates.h"
 #include "nsIAccessibleEvent.h"
 
 #include "nsIDOMNodeList.h"
@@ -99,39 +98,37 @@ public:
   }
 
 private:
   nsTArray<nsString> mNames;
 };
 
 
 #define NS_ACCESSIBLE_IMPL_CID                          \
-{  /* 16917f1e-6cee-4cde-be3f-8bb5943f506c */           \
-  0x16917f1e,                                           \
-  0x6cee,                                               \
-  0x4cde,                                               \
-  { 0xbe, 0x3f, 0x8b, 0xb5, 0x94, 0x3F, 0x50, 0x6c }    \
+{  /* 53cfa871-be42-47fc-b416-0033653b3151 */           \
+  0x53cfa871,                                           \
+  0xbe42,                                               \
+  0x47fc,                                               \
+  { 0xb4, 0x16, 0x00, 0x33, 0x65, 0x3b, 0x31, 0x51 }    \
 }
 
 class nsAccessible : public nsAccessNodeWrap, 
                      public nsIAccessible, 
-                     public nsPIAccessible,
                      public nsIAccessibleHyperLink,
                      public nsIAccessibleSelectable,
                      public nsIAccessibleValue
 {
 public:
   nsAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
   virtual ~nsAccessible();
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsAccessible, nsAccessNode)
 
   NS_DECL_NSIACCESSIBLE
-  NS_DECL_NSPIACCESSIBLE
   NS_DECL_NSIACCESSIBLEHYPERLINK
   NS_DECL_NSIACCESSIBLESELECTABLE
   NS_DECL_NSIACCESSIBLEVALUE
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ACCESSIBLE_IMPL_CID)
 
   //////////////////////////////////////////////////////////////////////////////
   // nsAccessNode
 
@@ -141,16 +138,25 @@ public:
   // Public methods
 
   /**
    * Returns the accessible name specified by ARIA.
    */
   nsresult GetARIAName(nsAString& aName);
 
   /**
+   * Maps ARIA state attributes to state of accessible. Note the given state
+   * argument should hold states for accessible before you pass it into this
+   * method.
+   *
+   * @param  [in/out] where to fill the states into.
+   */
+  virtual nsresult GetARIAState(PRUint32 *aState);
+
+  /**
    * Returns the accessible name provided by native markup. It doesn't take
    * into account ARIA markup used to specify the name.
    *
    * @param  aName             [out] the accessible name
    *
    * @return NS_OK_EMPTY_NAME  points empty name was specified by native markup
    *                           explicitly (see nsIAccessible::name attribute for
    *                           details)
@@ -187,16 +193,88 @@ public:
    * @param  aDeepestChild  [in] flag points if deep child should be returned
    * @param  aChild         [out] found child
    */
   virtual nsresult GetChildAtPoint(PRInt32 aX, PRInt32 aY,
                                    PRBool aDeepestChild,
                                    nsIAccessible **aChild);
 
   //////////////////////////////////////////////////////////////////////////////
+  // Initializing and cache methods
+
+  /**
+   * Set accessible parent.
+   * XXX: shouldn't be virtual, bug 496783
+   */
+  virtual void SetParent(nsIAccessible *aParent);
+
+  /**
+   * Set first accessible child.
+   */
+  void SetFirstChild(nsIAccessible *aFirstChild);
+
+  /**
+   * Set next sibling accessible.
+   */
+  void SetNextSibling(nsIAccessible *aNextSibling);
+
+  /**
+   * Set the ARIA role map entry for a new accessible.
+   * For a newly created accessible, specify which role map entry should be used.
+   *
+   * @param aRoleMapEntry The ARIA nsRoleMapEntry* for the accessible, or 
+   *                      nsnull if none.
+   */
+  virtual void SetRoleMapEntry(nsRoleMapEntry *aRoleMapEntry);
+
+  /**
+   * Set the child count to -1 (unknown) and null out cached child pointers
+   */
+  virtual void InvalidateChildren();
+
+  /**
+   * Return parent accessible only if cached.
+   */
+  already_AddRefed<nsIAccessible> GetCachedParent();
+
+  /**
+   * Return first child accessible only if cached.
+   */
+  already_AddRefed<nsIAccessible> GetCachedFirstChild();
+
+  /**
+   * Assert if child not in parent's cache.
+   */
+  void TestChildCache(nsIAccessible *aCachedChild);
+
+  //////////////////////////////////////////////////////////////////////////////
+  // Miscellaneous methods.
+
+  /**
+   * Fire accessible event.
+   */
+  virtual nsresult FireAccessibleEvent(nsIAccessibleEvent *aAccEvent);
+
+  /**
+   * Return true if there are accessible children in anonymous content
+   */
+  virtual PRBool GetAllowsAnonChildAccessibles();
+
+  /**
+   * Returns text of accessible if accessible has text role otherwise empty
+   * string.
+   *
+   * @param aText         returned text of the accessible
+   * @param aStartOffset  start offset inside of the accesible
+   * @param aLength       required lenght of text
+   */
+  virtual nsresult AppendTextTo(nsAString& aText, PRUint32 aStartOffset,
+                                PRUint32 aLength);
+
+  //////////////////////////////////////////////////////////////////////////////
   // Helper methods
   
   already_AddRefed<nsIAccessible> GetParent() {
     nsIAccessible *parent = nsnull;
     GetParent(&parent);
     return parent;
   }
 
--- a/accessible/src/base/nsAccessibleEventData.cpp
+++ b/accessible/src/base/nsAccessibleEventData.cpp
@@ -71,25 +71,29 @@ NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsAccEvent)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsAccEvent)
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccEvent. Constructors
 
 nsAccEvent::nsAccEvent(PRUint32 aEventType, nsIAccessible *aAccessible,
-                       PRBool aIsAsynch, EEventRule aEventRule):
-  mEventType(aEventType), mAccessible(aAccessible), mEventRule(aEventRule)
+                       PRBool aIsAsynch, EEventRule aEventRule)
+  : mEventType(aEventType)
+  , mEventRule(aEventRule)
+  , mAccessible(aAccessible)
 {
   CaptureIsFromUserInput(aIsAsynch);
 }
 
 nsAccEvent::nsAccEvent(PRUint32 aEventType, nsIDOMNode *aDOMNode,
-                       PRBool aIsAsynch, EEventRule aEventRule):
-  mEventType(aEventType), mDOMNode(aDOMNode), mEventRule(aEventRule)
+                       PRBool aIsAsynch, EEventRule aEventRule)
+  : mEventType(aEventType)
+  , mEventRule(aEventRule)
+  , mDOMNode(aDOMNode)
 {
   CaptureIsFromUserInput(aIsAsynch);
 }
 
 void nsAccEvent::GetLastEventAttributes(nsIDOMNode *aNode,
                                         nsIPersistentProperties *aAttributes)
 {
   if (aNode == gLastEventNodeWeak) {
--- a/accessible/src/base/nsApplicationAccessible.cpp
+++ b/accessible/src/base/nsApplicationAccessible.cpp
@@ -231,30 +231,31 @@ nsApplicationAccessible::CacheChildren()
 
   if (mAccChildCount == eChildCountUninitialized) {
     mAccChildCount = 0;// Prevent reentry
     nsCOMPtr<nsISimpleEnumerator> enumerator;
     mChildren->Enumerate(getter_AddRefs(enumerator));
 
     nsCOMPtr<nsIWeakReference> childWeakRef;
     nsCOMPtr<nsIAccessible> accessible;
-    nsCOMPtr<nsPIAccessible> previousAccessible;
+    nsRefPtr<nsAccessible> prevAcc;
     PRBool hasMoreElements;
-    while(NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreElements))
-          && hasMoreElements) {
+
+    while(NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreElements)) &&
+          hasMoreElements) {
       enumerator->GetNext(getter_AddRefs(childWeakRef));
       accessible = do_QueryReferent(childWeakRef);
       if (accessible) {
-        if (previousAccessible)
-          previousAccessible->SetNextSibling(accessible);
+        if (prevAcc)
+          prevAcc->SetNextSibling(accessible);
         else
           SetFirstChild(accessible);
 
-        previousAccessible = do_QueryInterface(accessible);
-        previousAccessible->SetParent(this);
+        prevAcc = nsAccUtils::QueryAccessible(accessible);
+        prevAcc->SetParent(this);
       }
     }
 
     PRUint32 count = 0;
     mChildren->GetLength(&count);
     mAccChildCount = static_cast<PRInt32>(count);
   }
 }
--- a/accessible/src/base/nsBaseWidgetAccessible.cpp
+++ b/accessible/src/base/nsBaseWidgetAccessible.cpp
@@ -81,22 +81,21 @@ NS_IMETHODIMP nsLeafAccessible::GetLastC
 
 /* long getAccChildCount (); */
 NS_IMETHODIMP nsLeafAccessible::GetChildCount(PRInt32 *_retval)
 {
   *_retval = 0;
   return NS_OK;
 }
 
-/* readonly attribute boolean allowsAnonChildAccessibles; */
-NS_IMETHODIMP
-nsLeafAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
+// nsAccessible::GetAllowsAnonChildAccessibles()
+PRBool
+nsLeafAccessible::GetAllowsAnonChildAccessibles()
 {
-  *aAllowsAnonChildren = PR_FALSE;
-  return NS_OK;
+  return PR_FALSE;
 }
 
 // nsAccessible::GetChildAtPoint()
 nsresult
 nsLeafAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
                                   PRBool aDeepestChild,
                                   nsIAccessible **aChild)
 {
--- a/accessible/src/base/nsBaseWidgetAccessible.h
+++ b/accessible/src/base/nsBaseWidgetAccessible.h
@@ -62,23 +62,21 @@ public:
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessible
   NS_IMETHOD GetFirstChild(nsIAccessible **_retval);
   NS_IMETHOD GetLastChild(nsIAccessible **_retval);
   NS_IMETHOD GetChildCount(PRInt32 *_retval);
 
-  // nsPIAccessible
-  NS_IMETHOD GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren);
-
   // nsAccessible
   virtual nsresult GetChildAtPoint(PRInt32 aX, PRInt32 aY,
                                    PRBool aDeepestChild,
                                    nsIAccessible **aChild);
+  virtual PRBool GetAllowsAnonChildAccessibles();
 };
 
 /**
   * A type of accessible for DOM nodes containing an href="" attribute.
   *  It knows how to report the state of the link ( traveled or not )
   *  and can activate ( click ) the link programmatically.
   */
 class nsLinkableAccessible : public nsHyperTextAccessibleWrap
--- a/accessible/src/base/nsCoreUtils.cpp
+++ b/accessible/src/base/nsCoreUtils.cpp
@@ -73,18 +73,18 @@
 #include "nsIInterfaceRequestorUtils.h"
 
 static NS_DEFINE_IID(kRangeCID, NS_RANGE_CID);
 
 PRBool
 nsCoreUtils::HasListener(nsIContent *aContent, const nsAString& aEventType)
 {
   NS_ENSURE_TRUE(aContent, PR_FALSE);
-  nsCOMPtr<nsIEventListenerManager> listenerManager;
-  aContent->GetListenerManager(PR_FALSE, getter_AddRefs(listenerManager));
+  nsIEventListenerManager* listenerManager =
+    aContent->GetListenerManager(PR_FALSE);
 
   return listenerManager && listenerManager->HasListenersFor(aEventType);  
 }
 
 PRBool
 nsCoreUtils::DispatchMouseEvent(PRUint32 aEventType,
                                 nsIPresShell *aPresShell,
                                 nsIContent *aContent)
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -63,17 +63,17 @@
 #include "nsIPresShell.h"
 #include "nsIServiceManager.h"
 #include "nsIScrollableView.h"
 #include "nsIViewManager.h"
 #include "nsIView.h"
 #include "nsUnicharUtils.h"
 #include "nsIURI.h"
 #include "nsIWebNavigation.h"
-#include "nsIFocusController.h"
+#include "nsFocusManager.h"
 #ifdef MOZ_XUL
 #include "nsIXULDocument.h"
 #endif
 
 //=============================//
 // nsDocAccessible  //
 //=============================//
 
@@ -231,34 +231,38 @@ nsDocAccessible::GetRoleInternal(PRUint3
     else if (itemType == nsIDocShellTreeItem::typeContent) {
       *aRole = nsIAccessibleRole::ROLE_DOCUMENT;
     }
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP nsDocAccessible::SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry)
+void
+nsDocAccessible::SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry)
 {
-  NS_ENSURE_STATE(mDocument);
+  NS_ASSERTION(mDocument, "No document during initialization!");
+  if (!mDocument)
+    return;
 
   mRoleMapEntry = aRoleMapEntry;
 
   // Allow use of ARIA role from outer to override
   nsIDocument *parentDoc = mDocument->GetParentDocument();
-  NS_ENSURE_TRUE(parentDoc, NS_ERROR_FAILURE);
+  NS_ASSERTION(parentDoc, "No parent document during initialization!");
+  if (!parentDoc)
+    return;
+
   nsIContent *ownerContent = parentDoc->FindContentForSubDocument(mDocument);
   nsCOMPtr<nsIDOMNode> ownerNode(do_QueryInterface(ownerContent));
   if (ownerNode) {
     nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(ownerNode);
     if (roleMapEntry)
       mRoleMapEntry = roleMapEntry; // Override
   }
-
-  return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsDocAccessible::GetDescription(nsAString& aDescription)
 {
   if (mParent)
     mParent->GetDescription(aDescription);
 
@@ -318,43 +322,44 @@ nsDocAccessible::GetStateInternal(PRUint
   }
   else if (aExtraState) {
     *aExtraState |= nsIAccessibleStates::EXT_STATE_EDITABLE;
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
+nsresult
 nsDocAccessible::GetARIAState(PRUint32 *aState)
 {
   // Combine with states from outer doc
   NS_ENSURE_ARG_POINTER(aState);
   nsresult rv = nsAccessible::GetARIAState(aState);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsPIAccessible> privateParentAccessible = do_QueryInterface(mParent);
-  if (privateParentAccessible)  // Allow iframe/frame etc. to have final state override via ARIA
-    return privateParentAccessible->GetARIAState(aState);
+  nsRefPtr<nsAccessible> parent = nsAccUtils::QueryAccessible(mParent);
+  if (parent)  // Allow iframe/frame etc. to have final state override via ARIA
+    return parent->GetARIAState(aState);
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsDocAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
 {
   nsAccessible::GetAttributes(aAttributes);
   if (mParent) {
     mParent->GetAttributes(aAttributes); // Add parent attributes (override inner)
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP nsDocAccessible::GetFocusedChild(nsIAccessible **aFocusedChild)
 {
+  // XXXndeakin P3 accessibility shouldn't be caching the focus
   if (!gLastFocusedNode) {
     *aFocusedChild = nsnull;
     return NS_OK;
   }
 
   // Return an accessible for the current global focus, which does not have to
   // be contained within the current document.
   nsCOMPtr<nsIAccessibilityService> accService =
@@ -366,35 +371,30 @@ NS_IMETHODIMP nsDocAccessible::TakeFocus
 {
   NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE);
   PRUint32 state;
   GetStateInternal(&state, nsnull);
   if (0 == (state & nsIAccessibleStates::STATE_FOCUSABLE)) {
     return NS_ERROR_FAILURE; // Not focusable
   }
 
-  nsCOMPtr<nsIDocShellTreeItem> treeItem =
-    nsCoreUtils::GetDocShellTreeItemFor(mDOMNode);
-  nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(treeItem);
-  NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
-
-  nsCOMPtr<nsIPresShell> shell(GetPresShell());
-  if (!shell) {
-    NS_WARNING("Was not shutdown properly via InvalidateCacheSubtree()");
-    return NS_ERROR_FAILURE;
+  nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
+  if (fm) {
+    nsCOMPtr<nsIDOMDocument> domDocument;
+    mDOMNode->GetOwnerDocument(getter_AddRefs(domDocument));
+    nsCOMPtr<nsIDocument> document(do_QueryInterface(domDocument));
+    if (document) {
+      // focus the document
+      nsCOMPtr<nsIDOMElement> newFocus;
+      return fm->MoveFocus(document->GetWindow(), nsnull,
+                           nsIFocusManager::MOVEFOCUS_ROOT, 0,
+                           getter_AddRefs(newFocus));
+    }
   }
-  nsIEventStateManager *esm = shell->GetPresContext()->EventStateManager();
-  NS_ENSURE_TRUE(esm, NS_ERROR_FAILURE);
-
-  // Focus the document
-  nsresult rv = docShell->SetHasFocus(PR_TRUE);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Clear out any existing focus state
-  return esm->SetContentState(nsnull, NS_EVENT_STATE_FOCUS);
+  return NS_ERROR_FAILURE;
 }
 
 // ------- nsIAccessibleDocument Methods (5) ---------------
 
 NS_IMETHODIMP nsDocAccessible::GetURL(nsAString& aURL)
 {
   if (!mDocument) {
     return NS_ERROR_FAILURE; // Document has been shut down
@@ -537,24 +537,22 @@ NS_IMETHODIMP nsDocAccessible::GetCached
 {
   GetCacheEntry(mAccessNodeCache, aUniqueID, aAccessNode); // Addrefs for us
 #ifdef DEBUG_A11Y
   // All cached accessible nodes should be in the parent
   // It will assert if not all the children were created
   // when they were first cached, and no invalidation
   // ever corrected parent accessible's child cache.
   nsCOMPtr<nsIAccessible> accessible = do_QueryInterface(*aAccessNode);
-  nsCOMPtr<nsPIAccessible> privateAccessible = do_QueryInterface(accessible);
-  if (privateAccessible) {
-    nsCOMPtr<nsIAccessible> parent;
-    privateAccessible->GetCachedParent(getter_AddRefs(parent));
-    nsCOMPtr<nsPIAccessible> privateParent(do_QueryInterface(parent));
-    if (privateParent) {
-      privateParent->TestChildCache(accessible);
-    }
+  nsRefPtr<nsAccessible> acc = nsAccUtils::QueryAccessible(accessible);
+  if (acc) {
+    nsCOMPtr<nsIAccessible> parent = acc->GetCachedParent();
+    nsRefPtr<nsAccessible> parentAcc(nsAccUtils::QueryAccessible(parent));
+    if (parentAcc)
+      parentAcc->TestChildCache(accessible);
   }
 #endif
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocAccessible::CacheAccessNode(void *aUniqueID, nsIAccessNode *aAccessNode)
 {
@@ -884,21 +882,22 @@ NS_IMETHODIMP nsDocAccessible::FireDocLo
   }
   nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
   treeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
 
   if (isFinished) {
     // Need to wait until scrollable view is available
     AddScrollListener();
     nsCOMPtr<nsIAccessible> parent(nsAccessible::GetParent());
-    nsCOMPtr<nsPIAccessible> privateAccessible(do_QueryInterface(parent));
-    if (privateAccessible) {
+    nsRefPtr<nsAccessible> acc(nsAccUtils::QueryAccessible(parent));
+    if (acc) {
       // Make the parent forget about the old document as a child
-      privateAccessible->InvalidateChildren();
+      acc->InvalidateChildren();
     }
+
     if (sameTypeRoot != treeItem) {
       // Fire show/hide events to indicate frame/iframe content is new, rather than
       // doc load event which causes screen readers to act is if entire page is reloaded
       InvalidateCacheSubtree(nsnull, nsIAccessibleEvent::EVENT_DOM_SIGNIFICANT_CHANGE);
     }
     // Fire STATE_CHANGE event for doc load finish if focus is in same doc tree
     if (gLastFocusedNode) {
       nsCOMPtr<nsIDocShellTreeItem> focusedTreeItem =
@@ -1284,19 +1283,26 @@ nsDocAccessible::ARIAAttributeChanged(ns
     nsCOMPtr<nsIAccessibleStateChangeEvent> event =
       new nsAccStateChangeEvent(targetNode,
                                 nsIAccessibleStates::STATE_READONLY,
                                 PR_FALSE);
     FireDelayedAccessibleEvent(event);
     return;
   }
 
-  if (aAttribute == nsAccessibilityAtoms::aria_valuenow) {
-    FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
-                            targetNode);
+  // Fire value change event whenever aria-valuetext is changed, or
+  // when aria-valuenow is changed and aria-valuetext is empty
+  if (aAttribute == nsAccessibilityAtoms::aria_valuetext ||      
+      (aAttribute == nsAccessibilityAtoms::aria_valuenow &&
+       (!aContent->HasAttr(kNameSpaceID_None,
+           nsAccessibilityAtoms::aria_valuetext) ||
+        aContent->AttrValueIs(kNameSpaceID_None,
+            nsAccessibilityAtoms::aria_valuetext, nsAccessibilityAtoms::_empty,
+            eCaseMatters)))) {
+    FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, targetNode);
     return;
   }
 
   if (aAttribute == nsAccessibilityAtoms::aria_multiselectable &&
       aContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::role)) {
     // This affects whether the accessible supports nsIAccessibleSelectable.
     // COM says we cannot change what interfaces are supported on-the-fly,
     // so invalidate this object. A new one will be created on demand.
@@ -1573,18 +1579,27 @@ nsDocAccessible::FireDelayedAccessibleEv
 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
+  else {
+    // Flush layout so that all the frame construction, reflow, and styles are
+    // up-to-date. This will ensure we can get frames for the related nodes, as
+    // well as get the most current information for calculating things like
+    // visibility. We don't flush the display because we don't care about
+    // painting. If no flush is necessary the method will simple return.
+    presShell->FlushPendingNotifications(Flush_Layout);
+
+    // filter events
     nsAccEvent::ApplyEventRules(mEventsToFire);
+  }
   
   for (PRUint32 index = 0; index < length; index ++) {
     nsCOMPtr<nsIAccessibleEvent> accessibleEvent(
       do_QueryInterface(mEventsToFire[index]));
 
     if (nsAccEvent::EventRule(accessibleEvent) == nsAccEvent::eDoNotEmit)
       continue;
 
@@ -1630,20 +1645,20 @@ NS_IMETHODIMP nsDocAccessible::FlushPend
         GetAccessibleInParentChain(domNode, PR_TRUE,
                                    getter_AddRefs(containerAccessible));
         if (!containerAccessible)
           containerAccessible = this;
       }
 
       if (eventType == nsIAccessibleEvent::EVENT_ASYNCH_SHOW) {
         // For asynch show, delayed invalidatation of parent's children
-        nsCOMPtr<nsPIAccessible> privateContainerAccessible =
-          do_QueryInterface(containerAccessible);
-        if (privateContainerAccessible)
-          privateContainerAccessible->InvalidateChildren();
+        nsRefPtr<nsAccessible> containerAcc =
+          nsAccUtils::QueryAccessible(containerAccessible);
+        if (containerAcc)
+          containerAcc->InvalidateChildren();
 
         // Some show events in the subtree may have been removed to 
         // avoid firing redundant events. But, we still need to make sure any
         // accessibles parenting those shown nodes lose their child references.
         InvalidateChildrenInSubtree(domNode);
       }
 
       // Also fire text changes if the node being created could affect the text in an nsIAccessibleText parent.
@@ -1757,19 +1772,19 @@ void nsDocAccessible::FlushEventsCallbac
     accessibleDoc->FlushPendingEvents();
   }
 }
 
 void nsDocAccessible::InvalidateChildrenInSubtree(nsIDOMNode *aStartNode)
 {
   nsCOMPtr<nsIAccessNode> accessNode;
   GetCachedAccessNode(aStartNode, getter_AddRefs(accessNode));
-  nsCOMPtr<nsPIAccessible> accessible(do_QueryInterface(accessNode));
-  if (accessible)
-    accessible->InvalidateChildren();
+  nsRefPtr<nsAccessible> acc(nsAccUtils::QueryAccessible(accessNode));
+  if (acc)
+    acc->InvalidateChildren();
 
   // Invalidate accessible children in the DOM subtree 
   nsCOMPtr<nsINode> node = do_QueryInterface(aStartNode);
   PRInt32 index, numChildren = node->GetChildCount();
   for (index = 0; index < numChildren; index ++) {
     nsCOMPtr<nsIDOMNode> childNode = do_QueryInterface(node->GetChildAt(index));
     if (childNode)
       InvalidateChildrenInSubtree(childNode);
@@ -1797,22 +1812,21 @@ void nsDocAccessible::RefreshNodes(nsIDO
       nsCOMPtr<nsIDOMXULPopupElement> popup(do_QueryInterface(domNode));
       if (!popup) {
         // Popup elements already fire these via DOMMenuInactive
         // handling in nsRootAccessible::HandleEvent
         nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_END,
                                  accessible);
       }
     }
-    nsCOMPtr<nsPIAccessible> privateAccessible = do_QueryInterface(accessible);
-    NS_ASSERTION(privateAccessible, "No nsPIAccessible for nsIAccessible");
+    nsRefPtr<nsAccessible> acc = nsAccUtils::QueryAccessible(accessible);
 
-    nsCOMPtr<nsIAccessible> childAccessible;
-    // we only need to shutdown the accessibles here if one of them has been created
-    privateAccessible->GetCachedFirstChild(getter_AddRefs(childAccessible));
+    // We only need to shutdown the accessibles here if one of them has been
+    // created.
+    nsCOMPtr<nsIAccessible> childAccessible = acc->GetCachedFirstChild();
     if (childAccessible) {
       nsCOMPtr<nsIArray> children;
       // use GetChildren() to fetch children at one time, instead of using
       // GetNextSibling(), because after we shutdown the first child,
       // mNextSibling will be set null.
       accessible->GetChildren(getter_AddRefs(children));
       PRUint32 childCount =0;
       if (children)
@@ -1905,31 +1919,35 @@ NS_IMETHODIMP nsDocAccessible::Invalidat
     if (mAccessNodeCache.Count() <= 1) {
       // Still loading and no accessibles has yet been created other than this
       // doc accessible. In this case we optimize
       // by not firing SHOW/HIDE/REORDER events for every document mutation
       // caused by page load, since AT is not going to want to grab the
       // document and listen to these changes until after the page is first loaded
       // Leave early, and ensure mAccChildCount stays uninitialized instead of 0,
       // which it is if anyone asks for its children right now.
-      return InvalidateChildren();
+      InvalidateChildren();
+      return NS_OK;
     }
     nsIEventStateManager *esm = presShell->GetPresContext()->EventStateManager();
     NS_ENSURE_TRUE(esm, NS_ERROR_FAILURE);
     if (!esm->IsHandlingUserInputExternal()) {
       // Changes during page load, but not caused by user input
       // Just invalidate accessible hierarchy and return,
       // otherwise the page load time slows down way too much
       nsCOMPtr<nsIAccessible> containerAccessible;
       GetAccessibleInParentChain(childNode, PR_FALSE, getter_AddRefs(containerAccessible));
       if (!containerAccessible) {
         containerAccessible = this;
       }
-      nsCOMPtr<nsPIAccessible> privateContainer = do_QueryInterface(containerAccessible);
-      return privateContainer->InvalidateChildren();
+
+      nsRefPtr<nsAccessible> containerAcc =
+        nsAccUtils::QueryAccessible(containerAccessible);
+      containerAcc->InvalidateChildren();
+      return NS_OK;
     }     
     // else: user input, so we must fall through and for full handling,
     // e.g. fire the mutation events. Note: user input could cause DOM_CREATE
     // during page load if user typed into an input field or contentEditable area
   }
 
   // Update last change state information
   nsCOMPtr<nsIAccessNode> childAccessNode;
@@ -2014,21 +2032,21 @@ NS_IMETHODIMP nsDocAccessible::Invalidat
   // We will use this accessible to fire the accessible mutation event.
   // We're guaranteed success, because we will eventually end up at the doc accessible,
   // and there is always one of those.
 
   if (aChild && !isHiding) {
     if (!isAsynch) {
       // DOM already updated with new objects -- invalidate parent's children now
       // For asynch we must wait until layout updates before we invalidate the children
-      nsCOMPtr<nsPIAccessible> privateContainerAccessible =
-        do_QueryInterface(containerAccessible);
-      if (privateContainerAccessible) {
-        privateContainerAccessible->InvalidateChildren();
-      }
+      nsRefPtr<nsAccessible> containerAcc =
+        nsAccUtils::QueryAccessible(containerAccessible);
+      if (containerAcc)
+        containerAcc->InvalidateChildren();
+
     }
     // Fire EVENT_SHOW, EVENT_MENUPOPUP_START for newly visible content.
     // Fire after a short timer, because we want to make sure the view has been
     // updated to make this accessible content visible. If we don't wait,
     // the assistive technology may receive the event and then retrieve
     // nsIAccessibleStates::STATE_INVISIBLE for the event's accessible object.
     PRUint32 additionEvent = isAsynch ? nsIAccessibleEvent::EVENT_ASYNCH_SHOW :
                                         nsIAccessibleEvent::EVENT_DOM_CREATE;
--- a/accessible/src/base/nsDocAccessible.h
+++ b/accessible/src/base/nsDocAccessible.h
@@ -71,20 +71,18 @@ class nsDocAccessible : public nsHyperTe
   NS_DECL_NSPIACCESSIBLEDOCUMENT
   NS_DECL_NSIOBSERVER
 
   public:
     nsDocAccessible(nsIDOMNode *aNode, nsIWeakReference* aShell);
     virtual ~nsDocAccessible();
 
     // nsIAccessible
-    NS_IMETHOD SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry);
     NS_IMETHOD GetName(nsAString& aName);
     NS_IMETHOD GetDescription(nsAString& aDescription);
-    NS_IMETHOD GetARIAState(PRUint32 *aState);
     NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
     NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
     NS_IMETHOD GetParent(nsIAccessible **aParent);
     NS_IMETHOD TakeFocus(void);
 
     // ----- nsIScrollPositionListener ---------------------------
     NS_IMETHOD ScrollPositionWillChange(nsIScrollableView *aView, nscoord aX, nscoord aY);
     virtual void ViewPositionDidChange(nsIScrollableView* aScrollable) {}
@@ -98,16 +96,18 @@ class nsDocAccessible : public nsHyperTe
     // nsAccessNode
     virtual nsresult Init();
     virtual nsresult Shutdown();
     virtual nsIFrame* GetFrame();
 
     // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
+  virtual nsresult GetARIAState(PRUint32 *aState);
+  virtual void SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry);
 
     // nsIAccessibleText
     NS_IMETHOD GetAssociatedEditor(nsIEditor **aEditor);
 
     /**
       * Non-virtual method to fire a delayed event after a 0 length timeout
       *
       * @param aEvent - the nsIAccessibleEvent event type
--- a/accessible/src/base/nsOuterDocAccessible.cpp
+++ b/accessible/src/base/nsOuterDocAccessible.cpp
@@ -132,27 +132,25 @@ void nsOuterDocAccessible::CacheChildren
   if (!innerNode) {
     return;
   }
 
   nsCOMPtr<nsIAccessible> innerAccessible;
   nsCOMPtr<nsIAccessibilityService> accService = 
     do_GetService("@mozilla.org/accessibilityService;1");
   accService->GetAccessibleFor(innerNode, getter_AddRefs(innerAccessible));
-  nsCOMPtr<nsPIAccessible> privateInnerAccessible = 
-    do_QueryInterface(innerAccessible);
-  if (!privateInnerAccessible) {
+  nsRefPtr<nsAccessible> innerAcc(nsAccUtils::QueryAccessible(innerAccessible));
+  if (!innerAcc)
     return;
-  }
 
   // Success getting inner document as first child -- now we cache it.
   mAccChildCount = 1;
   SetFirstChild(innerAccessible); // weak ref
-  privateInnerAccessible->SetParent(this);
-  privateInnerAccessible->SetNextSibling(nsnull);
+  innerAcc->SetParent(this);
+  innerAcc->SetNextSibling(nsnull);
 }
 
 nsresult
 nsOuterDocAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
   nsAutoString tag;
   aAttributes->GetStringProperty(NS_LITERAL_CSTRING("tag"), tag);
   if (!tag.IsEmpty()) {
--- a/accessible/src/base/nsRootAccessible.cpp
+++ b/accessible/src/base/nsRootAccessible.cpp
@@ -55,31 +55,31 @@
 #include "nsIDOMDataContainerEvent.h"
 #include "nsIDOMNSEvent.h"
 #include "nsIDOMXULMenuListElement.h"
 #include "nsIDOMXULMultSelectCntrlEl.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
 #include "nsIDOMXULPopupElement.h"
 #include "nsIDocument.h"
 #include "nsIEventListenerManager.h"
-#include "nsIFocusController.h"
 #include "nsIFrame.h"
 #include "nsIMenuFrame.h"
 #include "nsIHTMLDocument.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIScrollableView.h"
 #include "nsISelectionPrivate.h"
 #include "nsIServiceManager.h"
 #include "nsIViewManager.h"
 #include "nsPIDOMWindow.h"
 #include "nsIWebBrowserChrome.h"
 #include "nsReadableUtils.h"
 #include "nsRootAccessible.h"
 #include "nsIDOMNSEventTarget.h"
 #include "nsIDOMDocumentEvent.h"
+#include "nsFocusManager.h"
 
 #ifdef MOZ_XUL
 #include "nsXULTreeAccessible.h"
 #include "nsIXULDocument.h"
 #include "nsIXULWindow.h"
 #endif
 
 #ifdef MOZ_ACCESSIBILITY_ATK
@@ -229,26 +229,28 @@ nsRootAccessible::GetStateInternal(PRUin
   }
 #endif
 
   if (!aExtraState)
     return NS_OK;
 
   nsCOMPtr<nsIDOMWindow> domWin;
   GetWindow(getter_AddRefs(domWin));
-  nsCOMPtr<nsPIDOMWindow> privateDOMWindow(do_QueryInterface(domWin));
-  if (privateDOMWindow) {
-    nsIFocusController *focusController =
-      privateDOMWindow->GetRootFocusController();
-    if (focusController) {
-      PRBool isActive = PR_FALSE;
-      focusController->GetActive(&isActive);
-      if (isActive) {
+  nsCOMPtr<nsIDocShellTreeItem> dsti = do_GetInterface(domWin);
+  if (dsti) {
+    nsCOMPtr<nsIDocShellTreeItem> root;
+    dsti->GetRootTreeItem(getter_AddRefs(root));
+    nsCOMPtr<nsIDOMWindow> rootWindow = do_GetInterface(root);
+
+    nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
+    if (fm && rootWindow) {
+      nsCOMPtr<nsIDOMWindow> activeWindow;
+      fm->GetActiveWindow(getter_AddRefs(activeWindow));
+      if (activeWindow == rootWindow)
         *aExtraState |= nsIAccessibleStates::EXT_STATE_ACTIVE;
-      }
     }
   }
 #ifdef MOZ_XUL
   if (GetChromeFlags() & nsIWebBrowserChrome::CHROME_MODAL) {
     *aExtraState |= nsIAccessibleStates::EXT_STATE_MODAL;
   }
 #endif
 
@@ -656,18 +658,18 @@ nsresult nsRootAccessible::HandleEventWi
 
   nsCOMPtr<nsIAccessible> accessible;
   accService->GetAccessibleInShell(aTargetNode, eventShell,
                                    getter_AddRefs(accessible));
 
   if (eventType.EqualsLiteral("popuphiding"))
     return HandlePopupHidingEvent(aTargetNode, accessible);
 
-  nsCOMPtr<nsPIAccessible> privAcc(do_QueryInterface(accessible));
-  if (!privAcc)
+  nsRefPtr<nsAccessible> acc(nsAccUtils::QueryAccessible(accessible));
+  if (!acc)
     return NS_OK;
 
 #ifdef MOZ_XUL
   if (isTree) {
     nsCOMPtr<nsIAccessibleTreeCache> treeAcc(do_QueryInterface(accessible));
     NS_ASSERTION(treeAcc,
                  "Accessible for xul:tree doesn't implement nsIAccessibleTreeCache interface.");
 
@@ -692,17 +694,17 @@ nsresult nsRootAccessible::HandleEventWi
     // nsXULListitemAccessible::GetStateInternal uses STATE_SELECTED in this case,
     // so we need to check nsIAccessibleStates::STATE_SELECTED also.
     PRBool isEnabled = (state & (nsIAccessibleStates::STATE_CHECKED |
                         nsIAccessibleStates::STATE_SELECTED)) != 0;
 
     nsCOMPtr<nsIAccessibleStateChangeEvent> accEvent =
       new nsAccStateChangeEvent(accessible, nsIAccessibleStates::STATE_CHECKED,
                                 PR_FALSE, isEnabled);
-    privAcc->FireAccessibleEvent(accEvent);
+    acc->FireAccessibleEvent(accEvent);
 
     if (isEnabled)
       FireAccessibleFocusEvent(accessible, aTargetNode, aEvent);
 
     return NS_OK;
   }
 
   if (eventType.EqualsLiteral("CheckboxStateChange")) {
@@ -710,17 +712,17 @@ nsresult nsRootAccessible::HandleEventWi
 
     PRBool isEnabled = !!(state & nsIAccessibleStates::STATE_CHECKED);
 
     nsCOMPtr<nsIAccessibleStateChangeEvent> accEvent =
       new nsAccStateChangeEvent(accessible,
                                 nsIAccessibleStates::STATE_CHECKED,
                                 PR_FALSE, isEnabled);
 
-    return privAcc->FireAccessibleEvent(accEvent);
+    return acc->FireAccessibleEvent(accEvent);
   }
 
   nsCOMPtr<nsIAccessible> treeItemAccessible;
 #ifdef MOZ_XUL
   // If it's a tree element, need the currently selected item
   if (isTree) {
     nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelect =
       do_QueryInterface(aTargetNode);
@@ -1121,19 +1123,18 @@ nsRootAccessible::HandlePopupShownEvent(
     if (comboboxRole == nsIAccessibleRole::ROLE_COMBOBOX ||
         comboboxRole == nsIAccessibleRole::ROLE_AUTOCOMPLETE) {
       nsCOMPtr<nsIAccessibleStateChangeEvent> event =
         new nsAccStateChangeEvent(comboboxAcc,
                                   nsIAccessibleStates::STATE_EXPANDED,
                                   PR_FALSE, PR_TRUE);
       NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
 
-      nsCOMPtr<nsPIAccessible> pComboboxAcc(do_QueryInterface(comboboxAcc));
-
-      return pComboboxAcc->FireAccessibleEvent(event);
+      nsRefPtr<nsAccessible> acc(nsAccUtils::QueryAccessible(comboboxAcc));
+      return acc->FireAccessibleEvent(event);
     }
   }
 
   return NS_OK;
 }
 
 nsresult
 nsRootAccessible::HandlePopupHidingEvent(nsIDOMNode *aNode,
@@ -1166,19 +1167,18 @@ nsRootAccessible::HandlePopupHidingEvent
   if (comboboxRole == nsIAccessibleRole::ROLE_COMBOBOX ||
       comboboxRole == nsIAccessibleRole::ROLE_AUTOCOMPLETE) {
     nsCOMPtr<nsIAccessibleStateChangeEvent> event =
       new nsAccStateChangeEvent(comboboxAcc,
                                 nsIAccessibleStates::STATE_EXPANDED,
                                 PR_FALSE, PR_FALSE);
     NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
 
-    nsCOMPtr<nsPIAccessible> pComboboxAcc(do_QueryInterface(comboboxAcc));
-
-    return pComboboxAcc->FireAccessibleEvent(event);
+    nsRefPtr<nsAccessible> acc(nsAccUtils::QueryAccessible(comboboxAcc));
+    return acc->FireAccessibleEvent(event);
   }
 
   return NS_OK;
 }
 
 #ifdef MOZ_XUL
 nsresult
 nsRootAccessible::HandleTreeRowCountChangedEvent(nsIDOMEvent *aEvent,
--- a/accessible/src/base/nsTextAccessible.cpp
+++ b/accessible/src/base/nsTextAccessible.cpp
@@ -48,18 +48,18 @@
 nsTextAccessible::nsTextAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell):
 nsLinkableAccessible(aDOMNode, aShell)
 { 
 }
 
 // Make sure we don't support text or other irrelevant interfaces.
 // We have nsLinkableAccessible in our inheritance chain as a convenience in order to
 // get link actions and states on the text accessibles. Windows screen readers expect that.
-NS_IMPL_ISUPPORTS_INHERITED3(nsTextAccessible, nsAccessNode,
-                             nsAccessible, nsIAccessible, nsPIAccessible)
+NS_IMPL_ISUPPORTS_INHERITED2(nsTextAccessible, nsAccessNode,
+                             nsAccessible, nsIAccessible)
 
 /**
   * We are text
   */
 nsresult
 nsTextAccessible::GetRoleInternal(PRUint32 *aRole)
 {
   *aRole = nsIAccessibleRole::ROLE_TEXT_LEAF;
@@ -88,17 +88,17 @@ NS_IMETHODIMP nsTextAccessible::GetLastC
   * No Children
   */
 NS_IMETHODIMP nsTextAccessible::GetChildCount(PRInt32 *_retval)
 {
   *_retval = 0;
   return NS_OK;
 }
 
-NS_IMETHODIMP
+nsresult
 nsTextAccessible::AppendTextTo(nsAString& aText, PRUint32 aStartOffset, PRUint32 aLength)
 {
   nsIFrame *frame = GetFrame();
   NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
 
   return frame->GetRenderedText(&aText, nsnull, nsnull, aStartOffset, aLength);
 }
 
--- a/accessible/src/base/nsTextAccessible.h
+++ b/accessible/src/base/nsTextAccessible.h
@@ -53,18 +53,17 @@ public:
 
   nsTextAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell);
 
   // nsIAccessible
   NS_IMETHOD GetFirstChild(nsIAccessible **_retval);
   NS_IMETHOD GetLastChild(nsIAccessible **_retval);
   NS_IMETHOD GetChildCount(PRInt32 *_retval);
 
-  // nsPIAccessible
-  NS_IMETHOD AppendTextTo(nsAString& aText, PRUint32 aStartOffset, PRUint32 aLength);
-
   // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
+  virtual nsresult AppendTextTo(nsAString& aText, PRUint32 aStartOffset,
+                                PRUint32 aLength);
 };
 
 
 #endif
 
--- a/accessible/src/base/nsTextAttrs.cpp
+++ b/accessible/src/base/nsTextAttrs.cpp
@@ -526,18 +526,18 @@ nsBGColorTextAttr::Format(const nscolor&
   aFormattedValue = value;
 }
 
 PRBool
 nsBGColorTextAttr::GetColor(nsIFrame *aFrame, nscolor *aColor)
 {
   const nsStyleBackground *styleBackground = aFrame->GetStyleBackground();
 
-  if (NS_GET_A(styleBackground->mFallbackBackgroundColor) > 0) {
-    *aColor = styleBackground->mFallbackBackgroundColor;
+  if (NS_GET_A(styleBackground->mBackgroundColor) > 0) {
+    *aColor = styleBackground->mBackgroundColor;
     return PR_TRUE;
   }
 
   nsIFrame *parentFrame = aFrame->GetParent();
   if (!parentFrame) {
     *aColor = aFrame->PresContext()->DefaultBackgroundColor();
     return PR_TRUE;
   }
--- a/accessible/src/base/nsTextEquivUtils.cpp
+++ b/accessible/src/base/nsTextEquivUtils.cpp
@@ -70,17 +70,18 @@ nsTextEquivUtils::GetNameFromSubtree(nsI
 
     nsCOMPtr<nsIDOMNode> DOMNode;
     accessNode->GetDOMNode(getter_AddRefs(DOMNode));
     nsCOMPtr<nsIContent> content(do_QueryInterface(DOMNode));
     if (content) {
       nsAutoString name;
       AppendFromAccessibleChildren(aAccessible, &name);
       name.CompressWhitespace();
-      aName = name;
+      if (!IsWhitespaceString(name))
+        aName = name;
     }
   }
 
   gInitiatorAcc = nsnull;
 
   return NS_OK;
 }
 
@@ -414,16 +415,37 @@ nsTextEquivUtils::AppendString(nsAString
 
   if (!aString->IsEmpty())
     aString->Append(PRUnichar(' '));
 
   aString->Append(aTextEquivalent);
   return PR_TRUE;
 }
 
+PRBool
+nsTextEquivUtils::IsWhitespaceString(const nsSubstring& aString)
+{
+  nsSubstring::const_char_iterator iterBegin, iterEnd;
+
+  aString.BeginReading(iterBegin);
+  aString.EndReading(iterEnd);
+
+  while (iterBegin != iterEnd && IsWhitespace(*iterBegin))
+    ++iterBegin;
+
+  return iterBegin == iterEnd;
+}
+
+PRBool
+nsTextEquivUtils::IsWhitespace(PRUnichar aChar)
+{
+  return aChar == ' ' || aChar == '\n' ||
+    aChar == '\r' || aChar == '\t' || aChar == 0xa0;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Name rules to role map.
 
 PRUint32 nsTextEquivUtils::gRoleToNameRulesMap[] =
 {
   eNoRule,           // ROLE_NOTHING
   eNoRule,           // ROLE_TITLEBAR
   eNoRule,           // ROLE_MENUBAR
--- a/accessible/src/base/nsTextEquivUtils.h
+++ b/accessible/src/base/nsTextEquivUtils.h
@@ -155,16 +155,28 @@ private:
   /**
    * Concatenates strings and appends space between them. Returns true if
    * text equivalent string was appended.
    */
   static PRBool AppendString(nsAString *aString,
                              const nsAString& aTextEquivalent);
 
   /**
+   * Returns true if the given string is empty or contains whitespace symbols
+   * only. In contrast to nsWhitespaceTokenizer class it takes into account
+   * non-breaking space (0xa0).
+   */
+  static PRBool IsWhitespaceString(const nsSubstring& aString);
+
+  /**
+   * Returns true if the given character is whitespace symbol.
+   */
+  static PRBool IsWhitespace(PRUnichar aChar);
+
+  /**
    * Map array from roles to name rules (constants of ETextEquivRule).
    */
   static PRUint32 gRoleToNameRulesMap[];
 
   /**
    * The accessible for which we are computing a text equivalent. It is useful
    * for bailing out during recursive text computation, or for special cases
    * like step f. of the ARIA implementation guide.
--- a/accessible/src/html/nsHTMLImageAccessible.cpp
+++ b/accessible/src/html/nsHTMLImageAccessible.cpp
@@ -172,31 +172,28 @@ void nsHTMLImageAccessible::CacheChildre
   if (!mapAreas)
     return;
 
   PRUint32 numMapAreas;
   mapAreas->GetLength(&numMapAreas);
   PRInt32 childCount = 0;
   
   nsCOMPtr<nsIAccessible> areaAccessible;
-  nsCOMPtr<nsPIAccessible> privatePrevAccessible;
+  nsRefPtr<nsAccessible> prevAcc;
   while (childCount < (PRInt32)numMapAreas && 
          (areaAccessible = GetAreaAccessible(mapAreas, childCount)) != nsnull) {
-    if (privatePrevAccessible) {
-      privatePrevAccessible->SetNextSibling(areaAccessible);
-    }
-    else {
+    if (prevAcc)
+      prevAcc->SetNextSibling(areaAccessible);
+    else
       SetFirstChild(areaAccessible);
-    }
 
     ++ childCount;
 
-    privatePrevAccessible = do_QueryInterface(areaAccessible);
-    NS_ASSERTION(privatePrevAccessible, "nsIAccessible impl's should always support nsPIAccessible as well");
-    privatePrevAccessible->SetParent(this);
+    prevAcc = nsAccUtils::QueryAccessible(areaAccessible);
+    prevAcc->SetParent(this);
   }
   mAccChildCount = childCount;
 }
 
 NS_IMETHODIMP
 nsHTMLImageAccessible::GetNumActions(PRUint8 *aNumActions)
 {
   NS_ENSURE_ARG_POINTER(aNumActions);
--- a/accessible/src/html/nsHTMLSelectAccessible.cpp
+++ b/accessible/src/html/nsHTMLSelectAccessible.cpp
@@ -372,33 +372,31 @@ nsHTMLSelectListAccessible::AccessibleFo
                                                 nsIAccessible *aLastGoodAccessible,
                                                 PRInt32 *aChildCount)
 {
   nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(aContent));
   NS_ASSERTION(domNode, "DOM node is null");
   // Accessibility service will initialize & cache any accessibles created
   nsCOMPtr<nsIAccessible> accessible;
   aAccService->GetAccessibleInWeakShell(domNode, mWeakShell, getter_AddRefs(accessible));
-  nsCOMPtr<nsPIAccessible> privateAccessible(do_QueryInterface(accessible));
-  if (!privateAccessible) {
+  nsRefPtr<nsAccessible> acc(nsAccUtils::QueryAccessible(accessible));
+  if (!acc)
     return nsnull;
-  }
 
   ++ *aChildCount;
-  privateAccessible->SetParent(this);
-  nsCOMPtr<nsPIAccessible> privatePrevAccessible(do_QueryInterface(aLastGoodAccessible));
-  if (privatePrevAccessible) {
-    privatePrevAccessible->SetNextSibling(accessible);
-  }
-  if (!mFirstChild) {
+  acc->SetParent(this);
+  nsRefPtr<nsAccessible> prevAcc =
+    nsAccUtils::QueryAccessible(aLastGoodAccessible);
+  if (prevAcc)
+    prevAcc->SetNextSibling(accessible);
+
+  if (!mFirstChild)
     mFirstChild = accessible;
-  }
-  nsIAccessible *returnAccessible = accessible;
-  NS_ADDREF(returnAccessible);
-  return returnAccessible;
+
+  return accessible.forget();
 }
 
 already_AddRefed<nsIAccessible>
 nsHTMLSelectListAccessible::CacheOptSiblings(nsIAccessibilityService *aAccService,
                                              nsIContent *aParentContent,
                                              nsIAccessible *aLastGoodAccessible,
                                              PRInt32 *aChildCount)
 {
@@ -426,23 +424,24 @@ nsHTMLSelectListAccessible::CacheOptSibl
         newAccessible = CacheOptSiblings(aAccService, childContent,
                                          lastGoodAccessible, aChildCount);
         if (newAccessible) {
           lastGoodAccessible = newAccessible;
         }
       }
     }
   }
+
   if (lastGoodAccessible) {
-    nsCOMPtr<nsPIAccessible> privateLastAcc =
-      do_QueryInterface(lastGoodAccessible);
-    privateLastAcc->SetNextSibling(nsnull);
-    NS_ADDREF(aLastGoodAccessible = lastGoodAccessible);
+    nsRefPtr<nsAccessible> lastAcc =
+      nsAccUtils::QueryAccessible(lastGoodAccessible);
+    lastAcc->SetNextSibling(nsnull);
   }
-  return aLastGoodAccessible;
+
+  return lastGoodAccessible.forget();
 }
 
 /**
   * Cache the children and child count of a Select List Accessible. We want to count 
   *  all the <optgroup>s and <option>s as children because we want a 
   *  flat tree under the Select List.
   */
 
@@ -840,28 +839,24 @@ void nsHTMLSelectOptionAccessible::Selec
     return;
   }
 
   nsCOMPtr<nsIDOMNode> optionNode(do_QueryInterface(aPossibleOption));
   NS_ASSERTION(optionNode, "No option node for nsIContent with option tag!");
 
   nsCOMPtr<nsIAccessible> multiSelect =
     nsAccUtils::GetMultiSelectFor(optionNode);
-  nsCOMPtr<nsPIAccessible> privateMultiSelect = do_QueryInterface(multiSelect);
-  if (!privateMultiSelect) {
+  if (!multiSelect)
     return;
-  }
 
-  nsCOMPtr<nsIAccessibilityService> accService = 
-    do_GetService("@mozilla.org/accessibilityService;1");
   nsCOMPtr<nsIAccessible> optionAccessible;
-  accService->GetAccessibleFor(optionNode, getter_AddRefs(optionAccessible));
-  if (!optionAccessible) {
+  GetAccService()->GetAccessibleFor(optionNode,
+                                    getter_AddRefs(optionAccessible));
+  if (!optionAccessible)
     return;
-  }
 
   nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_SELECTION_WITHIN,
                            multiSelect);
 
   PRUint32 state = nsAccUtils::State(optionAccessible);
   PRUint32 eventType;
   if (state & nsIAccessibleStates::STATE_SELECTED) {
     eventType = nsIAccessibleEvent::EVENT_SELECTION_ADD;
@@ -1245,20 +1240,20 @@ void nsHTMLComboboxTextFieldAccessible::
     nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, PR_TRUE);
     // Seed the frame hint early while we're still on a container node.
     // This is better than doing the GetPrimaryFrameFor() later on
     // a text node, because text nodes aren't in the frame map.
     walker.mState.frame = GetFrame();
 
     walker.GetFirstChild();
     SetFirstChild(walker.mState.accessible);
-    nsCOMPtr<nsPIAccessible> privateChild = 
-      do_QueryInterface(walker.mState.accessible);
-    privateChild->SetParent(this);
-    privateChild->SetNextSibling(nsnull);
+    nsRefPtr<nsAccessible> child =
+      nsAccUtils::QueryAccessible(walker.mState.accessible);
+    child->SetParent(this);
+    child->SetNextSibling(nsnull);
     mAccChildCount = 1;
   }
 }
 
 /** -----ComboboxButtonAccessible ----- */
 
 /** Constructor -- cache our parent */
 nsHTMLComboboxButtonAccessible::nsHTMLComboboxButtonAccessible(nsIAccessible* aParent, 
--- a/accessible/src/html/nsHTMLTableAccessible.cpp
+++ b/accessible/src/html/nsHTMLTableAccessible.cpp
@@ -415,24 +415,28 @@ void nsHTMLTableAccessible::CacheChildre
         if (captionParentAccessible != this) {
           NS_WARNING("Should not happen: parser ensures caption is the table's child, not the tbody's");
           return;
         }
         nsCOMPtr<nsIAccessible> beforeCaptionAccessible;
         captionAccessible->GetPreviousSibling(getter_AddRefs(beforeCaptionAccessible));
         if (beforeCaptionAccessible) {
           // Move caption accessible so that it's the first child
+          nsRefPtr<nsAccessible> acc =
+            nsAccUtils::QueryAccessible(beforeCaptionAccessible);
+
           nsCOMPtr<nsIAccessible> afterCaptionAccessible;
           captionAccessible->GetNextSibling(getter_AddRefs(afterCaptionAccessible));
-          nsCOMPtr<nsPIAccessible> privateAcc = do_QueryInterface(beforeCaptionAccessible);
-          privateAcc->SetNextSibling(afterCaptionAccessible);
+          acc->SetNextSibling(afterCaptionAccessible);
+
           GetFirstChild(getter_AddRefs(afterCaptionAccessible));
           SetFirstChild(captionAccessible);
-          privateAcc = do_QueryInterface(captionAccessible);
-          privateAcc->SetNextSibling(afterCaptionAccessible);        
+
+          acc = nsAccUtils::QueryAccessible(captionAccessible);
+          acc->SetNextSibling(afterCaptionAccessible);        
         }
         // Don't check for more captions, because nsAccessibilityService ensures
         // we don't create accessibles for the other captions, since only the
         // first is actually visible
         break;
       }
     }
   }
@@ -1232,17 +1236,17 @@ NS_IMETHODIMP nsHTMLTableAccessible::Get
 #ifdef DEBUG_A11Y
   printf("\nTABLE: %s\n", NS_ConvertUTF16toUTF8(mLayoutHeuristic).get());
 #endif
 #endif
 
   return NS_OK;
 }
 
-PRBool nsHTMLTableAccessible::HasDescendant(char *aTagName, PRBool aAllowEmpty)
+PRBool nsHTMLTableAccessible::HasDescendant(const char *aTagName, PRBool aAllowEmpty)
 {
   nsCOMPtr<nsIDOMElement> tableElt(do_QueryInterface(mDOMNode));
   NS_ENSURE_TRUE(tableElt, PR_FALSE);
 
   nsCOMPtr<nsIDOMNodeList> nodeList;
   nsAutoString tagName;
   tagName.AssignWithConversion(aTagName);
   tableElt->GetElementsByTagName(tagName, getter_AddRefs(nodeList));
@@ -1380,17 +1384,17 @@ NS_IMETHODIMP nsHTMLTableAccessible::IsP
   // Alternating background color is a common way 
   nsCOMPtr<nsIDOMNodeList> nodeList;
   nsCOMPtr<nsIDOMElement> tableElt(do_QueryInterface(mDOMNode));    
   tableElt->GetElementsByTagName(NS_LITERAL_STRING("tr"), getter_AddRefs(nodeList));
   NS_ENSURE_TRUE(nodeList, NS_ERROR_FAILURE);
   PRUint32 length;
   nodeList->GetLength(&length);
   nsAutoString color, lastRowColor;
-  for (PRInt32 rowCount = 0; rowCount < rows; rowCount ++) {
+  for (PRInt32 rowCount = 0; rowCount < length; rowCount ++) {
     nsCOMPtr<nsIDOMNode> rowNode;
     nodeList->Item(rowCount, getter_AddRefs(rowNode));
 
     nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl;
     nsCoreUtils::GetComputedStyleDeclaration(EmptyString(), rowNode,
                                              getter_AddRefs(styleDecl));
     NS_ENSURE_TRUE(styleDecl, NS_ERROR_FAILURE);
 
--- a/accessible/src/html/nsHTMLTableAccessible.h
+++ b/accessible/src/html/nsHTMLTableAccessible.h
@@ -205,17 +205,17 @@ protected:
    * @param aDoSelect - indicates whether cell should be selected or unselected
    */
   nsresult SelectCell(nsISelection *aSelection, nsIDocument *aDocument,
                       nsIDOMElement *aCellElement, PRBool aDoSelect);
 
   virtual void CacheChildren();
   nsresult GetTableNode(nsIDOMNode **_retval);
   nsresult GetTableLayout(nsITableLayout **aLayoutObject);
-  PRBool HasDescendant(char *aTagName, PRBool aAllowEmpty = PR_TRUE);
+  PRBool HasDescendant(const char *aTagName, PRBool aAllowEmpty = PR_TRUE);
 #ifdef SHOW_LAYOUT_HEURISTIC
   nsAutoString mLayoutHeuristic;
 #endif
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsHTMLTableAccessible,
                               NS_TABLEACCESSIBLE_IMPL_CID)
 
--- a/accessible/src/html/nsHTMLTextAccessible.cpp
+++ b/accessible/src/html/nsHTMLTextAccessible.cpp
@@ -338,32 +338,31 @@ nsHTMLListBulletAccessible::GetStateInte
   nsresult rv = nsLeafAccessible::GetStateInternal(aState, aExtraState);
   NS_ENSURE_A11Y_SUCCESS(rv, rv);
 
   *aState &= ~nsIAccessibleStates::STATE_FOCUSABLE;
   *aState |= nsIAccessibleStates::STATE_READONLY;
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsHTMLListBulletAccessible::SetParent(nsIAccessible *aParentAccessible)
+void
+nsHTMLListBulletAccessible::SetParent(nsIAccessible *aParent)
 {
   mParent = nsnull;
-  mWeakParent = aParentAccessible;
-  return NS_OK;
+  mWeakParent = aParent;
 }
 
 NS_IMETHODIMP
 nsHTMLListBulletAccessible::GetParent(nsIAccessible **aParentAccessible)
 {
   NS_IF_ADDREF(*aParentAccessible = mWeakParent);
   return NS_OK;
 }
 
-NS_IMETHODIMP
+nsresult
 nsHTMLListBulletAccessible::AppendTextTo(nsAString& aText, PRUint32 aStartOffset,
                                          PRUint32 aLength)
 {
   PRUint32 maxLength = mBulletText.Length() - aStartOffset;
   if (aLength > maxLength) {
     aLength = maxLength;
   }
   aText += nsDependentSubstring(mBulletText, aStartOffset, aLength);
--- a/accessible/src/html/nsHTMLTextAccessible.h
+++ b/accessible/src/html/nsHTMLTextAccessible.h
@@ -108,28 +108,27 @@ public:
   NS_IMETHOD GetUniqueID(void **aUniqueID);
 
   // nsIAccessible
   NS_IMETHOD GetName(nsAString& aName);
 
   // Don't cache via unique ID -- bullet accessible shares the same dom node as
   // this LI accessible. Also, don't cache via mParent/SetParent(), prevent
   // circular reference since li holds onto us.
-  NS_IMETHOD SetParent(nsIAccessible *aParentAccessible);
   NS_IMETHOD GetParent(nsIAccessible **aParentAccessible);
 
   // nsAccessNode
   virtual nsresult Shutdown();
 
   // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
-
-  // nsPIAccessible
-  NS_IMETHOD AppendTextTo(nsAString& aText, PRUint32 aStartOffset, PRUint32 aLength);
+  virtual void SetParent(nsIAccessible *aParent);
+  virtual nsresult AppendTextTo(nsAString& aText, PRUint32 aStartOffset,
+                                PRUint32 aLength);
 
 protected:
   // XXX: Ideally we'd get the bullet text directly from the bullet frame via
   // nsBulletFrame::GetListItemText(), but we'd need an interface for getting
   // text from contentless anonymous frames. Perhaps something like
   // nsIAnonymousFrame::GetText() ? However, in practice storing the bullet text
   // here should not be a problem if we invalidate the right parts of
   // the accessibility cache when mutation events occur.
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -226,27 +226,27 @@ void nsHyperTextAccessible::CacheChildre
     mAccChildCount = 0;  // Avoid reentry
     nsCOMPtr<nsIDOMElement> editorRoot;
     editor->GetRootElement(getter_AddRefs(editorRoot));
     nsCOMPtr<nsIDOMNode> editorRootDOMNode = do_QueryInterface(editorRoot);
     if (!editorRootDOMNode) {
       return;
     }
     nsAccessibleTreeWalker walker(mWeakShell, editorRootDOMNode, PR_TRUE);
-    nsCOMPtr<nsPIAccessible> privatePrevAccessible;
+    nsRefPtr<nsAccessible> prevAcc;
     PRInt32 childCount = 0;
     walker.GetFirstChild();
     SetFirstChild(walker.mState.accessible);
 
     while (walker.mState.accessible) {
       ++ childCount;
-      privatePrevAccessible = do_QueryInterface(walker.mState.accessible);
-      privatePrevAccessible->SetParent(this);
+      prevAcc = nsAccUtils::QueryAccessible(walker.mState.accessible);
+      prevAcc->SetParent(this);
       walker.GetNextSibling();
-      privatePrevAccessible->SetNextSibling(walker.mState.accessible);
+      prevAcc->SetNextSibling(walker.mState.accessible);
     }
     mAccChildCount = childCount;
   }
 }
 
 // Substring must be entirely within the same text node
 nsIntRect nsHyperTextAccessible::GetBoundsForString(nsIFrame *aFrame, PRUint32 aStartRenderedOffset,
                                                     PRUint32 aEndRenderedOffset)
@@ -434,19 +434,19 @@ nsHyperTextAccessible::GetPosAndText(PRI
           aEndOffset = endOffset;
         }
         if (aText) {
           if (isPassword) {
             for (PRInt32 count = startOffset; count < substringEndOffset; count ++)
               *aText += '*'; // Show *'s only for password text
           }
           else {
-            nsCOMPtr<nsPIAccessible> pAcc(do_QueryInterface(accessible));
-            pAcc->AppendTextTo(*aText, startOffset,
-                               substringEndOffset - startOffset);
+            nsRefPtr<nsAccessible> acc(nsAccUtils::QueryAccessible(accessible));
+            acc->AppendTextTo(*aText, startOffset,
+                              substringEndOffset - startOffset);
           }
         }
         if (aBoundsRect) {    // Caller wants the bounds of the text
           aBoundsRect->UnionRect(*aBoundsRect,
                                  GetBoundsForString(primaryFrame, startOffset,
                                                     substringEndOffset));
         }
         if (!startFrame) {
--- a/accessible/src/mac/Makefile.in
+++ b/accessible/src/mac/Makefile.in
@@ -72,16 +72,17 @@ CMMSRCS = nsAccessNodeWrap.mm \
           mozTextAccessible.mm \
           $(NULL)
           
 
 EXPORTS = \
   nsAccessNodeWrap.h \
   nsTextAccessibleWrap.h \
   nsAccessibleWrap.h \
+  nsARIAGridAccessibleWrap.h \
   nsDocAccessibleWrap.h \
   nsRootAccessibleWrap.h \
   nsXULMenuAccessibleWrap.h \
   nsXULTreeAccessibleWrap.h \
   nsHyperTextAccessibleWrap.h \
   nsHTMLImageAccessibleWrap.h \
   nsHTMLTableAccessibleWrap.h \
   nsAccessibleRelationWrap.h \
new file mode 100644
--- /dev/null
+++ b/accessible/src/mac/nsARIAGridAccessibleWrap.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 _NSARIAGRIDACCESSIBLEWRAP_H
+#define _NSARIAGRIDACCESSIBLEWRAP_H
+
+#include "nsARIAGridAccessible.h"
+
+typedef class nsARIAGridAccessible nsARIAGridAccessibleWrap;
+
+#endif
+
--- a/accessible/src/mac/nsAccessibleWrap.h
+++ b/accessible/src/mac/nsAccessibleWrap.h
@@ -70,20 +70,20 @@ class nsAccessibleWrap : public nsAccess
     // should be instantied with.   used on runtime to determine the
     // right type for this accessible's associated native object.
     virtual objc_class* GetNativeType ();
     
     // returns a pointer to the native window for this accessible tree.
     void GetNativeWindow (void **aOutNativeWindow);
     
     virtual nsresult Shutdown ();
-    virtual nsresult InvalidateChildren ();
+    virtual void InvalidateChildren();
 
-    NS_IMETHOD FireAccessibleEvent(nsIAccessibleEvent *aEvent);
-    
+    virtual nsresult FireAccessibleEvent(nsIAccessibleEvent *aEvent);
+
     // ignored means that the accessible might still have children, but is not displayed
     // to the user. it also has no native accessible object represented for it.
     PRBool IsIgnored();
     
     PRInt32 GetUnignoredChildCount(PRBool aDeepCount);
     
     PRBool HasPopup () {
       PRUint32 state = 0;
--- a/accessible/src/mac/nsAccessibleWrap.mm
+++ b/accessible/src/mac/nsAccessibleWrap.mm
@@ -154,17 +154,17 @@ nsAccessibleWrap::Shutdown ()
   if (mNativeWrapper) {
     delete mNativeWrapper;
     mNativeWrapper = nsnull;
   }
   
   return nsAccessible::Shutdown();
 }
 
-NS_IMETHODIMP
+nsresult
 nsAccessibleWrap::FireAccessibleEvent(nsIAccessibleEvent *aEvent)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   NS_ENSURE_ARG_POINTER(aEvent);
 
   nsresult rv = nsAccessible::FireAccessibleEvent(aEvent);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -206,28 +206,28 @@ nsAccessibleWrap::FirePlatformEvent(nsIA
       break;
   }
 
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
-nsresult
-nsAccessibleWrap::InvalidateChildren ()
+void
+nsAccessibleWrap::InvalidateChildren()
 {
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+  NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   if (mNativeWrapper) {
     mozAccessible *object = mNativeWrapper->getNativeObject();
     [object invalidateChildren];
   }
-  return nsAccessible::InvalidateChildren();
+  nsAccessible::InvalidateChildren();
 
-  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
+  NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 PRInt32
 nsAccessibleWrap::GetUnignoredChildCount(PRBool aDeepCount)
 {
   // if we're flat, we have no children.
   if (nsAccUtils::MustPrune(this))
     return 0;
--- a/accessible/src/msaa/Makefile.in
+++ b/accessible/src/msaa/Makefile.in
@@ -69,16 +69,17 @@ REQUIRES	= content \
 
 CPPSRCS = \
   nsAccessNodeWrap.cpp \
   nsAccessibleWrap.cpp \
   nsTextAccessibleWrap.cpp \
   nsDocAccessibleWrap.cpp \
   nsRootAccessibleWrap.cpp \
   nsHTMLWin32ObjectAccessible.cpp \
+  nsARIAGridAccessibleWrap.cpp \
   nsXULMenuAccessibleWrap.cpp \
   nsXULTreeAccessibleWrap.cpp \
   nsHyperTextAccessibleWrap.cpp \
   nsHTMLImageAccessibleWrap.cpp \
   nsHTMLTableAccessibleWrap.cpp \
   nsAccessibleRelationWrap.cpp \
   nsApplicationAccessibleWrap.cpp \
   CAccessibleAction.cpp \
@@ -94,16 +95,17 @@ CPPSRCS = \
 
 EXPORTS = \
   nsAccessNodeWrap.h \
   nsAccessibleWrap.h \
   nsTextAccessibleWrap.h \
   nsDocAccessibleWrap.h \
   nsRootAccessibleWrap.h \
   nsHTMLWin32ObjectAccessible.h \
+  nsARIAGridAccessibleWrap.h \
   nsXULMenuAccessibleWrap.h \
   nsXULTreeAccessibleWrap.h \
   nsHyperTextAccessibleWrap.h \
   nsHTMLImageAccessibleWrap.h \
   nsHTMLTableAccessibleWrap.h \
   nsAccessibleRelationWrap.h \
   nsApplicationAccessibleWrap.h \
   CAccessibleAction.h \
new file mode 100644
--- /dev/null
+++ b/accessible/src/msaa/nsARIAGridAccessibleWrap.cpp
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 "nsARIAGridAccessibleWrap.h"
+
+NS_IMPL_ISUPPORTS_INHERITED0(nsARIAGridAccessibleWrap,
+                             nsARIAGridAccessible)
+
+IMPL_IUNKNOWN_INHERITED1(nsARIAGridAccessibleWrap,
+                         nsAccessibleWrap,
+                         CAccessibleTable);
new file mode 100644
--- /dev/null
+++ b/accessible/src/msaa/nsARIAGridAccessibleWrap.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 _NSARIAGRIDACCESSIBLEWRAP_H
+#define _NSARIAGRIDACCESSIBLEWRAP_H
+
+#include "nsARIAGridAccessible.h"
+#include "CAccessibleTable.h"
+
+/**
+ * Accessible for ARIA grid and treegrid implementing IAccessibleTable
+ * interface.
+ */
+class nsARIAGridAccessibleWrap : public nsARIAGridAccessible,
+                                 public CAccessibleTable
+{
+public:
+  nsARIAGridAccessibleWrap(nsIDOMNode* aNode, nsIWeakReference* aShell) :
+    nsARIAGridAccessible(aNode, aShell) {}
+
+  // IUnknown
+  DECL_IUNKNOWN_INHERITED
+
+  // nsISupports
+  NS_DECL_ISUPPORTS_INHERITED
+};
+
+#endif
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -198,18 +198,23 @@ STDMETHODIMP nsAccessibleWrap::get_accPa
       // because MSAA iterates get_accParent() until it sees an object of ROLE_WINDOW
       // to know where the window for a given accessible is. We must expose the native
       // window accessible that MSAA creates for us. This must be done for the document
       // object as well as any layout that creates its own window (e.g. via overflow: scroll)
       nsIWidget *widget = view->GetWidget();
       if (widget) {
         hwnd = (HWND)widget->GetNativeData(NS_NATIVE_WINDOW);
         NS_ASSERTION(hwnd, "No window handle for window");
+
+        nsIViewManager* viewManager = view->GetViewManager();
+        if (!viewManager)
+          return E_UNEXPECTED;
+
         nsIView *rootView;
-        view->GetViewManager()->GetRootView(rootView);
+        viewManager->GetRootView(rootView);
         if (rootView == view) {
           // If the current object has a widget but was created by an
           // outer object with its own outer window, then
           // we want the native accessible for that outer window
           hwnd = ::GetParent(hwnd);
           NS_ASSERTION(hwnd, "No window handle for window");
         }
       }
@@ -1613,19 +1618,19 @@ STDMETHODIMP nsAccessibleWrap::Invoke(DI
 
 NS_IMETHODIMP nsAccessibleWrap::GetNativeInterface(void **aOutAccessible)
 {
   *aOutAccessible = static_cast<IAccessible*>(this);
   NS_ADDREF_THIS();
   return NS_OK;
 }
 
-// nsPIAccessible
+// nsAccessible
 
-NS_IMETHODIMP
+nsresult
 nsAccessibleWrap::FireAccessibleEvent(nsIAccessibleEvent *aEvent)
 {
   NS_ENSURE_ARG(aEvent);
 
   nsresult rv = nsAccessible::FireAccessibleEvent(aEvent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return FirePlatformEvent(aEvent);
--- a/accessible/src/msaa/nsAccessibleWrap.h
+++ b/accessible/src/msaa/nsAccessibleWrap.h
@@ -285,18 +285,18 @@ class nsAccessibleWrap : public nsAccess
   STDMETHODIMP GetTypeInfoCount(UINT *p);
   STDMETHODIMP GetTypeInfo(UINT i, LCID lcid, ITypeInfo **ppti);
   STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames,
                                UINT cNames, LCID lcid, DISPID *rgDispId);
   STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid,
         LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);
 
-  // nsPIAccessible
-  NS_IMETHOD FireAccessibleEvent(nsIAccessibleEvent *aEvent);
+  // nsAccessible
+  virtual nsresult FireAccessibleEvent(nsIAccessibleEvent *aEvent);
 
   // Helper methods
   static PRInt32 GetChildIDFor(nsIAccessible* aAccessible);
   static HWND GetHWNDFor(nsIAccessible *aAccessible);
   static HRESULT ConvertToIA2Attributes(nsIPersistentProperties *aAttributes,
                                         BSTR *aIA2Attributes);
 
   /**
--- a/accessible/src/msaa/nsHyperTextAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsHyperTextAccessibleWrap.cpp
@@ -43,17 +43,17 @@
 NS_IMPL_ISUPPORTS_INHERITED0(nsHyperTextAccessibleWrap,
                              nsHyperTextAccessible)
 
 IMPL_IUNKNOWN_INHERITED2(nsHyperTextAccessibleWrap,
                          nsAccessibleWrap,
                          CAccessibleHypertext,
                          CAccessibleEditableText);
 
-NS_IMETHODIMP
+nsresult
 nsHyperTextAccessibleWrap::FireAccessibleEvent(nsIAccessibleEvent *aEvent)
 {
   PRUint32 eventType;
   aEvent->GetEventType(&eventType);
 
   if (eventType == nsIAccessibleEvent::EVENT_TEXT_REMOVED ||
       eventType == nsIAccessibleEvent::EVENT_TEXT_INSERTED) {
     nsCOMPtr<nsIAccessible> accessible;
--- a/accessible/src/msaa/nsHyperTextAccessibleWrap.h
+++ b/accessible/src/msaa/nsHyperTextAccessibleWrap.h
@@ -55,18 +55,19 @@ public:
     nsHyperTextAccessible(aNode, aShell){}
 
   // IUnknown
   DECL_IUNKNOWN_INHERITED
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
-  // nsIAccessible
-  NS_IMETHOD FireAccessibleEvent(nsIAccessibleEvent *aEvent);
+  // nsAccessible
+  virtual nsresult FireAccessibleEvent(nsIAccessibleEvent *aEvent);
+
 protected:
   virtual nsresult GetModifiedText(PRBool aGetInsertedText, nsAString& aText,
                                    PRUint32 *aStartOffset,
                                    PRUint32 *aEndOffset);
 };
 
 #endif
 
--- a/accessible/src/other/Makefile.in
+++ b/accessible/src/other/Makefile.in
@@ -70,16 +70,17 @@ REQUIRES	= content \
 CPPSRCS = \
   nsAccessNodeWrap.cpp \
   nsAccessibleWrap.cpp \
   nsRootAccessibleWrap.cpp \
   $(NULL)
 
 EXPORTS = \
   nsAccessNodeWrap.h \
+  nsARIAGridAccessibleWrap.h \
   nsTextAccessibleWrap.h \
   nsAccessibleWrap.h \
   nsDocAccessibleWrap.h \
   nsRootAccessibleWrap.h \
   nsXULMenuAccessibleWrap.h \
   nsXULTreeAccessibleWrap.h \
   nsHyperTextAccessibleWrap.h \
   nsHTMLImageAccessibleWrap.h \
new file mode 100644
--- /dev/null
+++ b/accessible/src/other/nsARIAGridAccessibleWrap.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 _NSARIAGRIDACCESSIBLEWRAP_H
+#define _NSARIAGRIDACCESSIBLEWRAP_H
+
+#include "nsARIAGridAccessible.h"
+
+typedef class nsARIAGridAccessible nsARIAGridAccessibleWrap;
+
+#endif
+
--- a/accessible/src/xforms/nsXFormsAccessible.cpp
+++ b/accessible/src/xforms/nsXFormsAccessible.cpp
@@ -128,28 +128,27 @@ nsXFormsAccessible::CacheSelectChildren(
 
   if (!children)
     return;
 
   PRUint32 length = 0;
   children->GetLength(&length);
 
   nsCOMPtr<nsIAccessible> accessible;
-  nsCOMPtr<nsPIAccessible> currAccessible;
-  nsCOMPtr<nsPIAccessible> prevAccessible;
+  nsRefPtr<nsAccessible> currAccessible, prevAccessible;
 
   PRUint32 childLength = 0;
   for (PRUint32 index = 0; index < length; index++) {
     nsCOMPtr<nsIDOMNode> child;
     children->Item(index, getter_AddRefs(child));
     if (!child)
       continue;
 
     accService->GetAttachedAccessibleFor(child, getter_AddRefs(accessible));
-    currAccessible = do_QueryInterface(accessible);
+    currAccessible = nsAccUtils::QueryAccessible(accessible);
     if (!currAccessible)
       continue;
 
     if (childLength == 0)
       SetFirstChild(accessible);
 
     currAccessible->SetParent(this);
     if (prevAccessible) {
@@ -242,23 +241,20 @@ nsXFormsAccessible::GetDescription(nsASt
     aDescription = description;
     return NS_OK;
   }
 
   // search the xforms:hint element
   return GetBoundChildElementValue(NS_LITERAL_STRING("hint"), aDescription);
 }
 
-NS_IMETHODIMP
-nsXFormsAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
+PRBool
+nsXFormsAccessible::GetAllowsAnonChildAccessibles()
 {
-  NS_ENSURE_ARG_POINTER(aAllowsAnonChildren);
-
-  *aAllowsAnonChildren = PR_FALSE;
-  return NS_OK;
+  return PR_FALSE;
 }
 
 // nsXFormsContainerAccessible
 
 nsXFormsContainerAccessible::
 nsXFormsContainerAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell):
   nsXFormsAccessible(aNode, aShell)
 {
@@ -266,23 +262,20 @@ nsXFormsContainerAccessible(nsIDOMNode* 
 
 nsresult
 nsXFormsContainerAccessible::GetRoleInternal(PRUint32 *aRole)
 {
   *aRole = nsIAccessibleRole::ROLE_GROUPING;
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsXFormsContainerAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
+PRBool
+nsXFormsContainerAccessible::GetAllowsAnonChildAccessibles()
 {
-  NS_ENSURE_ARG_POINTER(aAllowsAnonChildren);
-
-  *aAllowsAnonChildren = PR_TRUE;
-  return NS_OK;
+  return PR_TRUE;
 }
 
 // nsXFormsEditableAccessible
 
 nsXFormsEditableAccessible::
   nsXFormsEditableAccessible(nsIDOMNode *aNode, nsIWeakReference *aShell):
   nsXFormsAccessible(aNode, aShell)
 {
--- a/accessible/src/xforms/nsXFormsAccessible.h
+++ b/accessible/src/xforms/nsXFormsAccessible.h
@@ -86,17 +86,17 @@ public:
   virtual nsresult GetNameInternal(nsAString& aName);
 
   // Returns state of xforms element taking into account state of instance node
   // that it is bound to.
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
 
   // Denies accessible nodes in anonymous content of xforms element by
   // always returning PR_FALSE value.
-  NS_IMETHOD GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren);
+  virtual PRBool GetAllowsAnonChildAccessibles();
 
 protected:
   // Returns value of first child xforms element by tagname that is bound to
   // instance node.
   nsresult GetBoundChildElementValue(const nsAString& aTagName,
                                      nsAString& aValue);
 
   // Cache accessible child item/choices elements. For example, the method is
@@ -122,22 +122,22 @@ protected:
  * an XForms upload element since it is constructed from textfield and
  * 'pick up file' and 'clear file' buttons.
  */
 class nsXFormsContainerAccessible : public nsXFormsAccessible
 {
 public:
   nsXFormsContainerAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
 
+  // nsAccessible
+  virtual nsresult GetRoleInternal(PRUint32 *aRole);
+
   // Allows accessible nodes in anonymous content of xforms element by
   // always returning PR_TRUE value.
-  NS_IMETHOD GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren);
-
-  // nsAccessible
-  virtual nsresult GetRoleInternal(PRUint32 *aRole);
+  virtual PRBool GetAllowsAnonChildAccessibles();
 };
 
 
 /**
  * The class is base for accessible objects for XForms elements that have
  * editable area.
  */
 class nsXFormsEditableAccessible : public nsXFormsAccessible
--- a/accessible/src/xforms/nsXFormsFormControlsAccessible.cpp
+++ b/accessible/src/xforms/nsXFormsFormControlsAccessible.cpp
@@ -581,23 +581,20 @@ nsXFormsSelectComboboxAccessible::GetSta
   else
     *aState = nsIAccessibleStates::STATE_COLLAPSED;
 
   *aState |= nsIAccessibleStates::STATE_HASPOPUP |
              nsIAccessibleStates::STATE_FOCUSABLE;
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsXFormsSelectComboboxAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
+PRBool
+nsXFormsSelectComboboxAccessible::GetAllowsAnonChildAccessibles()
 {
-  NS_ENSURE_ARG_POINTER(aAllowsAnonChildren);
-
-  *aAllowsAnonChildren = PR_TRUE;
-  return NS_OK;
+  return PR_TRUE;
 }
 
 
 // nsXFormsItemComboboxAccessible
 
 nsXFormsItemComboboxAccessible::
   nsXFormsItemComboboxAccessible(nsIDOMNode *aNode, nsIWeakReference *aShell):
   nsXFormsSelectableItemAccessible(aNode, aShell)
--- a/accessible/src/xforms/nsXFormsFormControlsAccessible.h
+++ b/accessible/src/xforms/nsXFormsFormControlsAccessible.h
@@ -276,23 +276,20 @@ public:
  * represented by combobox.
  */
 
 class nsXFormsSelectComboboxAccessible : public nsXFormsSelectableAccessible
 {
 public:
   nsXFormsSelectComboboxAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
 
-  // Allows accessible nodes in anonymous content of xforms element by
-  // always returning PR_TRUE value.
-  NS_IMETHOD GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren);
-
   // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
+  virtual PRBool GetAllowsAnonChildAccessibles();
 };
 
 
 /**
  * Accessible object for xforms:item element when it is represented by a
  * listitem. This occurs when the item is contained in a xforms:select with
  * minimal appearance. Such a xforms:select is represented by a combobox.
  */
--- a/accessible/src/xul/nsXULFormControlAccessible.cpp
+++ b/accessible/src/xul/nsXULFormControlAccessible.cpp
@@ -174,37 +174,37 @@ void nsXULButtonAccessible::CacheChildre
   // An XUL button accessible may have 1 child dropmarker accessible
   if (!mWeakShell) {
     mAccChildCount = eChildCountUninitialized;
     return;   // This outer doc node has been shut down
   }
   if (mAccChildCount == eChildCountUninitialized) {
     mAccChildCount = 0;  // Avoid reentry
     SetFirstChild(nsnull);
-    PRBool allowsAnonChildren = PR_FALSE;
-    GetAllowsAnonChildAccessibles(&allowsAnonChildren);
+    PRBool allowsAnonChildren = GetAllowsAnonChildAccessibles();
     nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, allowsAnonChildren);
     walker.GetFirstChild();
     nsCOMPtr<nsIAccessible> dropMarkerAccessible;
     while (walker.mState.accessible) {
       dropMarkerAccessible = walker.mState.accessible;
       walker.GetNextSibling();
     }
 
     // If the anonymous tree walker can find accessible children, 
     // and the last one is a push button, then use it as the only accessible 
     // child -- because this is the scenario where we have a dropmarker child
 
     if (dropMarkerAccessible) {
       if (nsAccUtils::RoleInternal(dropMarkerAccessible) ==
           nsIAccessibleRole::ROLE_PUSHBUTTON) {
         SetFirstChild(dropMarkerAccessible);
-        nsCOMPtr<nsPIAccessible> privChildAcc = do_QueryInterface(dropMarkerAccessible);
-        privChildAcc->SetNextSibling(nsnull);
-        privChildAcc->SetParent(this);
+        nsRefPtr<nsAccessible> childAcc =
+          nsAccUtils::QueryAccessible(dropMarkerAccessible);
+        childAcc->SetNextSibling(nsnull);
+        childAcc->SetParent(this);
         mAccChildCount = 1;
       }
     }
   }
 }
 
 /**
   * XUL Dropmarker: can contain arbitrary HTML content
@@ -984,21 +984,20 @@ NS_IMETHODIMP nsXULTextFieldAccessible::
       element->Focus();
       return NS_OK;
     }
     return NS_ERROR_FAILURE;
   }
   return NS_ERROR_INVALID_ARG;
 }
 
-NS_IMETHODIMP
-nsXULTextFieldAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
+PRBool
+nsXULTextFieldAccessible::GetAllowsAnonChildAccessibles()
 {
-  *aAllowsAnonChildren = PR_FALSE;
-  return NS_OK;
+  return PR_FALSE;
 }
 
 NS_IMETHODIMP nsXULTextFieldAccessible::GetAssociatedEditor(nsIEditor **aEditor)
 {
   *aEditor = nsnull;
   nsCOMPtr<nsIDOMNode> inputField = GetInputField();
   nsCOMPtr<nsIDOMNSEditableElement> editableElt(do_QueryInterface(inputField));
   NS_ENSURE_TRUE(editableElt, NS_ERROR_FAILURE);
--- a/accessible/src/xul/nsXULFormControlAccessible.h
+++ b/accessible/src/xul/nsXULFormControlAccessible.h
@@ -194,24 +194,24 @@ public:
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessible
   NS_IMETHOD GetValue(nsAString& aValue);
   NS_IMETHOD GetNumActions(PRUint8 *_retval);
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD DoAction(PRUint8 index);
-  NS_IMETHOD GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren);
 
   // nsIAccessibleEditableText
   NS_IMETHOD GetAssociatedEditor(nsIEditor **aEditor);
 
   // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
+  virtual PRBool GetAllowsAnonChildAccessibles();
 
 protected:
   already_AddRefed<nsIDOMNode> GetInputField();
 };
 
 
 #endif  
 
--- a/accessible/src/xul/nsXULMenuAccessible.cpp
+++ b/accessible/src/xul/nsXULMenuAccessible.cpp
@@ -510,22 +510,21 @@ nsXULMenuitemAccessible::GetAttributesIn
 
   nsresult rv = nsAccessible::GetAttributesInternal(aAttributes);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAccUtils::SetAccAttrsForXULContainerItem(mDOMNode, aAttributes);
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsXULMenuitemAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
+PRBool
+nsXULMenuitemAccessible::GetAllowsAnonChildAccessibles()
 {
   // That indicates we don't walk anonymous children for menuitems
-  *aAllowsAnonChildren = PR_FALSE;
-  return NS_OK;
+  return PR_FALSE;
 }
 
 NS_IMETHODIMP nsXULMenuitemAccessible::DoAction(PRUint8 index)
 {
   if (index == eAction_Click) {   // default action
     DoCommand();
     return NS_OK;
   }
--- a/accessible/src/xul/nsXULMenuAccessible.h
+++ b/accessible/src/xul/nsXULMenuAccessible.h
@@ -89,17 +89,17 @@ public:
   virtual nsresult Init();
 
   // nsAccessible
   virtual nsresult GetNameInternal(nsAString& aName);
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
   virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
 
-  NS_IMETHOD GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren);
+  virtual PRBool GetAllowsAnonChildAccessibles();
 };
 
 class nsXULMenuSeparatorAccessible : public nsXULMenuitemAccessible
 {
 public:
   nsXULMenuSeparatorAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell);
 
   // nsIAccessible
--- a/accessible/src/xul/nsXULSelectAccessible.cpp
+++ b/accessible/src/xul/nsXULSelectAccessible.cpp
@@ -954,22 +954,21 @@ NS_IMETHODIMP nsXULListitemAccessible::G
     else
       aName.AssignLiteral("check");
 
     return NS_OK;
   }
   return NS_ERROR_INVALID_ARG;
 }
 
-NS_IMETHODIMP
-nsXULListitemAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
+PRBool
+nsXULListitemAccessible::GetAllowsAnonChildAccessibles()
 {
   // That indicates we should walk anonymous children for listitems
-  *aAllowsAnonChildren = PR_TRUE;
-  return NS_OK;
+  return PR_TRUE;
 }
 
 nsresult
 nsXULListitemAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
   NS_ENSURE_ARG_POINTER(aAttributes);
 
   // Call base class instead of nsXULMenuAccessible because menu accessible
@@ -1101,37 +1100,36 @@ NS_IMETHODIMP nsXULComboboxAccessible::G
     accService->GetAccessibleInWeakShell(focusedOptionNode, mWeakShell, 
                                         getter_AddRefs(focusedOptionAccessible));
     NS_ENSURE_TRUE(focusedOptionAccessible, NS_ERROR_FAILURE);
     return focusedOptionAccessible->GetDescription(aDescription);
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsXULComboboxAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
+PRBool
+nsXULComboboxAccessible::GetAllowsAnonChildAccessibles()
 {
-  if (!mDOMNode)
-    return NS_ERROR_FAILURE;
-
   nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
+  NS_ASSERTION(content, "No content during accessible tree building!");
+  if (!content)
+    return PR_FALSE;
 
   if (content->NodeInfo()->Equals(nsAccessibilityAtoms::textbox, kNameSpaceID_XUL) ||
       content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::editable,
                            nsAccessibilityAtoms::_true, eIgnoreCase)) {
     // Both the XUL <textbox type="autocomplete"> and <menulist editable="true"> widgets
     // use nsXULComboboxAccessible. We need to walk the anonymous children for these
     // so that the entry field is a child
-    *aAllowsAnonChildren = PR_TRUE;
-  } else {
-    // Argument of PR_FALSE indicates we don't walk anonymous children for
-    // menuitems
-    *aAllowsAnonChildren = PR_FALSE;
+    return PR_TRUE;
   }
-  return NS_OK;
+
+  // Argument of PR_FALSE indicates we don't walk anonymous children for
+  // menuitems
+  return PR_FALSE;
 }
 
 /** Just one action ( click ). */
 NS_IMETHODIMP nsXULComboboxAccessible::GetNumActions(PRUint8 *aNumActions)
 {
   *aNumActions = 1;
   return NS_OK;
 }
--- a/accessible/src/xul/nsXULSelectAccessible.h
+++ b/accessible/src/xul/nsXULSelectAccessible.h
@@ -136,23 +136,23 @@ public:
   
   nsXULListitemAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
   virtual ~nsXULListitemAccessible() {}
 
   // nsIAccessible
   NS_IMETHOD GetActionName(PRUint8 index, nsAString& aName);
   // Don't use XUL menuitems's description attribute
   NS_IMETHOD GetDescription(nsAString& aDesc) { return nsAccessibleWrap::GetDescription(aDesc); }
-  NS_IMETHOD GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren);
 
   // nsAccessible
   virtual nsresult GetNameInternal(nsAString& aName);
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
   virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
+  virtual PRBool GetAllowsAnonChildAccessibles();
 
 protected:
   already_AddRefed<nsIAccessible> GetListAccessible();
 
 private:
   PRBool mIsCheckbox;
 };
 
@@ -178,25 +178,25 @@ public:
 class nsXULComboboxAccessible : public nsAccessibleWrap
 {
 public:
   enum { eAction_Click = 0 };
 
   nsXULComboboxAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
   virtual ~nsXULComboboxAccessible() {}
 
-  /* ----- nsIAccessible ----- */
+  // nsIAccessible
   NS_IMETHOD GetValue(nsAString& _retval);
   NS_IMETHOD GetDescription(nsAString& aDescription);
-  NS_IMETHOD GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren);
   NS_IMETHOD DoAction(PRUint8 index);
   NS_IMETHOD GetNumActions(PRUint8 *aNumActions);
   NS_IMETHOD GetActionName(PRUint8 index, nsAString& aName);
 
   // nsAccessNode
   virtual nsresult Init();
 
   // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
+  virtual PRBool GetAllowsAnonChildAccessibles();
 };
 
 #endif
--- a/accessible/src/xul/nsXULSliderAccessible.cpp
+++ b/accessible/src/xul/nsXULSliderAccessible.cpp
@@ -183,25 +183,21 @@ nsXULSliderAccessible::SetCurrentValue(d
 
   // ARIA redefined current value.
   if (rv != NS_OK_NO_ARIA_VALUE)
     return rv;
 
   return SetSliderAttr(nsAccessibilityAtoms::curpos, aValue);
 }
 
-// nsPIAccessible
-NS_IMETHODIMP
-nsXULSliderAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
+PRBool
+nsXULSliderAccessible::GetAllowsAnonChildAccessibles()
 {
-  NS_ENSURE_ARG_POINTER(aAllowsAnonChildren);
-
   // Do not allow anonymous xul:slider be accessible.
-  *aAllowsAnonChildren = PR_FALSE;
-  return NS_OK;
+  return PR_FALSE;
 }
 
 // Utils
 
 already_AddRefed<nsIContent>
 nsXULSliderAccessible::GetSliderNode()
 {
   if (!mDOMNode)
--- a/accessible/src/xul/nsXULSliderAccessible.h
+++ b/accessible/src/xul/nsXULSliderAccessible.h
@@ -58,19 +58,17 @@ public:
   NS_IMETHOD DoAction(PRUint8 aIndex);
 
   // nsIAccessibleValue
   NS_DECL_NSIACCESSIBLEVALUE
 
   // nsAccessible
   virtual nsresult GetRoleInternal(PRUint32 *aRole);
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
-
-  // nsPIAccessible
-  NS_IMETHOD GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren);
+  virtual PRBool GetAllowsAnonChildAccessibles();
 
 protected:
   already_AddRefed<nsIContent> GetSliderNode();
 
   nsresult GetSliderAttr(nsIAtom *aName, nsAString& aValue);
   nsresult SetSliderAttr(nsIAtom *aName, const nsAString& aValue);
 
   nsresult GetSliderAttr(nsIAtom *aName, double *aValue);
--- a/accessible/tests/Makefile.in
+++ b/accessible/tests/Makefile.in
@@ -40,14 +40,12 @@ DEPTH   = ../..
 topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH   = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE	= test_accessibility
 
-ifdef ENABLE_TESTS
-DIRS		+= mochitest
-endif
+DIRS	= mochitest
 
 include $(topsrcdir)/config/rules.mk
 
--- a/accessible/tests/mochitest/Makefile.in
+++ b/accessible/tests/mochitest/Makefile.in
@@ -70,29 +70,32 @@ include $(topsrcdir)/config/rules.mk
 		test_accessnode_invalidation.html \
 		test_actions_aria.html \
 		test_actions_inputs.html \
 		test_actions.xul \
 		test_aria_activedescendant.html \
 		test_aria_role_article.html \
 		test_aria_role_equation.html \
 		test_aria_role_grid.html \
+		test_aria_roles.html \
 		test_aria_token_attrs.html \
 		test_bug420863.html \
 	$(warning   test_childAtPoint.html temporarily disabled) \
 	$(warning	test_childAtPoint.xul temporarily disabled) \
 		test_cssattrs.html \
 		test_descr.html \
 		test_elm_filectrl.html \
 	$(warning   test_elm_media.html temporarily disabled) \
+		test_elm_table.html \
 		test_elm_txtcntnr.html \
 		test_events_caretmove.html \
 		test_events_focus.xul \
 		test_events_mutation.html \
 		test_events_tree.xul \
+		test_events_valuechange.html \
 		test_groupattrs.xul \
 		test_groupattrs.html \
 		test_name.html \
 		test_name.xul \
 		test_name_button.html \
 		test_name_link.html \
 		test_name_markup.html \
 		test_nsIAccessible_applicationAccessible.html \
@@ -120,16 +123,17 @@ include $(topsrcdir)/config/rules.mk
 		test_states_docarticle.html \
 		test_states_frames.html \
 		test_table_1.html \
 		test_table_2.html \
 		test_table_3.html \
 		test_table_4.html \
   $(warning test_table_indexes.html temporarily disabled) \
 		test_table_indexes_ariagrid.html \
+		test_table_sels_ariagrid.html \
 		test_textattrs.html \
 		test_textboxes.html \
 		test_textboxes.xul \
 		test_value.xul \
 		testTextboxes.js \
 		treeview.js \
 		z_states_frame.html \
 		z_states_framearticle.html \
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -55,16 +55,17 @@ const STATE_COLLAPSED = nsIAccessibleSta
 const STATE_EXPANDED = nsIAccessibleStates.STATE_EXPANDED;
 const STATE_EXTSELECTABLE = nsIAccessibleStates.STATE_EXTSELECTABLE;
 const STATE_FOCUSABLE = nsIAccessibleStates.STATE_FOCUSABLE;
 const STATE_FOCUSED = nsIAccessibleStates.STATE_FOCUSED;
 const STATE_HASPOPUP = nsIAccessibleStates.STATE_HASPOPUP;
 const STATE_LINKED = nsIAccessibleStates.STATE_LINKED;
 const STATE_MIXED = nsIAccessibleStates.STATE_MIXED;
 const STATE_MULTISELECTABLE = nsIAccessibleStates.STATE_MULTISELECTABLE;
+const STATE_OFFSCREEN = nsIAccessibleStates.STATE_OFFSCREEN;
 const STATE_PRESSED = nsIAccessibleStates.STATE_PRESSED;
 const STATE_READONLY = nsIAccessibleStates.STATE_READONLY;
 const STATE_SELECTABLE = nsIAccessibleStates.STATE_SELECTABLE;
 const STATE_SELECTED = nsIAccessibleStates.STATE_SELECTED;
 const STATE_TRAVERSED = nsIAccessibleStates.STATE_TRAVERSED;
 const STATE_UNAVAILABLE = nsIAccessibleStates.STATE_UNAVAILABLE;
 
 const EXT_STATE_EDITABLE = nsIAccessibleStates.EXT_STATE_EDITABLE;
--- a/accessible/tests/mochitest/events.js
+++ b/accessible/tests/mochitest/events.js
@@ -85,17 +85,17 @@ function unregisterA11yEventListener(aEv
  * to prepare action.
  */
 const INVOKER_ACTION_FAILED = 1;
 
 /**
  * Creates event queue for the given event type. The queue consists of invoker
  * objects, each of them generates the event of the event type. When queue is
  * started then every invoker object is asked to generate event after timeout.
- * When event is caught then current invoker object is asked to check wether
+ * When event is caught then current invoker object is asked to check whether
  * event was handled correctly.
  *
  * Invoker interface is:
  *
  *   var invoker = {
  *     // Generates accessible event or event sequence. If returns
  *     // INVOKER_ACTION_FAILED constant then stop tests.
  *     invoke: function(){},
--- a/accessible/tests/mochitest/grid.js
+++ b/accessible/tests/mochitest/grid.js
@@ -73,17 +73,17 @@ function grid(aTableIdentifier)
     if (aEvent instanceof nsIDOMKeyEvent)
       this.handleKeyEvent(aEvent);
     else
       this.handleClickEvent(aEvent);
   }
 
   this.handleKeyEvent = function handleKeyEvent(aEvent)
   {
-    if (aEvent.target.localName != "TD")
+    if (aEvent.target.localName != "td")
       return;
 
     var cell = aEvent.target;
     switch(aEvent.keyCode) {
       case nsIDOMKeyEvent.DOM_VK_UP:
         var colsCount = this.getColsCount();
         var idx = this.getIndexByCell(cell);
         var upidx = idx - colsCount;
@@ -126,17 +126,17 @@ function grid(aTableIdentifier)
           nextcell.focus();
         }
         break;
     }
   }
 
   this.handleClickEvent = function handleClickEvent(aEvent)
   {
-    if (aEvent.target.localName != "TD")
+    if (aEvent.target.localName != "td")
       return;
     
     var curCell = this.getCurrentCell();
     var cell = aEvent.target;
 
     if (cell != curCell) {
       curCell.removeAttribute("tabindex");
       cell.setAttribute("tabindex", "0");
--- a/accessible/tests/mochitest/role.js
+++ b/accessible/tests/mochitest/role.js
@@ -1,12 +1,13 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Role constants
 
 const ROLE_ALERT = nsIAccessibleRole.ROLE_ALERT;
+const ROLE_APPLICATION = nsIAccessibleRole.ROLE_APPLICATION;
 const ROLE_CELL = nsIAccessibleRole.ROLE_CELL;
 const ROLE_CHROME_WINDOW = nsIAccessibleRole.ROLE_CHROME_WINDOW;
 const ROLE_COMBOBOX = nsIAccessibleRole.ROLE_COMBOBOX;
 const ROLE_COMBOBOX_LIST = nsIAccessibleRole.ROLE_COMBOBOX_LIST;
 const ROLE_COMBOBOX_OPTION = nsIAccessibleRole.ROLE_COMBOBOX_OPTION;
 const ROLE_COLUMNHEADER = nsIAccessibleRole.ROLE_COLUMNHEADER;
 const ROLE_DOCUMENT = nsIAccessibleRole.ROLE_DOCUMENT;
 const ROLE_ENTRY = nsIAccessibleRole.ROLE_ENTRY;
--- a/accessible/tests/mochitest/table.js
+++ b/accessible/tests/mochitest/table.js
@@ -16,31 +16,31 @@ function testTableIndexes(aIdentifier, a
   var cellAcc;
 
   var id = prettyName(aIdentifier);
 
   for (var i = 0; i < aLen; i++) {
     try {
       row = tableAcc.getRowAtIndex(i);
     } catch (e) {
-      ok(false, id + ": can't get row index for cell index " + i + ".");
+      ok(false, id + ": can't get row index for cell index " + i + "," + e);
     }
 
     try {
       column = tableAcc.getColumnAtIndex(i);
     } catch (e) {
-      ok(false, id + ": can't get column index for cell index " + i + ".");
+      ok(false, id + ": can't get column index for cell index " + i + "," + e);
     }
 
     try {
       index = tableAcc.getIndexAt(aRowIdxes[i], aColIdxes[i]);
     } catch (e) {
       ok(false,
          id + ": can't get cell index by row index " + aRowIdxes[i] +
-           " and column index: " + aColIdxes[i]  + ".");
+           " and column index: " + aColIdxes[i]  + ", " + e);
     }
 
     is(row, aRowIdxes[i], id + ": row  for index " + i +" is nor correct");
     is(column, aColIdxes[i],
        id + ": column  for index " + i +" is not correct");
     is(index, i,
        id + ": row " + row + " /column " + column + " and index " + index + " aren't inconsistent.");
 
@@ -64,8 +64,219 @@ function testTableIndexes(aIdentifier, a
 
       if (strIdx) {
         is (parseInt(strIdx), index,
             id + ": cell index from object attributes of cell accessible isn't corrent.");
       }
     }
   }
 }
+
+/**
+ * Test table getters selection methods.
+ *
+ * @param  aIdentifier  [in] table accessible identifier
+ * @param  aCellsArray  [in] two dimensional array (row X columns) of selected
+ *                       cells states.
+ * @param  aMsg         [in] text appended before every message
+ */
+function testTableSelection(aIdentifier, aCellsArray, aMsg)
+{
+  var msg = aMsg ? aMsg : "";
+  var acc = getAccessible(aIdentifier, [nsIAccessibleTable]);
+  if (!acc)
+    return;
+
+  var rowsCount = aCellsArray.length;
+  var colsCount = aCellsArray[0].length;
+
+  // Columns selection tests.
+  var selCols = new Array();
+
+  // isColumnSelected test
+  for (var colIdx = 0; colIdx < colsCount; colIdx++) {
+    var isColSelected = true;
+    for (var rowIdx = 0; rowIdx < rowsCount; rowIdx++) {
+      if (!aCellsArray[rowIdx][colIdx]) {
+        isColSelected = false;
+        break;
+      }
+    }
+
+    is(acc.isColumnSelected(colIdx), isColSelected,
+       msg + "Wrong selection state of " + colIdx + " column for " +
+       prettyName(aIdentifier));
+
+    if (isColSelected)
+      selCols.push(colIdx);
+  }
+
+  // selectedColsCount test
+  is(acc.selectedColumnsCount, selCols.length,
+     msg + "Wrong count of selected columns for " + prettyName(aIdentifier));
+
+  // getSelectedColumns test
+  var actualSelColsCountObj = { value: null };
+  var actualSelCols = acc.getSelectedColumns(actualSelColsCountObj);
+
+  var actualSelColsCount = actualSelColsCountObj.value;
+  is (actualSelColsCount, selCols.length,
+      msg + "Wrong count of selected columns for " + prettyName(aIdentifier) +
+      "from getSelectedColumns.");
+
+  for (var i = 0; i < actualSelColsCount; i++) {
+    is (actualSelCols[i], selCols[i],
+        msg + "Column at index " + selCols[i] + " should be selected.");
+  }
+
+  // Rows selection tests.
+  var selRows = new Array();
+
+  // isRowSelected test
+  var selRowsCount = 0;
+  for (var rowIdx = 0; rowIdx < rowsCount; rowIdx++) {
+    var isRowSelected = true;
+    for (var colIdx = 0; colIdx < colsCount; colIdx++) {
+      if (!aCellsArray[rowIdx][colIdx]) {
+        isRowSelected = false;
+        break;
+      }
+    }
+
+    is(acc.isRowSelected(rowIdx), isRowSelected,
+       msg + "Wrong selection state of " + rowIdx + " row for " +
+       prettyName(aIdentifier));
+
+    if (isRowSelected)
+      selRows.push(rowIdx);
+  }
+
+  // selectedRowsCount test
+  is(acc.selectedRowsCount, selRows.length,
+     msg + "Wrong count of selected rows for " + prettyName(aIdentifier));
+
+  // getSelectedRows test
+  var actualSelRowsCountObj = { value: null };
+  var actualSelRows = acc.getSelectedRows(actualSelRowsCountObj);
+
+  var actualSelRowsCount = actualSelRowsCountObj.value;
+  is (actualSelRowsCount, selRows.length,
+      msg + "Wrong count of selected rows for " + prettyName(aIdentifier) +
+      "from getSelectedRows.");
+
+  for (var i = 0; i < actualSelRowsCount; i++) {
+    is (actualSelRows[i], selRows[i],
+        msg + "Row at index " + selRows[i] + " should be selected.");
+  }
+
+  // Cells selection tests.
+  var selCells = new Array();
+
+  // isCellSelected test
+  for (var rowIdx = 0; rowIdx < rowsCount; rowIdx++) {
+    for (var colIdx = 0; colIdx < colsCount; colIdx++) {
+      is(acc.isCellSelected(rowIdx, colIdx), aCellsArray[rowIdx][colIdx],
+         msg + "Wrong selection state of cell at " + rowIdx + " row and " +
+         colIdx + " column for " + prettyName(aIdentifier));
+
+      if (aCellsArray[rowIdx][colIdx])
+        selCells.push(acc.getIndexAt(rowIdx, colIdx));
+    }
+  }
+
+  // selectedCellsCount tests
+  is(acc.selectedCellsCount, selCells.length,
+     msg + "Wrong count of selected cells for " + prettyName(aIdentifier));
+
+  // getSelectedCells test
+  var actualSelCellsCountObj = { value: null };
+  var actualSelCells = acc.getSelectedCells(actualSelCellsCountObj);
+
+  var actualSelCellsCount = actualSelCellsCountObj.value;
+  is (actualSelCellsCount, selCells.length,
+      msg + "Wrong count of selected cells for " + prettyName(aIdentifier) +
+      "from getSelectedCells.");
+
+  for (var i = 0; i < actualSelCellsCount; i++) {
+    is (actualSelCells[i], selCells[i],
+        msg + "Cell at index " + selCells[i] + " should be selected.");
+  }
+}
+
+/**
+ * Test unselectColumn method of accessible table.
+ */
+function testUnselectTableColumn(aIdentifier, aColIdx, aCellsArray)
+{
+  var acc = getAccessible(aIdentifier, [nsIAccessibleTable]);
+  if (!acc)
+    return;
+
+  var rowsCount = aCellsArray.length;
+  for (var rowIdx = 0; rowIdx < rowsCount; rowIdx++)
+    aCellsArray[rowIdx][aColIdx] = false;
+
+  acc.unselectColumn(aColIdx);
+  testTableSelection(aIdentifier, aCellsArray,
+                     "Unselect " + aColIdx + " column: ");
+}
+
+/**
+ * Test selectColumn method of accessible table.
+ */
+function testSelectTableColumn(aIdentifier, aColIdx, aCellsArray)
+{
+  var acc = getAccessible(aIdentifier, [nsIAccessibleTable]);
+  if (!acc)
+    return;
+
+  var rowsCount = aCellsArray.length;
+  var colsCount = aCellsArray[0].length;
+
+  for (var rowIdx = 0; rowIdx < rowsCount; rowIdx++) {
+    for (var colIdx = 0; colIdx < colsCount; colIdx++)
+      aCellsArray[rowIdx][colIdx] = (colIdx == aColIdx);
+  }
+
+  acc.selectColumn(aColIdx);
+  testTableSelection(aIdentifier, aCellsArray,
+                     "Select " + aColIdx + " column: ");
+}
+
+/**
+ * Test unselectRow method of accessible table.
+ */
+function testUnselectTableRow(aIdentifier, aRowIdx, aCellsArray)
+{
+  var acc = getAccessible(aIdentifier, [nsIAccessibleTable]);
+  if (!acc)
+    return;
+
+  var colsCount = aCellsArray[0].length;
+  for (var colIdx = 0; colIdx < colsCount; colIdx++)
+    aCellsArray[aRowIdx][colIdx] = false;
+
+  acc.unselectRow(aRowIdx);
+  testTableSelection(aIdentifier, aCellsArray,
+                     "Unselect " + aRowIdx + " row: ");
+}
+
+/**
+ * Test selectRow method of accessible table.
+ */
+function testSelectTableRow(aIdentifier, aRowIdx, aCellsArray)
+{
+  var acc = getAccessible(aIdentifier, [nsIAccessibleTable]);
+  if (!acc)
+    return;
+
+  var rowsCount = aCellsArray.length;
+  var colsCount = aCellsArray[0].length;
+
+  for (var rowIdx = 0; rowIdx < rowsCount; rowIdx++) {
+    for (var colIdx = 0; colIdx < colsCount; colIdx++)
+      aCellsArray[rowIdx][colIdx] = (rowIdx == aRowIdx);
+  }
+
+  acc.selectRow(aRowIdx);
+  testTableSelection(aIdentifier, aCellsArray,
+                     "Select " + aRowIdx + " row: ");
+}
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_aria_roles.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=481114
+-->
+<head>
+  <title>Test weak ARIA roles</title>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/common.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/role.js"></script>
+
+  <script type="application/javascript">
+    function doTest()
+    {
+      // Note:
+      // The phrase "weak foo" here means that there is no good foo-to-platform
+      // role mapping. Similarly "strong foo" means there is a good foo-to-
+      // platform role mapping.
+
+      // weak roles that are forms of "live regions"
+      testRole("log_table", ROLE_TABLE);
+      testRole("marquee_h1", ROLE_HEADING);
+      testRole("timer_div", ROLE_SECTION);
+
+      // strong landmark
+      testRole("application", ROLE_APPLICATION);
+
+      // weak landmarks
+      var weak_landmarks = ["banner", "complementary", "contentinfo",
+          "main", "navigation", "search"];
+      for (l in weak_landmarks)
+        testRole(weak_landmarks[l], ROLE_SECTION);
+
+      // test gEmptyRoleMap
+      testRole("cell", ROLE_NOTHING);
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=481114">Mozilla Bug 481114</a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+  
+  <!-- "live" roles -->
+  <table role="log" id="log_table">
+    <tr><td>Table based log</td></tr>
+  </table>
+  <h1 role="marquee" id="marquee_h1">marquee</h1>
+  <div role="timer" id="timer_div">timer</div>
+
+  <!-- landmarks -->
+  <div role="application" id="application">application</div>
+  <div role="banner" id="banner">banner</div>
+  <div role="complementary" id="complementary">complementary</div>
+  <div role="contentinfo" id="contentinfo">contentinfo</div>
+  <div role="main" id="main">main</div>
+  <div role="navigation" id="navigation">navigation</div>
+  <div role="search" id="search">search</div>
+
+  <!-- test gEmptyRoleMap -->
+  <table role="label">
+    <tr>
+      <td id="cell">cell</td>
+    </tr>
+  </table>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_elm_table.html
@@ -0,0 +1,117 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=483573
+-->
+<head>
+  <title>File Input Control tests</title>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/common.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/role.js"></script>
+
+  <script type="application/javascript">
+    function doTest()
+    {
+      var accTree = {
+        role: ROLE_TABLE, // table
+        children: [
+          {
+            role: ROLE_TEXT_CONTAINER, // thead
+            children: [
+              {
+                role: ROLE_ROW,
+                children: [
+                  {
+                    role: ROLE_COLUMNHEADER
+                  },
+                  {
+                    role: ROLE_COLUMNHEADER
+                  }
+                ]
+              }
+            ]
+          },
+          {
+            role: ROLE_TEXT_CONTAINER, // tbody
+            children: [
+              {
+                role: ROLE_ROW,
+                children: [
+                  {
+                    role: ROLE_CELL
+                  },
+                  {
+                    role: ROLE_CELL
+                  }
+                ]
+              }
+            ]
+          },
+          {
+            role: ROLE_TEXT_CONTAINER, // tfoot
+            children: [
+              {
+                role: ROLE_ROW,
+                children: [
+                  {
+                    role: ROLE_COLUMNHEADER
+                  },
+                  {
+                    role: ROLE_COLUMNHEADER
+                  }
+                ]
+              }
+            ]
+          }
+        ]
+      };
+
+      if (LINUX)
+        todo(false, "No tests on linux because of different hierarchies.");
+      else
+        testAccessibleTree("table", accTree);
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     title="create accessibles for HTML tr"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=493695">Mozilla Bug 493695</a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <table id="table">
+    <thead>
+      <tr>
+        <th>col1</th><th>col2</th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td>cell1</td><td>cell2</td>
+      </tr>
+    </tbody>
+    <tfoot>
+      <tr>
+        <th>col1</th><th>col2</th>
+      </tr>
+    </tfoot>
+  </table>
+</body>
+</html>
--- a/accessible/tests/mochitest/test_events_mutation.html
+++ b/accessible/tests/mochitest/test_events_mutation.html
@@ -201,17 +201,17 @@
 
       this.invoke = function removeFromDOM_invoke()
       {
         this.DOMNode.parentNode.removeChild(this.DOMNode);
       }
 
       this.getID = function removeFromDOM_getID()
       {
-        return aNodeOrID + " remove from DOM.";
+        return prettyName(aNodeOrID) + " remove from DOM.";
       }
 
       if (aTargetsFunc && (eventTypes & kHideEvent))
         this.setTargets(kHideEvent, aTargetsFunc.call(null, this.DOMNode));
 
       if (aReorderTargetFunc && (eventTypes & kReorderEvent))
         this.setTarget(kReorderEvent,
                        aReorderTargetFunc.call(null, this.DOMNode));
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_events_valuechange.html
@@ -0,0 +1,109 @@
+<html>
+
+<head>
+  <title>Accessible value change events testing</title>
+
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/common.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/events.js"></script>
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/value.js"></script>
+
+  <script type="application/javascript">
+
+
+    /**
+     * Do tests.
+     */
+    var gQueue = null;
+
+    // Value change invoker
+    function changeValue(aNodeOrID, aValuenow, aValuetext)
+    {
+      this.DOMNode = getNode(aNodeOrID);
+
+      this.invoke = function changeValue_invoke() {
+
+        // Note: this should not fire an EVENT_VALUE_CHANGE when aria-valuetext
+        // is not empty
+        if (aValuenow != undefined)
+          this.DOMNode.setAttribute("aria-valuenow", aValuenow);
+ 
+        // Note: this should always fire an EVENT_VALUE_CHANGE
+        if (aValuetext != undefined)
+          this.DOMNode.setAttribute("aria-valuetext", aValuetext);
+      }
+
+      this.check = function changeValue_check() {
+        var acc = getAccessible(aNodeOrID, [nsIAccessibleValue]);
+        if (!acc)
+          return;
+
+        // Note: always test against valuetext first because the existence of 
+        // aria-valuetext takes precedence over aria-valuenow in gecko.
+        is(acc.value, (aValuetext != undefined)? aValuetext : aValuenow,
+            "Wrong value of " + prettyName(aNodeOrID));
+      }
+
+      this.getID = function changeValue_getID() {
+        return prettyName(aNodeOrID) + " value changed";
+      }
+    }
+
+    function doTests()
+    {
+      // Test initial values
+      testValue("slider_vn", "5", 5, 0, 1000, 0);
+      testValue("slider_vnvt", "plain", 0, 0, 5, 0);
+      testValue("slider_vt", "hi", 0, 0, 3, 0);
+
+      // Test value change events
+      gQueue = new eventQueue(nsIAccessibleEvent.EVENT_VALUE_CHANGE);
+
+      gQueue.push(new changeValue("slider_vn", "6", undefined));
+      gQueue.push(new changeValue("slider_vt", undefined, "hey!"));
+      gQueue.push(new changeValue("slider_vnvt", "3", "sweet"));
+
+      gQueue.invoke(); // Will call SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTests);
+  </script>
+</head>
+
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=478032"
+     title=" Fire delayed value changed event for aria-valuetext changes">
+    Mozilla Bug 478032
+  </a>
+
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+  <div id="eventdump"></div>
+
+  <!-- ARIA sliders -->
+  <div id="slider_vn" role="slider" aria-valuenow="5"
+    aria-valuemin="0" aria-valuemax="1000">slider</div>
+
+  <div id="slider_vt" role="slider" aria-valuetext="hi"
+    aria-valuemin="0" aria-valuemax="3">greeting slider</div>
+
+  <div id="slider_vnvt" role="slider" aria-valuenow="0" aria-valuetext="plain"
+    aria-valuemin="0" aria-valuemax="5">sweetness slider</div>
+</body>
+</html>
--- a/accessible/tests/mochitest/test_name.html
+++ b/accessible/tests/mochitest/test_name.html
@@ -87,16 +87,19 @@
 
       // Gets the name from html:p content, which doesn't allow name from
       // subtree, ignore @title attribute on label
       testName("from_p_ignoretitle", "Choose country from.");
 
       // Gets the name from html:input value, ignore @title attribute on input
       testName("from_input_ignoretitle", "Custom country");
 
+      // Gets the name from @title, ignore whitespace content
+      testName("from_label_ignore_ws_subtree", "about");
+
       //////////////////////////////////////////////////////////////////////////
       // 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");
 
@@ -298,16 +301,19 @@
 
   <!-- the name from subtree, name from html:input value rather than from its
     title attribute -->
   <p id="from_input_ignoretitle" aria-labelledby="input_ignoretitle">Country</p>
   <input id="input_ignoretitle"
          value="Custom country"
          title="Input your country of origin"/ >
 
+  <!-- no name from subtree because it holds whitespaces only -->
+  <a id="from_label_ignore_ws_subtree" href="about:" title="about">&nbsp;&nbsp;  </a>
+
   <!-- 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>
--- a/accessible/tests/mochitest/test_name.xul
+++ b/accessible/tests/mochitest/test_name.xul
@@ -163,33 +163,43 @@
       // 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");
 
 
+      //////////////////////////////////////////////////////////////////////////
+      // Name from aria-labelledby: menuitem label+ listitem label
+      testName("li_labelledby", "Show an Alert The moment the event starts");
+
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addLoadEvent(doTest);
   ]]>
   </script>
 
   <hbox flex="1" style="overflow: auto;">
 
   <body xmlns="http://www.w3.org/1999/xhtml">
     <a target="_blank"
        href="https://bugzilla.mozilla.org/show_bug.cgi?id=444279"
        title="mochitest for accessible name calculating">
       Mozilla Bug 444279
     </a>
-    <p id="display"></p>
+    <a target="_blank"
+      href="https://bugzilla.mozilla.org/show_bug.cgi?id=441991"
+      title="nsXULListitemAccessible::GetName prefers label \
+      		   attribute over aria-labelledby and doesn't allow recursion">
+      Mozilla Bug 441991
+    </a>
+  <p id="display"></p>
     <div id="content" style="display: none">
     </div>
     <pre id="test">
     </pre>
   </body>
 
   <vbox flex="1">
 
@@ -323,10 +333,29 @@
     <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>
 
   </vbox>
   </hbox>
+
+  <!-- bug 441991; create name from other menuitem label listitem's own label -->
+  <hbox>
+  <listbox>
+  <listitem id="li_labelledby"
+            label="The moment the event starts"
+            aria-labelledby="menuitem-DISPLAY li_labelledby"/>
+  </listbox>
+  <menulist>
+    <menupopup>
+      <menuitem id="menuitem-DISPLAY"
+                value="DISPLAY"
+                label="Show an Alert"/>
+      <menuitem id="menuitem-EMAIL"
+                value="EMAIL"
+                label="Send an E-mail"/>
+    </menupopup>
+  </menulist>
+  </hbox>  
 </window>
 
--- a/accessible/tests/mochitest/test_nsIAccessibleHyperLink.html
+++ b/accessible/tests/mochitest/test_nsIAccessibleHyperLink.html
@@ -63,33 +63,33 @@ https://bugzilla.mozilla.org/show_bug.cg
 
     function doTest()
     {
       //////////////////////////////////////////////////////////////////////////
       // normal hyperlink
       var normalHyperlinkAcc = getAccessible("NormalHyperlink",
                                              [nsIAccessibleHyperLink]);
       testThis("NormalHyperlink", normalHyperlinkAcc, ROLE_LINK, 1,
-               "Mozilla Foundation", true, 18, 19);
+               "Mozilla Foundation", true, 17, 18);
       is(normalHyperlinkAcc.getURI(0).spec, "http://www.mozilla.org/", 
          "URI wrong for normalHyperlinkElement!");
       testStates(normalHyperlinkAcc,
                  (STATE_FOCUSABLE | STATE_LINKED),
                  (EXT_STATE_HORIZONTAL));
       testFocus("NormalHyperlink", normalHyperlinkAcc, false, true);
       testStates(normalHyperlinkAcc,
                  (STATE_FOCUSABLE | STATE_FOCUSED | STATE_LINKED),
                  (EXT_STATE_HORIZONTAL));
 
       //////////////////////////////////////////////////////////////////////////
       // ARIA hyperlink
       var ariaHyperlinkAcc = getAccessible("AriaHyperlink",
                                            [nsIAccessibleHyperLink]);
       testThis("AriaHyperlink", ariaHyperlinkAcc, ROLE_LINK, 1,
-               "Mozilla Foundation Home", true, 32, 33);
+               "Mozilla Foundation Home", true, 30, 31);
       testStates(ariaHyperlinkAcc,
                  (STATE_FOCUSABLE | STATE_LINKED),
                  (EXT_STATE_HORIZONTAL));
       testFocus("AriaHyperlink", ariaHyperlinkAcc, false, true);
       testStates(ariaHyperlinkAcc,
                  (STATE_FOCUSABLE | STATE_FOCUSED | STATE_LINKED),
                  (EXT_STATE_HORIZONTAL));
       testAction("AriaHyperlink", ariaHyperlinkAcc, "click");
@@ -105,17 +105,17 @@ https://bugzilla.mozilla.org/show_bug.cg
       testFocus("InvalidAriaHyperlink", invalidAriaHyperlinkAcc,
                 false, false);
 
       //////////////////////////////////////////////////////////////////////////
       // image map and its link children
       var imageMapHyperlinkAcc = getAccessible("imgmap",
                                                [nsIAccessibleHyperLink]);
       testThis("imgmap", imageMapHyperlinkAcc, ROLE_IMAGE_MAP, 2, "b", true,
-               83, 84);
+               79, 80);
       is(imageMapHyperlinkAcc.getURI(0).spec,
          "http://www.bbc.co.uk/radio4/atoz/index.shtml#b", "URI wrong!");
       is(imageMapHyperlinkAcc.getURI(1).spec,
          "http://www.bbc.co.uk/radio4/atoz/index.shtml#a", "URI wrong!");
       testStates(imageMapHyperlinkAcc,
                  (0),
                  (EXT_STATE_HORIZONTAL));
 
@@ -132,196 +132,182 @@ https://bugzilla.mozilla.org/show_bug.cg
       is(area2.getURI(0).spec,
          "http://www.bbc.co.uk/radio4/atoz/index.shtml#a", "URI wrong!");
       testStates(area2, (STATE_LINKED));
 
       //////////////////////////////////////////////////////////////////////////
       // empty hyperlink
       var EmptyHLAcc = getAccessible("emptyLink",
                                      [nsIAccessibleHyperLink]);
-      testThis("emptyLink", EmptyHLAcc, ROLE_LINK, 1, null, true, 98, 99);
+      testThis("emptyLink", EmptyHLAcc, ROLE_LINK, 1, null, true, 93, 94);
       testStates(EmptyHLAcc,
                  (STATE_FOCUSABLE | STATE_LINKED),
                  (EXT_STATE_HORIZONTAL));
       testAction("emptyLink", EmptyHLAcc, "jump");
 
       //////////////////////////////////////////////////////////////////////////
       // normal hyperlink with embedded span
       var hyperlinkWithSpanAcc = getAccessible("LinkWithSpan",
                                                [nsIAccessibleHyperLink]);
       testThis("LinkWithSpan", hyperlinkWithSpanAcc, ROLE_LINK, 1,
-               "Heise Online", true, 124, 125);
+               "Heise Online", true, 119, 120);
       is(hyperlinkWithSpanAcc.getURI(0).spec, "http://www.heise.de/", 
          "URI wrong for hyperlinkElementWithSpan!");
       testStates(hyperlinkWithSpanAcc,
                  (STATE_FOCUSABLE | STATE_LINKED),
                (EXT_STATE_HORIZONTAL));
       testFocus("LinkWithSpan", hyperlinkWithSpanAcc, false, true);
       testStates(hyperlinkWithSpanAcc,
                  (STATE_FOCUSABLE | STATE_FOCUSED | STATE_LINKED),
                  (EXT_STATE_HORIZONTAL));
       testAction("LinkWithSpan", hyperlinkWithSpanAcc, "jump");
 
       //////////////////////////////////////////////////////////////////////////
       // Named anchor, should never have state_linked
       var namedAnchorAcc = getAccessible("namedAnchor",
                                          [nsIAccessibleHyperLink]);
       testThis("namedAnchor", namedAnchorAcc, ROLE_LINK, 1,
-               "This should never be of state_linked", true, 202, 203);
+               "This should never be of state_linked", true, 196, 197);
       testStates(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 noLinkAcc = getAccessible("noLink",
                                     [nsIAccessibleHyperLink]);
       testThis("noLink", noLinkAcc, ROLE_LINK, 1,
-               "This should never be of state_linked", true, 262, 263);
+               "This should never be of state_linked", true, 254, 255);
       testStates(noLinkAcc,
                  0,
                  (EXT_STATE_HORIZONTAL), (STATE_FOCUSABLE | STATE_LINKED));
       testAction("noLink", noLinkAcc, "");
 
       //////////////////////////////////////////////////////////////////////////
       // Link with registered 'click' event, should have state_linked
       var linkWithClickAcc = getAccessible("linkWithClick",
                                            [nsIAccessibleHyperLink]);
       testThis("linkWithClick", linkWithClickAcc, ROLE_LINK, 1,
-               "This should have state_linked", true, 301, 302);
+               "This should have state_linked", true, 292, 293);
       testStates(linkWithClickAcc,
                  (STATE_LINKED),
                  (EXT_STATE_HORIZONTAL));
       testAction("linkWithClick", linkWithClickAcc, "click");
 
       //////////////////////////////////////////////////////////////////////////
       // Maps to group links (bug 431615).
       var linksMapAcc = getAccessible("linksmap");
 
       //////////////////////////////////////////////////////////////////////////
       // Link with title attribute, no name from the subtree (bug 438325).
       var id = "linkWithTitleNoNameFromSubtree";
       var linkAcc = getAccessible(id, [nsIAccessibleHyperLink]);
-      testThis(id, linkAcc, ROLE_LINK, 1, "Link with title", true, 354, 355);
+      testThis(id, linkAcc, ROLE_LINK, 1, "Link with title", true, 344, 345);
       testStates(linkAcc,
                  (STATE_LINKED),
                  (EXT_STATE_HORIZONTAL));
       testAction(id, linkAcc, "jump");
 
       //////////////////////////////////////////////////////////////////////////
       // Link with title attribute, name from the subtree - onscreen name
       // (bug 438325).
       id = "linkWithTitleNameFromSubtree";
       linkAcc = getAccessible(id, [nsIAccessibleHyperLink]);
-      testThis(id, linkAcc, ROLE_LINK, 1, "the name from subtree", true, 403,
-               404);
+      testThis(id, linkAcc, ROLE_LINK, 1, "the name from subtree", true, 393,
+               394);
       testStates(linkAcc,
                  (STATE_LINKED),
                  (EXT_STATE_HORIZONTAL));
       testAction(id, linkAcc, "jump");
 
       //////////////////////////////////////////////////////////////////////////
       // Link with title attribute, name from the nested html:img (bug 438325).
       id = "linkWithTitleNameFromImg";
       linkAcc = getAccessible(id, [nsIAccessibleHyperLink]);
-      testThis(id, linkAcc, ROLE_LINK, 1, "The title for link", true, 458,
-               459);
+      testThis(id, linkAcc, ROLE_LINK, 1, "The title for link", true, 447,
+               448);
       testStates(linkAcc,
                  (STATE_LINKED),
                  (EXT_STATE_HORIZONTAL));
       testAction(id, linkAcc, "jump");
 
       //////////////////////////////////////////////////////////////////////////
       // Link with label, no name from the subtree (bug 438325).
       id = "linkWithLabelNoNameFromSubtree";
       linkAcc = getAccessible(id, [nsIAccessibleHyperLink]);
       testThis(id, linkAcc, ROLE_LINK, 1, "Link with label and nested image:",
-               true, 462, 463);
+               true, 450, 451);
       testStates(linkAcc,
                  (STATE_LINKED),
                  (EXT_STATE_HORIZONTAL));
       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"
+<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"
-        onclick="window.open('http:/www.mozilla.org/');">Invalid link</span>
-  <br>Image map:<br>
-  <map name="atoz_map">
-    <area href="http://www.bbc.co.uk/radio4/atoz/index.shtml#b"
+         tabindex="0">Mozilla Foundation Home</span
+  ><br
+  >Invalid, non-focusable hyperlink:<br
+  ><span id="InvalidAriaHyperlink" role="link" aria-invalid="true"
+         onclick="window.open('http:/www.mozilla.org/');">Invalid link</span
+  ><br>Image map:<br
+  ><map name="atoz_map"
+    ><area href="http://www.bbc.co.uk/radio4/atoz/index.shtml#b"
           coords="17,0,30,14"
           alt="b"
-          shape="rect"></area>
-    <area href="http://www.bbc.co.uk/radio4/atoz/index.shtml#a"
-          coords="0,0,13,14"
-          alt="a"
-          shape="rect"></area>
-  </map>
-  <img width="447" id="imgmap"
-       height="15"
-       usemap="#atoz_map"
-       src="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>
+          shape="rect"></area
+    ><area href="http://www.bbc.co.uk/radio4/atoz/index.shtml#a"
+           coords="0,0,13,14"
+           alt="a"
+           shape="rect"></area
+    ></map
+  ><img width="447" id="imgmap"
+        height="15"
+        usemap="#atoz_map"
+        src="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_nsIAccessibleHyperText.html
+++ b/accessible/tests/mochitest/test_nsIAccessibleHyperText.html
@@ -38,73 +38,71 @@ https://bugzilla.mozilla.org/show_bug.cg
 
       // Test link count
       is(gParagraphAcc.linkCount, 7, "Wrong link count for paragraph!");
 
       // normal hyperlink
       testThis("NormalHyperlink", 14, 0, "Mozilla Foundation");
 
       // ARIA hyperlink
-      testThis("AriaHyperlink", 28, 1, "Mozilla Foundation Home");
+      testThis("AriaHyperlink", 27, 1, "Mozilla Foundation Home");
 
       // ARIA hyperlink with status invalid
-      testThis("InvalidAriaHyperlink", 64, 2, "Invalid link");
+      testThis("InvalidAriaHyperlink", 63, 2, "Invalid link");
 
       // image map, but not its link children. They are not part of hypertext.
-      testThis("imgmap", 78, 3, "b");
+      testThis("imgmap", 76, 3, "b");
 
       // empty hyperlink
-      testThis("emptyLink", 93, 4, null);
+      testThis("emptyLink", 90, 4, null);
 
       // normal hyperlink with embedded span
-      testThis("LinkWithSpan", 119, 5, "Heise Online");
+      testThis("LinkWithSpan", 116, 5, "Heise Online");
 
       // Named anchor
-      testThis("namedAnchor", 197, 6, "This should never be of state_linked");
+      testThis("namedAnchor", 193, 6, "This should never be of state_linked");
 
       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>
-  <p id="testParagraph">  
-    <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"
-          onclick="window.open('http:/www.mozilla.org/');">Invalid link</span>
-    <br>Image map:<br>
-    <map name="atoz_map">
-      <area href="http://www.bbc.co.uk/radio4/atoz/index.shtml#b"
-            coords="17,0,30,14"
-            alt="b"
-            shape="rect"></area>
-      <area href="http://www.bbc.co.uk/radio4/atoz/index.shtml#a"
-            coords="0,0,13,14"
-            alt="a"
-            shape="rect"></area>
-    </map>
-    <img width="447" id="imgmap"
+  <p id="testParagraph"><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"
+         onclick="window.open('http:/www.mozilla.org/');">Invalid link</span><br
+  >Image map:<br
+  ><map name="atoz_map"><area href="http://www.bbc.co.uk/radio4/atoz/index.shtml#b"
+                              coords="17,0,30,14"
+                              alt="b"
+                              shape="rect"></area
+   ><area href="http://www.bbc.co.uk/radio4/atoz/index.shtml#a"
+          coords="0,0,13,14"
+          alt="a"
+          shape="rect"></area></map
+   ><img width="447" id="imgmap"
          height="15"
          usemap="#atoz_map"
-         src="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>
+         src="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>
   </p>
 </body>
 </html>
--- a/accessible/tests/mochitest/test_objectattrs.html
+++ b/accessible/tests/mochitest/test_objectattrs.html
@@ -1,11 +1,12 @@
 <html>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=475006
+https://bugzilla.mozilla.org/show_bug.cgi?id=391829
 -->
 <head>
   <title>Group 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>
@@ -24,80 +25,116 @@ https://bugzilla.mozilla.org/show_bug.cg
       testAttrs("atomic", {"atomic" : "true"}, true);
       testAttrs("autocomplete", {"autocomplete" : "true"}, true);
       testAttrs("checkbox", {"checkable" : "true"}, true); 
       testAttrs("checkedCheckbox", {"checkable" : "true"}, true); 
       testAttrs("checkedMenuitem", {"checkable" : "true"}, true); 
       testAttrs("checkedOption", {"checkable" : "true"}, true); 
       testAttrs("checkedRadio", {"checkable" : "true"}, true); 
       testAttrs("checkedTreeitem", {"checkable" : "true"}, true); 
+      testAttrs("grabbed", {"grabbed" : "true"}, true);
       testAttrs("dropeffect", {"dropeffect" : "copy"}, true);
       testAttrs("sortAscending", {"sort" : "ascending"}, true);
       testAttrs("sortDescending", {"sort" : "descending"}, true);
       testAttrs("sortNone", {"sort" : "none"}, true);
       testAttrs("sortOther", {"sort" : "other"}, true);
 
       // live object attribute
       testAttrs("live", {"live" : "polite"}, true);
       testAttrs("live2", {"live" : "polite"}, true);
       testAttrs("log", {"live" : "polite"}, true);
+      testAttrs("logAssertive", {"live" : "assertive"}, true);
       testAttrs("marquee", {"live" : "off"}, true);
       testAttrs("status", {"live" : "polite"}, true);
       testAttrs("timer", {"live" : "off"}, true);
 
       // container-live object attribute
       testAttrs("liveChild", {"container-live" : "polite"}, true);
       testAttrs("live2Child", {"container-live" : "polite"}, true);
       testAttrs("logChild", {"container-live" : "polite"}, true);
+      testAttrs("logAssertiveChild", {"container-live" : "assertive"}, true);
       testAttrs("marqueeChild", {"container-live" : "off"}, true);
       testAttrs("statusChild", {"container-live" : "polite"}, true);
       testAttrs("timerChild", {"container-live" : "off"}, true);
 
+      // container-live-role object attribute
+      testAttrs("log", {"container-live-role" : "log"}, true);
+      testAttrs("logAssertive", {"container-live-role" : "log"}, true);
+      testAttrs("marquee", {"container-live-role" : "marquee"}, true);
+      testAttrs("status", {"container-live-role" : "status"}, true);
+      testAttrs("timer", {"container-live-role" : "timer"}, true);
+      testAttrs("logChild", {"container-live-role" : "log"}, true);
+      testAttrs("logAssertive", {"container-live-role" : "log"}, true);
+      testAttrs("logAssertiveChild", {"container-live-role" : "log"}, true);
+      testAttrs("marqueeChild", {"container-live-role" : "marquee"}, true);
+      testAttrs("statusChild", {"container-live-role" : "status"}, true);
+      testAttrs("timerChild", {"container-live-role" : "timer"}, true);
+
+      // container that has no default live attribute
+      testAttrs("liveGroup", {"live" : "polite"}, true);
+      testAttrs("liveGroupChild", {"container-live" : "polite"}, true);
+      testAttrs("liveGroup", {"container-live-role" : "group"}, true);
+      testAttrs("liveGroupChild", {"container-live-role" : "group"}, true);
+
       // html
       testAttrs("radio", {"checkable" : "true"}, true); 
       testAttrs("checkbox", {"checkable" : "true"}, true); 
+      testAttrs("draggable", {"draggable" : "true"}, true); 
 
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addLoadEvent(doTest);
   </script>
 </head>
 <body>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=475006"
      title="Extend nsARIAMap to capture ARIA attribute characteristics">
     Mozilla Bug 475006
   </a>
+    <a target="_blank"
+      href="https://bugzilla.mozilla.org/show_bug.cgi?id=391829"
+      title="Add support for container-live-role to object attributes">
+     Mozilla Bug 391829
+   </a>
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <!-- aria -->
   <div id="atomic" aria-atomic="true"></div>
   <div id="autocomplete" role="textbox" aria-autocomplete="true"></div>
   <div id="checkbox" role="checkbox"></div>
   <div id="checkedCheckbox" role="checkbox" aria-checked="true"></div>
   <div id="checkedMenuitem" role="menuitem" aria-checked="true"></div>
   <div id="checkedOption" role="option" aria-checked="true"></div>
   <div id="checkedRadio" role="radio" aria-checked="true"></div>
   <div id="checkedTreeitem" role="treeitem" aria-checked="true"></div>
+  <div id="grabbed" aria-grabbed="true"></div>
   <div id="dropeffect" aria-dropeffect="copy"></div>
   <div id="sortAscending" role="columnheader" aria-sort="ascending"></div>
   <div id="sortDescending" role="columnheader" aria-sort="descending"></div>
   <div id="sortNone" role="columnheader" aria-sort="none"></div>
   <div id="sortOther" role="columnheader" aria-sort="other"></div>
 
   <div id="live" aria-live="polite">excuse <div id="liveChild">me</div></div>
   <div id="live2" role="marquee" aria-live="polite">excuse <div id="live2Child">me</div></div>
   <div id="log" role="log">excuse <div id="logChild">me</div></div>
+  <div id="logAssertive" role="log" aria-live="assertive">excuse <div id="logAssertiveChild">me</div></div>
   <div id="marquee" role="marquee">excuse <div id="marqueeChild">me</div></div>
   <div id="status" role="status">excuse <div id="statusChild">me</div></div>
   <div id="timer" role="timer">excuse <div id="timerChild">me</div></div>
 
+  <!-- unusual live case -->
+  <div id="liveGroup" role="group" aria-live="polite">
+    excuse <div id="liveGroupChild">me</div>
+  </div>
+
   <!-- html -->
   <input id="radio" type="radio"/>
   <input id="checkbox" type="checkbox"/>
+  <div id="draggable" draggable="true">Draggable div</div>
 </body>
 </html>
--- a/accessible/tests/mochitest/test_states.html
+++ b/accessible/tests/mochitest/test_states.html
@@ -1,16 +1,26 @@
 <html>
 
 <head>
   <title>nsIAccessible states testing</title>
 
   <link rel="stylesheet" type="text/css"
         href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
+  <style type="text/css">
+    .offscreen {
+      position: absolute;
+      left: -5000px;
+      top: -5000px;
+      height: 100px;
+      width: 100px;
+    }
+  </style>
+
   <script type="application/javascript"
           src="chrome://mochikit/content/MochiKit/packed.js"></script>
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="chrome://mochikit/content/a11y/accessible/common.js"></script>
   <script type="application/javascript"
@@ -35,22 +45,25 @@
 
       testStates("aria_checked_checkbox", STATE_CHECKED);
       testStates("aria_mixed_checkbox", STATE_MIXED);
 
       // test disabled group and all its descendants to see if they are
       // disabled, too. See bug 429285.
       testStatesInSubtree("group", STATE_UNAVAILABLE);
 
+      testStates("aria_offscreen_textbox", STATE_OFFSCREEN);
+
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addLoadEvent(doTest);
   </script>
+
 </head>
 
 <body>
 
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=457219"
      title="nsIAccessible states testing">
     Mozilla Bug 457219
@@ -86,10 +99,14 @@
     <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>
+  
+  <div id="offscreen_log" role="log" class="offscreen">
+    <div id="aria_offscreen_textbox" role="textbox" aria-readonly="true">This text should be offscreen</div>
+  </div>
 </body>
 </html>
--- a/accessible/tests/mochitest/test_table_4.html
+++ b/accessible/tests/mochitest/test_table_4.html
@@ -55,17 +55,17 @@ function doTest()
   if (!accTable4)
     tableInterfaceExposed = false;
   ok(tableInterfaceExposed, "table interface is not exposed");
 
   if (tableInterfaceExposed) {
     accNotCreated = (!isAccessible("tr"));
     ok(!accNotCreated, "missed tr accessible");
 
-    testRole(accTable4, ROLE_NOTHING); // XXX: it's a bug, should be ROLE_TABLE
+    testRole(accTable4, ROLE_TABLE);
 
     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
--- a/accessible/tests/mochitest/test_table_indexes_ariagrid.html
+++ b/accessible/tests/mochitest/test_table_indexes_ariagrid.html
@@ -26,17 +26,17 @@
       var tCol = new Array(0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2);
 
       testTableIndexes("grid", 12, tRow, tCol);
 
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
-    addLoadEvent(doTest);
+    addA11yLoadEvent(doTest);
   </script>
 </head>
 <body>
 
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=386813"
      title="support nsIAccessibleTable on ARIA grid/treegrid">Mozilla Bug 386813</a>
   <p id="display"></p>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/test_table_sels_ariagrid.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=410052
+-->
+<head>
+  <title>Table indexes 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"
+          src="chrome://mochikit/content/a11y/accessible/common.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/a11y/accessible/table.js"></script>
+
+  <script type="application/javascript">
+    function doTest()
+    {
+      //////////////////////////////////////////////////////////////////////////
+      // table
+      var cellsArray =
+      [
+        [ true, true,  false, true],
+        [ true, false, true,  true],
+        [ true, false, false, true],
+        [ true, true,  true,  true],
+        [ true, true,  true,  true]
+      ];
+
+      testTableSelection("table", cellsArray);
+      testUnselectTableColumn("table", 3, cellsArray);
+      testUnselectTableRow("table", 3, cellsArray);
+      testSelectTableColumn("table", 0, cellsArray);
+      testSelectTableRow("table", 0, cellsArray);
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     title="implement nsIAccessibleTable selection methods for ARIA grids"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=410052">Mozilla Bug 410052</a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <div role="grid" id="table">
+    <div role="row">
+      <span role="gridcell" aria-selected="true">cell1</span>
+      <span role="gridcell" aria-selected="true">cell2</span>
+      <span role="gridcell">cell3</span>
+      <span role="gridcell" aria-selected="true">cell4</span>
+    </div>
+    <div role="row">
+      <span role="gridcell" aria-selected="true">cell5</span>
+      <span role="gridcell">cell6</span>
+      <span role="gridcell" aria-selected="true">cell7</span>
+      <span role="gridcell" aria-selected="true">cell8</span>
+    </div>
+    <div role="row">
+      <span role="gridcell" aria-selected="true">cell9</span>
+      <span role="gridcell">cell10</span>
+      <span role="gridcell">cell11</span>
+      <span role="gridcell" aria-selected="true">cell12</span>
+    </div>
+    <div role="row" aria-selected="true">
+      <span role="gridcell">cell13</span>
+      <span role="gridcell">cell14</span>
+      <span role="gridcell">cell15</span>
+      <span role="gridcell">cell16</span>
+    </div>
+    <div role="row">
+      <span role="gridcell" aria-selected="true">cell17</span>
+      <span role="gridcell" aria-selected="true">cell18</span>
+      <span role="gridcell" aria-selected="true">cell19</span>
+      <span role="gridcell" aria-selected="true">cell20</span>
+    </div>
+  </div>
+
+</body>
+</html>
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -192,17 +192,16 @@ pref("browser.shell.checkDefaultBrowser"
 // 0 = blank, 1 = home (browser.startup.homepage), 2 = last visited page, 3 = resume previous browser session
 // The behavior of option 3 is detailed at: http://wiki.mozilla.org/Session_Restore
 pref("browser.startup.page",                1);
 pref("browser.startup.homepage",            "resource:/browserconfig.properties");
 
 pref("browser.enable_automatic_image_resizing", true);
 pref("browser.chrome.site_icons", true);
 pref("browser.chrome.favicons", true);
-pref("browser.formfill.enable", true);
 pref("browser.warnOnQuit", true);
 pref("browser.warnOnRestart", true);
 pref("browser.fullscreen.autohide", true);
 pref("browser.fullscreen.animateUp", 1);
 
 #ifdef UNIX_BUT_NOT_MAC
 pref("browser.urlbar.clickSelectsAll", false);
 #else
@@ -223,16 +222,20 @@ pref("browser.urlbar.filter.javascript",
 
 // the maximum number of results to show in autocomplete when doing richResults
 pref("browser.urlbar.maxRichResults", 12);
 // Size of "chunks" affects the number of places to process between each search
 // timeout (ms). Too big and the UI will be unresponsive; too small and we'll
 // be waiting on the timeout too often without many results.
 pref("browser.urlbar.search.chunkSize", 1000);
 pref("browser.urlbar.search.timeout", 100);
+// The amount of time (ms) to wait after the user has stopped typing
+// before starting to perform autocomplete.  50 is the default set in
+// autocomplete.xml.
+pref("browser.urlbar.delay", 50);
 
 // The special characters below can be typed into the urlbar to either restrict
 // the search to visited history, bookmarked, tagged pages; or force a match on
 // just the title text or url.
 pref("browser.urlbar.restrict.history", "^");
 pref("browser.urlbar.restrict.bookmark", "*");
 pref("browser.urlbar.restrict.tag", "+");
 pref("browser.urlbar.restrict.typed", "~");
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -446,17 +446,18 @@
 
             <menu id="history-menu"
                   oncommand="var node = event.target.node; if (node) { PlacesUIUtils.markPageAsTyped(node.uri); openUILink(node.uri, event, false, true); }"
                   onclick="checkForMiddleClick(this, event);"
                   label="&historyMenu.label;"
                   accesskey="&historyMenu.accesskey;">
               <menupopup id="goPopup"
                          type="places"
-                         onpopupshowing="HistoryMenu.onPopupShowing(this);"
+                         onpopupshowing="HistoryMenu.onPopupShowing(event);"
+                         onpopuphidden="HistoryMenu.onPopupHidden(event);"
                          place="place:redirectsMode=2&amp;sort=4&amp;maxResults=10"
                          tooltip="btTooltip">
                 <menuitem id="historyMenuBack"
                           label="&backCmd.label;"
 #ifdef XP_MACOSX
                           key="goBackKb2"
 #else
                           key="goBackKb"
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -575,43 +575,203 @@ var PlacesCommandHook = {
 
     // remove all tags for the associated url
     PlacesUtils.tagging.untagURI(gEditItemOverlay._uri, null);
 
     this.panel.hidePopup();
   }
 };
 
-// Functions for the history menu.
+// Helper object for the history menu.
 var HistoryMenu = {
   get _ss() {
     delete this._ss;
-    return this._ss = Components.classes["@mozilla.org/browser/sessionstore;1"].
-                      getService(Components.interfaces.nsISessionStore);
+    return this._ss = Cc["@mozilla.org/browser/sessionstore;1"].
+                      getService(Ci.nsISessionStore);
+  },
+
+  toggleRecentlyClosedTabs: function PHM_toggleRecentlyClosedTabs() {
+    // enable/disable the Recently Closed Tabs sub menu
+    var undoPopup = document.getElementById("historyUndoPopup");
+
+    // no restorable tabs, so disable menu
+    if (this._ss.getClosedTabCount(window) == 0)
+      undoPopup.parentNode.setAttribute("disabled", true);
+    else
+      undoPopup.parentNode.removeAttribute("disabled");
+  },
+
+  /**
+    * Re-open a closed tab and put it to the end of the tab strip.
+    * Used for a middle click.
+    * @param aEvent
+    *        The event when the user clicks the menu item
+    */
+  _undoCloseMiddleClick: function PHM__undoCloseMiddleClick(aEvent) {
+    if (aEvent.button != 1)
+      return;
+
+    undoCloseTab(aEvent.originalTarget.value);
+    gBrowser.moveTabToEnd();
+  },
+
+  /**
+   * Populate when the history menu is opened
+   */
+  populateUndoSubmenu: function PHM_populateUndoSubmenu() {
+    var undoPopup = document.getElementById("historyUndoPopup");
+
+    // remove existing menu items
+    while (undoPopup.hasChildNodes())
+      undoPopup.removeChild(undoPopup.firstChild);
+
+    // no restorable tabs, so make sure menu is disabled, and return
+    if (this._ss.getClosedTabCount(window) == 0) {
+      undoPopup.parentNode.setAttribute("disabled", true);
+      return;
+    }
+
+    // enable menu
+    undoPopup.parentNode.removeAttribute("disabled");
+
+    // populate menu
+    var undoItems = eval("(" + this._ss.getClosedTabData(window) + ")");
+    for (var i = 0; i < undoItems.length; i++) {
+      var m = document.createElement("menuitem");
+      m.setAttribute("label", undoItems[i].title);
+      if (undoItems[i].image) {
+        let iconURL = undoItems[i].image;
+        // don't initiate a connection just to fetch a favicon (see bug 467828)
+        if (/^https?:/.test(iconURL))
+          iconURL = "moz-anno:favicon:" + iconURL;
+        m.setAttribute("image", iconURL);
+      }
+      m.setAttribute("class", "menuitem-iconic bookmark-item");
+      m.setAttribute("value", i);
+      m.setAttribute("oncommand", "undoCloseTab(" + i + ");");
+      m.addEventListener("click", this._undoCloseMiddleClick, false);
+      if (i == 0)
+        m.setAttribute("key", "key_undoCloseTab");
+      undoPopup.appendChild(m);
+    }
+
+    // "Open All in Tabs"
+    var strings = gNavigatorBundle;
+    undoPopup.appendChild(document.createElement("menuseparator"));
+    m = undoPopup.appendChild(document.createElement("menuitem"));
+    m.setAttribute("label", strings.getString("menuOpenAllInTabs.label"));
+    m.setAttribute("accesskey", strings.getString("menuOpenAllInTabs.accesskey"));
+    m.addEventListener("command", function() {
+      for (var i = 0; i < undoItems.length; i++)
+        undoCloseTab();
+    }, false);
+  },
+
+  toggleRecentlyClosedWindows: function PHM_toggleRecentlyClosedWindows() {
+    // enable/disable the Recently Closed Windows sub menu
+    let undoPopup = document.getElementById("historyUndoWindowPopup");
+
+    // no restorable windows, so disable menu
+    if (this._ss.getClosedWindowCount() == 0)
+      undoPopup.parentNode.setAttribute("disabled", true);
+    else
+      undoPopup.parentNode.removeAttribute("disabled");
+  },
+
+  /**
+   * Populate when the history menu is opened
+   */
+  populateUndoWindowSubmenu: function PHM_populateUndoWindowSubmenu() {
+    let undoPopup = document.getElementById("historyUndoWindowPopup");
+    let menuLabelString = gNavigatorBundle.getString("menuUndoCloseWindowLabel");
+    let menuLabelStringSingleTab =
+      gNavigatorBundle.getString("menuUndoCloseWindowSingleTabLabel");
+
+    // remove existing menu items
+    while (undoPopup.hasChildNodes())
+      undoPopup.removeChild(undoPopup.firstChild);
+
+    // no restorable windows, so make sure menu is disabled, and return
+    if (this._ss.getClosedWindowCount() == 0) {
+      undoPopup.parentNode.setAttribute("disabled", true);
+      return;
+    }
+
+    // enable menu
+    undoPopup.parentNode.removeAttribute("disabled");
+
+    // populate menu
+    let undoItems = JSON.parse(this._ss.getClosedWindowData());
+    for (let i = 0; i < undoItems.length; i++) {
+      let undoItem = undoItems[i];
+      let otherTabsCount = undoItem.tabs.length - 1;
+      let label = (otherTabsCount == 0) ? menuLabelStringSingleTab
+                                        : PluralForm.get(otherTabsCount, menuLabelString);
+      let menuLabel = label.replace("#1", undoItem.title)
+                           .replace("#2", otherTabsCount);
+      let m = document.createElement("menuitem");
+      m.setAttribute("label", menuLabel);
+      let selectedTab = undoItem.tabs[undoItem.selected - 1];
+      if (selectedTab.attributes.image) {
+        let iconURL = selectedTab.attributes.image;
+        // don't initiate a connection just to fetch a favicon (see bug 467828)
+        if (/^https?:/.test(iconURL))
+          iconURL = "moz-anno:favicon:" + iconURL;
+        m.setAttribute("image", iconURL);
+      }
+      m.setAttribute("class", "menuitem-iconic bookmark-item");
+      m.setAttribute("oncommand", "undoCloseWindow(" + i + ");");
+      if (i == 0)
+        m.setAttribute("key", "key_undoCloseWindow");
+      undoPopup.appendChild(m);
+    }
+
+    // "Open All in Windows"
+    undoPopup.appendChild(document.createElement("menuseparator"));
+    let m = undoPopup.appendChild(document.createElement("menuitem"));
+    m.setAttribute("label", gNavigatorBundle.getString("menuRestoreAllWindows.label"));
+    m.setAttribute("accesskey", gNavigatorBundle.getString("menuRestoreAllWindows.accesskey"));
+    m.setAttribute("oncommand",
+      "for (var i = 0; i < " + undoItems.length + "; i++) undoCloseWindow();");
   },
 
   /**
    * popupshowing handler for the history menu.
-   * @param aMenuPopup
-   *        XULNode for the history menupopup
+   * @param aEvent
+   *        The popupshowing event.
    */
-  onPopupShowing: function PHM_onPopupShowing(aMenuPopup) {
-    var resultNode = aMenuPopup.getResultNode();
-    var wasOpen = resultNode.containerOpen;
+  onPopupShowing: function PHM_onPopupShowing(aEvent) {
+    // Don't handle events for submenus.
+    if (aEvent.target != aEvent.currentTarget)
+      return;
+
+    var menuPopup = aEvent.target;
+    var resultNode = menuPopup.getResultNode();
     resultNode.containerOpen = true;
     document.getElementById("endHistorySeparator").hidden =
       resultNode.childCount == 0;
 
-    if (!wasOpen)
-      resultNode.containerOpen = false;
-
-    // HistoryMenu.toggleRecentlyClosedTabs, HistoryMenu.toggleRecentlyClosedWindows
-    // are defined in browser.js
     this.toggleRecentlyClosedTabs();
     this.toggleRecentlyClosedWindows();
+  },
+
+  /**
+   * popuphidden handler for the history menu.
+   * @param aEvent
+   *        The popuphidden event.
+   */
+  onPopupHidden: function PHM_onPopupHidden(aEvent) {
+    // Don't handle events for submenus.
+    if (aEvent.target != aEvent.currentTarget)
+      return;
+
+    var menuPopup = aEvent.target;
+    var resultNode = menuPopup.getResultNode();
+    if (resultNode.containerOpen)
+      resultNode.containerOpen = false;
   }
 };
 
 /**
  * Functions for handling events in the Bookmarks Toolbar and menu.
  */
 var BookmarksEventHandler = {  
   /**
@@ -694,17 +854,17 @@ var BookmarksEventHandler = {
           break;
         }
       }
       currentChild = currentChild.nextSibling;
     }
 
     var itemId = target._resultNode.itemId;
     var siteURIString = "";
-    if (itemId != -1 && PlacesUtils.livemarks.isLivemark(itemId)) {
+    if (itemId != -1 && PlacesUtils.itemIsLivemark(itemId)) {
       var siteURI = PlacesUtils.livemarks.getSiteURI(itemId);
       if (siteURI)
         siteURIString = siteURI.spec;
     }
 
     if (!siteURIString && target._endOptOpenSiteURI) {
         target.removeChild(target._endOptOpenSiteURI);
         target._endOptOpenSiteURI = null;
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1072,17 +1072,18 @@ function BrowserStartup() {
       // border.  Use 28px as a guess (titlebar + bottom window border)
       defaultHeight -= 28;
 #endif
     }
     document.documentElement.setAttribute("width", defaultWidth);
     document.documentElement.setAttribute("height", defaultHeight);
   }
 
-  if (gURLBar && document.documentElement.getAttribute("chromehidden").indexOf("toolbar") != -1) {
+  if (gURLBar &&
+      document.documentElement.getAttribute("chromehidden").indexOf("toolbar") != -1) {
     gURLBar.setAttribute("readonly", "true");
     gURLBar.setAttribute("enablehistory", "false");
   }
 
   setTimeout(delayedStartup, 0, isLoadingBlank, mustLoadSidebar);
 }
 
 function HandleAppCommandEvent(evt) {
@@ -1232,17 +1233,17 @@ function delayedStartup(isLoadingBlank, 
   window.addEventListener("fullscreen", onFullScreen, true);
 
   if (isLoadingBlank && gURLBar && isElementVisible(gURLBar))
     focusElement(gURLBar);
   else
     focusElement(content);
 
   if (gURLBar)
-    gURLBar.setAttribute("emptytext", gURLBarEmptyText.value);
+    gURLBar.emptyText = gURLBarEmptyText.value;
 
   gNavToolbox.customizeDone = BrowserToolboxCustomizeDone;
   gNavToolbox.customizeChange = BrowserToolboxCustomizeChange;
 
   // Set up Sanitize Item
   initializeSanitizer();
 
   // Enable/Disable auto-hide tabbar
@@ -1585,17 +1586,20 @@ function initializeSanitizer()
       if (!doMigrate)
         doMigrate = prefService.getBoolPref("privacy.sanitize.sanitizeOnShutdown");
 
       if (doMigrate) {
         var cpdBranch = prefService.getBranch("privacy.cpd.");
         var clearOnShutdownBranch = prefService.getBranch("privacy.clearOnShutdown.");
         itemArray.forEach(function (name) {
           try {
-            cpdBranch.setBoolPref(name, itemBranch.getBoolPref(name));
+            // don't migrate password or offlineApps clearing in the CRH dialog since
+            // there's no UI for those anymore. They default to false. bug 497656
+            if (name != "passwords" && name != "offlineApps")
+              cpdBranch.setBoolPref(name, itemBranch.getBoolPref(name));
             clearOnShutdownBranch.setBoolPref(name, itemBranch.getBoolPref(name));
           }
           catch(e) {
             Components.utils.reportError("Exception thrown during privacy pref migration: " + e);
           }
         });
       }
 
@@ -2293,26 +2297,16 @@ function PageProxySetIcon (aURL)
     gProxyFavIcon.setAttribute("src", aURL);
 }
 
 function PageProxyClearIcon ()
 {
   gProxyFavIcon.removeAttribute("src");
 }
 
-
-function PageProxyDragGesture(aEvent)
-{
-  if (gProxyFavIcon.getAttribute("pageproxystate") == "valid") {
-    nsDragAndDrop.startDrag(aEvent, proxyIconDNDObserver);
-    return true;
-  }
-  return false;
-}
-
 function PageProxyClickHandler(aEvent)
 {
   if (aEvent.button == 1 && gPrefService.getBoolPref("middlemouse.paste"))
     middleMousePaste(aEvent);
 }
 
 function BrowserImport()
 {
@@ -2659,66 +2653,98 @@ function FillInHTMLTooltip(tipElement)
       tipNode.setAttribute("label", t);
       retVal = true;
     }
   }
 
   return retVal;
 }
 
+var browserDragAndDrop = {
+  getDragURLFromDataTransfer : function (dt)
+  {
+    var types = dt.types;
+    for (var t = 0; t < types.length; t++) {
+      var type = types[t];
+      switch (type) {
+        case "text/uri-list":
+          var url = dt.getData("URL").replace(/^\s+|\s+$/g, "");
+          return [url, url];
+        case "text/plain":
+        case "text/x-moz-text-internal":
+          var url = dt.getData(type).replace(/^\s+|\s+$/g, "");
+          return [url, url];
+        case "text/x-moz-url":
+          var split = dt.getData(type).split("\n");
+          return [split[0], split[1]];
+        case "application/x-moz-file":
+          var file = dt.mozGetDataAt(type, 0);
+          var name = file instanceof Components.interfaces.nsIFile ? file.leafName : "";
+          var ioService = Components.classes["@mozilla.org/network/io-service;1"]
+                                    .getService(Components.interfaces.nsIIOService);
+          var fileHandler = ioService.getProtocolHandler("file")
+                                     .QueryInterface(Components.interfaces.nsIFileProtocolHandler);
+          return [fileHandler.getURLSpecFromFile(file), name];
+      }
+    }
+    return [ , ];
+  },
+
+  dragOver : function (aEvent, statusString)
+  {
+    var types = aEvent.dataTransfer.types;
+    if (types.contains("application/x-moz-file") ||
+        types.contains("text/x-moz-url") ||
+        types.contains("text/uri-list") ||
+        types.contains("text/plain")) {
+      aEvent.preventDefault();
+
+      if (statusString) {
+        var statusTextFld = document.getElementById("statusbar-display");
+        statusTextFld.label = gNavigatorBundle.getString(statusString);
+      }
+    }
+  }
+}
+
+
 var proxyIconDNDObserver = {
   onDragStart: function (aEvent, aXferData, aDragAction)
     {
+      if (gProxyFavIcon.getAttribute("pageproxystate") != "valid")
+        return;
+
       var value = content.location.href;
       var urlString = value + "\n" + content.document.title;
       var htmlString = "<a href=\"" + value + "\">" + value + "</a>";
 
-      aXferData.data = new TransferData();
-      aXferData.data.addDataForFlavour("text/x-moz-url", urlString);
-      aXferData.data.addDataForFlavour("text/unicode", value);
-      aXferData.data.addDataForFlavour("text/html", htmlString);
-
-      // we're copying the URL from the proxy icon, not moving
-      // we specify all of them though, because d&d sucks and OS's
-      // get confused if they don't get the one they want
-      aDragAction.action =
-        Components.interfaces.nsIDragService.DRAGDROP_ACTION_COPY |
-        Components.interfaces.nsIDragService.DRAGDROP_ACTION_MOVE |
-        Components.interfaces.nsIDragService.DRAGDROP_ACTION_LINK;
+      var dt = aEvent.dataTransfer;
+      dt.setData("text/x-moz-url", urlString);
+      dt.setData("text/uri-list", value);
+      dt.setData("text/plain", value);
+      dt.setData("text/html", htmlString);
     }
 }
 
 var homeButtonObserver = {
-  onDrop: function (aEvent, aXferData, aDragSession)
+  onDrop: function (aEvent)
     {
-      var url = transferUtils.retrieveURLFromData(aXferData.data, aXferData.flavour.contentType);
+      let url = browserDragAndDrop.getDragURLFromDataTransfer(aEvent.dataTransfer)[0];
       setTimeout(openHomeDialog, 0, url);
     },
 
-  onDragOver: function (aEvent, aFlavour, aDragSession)
+  onDragOver: function (aEvent)
     {
-      var statusTextFld = document.getElementById("statusbar-display");
-      statusTextFld.label = gNavigatorBundle.getString("droponhomebutton");
-      aDragSession.dragAction = Components.interfaces.nsIDragService.DRAGDROP_ACTION_LINK;
+      browserDragAndDrop.dragOver(aEvent, "droponhomebutton");
+      aEvent.dropEffect = "link";
     },
-
-  onDragExit: function (aEvent, aDragSession)
+  onDragLeave: function (aEvent)
     {
       var statusTextFld = document.getElementById("statusbar-display");
       statusTextFld.label = "";
-    },
-
-  getSupportedFlavours: function ()
-    {
-      var flavourSet = new FlavourSet();
-      flavourSet.appendFlavour("application/x-moz-file", "nsIFile");
-      flavourSet.appendFlavour("text/x-moz-url");
-      flavourSet.appendFlavour("text/unicode");
-      flavourSet.appendFlavour("text/x-moz-text-internal");  // for tabs
-      return flavourSet;
     }
 }
 
 function openHomeDialog(aURL)
 {
   var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService);
   var promptTitle = gNavigatorBundle.getString("droponhometitle");
   var promptMsg   = gNavigatorBundle.getString("droponhomemsg");
@@ -2737,146 +2763,110 @@ function openHomeDialog(aURL)
       homeButton.setAttribute("tooltiptext", aURL);
     } catch (ex) {
       dump("Failed to set the home page.\n"+ex+"\n");
     }
   }
 }
 
 var bookmarksButtonObserver = {
-  onDrop: function (aEvent, aXferData, aDragSession)
+  onDrop: function (aEvent)
   {
-    var split = aXferData.data.split("\n");
-    var url = split[0];
-    if (url != aXferData.data)  // do nothing if it's not a valid URL
-      PlacesUIUtils.showMinimalAddBookmarkUI(makeURI(url), split[1]);
-  },
-
-  onDragOver: function (aEvent, aFlavour, aDragSession)
+    let [url, name] = browserDragAndDrop.getDragURLFromDataTransfer(aEvent.dataTransfer);
+    try {
+      PlacesUIUtils.showMinimalAddBookmarkUI(makeURI(url), name);
+    } catch(ex) { }
+  },
+
+  onDragOver: function (aEvent)
   {
-    var statusTextFld = document.getElementById("statusbar-display");
-    statusTextFld.label = gNavigatorBundle.getString("droponbookmarksbutton");
-    aDragSession.dragAction = Components.interfaces.nsIDragService.DRAGDROP_ACTION_LINK;
-  },
-
-  onDragExit: function (aEvent, aDragSession)
+    browserDragAndDrop.dragOver(aEvent, "droponbookmarksbutton");
+    aEvent.dropEffect = "link";
+  },
+
+  onDragLeave: function (aEvent)
   {
     var statusTextFld = document.getElementById("statusbar-display");
     statusTextFld.label = "";
-  },
-
-  getSupportedFlavours: function ()
-  {
-    var flavourSet = new FlavourSet();
-    flavourSet.appendFlavour("application/x-moz-file", "nsIFile");
-    flavourSet.appendFlavour("text/x-moz-url");
-    flavourSet.appendFlavour("text/unicode");
-    return flavourSet;
   }
 }
 
 var newTabButtonObserver = {
-  onDragOver: function(aEvent, aFlavour, aDragSession) {
-    var statusTextFld = document.getElementById("statusbar-display");
-    statusTextFld.label = gNavigatorBundle.getString("droponnewtabbutton");
-    return true;
-  },
-  onDragExit: function (aEvent, aDragSession) {
+  onDragOver: function (aEvent)
+  {
+    browserDragAndDrop.dragOver(aEvent, "droponnewtabbutton");
+  },
+
+  onDragLeave: function (aEvent)
+  {
     var statusTextFld = document.getElementById("statusbar-display");
     statusTextFld.label = "";
   },
-  onDrop: function (aEvent, aXferData, aDragSession) {
-    var xferData = aXferData.data.split("\n");
-    var draggedText = xferData[0] || xferData[1];
+
+  onDrop: function (aEvent)
+  {
+    let url = browserDragAndDrop.getDragURLFromDataTransfer(aEvent.dataTransfer)[0];
     var postData = {};
-    var url = getShortcutOrURI(draggedText, postData);
+    url = getShortcutOrURI(url, postData);
     if (url) {
-      nsDragAndDrop.dragDropSecurityCheck(aEvent, aDragSession, url);
+      nsDragAndDrop.dragDropSecurityCheck(aEvent, null, url);
       // allow third-party services to fixup this URL
       openNewTabWith(url, null, postData.value, aEvent, true);
     }
-  },
-  getSupportedFlavours: function () {
-    var flavourSet = new FlavourSet();
-    flavourSet.appendFlavour("text/unicode");
-    flavourSet.appendFlavour("text/x-moz-url");
-    flavourSet.appendFlavour("application/x-moz-file", "nsIFile");
-    return flavourSet;
   }
 }
 
 var newWindowButtonObserver = {
-  onDragOver: function(aEvent, aFlavour, aDragSession)
-    {
-      var statusTextFld = document.getElementById("statusbar-display");
-      statusTextFld.label = gNavigatorBundle.getString("droponnewwindowbutton");
-      return true;
-    },
-  onDragExit: function (aEvent, aDragSession)
-    {
-      var statusTextFld = document.getElementById("statusbar-display");
-      statusTextFld.label = "";
-    },
-  onDrop: function (aEvent, aXferData, aDragSession)
-    {
-      var xferData = aXferData.data.split("\n");
-      var draggedText = xferData[0] || xferData[1];
-      var postData = {};
-      var url = getShortcutOrURI(draggedText, postData);
-      if (url) {
-        nsDragAndDrop.dragDropSecurityCheck(aEvent, aDragSession, url);
-        // allow third-party services to fixup this URL
-        openNewWindowWith(url, null, postData.value, true);
-      }
-    },
-  getSupportedFlavours: function ()
-    {
-      var flavourSet = new FlavourSet();
-      flavourSet.appendFlavour("text/unicode");
-      flavourSet.appendFlavour("text/x-moz-url");
-      flavourSet.appendFlavour("application/x-moz-file", "nsIFile");
-      flavourSet.appendFlavour("text/x-moz-text-internal");  // for tabs
-      return flavourSet;
-    }
+  onDragOver: function (aEvent)
+  {
+    browserDragAndDrop.dragOver(aEvent, "droponnewwindowbutton");
+  },
+  onDragLeave: function (aEvent)
+  {
+    var statusTextFld = document.getElementById("statusbar-display");
+    statusTextFld.label = "";
+  },
+  onDrop: function (aEvent)
+  {
+    let url = browserDragAndDrop.getDragURLFromDataTransfer(aEvent.dataTransfer)[0];
+    var postData = {};
+    url = getShortcutOrURI(url, postData);
+    if (url) {
+      nsDragAndDrop.dragDropSecurityCheck(aEvent, null, url);
+      // allow third-party services to fixup this URL
+      openNewWindowWith(url, null, postData.value, true);
+    }
+  }
 }
 
 var DownloadsButtonDNDObserver = {
   /////////////////////////////////////////////////////////////////////////////
   // nsDragAndDrop
-  onDragOver: function (aEvent, aFlavour, aDragSession)
+  onDragOver: function (aEvent)
   {
     var statusTextFld = document.getElementById("statusbar-display");
     statusTextFld.label = gNavigatorBundle.getString("dropondownloadsbutton");
-    aDragSession.canDrop = (aFlavour.contentType == "text/x-moz-url" ||
-                            aFlavour.contentType == "text/unicode");
-  },
-
-  onDragExit: function (aEvent, aDragSession)
+    var types = aEvent.dataTransfer.types;
+    if (types.contains("text/x-moz-url") ||
+        types.contains("text/uri-list") ||
+        types.contains("text/plain"))
+      aEvent.preventDefault();
+  },
+
+  onDragLeave: function (aEvent)
   {
     var statusTextFld = document.getElementById("statusbar-display");
     statusTextFld.label = "";
   },
 
-  onDrop: function (aEvent, aXferData, aDragSession)
+  onDrop: function (aEvent)
   {
-    var split = aXferData.data.split("\n");
-    var url = split[0];
-    if (url != aXferData.data) {  //do nothing, not a valid URL
-      nsDragAndDrop.dragDropSecurityCheck(aEvent, aDragSession, url);
-
-      var name = split[1];
-      saveURL(url, name, null, true, true);
-    }
-  },
-  getSupportedFlavours: function ()
-  {
-    var flavourSet = new FlavourSet();
-    flavourSet.appendFlavour("text/x-moz-url");
-    flavourSet.appendFlavour("text/unicode");
-    return flavourSet;
+    let [url, name] = browserDragAndDrop.getDragURLFromDataTransfer(aEvent.dataTransfer);
+    nsDragAndDrop.dragDropSecurityCheck(aEvent, null, url);
+    saveURL(url, name, null, true, true);
   }
 }
 
 const DOMLinkHandler = {
   handleEvent: function (event) {
     switch (event.type) {
       case "DOMLinkAdded":
         this.onLinkAdded(event);
@@ -4522,39 +4512,43 @@ function onViewToolbarsPopupShowing(aEve
       popup.removeChild(deadItem);
   }
 
   var firstMenuItem = popup.firstChild;
 
   for (i = 0; i < gNavToolbox.childNodes.length; ++i) {
     var toolbar = gNavToolbox.childNodes[i];
     var toolbarName = toolbar.getAttribute("toolbarname");
-    var type = toolbar.getAttribute("type");
-    if (toolbarName && type != "menubar") {
-      var menuItem = document.createElement("menuitem");
+    if (toolbarName) {
+      let menuItem = document.createElement("menuitem");
+      let hidingAttribute = toolbar.getAttribute("type") == "menubar" ?
+                            "autohide" : "collapsed";
       menuItem.setAttribute("toolbarindex", i);
       menuItem.setAttribute("type", "checkbox");
       menuItem.setAttribute("label", toolbarName);
       menuItem.setAttribute("accesskey", toolbar.getAttribute("accesskey"));
-      menuItem.setAttribute("checked", toolbar.getAttribute("collapsed") != "true");
+      menuItem.setAttribute("checked", toolbar.getAttribute(hidingAttribute) != "true");
       popup.insertBefore(menuItem, firstMenuItem);
 
       menuItem.addEventListener("command", onViewToolbarCommand, false);
     }
     toolbar = toolbar.nextSibling;
   }
 }
 
 function onViewToolbarCommand(aEvent)
 {
   var index = aEvent.originalTarget.getAttribute("toolbarindex");
   var toolbar = gNavToolbox.childNodes[index];
-
-  toolbar.collapsed = aEvent.originalTarget.getAttribute("checked") != "true";
-  document.persist(toolbar.id, "collapsed");
+  var hidingAttribute = toolbar.getAttribute("type") == "menubar" ?
+                        "autohide" : "collapsed";
+
+  toolbar.setAttribute(hidingAttribute,
+                       aEvent.originalTarget.getAttribute("checked") != "true");
+  document.persist(toolbar.id, hidingAttribute);
 }
 
 function displaySecurityInfo()
 {
   BrowserPageInfo(null, "securityTab");
 }
 
 /**
@@ -4955,23 +4949,17 @@ function handleLinkClick(event, href, li
       if (event.altKey) {
         saveURL(href, linkNode ? gatherTextUnder(linkNode) : "", null, true,
                 true, doc.documentURIObject);
         return true;
       }
 
       return false;
     case 1:    // if middle button clicked
-      var tab;
-      try {
-        tab = gPrefService.getBoolPref("browser.tabs.opentabfor.middleclick")
-      }
-      catch(ex) {
-        tab = true;
-      }
+      var tab = gPrefService.getBoolPref("browser.tabs.opentabfor.middleclick");
       if (tab)
         openNewTabWith(href, doc, null, event, false);
       else
         openNewWindowWith(href, doc, null, false);
       event.stopPropagation();
       return true;
   }
   return false;
@@ -5008,61 +4996,56 @@ function middleMousePaste(event)
  * be available for all <browser> tags as well as gecko embedding. See
  * mozilla/content/base/src/nsContentAreaDragDrop.cpp.
  *
  * Do not add any new fuctionality here other than what is needed for
  * a standalone product.
  */
 
 var contentAreaDNDObserver = {
-  onDrop: function (aEvent, aXferData, aDragSession)
+  onDragOver: function (aEvent)
+    {
+      var types = aEvent.dataTransfer.types;
+      if (types.contains("application/x-moz-file") ||
+          types.contains("text/x-moz-url") ||
+          types.contains("text/uri-list") ||
+          types.contains("text/plain"))
+        aEvent.preventDefault();
+    },
+  onDrop: function (aEvent)
     {
       if (aEvent.getPreventDefault())
         return;
 
-      var dragType = aXferData.flavour.contentType;
-      var dragData = aXferData.data;
-
-      var url = transferUtils.retrieveURLFromData(dragData, dragType);
+      let [url, name] = browserDragAndDrop.getDragURLFromDataTransfer(aEvent.dataTransfer);
 
       // valid urls don't contain spaces ' '; if we have a space it
       // isn't a valid url, or if it's a javascript: or data: url,
       // bail out
       if (!url || !url.length || url.indexOf(" ", 0) != -1 ||
           /^\s*(javascript|data):/.test(url))
         return;
 
-      nsDragAndDrop.dragDropSecurityCheck(aEvent, aDragSession, url);
+      nsDragAndDrop.dragDropSecurityCheck(aEvent, null, url);
 
       switch (document.documentElement.getAttribute('windowtype')) {
         case "navigator:browser":
           var postData = { };
           var uri = getShortcutOrURI(url, postData);
           loadURI(uri, null, postData.value, false);
           break;
         case "navigator:view-source":
           viewSource(url);
           break;
       }
 
       // keep the event from being handled by the dragDrop listeners
       // built-in to gecko if they happen to be above us.
       aEvent.preventDefault();
-    },
-
-  getSupportedFlavours: function ()
-    {
-      var flavourSet = new FlavourSet();
-      flavourSet.appendFlavour(TAB_DROP_TYPE);
-      flavourSet.appendFlavour("text/x-moz-url");
-      flavourSet.appendFlavour("text/plain");
-      flavourSet.appendFlavour("application/x-moz-file", "nsIFile");
-      return flavourSet;
-    }
-
+    }
 };
 
 function MultiplexHandler(event)
 { try {
     var node = event.target;
     var name = node.getAttribute('name');
 
     if (name == 'detectorGroup') {
@@ -6243,161 +6226,16 @@ var FeedHandler = {
 };
 
 #include browser-places.js
 
 #include browser-textZoom.js
 
 #include browser-tabPreviews.js
 
-HistoryMenu.toggleRecentlyClosedTabs = function PHM_toggleRecentlyClosedTabs() {
-  // enable/disable the Recently Closed Tabs sub menu
-  var undoPopup = document.getElementById("historyUndoPopup");
-
-  // no restorable tabs, so disable menu
-  if (this._ss.getClosedTabCount(window) == 0)
-    undoPopup.parentNode.setAttribute("disabled", true);
-  else
-    undoPopup.parentNode.removeAttribute("disabled");
-}
-
-/**
- * Populate when the history menu is opened
- */
-HistoryMenu.populateUndoSubmenu = function PHM_populateUndoSubmenu() {
-  var undoPopup = document.getElementById("historyUndoPopup");
-
-  // remove existing menu items
-  while (undoPopup.hasChildNodes())
-    undoPopup.removeChild(undoPopup.firstChild);
-
-  // no restorable tabs, so make sure menu is disabled, and return
-  if (this._ss.getClosedTabCount(window) == 0) {
-    undoPopup.parentNode.setAttribute("disabled", true);
-    return;
-  }
-
-  // enable menu
-  undoPopup.parentNode.removeAttribute("disabled");
-
-  // populate menu
-  var undoItems = eval("(" + this._ss.getClosedTabData(window) + ")");
-  for (var i = 0; i < undoItems.length; i++) {
-    var m = document.createElement("menuitem");
-    m.setAttribute("label", undoItems[i].title);
-    if (undoItems[i].image) {
-      let iconURL = undoItems[i].image;
-      // don't initiate a connection just to fetch a favicon (see bug 467828)
-      if (/^https?:/.test(iconURL))
-        iconURL = "moz-anno:favicon:" + iconURL;
-      m.setAttribute("image", iconURL);
-    }
-    m.setAttribute("class", "menuitem-iconic bookmark-item");
-    m.setAttribute("value", i);
-    m.setAttribute("oncommand", "undoCloseTab(" + i + ");");
-    m.addEventListener("click", undoCloseMiddleClick, false);
-    if (i == 0)
-      m.setAttribute("key", "key_undoCloseTab");
-    undoPopup.appendChild(m);
-  }
-
-  // "Open All in Tabs"
-  var strings = gNavigatorBundle;
-  undoPopup.appendChild(document.createElement("menuseparator"));
-  m = undoPopup.appendChild(document.createElement("menuitem"));
-  m.setAttribute("label", strings.getString("menuOpenAllInTabs.label"));
-  m.setAttribute("accesskey", strings.getString("menuOpenAllInTabs.accesskey"));
-  m.addEventListener("command", function() {
-    for (var i = 0; i < undoItems.length; i++)
-      undoCloseTab();
-  }, false);
-}
-
-HistoryMenu.toggleRecentlyClosedWindows = function PHM_toggleRecentlyClosedWindows() {
-  // enable/disable the Recently Closed Windows sub menu
-  let undoPopup = document.getElementById("historyUndoWindowPopup");
-
-  // no restorable windows, so disable menu
-  if (this._ss.getClosedWindowCount() == 0)
-    undoPopup.parentNode.setAttribute("disabled", true);
-  else
-    undoPopup.parentNode.removeAttribute("disabled");
-}
-
-/**
- * Populate when the history menu is opened
- */
-HistoryMenu.populateUndoWindowSubmenu = function PHM_populateUndoWindowSubmenu() {
-  let undoPopup = document.getElementById("historyUndoWindowPopup");
-  let menuLabelString = gNavigatorBundle.getString("menuUndoCloseWindowLabel");
-  let menuLabelStringSingleTab =
-    gNavigatorBundle.getString("menuUndoCloseWindowSingleTabLabel");
-
-  // remove existing menu items
-  while (undoPopup.hasChildNodes())
-    undoPopup.removeChild(undoPopup.firstChild);
-
-  // no restorable windows, so make sure menu is disabled, and return
-  if (this._ss.getClosedWindowCount() == 0) {
-    undoPopup.parentNode.setAttribute("disabled", true);
-    return;
-  }
-
-  // enable menu
-  undoPopup.parentNode.removeAttribute("disabled");
-
-  // populate menu
-  let undoItems = JSON.parse(this._ss.getClosedWindowData());
-  for (let i = 0; i < undoItems.length; i++) {
-    let undoItem = undoItems[i];
-    let otherTabsCount = undoItem.tabs.length - 1;
-    let label = (otherTabsCount == 0) ? menuLabelStringSingleTab
-                                      : PluralForm.get(otherTabsCount, menuLabelString);
-    let menuLabel = label.replace("#1", undoItem.title)
-                         .replace("#2", otherTabsCount);
-    let m = document.createElement("menuitem");
-    m.setAttribute("label", menuLabel);
-    let selectedTab = undoItem.tabs[undoItem.selected - 1];
-    if (selectedTab.attributes.image) {
-      let iconURL = selectedTab.attributes.image;
-      // don't initiate a connection just to fetch a favicon (see bug 467828)
-      if (/^https?:/.test(iconURL))
-        iconURL = "moz-anno:favicon:" + iconURL;
-      m.setAttribute("image", iconURL);
-    }
-    m.setAttribute("class", "menuitem-iconic bookmark-item");
-    m.setAttribute("oncommand", "undoCloseWindow(" + i + ");");
-    if (i == 0)
-      m.setAttribute("key", "key_undoCloseWindow");
-    undoPopup.appendChild(m);
-  }
-
-  // "Open All in Windows"
-  undoPopup.appendChild(document.createElement("menuseparator"));
-  let m = undoPopup.appendChild(document.createElement("menuitem"));
-  m.setAttribute("label", gNavigatorBundle.getString("menuRestoreAllWindows.label"));
-  m.setAttribute("accesskey", gNavigatorBundle.getString("menuRestoreAllWindows.accesskey"));
-  m.setAttribute("oncommand",
-    "for (var i = 0; i < " + undoItems.length + "; i++) undoCloseWindow();");
-}
-
-/**
-  * Re-open a closed tab and put it to the end of the tab strip. 
-  * Used for a middle click.
-  * @param aEvent
-  *        The event when the user clicks the menu item
-  */
-function undoCloseMiddleClick(aEvent) {
-  if (aEvent.button != 1)
-    return;
-
-  undoCloseTab(aEvent.originalTarget.value);
-  gBrowser.moveTabToEnd();
-}
-
 /**
  * Re-open a closed tab.
  * @param aIndex
  *        The index of the tab (via nsSessionStore.getClosedTabData)
  * @returns a reference to the reopened tab.
  */
 function undoCloseTab(aIndex) {
   // wallpaper patch to prevent an unnecessary blank tab (bug 343895)
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -279,16 +279,20 @@
   </tooltip>
 
   <toolbox id="navigator-toolbox" class="toolbox-top" mode="icons"
            defaultmode="icons">
     <!-- Menu -->
     <toolbar type="menubar" id="toolbar-menubar" class="chromeclass-menubar" customizable="true"
              defaultset="menubar-items"
              mode="icons" iconsize="small" defaulticonsize="small"
+#ifdef XP_WIN
+             toolbarname="&menubarCmd.label;"
+             accesskey="&menubarCmd.accesskey;"
+#endif
              context="toolbar-context-menu">
       <toolbaritem id="menubar-items" align="center">
 # The entire main menubar is placed into browser-menubar.inc, so that it can be shared by 
 # hiddenWindow.xul.
 #include browser-menubar.inc
       </toolbaritem>
     </toolbar>
 
@@ -335,19 +339,20 @@
       <toolbarbutton id="stop-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                      label="&stopCmd.label;"
                      command="Browser:Stop"
                      tooltiptext="&stopButton.tooltip;"/>
 
       <toolbarbutton id="home-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                      persist="class"
                      label="&homeButton.label;"
-                     ondragover="nsDragAndDrop.dragOver(event, homeButtonObserver);"
-                     ondragdrop="nsDragAndDrop.drop(event, homeButtonObserver);"
-                     ondragexit="nsDragAndDrop.dragExit(event, homeButtonObserver);"
+                     ondragover="homeButtonObserver.onDragOver(event)"
+                     ondragenter="homeButtonObserver.onDragOver(event)"
+                     ondrop="homeButtonObserver.onDrop(event)"
+                     ondragleave="homeButtonObserver.onDragLeave(event)"
                      onclick="BrowserGoHome(event);"/>
 
       <toolbaritem id="urlbar-container" align="center" flex="400" persist="width"
                    title="&locationItem.title;" class="chromeclass-location">
         <textbox id="urlbar" flex="1"
                  bookmarkhistoryemptytext="&urlbar.bookmarkhistory.emptyText;"
                  bookmarkemptytext="&urlbar.bookmark.emptyText;"
                  historyemptytext="&urlbar.history.emptyText;"
@@ -365,32 +370,32 @@
                  newlines="stripsurroundingwhitespace"
                  oninput="gBrowser.userTypedValue = this.value;"
                  ontextentered="this.handleCommand(param);"
                  ontextreverted="return this.handleRevert();"
                  pageproxystate="invalid"
                  onsearchbegin="LocationBarHelpers._searchBegin();"
                  onsearchcomplete="LocationBarHelpers._searchComplete();"
                  onfocus="document.getElementById('identity-box').style.MozUserFocus= 'normal'"
-                 onblur="document.getElementById('identity-box').style.MozUserFocus = 'ignore';">
+                 onblur="setTimeout(function() document.getElementById('identity-box').style.MozUserFocus = '', 0);">
           <!-- Use onclick instead of normal popup= syntax since the popup
                code fires onmousedown, and hence eats our favicon drag events.
                We only add the identity-box button to the tab order when the location bar
                has focus, otherwise pressing F6 focuses it instead of the location bar -->
           <box id="identity-box" role="button"
                chromedir="&locale.dir;"
                onclick="gIdentityHandler.handleIdentityButtonEvent(event);"
                onkeypress="gIdentityHandler.handleIdentityButtonEvent(event);">
             <hbox align="center">
               <stack id="page-proxy-stack"
                      onclick="PageProxyClickHandler(event);">
                 <image id="urlbar-throbber" busy="false"/>
                 <image id="page-proxy-favicon" validate="never"
                        pageproxystate="invalid"
-                       ondraggesture="PageProxyDragGesture(event);"
+                       ondragstart="proxyIconDNDObserver.onDragStart(event);"
                        onerror="this.removeAttribute('src');"/>
               </stack>
               <label id="identity-icon-label" crop="center" flex="1"/>
             </hbox>
           </box>
           <hbox id="urlbar-icons">
             <button type="menu"
                     style="-moz-user-focus: none"
@@ -440,49 +445,52 @@
                onclick="BookmarksEventHandler.onClick(event);"
                oncommand="BookmarksEventHandler.onCommand(event);"
                onpopupshowing="BookmarksEventHandler.onPopupShowing(event);"
                tooltip="btTooltip"/>
       </toolbaritem>
 
         <toolbarbutton id="downloads-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                        observes="Tools:Downloads"
-                       ondragdrop="nsDragAndDrop.drop(event, DownloadsButtonDNDObserver); event.stopPropagation()"
-                       ondragover="nsDragAndDrop.dragOver(event, DownloadsButtonDNDObserver); event.stopPropagation()"
-                       ondragenter="nsDragAndDrop.dragEnter(event, DownloadsButtonDNDObserver); event.stopPropagation()"
-                       ondragexit="nsDragAndDrop.dragExit(event, DownloadsButtonDNDObserver); event.stopPropagation()"
+                       ondrop="DownloadsButtonDNDObserver.onDrop(event)"
+                       ondragover="DownloadsButtonDNDObserver.onDragOver(event)"
+                       ondragenter="DownloadsButtonDNDObserver.onDragOver(event)"
+                       ondragleave="DownloadsButtonDNDObserver.onDragLeave(event)"
                        label="&downloads.label;"
                        tooltiptext="&downloads.tooltip;"/>
 
         <toolbarbutton id="history-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                        observes="viewHistorySidebar" label="&historyButton.label;"
                        tooltiptext="&historyButton.tooltip;"/>
 
         <toolbarbutton id="bookmarks-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                        observes="viewBookmarksSidebar"
                        tooltiptext="&bookmarksButton.tooltip;"
-                       ondragover="nsDragAndDrop.dragOver(event, bookmarksButtonObserver);"
-                       ondragdrop="nsDragAndDrop.drop(event, bookmarksButtonObserver);"
-                       ondragexit="nsDragAndDrop.dragExit(event, bookmarksButtonObserver);"/>
+                       ondrop="bookmarksButtonObserver.onDrop(event)"
+                       ondragover="bookmarksButtonObserver.onDragOver(event)"
+                       ondragenter="bookmarksButtonObserver.onDragOver(event)"
+                       ondragleave="bookmarksButtonObserver.onDragLeave(event)"/>
 
         <toolbarbutton id="new-tab-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                        label="&tabCmd.label;"
                        command="cmd_newNavigatorTab"
                        tooltiptext="&newTabButton.tooltip;"
-                       ondragover="nsDragAndDrop.dragOver(event, newTabButtonObserver);"
-                       ondragdrop="nsDragAndDrop.drop(event, newTabButtonObserver);"
-                       ondragexit="nsDragAndDrop.dragExit(event, newTabButtonObserver);"/>
+                       ondrop="newTabButtonObserver.onDrop(event)"
+                       ondragover="newTabButtonObserver.onDragOver(event)"
+                       ondragenter="newTabButtonObserver.onDragOver(event)"
+                       ondragleave="newTabButtonObserver.onDragLeave(event)"/>
 
         <toolbarbutton id="new-window-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                        label="&newNavigatorCmd.label;"
                        command="key_newNavigator"
                        tooltiptext="&newWindowButton.tooltip;"
-                       ondragover="nsDragAndDrop.dragOver(event, newWindowButtonObserver);"
-                       ondragdrop="nsDragAndDrop.drop(event, newWindowButtonObserver);"
-                       ondragexit="nsDragAndDrop.dragExit(event, newWindowButtonObserver);"/>
+                       ondrop="newWindowButtonObserver.onDrop(event)"
+                       ondragover="newWindowButtonObserver.onDragOver(event)"
+                       ondragenter="newWindowButtonObserver.onDragOver(event)"
+                       ondragleave="newWindowButtonObserver.onDragLeave(event)"/>
 
         <toolbarbutton id="cut-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                        label="&cutCmd.label;"
                        command="cmd_cut"
                        tooltiptext="&cutButton.tooltip;"/>
 
         <toolbarbutton id="copy-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                        label="&copyCmd.label;"
@@ -548,31 +556,31 @@
 
     <splitter id="sidebar-splitter" class="chromeclass-extrachrome" hidden="true"/>
     <vbox id="appcontent" flex="1">
       <tabbrowser id="content" disablehistory="true"
                   flex="1" contenttooltip="aHTMLTooltip"
                   contentcontextmenu="contentAreaContextMenu"
                   onnewtab="BrowserOpenTab();"
                   autocompletepopup="PopupAutoComplete"
-                  ondrop="nsDragAndDrop.drop(event, contentAreaDNDObserver);"
+                  ondrop="contentAreaDNDObserver.onDrop(event)"
                   onclick="return contentAreaClick(event, false);"/>
     </vbox>
   </hbox>
   <panel id="customizeToolbarSheetPopup" noautohide="true">
     <iframe id="customizeToolbarSheetIFrame"
             style="&dialog.style;"
             hidden="true"/>
   </panel>
 
   <vbox id="browser-bottombox">
     <findbar browserid="content" id="FindToolbar"/>
   
     <statusbar class="chromeclass-status" id="status-bar"
-               ondrop="nsDragAndDrop.drop(event, contentAreaDNDObserver);">
+               ondrop="contentAreaDNDObserver.onDrop(event)">
       <statusbarpanel id="statusbar-display" label="" flex="1"/>
       <statusbarpanel class="statusbarpanel-progress" collapsed="true" id="statusbar-progresspanel">
         <progressmeter class="progressmeter-statusbar" id="statusbar-icon" mode="normal" value="0"/>
       </statusbarpanel>
       <statusbarpanel id="download-monitor" class="statusbarpanel-iconic-text"
                       tooltiptext="&downloadMonitor2.tooltip;" hidden="true"
                       command="Tools:Downloads"/>
       <statusbarpanel id="security-button" class="statusbarpanel-iconic-text"
--- a/browser/base/content/credits.xhtml
+++ b/browser/base/content/credits.xhtml
@@ -215,97 +215,125 @@
         <div class="links" dir="&locale.dir;">
           &credit.thanks2; <a href="" link="about:credits" onclick="visitLink(event);">&credit.contributors2;</a>
         </div>
 
         <div class="creditsGroup">
           <ul>
             <li>Josh Aas</li>
             <li>Robert Accettura</li>
+            <li>Lucas Adamski</li>
             <li>Ehsan Akhgari</li>
             <li>Sean Alamares</li>
+            <li>Pedro Alves</li>
+            <li>David Anderson</li>
             <li>Harvey Anderson</li>
             <li>Smokey Ardisson</li>
             <li>Rob Arnold</li>
             <li>Tomoya Asai</li>
+            <li>Chris AtLee</li>
             <li>Dietrich Ayala</li>
             <li>Mitchell Baker</li>
             <li>Rhian Baker</li>
+            <li>Jeff Balogh</li>
+            <li>Honza Bambas</li>
             <li>Jan Bambas</li>
+            <li>Rey Bango</li>
+            <li>Mark Banner</li>
             <li>Jason Barnabe</li>
             <li>David Baron</li>
             <li>Colin Barrett</li>
+            <li>Curtis Bartley</li>
             <li>Bo Bayles</li>
             <li>Christopher Beard</li>
             <li>Glen Beasley</li>
             <li>Juan Becerra</li>
             <li>Brian Behlendorf</li>
             <li>Mike Beltzner</li>
             <li>Mic Berman</li>
             <li>Uri Bernstein</li>
             <li>Christian Biesinger</li>
             <li>Al Billings</li>
             <li>Seth Bindernagel</li>
+            <li>Lukas Blakk</li>
+            <li>Jim Blandy</li>
             <li>Chris Blizzard</li>
             <li>Jamey Boje</li>
+            <li>David Bolter</li>
             <li>Nelson Bolyard</li>
             <li>Marco Bonardo</li>
             <li>Carsten Book</li>
             <li>Paul Booker</li>
+            <li>Jennifer Boriss</li>
             <li>Dan Born</li>
+            <li>Arpad Borsos</li>
+            <li>David Boswell</li>
             <li>Ondřej Brablc</li>
             <li>Catherine Brady</li>
             <li>Dave Bragsalla</li>
+            <li>Alex Buchanan</li>
             <li>Igor Bukanov</li>
             <li>Simon Bünzli</li>
             <li>Lapo Calamandrei</li>
             <li>Dave Camp</li>
             <li>Rob Campbell</li>
             <li>Regis Caspar</li>
             <li>Garrett Casto</li>
             <li>Tony Chang</li>
             <li>Wan-Teh Chang</li>
             <li>Emily Chen</li>
             <li>Ginn Chen</li>
             <li>Pascal Chevrel</li>
+            <li>Adam Christian</li>
             <li>Tony Chung</li>
             <li>Bob Clary</li>
             <li>Wil Clouser</li>
             <li>Mary Colvig</li>
             <li>Majken Connor</li>
             <li>Mike Connor</li>
             <li>Chris Cooper</li>
+            <li>Eric Cooper</li>
+            <li>Paul Craciunoiu</li>
             <li>Brian Crowder</li>
             <li>John Daggett</li>
             <li>David Dahl</li>
             <li>Michael Davis</li>
             <li>Neil Deakin</li>
             <li>Julie Deroche</li>
+            <li>Aakash Desai</li>
+            <li>Ryan Doherty</li>
             <li>Justin Dolske</li>
             <li>Stephen Donner</li>
             <li>Asa Dotzler</li>
             <li>Chris Double</li>
+            <li>Joe Drew</li>
+            <li>Jason Duell</li>
+            <li>Karsten Düsterloh</li>
             <li>Brendan Eich</li>
+            <li>Daniel Einspanjer</li>
             <li>Kai Engert</li>
             <li>Steve England</li>
             <li>Madhava Enros</li>
             <li>Behdad Esfahbod</li>
             <li>Elika Etemad</li>
             <li>Anthony Evans</li>
             <li>Jason Evans</li>
             <li>Alex Faaborg</li>
             <li>Jane Finette</li>
             <li>Mark Finkle</li>
             <li>Darin Fisher</li>
             <li>Jayson Fittipaldi</li>
             <li>Justin Fitzhugh</li>
             <li>Ryan Flint</li>
             <li>Alix Franquet</li>
             <li>Eli Friedman</li>
+            <li>Andreas Gal</li>
             <li>Steven Garrity</li>
+            <li>Armen Zambrano Gasparnian</li>
+            <li>Serge Gautherie</li>
             <li>Kevin Gerich</li>
             <li>Taras Glek</li>
             <li>Aravind Gottipati</li>
             <li>Dão Gottwald</li>
             <li>Zak Greant</li>
             <li>Matthew Gregan</li>
             <li>Will Guaraldi</li>
             <li>Adam Guthrie</li>
@@ -318,126 +346,165 @@
             <li>Frank Hecker</li>
             <li>Robert Helmer</li>
             <li>Stefan Hermes</li>
             <li>Jon Hicks</li>
             <li>Graydon Hoare</li>
             <li>Chris Hofmann</li>
             <li>Timothy Hogan</li>
             <li>Daniel Holbert</li>
+            <li>Bobby Holley</li>
             <li>Mike Hommey</li>
             <li>Stephen Horlander</li>
+            <li>Barbara Hueppe</li>
+            <li>Anthony Hughes</li>
             <li>David Humphrey</li>
             <li>Takeshi Ichimaru</li>
             <li>Chris Ilias</li>
-            <li>Eri Inoue </li>
+            <li>Eri Inoue</li>
             <li>Joichi Ito</li>
+            <li>Steven Johnson</li>
             <li>Laurent Jouanneau</li>
+            <li>Robert Kaiser</li>
             <li>Gen Kanai</li>
             <li>Masanori Kaneko</li>
             <li>Blake Kaplan</li>
+            <li>Mike Kaplinskiy</li>
             <li>Michael Kaply</li>
             <li>Mitch Kapor</li>
             <li>Kazuyoshi Kato</li>
+            <li>Tomomi Kato</li>
             <li>Alfred Kayser</li>
+            <li>Jonathan Kew</li>
             <li>Paul Kim</li>
             <li>Masatoshi Kimura</li>
+            <li>Austin King</li>
             <li>Ria Klaassen</li>
             <li>Marcia Knous</li>
             <li>Nelson Ko</li>
             <li>Michael Kohler</li>
             <li>Gary Kwong</li>
             <li>David Lanham</li>
+            <li>Brad Lassey</li>
+            <li>Delphine Lebédel</li>
             <li>Edward Lee</li>
+            <li>Neil Lee</li>
             <li>Raymond Lee</li>
             <li>Garrett LeSage</li>
             <li>Aaron Leventhal</li>
             <li>Anne-Julie Ligneau</li>
             <li>John Lilly</li>
             <li>Zach Lipton</li>
             <li>Kai Liu</li>
             <li>Reed Loden</li>
             <li>Lars Lohn</li>
             <li>Robert Longson</li>
             <li>Bob Lord</li>
             <li>Phil Machalski</li>
             <li>Joel Maher</li>
             <li>Ere Maijala</li>
+            <li>David Mandelin</li>
             <li>Gervase Markham</li>
             <li>Sean Martell</li>
             <li>Jim Mathies</li>
+            <li>Erica McClure</li>
             <li>Graeme McCutcheon</li>
+            <li>Patrick McManus</li>
             <li>Heather Meeker</li>
+            <li>Walter Meinl</li>
             <li>Myk Melez</li>
             <li>Federico Mena-Quintero</li>
             <li>Mark Mentovai</li>
+            <li>Laura Mesa</li>
             <li>Steven Michaud</li>
             <li>Matthew Middleton</li>
             <li>Ted Mielczarek</li>
             <li>Bernd Mielke</li>
             <li>Dave Miller</li>
             <li>Dan Mills</li>
             <li>Michael Monreal</li>
             <li>Simon Montagu</li>
+            <li>Derek Moore</li>
             <li>Mike Morgan</li>
+            <li>Tiffney Mortensen</li>
             <li>Dan Mosedale</li>
             <li>Michael Moy</li>
+            <li>Jeff Muizelaar</li>
             <li>Masayuki Nakano</li>
+            <li>Murali Nandigama</li>
             <li>Marria Nazif</li>
             <li>Kev Needham</li>
             <li>Kaori Negoro</li>
+            <li>Nicholas Nethercote</li>
+            <li>Ben Newman</li>
+            <li>Nick Nguyen</li>
             <li>Johnathan Nightingale</li>
+            <li>Timothy Nikkel</li>
             <li>Andreas Nilsson</li>
             <li>Tristan Nitot</li>
             <li>Alice Nodelman</li>
+            <li>Matthew Noorenberghe</li>
             <li>Michal Novotny</li>
             <li>Robert O'Callahan</li>
             <li>John O'Duinn</li>
             <li>Paul O'Shannessy</li>
             <li>Jan Odvárko</li>
             <li>Tomoyuki Okazaki</li>
+            <li>Les Orchard</li>
             <li>Jeremy Orem</li>
+            <li>Jason Orendorff</li>
             <li>Hideo Oshima</li>
             <li>Mats Palmgren</li>
             <li>Stuart Parmenter</li>
             <li>Jay Patel</li>
             <li>Chris Pearce</li>
             <li>Javier Pedemonte</li>
             <li>Alfred Peng</li>
             <li>Christian Persch</li>
             <li>Kalle Persson</li>
             <li>Ulisse Perusin</li>
             <li>Olli Pettay</li>
             <li>Julien Pierre</li>
+            <li>Anthony Piraino</li>
             <li>Alex Polvi</li>
             <li>Nickolay Ponomarev</li>
             <li>Dan Portillo</li>
             <li>Karen Prescott</li>
             <li>Florian Quèze</li>
+            <li>Krupa Raj</li>
+            <li>Arun Ranganathan</li>
             <li>Neil Rashbrook</li>
             <li>Bret Reckard</li>
             <li>J. Paul Reed</li>
+            <li>Rick Reitmaier</li>
             <li>Robert Relyea</li>
             <li>John Resig</li>
             <li>Deb Richardson</li>
             <li>Tim Riley</li>
             <li>Phil Ringnalda</li>
             <li>Julien Rivaud</li>
+            <li>Mikeal Rogers</li>
             <li>David Rolnitzky</li>
             <li>Asaf Romano</li>
+            <li>Oleg Romashin</li>
+            <li>Paul Rouget</li>
             <li>Tim Rowley</li>
             <li>Jesse Ruderman</li>
             <li>Brian Ryner</li>
             <li>Alexander Sack</li>
             <li>Hideo Saito</li>
+            <li>Atsushi Sakai</li>
             <li>Eiko Sakuma</li>
+            <li>Andrei Saprykin</li>
+            <li>Aki Sasaki</li>
             <li>Ken Saunders</li>
             <li>Robert Sayre</li>
             <li>Mike Schroepfer</li>
             <li>Kurt Schultz</li>
+            <li>Keith Schwarz</li>
             <li>Justin Scott</li>
             <li>Hiroshi Sekiya</li>
             <li>Tara Shahian</li>
             <li>Melissa Shapiro</li>
             <li>Gavin Sharp</li>
             <li>Mike Shaver</li>
             <li>Eric Shepherd</li>
             <li>Hiroshi Shimoda</li>
@@ -446,59 +513,72 @@
             <li>Jonas Sicking</li>
             <li>Damon Sicore</li>
             <li>Roger B. Sidje</li>
             <li>Samuel Sidler</li>
             <li>Henrik Skupin</li>
             <li>John Slater</li>
             <li>Benjamin Smedberg</li>
             <li>Andrew Smith</li>
+            <li>Edwin Smith</li>
             <li>Mark Smith</li>
             <li>Window Snyder</li>
             <li>Josh Soref</li>
             <li>Nochum Sossonko</li>
             <li>Ian Spence</li>
             <li>Seth Spitzer</li>
             <li>Markus Stange</li>
             <li>Jakub Steiner</li>
             <li>Johnny Stenback</li>
             <li>Brandon Sterne</li>
             <li>Rob Stradling</li>
             <li>Robert Strong</li>
+            <li>Jay Sullivan</li>
             <li>Vicky Sun</li>
+            <li>Alexander Surkov</li>
+            <li>Mark Surman</li>
+            <li>Andrew Sutherland</li>
             <li>Clint Talbert</li>
+            <li>Margaret Tallman</li>
             <li>David Tenser</li>
             <li>Chris Thomas</li>
             <li>Nick Thomas</li>
             <li>Laura Thomson</li>
             <li>Karl Tomlinson</li>
             <li>Dave Townsend</li>
+            <li>Aaron Train</li>
+            <li>Phong Tran</li>
             <li>Ben Turner</li>
             <li>Doug Turner</li>
+            <li>Amié Tyrrel</li>
             <li>Peter Van der Beken</li>
             <li>Peter van der Woude</li>
             <li>Teune van Steeg</li>
             <li>Ryan VanderMeulen</li>
             <li>Daniel Veditz</li>
             <li>Michael Ventnor</li>
             <li>Alexei Volkov</li>
             <li>Vladimir Vukićević</li>
             <li>Håkan Waara</li>
             <li>Jeff Walden</li>
             <li>Tracy Walker</li>
             <li>Cheng Wang</li>
             <li>Martijn Wargers</li>
             <li>Jonathan Watt</li>
             <li>Peter Weilbacher</li>
+            <li>Zack Weinberg</li>
             <li>Frédéric Wenzel</li>
             <li>Steffen Wilberg</li>
             <li>Drew Willcoxon</li>
             <li>Shawn Wilsher</li>
+            <li>Kathleen Wilson</li>
             <li>Dan Witte</li>
+            <li>John Wolfe</li>
             <li>Steve Won</li>
+            <li>Justin Wood</li>
             <li>Michael Wu</li>
             <li>Masahiro Yamada</li>
             <li>Satoko Takita Yamaguchi (Chibi)</li>
             <li>Christine Yen</li>
             <li>Kohei Yoshino</li>
             <li>Shigeru Yoshitake</li>
             <li>Boris Zbarsky</li>
             <li>Marco Zehe</li>
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -38,16 +38,18 @@
 #   Joe Hughes <joe@retrovirus.com>
 #   Pamela Greene <pamg.bugs@gmail.com>
 #   Michael Ventnor <ventnors_dogs234@yahoo.com.au>
 #   Simon Bünzli <zeniko@gmail.com>
 #   Gijs Kruitbosch <gijskruitbosch@gmail.com>
 #   Ehsan Akhgari <ehsan.akhgari@gmail.com>
 #   Dan Mosedale <dmose@mozilla.org>
 #   Justin Dolske <dolske@mozilla.com>
+#   Kathleen Brade <brade@pearlcrescent.com>
+#   Mark Smith <mcs@pearlcrescent.com>
 #
 # Alternatively, the contents of this file may be used under the terms of
 # either the GNU General Public License Version 2 or later (the "GPL"), or
 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 # in which case the provisions of the GPL or the LGPL are applicable instead
 # of those above. If you wish to allow use of your version of this file only
 # under the terms of either the GPL or the LGPL, and not to allow others to
 # use your version of this file under the terms of the MPL, indicate your
@@ -941,18 +943,21 @@ nsContextMenu.prototype = {
 
     // set up a channel to do the saving
     var ioService = Cc["@mozilla.org/network/io-service;1"].
                     getService(Ci.nsIIOService);
     var channel = ioService.newChannelFromURI(this.getLinkURI());
     channel.notificationCallbacks = new callbacks();
     channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE |
                          Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS;
-    if (channel instanceof Ci.nsIHttpChannel)
+    if (channel instanceof Ci.nsIHttpChannel) {
       channel.referrer = doc.documentURIObject;
+      if (channel instanceof Ci.nsIHttpChannelInternal)
+        channel.forceAllowThirdPartyCookie = true;
+    }
 
     // fallback to the old way if we don't see the headers quickly 
     var timeToWait = 
       gPrefService.getIntPref("browser.download.saveLinkAsFilenameTimeout");
     var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
     timer.initWithCallback(new timerCallback(), timeToWait,
                            timer.TYPE_ONE_SHOT);
 
@@ -1397,10 +1402,16 @@ nsContextMenu.prototype = {
         break;
     }
   },
 
   copyMediaLocation : function () {
     var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].
                     getService(Ci.nsIClipboardHelper);
     clipboard.copyString(this.mediaURL);
+  },
+
+  get imageURL() {
+    if (this.onImage)
+      return this.mediaURL;
+    return "";
   }
 };
--- a/browser/base/content/pageinfo/pageInfo.xul
+++ b/browser/base/content/pageinfo/pageInfo.xul
@@ -211,17 +211,17 @@
                   oncommand="onClickMore();"/>
         </hbox>
       </groupbox>
     </vbox>
 
     <!-- Media information -->
     <vbox id="mediaPanel">
       <tree id="imagetree" onselect="onImageSelect();" contextmenu="picontext"
-            ondraggesture="onBeginLinkDrag(event,'image-address','image-alt')">
+            ondragstart="onBeginLinkDrag(event,'image-address','image-alt')">
         <treecols>
           <treecol sortSeparators="true" persist="hidden width" flex="10"
                         width="10" id="image-address" label="&mediaAddress;"/>
           <splitter class="tree-splitter"/>
           <treecol sortSeparators="true" persist="hidden width" flex="2"
                         width="2"  id="image-type"    label="&mediaType;"/>
           <splitter class="tree-splitter"/>
           <treecol sortSeparators="true" hidden="true" persist="hidden width" flex="2"
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -243,17 +243,17 @@
           ]]>
         </body>
       </method>
 
       <method name="getBrowserIndexForDocument">
         <parameter name="aDocument"/>
         <body>
           <![CDATA[
-	    var browsers = this.browsers;
+            var browsers = this.browsers;
             for (var i = 0; i < browsers.length; i++)
               if (browsers[i].contentDocument == aDocument)
                 return i;
             return -1;
           ]]>
         </body>
       </method>
 
@@ -309,39 +309,39 @@
                                          aCurTotalProgress, aMaxTotalProgress)
             {
               this.mTotalProgress = aMaxTotalProgress ? aCurTotalProgress / aMaxTotalProgress : 0;
 
               if (this.mBlank)
                 return;
 
               if (this.mTabBrowser.mCurrentTab == this.mTab) {
-                for (var i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
-                  var p = this.mTabBrowser.mProgressListeners[i];
+                for (let i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
+                  let p = this.mTabBrowser.mProgressListeners[i];
                   if (p)
                     try {
                       p.onProgressChange(aWebProgress, aRequest,
                                          aCurSelfProgress, aMaxSelfProgress,
                                          aCurTotalProgress, aMaxTotalProgress);
                     } catch (e) {
-                      // don't inhibit other listeners or following code
+                      // don't inhibit other listeners
                       Components.utils.reportError(e);
                     }
                 }
               }
 
-              for (var i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
-                var p = this.mTabBrowser.mTabsProgressListeners[i];
+              for (let i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
+                let p = this.mTabBrowser.mTabsProgressListeners[i];
                 if (p)
                   try {
                     p.onProgressChange(this.mBrowser, aWebProgress, aRequest,
                                        aCurSelfProgress, aMaxSelfProgress,
                                        aCurTotalProgress, aMaxTotalProgress);
                   } catch (e) {
-                    // don't inhibit other listeners or following code
+                    // don't inhibit other listeners
                     Components.utils.reportError(e);
                   }
               }
             },
 
             onProgressChange64 : function (aWebProgress, aRequest,
                                          aCurSelfProgress, aMaxSelfProgress,
                                          aCurTotalProgress, aMaxTotalProgress)
@@ -427,39 +427,39 @@
                 if (this.mTab.label == this.mTabBrowser.mStringBundle.getString("tabs.loading"))
                   this.mTabBrowser.setTabTitle(this.mTab);
 
                 if (this.mTabBrowser.mCurrentTab == this.mTab)
                   this.mTabBrowser.mIsBusy = false;
               }
 
               if (this.mTabBrowser.mCurrentTab == this.mTab) {
-                for (var i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
-                  var p = this.mTabBrowser.mProgressListeners[i];
+                for (let i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
+                  let p = this.mTabBrowser.mProgressListeners[i];
                   if (p)
                     try {
                       if (!oldBlank)
                         p.onStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
                       // make sure that the visible status of new blank tabs is correctly set
                       else if ("onUpdateCurrentBrowser" in p)
                         p.onUpdateCurrentBrowser(aStateFlags, aStatus, "", 0);
                     } catch (e) {
-                      // don't inhibit other listeners or following code
+                      // don't inhibit other listeners
                       Components.utils.reportError(e);
                     }
                 }
               }
 
-              for (var i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
-                var p = this.mTabBrowser.mTabsProgressListeners[i];
+              for (let i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
+                let p = this.mTabBrowser.mTabsProgressListeners[i];
                 if (p)
                   try {
                     p.onStateChange(this.mBrowser, aWebProgress, aRequest, aStateFlags, aStatus);
                   } catch (e) {
-                    // don't inhibit other listeners or following code
+                    // don't inhibit other listeners
                     Components.utils.reportError(e);
                   }
               }
 
               if (aStateFlags & (nsIWebProgressListener.STATE_START |
                                  nsIWebProgressListener.STATE_STOP)) {
                 // reset cached temporary values at beginning and end
                 this.mMessage = "";
@@ -481,125 +481,125 @@
 
               // changing location, clear out the missing plugins list
               this.mBrowser.missingPlugins = null;
 
               if (this.mBlank)
                 return;
 
               if (this.mTabBrowser.mCurrentTab == this.mTab) {
-                for (var i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
-                  var p = this.mTabBrowser.mProgressListeners[i];
+                for (let i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
+                  let p = this.mTabBrowser.mProgressListeners[i];
                   if (p)
                     try {
                       p.onLocationChange(aWebProgress, aRequest, aLocation);
                     } catch (e) {
                       // don't inhibit other listeners
                       Components.utils.reportError(e);
                     }
                 }
               }
 
-              for (var i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
-                var p = this.mTabBrowser.mTabsProgressListeners[i];
+              for (let i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
+                let p = this.mTabBrowser.mTabsProgressListeners[i];
                 if (p)
                   try {
                     p.onLocationChange(this.mBrowser, aWebProgress, aRequest, aLocation);
                   } catch (e) {
                     // don't inhibit other listeners
                     Components.utils.reportError(e);
                   }
               }
             },
 
             onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage)
             {
               if (this.mBlank)
                 return;
 
               if (this.mTabBrowser.mCurrentTab == this.mTab) {
-                for (var i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
-                  var p = this.mTabBrowser.mProgressListeners[i];
+                for (let i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
+                  let p = this.mTabBrowser.mProgressListeners[i];
                   if (p)
                     try {
                       p.onStatusChange(aWebProgress, aRequest, aStatus, aMessage);
                     } catch (e) {
-                      // don't inhibit other listeners or following code
+                      // don't inhibit other listeners
                       Components.utils.reportError(e);
                     }
                 }
               }
 
-              for (var i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
-                var p = this.mTabBrowser.mTabsProgressListeners[i];
+              for (let i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
+                let p = this.mTabBrowser.mTabsProgressListeners[i];
                 if (p)
                   try {
                     p.onStatusChange(this.mBrowser, aWebProgress, aRequest, aStatus, aMessage);
                   } catch (e) {
-                    // don't inhibit other listeners or following code
+                    // don't inhibit other listeners
                     Components.utils.reportError(e);
                   }
               }
 
               this.mMessage = aMessage;
             },
 
             onSecurityChange : function(aWebProgress, aRequest, aState)
             {
               if (this.mTabBrowser.mCurrentTab == this.mTab) {
-                for (var i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
-                  var p = this.mTabBrowser.mProgressListeners[i];
+                for (let i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
+                  let p = this.mTabBrowser.mProgressListeners[i];
                   if (p)
                     try {
                       p.onSecurityChange(aWebProgress, aRequest, aState);
                     } catch (e) {
                       // don't inhibit other listeners
                       Components.utils.reportError(e);
                     }
                 }
               }
 
-              for (var i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
-                var p = this.mTabBrowser.mTabsProgressListeners[i];
+              for (let i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
+                let p = this.mTabBrowser.mTabsProgressListeners[i];
                 if (p)
                   try {
                     p.onSecurityChange(this.mBrowser, aWebProgress, aRequest, aState);
                   } catch (e) {
                     // don't inhibit other listeners
                     Components.utils.reportError(e);
                   }
               }
             },
 
             onRefreshAttempted : function(aWebProgress, aURI, aDelay, aSameURI)
             {
               var allowRefresh = true;
               if (this.mTabBrowser.mCurrentTab == this.mTab) {
-                for (var i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
-                  var p = this.mTabBrowser.mProgressListeners[i];
+                for (let i = 0; i < this.mTabBrowser.mProgressListeners.length; i++) {
+                  let p = this.mTabBrowser.mProgressListeners[i];
                   if (p && "onRefreshAttempted" in p) {
                     try {
                       if (!p.onRefreshAttempted(aWebProgress, aURI, aDelay, aSameURI))
                         allowRefresh = false;
                      } catch (e) {
-                       // don't inhibit other listeners or following code
+                       // don't inhibit other listeners
                        Components.utils.reportError(e);
                      }
                   }
                 }
               }
 
-              for (var i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
-                var p = this.mTabBrowser.mTabsProgressListeners[i];
+              for (let i = 0; i < this.mTabBrowser.mTabsProgressListeners.length; i++) {
+                let p = this.mTabBrowser.mTabsProgressListeners[i];
                 if (p && "onRefreshAttempted" in p) {
                   try {
                     if (!p.onRefreshAttempted(this.mBrowser, aWebProgress, aURI, aDelay, aSameURI))
                       allowRefresh = false;
                    } catch (e) {
-                     // don't inhibit other listeners or following code
+                     // don't inhibit other listeners
                      Components.utils.reportError(e);
                    }
                 }
               }
               return allowRefresh;
             },
 
             QueryInterface : function(aIID)
@@ -633,30 +633,30 @@
               if (this.mFaviconService)
                 this.mFaviconService.setAndLoadFaviconForPage(browser.currentURI,
                                                               aURI, false);
             }
 
             this.updateIcon(aTab);
 
             if (browser == this.mCurrentBrowser) {
-              for (var i = 0; i < this.mProgressListeners.length; i++) {
-                var p = this.mProgressListeners[i];
+              for (let i = 0; i < this.mProgressListeners.length; i++) {
+                let p = this.mProgressListeners[i];
                 if ('onLinkIconAvailable' in p)
                   try {
                     p.onLinkIconAvailable(browser);
                   } catch (e) {
                     // don't inhibit other listeners
                     Components.utils.reportError(e);
                   }
               }
             }
 
-            for (var i = 0; i < this.mTabsProgressListeners.length; i++) {
-              var p = this.mTabsProgressListeners[i];
+            for (let i = 0; i < this.mTabsProgressListeners.length; i++) {
+              let p = this.mTabsProgressListeners[i];
               if ('onLinkIconAvailable' in p)
                 try {
                   p.onLinkIconAvailable(browser);
                 } catch (e) {
                   // don't inhibit other listeners
                   Components.utils.reportError(e);
                 }
             }
@@ -808,72 +808,28 @@
           <![CDATA[
             var newBrowser = this.getBrowserAtIndex(this.mTabContainer.selectedIndex);
             if (this.mCurrentBrowser == newBrowser && !aForceUpdate)
               return;
 
             if (this.mCurrentTab != this.selectedTab)
               this.mCurrentTab.owner = null;
 
-            if (this.mCurrentBrowser) {
-              // Only save the focused element if it is in our content window
-              // or in an ancestor window.
-              var focusedWindow = document.commandDispatcher.focusedWindow;
-              var saveFocus = false;
-
-              if (focusedWindow && focusedWindow.top == window.content) {
-                saveFocus = true;
-              } else {
-                var contentWindow = window;
-
-                while (contentWindow) {
-                  if (contentWindow == focusedWindow) {
-                    saveFocus = true;
-                    break;
-                  }
-
-                  if (contentWindow.parent == contentWindow) {
-                    break;
-                  }
-
-                  contentWindow = contentWindow.parent;
-                }
-              }
-
-              if (saveFocus) {
-                // Preserve the currently-focused element or DOM window for
-                // this tab.
-
-                this.mCurrentBrowser.focusedWindow = focusedWindow;
-                this.mCurrentBrowser.focusedElement = document.commandDispatcher.focusedElement;
-              }
-
-              if (this.mCurrentBrowser.focusedElement &&
-                  this.mCurrentBrowser.focusedElement.parentNode !=
-                  this.mCurrentTab.parentNode) {
-                // Clear focus outline before we draw on top of it.
-                // Only blur the focused element if it isn't a tab, 
-                // to avoid breaking keyboard tab navigation
-                var elem = this.mCurrentBrowser.focusedElement;
-                if (elem instanceof HTMLElement || elem instanceof XULElement) {
-                  elem.blur();
-                }
-                else {
-                  var content = elem.ownerDocument.defaultView;
-                  if (content instanceof Components.interfaces.nsIInterfaceRequestor)
-                    content.getInterface(Components.interfaces.nsIDOMWindowUtils).focus(null);
-                }
-              }
-              this.mCurrentBrowser.setAttribute("type", "content-targetable");
-            }
+            var fm = Components.classes["@mozilla.org/focus-manager;1"].
+                       getService(Components.interfaces.nsIFocusManager);
+            var focusedChromeElement = fm.getFocusedElementForWindow(window, false, {});
+
+            var oldBrowser = this.mCurrentBrowser;
+            if (oldBrowser)
+              oldBrowser.setAttribute("type", "content-targetable");
 
             var updatePageReport = false;
-            if (!this.mCurrentBrowser ||
-                (this.mCurrentBrowser.pageReport && !newBrowser.pageReport) ||
-                (!this.mCurrentBrowser.pageReport && newBrowser.pageReport))
+            if (!oldBrowser ||
+                (oldBrowser.pageReport && !newBrowser.pageReport) ||
+                (!oldBrowser.pageReport && newBrowser.pageReport))
               updatePageReport = true;
 
             newBrowser.setAttribute("type", "content-primary");
             this.mCurrentBrowser = newBrowser;
             this.mCurrentTab = this.selectedTab;
 
             if (updatePageReport)
               this.mCurrentBrowser.updatePageReport();
@@ -946,74 +902,23 @@
               }
             }
 
             // We've selected the new tab, so go ahead and notify listeners.
             var event = document.createEvent("Events");
             event.initEvent("TabSelect", true, false);
             this.mCurrentTab.dispatchEvent(event);
 
-            if (document.commandDispatcher.focusedElement &&
-                document.commandDispatcher.focusedElement.parentNode ==
-                this.mCurrentTab.parentNode) {
-              // The focus is on a tab in the same tab panel
-              return;  // If focus was on a tab, switching tabs focuses the new tab
-            }
-
-            var whatToFocus = window.content;
-
-            // Focus the previously focused element or window, but make sure
-            // the focused element is still part of the document
-            let focusedElem = newBrowser.focusedElement;
-            if (focusedElem && focusedElem.ownerDocument &&
-                !(focusedElem.ownerDocument.compareDocumentPosition(focusedElem) &
-                  Node.DOCUMENT_POSITION_DISCONNECTED)) {
-              if (newBrowser.focusedElement.parentNode !=
-                  this.mCurrentTab.parentNode) {
-                // Focus the remembered element unless it's in the current tab panel
-                whatToFocus = newBrowser.focusedElement;
-              }
-            }
-            else if (newBrowser.focusedWindow) {
-              whatToFocus = newBrowser.focusedWindow;
-            }
- 
-            // Change focus for this window to |whatToFocus|, without
-            // focusing the window itself.
-            var cmdDispatcher = document.commandDispatcher;
-
-            var ww =
-              Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
-                        .getService(Components.interfaces.nsIWindowWatcher);
-            if (ww.activeWindow == window) {
-              cmdDispatcher.suppressFocusScroll = true;
-              if (whatToFocus instanceof HTMLElement ||
-                  whatToFocus instanceof XULElement ||
-                  whatToFocus instanceof Window) {
-                whatToFocus.focus();
-              }
-              else if (whatToFocus instanceof Node) {
-                var content = window.content;
-                if (content instanceof Components.interfaces.nsIInterfaceRequestor)
-                  content.getInterface(Components.interfaces.nsIDOMWindowUtils).focus(whatToFocus);
-              }
-              cmdDispatcher.suppressFocusScroll = false;
-            }
-            else {
-              // set the element in command dispatcher so focus will restore
-              // properly when the window does become active
-              if (whatToFocus instanceof Window) {
-                cmdDispatcher.focusedWindow = whatToFocus;
-                cmdDispatcher.focusedElement = null;
-              }
-              else {
-                cmdDispatcher.focusedWindow = whatToFocus.ownerDocument.defaultView;
-                cmdDispatcher.focusedElement = whatToFocus;
-              }
-            }
+            // change focus to the new tab if nothing is focused, the old tab
+            // is focused or there is something in the new tab to focus. One
+            // specific case where focus is not changed is when the new tab
+            // has no focused element and a chrome element is focused.
+            if (!focusedChromeElement || focusedChromeElement == oldBrowser ||
+                fm.getFocusedElementForWindow(window.content, true, {}))
+              fm.setFocus(newBrowser, fm.FLAG_NOSCROLL);
           ]]>
         </body>
       </method>
 
       <method name="onTabClick">
         <parameter name="event"/>
         <body>
           <![CDATA[
@@ -1622,19 +1527,17 @@
 
             // Because of the way XBL works (fields just set JS
             // properties on the element) and the code we have in place
             // to preserve the JS objects for any elements that have
             // JS properties set on them, the browser element won't be
             // destroyed until the document goes away.  So we force a
             // cleanup ourselves.
             // This has to happen before we remove the child so that the
-            // XBL implementation of nsIObserver still works.  But
-            // clearing focusedWindow happens below because it gets
-            // reset by updateCurrentBrowser.
+            // XBL implementation of nsIObserver still works.
             browser.destroy();
 
             if (browser == this.mCurrentBrowser)
               this.mCurrentBrowser = null;
 
             // Invalidate browsers cache, as the tab is removed from the
             // tab container.
             this._browsers = null;
@@ -1657,20 +1560,16 @@
             this.mPanelContainer.removeChild(browser.parentNode);
 
             // As the panel is removed, the removal of a dependent document can
             // cause the whole window to close. So at this point, it's possible
             // that the binding is destructed.
             if (this.mTabBox)
               this.mTabBox.selectedPanel = this.getBrowserForTab(this.mCurrentTab).parentNode;
 
-            // see comment about destroy above
-            browser.focusedWindow = null;
-            browser.focusedElement = null;
-
             if (aCloseWindow)
               this._windowIsClosing = closeWindow(true);
           ]]>
         </body>
       </method>
 
       <method name="_blurTab">
         <parameter name="aTab"/>
@@ -2992,24 +2891,18 @@
                              command="cmd_newNavigatorTab" chromedir="&locale.dir;"
                              tooltiptext="&newTabButton.tooltip;"/>
           <xul:stack align="center" pack="end" chromedir="&locale.dir;">
             <xul:hbox flex="1" class="tabs-alltabs-box-animate" anonid="alltabs-box-animate"/>
             <xul:toolbarbutton class="tabs-alltabs-button" anonid="alltabs-button"
                                tooltiptext="&listAllTabs.label;"
                                oncommand="ctrlTab.open(true);"/>
           </xul:stack>
-#ifdef XP_MACOSX
-          <xul:hbox anonid="tabstrip-closebutton" class="tabs-closebutton-box" align="center" pack="end" chromedir="&locale.dir;">
-#endif
           <xul:toolbarbutton anonid="tabs-closebutton"
                              class="close-button tabs-closebutton" chromedir="&locale.dir;"/>
-#ifdef XP_MACOSX
-          </xul:hbox>
-#endif
         </xul:hbox>
       </xul:stack>
     </content>
     <implementation implements="nsITimerCallback, nsIDOMEventListener">
       <constructor>
         <![CDATA[
           var pb2 =
               Components.classes['@mozilla.org/preferences-service;1'].
@@ -3060,21 +2953,17 @@
 
       <field name="mTabstripWidth">0</field>
 
       <field name="mTabstrip">
         document.getAnonymousElementByAttribute(this, "anonid", "arrowscrollbox");
       </field>
 
       <field name="mTabstripClosebutton">
-#ifdef XP_MACOSX
-        document.getAnonymousElementByAttribute(this, "anonid", "tabstrip-closebutton");
-#else
         document.getAnonymousElementByAttribute(this, "anonid", "tabs-closebutton");
-#endif
       </field>
 
       <field name="_prefObserver">({
         tabbox: this,
   
         observe: function(subject, topic, data)
         {
           if (topic == "nsPref:changed") {
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -52,16 +52,19 @@ include $(topsrcdir)/config/rules.mk
 		ctxmenu-image.png \
 		test_offlineNotification.html \
 		offlineChild.html \
 		offlineChild.cacheManifest \
 		offlineChild.cacheManifest^headers^ \
 		offlineChild2.html \
 		offlineChild2.cacheManifest \
 		offlineChild2.cacheManifest^headers^ \
+		offlineEvent.html \
+		offlineEvent.cacheManifest \
+		offlineEvent.cacheManifest^headers^ \
 		$(NULL)
 
 # The following tests are disabled because they are unreliable:
 #   browser_bug321000.js is bug 474081
 #   browser_bug423833.js is bug 428712
 #   browser_sanitize-download-history.js is bug 432425
 #
 # browser_sanitizeDialog_treeView.js is disabled until the tree view is added
@@ -77,17 +80,19 @@ include $(topsrcdir)/config/rules.mk
                  browser_bug424101.js \
                  browser_bug427559.js \
                  browser_bug432599.js \
                  browser_bug441778.js \
                  browser_bug455852.js \
                  browser_bug462673.js \
                  browser_bug481560.js \
                  browser_bug477014.js \
+                 browser_bug495058.js \
                  browser_discovery.js \
+                 browser_tabfocus.js \
                  discovery.html \
                  moz.png \
                  test_bug462673.html \
                  browser_getshortcutoruri.js \
                  browser_page_style_menu.js \
                  page_style_sample.html \
                  browser_ctrlTab.js \
                  browser_selectTabAtIndex.js \
@@ -112,16 +117,17 @@ include $(topsrcdir)/config/rules.mk
                  browser_bug479408.js \
                  browser_bug479408_sample.html \
                  browser_scope.js \
                  browser_overflowScroll.js \
                  browser_sanitizeDialog.js \
                  browser_tabs_owner.js \
                  browser_bug491431.js \
                  browser_bug304198.js \
+                 browser_drag.js \
     $(NULL)
 
 ifeq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
 _BROWSER_FILES += browser_bug462289.js
 else
 _BROWSER_FILES += browser_customize.js
 endif
 
--- a/browser/base/content/test/browser_bug481560.js
+++ b/browser/base/content/test/browser_bug481560.js
@@ -1,19 +1,30 @@
 function test() {
   waitForExplicitFinish();
 
+  // focus the url field so that it will can ensure the focus is there when
+  // the window is refocused after the dialog closes
+  gURLBar.focus();
+
+  window.addEventListener("focus", function () {
+    window.removeEventListener("focus", arguments.callee, false);
+    finish();
+  }, false);
+
   var win = openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no");
 
   win.addEventListener("load", function () {
     win.removeEventListener("load", arguments.callee, false);
 
+    win.content.addEventListener("focus", function () {
+      win.content.removeEventListener("focus", arguments.callee, false);
+
+      EventUtils.synthesizeKey("w", { accelKey: true }, win);
+      ok(win.closed, "accel+w closed the window immediately");
+    }, false);
+
     win.gBrowser.selectedTab.addEventListener("TabClose", function () {
       ok(false, "shouldn't have gotten the TabClose event for the last tab");
     }, false);
 
-    EventUtils.synthesizeKey("w", { accelKey: true }, win);
-
-    ok(win.closed, "accel+w closed the window immediately");
-
-    finish();
   }, false);
 }
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_bug495058.js
@@ -0,0 +1,52 @@
+function test() {
+  waitForExplicitFinish();
+  next();
+}
+
+var uris = [
+  "about:blank",
+  "about:sessionrestore",
+  "about:privatebrowsing",
+];
+
+function next() {
+  var tab = gBrowser.addTab();
+  var uri = uris.shift();
+
+  if (uri == "about:blank") {
+    detach();
+  } else {
+    let browser = tab.linkedBrowser;
+    browser.addEventListener("load", function () {
+      browser.removeEventListener("load", arguments.callee, true);
+      detach();
+    }, true);
+    browser.loadURI(uri);
+  }
+
+  function detach() {
+    var win = gBrowser.replaceTabWithWindow(tab);
+    win.addEventListener("load", function () {
+      win.removeEventListener("load", arguments.callee, false);
+
+      win.gBrowser.addEventListener("pageshow", function() {
+        win.gBrowser.removeEventListener("pageshow", arguments.callee, false);
+
+        // wait for delayedStartup
+        win.setTimeout(function () {
+          is(win.gBrowser.currentURI.spec, uri, uri + ": uri loaded in detached tab");
+          is(win.document.activeElement, win.gBrowser.selectedBrowser, uri + ": browser is focused");
+          is(win.gURLBar.value, "", uri + ": urlbar is empty");
+          ok(win.gURLBar.emptyText, uri + ": emptytext is present");
+          ok(win.gURLBar.hasAttribute("isempty"), uri + ": emptytext is displayed");
+
+          win.close();
+          if (uris.length)
+            next();
+          else
+            executeSoon(finish);
+        }, 100);
+      }, false);
+    }, false);
+  }
+}
--- a/browser/base/content/test/browser_ctrlTab.js
+++ b/browser/base/content/test/browser_ctrlTab.js
@@ -62,17 +62,17 @@ function test() {
     let eventConsumed = true;
     let detectKeyEvent = function (event) {
       eventConsumed = event.getPreventDefault();
     };
     document.addEventListener("keypress", detectKeyEvent, false);
     pressCtrlTab();
     document.removeEventListener("keypress", detectKeyEvent, false);
     ok(eventConsumed, "Ctrl+Tab consumed by the tabbed browser if one tab is open");
-    is(focusedWindow.location, document.commandDispatcher.focusedWindow.location,
+    is(focusedWindow, document.commandDispatcher.focusedWindow,
        "Ctrl+Tab doesn't change focus if one tab is open");
   }
 
   gBrowser.addTab();
   gBrowser.addTab();
   gBrowser.addTab();
 
   assertTabs(4);
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_drag.js
@@ -0,0 +1,23 @@
+function test()
+{
+  // ---- Test dragging the proxy icon ---
+
+  var value = content.location.href;
+  var urlString = value + "\n" + content.document.title;
+  var htmlString = "<a href=\"" + value + "\">" + value + "</a>";
+
+  var expected = [ [
+    "text/x-moz-url: " + urlString,
+    "text/uri-list: " + value,
+    "text/plain: " + value,
+    "text/html: " + htmlString
+  ] ];
+
+  // set the valid attribute so dropping is allowed
+  var proxyicon = document.getElementById("page-proxy-favicon")
+  var oldstate = proxyicon.getAttribute("pageproxystate");
+  proxyicon.setAttribute("pageproxystate", "valid");
+  var dt = EventUtils.synthesizeDragStart(proxyicon, expected);
+  is(dt, null, "drag on proxy icon");
+  proxyicon.setAttribute("pageproxystate", oldstate);
+}
--- a/browser/base/content/test/browser_sanitizeDialog.js
+++ b/browser/base/content/test/browser_sanitizeDialog.js
@@ -277,29 +277,31 @@ var gAllTests = [
                 "timeSpan pref should be everything after accepting dialog " +
                 "with everything selected");
       ensureHistoryClearedState(uris, true);
     };
     wh.open();
   },
 
   /**
-   * Ensures that toggling details persists across dialog openings.
+   * These next two tests together ensure that toggling details persists
+   * across dialog openings.
    */
   function () {
     let wh = new WindowHelper();
-
     wh.onload = function () {
       // Show details
       this.toggleDetails();
       this.checkDetails(true);
       this.cancelDialog();
     };
     wh.open();
-
+  },
+  function () {
+    let wh = new WindowHelper();
     wh.onload = function () {
       // Details should have remained open
       this.checkDetails(true);
       
       // Hide details
       this.toggleDetails();
       this.checkDetails(false);
       this.cancelDialog();
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_tabfocus.js
@@ -0,0 +1,216 @@
+/*
+ * This test checks that focus is adjusted properly when switching tabs.
+ */
+
+let testPage1 = "data:text/html,<html id='tab1'><body><button id='button1'>Tab 1</button></body></html>";
+let testPage2 = "data:text/html,<html id='tab2'><body><button id='button2'>Tab 2</button></body></html>";
+
+function test() {
+  waitForExplicitFinish();
+
+  var tab1 = gBrowser.addTab();
+  var tab2 = gBrowser.addTab();
+  var browser1 = gBrowser.getBrowserForTab(tab1);
+  var browser2 = gBrowser.getBrowserForTab(tab2);
+
+  gURLBar.focus();
+
+  var loadCount = 0;
+  function check()
+  {
+    // wait for both tabs to load
+    if (++loadCount != 2)
+      return;
+
+    window.focus();
+
+    _browser_tabfocus_test_lastfocus = gURLBar;
+    _browser_tabfocus_test_lastfocuswindow = window;
+
+    window.addEventListener("focus", _browser_tabfocus_test_eventOccured, true);
+    window.addEventListener("blur", _browser_tabfocus_test_eventOccured, true);
+
+    gBrowser.selectedTab = tab2;
+
+    var fm = Components.classes["@mozilla.org/focus-manager;1"].
+               getService(Components.interfaces.nsIFocusManager);
+    is(fm.focusedWindow, window, "focusedWindow after tab load");
+    is(fm.focusedElement, gURLBar.inputField, "focusedElement after tab load");
+
+    // make sure that the focus initially starts out blank
+    var focusedWindow = {};
+    is(fm.getFocusedElementForWindow(browser1.contentWindow, false, focusedWindow), null, "initial focus in tab 1");
+    is(focusedWindow.value, browser1.contentWindow, "initial frame focus in tab 1");
+    is(fm.getFocusedElementForWindow(browser2.contentWindow, false, focusedWindow), null, "initial focus in tab 2");
+    is(focusedWindow.value, browser2.contentWindow, "initial frame focus in tab 2");
+
+    // switching tabs when the urlbar is focused and nothing in the new tab is focused
+    // should keep focus in the urlbar
+    expectFocusShift(function () gBrowser.selectedTab = tab1,
+                     window, gURLBar.inputField, false,
+                     "focusedElement after tab change, focus in url field, no focus in new tab");
+
+    // focusing a button in the current tab should focus it
+    var button1 = browser1.contentWindow.document.getElementById("button1");
+    expectFocusShift(function () button1.focus(),
+                     browser1.contentWindow, button1, true,
+                     "focusedWindow after focus in focused tab");
+
+    // focusing a button in a background tab should not change the actual
+    // focus, but should set the focus that would be in that background tab to
+    // that button.
+    var button2 = browser2.contentWindow.document.getElementById("button2");
+    button2.focus();
+
+    expectFocusShift(function () button2.focus(),
+                     browser1.contentWindow, button1, false,
+                     "focusedWindow after focus in unfocused tab");
+    is(fm.getFocusedElementForWindow(browser2.contentWindow, false, {}), button2, "focus in unfocused tab");
+
+    // switching tabs should now make the button in the other tab focused
+    expectFocusShift(function () gBrowser.selectedTab = tab2,
+                     browser2.contentWindow, button2, true,
+                     "focusedWindow after tab change");
+
+    // blurring an element in a background tab should not change the active
+    // focus, but should clear the focus in that tab.
+    expectFocusShift(function () button1.blur(),
+                     browser2.contentWindow, button2, false,
+                     "focusedWindow after blur in unfocused tab");
+    is(fm.getFocusedElementForWindow(browser1.contentWindow, false, {}), null, "blur in unfocused tab");
+
+    // focusing the url field should switch active focus away from the tab but
+    // not clear what would be the focus in the tab 
+    button1.focus();
+    expectFocusShift(function () gURLBar.focus(),
+                     window, gURLBar.inputField, true,
+                     "focusedWindow after url field focused");
+    is(fm.getFocusedElementForWindow(browser2.contentWindow, false, {}), button2, "url field focused, button in tab");
+
+    // when a chrome element is focused, switching tabs to a tab with a button
+    // with the current focus should focus the button
+    expectFocusShift(function () gBrowser.selectedTab = tab1,
+                     browser1.contentWindow, button1, true,
+                     "focusedWindow after tab change, focus in url field, button focused in new tab");
+    is(fm.getFocusedElementForWindow(browser2.contentWindow, false, {}), button2, "after switch tab, focus in unfocused tab");
+
+    // blurring an element in the current tab should clear the active focus
+    expectFocusShift(function () button1.blur(),
+                     browser1.contentWindow, null, true,
+                     "focusedWindow after blur in focused tab");
+
+    // blurring an non-focused url field should have no effect
+    expectFocusShift(function () gURLBar.blur(),
+                     browser1.contentWindow, null, false,
+                     "focusedWindow after blur in unfocused url field");
+
+    // switch focus to a tab with a currently focused element
+    expectFocusShift(function () gBrowser.selectedTab = tab2,
+                     browser2.contentWindow, button2, true,
+                     "focusedWindow after switch from unfocused to focused tab");
+
+    // clearing focus on the chrome window should switch the focus to the
+    // chrome window
+    expectFocusShift(function () fm.clearFocus(window),
+                     window, null, true,
+                     "focusedWindow after switch to chrome with no focused element");
+
+    // switch focus to another tab when neither have an active focus
+    expectFocusShift(function () gBrowser.selectedTab = tab1,
+                     browser1.contentWindow, null, true,
+                     "focusedWindow after tab switch from no focus to no focus");
+    
+    gBrowser.removeCurrentTab();
+    gBrowser.removeCurrentTab();
+    finish();
+  }
+
+  browser1.addEventListener("load", check, true);
+  browser2.addEventListener("load", check, true);
+  browser1.contentWindow.location = testPage1;
+  browser2.contentWindow.location = testPage2;
+}
+
+var _browser_tabfocus_test_lastfocus;
+var _browser_tabfocus_test_lastfocuswindow = null;
+var _browser_tabfocus_test_events = "";
+
+function _browser_tabfocus_test_eventOccured(event)
+{
+  var id;
+  if (event.target instanceof Window)
+    id = event.originalTarget.document.documentElement.id + "-window";
+  else if (event.target instanceof Document)
+    id = event.originalTarget.documentElement.id + "-document";
+  else if (event.target.id == "urlbar" && event.originalTarget.localName == "input")
+    id = "urlbar";
+  else
+    id = event.originalTarget.id;
+
+  if (_browser_tabfocus_test_events)
+    _browser_tabfocus_test_events += " ";
+  _browser_tabfocus_test_events += event.type + ": " + id;
+}
+
+function getId(element)
+{
+  return (element.localName == "input") ? "urlbar" : element.id;
+}
+
+function expectFocusShift(callback, expectedWindow, expectedElement, focusChanged, testid)
+{
+  var expectedEvents = "";
+  if (focusChanged) {
+    if (_browser_tabfocus_test_lastfocus)
+      expectedEvents += "blur: " + getId(_browser_tabfocus_test_lastfocus);
+
+    if (_browser_tabfocus_test_lastfocuswindow &&
+        _browser_tabfocus_test_lastfocuswindow != expectedWindow) {
+      if (expectedEvents)
+        expectedEvents += " ";
+      var windowid = _browser_tabfocus_test_lastfocuswindow.document.documentElement.id;
+      expectedEvents += "blur: " + windowid + "-document " +
+                        "blur: " + windowid + "-window";
+    }
+
+    if (expectedWindow && _browser_tabfocus_test_lastfocuswindow != expectedWindow) {
+      if (expectedEvents)
+        expectedEvents += " ";
+      var windowid = expectedWindow.document.documentElement.id;
+      expectedEvents += "focus: " + windowid + "-document " +
+                        "focus: " + windowid + "-window";
+    }
+
+    if (expectedElement) {
+      if (expectedEvents)
+        expectedEvents += " ";
+      expectedEvents += "focus: " + getId(expectedElement);
+    }
+
+    _browser_tabfocus_test_lastfocus = expectedElement;
+    _browser_tabfocus_test_lastfocuswindow = expectedWindow;
+  }
+
+  callback();
+
+  is(_browser_tabfocus_test_events, expectedEvents, testid + " events");
+  _browser_tabfocus_test_events = "";
+
+  var fm = Components.classes["@mozilla.org/focus-manager;1"].
+             getService(Components.interfaces.nsIFocusManager);
+
+  var focusedElement = fm.focusedElement;
+  is(focusedElement ? getId(focusedElement) : "none",
+     expectedElement ? getId(expectedElement) : "none", testid + " focusedElement");
+  is(fm.focusedWindow, expectedWindow, testid + " focusedWindow");
+  var focusedWindow = {};
+  is(fm.getFocusedElementForWindow(expectedWindow, false, focusedWindow),
+     expectedElement, testid + " getFocusedElementForWindow");
+  is(focusedWindow.value, expectedWindow, testid + " getFocusedElementForWindow frame");
+  is(expectedWindow.document.hasFocus(), true, testid + " hasFocus");
+  var expectedActive = expectedElement;
+  if (!expectedActive)
+    expectedActive = expectedWindow.document instanceof XULDocument ?
+                     expectedWindow.document.documentElement : expectedWindow.document.body;
+  is(expectedWindow.document.activeElement, expectedActive, testid + " activeElement");
+}
new file mode 100644
--- /dev/null
+++ b/browser/