Merge MC -> JM
authorBrian Hackett <bhackett1024@gmail.com>
Fri, 12 Aug 2011 07:20:08 -0700
changeset 76118 1f767f82d1c309e5f69364f1ddcb24d1f5eff0f9
parent 76117 3a7425b9623025ea6886589cd577cf27fbe0a8d7 (current diff)
parent 74259 f262c389193eebbb714074f8c340bad268071646 (diff)
child 76119 0a8195cb7590cc4c803adced8fea4c1f99b34c03
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
milestone8.0a1
Merge MC -> JM
accessible/src/atk/nsAccessibleRelationWrap.h
accessible/src/base/nsAccessibleRelation.cpp
accessible/src/base/nsAccessibleRelation.h
accessible/src/base/nsRelUtils.cpp
accessible/src/base/nsRelUtils.h
accessible/src/mac/nsAccessibleRelationWrap.h
accessible/src/msaa/nsAccessibleRelationWrap.cpp
accessible/src/msaa/nsAccessibleRelationWrap.h
accessible/src/other/nsAccessibleRelationWrap.h
accessible/tests/mochitest/test_takeFocus.html
content/base/public/nsISelection2.idl
content/base/public/nsISelection3.idl
dom/base/nsDOMClassInfo.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsJSEnvironment.cpp
js/src/Makefile.in
js/src/assembler/assembler/ARMAssembler.cpp
js/src/assembler/assembler/ARMAssembler.h
js/src/assembler/assembler/MacroAssemblerARM.h
js/src/configure.in
js/src/jsbuiltins.h
js/src/jscompartment.cpp
js/src/jsgc.cpp
js/src/jsgc.h
js/src/jsgcinlines.h
js/src/jshashtable.h
js/src/jsinfer.cpp
js/src/jsinterp.cpp
js/src/jstracer.cpp
js/src/jstypedarray.cpp
js/src/jstypedarray.h
js/src/jstypedarrayinlines.h
js/src/jswrapper.cpp
js/src/methodjit/BaseAssembler.h
js/src/methodjit/Compiler.cpp
js/src/methodjit/Logging.h
js/src/methodjit/MonoIC.cpp
js/src/methodjit/PolyIC.cpp
js/src/shell/js.cpp
js/src/tests/js1_8_5/extensions/jstests.list
js/src/tracejit/Writer.h
js/src/vm/Stack-inl.h
js/src/vm/Stack.cpp
js/src/vm/Stack.h
js/src/xpconnect/shell/xpcshell.cpp
js/src/xpconnect/src/xpcjsruntime.cpp
js/src/xpconnect/src/xpcprivate.h
js/src/xpconnect/src/xpcpublic.h
xpcom/glue/nsTPtrArray.h
xpcom/glue/pldhash.c
xpcom/io/nsIBaseStream.idl
--- a/accessible/src/atk/Makefile.in
+++ b/accessible/src/atk/Makefile.in
@@ -77,17 +77,16 @@ EXPORTS = \
   nsRootAccessibleWrap.h \
   nsTextAccessibleWrap.h \
   nsXULMenuAccessibleWrap.h \
   nsXULListboxAccessibleWrap.h \
   nsXULTreeGridAccessibleWrap.h \
   nsHyperTextAccessibleWrap.h \
   nsHTMLImageAccessibleWrap.h \
   nsHTMLTableAccessibleWrap.h \
-  nsAccessibleRelationWrap.h \
   $(NULL)
 
 # we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 CFLAGS		+= $(MOZ_GTK2_CFLAGS)
deleted file mode 100644
--- a/accessible/src/atk/nsAccessibleRelationWrap.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 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.org code.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2007
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either 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 _NS_ACCESSIBLE_RELATION_WRAP_H
-#define _NS_ACCESSIBLE_RELATION_WRAP_H
-
-#include "nsAccessibleRelation.h"
-
-typedef class nsAccessibleRelation nsAccessibleRelationWrap;
-
-#endif
-
--- a/accessible/src/atk/nsAccessibleWrap.cpp
+++ b/accessible/src/atk/nsAccessibleWrap.cpp
@@ -33,29 +33,31 @@
  * 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 "nsAccessible.h"
 #include "nsAccessibleWrap.h"
 
 #include "nsAccUtils.h"
 #include "nsApplicationAccessibleWrap.h"
+#include "nsIAccessibleRelation.h"
 #include "nsRootAccessible.h"
 #include "nsDocAccessibleWrap.h"
 #include "nsIAccessibleValue.h"
 #include "nsString.h"
 #include "nsAutoPtr.h"
 #include "prprf.h"
 #include "nsRoleMap.h"
-#include "nsRelUtils.h"
 #include "nsStateMap.h"
+#include "Relation.h"
 #include "States.h"
 
 #include "nsMaiInterfaceComponent.h"
 #include "nsMaiInterfaceAction.h"
 #include "nsMaiInterfaceText.h"
 #include "nsMaiInterfaceEditableText.h"
 #include "nsMaiInterfaceSelection.h"
 #include "nsMaiInterfaceValue.h"
@@ -936,70 +938,55 @@ refStateSetCB(AtkObject *aAtkObj)
     TranslateStates(accWrap->State(), state_set);
 
     return state_set;
 }
 
 AtkRelationSet *
 refRelationSetCB(AtkObject *aAtkObj)
 {
-    AtkRelationSet *relation_set = nsnull;
-    relation_set = ATK_OBJECT_CLASS(parent_class)->ref_relation_set(aAtkObj);
+  AtkRelationSet* relation_set =
+    ATK_OBJECT_CLASS(parent_class)->ref_relation_set(aAtkObj);
 
-    nsAccessibleWrap *accWrap = GetAccessibleWrap(aAtkObj);
-    if (!accWrap) {
-        return relation_set;
-    }
+  nsAccessibleWrap *accWrap = GetAccessibleWrap(aAtkObj);
+  if (!accWrap)
+    return relation_set;
 
-    AtkRelation* relation;
-    
-    PRUint32 relationType[] = {nsIAccessibleRelation::RELATION_LABELLED_BY,
-                               nsIAccessibleRelation::RELATION_LABEL_FOR,
-                               nsIAccessibleRelation::RELATION_NODE_CHILD_OF,
-                               nsIAccessibleRelation::RELATION_CONTROLLED_BY,
-                               nsIAccessibleRelation::RELATION_CONTROLLER_FOR,
-                               nsIAccessibleRelation::RELATION_EMBEDS,
-                               nsIAccessibleRelation::RELATION_FLOWS_TO,
-                               nsIAccessibleRelation::RELATION_FLOWS_FROM,
-                               nsIAccessibleRelation::RELATION_DESCRIBED_BY,
-                               nsIAccessibleRelation::RELATION_DESCRIPTION_FOR,
-                               };
+  PRUint32 relationTypes[] = {
+    nsIAccessibleRelation::RELATION_LABELLED_BY,
+    nsIAccessibleRelation::RELATION_LABEL_FOR,
+    nsIAccessibleRelation::RELATION_NODE_CHILD_OF,
+    nsIAccessibleRelation::RELATION_CONTROLLED_BY,
+    nsIAccessibleRelation::RELATION_CONTROLLER_FOR,
+    nsIAccessibleRelation::RELATION_EMBEDS,
+    nsIAccessibleRelation::RELATION_FLOWS_TO,
+    nsIAccessibleRelation::RELATION_FLOWS_FROM,
+    nsIAccessibleRelation::RELATION_DESCRIBED_BY,
+    nsIAccessibleRelation::RELATION_DESCRIPTION_FOR,
+  };
 
-    for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(relationType); i++) {
-        relation = atk_relation_set_get_relation_by_type(relation_set, static_cast<AtkRelationType>(relationType[i]));
-        if (relation) {
-            atk_relation_set_remove(relation_set, relation);
-        }
+  for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(relationTypes); i++) {
+    AtkRelationType atkType = static_cast<AtkRelationType>(relationTypes[i]);
+    AtkRelation* atkRelation =
+      atk_relation_set_get_relation_by_type(relation_set, atkType);
+    if (atkRelation)
+      atk_relation_set_remove(relation_set, atkRelation);
 
-        nsCOMPtr<nsIAccessibleRelation> geckoRelation;
-        nsresult rv = accWrap->GetRelationByType(relationType[i],
-                                                 getter_AddRefs(geckoRelation));
-        if (NS_SUCCEEDED(rv) && geckoRelation) {
-            PRUint32 targetsCount = 0;
-            geckoRelation->GetTargetsCount(&targetsCount);
-            if (targetsCount) {
-                AtkObject** accessible_array = new AtkObject*[targetsCount];
-                for (PRUint32 index = 0; index < targetsCount; index++) {
-                    nsCOMPtr<nsIAccessible> geckoTarget;
-                    geckoRelation->GetTarget(index, getter_AddRefs(geckoTarget));
-                    accessible_array[index] =
-                        nsAccessibleWrap::GetAtkObject(geckoTarget);
-                }
+    Relation rel(accWrap->RelationByType(relationTypes[i]));
+    nsTArray<AtkObject*> targets;
+    nsAccessible* tempAcc = nsnull;
+    while ((tempAcc = rel.Next()))
+      targets.AppendElement(nsAccessibleWrap::GetAtkObject(tempAcc));
 
-                relation = atk_relation_new(accessible_array, targetsCount,
-                                            static_cast<AtkRelationType>(relationType[i]));
-                atk_relation_set_add(relation_set, relation);
-                g_object_unref(relation);
+    atkRelation = atk_relation_new(targets.Elements(), targets.Length(), atkType);
+    atk_relation_set_add(relation_set, atkRelation);
+    g_object_unref(atkRelation);
+  }
 
-                delete [] accessible_array;
-            }
-        }
-    }
-
-    return relation_set;
+  return relation_set;
 }
 
 // Check if aAtkObj is a valid MaiAtkObject, and return the nsAccessibleWrap
 // for it.
 nsAccessibleWrap *GetAccessibleWrap(AtkObject *aAtkObj)
 {
     NS_ENSURE_TRUE(IS_MAI_OBJECT(aAtkObj), nsnull);
     nsAccessibleWrap *tmpAccWrap = MAI_ATK_OBJECT(aAtkObj)->accWrap;
--- a/accessible/src/base/AccIterator.cpp
+++ b/accessible/src/base/AccIterator.cpp
@@ -35,16 +35,18 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "AccIterator.h"
 
 #include "nsAccessibilityService.h"
 #include "nsAccessible.h"
 
+#include "mozilla/dom/Element.h"
+
 ////////////////////////////////////////////////////////////////////////////////
 // AccIterator
 ////////////////////////////////////////////////////////////////////////////////
 
 AccIterator::AccIterator(nsAccessible *aAccessible,
                          filters::FilterFuncPtr aFilterFunc,
                          IterationType aIterationType) :
   mFilterFunc(aFilterFunc), mIsDeep(aIterationType != eFlatNav)
@@ -57,17 +59,17 @@ AccIterator::~AccIterator()
   while (mState) {
     IteratorState *tmp = mState;
     mState = tmp->mParentState;
     delete tmp;
   }
 }
 
 nsAccessible*
-AccIterator::GetNext()
+AccIterator::Next()
 {
   while (mState) {
     nsAccessible *child = mState->mParent->GetChildAt(mState->mIndex++);
     if (!child) {
       IteratorState *tmp = mState;
       mState = mState->mParentState;
       delete tmp;
 
@@ -250,8 +252,98 @@ XULDescriptionIterator::Next()
   nsAccessible* descr = nsnull;
   while ((descr = mRelIter.Next())) {
     if (descr->GetContent()->Tag() == nsAccessibilityAtoms::description)
       return descr;
   }
 
   return nsnull;
 }
+
+////////////////////////////////////////////////////////////////////////////////
+// IDRefsIterator
+////////////////////////////////////////////////////////////////////////////////
+
+IDRefsIterator::IDRefsIterator(nsIContent* aContent, nsIAtom* aIDRefsAttr) :
+  mCurrIdx(0)
+{
+  if (!aContent->IsInDoc() ||
+      !aContent->GetAttr(kNameSpaceID_None, aIDRefsAttr, mIDs))
+    return;
+
+  if (aContent->IsInAnonymousSubtree()) {
+    mXBLDocument = do_QueryInterface(aContent->GetOwnerDoc());
+    mBindingParent = do_QueryInterface(aContent->GetBindingParent());
+  } else {
+    mDocument = aContent->GetOwnerDoc();
+  }
+}
+
+const nsDependentSubstring
+IDRefsIterator::NextID()
+{
+  for (; mCurrIdx < mIDs.Length(); mCurrIdx++) {
+    if (!NS_IsAsciiWhitespace(mIDs[mCurrIdx]))
+      break;
+  }
+
+  if (mCurrIdx >= mIDs.Length())
+    return nsDependentSubstring();
+
+  nsAString::index_type idStartIdx = mCurrIdx;
+  while (++mCurrIdx < mIDs.Length()) {
+    if (NS_IsAsciiWhitespace(mIDs[mCurrIdx]))
+      break;
+  }
+
+  return Substring(mIDs, idStartIdx, mCurrIdx++ - idStartIdx);
+}
+
+nsIContent*
+IDRefsIterator::NextElem()
+{
+  while (true) {
+    const nsDependentSubstring id = NextID();
+    if (id.IsEmpty())
+      break;
+
+    nsIContent* refContent = GetElem(id);
+    if (refContent)
+      return refContent;
+  }
+
+  return nsnull;
+}
+
+nsIContent*
+IDRefsIterator::GetElem(const nsDependentSubstring& aID)
+{
+  if (mXBLDocument) {
+    // If content is anonymous subtree then use "anonid" attribute to get
+    // elements, otherwise search elements in DOM by ID attribute.
+
+    nsCOMPtr<nsIDOMElement> refElm;
+    mXBLDocument->GetAnonymousElementByAttribute(mBindingParent,
+                                                 NS_LITERAL_STRING("anonid"),
+                                                 aID,
+                                                 getter_AddRefs(refElm));
+    nsCOMPtr<nsIContent> refContent = do_QueryInterface(refElm);
+    return refContent;
+  }
+
+  return mDocument->GetElementById(aID);
+}
+
+nsAccessible*
+IDRefsIterator::Next()
+{
+  nsIContent* nextElm = NextElem();
+  return nextElm ? GetAccService()->GetAccessible(nextElm) : nsnull;
+}
+
+nsAccessible*
+SingleAccIterator::Next()
+{
+  nsRefPtr<nsAccessible> nextAcc;
+  mAcc.swap(nextAcc);
+  return (nextAcc && !nextAcc->IsDefunct()) ? nextAcc : nsnull;
+}
+
--- a/accessible/src/base/AccIterator.h
+++ b/accessible/src/base/AccIterator.h
@@ -1,8 +1,10 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 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/
  *
@@ -33,25 +35,42 @@
  * 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 "nsAccessibilityService.h"
 #include "filters.h"
 #include "nscore.h"
 #include "nsDocAccessible.h"
 
+#include "nsIDOMDocumentXBL.h"
+
+/**
+ * AccIterable is a basic interface for iterators over accessibles.
+ */
+class AccIterable
+{
+public:
+  virtual ~AccIterable() { }
+  virtual nsAccessible* Next() = 0;
+
+private:
+  friend class Relation;
+  nsAutoPtr<AccIterable> mNextIter;
+};
+
 /**
  * Allows to iterate through accessible children or subtree complying with
  * filter function.
  */
-class AccIterator
+class AccIterator : public AccIterable
 {
 public:
   /**
    * Used to define iteration type.
    */
   enum IterationType {
     /**
      * Navigation happens through direct children.
@@ -62,23 +81,23 @@ public:
      * Navigation through subtree excluding iterator root; if the accessible
      * complies with filter, iterator ignores its children.
      */
     eTreeNav
   };
 
   AccIterator(nsAccessible* aRoot, filters::FilterFuncPtr aFilterFunc,
               IterationType aIterationType = eFlatNav);
-  ~AccIterator();
+  virtual ~AccIterator();
 
   /**
    * Return next accessible complying with filter function. Return the first
    * accessible for the first time.
    */
-  nsAccessible *GetNext();
+  virtual nsAccessible *Next();
 
 private:
   AccIterator();
   AccIterator(const AccIterator&);
   AccIterator& operator =(const AccIterator&);
 
   struct IteratorState
   {
@@ -94,36 +113,38 @@ private:
   IteratorState *mState;
 };
 
 
 /**
  * Allows to traverse through related accessibles that are pointing to the given
  * dependent accessible by relation attribute.
  */
-class RelatedAccIterator
+class RelatedAccIterator : public AccIterable
 {
 public:
   /**
    * Constructor.
    *
    * @param aDocument         [in] the document accessible the related
    * &                         accessibles belong to.
    * @param aDependentContent [in] the content of dependent accessible that
    *                           relations were requested for
    * @param aRelAttr          [in] relation attribute that relations are
    *                           pointed by
    */
   RelatedAccIterator(nsDocAccessible* aDocument, nsIContent* aDependentContent,
                      nsIAtom* aRelAttr);
 
+  virtual ~RelatedAccIterator() { }
+
   /**
    * Return next related accessible for the given dependent accessible.
    */
-  nsAccessible* Next();
+  virtual nsAccessible* Next();
 
 private:
   RelatedAccIterator();
   RelatedAccIterator(const RelatedAccIterator&);
   RelatedAccIterator& operator = (const RelatedAccIterator&);
 
   nsDocAccessible* mDocument;
   nsIAtom* mRelAttr;
@@ -131,101 +152,168 @@ private:
   nsIContent* mBindingParent;
   PRUint32 mIndex;
 };
 
 
 /**
  * Used to iterate through HTML labels associated with the given element.
  */
-class HTMLLabelIterator
+class HTMLLabelIterator : public AccIterable
 {
 public:
   enum LabelFilter {
     eAllLabels,
     eSkipAncestorLabel
   };
 
   HTMLLabelIterator(nsDocAccessible* aDocument, nsIContent* aElement,
                     LabelFilter aFilter = eAllLabels);
 
+  virtual ~HTMLLabelIterator() { }
+
   /**
    * Return next label accessible associated with the given element.
    */
-  nsAccessible* Next();
+  virtual nsAccessible* Next();
 
 private:
   HTMLLabelIterator();
   HTMLLabelIterator(const HTMLLabelIterator&);
   HTMLLabelIterator& operator = (const HTMLLabelIterator&);
 
   RelatedAccIterator mRelIter;
   nsIContent* mElement;
   LabelFilter mLabelFilter;
 };
 
 
 /**
  * Used to iterate through HTML outputs associated with the given element.
  */
-class HTMLOutputIterator
+class HTMLOutputIterator : public AccIterable
 {
 public:
   HTMLOutputIterator(nsDocAccessible* aDocument, nsIContent* aElement);
+  virtual ~HTMLOutputIterator() { }
 
   /**
    * Return next output accessible associated with the given element.
    */
-  nsAccessible* Next();
+  virtual nsAccessible* Next();
 
 private:
   HTMLOutputIterator();
   HTMLOutputIterator(const HTMLOutputIterator&);
   HTMLOutputIterator& operator = (const HTMLOutputIterator&);
 
   RelatedAccIterator mRelIter;
 };
 
 
 /**
  * Used to iterate through XUL labels associated with the given element.
  */
-class XULLabelIterator
+class XULLabelIterator : public AccIterable
 {
 public:
   XULLabelIterator(nsDocAccessible* aDocument, nsIContent* aElement);
+  virtual ~XULLabelIterator() { }
 
   /**
    * Return next label accessible associated with the given element.
    */
-  nsAccessible* Next();
+  virtual nsAccessible* Next();
 
 private:
   XULLabelIterator();
   XULLabelIterator(const XULLabelIterator&);
   XULLabelIterator& operator = (const XULLabelIterator&);
 
   RelatedAccIterator mRelIter;
 };
 
 
 /**
  * Used to iterate through XUL descriptions associated with the given element.
  */
-class XULDescriptionIterator
+class XULDescriptionIterator : public AccIterable
 {
 public:
   XULDescriptionIterator(nsDocAccessible* aDocument, nsIContent* aElement);
+  virtual ~XULDescriptionIterator() { }
 
   /**
    * Return next description accessible associated with the given element.
    */
-  nsAccessible* Next();
+  virtual nsAccessible* Next();
 
 private:
   XULDescriptionIterator();
   XULDescriptionIterator(const XULDescriptionIterator&);
   XULDescriptionIterator& operator = (const XULDescriptionIterator&);
 
   RelatedAccIterator mRelIter;
 };
 
+/**
+ * Used to iterate through IDs, elements or accessibles pointed by IDRefs
+ * attribute. Note, any method used to iterate through IDs, elements, or
+ * accessibles moves iterator to next position.
+ */
+class IDRefsIterator : public AccIterable
+{
+public:
+  IDRefsIterator(nsIContent* aContent, nsIAtom* aIDRefsAttr);
+  virtual ~IDRefsIterator() { }
+
+  /**
+   * Return next ID.
+   */
+  const nsDependentSubstring NextID();
+
+  /**
+   * Return next element.
+   */
+  nsIContent* NextElem();
+
+  /**
+   * Return the element with the given ID.
+   */
+  nsIContent* GetElem(const nsDependentSubstring& aID);
+
+  // AccIterable
+  virtual nsAccessible* Next();
+
+private:
+  IDRefsIterator();
+  IDRefsIterator(const IDRefsIterator&);
+  IDRefsIterator operator = (const IDRefsIterator&);
+
+  nsString mIDs;
+  nsAString::index_type mCurrIdx;
+
+  nsIDocument* mDocument;
+  nsCOMPtr<nsIDOMDocumentXBL> mXBLDocument;
+  nsCOMPtr<nsIDOMElement> mBindingParent;
+};
+
+/**
+ * Iterator that points to a single accessible returning it on the first call
+ * to Next().
+ */
+class SingleAccIterator : public AccIterable
+{
+public:
+  SingleAccIterator(nsAccessible* aTarget): mAcc(aTarget) { }
+  virtual ~SingleAccIterator() { }
+
+  virtual nsAccessible* Next();
+
+private:
+  SingleAccIterator();
+  SingleAccIterator(const SingleAccIterator&);
+  SingleAccIterator& operator = (const SingleAccIterator&);
+
+  nsRefPtr<nsAccessible> mAcc;
+};
+
 #endif
--- a/accessible/src/base/Makefile.in
+++ b/accessible/src/base/Makefile.in
@@ -58,20 +58,18 @@ CPPSRCS = \
   nsAccessNode.cpp \
   nsARIAGridAccessible.cpp \
   nsARIAMap.cpp \
   nsDocAccessible.cpp \
   nsOuterDocAccessible.cpp \
   nsAccessibilityAtoms.cpp \
   nsCoreUtils.cpp \
   nsAccUtils.cpp \
-  nsRelUtils.cpp \
   nsAccessibilityService.cpp \
   nsAccessible.cpp \
-  nsAccessibleRelation.cpp \
   nsAccTreeWalker.cpp \
   nsBaseWidgetAccessible.cpp \
   nsEventShell.cpp \
   nsFormControlAccessible.cpp \
   nsRootAccessible.cpp \
   nsApplicationAccessible.cpp \
   nsCaretAccessible.cpp \
   nsTextAccessible.cpp \
new file mode 100644
--- /dev/null
+++ b/accessible/src/base/Relation.h
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Trevor Saunders <trev.saunders@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 RELATION_H_
+#define RELATION_H_
+
+#include "AccIterator.h"
+
+/**
+ * This class is used to return Relation objects from functions.  A copy
+ * constructor doesn't work here because we need to mutate the old relation to
+ * have its nsAutoPtr forget what it points to.
+ */
+struct RelationCopyHelper
+{
+  RelationCopyHelper(AccIterable* aFirstIter, AccIterable* aLastIter) :
+    mFirstIter(aFirstIter), mLastIter(aLastIter) { }
+
+  AccIterable* mFirstIter;
+  AccIterable* mLastIter;
+};
+
+/**
+ * A collection of relation targets of a certain type.  Targets are computed
+ * lazily while enumerating.
+ */
+class Relation
+{
+public:
+  Relation() : mFirstIter(nsnull), mLastIter(nsnull) { }
+
+  Relation(const RelationCopyHelper aRelation) :
+    mFirstIter(aRelation.mFirstIter), mLastIter(aRelation.mLastIter) { }
+
+  Relation(AccIterable* aIter) : mFirstIter(aIter), mLastIter(aIter) { }
+
+  Relation(nsAccessible* aAcc) :
+    mFirstIter(nsnull), mLastIter(nsnull)
+    { AppendTarget(aAcc); }
+
+  Relation(nsIContent* aContent) :
+    mFirstIter(nsnull), mLastIter(nsnull)
+    { AppendTarget(aContent); }
+
+  Relation& operator = (const RelationCopyHelper& aRH)
+  {
+    mFirstIter = aRH.mFirstIter;
+    mLastIter = aRH.mLastIter;
+    return *this;
+  }
+
+  Relation& operator = (Relation& aRelation)
+  {
+    mFirstIter = aRelation.mFirstIter;
+    mLastIter = aRelation.mLastIter;
+    return *this;
+  }
+
+  operator RelationCopyHelper()
+  {
+    return RelationCopyHelper(mFirstIter.forget(), mLastIter);
+  }
+
+  inline void AppendIter(AccIterable* aIter)
+  {
+    if (mLastIter)
+      mLastIter->mNextIter = aIter;
+    else
+      mFirstIter = aIter;
+
+    mLastIter = aIter;
+  }
+
+  /**
+   * Append the given accessible to the set of related accessibles.
+   */
+  inline void AppendTarget(nsAccessible* aAcc)
+  {
+    if (aAcc)
+      AppendIter(new SingleAccIterator(aAcc));
+  }
+
+  /**
+   * Append the one accessible for this content node to the set of related
+   * accessibles.
+   */
+  inline void AppendTarget(nsIContent* aContent)
+  {
+    if (aContent)
+      AppendTarget(GetAccService()->GetAccessible(aContent));
+  }
+
+  /**
+   * compute and return the next related accessible.
+   */
+  inline nsAccessible* Next()
+  {
+    nsAccessible* target = nsnull;
+
+    // a trick nsAutoPtr deletes what it used to point to when assigned to
+    while (mFirstIter && !(target = mFirstIter->Next()))
+      mFirstIter = mFirstIter->mNextIter;
+
+    if (!mFirstIter)
+      mLastIter = nsnull;
+
+    return target;
+  }
+
+private:
+  Relation& operator = (const Relation&);
+
+  nsAutoPtr<AccIterable> mFirstIter;
+  AccIterable* mLastIter;
+};
+
+#endif
+
--- a/accessible/src/base/nsARIAGridAccessible.cpp
+++ b/accessible/src/base/nsARIAGridAccessible.cpp
@@ -101,40 +101,40 @@ nsARIAGridAccessible::GetColumnCount(PRI
 {
   NS_ENSURE_ARG_POINTER(acolumnCount);
   *acolumnCount = 0;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   AccIterator rowIter(this, filters::GetRow);
-  nsAccessible* row = rowIter.GetNext();
+  nsAccessible* row = rowIter.Next();
   if (!row)
     return NS_OK;
 
   AccIterator cellIter(row, filters::GetCell);
   nsAccessible *cell = nsnull;
 
-  while ((cell = cellIter.GetNext()))
+  while ((cell = cellIter.Next()))
     (*acolumnCount)++;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsARIAGridAccessible::GetRowCount(PRInt32 *arowCount)
 {
   NS_ENSURE_ARG_POINTER(arowCount);
   *arowCount = 0;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   AccIterator rowIter(this, filters::GetRow);
-  while (rowIter.GetNext())
+  while (rowIter.Next())
     (*arowCount)++;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsARIAGridAccessible::GetCellAt(PRInt32 aRowIndex, PRInt32 aColumnIndex,
                                 nsIAccessible **aAccessible)
@@ -322,30 +322,30 @@ nsARIAGridAccessible::IsColumnSelected(P
   *aIsSelected = PR_FALSE;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   NS_ENSURE_ARG(IsValidColumn(aColumn));
 
   AccIterator rowIter(this, filters::GetRow);
-  nsAccessible *row = rowIter.GetNext();
+  nsAccessible *row = rowIter.Next();
   if (!row)
     return NS_OK;
 
   do {
     if (!nsAccUtils::IsARIASelected(row)) {
       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 = rowIter.GetNext()));
+  } while ((row = rowIter.Next()));
 
   *aIsSelected = PR_TRUE;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsARIAGridAccessible::IsRowSelected(PRInt32 aRow, PRBool *aIsSelected)
 {
@@ -356,17 +356,17 @@ nsARIAGridAccessible::IsRowSelected(PRIn
     return NS_ERROR_FAILURE;
 
   nsAccessible *row = GetRowAt(aRow);
   NS_ENSURE_ARG(row);
 
   if (!nsAccUtils::IsARIASelected(row)) {
     AccIterator cellIter(row, filters::GetCell);
     nsAccessible *cell = nsnull;
-    while ((cell = cellIter.GetNext())) {
+    while ((cell = cellIter.Next())) {
       if (!nsAccUtils::IsARIASelected(cell))
         return NS_OK;
     }
   }
 
   *aIsSelected = PR_TRUE;
   return NS_OK;
 }
@@ -406,26 +406,26 @@ nsARIAGridAccessible::GetSelectedCellCou
     return NS_ERROR_FAILURE;
 
   PRInt32 colCount = 0;
   GetColumnCount(&colCount);
 
   AccIterator rowIter(this, filters::GetRow);
 
   nsAccessible *row = nsnull;
-  while ((row = rowIter.GetNext())) {
+  while ((row = rowIter.Next())) {
     if (nsAccUtils::IsARIASelected(row)) {
       (*aCount) += colCount;
       continue;
     }
 
     AccIterator cellIter(row, filters::GetCell);
     nsAccessible *cell = nsnull;
 
-    while ((cell = cellIter.GetNext())) {
+    while ((cell = cellIter.Next())) {
       if (nsAccUtils::IsARIASelected(cell))
         (*aCount)++;
     }
   }
 
   return NS_OK;
 }
 
@@ -442,34 +442,34 @@ nsARIAGridAccessible::GetSelectedRowCoun
   *aCount = 0;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   AccIterator rowIter(this, filters::GetRow);
 
   nsAccessible *row = nsnull;
-  while ((row = rowIter.GetNext())) {
+  while ((row = rowIter.Next())) {
     if (nsAccUtils::IsARIASelected(row)) {
       (*aCount)++;
       continue;
     }
 
     AccIterator cellIter(row, filters::GetCell);
-    nsAccessible *cell = cellIter.GetNext();
+    nsAccessible *cell = cellIter.Next();
     if (!cell)
       continue;
 
     PRBool isRowSelected = PR_TRUE;
     do {
       if (!nsAccUtils::IsARIASelected(cell)) {
         isRowSelected = PR_FALSE;
         break;
       }
-    } while ((cell = cellIter.GetNext()));
+    } while ((cell = cellIter.Next()));
 
     if (isRowSelected)
       (*aCount)++;
   }
 
   return NS_OK;
 }
 
@@ -485,28 +485,28 @@ nsARIAGridAccessible::GetSelectedCells(n
   nsresult rv = NS_OK;
   nsCOMPtr<nsIMutableArray> selCells =
     do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   AccIterator rowIter(this, filters::GetRow);
 
   nsAccessible *row = nsnull;
-  while ((row = rowIter.GetNext())) {
+  while ((row = rowIter.Next())) {
     AccIterator cellIter(row, filters::GetCell);
     nsAccessible *cell = nsnull;
 
     if (nsAccUtils::IsARIASelected(row)) {
-      while ((cell = cellIter.GetNext()))
+      while ((cell = cellIter.Next()))
         selCells->AppendElement(static_cast<nsIAccessible *>(cell), PR_FALSE);
 
       continue;
     }
 
-    while ((cell = cellIter.GetNext())) {
+    while ((cell = cellIter.Next())) {
       if (nsAccUtils::IsARIASelected(cell))
         selCells->AppendElement(static_cast<nsIAccessible *>(cell), PR_FALSE);
     }
   }
 
   NS_ADDREF(*aCells = selCells);
   return NS_OK;
 }
@@ -529,28 +529,28 @@ nsARIAGridAccessible::GetSelectedCellInd
   PRInt32 colCount = 0;
   GetColumnCount(&colCount);
 
   nsTArray<PRInt32> selCells(rowCount * colCount);
 
   AccIterator rowIter(this, filters::GetRow);
 
   nsAccessible *row = nsnull;
-  for (PRInt32 rowIdx = 0; (row = rowIter.GetNext()); rowIdx++) {
+  for (PRInt32 rowIdx = 0; (row = rowIter.Next()); rowIdx++) {
     if (nsAccUtils::IsARIASelected(row)) {
       for (PRInt32 colIdx = 0; colIdx < colCount; colIdx++)
         selCells.AppendElement(rowIdx * colCount + colIdx);
 
       continue;
     }
 
     AccIterator cellIter(row, filters::GetCell);
     nsAccessible *cell = nsnull;
 
-    for (PRInt32 colIdx = 0; (cell = cellIter.GetNext()); colIdx++) {
+    for (PRInt32 colIdx = 0; (cell = cellIter.Next()); colIdx++) {
       if (nsAccUtils::IsARIASelected(cell))
         selCells.AppendElement(rowIdx * colCount + colIdx);
     }
   }
 
   PRUint32 selCellsCount = selCells.Length();
   if (!selCellsCount)
     return NS_OK;
@@ -589,34 +589,34 @@ nsARIAGridAccessible::GetSelectedRowIndi
   if (!rowCount)
     return NS_OK;
 
   nsTArray<PRInt32> selRows(rowCount);
 
   AccIterator rowIter(this, filters::GetRow);
 
   nsAccessible *row = nsnull;
-  for (PRInt32 rowIdx = 0; (row = rowIter.GetNext()); rowIdx++) {
+  for (PRInt32 rowIdx = 0; (row = rowIter.Next()); rowIdx++) {
     if (nsAccUtils::IsARIASelected(row)) {
       selRows.AppendElement(rowIdx);
       continue;
     }
 
     AccIterator cellIter(row, filters::GetCell);
-    nsAccessible *cell = cellIter.GetNext();
+    nsAccessible *cell = cellIter.Next();
     if (!cell)
       continue;
 
     PRBool isRowSelected = PR_TRUE;
     do {
       if (!nsAccUtils::IsARIASelected(cell)) {
         isRowSelected = PR_FALSE;
         break;
       }
-    } while ((cell = cellIter.GetNext()));
+    } while ((cell = cellIter.Next()));
 
     if (isRowSelected)
       selRows.AppendElement(rowIdx);
   }
 
   PRUint32 selrowCount = selRows.Length();
   if (!selrowCount)
     return NS_OK;
@@ -635,17 +635,17 @@ nsARIAGridAccessible::SelectRow(PRInt32 
   NS_ENSURE_ARG(IsValidRow(aRow));
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   AccIterator rowIter(this, filters::GetRow);
 
   nsAccessible *row = nsnull;
-  for (PRInt32 rowIdx = 0; (row = rowIter.GetNext()); rowIdx++) {
+  for (PRInt32 rowIdx = 0; (row = rowIter.Next()); rowIdx++) {
     nsresult rv = SetARIASelected(row, rowIdx == aRow);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -654,17 +654,17 @@ nsARIAGridAccessible::SelectColumn(PRInt
   NS_ENSURE_ARG(IsValidColumn(aColumn));
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   AccIterator rowIter(this, filters::GetRow);
 
   nsAccessible *row = nsnull;
-  while ((row = rowIter.GetNext())) {
+  while ((row = rowIter.Next())) {
     // Unselect all cells in the row.
     nsresult rv = SetARIASelected(row, PR_FALSE);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Select cell at the column index.
     nsAccessible *cell = GetCellInRowAt(row, aColumn);
     if (cell) {
       rv = SetARIASelected(cell, PR_TRUE);
@@ -693,17 +693,17 @@ nsARIAGridAccessible::UnselectColumn(PRI
   NS_ENSURE_ARG(IsValidColumn(aColumn));
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   AccIterator rowIter(this, filters::GetRow);
 
   nsAccessible *row = nsnull;
-  while ((row = rowIter.GetNext())) {
+  while ((row = rowIter.Next())) {
     nsAccessible *cell = GetCellInRowAt(row, aColumn);
     if (cell) {
       nsresult rv = SetARIASelected(cell, PR_FALSE);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
   return NS_OK;
@@ -761,31 +761,31 @@ nsARIAGridAccessible::IsValidRowNColumn(
 
 nsAccessible*
 nsARIAGridAccessible::GetRowAt(PRInt32 aRow)
 {
   PRInt32 rowIdx = aRow;
 
   AccIterator rowIter(this, filters::GetRow);
 
-  nsAccessible *row = rowIter.GetNext();
-  while (rowIdx != 0 && (row = rowIter.GetNext()))
+  nsAccessible *row = rowIter.Next();
+  while (rowIdx != 0 && (row = rowIter.Next()))
     rowIdx--;
 
   return row;
 }
 
 nsAccessible*
 nsARIAGridAccessible::GetCellInRowAt(nsAccessible *aRow, PRInt32 aColumn)
 {
   PRInt32 colIdx = aColumn;
 
   AccIterator cellIter(aRow, filters::GetCell);
-  nsAccessible *cell = cellIter.GetNext();
-  while (colIdx != 0 && (cell = cellIter.GetNext()))
+  nsAccessible *cell = cellIter.Next();
+  while (colIdx != 0 && (cell = cellIter.Next()))
     colIdx--;
 
   return cell;
 }
 
 nsresult
 nsARIAGridAccessible::SetARIASelected(nsAccessible *aAccessible,
                                       PRBool aIsSelected, PRBool aNotify)
@@ -816,17 +816,17 @@ nsARIAGridAccessible::SetARIASelected(ns
   PRUint32 role = aAccessible->Role();
 
   // If the given accessible is row that was unselected then remove
   // aria-selected from cell accessible.
   if (role == nsIAccessibleRole::ROLE_ROW) {
     AccIterator cellIter(aAccessible, filters::GetCell);
     nsAccessible *cell = nsnull;
 
-    while ((cell = cellIter.GetNext())) {
+    while ((cell = cellIter.Next())) {
       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
@@ -838,17 +838,17 @@ nsARIAGridAccessible::SetARIASelected(ns
 
     if (row && row->Role() == nsIAccessibleRole::ROLE_ROW &&
         nsAccUtils::IsARIASelected(row)) {
       rv = SetARIASelected(row, PR_FALSE, PR_FALSE);
       NS_ENSURE_SUCCESS(rv, rv);
 
       AccIterator cellIter(row, filters::GetCell);
       nsAccessible *cell = nsnull;
-      while ((cell = cellIter.GetNext())) {
+      while ((cell = cellIter.Next())) {
         if (cell != aAccessible) {
           rv = SetARIASelected(cell, PR_TRUE, PR_FALSE);
           NS_ENSURE_SUCCESS(rv, rv);
         }
       }
     }
   }
 
@@ -863,17 +863,17 @@ nsARIAGridAccessible::GetSelectedColumns
   *acolumnCount = 0;
   if (aColumns)
     *aColumns = nsnull;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   AccIterator rowIter(this, filters::GetRow);
-  nsAccessible *row = rowIter.GetNext();
+  nsAccessible *row = rowIter.Next();
   if (!row)
     return NS_OK;
 
   PRInt32 colCount = 0;
   GetColumnCount(&colCount);
   if (!colCount)
     return NS_OK;
 
@@ -887,24 +887,24 @@ nsARIAGridAccessible::GetSelectedColumns
   do {
     if (nsAccUtils::IsARIASelected(row))
       continue;
 
     PRInt32 colIdx = 0;
 
     AccIterator cellIter(row, filters::GetCell);
     nsAccessible *cell = nsnull;
-    for (colIdx = 0; (cell = cellIter.GetNext()); colIdx++) {
+    for (colIdx = 0; (cell = cellIter.Next()); colIdx++) {
       if (isColSelArray.SafeElementAt(colIdx, PR_FALSE) &&
           !nsAccUtils::IsARIASelected(cell)) {
         isColSelArray[colIdx] = PR_FALSE;
         selColCount--;
       }
     }
-  } while ((row = rowIter.GetNext()));
+  } while ((row = rowIter.Next()));
 
   if (!selColCount)
     return NS_OK;
 
   if (!aColumns) {
     *acolumnCount = selColCount;
     return NS_OK;
   }
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -43,20 +43,22 @@
 
 #include "AccGroupInfo.h"
 #include "AccIterator.h"
 #include "nsAccUtils.h"
 #include "nsDocAccessible.h"
 #include "nsEventShell.h"
 
 #include "nsAccEvent.h"
+#include "nsAccessibleRelation.h"
 #include "nsAccessibilityService.h"
 #include "nsAccTreeWalker.h"
-#include "nsRelUtils.h"
+#include "nsIAccessibleRelation.h"
 #include "nsTextEquivUtils.h"
+#include "Relation.h"
 #include "States.h"
 
 #include "nsIDOMElement.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMDocumentXBL.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsIDOMNodeFilter.h"
@@ -1523,23 +1525,21 @@ nsAccessible::State()
                              nsAccessibilityAtoms::aria_selected,
                              nsAccessibilityAtoms::_false, eCaseMatters)) {
     // Special case: for tabs, focused implies selected, unless explicitly
     // false, i.e. aria-selected="false".
     if (state & states::FOCUSED) {
       state |= states::SELECTED;
     } else {
       // If focus is in a child of the tab panel surely the tab is selected!
-      nsCOMPtr<nsIAccessible> tabPanel = nsRelUtils::
-        GetRelatedAccessible(this, nsIAccessibleRelation::RELATION_LABEL_FOR);
-
-      if (nsAccUtils::Role(tabPanel) == nsIAccessibleRole::ROLE_PROPERTYPAGE) {
-        nsRefPtr<nsAccessible> tabPanelAcc(do_QueryObject(tabPanel));
-        nsINode *tabPanelNode = tabPanelAcc->GetNode();
-        if (nsCoreUtils::IsAncestorOf(tabPanelNode, gLastFocusedNode))
+      Relation rel = RelationByType(nsIAccessibleRelation::RELATION_LABEL_FOR);
+      nsAccessible* relTarget = nsnull;
+      while ((relTarget = rel.Next())) {
+        if (relTarget->Role() == nsIAccessibleRole::ROLE_PROPERTYPAGE &&
+            nsCoreUtils::IsAncestorOf(relTarget->GetNode(), gLastFocusedNode))
           state |= states::SELECTED;
       }
     }
   }
 
   const PRUint32 kExpandCollapseStates = states::COLLAPSED | states::EXPANDED;
   if ((state & kExpandCollapseStates) == kExpandCollapseStates) {
     // Cannot be both expanded and collapsed -- this happens in ARIA expanded
@@ -1825,21 +1825,21 @@ nsAccessible::ARIARoleInternal()
     }
 
   } else if (mRoleMapEntry->role == nsIAccessibleRole::ROLE_LISTBOX) {
     // A listbox inside of a combobox needs a special role because of ATK
     // mapping to menu.
     if (mParent && mParent->Role() == nsIAccessibleRole::ROLE_COMBOBOX) {
       return nsIAccessibleRole::ROLE_COMBOBOX_LIST;
 
-      nsCOMPtr<nsIAccessible> possibleCombo =
-        nsRelUtils::GetRelatedAccessible(this,
-                                         nsIAccessibleRelation::RELATION_NODE_CHILD_OF);
-      if (nsAccUtils::Role(possibleCombo) == nsIAccessibleRole::ROLE_COMBOBOX)
-        return nsIAccessibleRole::ROLE_COMBOBOX_LIST;
+      Relation rel = RelationByType(nsIAccessibleRelation::RELATION_NODE_CHILD_OF);
+      nsAccessible* targetAcc = nsnull;
+      while ((targetAcc = rel.Next()))
+        if (targetAcc->Role() == nsIAccessibleRole::ROLE_COMBOBOX)
+          return nsIAccessibleRole::ROLE_COMBOBOX_LIST;
     }
 
   } else if (mRoleMapEntry->role == nsIAccessibleRole::ROLE_OPTION) {
     if (mParent && mParent->Role() == nsIAccessibleRole::ROLE_COMBOBOX_LIST)
       return nsIAccessibleRole::ROLE_COMBOBOX_OPTION;
   }
 
   return mRoleMapEntry->role;
@@ -1993,252 +1993,153 @@ NS_IMETHODIMP nsAccessible::GetAccessibl
 }
 
 /* nsIAccessible getAccessibleBelow(); */
 NS_IMETHODIMP nsAccessible::GetAccessibleBelow(nsIAccessible **_retval)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-nsIDOMNode* nsAccessible::GetAtomicRegion()
+nsIContent*
+nsAccessible::GetAtomicRegion() const
 {
   nsIContent *loopContent = mContent;
   nsAutoString atomic;
-  while (loopContent && !loopContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_atomic, atomic)) {
+  while (loopContent && !loopContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_atomic, atomic))
     loopContent = loopContent->GetParent();
-  }
-
-  nsCOMPtr<nsIDOMNode> atomicRegion;
-  if (atomic.EqualsLiteral("true")) {
-    atomicRegion = do_QueryInterface(loopContent);
-  }
-  return atomicRegion;
+
+  return atomic.EqualsLiteral("true") ? loopContent : nsnull;
 }
 
 // nsIAccessible getRelationByType()
 NS_IMETHODIMP
-nsAccessible::GetRelationByType(PRUint32 aRelationType,
-                                nsIAccessibleRelation **aRelation)
+nsAccessible::GetRelationByType(PRUint32 aType,
+                                nsIAccessibleRelation** aRelation)
 {
   NS_ENSURE_ARG_POINTER(aRelation);
   *aRelation = nsnull;
-
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
+  Relation rel = RelationByType(aType);
+  NS_ADDREF(*aRelation = new nsAccessibleRelation(aType, &rel));
+  return *aRelation ? NS_OK : NS_ERROR_FAILURE;
+}
+
+Relation
+nsAccessible::RelationByType(PRUint32 aType)
+{
   // Relationships are defined on the same content node that the role would be
   // defined on.
-  nsresult rv = NS_OK_NO_RELATION_TARGET;
-  switch (aRelationType)
-  {
-  case nsIAccessibleRelation::RELATION_LABEL_FOR:
-    {
-      RelatedAccIterator iter(GetDocAccessible(), mContent,
-                              nsAccessibilityAtoms::aria_labelledby);
-
-      nsAccessible* related = nsnull;
-      while ((related = iter.Next())) {
-        rv = nsRelUtils::AddTarget(aRelationType, aRelation, related);
-        NS_ENSURE_SUCCESS(rv, rv);
-      }
-
-      if (mContent->Tag() == nsAccessibilityAtoms::label) {
-        nsIAtom *IDAttr = mContent->IsHTML() ?
-          nsAccessibilityAtoms::_for : nsAccessibilityAtoms::control;
-        rv = nsRelUtils::
-          AddTargetFromIDRefAttr(aRelationType, aRelation, mContent, IDAttr);
-        NS_ENSURE_SUCCESS(rv, rv);
-      }
-      return rv;
+  switch (aType) {
+    case nsIAccessibleRelation::RELATION_LABEL_FOR: {
+      Relation rel(new RelatedAccIterator(GetDocAccessible(), mContent,
+                                          nsAccessibilityAtoms::aria_labelledby));
+      if (mContent->Tag() == nsAccessibilityAtoms::label)
+        rel.AppendIter(new IDRefsIterator(mContent, mContent->IsHTML() ?
+                                          nsAccessibilityAtoms::_for :
+                                          nsAccessibilityAtoms::control));
+
+      return rel;
     }
-
-  case nsIAccessibleRelation::RELATION_LABELLED_BY:
-    {
-      rv = nsRelUtils::
-        AddTargetFromIDRefsAttr(aRelationType, aRelation, mContent,
-                                nsAccessibilityAtoms::aria_labelledby);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      nsAccessible* label = nsnull;
+    case nsIAccessibleRelation::RELATION_LABELLED_BY: {
+      Relation rel(new IDRefsIterator(mContent,
+                                      nsAccessibilityAtoms::aria_labelledby));
       if (mContent->IsHTML()) {
-        HTMLLabelIterator iter(GetDocAccessible(), mContent);
-        while ((label = iter.Next())) {
-          rv = nsRelUtils::AddTarget(aRelationType, aRelation, label);
-          NS_ENSURE_SUCCESS(rv, rv);
-        }
-        return rv;
+        rel.AppendIter(new HTMLLabelIterator(GetDocAccessible(), mContent));
+      } else if (mContent->IsXUL()) {
+        rel.AppendIter(new XULLabelIterator(GetDocAccessible(), mContent));
       }
 
-      if (mContent->IsXUL()) {
-        XULLabelIterator iter(GetDocAccessible(), mContent);
-        while ((label = iter.Next())) {
-          rv = nsRelUtils::AddTarget(aRelationType, aRelation, label);
-          NS_ENSURE_SUCCESS(rv, rv);
-        }
-      }
-      return rv;
+      return rel;
     }
-
-  case nsIAccessibleRelation::RELATION_DESCRIBED_BY:
-    {
-      rv = nsRelUtils::
-        AddTargetFromIDRefsAttr(aRelationType, aRelation, mContent,
-                                nsAccessibilityAtoms::aria_describedby);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      if (mContent->IsXUL()) {
-        XULDescriptionIterator iter(GetDocAccessible(), mContent);
-        nsAccessible* descr = nsnull;
-        while ((descr = iter.Next())) {
-          rv = nsRelUtils::AddTarget(aRelationType, aRelation, descr);
-          NS_ENSURE_SUCCESS(rv, rv);
-        }
-      }
-
-      return rv;
+    case nsIAccessibleRelation::RELATION_DESCRIBED_BY: {
+      Relation rel(new IDRefsIterator(mContent,
+                                        nsAccessibilityAtoms::aria_describedby));
+      if (mContent->IsXUL())
+        rel.AppendIter(new XULDescriptionIterator(GetDocAccessible(), mContent));
+
+      return rel;
     }
-
-  case nsIAccessibleRelation::RELATION_DESCRIPTION_FOR:
-    {
-      RelatedAccIterator iter(GetDocAccessible(), mContent,
-                              nsAccessibilityAtoms::aria_describedby);
-
-      nsAccessible* related = nsnull;
-      while ((related = iter.Next())) {
-        rv = nsRelUtils::AddTarget(aRelationType, aRelation, related);
-        NS_ENSURE_SUCCESS(rv, rv);
-      }
-
+    case nsIAccessibleRelation::RELATION_DESCRIPTION_FOR: {
+      Relation rel(new RelatedAccIterator(GetDocAccessible(), mContent,
+                                            nsAccessibilityAtoms::aria_describedby));
+
+      // This affectively adds an optional control attribute to xul:description,
+      // which only affects accessibility, by allowing the description to be
+      // tied to a control.
       if (mContent->Tag() == nsAccessibilityAtoms::description &&
-          mContent->IsXUL()) {
-        // This affectively adds an optional control attribute to xul:description,
-        // which only affects accessibility, by allowing the description to be
-        // tied to a control.
-        return nsRelUtils::
-          AddTargetFromIDRefAttr(aRelationType, aRelation, mContent,
-                                 nsAccessibilityAtoms::control);
-      }
-
-      return rv;
+          mContent->IsXUL())
+        rel.AppendIter(new IDRefsIterator(mContent,
+                                          nsAccessibilityAtoms::control));
+
+      return rel;
     }
-
-  case nsIAccessibleRelation::RELATION_NODE_CHILD_OF:
-    {
-      RelatedAccIterator iter(GetDocAccessible(), mContent,
-                              nsAccessibilityAtoms::aria_owns);
-
-      nsAccessible* related = nsnull;
-      while ((related = iter.Next())) {
-        rv = nsRelUtils::AddTarget(aRelationType, aRelation, related);
-        NS_ENSURE_SUCCESS(rv, rv);
-      }
-
-      // Got relation from aria-owns, don't calculate it from native markup.
-      if (rv != NS_OK_NO_RELATION_TARGET)
-        return NS_OK;
-
+    case nsIAccessibleRelation::RELATION_NODE_CHILD_OF: {
+      Relation rel(new RelatedAccIterator(GetDocAccessible(), mContent,
+                                            nsAccessibilityAtoms::aria_owns));
+      
       // This is an ARIA tree or treegrid that doesn't use owns, so we need to
       // get the parent the hard way.
       if (mRoleMapEntry &&
           (mRoleMapEntry->role == nsIAccessibleRole::ROLE_OUTLINEITEM ||
            mRoleMapEntry->role == nsIAccessibleRole::ROLE_ROW)) {
-
         AccGroupInfo* groupInfo = GetGroupInfo();
         if (!groupInfo)
-          return NS_OK_NO_RELATION_TARGET;
-
-        return nsRelUtils::AddTarget(aRelationType, aRelation,
-                                     groupInfo->ConceptualParent());
+          return rel;
+
+        rel.AppendTarget(groupInfo->ConceptualParent());
       }
 
       // If accessible is in its own Window, or is the root of a document,
       // then we should provide NODE_CHILD_OF relation so that MSAA clients
       // can easily get to true parent instead of getting to oleacc's
       // ROLE_WINDOW accessible which will prevent us from going up further
       // (because it is system generated and has no idea about the hierarchy
       // above it).
       nsIFrame *frame = GetFrame();
       if (frame) {
         nsIView *view = frame->GetViewExternal();
         if (view) {
           nsIScrollableFrame *scrollFrame = do_QueryFrame(frame);
           if (scrollFrame || view->GetWidget() || !frame->GetParent())
-            return nsRelUtils::AddTarget(aRelationType, aRelation, Parent());
+            rel.AppendTarget(Parent());
         }
       }
 
-      return rv;
-    }
-
-  case nsIAccessibleRelation::RELATION_CONTROLLED_BY:
-    {
-      RelatedAccIterator iter(GetDocAccessible(), mContent,
-                              nsAccessibilityAtoms::aria_controls);
-
-      nsAccessible* related = nsnull;
-      while ((related = iter.Next())) {
-        rv = nsRelUtils::AddTarget(aRelationType, aRelation, related);
-        NS_ENSURE_SUCCESS(rv, rv);
-      }
-      return rv;
+      return rel;
     }
-
-  case nsIAccessibleRelation::RELATION_CONTROLLER_FOR:
-    {
-      nsresult rv = nsRelUtils::
-        AddTargetFromIDRefsAttr(aRelationType, aRelation, mContent,
-                                nsAccessibilityAtoms::aria_controls);
-      NS_ENSURE_SUCCESS(rv,rv);
-
-      HTMLOutputIterator iter(GetDocAccessible(), mContent);
-      nsAccessible* related = nsnull;
-      while ((related = iter.Next())) {
-        rv = nsRelUtils::AddTarget(aRelationType, aRelation, related);
-        NS_ENSURE_SUCCESS(rv, rv);
-      }
-
-      return rv;
+    case nsIAccessibleRelation::RELATION_CONTROLLED_BY:
+      return Relation(new RelatedAccIterator(GetDocAccessible(), mContent,
+                                             nsAccessibilityAtoms::aria_controls));
+    case nsIAccessibleRelation::RELATION_CONTROLLER_FOR: {
+      Relation rel(new IDRefsIterator(mContent,
+                                      nsAccessibilityAtoms::aria_controls));
+      rel.AppendIter(new HTMLOutputIterator(GetDocAccessible(), mContent));
+      return rel;
     }
-
-  case nsIAccessibleRelation::RELATION_FLOWS_TO:
-    {
-      return nsRelUtils::
-        AddTargetFromIDRefsAttr(aRelationType, aRelation, mContent,
-                                nsAccessibilityAtoms::aria_flowto);
-    }
-
-  case nsIAccessibleRelation::RELATION_FLOWS_FROM:
-    {
-      RelatedAccIterator iter(GetDocAccessible(), mContent,
-                              nsAccessibilityAtoms::aria_flowto);
-
-      nsAccessible* related = nsnull;
-      while ((related = iter.Next())) {
-        rv = nsRelUtils::AddTarget(aRelationType, aRelation, related);
-        NS_ENSURE_SUCCESS(rv, rv);
-      }
-      return rv;
-    }
-
-  case nsIAccessibleRelation::RELATION_DEFAULT_BUTTON:
-    {
+    case nsIAccessibleRelation::RELATION_FLOWS_TO:
+      return Relation(new IDRefsIterator(mContent,
+                                         nsAccessibilityAtoms::aria_flowto));
+    case nsIAccessibleRelation::RELATION_FLOWS_FROM:
+      return Relation(new RelatedAccIterator(GetDocAccessible(), mContent,
+                                             nsAccessibilityAtoms::aria_flowto));
+    case nsIAccessibleRelation::RELATION_DEFAULT_BUTTON: {
       if (mContent->IsHTML()) {
         // HTML form controls implements nsIFormControl interface.
         nsCOMPtr<nsIFormControl> control(do_QueryInterface(mContent));
         if (control) {
           nsCOMPtr<nsIForm> form(do_QueryInterface(control->GetFormElement()));
           if (form) {
             nsCOMPtr<nsIContent> formContent =
               do_QueryInterface(form->GetDefaultSubmitElement());
-            return nsRelUtils::AddTargetFromContent(aRelationType, aRelation,
-                                                    formContent);
+            return Relation(formContent);
           }
         }
-      }
-      else {
+      } else {
         // In XUL, use first <button default="true" .../> in the document
         nsCOMPtr<nsIDOMXULDocument> xulDoc =
           do_QueryInterface(mContent->GetOwnerDoc());
         nsCOMPtr<nsIDOMXULButtonElement> buttonEl;
         if (xulDoc) {
           nsCOMPtr<nsIDOMNodeList> possibleDefaultButtons;
           xulDoc->GetElementsByAttribute(NS_LITERAL_STRING("default"),
                                          NS_LITERAL_STRING("true"),
@@ -2266,98 +2167,92 @@ nsAccessible::GetRelationByType(PRUint32
                                                       NS_LITERAL_STRING("default"),
                                                       NS_LITERAL_STRING("true"),
                                                       getter_AddRefs(possibleButtonEl));
                 buttonEl = do_QueryInterface(possibleButtonEl);
               }
             }
           }
           nsCOMPtr<nsIContent> relatedContent(do_QueryInterface(buttonEl));
-          return nsRelUtils::AddTargetFromContent(aRelationType, aRelation,
-                                                  relatedContent);
+          return Relation(relatedContent);
         }
       }
-      return NS_OK;
-    }
-
-  case nsIAccessibleRelation::RELATION_MEMBER_OF:
-    {
-      nsCOMPtr<nsIContent> regionContent = do_QueryInterface(GetAtomicRegion());
-      return nsRelUtils::
-        AddTargetFromContent(aRelationType, aRelation, regionContent);
+      return Relation();
     }
-
-  case nsIAccessibleRelation::RELATION_SUBWINDOW_OF:
-  case nsIAccessibleRelation::RELATION_EMBEDS:
-  case nsIAccessibleRelation::RELATION_EMBEDDED_BY:
-  case nsIAccessibleRelation::RELATION_POPUP_FOR:
-  case nsIAccessibleRelation::RELATION_PARENT_WINDOW_OF:
-    {
-      return NS_OK_NO_RELATION_TARGET;
-    }
-
-  default:
-    return NS_ERROR_INVALID_ARG;
+    case nsIAccessibleRelation::RELATION_MEMBER_OF:
+      return Relation(GetAtomicRegion());
+    case nsIAccessibleRelation::RELATION_SUBWINDOW_OF:
+    case nsIAccessibleRelation::RELATION_EMBEDS:
+    case nsIAccessibleRelation::RELATION_EMBEDDED_BY:
+    case nsIAccessibleRelation::RELATION_POPUP_FOR:
+    case nsIAccessibleRelation::RELATION_PARENT_WINDOW_OF:
+    default:
+    return Relation();
   }
 }
 
 NS_IMETHODIMP
-nsAccessible::GetRelationsCount(PRUint32 *aCount)
+nsAccessible::GetRelationsCount(PRUint32* aCount)
 {
   NS_ENSURE_ARG_POINTER(aCount);
   *aCount = 0;
 
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
   nsCOMPtr<nsIArray> relations;
   nsresult rv = GetRelations(getter_AddRefs(relations));
   NS_ENSURE_SUCCESS(rv, rv);
 
   return relations->GetLength(aCount);
 }
 
 NS_IMETHODIMP
-nsAccessible::GetRelation(PRUint32 aIndex, nsIAccessibleRelation **aRelation)
+nsAccessible::GetRelation(PRUint32 aIndex, nsIAccessibleRelation** aRelation)
 {
   NS_ENSURE_ARG_POINTER(aRelation);
   *aRelation = nsnull;
 
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
   nsCOMPtr<nsIArray> relations;
-  nsresult rv = GetRelations(getter_AddRefs(relations));
+  nsresult rv= GetRelations(getter_AddRefs(relations));
   NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIAccessibleRelation> relation;
-  rv = relations->QueryElementAt(aIndex, NS_GET_IID(nsIAccessibleRelation),
-                                 getter_AddRefs(relation));
-
-  // nsIArray::QueryElementAt() returns NS_ERROR_ILLEGAL_VALUE on invalid index.
-  if (rv == NS_ERROR_ILLEGAL_VALUE)
-    return NS_ERROR_INVALID_ARG;
-
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  NS_IF_ADDREF(*aRelation = relation);
-  return NS_OK;
+  nsCOMPtr<nsIAccessibleRelation> relation = do_QueryElementAt(relations,
+                                                               aIndex, &rv);
+  NS_ADDREF(*aRelation = relation);
+  return rv;
 }
 
 NS_IMETHODIMP
 nsAccessible::GetRelations(nsIArray **aRelations)
 {
   NS_ENSURE_ARG_POINTER(aRelations);
+  *aRelations = nsnull;
+
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsIMutableArray> relations = do_CreateInstance(NS_ARRAY_CONTRACTID);
   NS_ENSURE_TRUE(relations, NS_ERROR_OUT_OF_MEMORY);
 
   for (PRUint32 relType = nsIAccessibleRelation::RELATION_FIRST;
        relType < nsIAccessibleRelation::RELATION_LAST;
        ++relType) {
 
     nsCOMPtr<nsIAccessibleRelation> relation;
     nsresult rv = GetRelationByType(relType, getter_AddRefs(relation));
 
-    if (NS_SUCCEEDED(rv) && relation)
-      relations->AppendElement(relation, PR_FALSE);
+    if (NS_SUCCEEDED(rv) && relation) {
+      PRUint32 targets = 0;
+      relation->GetTargetsCount(&targets);
+      if (targets)
+        relations->AppendElement(relation, PR_FALSE);
+    }
   }
 
   NS_ADDREF(*aRelations = relations);
   return NS_OK;
 }
 
 /* void extendSelection (); */
 NS_IMETHODIMP nsAccessible::ExtendSelection()
@@ -2969,114 +2864,114 @@ already_AddRefed<nsIArray>
 nsAccessible::SelectedItems()
 {
   nsCOMPtr<nsIMutableArray> selectedItems = do_CreateInstance(NS_ARRAY_CONTRACTID);
   if (!selectedItems)
     return nsnull;
 
   AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav);
   nsIAccessible* selected = nsnull;
-  while ((selected = iter.GetNext()))
+  while ((selected = iter.Next()))
     selectedItems->AppendElement(selected, PR_FALSE);
 
   nsIMutableArray* items = nsnull;
   selectedItems.forget(&items);
   return items;
 }
 
 PRUint32
 nsAccessible::SelectedItemCount()
 {
   PRUint32 count = 0;
   AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav);
   nsAccessible* selected = nsnull;
-  while ((selected = iter.GetNext()))
+  while ((selected = iter.Next()))
     ++count;
 
   return count;
 }
 
 nsAccessible*
 nsAccessible::GetSelectedItem(PRUint32 aIndex)
 {
   AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav);
   nsAccessible* selected = nsnull;
 
   PRUint32 index = 0;
-  while ((selected = iter.GetNext()) && index < aIndex)
+  while ((selected = iter.Next()) && index < aIndex)
     index++;
 
   return selected;
 }
 
 bool
 nsAccessible::IsItemSelected(PRUint32 aIndex)
 {
   PRUint32 index = 0;
   AccIterator iter(this, filters::GetSelectable, AccIterator::eTreeNav);
   nsAccessible* selected = nsnull;
-  while ((selected = iter.GetNext()) && index < aIndex)
+  while ((selected = iter.Next()) && index < aIndex)
     index++;
 
   return selected &&
     selected->State() & states::SELECTED;
 }
 
 bool
 nsAccessible::AddItemToSelection(PRUint32 aIndex)
 {
   PRUint32 index = 0;
   AccIterator iter(this, filters::GetSelectable, AccIterator::eTreeNav);
   nsAccessible* selected = nsnull;
-  while ((selected = iter.GetNext()) && index < aIndex)
+  while ((selected = iter.Next()) && index < aIndex)
     index++;
 
   if (selected)
     selected->SetSelected(PR_TRUE);
 
   return static_cast<bool>(selected);
 }
 
 bool
 nsAccessible::RemoveItemFromSelection(PRUint32 aIndex)
 {
   PRUint32 index = 0;
   AccIterator iter(this, filters::GetSelectable, AccIterator::eTreeNav);
   nsAccessible* selected = nsnull;
-  while ((selected = iter.GetNext()) && index < aIndex)
+  while ((selected = iter.Next()) && index < aIndex)
     index++;
 
   if (selected)
     selected->SetSelected(PR_FALSE);
 
   return static_cast<bool>(selected);
 }
 
 bool
 nsAccessible::SelectAll()
 {
   bool success = false;
   nsAccessible* selectable = nsnull;
 
   AccIterator iter(this, filters::GetSelectable, AccIterator::eTreeNav);
-  while((selectable = iter.GetNext())) {
+  while((selectable = iter.Next())) {
     success = true;
     selectable->SetSelected(PR_TRUE);
   }
   return success;
 }
 
 bool
 nsAccessible::UnselectAll()
 {
   bool success = false;
   nsAccessible* selected = nsnull;
 
   AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav);
-  while ((selected = iter.GetNext())) {
+  while ((selected = iter.Next())) {
     success = true;
     selected->SetSelected(PR_FALSE);
   }
   return success;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -57,16 +57,17 @@
 class AccEvent;
 class AccGroupInfo;
 class EmbeddedObjCollector;
 class KeyBinding;
 class nsAccessible;
 class nsHyperTextAccessible;
 class nsHTMLLIAccessible;
 struct nsRoleMapEntry;
+class Relation;
 class nsTextAccessible;
 
 struct nsRect;
 class nsIContent;
 class nsIFrame;
 class nsIAtom;
 class nsIView;
 
@@ -232,16 +233,21 @@ public:
    * on accessible hierarchy.
    *
    * @param  aPosInSet  [out] accessible position in the group
    * @param  aSetSize   [out] the group size
    */
   virtual void GetPositionAndSizeInternal(PRInt32 *aPosInSet,
                                           PRInt32 *aSetSize);
 
+  /**
+   * Get the relation of the given type.
+   */
+  virtual Relation RelationByType(PRUint32 aType);
+
   //////////////////////////////////////////////////////////////////////////////
   // Initializing methods
 
   /**
    * Set the ARIA role map entry for a new accessible.
    * For a newly created accessible, specify which role map entry should be used.
    *
    * @param aRoleMapEntry The ARIA nsRoleMapEntry* for the accessible, or 
@@ -662,17 +668,17 @@ protected:
 
   //////////////////////////////////////////////////////////////////////////////
   // Helpers
 
   /**
    *  Get the container node for an atomic region, defined by aria-atomic="true"
    *  @return the container node
    */
-  nsIDOMNode* GetAtomicRegion();
+  nsIContent* GetAtomicRegion() const;
 
   /**
    * Get numeric value of the given ARIA attribute.
    *
    * @param aAriaProperty - the ARIA property we're using
    * @param aValue - value of the attribute
    *
    * @return - NS_OK_NO_ARIA_VALUE if there is no setted ARIA attribute
--- a/accessible/src/base/nsApplicationAccessible.cpp
+++ b/accessible/src/base/nsApplicationAccessible.cpp
@@ -37,16 +37,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 "nsApplicationAccessible.h"
 
+#include "Relation.h"
 #include "States.h"
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
 
 #include "nsIComponentManager.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMWindow.h"
 #include "nsIWindowMediator.h"
@@ -165,48 +166,32 @@ nsApplicationAccessible::GroupPosition(P
 
 nsAccessible*
 nsApplicationAccessible::ChildAtPoint(PRInt32 aX, PRInt32 aY,
                                       EWhichChildAtPoint aWhichChild)
 {
   return nsnull;
 }
 
-NS_IMETHODIMP
-nsApplicationAccessible::GetRelationByType(PRUint32 aRelationType,
-                                           nsIAccessibleRelation **aRelation)
+nsAccessible*
+nsApplicationAccessible::FocusedChild()
 {
-  NS_ENSURE_ARG_POINTER(aRelation);
-  *aRelation = nsnull;
-  return NS_OK;
+  if (gLastFocusedNode) {
+    nsAccessible* focusedChild =
+      GetAccService()->GetAccessible(gLastFocusedNode);
+    if (focusedChild && focusedChild->Parent() == this)
+      return focusedChild;
+  }
+  return nsnull;
 }
 
-NS_IMETHODIMP
-nsApplicationAccessible::GetRelationsCount(PRUint32 *aCount)
-{
-  NS_ENSURE_ARG_POINTER(aCount);
-  *aCount = 0;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsApplicationAccessible::GetRelation(PRUint32 aIndex,
-                                     nsIAccessibleRelation **aRelation)
+Relation
+nsApplicationAccessible::RelationByType(PRUint32 aRelationType)
 {
-  NS_ENSURE_ARG_POINTER(aRelation);
-  *aRelation = nsnull;
-  return NS_ERROR_INVALID_ARG;
-}
-
-NS_IMETHODIMP
-nsApplicationAccessible::GetRelations(nsIArray **aRelations)
-{
-  NS_ENSURE_ARG_POINTER(aRelations);
-  *aRelations = nsnull;
-  return NS_OK;
+  return Relation();
 }
 
 NS_IMETHODIMP
 nsApplicationAccessible::GetBounds(PRInt32 *aX, PRInt32 *aY,
                                    PRInt32 *aWidth, PRInt32 *aHeight)
 {
   NS_ENSURE_ARG_POINTER(aX);
   *aX = 0;
--- a/accessible/src/base/nsApplicationAccessible.h
+++ b/accessible/src/base/nsApplicationAccessible.h
@@ -88,21 +88,16 @@ public:
   NS_IMETHOD GetParent(nsIAccessible **aParent);
   NS_IMETHOD GetNextSibling(nsIAccessible **aNextSibling);
   NS_IMETHOD GetPreviousSibling(nsIAccessible **aPreviousSibling);
   NS_IMETHOD GetName(nsAString &aName);
   NS_IMETHOD GetValue(nsAString &aValue);
   NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
   NS_IMETHOD GroupPosition(PRInt32 *aGroupLevel, PRInt32 *aSimilarItemsInGroup,
                            PRInt32 *aPositionInGroup);
-  NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
-                               nsIAccessibleRelation **aRelation);
-  NS_IMETHOD GetRelationsCount(PRUint32 *aRelationsCount);
-  NS_IMETHOD GetRelation(PRUint32 aIndex, nsIAccessibleRelation **aRelation);
-  NS_IMETHOD GetRelations(nsIArray **aRelations);
   NS_IMETHOD GetBounds(PRInt32 *aX, PRInt32 *aY,
                        PRInt32 *aWidth, PRInt32 *aHeight);
   NS_IMETHOD SetSelected(PRBool aIsSelected);
   NS_IMETHOD TakeSelection();
   NS_IMETHOD TakeFocus();
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString &aName);
   NS_IMETHOD GetActionDescription(PRUint8 aIndex, nsAString &aDescription);
   NS_IMETHOD DoAction(PRUint8 aIndex);
@@ -117,18 +112,21 @@ public:
   virtual bool IsPrimaryForNode() const;
 
   // nsAccessible
   virtual void ApplyARIAState(PRUint64* aState);
   virtual void Description(nsString& aDescription);
   virtual PRUint32 NativeRole();
   virtual PRUint64 State();
   virtual PRUint64 NativeState();
+  virtual Relation RelationByType(PRUint32 aRelType);
+
   virtual nsAccessible* ChildAtPoint(PRInt32 aX, PRInt32 aY,
                                      EWhichChildAtPoint aWhichChild);
+  virtual nsAccessible* FocusedChild();
 
   virtual void InvalidateChildren();
 
   // ActionAccessible
   virtual PRUint8 ActionCount();
   virtual KeyBinding AccessKey() const;
 
 protected:
--- a/accessible/src/base/nsCaretAccessible.cpp
+++ b/accessible/src/base/nsCaretAccessible.cpp
@@ -206,20 +206,20 @@ nsCaretAccessible::NotifySelectionChange
 {
   NS_ENSURE_ARG(aDOMDocument);
   NS_ENSURE_STATE(mRootAccessible);
 
   nsCOMPtr<nsIDocument> documentNode(do_QueryInterface(aDOMDocument));
   nsDocAccessible* document = GetAccService()->GetDocAccessible(documentNode);
 
 #ifdef DEBUG_NOTIFICATIONS
-  nsCOMPtr<nsISelection2> sel2(do_QueryInterface(aSelection));
+  nsCOMPtr<nsISelectionPrivate> privSel(do_QueryInterface(aSelection));
 
   PRInt16 type = 0;
-  sel2->GetType(&type);
+  privSel->GetType(&type);
 
   if (type == nsISelectionController::SELECTION_NORMAL ||
       type == nsISelectionController::SELECTION_SPELLCHECK) {
 
     bool isNormalSelection =
       (type == nsISelectionController::SELECTION_NORMAL);
 
     bool isIgnored = !document || !document->IsContentLoaded();
@@ -240,20 +240,20 @@ nsCaretAccessible::NotifySelectionChange
   }
 
   return NS_OK;
 }
 
 void
 nsCaretAccessible::ProcessSelectionChanged(nsISelection* aSelection)
 {
-  nsCOMPtr<nsISelection2> sel2(do_QueryInterface(aSelection));
+  nsCOMPtr<nsISelectionPrivate> privSel(do_QueryInterface(aSelection));
 
   PRInt16 type = 0;
-  sel2->GetType(&type);
+  privSel->GetType(&type);
 
   if (type == nsISelectionController::SELECTION_NORMAL)
     NormalSelectionChanged(aSelection);
 
   else if (type == nsISelectionController::SELECTION_SPELLCHECK)
     SpellcheckSelectionChanged(aSelection);
 }
 
--- a/accessible/src/base/nsCaretAccessible.h
+++ b/accessible/src/base/nsCaretAccessible.h
@@ -37,17 +37,16 @@
 
 #ifndef __nsCaretAccessible_h__
 #define __nsCaretAccessible_h__
 
 #include "NotificationController.h"
 #include "nsHyperTextAccessible.h"
 
 #include "nsISelectionListener.h"
-#include "nsISelection2.h"
 
 class nsRootAccessible;
 
 /*
  * This special accessibility class is for the caret, which is really the currently focused selection.
  * There is only 1 visible caret per top level window (nsRootAccessible),
  * However, there may be several visible selections.
  *
--- a/accessible/src/base/nsCoreUtils.cpp
+++ b/accessible/src/base/nsCoreUtils.cpp
@@ -51,17 +51,17 @@
 #include "nsIDOMXULElement.h"
 #include "nsIDocShell.h"
 #include "nsIContentViewer.h"
 #include "nsEventListenerManager.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsIScrollableFrame.h"
 #include "nsEventStateManager.h"
-#include "nsISelection2.h"
+#include "nsISelectionPrivate.h"
 #include "nsISelectionController.h"
 #include "nsPIDOMWindow.h"
 #include "nsGUIEvent.h"
 #include "nsIView.h"
 #include "nsLayoutUtils.h"
 
 #include "nsContentCID.h"
 #include "nsComponentManagerUtils.h"
@@ -326,30 +326,28 @@ nsCoreUtils::ScrollSubstringTo(nsIFrame 
 
   nsCOMPtr<nsISelectionController> selCon;
   aFrame->GetSelectionController(presContext, getter_AddRefs(selCon));
   NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
 
   scrollToRange->SetStart(aStartNode, aStartIndex);
   scrollToRange->SetEnd(aEndNode, aEndIndex);
 
-  nsCOMPtr<nsISelection> selection1;
+  nsCOMPtr<nsISelection> selection;
   selCon->GetSelection(nsISelectionController::SELECTION_ACCESSIBILITY,
-                       getter_AddRefs(selection1));
+                       getter_AddRefs(selection));
 
-  nsCOMPtr<nsISelection2> selection(do_QueryInterface(selection1));
-  if (selection) {
-    selection->RemoveAllRanges();
-    selection->AddRange(scrollToRange);
+  nsCOMPtr<nsISelectionPrivate> privSel(do_QueryInterface(selection));
+  selection->RemoveAllRanges();
+  selection->AddRange(scrollToRange);
 
-    selection->ScrollIntoView(nsISelectionController::SELECTION_ANCHOR_REGION,
-                              PR_TRUE, aVPercent, aHPercent);
+  privSel->ScrollIntoView(nsISelectionController::SELECTION_ANCHOR_REGION,
+                          PR_TRUE, aVPercent, aHPercent);
 
-    selection->CollapseToStart();
-  }
+  selection->CollapseToStart();
 
   return NS_OK;
 }
 
 void
 nsCoreUtils::ScrollFrameToPoint(nsIFrame *aScrollableFrame,
                                 nsIFrame *aFrame,
                                 const nsIntPoint& aPoint)
@@ -825,82 +823,8 @@ nsAccessibleDOMStringList::GetLength(PRU
 NS_IMETHODIMP
 nsAccessibleDOMStringList::Contains(const nsAString& aString, PRBool *aResult)
 {
   *aResult = mNames.Contains(aString);
 
   return NS_OK;
 }
 
-
-////////////////////////////////////////////////////////////////////////////////
-// IDRefsIterator
-////////////////////////////////////////////////////////////////////////////////
-
-IDRefsIterator::IDRefsIterator(nsIContent* aContent, nsIAtom* aIDRefsAttr) :
-  mCurrIdx(0)
-{
-  if (!aContent->IsInDoc() ||
-      !aContent->GetAttr(kNameSpaceID_None, aIDRefsAttr, mIDs))
-    return;
-
-  if (aContent->IsInAnonymousSubtree()) {
-    mXBLDocument = do_QueryInterface(aContent->GetOwnerDoc());
-    mBindingParent = do_QueryInterface(aContent->GetBindingParent());
-  } else {
-    mDocument = aContent->GetOwnerDoc();
-  }
-}
-
-const nsDependentSubstring
-IDRefsIterator::NextID()
-{
-  for (; mCurrIdx < mIDs.Length(); mCurrIdx++) {
-    if (!NS_IsAsciiWhitespace(mIDs[mCurrIdx]))
-      break;
-  }
-
-  if (mCurrIdx >= mIDs.Length())
-    return nsDependentSubstring();
-
-  nsAString::index_type idStartIdx = mCurrIdx;
-  while (++mCurrIdx < mIDs.Length()) {
-    if (NS_IsAsciiWhitespace(mIDs[mCurrIdx]))
-      break;
-  }
-
-  return Substring(mIDs, idStartIdx, mCurrIdx++ - idStartIdx);
-}
-
-nsIContent*
-IDRefsIterator::NextElem()
-{
-  while (true) {
-    const nsDependentSubstring id = NextID();
-    if (id.IsEmpty())
-      break;
-
-    nsIContent* refContent = GetElem(id);
-    if (refContent)
-      return refContent;
-  }
-
-  return nsnull;
-}
-
-nsIContent*
-IDRefsIterator::GetElem(const nsDependentSubstring& aID)
-{
-  if (mXBLDocument) {
-    // If content is anonymous subtree then use "anonid" attribute to get
-    // elements, otherwise search elements in DOM by ID attribute.
-
-    nsCOMPtr<nsIDOMElement> refElm;
-    mXBLDocument->GetAnonymousElementByAttribute(mBindingParent,
-                                                 NS_LITERAL_STRING("anonid"),
-                                                 aID,
-                                                 getter_AddRefs(refElm));
-    nsCOMPtr<nsIContent> refContent = do_QueryInterface(refElm);
-    return refContent;
-  }
-
-  return mDocument->GetElementById(aID);
-}
--- a/accessible/src/base/nsCoreUtils.h
+++ b/accessible/src/base/nsCoreUtils.h
@@ -36,17 +36,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsCoreUtils_h_
 #define nsCoreUtils_h_
 
 #include "nsAccessibilityAtoms.h"
 
-#include "nsIDOMDocumentXBL.h"
 #include "nsIDOMNode.h"
 #include "nsIContent.h"
 #include "nsIBoxObject.h"
 #include "nsITreeBoxObject.h"
 #include "nsITreeColumns.h"
 
 #include "nsIFrame.h"
 #include "nsIDocShellTreeItem.h"
@@ -396,44 +395,10 @@ public:
   PRBool Add(const nsAString& aName) {
     return mNames.AppendElement(aName) != nsnull;
   }
 
 private:
   nsTArray<nsString> mNames;
 };
 
-/**
- * Used to iterate through IDs or elements pointed by IDRefs attribute. Note,
- * any method used to iterate through IDs or elements moves iterator to next
- * position.
- */
-class IDRefsIterator
-{
-public:
-  IDRefsIterator(nsIContent* aContent, nsIAtom* aIDRefsAttr);
-
-  /**
-   * Return next ID.
-   */
-  const nsDependentSubstring NextID();
-
-  /**
-   * Return next element.
-   */
-  nsIContent* NextElem();
-
-  /**
-   * Return the element with the given ID.
-   */
-  nsIContent* GetElem(const nsDependentSubstring& aID);
-
-private:
-  nsString mIDs;
-  nsAString::index_type mCurrIdx;
-
-  nsIDocument* mDocument;
-  nsCOMPtr<nsIDOMDocumentXBL> mXBLDocument;
-  nsCOMPtr<nsIDOMElement> mBindingParent;
-};
-
 #endif
 
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -31,16 +31,17 @@
  * 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 "AccIterator.h"
 #include "States.h"
 #include "nsAccCache.h"
 #include "nsAccessibilityAtoms.h"
 #include "nsAccessibilityService.h"
 #include "nsAccTreeWalker.h"
 #include "nsAccUtils.h"
 #include "nsRootAccessible.h"
 #include "nsTextEquivUtils.h"
deleted file mode 100644
--- a/accessible/src/base/nsRelUtils.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsRelUtils.h"
-
-#include "nsAccessibilityService.h"
-#include "nsAccessible.h"
-#include "nsCoreUtils.h"
-
-#include "nsIDOMDocument.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMDocumentXBL.h"
-
-#include "nsAutoPtr.h"
-#include "nsArrayUtils.h"
-
-already_AddRefed<nsIAccessible>
-nsRelUtils::GetRelatedAccessible(nsIAccessible *aAccessible,
-                                 PRUint32 aRelationType)
-{
-  nsCOMPtr<nsIAccessibleRelation> relation;
-  nsresult rv = aAccessible->GetRelationByType(aRelationType,
-                                               getter_AddRefs(relation));
-  if (NS_FAILED(rv) || !relation)
-    return nsnull;
-
-  nsIAccessible *targetAccessible = nsnull;
-  rv = relation->GetTarget(0, &targetAccessible);
-  return targetAccessible;
-}
-
-nsresult
-nsRelUtils::AddTarget(PRUint32 aRelationType, nsIAccessibleRelation **aRelation,
-                      nsIAccessible *aTarget)
-{
-  if (!aTarget)
-    return NS_OK_NO_RELATION_TARGET;
-
-  if (*aRelation) {
-    nsRefPtr<nsAccessibleRelation> relation = QueryAccRelation(*aRelation);
-    return relation->AddTarget(aTarget);
-  }
-
-  *aRelation = new nsAccessibleRelationWrap(aRelationType, aTarget);
-  NS_ENSURE_TRUE(*aRelation, NS_ERROR_OUT_OF_MEMORY);
-
-  NS_ADDREF(*aRelation);
-  return NS_OK;
-}
-
-nsresult
-nsRelUtils::AddTargetFromContent(PRUint32 aRelationType,
-                                 nsIAccessibleRelation **aRelation,
-                                 nsIContent *aContent)
-{
-  if (!aContent)
-    return NS_OK_NO_RELATION_TARGET;
-
-  nsAccessible* accessible = GetAccService()->GetAccessible(aContent);
-  return AddTarget(aRelationType, aRelation, accessible);
-}
-
-nsresult
-nsRelUtils::AddTargetFromIDRefAttr(PRUint32 aRelationType,
-                                   nsIAccessibleRelation **aRelation,
-                                   nsIContent *aContent, nsIAtom *aAttr,
-                                   PRBool aMayBeAnon)
-{
-  nsAutoString id;
-  if (!aContent->GetAttr(kNameSpaceID_None, aAttr, id))
-    return NS_OK_NO_RELATION_TARGET;
-
-  nsCOMPtr<nsIDOMDocument> document =
-    do_QueryInterface(aContent->GetOwnerDoc());
-  NS_ASSERTION(document, "The given node is not in document!");
-  if (!document)
-    return NS_OK_NO_RELATION_TARGET;
-
-  nsCOMPtr<nsIDOMElement> refElm;
-  if (aMayBeAnon && aContent->GetBindingParent()) {
-    nsCOMPtr<nsIDOMDocumentXBL> documentXBL(do_QueryInterface(document));
-    nsCOMPtr<nsIDOMElement> bindingParent =
-      do_QueryInterface(aContent->GetBindingParent());
-    documentXBL->GetAnonymousElementByAttribute(bindingParent,
-                                                NS_LITERAL_STRING("id"),
-                                                id,
-                                                getter_AddRefs(refElm));
-  }
-  else {
-    document->GetElementById(id, getter_AddRefs(refElm));
-  }
-
-  nsCOMPtr<nsIContent> refContent(do_QueryInterface(refElm));
-  return AddTargetFromContent(aRelationType, aRelation, refContent);
-}
-
-nsresult
-nsRelUtils::AddTargetFromIDRefsAttr(PRUint32 aRelationType,
-                                    nsIAccessibleRelation **aRelation,
-                                    nsIContent *aContent, nsIAtom *aAttr)
-{
-  nsresult rv = NS_OK_NO_RELATION_TARGET;
-
-  nsIContent* refElm = nsnull;
-  IDRefsIterator iter(aContent, aAttr);
-  while ((refElm = iter.NextElem())) {
-    rv = AddTargetFromContent(aRelationType, aRelation, refElm);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  return rv;
-}
deleted file mode 100644
--- a/accessible/src/base/nsRelUtils.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef _nsRelUtils_H_
-#define _nsRelUtils_H_
-
-#include "nsAccessibleRelationWrap.h"
-
-#include "nsIAtom.h"
-#include "nsIContent.h"
-
-// Used by AddTarget...() methods. Returned when can't get target accessible.
-#define NS_OK_NO_RELATION_TARGET \
-NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_GENERAL, 0x24)
-
-/**
- * Utils class designed to work with accessible relations.
- */
-class nsRelUtils
-{
-public:
-  /**
-   * Return first target of the relation of the given relation type for
-   * the given accessible.
-   *
-   * @param aAccessible   [in] the accessible to get an relation
-   * @param aRelationType [in] relation type
-   * @return              an accessible
-   */
-  static already_AddRefed<nsIAccessible>
-    GetRelatedAccessible(nsIAccessible *aAccessible, PRUint32 aRelationType);
-
-  /**
-   * Create the relation if the given relation is null. Add target to it
-   * which is the given accessible.
-   *
-   * @param  aRelationType  [in] relation type
-   * @param  aRelation      [in, out] relation object
-   * @param  aTarget        [in] accessible object
-   */
-  static nsresult AddTarget(PRUint32 aRelationType,
-                            nsIAccessibleRelation **aRelation,
-                            nsIAccessible *aTarget);
-
-  /**
-   * Create the relation if the given relation is null and add the target to it
-   * which is the accessible for the given node.
-   *
-   * @param  aRelationType  [in] relation type
-   * @param  aRelation      [in, out] relation object
-   * @param  aContent       [in] accessible node
-   */
-  static nsresult AddTargetFromContent(PRUint32 aRelationType,
-                                       nsIAccessibleRelation **aRelation,
-                                       nsIContent *aContent);
-
-  /**
-   * Create the relation if the given relation is null and add the target to it
-   * pointed by IDRef attribute on the given node.
-   *
-   * @param  aRelationType  [in] relation type
-   * @param  aRelation      [in, out] relation object
-   * @param  aContent       [in] node having the given IDRef attribute
-   * @param  aAttr          [in] IDRef attribute
-   * @param  aMayBeAnon     [in] true if the target may be anonymous; if so,
-   *                             we need to look for it under the binding
-   *                             parent of aContent.
-   */
-  static nsresult AddTargetFromIDRefAttr(PRUint32 aRelationType,
-                                         nsIAccessibleRelation **aRelation,
-                                         nsIContent *aContent, nsIAtom *aAttr,
-                                         PRBool aMayBeAnon = PR_FALSE);
-
-  /**
-   * Create the relation if the given relation is null and add the targets to it
-   * that are pointed by IDRefs attribute on the given node.
-   *
-   * @param  aRelationType  [in] relation type
-   * @param  aRelation      [in, out] relation object
-   * @param  aContent       [in] node having the given IDRefs attribute
-   * @param  aAttr          [in] IDRefs attribute
-   */
-  static nsresult AddTargetFromIDRefsAttr(PRUint32 aRelationType,
-                                          nsIAccessibleRelation **aRelation,
-                                          nsIContent *aContent, nsIAtom *aAttr);
-
-  /**
-   * Query nsAccessibleRelation from the given nsIAccessibleRelation.
-   */
-  static already_AddRefed<nsAccessibleRelation>
-  QueryAccRelation(nsIAccessibleRelation *aRelation)
-  {
-    nsAccessibleRelation* relation = nsnull;
-    if (aRelation)
-      CallQueryInterface(aRelation, &relation);
-
-    return relation;
-  }
-};
-
-#endif
--- a/accessible/src/base/nsRootAccessible.cpp
+++ b/accessible/src/base/nsRootAccessible.cpp
@@ -33,25 +33,26 @@
  * 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 ***** */
 
 #define CreateEvent CreateEventA
 #include "nsIDOMDocument.h"
 
-#include "States.h"
 #include "nsAccessibilityService.h"
 #include "nsApplicationAccessibleWrap.h"
 #include "nsAccUtils.h"
 #include "nsCoreUtils.h"
-#include "nsRelUtils.h"
+#include "Relation.h"
+#include "States.h"
 
 #include "mozilla/dom/Element.h"
 #include "nsHTMLSelectAccessible.h"
+#include "nsIAccessibleRelation.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDocShellTreeNode.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMEventListener.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOMHTMLAnchorElement.h"
@@ -825,37 +826,30 @@ nsRootAccessible::GetContentDocShell(nsI
         return aStart;
       }
     }
   }
   return nsnull;
 }
 
 // nsIAccessible method
-NS_IMETHODIMP
-nsRootAccessible::GetRelationByType(PRUint32 aRelationType,
-                                    nsIAccessibleRelation **aRelation)
+Relation
+nsRootAccessible::RelationByType(PRUint32 aType)
 {
-  NS_ENSURE_ARG_POINTER(aRelation);
-  *aRelation = nsnull;
-
-  if (!mDocument || aRelationType != nsIAccessibleRelation::RELATION_EMBEDS) {
-    return nsDocAccessibleWrap::GetRelationByType(aRelationType, aRelation);
-  }
+  if (!mDocument || aType != nsIAccessibleRelation::RELATION_EMBEDS)
+    return nsDocAccessibleWrap::RelationByType(aType);
 
   nsCOMPtr<nsIDocShellTreeItem> treeItem =
     nsCoreUtils::GetDocShellTreeItemFor(mDocument);
   nsCOMPtr<nsIDocShellTreeItem> contentTreeItem = GetContentDocShell(treeItem);
   // there may be no content area, so we need a null check
-  if (contentTreeItem) {
-    nsDocAccessible *accDoc = nsAccUtils::GetDocAccessibleFor(contentTreeItem);
-    return nsRelUtils::AddTarget(aRelationType, aRelation, accDoc);
-  }
+  if (!contentTreeItem)
+    return Relation();
 
-  return NS_OK;
+  return Relation(nsAccUtils::GetDocAccessibleFor(contentTreeItem));
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Protected members
 
 void
 nsRootAccessible::HandlePopupShownEvent(nsAccessible* aAccessible)
 {
--- a/accessible/src/base/nsRootAccessible.h
+++ b/accessible/src/base/nsRootAccessible.h
@@ -46,16 +46,18 @@
 #include "nsXULTreeAccessible.h"
 #endif
 
 #include "nsHashtable.h"
 #include "nsCaretAccessible.h"
 #include "nsIDocument.h"
 #include "nsIDOMEventListener.h"
 
+class Relation;
+
 #define NS_ROOTACCESSIBLE_IMPL_CID                      \
 {  /* eaba2cf0-21b1-4e2b-b711-d3a89dcd5e1a */           \
   0xeaba2cf0,                                           \
   0x21b1,                                               \
   0x4e2b,                                               \
   { 0xb7, 0x11, 0xd3, 0xa8, 0x9d, 0xcd, 0x5e, 0x1a }    \
 }
 
@@ -68,26 +70,25 @@ class nsRootAccessible : public nsDocAcc
 
 public:
   nsRootAccessible(nsIDocument *aDocument, nsIContent *aRootContent,
                    nsIWeakReference *aShell);
   virtual ~nsRootAccessible();
 
   // nsIAccessible
   NS_IMETHOD GetName(nsAString& aName);
-  NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
-                               nsIAccessibleRelation **aRelation);
 
   // nsIDOMEventListener
   NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
 
   // nsAccessNode
   virtual void Shutdown();
 
   // nsAccessible
+  virtual Relation RelationByType(PRUint32 aType);
   virtual PRUint32 NativeRole();
   virtual PRUint64 NativeState();
 
   // nsRootAccessible
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ROOTACCESSIBLE_IMPL_CID)
 
   /**
    * Fire an accessible focus event for the focused accessible and attach a new
--- a/accessible/src/base/nsTextAttrs.cpp
+++ b/accessible/src/base/nsTextAttrs.cpp
@@ -142,17 +142,17 @@ nsTextAttrsMgr::GetAttributes(nsIPersist
   nsIContent *offsetNode = nsnull, *offsetElm = nsnull;
   nsIFrame *frame = nsnull;
   if (mOffsetAcc) {
     offsetNode = mOffsetAcc->GetContent();
     offsetElm = nsCoreUtils::GetDOMElementFor(offsetNode);
     frame = offsetElm->GetPrimaryFrame();
   }
 
-  nsTPtrArray<nsITextAttr> textAttrArray(10);
+  nsTArray<nsITextAttr*> textAttrArray(10);
 
   // "language" text attribute
   nsLangTextAttr langTextAttr(mHyperTextAcc, hyperTextElm, offsetNode);
   textAttrArray.AppendElement(static_cast<nsITextAttr*>(&langTextAttr));
 
   // "color" text attribute
   nsCSSTextAttr colorTextAttr(0, hyperTextElm, offsetElm);
   textAttrArray.AppendElement(static_cast<nsITextAttr*>(&colorTextAttr));
@@ -207,17 +207,17 @@ nsTextAttrsMgr::GetAttributes(nsIPersist
   if (mOffsetAcc)
     rv = GetRange(textAttrArray, aStartHTOffset, aEndHTOffset);
 
   textAttrArray.Clear();
   return rv;
 }
 
 nsresult
-nsTextAttrsMgr::GetRange(const nsTPtrArray<nsITextAttr>& aTextAttrArray,
+nsTextAttrsMgr::GetRange(const nsTArray<nsITextAttr*>& aTextAttrArray,
                          PRInt32 *aStartHTOffset, PRInt32 *aEndHTOffset)
 {
   PRUint32 attrLen = aTextAttrArray.Length();
 
   // Navigate backward from anchor accessible to find start offset.
   for (PRInt32 childIdx = mOffsetAccIdx - 1; childIdx >= 0; childIdx--) {
     nsAccessible *currAcc = mHyperTextAcc->GetChildAt(childIdx);
 
--- a/accessible/src/base/nsTextAttrs.h
+++ b/accessible/src/base/nsTextAttrs.h
@@ -47,17 +47,16 @@ class nsHyperTextAccessible;
 #include "nsIDOMElement.h"
 
 #include "nsIContent.h"
 #include "nsIFrame.h"
 #include "nsIPersistentProperties2.h"
 
 #include "nsCOMPtr.h"
 #include "nsString.h"
-#include "nsTPtrArray.h"
 
 class nsITextAttr;
 
 /**
  * Used to expose text attributes for the hyper text accessible (see
  * nsHyperTextAccessible class). It is indended for the work with 'language' and
  * CSS based text attributes.
  *
@@ -107,17 +106,17 @@ protected:
    * Calculates range (start and end offsets) of text where the text attributes
    * are stretched. New offsets may be smaller if one of text attributes changes
    * its value before or after the given offsets.
    *
    * @param aTextAttrArray  [in] text attributes array
    * @param aStartHTOffset  [in, out] the start offset
    * @param aEndHTOffset    [in, out] the end offset
    */
-   nsresult GetRange(const nsTPtrArray<nsITextAttr>& aTextAttrArray,
+   nsresult GetRange(const nsTArray<nsITextAttr*>& aTextAttrArray,
                      PRInt32 *aStartHTOffset, PRInt32 *aEndHTOffset);
 
 private:
   nsRefPtr<nsHyperTextAccessible> mHyperTextAcc;
 
   PRBool mIncludeDefAttrs;
 
   nsRefPtr<nsAccessible> mOffsetAcc;
--- a/accessible/src/base/nsTextEquivUtils.cpp
+++ b/accessible/src/base/nsTextEquivUtils.cpp
@@ -34,16 +34,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 "nsTextEquivUtils.h"
 
+#include "AccIterator.h"
 #include "nsAccessibilityService.h"
 #include "nsAccessible.h"
 #include "nsAccUtils.h"
 
 #include "nsIDOMXULLabeledControlEl.h"
 
 #include "nsArrayUtils.h"
 
--- a/accessible/src/html/nsHTMLFormControlAccessible.cpp
+++ b/accessible/src/html/nsHTMLFormControlAccessible.cpp
@@ -33,29 +33,31 @@
  * 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 "nsHTMLFormControlAccessible.h"
 
+#include "Relation.h"
 #include "States.h"
 #include "nsAccessibilityAtoms.h"
 #include "nsAccUtils.h"
-#include "nsRelUtils.h"
 #include "nsTextEquivUtils.h"
 
+#include "nsIAccessibleRelation.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMHTMLInputElement.h"
 #include "nsIDOMNSHTMLElement.h"
 #include "nsIDOMNSEditableElement.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsIDOMHTMLLegendElement.h"
 #include "nsIDOMHTMLTextAreaElement.h"
+#include "nsIDOMNodeList.h"
 #include "nsIEditor.h"
 #include "nsIFrame.h"
 #include "nsINameSpaceManager.h"
 #include "nsISelectionController.h"
 #include "jsapi.h"
 #include "nsIJSContextStack.h"
 #include "nsIServiceManager.h"
 #include "nsITextControlFrame.h"
@@ -610,72 +612,48 @@ nsHTMLGroupboxAccessible::GetNameInterna
   if (legendContent) {
     return nsTextEquivUtils::
       AppendTextEquivFromContent(this, legendContent, &aName);
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsHTMLGroupboxAccessible::GetRelationByType(PRUint32 aRelationType,
-                                            nsIAccessibleRelation **aRelation)
+Relation
+nsHTMLGroupboxAccessible::RelationByType(PRUint32 aType)
 {
-  nsresult rv = nsHyperTextAccessibleWrap::GetRelationByType(aRelationType,
-                                                             aRelation);
-  NS_ENSURE_SUCCESS(rv, rv);
+  Relation rel = nsHyperTextAccessibleWrap::RelationByType(aType);
+    // No override for label, so use <legend> for this <fieldset>
+  if (aType == nsIAccessibleRelation::RELATION_LABELLED_BY)
+    rel.AppendTarget(GetLegend());
 
-  if (aRelationType == nsIAccessibleRelation::RELATION_LABELLED_BY) {
-    // No override for label, so use <legend> for this <fieldset>
-    return nsRelUtils::
-      AddTargetFromContent(aRelationType, aRelation, GetLegend());
-  }
-
-  return NS_OK;
+  return rel;
 }
 
-
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLLegendAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsHTMLLegendAccessible::
   nsHTMLLegendAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
   nsHyperTextAccessibleWrap(aContent, aShell)
 {
 }
 
-NS_IMETHODIMP
-nsHTMLLegendAccessible::GetRelationByType(PRUint32 aRelationType,
-                                          nsIAccessibleRelation **aRelation)
+Relation
+nsHTMLLegendAccessible::RelationByType(PRUint32 aType)
 {
-  nsresult rv = nsHyperTextAccessibleWrap::
-    GetRelationByType(aRelationType, aRelation);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (aRelationType == nsIAccessibleRelation::RELATION_LABEL_FOR) {
-    // Look for groupbox parent
-    nsAccessible* groupbox = Parent();
+  Relation rel = nsHyperTextAccessibleWrap::RelationByType(aType);
+  if (aType != nsIAccessibleRelation::RELATION_LABEL_FOR)
+    return rel;
 
-    if (groupbox && groupbox->Role() == nsIAccessibleRole::ROLE_GROUPING) {
-      // XXX: if group box exposes more than one relation of the given type
-      // then we fail.
-      nsCOMPtr<nsIAccessible> testLabelAccessible =
-        nsRelUtils::GetRelatedAccessible(groupbox,
-                                         nsIAccessibleRelation::RELATION_LABELLED_BY);
+  nsAccessible* groupbox = Parent();
+  if (groupbox && groupbox->Role() == nsIAccessibleRole::ROLE_GROUPING)
+    rel.AppendTarget(groupbox);
 
-      if (testLabelAccessible == this) {
-        // We're the first child of the parent groupbox, see
-        // nsHTMLGroupboxAccessible::GetRelationByType().
-        return nsRelUtils::
-          AddTarget(aRelationType, aRelation, groupbox);
-      }
-    }
-  }
-
-  return NS_OK;
+  return rel;
 }
 
 PRUint32
 nsHTMLLegendAccessible::NativeRole()
 {
   return nsIAccessibleRole::ROLE_LABEL;
 }
--- a/accessible/src/html/nsHTMLFormControlAccessible.h
+++ b/accessible/src/html/nsHTMLFormControlAccessible.h
@@ -171,38 +171,32 @@ public:
 /**
  * Accessible for HTML fieldset element.
  */
 class nsHTMLGroupboxAccessible : public nsHyperTextAccessibleWrap
 {
 public:
   nsHTMLGroupboxAccessible(nsIContent *aContent, nsIWeakReference *aShell);
 
-  // nsIAccessible
-  NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
-                               nsIAccessibleRelation **aRelation);
-
   // nsAccessible
   virtual nsresult GetNameInternal(nsAString& aName);
   virtual PRUint32 NativeRole();
+  virtual Relation RelationByType(PRUint32 aType);
 
 protected:
   nsIContent* GetLegend();
 };
 
 
 /**
  * Accessible for HTML legend element.
  */
 class nsHTMLLegendAccessible : public nsHyperTextAccessibleWrap
 {
 public:
   nsHTMLLegendAccessible(nsIContent *aContent, nsIWeakReference *aShell);
 
-  // nsIAccessible
-  NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
-                               nsIAccessibleRelation **aRelation);
-
   // nsAccessible
   virtual PRUint32 NativeRole();
+  virtual Relation RelationByType(PRUint32 aType);
 };
 
 #endif  
--- a/accessible/src/html/nsHTMLTableAccessible.cpp
+++ b/accessible/src/html/nsHTMLTableAccessible.cpp
@@ -34,42 +34,44 @@
  * 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 "nsHTMLTableAccessible.h"
 
+#include "Relation.h"
 #include "States.h"
 #include "nsAccessibilityService.h"
 #include "nsAccTreeWalker.h"
 #include "nsAccUtils.h"
 #include "nsDocAccessible.h"
-#include "nsRelUtils.h"
 #include "nsTextEquivUtils.h"
 
+#include "nsIAccessibleRelation.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMRange.h"
-#include "nsISelection2.h"
 #include "nsISelectionPrivate.h"
 #include "nsINameSpaceManager.h"
+#include "nsIDOMNodeList.h"
 #include "nsIDOMHTMLCollection.h"
 #include "nsIDOMHTMLTableCellElement.h"
 #include "nsIDOMHTMLTableElement.h"
 #include "nsIDOMHTMLTableRowElement.h"
 #include "nsIDOMHTMLTableSectionElem.h"
 #include "nsIDocument.h"
 #include "nsIPresShell.h"
 #include "nsITableLayout.h"
 #include "nsITableCellLayout.h"
 #include "nsFrameSelection.h"
 #include "nsLayoutErrors.h"
 #include "nsArrayUtils.h"
+#include "nsComponentManagerUtils.h"
 
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLTableCellAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsHTMLTableCellAccessible::
@@ -500,28 +502,24 @@ nsHTMLTableAccessible::GetAttributesInte
   }
   
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLTableAccessible: nsIAccessible implementation
 
-NS_IMETHODIMP
-nsHTMLTableAccessible::GetRelationByType(PRUint32 aRelationType,
-                                         nsIAccessibleRelation **aRelation)
+Relation
+nsHTMLTableAccessible::RelationByType(PRUint32 aType)
 {
-  nsresult rv = nsAccessibleWrap::GetRelationByType(aRelationType,
-                                                    aRelation);
-  NS_ENSURE_SUCCESS(rv, rv);
+  Relation rel = nsAccessibleWrap::RelationByType(aType);
+  if (aType == nsIAccessibleRelation::RELATION_LABELLED_BY)
+    rel.AppendTarget(Caption());
 
-  if (aRelationType == nsIAccessibleRelation::RELATION_LABELLED_BY)
-    return nsRelUtils::AddTarget(aRelationType, aRelation, Caption());
-
-  return NS_OK;
+  return rel;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLTableAccessible: nsIAccessibleTable implementation
 
 NS_IMETHODIMP
 nsHTMLTableAccessible::GetCaption(nsIAccessible **aCaption)
 {
@@ -1517,28 +1515,23 @@ nsHTMLTableAccessible::IsProbablyForLayo
   RETURN_LAYOUT_ANSWER(PR_FALSE, "no layout factor strong enough, so will guess data");
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLCaptionAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
-NS_IMETHODIMP
-nsHTMLCaptionAccessible::GetRelationByType(PRUint32 aRelationType,
-                                           nsIAccessibleRelation **aRelation)
+Relation
+nsHTMLCaptionAccessible::RelationByType(PRUint32 aType)
 {
-  nsresult rv = nsHyperTextAccessible::GetRelationByType(aRelationType,
-                                                         aRelation);
-  NS_ENSURE_SUCCESS(rv, rv);
+  Relation rel = nsHyperTextAccessible::RelationByType(aType);
+  if (aType == nsIAccessibleRelation::RELATION_LABEL_FOR)
+    rel.AppendTarget(Parent());
 
-  if (aRelationType == nsIAccessibleRelation::RELATION_LABEL_FOR) {
-      return nsRelUtils::AddTarget(aRelationType, aRelation, Parent());
-  }
-
-  return NS_OK;
+  return rel;
 }
 
 PRUint32
 nsHTMLCaptionAccessible::NativeRole()
 {
   return nsIAccessibleRole::ROLE_CAPTION;
 }
--- a/accessible/src/html/nsHTMLTableAccessible.h
+++ b/accessible/src/html/nsHTMLTableAccessible.h
@@ -125,26 +125,23 @@ class nsHTMLTableAccessible : public nsA
 {
 public:
   nsHTMLTableAccessible(nsIContent *aContent, nsIWeakReference *aShell);
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIACCESSIBLETABLE
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_TABLEACCESSIBLE_IMPL_CID)
 
-  // nsIAccessible
-  NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
-                               nsIAccessibleRelation **aRelation);
-
   // nsAccessible
   virtual void Description(nsString& aDescription);
   virtual nsresult GetNameInternal(nsAString& aName);
   virtual PRUint32 NativeRole();
   virtual PRUint64 NativeState();
   virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
+  virtual Relation RelationByType(PRUint32 aRelationType);
 
   // TableAccessible
   inline nsAccessible* Caption() const
   {
     nsAccessible* child = mChildren.SafeElementAt(0, nsnull);
     return child && child->Role() == nsIAccessibleRole::ROLE_CAPTION ?
       child : nsnull;
   }
@@ -214,16 +211,15 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsHTMLTabl
  */
 class nsHTMLCaptionAccessible : public nsHyperTextAccessibleWrap
 {
 public:
   nsHTMLCaptionAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
     nsHyperTextAccessibleWrap(aContent, aShell) { }
 
   // nsIAccessible
-  NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
-                               nsIAccessibleRelation **aRelation);
 
   // nsAccessible
   virtual PRUint32 NativeRole();
+  virtual Relation RelationByType(PRUint32 aRelationType);
 };
 
 #endif  
--- a/accessible/src/html/nsHTMLTextAccessible.cpp
+++ b/accessible/src/html/nsHTMLTextAccessible.cpp
@@ -36,20 +36,21 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsHTMLTextAccessible.h"
 
 #include "nsDocAccessible.h"
 #include "nsAccUtils.h"
-#include "nsRelUtils.h"
 #include "nsTextEquivUtils.h"
+#include "Relation.h"
 #include "States.h"
 
+#include "nsIAccessibleRelation.h"
 #include "nsIFrame.h"
 #include "nsPresContext.h"
 #include "nsBlockFrame.h"
 #include "nsISelection.h"
 #include "nsISelectionController.h"
 #include "nsComponentManagerUtils.h"
 
 using namespace mozilla::a11y;
@@ -193,33 +194,24 @@ nsHTMLLabelAccessible::NativeRole()
 nsHTMLOutputAccessible::
   nsHTMLOutputAccessible(nsIContent* aContent, nsIWeakReference* aShell) :
   nsHyperTextAccessibleWrap(aContent, aShell)
 {
 }
 
 NS_IMPL_ISUPPORTS_INHERITED0(nsHTMLOutputAccessible, nsHyperTextAccessible)
 
-NS_IMETHODIMP
-nsHTMLOutputAccessible::GetRelationByType(PRUint32 aRelationType,
-                                          nsIAccessibleRelation** aRelation)
+Relation
+nsHTMLOutputAccessible::RelationByType(PRUint32 aType)
 {
-  nsresult rv = nsAccessibleWrap::GetRelationByType(aRelationType, aRelation);
-  NS_ENSURE_SUCCESS(rv, rv);
+  Relation rel = nsAccessibleWrap::RelationByType(aType);
+  if (aType == nsIAccessibleRelation::RELATION_CONTROLLED_BY)
+    rel.AppendIter(new IDRefsIterator(mContent, nsAccessibilityAtoms::_for));
 
-  if (rv != NS_OK_NO_RELATION_TARGET)
-    return NS_OK; // XXX bug 381599, avoid performance problems
-
-  if (aRelationType == nsIAccessibleRelation::RELATION_CONTROLLED_BY) {
-    return nsRelUtils::
-      AddTargetFromIDRefsAttr(aRelationType, aRelation, mContent,
-                              nsAccessibilityAtoms::_for);
-  }
-
-  return NS_OK;
+  return rel;
 }
 
 PRUint32
 nsHTMLOutputAccessible::NativeRole()
 {
   return nsIAccessibleRole::ROLE_SECTION;
 }
 
--- a/accessible/src/html/nsHTMLTextAccessible.h
+++ b/accessible/src/html/nsHTMLTextAccessible.h
@@ -110,23 +110,20 @@ public:
  */
 class nsHTMLOutputAccessible : public nsHyperTextAccessibleWrap
 {
 public:
   nsHTMLOutputAccessible(nsIContent* aContent, nsIWeakReference* aShell);
 
   NS_DECL_ISUPPORTS_INHERITED
 
-  // nsIAccessible
-  NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
-                               nsIAccessibleRelation** aRelation);
-
   // nsAccessible
   virtual PRUint32 NativeRole();
   virtual nsresult GetAttributesInternal(nsIPersistentProperties* aAttributes);
+  virtual Relation RelationByType(PRUint32 aType);
 };
 
 /**
  * Used for bullet of HTML list item element (for example, HTML li).
  */
 class nsHTMLListBulletAccessible : public nsLeafAccessible
 {
 public:
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -55,17 +55,16 @@
 #include "nsIEditingSession.h"
 #include "nsIEditor.h"
 #include "nsIFrame.h"
 #include "nsFrameSelection.h"
 #include "nsILineIterator.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIPlaintextEditor.h"
 #include "nsIScrollableFrame.h"
-#include "nsISelection2.h"
 #include "nsISelectionPrivate.h"
 #include "nsIServiceManager.h"
 #include "nsTextFragment.h"
 #include "gfxSkipChars.h"
 
 using namespace mozilla::a11y;
 
 static NS_DEFINE_IID(kRangeCID, NS_RANGE_CID);
@@ -1786,30 +1785,29 @@ nsHyperTextAccessible::GetSelections(PRI
   if (aSelCon) {
     NS_ADDREF(*aSelCon = selCon);
   }
   if (aDomSel) {
     NS_ADDREF(*aDomSel = domSel);
   }
 
   if (aRanges) {
-    nsCOMPtr<nsISelection2> selection2(do_QueryInterface(domSel));
-    NS_ENSURE_TRUE(selection2, NS_ERROR_FAILURE);
+    nsCOMPtr<nsISelectionPrivate> privSel(do_QueryInterface(domSel));
 
     nsCOMPtr<nsINode> startNode = GetNode();
     if (peditor) {
       nsCOMPtr<nsIDOMElement> editorRoot;
       editor->GetRootElement(getter_AddRefs(editorRoot));
       startNode = do_QueryInterface(editorRoot);
     }
     NS_ENSURE_STATE(startNode);
 
     PRUint32 childCount = startNode->GetChildCount();
     nsCOMPtr<nsIDOMNode> startDOMNode(do_QueryInterface(startNode));
-    nsresult rv = selection2->
+    nsresult rv = privSel->
       GetRangesForIntervalCOMArray(startDOMNode, 0, startDOMNode, childCount,
                                    PR_TRUE, aRanges);
     NS_ENSURE_SUCCESS(rv, rv);
     // Remove collapsed ranges
     PRInt32 numRanges = aRanges->Count();
     for (PRInt32 count = 0; count < numRanges; count ++) {
       PRBool isCollapsed;
       (*aRanges)[count]->GetCollapsed(&isCollapsed);
--- a/accessible/src/mac/Makefile.in
+++ b/accessible/src/mac/Makefile.in
@@ -67,17 +67,16 @@ EXPORTS = \
   nsDocAccessibleWrap.h \
   nsRootAccessibleWrap.h \
   nsXULMenuAccessibleWrap.h \
   nsXULListboxAccessibleWrap.h \
   nsXULTreeGridAccessibleWrap.h \
   nsHyperTextAccessibleWrap.h \
   nsHTMLImageAccessibleWrap.h \
   nsHTMLTableAccessibleWrap.h \
-  nsAccessibleRelationWrap.h \
   nsApplicationAccessibleWrap.h \
   mozDocAccessible.h \
   mozAccessible.h \
   mozAccessibleWrapper.h \
   mozAccessibleProtocol.h \
   mozActionElements.h \
   mozTextAccessible.h \
   nsRoleMap.h \
deleted file mode 100644
--- a/accessible/src/mac/nsAccessibleRelationWrap.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2:
- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2007
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either 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 _NS_ACCESSIBLE_RELATION_WRAP_H
-#define _NS_ACCESSIBLE_RELATION_WRAP_H
-
-#include "nsAccessibleRelation.h"
-
-typedef class nsAccessibleRelation nsAccessibleRelationWrap;
-
-#endif
-
--- a/accessible/src/msaa/Makefile.in
+++ b/accessible/src/msaa/Makefile.in
@@ -56,26 +56,26 @@ CPPSRCS = \
   nsARIAGridAccessibleWrap.cpp \
   nsRootAccessibleWrap.cpp \
   nsXULMenuAccessibleWrap.cpp \
   nsXULListboxAccessibleWrap.cpp \
   nsXULTreeGridAccessibleWrap.cpp \
   nsHyperTextAccessibleWrap.cpp \
   nsHTMLImageAccessibleWrap.cpp \
   nsHTMLTableAccessibleWrap.cpp \
-  nsAccessibleRelationWrap.cpp \
   nsApplicationAccessibleWrap.cpp \
   nsWinUtils.cpp \
   CAccessibleAction.cpp \
   CAccessibleImage.cpp \
   CAccessibleComponent.cpp \
   CAccessibleText.cpp \
   CAccessibleEditableText.cpp \
   CAccessibleHyperlink.cpp \
   CAccessibleHypertext.cpp \
+  ia2AccessibleRelation.cpp \
   CAccessibleTable.cpp \
   CAccessibleTableCell.cpp \
   CAccessibleValue.cpp \
   $(NULL)
 
 EXPORTS = \
   nsAccessNodeWrap.h \
   nsAccessibleWrap.h \
@@ -85,17 +85,16 @@ EXPORTS = \
   nsHTMLWin32ObjectAccessible.h \
   nsARIAGridAccessibleWrap.h \
   nsXULMenuAccessibleWrap.h \
   nsXULListboxAccessibleWrap.h \
   nsXULTreeGridAccessibleWrap.h \
   nsHyperTextAccessibleWrap.h \
   nsHTMLImageAccessibleWrap.h \
   nsHTMLTableAccessibleWrap.h \
-  nsAccessibleRelationWrap.h \
   nsApplicationAccessibleWrap.h \
   CAccessibleAction.h \
   CAccessibleImage.h \
   CAccessibleComponent.h \
   CAccessibleText.h \
   CAccessibleEditableText.h \
   CAccessibleHyperlink.h \
   CAccessibleHypertext.h \
rename from accessible/src/msaa/nsAccessibleRelationWrap.cpp
rename to accessible/src/msaa/ia2AccessibleRelation.cpp
--- a/accessible/src/msaa/nsAccessibleRelationWrap.cpp
+++ b/accessible/src/msaa/ia2AccessibleRelation.cpp
@@ -33,225 +33,191 @@
  * 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 "nsAccessibleRelationWrap.h"
+#include "ia2AccessibleRelation.h"
+
+#include "Relation.h"
+
+#include "nsIAccessibleRelation.h"
+#include "nsID.h"
 
 #include "AccessibleRelation_i.c"
-#include "nsAccessNodeWrap.h"
 
-#include "nsArrayUtils.h"
-
-nsAccessibleRelationWrap::
-  nsAccessibleRelationWrap(PRUint32 aType, nsIAccessible *aTarget) :
-  nsAccessibleRelation(aType, aTarget)
+ia2AccessibleRelation::ia2AccessibleRelation(PRUint32 aType, Relation* aRel) :
+  mType(aType), mReferences(0)
 {
-}
-
-// ISupports
-
-NS_IMPL_ISUPPORTS_INHERITED1(nsAccessibleRelationWrap, nsAccessibleRelation,
-                             nsIWinAccessNode)
-
-// nsIWinAccessNode
-
-NS_IMETHODIMP
-nsAccessibleRelationWrap::QueryNativeInterface(REFIID aIID, void** aInstancePtr)
-{
-  return QueryInterface(aIID, aInstancePtr);
+  nsAccessible* target = nsnull;
+  while ((target = aRel->Next()))
+    mTargets.AppendElement(target);
 }
 
 // IUnknown
 
 STDMETHODIMP
-nsAccessibleRelationWrap::QueryInterface(REFIID iid, void** ppv)
+ia2AccessibleRelation::QueryInterface(REFIID iid, void** ppv)
 {
+  if (!ppv)
+    return E_INVALIDARG;
+
   *ppv = NULL;
 
   if (IID_IAccessibleRelation == iid || IID_IUnknown == iid) {
     *ppv = static_cast<IAccessibleRelation*>(this);
     (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
     return S_OK;
   }
 
   return E_NOINTERFACE;
 }
 
+ULONG STDMETHODCALLTYPE
+ia2AccessibleRelation::AddRef()
+{
+  return mReferences++;
+}
+
+ULONG STDMETHODCALLTYPE 
+ia2AccessibleRelation::Release()
+{
+  mReferences--;
+  ULONG references = mReferences;
+  if (!mReferences)
+    delete this;
+
+  return references;
+}
+
 // IAccessibleRelation
 
 STDMETHODIMP
-nsAccessibleRelationWrap::get_relationType(BSTR *aRelationType)
+ia2AccessibleRelation::get_relationType(BSTR *aRelationType)
 {
 __try {
+  if (!aRelationType)
+    return E_INVALIDARG;
+
   *aRelationType = NULL;
 
-  PRUint32 type = 0;
-  nsresult rv = GetRelationType(&type);
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
-
-  switch (type) {
-    case RELATION_CONTROLLED_BY:
+  switch (mType) {
+    case nsIAccessibleRelation::RELATION_CONTROLLED_BY:
       *aRelationType = ::SysAllocString(IA2_RELATION_CONTROLLED_BY);
       break;
-    case RELATION_CONTROLLER_FOR:
+    case nsIAccessibleRelation::RELATION_CONTROLLER_FOR:
       *aRelationType = ::SysAllocString(IA2_RELATION_CONTROLLER_FOR);
       break;
-    case RELATION_DESCRIBED_BY:
+    case nsIAccessibleRelation::RELATION_DESCRIBED_BY:
       *aRelationType = ::SysAllocString(IA2_RELATION_DESCRIBED_BY);
       break;
-    case RELATION_DESCRIPTION_FOR:
+    case nsIAccessibleRelation::RELATION_DESCRIPTION_FOR:
       *aRelationType = ::SysAllocString(IA2_RELATION_DESCRIPTION_FOR);
       break;
-    case RELATION_EMBEDDED_BY:
+    case nsIAccessibleRelation::RELATION_EMBEDDED_BY:
       *aRelationType = ::SysAllocString(IA2_RELATION_EMBEDDED_BY);
       break;
-    case RELATION_EMBEDS:
+    case nsIAccessibleRelation::RELATION_EMBEDS:
       *aRelationType = ::SysAllocString(IA2_RELATION_EMBEDS);
       break;
-    case RELATION_FLOWS_FROM:
+    case nsIAccessibleRelation::RELATION_FLOWS_FROM:
       *aRelationType = ::SysAllocString(IA2_RELATION_FLOWS_FROM);
       break;
-    case RELATION_FLOWS_TO:
+    case nsIAccessibleRelation::RELATION_FLOWS_TO:
       *aRelationType = ::SysAllocString(IA2_RELATION_FLOWS_TO);
       break;
-    case RELATION_LABEL_FOR:
+    case nsIAccessibleRelation::RELATION_LABEL_FOR:
       *aRelationType = ::SysAllocString(IA2_RELATION_LABEL_FOR);
       break;
-    case RELATION_LABELLED_BY:
+    case nsIAccessibleRelation::RELATION_LABELLED_BY:
       *aRelationType = ::SysAllocString(IA2_RELATION_LABELED_BY);
       break;
-    case RELATION_MEMBER_OF:
+    case nsIAccessibleRelation::RELATION_MEMBER_OF:
       *aRelationType = ::SysAllocString(IA2_RELATION_MEMBER_OF);
       break;
-    case RELATION_NODE_CHILD_OF:
+    case nsIAccessibleRelation::RELATION_NODE_CHILD_OF:
       *aRelationType = ::SysAllocString(IA2_RELATION_NODE_CHILD_OF);
       break;
-    case RELATION_PARENT_WINDOW_OF:
+    case nsIAccessibleRelation::RELATION_PARENT_WINDOW_OF:
       *aRelationType = ::SysAllocString(IA2_RELATION_PARENT_WINDOW_OF);
       break;
-    case RELATION_POPUP_FOR:
+    case nsIAccessibleRelation::RELATION_POPUP_FOR:
       *aRelationType = ::SysAllocString(IA2_RELATION_POPUP_FOR);
       break;
-    case RELATION_SUBWINDOW_OF:
+    case nsIAccessibleRelation::RELATION_SUBWINDOW_OF:
       *aRelationType = ::SysAllocString(IA2_RELATION_SUBWINDOW_OF);
       break;
     default:
       return E_FAIL;
   }
 
   return *aRelationType ? S_OK : E_OUTOFMEMORY;
 
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return E_FAIL;
 }
 
 STDMETHODIMP
-nsAccessibleRelationWrap::get_localizedRelationType(BSTR *aLocalizedRelationType)
+ia2AccessibleRelation::get_localizedRelationType(BSTR *aLocalizedRelationType)
 {
 __try {
+  if (!aLocalizedRelationType)
+    return E_INVALIDARG;
+
   *aLocalizedRelationType = NULL;
 
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return E_NOTIMPL;
 }
 
 STDMETHODIMP
-nsAccessibleRelationWrap::get_nTargets(long *aNTargets)
+ia2AccessibleRelation::get_nTargets(long *aNTargets)
 {
 __try {
-  *aNTargets = 0;
+ if (!aNTargets)
+   return E_INVALIDARG;
 
-  PRUint32 count = 0;
-  nsresult rv = GetTargetsCount(&count);
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
-
-  *aNTargets = count;
+ *aNTargets = mTargets.Length();
   return S_OK;
-
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return E_FAIL;
 }
 
 STDMETHODIMP
-nsAccessibleRelationWrap::get_target(long aTargetIndex, IUnknown **aTarget)
+ia2AccessibleRelation::get_target(long aTargetIndex, IUnknown **aTarget)
 {
 __try {
-  nsCOMPtr<nsIAccessible> accessible;
-  nsresult rv = GetTarget(aTargetIndex, getter_AddRefs(accessible));
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
+  if (aTargetIndex < 0 || aTargetIndex >= mTargets.Length() || !aTarget)
+    return E_INVALIDARG;
 
-  nsCOMPtr<nsIWinAccessNode> winAccessNode(do_QueryInterface(accessible));
-  if (!winAccessNode)
-    return E_FAIL;
-
-  void *instancePtr = NULL;
-  rv = winAccessNode->QueryNativeInterface(IID_IUnknown, &instancePtr);
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
-
-  *aTarget = static_cast<IUnknown*>(instancePtr);
+  mTargets[aTargetIndex]->QueryInterface((const nsID&) IID_IUnknown, (void**) aTarget);
   return S_OK;
 
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return E_FAIL;
 }
 
 STDMETHODIMP
-nsAccessibleRelationWrap::get_targets(long aMaxTargets, IUnknown **aTarget,
-                                      long *aNTargets)
+ia2AccessibleRelation::get_targets(long aMaxTargets, IUnknown **aTargets,
+                                   long *aNTargets)
 {
 __try {
-  *aNTargets = 0;
-
-  nsCOMPtr<nsIArray> targets;
-  nsresult rv = GetTargets(getter_AddRefs(targets));
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
-
-  PRUint32 length = 0;
-  rv = targets->GetLength(&length);
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
-
-  if (length == 0)
-    return S_FALSE;
-
-  PRUint32 count = length < PRUint32(aMaxTargets) ? length : aMaxTargets;
+  if (!aNTargets || !aTargets)
+    return E_INVALIDARG;
 
-  PRUint32 index = 0;
-  for (; index < count; index++) {
-    nsCOMPtr<nsIWinAccessNode> winAccessNode =
-      do_QueryElementAt(targets, index, &rv);
-    if (NS_FAILED(rv))
-      break;
-
-    void *instancePtr = NULL;
-    nsresult rv =  winAccessNode->QueryNativeInterface(IID_IUnknown,
-                                                       &instancePtr);
-    if (NS_FAILED(rv))
-      break;
+  *aNTargets = 0;
+  PRUint32 maxTargets = mTargets.Length();
+  if (maxTargets > aMaxTargets)
+    maxTargets = aMaxTargets;
 
-    aTarget[index] = static_cast<IUnknown*>(instancePtr);
-  }
+  for (PRUint32 idx = 0; idx < maxTargets; idx++)
+    get_target(idx, aTargets + idx);
 
-  if (NS_FAILED(rv)) {
-    for (PRUint32 index2 = 0; index2 < index; index2++) {
-      aTarget[index2]->Release();
-      aTarget[index2] = NULL;
-    }
-    return GetHRESULT(rv);
-  }
-
-  *aNTargets = count;
+  *aNTargets = maxTargets;
   return S_OK;
 
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return E_FAIL;
 }
 
rename from accessible/src/msaa/nsAccessibleRelationWrap.h
rename to accessible/src/msaa/ia2AccessibleRelation.h
--- a/accessible/src/msaa/nsAccessibleRelationWrap.h
+++ b/accessible/src/msaa/ia2AccessibleRelation.h
@@ -36,37 +36,32 @@
  * 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 _NS_ACCESSIBLE_RELATION_WRAP_H
 #define _NS_ACCESSIBLE_RELATION_WRAP_H
 
-#include "nsAccessibleRelation.h"
+#include "nsAccessible.h"
+
+#include "nsTArray.h"
+
 #include "AccessibleRelation.h"
 
-#include "nsIWinAccessNode.h"
-#include "nsISupports.h"
-
-class nsAccessibleRelationWrap: public nsAccessibleRelation,
-                                public nsIWinAccessNode,
-                                public IAccessibleRelation
+class ia2AccessibleRelation : public IAccessibleRelation
 {
 public:
-  nsAccessibleRelationWrap(PRUint32 aType, nsIAccessible *aTarget);
-
-  // nsISupports
-  NS_DECL_ISUPPORTS_INHERITED
-
-  // nsIWinAccessNode
-  NS_DECL_NSIWINACCESSNODE
+  ia2AccessibleRelation(PRUint32 aType, Relation* aRel);
+  virtual ~ia2AccessibleRelation() { }
 
   // IUnknown
-  STDMETHODIMP QueryInterface(REFIID, void**);
+  virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID aIID, void** aOutPtr);
+  virtual ULONG STDMETHODCALLTYPE AddRef();
+  virtual ULONG STDMETHODCALLTYPE Release();
 
   // IAccessibleRelation
   virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_relationType(
       /* [retval][out] */ BSTR *relationType);
 
   virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_localizedRelationType(
       /* [retval][out] */ BSTR *localizedRelationType);
 
@@ -77,12 +72,23 @@ public:
       /* [in] */ long targetIndex,
       /* [retval][out] */ IUnknown **target);
 
   virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_targets(
       /* [in] */ long maxTargets,
       /* [length_is][size_is][out] */ IUnknown **target,
       /* [retval][out] */ long *nTargets);
 
+  inline bool HasTargets() const
+    { return mTargets.Length(); }
+
+private:
+  ia2AccessibleRelation();
+  ia2AccessibleRelation(const ia2AccessibleRelation&);
+  ia2AccessibleRelation& operator = (const ia2AccessibleRelation&);
+
+  PRUint32 mType;
+  nsTArray<nsRefPtr<nsAccessible> > mTargets;
+  ULONG mReferences;
 };
 
 #endif
 
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -36,22 +36,25 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsAccessibleWrap.h"
 
 #include "nsAccessibilityAtoms.h"
 #include "nsAccUtils.h"
 #include "nsCoreUtils.h"
-#include "nsRelUtils.h"
 #include "nsWinUtils.h"
+#include "Relation.h"
 #include "States.h"
 
+#include "ia2AccessibleRelation.h"
+
 #include "nsIAccessibleDocument.h"
 #include "nsIAccessibleEvent.h"
+#include "nsIAccessibleRelation.h"
 #include "nsIAccessibleWin32Object.h"
 
 #include "Accessible2_i.c"
 #include "AccessibleStates.h"
 
 #include "nsIMutableArray.h"
 #include "nsIDOMDocument.h"
 #include "nsIFrame.h"
@@ -889,23 +892,25 @@ STDMETHODIMP nsAccessibleWrap::accNaviga
       break;
     case NAVRELATION_DESCRIPTION_FOR:
       xpRelation = nsIAccessibleRelation::RELATION_DESCRIPTION_FOR;
       break;
   }
 
   pvarEndUpAt->vt = VT_EMPTY;
 
-  if (xpRelation)
-    xpAccessibleResult = nsRelUtils::GetRelatedAccessible(this, xpRelation);
+  if (xpRelation) {
+    Relation rel = RelationByType(xpRelation);
+    xpAccessibleResult = rel.Next();
+  }
 
   if (xpAccessibleResult) {
     pvarEndUpAt->pdispVal = NativeAccessible(xpAccessibleResult);
     pvarEndUpAt->vt = VT_DISPATCH;
-    return NS_OK;
+    return S_OK;
   }
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return E_FAIL;
 }
 
 STDMETHODIMP nsAccessibleWrap::accHitTest(
       /* [in] */ long xLeft,
       /* [in] */ long yTop,
@@ -1051,104 +1056,94 @@ nsAccessibleWrap::Clone(IEnumVARIANT FAR
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessibleWrap. IAccessible2
 
 STDMETHODIMP
 nsAccessibleWrap::get_nRelations(long *aNRelations)
 {
 __try {
-  PRUint32 count = 0;
-  nsresult rv = GetRelationsCount(&count);
-  *aNRelations = count;
+  if (!aNRelations)
+    return E_INVALIDARG;
+
+  *aNRelations = 0;
+
+  if (IsDefunct())
+    return E_FAIL;
 
-  return GetHRESULT(rv);
-
+  for (PRUint32 relType = nsIAccessibleRelation::RELATION_FIRST;
+       relType <= nsIAccessibleRelation::RELATION_LAST; relType++) {
+    Relation rel = RelationByType(relType);
+    if (rel.Next())
+      (*aNRelations)++;
+  }
+  return S_OK;
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return E_FAIL;
 }
 
 STDMETHODIMP
 nsAccessibleWrap::get_relation(long aRelationIndex,
                                IAccessibleRelation **aRelation)
 {
 __try {
+  if (!aRelation)
+    return E_INVALIDARG;
+
   *aRelation = NULL;
 
-  nsCOMPtr<nsIAccessibleRelation> relation;
-  nsresult rv = GetRelation(aRelationIndex, getter_AddRefs(relation));
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
-
-  nsCOMPtr<nsIWinAccessNode> winAccessNode(do_QueryInterface(relation));
-  if (!winAccessNode)
+  if (IsDefunct())
     return E_FAIL;
 
-  void *instancePtr = NULL;
-  rv =  winAccessNode->QueryNativeInterface(IID_IAccessibleRelation,
-                                            &instancePtr);
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
+  PRUint32 relIdx = 0;
+  for (PRUint32 relType = nsIAccessibleRelation::RELATION_FIRST;
+       relType <= nsIAccessibleRelation::RELATION_LAST; relType++) {
+    Relation rel = RelationByType(relType);
+    nsRefPtr<ia2AccessibleRelation> ia2Relation =
+      new ia2AccessibleRelation(relType, &rel);
+    if (ia2Relation->HasTargets()) {
+      if (relIdx == aRelationIndex) {
+        ia2Relation.forget(aRelation);
+        return S_OK;
+      }
 
-  *aRelation = static_cast<IAccessibleRelation*>(instancePtr);
-  return S_OK;
+      relIdx++;
+    }
+  }
 
+  return E_INVALIDARG;
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return E_FAIL;
 }
 
 STDMETHODIMP
 nsAccessibleWrap::get_relations(long aMaxRelations,
                                 IAccessibleRelation **aRelation,
                                 long *aNRelations)
 {
 __try {
-  *aRelation = NULL;
+  if (!aRelation || !aNRelations)
+    return E_INVALIDARG;
+
   *aNRelations = 0;
 
-  nsCOMPtr<nsIArray> relations;
-  nsresult rv = GetRelations(getter_AddRefs(relations));
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
-
-  PRUint32 length = 0;
-  rv = relations->GetLength(&length);
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
-
-  if (length == 0)
-    return S_FALSE;
-
-  PRUint32 count = length < (PRUint32)aMaxRelations ? length : aMaxRelations;
+  if (IsDefunct())
+    return E_FAIL;
 
-  PRUint32 index = 0;
-  for (; index < count; index++) {
-    nsCOMPtr<nsIWinAccessNode> winAccessNode =
-      do_QueryElementAt(relations, index, &rv);
-    if (NS_FAILED(rv))
-      break;
-
-    void *instancePtr = NULL;
-    nsresult rv =  winAccessNode->QueryNativeInterface(IID_IAccessibleRelation,
-                                                       &instancePtr);
-    if (NS_FAILED(rv))
-      break;
-
-    aRelation[index] = static_cast<IAccessibleRelation*>(instancePtr);
+  for (PRUint32 relType = nsIAccessibleRelation::RELATION_FIRST;
+       relType <= nsIAccessibleRelation::RELATION_LAST &&
+       *aNRelations < aMaxRelations; relType++) {
+    Relation rel = RelationByType(relType);
+    nsRefPtr<ia2AccessibleRelation> ia2Rel =
+      new ia2AccessibleRelation(relType, &rel);
+    if (ia2Rel->HasTargets()) {
+      ia2Rel.forget(aRelation + (*aNRelations));
+      (*aNRelations)++;
+    }
   }
-
-  if (NS_FAILED(rv)) {
-    for (PRUint32 index2 = 0; index2 < index; index2++) {
-      aRelation[index2]->Release();
-      aRelation[index2] = NULL;
-    }
-    return GetHRESULT(rv);
-  }
-
-  *aNRelations = count;
   return S_OK;
 
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return E_FAIL;
 }
 
 STDMETHODIMP
 nsAccessibleWrap::role(long *aRole)
--- a/accessible/src/other/Makefile.in
+++ b/accessible/src/other/Makefile.in
@@ -61,17 +61,16 @@ EXPORTS = \
   nsDocAccessibleWrap.h \
   nsRootAccessibleWrap.h \
   nsXULMenuAccessibleWrap.h \
   nsXULListboxAccessibleWrap.h \
   nsXULTreeGridAccessibleWrap.h \
   nsHyperTextAccessibleWrap.h \
   nsHTMLImageAccessibleWrap.h \
   nsHTMLTableAccessibleWrap.h \
-  nsAccessibleRelationWrap.h \
   nsApplicationAccessibleWrap.h \
   $(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
deleted file mode 100644
--- a/accessible/src/other/nsAccessibleRelationWrap.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:expandtab:shiftwidth=2:tabstop=2:
- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2007
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either 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 _NS_ACCESSIBLE_RELATION_WRAP_H
-#define _NS_ACCESSIBLE_RELATION_WRAP_H
-
-#include "nsAccessibleRelation.h"
-
-typedef class nsAccessibleRelation nsAccessibleRelationWrap;
-
-#endif
-
--- a/accessible/src/xforms/nsXFormsAccessible.cpp
+++ b/accessible/src/xforms/nsXFormsAccessible.cpp
@@ -46,16 +46,17 @@
 #include "nscore.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMNodeList.h"
 #include "nsIEditor.h"
 #include "nsIMutableArray.h"
 #include "nsIXFormsUtilityService.h"
 #include "nsIPlaintextEditor.h"
+#include "nsINodeList.h"
 
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXFormsAccessibleBase
 ////////////////////////////////////////////////////////////////////////////////
 
 nsIXFormsUtilityService *nsXFormsAccessibleBase::sXFormsService = nsnull;
--- a/accessible/src/xpcom/Makefile.in
+++ b/accessible/src/xpcom/Makefile.in
@@ -44,16 +44,17 @@ VPATH = @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = accessibility
 LIBRARY_NAME = accessibility_xpcom_s
 LIBXUL_LIBRARY = 1
 
 CPPSRCS = \
   nsAccEvent.cpp \
+  nsAccessibleRelation.cpp \
   $(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES = \
rename from accessible/src/base/nsAccessibleRelation.cpp
rename to accessible/src/xpcom/nsAccessibleRelation.cpp
--- a/accessible/src/base/nsAccessibleRelation.cpp
+++ b/accessible/src/xpcom/nsAccessibleRelation.cpp
@@ -33,83 +33,61 @@
  * 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 "nsAccessibleRelation.h"
 
+#include "Relation.h"
+#include "nsAccessible.h"
+
 #include "nsArrayUtils.h"
 #include "nsComponentManagerUtils.h"
 
-nsAccessibleRelation::
-  nsAccessibleRelation(PRUint32 aType, nsIAccessible *aTarget) :
+nsAccessibleRelation::nsAccessibleRelation(PRUint32 aType,
+                                           Relation* aRel) :
   mType(aType)
 {
   mTargets = do_CreateInstance(NS_ARRAY_CONTRACTID);
-  if (aTarget)
-    mTargets->AppendElement(aTarget, PR_FALSE);
+  nsIAccessible* targetAcc = nsnull;
+  while ((targetAcc = aRel->Next()))
+    mTargets->AppendElement(targetAcc, false);
 }
 
 // nsISupports
-NS_IMPL_ISUPPORTS2(nsAccessibleRelation, nsAccessibleRelation,
-                   nsIAccessibleRelation)
+NS_IMPL_ISUPPORTS1(nsAccessibleRelation, nsIAccessibleRelation)
 
 // nsIAccessibleRelation
 NS_IMETHODIMP
 nsAccessibleRelation::GetRelationType(PRUint32 *aType)
 {
   NS_ENSURE_ARG_POINTER(aType);
-
   *aType = mType;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAccessibleRelation::GetTargetsCount(PRUint32 *aCount)
 {
   NS_ENSURE_ARG_POINTER(aCount);
   *aCount = 0;
-
-  NS_ENSURE_TRUE(mTargets, NS_ERROR_NOT_INITIALIZED);
-
   return mTargets->GetLength(aCount);
 }
 
 NS_IMETHODIMP
 nsAccessibleRelation::GetTarget(PRUint32 aIndex, nsIAccessible **aTarget)
 {
   NS_ENSURE_ARG_POINTER(aTarget);
-  *aTarget = nsnull;
-
-  NS_ENSURE_TRUE(mTargets, NS_ERROR_NOT_INITIALIZED);
-
   nsresult rv = NS_OK;
   nsCOMPtr<nsIAccessible> target = do_QueryElementAt(mTargets, aIndex, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  target.swap(*aTarget);
-  return NS_OK;
+  target.forget(aTarget);
+  return rv;
 }
 
 NS_IMETHODIMP
 nsAccessibleRelation::GetTargets(nsIArray **aTargets)
 {
   NS_ENSURE_ARG_POINTER(aTargets);
-  *aTargets = nsnull;
-
-  NS_ENSURE_TRUE(mTargets, NS_ERROR_NOT_INITIALIZED);
-
   NS_ADDREF(*aTargets = mTargets);
   return NS_OK;
 }
-
-// nsAccessibleRelation
-nsresult
-nsAccessibleRelation::AddTarget(nsIAccessible *aTarget)
-{
-  NS_ENSURE_ARG(aTarget);
-
-  NS_ENSURE_TRUE(mTargets, NS_ERROR_NOT_INITIALIZED);
-
-  return mTargets->AppendElement(aTarget, PR_FALSE);
-}
rename from accessible/src/base/nsAccessibleRelation.h
rename to accessible/src/xpcom/nsAccessibleRelation.h
--- a/accessible/src/base/nsAccessibleRelation.h
+++ b/accessible/src/xpcom/nsAccessibleRelation.h
@@ -34,50 +34,36 @@
  * 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 _nsAccessibleRelation_H_
 #define _nsAccessibleRelation_H_
 
-#include "nsIAccessible.h"
 #include "nsIAccessibleRelation.h"
 
 #include "nsCOMPtr.h"
 #include "nsIMutableArray.h"
 
-#define NS_ACCRELATION_IMPL_CID                         \
-{                                                       \
-  0xb20390d0,                                           \
-  0x40d3,                                               \
-  0x4c76,                                               \
-  { 0xb6, 0x2e, 0xc2, 0x30, 0xc8, 0xea, 0x0c, 0x1e }    \
-}
+class Relation;
 
 /**
  * Class represents an accessible relation.
  */
 class nsAccessibleRelation: public nsIAccessibleRelation
 {
 public:
-  nsAccessibleRelation(PRUint32 aType, nsIAccessible *aTarget);
+  nsAccessibleRelation(PRUint32 aType, Relation* aRel);
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIACCESSIBLERELATION
 
-  NS_DECLARE_STATIC_IID_ACCESSOR(NS_ACCRELATION_IMPL_CID)
-
-  /**
-   * Add target for the given key.
-   *
-   * @param aTarget - accessible target for the given relation.
-   */
-  nsresult AddTarget(nsIAccessible *aTarget);
-
 private:
+  nsAccessibleRelation();
+  nsAccessibleRelation(const nsAccessibleRelation&);
+  nsAccessibleRelation& operator = (const nsAccessibleRelation&);
+  
   PRUint32 mType;
   nsCOMPtr<nsIMutableArray> mTargets;
 };
 
-NS_DEFINE_STATIC_IID_ACCESSOR(nsAccessibleRelation, NS_ACCRELATION_IMPL_CID)
-
 #endif
--- a/accessible/src/xul/nsXULFormControlAccessible.cpp
+++ b/accessible/src/xul/nsXULFormControlAccessible.cpp
@@ -39,22 +39,23 @@
 
 #include "nsXULFormControlAccessible.h"
 
 #include "nsAccessibilityAtoms.h"
 #include "nsAccUtils.h"
 #include "nsAccTreeWalker.h"
 #include "nsCoreUtils.h"
 #include "nsDocAccessible.h"
-#include "nsRelUtils.h"
+#include "Relation.h"
 #include "States.h"
 
 // NOTE: alphabetically ordered
 #include "nsHTMLFormControlAccessible.h"
 #include "nsXULMenuAccessible.h"
+#include "nsIAccessibleRelation.h"
 #include "nsIDOMHTMLInputElement.h"
 #include "nsIDOMNSEditableElement.h"
 #include "nsIDOMXULButtonElement.h"
 #include "nsIDOMXULCheckboxElement.h"
 #include "nsIDOMXULMenuListElement.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
 #include "nsIDOMXULTextboxElement.h"
 #include "nsIEditor.h"
@@ -412,58 +413,51 @@ nsXULGroupboxAccessible::NativeRole()
 {
   return nsIAccessibleRole::ROLE_GROUPING;
 }
 
 nsresult
 nsXULGroupboxAccessible::GetNameInternal(nsAString& aName)
 {
   // XXX: we use the first related accessible only.
-  nsCOMPtr<nsIAccessible> label =
-    nsRelUtils::GetRelatedAccessible(this, nsIAccessibleRelation::RELATION_LABELLED_BY);
-
-  if (label) {
+  nsAccessible* label =
+    RelationByType(nsIAccessibleRelation::RELATION_LABELLED_BY).Next();
+  if (label)
     return label->GetName(aName);
-  }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsXULGroupboxAccessible::GetRelationByType(PRUint32 aRelationType,
-                                           nsIAccessibleRelation **aRelation)
+Relation
+nsXULGroupboxAccessible::RelationByType(PRUint32 aType)
 {
-  nsresult rv = nsAccessibleWrap::GetRelationByType(aRelationType, aRelation);
-  NS_ENSURE_SUCCESS(rv, rv);
+  Relation rel = nsAccessibleWrap::RelationByType(aType);
+  if (aType != nsIAccessibleRelation::RELATION_LABELLED_BY)
+    return rel;
 
-  if (aRelationType == nsIAccessibleRelation::RELATION_LABELLED_BY) {
-    // The label for xul:groupbox is generated from xul:label that is
-    // inside the anonymous content of the xul:caption.
-    // The xul:label has an accessible object but the xul:caption does not
-    PRInt32 childCount = GetChildCount();
-    for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
-      nsAccessible *childAcc = GetChildAt(childIdx);
-      if (childAcc->Role() == nsIAccessibleRole::ROLE_LABEL) {
-        // Ensure that it's our label
-        // XXX: we'll fail if group accessible expose more than one relation
-        // targets.
-        nsCOMPtr<nsIAccessible> testGroupboxAccessible =
-          nsRelUtils::GetRelatedAccessible(childAcc,
-                                           nsIAccessibleRelation::RELATION_LABEL_FOR);
-
-        if (testGroupboxAccessible == this) {
+  // The label for xul:groupbox is generated from xul:label that is
+  // inside the anonymous content of the xul:caption.
+  // The xul:label has an accessible object but the xul:caption does not
+  PRInt32 childCount = GetChildCount();
+  for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
+    nsAccessible *childAcc = GetChildAt(childIdx);
+    if (childAcc->Role() == nsIAccessibleRole::ROLE_LABEL) {
+      // Ensure that it's our label
+      Relation reverseRel =
+        childAcc->RelationByType(nsIAccessibleRelation::RELATION_LABEL_FOR);
+      nsAccessible* testGroupbox = nsnull;
+      while ((testGroupbox = reverseRel.Next()))
+        if (testGroupbox == this) {
           // The <label> points back to this groupbox
-          return nsRelUtils::
-            AddTarget(aRelationType, aRelation, childAcc);
+          rel.AppendTarget(childAcc);
         }
-      }
     }
   }
 
-  return NS_OK;
+  return rel;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULRadioButtonAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULRadioButtonAccessible::
   nsXULRadioButtonAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
--- a/accessible/src/xul/nsXULFormControlAccessible.h
+++ b/accessible/src/xul/nsXULFormControlAccessible.h
@@ -135,23 +135,20 @@ private:
 /**
  * Used for XUL groupbox element.
  */
 class nsXULGroupboxAccessible : public nsAccessibleWrap
 {
 public:
   nsXULGroupboxAccessible(nsIContent *aContent, nsIWeakReference *aShell);
 
-  // nsIAccessible
-  NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
-                               nsIAccessibleRelation **aRelation);
-
   // nsAccessible
   virtual PRUint32 NativeRole();
   virtual nsresult GetNameInternal(nsAString& aName);
+  virtual Relation RelationByType(PRUint32 aRelationType);
 };
 
 /**
  * Used for XUL radio element (radio button).
  */
 class nsXULRadioButtonAccessible : public nsRadioButtonAccessible
 {
 
--- a/accessible/src/xul/nsXULListboxAccessible.cpp
+++ b/accessible/src/xul/nsXULListboxAccessible.cpp
@@ -42,16 +42,18 @@
 
 #include "States.h"
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
 
 #include "nsIDOMXULPopupElement.h"
 #include "nsIDOMXULMultSelectCntrlEl.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
+#include "nsIDOMNodeList.h"
+#include "nsComponentManagerUtils.h"
 
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULColumnsAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULColumnsAccessible::
--- a/accessible/src/xul/nsXULTabAccessible.cpp
+++ b/accessible/src/xul/nsXULTabAccessible.cpp
@@ -34,20 +34,21 @@
  * 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 "nsXULTabAccessible.h"
 
 #include "nsAccUtils.h"
-#include "nsRelUtils.h"
+#include "Relation.h"
 #include "States.h"
 
 // NOTE: alphabetically ordered
+#include "nsIAccessibleRelation.h"
 #include "nsIDocument.h"
 #include "nsIFrame.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMXULSelectCntrlEl.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
 #include "nsIDOMXULRelatedElement.h"
 
 using namespace mozilla::a11y;
@@ -133,42 +134,38 @@ nsXULTabAccessible::NativeState()
     PRBool selected = PR_FALSE;
     if (NS_SUCCEEDED(tab->GetSelected(&selected)) && selected)
       state |= states::SELECTED;
   }
   return state;
 }
 
 // nsIAccessible
-NS_IMETHODIMP
-nsXULTabAccessible::GetRelationByType(PRUint32 aRelationType,
-                                      nsIAccessibleRelation **aRelation)
+Relation
+nsXULTabAccessible::RelationByType(PRUint32 aType)
 {
-  nsresult rv = nsAccessibleWrap::GetRelationByType(aRelationType,
-                                                    aRelation);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (aRelationType != nsIAccessibleRelation::RELATION_LABEL_FOR)
-    return NS_OK;
+  Relation rel = nsAccessibleWrap::RelationByType(aType);
+  if (aType != nsIAccessibleRelation::RELATION_LABEL_FOR)
+    return rel;
 
   // Expose 'LABEL_FOR' relation on tab accessible for tabpanel accessible.
   nsCOMPtr<nsIDOMXULRelatedElement> tabsElm =
     do_QueryInterface(mContent->GetParent());
   if (!tabsElm)
-    return NS_OK;
+    return rel;
 
   nsCOMPtr<nsIDOMNode> DOMNode(GetDOMNode());
   nsCOMPtr<nsIDOMNode> tabpanelNode;
   tabsElm->GetRelatedElement(DOMNode, getter_AddRefs(tabpanelNode));
   if (!tabpanelNode)
-    return NS_OK;
+    return rel;
 
   nsCOMPtr<nsIContent> tabpanelContent(do_QueryInterface(tabpanelNode));
-  return nsRelUtils::AddTargetFromContent(aRelationType, aRelation,
-                                          tabpanelContent);
+  rel.AppendTarget(tabpanelContent);
+  return rel;
 }
 
 void
 nsXULTabAccessible::GetPositionAndSizeInternal(PRInt32 *aPosInSet,
                                                PRInt32 *aSetSize)
 {
   nsAccUtils::GetPositionAndSizeForXULSelectControlItem(mContent, aPosInSet,
                                                         aSetSize);
@@ -239,34 +236,31 @@ nsXULTabpanelAccessible::
 }
 
 PRUint32
 nsXULTabpanelAccessible::NativeRole()
 {
   return nsIAccessibleRole::ROLE_PROPERTYPAGE;
 }
 
-NS_IMETHODIMP
-nsXULTabpanelAccessible::GetRelationByType(PRUint32 aRelationType,
-                                           nsIAccessibleRelation **aRelation)
+Relation
+nsXULTabpanelAccessible::RelationByType(PRUint32 aType)
 {
-  nsresult rv = nsAccessibleWrap::GetRelationByType(aRelationType, aRelation);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (aRelationType != nsIAccessibleRelation::RELATION_LABELLED_BY)
-    return NS_OK;
+  Relation rel = nsAccessibleWrap::RelationByType(aType);
+  if (aType != nsIAccessibleRelation::RELATION_LABELLED_BY)
+    return rel;
 
   // Expose 'LABELLED_BY' relation on tabpanel accessible for tab accessible.
   nsCOMPtr<nsIDOMXULRelatedElement> tabpanelsElm =
     do_QueryInterface(mContent->GetParent());
   if (!tabpanelsElm)
-    return NS_OK;
+    return rel;
 
   nsCOMPtr<nsIDOMNode> DOMNode(GetDOMNode());
   nsCOMPtr<nsIDOMNode> tabNode;
   tabpanelsElm->GetRelatedElement(DOMNode, getter_AddRefs(tabNode));
   if (!tabNode)
-    return NS_OK;
+    return rel;
 
   nsCOMPtr<nsIContent> tabContent(do_QueryInterface(tabNode));
-  return nsRelUtils::AddTargetFromContent(aRelationType, aRelation,
-                                          tabContent);
+  rel.AppendTarget(tabContent);
+  return rel;
 }
--- a/accessible/src/xul/nsXULTabAccessible.h
+++ b/accessible/src/xul/nsXULTabAccessible.h
@@ -51,24 +51,23 @@ class nsXULTabAccessible : public nsAcce
 public:
   enum { eAction_Switch = 0 };
 
   nsXULTabAccessible(nsIContent *aContent, nsIWeakReference *aShell);
 
   // nsIAccessible
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD DoAction(PRUint8 index);
-  NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
-                               nsIAccessibleRelation **aRelation);
 
   // nsAccessible
   virtual void GetPositionAndSizeInternal(PRInt32 *aPosInSet,
                                           PRInt32 *aSetSize);
   virtual PRUint32 NativeRole();
   virtual PRUint64 NativeState();
+  virtual Relation RelationByType(PRUint32 aType);
 
   // ActionAccessible
   virtual PRUint8 ActionCount();
 };
 
 
 /**
  * A container of tab objects, xul:tabs element.
@@ -113,18 +112,15 @@ public:
  * for example we do not create instance of this class for XUL textbox used as
  * a tabpanel.
  */
 class nsXULTabpanelAccessible : public nsAccessibleWrap
 {
 public:
   nsXULTabpanelAccessible(nsIContent *aContent, nsIWeakReference *aShell);
 
-  // nsIAccessible
-  NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
-                               nsIAccessibleRelation **aRelation);
-
   // nsAccessible
   virtual PRUint32 NativeRole();
+  virtual Relation RelationByType(PRUint32 aType);
 };
 
 #endif
 
--- a/accessible/src/xul/nsXULTextAccessible.cpp
+++ b/accessible/src/xul/nsXULTextAccessible.cpp
@@ -39,20 +39,21 @@
 
 // NOTE: groups are alphabetically ordered
 #include "nsXULTextAccessible.h"
 
 #include "nsAccessibilityAtoms.h"
 #include "nsAccUtils.h"
 #include "nsBaseWidgetAccessible.h"
 #include "nsCoreUtils.h"
-#include "nsRelUtils.h"
 #include "nsTextEquivUtils.h"
+#include "Relation.h"
 #include "States.h"
 
+#include "nsIAccessibleRelation.h"
 #include "nsIDOMXULDescriptionElement.h"
 #include "nsINameSpaceManager.h"
 #include "nsString.h"
 #include "nsNetUtil.h"
 
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -83,35 +84,31 @@ nsXULTextAccessible::NativeRole()
 PRUint64
 nsXULTextAccessible::NativeState()
 {
   // Labels and description have read only state
   // They are not focusable or selectable
   return nsHyperTextAccessibleWrap::NativeState() | states::READONLY;
 }
 
-NS_IMETHODIMP
-nsXULTextAccessible::GetRelationByType(PRUint32 aRelationType,
-                                       nsIAccessibleRelation **aRelation)
+Relation
+nsXULTextAccessible::RelationByType(PRUint32 aType)
 {
-  nsresult rv =
-    nsHyperTextAccessibleWrap::GetRelationByType(aRelationType, aRelation);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (aRelationType == nsIAccessibleRelation::RELATION_LABEL_FOR) {
+  Relation rel = nsHyperTextAccessibleWrap::RelationByType(aType);
+  if (aType == nsIAccessibleRelation::RELATION_LABEL_FOR) {
     // Caption is the label for groupbox
     nsIContent *parent = mContent->GetParent();
     if (parent && parent->Tag() == nsAccessibilityAtoms::caption) {
       nsAccessible* parent = Parent();
       if (parent && parent->Role() == nsIAccessibleRole::ROLE_GROUPING)
-        return nsRelUtils::AddTarget(aRelationType, aRelation, parent);
+        rel.AppendTarget(parent);
     }
   }
 
-  return NS_OK;
+  return rel;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTooltipAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULTooltipAccessible::
--- a/accessible/src/xul/nsXULTextAccessible.h
+++ b/accessible/src/xul/nsXULTextAccessible.h
@@ -43,28 +43,24 @@
 #include "nsBaseWidgetAccessible.h"
 #include "nsHyperTextAccessibleWrap.h"
 
 /**
  * Used for XUL description and label elements.
  */
 class nsXULTextAccessible : public nsHyperTextAccessibleWrap
 {
-
 public:
   nsXULTextAccessible(nsIContent *aContent, nsIWeakReference *aShell);
 
-  // nsIAccessible
-  NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
-                               nsIAccessibleRelation **aRelation);
-
   // nsAccessible
   virtual nsresult GetNameInternal(nsAString& aName);
   virtual PRUint32 NativeRole();
   virtual PRUint64 NativeState();
+  virtual Relation RelationByType(PRUint32 aRelationType);
 };
 
 /**
  * Used for XUL tooltip element.
  */
 class nsXULTooltipAccessible : public nsLeafAccessible
 {
 
--- a/accessible/src/xul/nsXULTreeAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeAccessible.cpp
@@ -1,9 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 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/
  *
@@ -37,19 +38,20 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsXULTreeAccessible.h"
 
 #include "nsAccCache.h"
 #include "nsAccUtils.h"
 #include "nsCoreUtils.h"
 #include "nsDocAccessible.h"
-#include "nsRelUtils.h"
+#include "Relation.h"
 #include "States.h"
 
+#include "nsIAccessibleRelation.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDOMXULMultSelectCntrlEl.h"
 #include "nsIDOMXULTreeElement.h"
 #include "nsITreeSelection.h"
 #include "nsIMutableArray.h"
 #include "nsComponentManagerUtils.h"
 
 using namespace mozilla::a11y;
@@ -751,42 +753,36 @@ nsXULTreeItemAccessibleBase::TakeFocus()
   mTreeView->GetSelection(getter_AddRefs(selection));
   if (selection)
     selection->SetCurrentIndex(mRow);
 
   // focus event will be fired here
   return nsAccessible::TakeFocus();
 }
 
-NS_IMETHODIMP
-nsXULTreeItemAccessibleBase::GetRelationByType(PRUint32 aRelationType,
-                                               nsIAccessibleRelation **aRelation)
+Relation
+nsXULTreeItemAccessibleBase::RelationByType(PRUint32 aType)
 {
-  NS_ENSURE_ARG_POINTER(aRelation);
-  *aRelation = nsnull;
+  if (aType != nsIAccessibleRelation::RELATION_NODE_CHILD_OF)
+    return nsAccessible::RelationByType(aType);
 
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  if (aRelationType == nsIAccessibleRelation::RELATION_NODE_CHILD_OF) {
+  Relation rel;
     PRInt32 parentIndex;
-    if (NS_SUCCEEDED(mTreeView->GetParentIndex(mRow, &parentIndex))) {
-      if (parentIndex == -1)
-        return nsRelUtils::AddTarget(aRelationType, aRelation, mParent);
-
-      nsRefPtr<nsXULTreeAccessible> treeAcc = do_QueryObject(mParent);
+  if (!NS_SUCCEEDED(mTreeView->GetParentIndex(mRow, &parentIndex)))
+    return rel;
 
-      nsAccessible *logicalParent = treeAcc->GetTreeItemAccessible(parentIndex);
-      return nsRelUtils::AddTarget(aRelationType, aRelation, logicalParent);
-    }
-
-    return NS_OK;
+  if (parentIndex == -1) {
+    rel.AppendTarget(mParent);
+    return rel;
   }
 
-  return nsAccessible::GetRelationByType(aRelationType, aRelation);
+  nsRefPtr<nsXULTreeAccessible> treeAcc = do_QueryObject(mParent);
+
+  rel.AppendTarget(treeAcc->GetTreeItemAccessible(parentIndex));
+  return rel;
 }
 
 PRUint8
 nsXULTreeItemAccessibleBase::ActionCount()
 {
   // "activate" action is available for all treeitems, "expand/collapse" action
   // is avaible for treeitem which is container.
   return IsExpandable() ? 2 : 1;
--- a/accessible/src/xul/nsXULTreeAccessible.h
+++ b/accessible/src/xul/nsXULTreeAccessible.h
@@ -183,34 +183,32 @@ public:
 
   // nsIAccessible
   NS_IMETHOD GetBounds(PRInt32 *aX, PRInt32 *aY,
                        PRInt32 *aWidth, PRInt32 *aHeight);
 
   NS_IMETHOD SetSelected(PRBool aSelect); 
   NS_IMETHOD TakeFocus();
 
-  NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
-                               nsIAccessibleRelation **aRelation);
-
   NS_IMETHOD GroupPosition(PRInt32 *aGroupLevel,
                            PRInt32 *aSimilarItemsInGroup,
                            PRInt32 *aPositionInGroup);
 
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD DoAction(PRUint8 aIndex);
 
   // nsAccessNode
   virtual bool IsDefunct() const;
   virtual void Shutdown();
   virtual bool IsPrimaryForNode() const;
 
   // nsAccessible
   virtual PRUint64 NativeState();
   virtual PRInt32 IndexInParent() const;
+  virtual Relation RelationByType(PRUint32 aType);
   virtual nsAccessible* FocusedChild();
 
   // ActionAccessible
   virtual PRUint8 ActionCount();
 
   // nsXULTreeItemAccessibleBase
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_XULTREEITEMBASEACCESSIBLE_IMPL_CID)
 
--- a/accessible/src/xul/nsXULTreeGridAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeGridAccessible.cpp
@@ -41,16 +41,17 @@
 #include "nsAccCache.h"
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
 #include "nsDocAccessible.h"
 #include "nsEventShell.h"
 #include "States.h"
 
 #include "nsITreeSelection.h"
+#include "nsComponentManagerUtils.h"
 
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeGridAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULTreeGridAccessible::
--- a/accessible/tests/mochitest/Makefile.in
+++ b/accessible/tests/mochitest/Makefile.in
@@ -42,16 +42,17 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = accessible
 
 DIRS	= \
   actions \
   attributes \
   editabletext \
   events \
+  focus \
   hyperlink \
   hypertext \
   name \
   relations \
   selectable \
   states \
   table \
   text \
@@ -98,17 +99,16 @@ include $(topsrcdir)/config/rules.mk
 		test_elm_nsApplicationAcc.html \
 		test_elm_plugin.html \
  		test_nsIAccessible_selects.html \
 		test_nsIAccessibleDocument.html \
 		test_nsIAccessibleImage.html \
 		test_nsIAccessNode_utils.html \
 		test_nsOuterDocAccessible.html \
 		test_role_nsHyperTextAcc.html \
-		test_takeFocus.html \
 		test_text_caret.html \
 		test_textboxes.html \
 		test_textboxes.xul \
 		testTextboxes.js \
 		text.js \
 		treeview.css \
 		treeview.js \
 		$(NULL)
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/focus/Makefile.in
@@ -0,0 +1,54 @@
+#
+# ***** 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) 2011
+# 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/focus
+
+include $(DEPTH)/config/autoconf.mk
+include $(topsrcdir)/config/rules.mk
+
+_TEST_FILES =\
+		test_focusedChild.html \
+		test_takeFocus.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/focus/test_focusedChild.html
@@ -0,0 +1,85 @@
+<html>
+
+<head>
+  <title>nsIAccessible::focusedChild 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="../common.js"></script>
+  <script type="application/javascript"
+          src="../states.js"></script>
+  <script type="application/javascript"
+          src="../events.js"></script>
+
+  <script type="application/javascript">
+    function openWnd()
+    {
+      this.eventSeq = [ new invokerChecker(EVENT_FOCUS,
+                                           getDialogAccessible,
+                                           this) ];
+
+      this.invoke = function openWnd_invoke()
+      {
+        this.dialog = window.openDialog("about:mozilla",
+                                        "AboutMozilla",
+                                        "chrome,width=600,height=600");
+      }
+
+      this.finalCheck = function openWnd_finalCheck()
+      {
+        var app = getApplicationAccessible();
+        is(app.focusedChild, getDialogAccessible(this),
+           "Wrong focused child");
+
+        this.dialog.close();
+      }
+
+      this.getID = function openWnd_getID()
+      {
+        return "focusedChild for application accessible";
+      }
+
+      function getDialogAccessible(aInvoker)
+      {
+        return getAccessible(aInvoker.dialog.document);
+      }
+    }
+
+    //gA11yEventDumpToConsole = true;
+    var gQueue = null;
+
+    function doTest()
+    {
+      gQueue = new eventQueue();
+
+      gQueue.push(new openWnd());
+
+      gQueue.invoke(); // Will call SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=677467"
+     title="focusedChild crashes on application accessible">
+    Mozilla Bug 677467
+  </a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+</body>
+</html>
rename from accessible/tests/mochitest/test_takeFocus.html
rename to accessible/tests/mochitest/focus/test_takeFocus.html
--- a/accessible/tests/mochitest/test_takeFocus.html
+++ b/accessible/tests/mochitest/focus/test_takeFocus.html
@@ -5,22 +5,23 @@
 
   <link rel="stylesheet" type="text/css"
         href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/MochiKit/packed.js"></script>
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
   <script type="application/javascript"
-          src="common.js"></script>
+          src="../common.js"></script>
   <script type="application/javascript"
-          src="states.js"></script>
+          src="../states.js"></script>
   <script type="application/javascript"
-          src="events.js"></script>
+          src="../events.js"></script>
 
   <script type="application/javascript">
     ////////////////////////////////////////////////////////////////////////////
     // Test
 
     var gQueue = null;
 
     function takeFocusInvoker(aID)
--- a/accessible/tests/mochitest/relations/test_tabbrowser.xul
+++ b/accessible/tests/mochitest/relations/test_tabbrowser.xul
@@ -69,17 +69,17 @@
           }
         },
 
         tabBrowser: tabBrowser,
         reorderCnt: 0
       };
       registerA11yEventListener(EVENT_REORDER, handler);
 
-      tabBrowser.loadTabs(["about:", "about:mozilla"], false, true);
+      tabBrowser.loadTabs(docURIs, false, true);
     }
 
     function testRelations()
     {
       //////////////////////////////////////////////////////////////////////////
       // 'labelled by'/'label for' relations for xul:tab and xul:tabpanel
 
       var tabs = getNode("tabbrowser").tabContainer.childNodes;
--- a/browser/app/Makefile.in
+++ b/browser/app/Makefile.in
@@ -151,20 +151,16 @@ RCFLAGS += -DMOZ_PHOENIX
 ifdef DEBUG
 RCFLAGS += -DDEBUG
 endif
 RCFLAGS += -DFIREFOX_ICO=\"$(DIST)/branding/firefox-os2.ico\" -DDOCUMENT_ICO=\"$(DIST)/branding/document-os2.ico\"
 endif
 
 include $(topsrcdir)/config/rules.mk
 
-ifeq ($(MOZ_WIDGET_TOOLKIT),photon)
-LIBS += -lphexlib
-endif
-
 ifeq ($(OS_ARCH),WINNT)
 #
 # Control the default heap size.
 # This is the heap returned by GetProcessHeap().
 # As we use the CRT heap, the default size is too large and wastes VM.
 #
 # The default heap size is 1MB on Win32.
 # The heap will grow if need be.
--- a/browser/base/content/tabview/groupitems.js
+++ b/browser/base/content/tabview/groupitems.js
@@ -481,36 +481,46 @@ GroupItem.prototype = Utils.extend(new I
       if (arrangeGroup)
         this.arrange();
     }
   },
 
   // ----------
   // Function: getContentBounds
   // Returns a <Rect> for the groupItem's content area (which doesn't include the title, etc).
-  getContentBounds: function GroupItem_getContentBounds() {
+  //
+  // Parameters:
+  //   options - an object with additional parameters, see below
+  //
+  // Possible options:
+  //   forceStacked - true to force content bounds for stacked mode
+  getContentBounds: function GroupItem_getContentBounds(options) {
     var box = this.getBounds();
     var titleHeight = this.$titlebar.height();
     box.top += titleHeight;
     box.height -= titleHeight;
 
     let appTabTrayContainer = iQ(this.$appTabTray[0].parentNode);
     var appTabTrayWidth = appTabTrayContainer.width();
     if (appTabTrayWidth)
       appTabTrayWidth += parseInt(appTabTrayContainer.css(UI.rtl ? "left" : "right"));
 
     box.width -= appTabTrayWidth;
     if (UI.rtl) {
       box.left += appTabTrayWidth;
     }
 
-    // Make the computed bounds' "padding" and new tab button margin actually be
+    // Make the computed bounds' "padding" and expand button margin actually be
     // themeable --OR-- compute this from actual bounds. Bug 586546
     box.inset(6, 6);
-    box.height -= 33; // For new tab button
+
+    // make some room for the expand button if we're stacked
+    let isStacked = (options && options.forceStacked) || this.isStacked();
+    if (isStacked)
+      box.height -= 33; // 33px room for the expand button
 
     return box;
   },
 
   // ----------
   // Function: setBounds
   // Sets the bounds with the given <Rect>, animating unless "immediately" is false.
   //
@@ -1350,20 +1360,21 @@ GroupItem.prototype = Utils.extend(new I
     });
 
     if (GroupItems._arrangePaused) {
       GroupItems.pushArrange(this, options);
       return false;
     }
     
     let shouldStack = this.shouldStack(childrenToArrange.length + (options.addTab ? 1 : 0));
-    let box = this.getContentBounds();
+    let shouldStackArrange = (shouldStack && !this.expanded);
+    let box = this.getContentBounds({forceStacked: shouldStackArrange});
     
     // if we should stack and we're not expanded
-    if (shouldStack && !this.expanded) {
+    if (shouldStackArrange) {
       this.showExpandControl();
       this._stackArrange(childrenToArrange, box, options);
       return false;
     } else {
       this.hideExpandControl();
       // a dropIndex is returned
       return this._gridArrange(childrenToArrange, box, options);
     }
--- a/browser/base/content/test/subtst_contextmenu.html
+++ b/browser/base/content/test/subtst_contextmenu.html
@@ -21,16 +21,17 @@ Browser context menu subtest.
 <textarea id="test-textarea">chssseesbbbie</textarea> <!-- a weird word which generates only one suggestion -->
 <div id="test-contenteditable" contenteditable="true">chssseefsbbbie</div> <!-- a more weird word which generates no suggestions -->
 <input id="test-input-spellcheck" type="text" spellcheck="true" autofocus value="prodkjfgigrty"> <!-- this one also generates one suggestion -->
 <div contextmenu="myMenu">
   <p id="test-pagemenu" hopeless="true">I've got a context menu!</p>
   <menu id="myMenu" type="context">
     <menuitem label="Plain item" onclick="document.getElementById('test-pagemenu').removeAttribute('hopeless');"></menuitem>
     <menuitem label="Disabled item" disabled></menuitem>
+    <menuitem> Item w/ textContent</menuitem>
     <menu>
       <menuitem type="checkbox" label="Checkbox" checked></menuitem>
     </menu>
     <menu>
       <menuitem type="radio" label="Radio1" checked></menuitem>
       <menuitem type="radio" label="Radio2"></menuitem>
       <menuitem type="radio" label="Radio3"></menuitem>
     </menu>
--- a/browser/base/content/test/tabview/browser_tabview_bug588265.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug588265.js
@@ -5,27 +5,27 @@ let contentWindow;
 let groupItemTwoId;
 
 function test() {
   waitForExplicitFinish();
   
   registerCleanupFunction(function() {
     while (gBrowser.tabs[1])
       gBrowser.removeTab(gBrowser.tabs[1]);
-    hideTabView(function() {});
+    hideTabView();
   });
   gBrowser.loadOneTab("about:blank", { inBackground: true });
   showTabView(setup);
 }
 
 function setup() {
   registerCleanupFunction(function() {
     let groupItem = contentWindow.GroupItems.groupItem(groupItemTwoId);
     if (groupItem)
-      closeGroupItem(groupItem, function() {}); 
+      closeGroupItem(groupItem);
   });
 
   let contentWindow = TabView.getContentWindow();
   is(contentWindow.GroupItems.groupItems.length, 1, "Has only one group");
 
   let groupItemOne = contentWindow.GroupItems.groupItems[0];
   is(groupItemOne.getChildren().length, 2, "Group one has 2 tab items");
 
--- a/browser/base/content/test/tabview/browser_tabview_bug590606.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug590606.js
@@ -10,26 +10,26 @@ function test() {
 
   originalTab = gBrowser.visibleTabs[0];
   // add a tab to the existing group.
   newTabOne = gBrowser.addTab();
 
   registerCleanupFunction(function() {
     while (gBrowser.tabs[1])
       gBrowser.removeTab(gBrowser.tabs[1]);
-    hideTabView(function() {});
+    hideTabView();
   });
 
   showTabView(function() {
     let contentWindow = TabView.getContentWindow();
 
     registerCleanupFunction(function() {
       let groupItem = contentWindow.GroupItems.groupItem(groupItemTwoId);
       if (groupItem)
-        closeGroupItem(groupItem, function() {});
+        closeGroupItem(groupItem);
     });
 
     is(contentWindow.GroupItems.groupItems.length, 1, 
        "There is one group item on startup");
     let groupItemOne = contentWindow.GroupItems.groupItems[0];
     is(groupItemOne.getChildren().length, 2, 
        "There should be two tab items in that group.");
     is(gBrowser.selectedTab, groupItemOne.getChild(0).tab,
--- a/browser/base/content/test/tabview/browser_tabview_bug604098.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug604098.js
@@ -5,17 +5,17 @@ let contentWindow;
 let contentElement;
 
 function test() {
   waitForExplicitFinish();
 
   registerCleanupFunction(function() {
     if (gBrowser.tabs.length > 1)
       gBrowser.removeTab(gBrowser.tabs[1]);
-    hideTabView(function() {});
+    hideTabView();
   });
 
   showTabView(function() {
     contentWindow = TabView.getContentWindow();
     contentElement = contentWindow.document.getElementById("content");
     test1();
   });
 }
--- a/browser/base/content/test/tabview/browser_tabview_bug610208.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug610208.js
@@ -123,25 +123,29 @@ function test() {
   }
 
   // make sure we don't freeze item size when removing an item from a stack
   let testRemoveWhileStacked = function () {
     let oldBounds = groupItem.getBounds();
     groupItem.setSize(250, 250, true);
     groupItem.setUserSize();
 
-    let originalBounds = groupItem.getChild(0).getBounds();
     ok(!groupItem.isStacked(), 'testRemoveWhileStacked: group is not stacked');
 
+    let originalBounds;
+    let tabItem = groupItem.getChild(0);
+
     // add new tabs to let the group stack
-    while (!groupItem.isStacked())
-      win.gBrowser.loadOneTab('about:blank', {inBackground: true});
+    while (!groupItem.isStacked()) {
+      originalBounds = tabItem.getBounds();
+      win.gBrowser.addTab();
+    }
 
     afterAllTabsLoaded(function () {
-      groupItem.getChild(0).close();
+      tabItem.close();
       ok(!groupItem.isStacked(), 'testRemoveWhileStacked: group is not stacked');
 
       let bounds = groupItem.getChild(0).getBounds();
       ok(originalBounds.equals(bounds), 'testRemoveWhileStacked: tabs did not change their size');
 
       // reset group size
       groupItem.setBounds(oldBounds);
       groupItem.setUserSize();
--- a/browser/base/content/test/tabview/browser_tabview_bug624265.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug624265.js
@@ -148,24 +148,8 @@ function loadTabView(callback) {
 }
 
 // ----------
 function enterAndLeavePrivateBrowsing(callback) {
   togglePrivateBrowsing(function () {
     togglePrivateBrowsing(callback);
   });
 }
-
-// ----------
-function togglePrivateBrowsing(callback) {
-  let topic = "private-browsing-transition-complete";
-
-  function pbObserver(aSubject, aTopic, aData) {
-    if (aTopic != topic)
-      return;
-
-    Services.obs.removeObserver(pbObserver, topic, false);
-    afterAllTabsLoaded(callback);
-  }
-
-  Services.obs.addObserver(pbObserver, topic, false);
-  pb.privateBrowsingEnabled = !pb.privateBrowsingEnabled;
-}
--- a/browser/base/content/test/tabview/browser_tabview_bug624727.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug624727.js
@@ -58,18 +58,17 @@ function test() {
     assertOneTabInGroup(prefix, group1);
     assertOneTabInGroup(prefix, group2);
   }
 
   let testStateAfterEnteringPB = function () {
     let prefix = 'enter';
     ok(!pb.privateBrowsingEnabled, prefix + ': private browsing is disabled');
     registerCleanupFunction(function () {
-      if (pb.privateBrowsingEnabled)
-        pb.privateBrowsingEnabled = false
+      pb.privateBrowsingEnabled = false;
     });
 
     togglePrivateBrowsing(function () {
       assertTabViewIsHidden(prefix);
 
       showTabView(function () {
         assertNumberOfGroups(prefix, 1);
         assertNumberOfTabs(prefix, 1);
@@ -124,24 +123,8 @@ function test() {
       gBrowser.pinTab(tabItem1.tab);
       gBrowser.pinTab(tabItem2.tab);
 
       assertValidSetup('setup');
       hideTabView(testStateAfterEnteringPB);
     });
   });
 }
-
-// ----------
-function togglePrivateBrowsing(callback) {
-  let topic = 'private-browsing-transition-complete';
-
-  function pbObserver(aSubject, aTopic, aData) {
-    if (aTopic != topic)
-      return;
-
-    Services.obs.removeObserver(pbObserver, topic);
-    afterAllTabsLoaded(callback);
-  }
-
-  Services.obs.addObserver(pbObserver, topic, false);
-  pb.privateBrowsingEnabled = !pb.privateBrowsingEnabled;
-}
--- a/browser/base/content/test/tabview/browser_tabview_bug627239.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug627239.js
@@ -10,17 +10,17 @@ function test() {
   newTab = gBrowser.addTab();
 
   HttpRequestObserver.register();
 
   registerCleanupFunction(function () {
     HttpRequestObserver.unregister();
     if (gBrowser.tabs[1])
       gBrowser.removeTab(gBrowser.tabs[1]);
-    hideTabView(function () {});
+    hideTabView();
 
     contentWindow.ThumbnailStorage.enablePersistentHttpsCaching =
         enablePersistentHttpsCaching;
   });
 
   showTabView(function() {
     contentWindow = TabView.getContentWindow();
     test1();
--- a/browser/base/content/test/tabview/browser_tabview_bug641802.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug641802.js
@@ -24,21 +24,21 @@ function test() {
   let tvMenu = document.getElementById("context_tabViewMenu");
   let contextMenu = document.getElementById("tabContextMenu");
   let tvMenuPopup = document.getElementById("context_tabViewMenuPopup");
 
   waitForExplicitFinish();
 
   registerCleanupFunction(function () {
     hideMoveToGroupPopup();
-    hideTabView(function () {});
+    hideTabView();
 
     let groupItems = TabView.getContentWindow().GroupItems.groupItems;
     if (groupItems.length > 1)
-      closeGroupItem(groupItems[0], function () {});
+      closeGroupItem(groupItems[0]);
   });
 
   showTabView(function () {
     assertValidPrerequisites(true);
 
     hideTabView(function () {
       let groupItem = createGroupItemWithBlankTabs(window, 200, 200, 10, 1);
       groupItem.setTitle("group2");
--- a/browser/base/content/test/tabview/browser_tabview_bug649006.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug649006.js
@@ -3,17 +3,17 @@
 let contentWindow;
 let contentElement;
 let groupItem;
 
 function test() {
   waitForExplicitFinish();
 
   registerCleanupFunction(function () {
-    hideTabView(function () {});
+    hideTabView();
   });
 
   showTabView(function() {
     contentWindow = TabView.getContentWindow();
     contentElement = contentWindow.document.getElementById("content");
     test1();
   });
 }
--- a/browser/base/content/test/tabview/browser_tabview_click_group.js
+++ b/browser/base/content/test/tabview/browser_tabview_click_group.js
@@ -7,18 +7,18 @@ let groupItemId;
 
 function test() {
   waitForExplicitFinish();
 
   registerCleanupFunction(function() {
     contentWindow.gPrefBranch.clearUserPref("animate_zoom");
     let createdGroupItem = contentWindow.GroupItems.groupItem(groupItemId)
     if (createdGroupItem)
-      closeGroupItem(createdGroupItem, function() {});
-    hideTabView(function() {});
+      closeGroupItem(createdGroupItem);
+    hideTabView();
   });
 
   showTabView(function() {
     contentWindow = TabView.getContentWindow();
     groupItem = createEmptyGroupItem(contentWindow, 300, 300, 200);
     groupItemId = groupItem.id;
     testMouseClickOnEmptyGroupItem();
   });
--- a/browser/base/content/test/tabview/browser_tabview_privatebrowsing.js
+++ b/browser/base/content/test/tabview/browser_tabview_privatebrowsing.js
@@ -60,23 +60,23 @@ function onTabViewLoadedAndShown() {
     // Get normal tab urls
     for (let a = 0; a < gBrowser.tabs.length; a++)
       normalURLs.push(gBrowser.tabs[a].linkedBrowser.currentURI.spec);
 
     // verify that we're all set up for our test
     verifyNormal();
 
     // go into private browsing and make sure Tab View becomes hidden
-    togglePBAndThen(function() {
+    togglePrivateBrowsing(function() {
       whenTabViewIsHidden(function() {
         ok(!TabView.isVisible(), "Tab View is no longer visible");
         verifyPB();
 
         // exit private browsing and make sure Tab View is shown again
-        togglePBAndThen(function() {
+        togglePrivateBrowsing(function() {
           whenTabViewIsShown(function() {
             ok(TabView.isVisible(), "Tab View is visible again");
             verifyNormal();
 
             hideTabView(onTabViewHidden);
           });
         });
       });
@@ -84,22 +84,22 @@ function onTabViewLoadedAndShown() {
   });
 }
 
 // -----------
 function onTabViewHidden() {
   ok(!TabView.isVisible(), "Tab View is not visible");
   
   // go into private browsing and make sure Tab View remains hidden
-  togglePBAndThen(function() {
+  togglePrivateBrowsing(function() {
     ok(!TabView.isVisible(), "Tab View is still not visible");
     verifyPB();
     
     // turn private browsing back off
-    togglePBAndThen(function() {
+    togglePrivateBrowsing(function() {
       verifyNormal();
       
       // end game
       ok(!TabView.isVisible(), "we finish with Tab View not visible");
       registerCleanupFunction(verifyCleanState); // verify after all cleanups
 
       gBrowser.selectedTab = gBrowser.tabs[0];
       finish();
@@ -148,22 +148,8 @@ function verifyNormal() {
 
     let groupItem = contentWindow.GroupItems.groupItems[a];
     is(groupItem.getTitle(), groupTitles[a], prefix + "correct group title");
     
     ok(tab._tabViewTabItem.parent == groupItem,
         prefix + "tab " + a + " is in group " + a);
   }
 }
-
-// ----------
-function togglePBAndThen(callback) {
-  function pbObserver(aSubject, aTopic, aData) {
-    if (aTopic != "private-browsing-transition-complete")
-      return;
-
-    Services.obs.removeObserver(pbObserver, "private-browsing-transition-complete");
-    afterAllTabsLoaded(callback);
-  }
-
-  Services.obs.addObserver(pbObserver, "private-browsing-transition-complete", false);
-  pb.privateBrowsingEnabled = !pb.privateBrowsingEnabled;
-}
--- a/browser/base/content/test/tabview/browser_tabview_undo_group.js
+++ b/browser/base/content/test/tabview/browser_tabview_undo_group.js
@@ -2,30 +2,30 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 function test() {
   waitForExplicitFinish();
 
   registerCleanupFunction(function() {
     while (gBrowser.tabs[1])
       gBrowser.removeTab(gBrowser.tabs[1]);
-    hideTabView(function() {});
+    hideTabView();
   });
   showTabView(onTabViewWindowLoaded);
 }
 
 function onTabViewWindowLoaded() {
   ok(TabView.isVisible(), "Tab View is visible");
 
   let contentWindow = TabView.getContentWindow();
 
   registerCleanupFunction(function() {
     let groupItem = contentWindow.GroupItems.groupItem(groupItemId);
     if (groupItem)
-      closeGroupItem(groupItem, function() {});
+      closeGroupItem(groupItem);
   });
 
   // create a group item
   let groupItem = createGroupItemWithBlankTabs(window, 300, 300, 400, 1);
   let groupItemId = groupItem.id;
   is(groupItem.getChildren().length, 1, "The new group has a tab item");
   // start the tests
   waitForFocus(function() {
--- a/browser/base/content/test/tabview/head.js
+++ b/browser/base/content/test/tabview/head.js
@@ -43,21 +43,22 @@ function createGroupItemWithBlankTabs(wi
   let urls = [];
   while(numNewTabs--)
     urls.push("about:blank");
   return createGroupItemWithTabs(win, width, height, padding, urls, animate);
 }
 
 // ----------
 function closeGroupItem(groupItem, callback) {
-  groupItem.addSubscriber("close", function onClose() {
-    groupItem.removeSubscriber("close", onClose);
-    if ("function" == typeof callback)
+  if (callback) {
+    groupItem.addSubscriber("close", function onClose() {
+      groupItem.removeSubscriber("close", onClose);
       executeSoon(callback);
-  });
+    });
+  }
 
   if (groupItem.getChildren().length) {
     groupItem.addSubscriber("groupHidden", function onHide() {
       groupItem.removeSubscriber("groupHidden", onHide);
       groupItem.closeHidden();
     });
   }
 
@@ -135,32 +136,36 @@ function afterAllTabsLoaded(callback, wi
 function showTabView(callback, win) {
   win = win || window;
 
   if (win.TabView.isVisible()) {
     waitForFocus(callback, win);
     return;
   }
 
-  whenTabViewIsShown(function() {
+  whenTabViewIsShown(function () {
     waitForFocus(callback, win);
   }, win);
+
   win.TabView.show();
 }
 
 // ----------
 function hideTabView(callback, win) {
   win = win || window;
 
   if (!win.TabView.isVisible()) {
-    callback();
+    if (callback)
+      callback();
     return;
   }
 
-  whenTabViewIsHidden(callback, win);
+  if (callback)
+    whenTabViewIsHidden(callback, win);
+
   win.TabView.hide();
 }
 
 // ----------
 function whenTabViewIsHidden(callback, win) {
   win = win || window;
 
   if (!win.TabView.isVisible()) {
@@ -185,40 +190,29 @@ function whenTabViewIsShown(callback, wi
 
   win.addEventListener('tabviewshown', function onShown() {
     win.removeEventListener('tabviewshown', onShown, false);
     callback();
   }, false);
 }
 
 // ----------
-function showSearch(callback, win) {
-  win = win || window;
-
-  let contentWindow = win.TabView.getContentWindow();
-  if (contentWindow.isSearchEnabled()) {
-    callback();
-    return;
-  }
-
-  whenSearchIsEnabled(callback, win);
-  contentWindow.performSearch();
-}
-
-// ----------
 function hideSearch(callback, win) {
   win = win || window;
 
   let contentWindow = win.TabView.getContentWindow();
   if (!contentWindow.isSearchEnabled()) {
-    callback();
+    if (callback)
+      callback();
     return;
   }
 
-  whenSearchIsDisabled(callback, win);
+  if (callback)
+    whenSearchIsDisabled(callback, win);
+
   contentWindow.hideSearch();
 }
 
 // ----------
 function whenSearchIsEnabled(callback, win) {
   win = win || window;
 
   let contentWindow = win.TabView.getContentWindow();
@@ -248,38 +242,46 @@ function whenSearchIsDisabled(callback, 
     callback();
   }, false);
 }
 
 
 // ----------
 function hideGroupItem(groupItem, callback) {
   if (groupItem.hidden) {
-    callback();
+    if (callback)
+      callback();
     return;
   }
 
-  groupItem.addSubscriber("groupHidden", function onHide() {
-    groupItem.removeSubscriber("groupHidden", onHide);
-    callback();
-  });
+  if (callback) {
+    groupItem.addSubscriber("groupHidden", function onHide() {
+      groupItem.removeSubscriber("groupHidden", onHide);
+      callback();
+    });
+  }
+
   groupItem.closeAll();
 }
 
 // ----------
 function unhideGroupItem(groupItem, callback) {
   if (!groupItem.hidden) {
-    callback();
+    if (callback)
+      callback();
     return;
   }
 
-  groupItem.addSubscriber("groupShown", function onShown() {
-    groupItem.removeSubscriber("groupShown", onShown);
-    callback();
-  });
+  if (callback) {
+    groupItem.addSubscriber("groupShown", function onShown() {
+      groupItem.removeSubscriber("groupShown", onShown);
+      callback();
+    });
+  }
+
   groupItem._unhide();
 }
 
 // ----------
 function whenWindowLoaded(win, callback) {
   win.addEventListener("load", function onLoad() {
     win.removeEventListener("load", onLoad, false);
     executeSoon(callback);
@@ -347,8 +349,23 @@ function restoreTab(callback, index, win
     return;
   }
 
   tab._tabViewTabItem.addSubscriber("reconnected", function onReconnected() {
     tab._tabViewTabItem.removeSubscriber("reconnected", onReconnected);
     finalize();
   });
 }
+
+// ----------
+function togglePrivateBrowsing(callback) {
+  let topic = "private-browsing-transition-complete";
+
+  Services.obs.addObserver(function observe() {
+    Services.obs.removeObserver(observe, topic);
+    afterAllTabsLoaded(callback);
+  }, topic, false);
+
+  let pb = Cc["@mozilla.org/privatebrowsing;1"].
+           getService(Ci.nsIPrivateBrowsingService);
+
+  pb.privateBrowsingEnabled = !pb.privateBrowsingEnabled;
+}
--- a/browser/base/content/test/test_contextmenu.html
+++ b/browser/base/content/test/test_contextmenu.html
@@ -471,16 +471,17 @@ function runTest(testNum) {
         closeContextMenu();
         openContextMenuFor(pagemenu); // Invoke context menu for next test.
         break;
 
     case 16:
         // Context menu for element with assigned content context menu
         checkContextMenu(["+Plain item",          {type: "", icon: "", checked: false, disabled: false},
                           "+Disabled item",       {type: "", icon: "", checked: false, disabled: true},
+                          "+Item w/ textContent", {type: "", icon: "", checked: false, disabled: false},
                           "---",                  null,
                           "+Checkbox",            {type: "checkbox", icon: "", checked: true, disabled: false},
                           "---",                  null,
                           "+Radio1",              {type: "checkbox", icon: "", checked: true, disabled: false},
                           "+Radio2",              {type: "checkbox", icon: "", checked: false, disabled: false},
                           "+Radio3",              {type: "checkbox", icon: "", checked: false, disabled: false},
                           "---",                  null,
                           "+Item w/ icon",        {type: "", icon: "favicon.ico", checked: false, disabled: false},
--- a/build/autoconf/lto.m4
+++ b/build/autoconf/lto.m4
@@ -1,11 +1,11 @@
 dnl check if the build is using lto. This is really primitive and only detects llvm based
 dnl compilers right now.
-AC_DEFUN(MOZ_DOING_LTO,
+AC_DEFUN([MOZ_DOING_LTO],
 [
   cat > conftest.c <<EOF
                   int foo = 1;
 EOF
   $1=no
   if ${CC-cc} ${CFLAGS} -S conftest.c -o conftest.s >/dev/null 2>&1; then
     if grep '^target triple =' conftest.s; then
       $1=yes
--- a/build/autoconf/mozheader.m4
+++ b/build/autoconf/mozheader.m4
@@ -32,17 +32,17 @@ dnl use your version of this file under 
 dnl decision by deleting the provisions above and replace them with the notice
 dnl and other provisions required by the GPL or the LGPL. If you do not delete
 dnl the provisions above, a recipient may use your version of this file under
 dnl the terms of any one of the MPL, the GPL or the LGPL.
 dnl
 dnl ***** END LICENSE BLOCK *****
 
 dnl MOZ_CHECK_HEADER(HEADER-FILE, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
-AC_DEFUN(MOZ_CHECK_HEADER,
+AC_DEFUN([MOZ_CHECK_HEADER],
 [ dnl Do the transliteration at runtime so arg 1 can be a shell variable.
   ac_safe=`echo "$1" | sed 'y%./+-%__p_%'`
   AC_MSG_CHECKING([for $1])
   AC_CACHE_VAL(ac_cv_header_$ac_safe,
  [ AC_TRY_COMPILE([#include <$1>], ,
                   eval "ac_cv_header_$ac_safe=yes",
                   eval "ac_cv_header_$ac_safe=no") ])
   if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
@@ -50,16 +50,16 @@ AC_DEFUN(MOZ_CHECK_HEADER,
     ifelse([$2], , :, [$2])
   else
     AC_MSG_RESULT(no)
     ifelse([$3], , , [$3])
   fi
 ])
 
 dnl MOZ_CHECK_HEADERS(HEADER-FILE... [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
-AC_DEFUN(MOZ_CHECK_HEADERS,
+AC_DEFUN([MOZ_CHECK_HEADERS],
 [ for ac_hdr in $1
   do
     MOZ_CHECK_HEADER($ac_hdr,
                      [ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
                        AC_DEFINE_UNQUOTED($ac_tr_hdr) $2], $3)
   done
 ])
--- a/build/autoconf/moznbytetype.m4
+++ b/build/autoconf/moznbytetype.m4
@@ -44,17 +44,17 @@ dnl whose written form contains spaces s
 dnl enclosed by shell quotes.
 dnl
 dnl The cache variable moz_cv_n_byte_type_VARIABLE gets set to the
 dnl type, if found.
 dnl 
 dnl for example:
 dnl MOZ_N_BYTE_TYPE([JS_INT32_T], [4], [int long 'long long' short])
 dnl
-AC_DEFUN(MOZ_N_BYTE_TYPE,
+AC_DEFUN([MOZ_N_BYTE_TYPE],
 [
 dnl The simplest approach would simply be to run a program that says
 dnl   printf ("%d\n", sizeof ($type));
 dnl But that won't work when cross-compiling; this will.
 AC_CACHE_CHECK([for a $2-byte type], moz_cv_n_byte_type_$1, [
   moz_cv_n_byte_type_$1=
   for type in $3; do
     AC_TRY_COMPILE([],
@@ -78,17 +78,17 @@ dnl Check to see which of POSSIBLE-SIZES
 dnl define VARIABLE SIZE. If no size matches, exit the configure script with
 dnl an error message.
 dnl
 dnl The cache variable moz_cv_size_of_VARIABLE gets set to the size, if
 dnl found.
 dnl
 dnl for example:
 dnl MOZ_SIZE_OF_TYPE([JS_BYTES_PER_WORD], [void*], [4 8])
-AC_DEFUN(MOZ_SIZE_OF_TYPE,
+AC_DEFUN([MOZ_SIZE_OF_TYPE],
 [
 AC_CACHE_CHECK([for the size of $2], moz_cv_size_of_$1, [
   moz_cv_size_of_$1=
   for size in $3; do
     AC_TRY_COMPILE([],
                    [
                      int a[sizeof ($2) == $size ? 1 : -1];
                      return 0;
@@ -108,17 +108,17 @@ dnl Check to see which of POSSIBLE-ALIGN
 dnl If we find one, define VARIABLE ALIGNMENT. If no alignment matches, exit
 dnl the configure script with an error message.
 dnl
 dnl The cache variable moz_cv_align_of_VARIABLE gets set to the size, if
 dnl found.
 dnl
 dnl for example:
 dnl MOZ_ALIGN_OF_TYPE(JS_ALIGN_OF_POINTER, void*, 2 4 8 16)
-AC_DEFUN(MOZ_ALIGN_OF_TYPE,
+AC_DEFUN([MOZ_ALIGN_OF_TYPE],
 [
 AC_CACHE_CHECK([for the alignment of $2], moz_cv_align_of_$1, [
   moz_cv_align_of_$1=
   for align in $3; do
     AC_TRY_COMPILE([
                      #include <stddef.h>
                      struct aligner { char c; $2 a; };
                    ],
--- a/build/autoconf/mozprog.m4
+++ b/build/autoconf/mozprog.m4
@@ -31,40 +31,40 @@ dnl under the terms of either the GPL or
 dnl use your version of this file under the terms of the MPL, indicate your
 dnl decision by deleting the provisions above and replace them with the notice
 dnl and other provisions required by the GPL or the LGPL. If you do not delete
 dnl the provisions above, a recipient may use your version of this file under
 dnl the terms of any one of the MPL, the GPL or the LGPL.
 dnl
 dnl ***** END LICENSE BLOCK *****
 
-AC_DEFUN(MOZ_PROG_CHECKMSYS,
+AC_DEFUN([MOZ_PROG_CHECKMSYS],
 [AC_REQUIRE([AC_INIT_BINSH])dnl
 if test `uname -s | grep -c MINGW 2>/dev/null` != "0"; then
   msyshost=1
 fi
 ])
 
-AC_DEFUN(MOZ_PATH_PROG,
+AC_DEFUN([MOZ_PATH_PROG],
 [ AC_PATH_PROG($1,$2,$3,$4)
   if test "$msyshost"; then
     case "[$]$1" in
     /*)
       tmp_DIRNAME=`dirname "[$]$1"`
       tmp_BASENAME=`basename "[$]$1"`
       tmp_PWD=`cd "$tmp_DIRNAME" && pwd -W`
       $1="$tmp_PWD/$tmp_BASENAME"
       if test -e "[$]$1.exe"; then
         $1="[$]$1.exe"
       fi
     esac
   fi
 ])
 
-AC_DEFUN(MOZ_PATH_PROGS,
+AC_DEFUN([MOZ_PATH_PROGS],
 [  AC_PATH_PROGS($1,$2,$3,$4)
   if test "$msyshost"; then
     case "[$]$1" in
     /*)
       tmp_DIRNAME=`dirname "[$]$1"`
       tmp_BASENAME=`basename "[$]$1"`
       tmp_PWD=`cd "$tmp_DIRNAME" && pwd -W`
       $1="$tmp_PWD/$tmp_BASENAME"
--- a/build/autoconf/nss.m4
+++ b/build/autoconf/nss.m4
@@ -1,16 +1,16 @@
 # -*- tab-width: 4; -*-
 # Configure paths for NSS
 # Public domain - Chris Seawood <cls@seawood.org> 2001-04-05
 # Based upon gtk.m4 (also PD) by Owen Taylor
 
 dnl AM_PATH_NSS([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
 dnl Test for NSS, and define NSS_CFLAGS and NSS_LIBS
-AC_DEFUN(AM_PATH_NSS,
+AC_DEFUN([AM_PATH_NSS],
 [dnl
 
 AC_ARG_WITH(nss-prefix,
 	[  --with-nss-prefix=PFX   Prefix where NSS is installed],
 	nss_config_prefix="$withval",
 	nss_config_prefix="")
 
 AC_ARG_WITH(nss-exec-prefix,
new file mode 100644
--- /dev/null
+++ b/build/macosx/mozconfig.leopard
@@ -0,0 +1,13 @@
+if test -z "$CC" ; then
+   CC=gcc-4.2
+fi
+
+if test -z "$CXX" ; then
+   CXX=g++-4.2
+fi
+
+# We do 32 bit builds for leopard
+CC="$CC -arch i386"
+CXX="$CXX -arch i386"
+
+ac_add_options --with-macos-sdk=/Developer/SDKs/MacOSX10.5.sdk
--- a/build/mobile/sutagent/android/ASMozStub.java
+++ b/build/mobile/sutagent/android/ASMozStub.java
@@ -60,25 +60,30 @@ public class ASMozStub extends android.a
     private ServerSocket dataChnl = null;
     private Handler handler = new Handler();
     RunCmdThread runCmdThrd = null;
     RunDataThread runDataThrd = null;
     Thread monitor = null;
     Timer timer = null;
 
     @SuppressWarnings("unchecked")
-    private static final Class[] mStartForegroundSignature = new Class[] {
+    private static final Class<?>[] mSetForegroundSignature = new Class[] {
+    boolean.class};
+    @SuppressWarnings("unchecked")
+    private static final Class<?>[] mStartForegroundSignature = new Class[] {
         int.class, Notification.class};
     @SuppressWarnings("unchecked")
-    private static final Class[] mStopForegroundSignature = new Class[] {
+    private static final Class<?>[] mStopForegroundSignature = new Class[] {
         boolean.class};
 
     private NotificationManager mNM;
+    private Method mSetForeground;
     private Method mStartForeground;
     private Method mStopForeground;
+    private Object[] mSetForegroundArgs = new Object[1];
     private Object[] mStartForegroundArgs = new Object[2];
     private Object[] mStopForegroundArgs = new Object[1];
 
     @Override
     public IBinder onBind(Intent intent)
         {
         return null;
         }
@@ -92,16 +97,23 @@ public class ASMozStub extends android.a
             mStartForeground = getClass().getMethod("startForeground", mStartForegroundSignature);
             mStopForeground = getClass().getMethod("stopForeground", mStopForegroundSignature);
             }
         catch (NoSuchMethodException e) {
             // Running on an older platform.
             mStartForeground = mStopForeground = null;
             }
 
+        try {
+            mSetForeground = getClass().getMethod("setForeground", mSetForegroundSignature);
+            }
+        catch (NoSuchMethodException e) {
+            mSetForeground = null;
+            }
+
         doToast("Listener Service created...");
         }
 
     public void onStart(Intent intent, int startId) {
         super.onStart(intent, startId);
 
         try {
             cmdChnl = new ServerSocket(20701);
@@ -178,17 +190,28 @@ public class ASMozStub extends android.a
             } catch (IllegalAccessException e) {
                 // Should not happen.
                 Log.w("ScreenOnWidget", "Unable to invoke startForeground", e);
             }
             return;
         }
 
         // Fall back on the old API.
-        setForeground(true);
+        if  (mSetForeground != null) {
+            try {
+                mSetForegroundArgs[0] = Boolean.TRUE;
+                mSetForeground.invoke(this, mSetForegroundArgs);
+            } catch (IllegalArgumentException e) {
+                e.printStackTrace();
+            } catch (IllegalAccessException e) {
+                e.printStackTrace();
+            } catch (InvocationTargetException e) {
+                e.printStackTrace();
+            }
+        }
         mNM.notify(id, notification);
     }
 
     /**
      * This is a wrapper around the new stopForeground method, using the older
      * APIs if it is not available.
      */
     void stopForegroundCompat(int id) {
@@ -205,11 +228,22 @@ public class ASMozStub extends android.a
                 Log.w("ScreenOnWidget", "Unable to invoke stopForeground", e);
             }
             return;
         }
 
         // Fall back on the old API.  Note to cancel BEFORE changing the
         // foreground state, since we could be killed at that point.
         mNM.cancel(id);
-        setForeground(false);
+        if  (mSetForeground != null) {
+            try {
+                mSetForegroundArgs[0] = Boolean.FALSE;
+                mSetForeground.invoke(this, mSetForegroundArgs);
+            } catch (IllegalArgumentException e) {
+                e.printStackTrace();
+            } catch (IllegalAccessException e) {
+                e.printStackTrace();
+            } catch (InvocationTargetException e) {
+                e.printStackTrace();
+            }
+        }
     }
 }
--- a/build/mobile/sutagent/android/DoCommand.java
+++ b/build/mobile/sutagent/android/DoCommand.java
@@ -132,17 +132,17 @@ public class DoCommand {
 
     String    currentDir = "/";
     String    sErrorPrefix = "##AGENT-WARNING## ";
     boolean bTraceOn = false;
 
     String ffxProvider = "org.mozilla.ffxcp";
     String fenProvider = "org.mozilla.fencp";
 
-    private final String prgVersion = "SUTAgentAndroid Version 1.01";
+    private final String prgVersion = "SUTAgentAndroid Version 1.02";
 
     public enum Command
         {
         RUN ("run"),
         EXEC ("exec"),
         ENVRUN ("envrun"),
         KILL ("kill"),
         PS ("ps"),
--- a/build/mobile/sutagent/android/watcher/WatcherService.java
+++ b/build/mobile/sutagent/android/watcher/WatcherService.java
@@ -83,30 +83,36 @@ public class WatcherService extends Serv
     Process    pProc;
     Context myContext = null;
     Timer myTimer = null;
     private PowerManager.WakeLock pwl = null;
     public static final int NOTIFICATION_ID = 1964;
     boolean bInstalling = false;
 
     @SuppressWarnings("unchecked")
+    private static final Class<?>[] mSetForegroundSignature = new Class[] {
+    boolean.class};
+    @SuppressWarnings("unchecked")
     private static final Class[] mStartForegroundSignature = new Class[] {
         int.class, Notification.class};
     @SuppressWarnings("unchecked")
     private static final Class[] mStopForegroundSignature = new Class[] {
         boolean.class};
 
     private NotificationManager mNM;
+    private Method mSetForeground;
     private Method mStartForeground;
     private Method mStopForeground;
+    private Object[] mSetForegroundArgs = new Object[1];
     private Object[] mStartForegroundArgs = new Object[2];
     private Object[] mStopForegroundArgs = new Object[1];
 
 
     private IWatcherService.Stub stub = new IWatcherService.Stub() {
+        @Override
         public int UpdateApplication(String sAppName, String sFileName, String sOutFile, int bReboot) throws RemoteException
             {
             return UpdtApp(sAppName, sFileName, sOutFile, bReboot);
             }
     };
 
     @Override
     public IBinder onBind(Intent arg0) {
@@ -274,16 +280,22 @@ public class WatcherService extends Serv
                     mStartForeground = getClass().getMethod("startForeground", mStartForegroundSignature);
                     mStopForeground = getClass().getMethod("stopForeground", mStopForegroundSignature);
                     }
                 catch (NoSuchMethodException e)
                     {
                     // Running on an older platform.
                     mStartForeground = mStopForeground = null;
                     }
+                try {
+                    mSetForeground = getClass().getMethod("setForeground", mSetForegroundSignature);
+                    }
+                catch (NoSuchMethodException e) {
+                    mSetForeground = null;
+                    }
                 Notification notification = new Notification();
                 startForegroundCompat(R.string.foreground_service_started, notification);
                 }
             };
         t.start();
         }
 
     /**
@@ -303,17 +315,28 @@ public class WatcherService extends Serv
             } catch (IllegalAccessException e) {
                 // Should not happen.
                 Log.w("ApiDemos", "Unable to invoke startForeground", e);
             }
             return;
         }
 
         // Fall back on the old API.
-        setForeground(true);
+        if  (mSetForeground != null) {
+            try {
+                mSetForegroundArgs[0] = Boolean.TRUE;
+                mSetForeground.invoke(this, mSetForegroundArgs);
+            } catch (IllegalArgumentException e) {
+                e.printStackTrace();
+            } catch (IllegalAccessException e) {
+                e.printStackTrace();
+            } catch (InvocationTargetException e) {
+                e.printStackTrace();
+            }
+        }
         mNM.notify(id, notification);
     }
 
     /**
      * This is a wrapper around the new stopForeground method, using the older
      * APIs if it is not available.
      */
     void stopForegroundCompat(int id) {
@@ -330,17 +353,28 @@ public class WatcherService extends Serv
                 Log.w("ApiDemos", "Unable to invoke stopForeground", e);
             }
             return;
         }
 
         // Fall back on the old API.  Note to cancel BEFORE changing the
         // foreground state, since we could be killed at that point.
         mNM.cancel(id);
-        setForeground(false);
+        if  (mSetForeground != null) {
+            try {
+                mSetForegroundArgs[0] = Boolean.FALSE;
+                mSetForeground.invoke(this, mSetForegroundArgs);
+            } catch (IllegalArgumentException e) {
+                e.printStackTrace();
+            } catch (IllegalAccessException e) {
+                e.printStackTrace();
+            } catch (InvocationTargetException e) {
+                e.printStackTrace();
+            }
+        }
     }
 
     public void doToast(String sMsg)
         {
         Toast toast = Toast.makeText(this, sMsg, Toast.LENGTH_LONG);
         toast.setGravity(Gravity.TOP|Gravity.CENTER_HORIZONTAL, 0, 100);
         toast.show();
         }
@@ -835,16 +869,17 @@ public class WatcherService extends Serv
             runner = new Thread(this);
             msPkgName = sPkgName;
             msPkgFileName = sPkgFileName;
             msOutFile = sOutFile;
             mbReboot = bReboot;
             runner.start();
         }
 
+        @Override
         public void run() {
                bInstalling = true;
             UpdtApp(msPkgName, msPkgFileName, msOutFile, mbReboot);
                bInstalling = false;
         }
     }
 
     private class MyTime extends TimerTask
--- a/build/unix/Makefile.in
+++ b/build/unix/Makefile.in
@@ -1,8 +1,9 @@
+# -*- makefile -*-
 #
 # ***** 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/
@@ -16,16 +17,17 @@
 # March 31, 1998.
 #
 # The Initial Developer of the Original Code is
 # Netscape Communications Corporation.
 # Portions created by the Initial Developer are Copyright (C) 1998
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
+#   Joey Armstrong <joey@mozilla.com>
 #
 # 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
@@ -44,12 +46,20 @@ VPATH		= @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 MODULE       = build
 
 ifdef USE_ELF_HACK
 DIRS = elfhack
 endif
 
+ifdef ENABLE_TESTS
+  ifeq (,$(filter WINNT OS2,$(OS_ARCH)))
+    DIRS += test
+  endif # WIN
+endif # ENABLE_TESTS
+
 include $(topsrcdir)/config/rules.mk
 
 libs:: $(srcdir)/run-mozilla.sh
 	$(INSTALL) $< $(DIST)/bin
+
+# EOF
--- a/build/unix/elfhack/Makefile.in
+++ b/build/unix/elfhack/Makefile.in
@@ -70,43 +70,52 @@ endif
 
 CSRCS := \
   inject/$(CPU).c \
   inject/$(CPU)-noinit.c \
   $(NULL)
 
 libs:: $(CSRCS:.c=.$(OBJ_SUFFIX))
 
-ifndef CROSS_COMPILE
+WRAP_MALLOC_CFLAGS=
+WRAP_MALLOC_LIB=
+
 test$(DLL_SUFFIX): test.$(OBJ_SUFFIX) elfhack $(CSRCS:.c=.$(OBJ_SUFFIX))
 	$(MKSHLIB) $(LDFLAGS) $<
 	@echo ===
 	@echo === If you get failures below, please file a bug describing the error
 	@echo === and your environment \(compiler and linker versions\), and use
 	@echo === --disable-elf-hack until this is fixed.
 	@echo ===
 	@rm -f $@.bak
 	$(CURDIR)/elfhack -b $@
 	# Fail if the backup file doesn't exist
 	[ -f "$@.bak" ]
 	# Fail if the new library doesn't contain less relocations
 	[ $$(objdump -R $@.bak | wc -l) -gt $$(objdump -R $@ | wc -l) ]
 
 .PRECIOUS: test$(DLL_SUFFIX)
 
+CSRCS += test.c
+
+GARBAGE += test$(DLL_SUFFIX) test$(DLL_SUFFIX).bak
+
+libs:: test$(DLL_SUFFIX)
+
+ifndef CROSS_COMPILE
 dummy: dummy.$(OBJ_SUFFIX) test$(DLL_SUFFIX)
 	$(CC) -o $@ $^ $(LDFLAGS)
 
 libs:: dummy
 	# Will either crash or return exit code 1 if elfhack is broken
 	LD_LIBRARY_PATH=$(CURDIR) $(CURDIR)/dummy
 
-CSRCS += test.c dummy.c
+CSRCS += dummy.c
 
-GARBAGE += dummy test$(DLL_SUFFIX) test$(DLL_SUFFIX).bak
+GARBAGE += dummy
 endif
 
 inject:
 	$(NSINSTALL) -D $@
 
 inject/%.c: inject.c | inject
 	cp $< $@
 
new file mode 100644
--- /dev/null
+++ b/build/unix/test/Makefile.in
@@ -0,0 +1,76 @@
+# -*- makefile -*-
+#
+# ***** 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) 2011
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Joey Armstrong <joey@mozilla.com>
+#
+# 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@
+
+include $(DEPTH)/config/autoconf.mk
+include $(topsrcdir)/config/rules.mk
+
+##################################################
+## Gather a list of tests, generate timestamp deps
+##################################################
+TS=.ts
+ifneq (,$(findstring check,$(MAKECMDGOALS)))
+          allsrc = $(wildcard $(srcdir)/*)
+       tests2run = $(notdir $(filter %.tpl,$(allsrc)))
+  check_targets += $(addprefix $(TS)/,$(tests2run))
+endif
+
+check:: $(TS) $(check_targets)
+
+#############################################
+# Only invoke tests when sources have changed
+#############################################
+$(TS)/%: $(srcdir)/%
+	$(PERL) $(srcdir)/runtest $<
+	@touch $@
+
+#####################################################
+## Extra dep needed to synchronize parallel execution
+#####################################################
+$(TS): $(TS)/.done
+$(TS)/.done:
+	$(MKDIR) -p $(dir $@)
+	touch $@
+
+GARBAGE_DIRS += $(TS)
+
+# EOF
new file mode 100644
--- /dev/null
+++ b/build/unix/test/runtest
@@ -0,0 +1,95 @@
+#!/usr/bin/env perl
+###########################################################################
+## Intent:
+##   Test::Harness is a testing wrapper that will process output
+##   from Test.pm module tests.  Sumarize results, report stats
+##   and exit with overall status for the testing suites.
+##
+## Run testing suite:
+##   % make clean test
+##   % perl runtest
+##
+## Run Individual tests
+##   % perl tUtils0
+###########################################################################
+
+##----------------------------##
+##---] CORE/CPAN INCLUDES [---##
+##----------------------------##
+use strict;
+use warnings;
+use Getopt::Long;
+
+use Test::Harness;
+
+##-------------------##
+##---]  EXPORTS  [---##
+##-------------------##
+our $VERSION = qw(1.0);
+use FindBin;
+
+##-------------------##
+##---]  GLOBALS  [---##
+##-------------------##
+my %argv;
+
+##----------------##
+##---]  MAIN  [---##
+##----------------##
+unless(GetOptions(\%argv,
+		  qw(debug|d)
+		 ))
+{
+    print "Usage: $0\n";
+    print "  --debug  Enable debug mode\n";
+    exit 1;
+}
+
+if (2 > $Test::Harness::VERSION)
+{
+    print "Unit tests will not be run, Test::Harness is too old\n"
+	if ($argv{debug});
+    exit 0;
+}
+
+
+my @tests;
+
+########################################
+## Gather a list of tests if none passed
+########################################
+unless (@tests = @ARGV)
+{
+  local *D;
+    opendir(D, '.');
+    while($_ = readdir(D)) {
+	next unless /.t\S+$/;
+	next if (/\.ts$/);
+	push(@tests, $_);
+    }
+    closedir(D);
+}
+
+###############################################
+## Glob a list of tests when directories passed
+###############################################
+my @tmp;
+foreach (@tests)
+{
+  local *D;
+    if (-d $_ && (my $dir = $_))
+    {
+        opendir(D, $_) || die "opendir(D) failed: $!";
+	my @tests = grep(/\.t[^\.\s]+/o, readdir(D));
+	closedir(D);
+	push(@tmp, map{ join('/', $dir, $_); } @tests);
+    } else {
+        push(@tmp, $_);
+    }
+}
+@tests = @tmp;
+
+print "$0: @ARGV\n" if ($argv{debug});
+runtests(@tests);
+
+# EOF
new file mode 100644
--- /dev/null
+++ b/build/unix/test/uniq.tpl
@@ -0,0 +1,151 @@
+#!/usr/bin/env perl
+###########################################################################
+## Intent: Unit test to verify uniq.pl
+###########################################################################
+
+##----------------------------##
+##---] CORE/CPAN INCLUDES [---##
+##----------------------------##
+use strict;
+use warnings;
+use Cwd;
+use Getopt::Long;  # GetOptions
+
+use Test;
+sub BEGIN { plan tests => 12 }
+
+##-------------------##
+##---]  EXPORTS  [---##
+##-------------------##
+our $VERSION = qw(1.0);
+
+##------------------##
+##---] INCLUDES [---##
+##------------------##
+use FindBin;
+
+##-------------------##
+##---]  GLOBALS  [---##
+##-------------------##
+my %argv;
+
+
+###########################################################################
+## Intent: Run the arch command for output
+##
+## Returns:
+##    0   on success
+##    $?  command shell exit status
+###########################################################################
+sub uniq_pl
+{
+    my $cmd = "perl $FindBin::RealBin/../uniq.pl @_";
+    print "Running: $cmd\n" if ($argv{debug});
+    my @tmp = `$cmd 2>&1`;
+    my @output = map{ split(/\s+/o); } @tmp;
+    wantarray ? @output : "@output";
+} # uniq_pl
+
+###########################################################################
+## Intent:
+##
+## Returns:
+##    0 on success
+###########################################################################
+sub check_uniq
+{
+    print STDERR "Running test: check_uniq\n" if ($argv{debug});
+
+    # TODO: improve test, uniq.pl regexpr handling not quite right
+
+    my @todo =
+      (
+       [ '', qw(a a/b a/b/c) ] => [  qw(a a/b a/b/c) ],
+       [ '', qw(a/b a a/b/c) ] => [ qw(a/b a a/b/c) ],
+       [ '', qw(a/b/c a/b a) ] => [ qw(a/b/c a/b a) ],
+
+       [ '', qw(a a/b a/b/c a/b a) ] => [  qw(a a/b a/b/c) ], # dup removal
+
+       [ '-s', qw(a a/b a/b/c) ] => [ qw(a a/b a/b/c)  ],
+       [ '-s', qw(a/b a a/b/c) ] => [ qw(a a/b a/b/c) ],
+       [ '-s', qw(a/b/c a/b a) ] => [ qw(a a/b a/b/c) ],
+
+       [ '-r', qw(a a/b a/b/c) ] => [ qw(a) ],
+       [ '-r', qw(a/b a a/b/c) ] => [ qw(a/b a) ],
+       [ '-r', qw(a/b/c a/b a) ] => [ qw(a/b/c a/b a) ],
+
+       [ '-r', qw(. .. a/b ../a aa/bb) ] => [ qw(. .. a/b aa/bb) ],
+       [ '-r', qw(.. a/b ../a . aa/bb) ] => [ qw(.. a/b . aa/bb) ],
+      );
+
+    my $ct=1;
+    while (@todo)
+    {
+        my ($a, $b) = splice(@todo, 0, 2);
+	my @args = @{ $a };
+	my @exp = @{ $b };
+
+	my @out = uniq_pl(@args);
+#	compareExp(\@out, \@exp, 'Failed on line ' . __LINE__ . ", dataset $ct");
+	if (0 && 7 == $ct)
+	  {
+	    print STDERR "\n";
+	    print STDERR map{ "args> $_\n" }@args;
+	    print STDERR "\n";
+	    print STDERR map{ "exp> $_\n" }@exp;
+	    print STDERR "\n";
+	    print STDERR map{ "out> $_\n" }@out;
+	  }
+
+	ok("@out", "@exp", 'Failed on line ' . __LINE__ . ", dataset $ct");
+	$ct++;
+    }
+
+} # check_uniq
+
+###########################################################################
+## Intent: Smoke tests for the unittests module
+###########################################################################
+sub smoke
+{
+    print STDERR "Running test: smoke()\n" if ($argv{debug});
+} # smoke()
+
+###########################################################################
+## Intent: Intitialize global test objects and consts
+###########################################################################
+sub init
+{
+    print "Running: init()\n" if ($argv{debug});
+#    testplan(24, 0);
+} # init()
+
+##----------------##
+##---]  MAIN  [---##
+##----------------##
+unless(GetOptions(\%argv,
+		  qw(
+		     debug|d
+                     manual
+		     test=s@
+		     verbose
+		     )))
+{
+    print "USAGE: $0\n";
+    print "  --debug    Enable script debug mode\n";
+    print "  --fail     Force a testing failure condition\n";
+    print "  --manual   Also run disabled tests\n";
+    print "  --smoke    Run smoke tests then exit\n";
+    print "  --test     Run a list of tests by function name\n";
+    print "  --verbose  Enable script verbose mode\n";
+    exit 1;
+}
+
+init();
+testbyname(@{ $argv{test} }) if ($argv{test});
+smoke();
+
+check_uniq();
+ok(1, 0, 'Forced failure by command line arg --fail') if ($argv{fail});
+
+# EOF
--- a/build/unix/uniq.pl
+++ b/build/unix/uniq.pl
@@ -17,47 +17,109 @@
 #
 # The Initial Developer of the Original Code is
 # Netscape Communications Corporation.
 # Portions created by the Initial Developer are Copyright (C) 2000
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
 #   Christopher Seawood <cls@seawood.org>
+#   Joey Armstrong <joey@mozilla.com>
 #
 # 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 *****
 
-use Getopt::Std;
+##----------------------------##
+##---] CORE/CPAN INCLUDES [---##
+##----------------------------##
+use strict;
+use warnings;
+use Getopt::Long;
+
+##-------------------##
+##---]  EXPORTS  [---##
+##-------------------##
+our $VERSION = qw(1.1);
+
+##-------------------##
+##---]  GLOBALS  [---##
+##-------------------##
+my %argv;
+my $modver = $Getopt::Long::VERSION || 0;
+my $isOldGetopt = ($modver eq '2.25') ? 1 : 0;
 
-getopts('rs');
-$regexp = 1 if (defined($opt_r));
-$sort = 1 if (defined($opt_s));
+###########################################################################
+## Intent: Script init function
+###########################################################################
+sub init
+{
+    if ($isOldGetopt)
+    {
+	# mozilla.build/mingw perl in need of an upgrade
+	# emulate Getopt::Long switch|short:init
+	foreach (qw(debug regex sort))
+	{
+	    if (defined($argv{$_}))
+	    {
+		$argv{$_} ||= 1;
+	    }
+	}
+    }
+} # init
 
-undef @out;
-if ($sort) {
-    @in = sort @ARGV;
-} else {
-    @in = @ARGV;
+##----------------##
+##---]  MAIN  [---##
+##----------------##
+my @args = ($isOldGetopt)
+    ? qw(debug|d regex|r sort|s)
+    : qw(debug|d:1 regex|r:1 sort|s:1)
+    ;
+
+unless(GetOptions(\%argv, @args))
+{
+    print "Usage: $0\n";
+    print "  --sort   Sort list elements early\n";
+    print "  --regex  Exclude subdirs by pattern\n";
 }
-foreach $d (@in) { 
-    if ($regexp) {
-        $found = 0; 
-        foreach $dir (@out) {
-            $found++, last if ($d =~ m/^$dir\// || $d eq $dir);
+
+init();
+my $debug = $argv{debug} || 0;
+
+my %seen;
+my @out;
+my @in = ($argv{sort}) ? sort @ARGV : @ARGV;
+
+foreach my $d (@in)
+{
+    next if ($seen{$d}++);
+
+    print "   arg is $d\n" if ($debug);
+
+    if ($argv{regex})
+    {
+        my $found = 0;
+        foreach my $dir (@out)
+	{
+	    my $dirM = quotemeta($dir);
+            $found++, last if ($d eq $dir || $d =~ m!^${dirM}\/!);
         }
+	print "Adding $d\n" if ($debug && !$found);
         push @out, $d if (!$found);
     } else {
-        push @out, $d if (!grep(/^$d$/, @out));
+	print "Adding: $d\n" if ($debug);
+        push(@out, $d);
     }
 }
+
 print "@out\n"
+
+# EOF
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -526,17 +526,16 @@ MOZ_TOOLKIT_REGISTRY_CFLAGS = \
 	$(TK_CFLAGS)
 
 CAIRO_FT_CFLAGS		= @CAIRO_FT_CFLAGS@
 
 MOZ_TREE_FREETYPE		= @MOZ_TREE_FREETYPE@
 MOZ_ENABLE_CAIRO_FT	= @MOZ_ENABLE_CAIRO_FT@
 MOZ_ENABLE_GTK2		= @MOZ_ENABLE_GTK2@
 MOZ_ENABLE_QT		= @MOZ_ENABLE_QT@
-MOZ_ENABLE_PHOTON	= @MOZ_ENABLE_PHOTON@
 MOZ_ENABLE_XREMOTE	= @MOZ_ENABLE_XREMOTE@
 MOZ_ENABLE_DWRITE_FONT	= @MOZ_ENABLE_DWRITE_FONT@
 MOZ_ENABLE_D2D_SURFACE	= @MOZ_ENABLE_D2D_SURFACE@
 MOZ_ENABLE_D3D9_LAYER	= @MOZ_ENABLE_D3D9_LAYER@
 MOZ_ENABLE_D3D10_LAYER  = @MOZ_ENABLE_D3D10_LAYER@
 
 MOZ_GTK2_CFLAGS		= @MOZ_GTK2_CFLAGS@
 MOZ_GTK2_LIBS		= @MOZ_GTK2_LIBS@
--- a/config/config.mk
+++ b/config/config.mk
@@ -40,19 +40,19 @@
 # config.mk
 #
 # Determines the platform and builds the macros needed to load the
 # appropriate platform-specific .mk file, then defines all (most?)
 # of the generic macros.
 #
 
 # Define an include-at-most-once flag
-#ifdef INCLUDED_CONFIG_MK
-#$(error Don't include config.mk twice!)
-#endif
+ifdef INCLUDED_CONFIG_MK
+$(error Don't include config.mk twice!)
+endif
 INCLUDED_CONFIG_MK = 1
 
 EXIT_ON_ERROR = set -e; # Shell loops continue past errors without this.
 
 ifndef topsrcdir
 topsrcdir	= $(DEPTH)
 endif
 
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1527,34 +1527,39 @@ endif
 	$(MKDIR) -p $(XPIDL_GEN_DIR)
 	@$(TOUCH) $@
 
 # don't depend on $(XPIDL_GEN_DIR), because the modification date changes
 # with any addition to the directory, regenerating all .h files -> everything.
 
 XPIDL_DEPS = \
   $(topsrcdir)/xpcom/idl-parser/header.py \
+  $(topsrcdir)/xpcom/idl-parser/typelib.py \
   $(topsrcdir)/xpcom/idl-parser/xpidl.py \
   $(NULL)
 
 $(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
 	$(REPORT_BUILD)
 	$(PYTHON_PATH) \
 	  -I$(topsrcdir)/other-licenses/ply \
 	  -I$(topsrcdir)/xpcom/idl-parser \
 	  $(topsrcdir)/xpcom/idl-parser/header.py --cachedir=$(topsrcdir)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
 	@if test -n "$(findstring $*.h, $(EXPORTS))"; \
 	  then echo "*** WARNING: file $*.h generated from $*.idl overrides $(srcdir)/$*.h"; else true; fi
 
 ifndef NO_GEN_XPT
 # generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link
 # into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components.
-$(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_COMPILE) $(XPIDL_GEN_DIR)/.done
+$(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
 	$(REPORT_BUILD)
-	$(ELOG) $(XPIDL_COMPILE) -m typelib -w $(XPIDL_FLAGS) -e $@ -d $(MDDEPDIR)/$(@F).pp $(_VPATH_SRCS)
+	$(PYTHON_PATH) \
+	  -I$(topsrcdir)/other-licenses/ply \
+	  -I$(topsrcdir)/xpcom/idl-parser \
+	  -I$(topsrcdir)/xpcom/typelib/xpt/tools \
+	  $(topsrcdir)/xpcom/idl-parser/typelib.py --cachedir=$(topsrcdir)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
 
 # no need to link together if XPIDLSRCS contains only XPIDL_MODULE
 ifneq ($(XPIDL_MODULE).idl,$(strip $(XPIDLSRCS)))
 $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.xpt,$(XPIDLSRCS)) $(GLOBAL_DEPS)
 	$(XPIDL_LINK) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.xpt,$(XPIDLSRCS))
 endif # XPIDL_MODULE.xpt != XPIDLSRCS
 
 libs:: $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt
--- a/config/system-headers
+++ b/config/system-headers
@@ -560,24 +560,16 @@ pango/pangoxft.h
 pango/pango-utils.h
 pascal.h
 Patches.h
 Path.h
 pcfs/pc_dir.h
 Pgenerr.h
 PGenErr.h
 Ph.h
-photon/Pg.h
-photon/PhProto.h
-photon/PhRender.h
-photon/PpProto.h
-photon/PtProgress.h
-photon/PtServer.h
-photon/PtWebClient.h
-photon/PxImage.h
 pk11func.h
 pk11pub.h
 pkcs11t.h
 PLStringFuncs.h
 PMApplication.h
 pmddim.h
 poll.h
 Polygon.h
--- a/configure.in
+++ b/configure.in
@@ -298,21 +298,49 @@ case "$target" in
     fi
 
     android_platform_tools="$android_sdk"/../../platform-tools
     if test ! -d "$android_platform_tools" ; then
         android_platform_tools="$android_sdk"/tools # SDK Tools < r8
     fi
 
     if test -z "$android_toolchain" ; then
-        android_toolchain="$android_ndk"/build/prebuilt/`uname -s | tr "[[:upper:]]" "[[:lower:]]"`-x86/arm-eabi-4.4.0
+        AC_MSG_CHECKING([for android toolchain directory])
+
+        kernel_name=`uname -s | tr "[[:upper:]]" "[[:lower:]]"`
+
+        android_toolchain="$android_ndk"/build/prebuilt/$kernel_name-x86/arm-eabi-4.4.0
+
+        # With newer NDK, the toolchain path has changed.
+        if ! test -d "$android_toolchain" ; then
+            android_toolchain="$android_ndk"/toolchains/arm-$kernel_name-androideabi-4.4.3/prebuilt/$kernel_name-x86
+        fi
+
+        if test -d "$android_toolchain" ; then
+            AC_MSG_RESULT([$android_toolchain])
+        else
+            AC_MSG_ERROR([not found. You have to specify --with-android-toolchain=/path/to/ndk/toolchain.])
+        fi
     fi
 
     if test -z "$android_platform" ; then
-       android_platform="$android_ndk"/build/platforms/android-"$android_version"/arch-"$target_cpu"
+        AC_MSG_CHECKING([for android platform directory])
+
+        android_platform="$android_ndk"/build/platforms/android-"$android_version"/arch-"$target_cpu"
+
+        # With newer NDK, the platform path has changed.
+        if ! test -d "$android_platform" ; then
+            android_platform="$android_ndk"/platforms/android-"$android_version"/arch-"$target_cpu"
+        fi
+
+        if test -d "$android_platform" ; then
+            AC_MSG_RESULT([$android_platform])
+        else
+            AC_MSG_ERROR([not found. You have to specify --with-android-platform=/path/to/ndk/platform.])
+        fi
     fi
 
     dnl set up compilers
     AS="$android_toolchain"/bin/"$android_tool_prefix"-as
     CC="$android_toolchain"/bin/"$android_tool_prefix"-gcc
     CXX="$android_toolchain"/bin/"$android_tool_prefix"-g++
     CPP="$android_toolchain"/bin/"$android_tool_prefix"-cpp
     LD="$android_toolchain"/bin/"$android_tool_prefix"-ld
@@ -338,17 +366,17 @@ case "$target" in
     elif test "$target" != "arm-android-eabi"; then
        dnl fail if we're not building with NDKr4
        AC_MSG_ERROR([Couldn't find path to stlport in the android ndk])
     fi
 
     CPPFLAGS="-I$android_platform/usr/include $STLPORT_CPPFLAGS $CPPFLAGS"
     CFLAGS="-mandroid -I$android_platform/usr/include -fno-short-enums -fno-exceptions $CFLAGS"
     CXXFLAGS="-mandroid -I$android_platform/usr/include -fno-short-enums -fno-exceptions $CXXFLAGS"
-    LIBS="$LIBS $STLPORT_LIBS -static-libstdc++"
+    LIBS="$LIBS $STLPORT_LIBS"
 
     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 $STLPORT_LDFLAGS -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
@@ -361,18 +389,18 @@ case "$target" in
     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_TOOLCHAIN="${android_toolchain}"
+    ANDROID_PLATFORM="${android_platform}"
     ANDROID_SDK="${android_sdk}"
     ANDROID_PLATFORM_TOOLS="${android_platform_tools}"
     ANDROID_VERSION="${android_version}"
     if test -z "$ANDROID_PACKAGE_NAME" ; then
         ANDROID_PACKAGE_NAME='org.mozilla.$(MOZ_APP_NAME)'
     fi
 
     AC_DEFINE(ANDROID)
@@ -1355,18 +1383,16 @@ ncr)
 UNIX_SYSTEM_V)
     HOST_OS_ARCH=NEC
     ;;
 OSF1)
     ;;
 OS_2)
     HOST_OS_ARCH=OS2
     ;;
-QNX)
-    ;;
 SCO_SV)
     HOST_OS_ARCH=SCOOS
     ;;
 SINIX-N | SINIX-Y | SINIX-Z |ReliantUNIX-M)
     HOST_OS_ARCH=SINIX
     ;;
 UnixWare)
     HOST_OS_ARCH=UNIXWARE
@@ -1445,24 +1471,16 @@ OSF1)
         ;;
     esac
     ;;
 OS_2)
     OS_ARCH=OS2
     OS_TARGET=OS2
     OS_RELEASE=`uname -v`
     ;;
-QNX)
-    if test "$OS_TARGET" != "NTO"; then
-        changequote(,)
-        OS_RELEASE=`uname -v | sed 's/^\([0-9]\)\([0-9]*\)$/\1.\2/'`
-        changequote([,])
-    fi
-    OS_TEST=x86
-    ;;
 SCO_SV)
     OS_ARCH=SCOOS
     OS_RELEASE=5.0
     ;;
 SINIX-N | SINIX-Y | SINIX-Z |ReliantUNIX-M)
     OS_ARCH=SINIX
     OS_TEST=`uname -p`
     ;;
@@ -2494,47 +2512,16 @@ ia64*-hpux*)
     MKSHLIB_UNFORCE_ALL='-Wl,--no-whole-archive'
     if test "$LIBRUNPATH"; then
 	DSO_LDOPTS="-Wl,-R$LIBRUNPATH $DSO_LDOPTS"
     fi
     MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-soname,lib$(LIBRARY_NAME)$(DLL_SUFFIX) -o $@'
     MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-soname,lib$(LIBRARY_NAME)$(DLL_SUFFIX) -o $@'
     ;;
 
-*-nto*) 
-	AC_DEFINE(NTO)	
-	AC_DEFINE(_QNX_SOURCE)
-	AC_DEFINE(_i386)
-	OS_TARGET=NTO
-	WARNINGS_AS_ERRORS=''
-	MOZ_OPTIMIZE_FLAGS="-O"
-	MOZ_DEBUG_FLAGS="-gstabs"
-	USE_PTHREADS=1
-	_PEDANTIC=
-	LIBS="$LIBS -lsocket -lstdc++"
-	_DEFINES_CFLAGS='-include $(DEPTH)/mozilla-config.h -DMOZILLA_CLIENT -D_POSIX_C_SOURCE=199506'
-	_DEFINES_CXXFLAGS='-DMOZILLA_CLIENT -include $(DEPTH)/mozilla-config.h -D_POSIX_C_SOURCE=199506'
-	if test "$with_x" != "yes"
-	then
-		_PLATFORM_DEFAULT_TOOLKIT="photon"
-	    TK_CFLAGS='-I/usr/include/photon'
-		TK_LIBS='-lph'
-	fi
-	case "${target_cpu}" in
-	ppc*)
-	AC_DEFINE(HAVE_VA_LIST_AS_ARRAY)	
-	;;
-	esac
-	case "${host_cpu}" in
-	i*86)
-	USE_ELF_DYNSTR_GC=1
-	;;
-	esac
-	;;
-
 *-openbsd*)
     if test "$SO_VERSION"; then
         DLL_SUFFIX=".so.$SO_VERSION"
     else
         DLL_SUFFIX=".so.1.0"
     fi
     MOZ_FIX_LINK_PATHS='-Wl,-rpath-link,$(LIBXUL_DIST)/bin -Wl,-rpath-link,$(prefix)/lib -Wl,-rpath-link,$(if $(X11BASE),$(X11BASE),/usr/X11R6)/lib'
     DSO_CFLAGS=''
@@ -2631,30 +2618,16 @@ alpha*-*-osf*)
 	AC_DEFINE(NSCAP_DISABLE_DEBUG_PTR_TYPES)
     fi
     if test -z "$GNU_CXX"; then
       COMPAQ_CXX=1
     fi
     AC_DEFINE(NEED_USLEEP_PROTOTYPE)
     ;;
 
-*-qnx*) 
-    DIRENT_INO=d_stat.st_ino
-    dnl Solves the problems the QNX compiler has with nsCOMPtr.h.
-    AC_DEFINE(NSCAP_DISABLE_TEST_DONTQUERY_CASES)
-    AC_DEFINE(NSCAP_DISABLE_DEBUG_PTR_TYPES)
-    dnl Explicit set STDC_HEADERS to workaround QNX 6.0's failing of std test
-    AC_DEFINE(STDC_HEADERS)
-    if test "$no_x" = "yes"; then
-	    _PLATFORM_DEFAULT_TOOLKIT='photon'
-	    TK_CFLAGS='-I/usr/nto/include/photon'
-	    TK_LIBS='-lphoton -lphrender'
-    fi
-    ;;
-
 *-sco*) 
     AC_DEFINE(NSCAP_DISABLE_TEST_DONTQUERY_CASES)
     AC_DEFINE(NSCAP_DISABLE_DEBUG_PTR_TYPES)
     CXXFLAGS="$CXXFLAGS -I/usr/include/CC"
     if test ! "$GNU_CC"; then
        DSO_LDOPTS='-G'
     fi
     ;;
@@ -4958,27 +4931,25 @@ MOZ_ARG_HEADER(Toolkit Options)
     dnl ========================================================
     dnl = Select the default toolkit
     dnl ========================================================
 	MOZ_ARG_ENABLE_STRING(default-toolkit,
 	[  --enable-default-toolkit=TK
                           Select default toolkit
                           Platform specific defaults:
                             Mac OS X - cairo-cocoa
-                            Neutrino/QNX - photon
                             OS/2 - cairo-os2
                             Win32 - cairo-windows
                             Gtk2 with DirectFB - cairo-gtk2-dfb
                             * - cairo-gtk2
                             * - cairo-qt],
     [ _DEFAULT_TOOLKIT=$enableval ],
     [ _DEFAULT_TOOLKIT=$_PLATFORM_DEFAULT_TOOLKIT])
 
-    if test "$_DEFAULT_TOOLKIT" = "photon" \
-        -o "$_DEFAULT_TOOLKIT" = "cairo-windows" \
+    if test "$_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-os2" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-cocoa" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-android"
     then
@@ -4989,20 +4960,16 @@ MOZ_ARG_HEADER(Toolkit Options)
         AC_MSG_ERROR([You must specify a default toolkit (perhaps $_PLATFORM_DEFAULT_TOOLKIT).])
     fi
 
 dnl ========================================================
 dnl = Enable the toolkit as needed                         =
 dnl ========================================================
 
 case "$MOZ_WIDGET_TOOLKIT" in
-photon)
-	MOZ_ENABLE_PHOTON=1
-	AC_DEFINE(MOZ_WIDGET_PHOTON)
-    ;;
 
 cairo-windows)
     MOZ_WIDGET_TOOLKIT=windows
     MOZ_WEBGL=1
     MOZ_PDF_PRINTING=1
     MOZ_INSTRUMENT_EVENT_LOOP=1
     ;;
 
@@ -5247,17 +5214,16 @@ incorrect])
     fi
 fi
 
 AC_SUBST(GTK_CONFIG)
 AC_SUBST(TK_CFLAGS)
 AC_SUBST(TK_LIBS)
 
 AC_SUBST(MOZ_ENABLE_GTK2)
-AC_SUBST(MOZ_ENABLE_PHOTON)
 AC_SUBST(MOZ_ENABLE_QT)
 AC_SUBST(MOZ_ENABLE_QTNETWORK)
 AC_SUBST(MOZ_ENABLE_QMSYSTEM2)
 AC_SUBST(MOZ_ENABLE_QTMOBILITY)
 AC_SUBST(MOZ_ENABLE_XREMOTE)
 AC_SUBST(MOZ_GTK2_CFLAGS)
 AC_SUBST(MOZ_GTK2_LIBS)
 AC_SUBST(MOZ_QT_CFLAGS)
@@ -7263,16 +7229,48 @@ MOZ_ARG_ENABLE_STRING(debug-symbols,
   MOZ_DEBUG_SYMBOLS=1)
 
 if test -n "$MOZ_DEBUG" -o -n "$MOZ_DEBUG_SYMBOLS"; then
     AC_DEFINE(MOZ_DEBUG_SYMBOLS)
     export MOZ_DEBUG_SYMBOLS
 fi
 
 dnl ========================================================
+dnl = Identical Code Folding
+dnl ========================================================
+
+MOZ_ARG_DISABLE_BOOL(icf,
+[  --disable-icf          Disable Identical Code Folding],
+    MOZ_DISABLE_ICF=1,
+    MOZ_DISABLE_ICF= )
+
+if test "$GNU_CC" -a "$GCC_USE_GNU_LD" -a -z "$MOZ_DISABLE_ICF"; then
+    AC_CACHE_CHECK([whether the linker supports Identical Code Folding],
+        LD_SUPPORTS_ICF,
+        [echo 'int foo() {return 42;}' \
+              'int bar() {return 42;}' \
+              'int main() {return foo() - bar();}' > conftest.${ac_ext}
+        # If the linker supports ICF, foo and bar symbols will have
+        # the same address
+        if AC_TRY_COMMAND([${CC-cc} -o conftest${ac_exeext} $LDFLAGS -Wl,--icf=safe -ffunction-sections conftest.${ac_ext} $LIBS 1>&2]) &&
+           test -s conftest${ac_exeext} &&
+           objdump -t conftest${ac_exeext} | awk '{a[[$6]] = $1} END {if (a[["foo"]] && (a[["foo"]] != a[["bar"]])) { exit 1 }}'; then
+            LD_SUPPORTS_ICF=yes
+        else
+            LD_SUPPORTS_ICF=no
+        fi
+        rm -rf conftest*])
+    if test "$LD_SUPPORTS_ICF" = yes; then
+        LDFLAGS="$LDFLAGS -Wl,--icf=safe"
+        CFLAGS="$CFLAGS -ffunction-sections"
+        CXXFLAGS="$CXXFLAGS -ffunction-sections"
+    fi
+fi
+
+dnl ========================================================
 dnl = Automatically remove dead symbols
 dnl ========================================================
 
 if test "$GNU_CC" -a "$GCC_USE_GNU_LD" -a -n "$MOZ_DEBUG_FLAGS"; then
    dnl See bug 670659
    AC_CACHE_CHECK([whether removing dead symbols breaks debugging],
        GC_SECTIONS_BREAKS_DEBUG_RANGES,
        [echo 'int foo() {return 42;}' \
@@ -7289,18 +7287,26 @@ if test "$GNU_CC" -a "$GCC_USE_GNU_LD" -
             fi
         else
              dnl We really don't expect to get here, but just in case
              AC_ERROR([couldn't compile a simple C file])
         fi
         rm -rf conftest*])
     if test "$GC_SECTIONS_BREAKS_DEBUG_RANGES" = no; then
         DSO_LDOPTS="$DSO_LDOPTS -Wl,--gc-sections"
-        CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"
-        CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections"
+        case "$CFLAGS" in
+        *-ffunction-sections*)
+            CFLAGS="$CFLAGS -fdata-sections"
+            CXXFLAGS="$CXXFLAGS -fdata-sections"
+            ;;
+        *)
+            CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"
+            CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections"
+            ;;
+        esac
     fi
 fi
 
 dnl ========================================================
 dnl = Disable any treating of compile warnings as errors
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(warnings-as-errors,
 [  --disable-warnings-as-errors
@@ -7456,26 +7462,27 @@ else
         WIN32_CUSTOM_CRT_DIR="$_objdir_win/memory/jemalloc/crtsrc/build/$MOZ_CRT_CPU_ARCH"
         MOZ_MEMORY_LDFLAGS="-MANIFEST:NO -LIBPATH:\"$WIN32_CUSTOM_CRT_DIR\" -NODEFAULTLIB:msvcrt -NODEFAULTLIB:msvcrtd -NODEFAULTLIB:msvcprt -NODEFAULTLIB:msvcprtd -DEFAULTLIB:mozcrt19 -DEFAULTLIB:mozcpp19"
       fi
     fi
     if test -z "$WIN32_OLD_STYLE_JEMALLOC"; then
       AC_MSG_RESULT([no])
       WIN32_NEW_STYLE_JEMALLOC=1
       AC_DEFINE(WIN32_NEW_STYLE_JEMALLOC)
+      WIN32_CRT_SRC_DIR=
       if test -z "$MOZ_DEBUG"; then
         WIN32_CRT_LIBS="msvcrt.lib msvcprt.lib"
       else
         WIN32_CRT_LIBS="msvcrtd.lib msvcprtd.lib"
       fi
       dnl Look for a broken crtdll.obj
       WIN32_CRTDLL_FULLPATH=`lib -nologo -list $WIN32_CRT_LIBS | grep crtdll\\.obj`
       lib -NOLOGO -OUT:crtdll.obj $WIN32_CRT_LIBS -EXTRACT:$WIN32_CRTDLL_FULLPATH
       if grep -q '__imp__\{0,1\}free' crtdll.obj; then
-        MOZ_MEMORY_LDFLAGS='-MANIFEST:NO -LIBPATH:$(DIST)/lib -NODEFAULTLIB:msvcrt -NODEFAULTLIB:msvcrtd -NODEFAULTLIB:msvcprt -NODEFAULTLIB:msvcprtd -DEFAULTLIB:mozcrt'
+        MOZ_MEMORY_LDFLAGS='-LIBPATH:$(DIST)/lib -NODEFAULTLIB:msvcrt -NODEFAULTLIB:msvcrtd -NODEFAULTLIB:msvcprt -NODEFAULTLIB:msvcprtd -DEFAULTLIB:mozcrt'
       else
         MOZ_MEMORY_LDFLAGS='$(DIST)/../memory/jemalloc/jemalloc.lib'
       fi
       rm crtdll.obj
     fi
 
     dnl Also pass this to NSPR/NSS
     DLLFLAGS="$DLLFLAGS $MOZ_MEMORY_LDFLAGS"
@@ -7854,17 +7861,17 @@ dnl Omnijar packaging is compatible with
 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)
-    if test "$OS_ARCH" = "WINNT"; then
+    if test "$OS_ARCH" = "WINNT" -o "$OS_ARCH" = "OS2"; then
         MOZ_CHROME_FILE_FORMAT=flat
     else
         MOZ_CHROME_FILE_FORMAT=symlink
     fi
 elif test "$MOZ_CHROME_FILE_FORMAT" = "jar"; then
     AC_DEFINE(MOZ_CHROME_FILE_FORMAT_JAR)
 fi
 
--- a/content/base/public/Makefile.in
+++ b/content/base/public/Makefile.in
@@ -103,18 +103,16 @@ XPIDLSRCS	= \
 		nsIDOMFile.idl \
 		nsIDOMFileReader.idl \
 		nsIDOMFileList.idl \
 		nsIDOMFileException.idl \
 		nsIDOMFileError.idl \
 		nsIDOMFormData.idl \
 		nsIDOMParser.idl \
 		nsIDOMSerializer.idl \
-		nsISelection2.idl \
-		nsISelection3.idl \
 		nsISelectionController.idl  \
 		nsISelectionDisplay.idl  \
 		nsISelectionListener.idl  \
 		nsISelectionPrivate.idl  \
 		nsIScriptLoaderObserver.idl  \
 		nsIDroppedLinkHandler.idl \
 		nsIImageLoadingContent.idl \
 		nsIObjectLoadingContent.idl \
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -1687,16 +1687,20 @@ protected:
   PRPackedBool mHasHadScriptHandlingObject;
 
   // True if we're waiting for a before-paint event.
   PRPackedBool mHavePendingPaint;
 
   // True if we're an SVG document being used as an image.
   PRPackedBool mIsBeingUsedAsImage;
 
+  // True is this document is synthetic : stand alone image, video, audio
+  // file, etc.
+  PRPackedBool mIsSyntheticDocument;
+
   // The document's script global object, the object from which the
   // document can get its script context and scope. This is the
   // *inner* window object.
   nsCOMPtr<nsIScriptGlobalObject> mScriptGlobalObject;
 
   // If mIsStaticDocument is true, mOriginalDocument points to the original
   // document.
   nsCOMPtr<nsIDocument> mOriginalDocument;
--- a/content/base/public/nsISelection.idl
+++ b/content/base/public/nsISelection.idl
@@ -44,17 +44,17 @@ interface nsIDOMRange;
 
 /**
  * Interface for manipulating and querying the current selected range
  * of nodes within the document.
  *
  * @version 1.0
  */
 
-[scriptable, uuid(B2C7ED59-8634-4352-9E37-5484C8B6E4E1)]
+[scriptable, uuid(5ac0cd5d-3c08-4c4c-8e70-230c433f5d5c)]
 interface nsISelection : nsISupports
 {
     /**
      * Returns the node in which the selection begins.
      */
     readonly attribute nsIDOMNode anchorNode;
 
     /**
@@ -160,9 +160,30 @@ interface nsISelection : nsISupports
      *                PR_FALSE if the new language is left-to-right.
      */
     void selectionLanguageChange(in boolean langRTL);
 
     /**
      * Returns the whole selection into a plain text string.
      */
     wstring toString();
+    
+    /**
+     * Modifies the selection.  Note that the parameters are case-insensitive.
+     *
+     * @param alter can be one of { "move", "extend" }
+     *   - "move" collapses the selection to the end of the selection and
+     *      applies the movement direction/granularity to the collapsed
+     *      selection.
+     *   - "extend" leaves the start of the selection unchanged, and applies
+     *      movement direction/granularity to the end of the selection.
+     * @param direction can be one of { "forward", "backward", "left", "right" }
+     * @param granularity can be one of { "character", "word",
+     *                                    "line", "lineboundary" }
+     *
+     * @returns NS_ERROR_NOT_IMPLEMENTED if the granularity is "sentence",
+     * "sentenceboundary", "paragraph", "paragraphboundary", or
+     * "documentboundary".  Returns NS_ERROR_INVALID_ARG if alter, direction,
+     * or granularity has an unrecognized value.
+     */
+    void modify(in DOMString alter, in DOMString direction,
+                in DOMString granularity);
 };
deleted file mode 100644
--- a/content/base/public/nsISelection2.idl
+++ /dev/null
@@ -1,111 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; 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 Selection code.
- *
- * The Initial Developer of the Original Code is
- * Google Inc.
- * Portions created by the Initial Developer are Copyright (C) 2006
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Brett Wilson <brettw@gmail.com>
- *   Alexander Surkov <surkov.alexander@gmail.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsISelection.idl"
-
-interface nsIDOMNode;
-interface nsIDOMRange;
-
-%{C++
-#include "nsCOMArray.h"
-%}
-
-[ptr] native RangeArray(nsCOMArray<nsIDOMRange>);
-
-[scriptable, uuid(5d21d5fe-3691-4716-a334-4691eea54d29)]
-interface nsISelection2 : nsISelection
-{
-  /**
-   * Returns the type of the selection (see nsISelectionController for
-   * available constants).
-   */
-  readonly attribute short type;
-
-  /**
-   * Return array of ranges intersecting with the given DOM interval.
-   */
-  void GetRangesForInterval(
-      in nsIDOMNode beginNode, in PRInt32 beginOffset,
-      in nsIDOMNode endNode, in PRInt32 endOffset,
-      in boolean allowAdjacent,
-      out PRUint32 resultCount,
-      [retval, array, size_is(resultCount)] out nsIDOMRange results);
-
-  [noscript] void GetRangesForIntervalCOMArray(
-      in nsIDOMNode beginNode, in PRInt32 beginOffset,
-      in nsIDOMNode endNode, in PRInt32 endOffset,
-      in boolean allowAdjacent,
-      in RangeArray results);
-
-  /**
-   * Scrolls a region of the selection, so that it is visible in
-   * the scrolled view.
-   *
-   * @param aRegion - the region inside the selection to scroll into view
-   *                  (see selection region constants defined in
-   *                   nsISelectionController).
-   * @param aIsSynchronous - when true, scrolls the selection into view
-   *                         before returning. If false, posts a request which
-   *                         is processed at some point after the method returns.
-   * @param aVPercent - how to align the frame vertically. A value of 0
-   *                   means the frame's upper edge is aligned with the top edge
-   *                   of the visible area. A value of 100 means the frame's
-   *                   bottom edge is aligned with the bottom edge of
-   *                   the visible area. For values in between, the point
-   *                   "aVPercent" down the frame is placed at the point
-   *                   "aVPercent" down the visible area. A value of 50 centers
-   *                   the frame vertically. A value of -1 means move
-   *                   the frame the minimum amount necessary in order for
-   *                   the entire frame to be visible vertically (if possible).
-   * @param aHPercent - how to align the frame horizontally. A value of 0
-   *                    means the frame's left edge is aligned with the left
-   *                    edge of the visible area. A value of 100 means the
-   *                    frame's right edge is aligned with the right edge of
-   *                    the visible area. For values in between, the point
-   *                    "aHPercent" across the frame is placed at the point
-   *                    "aHPercent" across the visible area. A value of 50
-   *                    centers the frame horizontally . A value of -1 means
-   *                    move the frame the minimum amount necessary in order
-   *                    for the entire frame to be visible horizontally
-   *                    (if possible).
-   */
-  void scrollIntoView(in short aRegion, in boolean aIsSynchronous,
-                      in short aVPercent, in short aHPercent);
-};
-
deleted file mode 100644
--- a/content/base/public/nsISelection3.idl
+++ /dev/null
@@ -1,65 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; 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 Selection code.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Corporation
- * Portions created by the Initial Developer are Copyright (C) 2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Justin Lebar <justin.lebar@gmail.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(94ac0cb4-95b4-11df-8e13-0026b9792740)]
-interface nsISelection3 : nsISupports
-{
-  /**
-   * Modifies the selection.  Note that the parameters are case-insensitive.
-   *
-   * @param alter can be one of { "move", "extend" }
-   *   - "move" collapses the selection to the end of the selection and
-   *      applies the movement direction/granularity to the collapsed
-   *      selection.
-   *   - "extend" leaves the start of the selection unchanged, and applies
-   *      movement direction/granularity to the end of the selection.
-   * @param direction can be one of { "forward", "backward", "left", "right" }
-   * @param granularity can be one of { "character", "word",
-   *                                    "line", "lineboundary" }
-   *
-   * @returns NS_ERROR_NOT_IMPLEMENTED if the granularity is "sentence",
-   * "sentenceboundary", "paragraph", "paragraphboundary", or
-   * "documentboundary".  Returns NS_ERROR_INVALID_ARG if alter, direction,
-   * or granularity has an unrecognized value.
-   */
-  void modify(in DOMString alter, in DOMString direction,
-              in DOMString granularity);
-
-};
--- a/content/base/public/nsISelectionPrivate.idl
+++ b/content/base/public/nsISelectionPrivate.idl
@@ -33,39 +33,43 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 #include "nsISelectionListener.idl"
 #include "nsIEnumerator.idl"
+#include "nsISelection.idl"
 
 interface nsIDOMRange;
+interface nsIDOMNode;
 interface nsISelectionListener;
 interface nsIContent;
 
 %{C++
 class nsFrameSelection;
 class nsIFrame;
 class nsIPresShell;
 struct nsTextRangeStyle;
 struct nsPoint;
 #include "nsIFrame.h"
+#include "nsCOMArray.h"
 %}
 
 [ptr] native nsFrameSelection(nsFrameSelection);
 [ptr] native nsIFrame(nsIFrame);
 [ptr] native nsIPresShell(nsIPresShell);
+[ptr] native RangeArray(nsCOMArray<nsIDOMRange>);
 [ref] native constTextRangeStyleRef(const nsTextRangeStyle);
 [ref] native nsPointRef(nsPoint);
 native nsDirection(nsDirection);
 
-[scriptable, uuid(98552206-ad7a-4d2d-8ce3-b6fa2389298b)]
-interface nsISelectionPrivate : nsISupports
+[scriptable, uuid(1820a940-6203-4e27-bc94-fa81131722a4)]
+interface nsISelectionPrivate : nsISelection
  {
     const short ENDOFPRECEDINGLINE=0;
     const short STARTOFNEXTLINE=1;
     
     attribute boolean interlinePosition;
 
     /* startBatchChanges
        match this up with endbatchChanges. will stop ui updates while multiple selection methods are called
@@ -131,10 +135,67 @@ interface nsISelectionPrivate : nsISuppo
     [noscript] void setTextRangeStyle(in nsIDOMRange range,
                       in constTextRangeStyleRef textRangeStyle);
 
     /**
      * Get the direction of the selection.
      */
     [noscript, notxpcom] nsDirection getSelectionDirection();
     [noscript, notxpcom] void setSelectionDirection(in nsDirection aDirection);
+    
+    /**
+     * Returns the type of the selection (see nsISelectionController for
+     * available constants).
+     */
+    readonly attribute short type;
+
+    /**
+     * Return array of ranges intersecting with the given DOM interval.
+     */
+    void GetRangesForInterval(
+        in nsIDOMNode beginNode, in PRInt32 beginOffset,
+        in nsIDOMNode endNode, in PRInt32 endOffset,
+        in PRBool allowAdjacent,
+        out PRUint32 resultCount,
+        [retval, array, size_is(resultCount)] out nsIDOMRange results);
+
+    [noscript] void GetRangesForIntervalCOMArray(
+        in nsIDOMNode beginNode, in PRInt32 beginOffset,
+        in nsIDOMNode endNode, in PRInt32 endOffset,
+        in PRBool allowAdjacent,
+        in RangeArray results);
+
+    /**
+     * Scrolls a region of the selection, so that it is visible in
+     * the scrolled view.
+     *
+     * @param aRegion - the region inside the selection to scroll into view
+     *                  (see selection region constants defined in
+     *                   nsISelectionController).
+     * @param aIsSynchronous - when true, scrolls the selection into view
+     *                         before returning. If false, posts a request which
+     *                         is processed at some point after the method returns.
+     * @param aVPercent - how to align the frame vertically. A value of 0
+     *                   means the frame's upper edge is aligned with the top edge
+     *                   of the visible area. A value of 100 means the frame's
+     *                   bottom edge is aligned with the bottom edge of
+     *                   the visible area. For values in between, the point
+     *                   "aVPercent" down the frame is placed at the point
+     *                   "aVPercent" down the visible area. A value of 50 centers
+     *                   the frame vertically. A value of -1 means move
+     *                   the frame the minimum amount necessary in order for
+     *                   the entire frame to be visible vertically (if possible).
+     * @param aHPercent - how to align the frame horizontally. A value of 0
+     *                    means the frame's left edge is aligned with the left
+     *                    edge of the visible area. A value of 100 means the
+     *                    frame's right edge is aligned with the right edge of
+     *                    the visible area. For values in between, the point
+     *                    "aHPercent" across the frame is placed at the point
+     *                    "aHPercent" across the visible area. A value of 50
+     *                    centers the frame horizontally . A value of -1 means
+     *                    move the frame the minimum amount necessary in order
+     *                    for the entire frame to be visible horizontally
+     *                    (if possible).
+     */
+    void scrollIntoView(in short aRegion, in boolean aIsSynchronous,
+                        in short aVPercent, in short aHPercent);
 };
 
--- a/content/base/src/mozAutoDocUpdate.h
+++ b/content/base/src/mozAutoDocUpdate.h
@@ -29,16 +29,20 @@
  * 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 "nsContentUtils.h"
+#include "nsIDocument.h"
+#include "nsIDocumentObserver.h"
+
 /**
  * Helper class to automatically handle batching of document updates.  This
  * class will call BeginUpdate on construction and EndUpdate on destruction on
  * the given document with the given update type.  The document could be null,
  * in which case no updates will be called.  The constructor also takes a
  * boolean that can be set to false to prevent notifications.
  */
 class NS_STACK_CLASS mozAutoDocUpdate
--- a/content/base/src/mozSanitizingSerializer.cpp
+++ b/content/base/src/mozSanitizingSerializer.cpp
@@ -47,17 +47,16 @@
    all of the functions in the beginning. Possible that I fail to do
    something or do something useless.
    I am not proud about the implementation here at all.
    Feel free to fix it :-).
 */
 
 #include "mozSanitizingSerializer.h"
 #include "nsIServiceManager.h"
-#include "nsIDOMText.h"
 #include "nsIDOMElement.h"
 #include "nsTextFragment.h"
 #include "nsContentUtils.h"
 #include "nsReadableUtils.h"
 #include "plstr.h"
 #include "nsIProperties.h"
 #include "nsUnicharUtils.h"
 #include "nsIURI.h"
--- a/content/base/src/nsAttrAndChildArray.cpp
+++ b/content/base/src/nsAttrAndChildArray.cpp
@@ -46,16 +46,17 @@
 #include "prmem.h"
 #include "prbit.h"
 #include "nsString.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsRuleWalker.h"
 #include "nsMappedAttributes.h"
 #include "nsUnicharUtils.h"
 #include "nsAutoPtr.h"
+#include "nsContentUtils.h" // nsAutoScriptBlocker
 
 /*
 CACHE_POINTER_SHIFT indicates how many steps to downshift the |this| pointer.
 It should be small enough to not cause collisions between adjecent arrays, and
 large enough to make sure that all indexes are used. The size below is based
 on the size of the smallest possible element (currently 24[*] bytes) which is
 the smallest distance between two nsAttrAndChildArray. 24/(2^_5_) is 0.75.
 This means that two adjacent nsAttrAndChildArrays will overlap one in 4 times.
@@ -855,13 +856,19 @@ nsAttrAndChildArray::SizeOf() const
 
   if (mImpl) {
     // Don't add the size taken by *mMappedAttrs because it's shared.
 
     // mBuffer cointains InternalAttr and nsIContent* (even if it's void**)
     // so, we just have to compute the size of *mBuffer given that this object
     // doesn't own the children list.
     size += mImpl->mBufferSize * sizeof(*(mImpl->mBuffer)) + NS_IMPL_EXTRA_SIZE;
+
+    PRUint32 slotCount = AttrSlotCount();
+    for (PRUint32 i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) {
+      nsAttrValue* value = &ATTRS(mImpl)[i].mValue;
+      size += value->SizeOf() - sizeof(*value);
+    }
   }
 
   return size;
 }
 
--- a/content/base/src/nsAttrValue.cpp
+++ b/content/base/src/nsAttrValue.cpp
@@ -43,28 +43,27 @@
 
 #include "nsAttrValue.h"
 #include "nsIAtom.h"
 #include "nsUnicharUtils.h"
 #include "mozilla/css/StyleRule.h"
 #include "mozilla/css/Declaration.h"
 #include "nsIHTMLDocument.h"
 #include "nsIDocument.h"
-#include "nsTPtrArray.h"
 #include "nsContentUtils.h"
 #include "nsReadableUtils.h"
 #include "prprf.h"
 #include "nsISVGValue.h"
 
 namespace css = mozilla::css;
 
 #define MISC_STR_PTR(_cont) \
   reinterpret_cast<void*>((_cont)->mStringBits & NS_ATTRVALUE_POINTERVALUE_MASK)
 
-nsTPtrArray<const nsAttrValue::EnumTable>* nsAttrValue::sEnumTableArray = nsnull;
+nsTArray<const nsAttrValue::EnumTable*>* nsAttrValue::sEnumTableArray = nsnull;
 
 nsAttrValue::nsAttrValue()
     : mBits(0)
 {
 }
 
 nsAttrValue::nsAttrValue(const nsAttrValue& aOther)
     : mBits(0)
@@ -102,17 +101,17 @@ nsAttrValue::~nsAttrValue()
 }
 
 /* static */
 nsresult
 nsAttrValue::Init()
 {
   NS_ASSERTION(!sEnumTableArray, "nsAttrValue already initialized");
 
-  sEnumTableArray = new nsTPtrArray<const EnumTable>;
+  sEnumTableArray = new nsTArray<const EnumTable*>;
   NS_ENSURE_TRUE(sEnumTableArray, NS_ERROR_OUT_OF_MEMORY);
   
   return NS_OK;
 }
 
 /* static */
 void
 nsAttrValue::Shutdown()
@@ -976,52 +975,53 @@ nsAttrValue::SetIntValueAndType(PRInt32 
       SetMiscAtomOrString(aStringValue);
     }
   } else {
     NS_ASSERTION(!mBits, "Reset before calling SetIntValueAndType!");
     mBits = (aValue * NS_ATTRVALUE_INTEGERTYPE_MULTIPLIER) | aType;
   }
 }
 
-PRBool
-nsAttrValue::GetEnumTableIndex(const EnumTable* aTable, PRInt16& aResult)
+PRInt16
+nsAttrValue::GetEnumTableIndex(const EnumTable* aTable)
 {
   PRInt16 index = sEnumTableArray->IndexOf(aTable);
   if (index < 0) {
     index = sEnumTableArray->Length();
     NS_ASSERTION(index <= NS_ATTRVALUE_ENUMTABLEINDEX_MAXVALUE,
         "too many enum tables");
-    if (!sEnumTableArray->AppendElement(aTable)) {
-      return PR_FALSE;
-    }
+    sEnumTableArray->AppendElement(aTable);
   }
 
-  aResult = index;
+  return index;
+}
 
-  return PR_TRUE;
+PRInt32
+nsAttrValue::EnumTableEntryToValue(const EnumTable* aEnumTable,
+                                   const EnumTable* aTableEntry)
+{
+  PRInt16 index = GetEnumTableIndex(aEnumTable);
+  PRInt32 value = (aTableEntry->value << NS_ATTRVALUE_ENUMTABLEINDEX_BITS) +
+                  index;
+  return value;
 }
 
 PRBool
 nsAttrValue::ParseEnumValue(const nsAString& aValue,
                             const EnumTable* aTable,
-                            PRBool aCaseSensitive)
+                            PRBool aCaseSensitive,
+                            const EnumTable* aDefaultValue)
 {
   ResetIfSet();
   const EnumTable* tableEntry = aTable;
 
   while (tableEntry->tag) {
     if (aCaseSensitive ? aValue.EqualsASCII(tableEntry->tag) :
                          aValue.LowerCaseEqualsASCII(tableEntry->tag)) {
-      PRInt16 index;
-      if (!GetEnumTableIndex(aTable, index)) {
-        return PR_FALSE;
-      }
-
-      PRInt32 value = (tableEntry->value << NS_ATTRVALUE_ENUMTABLEINDEX_BITS) +
-                      index;
+      PRInt32 value = EnumTableEntryToValue(aTable, tableEntry);
 
       PRBool equals = aCaseSensitive || aValue.EqualsASCII(tableEntry->tag);
       if (!equals) {
         nsAutoString tag;
         tag.AssignASCII(tableEntry->tag);
         ToUpperCase(tag);
         if ((equals = tag.Equals(aValue))) {
           value |= NS_ATTRVALUE_ENUMTABLE_VALUE_NEEDS_TO_UPPER;
@@ -1031,16 +1031,24 @@ nsAttrValue::ParseEnumValue(const nsAStr
       NS_ASSERTION(GetEnumValue() == tableEntry->value,
                    "failed to store enum properly");
 
       return PR_TRUE;
     }
     tableEntry++;
   }
 
+  if (aDefaultValue) {
+    NS_PRECONDITION(aTable <= aDefaultValue && aDefaultValue < tableEntry,
+                    "aDefaultValue not inside aTable?");
+    SetIntValueAndType(EnumTableEntryToValue(aTable, aDefaultValue),
+                       eEnum, &aValue);
+    return PR_TRUE;
+  }
+
   return PR_FALSE;
 }
 
 PRBool
 nsAttrValue::ParseSpecialIntValue(const nsAString& aString)
 {
   ResetIfSet();
 
@@ -1444,8 +1452,68 @@ nsAttrValue::StringToInteger(const nsASt
         }
       }
     }
   }
 
   nsAutoString tmp(aValue);
   return tmp.ToInteger(aErrorCode);
 }
+
+PRInt64
+nsAttrValue::SizeOf() const
+{
+  PRInt64 size = sizeof(*this);
+
+  switch (BaseType()) {
+    case eStringBase:
+    {
+      // TODO: we might be counting the string size more than once.
+      // This should be fixed with bug 677487.
+      nsStringBuffer* str = static_cast<nsStringBuffer*>(GetPtr());
+      size += str ? str->StorageSize() : 0;
+      break;
+    }
+    case eOtherBase:
+    {
+      MiscContainer* container = GetMiscContainer();
+
+      if (!container) {
+        break;
+      }
+
+      size += sizeof(*container);
+
+      void* otherPtr = MISC_STR_PTR(container);
+      // We only count the size of the object pointed by otherPtr if it's a
+      // string. When it's an atom, it's counted separatly.
+      if (otherPtr &&
+          static_cast<ValueBaseType>(container->mStringBits & NS_ATTRVALUE_BASETYPE_MASK) == eStringBase) {
+        // TODO: we might be counting the string size more than once.
+        // This should be fixed with bug 677487.
+        nsStringBuffer* str = static_cast<nsStringBuffer*>(otherPtr);
+        size += str ? str->StorageSize() : 0;
+      }
+
+      // TODO: mCSSStyleRule and mSVGValue might be owned by another object
+      // which would make us count them twice, bug 677493.
+      if (Type() == eCSSStyleRule && container->mCSSStyleRule) {
+        // TODO: Add SizeOf() to StyleRule, bug 677503.
+        size += sizeof(*container->mCSSStyleRule);
+      } else if (Type() == eSVGValue && container->mSVGValue) {
+        // TODO: Add SizeOf() to nsSVGValue, bug 677504.
+        size += sizeof(*container->mSVGValue);
+      } else if (Type() == eAtomArray && container->mAtomArray) {
+        size += sizeof(container->mAtomArray) + sizeof(nsTArrayHeader);
+        size += container->mAtomArray->Capacity() * sizeof(nsCOMPtr<nsIAtom>);
+        // Don't count the size of each nsIAtom, they are counted separatly.
+      }
+
+      break;
+    }
+    case eAtomBase:    // Atoms are counted separatly.
+    case eIntegerBase: // The value is in mBits, nothing to do.
+      break;
+  }
+
+  return size;
+}
+
--- a/content/base/src/nsAttrValue.h
+++ b/content/base/src/nsAttrValue.h
@@ -53,17 +53,16 @@
 #include "nsCOMPtr.h"
 
 typedef PRUptrdiff PtrBits;
 class nsAString;
 class nsIAtom;
 class nsISVGValue;
 class nsIDocument;
 template<class E, class A> class nsTArray;
-template<class E, class A> class nsTPtrArray;
 struct nsTArrayDefaultAllocator;
 
 namespace mozilla {
 namespace css {
 class StyleRule;
 }
 }
 
@@ -209,21 +208,25 @@ public:
   };
 
   /**
    * Parse into an enum value.
    *
    * @param aValue the string to find the value for
    * @param aTable the enumeration to map with
    * @param aCaseSensitive specify if the parsing has to be case sensitive
+   * @param aDefaultValue if non-null, this function will always return true.
+   *        Failure to parse aValue as one of the values in aTable will just
+   *        cause aDefaultValue->value to be stored as the enumeration value.
    * @return whether the enum value was found or not
    */
   PRBool ParseEnumValue(const nsAString& aValue,
                         const EnumTable* aTable,
-                        PRBool aCaseSensitive);
+                        PRBool aCaseSensitive,
+                        const EnumTable* aDefaultValue = nsnull);
 
   /**
    * Parse a string into an integer. Can optionally parse percent (n%).
    * This method explicitly sets a lower bound of zero on the element,
    * whether it be percent or raw integer.
    *
    * @param aString the string to parse
    * @return whether the value could be parsed
@@ -306,16 +309,18 @@ public:
    * Parse a margin string of format 'top, right, bottom, left' into
    * an nsIntMargin.
    *
    * @param aString the string to parse
    * @return whether the value could be parsed
    */
   PRBool ParseIntMarginValue(const nsAString& aString);
 
+  PRInt64 SizeOf() const;
+
 private:
   // These have to be the same as in ValueType
   enum ValueBaseType {
     eStringBase =    eString,    // 00
     eOtherBase =     0x01,       // 01
     eAtomBase =      eAtom,      // 10
     eIntegerBase =   0x03        // 11
   };
@@ -341,23 +346,21 @@ private:
     };
   };
 
   inline ValueBaseType BaseType() const;
 
   /**
    * Get the index of an EnumTable in the sEnumTableArray.
    * If the EnumTable is not in the sEnumTableArray, it is added.
-   * If there is no more space in sEnumTableArray, it returns PR_FALSE.
    *
    * @param aTable   the EnumTable to get the index of.
-   * @param aResult  the index of the EnumTable.
-   * @return         whether the index has been found or inserted.
+   * @return         the index of the EnumTable.
    */
-  PRBool GetEnumTableIndex(const EnumTable* aTable, PRInt16& aResult);
+  PRInt16  GetEnumTableIndex(const EnumTable* aTable);
 
   inline void SetPtrValueAndType(void* aValue, ValueBaseType aType);
   void SetIntValueAndType(PRInt32 aValue, ValueType aType,
                           const nsAString* aStringValue);
   void SetColorValue(nscolor aColor, const nsAString& aString);
   void SetMiscAtomOrString(const nsAString* aValue);
   void ResetMiscAtomOrString();
   inline void ResetIfSet();
@@ -371,18 +374,22 @@ private:
   nsStringBuffer* GetStringBuffer(const nsAString& aValue) const;
   // aStrict is set PR_TRUE if stringifying the return value equals with
   // aValue.
   PRInt32 StringToInteger(const nsAString& aValue,
                           PRBool* aStrict,
                           PRInt32* aErrorCode,
                           PRBool aCanBePercent = PR_FALSE,
                           PRBool* aIsPercent = nsnull) const;
+  // Given an enum table and a particular entry in that table, return
+  // the actual integer value we should store.
+  PRInt32 EnumTableEntryToValue(const EnumTable* aEnumTable,
+                                const EnumTable* aTableEntry);  
 
-  static nsTPtrArray<const EnumTable, nsTArrayDefaultAllocator>* sEnumTableArray;
+  static nsTArray<const EnumTable*, nsTArrayDefaultAllocator>* sEnumTableArray;
 
   PtrBits mBits;
 };
 
 /**
  * Implementation of inline methods
  */
 
--- a/content/base/src/nsCommentNode.cpp
+++ b/content/base/src/nsCommentNode.cpp
@@ -36,18 +36,20 @@
  * ***** END LICENSE BLOCK ***** */
 
 /*
  * Implementations of DOM Core's nsIDOMComment node.
  */
 
 #include "nsIDOMComment.h"
 #include "nsGenericDOMDataNode.h"
+
 #include "nsCOMPtr.h"
 #include "nsIDocument.h"
+#include "nsGenericElement.h" // DOMCI_NODE_DATA
 #include "nsDOMMemoryReporter.h"
 
 class nsCommentNode : public nsGenericDOMDataNode,
                       public nsIDOMComment
 {
 public:
   nsCommentNode(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsCommentNode();
--- a/content/base/src/nsContentIterator.cpp
+++ b/content/base/src/nsContentIterator.cpp
@@ -36,17 +36,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.h"
 #include "nsIDOMNodeList.h"
 #include "nsIContentIterator.h"
 #include "nsRange.h"
 #include "nsIContent.h"
-#include "nsIDOMText.h"
 #include "nsCOMPtr.h"
 #include "nsTArray.h"
 #include "nsContentUtils.h"
 #include "nsINode.h"
 #include "nsCycleCollectionParticipant.h"
 
 // couple of utility static functs
 
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -129,17 +129,16 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_
 #include "nsXBLBinding.h"
 #include "nsXBLPrototypeBinding.h"
 #include "nsEscape.h"
 #include "nsICharsetConverterManager.h"
 #include "nsEventListenerManager.h"
 #include "nsAttrName.h"
 #include "nsIDOMUserDataHandler.h"
 #include "nsContentCreatorFunctions.h"
-#include "nsTPtrArray.h"
 #include "nsGUIEvent.h"
 #include "nsMutationEvent.h"
 #include "nsIMEStateManager.h"
 #include "nsContentErrors.h"
 #include "nsUnicharUtilCIID.h"
 #include "nsCompressedCharMap.h"
 #include "nsINativeKeyBindings.h"
 #include "nsIDOMNSUIEvent.h"
@@ -1553,17 +1552,17 @@ nsINode*
 nsContentUtils::GetCommonAncestor(nsINode* aNode1,
                                   nsINode* aNode2)
 {
   if (aNode1 == aNode2) {
     return aNode1;
   }
 
   // Build the chain of parents
-  nsAutoTPtrArray<nsINode, 30> parents1, parents2;
+  nsAutoTArray<nsINode*, 30> parents1, parents2;
   do {
     parents1.AppendElement(aNode1);
     aNode1 = aNode1->GetNodeParent();
   } while (aNode1);
   do {
     parents2.AppendElement(aNode2);
     aNode2 = aNode2->GetNodeParent();
   } while (aNode2);
--- a/content/base/src/nsDOMAttribute.cpp
+++ b/content/base/src/nsDOMAttribute.cpp
@@ -55,16 +55,17 @@
 #include "nsGkAtoms.h"
 #include "nsCOMArray.h"
 #include "nsNodeUtils.h"
 #include "nsEventListenerManager.h"
 #include "nsTextNode.h"
 #include "mozAutoDocUpdate.h"
 #include "nsMutationEvent.h"
 #include "nsPLDOMEvent.h"
+#include "nsContentUtils.h" // NS_IMPL_CYCLE_COLLECTION_UNLINK_LISTENERMANAGER
 
 using namespace mozilla::dom;
 
 //----------------------------------------------------------------------
 PRBool nsDOMAttribute::sInitialized;
 
 nsDOMAttribute::nsDOMAttribute(nsDOMAttributeMap *aAttrMap,
                                already_AddRefed<nsINodeInfo> aNodeInfo,
--- a/content/base/src/nsDOMAttribute.h
+++ b/content/base/src/nsDOMAttribute.h
@@ -46,17 +46,16 @@
 #include "nsIDOMAttr.h"
 #include "nsIDOMText.h"
 #include "nsIDOMNodeList.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsINodeInfo.h"
 #include "nsDOMAttributeMap.h"
 #include "nsCycleCollectionParticipant.h"
-#include "nsContentUtils.h"
 #include "nsStubMutationObserver.h"
 
 // Attribute helper class used to wrap up an attribute with a dom
 // object that implements nsIDOMAttr and nsIDOMNode
 class nsDOMAttribute : public nsIAttribute,
                        public nsIDOMAttr,
                        public nsStubMutationObserver
 {
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -5915,16 +5915,23 @@ nsDocument::GetXmlStandalone(PRBool *aXm
 
 NS_IMETHODIMP
 nsDocument::SetXmlStandalone(PRBool aXmlStandalone)
 {
   return IsHTML() ? NS_ERROR_DOM_NOT_SUPPORTED_ERR : NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
+nsDocument::GetMozSyntheticDocument(PRBool *aSyntheticDocument)
+{
+  *aSyntheticDocument = mIsSyntheticDocument;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDocument::GetXmlVersion(nsAString& aXmlVersion)
 {
   if (IsHTML()) {
     SetDOMStringToNull(aXmlVersion);
     return NS_OK;
   }
 
   // If there is no declaration, the value is "1.0".
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -82,29 +82,28 @@
 #include "nsContentList.h"
 #include "nsGkAtoms.h"
 #include "nsIApplicationCache.h"
 #include "nsIApplicationCacheContainer.h"
 #include "nsStyleSet.h"
 #include "pldhash.h"
 #include "nsAttrAndChildArray.h"
 #include "nsDOMAttributeMap.h"
-#include "nsContentUtils.h"
 #include "nsThreadUtils.h"
 #include "nsIDocumentViewer.h"
 #include "nsIDOMXPathNSResolver.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsILoadContext.h"
 #include "nsIProgressEventSink.h"
 #include "nsISecurityEventSink.h"
 #include "nsIChannelEventSink.h"
 #include "imgIRequest.h"
 #include "nsIDOMDOMImplementation.h"
 #include "nsIDOMTouchEvent.h"
-
+#include "nsDataHashtable.h"
 #include "TimeStamp.h"
 
 #define XML_DECLARATION_BITS_DECLARATION_EXISTS   (1 << 0)
 #define XML_DECLARATION_BITS_ENCODING_EXISTS      (1 << 1)
 #define XML_DECLARATION_BITS_STANDALONE_EXISTS    (1 << 2)
 #define XML_DECLARATION_BITS_STANDALONE_YES       (1 << 3)
 
 
@@ -518,17 +517,17 @@ public:
                                      PRBool aReset = PR_TRUE,
                                      nsIContentSink* aContentSink = nsnull) = 0;
 
   virtual void StopDocumentLoad();
 
   virtual void NotifyPossibleTitleChange(PRBool aBoundTitleElement);
 
   virtual void SetDocumentURI(nsIURI* aURI);
-  
+
   /**
    * Set the principal responsible for this document.
    */
   virtual void SetPrincipal(nsIPrincipal *aPrincipal);
 
   /**
    * Get the Content-Type of this document.
    */
--- a/content/base/src/nsEventSource.cpp
+++ b/content/base/src/nsEventSource.cpp
@@ -52,16 +52,17 @@
 #include "nsIScriptObjectPrincipal.h"
 #include "jsdbgapi.h"
 #include "nsJSUtils.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsIScriptError.h"
 #include "nsICharsetConverterManager.h"
 #include "nsIChannelPolicy.h"
 #include "nsIContentSecurityPolicy.h"
+#include "nsContentUtils.h"
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
 
 #define REPLACEMENT_CHAR     (PRUnichar)0xFFFD
 #define BOM_CHAR             (PRUnichar)0xFEFF
 #define SPACE_CHAR           (PRUnichar)0x0020
 #define CR_CHAR              (PRUnichar)0x000D
--- a/content/base/src/nsGenericDOMDataNode.h
+++ b/content/base/src/nsGenericDOMDataNode.h
@@ -39,23 +39,22 @@
  * Base class for DOM Core's nsIDOMComment, nsIDOMDocumentType, nsIDOMText,
  * nsIDOMCDATASection, and nsIDOMProcessingInstruction nodes.
  */
 
 #ifndef nsGenericDOMDataNode_h___
 #define nsGenericDOMDataNode_h___
 
 #include "nsIContent.h"
-#include "nsIDOMCharacterData.h"
+
 #include "nsTextFragment.h"
 #include "nsDOMError.h"
 #include "nsEventListenerManager.h"
 #include "nsGenericElement.h"
 #include "nsCycleCollectionParticipant.h"
-#include "nsContentUtils.h"
 #include "nsDOMMemoryReporter.h"
 
 #ifdef MOZ_SMIL
 #include "nsISMILAttr.h"
 #endif // MOZ_SMIL
 
 // This bit is set to indicate that if the text node changes to
 // non-whitespace, we may need to create a frame for it. This bit must
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -47,17 +47,16 @@
 
 #include "nsDOMAttribute.h"
 #include "nsDOMAttributeMap.h"
 #include "nsIAtom.h"
 #include "nsINodeInfo.h"
 #include "nsIDocument.h"
 #include "nsIDOMNodeList.h"
 #include "nsIDOMDocument.h"
-#include "nsIDOMText.h"
 #include "nsIContentIterator.h"
 #include "nsEventListenerManager.h"
 #include "nsFocusManager.h"
 #include "nsILinkHandler.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIURL.h"
 #include "nsNetUtil.h"
 #include "nsIFrame.h"
@@ -137,17 +136,16 @@
 #endif /* MOZ_XUL */
 
 #include "nsCycleCollectionParticipant.h"
 #include "nsCCUncollectableMarker.h"
 
 #include "mozAutoDocUpdate.h"
 
 #include "nsCSSParser.h"
-#include "nsTPtrArray.h"
 #include "prprf.h"
 
 #include "nsSVGFeatures.h"
 #include "nsDOMMemoryReporter.h"
 
 using namespace mozilla::dom;
 namespace css = mozilla::css;
 
@@ -751,17 +749,17 @@ PRUint16
 nsINode::CompareDocPosition(nsINode* aOtherNode)
 {
   NS_PRECONDITION(aOtherNode, "don't pass null");
 
   if (this == aOtherNode) {
     return 0;
   }
 
-  nsAutoTPtrArray<nsINode, 32> parents1, parents2;
+  nsAutoTArray<nsINode*, 32> parents1, parents2;
 
   nsINode *node1 = aOtherNode, *node2 = this;
 
   // Check if either node is an attribute
   nsIAttribute* attr1 = nsnull;
   if (node1->IsNodeOfType(nsINode::eATTRIBUTE)) {
     attr1 = static_cast<nsIAttribute*>(node1);
     nsIContent* elem = attr1->GetContent();
@@ -2030,16 +2028,23 @@ nsGenericElement::GetBoundingClientRect(
 
 NS_IMETHODIMP
 nsNSElementTearoff::GetBoundingClientRect(nsIDOMClientRect** aResult)
 {
   return mContent->GetBoundingClientRect(aResult);
 }
 
 nsresult
+nsGenericElement::GetElementsByClassName(const nsAString& aClasses,
+                                         nsIDOMNodeList** aReturn)
+{
+  return nsContentUtils::GetElementsByClassName(this, aClasses, aReturn);
+}
+
+nsresult
 nsGenericElement::GetClientRects(nsIDOMClientRectList** aResult)
 {
   *aResult = nsnull;
 
   nsRefPtr<nsClientRectList> rectList = new nsClientRectList();
   if (!rectList)
     return NS_ERROR_OUT_OF_MEMORY;
 
@@ -3539,16 +3544,29 @@ nsINode::doRemoveChildAt(PRUint32 aIndex
     nsNodeUtils::ContentRemoved(this, aKid, aIndex, previousSibling);
   }
 
   aKid->UnbindFromTree();
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsGenericElement::GetTextContent(nsAString &aTextContent)
+{
+  nsContentUtils::GetNodeTextContent(this, PR_TRUE, aTextContent);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsGenericElement::SetTextContent(const nsAString& aTextContent)
+{
+  return nsContentUtils::SetNodeTextContent(this, aTextContent, PR_FALSE);
+}
+
 /* static */
 nsresult
 nsGenericElement::DispatchEvent(nsPresContext* aPresContext,
                                 nsEvent* aEvent,
                                 nsIContent* aTarget,
                                 PRBool aFullDispatch,
                                 nsEventStatus* aStatus)
 {
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -46,28 +46,29 @@
 
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "mozilla/dom/Element.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMDocumentFragment.h"
 #include "nsIDOMNSElement.h"
 #include "nsILinkHandler.h"
-#include "nsContentUtils.h"
 #include "nsNodeUtils.h"
 #include "nsAttrAndChildArray.h"
 #include "mozFlushType.h"
 #include "nsDOMAttributeMap.h"
 #include "nsIWeakReference.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIDocument.h"
 #include "nsIDOMNodeSelector.h"
 #include "nsIDOMXPathNSResolver.h"
 #include "nsPresContext.h"
 #include "nsIDOMDOMStringMap.h"
+#include "nsContentList.h"
+#include "nsDOMClassInfoID.h" // DOMCI_DATA
 
 #ifdef MOZ_SMIL
 #include "nsISMILAttr.h"
 #endif // MOZ_SMIL
 
 class nsIDOMAttr;
 class nsIDOMEventListener;
 class nsIFrame;
@@ -251,25 +252,18 @@ public:
   // nsINode interface methods
   virtual PRUint32 GetChildCount() const;
   virtual nsIContent *GetChildAt(PRUint32 aIndex) const;
   virtual nsIContent * const * GetChildArray(PRUint32* aChildCount) const;
   virtual PRInt32 IndexOf(nsINode* aPossibleChild) const;
   virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
                                  PRBool aNotify);
   virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
-  NS_IMETHOD GetTextContent(nsAString &aTextContent)
-  {
-    nsContentUtils::GetNodeTextContent(this, PR_TRUE, aTextContent);
-    return NS_OK;
-  }
-  NS_IMETHOD SetTextContent(const nsAString& aTextContent)
-  {
-    return nsContentUtils::SetNodeTextContent(this, aTextContent, PR_FALSE);
-  }
+  NS_IMETHOD GetTextContent(nsAString &aTextContent);
+  NS_IMETHOD SetTextContent(const nsAString& aTextContent);
 
   // nsIContent interface methods
   virtual void UpdateEditableState(PRBool aNotify);
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               PRBool aCompileEventHandlers);
   virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
@@ -585,20 +579,17 @@ public:
   }
 
   virtual void RecompileScriptEventListeners()
   {
   }
 
   // nsIDOMNSElement methods
   nsresult GetElementsByClassName(const nsAString& aClasses,
-                                  nsIDOMNodeList** aReturn)
-  {
-    return nsContentUtils::GetElementsByClassName(this, aClasses, aReturn);
-  }
+                                  nsIDOMNodeList** aReturn);
   nsresult GetClientRects(nsIDOMClientRectList** aResult);
   nsresult GetBoundingClientRect(nsIDOMClientRect** aResult);
   PRInt32 GetScrollTop();
   void SetScrollTop(PRInt32 aScrollTop);
   PRInt32 GetScrollLeft();
   void SetScrollLeft(PRInt32 aScrollLeft);
   PRInt32 GetScrollHeight();
   PRInt32 GetScrollWidth();
--- a/content/base/src/nsHTMLContentSerializer.cpp
+++ b/content/base/src/nsHTMLContentSerializer.cpp
@@ -42,17 +42,16 @@
  * nsIContentSerializer implementation that can be used with an
  * nsIDocumentEncoder to convert an HTML (not XHTML!) DOM to an HTML
  * string that could be parsed into more or less the original DOM.
  */
 
 #include "nsHTMLContentSerializer.h"
 
 #include "nsIDOMElement.h"
-#include "nsIDOMText.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "nsINameSpaceManager.h"
 #include "nsString.h"
 #include "nsUnicharUtils.h"
 #include "nsXPIDLString.h"
 #include "nsIServiceManager.h"
--- a/content/base/src/nsImageLoadingContent.h
+++ b/content/base/src/nsImageLoadingContent.h
@@ -45,17 +45,17 @@
 #ifndef nsImageLoadingContent_h__
 #define nsImageLoadingContent_h__
 
 #include "nsIImageLoadingContent.h"
 #include "nsINode.h"
 #include "imgIRequest.h"
 #include "prtypes.h"
 #include "nsCOMPtr.h"
-#include "nsContentUtils.h"
+#include "nsContentUtils.h" // NS_CONTENT_DELETE_LIST_MEMBER
 #include "nsString.h"
 #include "nsEventStates.h"
 
 class nsIURI;
 class nsIDocument;
 class imgILoader;
 class nsIIOService;
 
--- a/content/base/src/nsMappedAttributes.cpp
+++ b/content/base/src/nsMappedAttributes.cpp
@@ -272,8 +272,24 @@ nsMappedAttributes::IndexOfAttr(nsIAtom*
       if (Attrs()[i].mName.Equals(aLocalName, aNamespaceID)) {
         return i;
       }
     }
   }
 
   return -1;
 }
+
+PRInt64
+nsMappedAttributes::SizeOf() const
+{
+  NS_ASSERTION(mAttrCount == mBufferSize,
+               "mBufferSize and mAttrCount are expected to be the same.");
+
+  PRInt64 size = sizeof(*this) - sizeof(void*) + mAttrCount * sizeof(InternalAttr);
+
+  for (PRUint16 i = 0; i < mAttrCount; ++i) {
+    size += Attrs()[i].mValue.SizeOf() - sizeof(Attrs()[i].mValue);
+  }
+
+  return size;
+}
+
--- a/content/base/src/nsMappedAttributes.h
+++ b/content/base/src/nsMappedAttributes.h
@@ -103,21 +103,17 @@ public:
   
 
   // nsIStyleRule 
   virtual void MapRuleInfoInto(nsRuleData* aRuleData);
 #ifdef DEBUG
   virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
 #endif
 
-  PRInt64 SizeOf() const {
-    NS_ASSERTION(mAttrCount == mBufferSize,
-                 "mBufferSize and mAttrCount are expected to be the same.");
-    return sizeof(*this) - sizeof(void*) + mAttrCount * sizeof(InternalAttr);
-  }
+  PRInt64 SizeOf() const;
 
 private:
   nsMappedAttributes(const nsMappedAttributes& aCopy);
   ~nsMappedAttributes();
 
   struct InternalAttr
   {
     nsAttrName mName;
--- a/content/base/src/nsPlainTextSerializer.cpp
+++ b/content/base/src/nsPlainTextSerializer.cpp
@@ -42,19 +42,16 @@
  * nsIDocumentEncoder to convert a DOM into plaintext in a nice way
  * (eg for copy/paste as plaintext).
  */
 
 #include "nsPlainTextSerializer.h"
 #include "nsLWBrkCIID.h"
 #include "nsIServiceManager.h"
 #include "nsGkAtoms.h"
-#include "nsIDOMText.h"
-#include "nsIDOMCDATASection.h"
-#include "nsIDOMElement.h"
 #include "nsINameSpaceManager.h"
 #include "nsTextFragment.h"
 #include "nsContentUtils.h"
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsCRT.h"
 #include "nsIParserService.h"
 #include "mozilla/dom/Element.h"
--- a/content/base/src/nsScriptLoader.h
+++ b/content/base/src/nsScriptLoader.h
@@ -331,9 +331,32 @@ private:
   // XXXbz do we want to cycle-collect these or something?  Not sure.
   nsTArray< nsRefPtr<nsScriptLoader> > mPendingChildLoaders;
   PRUint32 mBlockerCount;
   PRPackedBool mEnabled;
   PRPackedBool mDeferEnabled;
   PRPackedBool mDocumentParsingDone;
 };
 
+class nsAutoScriptLoaderDisabler
+{
+public:
+  nsAutoScriptLoaderDisabler(nsIDocument* aDoc)
+  {
+    mLoader = aDoc->ScriptLoader();
+    mWasEnabled = mLoader->GetEnabled();
+    if (mWasEnabled) {
+      mLoader->SetEnabled(PR_FALSE);
+    }
+  }
+  
+  ~nsAutoScriptLoaderDisabler()
+  {
+    if (mWasEnabled) {
+      mLoader->SetEnabled(PR_TRUE);
+    }
+  }
+  
+  PRBool mWasEnabled;
+  nsRefPtr<nsScriptLoader> mLoader;
+};
+
 #endif //__nsScriptLoader_h__
--- a/content/base/src/nsStyleLinkElement.cpp
+++ b/content/base/src/nsStyleLinkElement.cpp
@@ -47,17 +47,16 @@
 
 #include "nsIContent.h"
 #include "mozilla/css/Loader.h"
 #include "nsCSSStyleSheet.h"
 #include "nsIDocument.h"
 #include "nsIDOMComment.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMStyleSheet.h"
-#include "nsIDOMText.h"
 #include "nsNetUtil.h"
 #include "nsUnicharUtils.h"
 #include "nsCRT.h"
 #include "nsXPCOMCIDInternal.h"
 #include "nsUnicharInputStream.h"
 #include "nsContentUtils.h"
 
 nsStyleLinkElement::nsStyleLinkElement()
--- a/content/base/src/nsTextNode.h
+++ b/content/base/src/nsTextNode.h
@@ -36,19 +36,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 /*
  * Implementation of DOM Core's nsIDOMText node.
  */
 
 #include "nsGenericDOMDataNode.h"
 #include "nsIDOMText.h"
-#include "nsContentUtils.h"
-#include "nsIDOMEventListener.h"
-#include "nsIDOMMutationEvent.h"
+
 #include "nsIAttribute.h"
 #include "nsIDocument.h"
 #include "nsThreadUtils.h"
 #include "nsDOMMemoryReporter.h"
 
 /**
  * Class used to implement DOM text nodes
  */
--- a/content/base/src/nsTreeSanitizer.cpp
+++ b/content/base/src/nsTreeSanitizer.cpp
@@ -47,16 +47,17 @@
 #include "nsUnicharInputStream.h"
 #include "nsCSSStyleSheet.h"
 #include "nsIDOMCSSRule.h"
 #include "nsAttrName.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsNetUtil.h"
 #include "nsComponentManagerUtils.h"
 #include "nsNullPrincipal.h"
+#include "nsContentUtils.h"
 
 //
 // Thanks to Mark Pilgrim and Sam Ruby for the initial whitelist
 //
 nsIAtom** const kElementsHTML[] = {
   &nsGkAtoms::a,
   &nsGkAtoms::abbr,
   &nsGkAtoms::acronym,
@@ -1190,17 +1191,17 @@ nsTreeSanitizer::SanitizeAttributes(mozi
   PRUint32 ac = aElement->GetAttrCount();
 
   nsresult rv;
 
   for (PRInt32 i = ac - 1; i >= 0; --i) {
     rv = NS_OK;
     const nsAttrName* attrName = aElement->GetAttrNameAt(i);
     PRInt32 attrNs = attrName->NamespaceID();
-    nsIAtom* attrLocal = attrName->LocalName();
+    nsCOMPtr<nsIAtom> attrLocal = attrName->LocalName();
 
     if (kNameSpaceID_None == attrNs) {
       if (aAllowStyle && nsGkAtoms::style == attrLocal) {
         nsCOMPtr<nsIURI> baseURI = aElement->GetBaseURI();
         nsIDocument* document = aElement->GetOwnerDoc();
         // Pass the CSS Loader object to the parser, to allow parser error
         // reports to include the outer window ID.
         nsCSSParser parser(document->CSSLoader());
--- a/content/base/src/nsXHTMLContentSerializer.cpp
+++ b/content/base/src/nsXHTMLContentSerializer.cpp
@@ -42,17 +42,16 @@
  * nsIContentSerializer implementation that can be used with an
  * nsIDocumentEncoder to convert an XHTML (not HTML!) DOM to an XHTML
  * string that could be parsed into more or less the original DOM.
  */
 
 #include "nsXHTMLContentSerializer.h"
 
 #include "nsIDOMElement.h"
-#include "nsIDOMText.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "nsINameSpaceManager.h"
 #include "nsString.h"
 #include "nsUnicharUtils.h"
 #include "nsXPIDLString.h"
 #include "nsIServiceManager.h"
--- a/content/base/src/nsXMLContentSerializer.cpp
+++ b/content/base/src/nsXMLContentSerializer.cpp
@@ -40,23 +40,19 @@
  * nsIContentSerializer implementation that can be used with an
  * nsIDocumentEncoder to convert an XML DOM to an XML string that
  * could be parsed into more or less the original DOM.
  */
 
 #include "nsXMLContentSerializer.h"
 
 #include "nsGkAtoms.h"
-#include "nsIDOMText.h"
-#include "nsIDOMCDATASection.h"
 #include "nsIDOMProcessingInstruction.h"
 #include "nsIDOMComment.h"
-#include "nsIDOMDocument.h"
 #include "nsIDOMDocumentType.h"
-#include "nsIDOMElement.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "nsIDocumentEncoder.h"
 #include "nsINameSpaceManager.h"
 #include "nsTextFragment.h"
 #include "nsString.h"
 #include "prprf.h"
 #include "nsUnicharUtils.h"
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -1343,16 +1343,22 @@ nsXMLHttpRequest::GetCurrentHttpChannel(
 
   if (!httpChannel && mChannel) {
     CallQueryInterface(mChannel, &httpChannel);
   }
 
   return httpChannel;
 }
 
+bool
+nsXMLHttpRequest::IsSystemXHR()
+{
+  return !!nsContentUtils::IsSystemPrincipal(mPrincipal);
+}
+
 nsresult
 nsXMLHttpRequest::CheckChannelForCrossSiteRequest(nsIChannel* aChannel)
 {
   // First check if cross-site requests are enabled...
   if (IsSystemXHR()) {
     return NS_OK;
   }
 
--- a/content/base/src/nsXMLHttpRequest.h
+++ b/content/base/src/nsXMLHttpRequest.h
@@ -221,19 +221,17 @@ protected:
                                   nsRefPtr<nsDOMEventListenerWrapper>& aCurrent,
                                   nsIDOMEventListener* aNew);
 
   nsresult GetInnerEventListener(nsRefPtr<nsDOMEventListenerWrapper>& aWrapper,
                                  nsIDOMEventListener** aListener);
 
   already_AddRefed<nsIHttpChannel> GetCurrentHttpChannel();
 
-  bool IsSystemXHR() {
-    return !!nsContentUtils::IsSystemPrincipal(mPrincipal);
-  }
+  bool IsSystemXHR();
 
   /**
    * Check if aChannel is ok for a cross-site request by making sure no
    * inappropriate headers are set, and no username/password is set.
    *
    * Also updates the XML_HTTP_REQUEST_USE_XSITE_AC bit.
    */
   nsresult CheckChannelForCrossSiteRequest(nsIChannel* aChannel);
--- a/content/base/test/test_copypaste.html
+++ b/content/base/test/test_copypaste.html
@@ -219,16 +219,24 @@ if (false) {
   textarea.select();
   textarea.editor.copy();
   
   textarea.value="";
   textarea.editor.paste(1);
   is(textarea.value, val);
   textarea.value="";
 
+  // ============ NOSCRIPT should not be copied
+
+  copyChildrenToClipboard("div13");
+  testSelectionToString("__");
+  testClipboardValue("text/unicode", "__");
+  testClipboardValue("text/html", "<div id=\"div13\">__</div>");
+  testPasteText("__");
+
   // ============ manipulating Selection in oncopy
 
   copyRangeToClipboard($("div11").childNodes[0],0, $("div11").childNodes[1],2);
   testClipboardValue("text/unicode", "Xdiv11");
   testClipboardValue("text/html", "<div><p>X<span>div</span>11</p></div>");
   setTimeout(function(){testSelectionToString("div11")},0);
 
   setTimeout(function(){
@@ -306,11 +314,13 @@ x.appendChild(document.createTextNode('v
 var x = $("div10")
 x.appendChild(document.createTextNode('div'))
 x.appendChild(document.createTextNode('10'))
 </script>
 
 <div id="div11" oncopy="modifySelection('X')"><span>div</span>11</div>
 <div id="div12" oncopy="modifySelection('X<b style=\'display:none\'>Y</b>')"><span>div</span>12</div>
 
+<div id="div13">_<noscript>FAIL</noscript>_</div>
+
 </div>
 </body>
 </html>
--- a/content/canvas/src/CanvasImageCache.cpp
+++ b/content/canvas/src/CanvasImageCache.cpp
@@ -39,16 +39,17 @@
 #include "nsIImageLoadingContent.h"
 #include "nsExpirationTracker.h"
 #include "imgIRequest.h"
 #include "gfxASurface.h"
 #include "gfxPoint.h"
 #include "nsIDOMElement.h"
 #include "nsTHashtable.h"
 #include "nsHTMLCanvasElement.h"
+#include "nsContentUtils.h"
 
 namespace mozilla {
 
 struct ImageCacheKey {
   ImageCacheKey(nsIDOMElement* aImage, nsHTMLCanvasElement* aCanvas)
     : mImage(aImage), mCanvas(aCanvas) {}
   nsIDOMElement* mImage;
   nsHTMLCanvasElement* mCanvas;
@@ -206,9 +207,9 @@ CanvasImageCacheShutdownObserver::Observ
     gImageCache = nsnull;
 
     nsContentUtils::UnregisterShutdownObserver(this);
   }
 
   return NS_OK;
 }
 
-}
+} // namespace mozilla
--- a/content/canvas/src/DocumentRendererChild.cpp
+++ b/content/canvas/src/DocumentRendererChild.cpp
@@ -29,16 +29,18 @@
  * 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 "mozilla/ipc/DocumentRendererChild.h"
+
 #include "base/basictypes.h"
 
 #include "gfxImageSurface.h"
 #include "gfxPattern.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMDocument.h"
 #include "nsIDocShellTreeNode.h"
@@ -48,18 +50,17 @@
 #include "nsComponentManagerUtils.h"
 #include "nsCSSParser.h"
 #include "nsPresContext.h"
 #include "nsCOMPtr.h"
 #include "nsColor.h"
 #include "gfxContext.h"
 #include "gfxImageSurface.h"
 #include "nsLayoutUtils.h"
-
-#include "mozilla/ipc/DocumentRendererChild.h"
+#include "nsContentUtils.h"
 
 using namespace mozilla::ipc;
 
 DocumentRendererChild::DocumentRendererChild()
 {}
 
 DocumentRendererChild::~DocumentRendererChild()
 {}
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -2178,27 +2178,27 @@ class WebGLMemoryReporter
     ~WebGLMemoryReporter();
     static WebGLMemoryReporter* sUniqueInstance;
 
     // here we store plain pointers, not RefPtrs: we don't want the WebGLMemoryReporter unique instance to keep alive all
     // WebGLContexts ever created.
     typedef nsTArray<const WebGLContext*> ContextsArrayType;
     ContextsArrayType mContexts;
     
-    nsIMemoryReporter *mTextureMemoryUsageReporter;
-    nsIMemoryReporter *mTextureCountReporter;
-    nsIMemoryReporter *mBufferMemoryUsageReporter;
-    nsIMemoryReporter *mBufferCacheMemoryUsageReporter;
-    nsIMemoryReporter *mBufferCountReporter;
-    nsIMemoryReporter *mRenderbufferMemoryUsageReporter;
-    nsIMemoryReporter *mRenderbufferCountReporter;
-    nsIMemoryReporter *mShaderSourcesSizeReporter;
-    nsIMemoryReporter *mShaderTranslationLogsSizeReporter;
-    nsIMemoryReporter *mShaderCountReporter;
-    nsIMemoryReporter *mContextCountReporter;
+    nsCOMPtr<nsIMemoryReporter> mTextureMemoryUsageReporter;
+    nsCOMPtr<nsIMemoryReporter> mTextureCountReporter;
+    nsCOMPtr<nsIMemoryReporter> mBufferMemoryUsageReporter;
+    nsCOMPtr<nsIMemoryReporter> mBufferCacheMemoryUsageReporter;
+    nsCOMPtr<nsIMemoryReporter> mBufferCountReporter;
+    nsCOMPtr<nsIMemoryReporter> mRenderbufferMemoryUsageReporter;
+    nsCOMPtr<nsIMemoryReporter> mRenderbufferCountReporter;
+    nsCOMPtr<nsIMemoryReporter> mShaderSourcesSizeReporter;
+    nsCOMPtr<nsIMemoryReporter> mShaderTranslationLogsSizeReporter;
+    nsCOMPtr<nsIMemoryReporter> mShaderCountReporter;
+    nsCOMPtr<nsIMemoryReporter> mContextCountReporter;
 
     static WebGLMemoryReporter* UniqueInstance();
 
     static ContextsArrayType & Contexts() { return UniqueInstance()->mContexts; }
 
   public:
 
     static void AddWebGLContext(const WebGLContext* c) {
--- a/content/canvas/test/webgl/crossorigin/test_webgl_crossorigin_textures.html
+++ b/content/canvas/test/webgl/crossorigin/test_webgl_crossorigin_textures.html
@@ -30,18 +30,24 @@
     ok(actual_error == expected_error,
        message + ": expected " + nameForErrorCode(expected_error)
                + ", got " + nameForErrorCode(actual_error));
   }
 
   function testTexture(url, crossOriginAttribute, expected_result) {
     number_of_tests_live++;
     var image = new Image();
-    if (crossOriginAttribute != "leave-default-crossOrigin-attribute")
+    if (crossOriginAttribute == "just-crossOrigin-without-value") {
+      var div = document.createElement('div');
+      div.innerHTML="<img crossOrigin>";
+      image = div.children[0];
+    }
+    else if (crossOriginAttribute != "missing-value-default")
       image.crossOrigin = crossOriginAttribute;
+    
 
     function testDone() {
       number_of_tests_live--;
         
       if (number_of_tests_live == 0 && all_tests_started)
         SimpleTest.finish();
     }
 
@@ -72,66 +78,77 @@
     var canvas = document.getElementById("canvas");
     try {
       gl = canvas.getContext("experimental-webgl");
     } catch (e) {
       SimpleTest.finish();
       return;
     }
 
+
     testTexture("http://mochi.test:8888/tests/content/canvas/test/webgl/crossorigin/image.png",
-                "leave-default-crossOrigin-attribute",
+                "missing-value-default",
                 OK);
-
     testTexture("http://mochi.test:8888/tests/content/canvas/test/webgl/crossorigin/image.png",
                 "",
                 OK);
-
+    testTexture("http://mochi.test:8888/tests/content/canvas/test/webgl/crossorigin/image.png",
+                "just-crossOrigin-without-value",
+                OK);
     testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image.png",
-                "leave-default-crossOrigin-attribute",
+                "missing-value-default",
                 SECURITY_ERR);
     testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image.png",
                 "",
                 SECURITY_ERR);
+    testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image.png",
+                "just-crossOrigin-without-value",
+                SECURITY_ERR);
 
     testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image-allow-star.png",
-                "leave-default-crossOrigin-attribute",
+                "missing-value-default",
                 SECURITY_ERR);
     testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image-allow-star.png",
                 "",
-                SECURITY_ERR);
+                OK);
+    testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image-allow-star.png",
+                "just-crossOrigin-without-value",
+                OK);
     testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image-allow-star.png",
                 "anonymous",
                 OK);
     testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image-allow-star.png",
                 "use-credentials",
                 SECURITY_ERR);
 
     testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image-allow-credentials.png",
-                "leave-default-crossOrigin-attribute",
+                "missing-value-default",
                 SECURITY_ERR);
     testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image-allow-credentials.png",
                 "",
-                SECURITY_ERR);
+                OK);
+    testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image-allow-credentials.png",
+                "just-crossOrigin-without-value",
+                OK);
     testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image-allow-credentials.png",
                 "anonymous",
                 OK);
     testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image-allow-credentials.png",
                 "use-credentials",
                 OK);
 
-    // Test that bad values for crossorigin="..." are interpreted as default.
+    // Test that bad values for crossorigin="..." are interpreted as invalid-value-default which is "anonymous".
     testTexture("http://mochi.test:8888/tests/content/canvas/test/webgl/crossorigin/image.png",
                 "foobar",
                 OK);
     testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image.png",
                 "foobar",
                 SECURITY_ERR);
     testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image-allow-star.png",
                 "foobar",
-                SECURITY_ERR);
+                OK);
     testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image-allow-credentials.png",
                 "foobar",
-                SECURITY_ERR);
+                OK);
 
     all_tests_started = true;
   });
 </script>
--- a/content/events/src/nsContentEventHandler.cpp
+++ b/content/events/src/nsContentEventHandler.cpp
@@ -38,33 +38,31 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsContentEventHandler.h"
 #include "nsCOMPtr.h"
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
 #include "nsISelection.h"
-#include "nsIDOMText.h"
 #include "nsIDOMRange.h"
 #include "nsRange.h"
 #include "nsGUIEvent.h"
 #include "nsCaret.h"
 #include "nsCopySupport.h"
 #include "nsFrameSelection.h"
 #include "nsIFrame.h"
 #include "nsIView.h"
 #include "nsIContentIterator.h"
 #include "nsTextFragment.h"
 #include "nsTextFrame.h"
 #include "nsISelectionController.h"
 #include "nsISelectionPrivate.h"
 #include "nsContentUtils.h"
 #include "nsLayoutUtils.h"
-#include "nsISelection2.h"
 #include "nsIMEStateManager.h"
 #include "nsIObjectFrame.h"
 
 nsresult NS_NewContentIterator(nsIContentIterator** aInstancePtrResult);
 
 /******************************************************************/
 /* nsContentEventHandler                                          */
 /******************************************************************/
@@ -1066,18 +1064,17 @@ nsContentEventHandler::OnSelectionEvent(
   PRInt32 endOffset = range->EndOffset();
   AdjustRangeForSelection(mRootContent, &startNode, &startOffset);
   AdjustRangeForSelection(mRootContent, &endNode, &endOffset);
 
   nsCOMPtr<nsIDOMNode> startDomNode(do_QueryInterface(startNode));
   nsCOMPtr<nsIDOMNode> endDomNode(do_QueryInterface(endNode));
   NS_ENSURE_TRUE(startDomNode && endDomNode, NS_ERROR_UNEXPECTED);
 
-  nsCOMPtr<nsISelectionPrivate> selPrivate = do_QueryInterface(mSelection);
-  NS_ENSURE_TRUE(selPrivate, NS_ERROR_UNEXPECTED);
+  nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(mSelection));
   selPrivate->StartBatchChanges();
 
   // Clear selection first before setting
   rv = mSelection->RemoveAllRanges();
   // Need to call EndBatchChanges at the end even if call failed
   if (NS_SUCCEEDED(rv)) {
     if (aEvent->mReversed) {
       rv = mSelection->Collapse(endDomNode, endOffset);
@@ -1091,13 +1088,13 @@ nsContentEventHandler::OnSelectionEvent(
       } else {
         rv = mSelection->Extend(endDomNode, endOffset);
       }
     }
   }
   selPrivate->EndBatchChanges();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsISelection2>(do_QueryInterface(mSelection))->ScrollIntoView(
+  selPrivate->ScrollIntoView(
       nsISelectionController::SELECTION_FOCUS_REGION, PR_FALSE, -1, -1);
   aEvent->mSucceeded = PR_TRUE;
   return NS_OK;
 }
--- a/content/events/src/nsDOMNotifyAudioAvailableEvent.cpp
+++ b/content/events/src/nsDOMNotifyAudioAvailableEvent.cpp
@@ -33,16 +33,18 @@
  * 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 "nsDOMNotifyAudioAvailableEvent.h"
+#include "nsDOMClassInfoID.h" // DOMCI_DATA, NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO
+#include "nsContentUtils.h" // NS_DROP_JS_OBJECTS
 #include "jstypedarray.h"
 
 nsDOMNotifyAudioAvailableEvent::nsDOMNotifyAudioAvailableEvent(nsPresContext* aPresContext,
                                                                nsEvent* aEvent,
                                                                PRUint32 aEventType,
                                                                float* aFrameBuffer,
                                                                PRUint32 aFrameBufferLength,
                                                                float aTime)
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -136,20 +136,16 @@
 #include "mozilla/Services.h"
 #include "mozAutoDocUpdate.h"
 #include "nsHTMLLabelElement.h"
 
 #include "mozilla/Preferences.h"
 
 #ifdef XP_MACOSX
 #import <ApplicationServices/ApplicationServices.h>
-
-#ifdef MOZ_WIDGET_COCOA
-#include "nsCocoaFeatures.h"
-#endif 
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 //#define DEBUG_DOCSHELL_FOCUS
 
 #define NS_USER_INTERACTION_INTERVAL 5000 // ms
@@ -372,30 +368,25 @@ public:
   // Be careful, UpdateTransaction may fire a DOM event, therefore, the target
   // frame might be destroyed in the event handler.
   static PRBool UpdateTransaction(PRInt32 aNumLines,
                                   PRBool aScrollHorizontal);
   static void EndTransaction();
   static void OnEvent(nsEvent* aEvent);
   static void Shutdown();
   static PRUint32 GetTimeoutTime();
-  static PRUint32 GetGestureTimeoutTime();
   static PRInt32 AccelerateWheelDelta(PRInt32 aScrollLines,
                    PRBool aIsHorizontal, PRBool aAllowScrollSpeedOverride,
                    nsIScrollableFrame::ScrollUnit *aScrollQuantity,
                    PRBool aLimitToMaxOnePageScroll = PR_TRUE);
   static PRBool IsAccelerationEnabled();
 
   enum {
     kScrollSeriesTimeout = 80
   };
-#ifdef MOZ_WIDGET_COCOA
-  static PRBool GetGestureTriggered();
-  static void SetGestureTriggered();
-#endif
 protected:
   static nsIntPoint GetScreenPoint(nsGUIEvent* aEvent);
   static void OnFailToScrollTarget();
   static void OnTimeout(nsITimer *aTimer, void *aClosure);
   static void SetTimeout();
   static PRUint32 GetIgnoreMoveDelayTime();
   static PRInt32 GetAccelerationStart();
   static PRInt32 GetAccelerationFactor();
@@ -406,29 +397,23 @@ protected:
                    PRBool aIsHorizontal,
                    nsIScrollableFrame::ScrollUnit *aScrollQuantity);
 
   static nsWeakFrame sTargetFrame;
   static PRUint32    sTime;        // in milliseconds
   static PRUint32    sMouseMoved;  // in milliseconds
   static nsITimer*   sTimer;
   static PRInt32     sScrollSeriesCounter;
-#ifdef MOZ_WIDGET_COCOA
-  static PRUint32    sGestureTriggered; // in milliseconds
-#endif
 };
 
 nsWeakFrame nsMouseWheelTransaction::sTargetFrame(nsnull);
 PRUint32    nsMouseWheelTransaction::sTime        = 0;
 PRUint32    nsMouseWheelTransaction::sMouseMoved  = 0;
 nsITimer*   nsMouseWheelTransaction::sTimer       = nsnull;
 PRInt32     nsMouseWheelTransaction::sScrollSeriesCounter = 0;
-#ifdef MOZ_WIDGET_COCOA
-PRUint32      nsMouseWheelTransaction::sGestureTriggered = 0;
-#endif
 
 static PRBool
 OutOfTime(PRUint32 aBaseTime, PRUint32 aThreshold)
 {
   PRUint32 now = PR_IntervalToMilliseconds(PR_IntervalNow());
   return (now - aBaseTime > aThreshold);
 }
 
@@ -497,39 +482,18 @@ nsMouseWheelTransaction::UpdateTransacti
 
 void
 nsMouseWheelTransaction::EndTransaction()
 {
   if (sTimer)
     sTimer->Cancel();
   sTargetFrame = nsnull;
   sScrollSeriesCounter = 0;
-#ifdef MOZ_WIDGET_COCOA
-  sGestureTriggered = 0;
-#endif
 }
 
-#ifdef MOZ_WIDGET_COCOA
-void
-nsMouseWheelTransaction::SetGestureTriggered() {
-  sGestureTriggered = PR_IntervalToMilliseconds(PR_IntervalNow());
-}
-
-PRBool
-nsMouseWheelTransaction::GetGestureTriggered() {
-  if (sGestureTriggered != 0 &&
-      OutOfTime(sGestureTriggered, GetGestureTimeoutTime())) {
-    // Start accepting new gestures
-    sGestureTriggered = 0;
-  }
-
-  return sGestureTriggered != 0;
-}
-#endif
-
 void
 nsMouseWheelTransaction::OnEvent(nsEvent* aEvent)
 {
   if (!sTargetFrame)
     return;
 
   if (OutOfTime(sTime, GetTimeoutTime())) {
     // Even if the scroll event which is handled after timeout, but onTimeout
@@ -666,22 +630,16 @@ nsIntPoint
 nsMouseWheelTransaction::GetScreenPoint(nsGUIEvent* aEvent)
 {
   NS_ASSERTION(aEvent, "aEvent is null");
   NS_ASSERTION(aEvent->widget, "aEvent-widget is null");
   return aEvent->refPoint + aEvent->widget->WidgetToScreenOffset();
 }
 
 PRUint32
-nsMouseWheelTransaction::GetGestureTimeoutTime()
-{
-  return Preferences::GetUint("mousewheel.transaction.gesturetimeout", 300);
-}
-
-PRUint32
 nsMouseWheelTransaction::GetTimeoutTime()
 {
   return Preferences::GetUint("mousewheel.transaction.timeout", 1500);
 }
 
 PRUint32
 nsMouseWheelTransaction::GetIgnoreMoveDelayTime()
 {
@@ -2834,32 +2792,16 @@ nsEventStateManager::DoScrollText(nsIFra
             passToParent = PR_TRUE;
             nsMouseWheelTransaction::EndTransaction();
           }
         }
       }
     }
   }
 
-#ifdef MOZ_WIDGET_COCOA
-  // On lion scroll will trigger back/forward at the edge of the page
-  if (isHorizontal && passToParent && nsCocoaFeatures::OnLionOrLater()) {
-    if (!nsMouseWheelTransaction::GetGestureTriggered()) {
-      if (numLines > 4 || numLines < -4) {
-        DoScrollHistory(-numLines);
-        nsMouseWheelTransaction::SetGestureTriggered();
-        return NS_OK;
-      }
-    } else {
-      // Extend the gesture in progress
-      nsMouseWheelTransaction::SetGestureTriggered();
-    }
-  }
-#endif
-
   if (!passToParent && frameToScroll) {
     if (aScrollQuantity == nsIScrollableFrame::LINES) {
       // When this is called for querying the scroll target information,
       // we shouldn't limit the scrolling amount to less one page.
       // Otherwise, we shouldn't scroll more one page at once.
       numLines =
         nsMouseWheelTransaction::AccelerateWheelDelta(numLines, isHorizontal,
                                                       aAllowScrollSpeedOverride,
--- a/content/events/src/nsIMEStateManager.cpp
+++ b/content/events/src/nsIMEStateManager.cpp
@@ -408,17 +408,17 @@ nsTextStateManager::nsTextStateManager()
 
 nsresult
 nsTextStateManager::Init(nsIWidget* aWidget,
                          nsPresContext* aPresContext,
                          nsINode* aNode,
                          PRBool aWantUpdates)
 {
   mWidget = aWidget;
-
+  MOZ_ASSERT(mWidget);
   if (!aWantUpdates) {
     mEditableNode = aNode;
     return NS_OK;
   }
 
   nsIPresShell* presShell = aPresContext->PresShell();
 
   // get selection and root content
@@ -496,55 +496,61 @@ NS_IMPL_ISUPPORTS2(nsTextStateManager,
                    nsISelectionListener)
 
 // Helper class, used for selection change notification
 class SelectionChangeEvent : public nsRunnable {
 public:
   SelectionChangeEvent(nsIWidget *widget)
     : mWidget(widget)
   {
+    MOZ_ASSERT(mWidget);
   }
 
   NS_IMETHOD Run() {
-    mWidget->OnIMESelectionChange();
+    if(mWidget) {
+        mWidget->OnIMESelectionChange();
+    }
     return NS_OK;
   }
 
 private:
   nsCOMPtr<nsIWidget> mWidget;
 };
 
 nsresult
 nsTextStateManager::NotifySelectionChanged(nsIDOMDocument* aDoc,
                                            nsISelection* aSel,
                                            PRInt16 aReason)
 {
   PRInt32 count = 0;
   nsresult rv = aSel->GetRangeCount(&count);
   NS_ENSURE_SUCCESS(rv, rv);
-  if (count > 0) {
+  if (count > 0 && mWidget) {
     nsContentUtils::AddScriptRunner(new SelectionChangeEvent(mWidget));
   }
   return NS_OK;
 }
 
 // Helper class, used for text change notification
 class TextChangeEvent : public nsRunnable {
 public:
   TextChangeEvent(nsIWidget *widget,
                   PRUint32 start, PRUint32 oldEnd, PRUint32 newEnd)
     : mWidget(widget)
     , mStart(start)
     , mOldEnd(oldEnd)
     , mNewEnd(newEnd)
   {
+    MOZ_ASSERT(mWidget);
   }
 
   NS_IMETHOD Run() {
-    mWidget->OnIMETextChange(mStart, mOldEnd, mNewEnd);
+    if(mWidget) {
+        mWidget->OnIMETextChange(mStart, mOldEnd, mNewEnd);
+    }
     return NS_OK;
   }
 
 private:
   nsCOMPtr<nsIWidget> mWidget;
   PRUint32 mStart, mOldEnd, mNewEnd;
 };
 
--- a/content/html/content/src/nsFormSubmission.cpp
+++ b/content/html/content/src/nsFormSubmission.cpp
@@ -64,16 +64,17 @@
 #include "nsIMultiplexInputStream.h"
 #include "nsIMIMEInputStream.h"
 #include "nsIMIMEService.h"
 #include "nsIConsoleService.h"
 #include "nsIScriptError.h"
 #include "nsIStringBundle.h"
 #include "nsCExternalHandlerService.h"
 #include "nsIFileStreams.h"
+#include "nsContentUtils.h"
 
 static void
 SendJSWarning(nsIDocument* aDocument,
               const char* aWarningName,
               const PRUnichar** aWarningArgs, PRUint32 aWarningArgsLen)
 {
   nsContentUtils::ReportToConsole(nsContentUtils::eFORMS_PROPERTIES,
                                   aWarningName,
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -97,18 +97,16 @@
 #include "nsIDOMHTMLFormElement.h"
 #include "nsHTMLFormElement.h"
 #include "nsFocusManager.h"
 
 #include "nsMutationEvent.h"
 
 #include "nsContentCID.h"
 
-#include "nsIDOMText.h"
-
 #include "nsDOMStringMap.h"
 
 #include "nsIEditor.h"
 #include "nsIEditorIMESupport.h"
 #include "nsEventDispatcher.h"
 #include "nsLayoutUtils.h"
 #include "nsContentCreatorFunctions.h"
 #include "mozAutoDocUpdate.h"
@@ -760,16 +758,18 @@ nsGenericHTMLElement::SetInnerHTML(const
   mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, PR_TRUE);
 
   // Remove childnodes.
   PRUint32 childCount = GetChildCount();
   for (PRUint32 i = 0; i < childCount; ++i) {
     RemoveChildAt(0, PR_TRUE);
   }
 
+  nsAutoScriptLoaderDisabler sld(doc);
+  
   nsCOMPtr<nsIDOMDocumentFragment> df;
 
   if (doc->IsHTML()) {
     PRInt32 oldChildCount = GetChildCount();
     nsContentUtils::ParseFragmentHTML(aInnerHTML,
                                       this,
                                       Tag(),
                                       GetNameSpaceID(),
@@ -823,27 +823,28 @@ nsGenericHTMLElement::InsertAdjacentHTML
     }
   } else {
     destination = this;
   }
 
   nsIDocument* doc = GetOwnerDoc();
   NS_ENSURE_STATE(doc);
 
+  // Needed when insertAdjacentHTML is used in combination with contenteditable
+  mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, PR_TRUE);
+  nsAutoScriptLoaderDisabler sld(doc);
+  
   // Batch possible DOMSubtreeModified events.
   mozAutoSubtreeModified subtree(doc, nsnull);
 
   // Parse directly into destination if possible
   if (doc->IsHTML() &&
       (position == eBeforeEnd ||
        (position == eAfterEnd && !GetNextSibling()) ||
        (position == eAfterBegin && !GetFirstChild()))) {
-    // Needed when insertAdjacentHTML is used in combination with contenteditable
-    mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, PR_TRUE);
-
     PRInt32 oldChildCount = destination->GetChildCount();
     PRInt32 contextNs = destination->GetNameSpaceID();
     nsIAtom* contextLocal = destination->Tag();
     if (contextLocal == nsGkAtoms::html && contextNs == kNameSpaceID_XHTML) {
       // For compat with IE6 through IE9. Willful violation of HTML5 as of
       // 2011-04-06. CreateContextualFragment does the same already.
       // Spec bug: http://www.w3.org/Bugs/Public/show_bug.cgi?id=12434
       contextLocal = nsGkAtoms::body;
@@ -864,16 +865,21 @@ nsGenericHTMLElement::InsertAdjacentHTML
   nsCOMPtr<nsIDOMDocumentFragment> df;
   nsresult rv = nsContentUtils::CreateContextualFragment(destination,
                                                          aText,
                                                          PR_TRUE,
                                                          getter_AddRefs(df));
   nsCOMPtr<nsINode> fragment = do_QueryInterface(df);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  // Suppress assertion about node removal mutation events that can't have
+  // listeners anyway, because no one has had the chance to register mutation
+  // listeners on the fragment that comes from the parser.
+  nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
+
   switch (position) {
     case eBeforeBegin:
       destination->InsertBefore(fragment, this, &rv);
       break;
     case eAfterBegin:
       static_cast<nsINode*>(this)->InsertBefore(fragment, GetFirstChild(), &rv);
       break;
     case eBeforeEnd:
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -1099,16 +1099,35 @@ protected:
   }                                                                  \
   NS_IMETHODIMP                                                      \
   _class::Set##_method(const nsAString& aValue)                      \
   {                                                                  \
     return SetAttrHelper(nsGkAtoms::_atom, aValue);                  \
   }
 
 /**
+ * This macro is similar to NS_IMPL_STRING_ATTR except that the getter method
+ * falls back to an alternative method if the content attribute isn't set.
+ */
+#define NS_IMPL_STRING_ATTR_WITH_FALLBACK(_class, _method, _atom, _fallback) \
+  NS_IMETHODIMP                                                              \
+  _class::Get##_method(nsAString& aValue)                                    \
+  {                                                                          \
+    if (!GetAttr(kNameSpaceID_None, nsGkAtoms::_atom, aValue)) {             \
+      _fallback(aValue);                                                     \
+    }                                                                        \
+    return NS_OK;                                                            \
+  }                                                                          \
+  NS_IMETHODIMP                                                              \
+  _class::Set##_method(const nsAString& aValue)                              \
+  {                                                                          \
+    return SetAttrHelper(nsGkAtoms::_atom, aValue);                          \
+  }
+
+/**
  * A macro to implement the getter and setter for a given boolean
  * valued content property. The method uses the generic GetAttr and
  * SetAttr methods.
  */
 #define NS_IMPL_BOOL_ATTR(_class, _method, _atom)                     \
   NS_IMETHODIMP                                                       \
   _class::Get##_method(PRBool* aValue)                                \
   {                                                                   \
--- a/content/html/content/src/nsHTMLAnchorElement.cpp
+++ b/content/html/content/src/nsHTMLAnchorElement.cpp
@@ -32,30 +32,31 @@
  * 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 "nsGenericHTMLElement.h"
+#include "nsIDOMHTMLAnchorElement.h"
+#include "nsILink.h"
+#include "Link.h"
+
 #include "nsCOMPtr.h"
+#include "nsContentUtils.h"
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.h"
-#include "nsIDOMHTMLAnchorElement.h"
-#include "nsGenericHTMLElement.h"
-#include "nsILink.h"
 #include "nsGkAtoms.h"
 #include "nsIPresShell.h"
 #include "nsIDocument.h"
 #include "nsPresContext.h"
-
 #include "nsHTMLDNSPrefetch.h"
 
-#include "Link.h"
 using namespace mozilla::dom;
 
 class nsHTMLAnchorElement : public nsGenericHTMLElement,
                             public nsIDOMHTMLAnchorElement,
                             public nsILink,
                             public Link
 {
 public:
--- a/content/html/content/src/nsHTMLAudioElement.cpp
+++ b/content/html/content/src/nsHTMLAudioElement.cpp
@@ -60,16 +60,17 @@
 #include "jscntxt.h"
 #include "jstypedarray.h"
 #include "nsJSUtils.h"
 
 #include "nsITimer.h"
 
 #include "nsEventDispatcher.h"
 #include "nsIDOMProgressEvent.h"
+#include "nsContentUtils.h"
 
 using namespace mozilla::dom;
 
 nsGenericHTMLElement*
 NS_NewHTMLAudioElement(already_AddRefed<nsINodeInfo> aNodeInfo,
                        FromParser aFromParser)
 {
   /*
--- a/content/html/content/src/nsHTMLCanvasElement.cpp
+++ b/content/html/content/src/nsHTMLCanvasElement.cpp
@@ -41,16 +41,17 @@
 #include "nsNetUtil.h"
 #include "prmem.h"
 #include "nsDOMFile.h"
 #include "CheckedInt.h"
 
 #include "nsIScriptSecurityManager.h"
 #include "nsIXPConnect.h"
 #include "jsapi.h"
+#include "nsContentUtils.h"
 #include "nsJSUtils.h"
 #include "nsMathUtils.h"
 #include "mozilla/Preferences.h"
 
 #include "nsFrameManager.h"
 #include "nsDisplayList.h"
 #include "ImageLayers.h"
 #include "BasicLayers.h"
--- a/content/html/content/src/nsHTMLElement.cpp
+++ b/content/html/content/src/nsHTMLElement.cpp
@@ -33,16 +33,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsGenericHTMLElement.h"
 #include "nsIDOMHTMLElement.h"
 
+#include "nsContentUtils.h"
+
 using namespace mozilla::dom;
 
 class nsHTMLElement : public nsGenericHTMLElement,
                       public nsIDOMHTMLElement
 {
 public:
   nsHTMLElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLElement();
--- a/content/html/content/src/nsHTMLFieldSetElement.h
+++ b/content/html/content/src/nsHTMLFieldSetElement.h
@@ -36,17 +36,16 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsHTMLFieldSetElement_h___
 #define nsHTMLFieldSetElement_h___
 
 #include "nsGenericHTMLElement.h"
 #include "nsIDOMHTMLFieldSetElement.h"
 #include "nsIConstraintValidation.h"
-#include "nsTPtrArray.h"
 
 
 class nsHTMLFieldSetElement : public nsGenericHTMLFormElement,
                               public nsIDOMHTMLFieldSetElement,
                               public nsIConstraintValidation
 {
 public:
   using nsIConstraintValidation::GetValidationMessage;
@@ -108,15 +107,15 @@ private:
   // This function is used to generate the nsContentList (listed form elements).
   static PRBool MatchListedElements(nsIContent* aContent, PRInt32 aNamespaceID,
                                     nsIAtom* aAtom, void* aData);
 
   // listed form controls elements.
   nsRefPtr<nsContentList> mElements;
 
   // List of elements which have this fieldset as first fieldset ancestor.
-  nsTPtrArray<nsGenericHTMLFormElement> mDependentElements;
+  nsTArray<nsGenericHTMLFormElement*> mDependentElements;
 
   nsIContent* mFirstLegend;
 };
 
 #endif /* nsHTMLFieldSetElement_h___ */
 
--- a/content/html/content/src/nsHTMLImageElement.cpp
+++ b/content/html/content/src/nsHTMLImageElement.cpp
@@ -223,25 +223,25 @@ NS_IMPL_INT_ATTR(nsHTMLImageElement, Hsp
 NS_IMPL_BOOL_ATTR(nsHTMLImageElement, IsMap, ismap)
 NS_IMPL_URI_ATTR(nsHTMLImageElement, LongDesc, longdesc)
 NS_IMPL_STRING_ATTR(nsHTMLImageElement, Lowsrc, lowsrc)
 NS_IMPL_URI_ATTR(nsHTMLImageElement, Src, src)
 NS_IMPL_STRING_ATTR(nsHTMLImageElement, UseMap, usemap)
 NS_IMPL_INT_ATTR(nsHTMLImageElement, Vspace, vspace)
 
 static const nsAttrValue::EnumTable kCrossOriginTable[] = {
-  { "",                nsImageLoadingContent::CORS_NONE },
+  // Order matters here; see ParseAttribute
   { "anonymous",       nsImageLoadingContent::CORS_ANONYMOUS },
   { "use-credentials", nsImageLoadingContent::CORS_USE_CREDENTIALS },
   { 0 }
 };
-// Default crossOrigin mode is CORS_NONE.
-static const nsAttrValue::EnumTable* kCrossOriginDefault = &kCrossOriginTable[0];
 
-NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLImageElement, CrossOrigin, crossorigin, kCrossOriginDefault->tag)
+// crossorigin is not "limited to only known values" per spec, so it's
+// just a string attr purposes of the DOM crossOrigin property.
+NS_IMPL_STRING_ATTR(nsHTMLImageElement, CrossOrigin, crossorigin)
 
 NS_IMETHODIMP
 nsHTMLImageElement::GetDraggable(PRBool* aDraggable)
 {
   // images may be dragged unless the draggable attribute is false
   *aDraggable = !AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable,
                              nsGkAtoms::_false, eIgnoreCase);
   return NS_OK;
@@ -347,17 +347,20 @@ nsHTMLImageElement::ParseAttribute(PRInt
                                    const nsAString& aValue,
                                    nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::align) {
       return ParseAlignValue(aValue, aResult);
     }
     if (aAttribute == nsGkAtoms::crossorigin) {
-      return aResult.ParseEnumValue(aValue, kCrossOriginTable, PR_FALSE);
+      return aResult.ParseEnumValue(aValue, kCrossOriginTable, PR_FALSE,
+                                    // default value is anonymous if aValue is
+                                    // not a value we understand
+                                    &kCrossOriginTable[0]);
     }
     if (ParseImageAttribute(aAttribute, aValue, aResult)) {
       return PR_TRUE;
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
@@ -651,14 +654,16 @@ nsHTMLImageElement::CopyInnerTo(nsGeneri
 }
 
 nsImageLoadingContent::CORSMode
 nsHTMLImageElement::GetCORSMode()
 {
   nsImageLoadingContent::CORSMode ret = nsImageLoadingContent::CORS_NONE;
 
   const nsAttrValue* value = GetParsedAttr(nsGkAtoms::crossorigin);
-  if (value && value->Type() == nsAttrValue::eEnum) {
+  if (value) {
+    NS_ASSERTION(value->Type() == nsAttrValue::eEnum,
+                 "Why is this not an enum value?");
     ret = (nsImageLoadingContent::CORSMode) value->GetEnumValue();
   }
 
   return ret;
 }
--- a/content/html/content/src/nsHTMLInputElement.cpp
+++ b/content/html/content/src/nsHTMLInputElement.cpp
@@ -115,22 +115,16 @@
 #include "nsImageLoadingContent.h"
 
 #include "mozAutoDocUpdate.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsContentUtils.h"
 #include "nsRadioVisitor.h"
 
-#include "nsTextEditRules.h"
-
-// JS headers are needed for the pattern attribute.
-#include "jsapi.h"
-#include "jscntxt.h"
-
 using namespace mozilla::dom;
 
 // XXX align=left, hspace, vspace, border? other nav4 attrs
 
 static NS_DEFINE_CID(kXULControllersCID,  NS_XULCONTROLLERS_CID);
 static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
 
 // First bits are needed for the control type.
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -1129,16 +1129,29 @@ NS_IMETHODIMP nsHTMLMediaElement::SetCur
 
 /* readonly attribute double duration; */
 NS_IMETHODIMP nsHTMLMediaElement::GetDuration(double *aDuration)
 {
   *aDuration = mDecoder ? mDecoder->GetDuration() : std::numeric_limits<double>::quiet_NaN();
   return NS_OK;
 }
 
+/* readonly attribute nsIDOMHTMLTimeRanges seekable; */
+NS_IMETHODIMP nsHTMLMediaElement::GetSeekable(nsIDOMTimeRanges** aSeekable)
+{
+  nsTimeRanges* ranges = new nsTimeRanges();
+  NS_ADDREF(*aSeekable = ranges);
+
+  if (mDecoder && mReadyState > nsIDOMHTMLMediaElement::HAVE_NOTHING) {
+    mDecoder->GetSeekable(ranges);
+  }
+  return NS_OK;
+}
+
+
 /* readonly attribute boolean paused; */
 NS_IMETHODIMP nsHTMLMediaElement::GetPaused(PRBool *aPaused)
 {
   *aPaused = mPaused;
 
   return NS_OK;
 }
 
@@ -1820,17 +1833,17 @@ nsresult nsHTMLMediaElement::InitializeD
 
   if (!decoder->Init(this)) {
     return NS_ERROR_FAILURE;
   }
 
   double duration = aOriginal->GetDuration();
   if (duration >= 0) {
     decoder->SetDuration(duration);
-    decoder->SetSeekable(aOriginal->GetSeekable());
+    decoder->SetSeekable(aOriginal->IsSeekable());
   }
 
   nsMediaStream* stream = originalStream->CloneData(decoder);
   if (!stream) {
     return NS_ERROR_FAILURE;
   }
 
   mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
--- a/content/html/content/src/nsHTMLMenuElement.cpp
+++ b/content/html/content/src/nsHTMLMenuElement.cpp
@@ -29,23 +29,25 @@
  * 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 "nsHTMLMenuElement.h"
+
 #include "nsIDOMNSHTMLElement.h"
 #include "nsIDOMHTMLMenuItemElement.h"
 #include "nsXULContextMenuBuilder.h"
 #include "nsGUIEvent.h"
 #include "nsEventDispatcher.h"
 #include "nsHTMLMenuItemElement.h"
-#include "nsHTMLMenuElement.h"
+#include "nsContentUtils.h"
 
 enum MenuType
 {
   MENU_TYPE_CONTEXT = 1,
   MENU_TYPE_TOOLBAR,
   MENU_TYPE_LIST
 };
 
--- a/content/html/content/src/nsHTMLMenuItemElement.cpp
+++ b/content/html/content/src/nsHTMLMenuItemElement.cpp
@@ -32,16 +32,17 @@
  * 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 "nsGUIEvent.h"
 #include "nsEventDispatcher.h"
 #include "nsHTMLMenuItemElement.h"
+#include "nsContentUtils.h"
 
 using namespace mozilla::dom;
 
 // First bits are needed for the menuitem type.
 #define NS_CHECKED_IS_TOGGLED (1 << 2)
 #define NS_ORIGINAL_CHECKED_VALUE (1 << 3)
 #define NS_MENUITEM_TYPE(bits) ((bits) & ~( \
   NS_CHECKED_IS_TOGGLED | NS_ORIGINAL_CHECKED_VALUE))
@@ -213,47 +214,43 @@ NS_INTERFACE_TABLE_HEAD(nsHTMLMenuItemEl
 NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLMenuItemElement)
 
 //NS_IMPL_ELEMENT_CLONE(nsHTMLMenuItemElement)
 nsresult
 nsHTMLMenuItemElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
 {
   *aResult = nsnull;
   nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
-  nsHTMLMenuItemElement *it = new nsHTMLMenuItemElement(ni.forget(),
-                                                        NOT_FROM_PARSER);
-  if (!it) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
-  nsCOMPtr<nsINode> kungFuDeathGrip = it;
+  nsRefPtr<nsHTMLMenuItemElement> it =
+    new nsHTMLMenuItemElement(ni.forget(), NOT_FROM_PARSER);
   nsresult rv = CopyInnerTo(it);
   if (NS_SUCCEEDED(rv)) {
     switch (mType) {
       case CMD_TYPE_CHECKBOX:
       case CMD_TYPE_RADIO:
         if (mCheckedDirty) {
           // We no longer have our original checked state.  Set our
           // checked state on the clone.
           it->mCheckedDirty = true;
           it->mChecked = mChecked;
         }
         break;
     }
 
-    kungFuDeathGrip.swap(*aResult);
+    it.forget(aResult);
   }
 
   return rv;
 }
 
 
 NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLMenuItemElement, Type, type,
                                 kMenuItemDefaultType->tag)
-NS_IMPL_STRING_ATTR(nsHTMLMenuItemElement, Label, label)
+// GetText returns a whitespace compressed .textContent value.
+NS_IMPL_STRING_ATTR_WITH_FALLBACK(nsHTMLMenuItemElement, Label, label, GetText)
 NS_IMPL_URI_ATTR(nsHTMLMenuItemElement, Icon, icon)
 NS_IMPL_BOOL_ATTR(nsHTMLMenuItemElement, Disabled, disabled)
 NS_IMPL_BOOL_ATTR(nsHTMLMenuItemElement, DefaultChecked, checked)
 //NS_IMPL_BOOL_ATTR(nsHTMLMenuItemElement, Checked, checked)
 NS_IMPL_STRING_ATTR(nsHTMLMenuItemElement, Radiogroup, radiogroup)
 
 NS_IMETHODIMP
 nsHTMLMenuItemElement::GetChecked(PRBool* aChecked)
@@ -403,16 +400,26 @@ nsHTMLMenuItemElement::DoneCreatingEleme
   mParserCreating = false;
 
   if (mShouldInitChecked) {
     InitChecked();
     mShouldInitChecked = false;
   }
 }
 
+void
+nsHTMLMenuItemElement::GetText(nsAString& aText)
+{
+  nsAutoString text;
+  nsContentUtils::GetNodeTextContent(this, PR_FALSE, text);
+
+  text.CompressWhitespace(PR_TRUE, PR_TRUE);
+  aText = text;
+}
+
 nsresult
 nsHTMLMenuItemElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                                     const nsAString* aValue, PRBool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None) {
     if ((aName == nsGkAtoms::radiogroup || aName == nsGkAtoms::type) &&
         mType == CMD_TYPE_RADIO &&
         !mParserCreating) {
--- a/content/html/content/src/nsHTMLMenuItemElement.h
+++ b/content/html/content/src/nsHTMLMenuItemElement.h
@@ -95,16 +95,18 @@ public:
   PRUint8 GetType() const { return mType; }
 
   /**
    * Syntax sugar to make it easier to check for checked and checked dirty
    */
   PRBool IsChecked() const { return mChecked; }
   PRBool IsCheckedDirty() const { return mCheckedDirty; }
 
+  void GetText(nsAString& aText);
+
 protected:
   virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
                                 const nsAString* aValue, PRBool aNotify);
 
   void WalkRadioGroup(Visitor* aVisitor);
 
   nsHTMLMenuItemElement* GetSelectedRadio();
 
--- a/content/html/content/src/nsHTMLMetaElement.cpp
+++ b/content/html/content/src/nsHTMLMetaElement.cpp
@@ -35,16 +35,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 #include "nsIDOMHTMLMetaElement.h"
 #include "nsIDOMEventTarget.h"
 #include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsPLDOMEvent.h"
+#include "nsContentUtils.h"
 
 
 class nsHTMLMetaElement : public nsGenericHTMLElement,
                           public nsIDOMHTMLMetaElement
 {
 public:
   nsHTMLMetaElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLMetaElement();
--- a/content/html/content/src/nsHTMLOptionElement.cpp
+++ b/content/html/content/src/nsHTMLOptionElement.cpp
@@ -42,17 +42,16 @@
 #include "nsHTMLSelectElement.h"
 #include "nsIDOMHTMLOptGroupElement.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsIDOMEventTarget.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsIFormControl.h"
 #include "nsIForm.h"
-#include "nsIDOMText.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMHTMLCollection.h"
 #include "nsISelectControlFrame.h"
 
 // Notify/query select frame for selected state
 #include "nsIFormControlFrame.h"
 #include "nsIDocument.h"
 #include "nsIFrame.h"
@@ -63,36 +62,16 @@
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "nsContentCreatorFunctions.h"
 #include "mozAutoDocUpdate.h"
 
 using namespace mozilla::dom;
 
 /**
- * This macro is similar to NS_IMPL_STRING_ATTR except that the getter method
- * falls back to GetText if the content attribute isn't set. GetText returns a
- * whitespace compressed .textContent value.
- */
-#define NS_IMPL_STRING_ATTR_WITH_TEXTCONTENT(_class, _method, _atom) \
-  NS_IMETHODIMP                                                      \
-  _class::Get##_method(nsAString& aValue)                            \
-  {                                                                  \
-    if (!GetAttr(kNameSpaceID_None, nsGkAtoms::_atom, aValue)) {     \
-      GetText(aValue);                                               \
-    }                                                                \
-    return NS_OK;                                                    \
-  }                                                                  \
-  NS_IMETHODIMP                                                      \
-  _class::Set##_method(const nsAString& aValue)                      \
-  {                                                                  \
-    return SetAttrHelper(nsGkAtoms::_atom, aValue);                  \
-  }
-
-/**
  * Implementation of &lt;option&gt;
  */
 
 nsGenericHTMLElement*
 NS_NewHTMLOptionElement(already_AddRefed<nsINodeInfo> aNodeInfo,
                         FromParser aFromParser)
 {
   /*
@@ -204,18 +183,19 @@ nsHTMLOptionElement::SetSelected(PRBool 
     SetSelectedInternal(aValue, PR_TRUE);
     return NS_OK;
   }
 
   return NS_OK;
 }
 
 NS_IMPL_BOOL_ATTR(nsHTMLOptionElement, DefaultSelected, selected)
-NS_IMPL_STRING_ATTR_WITH_TEXTCONTENT(nsHTMLOptionElement, Label, label)
-NS_IMPL_STRING_ATTR_WITH_TEXTCONTENT(nsHTMLOptionElement, Value, value)
+// GetText returns a whitespace compressed .textContent value.
+NS_IMPL_STRING_ATTR_WITH_FALLBACK(nsHTMLOptionElement, Label, label, GetText)
+NS_IMPL_STRING_ATTR_WITH_FALLBACK(nsHTMLOptionElement, Value, value, GetText)
 NS_IMPL_BOOL_ATTR(nsHTMLOptionElement, Disabled, disabled)
 
 NS_IMETHODIMP 
 nsHTMLOptionElement::GetIndex(PRInt32* aIndex)
 {
   NS_ENSURE_ARG_POINTER(aIndex);
 
   *aIndex = -1; // -1 indicates the index was not found
--- a/content/html/content/src/nsHTMLScriptElement.cpp
+++ b/content/html/content/src/nsHTMLScriptElement.cpp
@@ -39,17 +39,17 @@
 #include "nsIDOMEventTarget.h"
 #include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsIDocument.h"
 #include "nsScriptElement.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
-
+#include "nsContentUtils.h"
 #include "nsUnicharUtils.h"  // for nsCaseInsensitiveStringComparator()
 #include "jsapi.h"
 #include "nsIScriptContext.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIXPConnect.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIDOMDocument.h"
 #include "nsContentErrors.h"
--- a/content/html/content/src/nsHTMLSelectElement.h
+++ b/content/html/content/src/nsHTMLSelectElement.h
@@ -44,17 +44,16 @@
 #include "nsCOMArray.h"
 #include "nsGenericHTMLElement.h"
 #include "nsIDOMHTMLSelectElement.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsIDOMHTMLOptionElement.h"
 #include "nsIDOMHTMLOptionsCollection.h"
 #include "nsIDOMNSHTMLOptionCollectn.h"
 #include "nsISelectControlFrame.h"
-#include "nsContentUtils.h"
 #include "nsIHTMLCollection.h"
 #include "nsIConstraintValidation.h"
 
 // PresState
 #include "nsXPCOM.h"
 #include "nsPresState.h"
 #include "nsIComponentManager.h"
 #include "nsCheapSets.h"
--- a/content/html/content/src/nsHTMLSharedElement.cpp
+++ b/content/html/content/src/nsHTMLSharedElement.cpp
@@ -37,23 +37,22 @@
 
 #include "nsIDOMHTMLParamElement.h"
 #include "nsIDOMHTMLBaseElement.h"
 #include "nsIDOMHTMLDirectoryElement.h"
 #include "nsIDOMHTMLQuoteElement.h"
 #include "nsIDOMHTMLHeadElement.h"
 #include "nsIDOMHTMLHtmlElement.h"
 #include "nsGenericHTMLElement.h"
+
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsRuleData.h"
 #include "nsMappedAttributes.h"
-#include "nsNetUtil.h"
-#include "nsHTMLFormElement.h"
-#include "nsHtml5Module.h"
+#include "nsContentUtils.h"
 
 
 // XXX nav4 has type= start= (same as OL/UL)
 extern nsAttrValue::EnumTable kListTypeTable[];
 
 class nsHTMLSharedElement : public nsGenericHTMLElement,
                             public nsIDOMHTMLParamElement,
                             public nsIDOMHTMLBaseElement,
--- a/content/html/content/src/nsHTMLStyleElement.cpp
+++ b/content/html/content/src/nsHTMLStyleElement.cpp
@@ -44,17 +44,17 @@
 #include "nsIDOMStyleSheet.h"
 #include "nsIStyleSheet.h"
 #include "nsStyleLinkElement.h"
 #include "nsNetUtil.h"
 #include "nsIDocument.h"
 #include "nsUnicharUtils.h"
 #include "nsParserUtils.h"
 #include "nsThreadUtils.h"
-
+#include "nsContentUtils.h"
 
 class nsHTMLStyleElement : public nsGenericHTMLElement,
                            public nsIDOMHTMLStyleElement,
                            public nsStyleLinkElement,
                            public nsStubMutationObserver
 {
 public:
   nsHTMLStyleElement(already_AddRefed<nsINodeInfo> aNodeInfo);
--- a/content/html/content/src/nsHTMLTableElement.cpp
+++ b/content/html/content/src/nsHTMLTableElement.cpp
@@ -45,17 +45,17 @@
 #include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsPresContext.h"
 #include "nsHTMLParts.h"
 #include "nsRuleData.h"
 #include "nsStyleContext.h"
 #include "nsIDocument.h"
-
+#include "nsContentUtils.h"
 /* for collections */
 #include "nsIDOMElement.h"
 #include "nsGenericHTMLElement.h"
 #include "nsIHTMLCollection.h"
 /* end for collections */
 
 class TableRowsCollection;
 
--- a/content/html/content/src/nsHTMLTableRowElement.cpp
+++ b/content/html/content/src/nsHTMLTableRowElement.cpp
@@ -42,16 +42,17 @@
 #include "nsDOMError.h"
 #include "nsMappedAttributes.h"
 #include "nsGenericHTMLElement.h"
 #include "nsContentList.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsHTMLParts.h"
 #include "nsRuleData.h"
+#include "nsContentUtils.h"
 
 class nsHTMLTableRowElement : public nsGenericHTMLElement,
                               public nsIDOMHTMLTableRowElement
 {
 public:
   nsHTMLTableRowElement(already_AddRefed<nsINodeInfo> aNodeInfo);
 
   // nsISupports
--- a/content/html/content/src/nsHTMLTableSectionElement.cpp
+++ b/content/html/content/src/nsHTMLTableSectionElement.cpp
@@ -40,16 +40,17 @@
 #include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
 #include "nsHTMLParts.h"
 #include "nsStyleConsts.h"
 #include "nsContentList.h"
 #include "nsRuleData.h"
 #include "nsDOMError.h"
 #include "nsIDocument.h"
+#include "nsContentUtils.h"
 
 // you will see the phrases "rowgroup" and "section" used interchangably
 
 class nsHTMLTableSectionElement : public nsGenericHTMLElement,
                                   public nsIDOMHTMLTableSectionElement
 {
 public:
   nsHTMLTableSectionElement(already_AddRefed<nsINodeInfo> aNodeInfo);
--- a/content/html/content/src/nsHTMLTextAreaElement.cpp
+++ b/content/html/content/src/nsHTMLTextAreaElement.cpp
@@ -62,17 +62,16 @@
 #include "nsLinebreakConverter.h"
 #include "nsIDocument.h"
 #include "nsIFrame.h"
 #include "nsIFormControlFrame.h"
 #include "nsIPrivateDOMEvent.h"
 #include "nsGUIEvent.h"
 #include "nsLinebreakConverter.h"
 #include "nsPresState.h"
-#include "nsIDOMText.h"
 #include "nsReadableUtils.h"
 #include "nsEventDispatcher.h"
 #include "nsLayoutUtils.h"
 #include "nsLayoutErrors.h"
 #include "nsStubMutationObserver.h"
 #include "nsDOMError.h"
 #include "mozAutoDocUpdate.h"
 #include "nsISupportsPrimitives.h"
--- a/content/html/content/src/nsHTMLTitleElement.cpp
+++ b/content/html/content/src/nsHTMLTitleElement.cpp
@@ -34,17 +34,16 @@
  * 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 "nsIDOMHTMLTitleElement.h"
 #include "nsIDOMEventTarget.h"
 #include "nsGenericHTMLElement.h"
 #include "nsStyleConsts.h"
-#include "nsIDOMText.h"
 #include "nsIDocument.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsContentUtils.h"
 
 class nsHTMLTitleElement : public nsGenericHTMLElement,
                            public nsIDOMHTMLTitleElement,
                            public nsStubMutationObserver
 {
--- a/content/html/content/src/nsIConstraintValidation.cpp
+++ b/content/html/content/src/nsIConstraintValidation.cpp
@@ -38,17 +38,17 @@
 #include "nsIConstraintValidation.h"
 
 #include "nsAString.h"
 #include "nsGenericHTMLElement.h"
 #include "nsHTMLFormElement.h"
 #include "nsDOMValidityState.h"
 #include "nsIFormControl.h"
 #include "nsHTMLFormElement.h"
-
+#include "nsContentUtils.h"
 
 const PRUint16 nsIConstraintValidation::sContentSpecifiedMaxLengthMessage = 256;
 
 nsIConstraintValidation::nsIConstraintValidation()
   : mValidityBitField(0)
   , mValidity(nsnull)
   // By default, all elements are subjects to constraint validation.
   , mBarredFromConstraintValidation(PR_FALSE)
--- a/content/html/content/src/nsTextEditorState.cpp
+++ b/content/html/content/src/nsTextEditorState.cpp
@@ -61,16 +61,17 @@
 #include "nsINativeKeyBindings.h"
 #include "nsIDocumentEncoder.h"
 #include "nsISelectionPrivate.h"
 #include "nsPIDOMWindow.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIEditor.h"
 #include "nsTextEditRules.h"
 #include "nsEventListenerManager.h"
+#include "nsContentUtils.h"
 
 using namespace mozilla::dom;
 
 static NS_DEFINE_CID(kTextEditorCID, NS_TEXTEDITOR_CID);
 
 static nsINativeKeyBindings *sNativeInputBindings = nsnull;
 static nsINativeKeyBindings *sNativeTextAreaBindings = nsnull;
 
--- a/content/html/content/test/Makefile.in
+++ b/content/html/content/test/Makefile.in
@@ -276,12 +276,14 @@ include $(topsrcdir)/config/rules.mk
 		test_bug664299.html \
 		test_bug666200.html \
 		test_bug666666.html \
 		test_bug674558.html \
 		test_bug583533.html \
 		test_restore_from_parser_fragment.html \
 		test_bug617528.html \
 		test_checked.html \
+		test_bug677658.html \
+		test_bug677463.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
--- a/content/html/content/test/test_bug664299.html
+++ b/content/html/content/test/test_bug664299.html
@@ -13,18 +13,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=664299">Mozilla Bug 664299</a>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 <script type="application/javascript">
 /** Test to ensure we reflect <img crossorigin> correctly **/
-reflectLimitedEnumerated({
+reflectString({
   element: new Image(),
   attribute: "crossOrigin",
-  validValues: [ "", "anonymous", "use-credentials" ],
-  invalidValues: [ "foobar" ],
-  defaultValue: "" });
+  otherValues: [ "", "anonymous", "ANONYMOUS", "  aNOnYmous    ",
+                 "use-credentials", "USE-CREDENTIALS", "   UsE-CreDEntIALS      ",
+                 "foobar", "FOOBAR", "  fOoBaR  " ]});
 </script>
 </pre>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/test_bug677463.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=677463
+-->
+<head>
+  <title>Test for Bug 677463</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677463">Mozilla Bug 677463</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 677463 **/
+
+var o = document.createElement("option");
+var m = document.createElement("menuitem");
+is(o.label, m.label, "Should have same labels");
+o.textContent = "   ";
+is(o.label, m.label, "Should have same labels");
+m.textContent = " ";
+is(o.label, m.label, "Should have same labels");
+o.textContent = " foo";
+isnot(o.label, m.label, "Shouldn't have same labels");
+m.textContent = "foo ";
+is(o.label, m.label, "Should have same labels");
+m.label = "bar";
+isnot(o.label, m.label, "Shouldn't have same labels");
+o.label = "bar";
+is(o.label, m.label, "Should have same labels");
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/test_bug677658.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=677658
+-->
+<head>
+  <title>Test for Bug 677658</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="test()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677658">Mozilla Bug 677658</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript"><!--
+
+/** Test for Bug 677658 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function testDone() {
+  ok(window.testPassed, "Script shouldn't have run!");
+  SimpleTest.finish();
+}
+
+function test() {
+  window.testPassed = true;
+  document.getElementById("testtarget").innerHTML =
+    "<script async src='data:text/plain, window.testPassed = false;'></script>";
+  SimpleTest.executeSoon(testDone);
+}
+
+// -->
+</script>
+</pre>
+<div id="testtarget"></div>
+</body>
+</html>
--- a/content/html/document/src/ImageDocument.cpp
+++ b/content/html/document/src/ImageDocument.cpp
@@ -68,16 +68,17 @@
 #include "nsContentErrors.h"
 #include "nsURILoader.h"
 #include "nsIDocShell.h"
 #include "nsIContentViewer.h"
 #include "nsIMarkupDocumentViewer.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsThreadUtils.h"
 #include "nsIScrollableFrame.h"
+#include "nsContentUtils.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/Preferences.h"
 
 #define AUTOMATIC_IMAGE_RESIZING_PREF "browser.enable_automatic_image_resizing"
 #define CLICK_IMAGE_RESIZING_PREF "browser.enable_click_image_resizing"
 //XXX A hack needed for Firefox's site specific zoom.
 #define SITE_SPECIFIC_ZOOM "browser.zoom.siteSpecific"
 
@@ -644,36 +645,42 @@ ImageDocument::CreateSyntheticDocument()
   NS_ENSURE_SUCCESS(rv, rv);
 
   // We must declare the image as a block element. If we stay as
   // an inline element, our parent LineBox will be inline too and
   // ignore the available height during reflow.
   // This is bad during printing, it means tall image frames won't know
   // the size of the paper and cannot break into continuations along
   // multiple pages.
-  Element* body = GetBodyElement();
-  if (!body) {
-    NS_WARNING("no body on image document!");
+  Element* head = GetHeadElement();
+  if (!head) {
+    NS_WARNING("no head on image document!");
     return NS_ERROR_FAIL