merge m-c to fx-team
authorRob Campbell <rcampbell@mozilla.com>
Thu, 11 Aug 2011 11:10:32 -0300
changeset 74305 f803e527662ba9b22c45b767c6bd7e64ec00c70c
parent 74304 c14bbf65c00efb0e7e68dde2525ca8f6fbb1f6d6 (current diff)
parent 74246 10915aa173656cfb998cb28e04df37938b81b498 (diff)
child 74306 4d97114b4e602d5049a2f639a3087c88648be84e
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
milestone8.0a1
merge m-c to fx-team
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
testing/tps/config.json
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,22 +33,23 @@
  * 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 "nsIEditor.h"
@@ -610,72 +611,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,28 +34,28 @@
  * 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 "nsIDOMHTMLCollection.h"
 #include "nsIDOMHTMLTableCellElement.h"
 #include "nsIDOMHTMLTableElement.h"
 #include "nsIDOMHTMLTableRowElement.h"
 #include "nsIDOMHTMLTableSectionElem.h"
 #include "nsIDocument.h"
@@ -500,28 +500,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 +1513,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/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/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/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/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/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/nsAttrAndChildArray.cpp
+++ b/content/base/src/nsAttrAndChildArray.cpp
@@ -855,13 +855,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()
@@ -1444,8 +1443,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;
 }
 }
 
@@ -306,16 +305,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
   };
@@ -372,17 +373,17 @@ private:
   // 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;
 
-  static nsTPtrArray<const EnumTable, nsTArrayDefaultAllocator>* sEnumTableArray;
+  static nsTArray<const EnumTable*, nsTArrayDefaultAllocator>* sEnumTableArray;
 
   PtrBits mBits;
 };
 
 /**
  * Implementation of inline methods
  */
 
--- 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/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
@@ -518,17 +518,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/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -137,17 +137,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 +750,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();
--- 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/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/nsTreeSanitizer.cpp
+++ b/content/base/src/nsTreeSanitizer.cpp
@@ -1190,17 +1190,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/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/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/events/src/nsContentEventHandler.cpp
+++ b/content/events/src/nsContentEventHandler.cpp
@@ -54,17 +54,16 @@
 #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 +1065,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 +1089,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/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/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -760,16 +760,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 +825,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 +867,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/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/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/nsHTMLMenuItemElement.cpp
+++ b/content/html/content/src/nsHTMLMenuItemElement.cpp
@@ -243,17 +243,18 @@ nsHTMLMenuItemElement::Clone(nsINodeInfo
   }
 
   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 +404,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/nsHTMLOptionElement.cpp
+++ b/content/html/content/src/nsHTMLOptionElement.cpp
@@ -63,36 +63,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 +184,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/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)
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
@@ -644,36 +644,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_FAILURE;
   }
 
   nsCOMPtr<nsINodeInfo> nodeInfo;
   nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::style, nsnull,
                                            kNameSpaceID_XHTML,
                                            nsIDOMNode::ELEMENT_NODE);
   NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
   nsRefPtr<nsGenericHTMLElement> styleContent = NS_NewHTMLStyleElement(nodeInfo.forget());
   if (!styleContent) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   styleContent->SetTextContent(NS_LITERAL_STRING("img { display: block; }"));
-  body->AppendChildTo(styleContent, PR_FALSE);
+  head->AppendChildTo(styleContent, PR_FALSE);
 
   // Add the image element
+  Element* body = GetBodyElement();
+  if (!body) {
+    NS_WARNING("no body on image document!");
+    return NS_ERROR_FAILURE;
+  }
+
   nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::img, nsnull,
                                            kNameSpaceID_XHTML,
                                            nsIDOMNode::ELEMENT_NODE);
   NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
 
   mImageContent = NS_NewHTMLImageElement(nodeInfo.forget());
   if (!mImageContent) {
     return NS_ERROR_OUT_OF_MEMORY;
--- a/content/html/document/src/MediaDocument.cpp
+++ b/content/html/document/src/MediaDocument.cpp
@@ -145,16 +145,18 @@ MediaDocument::Init()
   // Create a bundle for the localization
   nsCOMPtr<nsIStringBundleService> stringService =
     mozilla::services::GetStringBundleService();
   if (stringService) {
     stringService->CreateBundle(NSMEDIADOCUMENT_PROPERTIES_URI,
                                 getter_AddRefs(mStringBundle));
   }
 
+  mIsSyntheticDocument = PR_TRUE;
+
   return NS_OK;
 }
 
 nsresult
 MediaDocument::StartDocumentLoad(const char*         aCommand,
                                  nsIChannel*         aChannel,
                                  nsILoadGroup*       aLoadGroup,
                                  nsISupports*        aContainer,
--- a/content/html/document/test/Makefile.in
+++ b/content/html/document/test/Makefile.in
@@ -98,16 +98,18 @@ include $(topsrcdir)/config/rules.mk
 		test_bug486741.html \
 		test_bug489532.html \
 		test_bug497242.xhtml \
 		test_bug499092.html \
 		bug499092.xml \
 		bug499092.html \
 		test_bug512367.html \
 		test_bug571981.html \
+		test_bug677495.html \
+		test_bug677495-1.html \
 		$(NULL)
 
 ifneq (mobile,$(MOZ_BUILD_APP))
 _BROWSER_TEST_FILES = \
 		browser_bug592641.js \
 		bug592641_img.jpg \
 		$(NULL)
 endif
new file mode 100644
--- /dev/null
+++ b/content/html/document/test/test_bug677495-1.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=677495
+
+As mandated by the spec, the body of a media document must only contain one child.
+-->
+<head>
+  <title>Test for Bug 571981</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"/>
+
+<script type="application/javascript">
+  SimpleTest.waitForExplicitFinish();
+
+  function frameLoaded() {
+    var testframe = document.getElementById('testframe');
+    var testframeChildren = testframe.contentDocument.body.childNodes;
+    is(testframeChildren.length, 1, "Body of video document has 1 child");
+    is(testframeChildren[0].nodeName, "VIDEO", "Only child of body must be a <video> element");
+
+    SimpleTest.finish();
+  }
+</script>
+
+</head>
+<body>
+  <p id="display"></p>
+
+  <iframe id="testframe" name="testframe" onload="frameLoaded()"
+   src="data:video/webm,"></iframe>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/html/document/test/test_bug677495.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=677495
+
+As mandated by the spec, the body of a media document must only contain one child.
+-->
+<head>
+  <title>Test for Bug 571981</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"/>
+
+<script type="application/javascript">
+  SimpleTest.waitForExplicitFinish();
+
+  function frameLoaded() {
+    var testframe = document.getElementById('testframe');
+    var testframeChildren = testframe.contentDocument.body.childNodes;
+    is(testframeChildren.length, 1, "Body of image document has 1 child");
+    is(testframeChildren[0].nodeName, "IMG", "Only child of body must be an <img> element");
+
+    SimpleTest.finish();
+  }
+</script>
+
+</head>
+<body>
+  <p id="display"></p>
+
+  <iframe id="testframe" name="testframe" onload="frameLoaded()"
+   src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9oMFgQGMyFwHucAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAADElEQVQI12P4//8/AAX+Av7czFnnAAAAAElFTkSuQmCC"></iframe>
+
+</body>
+</html>
--- a/content/media/nsBuiltinDecoder.cpp
+++ b/content/media/nsBuiltinDecoder.cpp
@@ -42,16 +42,17 @@
 #include "nsAudioStream.h"
 #include "nsHTMLVideoElement.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
 #include "nsTArray.h"
 #include "VideoUtils.h"
 #include "nsBuiltinDecoder.h"
 #include "nsBuiltinDecoderStateMachine.h"
+#include "nsTimeRanges.h"
 
 using namespace mozilla;
 
 #ifdef PR_LOGGING
 PRLogModuleInfo* gBuiltinDecoderLog;
 #define LOG(type, msg) PR_LOG(gBuiltinDecoderLog, type, msg)
 #else
 #define LOG(type, msg)
@@ -262,23 +263,92 @@ nsresult nsBuiltinDecoder::Play()
   }
   if (mPlayState == PLAY_STATE_ENDED)
     return Seek(0);
 
   ChangeState(PLAY_STATE_PLAYING);
   return NS_OK;
 }
 
+/**
+ * Returns PR_TRUE if aValue is inside a range of aRanges, and put the range
+ * index in aIntervalIndex if it is not null.
+ * If aValue is not inside a range, PR_FALSE is returned, and aIntervalIndex, if
+ * not null, is set to the index of the range which ends immediatly before aValue
+ * (and can be -1 if aValue is before aRanges.Start(0)).
+ */
+static PRBool IsInRanges(nsTimeRanges& aRanges, double aValue, PRInt32& aIntervalIndex) {
+  PRUint32 length;
+  aRanges.GetLength(&length);
+  for (PRUint32 i = 0; i < length; i++) {
+    double start, end;
+    aRanges.Start(i, &start);
+    if (start > aValue) {
+      aIntervalIndex = i - 1;
+      return PR_FALSE;
+    }
+    aRanges.End(i, &end);
+    if (aValue <= end) {
+      aIntervalIndex = i;
+      return PR_TRUE;
+    }
+  }
+  aIntervalIndex = length - 1;
+  return PR_FALSE;
+}
+
 nsresult nsBuiltinDecoder::Seek(double aTime)
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
 
-  if (aTime < 0.0)
-    return NS_ERROR_FAILURE;
+  NS_ABORT_IF_FALSE(aTime >= 0.0, "Cannot seek to a negative value.");
+
+  nsTimeRanges seekable;
+  nsresult res;
+  PRUint32 length = 0;
+  res = GetSeekable(&seekable);
+  NS_ENSURE_SUCCESS(res, NS_OK);
+
+  seekable.GetLength(&length);
+  if (!length) {
+    return NS_OK;
+  }
+
+  // If the position we want to seek to is not in a seekable range, we seek
+  // to the closest position in the seekable ranges instead . If two positions
+  // are equaly close, we seek to the closest position from the currentTime.
+  // See seeking spec, point 7 :
+  // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-element.html#seeking
+  PRInt32 range = 0;
+  if (!IsInRanges(seekable, aTime, range)) {
+    if (range != -1) {
+      double leftBound, rightBound;
+      res = seekable.End(range, &leftBound);
+      NS_ENSURE_SUCCESS(res, NS_OK);
+      double distanceLeft = NS_ABS(leftBound - aTime);
+
+      double distanceRight = -1;
+      if (range + 1 < length) {
+        res = seekable.Start(range+1, &rightBound);
+        NS_ENSURE_SUCCESS(res, NS_OK);
+        distanceRight = NS_ABS(rightBound - aTime);
+      }
+
+      if (distanceLeft == distanceRight) {
+        distanceLeft = NS_ABS(leftBound - mCurrentTime);
+        distanceRight = NS_ABS(rightBound - mCurrentTime);
+      } 
+      aTime = (distanceLeft < distanceRight) ? leftBound : rightBound;
+    } else {
+      // aTime is before the first range in |seekable|, the closest point we can
+      // seek to is the start of the first range.
+      seekable.Start(0, &aTime);
+    }
+  }
 
   mRequestedSeekTime = aTime;
   mCurrentTime = aTime;
 
   // If we are already in the seeking state, then setting mRequestedSeekTime
   // above will result in the new seek occurring when the current seek
   // completes.
   if (mPlayState != PLAY_STATE_SEEKING) {
@@ -842,22 +912,37 @@ void nsBuiltinDecoder::SetSeekable(PRBoo
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   mSeekable = aSeekable;
   if (mDecoderStateMachine) {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     mDecoderStateMachine->SetSeekable(aSeekable);
   }
 }
 
-PRBool nsBuiltinDecoder::GetSeekable()
+PRBool nsBuiltinDecoder::IsSeekable()
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   return mSeekable;
 }
 
