m-c to e10 merge
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Mon, 24 May 2010 17:45:59 +0300
changeset 46875 983e2271acc37e914e2d62f05f7510067fb6222c
parent 46874 5c29542bba4ea36ca88ca4c0fa3f7bbb0d0adf80 (current diff)
parent 42578 f4f9d45743a8b9a5ccf0d2cfe7d34a6df7af3e47 (diff)
child 46876 d9ea9578ff028a659b6a8ed364ff2807f27671e4
push idunknown
push userunknown
push dateunknown
milestone1.9.3a5pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
m-c to e10 merge
accessible/tests/mochitest/test_table_1.html
accessible/tests/mochitest/test_table_4.html
accessible/tests/mochitest/test_table_headers.html
accessible/tests/mochitest/test_table_headers_ariagrid.html
accessible/tests/mochitest/test_table_headers_listbox.xul
accessible/tests/mochitest/test_table_headers_tree.xul
accessible/tests/mochitest/test_table_indexes.html
accessible/tests/mochitest/test_table_indexes_ariagrid.html
accessible/tests/mochitest/test_table_indexes_listbox.xul
accessible/tests/mochitest/test_table_indexes_tree.xul
accessible/tests/mochitest/test_table_layoutguess.html
accessible/tests/mochitest/test_table_sels.html
accessible/tests/mochitest/test_table_sels_ariagrid.html
accessible/tests/mochitest/test_table_sels_listbox.xul
accessible/tests/mochitest/test_table_sels_tree.xul
accessible/tests/mochitest/test_table_struct.html
accessible/tests/mochitest/test_table_struct_ariagrid.html
accessible/tests/mochitest/test_table_struct_ariatreegrid.html
accessible/tests/mochitest/test_table_struct_listbox.xul
accessible/tests/mochitest/test_table_struct_tree.xul
caps/src/nsScriptSecurityManager.cpp
chrome/src/nsChromeRegistry.cpp
configure.in
content/base/public/Makefile.in
content/base/public/nsContentUtils.h
content/base/public/nsIFrameLoader.idl
content/base/public/nsIFrameMessageManager.idl
content/base/src/Makefile.in
content/base/src/nsContentUtils.cpp
content/base/src/nsFrameLoader.cpp
content/base/src/nsFrameLoader.h
content/base/src/nsFrameMessageManager.cpp
content/base/src/nsFrameMessageManager.h
content/base/src/nsGkAtomList.h
content/base/src/nsObjectLoadingContent.cpp
content/base/src/nsScriptLoader.cpp
content/base/test/chrome/Makefile.in
content/canvas/public/Makefile.in
content/canvas/public/WebGLArray.h
content/canvas/public/nsICanvasElement.h
content/canvas/public/nsICanvasRenderingContextInternal.h
content/canvas/src/Makefile.in
content/canvas/src/WebGLContext.cpp
content/canvas/src/WebGLContext.h
content/canvas/src/glwrap.cpp
content/canvas/src/glwrap.h
content/canvas/src/localgl.h
content/canvas/src/nsCanvasRenderingContext2D.cpp
content/canvas/src/nsGLPbuffer.cpp
content/canvas/src/nsGLPbuffer.h
content/canvas/src/nsGLPbufferCGL.cpp
content/canvas/src/nsGLPbufferEGL.cpp
content/canvas/src/nsGLPbufferGLX.cpp
content/canvas/src/nsGLPbufferOSMesa.cpp
content/canvas/src/nsGLPbufferWGL.cpp
content/html/content/public/nsHTMLCanvasElement.h
content/html/content/src/nsGenericHTMLElement.cpp
content/html/content/src/nsHTMLCanvasElement.cpp
content/media/ogg/nsOggDecoder.cpp
content/media/ogg/nsOggReader.cpp
content/media/ogg/nsOggReader.h
docshell/base/nsIChannelClassifier.idl
docshell/base/nsIURIClassifier.idl
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoClasses.h
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/base/nsJSEnvironment.cpp
dom/base/nsJSEnvironment.h
dom/ipc/TabChild.cpp
dom/plugins/PPluginInstance.ipdl
dom/plugins/PluginInstanceChild.cpp
dom/plugins/PluginInstanceParent.cpp
dom/plugins/PluginInstanceParent.h
dom/plugins/PluginMessageUtils.h
dom/plugins/PluginModuleChild.cpp
extensions/layout-debug/Makefile.in
extensions/layout-debug/application.ini
extensions/layout-debug/chrome.manifest
extensions/layout-debug/layoutdebug-prefs.js
extensions/layout-debug/makefiles.sh
extensions/layout-debug/src/Makefile.in
extensions/layout-debug/src/nsDebugFactory.cpp
extensions/layout-debug/src/nsILayoutDebuggingTools.idl
extensions/layout-debug/src/nsILayoutRegressionTester.idl
extensions/layout-debug/src/nsLayoutDebugCIID.h
extensions/layout-debug/src/nsLayoutDebugCLH.cpp
extensions/layout-debug/src/nsLayoutDebugCLH.h
extensions/layout-debug/src/nsLayoutDebuggingTools.cpp
extensions/layout-debug/src/nsLayoutDebuggingTools.h
extensions/layout-debug/src/nsRegressionTester.cpp
extensions/layout-debug/src/nsRegressionTester.h
extensions/layout-debug/ui/Makefile.in
extensions/layout-debug/ui/content/layoutdebug-overlay.xul
extensions/layout-debug/ui/content/layoutdebug.js
extensions/layout-debug/ui/content/layoutdebug.xul
extensions/layout-debug/ui/jar.mn
extensions/layout-debug/ui/locale/en-US/layoutdebug-overlay.dtd
extensions/layout-debug/ui/locale/en-US/layoutdebug.dtd
intl/uconv/src/nsGREResProperties.cpp
intl/uconv/src/nsGREResProperties.h
intl/uconv/src/unixcharset.sample.properties
ipc/glue/AsyncChannel.cpp
ipc/glue/AsyncChannel.h
ipc/glue/IPCMessageUtils.h
ipc/glue/RPCChannel.cpp
ipc/glue/RPCChannel.h
ipc/ipdl/ipdl/cxx/ast.py
ipc/ipdl/ipdl/cxx/cgen.py
ipc/ipdl/ipdl/lower.py
ipc/ipdl/ipdl/type.py
ipc/ipdl/test/cxx/PTestArrays.ipdl
ipc/ipdl/test/cxx/PTestArraysSub.ipdl
ipc/ipdl/test/cxx/TestArrays.cpp
ipc/ipdl/test/cxx/TestArrays.h
js/ipc/PObjectWrapper.ipdl
js/src/xpconnect/src/xpcthreadcontext.cpp
layout/base/nsPresContext.cpp
modules/plugin/test/mochitest/Makefile.in
netwerk/base/public/Makefile.in
netwerk/base/src/Makefile.in
netwerk/base/src/nsIOService.cpp
netwerk/cookie/src/nsCookieService.cpp
netwerk/protocol/http/src/nsHttpChannel.cpp
netwerk/protocol/http/src/nsHttpHandler.cpp
netwerk/protocol/http/src/nsHttpTransaction.cpp
netwerk/protocol/res/src/nsResProtocolHandler.cpp
netwerk/protocol/res/src/nsResProtocolHandler.h
toolkit/library/libxul-config.mk
toolkit/mozapps/update/test/chrome/test_0011_check_billboard_noLicense_noAddons.xul
toolkit/mozapps/update/test/chrome/test_0012_check_billboard_noAddons.xul
toolkit/mozapps/update/test/chrome/test_0021_check_noBillboard_noLicense_noAddons.xul
toolkit/mozapps/update/test/chrome/test_0022_check_noBillboard_noAddons.xul
toolkit/mozapps/update/test/chrome/test_0031_available_billboard_noLicense_noAddons.xul
toolkit/mozapps/update/test/chrome/test_0032_available_billboard_noAddons.xul
toolkit/mozapps/update/test/chrome/test_0041_available_noBillboard_noLicense_noAddons.xul
toolkit/mozapps/update/test/chrome/test_0042_available_noBillboard_noAddons.xul
toolkit/mozapps/update/test/chrome/test_0111_neverButton_billboard.xul
toolkit/mozapps/update/test/chrome/test_0112_neverButton_noBillboard.xul
toolkit/xre/nsAppRunner.cpp
widget/src/windows/nsWindow.cpp
widget/src/windows/nsWindow.h
--- a/accessible/src/atk/nsAccessibleWrap.cpp
+++ b/accessible/src/atk/nsAccessibleWrap.cpp
@@ -889,30 +889,28 @@ getChildCountCB(AtkObject *aAtkObj)
 AtkObject *
 refChildCB(AtkObject *aAtkObj, gint aChildIndex)
 {
     // aChildIndex should not be less than zero
     if (aChildIndex < 0) {
       return nsnull;
     }
 
-    // XXX Fix this so it is not O(n^2) to walk through the children!
-    // Either we can cache the last accessed child so that we can just GetNextSibling()
-    // or we should cache an array of children in each nsAccessible
-    // (instead of mNextSibling on the children)
     nsAccessibleWrap *accWrap = GetAccessibleWrap(aAtkObj);
     if (!accWrap || nsAccUtils::MustPrune(accWrap)) {
         return nsnull;
     }
 
     nsCOMPtr<nsIAccessible> accChild;
     nsCOMPtr<nsIAccessibleHyperText> hyperText;
     accWrap->QueryInterface(NS_GET_IID(nsIAccessibleHyperText), getter_AddRefs(hyperText));
     if (hyperText) {
-        // If HyperText, then number of links matches number of children
+        // If HyperText, then number of links matches number of children.
+        // XXX Fix this so it is not O(n^2) to walk through the children
+        // (bug 566328).
         nsCOMPtr<nsIAccessibleHyperLink> hyperLink;
         hyperText->GetLink(aChildIndex, getter_AddRefs(hyperLink));
         accChild = do_QueryInterface(hyperLink);
     }
     else {
         nsCOMPtr<nsIAccessibleText> accText;
         accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText), getter_AddRefs(accText));
         if (!accText) {  // Accessible Text that is not HyperText has no children
@@ -940,46 +938,36 @@ getIndexInParentCB(AtkObject *aAtkObj)
 {
     // We don't use nsIAccessible::GetIndexInParent() because
     // for ATK we don't want to include text leaf nodes as children
     nsAccessibleWrap *accWrap = GetAccessibleWrap(aAtkObj);
     if (!accWrap) {
         return -1;
     }
 
-    nsCOMPtr<nsIAccessible> parent;
-    accWrap->GetParent(getter_AddRefs(parent));
+    nsAccessible *parent = accWrap->GetParent();
     if (!parent) {
         return -1; // No parent
     }
 
-    nsCOMPtr<nsIAccessible> sibling;
-    parent->GetFirstChild(getter_AddRefs(sibling));
-    if (!sibling) {
-        return -1;  // Error, parent has no children
-    }
-
     PRInt32 currentIndex = 0;
 
-    while (sibling != static_cast<nsIAccessible*>(accWrap)) {
-      NS_ASSERTION(sibling, "Never ran into the same child that we started from");
-
-      if (!sibling) {
-          return -1;
-      }
-      if (nsAccUtils::IsEmbeddedObject(sibling)) {
-        ++ currentIndex;
+    PRInt32 childCount = parent->GetChildCount();
+    for (PRInt32 idx = 0; idx < childCount; idx++) {
+      nsAccessible *sibling = parent->GetChildAt(idx);
+      if (sibling == accWrap) {
+          return currentIndex;
       }
 
-      nsCOMPtr<nsIAccessible> tempAccessible;
-      sibling->GetNextSibling(getter_AddRefs(tempAccessible));
-      sibling.swap(tempAccessible);
+      if (nsAccUtils::IsEmbeddedObject(sibling)) {
+          ++ currentIndex;
+      }
     }
 
-    return currentIndex;
+    return -1;
 }
 
 static void TranslateStates(PRUint32 aState, const AtkStateMap *aStateMap,
                             AtkStateSet *aStateSet)
 {
   NS_ASSERTION(aStateSet, "Can't pass in null state set");
 
   // Convert every state to an entry in AtkStateMap
--- a/accessible/src/base/Makefile.in
+++ b/accessible/src/base/Makefile.in
@@ -45,16 +45,17 @@ include $(DEPTH)/config/autoconf.mk
 MODULE = accessibility
 LIBRARY_NAME = accessibility_base_s
 LIBXUL_LIBRARY = 1
 
 
 CPPSRCS = \
   nsAccessNode.cpp \
   nsAccEvent.cpp \
+  nsAccIterator.cpp \
   nsARIAGridAccessible.cpp \
   nsARIAMap.cpp \
   nsDocAccessible.cpp \
   nsOuterDocAccessible.cpp \
   nsAccessibilityAtoms.cpp \
   nsCoreUtils.cpp \
   nsAccUtils.cpp \
   nsRelUtils.cpp \
--- a/accessible/src/base/nsARIAGridAccessible.cpp
+++ b/accessible/src/base/nsARIAGridAccessible.cpp
@@ -33,17 +33,17 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsARIAGridAccessible.h"
 
-#include "nsAccUtils.h"
+#include "nsAccIterator.h"
 
 #include "nsIMutableArray.h"
 #include "nsComponentManagerUtils.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsARIAGridAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -96,54 +96,58 @@ NS_IMETHODIMP
 nsARIAGridAccessible::GetColumnCount(PRInt32 *acolumnCount)
 {
   NS_ENSURE_ARG_POINTER(acolumnCount);
   *acolumnCount = 0;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  nsCOMPtr<nsIAccessible> row = GetNextRow();
-  nsCOMPtr<nsIAccessible> cell;
-  while ((cell = GetNextCellInRow(row, cell)))
+  nsAccIterator rowIter(this, nsAccIterator::GetRow);
+  nsAccessible *row = rowIter.GetNext();
+
+  nsAccIterator cellIter(row, nsAccIterator::GetCell);
+  nsAccessible *cell = nsnull;
+
+  while ((cell = cellIter.GetNext()))
     (*acolumnCount)++;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsARIAGridAccessible::GetRowCount(PRInt32 *arowCount)
 {
   NS_ENSURE_ARG_POINTER(arowCount);
   *arowCount = 0;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  nsCOMPtr<nsIAccessible> row;
-  while ((row = GetNextRow(row)))
+  nsAccIterator rowIter(this, nsAccIterator::GetRow);
+  while (rowIter.GetNext())
     (*arowCount)++;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsARIAGridAccessible::GetCellAt(PRInt32 aRowIndex, PRInt32 aColumnIndex,
                                 nsIAccessible **aAccessible)
 {
   NS_ENSURE_ARG_POINTER(aAccessible);
   *aAccessible = nsnull;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  nsCOMPtr<nsIAccessible> row = GetRowAt(aRowIndex);
+  nsAccessible *row = GetRowAt(aRowIndex);
   NS_ENSURE_ARG(row);
 
-  nsCOMPtr<nsIAccessible> cell = GetCellInRowAt(row, aColumnIndex);
+  nsAccessible *cell = GetCellInRowAt(row, aColumnIndex);
   NS_ENSURE_ARG(cell);
 
   NS_ADDREF(*aAccessible = cell);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsARIAGridAccessible::GetCellIndexAt(PRInt32 aRowIndex, PRInt32 aColumnIndex,
@@ -283,50 +287,52 @@ nsARIAGridAccessible::IsColumnSelected(P
   NS_ENSURE_ARG_POINTER(aIsSelected);
   *aIsSelected = PR_FALSE;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   NS_ENSURE_ARG(IsValidColumn(aColumn));
 
-  nsCOMPtr<nsIAccessible> row = GetNextRow();
+  nsAccIterator rowIter(this, nsAccIterator::GetRow);
+  nsAccessible *row = rowIter.GetNext();
   if (!row)
     return NS_OK;
 
   do {
     if (!nsAccUtils::IsARIASelected(row)) {
-      nsCOMPtr<nsIAccessible> cell = GetCellInRowAt(row, aColumn);
+      nsAccessible *cell = GetCellInRowAt(row, aColumn);
       if (!cell) // Do not fail due to wrong markup
         return NS_OK;
       
       if (!nsAccUtils::IsARIASelected(cell))
         return NS_OK;
     }
-  } while ((row = GetNextRow(row)));
+  } while ((row = rowIter.GetNext()));
 
   *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;
 
-  nsCOMPtr<nsIAccessible> row = GetRowAt(aRow);
+  nsAccessible *row = GetRowAt(aRow);
   NS_ENSURE_ARG(row);
 
   if (!nsAccUtils::IsARIASelected(row)) {
-    nsCOMPtr<nsIAccessible> cell;
-    while ((cell = GetNextCellInRow(row, cell))) {
+    nsAccIterator cellIter(row, nsAccIterator::GetCell);
+    nsAccessible *cell = nsnull;
+    while ((cell = cellIter.GetNext())) {
       if (!nsAccUtils::IsARIASelected(cell))
         return NS_OK;
     }
   }
 
   *aIsSelected = PR_TRUE;
   return NS_OK;
 }
@@ -336,21 +342,21 @@ nsARIAGridAccessible::IsCellSelected(PRI
                                      PRBool *aIsSelected)
 {
   NS_ENSURE_ARG_POINTER(aIsSelected);
   *aIsSelected = PR_FALSE;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  nsCOMPtr<nsIAccessible> row(GetRowAt(aRow));
+  nsAccessible *row = GetRowAt(aRow);
   NS_ENSURE_ARG(row);
 
   if (!nsAccUtils::IsARIASelected(row)) {
-    nsCOMPtr<nsIAccessible> cell(GetCellInRowAt(row, aColumn));
+    nsAccessible *cell = GetCellInRowAt(row, aColumn);
     NS_ENSURE_ARG(cell);
 
     if (!nsAccUtils::IsARIASelected(cell))
       return NS_OK;
   }
 
   *aIsSelected = PR_TRUE;
   return NS_OK;
@@ -362,26 +368,30 @@ nsARIAGridAccessible::GetSelectedCellCou
   NS_ENSURE_ARG_POINTER(aCount);
   *aCount = 0;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   PRInt32 colCount = 0;
   GetColumnCount(&colCount);
-  
-  nsCOMPtr<nsIAccessible> row;
-  while ((row = GetNextRow(row))) {
+
+  nsAccIterator rowIter(this, nsAccIterator::GetRow);
+
+  nsAccessible *row = nsnull;
+  while ((row = rowIter.GetNext())) {
     if (nsAccUtils::IsARIASelected(row)) {
       (*aCount) += colCount;
       continue;
     }
 
-    nsCOMPtr<nsIAccessible> cell;
-    while ((cell = GetNextCellInRow(row, cell))) {
+    nsAccIterator cellIter(row, nsAccIterator::GetCell);
+    nsAccessible *cell = nsnull;
+
+    while ((cell = cellIter.GetNext())) {
       if (nsAccUtils::IsARIASelected(cell))
         (*aCount)++;
     }
   }
 
   return NS_OK;
 }
 
@@ -395,34 +405,37 @@ NS_IMETHODIMP
 nsARIAGridAccessible::GetSelectedRowCount(PRUint32* aCount)
 {
   NS_ENSURE_ARG_POINTER(aCount);
   *aCount = 0;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  nsCOMPtr<nsIAccessible> row;
-  while ((row = GetNextRow(row))) {
+  nsAccIterator rowIter(this, nsAccIterator::GetRow);
+
+  nsAccessible *row = nsnull;
+  while ((row = rowIter.GetNext())) {
     if (nsAccUtils::IsARIASelected(row)) {
       (*aCount)++;
       continue;
     }
 
-    nsCOMPtr<nsIAccessible> cell = GetNextCellInRow(row);
+    nsAccIterator cellIter(row, nsAccIterator::GetCell);
+    nsAccessible *cell = cellIter.GetNext();
     if (!cell)
       continue;
 
     PRBool isRowSelected = PR_TRUE;
     do {
       if (!nsAccUtils::IsARIASelected(cell)) {
         isRowSelected = PR_FALSE;
         break;
       }
-    } while ((cell = GetNextCellInRow(row, cell)));
+    } while ((cell = cellIter.GetNext()));
 
     if (isRowSelected)
       (*aCount)++;
   }
 
   return NS_OK;
 }
 
@@ -435,28 +448,31 @@ nsARIAGridAccessible::GetSelectedCells(n
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   nsresult rv = NS_OK;
   nsCOMPtr<nsIMutableArray> selCells =
     do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIAccessible> row;
-  while (row = GetNextRow(row)) {
+  nsAccIterator rowIter(this, nsAccIterator::GetRow);
+
+  nsAccessible *row = nsnull;
+  while (row = rowIter.GetNext()) {
+    nsAccIterator cellIter(row, nsAccIterator::GetCell);
+    nsIAccessible *cell = nsnull;
+
     if (nsAccUtils::IsARIASelected(row)) {
-      nsCOMPtr<nsIAccessible> cell;
-      while (cell = GetNextCellInRow(row, cell))
+      while (cell = cellIter.GetNext())
         selCells->AppendElement(cell, PR_FALSE);
 
       continue;
     }
 
-    nsCOMPtr<nsIAccessible> cell;
-    while (cell = GetNextCellInRow(row, cell)) {
+    while (cell = cellIter.GetNext()) {
       if (nsAccUtils::IsARIASelected(cell))
         selCells->AppendElement(cell, PR_FALSE);
     }
   }
 
   NS_ADDREF(*aCells = selCells);
   return NS_OK;
 }
@@ -476,27 +492,31 @@ nsARIAGridAccessible::GetSelectedCellInd
   PRInt32 rowCount = 0;
   GetRowCount(&rowCount);
 
   PRInt32 colCount = 0;
   GetColumnCount(&colCount);
 
   nsTArray<PRInt32> selCells(rowCount * colCount);
 
-  nsCOMPtr<nsIAccessible> row;
-  for (PRInt32 rowIdx = 0; row = GetNextRow(row); rowIdx++) {
+  nsAccIterator rowIter(this, nsAccIterator::GetRow);
+
+  nsAccessible *row = nsnull;
+  for (PRInt32 rowIdx = 0; row = rowIter.GetNext(); rowIdx++) {
     if (nsAccUtils::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++) {
+    nsAccIterator cellIter(row, nsAccIterator::GetCell);
+    nsAccessible *cell = nsnull;
+
+    for (PRInt32 colIdx = 0; cell = cellIter.GetNext(); colIdx++) {
       if (nsAccUtils::IsARIASelected(cell))
         selCells.AppendElement(rowIdx * colCount + colIdx);
     }
   }
 
   PRUint32 selCellsCount = selCells.Length();
   if (!selCellsCount)
     return NS_OK;
@@ -532,34 +552,37 @@ nsARIAGridAccessible::GetSelectedRowIndi
 
   PRInt32 rowCount = 0;
   GetRowCount(&rowCount);
   if (!rowCount)
     return NS_OK;
 
   nsTArray<PRInt32> selRows(rowCount);
 
-  nsCOMPtr<nsIAccessible> row;
-  for (PRInt32 rowIdx = 0; row = GetNextRow(row); rowIdx++) {
+  nsAccIterator rowIter(this, nsAccIterator::GetRow);
+
+  nsAccessible *row = nsnull;
+  for (PRInt32 rowIdx = 0; row = rowIter.GetNext(); rowIdx++) {
     if (nsAccUtils::IsARIASelected(row)) {
       selRows.AppendElement(rowIdx);
       continue;
     }
 
-    nsCOMPtr<nsIAccessible> cell = GetNextCellInRow(row);
+    nsAccIterator cellIter(row, nsAccIterator::GetCell);
+    nsAccessible *cell = cellIter.GetNext();
     if (!cell)
       continue;
 
     PRBool isRowSelected = PR_TRUE;
     do {
       if (!nsAccUtils::IsARIASelected(cell)) {
         isRowSelected = PR_FALSE;
         break;
       }
-    } while ((cell = GetNextCellInRow(row, cell)));
+    } while ((cell = cellIter.GetNext()));
 
     if (isRowSelected)
       selRows.AppendElement(rowIdx);
   }
 
   PRUint32 selrowCount = selRows.Length();
   if (!selrowCount)
     return NS_OK;
@@ -575,73 +598,79 @@ nsARIAGridAccessible::GetSelectedRowIndi
 NS_IMETHODIMP
 nsARIAGridAccessible::SelectRow(PRInt32 aRow)
 {
   NS_ENSURE_ARG(IsValidRow(aRow));
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  nsCOMPtr<nsIAccessible> row;
-  for (PRInt32 rowIdx = 0; row = GetNextRow(row); rowIdx++) {
+  nsAccIterator rowIter(this, nsAccIterator::GetRow);
+
+  nsAccessible *row = nsnull;
+  for (PRInt32 rowIdx = 0; row = rowIter.GetNext(); 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;
 
-  nsCOMPtr<nsIAccessible> row;
-  while ((row = GetNextRow(row))) {
+  nsAccIterator rowIter(this, nsAccIterator::GetRow);
+
+  nsAccessible *row = nsnull;
+  while ((row = rowIter.GetNext())) {
     // 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);
+    nsAccessible *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)
 {
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  nsCOMPtr<nsIAccessible> row = GetRowAt(aRow);
+  nsAccessible *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;
 
-  nsCOMPtr<nsIAccessible> row;
-  while ((row = GetNextRow(row))) {
-    nsCOMPtr<nsIAccessible> cell = GetCellInRowAt(row, aColumn);
+  nsAccIterator rowIter(this, nsAccIterator::GetRow);
+
+  nsAccessible *row = nsnull;
+  while ((row = rowIter.GetNext())) {
+    nsAccessible *cell = GetCellInRowAt(row, aColumn);
     if (cell) {
       nsresult rv = SetARIASelected(cell, PR_FALSE);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
   return NS_OK;
 }
@@ -691,94 +720,49 @@ nsARIAGridAccessible::IsValidRowNColumn(
   if (aRow >= rowCount)
     return PR_FALSE;
 
   PRInt32 colCount = 0;
   GetColumnCount(&colCount);
   return aColumn < colCount;
 }
 
-already_AddRefed<nsIAccessible>
+nsAccessible*
 nsARIAGridAccessible::GetRowAt(PRInt32 aRow)
 {
   PRInt32 rowIdx = aRow;
-  nsCOMPtr<nsIAccessible> row(GetNextRow());
-  while (rowIdx != 0 && (row = GetNextRow(row)))
+
+  nsAccIterator rowIter(this, nsAccIterator::GetRow);
+
+  nsAccessible *row = rowIter.GetNext();
+  while (rowIdx != 0 && (row = rowIter.GetNext()))
     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();
+  return row;
 }
 
-already_AddRefed<nsIAccessible>
-nsARIAGridAccessible::GetNextRow(nsIAccessible *aRow)
+nsAccessible*
+nsARIAGridAccessible::GetCellInRowAt(nsAccessible *aRow, PRInt32 aColumn)
 {
-  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;
-}
+  PRInt32 colIdx = aColumn;
 
-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));
+  nsAccIterator cellIter(aRow, nsAccIterator::GetCell);
+  nsAccessible *cell = cellIter.GetNext();
+  while (colIdx != 0 && (cell = cellIter.GetNext()))
+    colIdx--;
 
-  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;
+  return cell;
 }
 
 nsresult
-nsARIAGridAccessible::SetARIASelected(nsIAccessible *aAccessible,
+nsARIAGridAccessible::SetARIASelected(nsAccessible *aAccessible,
                                       PRBool aIsSelected, PRBool aNotify)
 {
-  nsRefPtr<nsAccessible> acc = do_QueryObject(aAccessible);
-  nsCOMPtr<nsIDOMNode> node;
-  acc->GetDOMNode(getter_AddRefs(node));
-  NS_ENSURE_STATE(node);
-
-  nsCOMPtr<nsIContent> content(do_QueryInterface(node));
+  nsCOMPtr<nsIContent> content(do_QueryInterface(aAccessible->GetDOMNode()));
+  NS_ENSURE_STATE(content);
 
   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);
@@ -795,40 +779,42 @@ nsARIAGridAccessible::SetARIASelected(ns
   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))) {
+    nsAccIterator cellIter(aAccessible, nsAccIterator::GetCell);
+    nsAccessible *cell = nsnull;
+
+    while ((cell = cellIter.GetNext())) {
       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));
+    nsAccessible *row = aAccessible->GetParent();
 
     if (nsAccUtils::Role(row) == nsIAccessibleRole::ROLE_ROW &&
         nsAccUtils::IsARIASelected(row)) {
       rv = SetARIASelected(row, PR_FALSE, PR_FALSE);
       NS_ENSURE_SUCCESS(rv, rv);
 
-      nsCOMPtr<nsIAccessible> cell;
-      while ((cell = GetNextCellInRow(row, cell))) {
+      nsAccIterator cellIter(row, nsAccIterator::GetCell);
+      nsAccessible *cell = nsnull;
+      while ((cell = cellIter.GetNext())) {
         if (cell != aAccessible) {
           rv = SetARIASelected(cell, PR_TRUE, PR_FALSE);
           NS_ENSURE_SUCCESS(rv, rv);
         }
       }
     }
   }
 
@@ -842,17 +828,18 @@ nsARIAGridAccessible::GetSelectedColumns
   NS_ENSURE_ARG_POINTER(acolumnCount);
   *acolumnCount = 0;
   if (aColumns)
     *aColumns = nsnull;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  nsCOMPtr<nsIAccessible> row = GetNextRow();
+  nsAccIterator rowIter(this, nsAccIterator::GetRow);
+  nsAccessible *row = rowIter.GetNext();
   if (!row)
     return NS_OK;
 
   PRInt32 colCount = 0;
   GetColumnCount(&colCount);
   if (!colCount)
     return NS_OK;
 
@@ -863,25 +850,27 @@ nsARIAGridAccessible::GetSelectedColumns
   for (PRInt32 i = 0; i < selColCount; i++)
     isColSelArray[i] = PR_TRUE;
 
   do {
     if (nsAccUtils::IsARIASelected(row))
       continue;
 
     PRInt32 colIdx = 0;
-    nsCOMPtr<nsIAccessible> cell;
-    for (colIdx = 0; cell = GetNextCellInRow(row, cell); colIdx++) {
+
+    nsAccIterator cellIter(row, nsAccIterator::GetCell);
+    nsAccessible *cell = nsnull;
+    for (colIdx = 0; cell = cellIter.GetNext(); colIdx++) {
       if (isColSelArray.SafeElementAt(colIdx, PR_FALSE) &&
           !nsAccUtils::IsARIASelected(cell)) {
         isColSelArray[colIdx] = PR_FALSE;
         selColCount--;
       }
     }
-  } while ((row = GetNextRow(row)));
+  } while ((row = rowIter.GetNext()));
 
   if (!selColCount)
     return NS_OK;
 
   if (!aColumns) {
     *acolumnCount = selColCount;
     return NS_OK;
   }
@@ -1125,52 +1114,48 @@ nsARIAGridCellAccessible::GetAttributesI
   if (IsDefunct())
     return NS_ERROR_FAILURE;
   
   nsresult rv = nsHyperTextAccessibleWrap::GetAttributesInternal(aAttributes);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Expose "table-cell-index" attribute.
 
-  nsCOMPtr<nsIAccessible> thisRow;
-  GetParent(getter_AddRefs(thisRow));
+  nsAccessible *thisRow = GetParent();
   if (nsAccUtils::Role(thisRow) != nsIAccessibleRole::ROLE_ROW)
     return NS_OK;
 
   PRInt32 colIdx = 0, colCount = 0;
-  nsCOMPtr<nsIAccessible> child, nextChild;
-  thisRow->GetFirstChild(getter_AddRefs(child));
-  while (child) {
+  PRInt32 childCount = thisRow->GetChildCount();
+  for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
+    nsAccessible *child = thisRow->GetChildAt(childIdx);
     if (child == this)
       colIdx = colCount;
 
     PRUint32 role = nsAccUtils::Role(child);
     if (role == nsIAccessibleRole::ROLE_GRID_CELL ||
         role == nsIAccessibleRole::ROLE_ROWHEADER ||
         role == nsIAccessibleRole::ROLE_COLUMNHEADER)
       colCount++;
-
-    child->GetNextSibling(getter_AddRefs(nextChild));
-    child.swap(nextChild);
   }
 
-  nsCOMPtr<nsIAccessible> table;
-  thisRow->GetParent(getter_AddRefs(table));
+  nsAccessible *table = thisRow->GetParent();
   if (nsAccUtils::Role(table) != nsIAccessibleRole::ROLE_TABLE &&
       nsAccUtils::Role(table) != nsIAccessibleRole::ROLE_TREE_TABLE)
     return NS_OK;
 
   PRInt32 rowIdx = 0;
-  table->GetFirstChild(getter_AddRefs(child));
-  while (child && child != thisRow) {
+  childCount = table->GetChildCount();
+  for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
+    nsAccessible *child = table->GetChildAt(childIdx);
+    if (child == thisRow)
+      break;
+
     if (nsAccUtils::Role(child) == nsIAccessibleRole::ROLE_ROW)
       rowIdx++;
-
-    child->GetNextSibling(getter_AddRefs(nextChild));
-    child.swap(nextChild);
   }
 
   PRInt32 idx = rowIdx * colCount + colIdx;
 
   nsAutoString stringIdx;
   stringIdx.AppendInt(idx);
   nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::tableCellIndex,
                          stringIdx);
--- a/accessible/src/base/nsARIAGridAccessible.h
+++ b/accessible/src/base/nsARIAGridAccessible.h
@@ -72,51 +72,32 @@ protected:
   /**
    * 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);
+  nsAccessible *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);
+  nsAccessible *GetCellInRowAt(nsAccessible *aRow, PRInt32 aColumn);
 
   /**
    * 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,
+  nsresult SetARIASelected(nsAccessible *aAccessible, PRBool aIsSelected,
                            PRBool aNotify = PR_TRUE);
 
   /**
    * Helper method for GetSelectedColumnCount and GetSelectedColumns.
    */
   nsresult GetSelectedColumnsArray(PRUint32 *acolumnCount,
                                    PRInt32 **aColumns = nsnull);
 };
new file mode 100644
--- /dev/null
+++ b/accessible/src/base/nsAccIterator.cpp
@@ -0,0 +1,93 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Alexander Surkov <surkov.alexander@gmail.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 "nsAccIterator.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// nsAccIterator
+
+nsAccIterator::nsAccIterator(nsAccessible *aAccessible,
+                             AccIteratorFilterFuncPtr aFilterFunc,
+                             IterationType aIterationType) :
+  mFilterFunc(aFilterFunc), mIsDeep(aIterationType != eFlatNav)
+{
+  mState = new IteratorState(aAccessible);
+}
+
+nsAccIterator::~nsAccIterator()
+{
+  while (mState) {
+    IteratorState *tmp = mState;
+    mState = tmp->mParentState;
+    delete tmp;
+  }
+}
+
+nsAccessible*
+nsAccIterator::GetNext()
+{
+  while (mState) {
+    nsAccessible *child = mState->mParent->GetChildAt(mState->mIndex++);
+    if (!child) {
+      IteratorState *tmp = mState;
+      mState = mState->mParentState;
+      delete tmp;
+
+      continue;
+    }
+
+    PRBool isComplying = mFilterFunc(child);
+    if (isComplying)
+      return child;
+
+    if (mIsDeep) {
+      IteratorState *childState = new IteratorState(child, mState);
+      mState = childState;
+    }
+  }
+
+  return nsnull;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsAccIterator::IteratorState
+
+nsAccIterator::IteratorState::IteratorState(nsAccessible *aParent,
+                                            IteratorState *mParentState) :
+  mParent(aParent), mIndex(0), mParentState(mParentState)
+{
+}
new file mode 100644
--- /dev/null
+++ b/accessible/src/base/nsAccIterator.h
@@ -0,0 +1,124 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Alexander Surkov <surkov.alexander@gmail.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 nsAccIterator_h_
+#define nsAccIterator_h_
+
+#include "nsAccessible.h"
+#include "nsAccUtils.h"
+
+/**
+ * Return true if the traversed accessible complies with filter.
+ */
+typedef PRBool (*AccIteratorFilterFuncPtr) (nsAccessible *);
+
+/**
+ * Allows to iterate through accessible children or subtree complying with
+ * filter function.
+ */
+class nsAccIterator
+{
+public:
+  /**
+   * Used to define iteration type.
+   */
+  enum IterationType {
+    /**
+     * Navigation happens through direct children.
+     */
+    eFlatNav,
+
+    /**
+     * Navigation through subtree excluding iterator root; if the accessible
+     * complies with filter, iterator ignores its children.
+     */
+    eTreeNav
+  };
+
+  nsAccIterator(nsAccessible *aRoot, AccIteratorFilterFuncPtr aFilterFunc,
+                IterationType aIterationType = eFlatNav);
+  ~nsAccIterator();
+
+  /**
+   * Return next accessible complying with filter function. Return the first
+   * accessible for the first time.
+   */
+  nsAccessible *GetNext();
+
+  /**
+   * Predefined filters.
+   */
+  static PRBool GetSelected(nsAccessible *aAccessible)
+  {
+    return nsAccUtils::State(aAccessible) & nsIAccessibleStates::STATE_SELECTED;
+  }
+  static PRBool GetSelectable(nsAccessible *aAccessible)
+  {
+    return nsAccUtils::State(aAccessible) & nsIAccessibleStates::STATE_SELECTABLE;
+  }
+  static PRBool GetRow(nsAccessible *aAccessible)
+  {
+    return nsAccUtils::Role(aAccessible) == nsIAccessibleRole::ROLE_ROW;
+  }
+  static PRBool GetCell(nsAccessible *aAccessible)
+  {
+    PRUint32 role = nsAccUtils::Role(aAccessible);
+    return role == nsIAccessibleRole::ROLE_GRID_CELL ||
+           role == nsIAccessibleRole::ROLE_ROWHEADER ||
+           role == nsIAccessibleRole::ROLE_COLUMNHEADER;
+  }
+
+private:
+  nsAccIterator();
+  nsAccIterator(const nsAccIterator&);
+  nsAccIterator& operator =(const nsAccIterator&);
+
+  struct IteratorState
+  {
+    IteratorState(nsAccessible *aParent, IteratorState *mParentState = nsnull);
+
+    nsAccessible *mParent;
+    PRInt32 mIndex;
+    IteratorState *mParentState;
+  };
+
+  AccIteratorFilterFuncPtr mFilterFunc;
+  PRBool mIsDeep;
+  IteratorState *mState;
+};
+
+#endif
--- a/accessible/src/base/nsAccUtils.cpp
+++ b/accessible/src/base/nsAccUtils.cpp
@@ -784,41 +784,39 @@ nsAccUtils::GetLiveAttrValue(PRUint32 aR
   }
 
   return PR_FALSE;
 }
 
 #ifdef DEBUG_A11Y
 
 PRBool
-nsAccUtils::IsTextInterfaceSupportCorrect(nsIAccessible *aAccessible)
+nsAccUtils::IsTextInterfaceSupportCorrect(nsAccessible *aAccessible)
 {
   PRBool foundText = PR_FALSE;
   
-  nsCOMPtr<nsIAccessibleDocument> accDoc = do_QueryInterface(aAccessible);
+  nsCOMPtr<nsIAccessibleDocument> accDoc = do_QueryObject(aAccessible);
   if (accDoc) {
     // Don't test for accessible docs, it makes us create accessibles too
     // early and fire mutation events before we need to
     return PR_TRUE;
   }
 
-  nsCOMPtr<nsIAccessible> child, nextSibling;
-  aAccessible->GetFirstChild(getter_AddRefs(child));
-  while (child) {
+  PRInt32 childCount = aAccessible->GetChildCount();
+  for (PRint32 childIdx = 0; childIdx < childCount; childIdx++) {
+    nsAccessible *child = GetChildAt(childIdx);
     if (IsText(child)) {
       foundText = PR_TRUE;
       break;
     }
-    child->GetNextSibling(getter_AddRefs(nextSibling));
-    child.swap(nextSibling);
   }
 
   if (foundText) {
     // found text child node
-    nsCOMPtr<nsIAccessibleText> text = do_QueryInterface(aAccessible);
+    nsCOMPtr<nsIAccessibleText> text = do_QueryObject(aAccessible);
     if (!text)
       return PR_FALSE;
   }
 
   return PR_TRUE; 
 }
 #endif
 
--- a/accessible/src/base/nsAccUtils.h
+++ b/accessible/src/base/nsAccUtils.h
@@ -319,17 +319,17 @@ public:
    */
   static PRBool GetLiveAttrValue(PRUint32 aRule, nsAString& aValue);
 
 #ifdef DEBUG_A11Y
   /**
    * Detect whether the given accessible object implements nsIAccessibleText,
    * when it is text or has text child node.
    */
-  static PRBool IsTextInterfaceSupportCorrect(nsIAccessible *aAccessible);
+  static PRBool IsTextInterfaceSupportCorrect(nsAccessible *aAccessible);
 #endif
 
   /**
    * Return true if the given accessible has text role.
    */
   static PRBool IsText(nsIAccessible *aAcc)
   {
     PRUint32 role = Role(aAcc);
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -105,25 +105,29 @@
 #include "nsHTMLWin32ObjectAccessible.h"
 #endif
 
 #ifndef DISABLE_XFORMS_HOOKS
 #include "nsXFormsFormControlsAccessible.h"
 #include "nsXFormsWidgetsAccessible.h"
 #endif
 
+#include "mozilla/FunctionTimer.h"
+
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessibilityService
 ////////////////////////////////////////////////////////////////////////////////
 
 nsAccessibilityService *nsAccessibilityService::gAccessibilityService = nsnull;
 PRBool nsAccessibilityService::gIsShutdown = PR_TRUE;
 
 nsAccessibilityService::nsAccessibilityService()
 {
+  NS_TIME_FUNCTION;
+
   // Add observers.
   nsCOMPtr<nsIObserverService> observerService =
     mozilla::services::GetObserverService();
   if (!observerService)
     return;
 
   observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
   nsCOMPtr<nsIWebProgress> progress(do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID));
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -36,16 +36,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsAccessible.h"
 
 #include "nsIXBLAccessible.h"
 
+#include "nsAccIterator.h"
 #include "nsAccUtils.h"
 #include "nsARIAMap.h"
 #include "nsDocAccessible.h"
 #include "nsEventShell.h"
 
 #include "nsAccessibilityService.h"
 #include "nsAccTreeWalker.h"
 #include "nsRelUtils.h"
@@ -170,19 +171,20 @@ nsresult nsAccessible::QueryInterface(RE
     if (mRoleMapEntry && mRoleMapEntry->valueRule != eNoValue) {
       *aInstancePtr = static_cast<nsIAccessibleValue*>(this);
       NS_ADDREF_THIS();
       return NS_OK;
     }
   }                       
 
   if (aIID.Equals(NS_GET_IID(nsIAccessibleHyperLink))) {
+    // Every embedded accessible within hypertext accessible implements
+    // hyperlink interface.
     nsCOMPtr<nsIAccessibleHyperText> hyperTextParent = do_QueryObject(GetParent());
-
-    if (hyperTextParent) {
+    if (hyperTextParent && nsAccUtils::IsEmbeddedObject(this)) {
       *aInstancePtr = static_cast<nsIAccessibleHyperLink*>(this);
       NS_ADDREF_THIS();
       return NS_OK;
     }
     return NS_ERROR_NO_INTERFACE;
   }
 
   return nsAccessNodeWrap::QueryInterface(aIID, aInstancePtr);
@@ -2460,99 +2462,74 @@ nsAccessible::DispatchClickEvent(nsICont
   PRBool res = nsCoreUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, presShell,
                                                aContent);
   if (!res)
     return;
 
   nsCoreUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_UP, presShell, aContent);
 }
 
-already_AddRefed<nsIAccessible>
-nsAccessible::GetNextWithState(nsIAccessible *aStart, PRUint32 matchState)
-{
-  // Return the next descendant that matches one of the states in matchState
-  // Uses depth first search
-  NS_ASSERTION(matchState, "GetNextWithState() not called with a state to match");
-  NS_ASSERTION(aStart, "GetNextWithState() not called with an accessible to start with");
-  nsCOMPtr<nsIAccessible> look, current = aStart;
-  PRUint32 state = 0;
-  while (0 == (state & matchState)) {
-    current->GetFirstChild(getter_AddRefs(look));
-    while (!look) {
-      if (current == this) {
-        return nsnull; // At top of subtree
-      }
-      current->GetNextSibling(getter_AddRefs(look));
-      if (!look) {
-        current->GetParent(getter_AddRefs(look));
-        current = look;
-        look = nsnull;
-        continue;
-      }
-    }
-    current.swap(look);
-    state = nsAccUtils::State(current);
-  }
-
-  nsIAccessible *returnAccessible = nsnull;
-  current.swap(returnAccessible);
-
-  return returnAccessible;
-}
-
 // nsIAccessibleSelectable
 NS_IMETHODIMP nsAccessible::GetSelectedChildren(nsIArray **aSelectedAccessibles)
 {
   *aSelectedAccessibles = nsnull;
 
   nsCOMPtr<nsIMutableArray> selectedAccessibles =
     do_CreateInstance(NS_ARRAY_CONTRACTID);
   NS_ENSURE_STATE(selectedAccessibles);
 
-  nsCOMPtr<nsIAccessible> selected = this;
-  while ((selected = GetNextWithState(selected, nsIAccessibleStates::STATE_SELECTED)) != nsnull) {
+  nsAccIterator iter(this, nsAccIterator::GetSelected, nsAccIterator::eTreeNav);
+  nsIAccessible *selected = nsnull;
+  while ((selected = iter.GetNext()))
     selectedAccessibles->AppendElement(selected, PR_FALSE);
-  }
 
   PRUint32 length = 0;
   selectedAccessibles->GetLength(&length); 
   if (length) { // length of nsIArray containing selected options
     *aSelectedAccessibles = selectedAccessibles;
     NS_ADDREF(*aSelectedAccessibles);
   }
 
   return NS_OK;
 }
 
 // return the nth selected descendant nsIAccessible object
 NS_IMETHODIMP nsAccessible::RefSelection(PRInt32 aIndex, nsIAccessible **aSelected)
 {
+  NS_ENSURE_ARG_POINTER(aSelected);
   *aSelected = nsnull;
+
   if (aIndex < 0) {
-    return NS_ERROR_FAILURE;
+    return NS_ERROR_INVALID_ARG;
   }
-  nsCOMPtr<nsIAccessible> selected = this;
+
+  nsAccIterator iter(this, nsAccIterator::GetSelected, nsAccIterator::eTreeNav);
+  nsAccessible *selected = nsnull;
+
   PRInt32 count = 0;
   while (count ++ <= aIndex) {
-    selected = GetNextWithState(selected, nsIAccessibleStates::STATE_SELECTED);
+    selected = iter.GetNext();
     if (!selected) {
-      return NS_ERROR_FAILURE; // aIndex out of range
+      // The index is out of range.
+      return NS_ERROR_INVALID_ARG;
     }
   }
   NS_IF_ADDREF(*aSelected = selected);
   return NS_OK;
 }
 
 NS_IMETHODIMP nsAccessible::GetSelectionCount(PRInt32 *aSelectionCount)
 {
+  NS_ENSURE_ARG_POINTER(aSelectionCount);
   *aSelectionCount = 0;
-  nsCOMPtr<nsIAccessible> selected = this;
-  while ((selected = GetNextWithState(selected, nsIAccessibleStates::STATE_SELECTED)) != nsnull) {
-    ++ *aSelectionCount;
-  }
+
+  nsAccIterator iter(this, nsAccIterator::GetSelected, nsAccIterator::eTreeNav);
+  nsAccessible *selected = nsnull;
+  while ((selected = iter.GetNext()))
+    ++(*aSelectionCount);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsAccessible::AddChildToSelection(PRInt32 aIndex)
 {
   // Tree views and other container widgets which may have grandchildren should
   // implement a selection methods for their specific interfaces, because being
@@ -2598,31 +2575,34 @@ NS_IMETHODIMP nsAccessible::IsChildSelec
   nsAccessible* child = GetChildAt(aIndex);
   PRUint32 state = nsAccUtils::State(child);
   if (state & nsIAccessibleStates::STATE_SELECTED) {
     *aIsSelected = PR_TRUE;
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP nsAccessible::ClearSelection()
+NS_IMETHODIMP
+nsAccessible::ClearSelection()
 {
-  nsCOMPtr<nsIAccessible> selected = this;
-  while ((selected = GetNextWithState(selected, nsIAccessibleStates::STATE_SELECTED)) != nsnull) {
+  nsAccIterator iter(this, nsAccIterator::GetSelected, nsAccIterator::eTreeNav);
+  nsAccessible *selected = nsnull;
+  while ((selected = iter.GetNext()))
     selected->SetSelected(PR_FALSE);
-  }
+
   return NS_OK;
 }
 
 NS_IMETHODIMP nsAccessible::SelectAllSelection(PRBool *_retval)
 {
-  nsCOMPtr<nsIAccessible> selectable = this;
-  while ((selectable = GetNextWithState(selectable, nsIAccessibleStates::STATE_SELECTED)) != nsnull) {
+  nsAccIterator iter(this, nsAccIterator::GetSelectable, nsAccIterator::eTreeNav);
+  nsAccessible *selectable = nsnull;
+  while((selectable = iter.GetNext()))
     selectable->SetSelected(PR_TRUE);
-  }
+
   return NS_OK;
 }
 
 // nsIAccessibleHyperLink
 // Because of new-atk design, any embedded object in text can implement
 // nsIAccessibleHyperLink, which helps determine where it is located
 // within containing text
 
@@ -2636,26 +2616,34 @@ nsAccessible::GetAnchorCount(PRInt32 *aA
 }
 
 // readonly attribute long nsIAccessibleHyperLink::startIndex
 NS_IMETHODIMP
 nsAccessible::GetStartIndex(PRInt32 *aStartIndex)
 {
   NS_ENSURE_ARG_POINTER(aStartIndex);
   *aStartIndex = 0;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
   PRInt32 endIndex;
   return GetLinkOffset(aStartIndex, &endIndex);
 }
 
 // readonly attribute long nsIAccessibleHyperLink::endIndex
 NS_IMETHODIMP
 nsAccessible::GetEndIndex(PRInt32 *aEndIndex)
 {
   NS_ENSURE_ARG_POINTER(aEndIndex);
   *aEndIndex = 0;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
   PRInt32 startIndex;
   return GetLinkOffset(&startIndex, aEndIndex);
 }
 
 NS_IMETHODIMP
 nsAccessible::GetURI(PRInt32 aIndex, nsIURI **aURI)
 {
   NS_ENSURE_ARG_POINTER(aURI);
@@ -2714,42 +2702,38 @@ nsAccessible::GetValid(PRBool *aValid)
 NS_IMETHODIMP
 nsAccessible::GetSelected(PRBool *aSelected)
 {
   NS_ENSURE_ARG_POINTER(aSelected);
   *aSelected = (gLastFocusedNode == mDOMNode);
   return NS_OK;
 }
 
-nsresult nsAccessible::GetLinkOffset(PRInt32* aStartOffset, PRInt32* aEndOffset)
+nsresult
+nsAccessible::GetLinkOffset(PRInt32 *aStartOffset, PRInt32 *aEndOffset)
 {
-  *aStartOffset = *aEndOffset = 0;
-  nsAccessible* parent = GetParent();
-  if (!parent) {
-    return NS_ERROR_FAILURE;
-  }
-
-  nsCOMPtr<nsIAccessible> accessible, nextSibling;
+  nsAccessible *parent = GetParent();
+  NS_ENSURE_STATE(parent);
+
   PRInt32 characterCount = 0;
-  parent->GetFirstChild(getter_AddRefs(accessible));
-
-  while (accessible) {
-    if (nsAccUtils::IsText(accessible))
-      characterCount += nsAccUtils::TextLength(accessible);
-
-    else if (accessible == this) {
+
+  PRInt32 childCount = parent->GetChildCount();
+  for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
+    nsAccessible *sibling = parent->GetChildAt(childIdx);
+
+    if (sibling == this) {
       *aStartOffset = characterCount;
       *aEndOffset = characterCount + 1;
       return NS_OK;
     }
-    else {
+
+    if (nsAccUtils::IsText(sibling))
+      characterCount += nsAccUtils::TextLength(sibling);
+    else
       ++ characterCount;
-    }
-    accessible->GetNextSibling(getter_AddRefs(nextSibling));
-    accessible.swap(nextSibling);
   }
 
   return NS_ERROR_FAILURE;
 }
 
 nsresult
 nsAccessible::AppendTextTo(nsAString& aText, PRUint32 aStartOffset, PRUint32 aLength)
 {
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -241,16 +241,21 @@ public:
   virtual PRInt32 GetIndexOf(nsIAccessible *aChild);
 
   /**
    * Return index in parent accessible.
    */
   PRInt32 GetIndexInParent();
 
   /**
+   * Return true if accessible has children;
+   */
+  PRBool HasChildren() { return !!GetChildAt(0); }
+
+  /**
    * Return parent accessible only if cached.
    */
   nsAccessible* GetCachedParent();
 
   /**
    * Return first child accessible only if cached.
    */
   nsAccessible* GetCachedFirstChild();
@@ -320,18 +325,16 @@ protected:
   /**
    * Compute the name for XUL node.
    */
   nsresult GetXULName(nsAString& aName);
 
   // helper method to verify frames
   static nsresult GetFullKeyName(const nsAString& aModifierName, const nsAString& aKeyName, nsAString& aStringOut);
   static nsresult GetTranslatedString(const nsAString& aKey, nsAString& aStringOut);
-    
-  already_AddRefed<nsIAccessible> GetNextWithState(nsIAccessible *aStart, PRUint32 matchState);
 
   /**
    * Return an accessible for the given DOM node, or if that node isn't
    * accessible, return the accessible for the next DOM node which has one
    * (based on forward depth first search).
    *
    * @param  aStartNode  [in] the DOM node to start from
    * @return              the resulting accessible
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -1455,28 +1455,24 @@ nsDocAccessible::FireTextChangeEventForT
   if (!node)
     return;
 
   nsCOMPtr<nsIAccessible> accessible;
   nsresult rv = GetAccessibleInParentChain(node, PR_TRUE, getter_AddRefs(accessible));
   if (NS_FAILED(rv) || !accessible)
     return;
 
-  nsRefPtr<nsHyperTextAccessible> textAccessible;
-  rv = accessible->QueryInterface(NS_GET_IID(nsHyperTextAccessible),
-                                  getter_AddRefs(textAccessible));
-  if (NS_FAILED(rv) || !textAccessible)
+  nsRefPtr<nsHyperTextAccessible> textAccessible(do_QueryObject(accessible));
+  if (!textAccessible)
     return;
 
   PRInt32 start = aInfo->mChangeStart;
 
   PRInt32 offset = 0;
-  rv = textAccessible->DOMPointToHypertextOffset(node, start, &offset);
-  if (NS_FAILED(rv))
-    return;
+  textAccessible->DOMPointToHypertextOffset(node, start, &offset);
 
   PRInt32 length = aIsInserted ?
     aInfo->mReplaceLength: // text has been added
     aInfo->mChangeEnd - start; // text has been removed
 
   if (length > 0) {
     PRUint32 renderedStartOffset, renderedEndOffset;
     nsIFrame* frame = aContent->GetPrimaryFrame();
@@ -1506,63 +1502,56 @@ nsDocAccessible::FireTextChangeEventForT
 already_AddRefed<nsAccEvent>
 nsDocAccessible::CreateTextChangeEventForNode(nsIAccessible *aContainerAccessible,
                                               nsIDOMNode *aChangeNode,
                                               nsIAccessible *aAccessibleForChangeNode,
                                               PRBool aIsInserting,
                                               PRBool aIsAsynch,
                                               EIsFromUserInput aIsFromUserInput)
 {
-  nsRefPtr<nsHyperTextAccessible> textAccessible;
-  aContainerAccessible->QueryInterface(NS_GET_IID(nsHyperTextAccessible),
-                                       getter_AddRefs(textAccessible));
+  nsRefPtr<nsHyperTextAccessible> textAccessible =
+    do_QueryObject(aContainerAccessible);
   if (!textAccessible) {
     return nsnull;
   }
 
   PRInt32 offset;
   PRInt32 length = 0;
-  nsCOMPtr<nsIAccessible> changeAccessible;
-  nsresult rv = textAccessible->DOMPointToHypertextOffset(aChangeNode, -1, &offset,
-                                                          getter_AddRefs(changeAccessible));
-  NS_ENSURE_SUCCESS(rv, nsnull);
+  nsAccessible *changeAcc =
+    textAccessible->DOMPointToHypertextOffset(aChangeNode, -1, &offset);
 
   if (!aAccessibleForChangeNode) {
     // A span-level object or something else without an accessible is being removed, where
     // it has no accessible but it has descendant content which is aggregated as text
     // into the parent hypertext.
     // In this case, accessibleToBeRemoved may just be the first
     // accessible that is removed, which affects the text in the hypertext container
-    if (!changeAccessible) {
+    if (!changeAcc)
       return nsnull; // No descendant content that represents any text in the hypertext parent
-    }
 
     nsCOMPtr<nsINode> changeNode(do_QueryInterface(aChangeNode));
-    nsCOMPtr<nsIAccessible> child = changeAccessible;
-    while (PR_TRUE) {
-      nsCOMPtr<nsIAccessNode> childAccessNode =
-        do_QueryInterface(changeAccessible);
 
-      nsCOMPtr<nsIDOMNode> childDOMNode;
-      childAccessNode->GetDOMNode(getter_AddRefs(childDOMNode));
+    nsAccessible *parent = changeAcc->GetParent();
+    PRInt32 childCount = parent->GetChildCount();
+    PRInt32 changeAccIdx = parent->GetIndexOf(changeAcc);
 
-      nsCOMPtr<nsINode> childNode(do_QueryInterface(childDOMNode));
+    for (PRInt32 idx = changeAccIdx; idx < childCount; idx++) {
+      nsAccessible *child = parent->GetChildAt(idx);
+      nsCOMPtr<nsINode> childNode(do_QueryInterface(child->GetDOMNode()));
+
       if (!nsCoreUtils::IsAncestorOf(changeNode, childNode)) {
-        break;  // We only want accessibles with DOM nodes as children of this node
-      }
-      length += nsAccUtils::TextLength(child);
-      child->GetNextSibling(getter_AddRefs(changeAccessible));
-      if (!changeAccessible) {
+        // We only want accessibles with DOM nodes as children of this node
         break;
       }
-      child.swap(changeAccessible);
+
+      length += nsAccUtils::TextLength(child);
     }
   }
   else {
-    NS_ASSERTION(!changeAccessible || changeAccessible == aAccessibleForChangeNode,
+    NS_ASSERTION(!changeAcc || changeAcc == aAccessibleForChangeNode,
                  "Hypertext is reporting a different accessible for this node");
 
     length = nsAccUtils::TextLength(aAccessibleForChangeNode);
     if (nsAccUtils::Role(aAccessibleForChangeNode) == nsIAccessibleRole::ROLE_WHITESPACE) {  // newline
       // Don't fire event for the first html:br in an editor.
       nsCOMPtr<nsIEditor> editor;
       textAccessible->GetAssociatedEditor(getter_AddRefs(editor));
       if (editor) {
@@ -1809,19 +1798,18 @@ void nsDocAccessible::RefreshNodes(nsIDO
                                 accessible);
       }
     }
 
     // We only need to shutdown the accessibles here if one of them has been
     // created.
     if (accessible->GetCachedFirstChild()) {
       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.
+      // use GetChildren() to fetch all children at once, because after shutdown
+      // the child references are cleared.
       accessible->GetChildren(getter_AddRefs(children));
       PRUint32 childCount =0;
       if (children)
         children->GetLength(&childCount);
       nsCOMPtr<nsIDOMNode> possibleAnonNode;
       for (PRUint32 index = 0; index < childCount; index++) {
         nsCOMPtr<nsIAccessNode> childAccessNode;
         children->QueryElementAt(index, NS_GET_IID(nsIAccessNode),
--- a/accessible/src/base/nsRootAccessible.cpp
+++ b/accessible/src/base/nsRootAccessible.cpp
@@ -203,32 +203,27 @@ nsRootAccessible::GetStateInternal(PRUin
     //     how to detect that
     *aState |= nsIAccessibleStates::STATE_MOVEABLE;
   }
 #endif
 
   if (!aExtraState)
     return NS_OK;
 
-  nsCOMPtr<nsIDOMWindow> domWin;
-  GetWindow(getter_AddRefs(domWin));
-  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) {
+    nsCOMPtr<nsIDOMWindow> rootWindow;
+    GetWindow(getter_AddRefs(rootWindow));
 
-    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;
-    }
+    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
 
   return NS_OK;
 }
--- a/accessible/src/base/nsTextAttrs.cpp
+++ b/accessible/src/base/nsTextAttrs.cpp
@@ -209,21 +209,18 @@ nsTextAttrsMgr::GetRange(const nsTPtrArr
 
     if (currNode != mOffsetNode) {
       PRBool stop = PR_FALSE;
       for (PRUint32 idx = 0; idx < len; idx++) {
         nsITextAttr *textAttr = aTextAttrArray[idx];
         if (!textAttr->Equal(currElm)) {
 
           PRInt32 startHTOffset = 0;
-          nsCOMPtr<nsIAccessible> startAcc;
-          nsresult rv = mHyperTextAcc->
-            DOMPointToHypertextOffset(tmpNode, -1, &startHTOffset,
-                                      getter_AddRefs(startAcc));
-          NS_ENSURE_SUCCESS(rv, rv);
+          nsAccessible *startAcc = mHyperTextAcc->
+            DOMPointToHypertextOffset(tmpNode, -1, &startHTOffset);
 
           if (!startAcc)
             startHTOffset = 0;
 
           if (startHTOffset > *aStartHTOffset)
             *aStartHTOffset = startHTOffset;
 
           stop = PR_TRUE;
@@ -257,19 +254,17 @@ nsTextAttrsMgr::GetRange(const nsTPtrArr
     // Stop new end offset searching if the given text attribute changes its
     // value.
     PRBool stop = PR_FALSE;
     for (PRUint32 idx = 0; idx < len; idx++) {
       nsITextAttr *textAttr = aTextAttrArray[idx];
       if (!textAttr->Equal(currElm)) {
 
         PRInt32 endHTOffset = 0;
-        nsresult rv = mHyperTextAcc->
-          DOMPointToHypertextOffset(currNode, -1, &endHTOffset);
-        NS_ENSURE_SUCCESS(rv, rv);
+        mHyperTextAcc->DOMPointToHypertextOffset(currNode, -1, &endHTOffset);
 
         if (endHTOffset < *aEndHTOffset)
           *aEndHTOffset = endHTOffset;
 
         stop = PR_TRUE;
         break;
       }
     }
@@ -312,20 +307,17 @@ nsTextAttrsMgr::FindEndOffsetInSubtree(c
 
   // If the given text attribute (pointed by nsTextAttr object) changes its
   // value on the traversed element then fit the end of range.
   PRUint32 len = aTextAttrArray.Length();
   for (PRUint32 idx = 0; idx < len; idx++) {
     nsITextAttr *textAttr = aTextAttrArray[idx];
     if (!textAttr->Equal(currElm)) {
       PRInt32 endHTOffset = 0;
-      nsresult rv = mHyperTextAcc->
-        DOMPointToHypertextOffset(aCurrNode, -1, &endHTOffset);
-      NS_ENSURE_SUCCESS(rv, PR_FALSE);
-
+      mHyperTextAcc->DOMPointToHypertextOffset(aCurrNode, -1, &endHTOffset);
       if (endHTOffset < *aHTOffset)
         *aHTOffset = endHTOffset;
 
       return PR_TRUE;
     }
   }
 
   // Deeply traverse into the tree to fit the end of range.
@@ -370,21 +362,18 @@ nsTextAttrsMgr::FindStartOffsetInSubtree
   // If the given text attribute (pointed by nsTextAttr object) changes its
   // value on the traversed element then fit the start of range.
   PRUint32 len = aTextAttrArray.Length();
   for (PRUint32 idx = 0; idx < len; idx++) {
     nsITextAttr *textAttr = aTextAttrArray[idx];
     if (!textAttr->Equal(currElm)) {
 
       PRInt32 startHTOffset = 0;
-      nsCOMPtr<nsIAccessible> startAcc;
-      nsresult rv = mHyperTextAcc->
-        DOMPointToHypertextOffset(aPrevNode, -1, &startHTOffset,
-                                  getter_AddRefs(startAcc));
-      NS_ENSURE_SUCCESS(rv, PR_FALSE);
+      nsAccessible *startAcc = mHyperTextAcc->
+        DOMPointToHypertextOffset(aPrevNode, -1, &startHTOffset);
 
       if (!startAcc)
         startHTOffset = 0;
 
       if (startHTOffset > *aHTOffset)
         *aHTOffset = startHTOffset;
 
       return PR_TRUE;
--- a/accessible/src/base/nsTextEquivUtils.cpp
+++ b/accessible/src/base/nsTextEquivUtils.cpp
@@ -231,26 +231,24 @@ nsTextEquivUtils::AppendTextEquivFromTex
 // nsTextEquivUtils. Private.
 
 nsCOMPtr<nsIAccessible> nsTextEquivUtils::gInitiatorAcc;
 
 nsresult
 nsTextEquivUtils::AppendFromAccessibleChildren(nsIAccessible *aAccessible,
                                                nsAString *aString)
 {
-  nsCOMPtr<nsIAccessible> accChild, accNextChild;
-  aAccessible->GetFirstChild(getter_AddRefs(accChild));
+  nsresult rv = NS_OK_NO_NAME_CLAUSE_HANDLED;
 
-  nsresult rv = NS_OK_NO_NAME_CLAUSE_HANDLED;
-  while (accChild) {
-    rv = AppendFromAccessible(accChild, aString);
+  nsRefPtr<nsAccessible> accessible(do_QueryObject(aAccessible));
+  PRInt32 childCount = accessible->GetChildCount();
+  for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
+    nsAccessible *child = accessible->GetChildAt(childIdx);
+    rv = AppendFromAccessible(child, aString);
     NS_ENSURE_SUCCESS(rv, rv);
-
-    accChild->GetNextSibling(getter_AddRefs(accNextChild));
-    accChild.swap(accNextChild);
   }
 
   return rv;
 }
 
 nsresult
 nsTextEquivUtils::AppendFromAccessible(nsIAccessible *aAccessible,
                                        nsAString *aString)
--- a/accessible/src/html/nsHTMLImageAccessible.cpp
+++ b/accessible/src/html/nsHTMLImageAccessible.cpp
@@ -180,17 +180,17 @@ nsHTMLImageAccessible::DoAction(PRUint8 
     nsCOMPtr<nsIDOMDocument> domDocument;
     rv = mDOMNode->GetOwnerDocument(getter_AddRefs(domDocument));
     NS_ENSURE_SUCCESS(rv, rv);
     nsCOMPtr<nsIDocument> document(do_QueryInterface(domDocument));
     nsCOMPtr<nsPIDOMWindow> piWindow = document->GetWindow();
     nsCOMPtr<nsIDOMWindowInternal> win(do_QueryInterface(piWindow));
     NS_ENSURE_TRUE(win, NS_ERROR_FAILURE);
     nsCOMPtr<nsIDOMWindow> tmp;
-    return win->Open(longDesc, NS_LITERAL_STRING(""), NS_LITERAL_STRING(""),
+    return win->Open(longDesc, EmptyString(), EmptyString(),
                      getter_AddRefs(tmp));
   }
   return nsLinkableAccessible::DoAction(aIndex);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessibleImage
 
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -518,71 +518,67 @@ NS_IMETHODIMP nsHyperTextAccessible::Get
 
   if (text.IsEmpty()) {
     return NS_ERROR_FAILURE;
   }
   *aCharacter = text.First();
   return NS_OK;
 }
 
-nsresult nsHyperTextAccessible::DOMPointToHypertextOffset(nsIDOMNode* aNode, PRInt32 aNodeOffset,
-                                                          PRInt32* aHyperTextOffset,
-                                                          nsIAccessible **aFinalAccessible,
-                                                          PRBool aIsEndOffset)
+nsAccessible*
+nsHyperTextAccessible::DOMPointToHypertextOffset(nsIDOMNode *aNode,
+                                                 PRInt32 aNodeOffset,
+                                                 PRInt32 *aHyperTextOffset,
+                                                 PRBool aIsEndOffset)
 {
-  // Turn a DOM Node and offset into an offset into this hypertext.
-  // On failure, return null. On success, return the DOM node which contains the offset.
-  NS_ENSURE_ARG_POINTER(aHyperTextOffset);
+  if (!aHyperTextOffset)
+    return nsnull;
   *aHyperTextOffset = 0;
 
-  if (!aNode) {
-    return NS_ERROR_FAILURE;
-  }
-  if (aFinalAccessible) {
-    *aFinalAccessible = nsnull;
-  }
+  if (!aNode)
+    return nsnull;
 
   PRUint32 addTextOffset = 0;
   nsCOMPtr<nsIDOMNode> findNode;
 
   unsigned short nodeType;
   aNode->GetNodeType(&nodeType);
   if (aNodeOffset == -1) {
     findNode = aNode;
   }
   else if (nodeType == nsIDOMNode::TEXT_NODE) {
     // For text nodes, aNodeOffset comes in as a character offset
     // Text offset will be added at the end, if we find the offset in this hypertext
     // We want the "skipped" offset into the text (rendered text without the extra whitespace)
     nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
     NS_ASSERTION(content, "No nsIContent for dom node");
     nsIFrame *frame = content->GetPrimaryFrame();
-    NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
+    NS_ENSURE_TRUE(frame, nsnull);
     nsresult rv = ContentToRenderedOffset(frame, aNodeOffset, &addTextOffset);
-    NS_ENSURE_SUCCESS(rv, rv);
+    NS_ENSURE_SUCCESS(rv, nsnull);
     // Get the child node and 
     findNode = aNode;
   }
   else {
     // For non-text nodes, aNodeOffset comes in as a child node index
     nsCOMPtr<nsIContent> parentContent(do_QueryInterface(aNode));
     // Should not happen, but better to protect against crash if doc node is somehow passed in
-    NS_ENSURE_TRUE(parentContent, NS_ERROR_FAILURE);
+    NS_ENSURE_TRUE(parentContent, nsnull);
     // findNode could be null if aNodeOffset == # of child nodes, which means one of two things:
     // 1) we're at the end of the children, keep findNode = null, so that we get the last possible offset
     // 2) there are no children and the passed-in node is mDOMNode, which means we're an aempty nsIAccessibleText
     // 3) there are no children, and the passed-in node is not mDOMNode -- use parentContent for the node to find
      
     findNode = do_QueryInterface(parentContent->GetChildAt(aNodeOffset));
     if (!findNode && !aNodeOffset) {
       if (SameCOMIdentity(parentContent, mDOMNode)) {
         // There are no children, which means this is an empty nsIAccessibleText, in which
         // case we can only be at hypertext offset 0
         *aHyperTextOffset = 0;
-        return NS_OK;
+        return nsnull;
       }
       findNode = do_QueryInterface(parentContent); // Case #2: there are no children
     }
   }
 
   // Get accessible for this findNode, or if that node isn't accessible, use the
   // accessible for the next DOM node which has one (based on forward depth first search)
   nsRefPtr<nsAccessible> descendantAcc;
@@ -591,17 +587,17 @@ nsresult nsHyperTextAccessible::DOMPoint
     if (findContent->IsHTML() && 
         findContent->NodeInfo()->Equals(nsAccessibilityAtoms::br) &&
         findContent->AttrValueIs(kNameSpaceID_None,
                                  nsAccessibilityAtoms::mozeditorbogusnode,
                                  nsAccessibilityAtoms::_true,
                                  eIgnoreCase)) {
       // This <br> is the hacky "bogus node" used when there is no text in a control
       *aHyperTextOffset = 0;
-      return NS_OK;
+      return nsnull;
     }
     descendantAcc = GetFirstAvailableAccessible(findNode);
   }
 
   // From the descendant, go up and get the immediate child of this hypertext
   nsRefPtr<nsAccessible> childAccAtOffset;
   while (descendantAcc) {
     nsRefPtr<nsAccessible> parentAcc = descendantAcc->GetParent();
@@ -651,25 +647,24 @@ nsresult nsHyperTextAccessible::DOMPoint
     *aHyperTextOffset += textLength;
   }
 
   if (childIdx < childCount) {
     *aHyperTextOffset += addTextOffset;
     NS_ASSERTION(childAcc == childAccAtOffset,
                  "These should be equal whenever we exit loop and childAcc != nsnull");
 
-    if (aFinalAccessible &&
-        (childIdx < childCount - 1 ||
-         static_cast<PRInt32>(addTextOffset) < nsAccUtils::TextLength(childAccAtOffset))) {  
+    if (childIdx < childCount - 1 ||
+        static_cast<PRInt32>(addTextOffset) < nsAccUtils::TextLength(childAccAtOffset)) {
       // If not at end of last text node, we will return the accessible we were in
-      NS_ADDREF(*aFinalAccessible = childAccAtOffset);
+      return childAccAtOffset;
     }
   }
 
-  return NS_OK;
+  return nsnull;
 }
 
 nsresult
 nsHyperTextAccessible::HypertextOffsetToDOMPoint(PRInt32 aHTOffset,
                                                  nsIDOMNode **aNode,
                                                  PRInt32 *aOffset)
 {
   nsCOMPtr<nsIDOMNode> endNode;
@@ -811,23 +806,21 @@ nsHyperTextAccessible::GetRelativeOffset
     }
   }
 
   // Turn the resulting node and offset into a hyperTextOffset
   PRInt32 hyperTextOffset;
   nsCOMPtr<nsIDOMNode> resultNode = do_QueryInterface(pos.mResultContent);
   NS_ENSURE_TRUE(resultNode, -1);
 
-  nsCOMPtr<nsIAccessible> finalAccessible;
-  rv = DOMPointToHypertextOffset(resultNode, pos.mContentOffset, &hyperTextOffset,
-                                 getter_AddRefs(finalAccessible),
-                                 aDirection == eDirNext);
-  // If finalAccessible == nsnull, then DOMPointToHypertextOffset() searched through the hypertext
-  // children without finding the node/offset position
-  NS_ENSURE_SUCCESS(rv, -1);
+  // If finalAccessible is nsnull, then DOMPointToHypertextOffset() searched
+  // through the hypertext children without finding the node/offset position.
+  nsAccessible *finalAccessible =
+    DOMPointToHypertextOffset(resultNode, pos.mContentOffset, &hyperTextOffset,
+                              aDirection == eDirNext);
 
   if (!finalAccessible && aDirection == eDirPrevious) {
     // If we reached the end during search, this means we didn't find the DOM point
     // and we're actually at the start of the paragraph
     hyperTextOffset = 0;
   }  
   else if (aAmount == eSelectBeginLine) {
     nsAccessible *firstChild = mChildren.SafeElementAt(0, nsnull);
@@ -1104,32 +1097,69 @@ nsHyperTextAccessible::GetTextAttributes
 
   NS_ENSURE_ARG_POINTER(aStartOffset);
   *aStartOffset = 0;
 
   NS_ENSURE_ARG_POINTER(aEndOffset);
   nsresult rv = GetCharacterCount(aEndOffset);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
   if (aAttributes) {
     *aAttributes = nsnull;
 
     nsCOMPtr<nsIPersistentProperties> attributes =
       do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
     NS_ENSURE_TRUE(attributes, NS_ERROR_OUT_OF_MEMORY);
 
     NS_ADDREF(*aAttributes = attributes);
   }
 
-  if (!mDOMNode)
-    return NS_ERROR_FAILURE;
+  // Offset 0 is correct offset when accessible has empty text. Include
+  // default attributes if they were requested, otherwise return empty set.
+  if (aOffset == 0) {
+    // XXX: bug 567321. We handle here the cases when there are no children
+    // or when existing children have zero length.
+    PRBool isEmpty = PR_TRUE;
+    PRInt32 childCount = GetChildCount();
+    for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
+      nsAccessible *child = mChildren[childIdx];
+      if (!nsAccUtils::IsText(child) || nsAccUtils::TextLength(child) > 0) {
+        isEmpty = PR_FALSE;
+        break;
+      }
+    }
+
+    if (isEmpty) {
+      if (aIncludeDefAttrs) {
+        nsTextAttrsMgr textAttrsMgr(this, mDOMNode, PR_TRUE, nsnull);
+        return textAttrsMgr.GetAttributes(*aAttributes);
+      }
+
+      return NS_OK;
+    }
+  }
+
+  // Get the frame and accessible at the given offset.
+  PRInt32 startOffset = aOffset, endOffset = aOffset;
+  nsCOMPtr<nsIAccessible> startAcc;
+  nsIFrame *startFrame = GetPosAndText(startOffset, endOffset,
+                                       nsnull, nsnull, nsnull,
+                                       getter_AddRefs(startAcc), nsnull);
+
+  // No start frame or accessible means wrong given offset.
+  if (!startFrame || !startAcc)
+    return NS_ERROR_INVALID_ARG;
 
   nsCOMPtr<nsIDOMNode> node;
   PRInt32 nodeOffset = 0;
-  rv = HypertextOffsetToDOMPoint(aOffset, getter_AddRefs(node), &nodeOffset);
+  rv = GetDOMPointByFrameOffset(startFrame, startOffset, startAcc,
+                                getter_AddRefs(node), &nodeOffset);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Set 'misspelled' text attribute.
   rv = GetSpellTextAttribute(node, nodeOffset, aStartOffset, aEndOffset,
                              aAttributes ? *aAttributes : nsnull);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIContent> content(do_QueryInterface(node));
@@ -1625,17 +1655,18 @@ nsHyperTextAccessible::GetCaretOffset(PR
       nsCoreUtils::GetDOMNodeFromDOMPoint(focusNode, focusOffset);
 
     nsCOMPtr<nsINode> resultNode(do_QueryInterface(resultDOMNode));
     if (resultNode != thisNode &&
         !nsCoreUtils::IsAncestorOf(thisNode, resultNode))
       return NS_OK;
   }
 
-  return DOMPointToHypertextOffset(focusNode, focusOffset, aCaretOffset);
+  DOMPointToHypertextOffset(focusNode, focusOffset, aCaretOffset);
+  return NS_OK;
 }
 
 PRInt32 nsHyperTextAccessible::GetCaretLineNumber()
 {
   // Provide the line number for the caret, relative to the
   // currently focused node. Use a 1-based index
   nsCOMPtr<nsISelection> domSel;
   GetSelections(nsISelectionController::SELECTION_NORMAL, nsnull,
@@ -1848,24 +1879,24 @@ NS_IMETHODIMP nsHyperTextAccessible::Get
     // Make sure start is before end, by swapping offsets
     // This occurs when the user selects backwards in the text
     startNode.swap(endNode);
     PRInt32 tempOffset = startOffset;
     startOffset = endOffset;
     endOffset = tempOffset;
   }
 
-  nsCOMPtr<nsIAccessible> startAccessible;
-  rv = DOMPointToHypertextOffset(startNode, startOffset, aStartOffset, getter_AddRefs(startAccessible));
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsAccessible *startAccessible =
+    DOMPointToHypertextOffset(startNode, startOffset, aStartOffset);
   if (!startAccessible) {
     *aStartOffset = 0; // Could not find start point within this hypertext, so starts before
   }
 
-  return DOMPointToHypertextOffset(endNode, endOffset, aEndOffset, nsnull, PR_TRUE);
+  DOMPointToHypertextOffset(endNode, endOffset, aEndOffset, PR_TRUE);
+  return NS_OK;
 }
 
 /*
  * Changes the start and end offset of the specified selection.
  */
 NS_IMETHODIMP
 nsHyperTextAccessible::SetSelectionBounds(PRInt32 aSelectionNum,
                                           PRInt32 aStartOffset,
@@ -2171,20 +2202,18 @@ nsHyperTextAccessible::DOMRangeBoundToHy
   } else {
     rv = aRange->GetEndContainer(getter_AddRefs(node));
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = aRange->GetEndOffset(&nodeOffset);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  nsCOMPtr<nsIAccessible> startAcc;
-  rv = DOMPointToHypertextOffset(node, nodeOffset, aHTOffset,
-                                 getter_AddRefs(startAcc));
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsAccessible *startAcc =
+    DOMPointToHypertextOffset(node, nodeOffset, aHTOffset);
 
   if (aIsStartHTOffset && !startAcc)
     *aHTOffset = 0;
 
   return NS_OK;
 }
 
 // nsHyperTextAccessible
--- a/accessible/src/html/nsHyperTextAccessible.h
+++ b/accessible/src/html/nsHyperTextAccessible.h
@@ -103,32 +103,32 @@ public:
     *
     * @param aNode - the node to look for
     * @param aNodeOffset - the offset to look for
     *                      if -1 just look directly for the node
     *                      if >=0 and aNode is text, this represents a char offset
     *                      if >=0 and aNode is not text, this represents a child node offset
     * @param aResultOffset - the character offset into the current
     *                        nsHyperTextAccessible
-    * @param aFinalAccessible [optional] - returns the accessible child which
-    *                                      contained the offset, if it is within
-    *                                      the current nsHyperTextAccessible,
-    *                                      otherwise it is set to nsnull.
     * @param aIsEndOffset - if PR_TRUE, then then this offset is not inclusive. The character
     *                       indicated by the offset returned is at [offset - 1]. This means
     *                       if the passed-in offset is really in a descendant, then the offset returned
     *                       will come just after the relevant embedded object characer.
     *                       If PR_FALSE, then the offset is inclusive. The character indicated
     *                       by the offset returned is at [offset]. If the passed-in offset in inside a
     *                       descendant, then the returned offset will be on the relevant embedded object char.
+    *
+    * @return               the accessible child which contained the offset, if
+    *                       it is within the current nsHyperTextAccessible,
+    *                       otherwise nsnull
     */
-  nsresult DOMPointToHypertextOffset(nsIDOMNode* aNode, PRInt32 aNodeOffset,
-                                     PRInt32 *aHypertextOffset,
-                                     nsIAccessible **aFinalAccessible = nsnull,
-                                     PRBool aIsEndOffset = PR_FALSE);
+  nsAccessible *DOMPointToHypertextOffset(nsIDOMNode *aNode,
+                                          PRInt32 aNodeOffset,
+                                          PRInt32 *aHypertextOffset,
+                                          PRBool aIsEndOffset = PR_FALSE);
 
   /**
    * Turn a hypertext offsets into DOM point.
    *
    * @param  aHTOffset  [in] the given start hypertext offset
    * @param  aNode      [out] start node
    * @param  aOffset    [out] offset inside the start node
    */
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -385,36 +385,31 @@ nsAccessibleWrap::get_accDescription(VAR
     if (groupLevel > 0) {
       // XXX: How do we calculate the number of children? Now we append
       // " with [numChildren]c" for tree item. In the future we may need to
       // use the ARIA owns property to calculate that if it's present.
       PRInt32 numChildren = 0;
 
       PRUint32 currentRole = nsAccUtils::Role(xpAccessible);
       if (currentRole == nsIAccessibleRole::ROLE_OUTLINEITEM) {
-        nsCOMPtr<nsIAccessible> child;
-        xpAccessible->GetFirstChild(getter_AddRefs(child));
-        while (child) {
+        PRInt32 childCount = xpAccessible->GetChildCount();
+        for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
+          nsAccessible *child = xpAccessible->GetChildAt(childIdx);
           currentRole = nsAccUtils::Role(child);
           if (currentRole == nsIAccessibleRole::ROLE_GROUPING) {
-            nsCOMPtr<nsIAccessible> groupChild;
-            child->GetFirstChild(getter_AddRefs(groupChild));
-            while (groupChild) {
+            PRInt32 groupChildCount = child->GetChildCount();
+            for (PRInt32 groupChildIdx = 0; groupChildIdx < groupChildCount;
+                 groupChildIdx++) {
+              nsAccessible *groupChild = child->GetChildAt(groupChildIdx);
               currentRole = nsAccUtils::Role(groupChild);
               numChildren +=
                 (currentRole == nsIAccessibleRole::ROLE_OUTLINEITEM);
-              nsCOMPtr<nsIAccessible> nextGroupChild;
-              groupChild->GetNextSibling(getter_AddRefs(nextGroupChild));
-              groupChild.swap(nextGroupChild);
             }
             break;
           }
-          nsCOMPtr<nsIAccessible> nextChild;
-          child->GetNextSibling(getter_AddRefs(nextChild));
-          child.swap(nextChild);
         }
       }
 
       if (numChildren) {
         nsTextFormatter::ssprintf(description,
                                   NS_LITERAL_STRING("L%d, %d of %d with %d").get(),
                                   groupLevel, positionInGroup, itemsInGroup,
                                   numChildren);
--- a/accessible/src/xforms/nsXFormsAccessible.cpp
+++ b/accessible/src/xforms/nsXFormsAccessible.cpp
@@ -548,49 +548,42 @@ nsXFormsSelectableAccessible::SelectAllS
   *aMultipleSelection = PR_TRUE;
   return sXFormsService->SelectAllItemsForSelect(mDOMNode);
 }
 
 already_AddRefed<nsIDOMNode>
 nsXFormsSelectableAccessible::GetItemByIndex(PRInt32 *aIndex,
                                              nsIAccessible *aAccessible)
 {
-  nsCOMPtr<nsIAccessible> accessible(aAccessible ? aAccessible : this);
+  nsRefPtr<nsAccessible> accessible(do_QueryObject(aAccessible));
+  if (!accessible)
+    accessible = this;
 
-  nsCOMPtr<nsIAccessible> curAccChild;
-  accessible->GetFirstChild(getter_AddRefs(curAccChild));
+  PRInt32 childCount = accessible->GetChildCount();
+  for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
+    nsAccessible *child = accessible->GetChildAt(childIdx);
 
-  while (curAccChild) {
-    nsCOMPtr<nsIAccessNode> curAccNodeChild(do_QueryInterface(curAccChild));
-    if (curAccNodeChild) {
-      nsCOMPtr<nsIDOMNode> curChildNode;
-      curAccNodeChild->GetDOMNode(getter_AddRefs(curChildNode));
-      nsCOMPtr<nsIContent> curChildContent(do_QueryInterface(curChildNode));
-      if (curChildContent) {
-        nsCOMPtr<nsINodeInfo> nodeInfo = curChildContent->NodeInfo();
-        if (nodeInfo->NamespaceEquals(NS_LITERAL_STRING(NS_NAMESPACE_XFORMS))) {
-          if (nodeInfo->Equals(nsAccessibilityAtoms::item)) {
-            if (!*aIndex) {
-              nsIDOMNode *itemNode = nsnull;
-              curChildNode.swap(itemNode);
-              return itemNode;
-            }
-            --*aIndex;
-          } else if (nodeInfo->Equals(nsAccessibilityAtoms::choices)) {
-            nsIDOMNode *itemNode = GetItemByIndex(aIndex, curAccChild).get();
-            if (itemNode)
-              return itemNode;
-          }
-        }
+    nsCOMPtr<nsIDOMNode> childNode(child->GetDOMNode());
+    nsCOMPtr<nsIContent> childContent(do_QueryInterface(childNode));
+    if (!childContent)
+      continue;
+
+    nsINodeInfo *nodeInfo = childContent->NodeInfo();
+    if (nodeInfo->NamespaceEquals(NS_LITERAL_STRING(NS_NAMESPACE_XFORMS))) {
+      if (nodeInfo->Equals(nsAccessibilityAtoms::item)) {
+        if (!*aIndex)
+          return childNode.forget();
+
+        --*aIndex;
+      } else if (nodeInfo->Equals(nsAccessibilityAtoms::choices)) {
+        nsIDOMNode *itemNode = GetItemByIndex(aIndex, child).get();
+        if (itemNode)
+          return itemNode;
       }
     }
-
-    nsCOMPtr<nsIAccessible> nextAccChild;
-    curAccChild->GetNextSibling(getter_AddRefs(nextAccChild));
-    curAccChild.swap(nextAccChild);
   }
 
   return nsnull;
 }
 
 
 // nsXFormsSelectableItemAccessible
 
--- a/accessible/src/xul/nsXULListboxAccessible.cpp
+++ b/accessible/src/xul/nsXULListboxAccessible.cpp
@@ -1144,35 +1144,33 @@ nsXULListCellAccessible::GetColumnHeader
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsIAccessibleTable> table;
   GetTable(getter_AddRefs(table));
   NS_ENSURE_STATE(table); // we expect to be in a listbox (table)
 
   // Get column header cell from XUL listhead.
-  nsCOMPtr<nsIAccessible> tableAcc(do_QueryInterface(table));
+  nsAccessible *list = nsnull;
 
-  nsCOMPtr<nsIAccessible> list, nextChild;
-  tableAcc->GetFirstChild(getter_AddRefs(list));
-  while (list) {
-    if (nsAccUtils::Role(list) == nsIAccessibleRole::ROLE_LIST)
+  nsRefPtr<nsAccessible> tableAcc(do_QueryObject(table));
+  PRInt32 tableChildCount = tableAcc->GetChildCount();
+  for (PRInt32 childIdx = 0; childIdx < tableChildCount; childIdx++) {
+    nsAccessible *child = tableAcc->GetChildAt(childIdx);
+    if (nsAccUtils::Role(child) == nsIAccessibleRole::ROLE_LIST) {
+      list = child;
       break;
-
-    list->GetNextSibling(getter_AddRefs(nextChild));
-    nextChild.swap(list);
+    }
   }
 
   if (list) {
     PRInt32 colIdx = -1;
     GetColumnIndex(&colIdx);
 
-    nsCOMPtr<nsIAccessible> headerCell;
-    list->GetChildAt(colIdx, getter_AddRefs(headerCell));
-
+    nsIAccessible *headerCell = list->GetChildAt(colIdx);
     if (headerCell) {
       nsresult rv = NS_OK;
       nsCOMPtr<nsIMutableArray> headerCells =
         do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
       NS_ENSURE_SUCCESS(rv, rv);
 
       headerCells->AppendElement(headerCell, PR_FALSE);
       NS_ADDREF(*aHeaderCells = headerCells);
--- a/accessible/tests/mochitest/Makefile.in
+++ b/accessible/tests/mochitest/Makefile.in
@@ -37,17 +37,17 @@
 # ***** END LICENSE BLOCK *****
 
 DEPTH		= ../../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = accessible
 
-DIRS	= actions attributes events relations selectable states tree
+DIRS	= actions attributes events relations selectable states table tree
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =\
 		formimage.png \
 		letters.gif \
 		moz.png \
@@ -63,16 +63,17 @@ include $(topsrcdir)/config/rules.mk
 		name.css \
 		name.js \
 		name.xbl \
 		name_nsRootAcc_wnd.xul \
 		namerules.xml \
  		nsIAccessible_selects.js \
 		relations.js \
 		role.js \
+		selectable.js \
 		states.js \
 		table.js \
 		value.js \
 		test_aria_activedescendant.html \
 		test_aria_role_article.html \
 		test_aria_role_equation.html \
 		test_aria_roles.html \
 		test_aria_roles.xul \
@@ -100,36 +101,16 @@ include $(topsrcdir)/config/rules.mk
 		test_nsIAccessibleDocument.html \
 		test_nsIAccessibleHyperLink.html \
 		test_nsIAccessibleHyperLink.xul \
 		test_nsIAccessibleHyperText.html \
 		test_nsIAccessibleImage.html \
 		test_nsIAccessNode_utils.html \
 		test_nsOuterDocAccessible.html \
 		test_role_nsHyperTextAcc.html \
-		test_table_1.html \
-		test_table_4.html \
-		test_table_headers.html \
-		test_table_headers_ariagrid.html \
-		test_table_headers_listbox.xul \
-		test_table_headers_tree.xul \
-		test_table_indexes.html \
-		test_table_indexes_ariagrid.html \
-		test_table_indexes_listbox.xul \
-		test_table_indexes_tree.xul \
-		test_table_layoutguess.html \
-		test_table_sels.html \
-		test_table_sels_ariagrid.html \
-		test_table_sels_listbox.xul \
-		test_table_sels_tree.xul \
-		test_table_struct.html \
-		test_table_struct_ariagrid.html \
-		test_table_struct_ariatreegrid.html \
-		test_table_struct_listbox.xul \
-		test_table_struct_tree.xul \
 		test_text_caret.html \
 		test_textboxes.html \
 		test_textboxes.xul \
 		test_value.html \
 		test_value.xul \
 		testTextboxes.js \
 		treeview.css \
 		treeview.js \
--- a/accessible/tests/mochitest/attributes.js
+++ b/accessible/tests/mochitest/attributes.js
@@ -155,16 +155,72 @@ function testDefaultTextAttrs(aID, aDefA
     ok(false, "Can't get default text attributes for " + aID);
     return;
   }
   
   var errorMsg = ". Getting default text attributes for " + aID;
   compareAttrs(errorMsg, defAttrs, aDefAttrs, aSkipUnexpectedAttrs);
 }
 
+/**
+ * Test text attributes for wrong offset.
+ */
+function testTextAttrsWrongOffset(aID, aOffset)
+{
+  var res = false;
+  try {
+  var s = {}, e = {};
+  var acc = getAccessible(ID, [nsIAccessibleText]);
+    acc.getTextAttributes(false, 157, s, e);
+  } catch (e) {
+    res = true;
+  }
+
+  ok(res,
+     "text attributes are calculated successfully at wrong offset " + aOffset + " for " + prettyName(aID));
+}
+
+const kNormalFontWeight =
+  function equalsToNormal(aWeight) { return aWeight <= 400 ; }
+
+const kBoldFontWeight =
+  function equalsToBold(aWeight) { return aWeight > 400; }
+
+// The pt font size of the input element can vary by Linux distro.
+const kInputFontSize = WIN ?
+  "10pt" : (MAC ? "8pt" : function() { return true; });
+
+/**
+ * Build an object of default text attributes expected for the given accessible.
+ *
+ * @param aID          [in] identifier of accessible
+ * @param aFontSize    [in] font size
+ * @param aFontWeight  [in, optional] kBoldFontWeight or kNormalFontWeight,
+ *                      default value is kNormalFontWeight
+ */
+function buildDefaultTextAttrs(aID, aFontSize, aFontWeight)
+{
+  var elm = getNode(aID);
+  var computedStyle = document.defaultView.getComputedStyle(elm, "");
+  var bgColor = computedStyle.backgroundColor == "transparent" ?
+    "rgb(255, 255, 255)" : computedStyle.backgroundColor;
+
+  var defAttrs = {
+    "font-style": computedStyle.fontStyle,
+    "font-size": aFontSize,
+    "background-color": bgColor,
+    "font-weight": aFontWeight ? aFontWeight : kNormalFontWeight,
+    "color": computedStyle.color,
+    "font-family": computedStyle.fontFamily,
+    "text-position": computedStyle.verticalAlign
+  };
+
+  return defAttrs;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Private.
 
 function getTextAttributes(aID, aAccessible, aIncludeDefAttrs, aOffset,
                            aStartOffset, aEndOffset)
 {
   // This function expects the passed in accessible to already be queried for
   // nsIAccessibleText.
--- a/accessible/tests/mochitest/attributes/test_text.html
+++ b/accessible/tests/mochitest/attributes/test_text.html
@@ -18,26 +18,16 @@
 
   <script type="application/javascript">
 
     const nsIDOMNSEditableElement =
       Components.interfaces.nsIDOMNSEditableElement;
 
     var gComputedStyle = null;
 
-    function equalsToNormal(aWeight)
-    {
-      return aWeight <= 400;
-    }
-
-    function equalsToBold(aWeight)
-    {
-      return aWeight > 400;
-    }
-
     var gTextAttrChangedEventHandler = {
       handleEvent: function gTextAttrChangedEventHandler_handleEvent(aEvent)
       {
         this.eventNumber++;
       },
 
       eventNumber: 0
     };
@@ -54,27 +44,17 @@
       node.focus();
 
       var editor = node.QueryInterface(nsIDOMNSEditableElement).editor;
       var spellchecker = editor.getInlineSpellChecker(true);
       spellchecker.enableRealTimeSpell = true;
 
       window.setTimeout(function()
         {
-          gComputedStyle = document.defaultView.getComputedStyle(node, "");
-          var defAttrs = {
-            "font-style": gComputedStyle.fontStyle,
-            // The pt font size of the input element can vary by Linux distro.
-            "font-size": (WIN ? "10pt" : (MAC ? "8pt" : function() { return true; })),
-            "background-color": gComputedStyle.backgroundColor,
-            "font-weight": equalsToNormal,
-            "color": gComputedStyle.color,
-            "font-family": gComputedStyle.fontFamily,
-            "text-position": gComputedStyle.verticalAlign
-          };
+          var defAttrs = buildDefaultTextAttrs(node, kInputFontSize);
           testDefaultTextAttrs(ID, defAttrs);
 
           var attrs = { };
           var misspelledAttrs = {
             "invalid": "spelling"
           };
 
           testTextAttrs(ID, 0, attrs, defAttrs, 0, 11);
@@ -92,98 +72,59 @@
         }, 0);
     }
 
     function doTest()
     {
       //////////////////////////////////////////////////////////////////////////
       // area1
       var ID = "area1";
-      var tempElem = document.getElementById(ID);
-      gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
-      var defAttrs = {
-        "font-style": gComputedStyle.fontStyle,
-        "font-size": "10pt",
-        "background-color": "rgb(255, 255, 255)",
-        "font-weight": equalsToNormal,
-        "color": gComputedStyle.color,
-        "font-family": gComputedStyle.fontFamily,
-        "text-position": gComputedStyle.verticalAlign
-      };
-
+      var defAttrs = buildDefaultTextAttrs(ID, "10pt");
       testDefaultTextAttrs(ID, defAttrs);
 
       var attrs = {};
       testTextAttrs(ID, 0, attrs, defAttrs, 0, 7);
 
-      tempElem = tempElem.firstChild.nextSibling;
-      gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
-      attrs = { "font-weight": equalsToBold };
+      attrs = { "font-weight": kBoldFontWeight };
       testTextAttrs(ID, 7, attrs, defAttrs, 7, 11);
 
       attrs = {};
       testTextAttrs(ID, 12, attrs, defAttrs, 11, 18);
 
       //////////////////////////////////////////////////////////////////////////
       // area2
       ID = "area2";
-      tempElem = document.getElementById(ID);
-      gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
-      defAttrs = {
-        "font-style": gComputedStyle.fontStyle,
-        "font-size": "14pt",
-        "background-color": "rgb(255, 255, 255)",
-        "font-weight": equalsToNormal,
-        "color": gComputedStyle.color,
-        "font-family": gComputedStyle.fontFamily,
-        "text-position": gComputedStyle.verticalAlign
-      };
-
+      defAttrs = buildDefaultTextAttrs(ID, "14pt");
       testDefaultTextAttrs(ID, defAttrs);
 
       attrs = {};
       testTextAttrs(ID, 0, attrs, defAttrs, 0, 7);
 
-      tempElem = tempElem.firstChild.nextSibling;
-      gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
-      attrs = { "font-weight": equalsToBold };
+      attrs = { "font-weight": kBoldFontWeight };
       testTextAttrs(ID, 7, attrs, defAttrs, 7, 12);
 
-      tempElem = tempElem.firstChild.nextSibling;
+      var tempElem = getNode(ID).firstChild.nextSibling.firstChild.nextSibling;
       gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
       attrs = {"font-style": gComputedStyle.fontStyle,
-               "font-weight": equalsToBold };
+               "font-weight": kBoldFontWeight };
       testTextAttrs(ID, 13, attrs, defAttrs, 12, 19);
 
-      tempElem = tempElem.parentNode;
-      gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
-      attrs = { "font-weight": equalsToBold };
+      attrs = { "font-weight": kBoldFontWeight };
       testTextAttrs(ID, 20, attrs, defAttrs, 19, 23);
 
       attrs = {};
       testTextAttrs(ID, 24, attrs, defAttrs, 23, 30);
 
       //////////////////////////////////////////////////////////////////////////
       // area3
       ID = "area3";
-      tempElem = document.getElementById(ID);
-      gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
-      defAttrs = {
-        "font-style": gComputedStyle.fontStyle,
-        "font-size": "12pt",
-        "background-color": gComputedStyle.backgroundColor,
-        "font-weight": equalsToNormal,
-        "color": gComputedStyle.color,
-        "font-family": gComputedStyle.fontFamily,
-        "text-position": gComputedStyle.verticalAlign
-      };
-
+      defAttrs = buildDefaultTextAttrs(ID, "12pt");
       testDefaultTextAttrs(ID, defAttrs);
 
-      tempElem = tempElem.firstChild.nextSibling;
+      tempElem = getNode(ID).firstChild.nextSibling;
       gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
       attrs = {"color": gComputedStyle.color};
       testTextAttrs(ID, 0, attrs, defAttrs, 0, 6);
 
       tempElem = tempElem.firstChild.nextSibling;
       gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
       attrs = {"color": gComputedStyle.color};
       testTextAttrs(ID, 6, attrs, defAttrs, 6, 26);
@@ -197,31 +138,20 @@
       gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
       attrs = {"color": gComputedStyle.color,
                "background-color": gComputedStyle.backgroundColor};
       testTextAttrs(ID, 27, attrs, defAttrs, 27, 50);
 
       //////////////////////////////////////////////////////////////////////////
       // area4
       ID = "area4";
-      tempElem = document.getElementById(ID);
-      gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
-      defAttrs = {
-        "font-style": gComputedStyle.fontStyle,
-        "font-size": "12pt",
-        "background-color": "rgb(255, 255, 255)",
-        "font-weight": equalsToNormal,
-        "color": gComputedStyle.color,
-        "font-family": gComputedStyle.fontFamily,
-        "text-position": gComputedStyle.verticalAlign
-      };
-
+      defAttrs = buildDefaultTextAttrs(ID, "12pt");
       testDefaultTextAttrs(ID, defAttrs);
 
-      tempElem = tempElem.firstChild.nextSibling;
+      tempElem = getNode(ID).firstChild.nextSibling;
       gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
       attrs = {"color": gComputedStyle.color};
       testTextAttrs(ID, 0, attrs, defAttrs, 0, 16);
 
       tempElem = tempElem.nextSibling.firstChild.nextSibling;
       gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
       attrs = {"color": gComputedStyle.color};
       testTextAttrs(ID, 16, attrs, defAttrs, 16, 33);
@@ -229,31 +159,20 @@
       tempElem = tempElem.parentNode;
       gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
       attrs = {"color": gComputedStyle.color};
       testTextAttrs(ID, 34, attrs, defAttrs, 33, 46);
 
       //////////////////////////////////////////////////////////////////////////
       // area5
       ID = "area5";
-      tempElem = document.getElementById(ID);
-      gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
-      defAttrs = {
-        "font-style": gComputedStyle.fontStyle,
-        "font-size": "12pt",
-        "background-color": "rgb(255, 255, 255)",
-        "font-weight": equalsToNormal,
-        "color": gComputedStyle.color,
-        "font-family": gComputedStyle.fontFamily,
-        "text-position": gComputedStyle.verticalAlign
-      };
-
+      defAttrs = buildDefaultTextAttrs(ID, "12pt");
       testDefaultTextAttrs(ID, defAttrs);
 
-      tempElem = tempElem.firstChild.nextSibling;
+      tempElem = getNode(ID).firstChild.nextSibling;
       gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
       attrs = {"color": gComputedStyle.color};
       testTextAttrs(ID, 0, attrs, defAttrs, 0, 5);
 
       attrs = {};
       testTextAttrs(ID, 7, attrs, defAttrs, 5, 8);
 
       tempElem = tempElem.nextSibling.nextSibling.nextSibling.nextSibling;
@@ -262,34 +181,23 @@
       testTextAttrs(ID, 9, attrs, defAttrs, 8, 11);
 
       attrs = {};
       testTextAttrs(ID, 11, attrs, defAttrs, 11, 18);
 
       //////////////////////////////////////////////////////////////////////////
       // area6 (CSS vertical-align property, bug 445938)
       ID = "area6";
-      tempElem = document.getElementById(ID);
-      gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
-      defAttrs = {
-        "font-style": gComputedStyle.fontStyle,
-        "font-size": "12pt",
-        "background-color": "rgb(255, 255, 255)",
-        "font-weight": equalsToNormal,
-        "color": gComputedStyle.color,
-        "font-family": gComputedStyle.fontFamily,
-        "text-position": gComputedStyle.verticalAlign
-      };
-
+      defAttrs = buildDefaultTextAttrs(ID, "12pt");
       testDefaultTextAttrs(ID, defAttrs);
 
       attrs = {};
       testTextAttrs(ID, 0, attrs, defAttrs, 0, 5);
 
-      tempElem = tempElem.firstChild.nextSibling;
+      tempElem = getNode(ID).firstChild.nextSibling;
       gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
       attrs = {"text-position": gComputedStyle.verticalAlign,
                "font-size": "10pt"};
       testTextAttrs(ID, 5, attrs, defAttrs, 5, 13);
 
       attrs = {};
       testTextAttrs(ID, 13, attrs, defAttrs, 13, 27);
 
@@ -313,38 +221,27 @@
       tempElem = tempElem.nextSibling.nextSibling;
       gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
       attrs = {"text-position": gComputedStyle.verticalAlign};
       testTextAttrs(ID, 55, attrs, defAttrs, 55, 64);
 
       //////////////////////////////////////////////////////////////////////////
       // area7
       ID = "area7";
-      tempElem = document.getElementById(ID);
-      gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
-      defAttrs = {
-        "language": "en",
-        "font-style": gComputedStyle.fontStyle,
-        "font-size": "12pt",
-        "background-color": "rgb(255, 255, 255)",
-        "font-weight": equalsToNormal,
-        "color": gComputedStyle.color,
-        "font-family": gComputedStyle.fontFamily,
-        "text-position": gComputedStyle.verticalAlign
-      };
-
+      defAttrs = buildDefaultTextAttrs(ID, "12pt");
+      defAttrs["language"] = "en";
       testDefaultTextAttrs(ID, defAttrs);
 
       attrs = {"language": "ru"};
       testTextAttrs(ID, 0, attrs, defAttrs, 0, 12);
 
       attrs = {};
       testTextAttrs(ID, 12, attrs, defAttrs, 12, 13);
 
-      tempElem = tempElem.firstChild.nextSibling.nextSibling.nextSibling;
+      tempElem = getNode(ID).firstChild.nextSibling.nextSibling.nextSibling;
       gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
       attrs = { "background-color": gComputedStyle.backgroundColor};
       testTextAttrs(ID, 13, attrs, defAttrs, 13, 26);
 
       attrs = {};
       testTextAttrs(ID, 26, attrs, defAttrs, 26, 27);
 
       attrs = {"language": "de"};
@@ -358,53 +255,42 @@
 
       tempElem = tempElem.nextSibling.nextSibling.nextSibling.nextSibling.firstChild.nextSibling;
       gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
       attrs = {"color": gComputedStyle.color};
       testTextAttrs(ID, 50, attrs, defAttrs, 50, 57);
 
       tempElem = tempElem.firstChild.nextSibling;
       gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
-      attrs = {"font-weight": equalsToBold,
+      attrs = {"font-weight": kBoldFontWeight,
                "color": gComputedStyle.color};
       testTextAttrs(ID, 57, attrs, defAttrs, 57, 61);
 
       tempElem = tempElem.parentNode;
       gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
       attrs = {"color": gComputedStyle.color};
       testTextAttrs(ID, 61, attrs, defAttrs, 61, 68);
 
       //////////////////////////////////////////////////////////////////////////
       // area9, different single style spans in styled paragraph
       ID = "area9";
-      tempElem = document.getElementById(ID);
-      gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
-      defAttrs = {
-        "font-style": gComputedStyle.fontStyle,
-        "font-size": "10pt",
-        "background-color": "rgb(255, 255, 255)",
-        "font-weight": equalsToNormal,
-        "color": gComputedStyle.color,
-        "font-family": gComputedStyle.fontFamily,
-        "text-position": gComputedStyle.verticalAlign
-      };
-
+      defAttrs = buildDefaultTextAttrs(ID, "10pt");
       testDefaultTextAttrs(ID, defAttrs);
 
       attrs = {};
       testTextAttrs(ID, 0, attrs, defAttrs, 0, 6);
 
       attrs = { "font-size": "12pt" };
       testTextAttrs(ID, 7, attrs, defAttrs, 6, 12);
 
       attrs = {};
       testTextAttrs(ID, 13, attrs, defAttrs, 12, 21);
 
       // Walk to the span with the different background color
-      tempElem = tempElem.firstChild.nextSibling.nextSibling.nextSibling;
+      tempElem = getNode(ID).firstChild.nextSibling.nextSibling.nextSibling;
       gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
       attrs = { "background-color": gComputedStyle.backgroundColor };
       testTextAttrs(ID, 22, attrs, defAttrs, 21, 36);
 
       attrs = {};
       testTextAttrs(ID, 37, attrs, defAttrs, 36, 44);
 
       // Walk from the background color span to the one with font-style
@@ -434,41 +320,30 @@
       attrs = { "text-line-through-style": "solid" };
       testTextAttrs(ID, 110, attrs, defAttrs, 109, 122);
 
       attrs = {};
       testTextAttrs(ID, 123, attrs, defAttrs, 122, 130);
 
       // area10, different single style spans in non-styled paragraph
       ID = "area10";
-      tempElem = document.getElementById(ID);
-      gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
-      defAttrs = {
-        "font-style": gComputedStyle.fontStyle,
-        "font-size": "12pt",
-        "background-color": "rgb(255, 255, 255)",
-        "font-weight": equalsToNormal,
-        "color": gComputedStyle.color,
-        "font-family": gComputedStyle.fontFamily,
-        "text-position": gComputedStyle.verticalAlign
-      };
-
+      defAttrs = buildDefaultTextAttrs(ID, "12pt");
       testDefaultTextAttrs(ID, defAttrs);
 
       attrs = {};
       testTextAttrs(ID, 0, attrs, defAttrs, 0, 7);
 
       attrs = { "font-size": "14pt" };
       testTextAttrs(ID, 7, attrs, defAttrs, 7, 13);
 
       attrs = {};
       testTextAttrs(ID, 13, attrs, defAttrs, 13, 22);
 
       // Walk to the span with the different background color
-      tempElem = tempElem.firstChild.nextSibling.nextSibling.nextSibling;
+      tempElem = getNode(ID).firstChild.nextSibling.nextSibling.nextSibling;
       gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
       attrs = { "background-color": gComputedStyle.backgroundColor };
       testTextAttrs(ID, 23, attrs, defAttrs, 22, 37);
 
       attrs = {};
       testTextAttrs(ID, 38, attrs, defAttrs, 37, 45);
 
       // Walk from the background color span to the one with font-style
@@ -498,53 +373,58 @@
       attrs = { "text-line-through-style": "solid" };
       testTextAttrs(ID, 111, attrs, defAttrs, 110, 123);
 
       attrs = {};
       testTextAttrs(ID, 124, attrs, defAttrs, 123, 131);
 
       // area11, "font-weight" tests
       ID = "area11";
-      tempElem = document.getElementById(ID);
-      gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
-
-      defAttrs = {
-        "font-style": gComputedStyle.fontStyle,
-        "font-size": "12pt",
-        "background-color": "rgb(255, 255, 255)",
-        "font-weight": equalsToBold,
-        "color": gComputedStyle.color,
-        "font-family": gComputedStyle.fontFamily,
-        "text-position": gComputedStyle.verticalAlign
-      };
-
+      defAttrs = buildDefaultTextAttrs(ID, "12pt", kBoldFontWeight);
       testDefaultTextAttrs(ID, defAttrs);
 
       attrs = { };
       testTextAttrs(ID, 0, attrs, defAttrs, 0, 13);
 
-      attrs = { "font-weight": equalsToNormal };
+      attrs = { "font-weight": kNormalFontWeight };
       testTextAttrs(ID, 13, attrs, defAttrs, 13, 20);
 
       attrs = { };
       testTextAttrs(ID, 20, attrs, defAttrs, 20, 27);
 
-      attrs = { "font-weight": equalsToNormal };
+      attrs = { "font-weight": kNormalFontWeight };
       testTextAttrs(ID, 27, attrs, defAttrs, 27, 33);
 
       attrs = { };
       testTextAttrs(ID, 33, attrs, defAttrs, 33, 51);
 
-      attrs = { "font-weight": equalsToNormal };
+      attrs = { "font-weight": kNormalFontWeight };
       testTextAttrs(ID, 51, attrs, defAttrs, 51, 57);
 
       attrs = { };
       testTextAttrs(ID, 57, attrs, defAttrs, 57, 97);
 
       //////////////////////////////////////////////////////////////////////////
+      // test out of range offset
+      testTextAttrsWrongOffset("area12", -1);
+      testTextAttrsWrongOffset("area12", 500);
+
+      //////////////////////////////////////////////////////////////////////////
+      // test zero offset on empty hypertext accessibles
+      ID = "area13";
+      defAttrs = buildDefaultTextAttrs(ID, "12pt");
+      attrs = { };
+      testTextAttrs(ID, 0, attrs, defAttrs, 0, 0);
+
+      ID = "area14";
+      defAttrs = buildDefaultTextAttrs(ID, kInputFontSize);
+      attrs = { };
+      testTextAttrs(ID, 0, attrs, defAttrs, 0, 0);
+
+      //////////////////////////////////////////////////////////////////////////
       // test spelling text attributes
       testSpellTextAttrs(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
@@ -626,10 +506,14 @@
     <span style="font-weight: lighter;">lighter</span>bolder
     <span style="font-weight: normal;">normal</span>bolder
     <b>bold</b>bolder
     <span style="font-weight: 400;">normal</span>bolder
     <span style="font-weight: 700;">bold</span>bolder
     <span style="font-weight: bold;">bold</span>bolder
     <span style="font-weight: 900;">bold</span>bolder
   </p>
+
+  <p id="area12">hello</p>
+  <p id="area13"></p>
+  <input id="area14">
 </body>
 </html>
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -3,16 +3,18 @@
 
 const nsIAccessibleRetrieval = Components.interfaces.nsIAccessibleRetrieval;
 
 const nsIAccessibleEvent = Components.interfaces.nsIAccessibleEvent;
 const nsIAccessibleStateChangeEvent =
   Components.interfaces.nsIAccessibleStateChangeEvent;
 const nsIAccessibleCaretMoveEvent =
   Components.interfaces.nsIAccessibleCaretMoveEvent;
+const nsIAccessibleTextChangeEvent =
+  Components.interfaces.nsIAccessibleTextChangeEvent;
 
 const nsIAccessibleStates = Components.interfaces.nsIAccessibleStates;
 const nsIAccessibleRole = Components.interfaces.nsIAccessibleRole;
 const nsIAccessibleTypes = Components.interfaces.nsIAccessibleTypes;
 
 const nsIAccessibleRelation = Components.interfaces.nsIAccessibleRelation;
 
 const nsIAccessNode = Components.interfaces.nsIAccessNode;
@@ -68,16 +70,17 @@ const STATE_OFFSCREEN = nsIAccessibleSta
 const STATE_PRESSED = nsIAccessibleStates.STATE_PRESSED;
 const STATE_READONLY = nsIAccessibleStates.STATE_READONLY;
 const STATE_REQUIRED = nsIAccessibleStates.STATE_REQUIRED;
 const STATE_SELECTABLE = nsIAccessibleStates.STATE_SELECTABLE;
 const STATE_SELECTED = nsIAccessibleStates.STATE_SELECTED;
 const STATE_TRAVERSED = nsIAccessibleStates.STATE_TRAVERSED;
 const STATE_UNAVAILABLE = nsIAccessibleStates.STATE_UNAVAILABLE;
 
+const EXT_STATE_ACTIVE = nsIAccessibleStates.EXT_STATE_ACTIVE;
 const EXT_STATE_EDITABLE = nsIAccessibleStates.EXT_STATE_EDITABLE;
 const EXT_STATE_EXPANDABLE = nsIAccessibleStates.EXT_STATE_EXPANDABLE;
 const EXT_STATE_HORIZONTAL = nsIAccessibleStates.EXT_STATE_HORIZONTAL;
 const EXT_STATE_MULTI_LINE = nsIAccessibleStates.EXT_STATE_MULTI_LINE;
 const EXT_STATE_SINGLE_LINE = nsIAccessibleStates.EXT_STATE_SINGLE_LINE;
 const EXT_STATE_SUPPORTS_AUTOCOMPLETION = 
       nsIAccessibleStates.EXT_STATE_SUPPORTS_AUTOCOMPLETION;
 const EXT_STATE_VERTICAL = nsIAccessibleStates.EXT_STATE_VERTICAL;
@@ -256,17 +259,18 @@ function isAccessible(aAccOrElmOrID, aIn
     true : false;
 }
 
 /**
  * Return root accessible for the given identifier.
  */
 function getRootAccessible(aAccOrElmOrID)
 {
-  var acc = getAccessible(aAccOrElmOrID ? aAccOrElmOrID : document);
+  var acc = getAccessible(aAccOrElmOrID ? aAccOrElmOrID : document,
+                          [nsIAccessNode]);
   return acc ? acc.rootDocument.QueryInterface(nsIAccessible) : null;
 }
 
 /**
  * Return application accessible.
  */
 function getApplicationAccessible()
 {
--- a/accessible/tests/mochitest/events.js
+++ b/accessible/tests/mochitest/events.js
@@ -5,16 +5,17 @@ const EVENT_DOCUMENT_LOAD_COMPLETE = nsI
 const EVENT_HIDE = nsIAccessibleEvent.EVENT_HIDE;
 const EVENT_FOCUS = nsIAccessibleEvent.EVENT_FOCUS;
 const EVENT_NAME_CHANGE = nsIAccessibleEvent.EVENT_NAME_CHANGE;
 const EVENT_REORDER = nsIAccessibleEvent.EVENT_REORDER;
 const EVENT_SCROLLING_START = nsIAccessibleEvent.EVENT_SCROLLING_START;
 const EVENT_SHOW = nsIAccessibleEvent.EVENT_SHOW;
 const EVENT_STATE_CHANGE = nsIAccessibleEvent.EVENT_STATE_CHANGE;
 const EVENT_TEXT_CARET_MOVED = nsIAccessibleEvent.EVENT_TEXT_CARET_MOVED;
+const EVENT_TEXT_REMOVED = nsIAccessibleEvent.EVENT_TEXT_REMOVED;
 
 ////////////////////////////////////////////////////////////////////////////////
 // General
 
 /**
  * Set up this variable to dump events into DOM.
  */
 var gA11yEventDumpID = "";
--- a/accessible/tests/mochitest/events/Makefile.in
+++ b/accessible/tests/mochitest/events/Makefile.in
@@ -56,14 +56,15 @@ include $(topsrcdir)/config/rules.mk
 		test_dragndrop.html \
 		test_flush.html \
 		test_focus.html \
 		test_focus.xul \
 		test_focus_name.html \
 		test_focusdoc.html \
 		test_mutation.html \
 		test_scroll.xul \
+		test_text.html \
 		test_tree.xul \
 		test_valuechange.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/events/test_text.html
@@ -0,0 +1,89 @@
+<html>
+
+<head>
+  <title>Accessible mutation 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/tests/SimpleTest/EventUtils.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">
+    /**
+     * Invokers.
+     */
+    function removeChildSpan(aID)
+    {
+      this.DOMNode = getNode(aID);
+
+      this.invoke = function removeChildSpan_invoke()
+      {
+        // remove HTML span, a first child of the node
+        this.DOMNode.removeChild(this.DOMNode.firstChild);
+      }
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_TEXT_REMOVED, this.DOMNode)
+      ];
+
+      this.check = function removeChildSpan_check(aEvent)
+      {
+        aEvent.QueryInterface(nsIAccessibleTextChangeEvent);
+        is(aEvent.length, 5, "Wrong length of removed text");
+      }
+
+      this.getID = function focusElmWhileSubdocIsFocused_getID()
+      {
+        return "Remove inaccessible span containing accessible nodes" + prettyName(aID);
+      }
+    }
+
+    /**
+     * Do tests.
+     */
+    var gQueue = null;
+    // gA11yEventDumpID = "eventdump"; // debug stuff
+
+    function doTests()
+    {
+      gQueue = new eventQueue();
+
+      // Text remove event on inaccessible child HTML span removal containing
+      // accessible text nodes.
+      gQueue.push(new removeChildSpan("p"));
+
+      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=566293"
+     title=" wrong length of text remove event when inaccessible node containing accessible nodes is removed">
+    Mozilla Bug 566293
+  </a>
+
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+  <div id="eventdump"></div>
+
+  <p id="p"><span><span>333</span><span>22</span></span>1111</p>
+</body>
+</html>
--- a/accessible/tests/mochitest/name_nsRootAcc_wnd.xul
+++ b/accessible/tests/mochitest/name_nsRootAcc_wnd.xul
@@ -26,19 +26,18 @@
     var handleDroppedLink = null; // needed for tabbrowser usage
 
     Components.utils.import("resource://gre/modules/Services.jsm");
     var XULBrowserWindow = {
       isBusy: false,
       setOverLink: function (link, b) {
       }
     };
-    var gFindBar = {
-      hidden: true
-    };
+
+    gFindBarInitialized = false;
 
     ////////////////////////////////////////////////////////////////////////////
     // Invoker implementation.
 
     function switchTabSelectChecker(aInvoker)
     {
       this.type = "select";
       Object.defineProperty(this, "target", { get: function() { return aInvoker.getTabsElm(); }});
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/selectable.js
@@ -0,0 +1,36 @@
+/**
+ * Test selection getter methods of nsIAccessibleSelectable.
+ *
+ * @param aIdentifier        [in] selectable container accessible
+ * @param aSelectedChildren  [in] array of selected children
+ */
+function testSelectableSelection(aIdentifier, aSelectedChildren)
+{
+  var acc = getAccessible(aIdentifier, [nsIAccessibleSelectable]);
+  if (!acc)
+    return;
+
+  var len = aSelectedChildren.length;
+
+  // getSelectedChildren
+  var selectedChildren = acc.GetSelectedChildren();
+  is(selectedChildren ? selectedChildren.length : 0, aSelectedChildren.length,
+     "getSelectedChildren: wrong selected children count for " + prettyName(aIdentifier));
+
+  for (var idx = 0; idx < len; idx++) {
+    var expectedAcc = getAccessible(aSelectedChildren[idx]);
+    is(selectedChildren.queryElementAt(idx, nsIAccessible), expectedAcc,
+       "getSelectedChildren: wrong selected child at index " + idx + " for " + prettyName(aIdentifier));
+  }
+
+  // selectionCount
+  is(acc.selectionCount, aSelectedChildren.length,
+     "selectionCount: wrong selected children count for " + prettyName(aIdentifier));
+
+  // refSelection
+  for (var idx = 0; idx < len; idx++) {
+    var expectedAcc = getAccessible(aSelectedChildren[idx]);
+    is(acc.refSelection(idx), expectedAcc,
+       "refSelection: wrong selected child at index " + idx + " for " + prettyName(aIdentifier));
+  }
+}
--- a/accessible/tests/mochitest/selectable/test_aria.html
+++ b/accessible/tests/mochitest/selectable/test_aria.html
@@ -12,18 +12,33 @@
           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"
+          src="chrome://mochikit/content/a11y/accessible/selectable.js"></script>
 
   <script type="application/javascript">
+    function testSelectable(aID, aSelectableChildren)
+    {
+      var acc = getAccessible(aID, [nsIAccessibleSelectable]);
+
+      testSelectableSelection(acc, []);
+
+      acc.selectAllSelection();
+      testSelectableSelection(acc, aSelectableChildren);
+
+      acc.clearSelection();
+      testSelectableSelection(acc, []);
+    }
+
     function doTest()
     {
       var id = "list1";
       ok(isAccessible(id, [nsIAccessibleSelectable]),
          "No selectable accessible for " + id);
 
       id = "listbox1";
       ok(isAccessible(id, [nsIAccessibleSelectable]),
@@ -40,32 +55,42 @@
       id = "tree1";
       ok(isAccessible(id, [nsIAccessibleSelectable]),
          "No selectable accessible for " + id);
 
       id = "treegrid1";
       ok(isAccessible(id, [nsIAccessibleSelectable]),
          "No selectable accessible for " + id);
 
+      // Test selection methods for selectable children in subtree.
+      testSelectable("grid2",
+                     ["grid2_colhead1", "grid2_colhead2", "grid2_colhead3",
+                      "grid2_rowhead", "grid2_cell1", "grid2_cell2"]);
+
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 
 </head>
 
 <body>
 
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=530014"
      title="ARIA single selectable widget should implement nsIAccessibleSelectable">
     Mozilla Bug 530014
   </a><br>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=566551"
+     title="ARIA grid and accessible selectable methods shouldn't use GetNextSibling">
+    Mozilla Bug 566551
+  </a><br>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <div role="list" id="list1">
     <div role="listitem">item1</div>
     <div role="listitem">item2</div>
@@ -111,10 +136,34 @@
       <span role="gridcell">cell</span>
       <span role="gridcell">cell</span>
     </div>
     <div role="row" aria-level="1">
       <span role="gridcell">cell</span>
       <span role="gridcell">cell</span>
     </div>
   </div>
+
+  <table tabindex="0" border="2" cellspacing="0" id="grid2" role="grid"
+         aria-multiselectable="true">
+    <thead>
+      <tr>
+        <th tabindex="-1" role="columnheader" id="grid2_colhead1"
+            style="width:6em">Entry #</th>
+        <th tabindex="-1" role="columnheader" id="grid2_colhead2"
+            style="width:10em">Date</th>
+        <th tabindex="-1" role="columnheader" id="grid2_colhead3"
+            style="width:20em">Expense</th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td tabindex="-1" role="rowheader" id="grid2_rowhead"
+            aria-readonly="true">1</td>
+        <td tabindex="-1" role="gridcell" id="grid2_cell1"
+            aria-selected="false">03/14/05</td>
+        <td tabindex="-1" role="gridcell" id="grid2_cell2"
+            aria-selected="false">Conference Fee</td>
+      </tr>
+    </tobdy>
+  </table>
 </body>
 </html>
--- a/accessible/tests/mochitest/states/test_doc.html
+++ b/accessible/tests/mochitest/states/test_doc.html
@@ -17,16 +17,19 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="application/javascript"
           src="chrome://mochikit/content/a11y/accessible/common.js"></script>
   <script type="application/javascript"
           src="chrome://mochikit/content/a11y/accessible/states.js"></script>
 
   <script type="application/javascript">
     function doTest()
     {
+      // Bug 566542: root accesible should expose active state when focused.
+      testStates(getRootAccessible(), 0, EXT_STATE_ACTIVE);
+
       // Bug 509696
       testStates(document, STATE_READONLY); // role=""
       todo(false, "enable commented tests when we support body role changes");
 /*
       document.body.setAttribute("role","banner"); // no platform mapping
       testStates(document, STATE_READONLY);
       document.body.setAttribute("role","foo"); // bogus role
       testStates(document, STATE_READONLY);
@@ -66,16 +69,20 @@ https://bugzilla.mozilla.org/show_bug.cg
      title="<body contenteditable='true'> exposed incorrectly"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=454997">Mozilla Bug 454997</a>
    <a target="_blank"
      title="nsIAccessible states tests of editable document"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=467387">Mozilla Bug 467387</a>
    <a target="_blank"
      title="Role attribute on body with empty string causes DocAccessible not to have read-only state."
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=509696">Mozilla Bug 509696</a>
+  <a target="_blank"
+     title="Frame for firefox does not implement the state "active" when firefox is the active frame"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=566542">Mozilla Bug 566542</a>
+
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <p id="p">hello</p>
 
   <div id="document" role="document">document</div>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/table/Makefile.in
@@ -0,0 +1,72 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2010
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Alexander Surkov <surkov.alexander@gmail.com> (original author)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir  = accessible/table
+
+include $(DEPTH)/config/autoconf.mk
+include $(topsrcdir)/config/rules.mk
+
+_TEST_FILES = \
+		test_headers_ariagrid.html \
+		test_headers_listbox.xul \
+		test_headers_table.html \
+		test_headers_tree.xul \
+		test_indexes_ariagrid.html \
+		test_indexes_listbox.xul \
+		test_indexes_table.html \
+		test_indexes_tree.xul \
+		test_layoutguess.html \
+		test_sels_ariagrid.html \
+		test_sels_listbox.xul \
+		test_sels_table.html \
+		test_sels_tree.xul \
+		test_struct_ariagrid.html \
+		test_struct_ariatreegrid.html \
+		test_struct_listbox.xul \
+		test_struct_table.html \
+		test_struct_tree.xul \
+		test_table_1.html \
+		test_table_2.html \
+		$(NULL)
+
+libs:: $(_TEST_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
rename from accessible/tests/mochitest/test_table_headers_ariagrid.html
rename to accessible/tests/mochitest/table/test_headers_ariagrid.html
rename from accessible/tests/mochitest/test_table_headers_listbox.xul
rename to accessible/tests/mochitest/table/test_headers_listbox.xul
rename from accessible/tests/mochitest/test_table_headers.html
rename to accessible/tests/mochitest/table/test_headers_table.html
rename from accessible/tests/mochitest/test_table_headers_tree.xul
rename to accessible/tests/mochitest/table/test_headers_tree.xul
rename from accessible/tests/mochitest/test_table_indexes_ariagrid.html
rename to accessible/tests/mochitest/table/test_indexes_ariagrid.html
rename from accessible/tests/mochitest/test_table_indexes_listbox.xul
rename to accessible/tests/mochitest/table/test_indexes_listbox.xul
rename from accessible/tests/mochitest/test_table_indexes.html
rename to accessible/tests/mochitest/table/test_indexes_table.html
rename from accessible/tests/mochitest/test_table_indexes_tree.xul
rename to accessible/tests/mochitest/table/test_indexes_tree.xul
rename from accessible/tests/mochitest/test_table_layoutguess.html
rename to accessible/tests/mochitest/table/test_layoutguess.html
rename from accessible/tests/mochitest/test_table_sels_ariagrid.html
rename to accessible/tests/mochitest/table/test_sels_ariagrid.html
rename from accessible/tests/mochitest/test_table_sels_listbox.xul
rename to accessible/tests/mochitest/table/test_sels_listbox.xul
rename from accessible/tests/mochitest/test_table_sels.html
rename to accessible/tests/mochitest/table/test_sels_table.html
rename from accessible/tests/mochitest/test_table_sels_tree.xul
rename to accessible/tests/mochitest/table/test_sels_tree.xul
rename from accessible/tests/mochitest/test_table_struct_ariagrid.html
rename to accessible/tests/mochitest/table/test_struct_ariagrid.html
rename from accessible/tests/mochitest/test_table_struct_ariatreegrid.html
rename to accessible/tests/mochitest/table/test_struct_ariatreegrid.html
rename from accessible/tests/mochitest/test_table_struct_listbox.xul
rename to accessible/tests/mochitest/table/test_struct_listbox.xul
rename from accessible/tests/mochitest/test_table_struct.html
rename to accessible/tests/mochitest/table/test_struct_table.html
rename from accessible/tests/mochitest/test_table_struct_tree.xul
rename to accessible/tests/mochitest/table/test_struct_tree.xul
rename from accessible/tests/mochitest/test_table_1.html
rename to accessible/tests/mochitest/table/test_table_1.html
rename from accessible/tests/mochitest/test_table_4.html
rename to accessible/tests/mochitest/table/test_table_2.html
--- a/accessible/tests/mochitest/test_name.html
+++ b/accessible/tests/mochitest/test_name.html
@@ -68,17 +68,18 @@
 
       // Gets the name from image accessible.
       testName("btn_labelledby_mixed_img", "text image");
 
       // Gets the name from input accessibles
       // Note: if input have label elements then the name isn't calculated
       // from them.
       testName("btn_labelledby_mixed_input",
-               "input button Submit Query Reset Submit Query");
+               "Submit Query Reset Submit Query");
+      // XXX Bug 567203 "input button Submit Query Reset Submit Query");
 
       // Gets the name from the title of object element.
       testName("btn_labelledby_mixed_object", "object");
 
       // Gets the name from text nodes. Element br adds space between them.
       testName("btn_labelledby_mixed_br", "text text");
 
       // Gets the name from label content which allows name from subtree,
--- a/accessible/tests/mochitest/test_nsIAccessibleHyperLink.html
+++ b/accessible/tests/mochitest/test_nsIAccessibleHyperLink.html
@@ -237,17 +237,21 @@ https://bugzilla.mozilla.org/show_bug.cg
       testThis(id, linkAcc, ROLE_LINK, 1, "Link with label and nested image:",
                true, 450, 451);
       testStates(linkAcc,
                  (STATE_LINKED),
                  (EXT_STATE_HORIZONTAL));
       testAction(id, linkAcc, "jump");
 
       //////////////////////////////////////////////////////////////////////////
-      //
+      // Text accessible shouldn't implement nsIAccessibleHyperLink
+      var res = isAccessible(getNode("namedAnchor").firstChild,
+                             [nsIAccessibleHyperLink]);
+      ok(!res, "Text accessible shouldn't implement nsIAccessibleHyperLink");
+
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 <body><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=418368">Mozilla Bug 418368</a
--- a/accessible/tests/mochitest/tree/test_formctrl.html
+++ b/accessible/tests/mochitest/tree/test_formctrl.html
@@ -31,34 +31,28 @@
       accTree = {
         role: ROLE_RADIOBUTTON,
         children: [ ]
       };
 
       testAccessibleTree("radio", accTree);
 
       // input@type="button" and input@type="submit"
-      accTree = {
-        role: ROLE_PUSHBUTTON,
-        children: [ ]
-      };
-
-      testAccessibleTree("btn1", accTree);
-      testAccessibleTree("submit", accTree);
-
       // button
       accTree = {
         role: ROLE_PUSHBUTTON,
         children: [
           {
-            role: ROLE_TEXT_LEAF
+            role: ROLE_TEXT_LEAF // XXX Bug 567203
           }
         ]
       };
 
+      testAccessibleTree("btn1", accTree);
+      testAccessibleTree("submit", accTree);
       testAccessibleTree("btn2", accTree);
 
       // input@type="image"
       accTree = {
         role: ROLE_PUSHBUTTON,
         children: [
           {
             role: ROLE_STATICTEXT
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -598,17 +598,17 @@
                         label="&addons.label;"
                         accesskey="&addons.accesskey;"
                         command="Tools:Addons"/>
               <menuseparator id="devToolsSeparator"/>
               <menuitem id="menu_pageinspect"
                         type="checkbox"
                         label="&inspectMenu.label;"
                         accesskey="&inspectMenu.accesskey;"
-                        key="&inspectMenu.commandkey;"
+                        key="key_inspect"
                         command="Tools:Inspect"/>
               <menuitem id="javascriptConsole"
                         label="&errorConsoleCmd.label;"
                         accesskey="&errorConsoleCmd.accesskey;"
                         key="key_errorConsole"
                         oncommand="toJavaScriptConsole();"/>
               <menuitem id="menu_pageInfo"
                         accesskey="&pageInfoCmd.accesskey;"
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -86,33 +86,50 @@ var gContextMenu = null; // nsContextMen
 #ifndef XP_MACOSX
 var gEditUIVisible = true;
 #endif
 
 [
   ["gBrowser",            "content"],
   ["gNavToolbox",         "navigator-toolbox"],
   ["gURLBar",             "urlbar"],
-  ["gNavigatorBundle",    "bundle_browser"],
-  ["gFindBar",            "FindToolbar"]
+  ["gNavigatorBundle",    "bundle_browser"]
 ].forEach(function (elementGlobal) {
   var [name, id] = elementGlobal;
   window.__defineGetter__(name, function () {
     var element = document.getElementById(id);
     if (!element)
       return null;
     delete window[name];
     return window[name] = element;
   });
   window.__defineSetter__(name, function (val) {
     delete window[name];
     return window[name] = val;
   });
 });
 
+// Smart getter for the findbar.  If you don't wish to force the creation of
+// the findbar, check gFindBarInitialized first.
+var gFindBarInitialized = false;
+XPCOMUtils.defineLazyGetter(window, "gFindBar", function() {
+  let XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+  let findbar = document.createElementNS(XULNS, "findbar");
+  findbar.setAttribute("browserid", "content");
+  findbar.id = "FindToolbar";
+
+  let browserBottomBox = document.getElementById("browser-bottombox");
+  browserBottomBox.insertBefore(findbar, browserBottomBox.firstChild);
+
+  // Force a style flush to ensure that our binding is attached.
+  findbar.clientTop;
+  window.gFindBarInitialized = true;
+  return findbar;
+});
+
 __defineGetter__("gPrefService", function() {
   delete this.gPrefService;
   return this.gPrefService = Services.prefs;
 });
 
 __defineGetter__("PluralForm", function() {
   Cu.import("resource://gre/modules/PluralForm.jsm");
   return this.PluralForm;
@@ -966,20 +983,23 @@ function BrowserStartup() {
     }
     // Note: loadOneOrMoreURIs *must not* be called if window.arguments.length >= 3.
     // Such callers expect that window.arguments[0] is handled as a single URI.
     else
       loadOneOrMoreURIs(uriToLoad);
   }
 
   if (window.opener && !window.opener.closed) {
-    let openerFindBar = window.opener.gFindBar;
-    if (openerFindBar && !openerFindBar.hidden &&
-        openerFindBar.findMode == gFindBar.FIND_NORMAL)
+    let openerFindBar = window.opener.gFindBarInitialized ?
+                        window.opener.gFindBar : null;
+    if (openerFindBar &&
+        !openerFindBar.hidden &&
+        openerFindBar.findMode == openerFindBar.FIND_NORMAL) {
       gFindBar.open();
+    }
 
     let openerSidebarBox = window.opener.document.getElementById("sidebar-box");
     // If the opener had a sidebar, open the same sidebar in our window.
     // The opener can be the hidden window too, if we're coming from the state
     // where no windows are open, and the hidden window has no sidebar box.
     if (openerSidebarBox && !openerSidebarBox.hidden) {
       let sidebarCmd = openerSidebarBox.getAttribute("sidebarcommand");
       let sidebarCmdElem = document.getElementById(sidebarCmd);
@@ -2593,18 +2613,19 @@ var PrintPreviewListener = {
     this._chromeState.notificationsOpen = !notificationBox.notificationsHidden;
     notificationBox.notificationsHidden = true;
 
     document.getElementById("sidebar").setAttribute("src", "about:blank");
     var statusbar = document.getElementById("status-bar");
     this._chromeState.statusbarOpen = !statusbar.hidden;
     statusbar.hidden = true;
 
-    this._chromeState.findOpen = !gFindBar.hidden;
-    gFindBar.close();
+    this._chromeState.findOpen = gFindBarInitialized && !gFindBar.hidden;
+    if (gFindBarInitialized)
+      gFindBar.close();
   },
   _showChrome: function () {
     if (this._chromeState.notificationsOpen)
       gBrowser.getNotificationBox().notificationsHidden = false;
 
     if (this._chromeState.statusbarOpen)
       document.getElementById("status-bar").hidden = false;
 
@@ -4107,26 +4128,28 @@ var XULBrowserWindow = {
         URLBarSetURI(uri, true);
 
         // Update starring UI
         PlacesStarButton.updateState();
       }
     }
     UpdateBackForwardCommands(gBrowser.webNavigation);
 
-    if (gFindBar.findMode != gFindBar.FIND_NORMAL) {
-      // Close the Find toolbar if we're in old-style TAF mode
-      gFindBar.close();
-    }
-
-    // XXXmano new-findbar, do something useful once it lands.
-    // Of course, this is especially wrong with bfcache on...
-
-    // fix bug 253793 - turn off highlight when page changes
-    gFindBar.getElement("highlight").checked = false;
+    if (gFindBarInitialized) {
+      if (gFindBar.findMode != gFindBar.FIND_NORMAL) {
+        // Close the Find toolbar if we're in old-style TAF mode
+        gFindBar.close();
+      }
+
+      // XXXmano new-findbar, do something useful once it lands.
+      // Of course, this is especially wrong with bfcache on...
+
+      // fix bug 253793 - turn off highlight when page changes
+      gFindBar.getElement("highlight").checked = false;      
+    }
 
     // See bug 358202, when tabs are switched during a drag operation,
     // timers don't fire on windows (bug 203573)
     if (aRequest)
       setTimeout(function () { XULBrowserWindow.asyncUpdateUI(); }, 0);
     else
       this.asyncUpdateUI();
   },
@@ -7250,17 +7273,17 @@ let gPrivateBrowsingUI = {
 
     return result;
   },
 
   onEnterPrivateBrowsing: function PBUI_onEnterPrivateBrowsing(aOnWindowOpen) {
     if (BrowserSearch.searchBar)
       this._searchBarValue = BrowserSearch.searchBar.textbox.value;
 
-    if (gFindBar)
+    if (gFindBarInitialized)
       this._findBarValue = gFindBar.getElement("findbar-textbox").value;
 
     this._setPBMenuTitle("stop");
 
     document.getElementById("menu_import").setAttribute("disabled", "true");
 
     // Disable the Clear Recent History... menu item when in PB mode
     // temporary fix until bug 463607 is fixed
@@ -7308,17 +7331,17 @@ let gPrivateBrowsingUI = {
     }
 
     document.getElementById("menu_import").removeAttribute("disabled");
 
     // Re-enable the Clear Recent History... menu item on exit of PB mode
     // temporary fix until bug 463607 is fixed
     document.getElementById("Tools:Sanitize").removeAttribute("disabled");
 
-    if (gFindBar) {
+    if (gFindBarInitialized) {
       let findbox = gFindBar.getElement("findbar-textbox");
       findbox.reset();
       if (this._findBarValue) {
         findbox.value = this._findBarValue;
         this._findBarValue = null;
       }
     }
 
@@ -7605,9 +7628,9 @@ var TabContextMenu = {
     // Session store
     // XXXzeniko should't we just disable this item as we disable
     // the tabbrowser-multiple items above - for consistency?
     document.getElementById("context_undoCloseTab").hidden =
       Cc["@mozilla.org/browser/sessionstore;1"].
       getService(Ci.nsISessionStore).
       getClosedTabCount(window) == 0;
   }
-}
+};
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -748,18 +748,16 @@
                   tabcontainer="tabbrowser-tabs"
                   contentcontextmenu="contentAreaContextMenu"
                   autocompletepopup="PopupAutoComplete"
                   onclick="return contentAreaClick(event, false);"/>
     </vbox>
   </hbox>
 
   <vbox id="browser-bottombox">
-    <findbar browserid="content" id="FindToolbar"/>
-  
     <statusbar class="chromeclass-status" id="status-bar"
 #ifdef WINCE
                hidden="true"
 #endif
                >
       <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"/>
--- a/browser/base/content/inspector.js
+++ b/browser/base/content/inspector.js
@@ -503,23 +503,20 @@ var InspectorUI = {
   /**
    * Toggle the inspector interface elements on or off.
    *
    * @param event
    *        The event that requested the UI change. Toolbar button or menu.
    */
   toggleInspectorUI: function InspectorUI_toggleInspectorUI()
   {
-    let toolsInspectCmd = document.getElementById("Tools:Inspect");
     if (this.isPanelOpen) {
       this.closeInspectorUI();
-      toolsInspectCmd.setAttribute("checked", "false");
     } else {
       this.openInspectorUI();
-      toolsInspectCmd.setAttribute("checked", "true");
     }
   },
 
   /**
    * Is the tree panel open?
    *
    * @returns boolean
    */
@@ -578,16 +575,17 @@ var InspectorUI = {
     }
     if (this._showDOMPanel) {
       this.openDOMPanel();
     }
     this.initializeHighlighter();
     this.startInspecting();
     this.win.document.addEventListener("scroll", this, false);
     gBrowser.tabContainer.addEventListener("TabSelect", this, false);
+    this.inspectCmd.setAttribute("checked", true);
   },
 
   /**
    * Initialize highlighter.
    */
   initializeHighlighter: function InspectorUI_initializeHighlighter()
   {
     this.highlighter = new PanelHighlighter(this.browser, this.highlightColor,
@@ -606,16 +604,17 @@ var InspectorUI = {
     this.stopInspecting();
     if (this.highlighter && this.highlighter.isHighlighting) {
       this.highlighter.unhighlight();
     }
     if (this.isPanelOpen) {
       this.treePanel.hidePopup();
       this.treeView.destroy();
     }
+    this.inspectCmd.setAttribute("checked", false);
     this.browser = this.win = null; // null out references to browser and window
   },
 
   /**
    * Begin inspecting webpage, attach page event listeners, activate
    * highlighter event listeners.
    */
   startInspecting: function InspectorUI_startInspecting()
@@ -751,8 +750,12 @@ var InspectorUI = {
    *        text message to send to the log
    */
   _log: function LOG(msg)
   {
     Services.console.logStringMessage(msg);
   },
 }
 
+XPCOMUtils.defineLazyGetter(InspectorUI, "inspectCmd", function () {
+  return document.getElementById("Tools:Inspect");
+});
+
--- a/browser/base/content/sanitize.xul
+++ b/browser/base/content/sanitize.xul
@@ -170,18 +170,17 @@
               class="expander-down"
               persist="class"
               oncommand="gSanitizePromptDialog.toggleItemList();"/>
       <label id="detailsExpanderLabel"
              value="&detailsProgressiveDisclosure.label;"
              accesskey="&detailsProgressiveDisclosure.accesskey;"
              control="detailsExpander"/>
     </hbox>
-    <listbox id="itemList" rows="6" collapsed="true" persist="collapsed"
-             flex="1">
+    <listbox id="itemList" rows="6" collapsed="true" persist="collapsed">
       <listitem label="&itemHistoryAndDownloads.label;"
                 type="checkbox"
                 accesskey="&itemHistoryAndDownloads.accesskey;"
                 preference="privacy.cpd.history"
                 onsyncfrompreference="return gSanitizePromptDialog.onReadGeneric();"/>
       <listitem label="&itemFormSearchHistory.label;"
                 type="checkbox"
                 accesskey="&itemFormSearchHistory.accesskey;"
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -899,17 +899,18 @@
               var event = document.createEvent("Events");
               event.initEvent("TabSelect", true, false);
               this.mCurrentTab.dispatchEvent(event);
 
               this._tabAttrModified(oldTab);
               this._tabAttrModified(this.mCurrentTab);
 
               // Change focus to the new browser unless the findbar is focused.
-              if (gFindBar.hidden ||
+              if (!gFindBarInitialized ||
+                  gFindBar.hidden ||
                   gFindBar.getElement("findbar-textbox").getAttribute("focused") != "true") {
 
                 var fm = Components.classes["@mozilla.org/focus-manager;1"].
                            getService(Components.interfaces.nsIFocusManager);
                 var newFocusedElement = fm.getFocusedElementForWindow(window.content, true, {});
 
                 // for anchors, use FLAG_SHOWRING so that it is clear what link was
                 // last clicked when switching back to that tab
--- a/browser/base/content/test/browser_NetworkPrioritizer.js
+++ b/browser/base/content/test/browser_NetworkPrioritizer.js
@@ -81,17 +81,17 @@ function test() {
 
     // Test 1 window, 1 tab case.
     isWindowState(window_A, [-10]);
 
     // Exising tab is tab_A1
     let tab_A2 = window_A.gBrowser.addTab("http://example.com");
     let tab_A3 = window_A.gBrowser.addTab("about:config");
     tab_A3.linkedBrowser.addEventListener("load", function(aEvent) {
-      tab_A3.removeEventListener("load", arguments.callee, true);
+      tab_A3.linkedBrowser.removeEventListener("load", arguments.callee, true);
 
       // tab_A2 isn't focused yet
       isWindowState(window_A, [-10, 0, 0]);
 
       // focus tab_A2 & make sure priority got updated
       window_A.gBrowser.selectedTab = tab_A2;
       isWindowState(window_A, [0, -10, 0]);
 
@@ -124,17 +124,16 @@ function test() {
 
                 // And we're done. Cleanup & run the next test
                 window_B.close();
                 window_A.gBrowser.removeTab(tab_A3);
                 executeSoon(runNextTest);
               }, window_B);
             }, window_A);
           }, window_B);
-
         }, true);
       }, false);
     }, true);
 
   }
 
 
   // This is more a test of nsLoadGroup and how it handles priorities. But since
--- a/browser/base/content/test/browser_sanitizeDialog.js
+++ b/browser/base/content/test/browser_sanitizeDialog.js
@@ -445,18 +445,20 @@ WindowHelper.prototype = {
     is(hidden, !aShouldBeShown,
        "Details should be " + (aShouldBeShown ? "shown" : "hidden") +
        " but were actually " + (hidden ? "hidden" : "shown"));
     let dir = hidden ? "down" : "up";
     is(button.className, "expander-" + dir,
        "Details button should be " + dir + " because item list is " +
        (hidden ? "" : "not ") + "hidden");
     let height = 0;
-    if (!hidden)
+    if (!hidden) {
+      ok(list.boxObject.height > 30, "listbox has sufficient size")
       height += list.boxObject.height;
+    }
     if (this.isWarningPanelVisible())
       height += this.getWarningPanel().boxObject.height;
     ok(height < this.win.innerHeight,
        "Window should be tall enough to fit warning panel and item list");
   },
 
   /**
    * (Un)checks a history scope checkbox (browser & download history,
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -1241,17 +1241,18 @@ BrowserGlue.prototype = {
                                          Ci.nsIBrowserGlue]),
 
   // redefine the default factory for XPCOMUtils
   _xpcom_factory: BrowserGlueServiceFactory,
 
   // get this contractID registered for certain categories via XPCOMUtils
   _xpcom_categories: [
     // make BrowserGlue a startup observer
-    { category: "app-startup", service: true }
+    { category: "app-startup", service: true,
+      apps: [ /* Firefox */ "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}" ] }
   ]
 }
 
 function GeolocationPrompt() {}
 
 GeolocationPrompt.prototype = {
   classDescription: "Geolocation Prompting Component",
   classID:          Components.ID("{C6E8C44D-9F39-4AF7-BCC0-76E38A8310F5}"),
--- a/browser/components/sessionstore/test/browser/Makefile.in
+++ b/browser/components/sessionstore/test/browser/Makefile.in
@@ -41,17 +41,16 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = browser/components/sessionstore/test/browser 
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 # browser_506482.js is disabled because of frequent failures (bug 538672)
-# browser_524745.js is disabled because of frequent failures (bug 539002)
 # browser_526613.js is disabled because of frequent failures (bug 534489)
 
 _BROWSER_TEST_FILES = \
 	browser_248970_a.js \
 	browser_248970_b.js \
 	browser_248970_b_sample.html \
 	browser_339445.js \
 	browser_339445_sample.html \
@@ -108,13 +107,14 @@ include $(topsrcdir)/config/rules.mk
 	browser_490040.js \
 	browser_491168.js \
 	browser_491577.js \
 	browser_493467.js \
 	browser_495495.js \
 	browser_500328.js \
 	browser_514751.js \
 	browser_522545.js \
+	browser_524745.js \
 	browser_528776.js \
 	$(NULL)
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -21,17 +21,16 @@
 [@AB_CD@]
 @BINPATH@/chrome/@AB_CD@.jar
 @BINPATH@/chrome/@AB_CD@.manifest
 @BINPATH@/@PREF_DIR@/firefox-l10n.js
 @BINPATH@/browserconfig.properties
 @BINPATH@/searchplugins/*
 @BINPATH@/defaults/profile/bookmarks.html
 @BINPATH@/defaults/profile/localstore.rdf
-@BINPATH@/defaults/profile/prefs.js
 @BINPATH@/defaults/profile/mimeTypes.rdf
 @BINPATH@/defaults/profile/chrome/*
 @BINPATH@/update.locale
 @BINPATH@/updater.ini
 @BINPATH@/dictionaries/*
 #ifdef XP_WIN32
 #ifndef WINCE
 @BINPATH@/uninstall/helper.exe
@@ -368,16 +367,17 @@
 ; [Default Preferences]
 ; All the pref files must be part of base to prevent migration bugs
 @BINPATH@/@PREF_DIR@/firefox.js
 @BINPATH@/@PREF_DIR@/firefox-branding.js
 @BINPATH@/@PREF_DIR@/channel-prefs.js
 @BINPATH@/greprefs.js
 @BINPATH@/defaults/autoconfig/platform.js
 @BINPATH@/defaults/autoconfig/prefcalls.js
+@BINPATH@/defaults/profile/prefs.js
 
 ; [Layout Engine Resources]
 ; Style Sheets, Graphics and other Resources used by the layout engine. 
 @BINPATH@/res/EditorOverride.css
 @BINPATH@/res/contenteditable.css
 @BINPATH@/res/designmode.css
 @BINPATH@/res/table-add-column-after-active.gif
 @BINPATH@/res/table-add-column-after-hover.gif
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -155,17 +155,17 @@
 <!ENTITY addons.label                 "Add-ons">
 <!ENTITY addons.accesskey             "A">
 
 <!ENTITY errorConsoleCmd.label        "Error Console">
 <!ENTITY errorConsoleCmd.accesskey    "C">
 <!ENTITY errorConsoleCmd.commandkey   "j">
 
 <!ENTITY inspectMenu.label            "Inspect">
-<!ENTITY inspectMenu.accesskey        "I">
+<!ENTITY inspectMenu.accesskey        "T">
 <!ENTITY inspectMenu.commandkey       "I">
 
 <!ENTITY fileMenu.label         "File"> 
 <!ENTITY fileMenu.accesskey       "F">
 <!ENTITY newNavigatorCmd.label        "New Window">
 <!ENTITY newNavigatorCmd.key        "N">
 <!ENTITY newNavigatorCmd.accesskey      "N">
 
--- a/chrome/src/nsChromeRegistry.cpp
+++ b/chrome/src/nsChromeRegistry.cpp
@@ -479,17 +479,17 @@ nsresult nsChromeRegistry::RefreshWindow
     nsCOMArray<nsIStyleSheet> agentSheets;
     rv = shell->GetAgentStyleSheets(agentSheets);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMArray<nsIStyleSheet> newAgentSheets;
     for (PRInt32 l = 0; l < agentSheets.Count(); ++l) {
       nsIStyleSheet *sheet = agentSheets[l];
 
-      nsCOMPtr<nsIURI> uri = sheet->GetSheetURI();
+      nsIURI* uri = sheet->GetSheetURI();
 
       if (IsChromeURI(uri)) {
         // Reload the sheet.
         nsRefPtr<nsCSSStyleSheet> newSheet;
         rv = document->LoadChromeSheetSync(uri, PR_TRUE,
                                            getter_AddRefs(newSheet));
         if (NS_FAILED(rv)) return rv;
         if (newSheet) {
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -75,16 +75,17 @@ MOZ_FS_LAYOUT = @MOZ_FS_LAYOUT@
 L10NBASEDIR     = @L10NBASEDIR@
 
 LIBXUL_DIST	= @LIBXUL_DIST@
 SYSTEM_LIBXUL   = @SYSTEM_LIBXUL@
 
 XULRUNNER_STUB_NAME = @XULRUNNER_STUB_NAME@
 
 MOZ_CHROME_FILE_FORMAT	= @MOZ_CHROME_FILE_FORMAT@
+MOZ_OMNIJAR		= @MOZ_OMNIJAR@
 
 MOZ_WIDGET_TOOLKIT	= @MOZ_WIDGET_TOOLKIT@
 MOZ_GFX_OPTIMIZE_MOBILE = @MOZ_GFX_OPTIMIZE_MOBILE@
 
 MOZ_DFB			= @MOZ_DFB@
 MOZ_X11			= @MOZ_X11@
 
 MOZ_PANGO = @MOZ_PANGO@
@@ -646,8 +647,14 @@ HAVE_GCC_ALIGN_ARG_POINTER = @HAVE_GCC_A
 MOZ_SPLASHSCREEN = @MOZ_SPLASHSCREEN@
 
 MOZ_THEME_FASTSTRIPE = @MOZ_THEME_FASTSTRIPE@
 
 MOZ_OFFICIAL_BRANDING = @MOZ_OFFICIAL_BRANDING@
 
 HAVE_CLOCK_MONOTONIC = @HAVE_CLOCK_MONOTONIC@
 REALTIME_LIBS = @REALTIME_LIBS@
+
+ANDROID_NDK       = @ANDROID_NDK@
+ANDROID_TOOLCHAIN = @ANDROID_TOOLCHAIN@
+ANDROID_PLATFORM  = @ANDROID_PLATFORM@
+ANDROID_SDK       = @ANDROID_SDK@
+ANDROID_TOOLS     = @ANDROID_TOOLS@
--- a/configure.in
+++ b/configure.in
@@ -235,16 +235,118 @@ AC_SUBST(L10NBASEDIR)
 
 dnl Check for Perl first -- needed for win32 SDK checks
 MOZ_PATH_PROGS(PERL, $PERL perl5 perl )
 if test -z "$PERL" || test "$PERL" = ":"; then
     AC_MSG_ERROR([perl not found in \$PATH])
 fi
 
 dnl ========================================================
+dnl = Android uses a very custom (hacky) toolchain; we need to do this
+dnl = here, so that the compiler checks can succeed
+dnl ========================================================
+
+MOZ_ARG_WITH_STRING(android-ndk,
+[  --with-android-ndk=DIR
+                           location where the Android NDK can be found],
+    android_ndk=$withval)
+
+MOZ_ARG_WITH_STRING(android-toolchain,
+[  --with-android-toolchain=DIR
+                           location of the android toolchain, default NDK/build/prebuilt/HOST/arm-eabi-4.4.0],
+    android_toolchain=$withval)
+
+MOZ_ARG_WITH_STRING(android-platform,
+[  --with-android-platform=DIR
+                           location of NDK platform dir, default NDK/build/platforms/android-5/arch-arm],
+    android_platform=$withval)
+
+MOZ_ARG_WITH_STRING(android-sdk,
+[  --with-android-sdk=DIR
+                           location where the Android SDK can be found (base directory, e.g. .../android/platforms/android-6)],
+    android_sdk=$withval)
+
+MOZ_ARG_WITH_STRING(android-tools,
+[  --with-android-tools=DIR
+                           location where the Android Tools can be found (base directory, e.g. .../android/tools)],
+    android_tools=$withval)
+
+if test "$target" = "arm-android-eabi" ; then
+    if test -z "$android_ndk" ; then
+        AC_MSG_ERROR([You must specify --with-android-ndk=/path/to/ndk when targeting Android.])
+    fi
+
+    if test -z "$android_sdk" ; then
+        AC_MSG_ERROR([You must specify --with-android-sdk=/path/to/sdk when targeting Android.])
+    fi
+
+    if test -z "$android_tools" ; then
+        AC_MSG_ERROR([You must specify --with-android-tools=/path/to/sdk/tools when targeting Android.])
+    fi
+
+    if test -z "$android_toolchain" ; then
+        android_toolchain="$android_ndk"/build/prebuilt/`uname -s | tr "[[:upper:]]" "[[:lower:]]"`-x86/arm-eabi-4.4.0
+    fi
+
+    if test -z "$android_platform" ; then
+       android_platform="$android_ndk"/build/platforms/android-5/arch-arm
+    fi
+
+    dnl set up compilers
+    AS="$android_toolchain"/bin/arm-eabi-as
+    CC="$android_toolchain"/bin/arm-eabi-gcc
+    CXX="$android_toolchain"/bin/arm-eabi-g++
+    CPP="$android_toolchain"/bin/arm-eabi-cpp
+    LD="$android_toolchain"/bin/arm-eabi-ld
+    AR="$android_toolchain"/bin/arm-eabi-ar
+    RANLIB="$android_toolchain"/bin/arm-eabi-ranlib
+    STRIP="$android_toolchain"/bin/arm-eabi-strip
+
+    CPPFLAGS="-I$android_platform/usr/include $CPPFLAGS"
+    CFLAGS="-mandroid -I$android_platform/usr/include -msoft-float -fno-short-enums -fno-exceptions -march=armv5te -mthumb-interwork $CFLAGS"
+    CXXFLAGS="-mandroid -I$android_platform/usr/include -msoft-float -fno-short-enums -fno-exceptions -march=armv5te -mthumb-interwork $CXXFLAGS"
+
+    dnl Add -llog by default, since we use it all over the place.
+    dnl Add --allow-shlib-undefined, because libGLESv2 links to an
+    dnl undefined symbol (present on the hardware, just not in the
+    dnl NDK.)
+    LDFLAGS="-mandroid -L$android_platform/usr/lib -Wl,-rpath-link=$android_platform/usr/lib --sysroot=$android_platform -llog -Wl,--allow-shlib-undefined $LDFLAGS"
+
+    dnl prevent cross compile section from using these flags as host flags
+    if test -z "$HOST_CPPFLAGS" ; then
+        HOST_CPPFLAGS=" "
+    fi
+    if test -z "$HOST_CFLAGS" ; then
+        HOST_CFLAGS=" "
+    fi
+    if test -z "$HOST_CXXFLAGS" ; then
+        HOST_CXXFLAGS=" "
+    fi
+    if test -z "$HOST_LDFLAGS" ; then
+        HOST_LDFLAGS=" "
+    fi
+
+    ANDROID_NDK="${android_ndk}"
+    ANDROID_TOOLCHAIN="{android_toolchain}"
+    ANDROID_PLATFORM="{android_platform}"
+    ANDROID_SDK="${android_sdk}"
+    ANDROID_TOOLS="${android_tools}"
+
+    AC_DEFINE(ANDROID)
+    CROSS_COMPILE=1
+    MOZ_CHROME_FILE_FORMAT=omni
+fi
+
+AC_SUBST(ANDROID_NDK)
+AC_SUBST(ANDROID_TOOLCHAIN)
+AC_SUBST(ANDROID_PLATFORM)
+AC_SUBST(ANDROID_SDK)
+AC_SUBST(ANDROID_TOOLS)
+
+dnl ========================================================
 dnl Checks for compilers.
 dnl ========================================================
 dnl Set CROSS_COMPILE in the environment when running configure
 dnl to use the cross-compile setup for now
 dnl ========================================================
 
 dnl AR_FLAGS set here so HOST_AR_FLAGS can be set correctly (see bug 538269)
 AR_FLAGS='cr $@'
@@ -1144,16 +1246,19 @@ if test -n "$CROSS_COMPILE"; then
         kfreebsd*-gnu) OS_ARCH=GNU_kFreeBSD OS_TARGET=GNU_kFreeBSD ;;
         gnu*)         OS_ARCH=GNU ;;
         solaris*)     OS_ARCH=SunOS OS_RELEASE=5 ;;
         mingw*)       OS_ARCH=WINNT ;;
         wince*)       OS_ARCH=WINCE ;;
         winmo*)       OS_ARCH=WINCE ;;
         darwin*)      OS_ARCH=Darwin OS_TARGET=Darwin ;;
     esac
+    case "${target}" in
+        arm-android-eabi) OS_ARCH=Linux OS_TARGET=Android ;;
+    esac
 else
     OS_TARGET=`uname -s`
     OS_ARCH=`uname -s | sed -e 's|/|_|g'`
     OS_RELEASE=`uname -r`
 fi
 
 # Before this used `uname -m` when not cross compiling
 # but that breaks when you have a 64 bit kernel with a 32 bit userland.
@@ -1455,16 +1560,19 @@ if test "$GNU_CC"; then
     # FIXME: Let us build with strict aliasing. bug 414641.
     CFLAGS="$CFLAGS -fno-strict-aliasing"
     MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$@ -o $@'
     MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$@ -o $@'
     DSO_LDOPTS='-shared'
     if test "$GCC_USE_GNU_LD"; then
         # Don't allow undefined symbols in libraries
         DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs"
+        LDFLAGS="$LDFLAGS -Wl,--gc-sections"
+        CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"
+        CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections"
     fi
     WARNINGS_AS_ERRORS='-Werror'
     DSO_CFLAGS=''
     DSO_PIC_CFLAGS='-fPIC'
     ASFLAGS="$ASFLAGS -fPIC"
     _MOZ_RTTI_FLAGS_ON=${_COMPILER_PREFIX}-frtti
     _MOZ_RTTI_FLAGS_OFF=${_COMPILER_PREFIX}-fno-rtti
     _MOZ_EXCEPTIONS_FLAGS_ON='-fhandle-exceptions'
@@ -1489,22 +1597,18 @@ if test "$GNU_CC"; then
            ;;
        esac
     fi
 
     dnl Turn pedantic on but disable the warnings for long long
     _PEDANTIC=1
 
     if test -z "$INTEL_CC"; then
-      _IGNORE_LONG_LONG_WARNINGS=1
       _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -W"
-    else
-      _IGNORE_LONG_LONG_WARNINGS=
-    fi
-
+    fi
 
     _DEFINES_CFLAGS='-include $(DEPTH)/mozilla-config.h -DMOZILLA_CLIENT'
     _USE_CPP_INCLUDE_FLAG=1
 elif test "$SOLARIS_SUNPRO_CC"; then
     MKSHLIB='$(LD) $(DSO_LDOPTS) -h $@ -o $@'
     MKCSHLIB='$(LD) $(DSO_LDOPTS) -h $@ -o $@'
 
     DSO_LDOPTS='-shared'
@@ -1909,17 +2013,16 @@ case "$target" in
     _MOZ_USE_RTTI=1
     USE_DEPENDENT_LIBS=
     MOZ_USER_DIR="Mozilla"
     ;;
 
 *-bsdi*)
     dnl -pedantic doesn't play well with BSDI's _very_ modified gcc (shlicc2)
     _PEDANTIC=
-    _IGNORE_LONG_LONG_WARNINGS=
     case $OS_RELEASE in
 	4.*|5.*)
             STRIP="$STRIP -d"
             ;;
 	*)
 	    DSO_CFLAGS=''
 	    DSO_LDOPTS='-r'
 	    _WARNINGS_CFLAGS="-Wall"
@@ -2788,16 +2891,28 @@ alpha*-*-osf*)
 *-sysv4.2uw7*) 
 	NSPR_LIBS="-lnspr$NSPR_VERSION -lplc$NSPR_VERSION -lplds$NSPR_VERSION -L/usr/ccs/lib -lcrt"
     ;;
 
 *-os2*)
     HOST_NSPR_MDCPUCFG='\"md/_os2.cfg\"'
     ;;
 
+*-android*)
+    AC_DEFINE(NO_PW_GECOS)
+    no_x=yes
+    _PLATFORM_DEFAULT_TOOLKIT=cairo-android
+    TARGET_NSPR_MDCPUCFG='\"md/_linux.cfg\"'
+
+    MOZ_GFX_OPTIMIZE_MOBILE=1
+    MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fno-reorder-functions -fomit-frame-pointer"
+
+    dnl MOZ_MEMORY=1
+    ;;
+
 esac
 
 dnl Only one oddball right now (QNX), but this gives us flexibility
 dnl if any other platforms need to override this in the future.
 AC_DEFINE_UNQUOTED(D_INO,$DIRENT_INO)
 
 dnl ========================================================
 dnl Any platform that doesn't have MKSHLIB_FORCE_ALL defined
@@ -4366,18 +4481,21 @@ AC_CACHE_CHECK(for __thread keyword for 
                [AC_TRY_LINK([__thread bool tlsIsMainThread = false;],
                             [return tlsIsMainThread;],
                             ac_cv_thread_keyword=yes,
                             ac_cv_thread_keyword=no)])
 LDFLAGS=$_SAVE_LDFLAGS
 if test "$ac_cv_thread_keyword" = yes; then
   # mips builds fail with TLS variables because of a binutils bug.
   # See bug 528687
-  case "${target_cpu}" in
-    mips*)
+  case "${target}" in
+    mips*-*)
+      :
+      ;;
+    *-android*)
       :
       ;;
     *)
       AC_DEFINE(HAVE_THREAD_TLS_KEYWORD)
       ;;
   esac
 fi
 
@@ -4550,22 +4668,22 @@ MOZ_ARG_WITH_BOOL(system-nspr,
 
 if test -n "$_USE_SYSTEM_NSPR"; then
     AM_PATH_NSPR(4.8.0, [MOZ_NATIVE_NSPR=1], [MOZ_NATIVE_NSPR=])
 fi
 
 if test -n "$MOZ_NATIVE_NSPR"; then
     _SAVE_CFLAGS=$CFLAGS
     CFLAGS="$CFLAGS $NSPR_CFLAGS"
-    AC_TRY_COMPILE([#include "prlog.h"],
+    AC_TRY_COMPILE([#include "prtypes.h"],
                 [#ifndef PR_STATIC_ASSERT
-                 #error PR_STATIC_ASSERT not defined
+                 #error PR_STATIC_ASSERT not defined or requires including prlog.h
                  #endif],
                 [MOZ_NATIVE_NSPR=1],
-                AC_MSG_ERROR([system NSPR does not support PR_STATIC_ASSERT]))
+                AC_MSG_ERROR([system NSPR does not support PR_STATIC_ASSERT or including prtypes.h does not provide it]))
     CFLAGS=$_SAVE_CFLAGS
 else
     if test "$OS_ARCH" = "WINCE"; then
         NSPR_CFLAGS="-I${LIBXUL_DIST}/include/nspr"
         NSPR_LIBS="${LIBXUL_DIST}/lib/nspr${NSPR_VERSION}.lib ${LIBXUL_DIST}/lib/plc${NSPR_VERSION}.lib ${LIBXUL_DIST}/lib/plds${NSPR_VERSION}.lib "
     elif test "$OS_ARCH" = "WINNT"; then
         NSPR_CFLAGS="-I${LIBXUL_DIST}/include/nspr"
         if test -n "$GNU_CC"; then
@@ -5058,17 +5176,18 @@ MOZ_ARG_HEADER(Toolkit Options)
     if test "$_DEFAULT_TOOLKIT" = "photon" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-windows" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-gtk2" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-gtk2-dfb" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-gtk2-x11" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-qt" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-beos" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-os2" \
-        -o "$_DEFAULT_TOOLKIT" = "cairo-cocoa"
+        -o "$_DEFAULT_TOOLKIT" = "cairo-cocoa" \
+        -o "$_DEFAULT_TOOLKIT" = "cairo-android"
     then
         dnl nglayout only supports building with one toolkit,
         dnl so ignore everything after the first comma (",").
         MOZ_WIDGET_TOOLKIT=`echo "$_DEFAULT_TOOLKIT" | sed -e "s/,.*$//"`
     else
         AC_MSG_ERROR([You must specify a default toolkit (perhaps $_PLATFORM_DEFAULT_TOOLKIT).])
     fi
 
@@ -5166,16 +5285,23 @@ cairo-cocoa)
     TK_CFLAGS="-DNO_X11"
     LDFLAGS="$LDFLAGS -framework Cocoa -lobjc"
     CFLAGS="$CFLAGS $TK_CFLAGS"
     CXXFLAGS="$CXXFLAGS $TK_CFLAGS"
     LIBXUL_LIBS='$(XPCOM_FROZEN_LDOPTS) $(LIBXUL_DIST)/bin/XUL'
     MOZ_FS_LAYOUT=bundle
     MOZ_WEBGL=1
     ;;
+
+cairo-android)
+    AC_DEFINE(MOZ_WIDGET_ANDROID)
+    MOZ_WIDGET_TOOLKIT=android
+    MOZ_WEBGL=
+    ;;
+
 esac
 
 if test "$MOZ_ENABLE_XREMOTE"; then
     AC_DEFINE(MOZ_ENABLE_XREMOTE)
 fi
 
 if test "$COMPILE_ENVIRONMENT"; then
   if test "$MOZ_ENABLE_GTK2"; then
@@ -5624,17 +5750,17 @@ MOZ_ARG_DISABLE_BOOL(jsd,
     MOZ_JSDEBUGGER=,
     MOZ_JSDEBUGGER=1)
 
 
 dnl ========================================================
 dnl = Disable IPC support for tabs and plugins
 dnl ========================================================
 case "${target}" in
-*-wince*)
+*-wince*|*-android*)
     MOZ_IPC=
     ;;
 esac
 
 MOZ_ARG_DISABLE_BOOL(ipc,
 [  --disable-ipc           Disable IPC supports for tabs and plugins],
     MOZ_IPC=,
     MOZ_IPC=1)
@@ -6806,29 +6932,17 @@ MOZ_ARG_ENABLE_STRING(debug,
         MOZ_DEBUG_FLAGS=`echo $enableval | sed -e 's|\\\ | |g'`
         _MOZ_DEBUG_FLAGS_SET=1
     fi
   else
     MOZ_DEBUG=
   fi ],
   MOZ_DEBUG=)
 
-MOZ_DEBUG_ENABLE_DEFS="-DDEBUG -D_DEBUG"
- case "${target_os}" in
-    beos*)
-        MOZ_DEBUG_ENABLE_DEFS="$MOZ_DEBUG_ENABLE_DEFS -DDEBUG_${USER}"
-        ;;
-    msvc*|mks*|cygwin*|mingw*|os2*|wince*|winmo*)
-        MOZ_DEBUG_ENABLE_DEFS="$MOZ_DEBUG_ENABLE_DEFS -DDEBUG_`echo ${USERNAME} | sed -e 's| |_|g'`"
-        ;;
-    *) 
-        MOZ_DEBUG_ENABLE_DEFS="$MOZ_DEBUG_ENABLE_DEFS -DDEBUG_`$WHOAMI`"
-        ;;
-  esac
-MOZ_DEBUG_ENABLE_DEFS="$MOZ_DEBUG_ENABLE_DEFS -DTRACING"
+MOZ_DEBUG_ENABLE_DEFS="-DDEBUG -D_DEBUG -DTRACING"
 
 MOZ_DEBUG_DISABLE_DEFS="-DNDEBUG -DTRIMMED"
 
 if test -n "$MOZ_DEBUG"; then
     AC_MSG_CHECKING([for valid debug flags])
     _SAVE_CFLAGS=$CFLAGS
     CFLAGS="$CFLAGS $MOZ_DEBUG_FLAGS"
     AC_TRY_COMPILE([#include <stdio.h>], 
@@ -7367,34 +7481,51 @@ MOZ_ARG_ENABLE_BOOL(xterm-updates,
 [  --enable-xterm-updates  Update XTERM titles with current command.],
     MOZ_UPDATE_XTERM=1,
     MOZ_UPDATE_XTERM= )
 
 dnl =========================================================
 dnl = Chrome format
 dnl =========================================================
 MOZ_ARG_ENABLE_STRING([chrome-format],
-[  --enable-chrome-format=jar|flat|both|symlink
+[  --enable-chrome-format=jar|flat|both|symlink|omni
                           Select FORMAT of chrome files (default=jar)],
     MOZ_CHROME_FILE_FORMAT=`echo $enableval | tr A-Z a-z`)
 
 if test -z "$MOZ_CHROME_FILE_FORMAT"; then
     MOZ_CHROME_FILE_FORMAT=jar
 fi
 
 if test "$MOZ_CHROME_FILE_FORMAT" != "jar" && 
     test "$MOZ_CHROME_FILE_FORMAT" != "flat" &&
     test "$MOZ_CHROME_FILE_FORMAT" != "symlink" &&
-    test "$MOZ_CHROME_FILE_FORMAT" != "both"; then
-    AC_MSG_ERROR([--enable-chrome-format must be set to either jar, flat, both, or symlink])
-fi
-
-if test "$MOZ_CHROME_FILE_FORMAT" = "jar"; then
-   AC_DEFINE(MOZ_CHROME_FILE_FORMAT_JAR)
-fi
+    test "$MOZ_CHROME_FILE_FORMAT" != "both" &&
+    test "$MOZ_CHROME_FILE_FORMAT" != "omni"; then
+    AC_MSG_ERROR([--enable-chrome-format must be set to either jar, flat, both, symlink, or omni])
+fi
+
+dnl =========================================================
+dnl Omnijar packaging (bug 552121)
+dnl =========================================================
+dnl Omnijar packaging is compatible with flat packaging.
+dnl In unpackaged builds, omnijar looks for files as if
+dnl things were flat packaged. After packaging, all files
+dnl are loaded from a single jar. MOZ_CHROME_FILE_FORMAT
+dnl is set to flat since putting files into jars is only
+dnl done during packaging with omnijar.
+if test "$MOZ_CHROME_FILE_FORMAT" = "omni"; then
+    MOZ_OMNIJAR=1
+    AC_DEFINE(MOZ_OMNIJAR)
+    MOZ_CHROME_FILE_FORMAT=flat
+elif test "$MOZ_CHROME_FILE_FORMAT" = "jar"; then
+    AC_DEFINE(MOZ_CHROME_FILE_FORMAT_JAR)
+fi
+
+AC_SUBST(MOZ_OMNIJAR)
+
 dnl ========================================================
 dnl = Define default location for MOZILLA_FIVE_HOME
 dnl ========================================================
 MOZ_ARG_WITH_STRING(default-mozilla-five-home,
 [  --with-default-mozilla-five-home
                           Set the default value for MOZILLA_FIVE_HOME],
 [ val=`echo $withval`
   AC_DEFINE_UNQUOTED(MOZ_DEFAULT_MOZILLA_FIVE_HOME,"$val") ])
@@ -7479,38 +7610,16 @@ if test -n "$GNU_CC" && test -n "$GNU_CX
     fi
     rm -f dummy-hello.c dummy-hello.s dummy-hello.S dummy-hello a.out
     AC_MSG_RESULT([$_res])
 else
     AC_MSG_RESULT([no])
 fi
 
 dnl ========================================================
-dnl Pass -Wno-long-long to the compiler
-dnl ========================================================
-MOZ_ARG_DISABLE_BOOL(long-long-warning,
-[  --disable-long-long-warning
-                          Do not warn about use of non-ANSI long long type (if supported)],
-    _IGNORE_LONG_LONG_WARNINGS=1,
-    _IGNORE_LONG_LONG_WARNINGS=)
-
-if test -n "$_IGNORE_LONG_LONG_WARNINGS"; then
-    _SAVE_CFLAGS="$CFLAGS"
-    CFLAGS="$CFLAGS ${_COMPILER_PREFIX}-Wno-long-long"
-    AC_MSG_CHECKING([whether compiler supports -Wno-long-long])
-    AC_TRY_COMPILE([], [return(0);],
-      [ _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} ${_COMPILER_PREFIX}-Wno-long-long"
-        _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-Wno-long-long"
-        result="yes" ],
-      result="no")
-    AC_MSG_RESULT([$result])
-    CFLAGS="$_SAVE_CFLAGS"
-fi
-
-dnl ========================================================
 dnl Profile guided optimization
 dnl ========================================================
 dnl Test for profiling options
 dnl Under gcc 3.3, use -fprofile-arcs/-fbranch-probabilities
 dnl Under gcc 3.4+, use -fprofile-generate/-fprofile-use
 
 dnl Provide a switch to disable PGO even when called via profiledbuild.
 MOZ_ARG_DISABLE_BOOL(profile-guided-optimization,
@@ -7576,28 +7685,28 @@ AC_LANG_CPLUSPLUS
 dnl ========================================================
 dnl Test for -pedantic bustage
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(pedantic,
 [  --disable-pedantic      Issue all warnings demanded by strict ANSI C ],
 _PEDANTIC= )
 if test "$_PEDANTIC"; then
     _SAVE_CXXFLAGS=$CXXFLAGS
-    CXXFLAGS="$CXXFLAGS ${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-pedantic"
+    CXXFLAGS="$CXXFLAGS ${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-pedantic ${_COMPILER_PREFIX}-Wno-long-long"
     AC_MSG_CHECKING([whether C++ compiler has -pedantic long long bug])
     AC_TRY_COMPILE([$configure_static_assert_macros],
                    [CONFIGURE_STATIC_ASSERT(sizeof(long long) == 8)],
                    result="no", result="yes" )
     AC_MSG_RESULT([$result])
     CXXFLAGS="$_SAVE_CXXFLAGS"
 
     case "$result" in
     no)
-        _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} ${_COMPILER_PREFIX}-pedantic"
-        _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-pedantic"
+        _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} ${_COMPILER_PREFIX}-pedantic ${_COMPILER_PREFIX}-Wno-long-long"
+        _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-pedantic ${_COMPILER_PREFIX}-Wno-long-long"
         ;;
     yes)
         AC_MSG_ERROR([Your compiler appears to have a known bug where long long is miscompiled when using -pedantic.  Reconfigure using --disable-pedantic. ])
         ;;
     esac
 fi
 
 dnl ========================================================
--- a/content/base/crashtests/crashtests.list
+++ b/content/base/crashtests/crashtests.list
@@ -14,17 +14,17 @@ load 326865-1.html
 load 327694.html
 load 330925-1.xhtml
 load 336381-1.xhtml
 load 336715-1.xhtml
 load 338391-1.xhtml
 load 340733-1.html
 load 343730-1.xhtml
 load 343850-1.xhtml
-asserts(3) load 343889-1.html # bug 563536
+load 343889-1.html
 load 344434-1.xhtml
 load 348049-1.xhtml
 load 344882-1.html
 load 345837-1.xhtml
 load 349355-1.html
 asserts(1) load 354645-1.xul # bug 512815
 load 360599-1.html
 load 366200-1.xhtml
@@ -36,17 +36,17 @@ load 386000-1.html
 load 386794-1.html
 load 387460-1.html
 load 395469-1.xhtml
 load 395469-2.xhtml
 skip load 399712-1.html # sporadically times out (bug 473680)
 load 398088-1.xul
 load 400763-1.html
 load 401993-1.html
-asserts(1) load 407818.html # bug 336104
+load 407818.html
 load 410860-1.xml
 load 416734-1.html
 load 418928-1.html
 load 420620-1.html
 asserts(2) load 424276-1.html # bug 462897
 load 426987-1.html
 load 443538-1.svg
 load 450383-1.html
@@ -55,14 +55,14 @@ skip load 458637-1.html # sporadically t
 load 472593-1.html
 load 474041-1.svg
 load 483818-1.html
 load 493281-1.html
 load 493281-2.html
 load 490760-1.xhtml
 load 494810-1.html
 load 529670.html
-asserts(1) load 554230-1.xhtml # bug 336104
+load 554230-1.xhtml
 load 552651.html
 load 558973.html
 load 564079-1.html 
 load 564114.html
 load 565125-1.html
--- a/content/base/public/mozFlushType.h
+++ b/content/base/public/mozFlushType.h
@@ -35,16 +35,19 @@
  *
  * ***** END LICENSE BLOCK ***** */
 #ifndef mozFlushType_h___
 #define mozFlushType_h___
 
 /**
  * This is the enum used by nsIDocument::FlushPendingNotifications to
  * decide what to flush.
+ *
+ * Please note that if you change these values, you should sync it with the
+ * flushTypeNames array inside PresShell::FlushPendingNotifications.
  */
 enum mozFlushType {
   Flush_Content          = 1, /* flush the content model construction */
   Flush_ContentAndNotify = 2, /* As above, plus flush the frame model
                                  construction and other nsIMutationObserver
                                  notifications. */
   Flush_Style            = 3, /* As above, plus flush style reresolution */
   Flush_Frames           = Flush_Style,
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -133,19 +133,24 @@ class nsPresContext;
 #ifndef have_PrefChangedFunc_typedef
 typedef int (*PR_CALLBACK PrefChangedFunc)(const char *, void *);
 #define have_PrefChangedFunc_typedef
 #endif
 
 namespace mozilla {
   class IHistory;
 
+namespace layers {
+  class LayerManager;
+} // namespace layers
+
 namespace dom {
 class Element;
 } // namespace dom
+
 } // namespace mozilla
 
 extern const char kLoadAsData[];
 
 enum EventNameType {
   EventNameType_None = 0x0000,
   EventNameType_HTML = 0x0001,
   EventNameType_XUL = 0x0002,
@@ -1598,16 +1603,29 @@ public:
   /**
    * Utility method for getElementsByClassName.  aRootNode is the node (either
    * document or element), which getElementsByClassName was called on.
    */
   static nsresult GetElementsByClassName(nsINode* aRootNode,
                                          const nsAString& aClasses,
                                          nsIDOMNodeList** aReturn);
 
+  /**
+   * Returns a layer manager to use for the given document. Basically we
+   * look up the document hierarchy for the first document which has
+   * a presentation with an associated widget, and use that widget's
+   * layer manager.
+   *
+   * If one can't be found, a BasicLayerManager is created and returned.
+   *
+   * @param aDoc the document for which to return a layer manager.
+   */
+  static already_AddRefed<mozilla::layers::LayerManager>
+  LayerManagerForDocument(nsIDocument *aDoc);
+
 private:
 
   static PRBool InitializeEventTable();
 
   static nsresult EnsureStringBundle(PropertiesFile aFile);
 
   static nsIDOMScriptObjectFactory *GetDOMScriptObjectFactory();
 
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -1353,16 +1353,25 @@ public:
    */
   virtual void RegisterFileDataUri(nsACString& aUri) = 0;
 
   virtual void SetScrollToRef(nsIURI *aDocumentURI) = 0;
   virtual void ScrollToRef() = 0;
   virtual void ResetScrolledToRefAlready() = 0;
   virtual void SetChangeScrollPosWhenScrollingToRef(PRBool aValue) = 0;
 
+  /**
+   * This method is similar to GetElementById() from nsIDOMDocument but it
+   * returns a mozilla::dom::Element instead of a nsIDOMElement.
+   * It prevents converting nsIDOMElement to mozill:dom::Element which is
+   * already converted from mozilla::dom::Element.
+   */
+  virtual mozilla::dom::Element* GetElementById(const nsAString& aElementId,
+                                                nsresult* aResult) = 0;
+
 protected:
   ~nsIDocument()
   {
     // XXX The cleanup of mNodeInfoManager (calling DropDocumentReference and
     //     releasing it) happens in the nsDocument destructor. We'd prefer to
     //     do it here but nsNodeInfoManager is a concrete class that we don't
     //     want to expose to users of the nsIDocument API outside of Gecko.
   }
--- a/content/base/public/nsIFrameLoader.idl
+++ b/content/base/public/nsIFrameLoader.idl
@@ -41,17 +41,17 @@
 
 interface nsIDocShell;
 interface nsIURI;
 interface nsIWebProgress;
 interface nsIFrame;
 interface nsIChromeFrameMessageManager;
 interface nsIVariant;
 
-[scriptable, uuid(85a7f80b-4a3f-4606-8513-a1c4cced874f)]
+[scriptable, uuid(bd69ff3d-d2cb-4dee-94e4-c6948df7603a)]
 interface nsIFrameLoader : nsISupports
 {
   /**
    * Get the docshell from the frame loader.
    */
   readonly attribute nsIDocShell docShell;
 
   /**
@@ -108,16 +108,17 @@ interface nsIFrameLoader : nsISupports
                                   in long aModifiers,
                                   [optional] in boolean aIgnoreRootScrollFrame);
 
   /**
    * Activate event forwarding from client (remote frame) to parent.
    */
   void activateFrameEvent(in AString aType, in boolean capture);
 
+  // Note, when frameloaders are swapped, also messageManagers are swapped.
   readonly attribute nsIChromeFrameMessageManager messageManager;
 
   /**
    * @see nsIDOMWindowUtils sendKeyEvent.
    */
   void sendCrossProcessKeyEvent(in AString aType,
                                 in long aKeyCode,
                                 in long aCharCode,
--- a/content/base/public/nsIFrameMessageManager.idl
+++ b/content/base/public/nsIFrameMessageManager.idl
@@ -34,16 +34,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 
 interface nsIDOMWindow;
 interface nsIDocShell;
+interface nsIContent;
 
 [scriptable, function, uuid(938fcb95-3d63-46be-aa72-94d08fd3b418)]
 interface nsIFrameMessageListener : nsISupports
 {
   /**
    * This is for JS only.
    * receiveMessage is called with one parameter, which has the following
    * properties:
@@ -92,16 +93,22 @@ interface nsIContentFrameMessageManager 
   readonly attribute nsIDocShell docShell;
 
   /**
    * Print a string to stdout.
    */
   void dump(in DOMString aStr);
 };
 
+[uuid(9c48d557-92fe-4edb-95fc-bfe97e77bdc3)]
+interface nsIInProcessContentFrameMessageManager : nsIContentFrameMessageManager
+{
+  [notxpcom] nsIContent getOwnerContent();
+};
+
 [scriptable, uuid(ed6522fd-ffb6-4920-b50d-cf629309616b)]
 interface nsIChromeFrameMessageManager : nsIFrameMessageManager
 {
   /*
    * Load a script in the (remote) frame. aURL must be the absolute URL.
    * data: URLs are also supported. For example data:,dump("foo\n");
    * If aAllowDelayedLoad is true, script will be loaded when the
    * remote frame becomes available. Otherwise the script will be loaded
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -138,18 +138,19 @@ CPPSRCS		= \
 		nsTextNode.cpp \
 		nsTraversal.cpp \
 		nsTreeWalker.cpp \
 		nsXHTMLContentSerializer.cpp \
 		nsXMLContentSerializer.cpp \
 		nsXMLHttpRequest.cpp \
 		nsXMLNameSpaceMap.cpp \
 		Link.cpp \
+		nsFileDataProtocolHandler.cpp \
 		nsFrameMessageManager.cpp \
-		nsFileDataProtocolHandler.cpp \
+		nsInProcessTabChildGlobal.cpp \
 		$(NULL)
 
 GQI_SRCS = contentbase.gqi
 
 # we don't want the shared lib, but we want to force the creation of a
 # static lib.
 FORCE_STATIC_LIB = 1
 
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -170,16 +170,19 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_
 #include "nsIMIMEHeaderParam.h"
 #include "nsIDOMXULCommandEvent.h"
 #include "nsIDOMAbstractView.h"
 #include "nsIDOMDragEvent.h"
 #include "nsDOMDataTransfer.h"
 #include "nsHtml5Module.h"
 #include "nsPresContext.h"
 #include "nsLayoutStatics.h"
+#include "nsLayoutUtils.h"
+#include "nsFrameManager.h"
+#include "BasicLayers.h"
 
 #ifdef IBMBIDI
 #include "nsIBidiKeyboard.h"
 #endif
 #include "nsCycleCollectionParticipant.h"
 
 // for ReportToConsole
 #include "nsIStringBundle.h"
@@ -190,16 +193,19 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_
 #include "imgICache.h"
 #include "jsinterp.h"
 #include "jsarray.h"
 #include "jsdate.h"
 #include "jsregexp.h"
 #include "jstypedarray.h"
 #include "xpcprivate.h"
 #include "nsScriptSecurityManager.h"
+#include "nsIChannelPolicy.h"
+#include "nsChannelPolicy.h"
+#include "nsIContentSecurityPolicy.h"
 
 using namespace mozilla::dom;
 
 const char kLoadAsData[] = "loadAsData";
 
 static const char kJSStackContractID[] = "@mozilla.org/js/xpc/ContextStack;1";
 static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
 static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
@@ -2319,33 +2325,45 @@ nsContentUtils::LoadImage(nsIURI* aURI, 
     return NS_OK;
   }
 
   nsCOMPtr<nsILoadGroup> loadGroup = aLoadingDocument->GetDocumentLoadGroup();
   NS_ASSERTION(loadGroup, "Could not get loadgroup; onload may fire too early");
 
   nsIURI *documentURI = aLoadingDocument->GetDocumentURI();
 
+  // check for a Content Security Policy to pass down to the channel that
+  // will get created to load the image
+  nsCOMPtr<nsIChannelPolicy> channelPolicy;
+  nsCOMPtr<nsIContentSecurityPolicy> csp;
+  if (aLoadingPrincipal) {
+    nsresult rv = aLoadingPrincipal->GetCsp(getter_AddRefs(csp));
+    NS_ENSURE_SUCCESS(rv, rv);
+    if (csp) {
+      channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
+      channelPolicy->SetContentSecurityPolicy(csp);
+      channelPolicy->SetLoadType(nsIContentPolicy::TYPE_IMAGE);
+    }
+  }
+    
   // Make the URI immutable so people won't change it under us
   NS_TryToSetImmutable(aURI);
 
-  // We don't use aLoadingPrincipal for anything here yet... but we
-  // will.  See bug 377092.
-
   // XXXbz using "documentURI" for the initialDocumentURI is not quite
   // right, but the best we can do here...
   return sImgLoader->LoadImage(aURI,                 /* uri to load */
                                documentURI,          /* initialDocumentURI */
                                aReferrer,            /* referrer */
                                loadGroup,            /* loadgroup */
                                aObserver,            /* imgIDecoderObserver */
                                aLoadingDocument,     /* uniquification key */
                                aLoadFlags,           /* load flags */
                                nsnull,               /* cache key */
                                nsnull,               /* existing request*/
+                               channelPolicy,        /* CSP info */
                                aRequest);
 }
 
 // static
 already_AddRefed<imgIContainer>
 nsContentUtils::GetImageFromContent(nsIImageLoadingContent* aContent,
                                     imgIRequest **aRequest)
 {
@@ -3186,24 +3204,32 @@ nsContentUtils::DispatchChromeEvent(nsID
   nsresult rv = GetEventAndTarget(aDoc, aTarget, aEventName, aCanBubble,
                                   aCancelable, getter_AddRefs(event),
                                   getter_AddRefs(target));
   NS_ENSURE_SUCCESS(rv, rv);
 
   NS_ASSERTION(aDoc, "GetEventAndTarget lied?");
   if (!aDoc->GetWindow())
     return NS_ERROR_INVALID_ARG;
-  if (!aDoc->GetWindow()->GetChromeEventHandler())
+
+  nsPIDOMEventTarget* piTarget = aDoc->GetWindow()->GetChromeEventHandler();
+  if (!piTarget)
     return NS_ERROR_INVALID_ARG;
 
+  nsCOMPtr<nsIFrameLoaderOwner> flo = do_QueryInterface(piTarget);
+  if (flo) {
+    nsRefPtr<nsFrameLoader> fl = flo->GetFrameLoader();
+    if (fl) {
+      nsPIDOMEventTarget* t = fl->GetTabChildGlobalAsEventTarget();
+      piTarget = t ? t : piTarget;
+    }
+  }
+
   nsEventStatus status = nsEventStatus_eIgnore;
-  rv = aDoc->GetWindow()->GetChromeEventHandler()->DispatchDOMEvent(nsnull,
-                                                                    event,
-                                                                    nsnull,
-                                                                    &status);
+  rv = piTarget->DispatchDOMEvent(nsnull, event, nsnull, &status);
   if (aDefaultAction) {
     *aDefaultAction = (status != nsEventStatus_eConsumeNoDefault);
   }
   return rv;
 }
 
 /* static */
 Element*
@@ -5489,17 +5515,17 @@ CloneSimpleValues(JSContext* cx,
   // We'll use immutable strings to prevent copying if we can.
   if (JSVAL_IS_STRING(val)) {
     if (!JS_MakeStringImmutable(cx, JSVAL_TO_STRING(val))) {
       return NS_ERROR_FAILURE;
     }
     return SetPropertyOnValueOrObject(cx, val, rval, robj, rid);
   }
 
-  NS_ASSERTION(JSVAL_IS_OBJECT(val), "Not an object!");
+  NS_ASSERTION(!JSVAL_IS_PRIMITIVE(val), "Not an object!");
   JSObject* obj = JSVAL_TO_OBJECT(val);
 
   // Dense arrays of primitives can be cloned quickly.
   JSObject* newArray;
   if (!js_CloneDensePrimitiveArray(cx, obj, &newArray)) {
     return NS_ERROR_FAILURE;
   }
   if (newArray) {
@@ -5958,28 +5984,77 @@ mozAutoRemovableBlockerRemover::~mozAuto
 
 void nsContentUtils::RemoveNewlines(nsString &aString)
 {
   // strip CR/LF and null
   static const char badChars[] = {'\r', '\n', 0};
   aString.StripChars(badChars);
 }
 
-void nsContentUtils::PlatformToDOMLineBreaks(nsString &aString)
+void
+nsContentUtils::PlatformToDOMLineBreaks(nsString &aString)
 {
   if (aString.FindChar(PRUnichar('\r')) != -1) {
     // Windows linebreaks: Map CRLF to LF:
     aString.ReplaceSubstring(NS_LITERAL_STRING("\r\n").get(),
                              NS_LITERAL_STRING("\n").get());
 
     // Mac linebreaks: Map any remaining CR to LF:
     aString.ReplaceSubstring(NS_LITERAL_STRING("\r").get(),
                              NS_LITERAL_STRING("\n").get());
   }
 }
 
+already_AddRefed<mozilla::layers::LayerManager>
+nsContentUtils::LayerManagerForDocument(nsIDocument *aDoc)
+{
+  nsIDocument* doc = aDoc;
+  nsIDocument* displayDoc = doc->GetDisplayDocument();
+  if (displayDoc) {
+    doc = displayDoc;
+  }
+
+  nsIPresShell* shell = doc->GetPrimaryShell();
+  nsCOMPtr<nsISupports> container = doc->GetContainer();
+  nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = do_QueryInterface(container);
+  while (!shell && docShellTreeItem) {
+    // We may be in a display:none subdocument, or we may not have a presshell
+    // created yet.
+    // Walk the docshell tree to find the nearest container that has a presshell,
+    // and find the root widget from that.
+    nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(docShellTreeItem);
+    nsCOMPtr<nsIPresShell> presShell;
+    docShell->GetPresShell(getter_AddRefs(presShell));
+    if (presShell) {
+      shell = presShell;
+    } else {
+      nsCOMPtr<nsIDocShellTreeItem> parent;
+      docShellTreeItem->GetParent(getter_AddRefs(parent));
+      docShellTreeItem = parent;
+    }
+  }
+
+  if (shell) {
+    nsIFrame* rootFrame = shell->FrameManager()->GetRootFrame();
+    if (rootFrame) {
+      nsIWidget* widget =
+        nsLayoutUtils::GetDisplayRootFrame(rootFrame)->GetWindow();
+      if (widget) {
+        nsRefPtr<mozilla::layers::LayerManager> manager = widget->GetLayerManager();
+        return manager.forget();
+      }
+    }
+  }
+
+  nsRefPtr<mozilla::layers::LayerManager> manager =
+    new mozilla::layers::BasicLayerManager(nsnull);
+  return manager.forget();
+}
+
+
 NS_IMPL_ISUPPORTS1(nsIContentUtils, nsIContentUtils)
 
 PRBool
 nsIContentUtils::IsSafeToRunScript()
 {
   return nsContentUtils::IsSafeToRunScript();
 }
+
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -2009,48 +2009,48 @@ nsDocument::ResetStylesheetsToURI(nsIURI
 
   // Release all the sheets
   mStyleSheets.Clear();
   // NOTE:  We don't release the catalog sheets.  It doesn't really matter
   // now, but it could in the future -- in which case not releasing them
   // is probably the right thing to do.
 
   // Now reset our inline style and attribute sheets.
-  nsresult rv;
+  nsresult rv = NS_OK;
   nsStyleSet::sheetType attrSheetType = GetAttrSheetType();
   if (mAttrStyleSheet) {
     // Remove this sheet from all style sets
     nsCOMPtr<nsIPresShell> shell = GetPrimaryShell();
     if (shell) {
       shell->StyleSet()->RemoveStyleSheet(attrSheetType, mAttrStyleSheet);
     }
-    rv = mAttrStyleSheet->Reset(aURI);
+    mAttrStyleSheet->Reset(aURI);
   } else {
     rv = NS_NewHTMLStyleSheet(getter_AddRefs(mAttrStyleSheet), aURI, this);
-  }
-  NS_ENSURE_SUCCESS(rv, rv);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
 
   // Don't use AddStyleSheet, since it'll put the sheet into style
   // sets in the document level, which is not desirable here.
   mAttrStyleSheet->SetOwningDocument(this);
   
   if (mStyleAttrStyleSheet) {
     // Remove this sheet from all style sets
     nsCOMPtr<nsIPresShell> shell = GetPrimaryShell();
     if (shell) {
       shell->StyleSet()->
         RemoveStyleSheet(nsStyleSet::eStyleAttrSheet, mStyleAttrStyleSheet);
     }
-    rv = mStyleAttrStyleSheet->Reset(aURI);
+    mStyleAttrStyleSheet->Reset(aURI);
   } else {
     mStyleAttrStyleSheet = new nsHTMLCSSStyleSheet();
     NS_ENSURE_TRUE(mStyleAttrStyleSheet, NS_ERROR_OUT_OF_MEMORY);
     rv = mStyleAttrStyleSheet->Init(aURI, this);
-  }
-  NS_ENSURE_SUCCESS(rv, rv);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
 
   // The loop over style sets below will handle putting this sheet
   // into style sets as needed.
   mStyleAttrStyleSheet->SetOwningDocument(this);
 
   // Now set up our style sets
   nsCOMPtr<nsIPresShell> shell = GetPrimaryShell();
   if (shell) {
@@ -3519,19 +3519,18 @@ nsDocument::EnsureCatalogStyleSheet(cons
 {
   mozilla::css::Loader* cssLoader = CSSLoader();
   if (cssLoader->GetEnabled()) {
     PRInt32 sheetCount = GetNumberOfCatalogStyleSheets();
     for (PRInt32 i = 0; i < sheetCount; i++) {
       nsIStyleSheet* sheet = GetCatalogStyleSheetAt(i);
       NS_ASSERTION(sheet, "unexpected null stylesheet in the document");
       if (sheet) {
-        nsCOMPtr<nsIURI> uri = sheet->GetSheetURI();
         nsCAutoString uriStr;
-        uri->GetSpec(uriStr);
+        sheet->GetSheetURI()->GetSpec(uriStr);
         if (uriStr.Equals(aStyleSheetURI))
           return;
       }
     }
 
     nsCOMPtr<nsIURI> uri;
     NS_NewURI(getter_AddRefs(uri), aStyleSheetURI);
     if (uri) {
@@ -3888,36 +3887,57 @@ nsDocument::GetElementByIdInternal(nsIAt
     // entry again, adding if necessary (the adding may be necessary in case
     // the flush actually deleted entries).
     entry = mIdentifierMap.PutEntry(aID);
   }
   
   return entry;
 }
 
-NS_IMETHODIMP
-nsDocument::GetElementById(const nsAString& aElementId,
-                           nsIDOMElement** aReturn)
-{
-  NS_ENSURE_ARG_POINTER(aReturn);
-  *aReturn = nsnull;
-
+Element*
+nsDocument::GetElementById(const nsAString& aElementId, nsresult *aResult)
+{
   nsCOMPtr<nsIAtom> idAtom(do_GetAtom(aElementId));
-  NS_ENSURE_TRUE(idAtom, NS_ERROR_OUT_OF_MEMORY);
-  if (!CheckGetElementByIdArg(idAtom))
-    return NS_OK;
+  if (!idAtom) {
+    *aResult = NS_ERROR_OUT_OF_MEMORY;
+
+    return nsnull;
+  }
+
+  if (!CheckGetElementByIdArg(idAtom)) {
+    *aResult = NS_OK;
+
+    return nsnull;
+  }
 
   nsIdentifierMapEntry *entry = GetElementByIdInternal(idAtom);
-  NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY);
-
-  Element *e = entry->GetIdElement();
-  if (!e)
-    return NS_OK;
-
-  return CallQueryInterface(e, aReturn);
+  if (!entry) {
+    *aResult = NS_ERROR_OUT_OF_MEMORY;
+
+    return nsnull;
+  }
+
+  *aResult = NS_OK;
+
+  return entry->GetIdElement();
+}
+
+NS_IMETHODIMP
+nsDocument::GetElementById(const nsAString& aId, nsIDOMElement** aReturn)
+{
+  nsresult rv;
+  Element *content = GetElementById(aId, &rv);
+  if (content) {
+    rv = CallQueryInterface(content, aReturn);
+  }
+  else {
+    *aReturn = nsnull;
+  }
+
+  return rv;
 }
 
 Element*
 nsDocument::AddIDTargetObserver(nsIAtom* aID, IDTargetObserver aObserver,
                                 void* aData)
 {
   if (!CheckGetElementByIdArg(aID))
     return nsnull;
@@ -4359,53 +4379,75 @@ nsDocument::CreateEntityReference(const 
                                   nsIDOMEntityReference** aReturn)
 {
   NS_ENSURE_ARG_POINTER(aReturn);
 
   *aReturn = nsnull;
   return NS_OK;
 }
 
+already_AddRefed<nsContentList>
+nsDocument::GetElementsByTagName(const nsAString& aTagname)
+{
+  nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aTagname);
+  if (IsHTML()) {
+    nsAutoString tmp(aTagname);
+    ToLowerCase(tmp); // HTML elements are lower case internally.
+    nameAtom = do_GetAtom(tmp);
+  }
+  else {
+    nameAtom = do_GetAtom(aTagname);
+  }
+  NS_ENSURE_TRUE(nameAtom, nsnull);
+
+  return NS_GetContentList(this, nameAtom, kNameSpaceID_Unknown);
+}
+
 NS_IMETHODIMP
 nsDocument::GetElementsByTagName(const nsAString& aTagname,
                                  nsIDOMNodeList** aReturn)
 {
-  nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aTagname);
-  NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
-
-  nsContentList *list = NS_GetContentList(this, nameAtom, kNameSpaceID_Unknown).get();
+  nsRefPtr<nsContentList> list = GetElementsByTagName(aTagname);
   NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
 
   // transfer ref to aReturn
-  *aReturn = list;
+  *aReturn = list.forget().get();
   return NS_OK;
 }
 
-NS_IMETHODIMP
+already_AddRefed<nsContentList>
 nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
-                                   const nsAString& aLocalName,
-                                   nsIDOMNodeList** aReturn)
+                                   const nsAString& aLocalName)
 {
   PRInt32 nameSpaceId = kNameSpaceID_Wildcard;
 
   if (!aNamespaceURI.EqualsLiteral("*")) {
     nsresult rv =
       nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI,
                                                             nameSpaceId);
-    NS_ENSURE_SUCCESS(rv, rv);
+    NS_ENSURE_SUCCESS(rv, nsnull);
   }
 
   nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aLocalName);
-  NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
-
-  nsContentList *list = NS_GetContentList(this, nameAtom, nameSpaceId).get();
+  NS_ENSURE_TRUE(nameAtom, nsnull);
+
+  return NS_GetContentList(this, nameAtom, nameSpaceId);
+}
+
+NS_IMETHODIMP
+nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
+                                   const nsAString& aLocalName,
+                                   nsIDOMNodeList** aReturn)
+{
+  nsRefPtr<nsContentList> list = GetElementsByTagNameNS(aNamespaceURI,
+                                                        aLocalName);
   NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
 
   // transfer ref to aReturn
-  *aReturn = list;
+  *aReturn = list.forget().get();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocument::GetAsync(PRBool *aAsync)
 {
   NS_ERROR("nsDocument::GetAsync() should be overriden by subclass!");
 
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -931,16 +931,25 @@ public:
   // Only BlockOnload should call this!
   void AsyncBlockOnload();
 
   virtual void SetScrollToRef(nsIURI *aDocumentURI);
   virtual void ScrollToRef();
   virtual void ResetScrolledToRefAlready();
   virtual void SetChangeScrollPosWhenScrollingToRef(PRBool aValue);
 
+  already_AddRefed<nsContentList>
+    GetElementsByTagName(const nsAString& aTagName);
+  already_AddRefed<nsContentList>
+    GetElementsByTagNameNS(const nsAString& aNamespaceURI,
+                           const nsAString& aLocalName);
+
+  virtual mozilla::dom::Element *GetElementById(const nsAString& aElementId,
+                                                nsresult *aResult);
+
 protected:
   friend class nsNodeUtils;
   void RegisterNamedItems(nsIContent *aContent);
   void UnregisterNamedItems(nsIContent *aContent);
   void UpdateNameTableEntry(Element *aElement);
   void UpdateIdTableEntry(Element *aElement);
   void RemoveFromNameTable(Element *aElement);
   void RemoveFromIdTable(Element *aElement);
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -103,16 +103,17 @@
 #include "nsGkAtoms.h"
 #include "nsINameSpaceManager.h"
 
 #include "nsThreadUtils.h"
 #include "nsIContentViewer.h"
 #include "nsIView.h"
 
 #include "nsIDOMChromeWindow.h"
+#include "nsInProcessTabChildGlobal.h"
 
 #ifdef MOZ_WIDGET_GTK2
 #include "mozcontainer.h"
 
 #include <gdk/gdkx.h>
 #include <gtk/gtk.h>
 #endif
 
@@ -157,17 +158,30 @@ public:
 // does not count chrome frames when determining depth, nor does it
 // prevent chrome recursion.  Number is fairly arbitrary, but meant to
 // keep number of shells to a reasonable number on accidental recursion with a
 // small (but not 1) branching factor.  With large branching factors the number
 // of shells can rapidly become huge and run us out of memory.  To solve that,
 // we'd need to re-institute a fixed version of bug 98158.
 #define MAX_DEPTH_CONTENT_FRAMES 10
 
-NS_IMPL_CYCLE_COLLECTION_1(nsFrameLoader, mDocShell)
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsFrameLoader)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFrameLoader)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocShell)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mMessageManager)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChildMessageManager)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFrameLoader)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocShell)
+  NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "nsFrameLoader::mMessageManager");
+  cb.NoteXPCOMChild(static_cast<nsIContentFrameMessageManager*>(tmp->mMessageManager.get()));
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChildMessageManager)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFrameLoader)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameLoader)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameLoader)
   NS_INTERFACE_MAP_ENTRY(nsIFrameLoader)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
@@ -1032,16 +1046,48 @@ nsFrameLoader::SwapWithOtherLoader(nsFra
   otherParentDocument->SetSubDocumentFor(otherContent, ourChildDocument);
 
   ourWindow->SetFrameElementInternal(otherFrameElement);
   otherWindow->SetFrameElementInternal(ourFrameElement);
 
   mOwnerContent = otherContent;
   aOther->mOwnerContent = ourContent;
 
+  nsRefPtr<nsFrameMessageManager> ourMessageManager = mMessageManager;
+  nsRefPtr<nsFrameMessageManager> otherMessageManager = aOther->mMessageManager;
+  // Swap pointers in child message managers.
+  if (mChildMessageManager) {
+    nsInProcessTabChildGlobal* tabChild =
+      static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get());
+    tabChild->SetOwner(otherContent);
+    tabChild->SetChromeMessageManager(otherMessageManager);
+  }
+  if (aOther->mChildMessageManager) {
+    nsInProcessTabChildGlobal* otherTabChild =
+      static_cast<nsInProcessTabChildGlobal*>(aOther->mChildMessageManager.get());
+    otherTabChild->SetOwner(ourContent);
+    otherTabChild->SetChromeMessageManager(ourMessageManager);
+  }
+  // Swap and setup things in parent message managers.
+  nsFrameMessageManager* ourParentManager = mMessageManager ?
+    mMessageManager->GetParentManager() : nsnull;
+  nsFrameMessageManager* otherParentManager = aOther->mMessageManager ?
+    aOther->mMessageManager->GetParentManager() : nsnull;
+  if (mMessageManager) {
+    mMessageManager->Disconnect();
+    mMessageManager->SetParentManager(otherParentManager);
+    mMessageManager->SetCallbackData(aOther, PR_FALSE);
+  }
+  if (aOther->mMessageManager) {
+    aOther->mMessageManager->Disconnect();
+    aOther->mMessageManager->SetParentManager(ourParentManager);
+    aOther->mMessageManager->SetCallbackData(this, PR_FALSE);
+  }
+  mMessageManager.swap(aOther->mMessageManager);
+
   aFirstToSwap.swap(aSecondToSwap);
 
   // Drop any cached content viewers in the two session histories.
   nsCOMPtr<nsISHistoryInternal> ourInternalHistory =
     do_QueryInterface(ourHistory);
   nsCOMPtr<nsISHistoryInternal> otherInternalHistory =
     do_QueryInterface(otherHistory);
   if (ourInternalHistory) {
@@ -1082,16 +1128,23 @@ nsFrameLoader::DestroyChild()
 NS_IMETHODIMP
 nsFrameLoader::Destroy()
 {
   if (mDestroyCalled) {
     return NS_OK;
   }
   mDestroyCalled = PR_TRUE;
 
+  if (mMessageManager) {
+    mMessageManager->Disconnect();
+  }
+  if (mChildMessageManager) {
+    static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get())->Disconnect();
+  }
+
   nsCOMPtr<nsIDocument> doc;
   if (mOwnerContent) {
     doc = mOwnerContent->GetOwnerDoc();
 
     if (doc) {
       doc->SetSubDocumentFor(mOwnerContent, nsnull);
     }
 
@@ -1106,17 +1159,17 @@ nsFrameLoader::Destroy()
       nsCOMPtr<nsIDocShellTreeItem> parentItem;
       ourItem->GetParent(getter_AddRefs(parentItem));
       nsCOMPtr<nsIDocShellTreeOwner> owner = do_GetInterface(parentItem);
       if (owner) {
         owner->ContentShellRemoved(ourItem);
       }
     }
   }
-
+  
   // Let our window know that we are gone
   nsCOMPtr<nsPIDOMWindow> win_private(do_GetInterface(mDocShell));
   if (win_private) {
     win_private->SetFrameElementInternal(nsnull);
   }
 
   if ((mNeedsAsyncDestroy || !doc ||
        NS_FAILED(doc->FinalizeFrameLoader(this))) && mDocShell) {
@@ -1219,17 +1272,16 @@ nsFrameLoader::MaybeCreateDocShell()
 
   // Create the docshell...
   mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
 
   // Get the frame name and tell the docshell about it.
   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
   NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
-
   nsAutoString frameName;
 
   PRInt32 namespaceID = mOwnerContent->GetNameSpaceID();
   if (namespaceID == kNameSpaceID_XHTML && !mOwnerContent->IsInHTMLDocument()) {
     mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, frameName);
   } else {
     mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, frameName);
     // XXX if no NAME then use ID, after a transition period this will be
@@ -1284,16 +1336,18 @@ nsFrameLoader::MaybeCreateDocShell()
       // handler from it and use that for our shell as well.
 
       parentShell->GetChromeEventHandler(getter_AddRefs(chromeEventHandler));
     }
 
     mDocShell->SetChromeEventHandler(chromeEventHandler);
   }
 
+  EnsureMessageManager();
+
   // This is nasty, this code (the do_GetInterface(mDocShell) below)
   // *must* come *after* the above call to
   // mDocShell->SetChromeEventHandler() for the global window to get
   // the right chrome event handler.
 
   // Tell the window about the frame that hosts it.
   nsCOMPtr<nsIDOMElement> frame_element(do_QueryInterface(mOwnerContent));
   NS_ASSERTION(frame_element, "frame loader owner element not a DOM element!");
@@ -1703,69 +1757,137 @@ nsFrameLoader::CreateStaticClone(nsIFram
   NS_ENSURE_STATE(doc);
   nsCOMPtr<nsIDocument> clonedDoc = doc->CreateStaticClone(dest->mDocShell);
   nsCOMPtr<nsIDOMDocument> clonedDOMDoc = do_QueryInterface(clonedDoc);
 
   viewer->SetDOMDocument(clonedDOMDoc);
   return NS_OK;
 }
 
-#ifdef MOZ_IPC
 bool LoadScript(void* aCallbackData, const nsAString& aURL)
 {
+#ifdef MOZ_IPC
   mozilla::dom::PIFrameEmbeddingParent* tabParent =
     static_cast<nsFrameLoader*>(aCallbackData)->GetChildProcess();
   if (tabParent) {
     return tabParent->SendloadRemoteScript(nsString(aURL));
   }
-  return false;
+#endif
+  nsFrameLoader* fl = static_cast<nsFrameLoader*>(aCallbackData);
+  nsRefPtr<nsInProcessTabChildGlobal> tabChild =
+    static_cast<nsInProcessTabChildGlobal*>(fl->GetTabChildGlobalAsEventTarget());
+  if (tabChild) {
+    tabChild->LoadFrameScript(aURL);
+  }
+  return true;
 }
 
+class nsAsyncMessageToChild : public nsRunnable
+{
+public:
+  nsAsyncMessageToChild(nsFrameLoader* aFrameLoader,
+                        const nsAString& aMessage, const nsAString& aJSON)
+    : mFrameLoader(aFrameLoader), mMessage(aMessage), mJSON(aJSON) {}
+
+  NS_IMETHOD Run()
+  {
+    nsInProcessTabChildGlobal* tabChild =
+      static_cast<nsInProcessTabChildGlobal*>(mFrameLoader->mChildMessageManager.get());
+    if (tabChild && tabChild->GetInnerManager()) {
+      tabChild->GetInnerManager()->
+        ReceiveMessage(static_cast<nsPIDOMEventTarget*>(tabChild), mMessage,
+                       PR_FALSE, mJSON, nsnull, nsnull);
+    }
+    return NS_OK;
+  }
+  nsRefPtr<nsFrameLoader> mFrameLoader;
+  nsString mMessage;
+  nsString mJSON;
+};
+
 bool SendAsyncMessageToChild(void* aCallbackData,
                              const nsAString& aMessage,
                              const nsAString& aJSON)
 {
+#ifdef MOZ_IPC
   mozilla::dom::PIFrameEmbeddingParent* tabParent =
     static_cast<nsFrameLoader*>(aCallbackData)->GetChildProcess();
   if (tabParent) {
     return tabParent->SendsendAsyncMessageToChild(nsString(aMessage),
                                                   nsString(aJSON));
   }
-  return false;
+#endif
+  nsRefPtr<nsIRunnable> ev =
+    new nsAsyncMessageToChild(static_cast<nsFrameLoader*>(aCallbackData),
+                              aMessage, aJSON);
+  NS_DispatchToCurrentThread(ev);
+  return true;
 }
-#endif
 
 NS_IMETHODIMP
 nsFrameLoader::GetMessageManager(nsIChromeFrameMessageManager** aManager)
 {
-#ifdef MOZ_IPC
+  EnsureMessageManager();
+  NS_IF_ADDREF(*aManager = mMessageManager);
+  return NS_OK;
+}
+
+nsresult
+nsFrameLoader::EnsureMessageManager()
+{
   NS_ENSURE_STATE(mOwnerContent);
-  if (!mMessageManager) {
-    nsresult rv;
-    nsIScriptContext* sctx = mOwnerContent->GetContextForEventHandlers(&rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-    NS_ENSURE_STATE(sctx);
-    JSContext* cx = static_cast<JSContext*>(sctx->GetNativeContext());
-    NS_ENSURE_STATE(cx);
+
+  nsresult rv = MaybeCreateDocShell();
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  if (mMessageManager) {
+    if (ShouldUseRemoteProcess()) {
+      mMessageManager->SetCallbackData(mRemoteWidgetCreated ? this : nsnull);
+    }
+    return NS_OK;
+  }
 
-    nsCOMPtr<nsIDOMChromeWindow> chromeWindow =
-      do_QueryInterface(mOwnerContent->GetOwnerDoc()->GetWindow());
-    NS_ENSURE_STATE(chromeWindow);
-    nsCOMPtr<nsIChromeFrameMessageManager> parentManager;
-    chromeWindow->GetMessageManager(getter_AddRefs(parentManager));
+  nsIScriptContext* sctx = mOwnerContent->GetContextForEventHandlers(&rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+  NS_ENSURE_STATE(sctx);
+  JSContext* cx = static_cast<JSContext*>(sctx->GetNativeContext());
+  NS_ENSURE_STATE(cx);
 
+  nsCOMPtr<nsIDOMChromeWindow> chromeWindow =
+    do_QueryInterface(mOwnerContent->GetOwnerDoc()->GetWindow());
+  NS_ENSURE_STATE(chromeWindow);
+  nsCOMPtr<nsIChromeFrameMessageManager> parentManager;
+  chromeWindow->GetMessageManager(getter_AddRefs(parentManager));
+
+#ifdef MOZ_IPC
+  if (ShouldUseRemoteProcess()) {
     mMessageManager = new nsFrameMessageManager(PR_TRUE,
                                                 nsnull,
                                                 SendAsyncMessageToChild,
                                                 LoadScript,
                                                 mRemoteWidgetCreated ? this : nsnull,
                                                 static_cast<nsFrameMessageManager*>(parentManager.get()),
                                                 cx);
     NS_ENSURE_TRUE(mMessageManager, NS_ERROR_OUT_OF_MEMORY);
-  } else {
-    mMessageManager->SetCallbackData(mRemoteWidgetCreated ? this : nsnull);
+  } else
+#endif
+  {
+
+    mMessageManager = new nsFrameMessageManager(PR_TRUE,
+                                                nsnull,
+                                                SendAsyncMessageToChild,
+                                                LoadScript,
+                                                this,
+                                                static_cast<nsFrameMessageManager*>(parentManager.get()),
+                                                cx);
+    NS_ENSURE_TRUE(mMessageManager, NS_ERROR_OUT_OF_MEMORY);
+    mChildMessageManager =
+      new nsInProcessTabChildGlobal(mDocShell, mOwnerContent, mMessageManager);
   }
-  return CallQueryInterface(mMessageManager.get(), aManager);
-#else
-  *aManager = nsnull;
   return NS_OK;
-#endif
 }
+
+nsPIDOMEventTarget*
+nsFrameLoader::GetTabChildGlobalAsEventTarget()
+{
+  return static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get());
+}
--- a/content/base/src/nsFrameLoader.h
+++ b/content/base/src/nsFrameLoader.h
@@ -51,16 +51,17 @@
 #include "nsIURI.h"
 #include "nsAutoPtr.h"
 #include "nsFrameMessageManager.h"
 
 class nsIContent;
 class nsIURI;
 class nsIFrameFrame;
 class nsIView;
+class nsIInProcessContentFrameMessageManager;
 
 #ifdef MOZ_IPC
 namespace mozilla {
   namespace dom {
     class TabParent;
     class PIFrameEmbeddingParent;
   }
 }
@@ -107,17 +108,17 @@ public:
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(nsFrameLoader)
   NS_DECL_NSIFRAMELOADER
   NS_HIDDEN_(nsresult) CheckForRecursiveLoad(nsIURI* aURI);
   nsresult ReallyStartLoading();
   void Finalize();
   nsIDocShell* GetExistingDocShell() { return mDocShell; }
-
+  nsPIDOMEventTarget* GetTabChildGlobalAsEventTarget();
   nsresult CreateStaticClone(nsIFrameLoader* aDest);
 
   /**
    * Called from the layout frame associated with this frame loader;
    * this notifies us to hook up with the widget and view.
    */
   bool Show(PRInt32 marginWidth, PRInt32 marginHeight,
             PRInt32 scrollbarPrefX, PRInt32 scrollbarPrefY,
@@ -155,17 +156,18 @@ private:
   bool ShouldUseRemoteProcess();
 #endif
 
   /**
    * If we are an IPC frame, set mRemoteFrame. Otherwise, create and
    * initialize mDocShell.
    */
   nsresult MaybeCreateDocShell();
-  void GetURL(nsString& aURL);
+  nsresult EnsureMessageManager();
+  NS_HIDDEN_(void) GetURL(nsString& aURL);
 
   // Properly retrieves documentSize of any subdocument type.
   NS_HIDDEN_(nsIntSize) GetSubDocumentSize(const nsIFrame *aIFrame);
 
   // Updates the subdocument position and size. This gets called only
   // when we have our own in-process DocShell.
   NS_HIDDEN_(nsresult) UpdateBaseWindowPositionAndSize(nsIFrame *aIFrame);
   nsresult CheckURILoad(nsIURI* aURI);
@@ -179,16 +181,21 @@ private:
   // Do the hookup necessary to actually show a remote frame once the view and
   // widget are available.
   bool ShowRemoteFrame(nsIFrameFrame* frame, nsIView* view);
 #endif
 
   nsCOMPtr<nsIDocShell> mDocShell;
   nsCOMPtr<nsIURI> mURIToLoad;
   nsIContent *mOwnerContent; // WEAK
+public:
+  // public because a callback needs these.
+  nsRefPtr<nsFrameMessageManager> mMessageManager;
+  nsCOMPtr<nsIInProcessContentFrameMessageManager> mChildMessageManager;
+private:
   PRPackedBool mDepthTooGreat : 1;
   PRPackedBool mIsTopLevelContent : 1;
   PRPackedBool mDestroyCalled : 1;
   PRPackedBool mNeedsAsyncDestroy : 1;
   PRPackedBool mInSwap : 1;
 
 #ifdef MOZ_IPC
   PRPackedBool mDelayRemoteDialogs : 1;
@@ -199,12 +206,11 @@ private:
   mozilla::dom::TabParent* mChildProcess;
 
 #ifdef MOZ_WIDGET_GTK2
   GtkWidget* mRemoteSocket;
 #elif defined(MOZ_WIDGET_QT)
   QX11EmbedContainer* mRemoteSocket;
 #endif
 #endif
-  nsRefPtr<nsFrameMessageManager> mMessageManager;
 };
 
 #endif
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -124,18 +124,20 @@ nsFrameMessageManager::LoadFrameScript(c
 #ifdef DEBUG_smaug
     printf("Will load %s \n", NS_ConvertUTF16toUTF8(aURL).get());
 #endif
     NS_ENSURE_TRUE(mLoadScriptCallback(mCallbackData, aURL), NS_ERROR_FAILURE);
   }
 
   PRInt32 len = mChildManagers.Count();
   for (PRInt32 i = 0; i < len; ++i) {
-    static_cast<nsFrameMessageManager*>(mChildManagers[i])->LoadFrameScript(aURL,
-                                                                            PR_FALSE);
+    nsCOMPtr<nsIContentFrameMessageManager> mm = mChildManagers[i];
+    if (mm) {
+      static_cast<nsFrameMessageManager*>(mm.get())->LoadFrameScript(aURL, PR_FALSE);
+    }
   }
   return NS_OK;
 }
 
 static JSBool
 JSONCreator(const jschar* aBuf, uint32 aLen, void* aData)
 {
   nsAString* result = static_cast<nsAString*>(aData);
@@ -317,16 +319,30 @@ nsFrameMessageManager::ReceiveMessage(ns
 
         jsval targetv;
         nsAutoGCRoot resultGCRoot2(&targetv, &rv);
         NS_ENSURE_SUCCESS(rv, rv);
         nsContentUtils::WrapNative(mContext,
                                    JS_GetGlobalObject(mContext),
                                    aTarget, &targetv);
 
+        // To keep compatibility with e10s message manager,
+        // define empty objects array.
+        if (!aObjectsArray) {
+          jsval* dest = nsnull;
+          // Because we want JS messages to have always the same properties,
+          // create array even if len == 0.
+          aObjectsArray = js_NewArrayObjectWithCapacity(mContext, 0, &dest);
+          if (!aObjectsArray) {
+            return false;
+          }
+        }
+        nsAutoGCRoot arrayGCRoot(&aObjectsArray, &rv);
+        NS_ENSURE_SUCCESS(rv, rv);
+
         jsval json = JSVAL_NULL;
         nsAutoGCRoot root(&json, &rv);
         if (NS_SUCCEEDED(rv) && !aJSON.IsEmpty()) {
           JSONParser* parser = JS_BeginJSONParse(mContext, &json);
           if (parser) {
             JSBool ok = JS_ConsumeJSONText(mContext, parser,
                                            (jschar*)nsString(aJSON).get(),
                                            (uint32)aJSON.Length());
@@ -399,35 +415,40 @@ nsFrameMessageManager::ReceiveMessage(ns
     }
   }
   return mParentManager ? mParentManager->ReceiveMessage(aTarget, aMessage,
                                                          aSync, aJSON, aObjectsArray,
                                                          aJSONRetVal) : NS_OK;
 }
 
 void
-nsFrameMessageManager::AddChildManager(nsFrameMessageManager* aManager)
+nsFrameMessageManager::AddChildManager(nsFrameMessageManager* aManager,
+                                       PRBool aLoadScripts)
 {
   mChildManagers.AppendObject(aManager);
-  for (PRUint32 i = 0; i < mPendingScripts.Length(); ++i) {
-    aManager->LoadFrameScript(mPendingScripts[i], PR_FALSE);
+  if (aLoadScripts) {
+    for (PRUint32 i = 0; i < mPendingScripts.Length(); ++i) {
+      aManager->LoadFrameScript(mPendingScripts[i], PR_FALSE);
+    }
   }
 }
 
 void
-nsFrameMessageManager::SetCallbackData(void* aData)
+nsFrameMessageManager::SetCallbackData(void* aData, PRBool aLoadScripts)
 {
   if (aData && mCallbackData != aData) {
     mCallbackData = aData;
     // First load global scripts by adding this to parent manager.
     if (mParentManager) {
-      mParentManager->AddChildManager(this);
+      mParentManager->AddChildManager(this, aLoadScripts);
     }
-    for (PRUint32 i = 0; i < mPendingScripts.Length(); ++i) {
-      LoadFrameScript(mPendingScripts[i], PR_FALSE);
+    if (aLoadScripts) {
+      for (PRUint32 i = 0; i < mPendingScripts.Length(); ++i) {
+        LoadFrameScript(mPendingScripts[i], PR_FALSE);
+      }
     }
   }
 }
 
 void
 nsFrameMessageManager::Disconnect(PRBool aRemoveFromParent)
 {
   if (mParentManager && aRemoveFromParent) {
--- a/content/base/src/nsFrameMessageManager.h
+++ b/content/base/src/nsFrameMessageManager.h
@@ -77,16 +77,17 @@ public:
                         nsFrameMessageManager* aParentManager,
                         JSContext* aContext)
   : mChrome(aChrome), mParentManager(aParentManager),
     mSyncCallback(aSyncCallback), mAsyncCallback(aAsyncCallback),
     mLoadScriptCallback(aLoadScriptCallback), mCallbackData(aCallbackData),
     mContext(aContext)
   {
     NS_ASSERTION(mContext, "Should have mContext!");
+    NS_ASSERTION(aChrome || !aParentManager, "Should not set parent manager!");
     if (mParentManager && mCallbackData) {
       mParentManager->AddChildManager(this);
     }
   }
 
   ~nsFrameMessageManager()
   {
     for (PRInt32 i = mChildManagers.Count(); i > 0; --i) {
@@ -101,28 +102,36 @@ public:
   NS_DECL_NSIFRAMEMESSAGEMANAGER
   NS_DECL_NSICONTENTFRAMEMESSAGEMANAGER
   NS_DECL_NSICHROMEFRAMEMESSAGEMANAGER
 
   nsresult ReceiveMessage(nsISupports* aTarget, const nsAString& aMessage,
                           PRBool aSync, const nsAString& aJSON,
                           JSObject* aObjectsArray,
                           nsTArray<nsString>* aJSONRetVal);
-  void AddChildManager(nsFrameMessageManager* aManager);
+  void AddChildManager(nsFrameMessageManager* aManager,
+                       PRBool aLoadScripts = PR_TRUE);
   void RemoveChildManager(nsFrameMessageManager* aManager)
   {
     mChildManagers.RemoveObject(aManager);
   }
 
   void Disconnect(PRBool aRemoveFromParent = PR_TRUE);
-  void SetCallbackData(void* aData);
+  void SetCallbackData(void* aData, PRBool aLoadScripts = PR_TRUE);
   nsresult GetParamsForMessage(nsAString& aMessageName, nsAString& aJSON);
   nsresult SendAsyncMessageInternal(const nsAString& aMessage,
                                     const nsAString& aJSON);
   JSContext* GetJSContext() { return mContext; }
+  nsFrameMessageManager* GetParentManager() { return mParentManager; }
+  void SetParentManager(nsFrameMessageManager* aParent)
+  {
+    NS_ASSERTION(!mParentManager, "We have parent manager already!");
+    NS_ASSERTION(mChrome, "Should not set parent manager!");
+    mParentManager = aParent;
+  }
 protected:
   nsTArray<nsMessageListenerInfo> mListeners;
   nsCOMArray<nsIContentFrameMessageManager> mChildManagers;
   PRBool mChrome;
   nsFrameMessageManager* mParentManager;
   nsSyncMessageCallback mSyncCallback;
   nsAsyncMessageCallback mAsyncCallback;
   nsLoadScriptCallback mLoadScriptCallback;
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -118,16 +118,17 @@ GK_ATOM(attribute, "attribute")
 GK_ATOM(attributeSet, "attribute-set")
 GK_ATOM(aural, "aural")
 GK_ATOM(_auto, "auto")
 #ifdef MOZ_MEDIA
 GK_ATOM(autobuffer, "autobuffer")
 #endif
 GK_ATOM(autocheck, "autocheck")
 GK_ATOM(autocomplete, "autocomplete")
+GK_ATOM(autofocus, "autofocus")
 #ifdef MOZ_MEDIA
 GK_ATOM(autoplay, "autoplay")
 #endif
 GK_ATOM(autorepeatbutton, "autorepeatbutton")
 GK_ATOM(axis, "axis")
 GK_ATOM(b, "b")
 GK_ATOM(background, "background")
 GK_ATOM(base, "base")
new file mode 100644
--- /dev/null
+++ b/content/base/src/nsInProcessTabChildGlobal.cpp
@@ -0,0 +1,366 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8; -*- */
+/* vim: set sw=4 ts=8 et tw=80 : */
+/* ***** 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 Content App.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * 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 "nsInProcessTabChildGlobal.h"
+#include "nsContentUtils.h"
+#include "nsIScriptSecurityManager.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "nsEventDispatcher.h"
+#include "nsIComponentManager.h"
+#include "nsIServiceManager.h"
+#include "nsIJSRuntimeService.h"
+#include "nsComponentManagerUtils.h"
+#include "nsNetUtil.h"
+#include "nsScriptLoader.h"
+#include "nsIJSContextStack.h"
+#include "nsFrameLoader.h"
+
+bool SendSyncMessageToParent(void* aCallbackData,
+                             const nsAString& aMessage,
+                             const nsAString& aJSON,
+                             nsTArray<nsString>* aJSONRetVal)
+{
+  nsInProcessTabChildGlobal* tabChild =
+    static_cast<nsInProcessTabChildGlobal*>(aCallbackData);
+  PRInt32 count = tabChild->mASyncMessages.Count();
+  for (PRInt32 i = 0; i < count; ++i) {
+    nsCOMPtr<nsIRunnable> async = tabChild->mASyncMessages.SafeObjectAt(i);
+    async->Run();
+  }
+  if (tabChild->mChromeMessageManager) {
+    tabChild->mChromeMessageManager->ReceiveMessage(tabChild->mOwner, aMessage, PR_TRUE,
+                                                    aJSON, nsnull, aJSONRetVal);
+  }
+  return true;
+}
+
+class nsAsyncMessageToParent : public nsRunnable
+{
+public:
+  nsAsyncMessageToParent(nsInProcessTabChildGlobal* aTabChild,
+                         const nsAString& aMessage, const nsAString& aJSON)
+    : mTabChild(aTabChild), mMessage(aMessage), mJSON(aJSON) {}
+
+  NS_IMETHOD Run()
+  {
+    mTabChild->mASyncMessages.RemoveObject(this);
+    if (mTabChild->mChromeMessageManager) {
+      mTabChild->mChromeMessageManager->ReceiveMessage(mTabChild->mOwner, mMessage,
+                                                       PR_FALSE,
+                                                       mJSON, nsnull, nsnull);
+    }
+    return NS_OK;
+  }
+  nsRefPtr<nsInProcessTabChildGlobal> mTabChild;
+  nsString mMessage;
+  nsString mJSON;
+};
+
+bool SendAsyncMessageToParent(void* aCallbackData,
+                              const nsAString& aMessage,
+                              const nsAString& aJSON)
+{
+  nsInProcessTabChildGlobal* tabChild =
+    static_cast<nsInProcessTabChildGlobal*>(aCallbackData);
+  nsRefPtr<nsIRunnable> ev = new nsAsyncMessageToParent(tabChild, aMessage, aJSON);
+  tabChild->mASyncMessages.AppendObject(ev);
+  NS_DispatchToCurrentThread(ev);
+  return true;
+}
+
+static int tabChildC = 0;
+nsInProcessTabChildGlobal::nsInProcessTabChildGlobal(nsIDocShell* aShell,
+                                                     nsIContent* aOwner,
+                                                     nsFrameMessageManager* aChrome)
+: mCx(nsnull), mDocShell(aShell), mInitialized(PR_FALSE), mLoadingScript(PR_FALSE),
+  mDelayedDisconnect(PR_FALSE), mOwner(aOwner), mChromeMessageManager(aChrome)
+{
+}
+
+nsInProcessTabChildGlobal::~nsInProcessTabChildGlobal()
+{
+  Disconnect();
+  NS_ASSERTION(!mCx, "Couldn't release JSContext?!?");
+}
+
+nsresult
+nsInProcessTabChildGlobal::Init()
+{
+  nsresult rv = InitTabChildGlobal();
+  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
+                   "Couldn't initialize nsInProcessTabChildGlobal");
+  mMessageManager = new nsFrameMessageManager(PR_FALSE,
+                                              SendSyncMessageToParent,
+                                              SendAsyncMessageToParent,
+                                              nsnull,
+                                              this,
+                                              nsnull,
+                                              mCx);
+  return NS_OK;
+}
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsInProcessTabChildGlobal)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsInProcessTabChildGlobal,
+                                                nsDOMEventTargetHelper)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mMessageManager)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mGlobal)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsInProcessTabChildGlobal,
+                                                  nsDOMEventTargetHelper)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mMessageManager)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mGlobal)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsInProcessTabChildGlobal)
+  NS_INTERFACE_MAP_ENTRY(nsIFrameMessageManager)
+  NS_INTERFACE_MAP_ENTRY(nsIContentFrameMessageManager)
+  NS_INTERFACE_MAP_ENTRY(nsIInProcessContentFrameMessageManager)
+  NS_INTERFACE_MAP_ENTRY(nsIScriptContextPrincipal)
+  NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ContentFrameMessageManager)
+NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
+
+NS_IMPL_ADDREF_INHERITED(nsInProcessTabChildGlobal, nsDOMEventTargetHelper)
+NS_IMPL_RELEASE_INHERITED(nsInProcessTabChildGlobal, nsDOMEventTargetHelper)
+
+NS_IMETHODIMP
+nsInProcessTabChildGlobal::GetContent(nsIDOMWindow** aContent)
+{
+  *aContent = nsnull;
+  nsCOMPtr<nsIDOMWindow> window = do_GetInterface(mDocShell);
+  window.swap(*aContent);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsInProcessTabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
+{
+  NS_IF_ADDREF(*aDocShell = mDocShell);
+  return NS_OK;
+}
+
+void
+nsInProcessTabChildGlobal::Disconnect()
+{
+  mDocShell = nsnull;
+  mOwner = nsnull;
+  mChromeMessageManager = nsnull;
+  if (mMessageManager) {
+    static_cast<nsFrameMessageManager*>(mMessageManager.get())->Disconnect();
+    mMessageManager = nsnull;
+  }
+  if (!mLoadingScript) {
+    if (mCx) {
+      JS_DestroyContext(mCx);
+      mCx = nsnull;
+    }
+  } else {
+    mDelayedDisconnect = PR_TRUE;
+  }
+}
+
+NS_IMETHODIMP_(nsIContent *)
+nsInProcessTabChildGlobal::GetOwnerContent()
+{
+  return mOwner;
+}
+
+nsresult
+nsInProcessTabChildGlobal::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
+{
+  aVisitor.mCanHandle = PR_TRUE;
+  aVisitor.mParentTarget = mOwner;
+
+#ifdef DEBUG
+  if (mOwner) {
+    nsCOMPtr<nsIFrameLoaderOwner> owner = do_QueryInterface(mOwner);
+    nsRefPtr<nsFrameLoader> fl = owner->GetFrameLoader();
+    if (fl) {
+      NS_ASSERTION(this == fl->GetTabChildGlobalAsEventTarget(),
+                   "Wrong event target!");
+      NS_ASSERTION(fl->mMessageManager == mChromeMessageManager,
+                   "Wrong message manager!");
+    }
+  }
+#endif
+
+  return NS_OK;
+}
+
+nsresult
+nsInProcessTabChildGlobal::InitTabChildGlobal()
+{
+  nsCOMPtr<nsIJSRuntimeService> runtimeSvc = 
+    do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
+  NS_ENSURE_STATE(runtimeSvc);
+
+  JSRuntime* rt = nsnull;
+  runtimeSvc->GetRuntime(&rt);
+  NS_ENSURE_STATE(rt);
+
+  JSContext* cx = JS_NewContext(rt, 8192);
+  NS_ENSURE_STATE(cx);
+
+  mCx = cx;
+
+  nsContentUtils::XPConnect()->SetSecurityManagerForJSContext(cx, nsContentUtils::GetSecurityManager(), 0);
+  nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(mPrincipal));
+
+  PRUint32 stackDummy;
+  jsuword stackLimit, currentStackAddr = (jsuword)&stackDummy;
+
+  // 256k stack space.
+  const jsuword kStackSize = 0x40000;
+
+#if JS_STACK_GROWTH_DIRECTION < 0
+  stackLimit = (currentStackAddr > kStackSize) ?
+               currentStackAddr - kStackSize :
+               0;
+#else
+  stackLimit = (currentStackAddr + kStackSize > currentStackAddr) ?
+               currentStackAddr + kStackSize :
+               (jsuword) -1;
+#endif
+
+  JS_SetThreadStackLimit(cx, stackLimit);
+  JS_SetScriptStackQuota(cx, 100*1024*1024);
+
+  JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_JIT | JSOPTION_ANONFUNFIX | JSOPTION_PRIVATE_IS_NSISUPPORTS);
+  JS_SetVersion(cx, JSVERSION_LATEST);
+  JS_SetGCParameterForThread(cx, JSGC_MAX_CODE_CACHE_BYTES, 1 * 1024 * 1024);
+
+  JSAutoRequest ar(cx);
+  nsIXPConnect* xpc = nsContentUtils::XPConnect();
+  const PRUint32 flags = nsIXPConnect::INIT_JS_STANDARD_CLASSES |
+                         /*nsIXPConnect::OMIT_COMPONENTS_OBJECT ?  |*/
+                         nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT;
+
+  nsISupports* scopeSupports =
+    NS_ISUPPORTS_CAST(nsPIDOMEventTarget*, this);
+  JS_SetContextPrivate(cx, scopeSupports);
+
+  nsresult rv =
+    xpc->InitClassesWithNewWrappedGlobal(cx, scopeSupports,
+                                         NS_GET_IID(nsISupports), flags,
+                                         getter_AddRefs(mGlobal));
+  NS_ENSURE_SUCCESS(rv, false);
+
+  JSObject* global = nsnull;
+  rv = mGlobal->GetJSObject(&global);
+  NS_ENSURE_SUCCESS(rv, false);
+
+  JS_SetGlobalObject(cx, global);
+
+  return NS_OK;
+}
+
+void
+nsInProcessTabChildGlobal::LoadFrameScript(const nsAString& aURL)
+{
+  if (!mInitialized) {
+    mInitialized = PR_TRUE;
+    Init();
+  }
+  if (!mGlobal || !mCx) {
+    return;
+  }
+
+  nsCString url = NS_ConvertUTF16toUTF8(aURL);
+  nsCOMPtr<nsIURI> uri;
+  nsresult rv = NS_NewURI(getter_AddRefs(uri), url);
+  if (NS_FAILED(rv)) {
+    return;
+  }
+  nsCOMPtr<nsIChannel> channel;
+  NS_NewChannel(getter_AddRefs(channel), uri);
+  if (!channel) {
+    return;
+  }
+
+  nsCOMPtr<nsIInputStream> input;
+  channel->Open(getter_AddRefs(input));
+  nsString dataString;
+  if (input) {
+    const PRUint32 bufferSize = 256;
+    char buffer[bufferSize];
+    nsCString data;
+    PRUint32 avail = 0;
+    input->Available(&avail);
+    PRUint32 read = 0;
+    if (avail) {
+      while (NS_SUCCEEDED(input->Read(buffer, bufferSize, &read)) && read) {
+        data.Append(buffer, read);
+        read = 0;
+      }
+    }
+    nsScriptLoader::ConvertToUTF16(channel, (PRUint8*)data.get(), data.Length(),
+                                   EmptyString(), nsnull, dataString);
+  }
+
+  if (!dataString.IsEmpty()) {
+    JSAutoRequest ar(mCx);
+    jsval retval;
+    JSObject* global = nsnull;
+    mGlobal->GetJSObject(&global);
+    if (!global) {
+      return;
+    }
+
+    JSPrincipals* jsprin = nsnull;
+    mPrincipal->GetJSPrincipals(mCx, &jsprin);
+    nsContentUtils::XPConnect()->FlagSystemFilenamePrefix(url.get(), PR_TRUE);
+    nsContentUtils::ThreadJSContextStack()->Push(mCx);
+    PRBool tmp = mLoadingScript;
+    mLoadingScript = PR_TRUE;
+    JS_EvaluateUCScriptForPrincipals(mCx, global, jsprin,
+                                     (jschar*)dataString.get(),
+                                     dataString.Length(),
+                                     url.get(), 1, &retval);
+    //XXX Argh, JSPrincipals are manually refcounted!
+    JSPRINCIPALS_DROP(mCx, jsprin);
+    mLoadingScript = tmp;
+    JSContext* unused;
+    nsContentUtils::ThreadJSContextStack()->Pop(&unused);
+  }
+  if (!mLoadingScript && mDelayedDisconnect) {
+    mDelayedDisconnect = PR_FALSE;
+    Disconnect();
+  }
+}
new file mode 100644
--- /dev/null
+++ b/content/base/src/nsInProcessTabChildGlobal.h
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8; -*- */
+/* vim: set sw=4 ts=8 et tw=80 : */
+/* ***** 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 Content App.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * 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 ***** */
+
+#ifndef nsInProcessTabChildGlobal_h
+#define nsInProcessTabChildGlobal_h
+
+#include "nsCOMPtr.h"
+#include "nsFrameMessageManager.h"
+#include "nsIScriptContext.h"
+#include "nsDOMEventTargetHelper.h"
+#include "nsIPrincipal.h"
+#include "nsIScriptObjectPrincipal.h"
+#include "nsIScriptContext.h"
+#include "nsIClassInfo.h"
+#include "jsapi.h"
+#include "nsIDocShell.h"
+#include "nsIXPConnect.h"
+#include "nsIDOMElement.h"
+#include "nsCOMArray.h"
+#include "nsThreadUtils.h"
+
+class nsInProcessTabChildGlobal : public nsDOMEventTargetHelper,
+                                  public nsIInProcessContentFrameMessageManager,
+                                  public nsIScriptObjectPrincipal,
+                                  public nsIScriptContextPrincipal
+{
+public:
+  nsInProcessTabChildGlobal(nsIDocShell* aShell, nsIContent* aOwner,
+                            nsFrameMessageManager* aChrome);
+  virtual ~nsInProcessTabChildGlobal();
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsInProcessTabChildGlobal,
+                                           nsDOMEventTargetHelper)
+  NS_FORWARD_SAFE_NSIFRAMEMESSAGEMANAGER(mMessageManager)
+  NS_IMETHOD SendSyncMessage()
+  {
+    return mMessageManager ? mMessageManager->SendSyncMessage()
+                           : NS_ERROR_NULL_POINTER;
+  }
+  NS_IMETHOD GetContent(nsIDOMWindow** aContent);
+  NS_IMETHOD GetDocShell(nsIDocShell** aDocShell);
+  NS_IMETHOD Dump(const nsAString& aStr)
+  {
+    return mMessageManager ? mMessageManager->Dump(aStr) : NS_OK;
+  }
+  NS_DECL_NSIINPROCESSCONTENTFRAMEMESSAGEMANAGER
+
+  virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
+  NS_IMETHOD AddEventListener(const nsAString& aType,
+                              nsIDOMEventListener* aListener,
+                              PRBool aUseCapture)
+  {
+    // By default add listeners only for trusted events!
+    return nsDOMEventTargetHelper::AddEventListener(aType, aListener,
+                                                    aUseCapture, PR_FALSE, 1);
+  }
+  NS_IMETHOD AddEventListener(const nsAString& aType,
+                              nsIDOMEventListener* aListener,
+                              PRBool aUseCapture, PRBool aWantsUntrusted,
+                              PRUint8 optional_argc)
+  {
+    return nsDOMEventTargetHelper::AddEventListener(aType, aListener,
+                                                    aUseCapture,
+                                                    aWantsUntrusted,
+                                                    optional_argc);
+  }
+
+  virtual nsIScriptObjectPrincipal* GetObjectPrincipal() { return this; }
+  virtual JSContext* GetJSContextForEventHandlers() { return mCx; }
+  virtual nsIPrincipal* GetPrincipal() { return mPrincipal; }
+  void LoadFrameScript(const nsAString& aURL);
+  void Disconnect();
+  void SendMessageToParent(const nsString& aMessage, PRBool aSync,
+                           const nsString& aJSON,
+                           nsTArray<nsString>* aJSONRetVal);
+  nsFrameMessageManager* GetInnerManager()
+  {
+    return static_cast<nsFrameMessageManager*>(mMessageManager.get());
+  }
+
+  void SetOwner(nsIContent* aOwner) { mOwner = aOwner; }
+  nsFrameMessageManager* GetChromeMessageManager()
+  {
+    return mChromeMessageManager;
+  }
+  void SetChromeMessageManager(nsFrameMessageManager* aParent)
+  {
+    mChromeMessageManager = aParent;
+  }
+protected:
+  nsresult Init();
+  nsresult InitTabChildGlobal();
+  nsCOMPtr<nsIContentFrameMessageManager> mMessageManager;
+  JSContext* mCx;
+  nsCOMPtr<nsIXPConnectJSObjectHolder> mGlobal;
+  nsCOMPtr<nsIPrincipal> mPrincipal;
+  nsCOMPtr<nsIDocShell> mDocShell;
+  PRPackedBool mInitialized;
+  PRPackedBool mLoadingScript;
+  PRPackedBool mDelayedDisconnect;
+public:
+  nsIContent* mOwner;
+  nsFrameMessageManager* mChromeMessageManager;
+  nsCOMArray<nsIRunnable> mASyncMessages;
+};
+
+#endif
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -495,19 +495,16 @@ nsObjectLoadingContent::OnStartRequest(n
                                        nsISupports *aContext)
 {
   if (aRequest != mChannel) {
     // This is a bit of an edge case - happens when a new load starts before the
     // previous one got here
     return NS_BINDING_ABORTED;
   }
 
-  // We're done with the classifier
-  mClassifier = nsnull;
-
   AutoNotifier notifier(this, PR_TRUE);
 
   if (!IsSuccessfulRequest(aRequest)) {
     LOG(("OBJLC [%p]: OnStartRequest: Request failed\n", this));
     Fallback(PR_FALSE);
     return NS_BINDING_ABORTED;
   }
 
@@ -1034,20 +1031,16 @@ nsObjectLoadingContent::OnChannelRedirec
                                           nsIChannel *aNewChannel,
                                           PRUint32    aFlags)
 {
   // If we're already busy with a new load, cancel the redirect
   if (aOldChannel != mChannel) {
     return NS_BINDING_ABORTED;
   }
 
-  if (mClassifier) {
-    mClassifier->OnRedirect(aOldChannel, aNewChannel);
-  }
-
   mChannel = aNewChannel;
   return NS_OK;
 }
 
 // <public>
 PRInt32
 nsObjectLoadingContent::ObjectState() const
 {
@@ -1205,21 +1198,16 @@ nsObjectLoadingContent::LoadObject(nsIUR
     return NS_OK;
   }
 
   // From here on, we will always change the content. This means that a
   // possibly-loading channel should be aborted.
   if (mChannel) {
     LOG(("OBJLC [%p]: Cancelling existing load\n", this));
 
-    if (mClassifier) {
-      mClassifier->Cancel();
-      mClassifier = nsnull;
-    }
-
     // These three statements are carefully ordered:
     // - onStopRequest should get a channel whose status is the same as the
     //   status argument
     // - onStopRequest must get a non-null channel
     mChannel->Cancel(NS_BINDING_ABORTED);
     if (mFinalListener) {
       // NOTE: Since mFinalListener is only set in onStartRequest, which takes
       // care of calling mFinalListener->OnStartRequest, mFinalListener is only
@@ -1437,17 +1425,18 @@ nsObjectLoadingContent::LoadObject(nsIUR
   rv = doc->NodePrincipal()->GetCsp(getter_AddRefs(csp));
   NS_ENSURE_SUCCESS(rv, rv);
   if (csp) {
     channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
     channelPolicy->SetContentSecurityPolicy(csp);
     channelPolicy->SetLoadType(nsIContentPolicy::TYPE_OBJECT);
   }
   rv = NS_NewChannel(getter_AddRefs(chan), aURI, nsnull, group, this,
-                     nsIChannel::LOAD_CALL_CONTENT_SNIFFERS, 
+                     nsIChannel::LOAD_CALL_CONTENT_SNIFFERS |
+                     nsIChannel::LOAD_CLASSIFY_URI,
                      channelPolicy);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Referrer
   nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
   if (httpChan) {
     httpChan->SetReferrer(doc->GetDocumentURI());
   }
@@ -1478,22 +1467,16 @@ nsObjectLoadingContent::LoadObject(nsIUR
   }
 
   // AsyncOpen can fail if a file does not exist.
   // Show fallback content in that case.
   rv = chan->AsyncOpen(this, nsnull);
   if (NS_SUCCEEDED(rv)) {
     LOG(("OBJLC [%p]: Channel opened.\n", this));
 
-    rv = CheckClassifier(chan);
-    if (NS_FAILED(rv)) {
-      chan->Cancel(rv);
-      return rv;
-    }
-
     mChannel = chan;
     mType = eType_Loading;
   }
   return NS_OK;
 }
 
 PRUint32
 nsObjectLoadingContent::GetCapabilities() const
@@ -1925,32 +1908,16 @@ nsObjectLoadingContent::Instantiate(nsIO
       if (blockState == nsIBlocklistService::STATE_OUTDATED)
         FirePluginError(thisContent, ePluginOutdated);
     }
   }
 
   return rv;
 }
 
-nsresult
-nsObjectLoadingContent::CheckClassifier(nsIChannel *aChannel)
-{
-  nsresult rv;
-  nsCOMPtr<nsIChannelClassifier> classifier =
-    do_CreateInstance(NS_CHANNELCLASSIFIER_CONTRACTID, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = classifier->Start(aChannel, PR_FALSE);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  mClassifier = classifier;
-
-  return NS_OK;
-}
-
 /* static */ PluginSupportState
 nsObjectLoadingContent::GetPluginSupportState(nsIContent* aContent,
                                               const nsCString& aContentType)
 {
   if (!aContent->IsHTML()) {
     return ePluginOtherState;
   }
 
--- a/content/base/src/nsObjectLoadingContent.h
+++ b/content/base/src/nsObjectLoadingContent.h
@@ -47,17 +47,16 @@
 
 #include "nsImageLoadingContent.h"
 #include "nsIStreamListener.h"
 #include "nsFrameLoader.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIChannelEventSink.h"
 #include "nsIObjectLoadingContent.h"
 #include "nsIRunnable.h"
-#include "nsIChannelClassifier.h"
 #include "nsIFrame.h"
 
 class nsAsyncInstantiateEvent;
 class AutoNotifier;
 class AutoFallback;
 class AutoSetInstantiatingToFalse;
 
 enum PluginSupportState {
@@ -324,23 +323,16 @@ class nsObjectLoadingContent : public ns
      * GetFrame()->Instantiate() in that it ensures that the URI will
      * be non-null, and that a MIME type will be passed. Note that
      * this can cause the frame to be deleted while we're
      * instantiating the plugin.
      */
     nsresult Instantiate(nsIObjectFrame* aFrame, const nsACString& aMIMEType, nsIURI* aURI);
 
     /**
-     * Check the channel load against the URI classifier service (if it
-     * exists).  The channel will be suspended until the classification is
-     * complete.
-     */
-    nsresult CheckClassifier(nsIChannel *aChannel);
-
-    /**
      * Get the plugin support state for the given content node and MIME type.
      * This is used for purposes of determining whether to fire PluginNotFound
      * events etc.  aContentType is the MIME type we ended up with.
      *
      * This should only be called if the type of this content is eType_Null.
      */
     static PluginSupportState
       GetPluginSupportState(nsIContent* aContent,
@@ -390,21 +382,16 @@ class nsObjectLoadingContent : public ns
      * Non-null between asyncOpen and onStopRequest.
      */
     nsIChannel*                 mChannel;
 
     // The data we were last asked to load
     nsCOMPtr<nsIURI>            mURI;
 
     /**
-     * Suspends/resumes channels based on the URI classifier.
-     */
-    nsCOMPtr<nsIChannelClassifier> mClassifier;
-
-    /**
      * Type of the currently-loaded content.
      */
     ObjectType                  mType          : 16;
 
     /**
      * Whether we are about to call instantiate on our frame. If we aren't,
      * SetFrame needs to asynchronously call Instantiate.
      */
--- a/content/base/src/nsScriptLoader.cpp
+++ b/content/base/src/nsScriptLoader.cpp
@@ -64,23 +64,24 @@
 #include "nsIDocShell.h"
 #include "nsContentUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsAutoPtr.h"
 #include "nsIXPConnect.h"
 #include "nsContentErrors.h"
 #include "nsIParser.h"
 #include "nsThreadUtils.h"
-#include "nsIChannelClassifier.h"
 #include "nsDocShellCID.h"
 #include "nsIContentSecurityPolicy.h"
 #include "prlog.h"
 #include "nsIChannelPolicy.h"
 #include "nsChannelPolicy.h"
 
+#include "mozilla/FunctionTimer.h"
+
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gCspPRLog;
 #endif
 
 using namespace mozilla::dom;
 
 //////////////////////////////////////////////////////////////
 // Per-request data structure
@@ -298,18 +299,18 @@ nsScriptLoader::StartLoad(nsScriptLoadRe
   if (csp) {
     channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
     channelPolicy->SetContentSecurityPolicy(csp);
     channelPolicy->SetLoadType(nsIContentPolicy::TYPE_SCRIPT);
   }
 
   nsCOMPtr<nsIChannel> channel;
   rv = NS_NewChannel(getter_AddRefs(channel),
-                     aRequest->mURI, nsnull, loadGroup,
-                     prompter, nsIRequest::LOAD_NORMAL,
+                     aRequest->mURI, nsnull, loadGroup, prompter,
+                     nsIRequest::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI,
                      channelPolicy);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
   if (httpChannel) {
     // HTTP content negotation has little value in this context.
     httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
                                   NS_LITERAL_CSTRING("*/*"),
@@ -318,27 +319,16 @@ nsScriptLoader::StartLoad(nsScriptLoadRe
   }
 
   rv = NS_NewStreamLoader(getter_AddRefs(loader), this);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = channel->AsyncOpen(loader, aRequest);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // Check the load against the URI classifier
-  nsCOMPtr<nsIChannelClassifier> classifier =
-    do_CreateInstance(NS_CHANNELCLASSIFIER_CONTRACTID);
-  if (classifier) {
-    rv = classifier->Start(channel, PR_TRUE);
-    if (NS_FAILED(rv)) {
-      channel->Cancel(rv);
-      return rv;
-    }
-  }
-
   return NS_OK;
 }
 
 PRBool
 nsScriptLoader::PreloadURIComparator::Equals(const PreloadInfo &aPi,
                                              nsIURI * const &aURI) const
 {
   PRBool same;
@@ -651,16 +641,18 @@ nsScriptLoader::ProcessRequest(nsScriptL
 {
   NS_ASSERTION(ReadyToExecuteScripts() && nsContentUtils::IsSafeToRunScript(),
                "Caller forgot to check ReadyToExecuteScripts()");
 
   NS_ENSURE_ARG(aRequest);
   nsAFlatString* script;
   nsAutoString textData;
 
+  NS_TIME_FUNCTION;
+
   // If there's no script text, we try to get it from the element
   if (aRequest->mIsInline) {
     // XXX This is inefficient - GetText makes multiple
     // copies.
     aRequest->mElement->GetScriptText(textData);
 
     script = &textData;
   }
--- a/content/base/src/nsStyleLinkElement.cpp
+++ b/content/base/src/nsStyleLinkElement.cpp
@@ -243,17 +243,17 @@ nsStyleLinkElement::DoUpdateStyleSheet(n
   if (!doc || !doc->CSSLoader()->GetEnabled()) {
     return NS_OK;
   }
 
   PRBool isInline;
   nsCOMPtr<nsIURI> uri = GetStyleSheetURL(&isInline);
 
   if (!aForceUpdate && mStyleSheet && !isInline && uri) {
-    nsCOMPtr<nsIURI> oldURI = mStyleSheet->GetSheetURI();
+    nsIURI* oldURI = mStyleSheet->GetSheetURI();
     if (oldURI) {
       PRBool equal;
       nsresult rv = oldURI->Equals(uri, &equal);
       if (NS_SUCCEEDED(rv) && equal) {
         return NS_OK; // We already loaded this stylesheet
       }
     }
   }
--- a/content/base/test/chrome/Makefile.in
+++ b/content/base/test/chrome/Makefile.in
@@ -53,15 +53,17 @@ include $(topsrcdir)/config/rules.mk
     test_bug421622.xul \
     test_bug429785.xul \
     test_bug430050.xul \
     test_bug467123.xul \
     test_bug514705.xul \
     bug514705_helper.xul \
     test_title.xul \
     title_window.xul \
+    test_bug549682.xul \
+    file_bug549682.xul \
     $(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
 libs:: $(_CHROME_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/content/base/test/chrome/file_bug549682.xul
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=549682
+-->
+<window title="Mozilla Bug 549682"
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+  onload="run()">
+  <label value="Mozilla Bug 549682"/>
+  <!-- test code goes here -->
+  <script type="application/javascript"><![CDATA[
+  var didRunAsync = false;
+
+  function asyncL(m) {
+    didRunAsync = true;
+    opener.wrappedJSObject.is(m.name, "async", "Wrong message!");
+    opener.wrappedJSObject.is(m.json.data, 1234, "Wrong data!");
+  }
+
+  function syncL(m) {
+    opener.wrappedJSObject.is(m.name, "sync", "Wrong message!");
+    opener.wrappedJSObject.is(m.json.data, 1234, "Wrong data!");
+    opener.wrappedJSObject.ok(didRunAsync, "Should have run async!");
+    opener.setTimeout("done()", 0);
+    var i = document.getElementById("ifr");
+    i.parentNode.removeChild(i); // This is a crash test!
+    window.close();
+  }
+
+  function loadScript() {
+    // Async should be prosessed first!
+    messageManager.loadFrameScript("data:,sendAsyncMessage('async', { data: 1234 }); sendSyncMessage('sync', { data: 1234 });", true);
+  }
+
+  function run() {
+    messageManager.addMessageListener("async", asyncL);
+    messageManager.addMessageListener("sync", syncL);
+    setTimeout(loadScript, 0);
+  }
+
+  ]]></script>
+  <browser type="content" src="about:blank" id="ifr"/>
+</window>
new file mode 100644
--- /dev/null
+++ b/content/base/test/chrome/test_bug549682.xul
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=549682
+-->
+<window title="Mozilla Bug 549682"
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <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>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=549682"
+     target="_blank">Mozilla Bug 549682</a>
+  </body>
+
+  <!-- test code goes here -->
+  <script type="application/javascript"><![CDATA[
+
+  /** Test for Bug 549682 **/
+  SimpleTest.waitForExplicitFinish();
+
+  function done() {
+    SimpleTest.finish();
+  }
+
+  addLoadEvent(function() {
+    window.open("file_bug549682.xul", "", "chrome");
+  });
+  ]]></script>
+</window>
--- a/content/base/test/file_csp_redirects_main.html
+++ b/content/base/test/file_csp_redirects_main.html
@@ -8,17 +8,17 @@
 
 <script>
 var thisSite = "http://mochi.test:8888";
 var otherSite = "http://example.com";
 var page = "/tests/content/base/test/file_csp_redirects_page.sjs";
 
 var tests = { "font-src": thisSite+page+"?testid=font-src&csp=1",
               "frame-src": thisSite+page+"?testid=frame-src&csp=1",
-//              "img-src":  thisSite+page+"?testid=img-src&csp=1",
+              "img-src":  thisSite+page+"?testid=img-src&csp=1",
               "media-src":  thisSite+page+"?testid=media-src&csp=1",
               "object-src":  thisSite+page+"?testid=object-src&csp=1",
               "script-src":  thisSite+page+"?testid=script-src&csp=1",
               "style-src":  thisSite+page+"?testid=style-src&csp=1",
               "worker":  thisSite+page+"?testid=worker&csp=1",
               "xhr-src":  thisSite+page+"?testid=xhr-src&csp=1",
             };
 
--- a/content/base/test/test_csp_redirects.html
+++ b/content/base/test/test_csp_redirects.html
@@ -78,18 +78,18 @@ examiner.prototype  = {
 }
 window.examiner = new examiner();
 
 // contains { test_frame_id : expected_result }
 var testExpectedResults = { "font-src": true,
                             "font-src-redir": false,
                             "frame-src": true,
                             "frame-src-redir": false,
-//                            "img-src": true,
-//                            "img-src-redir": false,
+                            "img-src": true,
+                            "img-src-redir": false,
                             "media-src": true,
                             "media-src-redir": false,
                             "object-src": true,
                             "object-src-redir": false,
                             "script-src": true,
                             "script-src-redir": false,
                             "style-src": true,
                             "style-src-redir": false,
--- a/content/canvas/public/Makefile.in
+++ b/content/canvas/public/Makefile.in
@@ -44,18 +44,17 @@ include $(DEPTH)/config/autoconf.mk
 
 MODULE		= content
 XPIDL_MODULE = content_canvas
 
 EXPORTS_NAMESPACES = mozilla/ipc
 
 EXPORTS		= \
 		nsICanvasRenderingContextInternal.h \
-		nsICanvasElement.h \
-		WebGLArray.h \
+		nsICanvasElementExternal.h \
 		$(NULL)
 
 EXPORTS_mozilla/ipc = \
 		DocumentRendererChild.h \
 		DocumentRendererParent.h \
 		DocumentRendererShmemChild.h \
 		DocumentRendererShmemParent.h \
 		$(NULL)
deleted file mode 100644
--- a/content/canvas/public/WebGLArray.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* ***** 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):
- *
- * 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 WEBGLARRAY_H_
-#define WEBGLARRAY_H_
-
-nsresult NS_NewWebGLArrayBuffer(nsISupports **aNewObject);
-nsresult NS_NewWebGLFloatArray(nsISupports **aNewObject);
-nsresult NS_NewWebGLByteArray(nsISupports **aNewObject);
-nsresult NS_NewWebGLUnsignedByteArray(nsISupports **aNewObject);
-nsresult NS_NewWebGLShortArray(nsISupports **aNewObject);
-nsresult NS_NewWebGLUnsignedShortArray(nsISupports **aNewObject);
-nsresult NS_NewWebGLIntArray(nsISupports **aNewObject);
-nsresult NS_NewWebGLUnsignedIntArray(nsISupports **aNewObject);
-
-#endif
deleted file mode 100644
--- a/content/canvas/public/nsICanvasElement.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* -*- Mode: C++; tab-width: 40; 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
- *   Vladimir Vukicevic <vladimir@pobox.com>
- * Portions created by the Initial Developer are Copyright (C) 2005
- * the Initial Developer. All Rights Reserved.
- *
- * 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 ***** */
-
-#ifndef nsICanvasElement_h___
-#define nsICanvasElement_h___
-
-#include "nsISupports.h"
-#include "gfxPattern.h"
-
-class gfxContext;
-class nsIFrame;
-struct gfxRect;
-
-// {D31B3CCF-DDA3-49a8-AEF6-B95AF8E09159}
-#define NS_ICANVASELEMENT_IID \
-    { 0xd31b3ccf, 0xdda3, 0x49a8, { 0xae, 0xf6, 0xb9, 0x5a, 0xf8, 0xe0, 0x91, 0x59 } }
-
-class nsIRenderingContext;
-
-class nsICanvasRenderingContextInternal;
-
-struct _cairo_surface;
-
-class nsICanvasElement : public nsISupports {
-public:
-  NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICANVASELEMENT_IID)
-
-  /**
-   * Ask the canvas Element to return the primary frame, if any
-   */
-  NS_IMETHOD GetPrimaryCanvasFrame (nsIFrame **aFrame) = 0;
-
-  /**
-   * Get the size in pixels of this canvas element
-   */
-  NS_IMETHOD GetSize (PRUint32 *width, PRUint32 *height) = 0;
-
-  /*
-   * Ask the canvas element to tell the contexts to render themselves
-   * to the given gfxContext at the origin of its coordinate space.
-   */
-  NS_IMETHOD RenderContexts (gfxContext *ctx, gfxPattern::GraphicsFilter aFilter) = 0;
-
-  /**
-   * Determine whether the canvas is write-only.
-   */
-  virtual PRBool IsWriteOnly() = 0;
-
-  /**
-   * Force the canvas to be write-only.
-   */
-  virtual void SetWriteOnly() = 0;
-
-  /*
-   * Ask the canvas frame to invalidate itself
-   */
-  NS_IMETHOD InvalidateFrame () = 0;
-
-  /*
-   * Ask the canvas frame to invalidate a portion of the frame; damageRect
-   * is relative to the origin of the canvas frame in CSS pixels.
-   */
-  NS_IMETHOD InvalidateFrameSubrect (const gfxRect& damageRect) = 0;
-
-  /*
-   * Get the number of contexts in this canvas, and request a context at
-   * an index.
-   */
-  virtual PRInt32 CountContexts () = 0;
-  virtual nsICanvasRenderingContextInternal *GetContextAtIndex (PRInt32 index) = 0;
-
-  virtual PRBool GetIsOpaque() = 0;
-
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsICanvasElement, NS_ICANVASELEMENT_IID)
-
-#endif /* nsICanvasElement_h___ */
new file mode 100644
--- /dev/null
+++ b/content/canvas/public/nsICanvasElementExternal.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 40; 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
+ *   Vladimir Vukicevic <vladimir@pobox.com>
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * 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 ***** */
+
+#ifndef nsICanvasElementExternal_h___
+#define nsICanvasElementExternal_h___
+
+#include "nsISupports.h"
+#include "gfxPattern.h"
+
+class gfxContext;
+class nsIFrame;
+struct gfxRect;
+
+#define NS_ICANVASELEMENTEXTERNAL_IID \
+  { 0x51870f54, 0x6c4c, 0x469a, {0xad, 0x46, 0xf0, 0xa9, 0x8e, 0x32, 0xa7, 0xe2 } }
+
+class nsIRenderingContext;
+class nsICanvasRenderingContextInternal;
+
+struct _cairo_surface;
+
+/*
+ * This interface contains methods that are needed outside of the content/layout
+ * modules, specifically widget.  It should eventually go away when we support
+ * libxul builds, and nsHTMLCanvasElement be used directly.
+ *
+ * Code internal to content/layout should /never/ use this interface; if the
+ * same functionality is needed in both places, two separate methods should be
+ * used.
+ */
+
+class nsICanvasElementExternal : public nsISupports {
+public:
+  NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICANVASELEMENTEXTERNAL_IID)
+
+  /**
+   * Get the size in pixels of this canvas element
+   */
+  NS_IMETHOD_(nsIntSize) GetSizeExternal() = 0;
+
+  /*
+   * Ask the canvas element to tell the contexts to render themselves
+   * to the given gfxContext at the origin of its coordinate space.
+   */
+  NS_IMETHOD RenderContextsExternal(gfxContext *ctx,
+                                    gfxPattern::GraphicsFilter aFilter) = 0;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsICanvasElementExternal, NS_ICANVASELEMENTEXTERNAL_IID)
+
+#endif /* nsICanvasElementExternal_h___ */
--- a/content/canvas/public/nsICanvasRenderingContextInternal.h
+++ b/content/canvas/public/nsICanvasRenderingContextInternal.h
@@ -34,41 +34,49 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsICanvasRenderingContextInternal_h___
 #define nsICanvasRenderingContextInternal_h___
 
 #include "nsISupports.h"
-#include "nsICanvasElement.h"
 #include "nsIInputStream.h"
 #include "nsIDocShell.h"
 #include "gfxPattern.h"
 
-// {3c4632ab-8443-4082-a8a310e7cfba4c74}
+// {b96168fd-6f13-4ca7-b820-e96f22e71fe5}
 #define NS_ICANVASRENDERINGCONTEXTINTERNAL_IID \
-  { 0x3c4632ab, 0x8443, 0x4082, { 0xa8, 0xa3, 0x10, 0xe7, 0xcf, 0xba, 0x4c, 0x74 } }
+{ 0xb96168fd, 0x6f13, 0x4ca7, \
+  { 0xb8, 0x20, 0xe9, 0x6f, 0x22, 0xe7, 0x1f, 0xe5 } }
 
+class nsHTMLCanvasElement;
 class gfxContext;
 class gfxASurface;
 
 namespace mozilla {
+namespace layers {
+class CanvasLayer;
+class LayerManager;
+}
 namespace ipc {
 class Shmem;
 }
 }
 
 class nsICanvasRenderingContextInternal : public nsISupports {
 public:
+  typedef mozilla::layers::CanvasLayer CanvasLayer;
+  typedef mozilla::layers::LayerManager LayerManager;
+
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICANVASRENDERINGCONTEXTINTERNAL_IID)
 
   // This method should NOT hold a ref to aParentCanvas; it will be called
   // with nsnull when the element is going away.
-  NS_IMETHOD SetCanvasElement(nsICanvasElement* aParentCanvas) = 0;
+  NS_IMETHOD SetCanvasElement(nsHTMLCanvasElement* aParentCanvas) = 0;
 
   // Sets the dimensions of the canvas, in pixels.  Called
   // whenever the size of the element changes.
   NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height) = 0;
 
   NS_IMETHOD InitializeWithSurface(nsIDocShell *docShell, gfxASurface *surface, PRInt32 width, PRInt32 height) = 0;
 
   // Render the canvas at the origin of the given gfxContext
@@ -89,16 +97,22 @@ public:
   NS_IMETHOD GetThebesSurface(gfxASurface **surface) = 0;
 
   // If this context is opaque, the backing store of the canvas should
   // be created as opaque; all compositing operators should assume the
   // dst alpha is always 1.0.  If this is never called, the context
   // defaults to false (not opaque).
   NS_IMETHOD SetIsOpaque(PRBool isOpaque) = 0;
 
+  // Return the CanvasLayer for this context, creating
+  // one for the given layer manager if not available.
+  virtual already_AddRefed<CanvasLayer> GetCanvasLayer(LayerManager *mgr) = 0;
+
+  virtual void MarkContextClean() = 0;
+
   // Redraw the dirty rectangle of this canvas.
   NS_IMETHOD Redraw(const gfxRect &dirty) = 0;
 
   // If this context can be set to use Mozilla's Shmem segments as its backing
   // store, this will set it to that state. Note that if you have drawn
   // anything into this canvas before changing the shmem state, it will be
   // lost.
   NS_IMETHOD SetIsShmem(PRBool isShmem) = 0;
--- a/content/canvas/src/CanvasUtils.cpp
+++ b/content/canvas/src/CanvasUtils.cpp
@@ -43,30 +43,30 @@
 
 #include "nsIServiceManager.h"
 
 #include "nsIConsoleService.h"
 #include "nsIDOMDocument.h"
 #include "nsIDocument.h"
 #include "nsIDOMCanvasRenderingContext2D.h"
 #include "nsICanvasRenderingContextInternal.h"
-#include "nsICanvasElement.h"
+#include "nsHTMLCanvasElement.h"
 #include "nsIPrincipal.h"
 #include "nsINode.h"
 
 #include "nsGfxCIID.h"
 
 #include "nsTArray.h"
 
 #include "CanvasUtils.h"
 
 using namespace mozilla;
 
 void
-CanvasUtils::DoDrawImageSecurityCheck(nsICanvasElement *aCanvasElement,
+CanvasUtils::DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
                                       nsIPrincipal *aPrincipal,
                                       PRBool forceWriteOnly)
 {
     // Callers should ensure that mCanvasElement is non-null before calling this
     if (!aCanvasElement) {
         NS_WARNING("DoDrawImageSecurityCheck called without canvas element!");
         return;
     }
@@ -78,17 +78,17 @@ CanvasUtils::DoDrawImageSecurityCheck(ns
     if (forceWriteOnly) {
         aCanvasElement->SetWriteOnly();
         return;
     }
 
     if (aPrincipal == nsnull)
         return;
 
-    nsCOMPtr<nsINode> elem = do_QueryInterface(aCanvasElement);
+    nsCOMPtr<nsINode> elem = do_QueryInterface(static_cast<nsIDOMHTMLCanvasElement*>(aCanvasElement));
     if (elem) { // XXXbz How could this actually be null?
         PRBool subsumes;
         nsresult rv =
             elem->NodePrincipal()->Subsumes(aPrincipal, &subsumes);
             
         if (NS_SUCCEEDED(rv) && subsumes) {
             // This canvas has access to that image anyway
             return;
--- a/content/canvas/src/CanvasUtils.h
+++ b/content/canvas/src/CanvasUtils.h
@@ -35,17 +35,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef _CANVASUTILS_H_
 #define _CANVASUTILS_H_
 
 #include "prtypes.h"
 
-class nsICanvasElement;
+class nsHTMLCanvasElement;
 class nsIPrincipal;
 
 namespace mozilla {
 
 class CanvasUtils {
 public:
     // Check that the rectangle [x,y,w,h] is a subrectangle of [0,0,realWidth,realHeight]
 
@@ -60,17 +60,17 @@ public:
             return PR_FALSE;
 
         return PR_TRUE;
     }
 
     // Flag aCanvasElement as write-only if drawing an image with aPrincipal
     // onto it would make it such.
 
-    static void DoDrawImageSecurityCheck(nsICanvasElement *aCanvasElement,
+    static void DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
                                          nsIPrincipal *aPrincipal,
                                          PRBool forceWriteOnly);
 
     static void LogMessage (const nsCString& errorString);
     static void LogMessagef (const char *fmt, ...);
 
 private:
     // this can't be instantiated
--- a/content/canvas/src/CustomQS_WebGL.h
+++ b/content/canvas/src/CustomQS_WebGL.h
@@ -83,17 +83,17 @@ nsICanvasRenderingContextWebGL_BufferDat
     int32 size;
     int32 usage;
 
     if (!JS_ValueToECMAInt32(cx, argv[0], &target))
         return JS_FALSE;
     if (!JS_ValueToECMAInt32(cx, argv[2], &usage))
         return JS_FALSE;
 
-    if (JSVAL_IS_OBJECT(argv[1])) {
+    if (!JSVAL_IS_PRIMITIVE(argv[1])) {
         JSObject *arg2 = JSVAL_TO_OBJECT(argv[1]);
         if (js_IsArrayBuffer(arg2)) {
             wb = js::ArrayBuffer::fromJSObject(arg2);
         } else if (js_IsTypedArray(arg2)) {
             wa = js::TypedArray::fromJSObject(arg2);
         }
     }
 
@@ -148,17 +148,17 @@ nsICanvasRenderingContextWebGL_BufferSub
     js::TypedArray *wa = 0;
     js::ArrayBuffer *wb = 0;
 
     if (!JS_ValueToECMAInt32(cx, argv[0], &target))
         return JS_FALSE;
     if (!JS_ValueToECMAInt32(cx, argv[1], &offset))
         return JS_FALSE;
 
-    if (!JSVAL_IS_OBJECT(argv[2])) {
+    if (JSVAL_IS_PRIMITIVE(argv[2])) {
         xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 2);
         return JS_FALSE;
     }
 
     JSObject *arg3 = JSVAL_TO_OBJECT(argv[2]);
     if (js_IsArrayBuffer(arg3)) {
         wb = js::ArrayBuffer::fromJSObject(arg3);
     } else if (js_IsTypedArray(arg3)) {
@@ -209,16 +209,17 @@ nsICanvasRenderingContextWebGL_TexImage2
         return JS_FALSE;
 
     if (argc < 3)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
     jsval *argv = JS_ARGV(cx, vp);
 
     int32 intargs[8];
+    JSObject *arg9 = nsnull;
 
     // convert the first two args, they must be ints
     for (jsuint i = 0; i < 2; ++i) {
         if (!JS_ValueToECMAInt32(cx, argv[i], &intargs[i]))
             return JS_FALSE;
     }
 
     if (JSVAL_IS_OBJECT(argv[2])) {
@@ -232,60 +233,51 @@ nsICanvasRenderingContextWebGL_TexImage2
 
             // convert args 4 and 5 if present, default to 0
             for (jsuint i = 3; i < 5 && i < argc; ++i) {
                 if (!JS_ValueToECMAInt32(cx, argv[i], &intargs[i]))
                     return JS_FALSE;
             }
 
             rv = self->TexImage2D_dom(intargs[0], intargs[1], elt, (GLboolean) intargs[3], (GLboolean) intargs[4]);
-            if (NS_FAILED(rv))
-                return xpc_qsThrowMethodFailed(cx, rv, vp);
-            return JS_TRUE;
+            goto check_rv_and_return;
         }
     }
 
     // didn't succeed? convert the rest of the int args
     for (jsuint i = 2; i < 8; ++i) {
         if (!JS_ValueToECMAInt32(cx, argv[i], &intargs[i]))
             return JS_FALSE;
     }
 
     if (!JSVAL_IS_OBJECT(argv[8])) {
         xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8);
         return JS_FALSE;
     }
 
-    // then try to grab either a js::ArrayBuffer or js::TypedArray
-    js::TypedArray *wa = 0;
-    js::ArrayBuffer *wb = 0;
-
-    JSObject *arg9 = JSVAL_TO_OBJECT(argv[8]);
-    if (js_IsArrayBuffer(arg9)) {
-        wb = js::ArrayBuffer::fromJSObject(arg9);
+    // then try to grab either a js::ArrayBuffer, js::TypedArray, or null
+    arg9 = JSVAL_TO_OBJECT(argv[8]);
+    if (arg9 == nsnull) {
+        rv = self->TexImage2D_buf(intargs[0], intargs[1], intargs[2], intargs[3],
+                                  intargs[4], intargs[5], intargs[6], intargs[7],
+                                  nsnull);
+    } else if (js_IsArrayBuffer(arg9)) {
+        rv = self->TexImage2D_buf(intargs[0], intargs[1], intargs[2], intargs[3],
+                                    intargs[4], intargs[5], intargs[6], intargs[7],
+                                    js::ArrayBuffer::fromJSObject(arg9));
     } else if (js_IsTypedArray(arg9)) {
-        wa = js::TypedArray::fromJSObject(arg9);
+        rv = self->TexImage2D_array(intargs[0], intargs[1], intargs[2], intargs[3],
+                                  intargs[4], intargs[5], intargs[6], intargs[7],
+                                  js::TypedArray::fromJSObject(arg9));
     } else {
         xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8);
         return JS_FALSE;
     }
 
-    if (wa) {
-        rv = self->TexImage2D_array(intargs[0], intargs[1], intargs[2], intargs[3],
-                                    intargs[4], intargs[5], intargs[6], intargs[7],
-                                    wa);
-    } else if (wb) {
-        rv = self->TexImage2D_buf(intargs[0], intargs[1], intargs[2], intargs[3],
-                                  intargs[4], intargs[5], intargs[6], intargs[7],
-                                  wb);
-    } else {
-        xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8);
-        return JS_FALSE;
-    }
-
+check_rv_and_return:
     if (NS_FAILED(rv))
         return xpc_qsThrowMethodFailed(cx, rv, vp);
 
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
 
 /*
@@ -350,17 +342,17 @@ nsICanvasRenderingContextWebGL_TexSubIma
     }
 
     // didn't succeed? convert the rest of the int args
     for (jsuint i = 6; i < 8; ++i) {
         if (!JS_ValueToECMAInt32(cx, argv[i], &intargs[i]))
             return JS_FALSE;
     }
 
-    if (!JSVAL_IS_OBJECT(argv[8])) {
+    if (JSVAL_IS_PRIMITIVE(argv[8])) {
         xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8);
         return JS_FALSE;
     }
 
     // then try to grab either a js::ArrayBuffer or js::TypedArray
     js::TypedArray *wa = 0;
     js::ArrayBuffer *wb = 0;
 
--- a/content/canvas/src/Makefile.in
+++ b/content/canvas/src/Makefile.in
@@ -64,53 +64,24 @@ CPPSRCS += \
 	DocumentRendererShmemChild.cpp \
 	$(NULL)
 endif
 
 # Canvas 3D Pieces
 
 ifdef MOZ_WEBGL
 
-ifdef MOZ_X11
-ifdef MOZ_PLATFORM_MAEMO
-WEBGL_PLATFORM = EGL
-DEFINES += -DUSE_GLES2
-else
-WEBGL_PLATFORM = GLX
-EXTRA_DSO_LIBS += X11
-endif
-endif
-
-ifeq (windows,$(MOZ_WIDGET_TOOLKIT))
-ifdef WINCE
-WEBGL_PLATFORM = EGL
-DEFINES += -DUSE_GLES2
-else
-WEBGL_PLATFORM = WGL
-endif
-endif
-
-ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
-WEBGL_PLATFORM = CGL
-endif
-
 CPPSRCS += \
 	WebGLContext.cpp \
 	WebGLContextGL.cpp \
 	WebGLContextUtils.cpp \
 	WebGLContextValidate.cpp \
 	NativeJSContext.cpp \
-	glwrap.cpp \
-	nsGLPbuffer.cpp \
-	nsGLPbufferOSMesa.cpp \
 	$(NULL)
 
-CPPSRCS += nsGLPbuffer$(WEBGL_PLATFORM).cpp
-DEFINES += -DUSE_$(WEBGL_PLATFORM)
-
 else
 
 CPPSRCS += WebGLContextNotSupported.cpp
 
 endif
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
--- a/content/canvas/src/NativeJSContext.cpp
+++ b/content/canvas/src/NativeJSContext.cpp
@@ -3,16 +3,17 @@
 #include "nsIJSRuntimeService.h"
 
 nsIJSRuntimeService* NativeJSContext::sJSRuntimeService = 0;
 JSRuntime* NativeJSContext::sJSScriptRuntime = 0;
 
 PRBool
 NativeJSContext::AddGCRoot(void *aPtr, const char *aName)
 {
+  NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
   if (!sJSScriptRuntime) {
     nsresult rv = CallGetService("@mozilla.org/js/xpc/RuntimeService;1",
                                  &sJSRuntimeService);
     NS_ENSURE_SUCCESS(rv, PR_FALSE);
     NS_ABORT_IF_FALSE(sJSRuntimeService, "CallGetService succeeded but returned a null pointer?");
 
     sJSRuntimeService->GetRuntime(&sJSScriptRuntime);
     if (!sJSScriptRuntime) {
@@ -24,15 +25,16 @@ NativeJSContext::AddGCRoot(void *aPtr, c
 
   PRBool ok;
   return ok = ::JS_AddNamedRootRT(sJSScriptRuntime, aPtr, aName);
 }
 
 void
 NativeJSContext::ReleaseGCRoot(void *aPtr)
 {
+  NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
   if (!sJSScriptRuntime) {
     NS_NOTREACHED("Trying to remove a JS GC root when none were added");
     return;
   }
 
   ::JS_RemoveRootRT(sJSScriptRuntime, aPtr);
 }
--- a/content/canvas/src/NativeJSContext.h
+++ b/content/canvas/src/NativeJSContext.h
@@ -34,67 +34,75 @@ public:
 
         JS_BeginRequest(ctx);
 
         ncc->GetArgc(&argc);
         ncc->GetArgvPtr(&argv);
     }
 
     ~NativeJSContext() {
-        JS_EndRequest(ctx);
+        if (NS_SUCCEEDED(error))
+            JS_EndRequest(ctx);
     }
 
     PRBool CheckArray (JSObject *obj, jsuint *sz) {
+        NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
         if (obj &&
             ::JS_IsArrayObject(ctx, obj) &&
             ::JS_GetArrayLength(ctx, obj, sz))
             return PR_TRUE;
         return PR_FALSE;
     }
 
     PRBool CheckArray (jsval val, jsuint *sz) {
+        NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
         if (!JSVAL_IS_NULL(val) &&
             JSVAL_IS_OBJECT(val) &&
             ::JS_IsArrayObject(ctx, JSVAL_TO_OBJECT(val)) &&
             ::JS_GetArrayLength(ctx, JSVAL_TO_OBJECT(val), sz))
             return PR_TRUE;
         return PR_FALSE;
     }
 
     PRBool AddGCRoot (void *aPtr, const char *aName);
     void ReleaseGCRoot (void *aPtr);
 
     void SetRetVal (PRInt32 val) {
+        NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
         if (INT_FITS_IN_JSVAL(val))
             SetRetValAsJSVal(INT_TO_JSVAL(val));
         else
             SetRetVal((double) val);
     }
 
     void SetRetVal (PRUint32 val) {
+        NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
         if (INT_FITS_IN_JSVAL(val))
             SetRetValAsJSVal(INT_TO_JSVAL((int) val));
         else
             SetRetVal((double) val);
     }
 
     void SetRetVal (double val) {
+        NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
         jsval *vp;
         ncc->GetRetValPtr(&vp);
         JS_NewDoubleValue(ctx, val, vp);
     }
 
     void SetBoolRetVal (PRBool val) {
+        NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
         if (val)
             SetRetValAsJSVal(JSVAL_TRUE);
         else
             SetRetValAsJSVal(JSVAL_FALSE);
     }
 
     void SetRetVal (PRInt32 *vp, PRUint32 len) {
+        NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
         nsAutoArrayPtr<jsval> jsvector(new jsval[len]);
 
         if (!JS_EnterLocalRootScope(ctx))
             return; // XXX ???
 
         for (PRUint32 i = 0; i < len; i++) {
             if (INT_FITS_IN_JSVAL(vp[i])) {
                 jsvector[i] = INT_TO_JSVAL(vp[i]);
@@ -105,68 +113,73 @@ public:
 
         JSObject *jsarr = JS_NewArrayObject(ctx, len, jsvector.get());
         SetRetVal(jsarr);
 
         JS_LeaveLocalRootScope(ctx);
     }
 
     void SetRetVal (PRUint32 *vp, PRUint32 len) {
+        NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
         nsAutoArrayPtr<jsval> jsvector(new jsval[len]);
 
         if (!JS_EnterLocalRootScope(ctx))
             return; // XXX ???
 
         for (PRUint32 i = 0; i < len; i++) {
             JS_NewNumberValue(ctx, vp[i], &jsvector[i]);
         }
 
         JSObject *jsarr = JS_NewArrayObject(ctx, len, jsvector.get());
         SetRetVal(jsarr);
 
         JS_LeaveLocalRootScope(ctx);
     }
 
     void SetRetVal (double *dp, PRUint32 len) {
+        NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
         nsAutoArrayPtr<jsval> jsvector(new jsval[len]);
 
         if (!JS_EnterLocalRootScope(ctx))
             return; // XXX ???
 
         for (PRUint32 i = 0; i < len; i++)
             JS_NewDoubleValue(ctx, (jsdouble) dp[i], &jsvector[i]);
             
         JSObject *jsarr = JS_NewArrayObject(ctx, len, jsvector.get());
         SetRetVal(jsarr);
 
         JS_LeaveLocalRootScope(ctx);
     }
 
     void SetRetVal (float *fp, PRUint32 len) {
+        NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
         nsAutoArrayPtr<jsval> jsvector(new jsval[len]);
 
         if (!JS_EnterLocalRootScope(ctx))
             return; // XXX ???
 
         for (PRUint32 i = 0; i < len; i++)
             JS_NewDoubleValue(ctx, (jsdouble) fp[i], &jsvector[i]);
         JSObject *jsarr = JS_NewArrayObject(ctx, len, jsvector.get());
         SetRetVal(jsarr);
 
         JS_LeaveLocalRootScope(ctx);
     }
 
     void SetRetValAsJSVal (jsval val) {
+        NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
         jsval *vp;
         ncc->GetRetValPtr(&vp);
         *vp = val;
         ncc->SetReturnValueWasSet(PR_TRUE);
     }
 
     void SetRetVal (JSObject *obj) {
+        NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
         SetRetValAsJSVal(OBJECT_TO_JSVAL(obj));
     }
 
     void SetRetVal (JSObjectHelper& objh);
 
     nsAXPCNativeCallContext *ncc;
     nsresult error;
     JSContext *ctx;
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -1,45 +1,88 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** 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):
+ *   Vladimir Vukicevic <vladimir@pobox.com> (original author)
+ *   Mark Steele <mwsteele@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * 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 "WebGLContext.h"
 
 #include "nsIConsoleService.h"
 #include "nsIPrefService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIClassInfoImpl.h"
 #include "nsContentUtils.h"
 #include "nsIXPConnect.h"
 #include "nsDOMError.h"
 
 #include "gfxContext.h"
 #include "gfxPattern.h"
 
-#include "localgl.h"
-
 #include "CanvasUtils.h"
 #include "NativeJSContext.h"
 
+#include "GLContextProvider.h"
+
 using namespace mozilla;
+using namespace mozilla::gl;
 
 nsresult NS_NewCanvasRenderingContextWebGL(nsICanvasRenderingContextWebGL** aResult);
 
 nsresult
 NS_NewCanvasRenderingContextWebGL(nsICanvasRenderingContextWebGL** aResult)
 {
     nsICanvasRenderingContextWebGL* ctx = new WebGLContext();
     if (!ctx)
         return NS_ERROR_OUT_OF_MEMORY;
 
     NS_ADDREF(*aResult = ctx);
     return NS_OK;
 }
 
 WebGLContext::WebGLContext()
-    : gl(nsnull), mCanvasElement(nsnull), mGLPbuffer(nsnull), mWidth(0), mHeight(0),
-      mInvalidated(PR_FALSE), mActiveTexture(0)
+    : mCanvasElement(nsnull),
+      gl(nsnull),
+      mWidth(0), mHeight(0),
+      mInvalidated(PR_FALSE),
+      mActiveTexture(0),
+      mSynthesizedGLError(LOCAL_GL_NO_ERROR)
 {
     mMapBuffers.Init();
     mMapTextures.Init();
     mMapPrograms.Init();
     mMapShaders.Init();
     mMapFramebuffers.Init();
     mMapRenderbuffers.Init();
 }
@@ -61,96 +104,57 @@ WebGLContext::Invalidate()
     mCanvasElement->InvalidateFrame();
 }
 
 //
 // nsICanvasRenderingContextInternal
 //
 
 NS_IMETHODIMP
-WebGLContext::SetCanvasElement(nsICanvasElement* aParentCanvas)
+WebGLContext::SetCanvasElement(nsHTMLCanvasElement* aParentCanvas)
 {
-    nsresult rv;
-
     if (aParentCanvas == nsnull) {
         // we get this on shutdown; we should do some more cleanup here,
         // but instead we just let our destructor do it.
         return NS_OK;
     }
 
     if (!SafeToCreateCanvas3DContext(aParentCanvas))
         return NS_ERROR_FAILURE;
 
-    //
-    // Let's find our prefs
-    //
-    nsCOMPtr<nsIPrefService> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    PRBool forceSoftware = PR_FALSE;
-
-    nsCOMPtr<nsIPrefBranch> prefBranch;
-    rv = prefService->GetBranch("webgl.", getter_AddRefs(prefBranch));
-    if (NS_SUCCEEDED(rv)) {
-        PRBool val;
-
-        rv = prefBranch->GetBoolPref("software_render", &val);
-        if (NS_SUCCEEDED(rv))
-            forceSoftware = val;
-    }
-
-    LogMessage("Canvas 3D: creating PBuffer...");
+    mCanvasElement = aParentCanvas;
 
-    if (!forceSoftware) {
-#if defined(USE_EGL)
-        mGLPbuffer = new nsGLPbufferEGL();
-#elif defined(USE_WGL)
-        mGLPbuffer = new nsGLPbufferWGL();
-#elif defined(USE_GLX)
-        mGLPbuffer = new nsGLPbufferGLX();
-#elif defined(USE_CGL)
-        mGLPbuffer = new nsGLPbufferCGL();
-#else
-        mGLPbuffer = nsnull;
-#endif
-
-        if (mGLPbuffer && !mGLPbuffer->Init(this))
-            mGLPbuffer = nsnull;
-    }
-
-    if (!mGLPbuffer) {
-        mGLPbuffer = new nsGLPbufferOSMESA();
-        if (!mGLPbuffer->Init(this))
-            mGLPbuffer = nsnull;
-    }
-
-    if (!mGLPbuffer)
-        return NS_ERROR_FAILURE;
-
-    gl = mGLPbuffer->GL();
-
-    if (!ValidateGL()) {
-        // XXX over here we need to destroy mGLPbuffer and create a mesa buffer
-
-        LogMessage("Canvas 3D: Couldn't validate OpenGL implementation; is everything needed present?");
-        return NS_ERROR_FAILURE;
-    }
-
-    mCanvasElement = aParentCanvas;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
 {
     if (mWidth == width && mHeight == height)
         return NS_OK;
 
-    if (!mGLPbuffer->Resize(width, height)) {
-        LogMessage("mGLPbuffer->Resize failed");
+    LogMessage("Canvas 3D: creating PBuffer...");
+
+    GLContextProvider::ContextFormat format(GLContextProvider::ContextFormat::BasicRGBA32);
+    format.depth = 16;
+    format.minDepth = 1;
+
+    gl = gl::sGLContextProvider.CreatePBuffer(gfxIntSize(width, height), format);
+
+    if (!gl) {
+        LogMessage("Canvas 3D: can't get a native PBuffer, trying OSMesa...");
+        gl = gl::GLContextProviderOSMesa::CreatePBuffer(gfxIntSize(width, height), format);
+        if (!gl) {
+            LogMessage("Canvas 3D: can't create a OSMesa pseudo-PBuffer.");
+            return NS_ERROR_FAILURE;
+        }
+    }
+
+    if (!ValidateGL()) {
+        LogMessage("Canvas 3D: Couldn't validate OpenGL implementation; is everything needed present?");
         return NS_ERROR_FAILURE;
     }
 
     LogMessage("Canvas 3D: ready");
 
     mWidth = width;
     mHeight = height;
 
@@ -176,111 +180,40 @@ WebGLContext::SetDimensions(PRInt32 widt
 #endif
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::Render(gfxContext *ctx, gfxPattern::GraphicsFilter f)
 {
-    nsresult rv = NS_OK;
-
-    if (mInvalidated) {
-        mGLPbuffer->SwapBuffers();
-        mInvalidated = PR_FALSE;
-    }
-
-    if (!mGLPbuffer)
+    if (!gl)
         return NS_OK;
 
-    // use GL Drawing if we can get a target GL context; otherwise
-    // go through the fallback path.
-#ifdef HAVE_GL_DRAWING
-    if (mCanvasElement->GLWidgetBeginDrawing()) {
-        glClearColor(0.0, 0.0, 0.0, 0.0);
-        glClear(GL_COLOR_BUFFER_BIT);
-
-        int bwidth = mGLPbuffer->Width();
-        int bheight = mGLPbuffer->Height();
-
-        GLuint tex = 0;
-        glGenTextures(1, &tex);
-        glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tex);
+    nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(gfxIntSize(mWidth, mHeight),
+                                                         gfxASurface::ImageFormatARGB32);
+    if (surf->CairoStatus() != 0)
+        return NS_ERROR_FAILURE;
 
-        CGLError err =
-            CGLTexImagePBuffer(CGLGetCurrentContext(),
-                               ((nsGLPbufferCGL*)mGLPbuffer)->GetCGLPbuffer(),
-                               GL_BACK);
-        if (err) {
-            fprintf (stderr, "CGLTexImagePBuffer failed: %d\n", err);
-            glDeleteTextures(1, &tex);
-            return NS_OK;
-        }
-
-        glEnable(GL_TEXTURE_RECTANGLE_EXT);
-
-        glMatrixMode(GL_PROJECTION);
-        glLoadIdentity();
-        //glFrustum(-halfWidth, halfWidth, halfHeight, -halfHeight, 1.0, 100000.0);
-        glOrtho(0, bwidth, bheight, 0, -0.5, 10.0);
-
-        glMatrixMode(GL_MODELVIEW);
-        glLoadIdentity();
-
-        glBegin(GL_QUADS);
-
-        /* Note that the texture needs a y-flip */
-        glTexCoord2f(0.0, bheight);
-        glVertex3f(0.0, 0.0, 0.0);
-
-        glTexCoord2f(bwidth, bheight);
-        glVertex3f(bwidth, 0.0, 0.0);
+    MakeContextCurrent();
+    gl->fReadPixels(0, 0, mWidth, mHeight,
+                    LOCAL_GL_BGRA,
+                    LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV,
+                    surf->Data());
 
-        glTexCoord2f(bwidth, 0);
-        glVertex3f(bwidth, bheight, 0.0);
+    gfxUtils::PremultiplyImageSurface(surf);
 
-        glTexCoord2f(0.0, 0);
-        glVertex3f(0.0, bheight, 0.0);
-
-        glEnd();
-
-        glDisable(GL_TEXTURE_RECTANGLE_EXT);
-        glDeleteTextures(1, &tex);
+    nsRefPtr<gfxPattern> pat = new gfxPattern(surf);
+    pat->SetFilter(f);
 
-        mCanvasElement->GLWidgetSwapBuffers();
-        mCanvasElement->GLWidgetEndDrawing();
-    } else
-#endif
-    {
-        nsRefPtr<gfxASurface> surf = mGLPbuffer->ThebesSurface();
-        if (!surf)
-            return NS_OK;
-        // XXX we can optimize this on win32 at least, by creating an upside-down
-        // DIB.
-        nsRefPtr<gfxPattern> pat = new gfxPattern(surf);
+    ctx->NewPath();
+    ctx->PixelSnappedRectangleAndSetPattern(gfxRect(0, 0, mWidth, mHeight), pat);
+    ctx->Fill();
 
-#if defined(USE_EGL) && defined(MOZ_X11)
-        if (getenv("IMAGE")) {
-#endif
-        gfxMatrix m;
-        m.Translate(gfxPoint(0.0, mGLPbuffer->Height()));
-        m.Scale(1.0, -1.0);
-        pat->SetMatrix(m);
-#if defined(USE_EGL) && defined(MOZ_X11)
-        }
-#endif
-
-        // XXX I don't want to use PixelSnapped here, but layout doesn't guarantee
-        // pixel alignment for this stuff!
-        ctx->NewPath();
-        ctx->PixelSnappedRectangleAndSetPattern(gfxRect(0, 0, mWidth, mHeight), pat);
-        ctx->Fill();
-    }
-
-    return rv;
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::GetInputStream(const char* aMimeType,
                              const PRUnichar* aEncoderOptions,
                              nsIInputStream **aStream)
 {
     return NS_ERROR_FAILURE;
@@ -344,24 +277,59 @@ WebGLContext::GetInputStream(const char*
 
     return CallQueryInterface(encoder, aStream);
 #endif
 }
 
 NS_IMETHODIMP
 WebGLContext::GetThebesSurface(gfxASurface **surface)
 {
-    if (!mGLPbuffer) {
-        *surface = nsnull;
-        return NS_ERROR_NOT_AVAILABLE;
+    return NS_ERROR_NOT_AVAILABLE;
+}
+
+already_AddRefed<layers::CanvasLayer>
+WebGLContext::GetCanvasLayer(LayerManager *manager)
+{
+    nsRefPtr<CanvasLayer> canvasLayer = manager->CreateCanvasLayer();
+    if (!canvasLayer) {
+        NS_WARNING("CreateCanvasLayer returned null!");
+        return nsnull;
     }
 
-    *surface = mGLPbuffer->ThebesSurface();
-    NS_IF_ADDREF(*surface);
-    return NS_OK;
+    CanvasLayer::Data data;
+
+    // the gl context may either provide a native PBuffer, in which case we want to initialize
+    // data with the gl context directly, or may provide a surface to which it renders (this is the case
+    // of OSMesa contexts), in which case we want to initialize data with that surface.
+
+    void* native_pbuffer = gl->GetNativeData(gl::GLContext::NativePBuffer);
+    void* native_surface = gl->GetNativeData(gl::GLContext::NativeImageSurface);
+
+    if (native_pbuffer) {
+        data.mGLContext = gl.get();
+    }
+    else if (native_surface) {
+        data.mSurface = static_cast<gfxASurface*>(native_surface);
+    }
+    else {
+        NS_WARNING("The GLContext has neither a native PBuffer nor a native surface!");
+        return nsnull;
+    }
+
+    data.mSize = nsIntSize(mWidth, mHeight);
+    data.mGLBufferIsPremultiplied = PR_FALSE;
+
+    canvasLayer->Initialize(data);
+    // once we support GL context attributes, we'll set the right thing here
+    canvasLayer->SetIsOpaqueContent(PR_FALSE);
+    canvasLayer->Updated(nsIntRect(0, 0, mWidth, mHeight));
+
+    mInvalidated = PR_FALSE;
+
+    return canvasLayer.forget().get();
 }
 
 //
 // XPCOM goop
 //
 
 NS_IMPL_ADDREF(WebGLContext)
 NS_IMPL_RELEASE(WebGLContext)
@@ -377,71 +345,77 @@ NS_INTERFACE_MAP_BEGIN(WebGLContext)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(WebGLBuffer)
 NS_IMPL_RELEASE(WebGLBuffer)
 
 DOMCI_DATA(WebGLBuffer, WebGLBuffer)
 
 NS_INTERFACE_MAP_BEGIN(WebGLBuffer)
+  NS_INTERFACE_MAP_ENTRY(WebGLBuffer)
   NS_INTERFACE_MAP_ENTRY(nsIWebGLBuffer)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLBuffer)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(WebGLTexture)
 NS_IMPL_RELEASE(WebGLTexture)
 
 DOMCI_DATA(WebGLTexture, WebGLTexture)
 
 NS_INTERFACE_MAP_BEGIN(WebGLTexture)
+  NS_INTERFACE_MAP_ENTRY(WebGLTexture)
   NS_INTERFACE_MAP_ENTRY(nsIWebGLTexture)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLTexture)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(WebGLProgram)
 NS_IMPL_RELEASE(WebGLProgram)
 
 DOMCI_DATA(WebGLProgram, WebGLProgram)
 
 NS_INTERFACE_MAP_BEGIN(WebGLProgram)
+  NS_INTERFACE_MAP_ENTRY(WebGLProgram)
   NS_INTERFACE_MAP_ENTRY(nsIWebGLProgram)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLProgram)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(WebGLShader)
 NS_IMPL_RELEASE(WebGLShader)
 
 DOMCI_DATA(WebGLShader, WebGLShader)
 
 NS_INTERFACE_MAP_BEGIN(WebGLShader)
+  NS_INTERFACE_MAP_ENTRY(WebGLShader)
   NS_INTERFACE_MAP_ENTRY(nsIWebGLShader)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLShader)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(WebGLFramebuffer)
 NS_IMPL_RELEASE(WebGLFramebuffer)
 
 DOMCI_DATA(WebGLFramebuffer, WebGLFramebuffer)
 
 NS_INTERFACE_MAP_BEGIN(WebGLFramebuffer)
+  NS_INTERFACE_MAP_ENTRY(WebGLFramebuffer)
   NS_INTERFACE_MAP_ENTRY(nsIWebGLFramebuffer)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLFramebuffer)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(WebGLRenderbuffer)
 NS_IMPL_RELEASE(WebGLRenderbuffer)
 
 DOMCI_DATA(WebGLRenderbuffer, WebGLRenderbuffer)
 
 NS_INTERFACE_MAP_BEGIN(WebGLRenderbuffer)
+  NS_INTERFACE_MAP_ENTRY(WebGLRenderbuffer)
   NS_INTERFACE_MAP_ENTRY(nsIWebGLRenderbuffer)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLRenderbuffer)
 NS_INTERFACE_MAP_END
 
 /* [noscript] attribute GLuint name; */
 NS_IMETHODIMP WebGLTexture::GetName(GLuint *aName)
 {
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -46,23 +46,23 @@
 #include "nsDataHashtable.h"
 #include "nsRefPtrHashtable.h"
 #include "nsHashKeys.h"
 
 #include "nsIDocShell.h"
 
 #include "nsICanvasRenderingContextWebGL.h"
 #include "nsICanvasRenderingContextInternal.h"
+#include "nsHTMLCanvasElement.h"
 #include "nsWeakReference.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIJSNativeInitializer.h"
 
-#include "nsGLPbuffer.h"
-
-#include "localgl.h"
+#include "GLContext.h"
+#include "Layers.h"
 
 class nsIDocShell;
 
 namespace mozilla {
 
 class WebGLTexture;
 class WebGLBuffer;
 class WebGLProgram;
@@ -228,67 +228,77 @@ class WebGLContext :
 public:
     WebGLContext();
     virtual ~WebGLContext();
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSICANVASRENDERINGCONTEXTWEBGL
 
     // nsICanvasRenderingContextInternal
-    NS_IMETHOD SetCanvasElement(nsICanvasElement* aParentCanvas);
+    NS_IMETHOD SetCanvasElement(nsHTMLCanvasElement* aParentCanvas);
     NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height);
     NS_IMETHOD InitializeWithSurface(nsIDocShell *docShell, gfxASurface *surface, PRInt32 width, PRInt32 height)
         { return NS_ERROR_NOT_IMPLEMENTED; }
     NS_IMETHOD Render(gfxContext *ctx, gfxPattern::GraphicsFilter f);
     NS_IMETHOD GetInputStream(const char* aMimeType,
                               const PRUnichar* aEncoderOptions,
                               nsIInputStream **aStream);
     NS_IMETHOD GetThebesSurface(gfxASurface **surface);
     NS_IMETHOD SetIsOpaque(PRBool b) { return NS_OK; };
     NS_IMETHOD SetIsShmem(PRBool b) { return NS_ERROR_NOT_IMPLEMENTED; }
     NS_IMETHOD Redraw(const gfxRect&) { return NS_ERROR_NOT_IMPLEMENTED; }
     NS_IMETHOD Swap(mozilla::ipc::Shmem& aBack,
                     PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h)
                     { return NS_ERROR_NOT_IMPLEMENTED; }
 
-protected:
-    GLES20Wrap *gl;
+    nsresult SynthesizeGLError(GLenum err);
+    nsresult SynthesizeGLError(GLenum err, const char *fmt, ...);
+
+    nsresult ErrorInvalidEnum(const char *fmt, ...);
+    nsresult ErrorInvalidOperation(const char *fmt, ...);
+    nsresult ErrorInvalidValue(const char *fmt, ...);
 
-    nsICanvasElement* mCanvasElement;
+    already_AddRefed<CanvasLayer> GetCanvasLayer(LayerManager *manager);
+    void MarkContextClean() { }
 
-    nsGLPbuffer *mGLPbuffer;
+protected:
+    nsHTMLCanvasElement* mCanvasElement;
+
+    nsRefPtr<gl::GLContext> gl;
+
     PRInt32 mWidth, mHeight;
 
     PRBool mInvalidated;
 
-    PRBool SafeToCreateCanvas3DContext(nsICanvasElement *canvasElement);
+    GLuint mActiveTexture;
+    GLenum mSynthesizedGLError;
+
+    PRBool SafeToCreateCanvas3DContext(nsHTMLCanvasElement *canvasElement);
     PRBool ValidateGL();
     PRBool ValidateBuffers(PRUint32 count);
 
     void Invalidate();
 
-    void MakeContextCurrent() { mGLPbuffer->MakeContextCurrent(); }
+    void MakeContextCurrent() { gl->MakeCurrent(); }
 
     // helpers
     nsresult TexImage2D_base(GLenum target, GLint level, GLenum internalformat,
                              GLsizei width, GLsizei height, GLint border,
                              GLenum format, GLenum type,
                              void *data, PRUint32 byteLength);
     nsresult TexSubImage2D_base(GLenum target, GLint level,
                                 GLint xoffset, GLint yoffset,
                                 GLsizei width, GLsizei height,
                                 GLenum format, GLenum type,
                                 void *pixels, PRUint32 byteLength);
 
     nsresult DOMElementToImageSurface(nsIDOMElement *imageOrCanvas,
                                       gfxImageSurface **imageOut,
                                       PRBool flipY, PRBool premultiplyAlpha);
 
-    GLuint mActiveTexture;
-
     // the buffers bound to the current program's attribs
     nsTArray<WebGLVertexAttribData> mAttribBuffers;
 
     // the textures bound to any sampler uniforms
     nsTArray<WebGLObjectRefPtr<WebGLTexture> > mUniformTextures;
 
     // textures bound to 
     nsTArray<WebGLObjectRefPtr<WebGLTexture> > mBound2DTextures;
@@ -309,19 +319,20 @@ protected:
     // lookup tables for GL name -> object wrapper
     nsRefPtrHashtable<nsUint32HashKey, WebGLTexture> mMapTextures;
     nsRefPtrHashtable<nsUint32HashKey, WebGLBuffer> mMapBuffers;
     nsRefPtrHashtable<nsUint32HashKey, WebGLProgram> mMapPrograms;
     nsRefPtrHashtable<nsUint32HashKey, WebGLShader> mMapShaders;
     nsRefPtrHashtable<nsUint32HashKey, WebGLFramebuffer> mMapFramebuffers;
     nsRefPtrHashtable<nsUint32HashKey, WebGLRenderbuffer> mMapRenderbuffers;
 
+public:
     // console logging helpers
-    void LogMessage (const char *fmt, ...);
-    nsresult ErrorMessage (const char *fmt, ...);
+    static void LogMessage (const char *fmt, ...);
+    static void LogMessage(const char *fmt, va_list ap);
 };
 
 // this class is a mixin for the named type wrappers, and is used
 // by WebGLObjectRefPtr to tell the object who holds references, so that
 // we can zero them out appropriately when the object is deleted, because
 // it will be unbound in the GL.
 class WebGLZeroingObject
 {
@@ -346,21 +357,58 @@ public:
 
         mRefOwners.Clear();
     }
 
 protected:
     nsTArray<WebGLObjectBaseRefPtr *> mRefOwners;
 };
 
+class WebGLRectangleObject
+{
+protected:
+    WebGLRectangleObject()
+        : mWidth(0), mHeight(0) { }
+
+public:
+    GLsizei width() { return mWidth; }
+    void width(GLsizei value) { mWidth = value; }
+
+    GLsizei height() { return mHeight; }
+    void height(GLsizei value) { mHeight = value; }
+
+    void setDimensions(GLsizei width, GLsizei height) {
+        mWidth = width;
+        mHeight = height;
+    }
+
+    void setDimensions(WebGLRectangleObject *rect) {
+        if (rect) {
+            mWidth = rect->width();
+            mHeight = rect->height();
+        } else {
+            mWidth = 0;
+            mHeight = 0;
+        }
+    }
+
+protected:
+    GLsizei mWidth;
+    GLsizei mHeight;
+};
+
+#define WEBGLBUFFER_PRIVATE_IID \
+    {0xd69f22e9, 0x6f98, 0x48bd, {0xb6, 0x94, 0x34, 0x17, 0xed, 0x06, 0x11, 0xab}}
 class WebGLBuffer :
     public nsIWebGLBuffer,
     public WebGLZeroingObject
 {
 public:
+    NS_DECLARE_STATIC_IID_ACCESSOR(WEBGLBUFFER_PRIVATE_IID)
+
     WebGLBuffer(GLuint name)
         : mName(name), mDeleted(PR_FALSE), mByteLength(0)
     { }
 
     void Delete() {
         if (mDeleted)
             return;
         ZeroOwners();
@@ -380,21 +428,28 @@ public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIWEBGLBUFFER
 protected:
     GLuint mName;
     PRBool mDeleted;
     PRUint32 mByteLength;
 };
 
+NS_DEFINE_STATIC_IID_ACCESSOR(WebGLBuffer, WEBGLBUFFER_PRIVATE_IID)
+
+#define WEBGLTEXTURE_PRIVATE_IID \
+    {0x4c19f189, 0x1f86, 0x4e61, {0x96, 0x21, 0x0a, 0x11, 0xda, 0x28, 0x10, 0xdd}}
 class WebGLTexture :
     public nsIWebGLTexture,
-    public WebGLZeroingObject
+    public WebGLZeroingObject,
+    public WebGLRectangleObject
 {
 public:
+    NS_DECLARE_STATIC_IID_ACCESSOR(WEBGLTEXTURE_PRIVATE_IID)
+
     WebGLTexture(GLuint name) :
         mName(name), mDeleted(PR_FALSE) { }
 
     void Delete() {
         if (mDeleted)
             return;
         ZeroOwners();
         mDeleted = PR_TRUE;
@@ -405,21 +460,27 @@ public:
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIWEBGLTEXTURE
 protected:
     GLuint mName;
     PRBool mDeleted;
 };
 
+NS_DEFINE_STATIC_IID_ACCESSOR(WebGLTexture, WEBGLTEXTURE_PRIVATE_IID)
+
+#define WEBGLPROGRAM_PRIVATE_IID \
+    {0xb3084a5b, 0xa5b4, 0x4ee0, {0xa0, 0xf0, 0xfb, 0xdd, 0x64, 0xaf, 0x8e, 0x82}}
 class WebGLProgram :
     public nsIWebGLProgram,
     public WebGLZeroingObject
 {
 public:
+    NS_DECLARE_STATIC_IID_ACCESSOR(WEBGLPROGRAM_PRIVATE_IID)
+
     WebGLProgram(GLuint name) :
         mName(name), mDeleted(PR_FALSE) { }
 
     void Delete() {
         if (mDeleted)
             return;
         ZeroOwners();
         mDeleted = PR_TRUE;
@@ -429,21 +490,27 @@ public:
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIWEBGLPROGRAM
 protected:
     GLuint mName;
     PRBool mDeleted;
 };
 
+NS_DEFINE_STATIC_IID_ACCESSOR(WebGLProgram, WEBGLPROGRAM_PRIVATE_IID)
+
+#define WEBGLSHADER_PRIVATE_IID \
+    {0x48cce975, 0xd459, 0x4689, {0x83, 0x82, 0x37, 0x82, 0x6e, 0xac, 0xe0, 0xa7}}
 class WebGLShader :
     public nsIWebGLShader,
     public WebGLZeroingObject
 {
 public:
+    NS_DECLARE_STATIC_IID_ACCESSOR(WEBGLSHADER_PRIVATE_IID)
+
     WebGLShader(GLuint name) :
         mName(name), mDeleted(PR_FALSE) { }
 
     void Delete() {
         if (mDeleted)
             return;
         ZeroOwners();
         mDeleted = PR_TRUE;
@@ -453,21 +520,28 @@ public:
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIWEBGLSHADER
 protected:
     GLuint mName;
     PRBool mDeleted;
 };
 
+NS_DEFINE_STATIC_IID_ACCESSOR(WebGLShader, WEBGLSHADER_PRIVATE_IID)
+
+#define WEBGLFRAMEBUFFER_PRIVATE_IID \
+    {0x0052a16f, 0x4bc9, 0x4a55, {0x9d, 0xa3, 0x54, 0x95, 0xaa, 0x4e, 0x80, 0xb9}}
 class WebGLFramebuffer :
     public nsIWebGLFramebuffer,
-    public WebGLZeroingObject
+    public WebGLZeroingObject,
+    public WebGLRectangleObject
 {
 public:
+    NS_DECLARE_STATIC_IID_ACCESSOR(WEBGLFRAMEBUFFER_PRIVATE_IID)
+
     WebGLFramebuffer(GLuint name) :
         mName(name), mDeleted(PR_FALSE) { }
 
     void Delete() {
         if (mDeleted)
             return;
         ZeroOwners();
         mDeleted = PR_TRUE;
@@ -477,21 +551,28 @@ public:
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIWEBGLFRAMEBUFFER
 protected:
     GLuint mName;
     PRBool mDeleted;
 };
 
+NS_DEFINE_STATIC_IID_ACCESSOR(WebGLFramebuffer, WEBGLFRAMEBUFFER_PRIVATE_IID)
+
+#define WEBGLRENDERBUFFER_PRIVATE_IID \
+    {0x3cbc2067, 0x5831, 0x4e3f, {0xac, 0x52, 0x7e, 0xf4, 0x5c, 0x04, 0xff, 0xae}}
 class WebGLRenderbuffer :
     public nsIWebGLRenderbuffer,
-    public WebGLZeroingObject
+    public WebGLZeroingObject,
+    public WebGLRectangleObject
 {
 public:
+    NS_DECLARE_STATIC_IID_ACCESSOR(WEBGLRENDERBUFFER_PRIVATE_IID)
+
     WebGLRenderbuffer(GLuint name) :
         mName(name), mDeleted(PR_FALSE) { }
 
     void Delete() {
         if (mDeleted)
             return;
         ZeroOwners();
         mDeleted = PR_TRUE;
@@ -501,11 +582,13 @@ public:
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIWEBGLRENDERBUFFER
 protected:
     GLuint mName;
     PRBool mDeleted;
 };
 
+NS_DEFINE_STATIC_IID_ACCESSOR(WebGLRenderbuffer, WEBGLRENDERBUFFER_PRIVATE_IID)
+
 }
 
 #endif
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -17,16 +17,17 @@
  * 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):
  *   Vladimir Vukicevic <vladimir@pobox.com> (original author)
  *   Mark Steele <mwsteele@gmail.com>
+ *   Cedric Vivier <cedricv@neonux.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
@@ -99,16 +100,120 @@ NS_IMETHODIMP WebGLContext::name(t1 a1, 
     MakeContextCurrent(); gl->f##glname(a1,a2,a3,a4,a5); return NS_OK;  \
 }
 
 #define GL_SAME_METHOD_6(glname, name, t1, t2, t3, t4, t5, t6)          \
 NS_IMETHODIMP WebGLContext::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) { \
     MakeContextCurrent(); gl->f##glname(a1,a2,a3,a4,a5,a6); return NS_OK; \
 }
 
+/* Helper function taking a BaseInterfaceType pointer and check that it matches the required concrete
+ * implementation type (if it's non-null), that it's not null/deleted unless we allowed it to,
+ * and obtain a pointer to the concrete object.
+ *
+ * By default, null (respectively: deleted) aInterface pointers are not allowed, but if you pass a
+ * non-null isNull (respectively: isDeleted) pointer, then they become allowed and the value at
+ * isNull (respecively isDeleted) is overwritten. In case of a null pointer, the resulting 
+ */
+
+template<class ConcreteObjectType, class BaseInterfaceType>
+static PRBool
+GetConcreteObject(BaseInterfaceType *aInterface,
+                  ConcreteObjectType **aConcreteObject,
+                  PRBool *isNull = 0,
+                  PRBool *isDeleted = 0)
+{
+    if (!aInterface) {
+        if (NS_LIKELY(isNull)) {
+            // non-null isNull means that the caller will accept a null arg
+            *isNull = PR_TRUE;
+            if(isDeleted) *isDeleted = PR_FALSE;
+            *aConcreteObject = 0;
+            return PR_TRUE;
+        } else {
+            WebGLContext::LogMessage("Null object passed to WebGL function");
+            return PR_FALSE;
+        }
+    }
+
+    if (isNull) {
+        *isNull = PR_FALSE;
+    }
+
+    nsresult rv;
+    nsCOMPtr<ConcreteObjectType> tmp(do_QueryInterface(aInterface, &rv));
+    if (NS_FAILED(rv)) {
+        return PR_FALSE;
+    }
+
+    *aConcreteObject = tmp;
+
+    if ((*aConcreteObject)->Deleted()) {
+        if (NS_LIKELY(isDeleted)) {
+            // non-null isDeleted means that the caller will accept a deleted arg
+            *isDeleted = PR_TRUE;
+            return PR_TRUE;
+        } else {
+            WebGLContext::LogMessage("Deleted object passed to WebGL function");
+            return PR_FALSE;
+        }
+    }
+
+    if (isDeleted)
+      *isDeleted = PR_FALSE;
+
+    return PR_TRUE;
+}
+
+/* Same as GetConcreteObject, and in addition gets the GL object name.
+ * Null objects give the name 0.
+ */
+template<class ConcreteObjectType, class BaseInterfaceType>
+static 
+PRBool
+GetConcreteObjectAndGLName(BaseInterfaceType *aInterface,
+                           ConcreteObjectType **aConcreteObject,
+                           GLuint *aGLObjectName,
+                           PRBool *isNull = 0,
+                           PRBool *isDeleted = 0)
+{
+    PRBool result = GetConcreteObject(aInterface, aConcreteObject, isNull, isDeleted);
+    if(result == PR_FALSE) return PR_FALSE;
+    *aGLObjectName = *aConcreteObject ? (*aConcreteObject)->GLName() : 0;
+    return PR_TRUE;
+}
+
+/* Same as GetConcreteObjectAndGLName when you don't need the concrete object pointer.
+ */
+template<class ConcreteObjectType, class BaseInterfaceType>
+static
+PRBool
+GetGLName(BaseInterfaceType *aInterface,
+          GLuint *aGLObjectName,
+          PRBool *isNull = 0,
+          PRBool *isDeleted = 0)
+{
+    ConcreteObjectType *aConcreteObject;
+    return GetConcreteObjectAndGLName(aInterface, &aConcreteObject, aGLObjectName, isNull, isDeleted);
+}
+
+/* Same as GetConcreteObject when you only want to check if the conversion succeeds.
+ */
+template<class ConcreteObjectType, class BaseInterfaceType>
+static
+PRBool
+CheckConversion(BaseInterfaceType *aInterface,
+                PRBool *isNull = 0,
+                PRBool *isDeleted = 0)
+{
+  ConcreteObjectType *aConcreteObject;
+  return GetConcreteObject(aInterface, &aConcreteObject, isNull, isDeleted);
+}
+
+
 //
 //  WebGL API
 //
 
 /* readonly attribute nsIDOMHTMLCanvasElement canvas; */
 NS_IMETHODIMP
 WebGLContext::GetCanvas(nsIDOMHTMLCanvasElement **aCanvas)
 {
@@ -138,145 +243,148 @@ WebGLContext::SizeInBytes(GLenum type, P
     return NS_OK;
 }
 
 /* void GlActiveTexture (in PRUint32 texture); */
 NS_IMETHODIMP
 WebGLContext::ActiveTexture(PRUint32 texture)
 {
     if (texture < LOCAL_GL_TEXTURE0 || texture >= LOCAL_GL_TEXTURE0+mBound2DTextures.Length())
-        return NS_ERROR_DOM_SYNTAX_ERR;
+        return ErrorInvalidEnum("ActiveTexture: texture unit %d out of range (0..%d)",
+                                texture, mBound2DTextures.Length()-1);
 
     MakeContextCurrent();
     mActiveTexture = texture - LOCAL_GL_TEXTURE0;
     gl->fActiveTexture(texture);
     return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::AttachShader(nsIWebGLProgram *prog, nsIWebGLShader *sh)
+WebGLContext::AttachShader(nsIWebGLProgram *pobj, nsIWebGLShader *shobj)
 {
-    if (!prog || static_cast<WebGLProgram*>(prog)->Deleted())
-        return ErrorMessage("%s: program is null or deleted!", __FUNCTION__);
-
-    if (!sh || static_cast<WebGLShader*>(sh)->Deleted())
-        return ErrorMessage("%s: shader is null or deleted!", __FUNCTION__);
-
-    GLuint program = static_cast<WebGLProgram*>(prog)->GLName();
-    GLuint shader = static_cast<WebGLShader*>(sh)->GLName();
+    GLuint progname, shadername;
+    if (!GetGLName<WebGLProgram>(pobj, &progname))
+        return ErrorInvalidOperation("AttachShader: invalid program");
+
+    if (!GetGLName<WebGLShader>(shobj, &shadername))
+        return ErrorInvalidOperation("AttachShader: invalid shader");
 
     MakeContextCurrent();
 
-    gl->fAttachShader(program, shader);
+    gl->fAttachShader(progname, shadername);
 
     return NS_OK;
 }
 
 
 NS_IMETHODIMP
-WebGLContext::BindAttribLocation(nsIWebGLProgram *prog, GLuint location, const nsAString& name)
+WebGLContext::BindAttribLocation(nsIWebGLProgram *pobj, GLuint location, const nsAString& name)
 {
-    if (!prog || static_cast<WebGLProgram*>(prog)->Deleted())
-        return ErrorMessage("%s: program is null or deleted!", __FUNCTION__);
+    GLuint progname;
+    if (!GetGLName<WebGLProgram>(pobj, &progname))
+        return ErrorInvalidOperation("BindAttribLocation: invalid program");
 
     if (name.IsEmpty())
-        return ErrorMessage("glBindAttribLocation: name can't be null or empty!");
-
-    GLuint program = static_cast<WebGLProgram*>(prog)->GLName();
+        return ErrorInvalidValue("BindAttribLocation: name can't be null or empty");
 
     MakeContextCurrent();
 
-    gl->fBindAttribLocation(program, location, NS_LossyConvertUTF16toASCII(name).get());
+    gl->fBindAttribLocation(progname, location, NS_LossyConvertUTF16toASCII(name).get());
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::BindBuffer(GLenum target, nsIWebGLBuffer *buffer)
+WebGLContext::BindBuffer(GLenum target, nsIWebGLBuffer *bobj)
 {
-    WebGLBuffer *wbuf = static_cast<WebGLBuffer*>(buffer);
-
-    if (wbuf && wbuf->Deleted())
-        return ErrorMessage("glBindBuffer: buffer has already been deleted!");
+    GLuint bufname;
+    WebGLBuffer* buf;
+    PRBool isNull;
+    if (!GetConcreteObjectAndGLName(bobj, &buf, &bufname, &isNull))
+        return ErrorInvalidOperation("BindBuffer: invalid buffer");
+
+    if (target == LOCAL_GL_ARRAY_BUFFER) {
+        mBoundArrayBuffer = buf;
+    } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
+        mBoundElementArrayBuffer = buf;
+    } else {
+        return ErrorInvalidEnum("BindBuffer: invalid target");
+    }
 
     MakeContextCurrent();
 
-    //printf ("BindBuffer0: %04x\n", gl->fGetError());
-
-    if (target == LOCAL_GL_ARRAY_BUFFER) {
-        mBoundArrayBuffer = wbuf;
-    } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
-        mBoundElementArrayBuffer = wbuf;
-    } else {
-        return ErrorMessage("glBindBuffer: invalid target!");
-    }
-
-    gl->fBindBuffer(target, wbuf ? wbuf->GLName() : 0);
-
-    //printf ("BindBuffer: %04x\n", gl->fGetError());
+    gl->fBindBuffer(target, bufname);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::BindFramebuffer(GLenum target, nsIWebGLFramebuffer *fb)
+WebGLContext::BindFramebuffer(GLenum target, nsIWebGLFramebuffer *fbobj)
 {
-    WebGLFramebuffer *wfb = static_cast<WebGLFramebuffer*>(fb);
-
-    if (wfb && wfb->Deleted())
-        return ErrorMessage("glBindFramebuffer: framebuffer has already been deleted!");
+    GLuint framebuffername;
+    PRBool isNull;
+    WebGLFramebuffer *wfb;
+
+    if (target != LOCAL_GL_FRAMEBUFFER)
+        return ErrorInvalidOperation("BindFramebuffer: target must be GL_FRAMEBUFFER");
+
+    if (!GetConcreteObjectAndGLName(fbobj, &wfb, &framebuffername, &isNull))
+        return ErrorInvalidOperation("BindFramebuffer: invalid framebuffer");
 
     MakeContextCurrent();
 
-    if (target != LOCAL_GL_FRAMEBUFFER) {
-        return ErrorMessage("glBindFramebuffer: target must be GL_FRAMEBUFFER");
-    }
-
-    gl->fBindFramebuffer(target, wfb ? wfb->GLName() : 0);
+    gl->fBindFramebuffer(target, framebuffername);
+
+    mBoundFramebuffer = wfb;
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::BindRenderbuffer(GLenum target, nsIWebGLRenderbuffer *rb)
+WebGLContext::BindRenderbuffer(GLenum target, nsIWebGLRenderbuffer *rbobj)
 {
-    WebGLRenderbuffer *wrb = static_cast<WebGLRenderbuffer*>(rb);
-
-    if (wrb && wrb->Deleted())
-        return ErrorMessage("glBindRenderbuffer: renderbuffer has already been deleted!");
+    GLuint renderbuffername;
+    PRBool isNull;
+    WebGLRenderbuffer *wrb;
 
     if (target != LOCAL_GL_RENDERBUFFER)
-        return ErrorMessage("glBindRenderbuffer: target must be GL_RENDERBUFFER");
+        return ErrorInvalidEnum("BindRenderbuffer: target must be GL_RENDERBUFFER");
+
+    if (!GetConcreteObjectAndGLName(rbobj, &wrb, &renderbuffername, &isNull))
+        return ErrorInvalidOperation("BindRenderbuffer: invalid renderbuffer");
 
     MakeContextCurrent();
 
-    gl->fBindRenderbuffer(target, wrb ? wrb->GLName() : 0);
+    gl->fBindRenderbuffer(target, renderbuffername);
+
+    mBoundRenderbuffer = wrb;
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::BindTexture(GLenum target, nsIWebGLTexture *tex)
+WebGLContext::BindTexture(GLenum target, nsIWebGLTexture *tobj)
 {
-    WebGLTexture *wtex = static_cast<WebGLTexture*>(tex);
-
-    if (wtex && wtex->Deleted())
-        return ErrorMessage("glBindTexture: texture has already been deleted!");
+    GLuint texturename;
+    WebGLTexture *tex;
+    PRBool isNull;
+    if (!GetConcreteObjectAndGLName(tobj, &tex, &texturename, &isNull))
+        return ErrorInvalidOperation("BindTexture: invalid texture");
+
+    if (target == LOCAL_GL_TEXTURE_2D) {
+        mBound2DTextures[mActiveTexture] = tex;
+    } else if (target == LOCAL_GL_TEXTURE_CUBE_MAP) {
+        mBoundCubeMapTextures[mActiveTexture] = tex;
+    } else {
+        return ErrorInvalidEnum("BindTexture: invalid target");
+    }
 
     MakeContextCurrent();
 
-    if (target == LOCAL_GL_TEXTURE_2D) {
-        mBound2DTextures[mActiveTexture] = wtex;
-    } else if (target == LOCAL_GL_TEXTURE_CUBE_MAP) {
-        mBoundCubeMapTextures[mActiveTexture] = wtex;
-    } else {
-        return ErrorMessage("glBindTexture: invalid target");
-    }
-
-    gl->fBindTexture(target, wtex ? wtex->GLName() : 0);
+    gl->fBindTexture(target, texturename);
 
     return NS_OK;
 }
 
 GL_SAME_METHOD_4(BlendColor, BlendColor, float, float, float, float)
 
 GL_SAME_METHOD_1(BlendEquation, BlendEquation, PRUint32)
 
@@ -299,21 +407,21 @@ WebGLContext::BufferData_size(GLenum tar
 {
     WebGLBuffer *boundBuffer = NULL;
 
     if (target == LOCAL_GL_ARRAY_BUFFER) {
         boundBuffer = mBoundArrayBuffer;
     } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
         boundBuffer = mBoundElementArrayBuffer;
     } else {
-        return ErrorMessage("BufferData: invalid target");
+        return ErrorInvalidEnum("BufferData: invalid target");
     }
 
-    if (boundBuffer == nsnull)
-        return ErrorMessage("BufferData: no buffer bound!");
+    if (!boundBuffer)
+        return ErrorInvalidOperation("BufferData: no buffer bound!");
 
     MakeContextCurrent();
 
     // XXX what happens if BufferData fails? We probably shouldn't
     // update our size here then, right?
     boundBuffer->SetByteLength(size);
     gl->fBufferData(target, size, 0, usage);
 
@@ -325,21 +433,21 @@ WebGLContext::BufferData_buf(GLenum targ
 {
     WebGLBuffer *boundBuffer = NULL;
 
     if (target == LOCAL_GL_ARRAY_BUFFER) {
         boundBuffer = mBoundArrayBuffer;
     } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
         boundBuffer = mBoundElementArrayBuffer;
     } else {
-        return ErrorMessage("BufferData: invalid target");
+        return ErrorInvalidEnum("BufferData: invalid target");
     }
 
-    if (boundBuffer == nsnull)
-        return ErrorMessage("BufferData: no buffer bound!");
+    if (!boundBuffer)
+        return ErrorInvalidOperation("BufferData: no buffer bound!");
 
     MakeContextCurrent();
 
     boundBuffer->SetByteLength(wb->byteLength);
     gl->fBufferData(target, wb->byteLength, wb->data, usage);
 
     return NS_OK;
 }
@@ -349,21 +457,21 @@ WebGLContext::BufferData_array(GLenum ta
 {
     WebGLBuffer *boundBuffer = NULL;
 
     if (target == LOCAL_GL_ARRAY_BUFFER) {
         boundBuffer = mBoundArrayBuffer;
     } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
         boundBuffer = mBoundElementArrayBuffer;
     } else {
-        return ErrorMessage("BufferData: invalid target");
+        return ErrorInvalidEnum("BufferData: invalid target");
     }
 
-    if (boundBuffer == nsnull)
-        return ErrorMessage("BufferData: no buffer bound!");
+    if (!boundBuffer)
+        return ErrorInvalidOperation("BufferData: no buffer bound!");
 
     MakeContextCurrent();
 
     boundBuffer->SetByteLength(wa->byteLength);
     gl->fBufferData(target, wa->byteLength, wa->data, usage);
 
     return NS_OK;
 }
@@ -379,25 +487,26 @@ WebGLContext::BufferSubData_buf(GLenum t
 {
     WebGLBuffer *boundBuffer = NULL;
 
     if (target == LOCAL_GL_ARRAY_BUFFER) {
         boundBuffer = mBoundArrayBuffer;
     } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
         boundBuffer = mBoundElementArrayBuffer;
     } else {
-        return ErrorMessage("BufferSubData: invalid target");
+        return ErrorInvalidEnum("BufferSubData: invalid target");
     }
 
-    if (boundBuffer == nsnull)
-        return ErrorMessage("BufferSubData: no buffer bound!");
+    if (!boundBuffer)
+        return ErrorInvalidOperation("BufferData: no buffer bound!");
 
     // XXX check for overflow
     if (offset + wb->byteLength > boundBuffer->ByteLength())
-        return ErrorMessage("BufferSubData: data too big! Operation requires %d bytes, but buffer only has %d bytes.", offset, wb->byteLength, boundBuffer->ByteLength());
+        return ErrorInvalidOperation("BufferSubData: not enough data - operation requires %d bytes, but buffer only has %d bytes",
+                                     offset, wb->byteLength, boundBuffer->ByteLength());
 
     MakeContextCurrent();
 
     gl->fBufferSubData(target, offset, wb->byteLength, wb->data);
 
     return NS_OK;
 }
 
@@ -406,25 +515,26 @@ WebGLContext::BufferSubData_array(GLenum
 {
     WebGLBuffer *boundBuffer = NULL;
 
     if (target == LOCAL_GL_ARRAY_BUFFER) {
         boundBuffer = mBoundArrayBuffer;
     } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
         boundBuffer = mBoundElementArrayBuffer;
     } else {
-        return ErrorMessage("BufferSubData: invalid target");
+        return ErrorInvalidEnum("BufferSubData: invalid target");
     }
 
-    if (boundBuffer == nsnull)
-        return ErrorMessage("BufferSubData: no buffer bound!");
+    if (!boundBuffer)
+        return ErrorInvalidOperation("BufferData: no buffer bound!");
 
     // XXX check for overflow
     if (offset + wa->byteLength > boundBuffer->ByteLength())
-        return ErrorMessage("BufferSubData: data too big! Operation requires %d bytes, but buffer only has %d bytes.", offset, wa->byteLength, boundBuffer->ByteLength());
+        return ErrorInvalidOperation("BufferSubData: not enough data -- operation requires %d bytes, but buffer only has %d bytes",
+                                     offset, wa->byteLength, boundBuffer->ByteLength());
 
     MakeContextCurrent();
 
     gl->fBufferSubData(target, offset, wa->byteLength, wa->data);
 
     return NS_OK;
 }
 
@@ -474,37 +584,36 @@ WebGLContext::CopyTexImage2D(GLenum targ
         case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
         case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
         case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
         case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
         case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
         case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
             break;
         default:
-            return ErrorMessage("copyTexImage2D: unsupported target");
+            return ErrorInvalidEnum("CopyTexImage2D: unsupported target");
     }
 
     switch (internalformat) {
         case LOCAL_GL_RGB:
         case LOCAL_GL_RGBA:
         case LOCAL_GL_ALPHA:
         case LOCAL_GL_LUMINANCE:
         case LOCAL_GL_LUMINANCE_ALPHA:
             break;
         default:
-            return ErrorMessage("copyTexImage2D: internal format not supported");
+            return ErrorInvalidEnum("CopyTexImage2D: internal format not supported");
     }
 
     if (border != 0) {
-        return ErrorMessage("copyTexImage2D: border != 0");
+        return ErrorInvalidValue("CopyTexImage2D: border != 0");
     }
 
-    if (!CanvasUtils::CheckSaneSubrectSize(x,y,width, height, mWidth, mHeight)) {
-        return ErrorMessage("copyTexImage2D: copied rectangle out of bounds");
-    }
+    if (!CanvasUtils::CheckSaneSubrectSize(x,y,width, height, mWidth, mHeight))
+        return ErrorInvalidOperation("CopyTexImage2D: copied rectangle out of bounds");
 
     MakeContextCurrent();
 
     gl->fCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
 
     return NS_OK;
 }
 
@@ -523,22 +632,21 @@ WebGLContext::CopyTexSubImage2D(GLenum t
         case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
         case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
         case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
         case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
         case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
         case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
             break;
         default:
-            return ErrorMessage("copyTexSubImage2D: unsupported target");
+            return ErrorInvalidEnum("CopyTexSubImage2D: unsupported target");
     }
 
-    if (!CanvasUtils::CheckSaneSubrectSize(x,y,width, height, mWidth, mHeight)) {
-        return ErrorMessage("copyTexSubImage2D: copied rectangle out of bounds");
-    }
+    if (!CanvasUtils::CheckSaneSubrectSize(x,y,width, height, mWidth, mHeight))
+        return ErrorInvalidOperation("CopyTexSubImage2D: copied rectangle out of bounds");
 
     MakeContextCurrent();
 
     gl->fCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
 
     return NS_OK;
 }
 
@@ -577,146 +685,162 @@ WebGLContext::CreateShader(GLenum type, 
     }
 
     return NS_OK;
 }
 
 GL_SAME_METHOD_1(CullFace, CullFace, GLenum)
 
 NS_IMETHODIMP
-WebGLContext::DeleteBuffer(nsIWebGLBuffer *globj)
+WebGLContext::DeleteBuffer(nsIWebGLBuffer *bobj)
 {
-    WebGLBuffer *obj = static_cast<WebGLBuffer*>(globj);
-    if (!obj || obj->Deleted()) {
+    GLuint bufname;
+    WebGLBuffer *buf;
+    PRBool isNull, isDeleted;
+    if (!GetConcreteObjectAndGLName(bobj, &buf, &bufname, &isNull, &isDeleted))
+        return ErrorInvalidOperation("DeleteBuffer: invalid buffer");
+
+    if (isNull || isDeleted)
         return NS_OK;
-    }
 
     MakeContextCurrent();
 
-    GLuint name = obj->GLName();
-    gl->fDeleteBuffers(1, &name);
-    obj->Delete();
-    mMapBuffers.Remove(name);
+    gl->fDeleteBuffers(1, &bufname);
+    buf->Delete();
+    mMapBuffers.Remove(bufname);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::DeleteFramebuffer(nsIWebGLFramebuffer *globj)
+WebGLContext::DeleteFramebuffer(nsIWebGLFramebuffer *fbobj)
 {
-    WebGLFramebuffer *obj = static_cast<WebGLFramebuffer*>(globj);
-    if (!obj || obj->Deleted()) {
+    GLuint fbufname;
+    WebGLFramebuffer *fbuf;
+    PRBool isNull, isDeleted;
+    if (!GetConcreteObjectAndGLName(fbobj, &fbuf, &fbufname, &isNull, &isDeleted))
+        return ErrorInvalidOperation("DeleteFramebuffer: invalid framebuffer");
+
+    if (isNull || isDeleted)
         return NS_OK;
-    }
 
     MakeContextCurrent();
 
-    GLuint name = obj->GLName();
-    gl->fDeleteFramebuffers(1, &name);
-    obj->Delete();
-    mMapFramebuffers.Remove(name);
+    gl->fDeleteFramebuffers(1, &fbufname);
+    fbuf->Delete();
+    mMapFramebuffers.Remove(fbufname);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::DeleteRenderbuffer(nsIWebGLRenderbuffer *globj)
+WebGLContext::DeleteRenderbuffer(nsIWebGLRenderbuffer *rbobj)
 {
-    WebGLRenderbuffer *obj = static_cast<WebGLRenderbuffer*>(globj);
-    if (!obj || obj->Deleted()) {
+    GLuint rbufname;
+    WebGLRenderbuffer *rbuf;
+    PRBool isNull, isDeleted;
+    if (!GetConcreteObjectAndGLName(rbobj, &rbuf, &rbufname, &isNull, &isDeleted))
+        return ErrorInvalidOperation("DeleteRenderbuffer: invalid renderbuffer");
+
+    if (isNull || isDeleted)
         return NS_OK;
-    }
 
     MakeContextCurrent();
 
     // XXX we need to track renderbuffer attachments; from glDeleteRenderbuffers man page:
 
     /*
             If a renderbuffer object that is currently bound is deleted, the binding reverts
             to 0 (the absence of any renderbuffer object). Additionally, special care
             must be taken when deleting a renderbuffer object if the image of the renderbuffer
             is attached to a framebuffer object. In this case, if the deleted renderbuffer object is
             attached to the currently bound framebuffer object, it is 
             automatically detached.  However, attachments to any other framebuffer objects are the
             responsibility of the application.
-    */  
-
-    GLuint name = obj->GLName();
-    gl->fDeleteRenderbuffers(1, &name);
-    obj->Delete();
-    mMapRenderbuffers.Remove(name);
+    */
+
+    gl->fDeleteRenderbuffers(1, &rbufname);
+    rbuf->Delete();
+    mMapRenderbuffers.Remove(rbufname);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::DeleteTexture(nsIWebGLTexture *globj)
+WebGLContext::DeleteTexture(nsIWebGLTexture *tobj)
 {
-    WebGLTexture *obj = static_cast<WebGLTexture*>(globj);
-    if (!obj || obj->Deleted()) {
+    GLuint texname;
+    WebGLTexture *tex;
+    PRBool isNull, isDeleted;
+    if (!GetConcreteObjectAndGLName(tobj, &tex, &texname, &isNull, &isDeleted))
+        return ErrorInvalidOperation("DeleteTexture: invalid texture");
+
+    if (isNull || isDeleted)
         return NS_OK;
-    }
 
     MakeContextCurrent();
 
-    GLuint name = obj->GLName();
-    gl->fDeleteTextures(1, &name);
-    obj->Delete();
-    mMapTextures.Remove(name);
+    gl->fDeleteTextures(1, &texname);
+    tex->Delete();
+    mMapTextures.Remove(texname);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::DeleteProgram(nsIWebGLProgram *globj)
+WebGLContext::DeleteProgram(nsIWebGLProgram *pobj)
 {
-    WebGLProgram *obj = static_cast<WebGLProgram*>(globj);
-    if (!obj || obj->Deleted()) {
+    GLuint progname;
+    WebGLProgram *prog;
+    PRBool isNull, isDeleted;
+    if (!GetConcreteObjectAndGLName(pobj, &prog, &progname, &isNull, &isDeleted))
+        return ErrorInvalidOperation("DeleteProgram: invalid program");
+
+    if (isNull || isDeleted)
         return NS_OK;
-    }
 
     MakeContextCurrent();
 
-    GLuint name = obj->GLName();
-    gl->fDeleteProgram(name);
-    obj->Delete();
-    mMapPrograms.Remove(name);
+    gl->fDeleteProgram(progname);
+    prog->Delete();
+    mMapPrograms.Remove(progname);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::DeleteShader(nsIWebGLShader *globj)
+WebGLContext::DeleteShader(nsIWebGLShader *sobj)
 {
-    WebGLShader *obj = static_cast<WebGLShader*>(globj);
-    if (!obj || obj->Deleted()) {
+    GLuint shadername;
+    WebGLShader *shader;
+    PRBool isNull, isDeleted;
+    if (!GetConcreteObjectAndGLName(sobj, &shader, &shadername, &isNull, &isDeleted))
+        return ErrorInvalidOperation("DeleteShader: invalid shader");
+
+    if (isNull || isDeleted)
         return NS_OK;
-    }
 
     MakeContextCurrent();
 
-    GLuint name = obj->GLName();
-    gl->fDeleteShader(name);
-    obj->Delete();
-    mMapShaders.Remove(name);
+    gl->fDeleteShader(shadername);
+    shader->Delete();
+    mMapShaders.Remove(shadername);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::DetachShader(nsIWebGLProgram *prog, nsIWebGLShader *sh)
+WebGLContext::DetachShader(nsIWebGLProgram *pobj, nsIWebGLShader *shobj)
 {
-    if (!prog || static_cast<WebGLProgram*>(prog)->Deleted())
-        return ErrorMessage("%s: program is null or deleted!", __FUNCTION__);
-
-    if (!sh || static_cast<WebGLShader*>(sh)->Deleted())
-        return ErrorMessage("%s: shader is null or deleted!", __FUNCTION__);
-
-    GLuint program = static_cast<WebGLProgram*>(prog)->GLName();
-    GLuint shader = static_cast<WebGLShader*>(sh)->GLName();
+    GLuint program, shader;
+    if (!GetGLName<WebGLProgram>(pobj, &program))
+        return ErrorInvalidOperation("DetachShader: invalid program");
+
+    if (!GetGLName<WebGLShader>(shobj, &shader))
+        return ErrorInvalidOperation("DetachShader: invalid shader");
 
     MakeContextCurrent();
 
     gl->fDetachShader(program, shader);
 
     return NS_OK;
 }
 
@@ -732,17 +856,17 @@ GL_SAME_METHOD_2(DepthRange, DepthRange,
 
 // XXX arg check!
 GL_SAME_METHOD_1(Disable, Disable, GLenum)
 
 NS_IMETHODIMP
 WebGLContext::DisableVertexAttribArray(GLuint index)
 {
     if (index > mAttribBuffers.Length())
-        return ErrorMessage("glDisableVertexAttribArray: index out of range");
+        return ErrorInvalidValue("DisableVertexAttribArray: index out of range");
 
     MakeContextCurrent();
 
     gl->fDisableVertexAttribArray(index);
     mAttribBuffers[index].enabled = PR_FALSE;
 
     return NS_OK;
 }
@@ -755,25 +879,25 @@ WebGLContext::DrawArrays(GLenum mode, GL
         case LOCAL_GL_TRIANGLE_STRIP:
         case LOCAL_GL_TRIANGLE_FAN:
         case LOCAL_GL_POINTS:
         case LOCAL_GL_LINE_STRIP:
         case LOCAL_GL_LINE_LOOP:
         case LOCAL_GL_LINES:
             break;
         default:
-            return ErrorMessage("drawA