+nsresult nsBuiltinDecoder::GetSeekable(nsTimeRanges* aSeekable)
+{
+  //TODO : change 0.0 to GetInitialTime() when available
+  double initialTime = 0.0;
+
+  if (IsSeekable()) {
+    double end = IsInfinite() ? std::numeric_limits<double>::infinity()
+                              : initialTime + GetDuration();
+    aSeekable->Add(initialTime, end);
+    return NS_OK;
+  }
+
+  return GetBuffered(aSeekable);
+}
+
 void nsBuiltinDecoder::Suspend()
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   if (mStream) {
     mStream->Suspend(PR_TRUE);
   }
 }
 
--- a/content/media/nsBuiltinDecoder.h
+++ b/content/media/nsBuiltinDecoder.h
@@ -311,17 +311,17 @@ public:
   // Called from the main thread to set whether the media resource can
   // seek into unbuffered ranges. The decoder monitor must be obtained
   // before calling this.
   virtual void SetSeekable(PRBool aSeekable) = 0;
 
   // Returns PR_TRUE if the media resource can seek into unbuffered ranges,
   // as set by SetSeekable(). The decoder monitor must be obtained before
   // calling this.
-  virtual PRBool GetSeekable() = 0;
+  virtual PRBool IsSeekable() = 0;
 
   // Update the playback position. This can result in a timeupdate event
   // and an invalidate of the frame being dispatched asynchronously if
   // there is no such event currently queued.
   // Only called on the decoder thread. Must be called with
   // the decode monitor held.
   virtual void UpdatePlaybackPosition(PRInt64 aTime) = 0;
 
@@ -428,17 +428,19 @@ class nsBuiltinDecoder : public nsMediaD
   // This is called via a channel listener if it can pick up the duration
   // from a content header. Must be called from the main thread only.
   virtual void SetDuration(double aDuration);
 
   // Set a flag indicating whether seeking is supported
   virtual void SetSeekable(PRBool aSeekable);
 
   // Return PR_TRUE if seeking is supported.
-  virtual PRBool GetSeekable();
+  virtual PRBool IsSeekable();
+
+  virtual nsresult GetSeekable(nsTimeRanges* aSeekable);
 
   virtual Statistics GetStatistics();
 
   // Suspend any media downloads that are in progress. Called by the
   // media element when it is sent to the bfcache. Call on the main
   // thread only.
   virtual void Suspend();
 
--- a/content/media/nsBuiltinDecoderStateMachine.h
+++ b/content/media/nsBuiltinDecoderStateMachine.h
@@ -247,17 +247,17 @@ public:
     mReader->NotifyDataArrived(aBuffer, aLength, aOffset);
   }
 
   PRInt64 GetEndMediaTime() const {
     mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
     return mEndTime;
   }
 
-  PRBool GetSeekable() {
+  PRBool IsSeekable() {
     mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
     return mSeekable;
   }
 
   // Sets the current frame buffer length for the MozAudioAvailable event.
   // Accessed on the main and state machine threads.
   virtual void SetFrameBufferLength(PRUint32 aLength);
 
--- a/content/media/nsMediaDecoder.h
+++ b/content/media/nsMediaDecoder.h
@@ -286,17 +286,20 @@ public:
   // This is called via a channel listener if it can pick up the duration
   // from a content header. Must be called from the main thread only.
   virtual void SetDuration(double aDuration) = 0;
 
   // Set a flag indicating whether seeking is supported
   virtual void SetSeekable(PRBool aSeekable) = 0;
 
   // Return PR_TRUE if seeking is supported.
-  virtual PRBool GetSeekable() = 0;
+  virtual PRBool IsSeekable() = 0;
+
+  // Return the time ranges that can be seeked into.
+  virtual nsresult GetSeekable(nsTimeRanges* aSeekable) = 0;
 
   // Invalidate the frame.
   virtual void Invalidate();
 
   // Fire progress events if needed according to the time and byte
   // constraints outlined in the specification. aTimer is PR_TRUE
   // if the method is called as a result of the progress timer rather
   // than the result of downloaded data.
--- a/content/media/ogg/nsOggReader.cpp
+++ b/content/media/ogg/nsOggReader.cpp
@@ -321,17 +321,17 @@ nsresult nsOggReader::ReadMetadata(nsVid
 
   {
     ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
 
     nsMediaStream* stream = mDecoder->GetCurrentStream();
     if (mDecoder->GetStateMachine()->GetDuration() == -1 &&
         mDecoder->GetStateMachine()->GetState() != nsDecoderStateMachine::DECODER_STATE_SHUTDOWN &&
         stream->GetLength() >= 0 &&
-        mDecoder->GetStateMachine()->GetSeekable())
+        mDecoder->GetStateMachine()->IsSeekable())
     {
       // We didn't get a duration from the index or a Content-Duration header.
       // Seek to the end of file to find the end time.
       PRInt64 length = stream->GetLength();
       NS_ASSERTION(length > 0, "Must have a content length to get end time");
 
       PRInt64 endTime = 0;
       {
--- a/content/media/test/Makefile.in
+++ b/content/media/test/Makefile.in
@@ -123,16 +123,17 @@ include $(topsrcdir)/config/rules.mk
 		test_networkState.html \
 		test_new_audio.html \
 		test_paused.html \
 		test_paused_after_ended.html \
 		test_play_events.html \
 		test_play_events_2.html \
 		test_playback.html \
 		test_playback_errors.html \
+ 		test_seekable1.html \
 		test_preload_actions.html \
 		test_preload_attribute.html \
 		test_progress.html \
 		test_reactivate.html \
 		test_readyState.html \
 		test_replay_metadata.html \
 		test_seek.html \
 		test_seek2.html \
@@ -254,16 +255,19 @@ ifdef MOZ_OGG
 		test_contentDuration7.html \
 		contentDuration1.sjs \
 		contentDuration2.sjs \
 		contentDuration3.sjs \
 		contentDuration4.sjs \
 		contentDuration5.sjs \
 		contentDuration6.sjs \
 		contentDuration7.sjs \
+		noContentLength.sjs \
+		test_seekable2.html \
+		test_seekable3.html \
 		test_a4_tone.html \
 		file_audio_event_adopt_iframe.html \
 		test_audio_event_adopt.html \
 		test_framebuffer.html \
 		test_referer.html \
 		$(NULL)
 else
 _TEST_FILES += \
--- a/content/media/test/manifest.js
+++ b/content/media/test/manifest.js
@@ -141,16 +141,29 @@ function fileUriToSrc(path, mustExist) {
     f.append(split[i]);
   }
   if (mustExist && !f.exists()) {
     ok(false, "We expected '" + path + "' to exist, but it doesn't!");
   }
   return f.path;
 }
 
+// Returns true if two nsTimeRanges are equal, false otherwise
+function range_equals(r1, r2) {
+  if (r1.length != r2.length) {
+    return false;
+  }
+  for (var i = 0; i < r1.length; i++) {
+    if (r1.start(i) != r2.start(i) || r1.end(i) != r2.end(i)) {
+      return false;
+    }
+  }
+  return true;
+}
+
 // These are URIs to files that we use to check that we don't leak any state
 // or other information such that script can determine stuff about a user's
 // environment. Used by test_info_leak.
 var gInfoLeakTests = [
   {
     type: 'video/ogg',
     src: fileUriToSrc("tests/content/media/test/320x240.ogv", true),
   },{
new file mode 100644
--- /dev/null
+++ b/content/media/test/noContentLength.sjs
@@ -0,0 +1,23 @@
+// Serve a media file without using content-range header
+function handleRequest(request, response)
+{
+  var file = Components.classes["@mozilla.org/file/directory_service;1"].
+                        getService(Components.interfaces.nsIProperties).
+                        get("CurWorkD", Components.interfaces.nsILocalFile);
+  var fis  = Components.classes['@mozilla.org/network/file-input-stream;1'].
+                        createInstance(Components.interfaces.nsIFileInputStream);
+  var bis  = Components.classes["@mozilla.org/binaryinputstream;1"].
+                        createInstance(Components.interfaces.nsIBinaryInputStream);
+  var paths = "tests/content/media/test/320x240.ogv";
+  var split = paths.split("/");
+  for(var i = 0; i < split.length; ++i) {
+    file.append(split[i]);
+  }
+  fis.init(file, -1, -1, false);
+  bis.setInputStream(fis);
+  var bytes = bis.readBytes(bis.available());
+  response.setStatusLine(request.httpVersion, 200, "Content Follows");
+  response.setHeader("Content-Type", "video/ogg", false);
+  response.write(bytes, bytes.length);
+  bis.close();
+}
new file mode 100644
--- /dev/null
+++ b/content/media/test/test_seekable1.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Test seekable member for media elements</title>
+<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+<script type="text/javascript" src="manifest.js"></script>
+</head>
+<body>
+<pre id='test'>
+<script class="testbody" type='application/javascript;version=1.8'>
+
+let manager = new MediaTestManager;
+
+function finish_test(element) {
+  if (element.parentNode)
+    element.parentNode.removeChild(element);
+  element.src="";
+  manager.finished(element.token);
+}
+
+var tests = [
+// Test using a finite media stream, and a server supporting range requests
+{
+setup : function(element) {
+          is(element.seekable.length, 0, "seekable.length should be initialy 0.");
+          element.addEventListener("loadedmetadata", function() {
+              is(element.seekable.length, 1, "seekable.length should be 1 for a server supporting range requests.");
+
+              //TODO : change this by using element.initialTime
+              is(element.seekable.start(0), 0.0, "The start of the first range should be the initialTime.");
+              is(element.seekable.end(0), element.duration, "The end of the first range should be the duration.")
+              finish_test(element);
+              }, false);
+        }
+}
+];
+
+function createTestArray() {
+  var A = [];
+    for (var k=0; k < gProgressTests.length; k++) {
+      var t = new Object();
+      t.setup = tests[0].setup;
+      t.name = gProgressTests[k].name;
+      t.type = gProgressTests[k].type;
+      A.push(t);
+    }
+  return A;
+}
+
+function startTest(test, token) {
+  var elemType = /^audio/.test(test.type) ? "audio" : "video";
+  var element = document.createElement(elemType);
+  element.src = test.name;
+  element.token = token;
+  test.setup(element);
+  manager.started(token);
+}
+
+manager.runTests(createTestArray(), startTest);
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/media/test/test_seekable2.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Media test: seek test 3</title>
+<script type="text/javascript" src="/MochiKit/packed.js"></script>
+<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="manifest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onunload="mediaTestCleanup();">
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+function on_metadataloaded() {
+  var v = document.getElementById('v');
+  ok(range_equals(v.seekable, v.buffered), "seekable.length should be initialy empty, or equal to buffered");
+  v.addEventListener("playing", function() {
+    ok(v.seekable.length > 0, "seekable.length should not be empty while playing.");
+  }, false);
+  v.addEventListener("ended", function() {
+    is(v.seekable.length, 1, "seekable.length should be 1 at end of playback.");
+    is(v.seekable.start(0), 0.0, "start of first range should 0.0");
+    is(v.seekable.end(0), v.duration, "end of first range should be equal to duration");
+    SimpleTest.finish();
+  }, false);
+
+  v.play();
+}
+
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+<video id='v'
+src='contentDuration6.sjs'
+onloadedmetadata='on_metadataloaded();'></video>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/media/test/test_seekable3.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Media test: seek test 3</title>
+<script type="text/javascript" src="/MochiKit/packed.js"></script>
+<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="manifest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onunload="mediaTestCleanup();">
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+function on_metadataloaded() {
+  var v = document.getElementById('v');
+  ok(range_equals(v.seekable, v.buffered), "seekable.length should be initialy empty");
+  v.addEventListener("playing", function() {
+    ok(v.seekable.length > 0, "seekable.length should not empty while playing.");
+  }, false);
+  v.addEventListener("ended", function() {
+    is(v.seekable.length, 1, "seekable.length should be 1 at end of playback.");
+    is(v.seekable.start(0), 0.0, "start of first range should 0.0");
+    is(v.seekable.end(0), v.duration, "end of first range should be equal to duration");
+    SimpleTest.finish();
+  }, false);
+
+  v.play();
+}
+
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+<video id='v'
+src='noContentLength.sjs'
+onloadedmetadata='on_metadataloaded();'></video>
+</body>
+</html>
--- a/content/xslt/src/base/txOwningArray.h
+++ b/content/xslt/src/base/txOwningArray.h
@@ -34,27 +34,25 @@
  * 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 txOwningArray_h__
 #define txOwningArray_h__
 
-#include "nsTPtrArray.h"
-
-// Class acting like a nsTPtrArray except that it deletes its objects
+// Class acting like a nsTArray except that it deletes its objects
 // on destruction. It does not however delete its objects on operations
 // like RemoveElementsAt or on |array[i] = bar|.
 
 template<class E>
-class txOwningArray : public nsTPtrArray<E>
+class txOwningArray : public nsTArray<E*>
 {
 public:
-    typedef nsTPtrArray<E> base_type;
+    typedef nsTArray<E*> base_type;
     typedef typename base_type::elem_type elem_type;
 
     ~txOwningArray()
     {
         elem_type* iter = base_type::Elements();
         elem_type* end = iter + base_type::Length();
         for (; iter < end; ++iter) {
             delete *iter;
--- a/content/xslt/src/xslt/txStylesheet.cpp
+++ b/content/xslt/src/xslt/txStylesheet.cpp
@@ -312,17 +312,17 @@ txStylesheet::doneCompiling()
     rv = addFrames(frameIter);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Loop through importframes in decreasing-precedence-order and process
     // all items
     frameIter.reset();
     ImportFrame* frame;
     while ((frame = static_cast<ImportFrame*>(frameIter.next()))) {
-        nsTPtrArray<txStripSpaceTest> frameStripSpaceTests;
+        nsTArray<txStripSpaceTest*> frameStripSpaceTests;
 
         txListIterator itemIter(&frame->mToplevelItems);
         itemIter.resetToEnd();
         txToplevelItem* item;
         while ((item = static_cast<txToplevelItem*>(itemIter.previous()))) {
             switch (item->getType()) {
                 case txToplevelItem::attributeSet:
                 {
@@ -497,17 +497,17 @@ txStylesheet::addFrames(txListIterator& 
         }
     }
     
     return NS_OK;
 }
 
 nsresult
 txStylesheet::addStripSpace(txStripSpaceItem* aStripSpaceItem,
-                            nsTPtrArray<txStripSpaceTest>& aFrameStripSpaceTests)
+                            nsTArray<txStripSpaceTest*>& aFrameStripSpaceTests)
 {
     PRInt32 testCount = aStripSpaceItem->mStripSpaceTests.Length();
     for (; testCount > 0; --testCount) {
         txStripSpaceTest* sst = aStripSpaceItem->mStripSpaceTests[testCount-1];
         double priority = sst->getDefaultPriority();
         PRInt32 i, frameCount = aFrameStripSpaceTests.Length();
         for (i = 0; i < frameCount; ++i) {
             if (aFrameStripSpaceTests[i]->getDefaultPriority() < priority) {
--- a/content/xslt/src/xslt/txStylesheet.h
+++ b/content/xslt/src/xslt/txStylesheet.h
@@ -38,17 +38,16 @@
 
 #ifndef TX_TXSTYLESHEET_H
 #define TX_TXSTYLESHEET_H
 
 #include "txOutputFormat.h"
 #include "txExpandedNameMap.h"
 #include "txList.h"
 #include "txXSLTPatterns.h"
-#include "nsTPtrArray.h"
 #include "nsISupportsImpl.h"
 
 class txInstruction;
 class txToplevelItem;
 class txTemplateItem;
 class txVariableItem;
 class txStripSpaceItem;
 class txAttributeSetItem;
@@ -140,17 +139,17 @@ public:
         PRBool mIsParam;
     };
 
 private:
     nsresult addTemplate(txTemplateItem* aTemplate, ImportFrame* aImportFrame);
     nsresult addGlobalVariable(txVariableItem* aVariable);
     nsresult addFrames(txListIterator& aInsertIter);
     nsresult addStripSpace(txStripSpaceItem* aStripSpaceItem,
-                           nsTPtrArray<txStripSpaceTest>& aFrameStripSpaceTests);
+                           nsTArray<txStripSpaceTest*>& aFrameStripSpaceTests);
     nsresult addAttributeSet(txAttributeSetItem* aAttributeSetItem);
 
     // List of ImportFrames
     txList mImportFrames;
     
     // output format
     txOutputFormat mOutputFormat;
 
--- a/content/xslt/src/xslt/txToplevelItems.h
+++ b/content/xslt/src/xslt/txToplevelItems.h
@@ -128,17 +128,17 @@ class txStripSpaceItem : public txToplev
 {
 public:
     ~txStripSpaceItem();
 
     TX_DECL_TOPLEVELITEM
 
     nsresult addStripSpaceTest(txStripSpaceTest* aStripSpaceTest);
 
-    nsTPtrArray<txStripSpaceTest> mStripSpaceTests;
+    nsTArray<txStripSpaceTest*> mStripSpaceTests;
 };
 
 // xsl:template
 class txTemplateItem : public txInstructionContainer
 {
 public:
     txTemplateItem(nsAutoPtr<txPattern> aMatch, const txExpandedName& aName,
                    const txExpandedName& aMode, double aPrio);
--- a/content/xul/document/src/nsXULControllers.h
+++ b/content/xul/document/src/nsXULControllers.h
@@ -41,17 +41,16 @@
   The XUL "controllers" object.
 
 */
 
 #ifndef nsXULControllers_h__
 #define nsXULControllers_h__
 
 #include "nsCOMPtr.h"
-#include "nsTPtrArray.h"
 #include "nsWeakPtr.h"
 #include "nsIControllers.h"
 #include "nsISecurityCheckedComponent.h"
 #include "nsCycleCollectionParticipant.h"
 
 /* non-XPCOM class for holding controllers and their IDs */
 class nsXULControllerData
 {
@@ -92,16 +91,16 @@ public:
     NS_DECL_NSISECURITYCHECKEDCOMPONENT
   
 protected:
     nsXULControllers();
     virtual ~nsXULControllers(void);
 
     void        DeleteControllers();
 
-    nsTPtrArray<nsXULControllerData> mControllers;
+    nsTArray<nsXULControllerData*>   mControllers;
     PRUint32                         mCurControllerID;
 };
 
 
 
 
 #endif // nsXULControllers_h__
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -337,17 +337,16 @@
 #include "nsIDOMTreeWalker.h"
 #include "nsIDOMXULDocument.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDOMXULCommandDispatcher.h"
 #include "nsIDOMCrypto.h"
 #include "nsIDOMCRMFObject.h"
 #include "nsIControllers.h"
 #include "nsISelection.h"
-#include "nsISelection3.h"
 #include "nsIBoxObject.h"
 #ifdef MOZ_XUL
 #include "nsITreeSelection.h"
 #include "nsITreeContentView.h"
 #include "nsITreeView.h"
 #include "nsIXULTemplateBuilder.h"
 #include "nsTreeColumns.h"
 #endif
@@ -2914,17 +2913,16 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(TreeWalker, nsIDOMTreeWalker)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMTreeWalker)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(Selection, nsISelection)
     DOM_CLASSINFO_MAP_ENTRY(nsISelection)
-    DOM_CLASSINFO_MAP_ENTRY(nsISelection3)
   DOM_CLASSINFO_MAP_END
 
 #ifdef MOZ_XUL
   if (nsDOMTouchEvent::PrefEnabled()) {
     DOM_CLASSINFO_MAP_BEGIN(XULDocument, nsIDOMXULDocument)
       DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocument)
       DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULDocument)
       DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentTouch)
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -37,17 +37,16 @@
 #include "mozilla/dom/TabParent.h"
 
 #include "nsFocusManager.h"
 
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIServiceManager.h"
 #include "nsIEnumerator.h"
-#include "nsTPtrArray.h"
 #include "nsGkAtoms.h"
 #include "nsContentUtils.h"
 #include "nsIDocument.h"
 #include "nsIDOMWindow.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDOMNSHTMLFrameElement.h"
@@ -1293,17 +1292,17 @@ nsFocusManager::GetCommonAncestor(nsPIDO
   nsCOMPtr<nsIWebNavigation> webnav(do_GetInterface(aWindow1));
   nsCOMPtr<nsIDocShellTreeItem> dsti1 = do_QueryInterface(webnav);
   NS_ENSURE_TRUE(dsti1, nsnull);
 
   webnav = do_GetInterface(aWindow2);
   nsCOMPtr<nsIDocShellTreeItem> dsti2 = do_QueryInterface(webnav);
   NS_ENSURE_TRUE(dsti2, nsnull);
 
-  nsAutoTPtrArray<nsIDocShellTreeItem, 30> parents1, parents2;
+  nsAutoTArray<nsIDocShellTreeItem*, 30> parents1, parents2;
   do {
     parents1.AppendElement(dsti1);
     nsCOMPtr<nsIDocShellTreeItem> parentDsti1;
     dsti1->GetParent(getter_AddRefs(parentDsti1));
     dsti1.swap(parentDsti1);
   } while (dsti1);
   do {
     parents2.AppendElement(dsti2);
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -10070,16 +10070,29 @@ nsGlobalWindow::HasIndexedDBSupport()
 
 // static
 bool
 nsGlobalWindow::HasPerformanceSupport() 
 {
   return Preferences::GetBool("dom.enable_performance", PR_FALSE);
 }
 
+PRInt64
+nsGlobalWindow::SizeOf() const
+{
+  PRInt64 size = sizeof(*this);
+
+  if (IsInnerWindow() && mDoc) {
+    size += mDoc->SizeOf();
+  }
+
+  size += mNavigator ? mNavigator->SizeOf() : 0;
+
+  return size;
+}
 
 // nsGlobalChromeWindow implementation
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalChromeWindow)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalChromeWindow,
                                                   nsGlobalWindow)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mBrowserDOMWindow)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mMessageManager)
@@ -11222,8 +11235,26 @@ NS_IMETHODIMP nsNavigator::GetMozNotific
                                                   scx);
   if (!mNotification) {
     return NS_ERROR_FAILURE;
   }
 
   NS_ADDREF(*aRetVal = mNotification);    
   return NS_OK; 
 }
+
+PRInt64
+nsNavigator::SizeOf() const
+{
+  PRInt64 size = sizeof(*this);
+
+  // TODO: add SizeOf() to nsMimeTypeArray, bug 674113.
+  size += mMimeTypes ? sizeof(*mMimeTypes.get()) : 0;
+  // TODO: add SizeOf() to nsPluginArray, bug 674114.
+  size += mPlugins ? sizeof(*mPlugins.get()) : 0;
+  // TODO: add SizeOf() to nsGeolocation, bug 674115.
+  size += mGeolocation ? sizeof(*mGeolocation.get()) : 0;
+  // TODO: add SizeOf() to nsDesktopNotificationCenter, bug 674116.
+  size += mNotification ? sizeof(*mNotification.get()) : 0;
+
+  return size;
+}
+
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -533,25 +533,17 @@ public:
   static bool HasIndexedDBSupport();
 
   static bool HasPerformanceSupport();
 
   static WindowByIdTable* GetWindowsTable() {
     return sWindowsById;
   }
 
-  PRInt64 SizeOf() const {
-    PRInt64 size = sizeof(*this);
-
-    if (IsInnerWindow() && mDoc) {
-      size += mDoc->SizeOf();
-    }
-
-    return size;
-  }
+  PRInt64 SizeOf() const;
 
 private:
   // Enable updates for the accelerometer.
   void EnableDeviceMotionUpdates();
 
   // Disables updates for the accelerometer.
   void DisableDeviceMotionUpdates();
 
@@ -1071,16 +1063,18 @@ public:
     return mDocShell;
   }
 
   void LoadingNewDocument();
   nsresult RefreshMIMEArray();
 
   static bool HasDesktopNotificationSupport();
 
+  PRInt64 SizeOf() const;
+
 protected:
   nsRefPtr<nsMimeTypeArray> mMimeTypes;
   nsRefPtr<nsPluginArray> mPlugins;
   nsRefPtr<nsGeolocation> mGeolocation;
   nsRefPtr<nsDesktopNotificationCenter> mNotification;
   nsIDocShell* mDocShell; // weak reference
 };
 
--- a/dom/interfaces/core/nsIDOMDocument.idl
+++ b/dom/interfaces/core/nsIDOMDocument.idl
@@ -57,17 +57,17 @@ interface nsIDOMLocation;
  * cannot exist outside the context of a Document, the nsIDOMDocument 
  * interface also contains the factory methods needed to create these 
  * objects.
  *
  * For more information on this interface please see 
  * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
  */
 
-[scriptable, uuid(d53c3d3d-2413-4abc-b54e-11c5c8380776)]
+[scriptable, uuid(10034b87-384e-4e19-902c-c4edafb899be)]
 interface nsIDOMDocument : nsIDOMNode
 {
   readonly attribute nsIDOMDocumentType         doctype;
   readonly attribute nsIDOMDOMImplementation    implementation;
   readonly attribute nsIDOMElement              documentElement;
   nsIDOMElement                 createElement(in DOMString tagName)
                                   raises(DOMException);
   nsIDOMDocumentFragment        createDocumentFragment();
@@ -312,16 +312,22 @@ interface nsIDOMDocument : nsIDOMNode
 
   // Mozilla extensions
   /**
    * @see <https://developer.mozilla.org/en/DOM/document.contentType>
    */
   readonly attribute DOMString      contentType;
 
   /**
+   * True if this document is synthetic : stand alone image, video, audio file,
+   * etc.
+   */
+  readonly attribute boolean        mozSyntheticDocument;
+
+  /**
    * Returns the script element whose script is currently being processed.
    *
    * @see <https://developer.mozilla.org/en/DOM/document.currentScript>
    */
   readonly attribute nsIDOMElement  currentScript;
 
   /**
    * Release the current mouse capture if it is on an element within this
--- a/dom/interfaces/html/nsIDOMHTMLMediaElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLMediaElement.idl
@@ -52,17 +52,17 @@
 
 // undef the GetCurrentTime macro defined in WinBase.h from the MS Platform SDK
 %{C++
 #ifdef GetCurrentTime
 #undef GetCurrentTime
 #endif
 %}
 
-[scriptable, uuid(d8213322-46d8-47ca-a15c-2abae47ddfde)]
+[scriptable, uuid(9441effd-fbe1-4f48-aa90-1741c1e390a1)]
 interface nsIDOMHTMLMediaElement : nsIDOMHTMLElement
 {
   // error state
   readonly attribute nsIDOMMediaError error;
 
   // network state
            attribute DOMString src;
   readonly attribute DOMString currentSrc;
@@ -84,16 +84,17 @@ interface nsIDOMHTMLMediaElement : nsIDO
   const unsigned short HAVE_ENOUGH_DATA = 4;
   readonly attribute unsigned short readyState;
   readonly attribute boolean seeking;
 
   // playback state
            attribute double currentTime;
   readonly attribute double duration;
   readonly attribute boolean paused;
+  readonly attribute nsIDOMTimeRanges seekable;
   readonly attribute boolean ended;
   readonly attribute boolean mozAutoplayEnabled;
            attribute boolean autoplay;
   void play();
   void pause();
 
   // controls
            attribute boolean controls;
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -522,22 +522,24 @@ ContentParent::RecvGetClipboardText(cons
     NS_ENSURE_SUCCESS(rv, true);
 
     nsCOMPtr<nsITransferable> trans = do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
     NS_ENSURE_SUCCESS(rv, true);
     
     clipboard->GetData(trans, whichClipboard);
     nsCOMPtr<nsISupports> tmp;
     PRUint32 len;
-    rv  = trans->GetTransferData(kUnicodeMime, getter_AddRefs(tmp), &len);
-    NS_ENSURE_SUCCESS(rv, rv);
+    rv = trans->GetTransferData(kUnicodeMime, getter_AddRefs(tmp), &len);
+    if (NS_FAILED(rv))
+        return false;
 
     nsCOMPtr<nsISupportsString> supportsString = do_QueryInterface(tmp);
     // No support for non-text data
-    NS_ENSURE_TRUE(supportsString, NS_ERROR_NOT_IMPLEMENTED);
+    if (!supportsString)
+        return false;
     supportsString->GetData(*text);
     return true;
 }
 
 bool
 ContentParent::RecvEmptyClipboard()
 {
     nsresult rv;
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -466,68 +466,76 @@ TabChild::DestroyWindow()
         mRemoteFrame->Destroy();
         mRemoteFrame = nsnull;
     }
 }
 
 void
 TabChild::ActorDestroy(ActorDestroyReason why)
 {
-  // The messageManager relays messages via the TabChild which
-  // no longer exists.
-  static_cast<nsFrameMessageManager*>
-    (mTabChildGlobal->mMessageManager.get())->Disconnect();
-  mTabChildGlobal->mMessageManager = nsnull;
+  if (mTabChildGlobal) {
+    // The messageManager relays messages via the TabChild which
+    // no longer exists.
+    static_cast<nsFrameMessageManager*>
+      (mTabChildGlobal->mMessageManager.get())->Disconnect();
+    mTabChildGlobal->mMessageManager = nsnull;
+  }
 }
 
 TabChild::~TabChild()
 {
     nsCOMPtr<nsIWebBrowser> webBrowser = do_QueryInterface(mWebNav);
     if (webBrowser) {
       webBrowser->SetContainerWindow(nsnull);
     }
     if (mCx) {
       DestroyCx();
     }
     
-    nsEventListenerManager* elm = mTabChildGlobal->GetListenerManager(PR_FALSE);
-    if (elm) {
-      elm->Disconnect();
+    if (mTabChildGlobal) {
+      nsEventListenerManager* elm = mTabChildGlobal->GetListenerManager(PR_FALSE);
+      if (elm) {
+        elm->Disconnect();
+      }
+      mTabChildGlobal->mTabChild = nsnull;
     }
-    mTabChildGlobal->mTabChild = nsnull;
 }
 
 bool
 TabChild::RecvLoadURL(const nsCString& uri)
 {
     printf("loading %s, %d\n", uri.get(), NS_IsMainThread());
 
     nsresult rv = mWebNav->LoadURI(NS_ConvertUTF8toUTF16(uri).get(),
                                    nsIWebNavigation::LOAD_FLAGS_NONE,
                                    NULL, NULL, NULL);
     if (NS_FAILED(rv)) {
         NS_WARNING("mWebNav->LoadURI failed. Eating exception, what else can I do?");
     }
 
-    return NS_SUCCEEDED(rv);
+    return true;
 }
 
 bool
 TabChild::RecvShow(const nsIntSize& size)
 {
     printf("[TabChild] SHOW (w,h)= (%d, %d)\n", size.width, size.height);
 
     nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(mWebNav);
     if (!baseWindow) {
         NS_ERROR("mWebNav doesn't QI to nsIBaseWindow");
         return false;
     }
 
     if (!InitWidget(size)) {
-        return false;
+        // We can fail to initialize our widget if the <browser
+        // remote> has already been destroyed, and we couldn't hook
+        // into the parent-process's layer system.  That's not a fatal
+        // error.
+        return true;
     }
 
     baseWindow->InitWindow(0, mWidget,
                            0, 0, size.width, size.height);
     baseWindow->Create();
     baseWindow->SetVisibility(PR_TRUE);
 
     // IPC uses a WebBrowser object for which DNS prefetching is turned off
@@ -546,16 +554,20 @@ TabChild::RecvShow(const nsIntSize& size
 
 bool
 TabChild::RecvUpdateDimensions(const nsRect& rect, const nsIntSize& size)
 {
 #ifdef DEBUG
     printf("[TabChild] Update Dimensions to (x,y,w,h)= (%ud, %ud, %ud, %ud) and move to (w,h)= (%ud, %ud)\n", rect.x, rect.y, rect.width, rect.height, size.width, size.height);
 #endif
 
+    if (!mRemoteFrame) {
+        return true;
+    }
+
     mOuterRect.x = rect.x;
     mOuterRect.y = rect.y;
     mOuterRect.width = rect.width;
     mOuterRect.height = rect.height;
 
     mWidget->Resize(0, 0, size.width, size.height,
                     PR_TRUE);
 
@@ -789,17 +801,19 @@ TabChild::DeallocPOfflineCacheUpdate(POf
   delete offlineCacheUpdate;
   return true;
 }
 
 bool
 TabChild::RecvLoadRemoteScript(const nsString& aURL)
 {
   if (!mCx && !InitTabChildGlobal())
-    return false;
+    // This can happen if we're half-destroyed.  It's not a fatal
+    // error.
+    return true;
 
   LoadFrameScriptInternal(aURL);
   return true;
 }
 
 bool
 TabChild::RecvAsyncMessage(const nsString& aMessage,
                            const nsString& aJSON)
@@ -839,20 +853,22 @@ public:
 
   nsRefPtr<TabChild> mTabChild;
   TabChildGlobal* mTabChildGlobal;
 };
 
 bool
 TabChild::RecvDestroy()
 {
-  // Let the frame scripts know the child is being closed
-  nsContentUtils::AddScriptRunner(
-    new UnloadScriptEvent(this, mTabChildGlobal)
-  );
+  if (mTabChildGlobal) {
+    // Let the frame scripts know the child is being closed
+    nsContentUtils::AddScriptRunner(
+      new UnloadScriptEvent(this, mTabChildGlobal)
+    );
+  }
 
   // XXX what other code in ~TabChild() should we be running here?
   DestroyWindow();
 
   return Send__delete__(this);
 }
 
 PRenderFrameChild*
@@ -960,32 +976,30 @@ TabChild::InitWidget(const nsIntSize& si
         static_cast<RenderFrameChild*>(SendPRenderFrameConstructor());
     if (!remoteFrame) {
       NS_WARNING("failed to construct RenderFrame");
       return false;
     }
 
     NS_ABORT_IF_FALSE(0 == remoteFrame->ManagedPLayersChild().Length(),
                       "shouldn't have a shadow manager yet");
-    PLayersChild* shadowManager = remoteFrame->SendPLayersConstructor();
+    LayerManager::LayersBackend be;
+    PLayersChild* shadowManager = remoteFrame->SendPLayersConstructor(&be);
     if (!shadowManager) {
       NS_WARNING("failed to construct LayersChild");
       // This results in |remoteFrame| being deleted.
       PRenderFrameChild::Send__delete__(remoteFrame);
       return false;
     }
 
-    LayerManager* lm = mWidget->GetLayerManager();
-    NS_ABORT_IF_FALSE(LayerManager::LAYERS_BASIC == lm->GetBackendType(),
-                      "content processes should only be using BasicLayers");
-
-    BasicShadowLayerManager* bslm = static_cast<BasicShadowLayerManager*>(lm);
-    NS_ABORT_IF_FALSE(!bslm->HasShadowManager(),
-                      "PuppetWidget shouldn't have shadow manager yet");
-    bslm->SetShadowManager(shadowManager);
+    ShadowLayerForwarder* lf =
+        mWidget->GetLayerManager(shadowManager, be)->AsShadowForwarder();
+    NS_ABORT_IF_FALSE(lf && lf->HasShadowManager(),
+                      "PuppetWidget should have shadow manager");
+    lf->SetParentBackendType(be);
 
     mRemoteFrame = remoteFrame;
     return true;
 }
 
 static bool
 SendSyncMessageToParent(void* aCallbackData,
                         const nsAString& aMessage,
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -763,18 +763,17 @@ TabParent::HandleDelayedDialogs()
                                          PR_TRUE, PR_TRUE);
   }
 }
 
 PRenderFrameParent*
 TabParent::AllocPRenderFrame()
 {
   nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
-  NS_WARN_IF_FALSE(frameLoader, "'message sent to unknown actor ID' coming up");
-  return frameLoader ? new RenderFrameParent(frameLoader) : nsnull;
+  return new RenderFrameParent(frameLoader);
 }
 
 bool
 TabParent::DeallocPRenderFrame(PRenderFrameParent* aFrame)
 {
   delete aFrame;
   return true;
 }
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -3513,17 +3513,23 @@ PluginInstanceChild::SwapSurfaces()
         mDoubleBufferCARenderer.HasBackSurface() &&
         (mDoubleBufferCARenderer.GetFrontSurfaceWidth() != 
             mDoubleBufferCARenderer.GetBackSurfaceWidth() ||
         mDoubleBufferCARenderer.GetFrontSurfaceHeight() != 
             mDoubleBufferCARenderer.GetBackSurfaceHeight())) {
 
         mDoubleBufferCARenderer.ClearFrontSurface();
     }
-#endif //MOZ_WIDGET_COCOA
+#else
+    if (mCurrentSurface && mBackSurface &&
+        (mCurrentSurface->GetSize() != mBackSurface->GetSize() ||
+         mCurrentSurface->GetContentType() != mBackSurface->GetContentType())) {
+        ClearCurrentSurface();
+    }
+#endif
 }
 
 void
 PluginInstanceChild::ClearCurrentSurface()
 {
     mCurrentSurface = nsnull;
 #ifdef MOZ_WIDGET_COCOA
     if (mDoubleBufferCARenderer.HasFrontSurface()) {
--- a/dom/system/nsDeviceMotion.cpp
+++ b/dom/system/nsDeviceMotion.cpp
@@ -44,18 +44,18 @@
 #include "nsIServiceManager.h"
 #include "nsIPrivateDOMEvent.h"
 #include "nsIDOMDeviceOrientationEvent.h"
 #include "nsIDOMDeviceMotionEvent.h"
 #include "nsIServiceManager.h"
 #include "nsIPrefService.h"
 #include "nsDOMDeviceMotionEvent.h"
 
-static const nsTPtrArray<nsIDOMWindow>::index_type NoIndex =
-    nsTPtrArray<nsIDOMWindow>::NoIndex;
+static const nsTArray<nsIDOMWindow*>::index_type NoIndex =
+    nsTArray<nsIDOMWindow*>::NoIndex;
 
 class nsDeviceMotionData : public nsIDeviceMotionData
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDEVICEMOTIONDATA
 
   nsDeviceMotionData(unsigned long type, double x, double y, double z);
--- a/dom/system/nsDeviceMotion.h
+++ b/dom/system/nsDeviceMotion.h
@@ -35,17 +35,16 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsDeviceMotion_h
 #define nsDeviceMotion_h
 
 #include "nsIDeviceMotion.h"
 #include "nsIDOMDeviceMotionEvent.h"
 #include "nsCOMArray.h"
-#include "nsTPtrArray.h"
 #include "nsCOMPtr.h"
 #include "nsITimer.h"
 
 #define NS_DEVICE_MOTION_CID \
 { 0xecba5203, 0x77da, 0x465a, \
 { 0x86, 0x5e, 0x78, 0xb7, 0xaf, 0x10, 0xd8, 0xf7 } }
 
 #define NS_DEVICE_MOTION_CONTRACTID "@mozilla.org/devicemotion;1"
@@ -60,17 +59,17 @@ public:
   NS_DECL_NSIDEVICEMOTIONUPDATE
 
   nsDeviceMotion();
 
   virtual ~nsDeviceMotion();
 
 private:
   nsCOMArray<nsIDeviceMotionListener> mListeners;
-  nsTPtrArray<nsIDOMWindow> mWindowListeners;
+  nsTArray<nsIDOMWindow*> mWindowListeners;
 
   void StartDisconnectTimer();
 
   PRBool mStarted;
 
   nsCOMPtr<nsITimer> mTimeoutTimer;
   static void TimeoutHandler(nsITimer *aTimer, void *aClosure);
 
--- a/editor/libeditor/html/nsHTMLEditRules.cpp
+++ b/editor/libeditor/html/nsHTMLEditRules.cpp
@@ -4719,16 +4719,20 @@ nsHTMLEditRules::WillAlign(nsISelection 
   nsCOMPtr<nsIDOMNode> curParent;
   nsCOMPtr<nsIDOMNode> curDiv;
   PRBool useCSS;
   mHTMLEditor->GetIsCSSEnabled(&useCSS);
   for (i=0; i<listCount; i++)
   {
     // here's where we actually figure out what to do
     nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[i];
+
+    // Ignore all non-editable nodes.  Leave them be.
+    if (!mHTMLEditor->IsEditable(curNode)) continue;
+
     PRInt32 offset;
     res = nsEditor::GetNodeLocation(curNode, address_of(curParent), &offset);
     NS_ENSURE_SUCCESS(res, res);
 
     // the node is a table element, an horiz rule, a paragraph, a div
     // or a section header; in HTML 4, it can directly carry the ALIGN
     // attribute and we don't need to nest it, just set the alignment.
     // In CSS, assign the corresponding CSS styles in AlignBlock
@@ -8699,17 +8703,33 @@ nsHTMLEditRules::RemoveAlignment(nsIDOMN
     else
     {
       tmp = nsnull;
     }
     PRBool isBlock;
     res = mHTMLEditor->NodeIsBlockStatic(child, &isBlock);
     NS_ENSURE_SUCCESS(res, res);
 
-    if ((isBlock && !nsHTMLEditUtils::IsDiv(child)) || nsHTMLEditUtils::IsHR(child))
+    if (nsEditor::NodeIsType(child, nsEditProperty::center))
+    {
+      // the current node is a CENTER element
+      // first remove children's alignment
+      res = RemoveAlignment(child, aAlignType, PR_TRUE);
+      NS_ENSURE_SUCCESS(res, res);
+
+      // we may have to insert BRs in first and last position of element's children
+      // if the nodes before/after are not blocks and not BRs
+      res = MakeSureElemStartsOrEndsOnCR(child);
+      NS_ENSURE_SUCCESS(res, res);
+
+      // now remove the CENTER container
+      res = mHTMLEditor->RemoveContainer(child);
+      NS_ENSURE_SUCCESS(res, res);
+    }
+    else if (isBlock || nsHTMLEditUtils::IsHR(child))
     {
       // the current node is a block element
       nsCOMPtr<nsIDOMElement> curElem = do_QueryInterface(child);
       if (nsHTMLEditUtils::SupportsAlignAttr(child))
       {
         // remove the ALIGN attribute if this element can have it
         res = mHTMLEditor->RemoveAttribute(curElem, NS_LITERAL_STRING("align"));
         NS_ENSURE_SUCCESS(res, res);
@@ -8729,57 +8749,16 @@ nsHTMLEditRules::RemoveAlignment(nsIDOMN
       }
       if (!nsHTMLEditUtils::IsTable(child))
       {
         // unless this is a table, look at children
         res = RemoveAlignment(child, aAlignType, PR_TRUE);
         NS_ENSURE_SUCCESS(res, res);
       }
     }
-    else if (nsEditor::NodeIsType(child, nsEditProperty::center)
-             || nsHTMLEditUtils::IsDiv(child))
-    {
-      // this is a CENTER or a DIV element and we have to remove it
-      // first remove children's alignment
-      res = RemoveAlignment(child, aAlignType, PR_TRUE);
-      NS_ENSURE_SUCCESS(res, res);
-
-      if (useCSS && nsHTMLEditUtils::IsDiv(child))
-      {
-        // if we are in CSS mode and if the element is a DIV, let's remove it
-        // if it does not carry any style hint (style attr, class or ID)
-        nsAutoString dummyCssValue;
-        res = mHTMLEditor->mHTMLCSSUtils->RemoveCSSInlineStyle(child, nsEditProperty::cssTextAlign, dummyCssValue);
-        NS_ENSURE_SUCCESS(res, res);
-        nsCOMPtr<nsIDOMElement> childElt = do_QueryInterface(child);
-        PRBool hasStyleOrIdOrClass;
-        res = mHTMLEditor->HasStyleOrIdOrClass(childElt, &hasStyleOrIdOrClass);
-        NS_ENSURE_SUCCESS(res, res);
-        if (!hasStyleOrIdOrClass)
-        {
-          // we may have to insert BRs in first and last position of DIV's children
-          // if the nodes before/after are not blocks and not BRs
-          res = MakeSureElemStartsOrEndsOnCR(child);
-          NS_ENSURE_SUCCESS(res, res);
-          res = mHTMLEditor->RemoveContainer(child);
-          NS_ENSURE_SUCCESS(res, res);
-        }
-      }
-      else
-      {
-        // we may have to insert BRs in first and last position of element's children
-        // if the nodes before/after are not blocks and not BRs
-        res = MakeSureElemStartsOrEndsOnCR(child);
-        NS_ENSURE_SUCCESS(res, res);
-
-        // in HTML mode, let's remove the element
-        res = mHTMLEditor->RemoveContainer(child);
-        NS_ENSURE_SUCCESS(res, res);
-      }
-    }
     child = tmp;
   }
   return NS_OK;
 }
 
 // Let's insert a BR as first (resp. last) child of aNode if its
 // first (resp. last) child is not a block nor a BR, and if the
 // previous (resp. next) sibling is not a block nor a BR
--- a/editor/libeditor/html/tests/Makefile.in
+++ b/editor/libeditor/html/tests/Makefile.in
@@ -41,25 +41,28 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = editor/libeditor/html/tests
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES = \
 		green.png \
+		test_bug290026.html \
+		test_bug291780.html \
 		test_bug332636.html \
 		test_bug332636.html^headers^ \
 		test_bug366682.html \
 		test_bug372345.html \
 		test_bug410986.html \
 		test_bug414526.html \
 		test_bug417418.html \
 		test_bug432225.html \
 		test_bug439808.html \
+		test_bug442186.html \
 		test_bug449243.html \
 		test_bug455992.html \
 		test_bug456244.html \
 		test_bug460740.html \
 		test_bug478725.html \
 		test_bug480972.html \
 		test_bug484181.html \
 		test_bug487524.html \
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/html/tests/test_bug290026.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=290026
+-->
+<head>
+  <title>Test for Bug 290026</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.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=290026">Mozilla Bug 290026</a>
+<p id="display"></p>
+<div id="editor" contenteditable></div>
+
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 290026 **/
+SimpleTest.waitForExplicitFinish();
+
+var editor = document.getElementById("editor");
+editor.innerHTML = '<p></p><ul><li>Item 1</li><li>Item 2</li></ul><p></p>';
+editor.focus();
+
+addLoadEvent(function() {
+
+  var sel = window.getSelection();
+  sel.removeAllRanges();
+  var lis = document.getElementsByTagName("li");
+  var range = document.createRange();
+  range.setStart(lis[0], 0);
+  range.setEnd(lis[1], lis[1].childNodes.length);
+  sel.addRange(range);
+  document.execCommand("indent", false, false);
+  var oneindent = '<p></p><ul style="margin-left: 40px;"><li>Item 1</li><li>Item 2</li></ul><p></p>';
+  is(editor.innerHTML, oneindent, "a once indented bulleted list");
+  document.execCommand("indent", false, false);
+  var twoindent = '<p></p><ul style="margin-left: 80px;"><li>Item 1</li><li>Item 2</li></ul><p></p>';
+  is(editor.innerHTML, twoindent, "a twice indented bulleted list");
+  document.execCommand("outdent", false, false);
+  todo_is(editor.innerHTML, oneindent, "outdenting a twice indented bulleted list");
+
+  // done
+  SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/html/tests/test_bug291780.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=291780
+-->
+<head>
+  <title>Test for Bug 291780</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.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=291780">Mozilla Bug 291780</a>
+<p id="display"></p>
+<div id="editor" contenteditable></div>
+
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 291780 **/
+SimpleTest.waitForExplicitFinish();
+
+var original = '<ul style="margin-left: 40px;"><li>Item 1</li><li>Item 2</li><li>Item 3</li><li>Item 4</li></ul>';
+var editor = document.getElementById("editor");
+editor.innerHTML = original;
+editor.focus();
+
+addLoadEvent(function() {
+
+  var sel = window.getSelection();
+  sel.removeAllRanges();
+  var lis = document.getElementsByTagName("li");
+  var range = document.createRange();
+  range.setStart(lis[1], 0);
+  range.setEnd(lis[2], lis[2].childNodes.length);
+  sel.addRange(range);
+  document.execCommand("indent", false, false);
+  var expected = '<ul style="margin-left: 40px;"><li>Item 1</li><ul><li>Item 2</li><li>Item 3</li></ul><li>Item 4</li></ul>';
+  is(editor.innerHTML, expected, "indenting part of an already indented bulleted list");
+  document.execCommand("outdent", false, false);
+  todo_is(editor.innerHTML, original, "outdenting the partially indented part of an already indented bulleted list"); 
+
+  // done
+  SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/html/tests/test_bug442186.html
@@ -0,0 +1,102 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=442186
+-->
+<head>
+  <title>Test for Bug 442186</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.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=442186">Mozilla Bug 442186</a>
+<p id="display"></p>
+<div id="content">
+  <h2> two &lt;div&gt; containers </h2>
+  <section contenteditable id="test1">
+    <div> First paragraph with some text. </div>
+    <div> Second paragraph with some text. </div>
+  </section>
+
+  <h2> two paragraphs </h2>
+  <section contenteditable id="test2">
+    <p> First paragraph with some text. </p>
+    <p> Second paragraph with some text. </p>
+  </section>
+
+  <h2> one text node, one paragraph </h2>
+  <section contenteditable id="test3">
+    First paragraph with some text.
+    <p> Second paragraph with some text. </p>
+  </section>
+</div>
+
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 442186 **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(runTests);
+
+function justify(textNode, pos) {
+  if (!pos) pos = 10;
+
+  // put the caret on the requested character
+  var range = document.createRange();
+  var sel = window.getSelection();
+  range.setStart(textNode, pos);
+  range.setEnd(textNode, pos);
+  sel.addRange(range);
+
+  // align
+  document.execCommand("justifyright", false, null);
+}
+
+function runTests() {
+  const test1 = document.getElementById("test1");
+  const test2 = document.getElementById("test2");
+  const test3 = document.getElementById("test3");
+
+  // #test1: two <div> containers
+  const line1 = test1.querySelector("div").firstChild;
+  test1.focus();
+  justify(line1);
+  is(test1.querySelectorAll("*").length, 2,
+    "Aligning the first child should not create nor remove any element.");
+  is(line1.parentNode.nodeName.toLowerCase(), "div",
+    "Aligning the first <div> should not modify its node type.");
+  is(line1.parentNode.style.textAlign, "right",
+    "Aligning the first <div> should set a 'text-align: right' style rule.");
+
+  // #test2: two paragraphs
+  const line2 = test2.querySelector("p").firstChild;
+  test2.focus();
+  justify(line2);
+  is(test2.querySelectorAll("*").length, 2,
+    "Aligning the first child should not create nor remove any element.");
+  is(line2.parentNode.nodeName.toLowerCase(), "p",
+    "Aligning the first paragraph should not modify its node type.");
+  is(line2.parentNode.style.textAlign, "right",
+    "Aligning the first paragraph should set a 'text-align: right' style rule.");
+
+  // #test3: one text node, two paragraphs
+  const line3 = test3.firstChild;
+  test3.focus();
+  justify(line3);
+  is(test3.querySelectorAll("*").length, 2,
+    "Aligning the first child should create a block element.");
+  is(line3.parentNode.nodeName.toLowerCase(), "div",
+    "Aligning the first child should create a block element.");
+  is(line3.parentNode.style.textAlign, "right",
+    "Aligning the first line should set a 'text-align: right' style rule.");
+
+  // done
+  SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
--- a/embedding/android/AndroidManifest.xml.in
+++ b/embedding/android/AndroidManifest.xml.in
@@ -1,16 +1,19 @@
 #filter substitution
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="@ANDROID_PACKAGE_NAME@"
       android:installLocation="auto"
       android:versionCode="@ANDROID_VERSION_CODE@"
       android:versionName="@MOZ_APP_VERSION@"
-      android:sharedUserId="@MOZ_ANDROID_SHARED_ID@">
+#ifdef MOZ_ANDROID_SHARED_ID
+      android:sharedUserId="@MOZ_ANDROID_SHARED_ID@"
+#endif
+      >
     <uses-sdk android:minSdkVersion="5"
               android:targetSdkVersion="5"/>
 
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
     <uses-permission android:name="android.permission.INTERNET"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
--- a/embedding/android/Makefile.in
+++ b/embedding/android/Makefile.in
@@ -96,23 +96,28 @@ GARBAGE += \
   $(NULL)
 
 GARBAGE_DIRS += classes res
 
 # Bug 567884 - Need a way to find appropriate icons during packaging
 ifeq ($(MOZ_APP_NAME),fennec)
 ICON_PATH = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/fennec_48x48.png
 ICON_PATH_HDPI = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/fennec_72x72.png
-ifeq (org.mozilla.fennec_unofficial,$(ANDROID_PACKAGE_NAME))
-DEFINES += -DMOZ_ANDROID_SHARED_ID="org.mozilla.fennec_unofficial.sharedID"
-else ifeq (,$(MOZ_OFFICIAL_BRANDING))
+
+# we released these builds to the public with shared IDs and need to keep them
+ifeq (org.mozilla.firefox,$(ANDROID_PACKAGE_NAME))
+DEFINES += -DMOZ_ANDROID_SHARED_ID="org.mozilla.firefox.sharedID"
+else ifeq (org.mozilla.firefox_beta,$(ANDROID_PACKAGE_NAME))
+DEFINES += -DMOZ_ANDROID_SHARED_ID="org.mozilla.firefox.sharedID"
+else ifeq (org.mozilla.fennec_aurora,$(ANDROID_PACKAGE_NAME))
 DEFINES += -DMOZ_ANDROID_SHARED_ID="org.mozilla.fennec.sharedID"
-else
-DEFINES += -DMOZ_ANDROID_SHARED_ID="org.mozilla.firefox.sharedID"
+else ifeq (org.mozilla.fennec,$(ANDROID_PACKAGE_NAME))
+DEFINES += -DMOZ_ANDROID_SHARED_ID="org.mozilla.fennec.sharedID"
 endif
+
 else
 ICON_PATH = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/icon48.png
 ICON_PATH_HDPI = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/icon64.png
 DEFINES += -DMOZ_ANDROID_SHARED_ID="$(ANDROID_PACKAGE_NAME).sharedID"
 endif
 
 RES_LAYOUT = \
   res/layout/notification_progress.xml \
--- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp
@@ -80,17 +80,17 @@
 #include "nsIDOMNSRange.h"
 #include "nsIDOMRange.h"
 #include "nsIDOMText.h"
 #include "nsIPlaintextEditor.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefService.h"
 #include "nsIRunnable.h"
 #include "nsISelection.h"
-#include "nsISelection2.h"
+#include "nsISelectionPrivate.h"
 #include "nsISelectionController.h"
 #include "nsIServiceManager.h"
 #include "nsITextServicesFilter.h"
 #include "nsString.h"
 #include "nsThreadUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsIContent.h"
 #include "nsEventListenerManager.h"
@@ -1276,18 +1276,17 @@ nsresult mozInlineSpellChecker::DoSpellC
     return NS_ERROR_FAILURE;
 
   PRBool iscollapsed;
   nsresult rv = aStatus->mRange->GetCollapsed(&iscollapsed);
   NS_ENSURE_SUCCESS(rv, rv);
   if (iscollapsed)
     return NS_OK;
 
-  nsCOMPtr<nsISelection2> sel2 = do_QueryInterface(aSpellCheckSelection, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsISelectionPrivate> privSel = do_QueryInterface(aSpellCheckSelection);
 
   // see if the selection has any ranges, if not, then we can optimize checking
   // range inclusion later (we have no ranges when we are initially checking or
   // when there are no misspelled words yet).
   PRInt32 originalRangeCount;
   rv = aSpellCheckSelection->GetRangeCount(&originalRangeCount);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -1342,19 +1341,19 @@ nsresult mozInlineSpellChecker::DoSpellC
     // there were no ranges when we started out.
     if (originalRangeCount > 0) {
       // likewise, if this word is inside new text, we won't bother testing
       PRBool inCreatedRange = PR_FALSE;
       if (createdRange)
         createdRange->IsPointInRange(beginNode, beginOffset, &inCreatedRange);
       if (! inCreatedRange) {
         nsCOMArray<nsIDOMRange> ranges;
-        rv = sel2->GetRangesForIntervalCOMArray(beginNode, beginOffset,
-                                                endNode, endOffset,
-                                                PR_TRUE, &ranges);
+        rv = privSel->GetRangesForIntervalCOMArray(beginNode, beginOffset,
+                                                   endNode, endOffset,
+                                                   PR_TRUE, &ranges);
         NS_ENSURE_SUCCESS(rv, rv);
         for (PRInt32 i = 0; i < ranges.Count(); i ++)
           RemoveRange(aSpellCheckSelection, ranges[i]);
       }
     }
 
     // some words are special and don't need checking
     if (dontCheckWord)
@@ -1473,23 +1472,21 @@ mozInlineSpellChecker::ResumeCheck(mozIn
 nsresult
 mozInlineSpellChecker::IsPointInSelection(nsISelection *aSelection,
                                           nsIDOMNode *aNode,
                                           PRInt32 aOffset,
                                           nsIDOMRange **aRange)
 {
   *aRange = nsnull;
 
-  nsresult rv;
-  nsCOMPtr<nsISelection2> sel2 = do_QueryInterface(aSelection, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsISelectionPrivate> privSel(do_QueryInterface(aSelection));
 
   nsCOMArray<nsIDOMRange> ranges;
-  rv = sel2->GetRangesForIntervalCOMArray(aNode, aOffset, aNode, aOffset,
-                                          PR_TRUE, &ranges);
+  nsresult rv = privSel->GetRangesForIntervalCOMArray(aNode, aOffset, aNode, aOffset,
+                                                      PR_TRUE, &ranges);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (ranges.Count() == 0)
     return NS_OK; // no matches
 
   // there may be more than one range returned, and we don't know what do
   // do with that, so just get the first one
   NS_ADDREF(*aRange = ranges[0]);
--- a/gfx/angle/src/libEGL/Makefile.in
+++ b/gfx/angle/src/libEGL/Makefile.in
@@ -55,17 +55,21 @@ STL_FLAGS=
 ENABLE_CXX_EXCEPTIONS=1
 
 # Since we're building off in our own world, we don't want to have
 # mozilla-config.h and -DMOZILLA_CLIENT automatically included and defined, so
 # we just overwrite OS_COMPILE_C(XX)FLAGS.
 OS_COMPILE_CFLAGS = $(OS_CPPFLAGS)
 OS_COMPILE_CXXFLAGS = $(OS_CPPFLAGS)
 
-LOCAL_INCLUDES += -I$(srcdir)/../../include -I$(srcdir)/.. -I"$(DXSDK_DIR)/include"
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../../include \
+ -I$(srcdir)/.. \
+ -I"$(DXSDK_DIR)/include" \
+ -I"$(MOZ_DIRECTX_SDK_PATH)/include" \
 
 VPATH += $(srcdir)/.. \
   $(srcdir)/../compiler \
   $(srcdir)/../compiler/preprocessor \
   $(srcdir)/../common \
   $(NULL)
 
 # Translator/compiler first
--- a/gfx/angle/src/libGLESv2/Makefile.in
+++ b/gfx/angle/src/libGLESv2/Makefile.in
@@ -55,17 +55,22 @@ STL_FLAGS=
 ENABLE_CXX_EXCEPTIONS=1
 
 # Since we're building off in our own world, we don't want to have
 # mozilla-config.h and -DMOZILLA_CLIENT automatically included and defined, so
 # we just overwrite OS_COMPILE_C(XX)FLAGS.
 OS_COMPILE_CFLAGS = $(OS_CPPFLAGS)
 OS_COMPILE_CXXFLAGS = $(OS_CPPFLAGS)
 
-LOCAL_INCLUDES = -I$(srcdir)/../../include -I$(srcdir)/.. -I"$(DXSDK_DIR)/include"
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../../include \
+ -I$(srcdir)/.. \
+ -I"$(DXSDK_DIR)/include" \
+ -I"$(MOZ_DIRECTX_SDK_PATH)/include" \
+
 
 VPATH += $(srcdir)/..
 VPATH += $(srcdir)/../compiler
 VPATH += $(srcdir)/../compiler/preprocessor
 VPATH += $(srcdir)/../common
 
 # Translator/compiler first
 
--- a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
+++ b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
@@ -2553,16 +2553,25 @@ static cairo_status_t
 	return _cairo_error(CAIRO_STATUS_NO_DEVICE);
     }
     *image_out = 
 	(cairo_image_surface_t*)cairo_image_surface_create_for_data((unsigned char*)data.pData,
 										  d2dsurf->format,
 										  size.width,
 										  size.height,
 										  data.RowPitch);
+
+    if (cairo_surface_status(&((*image_out)->base))) {
+	volatile cairo_status_t flambo[10];
+	for (int i=0; i<10; i++) {
+	    flambo[i] = cairo_surface_status(&((*image_out)->base));
+	}
+	volatile int p = 0;
+	p = 5/p;
+    }
     *image_extra = softTexture.forget();
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
 _cairo_d2d_release_source_image(void                   *abstract_surface,
 				cairo_image_surface_t  *image,
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -33,16 +33,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 "mozilla/layers/PLayers.h"
 #include "mozilla/layers/ShadowLayers.h"
 
 #include "ImageLayers.h"
 #include "Layers.h"
 #include "gfxPlatform.h"
 #include "ReadbackLayer.h"
 #include "gfxUtils.h"
 #include "mozilla/Util.h"
@@ -384,16 +385,22 @@ Layer::GetEffectiveOpacity()
   float opacity = GetOpacity();
   for (ContainerLayer* c = GetParent(); c && !c->UseIntermediateSurface();
        c = c->GetParent()) {
     opacity *= c->GetOpacity();
   }
   return opacity;
 }
 
+void
+ContainerLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
+{
+  aAttrs = ContainerLayerAttributes(GetFrameMetrics());
+}
+
 PRBool
 ContainerLayer::HasMultipleChildren()
 {
   PRUint32 count = 0;
   for (Layer* child = GetFirstChild(); child; child = child->GetNextSibling()) {
     const nsIntRect *clipRect = child->GetEffectiveClipRect();
     if (clipRect && clipRect->IsEmpty())
       continue;
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -74,19 +74,21 @@ namespace layers {
 
 class Layer;
 class ThebesLayer;
 class ContainerLayer;
 class ImageLayer;
 class ColorLayer;
 class ImageContainer;
 class CanvasLayer;
-class ShadowLayer;
 class ReadbackLayer;
 class ReadbackProcessor;
+class ShadowLayer;
+class ShadowLayerForwarder;
+class ShadowLayerManager;
 class SpecificLayerAttributes;
 
 /**
  * The viewport and displayport metrics for the painted frame at the
  * time of a layer-tree transaction.  These metrics are especially
  * useful for shadow layers, because the metrics values are updated
  * atomically with new pixels.
  */
@@ -110,16 +112,20 @@ public:
 
   PRBool operator==(const FrameMetrics& aOther) const
   {
     return (mViewport.IsEqualEdges(aOther.mViewport) &&
             mViewportScrollOffset == aOther.mViewportScrollOffset &&
             mDisplayPort.IsEqualEdges(aOther.mDisplayPort) &&
             mScrollId == aOther.mScrollId);
   }
+  PRBool operator!=(const FrameMetrics& aOther) const
+  { 
+    return !operator==(aOther);
+  }
 
   PRBool IsDefault() const
   {
     return (FrameMetrics() == *this);
   }
 
   PRBool IsRootScrollable() const
   {
@@ -278,16 +284,22 @@ public:
    * Release layers and resources held by this layer manager, and mark
    * it as destroyed.  Should do any cleanup necessary in preparation
    * for its widget going away.  After this call, only user data calls
    * are valid on the layer manager.
    */
   virtual void Destroy() { mDestroyed = PR_TRUE; mUserData.Clear(); }
   PRBool IsDestroyed() { return mDestroyed; }
 
+  virtual ShadowLayerForwarder* AsShadowForwarder()
+  { return nsnull; }
+
+  virtual ShadowLayerManager* AsShadowManager()
+  { return nsnull; }
+
   /**
    * Start a new transaction. Nested transactions are not allowed so
    * there must be no transaction currently in progress.
    * This transaction will update the state of the window from which
    * this LayerManager was obtained.
    */
   virtual void BeginTransaction() = 0;
   /**
@@ -1066,18 +1078,21 @@ public:
   /**
    * CONSTRUCTION PHASE ONLY
    * Set the (sub)document metrics used to render the Layer subtree
    * rooted at this.
    */
   void SetFrameMetrics(const FrameMetrics& aFrameMetrics)
   {
     mFrameMetrics = aFrameMetrics;
+    Mutated();
   }
 
+  virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs);
+
   // These getters can be used anytime.
 
   virtual ContainerLayer* AsContainerLayer() { return this; }
 
   virtual Layer* GetFirstChild() { return mFirstChild; }
   virtual Layer* GetLastChild() { return mLastChild; }
   const FrameMetrics& GetFrameMetrics() { return mFrameMetrics; }
 
--- a/gfx/layers/Makefile.in
+++ b/gfx/layers/Makefile.in
@@ -109,23 +109,24 @@ CPPSRCS += \
 endif
 ifdef MOZ_ENABLE_D3D10_LAYER
 EXPORTS += \
         LayerManagerD3D10.h \
         ReadbackManagerD3D10.h \
         $(NULL)
 
 CPPSRCS += \
-        LayerManagerD3D10.cpp \
-        ThebesLayerD3D10.cpp \
+        CanvasLayerD3D10.cpp \
+        ColorLayerD3D10.cpp \
         ContainerLayerD3D10.cpp \
         ImageLayerD3D10.cpp \
-        ColorLayerD3D10.cpp \
-        CanvasLayerD3D10.cpp \
+        LayerManagerD3D10.cpp \
         ReadbackManagerD3D10.cpp \
+	ShadowLayerUtilsD3D10.cpp \
+        ThebesLayerD3D10.cpp \
         $(NULL)
 endif
 endif
 
 EXPORTS_NAMESPACES = IPC mozilla/layers
 EXPORTS_IPC = ShadowLayerUtils.h
 EXPORTS_mozilla/layers =\
         ShadowLayers.h \
@@ -148,16 +149,21 @@ endif #}
 
 # Enable GLES2.0 under maemo
 ifdef MOZ_X11
 ifdef MOZ_PLATFORM_MAEMO
 DEFINES += -DUSE_GLES2
 endif
 endif
 
+ifdef MOZ_ENABLE_D3D10_LAYER
+EXPORTS_mozilla/layers += ShadowLayerUtilsD3D10.h
+DEFINES	+= -DMOZ_ENABLE_D3D10_LAYER
+endif
+
 include $(topsrcdir)/config/rules.mk
 
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 
 CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(TK_CFLAGS)
 
 LayerManagerOGLShaders.h: LayerManagerOGLShaders.txt genshaders.py $(GLOBAL_DEPS)
 	$(PYTHON) $(srcdir)/opengl/genshaders.py $< $@
--- a/gfx/layers/basic/BasicLayers.cpp
+++ b/gfx/layers/basic/BasicLayers.cpp
@@ -1902,21 +1902,16 @@ public:
   virtual ~BasicShadowableContainerLayer()
   {
     MOZ_COUNT_DTOR(BasicShadowableContainerLayer);
   }
 
   virtual void InsertAfter(Layer* aChild, Layer* aAfter);
   virtual void RemoveChild(Layer* aChild);
 
-  virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
-  {
-    aAttrs = ContainerLayerAttributes(GetFrameMetrics());
-  }
-
   virtual Layer* AsLayer() { return this; }
   virtual ShadowableLayer* AsShadowableLayer() { return this; }
 
   virtual void Disconnect()
   {
     BasicShadowableLayer::Disconnect();
   }
 
--- a/gfx/layers/basic/BasicLayers.h
+++ b/gfx/layers/basic/BasicLayers.h
@@ -219,16 +219,25 @@ class BasicShadowLayerManager : public B
                                 public ShadowLayerForwarder
 {
   typedef nsTArray<nsRefPtr<Layer> > LayerRefArray;
 
 public:
   BasicShadowLayerManager(nsIWidget* aWidget);
   virtual ~BasicShadowLayerManager();
 
+  virtual ShadowLayerForwarder* AsShadowForwarder()
+  {
+    return this;
+  }
+  virtual ShadowLayerManager* AsShadowManager()
+  {
+    return this;
+  }
+
   virtual void BeginTransactionWithTarget(gfxContext* aTarget);
   virtual bool EndEmptyTransaction();
   virtual void EndTransaction(DrawThebesLayerCallback aCallback,
                               void* aCallbackData);
 
   virtual void SetRoot(Layer* aLayer);
 
   virtual void Mutated(Layer* aLayer);
@@ -242,22 +251,16 @@ public:
   virtual already_AddRefed<ShadowContainerLayer> CreateShadowContainerLayer();
   virtual already_AddRefed<ShadowImageLayer> CreateShadowImageLayer();
   virtual already_AddRefed<ShadowColorLayer> CreateShadowColorLayer();
   virtual already_AddRefed<ShadowCanvasLayer> CreateShadowCanvasLayer();
 
   ShadowableLayer* Hold(Layer* aLayer);
 
   bool HasShadowManager() const { return ShadowLayerForwarder::HasShadowManager(); }
-  PLayersChild* GetShadowManager() const { return mShadowManager; }
-
-  void SetShadowManager(PLayersChild* aShadowManager)
-  {
-    mShadowManager = aShadowManager;
-  }
 
   virtual PRBool IsCompositingCheap();
   virtual bool HasShadowManagerInternal() const { return HasShadowManager(); }
 
 private:
   /**
    * Forward transaction results to the parent context.
    */
--- a/gfx/layers/d3d10/CanvasLayerD3D10.cpp
+++ b/gfx/layers/d3d10/CanvasLayerD3D10.cpp
@@ -33,16 +33,17 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "CanvasLayerD3D10.h"
 
+#include "../d3d9/Nv3DVUtils.h"
 #include "gfxImageSurface.h"
 #include "gfxWindowsSurface.h"
 #include "gfxWindowsPlatform.h"
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
--- a/gfx/layers/d3d10/ColorLayerD3D10.cpp
+++ b/gfx/layers/d3d10/ColorLayerD3D10.cpp
@@ -33,16 +33,18 @@
  * 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 "ColorLayerD3D10.h"
 
+#include "../d3d9/Nv3DVUtils.h"
+
 namespace mozilla {
 namespace layers {
 
 ColorLayerD3D10::ColorLayerD3D10(LayerManagerD3D10 *aManager)
   : ColorLayer(aManager, NULL)
   , LayerD3D10(aManager)
 {
   mImplData = static_cast<LayerD3D10*>(this);
--- a/gfx/layers/d3d10/ColorLayerD3D10.h
+++ b/gfx/layers/d3d10/ColorLayerD3D10.h
@@ -33,17 +33,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 ***** */
 
 #ifndef GFX_COLORLAYERD3D10_H
 #define GFX_COLORLAYERD3D10_H
 
-#include "Layers.h"
 #include "LayerManagerD3D10.h"
 
 namespace mozilla {
 namespace layers {
 
 class ColorLayerD3D10 : public ColorLayer,
                         public LayerD3D10
 {
--- a/gfx/layers/d3d10/ContainerLayerD3D10.cpp
+++ b/gfx/layers/d3d10/ContainerLayerD3D10.cpp
@@ -1,9 +1,9 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+/* -*- Mode: C++; tab-width: 20; 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/
  *
@@ -35,16 +35,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "ContainerLayerD3D10.h"
 #include "nsAlgorithm.h"
 #include "gfxUtils.h"
 #include "nsRect.h"
 
+#include "../d3d9/Nv3DVUtils.h"
 #include "ThebesLayerD3D10.h"
 #include "ReadbackProcessor.h"
 
 namespace mozilla {
 namespace layers {
 
 ContainerLayerD3D10::ContainerLayerD3D10(LayerManagerD3D10 *aManager)
   : ContainerLayer(aManager, NULL)
@@ -369,10 +370,60 @@ ContainerLayerD3D10::Validate()
       static_cast<ThebesLayerD3D10*>(layer)->Validate(&readback);
     } else {
       static_cast<LayerD3D10*>(layer->ImplData())->Validate();
     }
     layer = layer->GetNextSibling();
   }
 }
 
+ShadowContainerLayerD3D10::ShadowContainerLayerD3D10(LayerManagerD3D10 *aManager) 
+  : ShadowContainerLayer(aManager, NULL)
+  , LayerD3D10(aManager)
+{
+  mImplData = static_cast<LayerD3D10*>(this);
+}
+
+ShadowContainerLayerD3D10::~ShadowContainerLayerD3D10() {}
+
+void
+ShadowContainerLayerD3D10::InsertAfter(Layer* aChild, Layer* aAfter)
+{
+  mFirstChild = aChild;
+}
+
+void
+ShadowContainerLayerD3D10::RemoveChild(Layer* aChild)
+{
+
+}
+
+void
+ShadowContainerLayerD3D10::ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
+{
+  DefaultComputeEffectiveTransforms(aTransformToSurface);
+}
+
+LayerD3D10*
+ShadowContainerLayerD3D10::GetFirstChildD3D10()
+{
+  return static_cast<LayerD3D10*>(mFirstChild->ImplData());
+}
+
+void
+ShadowContainerLayerD3D10::RenderLayer()
+{
+  LayerD3D10* layerToRender = GetFirstChildD3D10();
+  layerToRender->RenderLayer();
+}
+
+void
+ShadowContainerLayerD3D10::Validate()
+{
+}
+ 
+void
+ShadowContainerLayerD3D10::LayerManagerDestroyed()
+{
+}
+
 } /* layers */
 } /* mozilla */
--- a/gfx/layers/d3d10/ContainerLayerD3D10.h
+++ b/gfx/layers/d3d10/ContainerLayerD3D10.h
@@ -1,9 +1,9 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+/* -*- Mode: C++; tab-width: 20; 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/
  *
@@ -33,17 +33,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 ***** */
 
 #ifndef GFX_CONTAINERLAYERD3D10_H
 #define GFX_CONTAINERLAYERD3D10_H
 
-#include "Layers.h"
 #include "LayerManagerD3D10.h"
 
 namespace mozilla {
 namespace layers {
 
 class ContainerLayerD3D10 : public ContainerLayer,
                             public LayerD3D10
 {
@@ -69,12 +68,39 @@ public:
   virtual void LayerManagerDestroyed();
 
   virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
   {
     DefaultComputeEffectiveTransforms(aTransformToSurface);
   }
 };
 
+// This is a bare-bones implementation of a container layer, only
+// enough to contain a shadow "window texture".  This impl doesn't
+// honor the transform/cliprect/etc. when rendering.
+class ShadowContainerLayerD3D10 : public ShadowContainerLayer,
+                                  public LayerD3D10
+{
+public:
+  ShadowContainerLayerD3D10(LayerManagerD3D10 *aManager);
+  ~ShadowContainerLayerD3D10();
+
+  void InsertAfter(Layer* aChild, Layer* aAfter);
+
+  void RemoveChild(Layer* aChild);
+
+  virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface);
+
+  /* LayerD3D10 implementation */
+  virtual LayerD3D10 *GetFirstChildD3D10();
+  virtual Layer* GetLayer() { return this; }
+  virtual void RenderLayer();
+  virtual void Validate();
+  virtual void LayerManagerDestroyed();
+
+private:
+    
+};
+
 } /* layers */
 } /* mozilla */
 
 #endif /* GFX_CONTAINERLAYERD3D10_H */
--- a/gfx/layers/d3d10/LayerManagerD3D10.cpp
+++ b/gfx/layers/d3d10/LayerManagerD3D10.cpp
@@ -1,9 +1,9 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+/* -*- Mode: C++; tab-width: 20; 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/
  *
@@ -30,35 +30,39 @@
  * 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 <algorithm>
+
 #include "LayerManagerD3D10.h"
 #include "LayerManagerD3D10Effect.h"
 #include "gfxWindowsPlatform.h"
 #include "gfxD2DSurface.h"
 #include "gfxFailure.h"
 #include "cairo-win32.h"
 #include "dxgi.h"
 
 #include "ContainerLayerD3D10.h"
 #include "ThebesLayerD3D10.h"
 #include "ColorLayerD3D10.h"
 #include "CanvasLayerD3D10.h"
 #include "ReadbackLayerD3D10.h"
 #include "ImageLayerD3D10.h"
+#include "mozilla/layers/PLayerChild.h"
 
 #include "../d3d9/Nv3DVUtils.h"
 
 #include "gfxCrashReporterUtils.h"
 
+using namespace std;
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
 typedef HRESULT (WINAPI*D3D10CreateEffectFromMemoryFunc)(
     void *pData,
     SIZE_T DataLength,
@@ -222,16 +226,21 @@ LayerManagerD3D10::Initialize()
 
     attachments->mVertexBuffer = mVertexBuffer;
   } else {
     mEffect = attachments->mEffect;
     mVertexBuffer = attachments->mVertexBuffer;
     mInputLayout = attachments->mInputLayout;
   }
 
+  if (HasShadowManager()) {
+    reporter.SetSuccessful();
+    return true;
+  }
+
   nsRefPtr<IDXGIDevice> dxgiDevice;
   nsRefPtr<IDXGIAdapter> dxgiAdapter;
   nsRefPtr<IDXGIFactory> dxgiFactory;
 
   mDevice->QueryInterface(dxgiDevice.StartAssignment());
   dxgiDevice->GetAdapter(getter_AddRefs(dxgiAdapter));
 
   dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.StartAssignment()));
@@ -282,29 +291,36 @@ LayerManagerD3D10::Initialize()
 
 void
 LayerManagerD3D10::Destroy()
 {
   if (!IsDestroyed()) {
     if (mRoot) {
       static_cast<LayerD3D10*>(mRoot->ImplData())->LayerManagerDestroyed();
     }
+    mRootForShadowTree = nsnull;
+    // XXX need to be careful here about surface destruction
+    // racing with share-to-chrome message
   }
   LayerManager::Destroy();
 }
 
 void
 LayerManagerD3D10::SetRoot(Layer *aRoot)
 {
   mRoot = aRoot;
 }
 
 void
 LayerManagerD3D10::BeginTransaction()
 {
+#ifdef MOZ_LAYERS_HAVE_LOG
+  MOZ_LAYERS_LOG(("[----- BeginTransaction"));
+  Log();
+#endif
 }
 
 void
 LayerManagerD3D10::BeginTransactionWithTarget(gfxContext* aTarget)
 {
   mTarget = aTarget;
 }
 
@@ -325,38 +341,62 @@ LayerManagerD3D10::EndTransaction(DrawTh
   if (mRoot) {
     mCurrentCallbackInfo.Callback = aCallback;
     mCurrentCallbackInfo.CallbackData = aCallbackData;
 
     // The results of our drawing always go directly into a pixel buffer,
     // so we don't need to pass any global transform here.
     mRoot->ComputeEffectiveTransforms(gfx3DMatrix());
 
+#ifdef MOZ_LAYERS_HAVE_LOG
+    MOZ_LAYERS_LOG(("  ----- (beginning paint)"));
+    Log();
+#endif
+
     Render();
     mCurrentCallbackInfo.Callback = nsnull;
     mCurrentCallbackInfo.CallbackData = nsnull;
   }
 
+#ifdef MOZ_LAYERS_HAVE_LOG
+  Log();
+  MOZ_LAYERS_LOG(("]----- EndTransaction"));
+#endif
+
   mTarget = nsnull;
 }
 
 already_AddRefed<ThebesLayer>
 LayerManagerD3D10::CreateThebesLayer()
 {
   nsRefPtr<ThebesLayer> layer = new ThebesLayerD3D10(this);
   return layer.forget();
 }
+ 
+already_AddRefed<ShadowThebesLayer>
+LayerManagerD3D10::CreateShadowThebesLayer()
+{
+  nsRefPtr<ShadowThebesLayerD3D10> layer = new ShadowThebesLayerD3D10(this);
+  return layer.forget();
+}
 
 already_AddRefed<ContainerLayer>
 LayerManagerD3D10::CreateContainerLayer()
 {
   nsRefPtr<ContainerLayer> layer = new ContainerLayerD3D10(this);
   return layer.forget();
 }
 
+already_AddRefed<ShadowContainerLayer>
+LayerManagerD3D10::CreateShadowContainerLayer()
+{
+  nsRefPtr<ShadowContainerLayer> layer = new ShadowContainerLayerD3D10(this);
+  return layer.forget();
+}
+
 already_AddRefed<ImageLayer>
 LayerManagerD3D10::CreateImageLayer()
 {
   nsRefPtr<ImageLayer> layer = new ImageLayerD3D10(this);
   return layer.forget();
 }
 
 already_AddRefed<ColorLayer>
@@ -541,49 +581,82 @@ LayerManagerD3D10::UpdateRenderTarget()
   if (mRTView) {
     return;
   }
 
   HRESULT hr;
 
   nsRefPtr<ID3D10Texture2D> backBuf;
   
-  hr = mSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (void**)backBuf.StartAssignment());
-  if (FAILED(hr)) {
-    return;
+  if (mSwapChain) {
+    hr = mSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (void**)backBuf.StartAssignment());
+    if (FAILED(hr)) {
+      return;
+    }
+  } else {
+    backBuf = mBackBuffer;
   }
   
   mDevice->CreateRenderTargetView(backBuf, NULL, getter_AddRefs(mRTView));
 }
 
 void
 LayerManagerD3D10::VerifyBufferSize()
 {
-  DXGI_SWAP_CHAIN_DESC swapDesc;
-  mSwapChain->GetDesc(&swapDesc);
-
   nsIntRect rect;
   mWidget->GetClientBounds(rect);
 
-  if (swapDesc.BufferDesc.Width == rect.width &&
-      swapDesc.BufferDesc.Height == rect.height) {
-    return;
-  }
+  HRESULT hr;
+  if (mSwapChain) {
+    DXGI_SWAP_CHAIN_DESC swapDesc;
+    mSwapChain->GetDesc(&swapDesc);
+
+    if (swapDesc.BufferDesc.Width == rect.width &&
+        swapDesc.BufferDesc.Height == rect.height) {
+      return;
+    }
 
-  mRTView = nsnull;
-  if (gfxWindowsPlatform::IsOptimus()) {
-    mSwapChain->ResizeBuffers(1, rect.width, rect.height,
-                              DXGI_FORMAT_B8G8R8A8_UNORM,
-                              0);
+    mRTView = nsnull;
+    if (gfxWindowsPlatform::IsOptimus()) {
+      mSwapChain->ResizeBuffers(1, rect.width, rect.height,
+                                DXGI_FORMAT_B8G8R8A8_UNORM,
+                                0);
+    } else {
+      mSwapChain->ResizeBuffers(1, rect.width, rect.height,
+                                DXGI_FORMAT_B8G8R8A8_UNORM,
+                                DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE);
+    }
   } else {
-    mSwapChain->ResizeBuffers(1, rect.width, rect.height,
-                              DXGI_FORMAT_B8G8R8A8_UNORM,
-                              DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE);
+    D3D10_TEXTURE2D_DESC oldDesc;    
+    if (mBackBuffer) {
+        mBackBuffer->GetDesc(&oldDesc);
+    } else {
+        oldDesc.Width = oldDesc.Height = 0;
+    }
+    if (oldDesc.Width == rect.width &&
+        oldDesc.Height == rect.height) {
+      return;
+    }
+
+    CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM,
+                               rect.width, rect.height, 1, 1);
+    desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
+    desc.MiscFlags = D3D10_RESOURCE_MIS